sms@wlv.imsd.contel.com (Steven M. Schultz) (06/15/91)
Subject: TS-11 alignment problems plus a few other changes Index sys/pdpuba/ts.c 2.11BSD Description: The command structure has to be aligned on a 4 byte boundary, for UNIBUS systems this means that the UNIBUS virtual address must be properly aligned rather than the physical address. The UMR allocation was moved from the tsinit() routine to the tsattach() routine. Only 1 UMR is required to map the structures for all TS-11 controllers in the system instead of a UMR per controller. Virtual addresses are calculated from the base of the ts_softc structure now. The sc_mapped element has been removed from the softc structure since it is no longer needed. Almost all of the UNIBUS_MAP conditionals have been removed, the address fields in ts_softc are calculated once at attach time just as they are for the UNIBUS case. Repeat-By: Examine the sources and the enclosed patch. Fix: Apply the following patch to ts.c and recompile the kernel if a TS-11 is configured in the system. *** /usr/src/sys/pdpuba/ts.c.old Fri May 24 20:46:13 1991 --- /usr/src/sys/pdpuba/ts.c Mon Jun 3 18:53:16 1991 *************** *** 3,9 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ts.c 2.0 (2.11BSD) 5/23/91 */ /* --- 3,9 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ts.c 2.1 (2.11BSD) 5/31/91 */ /* *************** *** 21,26 **** --- 21,28 ---- #include "fs.h" #include "tsreg.h" #include "mtio.h" + #include "map.h" + #include "uba.h" /* * Software state per tape transport: *************** *** 45,57 **** struct ts_cmd sc_cmd; /* the command packet */ struct ts_char sc_char;/* status packet, for returned status */ struct ts_sts sc_sts; /* characteristics packet */ - #ifdef UNIBUS_MAP u_short sc_uba; /* Unibus addr of cmd pkt for tsdb */ ubadr_t sc_uadr; /* actual unibus address */ ! short sc_mapped; /* is sc_cmd mapped in Unibus space? */ ! #endif } *ts_softc[NTS]; struct buf tstab[NTS]; /* --- 47,59 ---- struct ts_cmd sc_cmd; /* the command packet */ struct ts_char sc_char;/* status packet, for returned status */ struct ts_sts sc_sts; /* characteristics packet */ u_short sc_uba; /* Unibus addr of cmd pkt for tsdb */ ubadr_t sc_uadr; /* actual unibus address */ ! struct tty *sc_ttyp; /* record user's tty for errors */ } *ts_softc[NTS]; + static ubadr_t TS_ubadr; + struct buf tstab[NTS]; /* *************** *** 80,93 **** #define SCOM 3 /* sending a control command */ #define SREW 4 /* sending a drive rewind */ ! char softspace[sizeof(struct ts_softc)*NTS + 3]; tsattach(addr, unit) struct tsdevice *addr; register int unit; { ! register u_short sp = ((u_short)softspace + 3) & ~3; register struct ts_softc *sc; if (unit >= NTS) return(0); --- 82,96 ---- #define SCOM 3 /* sending a control command */ #define SREW 4 /* sending a drive rewind */ ! u_short softspace[NTS][(sizeof(struct ts_softc)/2) + 1]; tsattach(addr, unit) struct tsdevice *addr; register int unit; { ! register u_short sp = (u_short)softspace[unit]; register struct ts_softc *sc; + struct buf tbuf; if (unit >= NTS) return(0); *************** *** 97,107 **** * core address is a 4-byte multiple. The compiler only * guarantees word alignment. We reserve and extra 3 bytes * so that we can slide the array down by 2 if the compiler ! * gets it wrong. */ ! sp += (unit * sizeof (struct ts_softc)); ! sc = ts_softc[unit] = (struct ts_softc *)sp; sc->sc_addr = addr; return(1); } --- 100,135 ---- * core address is a 4-byte multiple. The compiler only * guarantees word alignment. We reserve and extra 3 bytes * so that we can slide the array down by 2 if the compiler ! * gets it wrong. Only allocate 1 UMR to map all of the ! * communication area instead of a UMR per controller. ! * ! * On a UNIBUS system the ts_softc structure is aligned so ! * that the UNIBUS virtual address of sc_cmd falls on a 4 ! * byte boundary - the physical address may be on a 2 byte bound. ! * ! * On non-UNIBUS systems the ts_softc structure is aligned so ! * that sc_cmd falls on a physical 4 byte boundary. */ ! sc = (struct ts_softc *)sp; ! if (((u_short)&sc->sc_cmd - (ubmap ? (u_short)softspace : 0)) & 3) ! sp += 2; ! if (ubmap && TS_ubadr == 0) { ! tbuf.b_xmem = 0; /* won't work above 64k any way */ ! tbuf.b_un.b_addr = (caddr_t) softspace; ! tbuf.b_flags = B_PHYS; ! tbuf.b_bcount = sizeof (softspace); ! #ifdef UNIBUS_MAP ! mapalloc(&tbuf); ! #endif ! TS_ubadr = ((long)((unsigned)tbuf.b_xmem)) << 16 ! | ((long)((unsigned)tbuf.b_un.b_addr)); ! } ! sc = ts_softc[unit] = (struct ts_softc *) sp; sc->sc_addr = addr; + sc->sc_uadr = TS_ubadr + ((u_short)&sc->sc_cmd - + (ubmap ? (u_short)softspace : 0)); + sc->sc_uba = loint(sc->sc_uadr) + | hiint(sc->sc_uadr); /* register format */ return(1); } *************** *** 141,146 **** --- 169,175 ---- sc->sc_blkno = (daddr_t) 0; sc->sc_nxrec = INF; sc->sc_lastiow = 0; + sc->sc_ttyp = u.u_ttyp; return(0); } *************** *** 335,345 **** if (um->b_errcnt) cmd |= TS_RETRY; tc->c_cmd = TS_ACK | TS_CVC | TS_IE | cmd; - #ifdef UNIBUS_MAP sc->sc_addr->tsdb = sc->sc_uba; - #else - sc->sc_addr->tsdb = (u_short)&sc->sc_cmd.c_cmd; - #endif return; } /* --- 364,370 ---- *************** *** 362,372 **** * Do the command in bp. */ tc->c_cmd = TS_ACK | TS_CVC | TS_IE | bp->b_command; - #ifdef UNIBUS_MAP sc->sc_addr->tsdb = sc->sc_uba; - #else - sc->sc_addr->tsdb = (u_short)&sc->sc_cmd.c_cmd; - #endif return; next: --- 387,393 ---- *************** *** 389,395 **** { int state; register struct buf *bp, *um = &tstab[dev]; ! register struct ts_softc *sc; if ((bp = um->b_actf) == NULL) return; --- 410,416 ---- { int state; register struct buf *bp, *um = &tstab[dev]; ! register struct ts_softc *sc = ts_softc[dev]; if ((bp = um->b_actf) == NULL) return; *************** *** 398,404 **** * If last command was a rewind, and tape is still * rewinding, wait for the rewind complete interrupt. * ! * SHOULD NEVER GET AN INTERRUPT IN THIS STATE. */ if (um->b_active == SREW) { um->b_active = SCOM; --- 419,426 ---- * If last command was a rewind, and tape is still * rewinding, wait for the rewind complete interrupt. * ! * SHOULD NEVER GET AN INTERRUPT IN THIS STATE, but it ! * happens when a rewind completes. */ if (um->b_active == SREW) { um->b_active = SCOM; *************** *** 408,414 **** /* * An operation completed... record status */ - sc = ts_softc[dev]; if ((bp->b_flags & B_READ) == 0) sc->sc_lastiow = 1; state = um->b_active; --- 430,435 ---- *************** *** 478,500 **** case TS_REJECT: if (state == SIO && sc->sc_sts.s_xs0 & TS_WLE) ! printf("ts%d: no write ring\n", dev); if ((sc->sc_sts.s_xs0 & TS_ONL) == 0) ! printf("ts%d: not online\n", dev); break; } /* * Couldn't recover error. */ ! printf("ts%d: hard error bn%D xs0=%b", dev, bp->b_blkno, sc->sc_sts.s_xs0, TSXS0_BITS); if (sc->sc_sts.s_xs1) ! printf(" xs1=%b", sc->sc_sts.s_xs1, TSXS1_BITS); if (sc->sc_sts.s_xs2) ! printf(" xs2=%b", sc->sc_sts.s_xs2, TSXS2_BITS); if (sc->sc_sts.s_xs3) ! printf(" xs3=%b", sc->sc_sts.s_xs3, TSXS3_BITS); ! printf("\n"); bp->b_flags |= B_ERROR; goto opdone; /*NOTREACHED*/ --- 499,521 ---- case TS_REJECT: if (state == SIO && sc->sc_sts.s_xs0 & TS_WLE) ! tprintf(sc->sc_ttyp,"ts%d: no write ring\n", dev); if ((sc->sc_sts.s_xs0 & TS_ONL) == 0) ! tprintf(sc->sc_ttyp,"ts%d: not online\n", dev); break; } /* * Couldn't recover error. */ ! tprintf(sc->sc_ttyp,"ts%d: hard error bn%D xs0=%b", dev, bp->b_blkno, sc->sc_sts.s_xs0, TSXS0_BITS); if (sc->sc_sts.s_xs1) ! tprintf(sc->sc_ttyp," xs1=%b", sc->sc_sts.s_xs1, TSXS1_BITS); if (sc->sc_sts.s_xs2) ! tprintf(sc->sc_ttyp," xs2=%b", sc->sc_sts.s_xs2, TSXS2_BITS); if (sc->sc_sts.s_xs3) ! tprintf(sc->sc_ttyp," xs3=%b", sc->sc_sts.s_xs3, TSXS3_BITS); ! tprintf(sc->sc_ttyp,"\n"); bp->b_flags |= B_ERROR; goto opdone; /*NOTREACHED*/ *************** *** 584,660 **** */ tsinit(ts11) { ! struct ts_softc *sc = ts_softc[ts11]; register struct ts_cmd *tcmd = &sc->sc_cmd; register struct ts_char *tchar = &sc->sc_char; int cnt; - #ifdef UNIBUS_MAP - struct buf tbuf; - /* - * Map the command and message packets into Unibus - * address space. We do all the command and message - * packets at once to minimize the amount of Unibus - * mapping necessary. - */ - if (!sc->sc_mapped) { - tbuf.b_xmem = 0; /* won't work past 64k any way */ - tbuf.b_un.b_addr = (caddr_t)tcmd; - tbuf.b_flags = B_PHYS; /* want map to point to phys. addr. */ - tbuf.b_bcount = sizeof(struct ts_cmd); - mapalloc(&tbuf); - sc->sc_uadr = ((long)((unsigned)tbuf.b_xmem)) << 16 - | ((long) ((unsigned)tbuf.b_un.b_addr)); - sc->sc_mapped++; - } - #endif UNIBUS_MAP - - /* * Now initialize the TS11 controller. * Set the characteristics. */ if (sc->sc_addr->tssr & (TS_NBA | TS_OFL)) { tcmd->c_cmd = TS_ACK | TS_CVC | TS_INIT; - #ifdef UNIBUS_MAP - sc->sc_uba = loint(sc->sc_uadr) - | hiint(sc->sc_uadr); /*register format*/ sc->sc_addr->tsdb = sc->sc_uba; - #else - sc->sc_addr->tsdb = (u_short) tcmd; - #endif for (cnt = 0; cnt < 10000; cnt++) { if (sc->sc_addr->tssr & TS_SSR) break; } ! if (cnt >= 10000) { ! printf("ts%d: subsystem init. failure\n", ts11); return (1); - } - #ifdef UNIBUS_MAP tchar->char_bptr = (u_short)loint(sc->sc_uadr)+ ((u_short)&sc->sc_sts-(u_short)tcmd); tchar->char_bae = hiint(sc->sc_uadr); - #else UNIBUS_MAP - tchar->char_bptr = (u_short) &sc->sc_sts; - tchar->char_bae = 0; - #endif tchar->char_size = sizeof(struct ts_sts); tchar->char_mode = TS_ESS; tcmd->c_cmd = TS_ACK | TS_CVC | TS_SETCHR; - #ifdef UNIBUS_MAP tcmd->c_loba = (u_short)loint(sc->sc_uadr)+ ((u_short)tchar-(u_short)tcmd); tcmd->c_hiba = hiint(sc->sc_uadr); - #else UNIBUS_MAP - tcmd->c_loba = (u_short) tchar; - tcmd->c_hiba = 0; - #endif tcmd->c_size = sizeof(struct ts_char); - #ifdef UNIBUS_MAP sc->sc_addr->tsdb = sc->sc_uba; - #else UNIBUS_MAP - sc->sc_addr->tsdb = (u_short) tcmd; - #endif for (cnt = 0; cnt < 10000; cnt++) { if (sc->sc_addr->tssr & TS_SSR) break; --- 605,638 ---- */ tsinit(ts11) { ! register struct ts_softc *sc = ts_softc[ts11]; register struct ts_cmd *tcmd = &sc->sc_cmd; register struct ts_char *tchar = &sc->sc_char; int cnt; /* * Now initialize the TS11 controller. * Set the characteristics. */ if (sc->sc_addr->tssr & (TS_NBA | TS_OFL)) { tcmd->c_cmd = TS_ACK | TS_CVC | TS_INIT; sc->sc_addr->tsdb = sc->sc_uba; for (cnt = 0; cnt < 10000; cnt++) { if (sc->sc_addr->tssr & TS_SSR) break; } ! if (cnt >= 10000) return (1); tchar->char_bptr = (u_short)loint(sc->sc_uadr)+ ((u_short)&sc->sc_sts-(u_short)tcmd); tchar->char_bae = hiint(sc->sc_uadr); tchar->char_size = sizeof(struct ts_sts); tchar->char_mode = TS_ESS; tcmd->c_cmd = TS_ACK | TS_CVC | TS_SETCHR; tcmd->c_loba = (u_short)loint(sc->sc_uadr)+ ((u_short)tchar-(u_short)tcmd); tcmd->c_hiba = hiint(sc->sc_uadr); tcmd->c_size = sizeof(struct ts_char); sc->sc_addr->tsdb = sc->sc_uba; for (cnt = 0; cnt < 10000; cnt++) { if (sc->sc_addr->tssr & TS_SSR) break;