sys/ 755 0 0 0 4156065450 4543 sys/pdpuba/ 755 0 12 0 6046604174 6043 sys/pdpuba/tags 751 0 12 0 6045324612 10643 2../sys/tagssys/pdpuba/dmreg.h 444 0 12 3213 4475701661 7377 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dmreg.h 1.1 (Berkeley) 12/1/86 */ /* * DM-11 device register definitions. */ struct dmdevice { short dmcsr; /* control status register */ union { /* Q22:Need to access high byte independently */ short dmlst_w; char dmlst_b[2]; } cs02un; #define dmlstat cs02un.dmlst_w /* line status register */ #define dmlst_l cs02un.dmlst_b[0] /* low byte */ #define dmlst_h cs02un.dmlst_b[1] /* high byte */ short dmpad1[2]; }; /* bits in dm csr */ #define DM_RF 0100000 /* ring flag */ #define DM_CF 0040000 /* carrier flag */ #define DM_CTS 0020000 /* clear to send */ #define DM_SRF 0010000 /* secondary receive flag */ #define DM_CS 0004000 /* clear scan */ #define DM_CM 0002000 /* clear multiplexor */ #define DM_MM 0001000 /* maintenance mode */ #define DM_STP 0000400 /* step */ #define DM_DONE 0000200 /* scanner is done */ #define DM_IE 0000100 /* interrupt enable */ #define DM_SE 0000040 /* scan enable */ #define DM_BUSY 0000020 /* scan busy */ /* bits in dm lsr */ #define DML_RNG 0000200 /* ring */ #define DML_CAR 0000100 /* carrier detect */ #define DML_CTS 0000040 /* clear to send */ #define DML_SR 0000020 /* secondary receive */ #define DML_ST 0000010 /* secondary transmit */ #define DML_RTS 0000004 /* request to send */ #define DML_DTR 0000002 /* data terminal ready */ #define DML_LE 0000001 /* line enable */ #define DML_ON (DML_DTR|DML_RTS|DML_LE) #define DML_OFF (DML_LE) sys/pdpuba/ht.c 644 0 12 23111 5321512737 6723 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ht.c 2.2 (2.11BSD GTE) 1/2/93 */ /* * TJU77/TWU77/TJE16/TWE16 tape driver */ #include "ht.h" #if NHT > 0 #include "param.h" #include "buf.h" #include "ioctl.h" #include "conf.h" #include "file.h" #include "user.h" #include "mtio.h" #include "fs.h" #include "htreg.h" #include "systm.h" struct buf httab, chtbuf; static short rh70; /* ht.c was ONLY user of B_RH70 and that bit * was wanted for something else (B_LOCKED) */ struct htdevice *HTADDR; #define INF 32760 struct softc { char sc_openf; char sc_lastiow; daddr_t sc_blkno; daddr_t sc_nxrec; u_short sc_erreg; u_short sc_fsreg; short sc_resid; short sc_dens; } tu_softc[NHT]; #define SIO 1 #define SSFOR 2 #define SSREV 3 #define SRETRY 4 #define SCOM 5 #define SOK 6 /* bits in minor device */ #define TUUNIT(dev) (minor(dev) & 03) #define H_NOREWIND 004 #define H_1600BPI 010 htattach(addr, unit) register struct htdevice *addr; { /* * This driver supports only one controller. */ if (unit == 0) { HTADDR = addr; if (fioword(&(addr->htbae)) != -1) rh70 = 1; return(1); } return(0); } htopen(dev, flag) dev_t dev; { register ds; register htunit = TUUNIT(dev); register struct softc *sc = &tu_softc[htunit]; int olddens, dens; httab.b_flags |= B_TAPE; if (!HTADDR || htunit >= NHT) return(ENXIO); if (sc->sc_openf) return(EBUSY); sc->sc_blkno = (daddr_t) 0; sc->sc_nxrec = (daddr_t) INF; sc->sc_lastiow = 0; olddens = sc->sc_dens; dens = sc->sc_dens = ((minor(dev)&H_1600BPI)?HTTC_1600BPI:HTTC_800BPI)| HTTC_PDP11|htunit; ds = htcommand(dev, HT_SENSE, 1); sc->sc_dens = olddens; if ((ds & HTFS_MOL) == 0) { uprintf("tu%d: not online\n", htunit); return(EIO); } if ((flag & FWRITE) && (ds & HTFS_WRL)) { uprintf("tu%d: no write ring\n", htunit); return(EIO); } if ((flag & FWRITE) && (ds & HTFS_BOT) == 0 && dens != sc->sc_dens) { uprintf("tu%d: can't change density in mid-tape\n", htunit); return (EIO); } sc->sc_openf = 1; sc->sc_dens = dens; return(0); } htclose(dev, flag) dev_t dev; { register struct softc *sc = &tu_softc[TUUNIT(dev)]; if (flag == FWRITE || ((flag & FWRITE) && sc->sc_lastiow)) { htcommand(dev, HT_WEOF, 1); htcommand(dev, HT_WEOF, 1); htcommand(dev, HT_SREV, 1); } if ((minor(dev) & H_NOREWIND) == 0) htcommand(dev, HT_REW, 1); sc->sc_openf = 0; } /*ARGSUSED*/ htcommand(dev, com, count) u_short count; dev_t dev; { register s; register struct buf *bp; bp = &chtbuf; s = splbio(); while(bp->b_flags & B_BUSY) { /* * This special check is because B_BUSY never * gets cleared in the non-waiting rewind case. */ if (bp->b_repcnt == 0 && (bp->b_flags & B_DONE)) break; bp->b_flags |= B_WANTED; sleep((caddr_t) bp, PRIBIO); } bp->b_flags = B_BUSY | B_READ; splx(s); bp->b_dev = dev; if (com == HT_SFORW || com == HT_SREV) bp->b_repcnt = count; bp->b_command = com; bp->b_blkno = (daddr_t) 0; htstrategy(bp); /* * In case of rewind from close, don't wait. * This is the only case where count can be 0. */ if (count == 0) return(0); iowait(bp); if(bp->b_flags & B_WANTED) wakeup((caddr_t)bp); bp->b_flags &= B_ERROR; return (bp->b_resid); } htstrategy(bp) register struct buf *bp; { register int s; register struct softc *sc = &tu_softc[TUUNIT(bp->b_dev)]; if (rh70 == 0) mapalloc(bp); if (bp->b_flags & B_PHYS) { sc->sc_blkno = sc->sc_nxrec = dbtofsb(bp->b_blkno); sc->sc_nxrec++; } bp->av_forw = NULL; s = splbio(); if (httab.b_actf == NULL) httab.b_actf = bp; else httab.b_actl->av_forw = bp; httab.b_actl = bp; if (httab.b_active == 0) htstart(); splx(s); } htstart() { register struct buf *bp; register den; daddr_t blkno; register struct softc *sc; loop: if ((bp = httab.b_actf) == NULL) return; sc = &tu_softc[TUUNIT(bp->b_dev)]; sc->sc_erreg = HTADDR->hter; sc->sc_fsreg = HTADDR->htfs; sc->sc_resid = HTADDR->htfc; HTADDR->htcs2 = 0; /* controller 0 - do we need this? */ if ((HTADDR->httc & 03777) != sc->sc_dens) HTADDR->httc = sc->sc_dens; sc->sc_lastiow = 0; if (sc->sc_openf < 0 || HTADDR->htcs2 & HTCS2_NEF || !(HTADDR->htfs & HTFS_MOL)) goto abort; if (bp == &chtbuf) { if (bp->b_command == HT_SENSE) { bp->b_resid = HTADDR->htfs; goto next; } httab.b_active = SCOM; HTADDR->htfc = 0; HTADDR->htcs1 = bp->b_command | HT_IE | HT_GO; return; } if (dbtofsb(bp->b_blkno) > sc->sc_nxrec) goto abort; if (dbtofsb(bp->b_blkno) == sc->sc_nxrec && bp->b_flags & B_READ) { /* * Reading at end of file returns 0 bytes. * Buffer will be cleared (if written) in rwip. */ bp->b_resid = bp->b_bcount; goto next; } if ((bp->b_flags & B_READ) == 0) /* * Writing sets EOF */ sc->sc_nxrec = dbtofsb(bp->b_blkno) + 1; if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) { httab.b_active = SIO; HTADDR->htba = bp->b_un.b_addr; if (rh70) HTADDR->htbae = bp->b_xmem; HTADDR->htfc = -bp->b_bcount; HTADDR->htwc = -(bp->b_bcount >> 1); den = ((bp->b_xmem & 3) << 8) | HT_IE | HT_GO; if(bp->b_flags & B_READ) den |= HT_RCOM; else { if(HTADDR->htfs & HTFS_EOT) { bp->b_resid = bp->b_bcount; bp->b_error = ENXIO; httab.b_active = 0; goto next; } den |= HT_WCOM; } HTADDR->htcs1 = den; } else { if (blkno < dbtofsb(bp->b_blkno)) { httab.b_active = SSFOR; HTADDR->htfc = blkno - dbtofsb(bp->b_blkno); HTADDR->htcs1 = HT_SFORW | HT_IE | HT_GO; } else { httab.b_active = SSREV; HTADDR->htfc = dbtofsb(bp->b_blkno) - blkno; HTADDR->htcs1 = HT_SREV | HT_IE | HT_GO; } } return; abort: bp->b_flags |= B_ERROR; next: httab.b_actf = bp->av_forw; iodone(bp); goto loop; } htintr() { register struct buf *bp; register state; int err, htunit; register struct softc *sc; if ((bp = httab.b_actf) == NULL) return; htunit = TUUNIT(bp->b_dev); sc = &tu_softc[htunit]; sc->sc_erreg = HTADDR->hter; sc->sc_fsreg = HTADDR->htfs; sc->sc_resid = HTADDR->htfc; if ((bp->b_flags & B_READ) == 0) sc->sc_lastiow = 1; state = httab.b_active; httab.b_active = 0; if (HTADDR->htcs1 & HT_TRE) { err = HTADDR->hter; if (HTADDR->htcs2 & HTCS2_ERR || (err & HTER_HARD)) state = 0; if (bp->b_flags & B_PHYS) err &= ~HTER_FCE; if ((bp->b_flags & B_READ) && (HTADDR->htfs & HTFS_PES)) err &= ~(HTER_CSITM | HTER_CORCRC); if ((HTADDR->htfs & HTFS_MOL) == 0) { if(sc->sc_openf) sc->sc_openf = -1; } else if (HTADDR->htfs & HTFS_TM) { HTADDR->htwc = -(bp->b_bcount >> 1); sc->sc_nxrec = dbtofsb(bp->b_blkno); state = SOK; } else if (state && err == 0) state = SOK; if (httab.b_errcnt > 4) printf("tu%d: hard error bn %D er=%b ds=%b\n", htunit, bp->b_blkno, sc->sc_erreg, HTER_BITS, sc->sc_fsreg, HTFS_BITS); htinit(); if (state == SIO && ++httab.b_errcnt < 10) { httab.b_active = SRETRY; sc->sc_blkno++; HTADDR->htfc = -1; HTADDR->htcs1 = HT_SREV | HT_IE | HT_GO; return; } if (state != SOK) { bp->b_flags |= B_ERROR; state = SIO; } } else if (HTADDR->htcs1 & HT_SC) if(HTADDR->htfs & HTFS_ERR) htinit(); switch (state) { case SIO: case SOK: sc->sc_blkno++; case SCOM: httab.b_errcnt = 0; httab.b_actf = bp->av_forw; iodone(bp); bp->b_resid = -(HTADDR->htwc << 1); break; case SRETRY: if((bp->b_flags & B_READ) == 0) { httab.b_active = SSFOR; HTADDR->htcs1 = HT_ERASE | HT_IE | HT_GO; return; } case SSFOR: case SSREV: if(HTADDR->htfs & HTFS_TM) { if(state == SSREV) { sc->sc_nxrec = dbtofsb(bp->b_blkno) - HTADDR->htfc; sc->sc_blkno = sc->sc_nxrec; } else { sc->sc_nxrec = dbtofsb(bp->b_blkno) + HTADDR->htfc - 1; sc->sc_blkno = sc->sc_nxrec + 1; } } else sc->sc_blkno = dbtofsb(bp->b_blkno); break; default: return; } htstart(); } htinit() { register ocs2; register omttc; omttc = HTADDR->httc & 03777; /* preserve old slave select, dens, format */ ocs2 = HTADDR->htcs2 & 07; /* preserve old unit */ HTADDR->htcs2 = HTCS2_CLR; HTADDR->htcs2 = ocs2; HTADDR->httc = omttc; HTADDR->htcs1 = HT_DCLR | HT_GO; } /*ARGSUSED*/ htioctl(dev, cmd, data, flag) dev_t dev; u_int cmd; caddr_t data; int flag; { register struct buf *bp = &chtbuf; register struct softc *sc = &tu_softc[minor(dev)&07]; register callcount; int fcount; struct mtop *mtop; struct mtget *mtget; /* we depend on the values and order of the MT codes here */ static htops[] = {HT_WEOF, HT_SFORW, HT_SREV, HT_SFORW, HT_SREV, HT_REW, HT_REWOFFL, HT_SENSE}; switch (cmd) { case MTIOCTOP: mtop = (struct mtop *)data; switch (mtop->mt_op) { case MTWEOF: callcount = mtop->mt_count; fcount = 1; break; case MTFSF: case MTBSF: callcount = mtop->mt_count; fcount = INF; break; case MTFSR: case MTBSR: callcount = 1; fcount = mtop->mt_count; break; case MTREW: case MTOFFL: case MTNOP: callcount = 1; fcount = 1; break; default: return (ENXIO); } if (callcount <= 0 || fcount <= 0) return (EINVAL); while (--callcount >= 0) { htcommand(dev, htops[mtop->mt_op], fcount); if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && bp->b_resid) return (EIO); if ((bp->b_flags&B_ERROR) || sc->sc_fsreg&HTFS_BOT) break; } return (geterror(bp)); case MTIOCGET: mtget = (struct mtget *)data; mtget->mt_dsreg = sc->sc_fsreg; mtget->mt_erreg = sc->sc_erreg; mtget->mt_resid = sc->sc_resid; mtget->mt_type = MT_ISHT; break; default: return (ENXIO); } return (0); } #endif NHT ((HTADDR->httc & 03777) != sc->sc_dens) HTADDR->httc = sc->sc_dens; sc->sc_lastiow = 0; if (sc->sc_openf < 0 || HTADDR->htcs2 & HTCS2_NEF || !(HTADDR->htfs & HTFS_MOL)) goto abort; if (bp == &chtbuf) { if (bp->b_command == HT_SENSE) { bp->b_resid = HTADDR->htfs; goto next; } httab.b_active = SCOM; HTADDR->htfc = 0; HTADDR->htcs1 = bp->b_command | HT_IE | HT_GO; return; } if (dbtofsb(bp->b_blkno) > sc->sc_nxresys/pdpuba/dhu.c 444 0 12 33705 5667261762 7114 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dhu.c 2.1 (2.11BSD GTE) 11/29/94 */ /* * based on dh.c 6.3 84/03/15 * and on dmf.c 6.2 84/02/16 * * Dave Johnson, Brown University Computer Science * ddj%brown@csnet-relay */ #include "dhu.h" #if NDHU > 0 /* * DHU-11 driver */ #include "param.h" #include "dhureg.h" #include "conf.h" #include "user.h" #include "file.h" #include "ioctl.h" #include "tty.h" #include "clist.h" #include "map.h" #include "proc.h" #include "uba.h" #include "ubavar.h" #include "systm.h" struct uba_device dhuinfo[NDHU]; #define NDHULINE (NDHU*16) #define UNIT(x) (minor(x) & 0177) #ifndef PORTSELECTOR #define ISPEED B9600 #define IFLAGS (EVENP|ODDP|ECHO) #else #define ISPEED B4800 #define IFLAGS (EVENP|ODDP) #endif /* * default receive silo timeout value -- valid values are 2..255 * number of ms. to delay between first char received and receive interrupt * * A value of 20 gives same response as ABLE dh/dm with silo alarm = 0 */ #define DHU_DEF_TIMO 20 /* * Other values for silo timeout register defined here but not used: * receive interrupt only on modem control or silo alarm (3/4 full) */ #define DHU_POLL_TIMO 0 /* * receive interrupt immediately on receive character */ #define DHU_NO_TIMO 1 /* * Local variables for the driver */ /* * Baud rates: no 50, 200, or 38400 baud; all other rates are from "Group B". * EXTA => 19200 baud * EXTB => 2000 baud */ char dhu_speeds[] = { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 8, 10, 11, 13, 14, 9 }; short dhusoftCAR[NDHU]; struct tty dhu_tty[NDHULINE]; int ndhu = NDHULINE; int dhuact; /* mask of active dhu's */ int dhustart(), ttrstrt(); long dhumctl(),dmtodhu(); #if defined(UCB_CLIST) extern ubadr_t clstaddr; #define cpaddr(x) (clstaddr + (ubadr_t)((x) - (char *)cfree)) #else #define cpaddr(x) ((u_short)(x)) #endif /* * Routine called to attach a dhu. * Called duattached for autoconfig. */ duattach(addr,unit) register caddr_t addr; register u_int unit; { register struct uba_device *ui; if (addr && unit < NDHU && !dhuinfo[unit].ui_addr) { ui = &dhuinfo[unit]; ui->ui_unit = unit; ui->ui_addr = addr; ui->ui_alive = 1; return (1); } return (0); } /* * Open a DHU11 line, mapping the clist onto the uba if this * is the first dhu on this uba. Turn on this dhu if this is * the first use of it. */ /*ARGSUSED*/ dhuopen(dev, flag) dev_t dev; { register struct tty *tp; register int unit, dhu; register struct dhudevice *addr; register struct uba_device *ui; int s; unit = UNIT(dev); dhu = unit >> 4; if (dev & 0200) dhusoftCAR[dhu] |= (1<<(unit&0xf)); else dhusoftCAR[dhu] &= ~(1<<(unit&0xf)); if (unit >= NDHULINE || (ui = &dhuinfo[dhu])->ui_alive == 0) return (ENXIO); tp = &dhu_tty[unit]; if (tp->t_state & TS_XCLUDE && u.u_uid != 0) return (EBUSY); addr = (struct dhudevice *)ui->ui_addr; tp->t_addr = (caddr_t)addr; tp->t_oproc = dhustart; /* * While setting up state for this uba and this dhu, * block uba resets which can clear the state. */ s = spl5(); if ((dhuact&(1<dhucsr = DHU_SELECT(0) | DHU_IE; addr->dhutimo = DHU_DEF_TIMO; dhuact |= (1<t_state&TS_ISOPEN) == 0) { ttychars(tp); #ifndef PORTSELECTOR if (tp->t_ispeed == 0) { #else tp->t_state |= TS_HUPCLS; #endif PORTSELECTOR tp->t_ispeed = ISPEED; tp->t_ospeed = ISPEED; tp->t_flags = IFLAGS; #ifndef PORTSELECTOR } #endif PORTSELECTOR tp->t_dev = dev; dhuparam(unit); } /* * Wait for carrier, then process line discipline specific open. */ s = spl5(); if ((dhumctl(dev, (long)DHU_ON, DMSET) & DHU_CAR) || (dhusoftCAR[dhu] & (1<<(unit&0xf)))) tp->t_state |= TS_CARR_ON; while ((tp->t_state & TS_CARR_ON) == 0) { tp->t_state |= TS_WOPEN; sleep((caddr_t)&tp->t_rawq, TTIPRI); } (void) splx(s); return ((*linesw[tp->t_line].l_open)(dev, tp)); } /* * Close a DHU11 line, turning off the modem control. */ /*ARGSUSED*/ dhuclose(dev, flag) dev_t dev; int flag; { register struct tty *tp; register unit; unit = UNIT(dev); tp = &dhu_tty[unit]; (*linesw[tp->t_line].l_close)(tp, flag); (void) dhumctl(unit, (long)DHU_BRK, DMBIC); if ((tp->t_state&(TS_HUPCLS|TS_WOPEN)) || (tp->t_state&TS_ISOPEN)==0) #ifdef PORTSELECTOR { extern int wakeup(); (void) dhumctl(unit, (long)DHU_OFF, DMSET); /* Hold DTR low for 0.5 seconds */ timeout(wakeup, (caddr_t) &tp->t_dev, LINEHZ/2); sleep((caddr_t) &tp->t_dev, PZERO); } #else (void) dhumctl(unit, DHU_OFF, DMSET); #endif PORTSELECTOR ttyclose(tp); } dhuread(dev, uio, flag) dev_t dev; struct uio *uio; { register struct tty *tp = &dhu_tty[UNIT(dev)]; return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); } dhuwrite(dev, uio, flag) dev_t dev; struct uio *uio; { register struct tty *tp = &dhu_tty[UNIT(dev)]; return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); } /* * DHU11 receiver interrupt. */ dhurint(dhu) int dhu; { register struct tty *tp; register c; register struct dhudevice *addr; register struct tty *tp0; register struct uba_device *ui; register line; int overrun = 0; ui = &dhuinfo[dhu]; if (ui == 0 || ui->ui_alive == 0) return; addr = (struct dhudevice *)ui->ui_addr; tp0 = &dhu_tty[dhu<<4]; /* * Loop fetching characters from the silo for this * dhu until there are no more in the silo. */ while ((c = addr->dhurbuf) < 0) { /* (c & DHU_RB_VALID) == on */ line = DHU_RX_LINE(c); tp = tp0 + line; if ((c & DHU_RB_STAT) == DHU_RB_STAT) { /* * modem changed or diag info */ if (c & DHU_RB_DIAG) { /* decode diagnostic messages */ continue; } if (c & DHU_ST_DCD) (void)(*linesw[tp->t_line].l_modem)(tp, 1); else if ((dhusoftCAR[dhu] & (1<t_line].l_modem)(tp, 0) == 0) (void) dhumctl((dhu<<4)|line, DHU_OFF, DMSET); continue; } if ((tp->t_state&TS_ISOPEN) == 0) { wakeup((caddr_t)&tp->t_rawq); #ifdef PORTSELECTOR if ((tp->t_state&TS_WOPEN) == 0) #endif continue; } if (c & DHU_RB_PE) if ((tp->t_flags&(EVENP|ODDP)) == EVENP || (tp->t_flags&(EVENP|ODDP)) == ODDP) continue; if ((c & DHU_RB_DO) && overrun == 0) { printf("dhu%d: silo overflow\n", dhu); overrun = 1; } if (c & DHU_RB_FE) /* * At framing error (break) generate * a null (in raw mode, for getty), or a * interrupt (in cooked/cbreak mode). */ if (tp->t_flags&RAW) c = 0; else #ifdef OLDWAY c = tp->t_intrc; #else c = tp->t_brkc; #endif #if NBK > 0 if (tp->t_line == NETLDISC) { c &= 0x7f; BKINPUT(c, tp); } else #endif (*linesw[tp->t_line].l_rint)(c, tp); } } /* * Ioctl for DHU11. */ /*ARGSUSED*/ dhuioctl(dev, cmd, data, flag) u_int cmd; caddr_t data; { register struct tty *tp; register int unit = UNIT(dev); int error; tp = &dhu_tty[unit]; error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); if (error >= 0) return (error); error = ttioctl(tp, cmd, data, flag); if (error >= 0) { if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLSET || cmd == TIOCLBIC || cmd == TIOCLBIS) dhuparam(unit); return (error); } switch (cmd) { case TIOCSBRK: (void) dhumctl(unit, (long)DHU_BRK, DMBIS); break; case TIOCCBRK: (void) dhumctl(unit, (long)DHU_BRK, DMBIC); break; case TIOCSDTR: (void) dhumctl(unit, (long)DHU_DTR|DHU_RTS, DMBIS); break; case TIOCCDTR: (void) dhumctl(unit, (long)DHU_DTR|DHU_RTS, DMBIC); break; case TIOCMSET: (void) dhumctl(dev, dmtodhu(*(int *)data), DMSET); break; case TIOCMBIS: (void) dhumctl(dev, dmtodhu(*(int *)data), DMBIS); break; case TIOCMBIC: (void) dhumctl(dev, dmtodhu(*(int *)data), DMBIC); break; case TIOCMGET: *(int *)data = dhutodm(dhumctl(dev, 0L, DMGET)); break; default: return (ENOTTY); } return (0); } static long dmtodhu(bits) register int bits; { long b = 0; if (bits & DML_RTS) b |= DHU_RTS; if (bits & DML_DTR) b |= DHU_DTR; if (bits & DML_LE) b |= DHU_LE; return(b); } static dhutodm(bits) long bits; { register int b = 0; if (bits & DHU_DSR) b |= DML_DSR; if (bits & DHU_RNG) b |= DML_RNG; if (bits & DHU_CAR) b |= DML_CAR; if (bits & DHU_CTS) b |= DML_CTS; if (bits & DHU_RTS) b |= DML_RTS; if (bits & DHU_DTR) b |= DML_DTR; if (bits & DHU_LE) b |= DML_LE; return(b); } /* * Set parameters from open or stty into the DHU hardware * registers. */ static dhuparam(unit) register int unit; { register struct tty *tp; register struct dhudevice *addr; register int lpar; int s; tp = &dhu_tty[unit]; addr = (struct dhudevice *)tp->t_addr; /* * Block interrupts so parameters will be set * before the line interrupts. */ s = spl5(); if ((tp->t_ispeed) == 0) { tp->t_state |= TS_HUPCLS; (void)dhumctl(unit, (long)DHU_OFF, DMSET); splx(s); return; } lpar = (dhu_speeds[tp->t_ospeed]<<12) | (dhu_speeds[tp->t_ispeed]<<8); if ((tp->t_ispeed) == B134) lpar |= DHU_LP_BITS6|DHU_LP_PENABLE; else if (tp->t_flags & (RAW|LITOUT|PASS8)) lpar |= DHU_LP_BITS8; else lpar |= DHU_LP_BITS7|DHU_LP_PENABLE; if (tp->t_flags&EVENP) lpar |= DHU_LP_EPAR; if ((tp->t_ospeed) == B110) lpar |= DHU_LP_TWOSB; addr->dhucsr = DHU_SELECT(unit) | DHU_IE; addr->dhulpr = lpar; splx(s); } /* * DHU11 transmitter interrupt. * Restart each line which used to be active but has * terminated transmission since the last interrupt. */ dhuxint(dhu) int dhu; { register struct tty *tp; register struct dhudevice *addr; register struct tty *tp0; register struct uba_device *ui; register int line, t; u_short cntr; ubadr_t base; ui = &dhuinfo[dhu]; tp0 = &dhu_tty[dhu<<4]; addr = (struct dhudevice *)ui->ui_addr; while ((t = addr->dhucsrh) & DHU_CSH_TI) { line = DHU_TX_LINE(t); tp = tp0 + line; tp->t_state &= ~TS_BUSY; if (t & DHU_CSH_NXM) { printf("dhu(%d,%d): NXM fault\n", dhu, line); /* SHOULD RESTART OR SOMETHING... */ } if (tp->t_state&TS_FLUSH) tp->t_state &= ~TS_FLUSH; else { addr->dhucsrl = DHU_SELECT(line) | DHU_IE; base = (ubadr_t) addr->dhubar1; /* * Clists are either: * 1) in kernel virtual space, * which in turn lies in the * first 64K of physical memory or * 2) at UNIBUS virtual address 0. * * In either case, the extension bits are 0. */ if (!ubmap) base |= (ubadr_t)((addr->dhubar2 & 037) << 16); cntr = base - cpaddr(tp->t_outq.c_cf); ndflush(&tp->t_outq,cntr); } if (tp->t_line) (*linesw[tp->t_line].l_start)(tp); else dhustart(tp); } } /* * Start (restart) transmission on the given DHU11 line. */ dhustart(tp) register struct tty *tp; { register struct dhudevice *addr; register int unit, nch; ubadr_t car; int s; unit = minor(tp->t_dev); unit &= 0xf; addr = (struct dhudevice *)tp->t_addr; /* * Must hold interrupts in following code to prevent * state of the tp from changing. */ s = spl5(); /* * If it's currently active, or delaying, no need to do anything. */ if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) goto out; /* * If there are sleepers, and output has drained below low * water mark, wake up the sleepers.. */ if (tp->t_outq.c_cc<=TTLOWAT(tp)) { if (tp->t_state&TS_ASLEEP) { tp->t_state &= ~TS_ASLEEP; wakeup((caddr_t)&tp->t_outq); } if (tp->t_wsel) { selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); tp->t_wsel = 0; tp->t_state &= ~TS_WCOLL; } } /* * Now restart transmission unless the output queue is * empty. */ if (tp->t_outq.c_cc == 0) goto out; if (tp->t_flags & (RAW|LITOUT)) nch = ndqb(&tp->t_outq, 0); else { nch = ndqb(&tp->t_outq, 0200); /* * If first thing on queue is a delay process it. */ if (nch == 0) { nch = getc(&tp->t_outq); timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6); tp->t_state |= TS_TIMEOUT; goto out; } } /* * If characters to transmit, restart transmission. */ if (nch) { car = cpaddr(tp->t_outq.c_cf); addr->dhucsrl = DHU_SELECT(unit) | DHU_IE; addr->dhulcr &= ~DHU_LC_TXABORT; addr->dhubcr = nch; addr->dhubar1 = loint(car); if (ubmap) addr->dhubar2 = (hiint(car) & DHU_BA2_XBA) | DHU_BA2_DMAGO; else addr->dhubar2 = (hiint(car) & 037) | DHU_BA2_DMAGO; tp->t_state |= TS_BUSY; } out: splx(s); } /* * Stop output on a line, e.g. for ^S/^Q or output flush. */ /*ARGSUSED*/ dhustop(tp, flag) register struct tty *tp; { register struct dhudevice *addr; register int unit, s; addr = (struct dhudevice *)tp->t_addr; /* * Block input/output interrupts while messing with state. */ s = spl5(); if (tp->t_state & TS_BUSY) { /* * Device is transmitting; stop output * by selecting the line and setting the * abort xmit bit. We will get an xmit interrupt, * where we will figure out where to continue the * next time the transmitter is enabled. If * TS_FLUSH is set, the outq will be flushed. * In either case, dhustart will clear the TXABORT bit. */ unit = minor(tp->t_dev); addr->dhucsrl = DHU_SELECT(unit) | DHU_IE; addr->dhulcr |= DHU_LC_TXABORT; if ((tp->t_state&TS_TTSTOP)==0) tp->t_state |= TS_FLUSH; } (void) splx(s); } /* * DHU11 modem control */ static long dhumctl(dev, bits, how) dev_t dev; long bits; int how; { register struct dhudevice *dhuaddr; register int unit; long mbits; int s; unit = UNIT(dev); dhuaddr = (struct dhudevice *)(dhu_tty[unit].t_addr); unit &= 0xf; s = spl5(); dhuaddr->dhucsr = DHU_SELECT(unit) | DHU_IE; /* * combine byte from stat register (read only, bits 16..23) * with lcr register (read write, bits 0..15). */ mbits = (u_short)dhuaddr->dhulcr | ((long)dhuaddr->dhustat << 16); switch (how) { case DMSET: mbits = (mbits & 0xff0000L) | bits; break; case DMBIS: mbits |= bits; break; case DMBIC: mbits &= ~bits; break; case DMGET: (void) splx(s); return(mbits); } dhuaddr->dhulcr = (mbits & 0xffff) | DHU_LC_RXEN; dhuaddr->dhulcr2 = DHU_LC2_TXEN; (void) splx(s); return(mbits); } #endif sys/pdpuba/hpreg.h 644 0 0 21476 6003612554 7407 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)hpreg.h 2.0 (2.11BSD) 1995/07/20 */ /* * Definitions for SMD-type disk drives and drivers. */ #define XP_CC 0x1 /* drivedata[0] bit indicating presence of current * cylinder 'hpcc' register. Only set for RP04,5,6,7. */ #define XP_NOSEARCH 0x2 /* drivedata[0] bit indicating lack of search cmd */ /* * Controller registers and bits */ struct hpdevice { union { int w; char c[2]; } hpcs1; /* control and status 1 register */ short hpwc; /* word count register */ caddr_t hpba; /* UNIBUS address register */ short hpda; /* desired address register */ union { int w; char c[2]; } hpcs2; /* control and status 2 register */ short hpds; /* drive status register */ short hper1; /* error register 1 */ short hpas; /* attention summary register */ short hpla; /* look ahead register */ short hpdb; /* data buffer register */ short hpmr; /* maintenance register (1) */ short hpdt; /* drive type register */ short hpsn; /* serial number register */ short hpof; /* offset register */ short hpdc; /* desired cylinder address register */ short hpcc; /* HP: current cylinder register */ #define rmhr hpcc /* RM: holding register */ short hper2; /* HP: error register 2 */ #define rmmr2 hper2 /* RM: maintenance register 2 */ short hper3; /* HP: error register 3 */ #define rmer2 hper3 /* RM: error register 2 */ short hpec1; /* burst error bit position */ short hpec2; /* burst error bit pattern */ short hpbae; /* bus address extension register (RH70 only) */ short hpcs3; /* control and status 3 register (RH70 only) */ }; /* Other bits of hpcs1 */ #define HP_SC 0100000 /* special condition */ #define HP_TRE 0040000 /* transfer error */ #define HP_MCPE 0020000 /* MASSBUS control bus read parity error */ /* bit 12 is unused */ #define HP_DVA 0004000 /* drive available */ /* bits 9 and 8 are the extended address bits */ #define HP_RDY 0000200 /* controller ready */ #define HP_IE 0000100 /* interrupt enable */ /* bits 5-1 are the command */ #define HP_GO 0000001 #define HP_BITS \ "\10\20SC\17TRE\16MCPE\14DVA\10RDY\7IE\1GO" /* commands */ #define HP_NOP 000 #define HP_UNLOAD 002 /* offline drive */ #define HP_SEEK 004 /* seek */ #define HP_RECAL 006 /* recalibrate */ #define HP_DCLR 010 /* drive clear */ #define HP_RELEASE 012 /* release */ #define HP_OFFSET 014 /* offset */ #define HP_RTC 016 /* return to center-line */ #define HP_PRESET 020 /* read-in preset */ #define HP_PACK 022 /* pack acknowledge */ #define HP_SEARCH 030 /* search */ #define HP_WCDATA 050 /* write check data */ #define HP_WCHDR 052 /* write check header and data */ #define HP_WCOM 060 /* write */ #define HP_WHDR 062 /* write header and data */ #define HP_RCOM 070 /* read data */ #define HP_RHDR 072 /* read header and data */ /* The following two are optionally enabled on some non-DEC controllers */ #define HP_BOOT 074 /* boot */ #define HP_FORMAT 076 /* format */ /* hpcs2 */ #define HPCS2_DLT 0100000 /* data late */ #define HPCS2_WCE 0040000 /* write check error */ #define HPCS2_UPE 0020000 /* UNIBUS parity error */ #define HPCS2_NED 0010000 /* nonexistent drive */ #define HPCS2_NEM 0004000 /* nonexistent memory */ #define HPCS2_PGE 0002000 /* programming error */ #define HPCS2_MXF 0001000 /* missed transfer */ #define HPCS2_MDPE 0000400 /* MASSBUS data read parity error */ #define HPCS2_OR 0000200 /* output ready */ #define HPCS2_IR 0000100 /* input ready */ #define HPCS2_CLR 0000040 /* controller clear */ #define HPCS2_PAT 0000020 /* parity test */ #define HPCS2_BAI 0000010 /* address increment inhibit */ /* bits 2-0 are drive select */ #define HPCS2_BITS \ "\10\20DLT\17WCE\16UPE\15NED\14NEM\13PGE\12MXF\11MDPE\ \10OR\7IR\6CLR\5PAT\4BAI" /* hpds */ #define HPDS_ATA 0100000 /* attention active */ #define HPDS_ERR 0040000 /* composite drive error */ #define HPDS_PIP 0020000 /* positioning in progress */ #define HPDS_MOL 0010000 /* medium on line */ #define HPDS_WRL 0004000 /* write locked */ #define HPDS_LST 0002000 /* last sector transferred */ #define HPDS_DAE 0001000 /* dual access enabled (programmable) */ #define HPDS_DPR 0000400 /* drive present */ #define HPDS_DRY 0000200 /* drive ready */ #define HPDS_VV 0000100 /* volume valid */ /* bits 5-3, 1 are spare */ #define HPDS_ILV 0000004 /* interleaved */ #define HPDS_OM 0000001 /* offset mode */ #define HPDS_DREADY (HPDS_DPR|HPDS_DRY|HPDS_MOL|HPDS_VV) #define HPDS_BITS \ "\10\20ATA\17ERR\16PIP\15MOL\14WRL\13LST\12DAE\11DPR\10DRY\7VV\3ILV\1OM" /* hper1 */ #define HPER1_DCK 0100000 /* data check */ #define HPER1_UNS 0040000 /* drive unsafe */ #define HPER1_OPI 0020000 /* operation incomplete */ #define HPER1_DTE 0010000 /* drive timing error */ #define HPER1_WLE 0004000 /* write lock error */ #define HPER1_IAE 0002000 /* invalid address error */ #define HPER1_AOE 0001000 /* address overflow error */ #define HPER1_HCRC 0000400 /* header crc error */ #define HPER1_HCE 0000200 /* header compare error */ #define HPER1_ECH 0000100 /* ecc hard error */ #define HPER1_WCF 0000040 /* write clock fail (0) */ #define HPER1_FER 0000020 /* format error */ #define HPER1_PAR 0000010 /* parity error */ #define HPER1_RMR 0000004 /* register modification refused */ #define HPER1_ILR 0000002 /* illegal register */ #define HPER1_ILF 0000001 /* illegal function */ #define HPER1_BITS \ "\10\20DCK\17UNS\16OPI\15DTE\14WLE\13IAE\12AOE\11HCRC\10HCE\ \7ECH\6WCF\5FER\4PAR\3RMR\2ILR\1ILF" /* hpdt */ #define HPDT_NBA 0100000 /* not block addressed; always 0 */ #define HPDT_TAPE 0040000 /* tape drive; always 0 */ #define HPDT_MH 0020000 /* moving head; always 1 */ /* bit 12 is unused */ #define HPDT_DRR 0004000 /* drive request required */ /* bits 10-9 are unused */ /* bits 8-0 are drive type; the correct values are hard to determine */ #define HPDT_RM02 0000025 /* rm02, possibly rm03? */ #define HPDT_RM80 0000026 /* rm80 */ #define HPDT_RM05 0000027 /* rm05 */ #define HPDT_RM03 0000024 /* rm03 */ #define HPDT_RP04 0000020 /* rp04 */ #define HPDT_RP05 0000021 /* rp05 */ #define HPDT_RP06 0000022 /* rp06 */ #define HPDT_RP07 0000042 /* rp07 */ /* hpof */ #define HPOF_FMT22 0010000 /* 16 bit format */ #define HPOF_ECI 0004000 /* ecc inhibit */ #define HPOF_HCI 0002000 /* header compare inhibit */ /* THE SC21 ACTUALLY JUST IMPLEMENTS ADVANCE/RETARD... */ #define HPOF_P400 0020 /* +400 uinches */ #define HPOF_M400 0220 /* -400 uinches */ #define HPOF_P800 0040 /* +800 uinches */ #define HPOF_M800 0240 /* -800 uinches */ #define HPOF_P1200 0060 /* +1200 uinches */ #define HPOF_M1200 0260 /* -1200 uinches */ #define HPOF_BITS \ "\10\15FMT22\14ECI\13HCI\10OD" /* * rmhr * * Emulex (i.e non DEC) controllers implement the ability to query for * the drive geometry by placing these codes into the 'holding register'. */ #define HPHR_MAXCYL 0x8017 /* max cylinder */ #define HPHR_MAXTRAK 0x8018 /* max track/cylinder */ #define HPHR_MAXSECT 0x8019 /* max sector/track */ /* rmer2: These are the bits for an RM error register 2 */ #define RMER2_BSE 0100000 /* bad sector error */ #define RMER2_SKI 0040000 /* seek incomplete */ #define RMER2_DPE 0020000 /* drive plug error */ #define RMER2_IVC 0010000 /* invalid command */ #define RMER2_LSC 0004000 /* loss of system clock */ #define RMER2_LBC 0002000 /* loss of bit clock */ /* bits 9-8 are unused */ #define RMER2_DVC 0000200 /* device check */ /* bits 6-4 are unused */ #define RMER2_MDPE 0000010 /* MASSBUS data read parity error */ /* bits 2-0 are unused */ #define RMER2_BITS \ "\10\20BSE\17SKI\16DPE\15IVC\14LSC\13LBC\10DVC\4MDPE" /* hpcs3 */ #define HPCS3_APE 0100000 /* address parity error */ #define HPCS3_DPE 0060000 /* data parity error */ #define HPCS3_WCE 0017000 /* write check error */ #define HPCS3_DW 0002000 /* double word */ /* bits 9-8 are unused */ #define HPCS3_IE 0000100 /* interrupt enable */ /* bits 5-4 are unused */ /* bits 3-0 are inverted parity check */ #define HPCS3_BITS \ "\10\20APE\17DPE\15WCE\13DW\7IE" /* * Systems Industries kludge: use value in * the serial # register to figure out real drive type. */ #define SIMB_MB 0xff00 /* model byte value */ #define SIMB_S6 0x2000 /* switch s6 */ #define SIMB_LU 0x0007 /* logical unit (should = drive #) */ #define SI9775D 0x0700 /* 9775 direct */ #define SI9775M 0x0e00 /* 9775 mapped */ #define SI9730D 0x0b00 /* 9730 or 9784 direct */ #define SI9730M 0x0d00 /* 9730 or 9784 mapped */ #define SI9766 0x0300 /* 9766 */ #define SI9762 0x0100 /* 9762 */ #define SICAPD 0x0500 /* Capricorn direct */ #define SICAPN 0x0400 /* Capricorn mapped */ #define SI9751D 0x0f00 /* Eagle direct */ #define SIRM03 0x8000 /* RM03 indication */ #define SIRM05 0x0000 /* RM05 pseudo-indication */ addr = (struct dhudevice *)(dhu_tty[unit].t_addr); unit &= 0xf; s = spl5(); dhuaddr->dhucsr = DHU_SELECT(unit) | DHU_IE; /* * combine byte from stat register (read only, bits 16..23) * wsys/pdpuba/dh.c 444 0 12 34525 5674212713 6716 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dh.c 1.3 (2.11BSD GTE) 11/29/94 */ /* * DH11, DM11 device drivers */ #include "dh.h" #if NDH > 0 /* * DH-11/DM-11 driver */ #include "param.h" #include "conf.h" #include "user.h" #include "file.h" #include "ioctl.h" #include "tty.h" #include "dhreg.h" #include "dmreg.h" #include "map.h" #include "uba.h" #include "ubavar.h" #include "clist.h" #include "systm.h" #include "vm.h" #include "kernel.h" #include "syslog.h" #include "proc.h" int dhtimer(); struct uba_device dhinfo[NDH]; struct uba_device dminfo[NDH]; #ifndef PORTSELECTOR #define ISPEED B9600 #define IFLAGS (EVENP|ODDP|ECHO) #else #define ISPEED B4800 #define IFLAGS (EVENP|ODDP) #endif #define FASTTIMER (LINEHZ/30) /* scan rate with silos on */ /* * Local variables for the driver */ short dhsar[NDH]; /* software copy of last bar */ short dhsoftCAR[NDH]; struct tty dh11[NDH*16]; int ndh11 = NDH*16; int dhact; /* mask of active dh's */ int dhsilos; /* mask of dh's with silo in use */ int dhchars[NDH]; /* recent input count */ int dhrate[NDH]; /* smoothed input count */ int dhhighrate = 100; /* silo on if dhchars > dhhighrate */ int dhlowrate = 75; /* silo off if dhrate < dhlowrate */ static short timerstarted; int dhstart(), ttrstrt(); #if defined(UCB_CLIST) extern ubadr_t clstaddr; #define cpaddr(x) (clstaddr + (ubadr_t)((x) - (char *)cfree)) #else #define cpaddr(x) (x) #endif #define UNIT(x) (minor(x) & 0177) /* * Routine called to attach a dh. */ dhattach(addr, unit) register caddr_t addr; register u_int unit; { register struct uba_device *ui; if (addr && unit < NDH && !dhinfo[unit].ui_addr) { ui = &dhinfo[unit]; ui->ui_unit = unit; ui->ui_addr = addr; ui->ui_alive = 1; return (1); } return (0); } /*ARGSUSED*/ dmattach(addr, unit) register caddr_t addr; register u_int unit; { register struct uba_device *ui; if (addr && unit < NDH && !dminfo[unit].ui_addr) { ui = &dminfo[unit]; ui->ui_unit = unit; ui->ui_addr = addr; ui->ui_alive = 1; return (1); } return (0); } /* * Open a DH11 line. Turn on this dh if this is * the first use of it. Also do a dmopen to wait for carrier. */ /*ARGSUSED*/ dhopen(dev, flag) dev_t dev; { register struct tty *tp; register int unit, dh; register struct dhdevice *addr; register struct uba_device *ui; int s; unit = UNIT(dev); dh = unit >> 4; if (unit >= NDH*16 || (ui = &dhinfo[dh])->ui_alive == 0) return (ENXIO); tp = &dh11[unit]; if (tp->t_state&TS_XCLUDE && u.u_uid!=0) return (EBUSY); addr = (struct dhdevice *)ui->ui_addr; tp->t_addr = (caddr_t)addr; tp->t_oproc = dhstart; tp->t_state |= TS_WOPEN; /* * While setting up state for this uba and this dh, * block uba resets which can clear the state. */ s = spl5(); if (timerstarted == 0) { timerstarted++; timeout(dhtimer, (caddr_t) 0, LINEHZ); } if ((dhact&(1<un.dhcsr |= DH_IE; dhact |= (1<dhsilo = 0; } splx(s); /* * If this is first open, initialize tty state to default. */ if ((tp->t_state&TS_ISOPEN) == 0) { ttychars(tp); #ifndef PORTSELECTOR if (tp->t_ispeed == 0) { #else tp->t_state |= TS_HUPCLS; #endif PORTSELECTOR tp->t_ispeed = ISPEED; tp->t_ospeed = ISPEED; tp->t_flags = IFLAGS; #ifndef PORTSELECTOR } #endif dhparam(unit); } dmopen(dev); return ((*linesw[tp->t_line].l_open)(dev, tp)); } /* * Close a DH line, turning off the DM11. */ /*ARGSUSED*/ dhclose(dev, flag) dev_t dev; int flag; { register struct tty *tp; register unit; unit = UNIT(dev); tp = &dh11[unit]; (*linesw[tp->t_line].l_close)(tp, flag); ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017)); if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0) dmctl(unit, DML_OFF, DMSET); ttyclose(tp); } dhread(dev, uio, flag) dev_t dev; struct uio *uio; int flag; { register struct tty *tp = &dh11[UNIT(dev)]; return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); } dhwrite(dev, uio, flag) dev_t dev; struct uio *uio; { register struct tty *tp = &dh11[UNIT(dev)]; return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); } /* * DH11 receiver interrupt. */ dhrint(dh) int dh; { register struct tty *tp; register int c; register struct dhdevice *addr; struct tty *tp0; struct uba_device *ui; int overrun = 0; ui = &dhinfo[dh]; if (ui == 0 || ui->ui_alive == 0) return; addr = (struct dhdevice *)ui->ui_addr; tp0 = &dh11[dh<<4]; /* * Loop fetching characters from the silo for this * dh until there are no more in the silo. */ while ((c = addr->dhrcr) < 0) { tp = tp0 + ((c>>8)&0xf); dhchars[dh]++; if ((tp->t_state&TS_ISOPEN)==0) { wakeup((caddr_t)&tp->t_rawq); #ifdef PORTSELECTOR if ((tp->t_state&TS_WOPEN) == 0) #endif continue; } if (c & DH_PE) if ((tp->t_flags & (EVENP|ODDP)) == EVENP || (tp->t_flags & (EVENP|ODDP)) == ODDP) continue; if ((c & DH_DO) && overrun == 0) { log(LOG_WARNING, "dh%d: silo overflow\n", dh); overrun = 1; } if (c & DH_FE) /* * At framing error (break) generate * a null (in raw mode, for getty), or an * interrupt (in cooked/cbreak mode). */ if (tp->t_flags & RAW) c = 0; else #ifdef OLDWAY c = tp->t_intrc; #else c = tp->t_brkc; /* why have brkc if not used? */ #endif #if NBK > 0 if (tp->t_line == NETLDISC) { c &= 0177; BKINPUT(c, tp); } else #endif (*linesw[tp->t_line].l_rint)(c, tp); } } /* * Ioctl for DH11. */ /*ARGSUSED*/ dhioctl(dev, cmd, data, flag) u_int cmd; caddr_t data; { register struct tty *tp; register unit = UNIT(dev); int error; tp = &dh11[unit]; error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); if (error >= 0) return (error); error = ttioctl(tp, cmd, data, flag); if (error >= 0) { if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS || cmd == TIOCLBIC || cmd == TIOCLSET) dhparam(unit); return (error); } switch (cmd) { case TIOCSBRK: ((struct dhdevice *)(tp->t_addr))->dhbreak |= 1<<(unit&017); break; case TIOCCBRK: ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017)); break; case TIOCSDTR: dmctl (unit, DML_DTR|DML_RTS, DMBIS); break; case TIOCCDTR: dmctl (unit, DML_DTR|DML_RTS, DMBIC); break; default: return (ENOTTY); } return (0); } /* * Set parameters from open or stty into the DH hardware * registers. */ dhparam(unit) register int unit; { register struct tty *tp; register struct dhdevice *addr; register int lpar; int s; tp = &dh11[unit]; addr = (struct dhdevice *)tp->t_addr; /* * Block interrupts so parameters will be set * before the line interrupts. */ s = spl5(); addr->un.dhcsrl = (unit&0xf)|DH_IE; if ((tp->t_ispeed)==0) { tp->t_state |= TS_HUPCLS; dmctl(unit, DML_OFF, DMSET); splx(s); return; } lpar = ((tp->t_ospeed)<<10) | ((tp->t_ispeed)<<6); if ((tp->t_ispeed) == B134) lpar |= BITS6|PENABLE|HDUPLX; else if (tp->t_flags & (RAW|LITOUT|PASS8)) lpar |= BITS8; else lpar |= BITS7|PENABLE; if ((tp->t_flags&EVENP) == 0) lpar |= OPAR; if ((tp->t_ospeed) == B110) lpar |= TWOSB; addr->dhlpr = lpar; splx(s); } /* * DH transmitter interrupt. * Restart each line which used to be active but has * terminated transmission since the last interrupt. */ dhxint(dh) int dh; { register struct tty *tp; register struct dhdevice *addr; short ttybit, bar, *sbar; struct uba_device *ui; register int unit; u_short cntr; ubadr_t car; struct dmdevice *dmaddr; ui = &dhinfo[dh]; addr = (struct dhdevice *)ui->ui_addr; if (addr->un.dhcsr & DH_NXM) { addr->un.dhcsr |= DH_CNI; printf("dh%d: NXM\n", dh); } sbar = &dhsar[dh]; bar = *sbar & ~addr->dhbar; unit = dh * 16; ttybit = 1; addr->un.dhcsr &= (short)~DH_TI; for(; bar; unit++, ttybit <<= 1) { if(bar & ttybit) { *sbar &= ~ttybit; bar &= ~ttybit; tp = &dh11[unit]; tp->t_state &= ~TS_BUSY; if (tp->t_state&TS_FLUSH) tp->t_state &= ~TS_FLUSH; else { addr->un.dhcsrl = (unit&017)|DH_IE; /* * Clists are either: * 1) in kernel virtual space, * which in turn lies in the * first 64K of physical memory or * 2) at UNIBUS virtual address 0. * * In either case, the extension bits are 0. */ car = (caddr_t)addr->dhcar; if (!ubmap) { #if defined(CS02) dmaddr = (struct dmdevice *)dminfo[dh].ui_addr; car |= ((ubadr_t)(dmaddr->dmlst_h&077) << 16); #else car |= (ubadr_t)((addr->dhsilo & 0300) << 10); #endif } cntr = car - cpaddr(tp->t_outq.c_cf); ndflush(&tp->t_outq, cntr); } if (tp->t_line) (*linesw[tp->t_line].l_start)(tp); else dhstart(tp); } } } /* * Start (restart) transmission on the given DH11 line. */ dhstart(tp) register struct tty *tp; { register struct dhdevice *addr; register int dh, unit, nch; int s, csrl; ubadr_t uba; struct dmdevice *dmaddr; unit = UNIT(tp->t_dev); dh = unit >> 4; unit &= 0xf; addr = (struct dhdevice *)tp->t_addr; /* * Must hold interrupts in following code to prevent * state of the tp from changing. */ s = spl5(); /* * If it's currently active, or delaying, no need to do anything. */ if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) goto out; /* * If there are sleepers, and the output has drained below low * water mark, wake up the sleepers. */ if (tp->t_outq.c_cc<=TTLOWAT(tp)) { if (tp->t_state&TS_ASLEEP) { tp->t_state &= ~TS_ASLEEP; wakeup((caddr_t)&tp->t_outq); } if (tp->t_wsel) { selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); tp->t_wsel = 0; tp->t_state &= ~TS_WCOLL; } } /* * Now restart transmission unless the output queue is * empty. */ if (tp->t_outq.c_cc == 0) goto out; if (tp->t_flags & (RAW|LITOUT)) nch = ndqb(&tp->t_outq, 0); else { nch = ndqb(&tp->t_outq, 0200); /* * If first thing on queue is a delay, process it. */ if (nch == 0) { nch = getc(&tp->t_outq); timeout(ttrstrt, (caddr_t) tp, (nch&0x7f)+6); tp->t_state |= TS_TIMEOUT; goto out; } } /* * If characters to transmit, restart transmission. */ if (nch) { uba = cpaddr(tp->t_outq.c_cf); csrl = (unit&017) | DH_IE; if (ubmap) addr->un.dhcsrl = (char)csrl; else { #if defined(CS02) dmaddr = (struct dmdevice *)dminfo[dh].ui_addr; addr->un.dhcsrl = csrl; dmaddr->dmlst_h = hiint(uba) & 077; #else addr->un.dhcsrl = csrl | DH_IE | ((hiint(uba)<<4)&060); #endif } addr->dhcar = loint(uba); { short word = 1 << unit; dhsar[dh] |= word; addr->dhbcr = -nch; addr->dhbar |= word; } tp->t_state |= TS_BUSY; } out: splx(s); } /* * Stop output on a line, e.g. for ^S/^Q or output flush. */ /*ARGSUSED*/ dhstop(tp, flag) register struct tty *tp; { register struct dhdevice *addr; register int unit, s; addr = (struct dhdevice *)tp->t_addr; /* * Block input/output interrupts while messing with state. */ s = spl5(); if (tp->t_state & TS_BUSY) { /* * Device is transmitting; stop output * by selecting the line and setting the byte * count to -1. We will clean up later * by examining the address where the dh stopped. */ unit = UNIT(tp->t_dev); addr->un.dhcsrl = (unit&017) | DH_IE; if ((tp->t_state & TS_TTSTOP) == 0) { tp->t_state |= TS_FLUSH; } addr->dhbcr = -1; } splx(s); } int dhtransitions, dhslowtimers, dhfasttimers; /*DEBUG*/ /* * At software clock interrupt time, check status. * Empty all the dh silos that are in use, and decide whether * to turn any silos off or on. */ dhtimer() { register int dh, s; static int timercalls; if (dhsilos) { dhfasttimers++; /*DEBUG*/ timercalls++; s = spl5(); for (dh = 0; dh < NDH; dh++) if (dhsilos & (1 << dh)) dhrint(dh); splx(s); } if ((dhsilos == 0) || ((timercalls += FASTTIMER) >= hz)) { dhslowtimers++; /*DEBUG*/ timercalls = 0; for (dh = 0; dh < NDH; dh++) { ave(dhrate[dh], dhchars[dh], 8); if ((dhchars[dh] > dhhighrate) && ((dhsilos & (1 << dh)) == 0)) { ((struct dhdevice *)(dhinfo[dh].ui_addr))->dhsilo = (dhchars[dh] > 500? 32 : 16); dhsilos |= (1 << dh); dhtransitions++; /*DEBUG*/ } else if ((dhsilos & (1 << dh)) && (dhrate[dh] < dhlowrate)) { ((struct dhdevice *)(dhinfo[dh].ui_addr))->dhsilo = 0; dhsilos &= ~(1 << dh); } dhchars[dh] = 0; } } timeout(dhtimer, (caddr_t) 0, dhsilos ? FASTTIMER : LINEHZ); } /* * Turn on the line associated with dh dev. */ dmopen(dev) dev_t dev; { register struct tty *tp; register struct dmdevice *addr; register struct uba_device *ui; register int unit; register int dm; int s; unit = UNIT(dev); dm = unit >> 4; tp = &dh11[unit]; unit &= 0xf; if (dev & 0200) dhsoftCAR[dm] |= (1<<(unit&0xf)); else dhsoftCAR[dm] &= ~(1<<(unit&0xf)); if (dm >= NDH || (ui = &dminfo[dm])->ui_alive == 0) { tp->t_state |= TS_CARR_ON; return; } addr = (struct dmdevice *)ui->ui_addr; s = spl5(); addr->dmcsr &= ~DM_SE; while (addr->dmcsr & DM_BUSY) ; addr->dmcsr = unit & 017; addr->dmlstat = DML_ON; if ((addr->dmlstat&DML_CAR) || (dhsoftCAR[dm]&(1<t_state |= TS_CARR_ON; addr->dmcsr = DM_IE|DM_SE; while ((tp->t_state & TS_CARR_ON)==0) sleep((caddr_t) &tp->t_rawq, TTIPRI); splx(s); } /* * Dump control bits into the DM registers. */ dmctl(unit, bits, how) int unit; int bits, how; { register struct uba_device *ui; register struct dmdevice *addr; register s; int dm; dm = unit >> 4; if ((ui = &dminfo[dm])->ui_alive == 0) return; addr = (struct dmdevice *)ui->ui_addr; s = spl5(); addr->dmcsr &= ~DM_SE; while (addr->dmcsr & DM_BUSY) ; addr->dmcsr = unit & 0xf; switch (how) { case DMSET: addr->dmlstat = bits; break; case DMBIS: addr->dmlstat |= bits; break; case DMBIC: addr->dmlstat &= ~bits; break; } addr->dmcsr = DM_IE|DM_SE; splx(s); } /* * DM interrupt; deal with carrier transitions. */ dmintr(dm) register int dm; { register struct uba_device *ui; register struct tty *tp; register struct dmdevice *addr; int unit; ui = &dminfo[dm]; if (ui == 0) return; addr = (struct dmdevice *)ui->ui_addr; if (addr->dmcsr&DM_DONE) { if (addr->dmcsr&DM_CF) { unit = addr->dmcsr & 0xf; tp = &dh11[(dm << 4) + unit]; if (addr->dmlstat & DML_CAR) (void)(*linesw[tp->t_line].l_modem)(tp, 1); else if ((dhsoftCAR[dm] & (1<t_line].l_modem)(tp, 0) == 0) addr->dmlstat = 0; } addr->dmcsr = DM_IE|DM_SE; } } #endif *tp0; struct uba_device *ui; int overrun = 0; ui = &dhinfo[dh]; if (ui == 0 || ui->ui_alive == 0) return; addr = (struct dhdevice *)ui->ui_addr; tp0 = &dh11[dh< 0 #include "param.h" #include "../machine/seg.h" #include "systm.h" #include "buf.h" #include "conf.h" #include "user.h" #include "hpreg.h" #include "dkbad.h" #include "dk.h" #include "disklabel.h" #include "disk.h" #include "file.h" #include "map.h" #include "uba.h" #include "stat.h" #include "syslog.h" #define XP_SDIST 2 #define XP_RDIST 6 /* * 'xp' is unique amoung 2.11BSD disk drivers. Drives are not organized * into groups of 8 drives per controller. Instead drives are numbered * across controllers: the second drive ("unit 1") could be on the 2nd * controller. This has the effect of turning the high 5 bits of the minor * device number into the unit number and drives are thus numbered 0 thru 31. * * NOTE: this is different than /boot's view of the world. Sigh. */ #define XPUNIT(dev) ((minor(dev) >> 3) & 0x1f) int xp_offset[] = { HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, 0, 0, 0, 0, }; struct xp_controller { struct buf *xp_actf; /* pointer to next active xputab */ struct buf *xp_actl; /* pointer to last active xputab */ struct hpdevice *xp_addr; /* csr address */ char xp_rh70; /* massbus flag */ char xp_active; /* nonzero if doing a transfer */ }; struct xp_drive { struct xp_controller *xp_ctlr; /* controller to which slave attached */ int xp_unit; /* slave number */ u_short xp_nsect; u_short xp_ntrack; u_short xp_nspc; /* sectors/cylinder */ u_short xp_cc; /* current cylinder, for RM's */ u_long xp_dd0; /* drivedata longword 0 */ struct dkdevice xp_dk; /* kernel resident portion of label */ u_short xp_ncyl; /* cylinders per pack */ }; /* * Some shorthand for accessing the in-kernel label structure. */ #define xp_bopen xp_dk.dk_bopenmask #define xp_copen xp_dk.dk_copenmask #define xp_open xp_dk.dk_openmask #define xp_flags xp_dk.dk_flags #define xp_label xp_dk.dk_label #define xp_parts xp_dk.dk_parts struct xp_controller xp_controller[NXPC]; struct xp_drive xp_drive[NXPD]; struct buf xptab; struct buf xputab[NXPD]; #ifdef BADSECT struct dkbad xpbad[NXPD]; struct buf bxpbuf[NXPD]; #endif #ifdef UCB_METER static int xp_dkn = -1; /* number for iostat */ #endif int xpstrategy(); void xpgetinfo(); daddr_t xpsize(); extern size_t physmem; /* * Setup root SMD ('xp') device (use bootcsr passed from ROMs). In the event * that the system was not booted from a SMD drive but swapdev is a SMD device * we attach the first (0176700) controller. This would be a very unusual * configuration and is unlikely to be encountered. * * This is very confusing, it is an ugly hack, but short of moving autoconfig * back into the kernel there's nothing else I can think of to do. * * NOTE: the swap device must be on the controller used for booting since * that is the only one attached here - the other controllers are attached * by /etc/autoconfig when it runs later. */ xproot(csr) register struct hpdevice *csr; { if (!csr) /* XXX */ csr = (struct hpdevice *)0176700; /* XXX */ xpattach(csr, 0); } /* * Attach controller at xpaddr. Mark as nonexistent if xpaddr is 0; otherwise * attach slaves. This routine must be called once per controller * in ascending controller numbers. * * NOTE: This means that the 'xp' lines in /etc/dtab _MUST_ be in order * starting with 'xp 0' first. */ xpattach(xpaddr, unit) register struct hpdevice *xpaddr; int unit; /* controller number */ { register struct xp_controller *xc = &xp_controller[unit]; static int last_attached = -1; #ifdef UCB_METER if (xp_dkn < 0) dk_alloc(&xp_dkn, NXPD+NXPC, "xp", 0L); #endif if ((unsigned)unit >= NXPC) return(0); if (xpaddr && (fioword(xpaddr) != -1)) { xc->xp_addr = xpaddr; if (fioword(&xpaddr->hpbae) != -1) xc->xp_rh70 = 1; /* * If already attached, ignore (don't want to renumber drives) */ if (unit > last_attached) { last_attached = unit; xpslave(xpaddr, xc); } return(1); } xc->xp_addr = 0; return(0); } /* * Determine what drives are attached to a controller; the type and geometry * information will be retrieved at open time from the disklabel. */ xpslave(xpaddr, xc) register struct hpdevice *xpaddr; struct xp_controller *xc; { register struct xp_drive *xd; register struct xpst *st; int j, dummy; static int nxp = 0; for (j = 0; j < 8; j++) { xpaddr->hpcs1.w = HP_NOP; xpaddr->hpcs2.w = j; xpaddr->hpcs1.w = HP_GO; /* testing... */ delay(6000L); dummy = xpaddr->hpds; if (xpaddr->hpcs2.w & HPCS2_NED) { xpaddr->hpcs2.w = HPCS2_CLR; continue; } if (nxp < NXPD) { xd = &xp_drive[nxp++]; xd->xp_ctlr = xc; xd->xp_unit = j; /* * Allocate the disklabel now. This is very early in the system's life * so fragmentation will be minimized if any labels are allocated from * main memory. Then initialize the flags to indicate a drive is present. */ xd->xp_label = disklabelalloc(); xd->xp_flags = DKF_ALIVE; } } } xpopen(dev, flags, mode) dev_t dev; int flags, mode; { register struct xp_drive *xd; int unit = XPUNIT(dev); int i, part = dkpart(dev), rpm; register int mask; if (unit >= NXPD) return(ENXIO); xd = &xp_drive[unit]; if ((xd->xp_flags & DKF_ALIVE) == 0) return(ENXIO); /* * Now we read the label. First wait for any pending opens/closes to * complete. */ while (xd->xp_flags & (DKF_OPENING|DKF_CLOSING)) sleep(xd, PRIBIO); /* * On first open get label (which has the geometry information as well as * the partition tables). We may block reading the label so be careful to * stop any other opens. */ if (xd->xp_open == 0) { xd->xp_flags |= DKF_OPENING; xpgetinfo(xd, dev); xd->xp_flags &= ~DKF_OPENING; wakeup(xd); } /* * Need to make sure the partition is not out of bounds. This requires * mapping in the external label. Since this only happens when a partition * is opened (at mount time for example) it is unlikely to be an efficiency * concern. */ mapseg5(xd->xp_label, LABELDESC); i = ((struct disklabel *)SEG5)->d_npartitions; rpm = ((struct disklabel *)SEG5)->d_rpm; normalseg5(); if (part >= i) return(ENXIO); #ifdef UCB_METER if (xp_dkn >= 0) dk_wps[xd - xp_drive] = (long) xd->xp_nsect * (rpm / 60) * 256L; #endif mask = 1 << part; dkoverlapchk(xd->xp_open, dev, xd->xp_label, "xp"); if (mode == S_IFCHR) xd->xp_copen |= mask; else if (mode == S_IFBLK) xd->xp_bopen |= mask; else return(EINVAL); xd->xp_open |= mask; return(0); } xpclose(dev, flags, mode) dev_t dev; int flags, mode; { int s; register int mask; register struct xp_drive *xd; int unit = XPUNIT(dev); xd = &xp_drive[unit]; mask = 1 << dkpart(dev); if (mode == S_IFCHR) xd->xp_copen &= ~mask; else if (mode == S_IFBLK) xd->xp_bopen &= ~mask; else return(EINVAL); xd->xp_open = xd->xp_copen | xd->xp_bopen; if (xd->xp_open == 0) { xd->xp_flags |= DKF_CLOSING; s = splbio(); while (xputab[unit].b_actf) sleep(&xputab[unit], PRIBIO); xd->xp_flags &= ~DKF_CLOSING; splx(s); wakeup(xd); } return(0); } void xpdfltlbl(xd, lp) register struct xp_drive *xd; register struct disklabel *lp; { register struct partition *pi = &lp->d_partitions[0]; /* * NOTE: partition 0 ('a') is used to read the label. Therefore 'a' must * start at the beginning of the disk! If there is no label or the label * is corrupted then a label containing a geometry sufficient *only* to * read/write sector 1 (LABELSECTOR) is created. 1 track, 1 cylinder and * 2 sectors per track. */ bzero(lp, sizeof (*lp)); lp->d_type = DTYPE_SMD; lp->d_secsize = 512; /* XXX */ lp->d_nsectors = LABELSECTOR + 1; /* # sectors/track */ lp->d_ntracks = 1; /* # tracks/cylinder */ lp->d_secpercyl = LABELSECTOR + 1; /* # sectors/cylinder */ lp->d_ncylinders = 1; /* # cylinders */ lp->d_npartitions = 1; /* 1 partition = 'a' */ /* * Need to put the information where the driver expects it. This is normally * done after reading the label. Since we're creating a fake label we have to * copy the invented geometry information to the right place. */ xd->xp_nsect = lp->d_nsectors; xd->xp_ntrack = lp->d_ntracks; xd->xp_nspc = lp->d_secpercyl; xd->xp_ncyl = lp->d_ncylinders; xd->xp_dd0 = lp->d_drivedata[0]; pi->p_size = LABELSECTOR + 1; pi->p_fstype = FS_V71K; pi->p_frag = 1; pi->p_fsize = 1024; bcopy(pi, xd->xp_parts, sizeof (lp->d_partitions)); } /* * Read disklabel. It is tempting to generalize this routine so that * all disk drivers could share it. However by the time all of the * necessary parameters are setup and passed the savings vanish. Also, * each driver has a different method of calculating the number of blocks * to use if one large partition must cover the disk. * * This routine used to always return success and callers carefully checked * the return status. Silly. This routine will fake a label (a single * partition spanning the drive) if necessary but will never return an error. * * It is the caller's responsibility to check the validity of partition * numbers, etc. */ void xpgetinfo(xd, dev) register struct xp_drive *xd; dev_t dev; { struct disklabel locallabel; char *msg; register struct disklabel *lp = &locallabel; xpdfltlbl(xd, lp); msg = readdisklabel((dev & ~7) | 0, xpstrategy, lp); /* 'a' */ if (msg != 0) { log(LOG_NOTICE, "xp%da using labelonly geometry: %s\n", XPUNIT(dev), msg); xpdfltlbl(xd, lp); } mapseg5(xd->xp_label, LABELDESC); bcopy(lp, (struct disklabel *)SEG5, sizeof (struct disklabel)); normalseg5(); bcopy(lp->d_partitions, xd->xp_parts, sizeof (lp->d_partitions)); xd->xp_nsect = lp->d_nsectors; xd->xp_ntrack = lp->d_ntracks; xd->xp_nspc = lp->d_secpercyl; xd->xp_ncyl = lp->d_ncylinders; xd->xp_dd0 = lp->d_drivedata[0]; return; } xpstrategy(bp) register struct buf *bp; { register struct xp_drive *xd; register struct partition *pi; int unit, part; struct buf *dp; int s; daddr_t sz; unit = XPUNIT(bp->b_dev); part = dkpart(bp->b_dev); xd = &xp_drive[unit]; if (unit >= NXPD || !xd->xp_ctlr || !(xd->xp_flags & DKF_ALIVE)) { bp->b_error = ENXIO; goto bad; } pi = &xd->xp_parts[part]; sz = (bp->b_bcount + 511) >> 9; if (bp->b_blkno < 0 || bp->b_blkno + sz > pi->p_size) { sz = pi->p_size - bp->b_blkno; /* If exactly at end of disk, return an EOF */ if (sz == 0) { bp->b_resid = bp->b_bcount; goto done; } /* or truncate if part of it fits */ if (sz < 0) { bp->b_error = EINVAL; goto bad; } bp->b_bcount = dbtob(sz); /* compute byte count */ } /* * Check for write to write-protected label area. This does not include * sector 0 which is the boot block. */ if (bp->b_blkno + pi->p_offset <= LABELSECTOR && bp->b_blkno + pi->p_offset + sz > LABELSECTOR && !(bp->b_flags & B_READ) && !(xd->xp_flags & DKF_WLABEL)) { bp->b_error = EROFS; goto bad; } if (xd->xp_ctlr->xp_rh70 == 0) mapalloc(bp); bp->b_cylin = (bp->b_blkno + pi->p_offset) / xd->xp_nspc; dp = &xputab[unit]; s = splbio(); disksort(dp, bp); if (dp->b_active == 0) { xpustart(unit); if (xd->xp_ctlr->xp_active == 0) xpstart(xd->xp_ctlr); } splx(s); return; bad: bp->b_flags |= B_ERROR; done: iodone(bp); return; } /* * Unit start routine. Seek the drive to where the data are and then generate * another interrupt to actually start the transfer. If there is only one * drive or we are very close to the data, don't bother with the search. If * called after searching once, don't bother to look where we are, just queue * for transfer (to avoid positioning forever without transferring). */ xpustart(unit) int unit; { register struct xp_drive *xd; register struct hpdevice *xpaddr; register struct buf *dp; struct buf *bp, *bbp; daddr_t bn; int sn, cn, csn; xd = &xp_drive[unit]; xpaddr = xd->xp_ctlr->xp_addr; xpaddr->hpcs2.w = xd->xp_unit; xpaddr->hpcs1.c[0] = HP_IE; xpaddr->hpas = 1 << xd->xp_unit; #ifdef UCB_METER if (xp_dkn >= 0) dk_busy &= ~(1 << (xp_dkn + unit)); #endif dp = &xputab[unit]; if ((bp=dp->b_actf) == NULL) return; /* * If we have already positioned this drive, * then just put it on the ready queue. */ if (dp->b_active) goto done; dp->b_active++; /* * If drive has just come up, set up the pack. */ if (((xpaddr->hpds & HPDS_VV) == 0) || !(xd->xp_flags & DKF_ONLINE)) { xpaddr->hpcs1.c[0] = HP_IE | HP_PRESET | HP_GO; xpaddr->hpof = HPOF_FMT22; xd->xp_flags |= DKF_ONLINE; #ifdef XPDEBUG log(LOG_NOTICE, "xp%d preset done\n", unit); #endif } /* * XXX - The 'h' partition is used below to access the bad block area. This * XXX - will almost certainly be wrong if the user has defined another * XXX - partition to span the entire drive including the bad block area. It * XXX - is not known what to do about this. */ #ifdef BADSECT bbp = &bxpbuf[unit]; bbp->b_flags = B_READ | B_BUSY | B_PHYS; bbp->b_dev = bp->b_dev | 7; /* "h" partition whole disk */ bbp->b_bcount = sizeof(struct dkbad); bbp->b_un.b_addr = (caddr_t)&xpbad[unit]; bbp->b_blkno = (daddr_t)xd->xp_ncyl * xd->xp_nspc - xd->xp_nsect; bbp->b_cylin = xd->xp_ncyl - 1; if (xd->xp_ctlr->xp_rh70 == 0) mapalloc(bbp); dp->b_actf = bbp; bbp->av_forw = bp; bp = bbp; #endif BADSECT #if NXPD > 1 /* * If drive is offline, forget about positioning. */ if (xpaddr->hpds & (HPDS_DREADY) != (HPDS_DREADY)) { xd->xp_flags &= ~DKF_ONLINE; goto done; } /* * Figure out where this transfer is going to * and see if we are close enough to justify not searching. */ bn = bp->b_blkno; cn = bp->b_cylin; sn = bn % xd->xp_nspc; sn += xd->xp_nsect - XP_SDIST; sn %= xd->xp_nsect; if ((!(xd->xp_dd0 & XP_CC) && (xd->xp_cc != cn)) || xpaddr->hpcc != cn) goto search; if (xd->xp_dd0 & XP_NOSEARCH) goto done; csn = (xpaddr->hpla >> 6) - sn + XP_SDIST - 1; if (csn < 0) csn += xd->xp_nsect; if (csn > xd->xp_nsect - XP_RDIST) goto done; search: xpaddr->hpdc = cn; xpaddr->hpda = sn; xpaddr->hpcs1.c[0] = (xd->xp_dd0 & XP_NOSEARCH) ? (HP_IE | HP_SEEK | HP_GO) : (HP_IE | HP_SEARCH | HP_GO); xd->xp_cc = cn; #ifdef UCB_METER /* * Mark unit busy for iostat. */ if (xp_dkn >= 0) { int dkn = xp_dkn + unit; dk_busy |= 1< 1 done: /* * Device is ready to go. * Put it on the ready queue for the controller. */ dp->b_forw = NULL; if (xd->xp_ctlr->xp_actf == NULL) xd->xp_ctlr->xp_actf = dp; else xd->xp_ctlr->xp_actl->b_forw = dp; xd->xp_ctlr->xp_actl = dp; } /* * Start up a transfer on a controller. */ xpstart(xc) register struct xp_controller *xc; { register struct hpdevice *xpaddr; register struct buf *bp; struct xp_drive *xd; struct buf *dp; daddr_t bn; int unit, part, sn, tn, cn; xpaddr = xc->xp_addr; loop: /* * Pull a request off the controller queue. */ if ((dp = xc->xp_actf) == NULL) return; if ((bp = dp->b_actf) == NULL) { /* * No more requests for this drive, remove from controller queue and * look at next drive. We know we're at the head of the controller queue. * The drive may not need anything, in which case it might be shutting * down in xpclose() and a wakeup is done. */ dp->b_active = 0; xc->xp_actf = dp->b_forw; unit = dp - xputab; xd = &xp_drive[unit]; if (xd->xp_open == 0) wakeup(dp); /* finish close protocol */ goto loop; } /* * Mark controller busy and determine destination of this request. */ xc->xp_active++; part = dkpart(bp->b_dev); unit = XPUNIT(bp->b_dev); xd = &xp_drive[unit]; bn = bp->b_blkno; cn = (xd->xp_parts[part].p_offset + bn) / xd->xp_nspc; sn = bn % xd->xp_nspc; tn = sn / xd->xp_nsect; sn = sn % xd->xp_nsect; /* * Select drive. */ xpaddr->hpcs2.w = xd->xp_unit; /* * Check that it is ready and online. */ if ((xpaddr->hpds & HPDS_DREADY) != (HPDS_DREADY)) { xd->xp_flags &= ~DKF_ONLINE; xc->xp_active = 0; dp->b_errcnt = 0; dp->b_actf = bp->av_forw; bp->b_flags |= B_ERROR; iodone(bp); goto loop; } xd->xp_flags |= DKF_ONLINE; if (dp->b_errcnt >= 16 && (bp->b_flags & B_READ)) { xpaddr->hpof = xp_offset[dp->b_errcnt & 017] | HPOF_FMT22; xpaddr->hpcs1.w = HP_OFFSET | HP_GO; while ((xpaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY); } xpaddr->hpdc = cn; xpaddr->hpda = (tn << 8) + sn; xpaddr->hpba = bp->b_un.b_addr; if (xc->xp_rh70) xpaddr->hpbae = bp->b_xmem; xpaddr->hpwc = -(bp->b_bcount >> 1); /* * Warning: unit is being used as a temporary. */ unit = ((bp->b_xmem & 3) << 8) | HP_IE | HP_GO; #ifdef XP_FORMAT if (minor(bp->b_dev) & 0200) unit |= bp->b_flags & B_READ ? HP_RHDR : HP_WHDR; else unit |= bp->b_flags & B_READ ? HP_RCOM : HP_WCOM; #else if (bp->b_flags & B_READ) unit |= HP_RCOM; else unit |= HP_WCOM; #endif xpaddr->hpcs1.w = unit; #ifdef UCB_METER if (xp_dkn >= 0) { int dkn = xp_dkn + NXPD + (xc - &xp_controller[0]); dk_busy |= 1<b_bcount>>6; } #endif } /* * Handle a disk interrupt. */ xpintr(dev) int dev; { register struct hpdevice *xpaddr; register struct buf *dp; struct xp_controller *xc; struct xp_drive *xd; struct buf *bp; register int unit; int as; xc = &xp_controller[dev]; xpaddr = xc->xp_addr; as = xpaddr->hpas & 0377; if (xc->xp_active) { #ifdef UCB_METER if (xp_dkn >= 0) dk_busy &= ~(1 << (xp_dkn + NXPD + dev)); #endif /* * Get device and block structures. Select the drive. */ dp = xc->xp_actf; bp = dp->b_actf; #ifdef BADSECT if (bp->b_flags & B_BAD) if (xpecc(bp, CONT)) return; #endif unit = XPUNIT(bp->b_dev); xd = &xp_drive[unit]; xpaddr->hpcs2.c[0] = xd->xp_unit; /* * Check for and process errors. */ if (xpaddr->hpcs1.w & HP_TRE) { while ((xpaddr->hpds & HPDS_DRY) == 0); if (xpaddr->hper1 & HPER1_WLE) { /* * Give up on write locked deviced immediately. */ log(LOG_NOTICE, "xp%d: write locked\n", unit); bp->b_flags |= B_ERROR; #ifdef BADSECT } else if ((xpaddr->rmer2 & RMER2_BSE) || (xpaddr->hper1 & HPER1_FER)) { #ifdef XP_FORMAT /* * Allow this error on format devices. */ if (minor(bp->b_dev) & 0200) goto errdone; #endif if (xpecc(bp, BSE)) return; else goto hard; #endif BADSECT } else { /* * After 28 retries (16 without offset and * 12 with offset positioning), give up. */ if (++dp->b_errcnt > 28) { hard: harderr(bp, "xp"); log(LOG_NOTICE,"cs2=%b er1=%b er2=%b\n", xpaddr->hpcs2.w, HPCS2_BITS, xpaddr->hper1, HPER1_BITS, xpaddr->rmer2, RMER2_BITS); bp->b_flags |= B_ERROR; } else xc->xp_active = 0; } /* * If soft ecc, correct it (continuing by returning if * necessary). Otherwise, fall through and retry the * transfer. */ if((xpaddr->hper1 & (HPER1_DCK|HPER1_ECH)) == HPER1_DCK) if (xpecc(bp, ECC)) return; errdone: xpaddr->hpcs1.w = HP_TRE | HP_IE | HP_DCLR | HP_GO; if ((dp->b_errcnt & 07) == 4) { xpaddr->hpcs1.w = HP_RECAL | HP_IE | HP_GO; while ((xpaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY); } xd->xp_cc = -1; } if (xc->xp_active) { if (dp->b_errcnt) { xpaddr->hpcs1.w = HP_RTC | HP_GO; while ((xpaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY); } xc->xp_active = 0; xc->xp_actf = dp->b_forw; dp->b_active = 0; dp->b_errcnt = 0; dp->b_actf = bp->b_actf; xd->xp_cc = bp->b_cylin; bp->b_resid = - (xpaddr->hpwc << 1); iodone(bp); xpaddr->hpcs1.w = HP_IE; if (dp->b_actf) xpustart(unit); } as &= ~(1 << xp_drive[unit].xp_unit); } else { if (as == 0) xpaddr->hpcs1.w = HP_IE; xpaddr->hpcs1.c[1] = HP_TRE >> 8; } for (unit = 0; unit < NXPD; unit++) if ((xp_drive[unit].xp_ctlr == xc) && (as & (1 << xp_drive[unit].xp_unit))) xpustart(unit); xpstart(xc); } #define exadr(x,y) (((long)(x) << 16) | (unsigned)(y)) /* * Correct an ECC error and restart the i/o to complete the transfer if * necessary. This is quite complicated because the correction may be going * to an odd memory address base and the transfer may cross a sector boundary. */ xpecc(bp, flag) register struct buf *bp; int flag; { register struct xp_drive *xd; register struct hpdevice *xpaddr; register unsigned byte; ubadr_t bb, addr; long wrong; int bit, wc; unsigned ndone, npx; int ocmd; int cn, tn, sn; daddr_t bn; struct ubmap *ubp; int unit; /* * ndone is #bytes including the error which is assumed to be in the * last disk page transferred. */ unit = XPUNIT(bp->b_dev); xd = &xp_drive[unit]; xpaddr = xd->xp_ctlr->xp_addr; #ifdef BADSECT if (flag == CONT) { npx = bp->b_error; bp->b_error = 0; ndone = npx * NBPG; wc = ((int)(ndone - bp->b_bcount)) / (int)NBPW; } else { #endif wc = xpaddr->hpwc; ndone = ((unsigned)wc * NBPW) + bp->b_bcount; npx = ndone / NBPG; #ifdef BADSECT } #endif ocmd = (xpaddr->hpcs1.w & ~HP_RDY) | HP_IE | HP_GO; bb = exadr(bp->b_xmem, bp->b_un.b_addr); bn = bp->b_blkno; cn = bp->b_cylin - (bn / xd->xp_nspc); bn += npx; cn += bn / xd->xp_nspc; sn = bn % xd->xp_nspc; tn = sn; tn /= xd->xp_nsect; sn %= xd->xp_nsect; switch (flag) { case ECC: log(LOG_NOTICE, "xp%d%c: soft ecc sn%D\n", unit, 'a' + dkpart(bp->b_dev), bp->b_blkno + (npx - 1)); wrong = xpaddr->hpec2; if (wrong == 0) { xpaddr->hpof = HPOF_FMT22; xpaddr->hpcs1.w |= HP_IE; return (0); } /* * Compute the byte/bit position of the err * within the last disk page transferred. * Hpec1 is origin-1. */ byte = xpaddr->hpec1 - 1; bit = byte & 07; byte >>= 3; byte += ndone - NBPG; wrong <<= bit; /* * Correct until mask is zero or until end of * transfer, whichever comes first. */ while (byte < bp->b_bcount && wrong != 0) { addr = bb + byte; if (bp->b_flags & (B_MAP|B_UBAREMAP)) { /* * Simulate UNIBUS map if UNIBUS * transfer. */ ubp = UBMAP + ((addr >> 13) & 037); addr = exadr(ubp->ub_hi, ubp->ub_lo) + (addr & 017777); } putmemc(addr, getmemc(addr) ^ (int) wrong); byte++; wrong >>= 8; } break; #ifdef BADSECT case BSE: if ((bn = isbad(&xpbad[unit], cn, tn, sn)) < 0) return(0); bp->b_flags |= B_BAD; bp->b_error = npx + 1; bn = (daddr_t)xd->xp_ncyl * xd->xp_nspc - xd->xp_nsect - 1 - bn; cn = bn/xd->xp_nspc; sn = bn%xd->xp_nspc; tn = sn; tn /= xd->xp_nsect; sn %= xd->xp_nsect; log(LOG_NOTICE, "revector to cn %d tn %d sn %d\n", cn, tn, sn); wc = -(512 / (int)NBPW); break; case CONT: bp->b_flags &= ~B_BAD; log(LOG_NOTICE, "xpecc CONT: bn %D cn %d tn %d sn %d\n", bn, cn, tn, sn); break; #endif BADSECT } xd->xp_ctlr->xp_active++; if (wc == 0) return (0); /* * Have to continue the transfer. Clear the drive and compute the * position where the transfer is to continue. We have completed * npx sectors of the transfer already. */ xpaddr->hpcs2.w = xd->xp_unit; xpaddr->hpcs1.w = HP_TRE | HP_DCLR | HP_GO; addr = bb + ndone; xpaddr->hpdc = cn; xpaddr->hpda = (tn << 8) + sn; xpaddr->hpwc = wc; xpaddr->hpba = (caddr_t)addr; if (xd->xp_ctlr->xp_rh70) xpaddr->hpbae = (int)(addr >> 16); xpaddr->hpcs1.w = ocmd; return (1); } xpioctl(dev, cmd, data, flag) dev_t dev; int cmd; caddr_t data; int flag; { register int error; struct dkdevice *disk = &xp_drive[XPUNIT(dev)].xp_dk; error = ioctldisklabel(dev, cmd, data, flag, disk, xpstrategy); return(error); } #ifdef XP_DUMP /* * Dump routine. Dumps from dumplo to end of memory/end of disk section for * minor(dev). */ #define DBSIZE 16 /* number of blocks to write */ xpdump(dev) dev_t dev; { struct xp_drive *xd; register struct hpdevice *xpaddr; struct partition *pi; daddr_t bn, dumpsize; long paddr; int sn, count, memblks, unit; register struct ubmap *ubp; unit = XPUNIT(dev); xd = &xp_drive[unit]; if (unit > NXPD || xd->xp_ctlr == 0) return(EINVAL); if (!(xd->xp_flags & DKF_ALIVE)) return(ENXIO); if (pi->p_fstype != FS_SWAP) return(EFTYPE); pi = &xd->xp_parts[dkpart(dev)]; xpaddr = xd->xp_ctlr->xp_addr; dumpsize = xpsize(dev) - dumplo; memblks = ctod(physmem); if (dumplo < 0 || dumpsize <= 0) return(EINVAL); if (memblks > dumpsize) memblks = dumpsize; bn = dumplo + pi->p_offset; xpaddr->hpcs2.w = xd->xp_unit; if ((xpaddr->hpds & HPDS_VV) == 0) { xpaddr->hpcs1.w = HP_DCLR | HP_GO; xpaddr->hpcs1.w = HP_PRESET | HP_GO; xpaddr->hpof = HPOF_FMT22; } if ((xpaddr->hpds & HPDS_DREADY) != (HPDS_DREADY)) return(EFAULT); ubp = &UBMAP[0]; for (paddr = 0L; memblks > 0; ) { count = MIN(memblks, DBSIZE); xpaddr->hpdc = bn / xd->xp_nspc; sn = bn % xd->xp_nspc; xpaddr->hpda = ((sn / xd->xp_nsect) << 8) | (sn % xd->xp_nsect); xpaddr->hpwc = -(count << (PGSHIFT - 1)); xpaddr->hper1 = 0; xpaddr->hper3 = 0; if (ubmap && (xd->xp_ctlr->xp_rh70 == 0)) { ubp->ub_lo = loint(paddr); ubp->ub_hi = hiint(paddr); xpaddr->hpba = 0; xpaddr->hpcs1.w = HP_WCOM | HP_GO; } else { /* * Non-UNIBUS map, or 11/70 RH70 (MASSBUS) */ xpaddr->hpba = (caddr_t)loint(paddr); if (xd->xp_ctlr->xp_rh70) xpaddr->hpbae = hiint(paddr); xpaddr->hpcs1.w = HP_WCOM | HP_GO | ((paddr >> 8) & (03 << 8)); } /* Emulex controller emulating two RM03's needs a delay */ delay(50000L); while (xpaddr->hpcs1.w & HP_GO) continue; if (xpaddr->hpcs1.w & HP_TRE) return(EIO); paddr += (DBSIZE << PGSHIFT); bn += count; memblks -= count; } return(0); } #endif XP_DUMP /* * Return the number of blocks in a partition. Call xpopen() to read the * label if necessary. If an open is necessary then a matching close * will be done. */ daddr_t xpsize(dev) register dev_t dev; { register struct xp_drive *xd; daddr_t psize; int didopen = 0; xd = &xp_drive[XPUNIT(dev)]; /* * This should never happen but if we get called early in the kernel's * life (before opening the swap or root devices) then we have to do * the open here. */ if (xd->xp_open == 0) { if (xpopen(dev, FREAD|FWRITE, S_IFBLK)) return(-1); didopen = 1; } psize = xd->xp_parts[dkpart(dev)].p_size; if (didopen) xpclose(dev, FREAD|FWRITE, S_IFBLK); return(psize); } #endif /* NXPD */ & B_READ)) { xpaddr->hpof = xp_offset[dp->b_errcnt & 017] | HPOF_FMT22; xpaddr->hpcs1.w = HP_OFFSET | HP_GO; while ((xpaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY); } xpaddr->hpdc = cn; xpaddr->hpda = (tn << 8) + sn; xpaddr->hpba = bp->b_un.b_addr; if (xc->xp_rh70) xpaddr->hpbae = bp->b_xmem; xpaddsys/pdpuba/pdma.h 444 0 12 1252 4001603754 7210 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)pdma.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * Structure to describe pseudo-DMA buffer used by DZ-11 pseudo-DMA * routines. The offsets in the structure are well-known in dzdma, * an assembly routine. We use pd_addr, not p_addr, because proc.h * got there first. */ struct pdma { struct dzdevice *pd_addr; /* address of controlling device */ char *p_mem; /* start of buffer */ char *p_end; /* end of buffer */ struct tty *p_arg; /* tty structure for this line */ }; >b_dev) & 0200) unit |= bp->b_flags & B_READ ? HP_RHDR : HP_WHDR; else unit |= bp->b_flags & B_READ ? HP_RCOM : HP_WCOM; #else if (bp->b_flags & B_READ) unit |= HP_RCOM; else unit |= HP_WCOM; #endif xpaddr->hpcs1.w = unit; #ifdef UCB_METER if (xp_dkn >= 0) { int dkn = xp_dkn + NXPD + (xc - &xp_controller[0]); dk_busy |= 1 0 #include "param.h" #include "buf.h" #include "conf.h" #include "file.h" #include "user.h" #include "ioctl.h" #include "fs.h" #include "tsreg.h" #include "mtio.h" #include "map.h" #include "uba.h" /* * Software state per tape transport: * * 1. A tape drive is a unique-open device: we refuse opens when it is already * 2. We keep track of the current position on a block tape and seek * before operations by forward/back spacing if necessary. * 3. We remember if the last operation was a write on a tape, so if a tape * is open read write and the last thing done is a write we can * write a standard end of tape mark (two eofs). * 4. We remember the status registers after the last command, using * them internally and returning them to the SENSE ioctl. */ struct ts_softc { struct tsdevice *sc_addr; /* CSR of controller */ char sc_openf; /* lock against multiple opens */ char sc_lastiow; /* last op was a write */ short sc_resid; /* copy of last bc */ daddr_t sc_blkno; /* block number, for block device tape */ daddr_t sc_nxrec; /* position of end of tape, if known */ 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]; /* * There is a ctsbuf per tape controller. * It is used as the token to pass to the internal routines * to execute tape ioctls. * In particular, when the tape is rewinding on close we release * the user process but any further attempts to use the tape drive * before the rewind completes will hang waiting for ctsbuf. */ struct buf ctsbuf[NTS]; #define INF ((daddr_t) ((u_short) 65535)) /* bits in minor device */ #define TSUNIT(dev) (minor(dev)&03) /* not used */ #define TSCTLR(dev) ((minor(dev) >> 6) & 3) #define T_NOREWIND 04 /* * States for tstab.b_active, the state flag. * This is used to sequence control in the driver. */ #define SSEEK 1 /* seeking */ #define SIO 2 /* doing seq. i/o */ #define SCOM 3 /* sending a control command */ #define SREW 4 /* sending a drive rewind */ u_short softspace[NTS][(sizeof(struct ts_softc)/2) + 1]; static char *tsmsg1 = "ts%d: not online\n"; static char *tsmsg2 = "ts%d: no write ring\n"; 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); /* * We want space for an array of NTS ts_softc structures, * where the sc_cmd field of each is long-aligned, i.e. the * 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); mapalloc(&tbuf); 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); } /* * Open the device. Tapes are unique open * devices so we refuse if it is already open. * We also check that a tape is available and * don't block waiting here: if you want to wait * for a tape you should timeout in user code. */ tsopen(dev, flag) dev_t dev; int flag; { register ts11 = TSCTLR(dev); register struct ts_softc *sc = ts_softc[ts11]; if (ts11 >= NTS || !sc || sc->sc_openf) return(ENXIO); if (tsinit(ts11)) { printf("ts%d: init failure tssr=%b\n", ts11, sc->sc_addr->tssr, TSSR_BITS); return(ENXIO); } tstab[ts11].b_flags |= B_TAPE; tscommand(dev, TS_SENSE, 1); if ((sc->sc_sts.s_xs0 & TS_ONL) == 0) { uprintf(tsmsg1, ts11); return(EIO); } if ((flag & (FREAD | FWRITE)) == FWRITE && (sc->sc_sts.s_xs0 & TS_WLK)) { uprintf(tsmsg2, ts11); return(EIO); } sc->sc_openf = 1; sc->sc_blkno = (daddr_t) 0; sc->sc_nxrec = INF; sc->sc_lastiow = 0; sc->sc_ttyp = u.u_ttyp; return(0); } /* * Close tape device. * * If tape was open for writing or last operation was * a write, then write two EOF's and backspace over the last one. * Unless his is a non-rewinding special file, rewind the tape. * Make the tape available to others. */ tsclose(dev, flag) register dev_t dev; register int flag; { register struct ts_softc *sc = ts_softc[TSCTLR(dev)]; if (flag == FWRITE || ((flag & FWRITE) && sc->sc_lastiow)) { tscommand(dev, TS_WEOF, 1); tscommand(dev, TS_WEOF, 1); tscommand(dev, TS_SREV, 1); } if ((minor(dev) & T_NOREWIND) == 0 ) /* * 0 count means don't hang waiting for rewind complete. * Rather ctsbuf stays busy until the operation completes * preventing further opens from completing by * preventing a TS_SENSE from completing. */ tscommand(dev, TS_REW, 0); sc->sc_openf = 0; } /* * Execute a command on the tape drive * a specified number of times. */ tscommand(dev, com, count) dev_t dev; register u_short count; { register int s; register struct buf *bp; bp = &ctsbuf[TSCTLR(dev)]; s = splbio(); while(bp->b_flags & B_BUSY) { /* * This special check is because B_BUSY never * gets cleared in the non-waiting rewind case. */ if (bp->b_repcnt == 0 && (bp->b_flags & B_DONE)) break; bp->b_flags |= B_WANTED; sleep((caddr_t) bp, PRIBIO); } bp->b_flags = B_BUSY | B_READ; splx(s); bp->b_dev = dev; bp->b_repcnt = count; bp->b_command = com; bp->b_blkno = (daddr_t) 0; tsstrategy(bp); /* * In case of rewind from close, don't wait. * This is the only case where count can be 0. */ if (count == 0) return; iowait(bp); if(bp->b_flags & B_WANTED) wakeup((caddr_t) bp); bp->b_flags &= B_ERROR; } /* * Queue a tape operation. */ tsstrategy(bp) register struct buf *bp; { register int s; int ts11 = TSCTLR(bp->b_dev); struct ts_softc *sc = ts_softc[ts11]; register struct buf *dp = &tstab[ts11]; if (bp->b_flags & B_PHYS) { /* if RAW I/O call */ mapalloc(bp); sc->sc_blkno = sc->sc_nxrec = dbtofsb(bp->b_blkno); sc->sc_nxrec++; } bp->av_forw = NULL; s = splbio(); if (dp->b_actf == NULL) dp->b_actf = bp; else dp->b_actl->av_forw = bp; dp->b_actl = bp; /* * If the controller is not busy, get * it going. */ if (dp->b_active == 0) tsstart(ts11); splx(s); } /* * Start activity on a ts controller. */ tsstart(ts11) int ts11; { daddr_t blkno; int cmd; register struct ts_softc *sc; register struct ts_cmd *tc; register struct buf *bp; struct buf *um = &tstab[ts11]; /* * Start the controller if there is something for it to do. */ loop: if ((bp = um->b_actf) == NULL) return; sc = ts_softc[ts11]; tc = &sc->sc_cmd; /* * Default is that last command was NOT a write command; * if we do a write command we will notice this in tsintr(). */ sc->sc_lastiow = 0; if (sc->sc_openf < 0 || (sc->sc_addr->tssr & TS_OFL)) { /* * Have had a hard error on a non-raw tape * or the tape unit is now unavailable * (e.g. taken off line). */ bp->b_flags |= B_ERROR; goto next; } if (bp == &ctsbuf[ts11]) { /* * Execute control operation with the specified count. */ um->b_active = bp->b_command == TS_REW ? SREW : SCOM; goto dobpcmd; } /* * The following checks handle boundary cases for operation * on non-raw tapes. On raw tapes the initialization of * sc->sc_nxrec by tsphys causes them to be skipped normally * (except in the case of retries). */ if (dbtofsb(bp->b_blkno) > sc->sc_nxrec) { /* * Can't read past known end-of-file. */ bp->b_flags |= B_ERROR; bp->b_error = ENXIO; goto next; } if (dbtofsb(bp->b_blkno) == sc->sc_nxrec && bp->b_flags & B_READ) { /* * Reading at end of file returns 0 bytes. * Buffer will be cleared (if written) in rwip. */ bp->b_resid = bp->b_bcount; goto next; } if((bp->b_flags & B_READ) == 0) /* * Writing sets EOF */ sc->sc_nxrec = dbtofsb(bp->b_blkno) + 1; /* * If the data transfer command is in the correct place, * set up all registers and do the transfer. */ if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) { um->b_active = SIO; tc->c_loba = (u_short)bp->b_un.b_addr; tc->c_hiba = bp->b_xmem; tc->c_size = bp->b_bcount; if ((bp->b_flags & B_READ) == 0) cmd = TS_WCOM; else cmd = TS_RCOM; if (um->b_errcnt) cmd |= TS_RETRY; tc->c_cmd = TS_ACK | TS_CVC | TS_IE | cmd; sc->sc_addr->tsdb = sc->sc_uba; return; } /* * Tape positioned incorrectly; * set to seek forward or backward to the correct spot. * This happens for raw tapes only on error retries. */ um->b_active = SSEEK; if (blkno < dbtofsb(bp->b_blkno)) { bp->b_command = TS_SFORW; bp->b_repcnt = dbtofsb(bp->b_blkno) - blkno; } else { bp->b_command = TS_SREV; bp->b_repcnt = blkno - dbtofsb(bp->b_blkno); } dobpcmd: tc->c_repcnt = bp->b_repcnt; /* * Do the command in bp. */ tc->c_cmd = TS_ACK | TS_CVC | TS_IE | bp->b_command; sc->sc_addr->tsdb = sc->sc_uba; return; next: /* * Done with this operation due to error or * the fact that it doesn't do anything. * Dequeue the transfer and continue processing this slave. */ um->b_errcnt = 0; um->b_actf = bp->av_forw; iodone(bp); goto loop; } /* * TS interrupt routine */ tsintr(dev) int dev; { int state; register struct buf *bp, *um = &tstab[dev]; register struct ts_softc *sc = ts_softc[dev]; if ((bp = um->b_actf) == NULL) return; /* * 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; if ((sc->sc_addr->tssr & TS_SSR) == 0) return; } /* * An operation completed... record status */ if ((bp->b_flags & B_READ) == 0) sc->sc_lastiow = 1; state = um->b_active; um->b_active = 0; /* * Check for errors. */ if (sc->sc_addr->tssr & TS_SC) { switch (sc->sc_addr->tssr & TS_TC) { case TS_UNREC: /* unrecoverable */ case TS_FATAL: /* fatal error */ case TS_ATTN: /* attention (shouldn't happen) */ case TS_RECNM: /* recoverable, no motion */ break; case TS_SUCC: /* successful termination */ goto ignoreerr; /*NOTREACHED*/ case TS_ALERT: /* tape status alert */ /* * If we hit the end of the tape file, * update our position. */ if (sc->sc_sts.s_xs0 & (TS_TMK | TS_EOT)) { tsseteof(bp); /* set blkno and nxrec */ state = SCOM; /* force completion */ /* * Stuff bc so it will be unstuffed * correctly later to get resid. */ sc->sc_sts.s_rbpcr = bp->b_bcount; goto opdone; /*NOTREACHED*/ } /* * If we were reading raw tape and the record * was too long or too short, then we don't * consider this an error. */ if ((bp->b_flags & B_PHYS) && (bp->b_flags & B_READ) && sc->sc_sts.s_xs0 & (TS_RLS | TS_RLL)) goto ignoreerr; /*NOTREACHED*/ case TS_RECOV: /* recoverable, tape moved */ /* * If this was an i/o operation, * retry up to 8 times. */ if (state == SIO) { if (++(um->b_errcnt) < 7) goto opcont; else sc->sc_blkno++; } else { /* * Non-i/o errors on non-raw tape * cause it to close. */ if (sc->sc_openf > 0 && !(bp->b_flags & B_PHYS)) sc->sc_openf = -1; } break; case TS_REJECT: if (state == SIO && sc->sc_sts.s_xs0 & TS_WLE) tprintf(sc->sc_ttyp, tsmsg2, dev); if ((sc->sc_sts.s_xs0 & TS_ONL) == 0) tprintf(sc->sc_ttyp, tsmsg1, 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*/ } /* * Advance tape control finite state machine. */ ignoreerr: switch (state) { case SIO: /* * Read/write increments tape block number. */ sc->sc_blkno++; goto opdone; /*NOTREACHED*/ case SCOM: /* * For forward/backward space record * update current position. */ if (bp == &ctsbuf[dev]) switch (bp->b_command) { case TS_SFORW: sc->sc_blkno += bp->b_repcnt; break; case TS_SREV: sc->sc_blkno -= bp->b_repcnt; break; } goto opdone; /*NOTREACHED*/ case SSEEK: sc->sc_blkno = dbtofsb(bp->b_blkno); goto opcont; /*NOTREACHED*/ default: panic("tsintr"); /*NOTREACHED*/ } opdone: /* * Reset error count and remove * from device queue. */ um->b_errcnt = 0; um->b_actf = bp->av_forw; bp->b_resid = sc->sc_sts.s_rbpcr; iodone(bp); if (um->b_actf == NULL) return; opcont: tsstart(dev); } tsseteof(bp) register struct buf *bp; { register int ts11 = TSCTLR(bp->b_dev); register struct ts_softc *sc = ts_softc[ts11]; if (bp == &ctsbuf[ts11]) { if (sc->sc_blkno > dbtofsb(bp->b_blkno)) { /* reversing */ sc->sc_nxrec = dbtofsb(bp->b_blkno) - sc->sc_sts.s_rbpcr; sc->sc_blkno = sc->sc_nxrec; } else { /* spacing forward */ sc->sc_blkno = dbtofsb(bp->b_blkno) + sc->sc_sts.s_rbpcr; sc->sc_nxrec = sc->sc_blkno - 1; } return; } /* eof on read */ sc->sc_nxrec = dbtofsb(bp->b_blkno); } /* * Initialize the TS11. */ 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; } if (sc->sc_addr->tssr & TS_NBA) { printf("ts%d: set char. failure\n", ts11); return (1); } } return(0); } /*ARGSUSED*/ tsioctl(dev, cmd, data, flag) dev_t dev; u_int cmd; caddr_t data; { int ts11 = TSCTLR(dev); register struct ts_softc *sc = ts_softc[ts11]; register struct buf *bp = &ctsbuf[ts11]; register callcount; u_short fcount; struct mtop *mtop; struct mtget *mtget; /* we depend on the values and order of the MT codes here */ static tsops[] = {TS_WEOF,TS_SFORWF,TS_SREVF,TS_SFORW,TS_SREV,TS_REW,TS_OFFL,TS_SENSE}; switch (cmd) { case MTIOCTOP: /* tape operation */ mtop = (struct mtop *)data; switch(mtop->mt_op) { case MTWEOF: callcount = mtop->mt_count; fcount = 1; break; case MTFSF: case MTBSF: case MTFSR: case MTBSR: callcount = 1; fcount = mtop->mt_count; break; case MTREW: case MTOFFL: case MTNOP: callcount = 1; fcount = 1; break; default: return (ENXIO); } if (callcount <= 0 || fcount <= 0) return (EINVAL); while (--callcount >= 0) { tscommand(dev, tsops[mtop->mt_op], fcount); if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && bp->b_resid) return (EIO); if ((bp->b_flags&B_ERROR) || sc->sc_sts.s_xs0&TS_BOT) break; } return (geterror(bp)); case MTIOCGET: mtget = (struct mtget *)data; mtget->mt_dsreg = 0; mtget->mt_erreg = sc->sc_sts.s_xs0; mtget->mt_resid = sc->sc_resid; mtget->mt_type = MT_ISTS; break; default: return (ENXIO); } return (0); } #endif NTS rtition. Call xpopen() to read the * label if necessary. If an open is necessary then a matching close * will be done. */ daddr_t xpsize(dev) register dev_t dev; { register struct xp_drive *xd; daddr_t psize; int didopen = 0; xd = &xp_drive[XPUNIT(dev)]; /* * This should never happen but if we get called early in the kernel's * life (before opening the swap or root devices) then we have to do * the open here. */ if (xd->xp_open == 0) { if (xpopen(dsys/pdpuba/dhreg.h 444 0 12 3233 4001545143 7356 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dhreg.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * DH-11 device register definitions. */ struct dhdevice { union { short dhcsr; /* control-status register */ char dhcsrl; /* low byte for line select */ } un; short dhrcr; /* receive character register */ short dhlpr; /* line parameter register */ u_short dhcar; /* current address register */ short dhbcr; /* byte count register */ u_short dhbar; /* buffer active register */ short dhbreak; /* break control register */ short dhsilo; /* silo status register */ }; /* Bits in dhcsr */ #define DH_TI 0100000 /* transmit interrupt */ #define DH_SI 0040000 /* storage interrupt */ #define DH_TIE 0020000 /* transmit interrupt enable */ #define DH_SIE 0010000 /* storage interrupt enable */ #define DH_MC 0004000 /* master clear */ #define DH_NXM 0002000 /* non-existant memory */ #define DH_MM 0001000 /* maintenance mode */ #define DH_CNI 0000400 /* clear non-existant memory interrupt */ #define DH_RI 0000200 /* receiver interrupt */ #define DH_RIE 0000100 /* receiver interrupt enable */ /* Bits in dhlpr */ #define BITS6 01 #define BITS7 02 #define BITS8 03 #define TWOSB 04 #define PENABLE 020 /* DEC manuals incorrectly say this bit causes generation of even parity. */ #define OPAR 040 #define HDUPLX 040000 #define DH_IE (DH_TIE|DH_SIE|DH_RIE) /* Bits in dhrcr */ #define DH_PE 0010000 /* parity error */ #define DH_FE 0020000 /* framing error */ #define DH_DO 0040000 /* data overrun */ sb(bp->b_blkno)) { um->b_active = SIO; tc->c_loba = (u_short)bp->b_un.b_addr; tc->c_hiba = bp->b_xmem; tc->c_size = bp->b_bcount; if ((bp->b_flags & B_READ) == 0) cmd = TS_WCOM; else cmd = TS_RCOM; if (um->b_errcnt) cmd |= TS_RETRY; tc->c_cmd = TS_ACK | TS_CVC | TS_IE | cmd; sc->sc_addr->tsdb = sc->sc_uba; return; } /* * Tsys/pdpuba/rx.c 444 0 12 16764 5321512752 6754 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)rx.c 1.3 (2.11BSD GTE) 1/2/93 */ /* * RX02 floppy disk device driver * * This driver was written by Bill Shannon and distributed on the * DEC v7m UNIX tape. It has been modified for 2BSD and has been * included with the permission of the DEC UNIX Engineering Group. * * Modified to actually work with 2.9BSD by Gregory Travis, Indiana Univ. * * Layout of logical devices: * * name min dev unit density * ---- ------- ---- ------- * rx0a 0 0 single * rx1a 1 1 single * rx0b 2 0 double * rx1b 3 1 double * * ioctl function call may be used to format a disk. */ #include "rx.h" #if NRX > 0 #include "param.h" #include "buf.h" #include "conf.h" #include "ioctl.h" #include "tty.h" #include "rxreg.h" #include "errno.h" struct rxdevice *RXADDR; /* * the following defines use some fundamental * constants of the RX02. */ #define NSPB ((minor(bp->b_dev)&2) ? 2 : 4) /* sectors per block */ #define NRXBLKS ((minor(bp->b_dev)&2) ? 1001 : 500) /* blocks on device */ #define NBPS ((minor(bp->b_dev)&2) ? 256 : 128) /* bytes per sector */ #define DENSITY (minor(bp->b_dev)&2) /* Density: 0 = single, 2 = double */ #define UNIT (minor(bp->b_dev)&1) /* Unit Number: 0 = left, 1 = right */ #define rxwait() while (((RXADDR->rxcs) & RX_XREQ) == 0) #define seccnt(bp) ((int)((bp)->b_seccnt)) struct buf rxtab; struct buf crxbuf; /* buffer header for control functions */ /* * states of driver, kept in b_state */ #define SREAD 1 /* read started */ #define SEMPTY 2 /* empty started */ #define SFILL 3 /* fill started */ #define SWRITE 4 /* write started */ #define SINIT 5 /* init started */ #define SFORMAT 6 /* format started */ rxattach(addr, unit) struct rxdevice *addr; u_int unit; { if (unit != 0) return (0); RXADDR = addr; return (1); } /*ARGSUSED*/ rxopen(dev, flag) dev_t dev; { if (minor(dev) >= 4 || !RXADDR) return (ENXIO); return (0); } rxstrategy(bp) register struct buf *bp; { register int s; if (minor(bp->b_dev) >= 4 || !RXADDR) goto bad; mapalloc(bp); if (bp->b_blkno >= NRXBLKS) { if (bp->b_flags&B_READ) bp->b_resid = bp->b_bcount; else { bad: bp->b_flags |= B_ERROR; bp->b_error = ENXIO; } iodone(bp); return; } bp->av_forw = (struct buf *) NULL; /* * seccnt is actually the number of floppy sectors transferred, * incremented by one after each successful transfer of a sector. */ bp->b_seccnt = 0; /* * We'll modify b_resid as each piece of the transfer * successfully completes. It will also tell us when * the transfer is complete. */ bp->b_resid = bp->b_bcount; s = splbio(); if (rxtab.b_actf == NULL) rxtab.b_actf = bp; else rxtab.b_actl->av_forw = bp; rxtab.b_actl = bp; if (rxtab.b_state == NULL) rxstart(); splx(s); } rxstart() { register struct buf *bp; int sector, track; char *addr, xmem; if ((bp = rxtab.b_actf) == NULL) { rxtab.b_state = NULL; return; } if (bp == &crxbuf) { /* is it a control request ? */ rxtab.b_state = SFORMAT; RXADDR->rxcs = RX_SMD | RX_GO | RX_IE | (UNIT << 4) | (DENSITY << 7); rxwait(); RXADDR->rxdb = 'I'; } else if (bp->b_flags & B_READ) { rxtab.b_state = SREAD; rxfactr((int)bp->b_blkno * NSPB + seccnt(bp), §or, &track); RXADDR->rxcs = RX_RSECT | RX_GO | RX_IE | (UNIT << 4) | (DENSITY << 7); rxwait(); RXADDR->rxsa = sector; rxwait(); RXADDR->rxta = track; } else { rxtab.b_state = SFILL; rxaddr(bp, &addr, &xmem); RXADDR->rxcs = RX_FILL | RX_GO | RX_IE | ((u_int)xmem << 12) | (DENSITY << 7); rxwait(); RXADDR->rxwc = (bp->b_resid >= NBPS ? NBPS : bp->b_resid) >> 1; rxwait(); RXADDR->rxba = (short)addr; } } rxintr() { register struct buf *bp; int sector, track; char *addr, xmem; if (rxtab.b_state == SINIT) { rxstart(); return; } if ((bp = rxtab.b_actf) == NULL) return; if (RXADDR->rxcs < 0) { if (rxtab.b_errcnt++ > 10 || rxtab.b_state == SFORMAT) { bp->b_flags |= B_ERROR; harderr(bp, "rx"); printf("cs=%b er=%b\n", RXADDR->rxcs, RX_BITS, RXADDR->rxes, RXES_BITS); rxtab.b_errcnt = 0; rxtab.b_actf = bp->av_forw; iodone(bp); } RXADDR->rxcs = RX_INIT; RXADDR->rxcs = RX_IE; rxtab.b_state = SINIT; return; } switch (rxtab.b_state) { case SREAD: /* read done, start empty */ rxtab.b_state = SEMPTY; rxaddr(bp, &addr, &xmem); RXADDR->rxcs = RX_EMPTY | RX_GO | RX_IE | ((u_int)xmem << 12) | (DENSITY << 7); rxwait(); RXADDR->rxwc = (bp->b_resid >= NBPS? NBPS : bp->b_resid) >> 1; rxwait(); RXADDR->rxba = (short)addr; return; case SFILL: /* fill done, start write */ rxtab.b_state = SWRITE; rxfactr((int)bp->b_blkno * NSPB + seccnt(bp), §or, &track); RXADDR->rxcs = RX_WSECT | RX_GO | RX_IE | (UNIT << 4) | (DENSITY << 7); rxwait(); RXADDR->rxsa = sector; rxwait(); RXADDR->rxta = track; return; case SWRITE: /* write done, start next fill */ case SEMPTY: /* empty done, start next read */ /* * increment amount remaining to be transferred. * if it becomes positive, last transfer was a * partial sector and we're done, so set remaining * to zero. */ if (bp->b_resid <= NBPS) { done: bp->b_resid = 0; rxtab.b_errcnt = 0; rxtab.b_actf = bp->av_forw; iodone(bp); break; } bp->b_resid -= NBPS; bp->b_seccnt++; break; case SFORMAT: /* format done (whew!!!) */ goto done; /* driver's getting too big... */ } /* end up here from states SWRITE and SEMPTY */ rxstart(); } /* * rxfactr -- calculates the physical sector and physical * track on the disk for a given logical sector. * call: * rxfactr(logical_sector,&p_sector,&p_track); * the logical sector number (0 - 2001) is converted * to a physical sector number (1 - 26) and a physical * track number (0 - 76). * the logical sectors specify physical sectors that * are interleaved with a factor of 2. thus the sectors * are read in the following order for increasing * logical sector numbers (1,3, ... 23,25,2,4, ... 24,26) * There is also a 6 sector slew between tracks. * Logical sectors start at track 1, sector 1; go to * track 76 and then to track 0. Thus, for example, unix block number * 498 starts at track 0, sector 25 and runs thru track 0, sector 2 * (or 6 depending on density). */ static rxfactr(sectr, psectr, ptrck) register int sectr; int *psectr, *ptrck; { register int p1, p2; p1 = sectr / 26; p2 = sectr % 26; /* 2 to 1 interleave */ p2 = (2 * p2 + (p2 >= 13 ? 1 : 0)) % 26; /* 6 sector per track slew */ *psectr = 1 + (p2 + 6 * p1) % 26; if (++p1 >= 77) p1 = 0; *ptrck = p1; } /* * rxaddr -- compute core address where next sector * goes to / comes from based on bp->b_un.b_addr, bp->b_xmem, * and seccnt(bp). */ static rxaddr(bp, addr, xmem) register struct buf *bp; register char **addr, *xmem; { *addr = bp->b_un.b_addr + seccnt(bp) * NBPS; *xmem = bp->b_xmem; if (*addr < bp->b_un.b_addr) /* overflow, bump xmem */ (*xmem)++; } /* * rxioctl -- format RX02 disk, single or double density. * density determined by device opened. */ /*ARGSUSED*/ rxioctl(dev, cmd, addr, flag) dev_t dev; u_int cmd; { register int s; register struct buf *bp; if (cmd != RXIOC_FORMAT) return (ENXIO); bp = &crxbuf; while (bp->b_flags & B_BUSY) { s = splbio(); bp->b_flags |= B_WANTED; sleep(bp, PRIBIO); } splx(s); bp->b_flags = B_BUSY; bp->b_dev = dev; bp->b_error = 0; rxstrategy(bp); iowait(bp); bp->b_flags = 0; return (0); } #endif work with 2.sys/pdpuba/rk.c 444 0 12 6112 5321511032 6667 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)rk.c 1.4 (2.11BSD GTE) 1/2/93 */ /* * RK05 device drive */ #include "rk.h" #if NRK > 0 #include "param.h" #include "systm.h" #include "buf.h" #include "conf.h" #include "user.h" #include "dk.h" #include "rkreg.h" #define NRKBLK 4872 /* Number of blocks per drive */ struct rkdevice *RKADDR; struct buf rktab; #define rkunit(dev) minor(dev) #ifdef UCB_METER static int rk_dkn = -1; /* number for iostat */ #endif rkattach(addr, unit) struct rkdevice *addr; { #ifdef UCB_METER if (rk_dkn < 0) dk_alloc(&rk_dkn, 1, "rk", 25L * 12L * 256L); #endif if (unit != 0) return(0); RKADDR = addr; return(1); } rkopen(dev, flag) dev_t dev; int flag; { register int unit = rkunit(dev); if (unit >= NRK || !RKADDR) return (ENXIO); return (0); } rkstrategy(bp) register struct buf *bp; { register int s; register int unit; unit = rkunit(bp->b_dev); if (unit >= NRK || !RKADDR) { bp->b_error = ENXIO; goto bad; } if (bp->b_blkno >= NRKBLK) { bp->b_error = EINVAL; bad: bp->b_flags |= B_ERROR; iodone(bp); return; } mapalloc(bp); bp->av_forw = (struct buf *)NULL; s = splbio(); if(rktab.b_actf == NULL) rktab.b_actf = bp; else rktab.b_actl->av_forw = bp; rktab.b_actl = bp; if(rktab.b_active == NULL) rkstart(); splx(s); } rkstart() { register struct rkdevice *rkaddr = RKADDR; register struct buf *bp; register com; daddr_t bn; int dn, cn, sn; if ((bp = rktab.b_actf) == NULL) return; rktab.b_active++; bn = bp->b_blkno; dn = minor(bp->b_dev); cn = bn / 12; sn = bn % 12; rkaddr->rkda = (dn << 13) | (cn << 4) | sn; rkaddr->rkba = bp->b_un.b_addr; rkaddr->rkwc = -(bp->b_bcount >> 1); com = ((bp->b_xmem & 3) << 4) | RKCS_IDE | RKCS_GO; if(bp->b_flags & B_READ) com |= RKCS_RCOM; else com |= RKCS_WCOM; rkaddr->rkcs = com; #ifdef UCB_METER if (rk_dkn >= 0) { dk_busy |= 1<b_bcount>>6; } #endif } rkintr() { register struct rkdevice *rkaddr = RKADDR; register struct buf *bp; if (rktab.b_active == NULL) return; #ifdef UCB_METER if (rk_dkn >= 0) dk_busy &= ~(1<rkcs & RKCS_ERR) { while ((rkaddr->rkcs & RKCS_RDY) == 0) ; if (rkaddr->rker & RKER_WLO) /* * Give up on write locked devices * immediately. */ printf("rk%d: write locked\n", minor(bp->b_dev)); else { harderr(bp, "rk"); printf("er=%b ds=%b\n", rkaddr->rker, RKER_BITS, rkaddr->rkds, RK_BITS); rkaddr->rkcs = RKCS_RESET | RKCS_GO; while((rkaddr->rkcs & RKCS_RDY) == 0) ; if (++rktab.b_errcnt <= 10) { rkstart(); return; } } bp->b_flags |= B_ERROR; } rktab.b_errcnt = 0; rktab.b_actf = bp->av_forw; bp->b_resid = -(rkaddr->rkwc << 1); iodone(bp); rkstart(); } /* * Hack - no one is using these anyhow, especially for swapping. */ daddr_t rksize(dev) dev_t dev; { return(NRKBLK); } #endif NRK /* is it a control request ? */ rxtab.b_state = SFORMAT; RXADDR->rxcs = RX_SMD | RX_GO | RX_IE | (UNIT << 4) | (DENSITY << 7); rxwait(); RXADDR->rxdb = 'I'; } else if (bp->b_flags & B_READ) { rxtab.b_state = SREAD; rxfactr((int)bp->b_blkno * NSPB + seccnt(bp), §or, &track); RXADDR->rxcs = RX_RSECT | RX_GO | RX_IE | (UNIT << 4) | (DENSITY << 7); rxwait(); RXADDR->rxsa = sector; rxwait(); RXADDR->rxta = tracksys/pdpuba/dkbad.c 444 0 12 1424 4236242204 7327 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dkbad.c 1.1 (2.10BSD Berkeley) 12/1/86 */ #include "param.h" #ifdef BADSECT #include "buf.h" #include "dkbad.h" /* * Search the bad sector table looking for * the specified sector. Return index if found. * Return -1 if not found. */ isbad(bt, cyl, trk, sec) register struct dkbad *bt; { register int i; register long blk, bblk; blk = ((long)cyl << 16) + (trk << 8) + sec; for (i = 0; i < MAXBAD; i++) { bblk = ((long)bt->bt_bad[i].bt_cyl << 16) + bt->bt_bad[i].bt_trksec; if (blk == bblk) return (i); if (blk < bblk || bblk < 0) break; } return (-1); } #endif RKADDR = addr; return(1); } rkopen(dev, flag) dev_t dev; int flag; { register int unit = rkunit(dev); if (unit >= NRK || !RKADDR) return (ENXIO); return (0); } rkstrategy(bp) register struct buf *bp; { register int s; regsys/pdpuba/tm.c 644 0 12 34240 5321512700 6723 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)tm.c 2.2 (2.11BSD GTE) 1/2/93 */ /* * TM11 tape drive */ #include "tm.h" #if NTM > 0 #include "param.h" #include "buf.h" #include "conf.h" #include "file.h" #include "user.h" #include "ioctl.h" #include "fs.h" #include "mtio.h" #include "kernel.h" #include "systm.h" #include "tmreg.h" struct tmdevice *TMADDR; struct buf tmtab; struct buf ctmbuf; /* * Software state per tape transport: * * 1. A tape drive is a unique-open device: we refuse opens when it is already. * 2. We keep track of the current position on a block tape and seek * before operations by forward/back spacing if necessary. * 3. We remember if the last operation was a write on a tape, so if a tape * is open read write and the last thing done is a write we can * write a standard end of tape mark (two eofs). * 4. We remember the status registers after the last command, using * them internally and returning them to the SENSE ioctl. * 5. We remember the last density the tape was used at. If it is * not a BOT when we start using it and we are writing, we don't * let the density be changed. */ struct te_softc { char sc_openf; char sc_lastiow; daddr_t sc_blkno; daddr_t sc_nxrec; u_short sc_erreg; u_short sc_dsreg; short sc_resid; u_short sc_dens; short sc_timo; short sc_tact; } te_softc[NTM]; /* * States for tmtab.b_active, the state flag. * This is used to sequence control in the driver. */ #define SSEEK 1 #define SIO 2 #define SCOM 3 #define SREW 4 /* * Bits in minor device. */ #define TEUNIT(dev) (minor(dev) & 03) #define T_NOREWIND 04 #ifdef AVIV #define TEDENS(dev) ((minor(dev) & 030) >> 3) #else #define TEDENS(dev) ((minor(dev) & 010) >> 3) #endif #define INF 32760 int tmtimer (); tmattach(addr, unit) struct tmdevice *addr; int unit; { /* * This driver supports only one controller. */ if (unit == 0) { TMADDR = addr; return(1); } return(0); } /* * Open the device. Tapes are unique open * devices so we refuse if it is already open. * We also check that the tape is available and * don't block waiting here: if you want to wait * for a tape you should timeout in user code. */ u_short tmdens[4] = { TM_D800, TM_D1600, TM_D6250, TM_D800 }; tmopen(dev, flag) register dev_t dev; { int s; u_short olddens, dens; register teunit = TEUNIT(dev); register struct te_softc *sc = &te_softc[teunit]; if (teunit >= NTM || TMADDR == (struct tmdevice *) NULL) return(ENXIO); else if (sc->sc_openf) return(EBUSY); olddens = sc->sc_dens; dens = TM_IE | TM_GO | (teunit << 8) | tmdens[TEDENS(dev)]; sc->sc_dens = dens; tmtab.b_flags |= B_TAPE; get: tmcommand(dev, TM_SENSE, 1); if (sc->sc_erreg & TMER_SDWN) { sleep ((caddr_t) &lbolt, PZERO+1); goto get; } sc->sc_dens = olddens; if ((sc->sc_erreg & (TMER_SELR | TMER_TUR)) != (TMER_SELR | TMER_TUR)) { uprintf("te%d: not online\n", teunit); return(EIO); } if ((flag & FWRITE) && (sc->sc_erreg & TMER_WRL)) { uprintf("te%d: no write ring\n", teunit); return(EIO); } if ((sc->sc_erreg & TMER_BOT) == 0 && (flag & FWRITE) && dens != sc->sc_dens) { uprintf("te%d: can't change density in mid-tape\n", teunit); return(EIO); } sc->sc_openf = 1; sc->sc_blkno = (daddr_t) 0; sc->sc_nxrec = (daddr_t) 65535; sc->sc_lastiow = 0; sc->sc_dens = dens; s = splclock(); if (sc->sc_tact == 0) { sc->sc_timo = INF; sc->sc_tact = 1; timeout(tmtimer, (caddr_t) dev, 5 * LINEHZ); } splx(s); return(0); } /* * Close tape device. * * If tape was open for writing or last operation was * a write, then write two EOF's and backspace over the last one. * Unless this is a non-rewinding special file, rewind the tape. * Make the tape available to others. */ tmclose(dev, flag) register dev_t dev; register flag; { register struct te_softc *sc = &te_softc[TEUNIT(dev)]; if (flag == FWRITE || (flag & FWRITE) && sc->sc_lastiow) { tmcommand(dev, TM_WEOF, 1); tmcommand(dev, TM_WEOF, 1); tmcommand(dev, TM_SREV, 1); } if ((minor(dev) & T_NOREWIND) == 0) /* * 0 count means don't hang waiting for rewind complete. * Rather ctmbuf stays busy until the operation completes * preventing further opens from completing by * preventing a TM_SENSE from completing. */ tmcommand(dev, TM_REW, 0); sc->sc_openf = 0; } /* * Execute a command on the tape drive * a specified number of times. */ tmcommand(dev, com, count) register dev_t dev; register u_short count; { int s; register struct buf *bp; bp = &ctmbuf; s = splbio(); while (bp->b_flags & B_BUSY) { /* * This special check is because B_BUSY never * gets cleared in the non-waiting rewind case. */ if (bp->b_repcnt == 0 && (bp->b_flags & B_DONE)) break; bp->b_flags |= B_WANTED; sleep((caddr_t)bp, PRIBIO); } bp->b_flags = B_BUSY | B_READ; splx(s); bp->b_dev = dev; bp->b_repcnt = -count; bp->b_command = com; bp->b_blkno = (daddr_t) 0; tmstrategy(bp); /* * In case of rewind from close, don't wait. * This is the only case where count can be 0. */ if (count == 0) return; iowait(bp); if (bp->b_flags & B_WANTED) wakeup((caddr_t)bp); bp->b_flags &= B_ERROR; } /* * Queue a tape operation. */ tmstrategy(bp) register struct buf *bp; { register s; register struct te_softc *sc = &te_softc[TEUNIT(bp->b_dev)]; if (bp->b_flags & B_PHYS) { mapalloc(bp); sc->sc_blkno = sc->sc_nxrec = dbtofsb(bp->b_blkno); sc->sc_nxrec++; } bp->av_forw = NULL; s = splbio(); if (tmtab.b_actf == NULL) tmtab.b_actf = bp; else tmtab.b_actl->av_forw = bp; tmtab.b_actl = bp; /* * If the controller is not busy, get * it going. */ if (tmtab.b_active == 0) tmstart(); splx(s); } tmstart() { daddr_t blkno; int cmd, teunit; register struct tmdevice *tmaddr = TMADDR; register struct buf *bp; register struct te_softc *sc; loop: if ((bp = tmtab.b_actf) == NULL) return; teunit = TEUNIT(bp->b_dev); /* * Record pre-transfer status (e.g. for TM_SENSE). */ sc = &te_softc[teunit]; tmaddr->tmcs = teunit << 8; sc->sc_erreg = tmaddr->tmer; sc->sc_dsreg = tmaddr->tmcs; sc->sc_resid = tmaddr->tmbc; /* * Default is that the last command was NOT a write command; * if we do a write command we will notice this in tmintr(). */ sc->sc_lastiow = 0; if (sc->sc_openf < 0 || (tmaddr->tmcs & TM_CUR) == 0) { /* * Have had a hard error on a non-raw tape * or the tape unit is now unavailable * (e.g. taken off line). */ bp->b_flags |= B_ERROR; goto next; } if (bp == &ctmbuf) { /* * Execute control operation with the specified count. */ if (bp->b_command == TM_SENSE) { goto next; } /* * Set next state; give 5 minutes to complete * rewind or 10 seconds per iteration (minimum 60 * seconds and max 5 minutes) to complete other ops. */ if (bp->b_command == TM_REW) { tmtab.b_active = SREW; sc->sc_timo = 5 * 60; } else { tmtab.b_active = SCOM; sc->sc_timo = MIN(MAX(10 * bp->b_repcnt, 60), 5 * 60); } if (bp->b_command == TM_SFORW || bp->b_command == TM_SREV) tmaddr->tmbc = bp->b_repcnt; goto dobpcmd; } /* * The following checks handle boundary cases for operation * on non-raw tapes. On raw tapes the initialization of * sc->sc_nxrec on entry causes them to be skipped normally * (except in the case of retries). */ if (dbtofsb(bp->b_blkno) > sc->sc_nxrec) { /* * Can't read past known end-of-file. */ bp->b_flags |= B_ERROR; bp->b_error = ENXIO; goto next; } if (dbtofsb(bp->b_blkno) == sc->sc_nxrec && bp->b_flags & B_READ) { /* * Reading at end of file returns 0 bytes. * Buffer will be cleared (if written) in rwip. */ bp->b_resid = bp->b_bcount; goto next; } if ((bp->b_flags & B_READ) == 0) /* * Writing sets EOF. */ sc->sc_nxrec = dbtofsb(bp->b_blkno) + (daddr_t) 1; /* * If the data transfer command is in the correct place, * set up all registers and do the transfer. */ if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) { tmaddr->tmbc = -bp->b_bcount; if ((bp->b_flags & B_READ) == 0) { if (tmtab.b_errcnt) cmd = TM_WIRG; else cmd = TM_WCOM; } else cmd = TM_RCOM; tmtab.b_active = SIO; tmaddr->tmba = bp->b_un.b_addr; cmd = sc->sc_dens | ((bp->b_xmem & 03) << 4) | cmd; sc->sc_timo = 60; /* premature, but should serve */ tmaddr->tmcs = cmd; return; } /* * Tape positioned incorrectly; * set to seek forward or backward to the correct spot. * This happens for raw tapes only on error retries. */ tmtab.b_active = SSEEK; if (blkno < dbtofsb(bp->b_blkno)) { bp->b_command = TM_SFORW; tmaddr->tmbc = (short) (blkno - dbtofsb(bp->b_blkno)); } else { bp->b_command = TM_SREV; tmaddr->tmbc = (short) (dbtofsb(bp->b_blkno) - blkno); } sc->sc_timo = MIN(MAX(10 * -tmaddr->tmbc, 60), 5 * 60); dobpcmd: /* * Do the command in bp. */ tmaddr->tmcs = (sc->sc_dens | bp->b_command); return; next: /* * Done with this operation due to error or * the fact that it doesn't do anything. * Dequeue the transfer and continue processing. */ tmtab.b_errcnt = 0; tmtab.b_actf = bp->av_forw; iodone(bp); goto loop; } /* * The interrupt routine. */ tmintr() { register struct tmdevice *tmaddr = TMADDR; register struct buf *bp; int teunit; int state; register struct te_softc *sc; if ((bp = tmtab.b_actf) == NULL) return; teunit = TEUNIT(bp->b_dev); sc = &te_softc[teunit]; /* * If last command was a rewind, and tape is still * rewinding, wait for the rewind complete interrupt. */ if (tmtab.b_active == SREW) { tmtab.b_active = SCOM; if (tmaddr->tmer & TMER_RWS) { sc->sc_timo = 5 * 60; /* 5 minutes */ return; } } /* * An operation completed... record status. */ sc->sc_timo = INF; sc->sc_erreg = tmaddr->tmer; sc->sc_dsreg = tmaddr->tmcs; sc->sc_resid = tmaddr->tmbc; if ((bp->b_flags & B_READ) == 0) sc->sc_lastiow = 1; state = tmtab.b_active; tmtab.b_active = 0; /* * Check for errors. */ if (tmaddr->tmcs & TM_ERR) { while(tmaddr->tmer & TMER_SDWN) ; /* await settle down */ /* * If we hit the end of the tape file, update our position. */ if (tmaddr->tmer & TMER_EOF) { tmseteof(bp); /* set blkno and nxrec */ state = SCOM; /* force completion */ /* * Stuff bc so it will be unstuffed correctly * later to get resid. */ tmaddr->tmbc = -bp->b_bcount; goto opdone; } /* * If we were reading raw tape and the only error was that the * record was too long, then we don't consider this an error. */ if ((bp->b_flags & B_PHYS) && (bp->b_flags & B_READ) && (tmaddr->tmer & (TMER_HARD | TMER_SOFT)) == TMER_RLE) goto ignoreerr; /* * If error is not hard, and this was an i/o operation * retry up to 8 times. */ if ((tmaddr->tmer & TMER_HARD) == 0 && state == SIO) { if (++tmtab.b_errcnt < 7) { sc->sc_blkno++; goto opcont; } } else /* * Hard or non-i/o errors on non-raw tape * cause it to close. */ if (sc->sc_openf > 0 && !(bp->b_flags & B_PHYS)) sc->sc_openf = -1; /* * Couldn't recover error */ printf("te%d: hard error bn%D er=%b\n", teunit, bp->b_blkno, sc->sc_erreg, TMER_BITS); bp->b_flags |= B_ERROR; goto opdone; } /* * Advance tape control finite state machine. */ ignoreerr: switch (state) { case SIO: /* * Read/write increments tape block number. */ sc->sc_blkno++; goto opdone; case SCOM: /* * For forward/backward space record update current position. */ if (bp == &ctmbuf) switch (bp->b_command) { case TM_SFORW: sc->sc_blkno -= (daddr_t) (bp->b_repcnt); break; case TM_SREV: sc->sc_blkno += (daddr_t) (bp->b_repcnt); break; } goto opdone; case SSEEK: sc->sc_blkno = dbtofsb(bp->b_blkno); goto opcont; default: panic("tmintr"); } opdone: /* * Reset error count and remove * from device queue. */ tmtab.b_errcnt = 0; tmtab.b_actf = bp->av_forw; bp->b_resid = -tmaddr->tmbc; iodone(bp); opcont: tmstart(); } tmtimer(dev) register dev_t dev; { register int s; register struct te_softc *sc = &te_softc[TEUNIT(dev)]; if (sc->sc_timo != INF && (sc->sc_timo -= 5) < 0) { printf("te%d: lost interrupt\n", TEUNIT(dev)); sc->sc_timo = INF; s = splbio(); tmintr(); splx(s); } timeout(tmtimer, (caddr_t) dev, 5 * LINEHZ); } tmseteof(bp) register struct buf *bp; { register struct tmdevice *tmaddr = TMADDR; daddr_t bn = dbtofsb(bp->b_blkno); register struct te_softc *sc = &te_softc[TEUNIT(bp->b_dev)]; if (bp == &ctmbuf) { if (sc->sc_blkno > bn) { /* reversing */ sc->sc_nxrec = bn - (daddr_t) (tmaddr->tmbc); sc->sc_blkno = sc->sc_nxrec; } else { /* spacing forward */ sc->sc_blkno = bn + (daddr_t) (tmaddr->tmbc); sc->sc_nxrec = sc->sc_blkno - (daddr_t) 1; } return; } /* eof on read */ sc->sc_nxrec = bn; } /*ARGSUSED*/ tmioctl(dev, cmd, data, flag) dev_t dev; u_int cmd; caddr_t data; { register struct buf *bp = &ctmbuf; register struct te_softc *sc = &te_softc[TEUNIT(dev)]; register callcount; u_short fcount; struct mtop *mtop; struct mtget *mtget; /* we depend on the values and order of the MT codes here */ static tmops[] = {TM_WEOF,TM_SFORW,TM_SREV,TM_SFORW,TM_SREV,TM_REW,TM_OFFL,TM_SENSE}; switch (cmd) { case MTIOCTOP: /* tape operation */ mtop = (struct mtop *)data; switch(mtop->mt_op) { case MTWEOF: callcount = mtop->mt_count; fcount = 1; break; case MTFSF: case MTBSF: callcount = mtop->mt_count; fcount = INF; break; case MTFSR: case MTBSR: callcount = 1; fcount = mtop->mt_count; break; case MTREW: case MTOFFL: case MTNOP: callcount = 1; fcount = 1; break; default: return (ENXIO); } if (callcount <= 0 || fcount <= 0) return (EINVAL); while (--callcount >= 0) { tmcommand(dev, tmops[mtop->mt_op], fcount); if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && bp->b_resid) return (EIO); if ((bp->b_flags & B_ERROR) || sc->sc_erreg & TMER_BOT) break; } return (geterror(bp)); case MTIOCGET: mtget = (struct mtget *)data; mtget->mt_dsreg = sc->sc_dsreg; mtget->mt_erreg = sc->sc_erreg; mtget->mt_resid = sc->sc_resid; mtget->mt_type = MT_ISTM; break; default: return (ENXIO); } return (0); } #endif NTM ng for rewind complete. * Rather ctmbuf stays busy until the operation completes * preventing further opens from completing by * preventing a TM_SENSE from completing. */ tmcommand(dev, TM_REW, 0); sc->sc_openf = 0; } /* * Execute a command on the tape drive * a specified number of times. */ tmcommand(dev, com, count) register dev_sys/pdpuba/dhureg.h 444 0 12 11407 4002272213 7561 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dhureg.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * DHU-11 device register definitions. */ struct dhudevice { union { u_short csr; /* control-status register */ struct { char csrl; /* low byte for line select */ char csrh; /* high byte for tx line */ } cb; } un1; #define dhucsr un1.csr #define dhucsrl un1.cb.csrl #define dhucsrh un1.cb.csrh union { u_short rbuf; /* recv.char/ds.change register (R) */ u_short timo; /* delay between recv -> intr (W) */ } un2; #define dhurbuf un2.rbuf #define dhutimo un2.timo u_short dhulpr; /* line parameter register */ union { char fbyte[1]; /* fifo data byte (low byte only) (W) */ u_short fdata; /* fifo data word (W) */ char sbyte[2]; /* line status/fifo size (R) */ } un3; #define dhubyte un3.fbyte[0] #define dhufifo un3.fdata #define dhusize un3.sbyte[0] #define dhustat un3.sbyte[1] u_short dhulcr; /* line control register */ u_short dhubar1; /* buffer address register 1 */ char dhubar2; /* buffer address register 2 */ char dhulcr2; /* xmit enable bit */ short dhubcr; /* buffer count register */ }; /* Bits in dhucsr */ #define DHU_CS_TIE 0x4000 /* transmit interrupt enable */ #define DHU_CS_DFAIL 0x2000 /* diagnostic fail */ #define DHU_CS_RI 0x0080 /* receiver interrupt */ #define DHU_CS_RIE 0x0040 /* receiver interrupt enable */ #define DHU_CS_MCLR 0x0020 /* master clear */ #define DHU_CS_SST 0x0010 /* skip self test (with DHU_CS_MCLR) */ #define DHU_CS_IAP 0x000f /* indirect address pointer */ #define DHU_IE (DHU_CS_TIE|DHU_CS_RIE) /* map unit into iap register select */ #define DHU_SELECT(unit) ((unit) & DHU_CS_IAP) /* Transmitter bits in high byte of dhucsr */ #define DHU_CSH_TI 0x80 /* transmit interrupt */ #define DHU_CSH_NXM 0x10 /* transmit dma err: non-exist-mem */ #define DHU_CSH_TLN 0x0f /* transmit line number */ /* map csrh line bits into line */ #define DHU_TX_LINE(csrh) ((csrh) & DHU_CSH_TLN) /* Bits in dhurbuf */ #define DHU_RB_VALID 0x8000 /* data valid */ #define DHU_RB_STAT 0x7000 /* status bits */ #define DHU_RB_DO 0x4000 /* data overrun */ #define DHU_RB_FE 0x2000 /* framing error */ #define DHU_RB_PE 0x1000 /* parity error */ #define DHU_RB_RLN 0x0f00 /* receive line number */ #define DHU_RB_RDS 0x00ff /* receive data/status */ #define DHU_RB_DIAG 0x0001 /* if DHU_RB_STAT -> diag vs modem */ /* map rbuf line bits into line */ #define DHU_RX_LINE(rbuf) (((rbuf) & DHU_RB_RLN) >> 8) /* Bits in dhulpr */ #define DHU_LP_TSPEED 0xf000 #define DHU_LP_RSPEED 0x0f00 #define DHU_LP_TWOSB 0x0080 #define DHU_LP_EPAR 0x0040 #define DHU_LP_PENABLE 0x0020 #define DHU_LP_BITS8 0x0018 #define DHU_LP_BITS7 0x0010 #define DHU_LP_BITS6 0x0008 /* Bits in dhustat */ #define DHU_ST_DSR 0x80 /* data set ready */ #define DHU_ST_RI 0x20 /* ring indicator */ #define DHU_ST_DCD 0x10 /* carrier detect */ #define DHU_ST_CTS 0x04 /* clear to send */ #define DHU_ST_DHU 0x01 /* always one on a dhu, zero on dhv */ /* Bits in dhulcr */ #define DHU_LC_RTS 0x1000 /* request to send */ #define DHU_LC_DTR 0x0200 /* data terminal ready */ #define DHU_LC_MODEM 0x0100 /* modem control enable */ #define DHU_LC_MAINT 0x00c0 /* maintenance mode */ #define DHU_LC_FXOFF 0x0020 /* force xoff */ #define DHU_LC_OAUTOF 0x0010 /* output auto flow */ #define DHU_LC_BREAK 0x0008 /* break control */ #define DHU_LC_RXEN 0x0004 /* receiver enable */ #define DHU_LC_IAUTOF 0x0002 /* input auto flow */ #define DHU_LC_TXABORT 0x0001 /* transmitter abort */ /* Bits in dhulcr2 */ #define DHU_LC2_TXEN 0x80 /* transmitter enable */ /* Bits in dhubar2 */ #define DHU_BA2_DMAGO 0x80 /* transmit dma start */ #define DHU_BA2_XBA 0x03 /* top two bits of dma address */ #define DHU_XBA_SHIFT 16 /* amount to shift xba bits */ /* Bits for dhumctl only: stat bits are shifted up 16 */ #define DHU_ON (DHU_LC_DTR|DHU_LC_RTS|DHU_LC_MODEM) #define DHU_OFF DHU_LC_MODEM #define DHU_DSR ((long)DHU_ST_DSR << 16) #define DHU_RNG ((long)DHU_ST_RI << 16) #define DHU_CAR ((long)DHU_ST_DCD << 16) #define DHU_CTS ((long)DHU_ST_CTS << 16) #define DHU_RTS DHU_LC_RTS #define DHU_DTR DHU_LC_DTR #define DHU_BRK DHU_LC_BREAK #define DHU_LE DHU_LC_MODEM /* bits in dm lsr, copied from dmreg.h */ #define DML_DSR 0000400 /* data set ready, not a real DM bit */ #define DML_RNG 0000200 /* ring */ #define DML_CAR 0000100 /* carrier detect */ #define DML_CTS 0000040 /* clear to send */ #define DML_SR 0000020 /* secondary receive */ #define DML_ST 0000010 /* secondary transmit */ #define DML_RTS 0000004 /* request to send */ #define DML_DTR 0000002 /* data terminal ready */ #define DML_LE 0000001 /* line enable */ sc->sc_timo = 60; /* premature, but should serve */ tmaddr->tmcs = cmd; return; } /* * Tape positioned incorrectly; * set to seek forward or backward to the correct spot. * This happens for raw tapes only on error retries. */ tmtab.sys/pdpuba/dr.c 444 0 12 20070 5667260157 6725 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dr.c 1.4 (2.11BSD GTE) 11/30/94 */ /* * DR11-W device driver */ #include "dr.h" #if NDR > 0 #include "param.h" #include "../machine/seg.h" #include "user.h" #include "proc.h" #include "buf.h" #include "conf.h" #include "ioctl.h" #include "drreg.h" struct dr11w { int i_flags; /* interface flags */ int i_req; /* request number (for timeout) */ int i_unit; /* unit number of device */ int i_prev; /* previous request number (timeout) */ short i_fun; /* function bits */ struct proc *i_proc; /* process pointer of opening process */ int i_sig; /* signal to send on ATTN */ int i_tsig; /* signal to send on timeout */ struct buf i_tab; /* buffer for device */ struct drdevice *i_addr; /* address of DR11-W interface */ }; struct dr11w dr11[NDR]; drattach(addr, unit) struct drdevice *addr; int unit; { if(unit > NDR) return(0); if((addr != (struct drdevice *)NULL) && (fioword(addr) != -1)) { dr11[unit].i_addr = addr; dr11[unit].i_flags = DR_ALIVE; /* mark as active */ dr11[unit].i_unit = unit; return(1); } return(0); } dropen(dev) dev_t dev; { register int unit; register struct dr11w *drptr; extern int drtimeout(); unit = minor(dev) & 07; /* get minor device number */ drptr = &dr11[unit]; if((unit > NDR) || !(drptr->i_flags & DR_ALIVE)) return(ENXIO); /* not attatched or present */ drptr->i_flags |= DR_OPEN; drptr->i_flags &= ~(DR_IGNORE | DR_TIMEOUT); drptr->i_proc = u.u_procp; /* process pointer of opener */ drptr->i_sig = 0; /* clear signals (set by ioctl) */ drptr->i_tsig = 0; drptr->i_fun = 0; /* clear function */ timeout(drtimeout, (caddr_t)drptr, LINEHZ); return(0); } drclose(dev, flag) dev_t dev; { register int unit; register struct drdevice *addr; unit = minor(dev) & 07; dr11[unit].i_flags &= ~DR_OPEN; /* clear opened status */ addr = dr11[unit].i_addr; /* get address of DR11-W */ addr->csr = dr11[unit].i_fun; /* clear IE and GO bits */ } drstrategy(bp) register struct buf *bp; { register struct buf *dp; register struct dr11w *drptr; int s; drptr = &dr11[minor(bp->b_dev) & 07]; if(!(drptr->i_flags & DR_OPEN)) { bp->b_flags |= B_ERROR; /* unit not open */ iodone(bp); return; } dp = &(drptr->i_tab); /* point to buffer */ bp->av_forw = NULL; s = splbio(); /* lock out interrupts */ mapalloc(bp); if(dp->b_actf == NULL) /* if nothing in current buffer */ dp->b_actf = bp; /* this request is first */ dp->b_actl = bp; /* set last request */ if(dp->b_active == 0) /* if not active now */ drstart(drptr); /* start the DR11-W */ splx(s); /* return to normal state */ } drstart(drptr) register struct dr11w *drptr; { register struct buf *bp, *dp; register struct drdevice *addr; short com; if(!drptr) return; dp = &(drptr->i_tab); /* point dp to device buffer */ if((bp = dp->b_actf) == NULL) /* if nothing in queue */ return; /* return */ drptr->i_req++; /* increment request number */ if(drptr->i_flags & DR_TIMEOUT) /* do we need timeout checking */ { drptr->i_flags |= DR_TACTIVE; /* mark active timeout */ } dp->b_active = 1; /* set active flag */ addr = drptr->i_addr; /* get device pointer */ /* * Set up DR11-W for specific operation */ addr->bar = (short)bp->b_un.b_addr; addr->wcr = -(bp->b_bcount >> 1); /* DR deals in words */ com = ((bp->b_xmem & 3) << 4) | drptr->i_fun; addr->csr = com; /* set csr fun and address */ com |= (DR_IE | DR_GO); /* set IE and GO bits (also) */ addr->csr = com; } drintr(unit) int unit; { register struct buf *bp; register struct drdevice *dr; register struct dr11w *drptr; mapinfo map; drptr = &dr11[unit]; /* point to struct for device */ dr = drptr->i_addr; /* get address of device */ if(drptr->i_tab.b_active == 0) /* if not active, return */ return; bp = drptr->i_tab.b_actf; /* point to current buffer */ if(dr->csr & DR_ERR) /* if error */ { /* * The error bit can be set in one of two ways: * a 'real' error (timing, non-existant memory) or * by the interface setting ATTN true. This is * not considered an 'error' but cause to send * a signal to the parent process. He (hopefully) * will know what to do then. */ if(dr->csr & DR_ATTN) { dr->csr = drptr->i_fun; savemap(map); if(drptr->i_sig) psignal(drptr->i_proc, drptr->i_sig); restormap(map); } else { printf("dr%d: error ", unit); printf("csr=%b, ", dr->csr, DRCSR_BITS); dr->csr = DR_ERR | drptr->i_fun; printf("eir=%b\n", dr->csr, DREIR_BITS); /* now reset the DR11-W interface */ dr->csr = DR_MANT | drptr->i_fun; dr->csr = drptr->i_fun; bp->b_flags |= B_ERROR; } } drptr->i_flags &= ~DR_TACTIVE; /* we beat the timeout */ drptr->i_tab.b_active = 0; /* clear global stuff */ drptr->i_tab.b_errcnt = 0; drptr->i_tab.b_actf = bp->b_forw; /* link to next request */ bp->b_resid = -(dr->wcr) << 1; /* change words to bytes */ iodone(bp); /* tell system we are done */ if(drptr->i_tab.b_actf) /* start next request */ drstart(drptr); } drioctl(dev, cmd, data, flag) dev_t dev; u_int cmd; register caddr_t data; int flag; { register struct dr11w *drptr; register struct drdevice *dr; int *sgbuf = (int *)data; drptr = &dr11[minor(dev) & 07]; dr = drptr->i_addr; if(drptr->i_tab.b_active) return (EINVAL); switch(cmd) { case DRGTTY: sgbuf[0] = drptr->i_flags; sgbuf[1] = drptr->i_fun >> 1; break; case DRSTTY: drptr->i_fun = (sgbuf[1] & 07) << 1; dr->csr = drptr->i_fun; drptr->i_flags &= ~(DR_TIMEOUT | DR_IGNORE); drptr->i_flags |= sgbuf[0] & (DR_TIMEOUT | DR_IGNORE); break; case DRSFUN: drptr->i_fun = (sgbuf[0] & 07) << 1; dr->csr = drptr->i_fun; break; case DRSFLAG: drptr->i_flags &= ~(DR_TIMEOUT | DR_IGNORE); drptr->i_flags |= sgbuf[0] & (DR_TIMEOUT | DR_IGNORE); break; case DRGCSR: sgbuf[0] = dr->csr; sgbuf[1] = dr->wcr; break; case DRSSIG: drptr->i_sig = sgbuf[0]; if((drptr->i_sig < 0) || (drptr->i_sig > 15)) { drptr->i_sig = 0; return (EINVAL); } break; case DRESET: dr->csr = DR_MANT | drptr->i_fun; dr->csr = drptr->i_fun; break; case DRSTIME: drptr->i_tsig = sgbuf[0]; if((drptr->i_tsig < 0) || (drptr->i_tsig > 15)) { drptr->i_tsig = 0; return (EINVAL); } drptr->i_flags |= DR_TIMEOUT; drptr->i_flags &= ~DR_IGNORE; break; case DRCTIME: drptr->i_flags &= ~(DR_TIMEOUT | DR_IGNORE); break; case DRITIME: drptr->i_flags |= DR_IGNORE; break; case DROUTPUT: dr->dar = sgbuf[0]; break; case DRINPUT: sgbuf[0] = dr->dar; break; default: return (EINVAL); } return (0); } drtimeout(ptr) caddr_t ptr; { register struct dr11w *drptr; mapinfo map; drptr = (struct dr11w *)ptr; if((drptr->i_flags & DR_TACTIVE) && (drptr->i_req == drptr->i_prev)) { printf("dr%d: timeout error\n", drptr->i_unit); savemap(map); if(drptr->i_tsig) psignal(drptr->i_proc, drptr->i_tsig); restormap(map); drabort(drptr); savemap(map); if(drptr->i_tab.b_actf) drstart(drptr); /* start next request */ restormap(map); } if(drptr->i_flags & (DR_TACTIVE | DR_OPEN)) { drptr->i_prev = drptr->i_req; /* arm timeout */ timeout(drtimeout, ptr, LINEHZ); } } drabort(drptr) register struct dr11w *drptr; { register struct buf *bp; register struct drdevice *dr; mapinfo map; savemap(map); dr = drptr->i_addr; /* point to device */ bp = drptr->i_tab.b_actf; /* point to current buffer */ drptr->i_flags &= ~DR_TACTIVE; /* turn off timeout active */ drptr->i_tab.b_active = 0; /* clean up global stuff */ drptr->i_tab.b_errcnt = 0; drptr->i_tab.b_actf = bp->b_forw; /* link to next request */ bp->b_resid = -(dr->wcr) << 1; /* make it bytes */ if(!(drptr->i_flags & DR_IGNORE)) bp->b_flags |= B_ERROR; /* set an error condition */ dr->csr = DR_MANT | drptr->i_fun; /* clear IE bit in csr */ dr->csr = drptr->i_fun; /* restore function bits */ restormap(map); iodone(bp); /* done with that request */ } #endif NDR bp->b_command = TM_SFORW; tmaddr->tmbc = (short) (blkno - dbtofsb(bp->b_blkno)); } else { bp->b_command = TM_SREV; tmaddr->tmbc = (short) (dbtofsb(bp->b_blkno) - blkno); } sc->sc_timo = MIN(MAX(10 * -tmaddr->tmbc, 60), 5 * 60); dobpcmd: /* * Do the command in bp. */ tmaddr->tmcs = (sc->sc_dens | bp->b_command); return; next: /* * Done with this operation due to error or * the fact that it doesn't do anything. * Dequeue the trasys/pdpuba/lp.c 444 0 12 12612 5667013472 6732 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)lp.c 1.2 (2.11BSD GTE) 11/29/94 */ #include "lp.h" #if NLP > 0 /* * LP-11 Line printer driver * * This driver has been modified to work on printers where * leaving LP_IE set would cause continuous interrupts. */ #include "param.h" #include "systm.h" #include "user.h" #include "ioctl.h" #include "tty.h" #include "uio.h" #include "kernel.h" #define LPPRI (PZERO + 8) #define LP_IE 0100 /* interrupt enable */ #define LP_RDY 0200 /* ready */ #define LP_ERR 0100000 /* error */ #define LPLWAT 40 #define LPHWAT 400 #define LPBUFSIZE 512 #define CAP 1 #ifndef LP_MAXCOL #define LP_MAXCOL 132 #endif #define LPUNIT(dev) (minor(dev) >> 3) struct lpdevice { short lpcs; short lpdb; }; struct lp_softc { struct clist sc_outq; int sc_state; int sc_physcol; int sc_logcol; int sc_physline; char sc_flags; int sc_lpchar; } lp_softc[NLP]; struct lpdevice *lp_addr[NLP]; int lptout(); /* bits for state */ #define OPEN 1 /* device is open */ #define TOUT 2 /* timeout is active */ #define MOD 4 /* device state has been modified */ #define ASLP 8 /* awaiting draining of printer */ lpattach(addr, unit) struct lpdevice *addr; register u_int unit; { if (unit >= NLP) return (0); lp_addr[unit] = addr; return (1); } /*ARGSUSED*/ lpopen(dev, flag) dev_t dev; int flag; { register struct lp_softc *sc; register int unit, s; if ((unit = LPUNIT(dev)) >= NLP || (sc = &lp_softc[unit])->sc_state&OPEN || lp_addr[unit] == 0) return (ENXIO); if (lp_addr[unit]->lpcs&LP_ERR) return (EIO); sc->sc_state |= OPEN; sc->sc_flags = minor(dev) & 07; s = spl4(); if ((sc->sc_state&TOUT) == 0) { sc->sc_state |= TOUT; timeout(lptout, (caddr_t)dev, 10*LINEHZ); } splx(s); lpcanon(dev, '\f'); return (0); } /*ARGSUSED*/ lpclose(dev, flag) dev_t dev; int flag; { register struct lp_softc *sc = &lp_softc[LPUNIT(dev)]; lpcanon(dev, '\f'); sc->sc_state &= ~OPEN; } lpwrite(dev, uio, flag) register dev_t dev; register struct uio *uio; int flag; { register int n; register char *cp; char inbuf[LPBUFSIZE]; int error; while (n = MIN(LPBUFSIZE, uio->uio_resid)) { cp = inbuf; error = uiomove(cp, (int)n, uio); if (error) return (error); do lpcanon(dev, *cp++); while (--n); } return (0); } lpcanon(dev, c) dev_t dev; register int c; { struct lp_softc *sc = &lp_softc[LPUNIT(dev)]; register int logcol, physcol, s; if (sc->sc_flags&CAP) { register c2; if (c >= 'a' && c <= 'z') c += 'A'-'a'; else switch (c) { case '{': c2 = '('; goto esc; case '}': c2 = ')'; goto esc; case '`': c2 = '\''; goto esc; case '|': c2 = '!'; goto esc; case '~': c2 = '^'; esc: lpcanon(dev, c2); sc->sc_logcol--; c = '-'; } } logcol = sc->sc_logcol; physcol = sc->sc_physcol; if (c == ' ') logcol++; else switch(c) { case '\t': logcol = (logcol + 8) & ~7; break; case '\f': if (sc->sc_physline == 0 && physcol == 0) break; /* fall into ... */ case '\n': lpoutput(dev, c); if (c == '\f') sc->sc_physline = 0; else sc->sc_physline++; physcol = 0; /* fall into ... */ case '\r': s = spl4(); logcol = 0; lpintr(LPUNIT(dev)); splx(s); break; case '\b': if (logcol > 0) logcol--; break; default: if (logcol < physcol) { lpoutput(dev, '\r'); physcol = 0; } if (logcol < LP_MAXCOL) { while (logcol > physcol) { lpoutput(dev, ' '); physcol++; } lpoutput(dev, c); physcol++; } logcol++; } if (logcol > 1000) /* ignore long lines */ logcol = 1000; sc->sc_logcol = logcol; sc->sc_physcol = physcol; } lpoutput(dev, c) dev_t dev; int c; { register struct lp_softc *sc = &lp_softc[LPUNIT(dev)]; int s; if (sc->sc_outq.c_cc >= LPHWAT) { s = spl4(); lpintr(LPUNIT(dev)); /* unchoke */ while (sc->sc_outq.c_cc >= LPHWAT) { sc->sc_state |= ASLP; /* must be LP_ERR */ sleep((caddr_t)sc, LPPRI); } splx(s); } while (putc(c, &sc->sc_outq)) sleep((caddr_t)&lbolt, LPPRI); } lpintr(lp11) int lp11; { register int n; register struct lp_softc *sc = &lp_softc[lp11]; register struct lpdevice *lpaddr = lp_addr[lp11]; lpaddr->lpcs &= ~LP_IE; n = sc->sc_outq.c_cc; if (sc->sc_lpchar < 0) sc->sc_lpchar = getc(&sc->sc_outq); while ((lpaddr->lpcs & LP_RDY) && sc->sc_lpchar >= 0) { lpaddr->lpdb = sc->sc_lpchar; sc->sc_lpchar = getc(&sc->sc_outq); } sc->sc_state |= MOD; if (sc->sc_outq.c_cc > 0 && (lpaddr->lpcs&LP_ERR) == 0) lpaddr->lpcs |= LP_IE; /* ok and more to do later */ if (n>LPLWAT && sc->sc_outq.c_cc<=LPLWAT && sc->sc_state&ASLP) { sc->sc_state &= ~ASLP; wakeup((caddr_t)sc); /* top half should go on */ } } lptout(dev) dev_t dev; { register struct lp_softc *sc; register struct lpdevice *lpaddr; sc = &lp_softc[LPUNIT(dev)]; lpaddr = lp_addr[LPUNIT(dev)]; if ((sc->sc_state&MOD) != 0) { sc->sc_state &= ~MOD; /* something happened */ /* so don't sweat */ timeout(lptout, (caddr_t)dev, 2*LINEHZ); return; } if ((sc->sc_state&OPEN) == 0 && sc->sc_outq.c_cc == 0) { sc->sc_state &= ~TOUT; /* no longer open */ lpaddr->lpcs = 0; return; } if (sc->sc_outq.c_cc && (lpaddr->lpcs&LP_RDY) && (lpaddr->lpcs&LP_ERR)==0) lpintr(LPUNIT(dev)); /* ready to go */ timeout(lptout, (caddr_t)dev, 10*LINEHZ); } #endif unit] = addr; return (1); } /*ARGSUSED*/ lpopen(dev, flag) dev_t dev; int flag; { register struct lp_softc *sc; sys/pdpuba/drreg.h 444 0 12 5627 4001144527 7402 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)drreg.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * Registers of the DR11-W parallel DMA interface */ struct drdevice { short wcr; /* word count register */ short bar; /* bus address register */ short csr; /* csr/eir register */ short dar; /* input/output data register */ }; struct sg1 { short word; /* pass one word of info in or out */ }; struct sg2 { short word1; /* pass two words of info in or out */ short word2; }; /* Bits of the csr */ #define DR_GO 0000001 /* start transfer */ #define DR_FN1 0000002 /* user defined function bits */ #define DR_FN2 0000004 #define DR_FN3 0000010 #define DR_XBA 0000060 /* Unibus extension bits */ #define DR_IE 0000100 /* interrupt enable */ #define DR_RDY 0000200 /* ready bit */ #define DR_CYL 0000400 /* cycle start */ #define DR_ST1 0001000 /* user defined status */ #define DR_ST2 0002000 #define DR_ST3 0004000 #define DR_MANT 0010000 /* maintenance mode bit */ #define DR_ATTN 0020000 /* attention bit from interface */ #define DR_NEX 0040000 /* non-existant memory */ #define DR_ERR 0100000 /* general error bit */ #define DRCSR_BITS \ "\10\20ERR\17NEX\16ATTN\15MAINT\14STA\13STB\12STC\ \11CYCL\10RDY\7IE\6XBA17\5XBA16\4FN3\3FN2\2FN1\1GO" /* Bits of the EIR */ #define DR_FLG 0000001 /* register flag 1=EIR, 0=CSR */ #define DR_NCYL 0000400 /* N-cycle burst selected */ #define DR_BDL 0001000 /* Burst data late */ #define DR_PAR 0002000 /* parity error */ #define DR_ACLO 0004000 /* powerfailure */ #define DR_MRQ 0010000 /* multicycle request */ /* All remaining bits same as CSR */ #define DREIR_BITS \ "\10\20ERR\17NEX\16ATTN\15MRQ\14ACLO\13PAR\12BDL\11NCYL\1REG" /* * Definitions for ioctl calls for DR11-W interface */ #define DRGTTY _IOR(d, 1, struct sg2) /* get dr11 status */ #define DRSTTY _IOW(d, 2, struct sg2) /* set flags & function */ #define DRSFUN _IOW(d, 3, struct sg1) /* set function */ #define DRSFLAG _IOW(d, 4, struct sg1) /* set flags */ #define DRGCSR _IOR(d, 5, struct sg2) /* get csr and wcr */ #define DRSSIG _IOW(d, 6, struct sg1) /* set sig for ATTN interrupt */ #define DRESET _IO(d, 7) /* reset DR11-W interface */ #define DRSTIME _IOW(d, 8, struct sg1) /* set timeout */ #define DRCTIME _IO(d, 9) /* set timeout inactive */ #define DROUTPUT _IOW(d, 10, struct sg1) /* word to output data reg */ #define DRINPUT _IOR(d, 11, struct sg1) /* word from input data reg */ #define DRITIME _IO(d, 12) /* no set error on timeout */ /* * i_flags definition */ #define DR_ALIVE 0000001 /* unit has attatched */ #define DR_OPEN 0000002 /* unit has been opened */ #define DR_TIMEOUT 0000004 /* unit needs timeout (set by user) */ #define DR_TACTIVE 0000010 /* timeout active on unit */ #define DR_IGNORE 0000020 /* ignore timeout error */ ogcol; physcol = sc->sc_physcol; if (c == ' ') logcol++; else switch(c) { case '\t': logcol = (lsys/pdpuba/dz.c 444 0 12 27001 5667262034 6732 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dz.c 1.3 (2.11BSD GTE) 11/29/94 */ /* * DZ11 device driver * * This driver mimics dh.c; see it for explanation of common code. */ #include "dz.h" #if NDZ > 0 #include "param.h" #include "user.h" #include "file.h" #include "conf.h" #include "ioctl.h" #include "tty.h" #include "dzreg.h" #include "pdma.h" #include "proc.h" #include "ubavar.h" #include "vm.h" #include "kernel.h" #include "syslog.h" #include "systm.h" struct uba_device dzinfo[NDZ]; #define NDZLINE (NDZ*8) #define FASTTIMER (LINEHZ/30) /* rate to drain silos, when in use */ int dzstart(), dzxint(), dzdma(); int ttrstrt(); struct tty dz_tty[NDZLINE]; int dz_cnt = { NDZLINE }; int dzact; int dzsilos; /* mask of dz's with silo in use */ int dzchars[NDZ]; /* recent input count */ int dzrate[NDZ]; /* smoothed input count */ int dztimerintvl; /* time interval for dztimer */ int dzhighrate = 100; /* silo on if dzchars > dzhighrate */ int dzlowrate = 75; /* silo off if dzrate < dzlowrate */ #define dzwait(x) while (((x)->dzlcs & DZ_ACK) == 0) /* * Software copy of dzbrk since it isn't readable */ char dz_brk[NDZ]; char dzsoftCAR[NDZ]; char dz_lnen[NDZ]; /* saved line enable bits for DZ32 */ /* * The dz11 doesn't interrupt on carrier transitions, so * we have to use a timer to watch it. */ char dz_timer; /* timer started? */ /* * Pdma structures for fast output code */ struct pdma dzpdma[NDZLINE]; char dz_speeds[] = { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,037,0 }; #ifndef PORTSELECTOR #define ISPEED B9600 #define IFLAGS (EVENP|ODDP|ECHO) #else #define ISPEED B4800 #define IFLAGS (EVENP|ODDP) #endif #define UNIT(x) (minor(x)&0177) dzattach(addr, unit) caddr_t addr; u_int unit; { extern dzscan(); if (!addr || unit >= NDZ || dzinfo[unit].ui_addr) return (0); { register struct uba_device *ui; ui = &dzinfo[unit]; ui->ui_unit = unit; ui->ui_addr = addr; ui->ui_alive = 1; } { register struct pdma *pdp = &dzpdma[unit*8]; register struct tty *tp = &dz_tty[unit*8]; register int cntr; for (cntr = 0; cntr < 8; cntr++) { pdp->pd_addr = (struct dzdevice *)addr; pdp->p_arg = tp; pdp++, tp++; } } if (dz_timer == 0) { dz_timer++; timeout(dzscan, (caddr_t)0, LINEHZ); dztimerintvl = FASTTIMER; } return (1); } /*ARGSUSED*/ dzopen(dev, flag) register dev_t dev; { register struct tty *tp; register int unit; unit = UNIT(dev); if (unit >= NDZLINE || dzpdma[unit].pd_addr == 0) return (ENXIO); tp = &dz_tty[unit]; tp->t_addr = (caddr_t)&dzpdma[unit]; tp->t_oproc = dzstart; if ((tp->t_state & TS_ISOPEN) == 0) { ttychars(tp); #ifndef PORTSELECTOR if (tp->t_ispeed == 0) { #else tp->t_state |= TS_HUPCLS; #endif PORTSELECTOR tp->t_ispeed = ISPEED; tp->t_ospeed = ISPEED; tp->t_flags = IFLAGS; #ifndef PORTSELECTOR } #endif PORTSELECTOR dzparam(unit); } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) return (EBUSY); (void) dzmctl(dev, DZ_ON, DMSET); #ifdef pdp11 if (dev & 0200) { dzsoftCAR[unit >> 3] |= (1<<(unit&07)); tp->t_state |= TS_CARR_ON; } else dzsoftCAR[unit >> 3] &= ~(1<<(unit&07)); #endif (void) _spl5(); while ((tp->t_state & TS_CARR_ON) == 0) { tp->t_state |= TS_WOPEN; sleep((caddr_t)&tp->t_rawq, TTIPRI); } (void) _spl0(); return ((*linesw[tp->t_line].l_open)(dev, tp)); } /*ARGSUSED*/ dzclose(dev, flag) dev_t dev; int flag; { register struct tty *tp; register int unit; struct dzdevice *dzaddr; register int dz; unit = UNIT(dev); dz = unit >> 3; tp = &dz_tty[unit]; (*linesw[tp->t_line].l_close)(tp, flag); dzaddr = dzpdma[unit].pd_addr; dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07))); if ((tp->t_state&(TS_HUPCLS|TS_WOPEN)) || (tp->t_state&TS_ISOPEN) == 0) (void) dzmctl(dev, DZ_OFF, DMSET); ttyclose(tp); } dzread(dev, uio, flag) register dev_t dev; struct uio *uio; int flag; { register struct tty *tp; tp = &dz_tty[UNIT(dev)]; return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); } dzwrite(dev, uio, flag) register dev_t dev; struct uio *uio; int flag; { register struct tty *tp; tp = &dz_tty[UNIT(dev)]; return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); } /*ARGSUSED*/ dzrint(dz) int dz; { register struct tty *tp; register int c; register struct dzdevice *dzaddr; struct tty *tp0; register int unit; int overrun = 0; if ((dzact & (1<dzrbuf) < 0) { /* char present */ dzchars[dz]++; tp = tp0 + ((c>>8)&07); if (tp >= &dz_tty[NDZLINE]) continue; if ((tp->t_state & TS_ISOPEN) == 0) { wakeup((caddr_t)&tp->t_rawq); #ifdef PORTSELECTOR if ((tp->t_state&TS_WOPEN) == 0) #endif continue; } if (c&DZ_FE) if (tp->t_flags & RAW) c = 0; else #ifdef OLDWAY c = tp->t_intrc; #else c = tp->t_brkc; #endif if (c&DZ_DO && overrun == 0) { log(LOG_WARNING, "dz%d,%d: silo overflow\n", dz, (c>>8)&7); overrun = 1; } if (c&DZ_PE) if (((tp->t_flags & (EVENP|ODDP)) == EVENP) || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) continue; #if NBK > 0 if (tp->t_line == NETLDISC) { c &= 0177; BKINPUT(c, tp); } else #endif (*linesw[tp->t_line].l_rint)(c, tp); } } /*ARGSUSED*/ dzioctl(dev, cmd, data, flag) dev_t dev; u_int cmd; caddr_t data; { register struct tty *tp; register int unit = UNIT(dev); int dz = unit >> 3; register struct dzdevice *dzaddr; register int error; tp = &dz_tty[unit]; error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); if (error >= 0) return (error); error = ttioctl(tp, cmd, data, flag); if (error >= 0) { if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS || cmd == TIOCLBIC || cmd == TIOCLSET) dzparam(unit); return (error); } switch (cmd) { case TIOCSBRK: dzaddr = ((struct pdma *)(tp->t_addr))->pd_addr; dzaddr->dzbrk = (dz_brk[dz] |= 1 << (unit&07)); break; case TIOCCBRK: dzaddr = ((struct pdma *)(tp->t_addr))->pd_addr; dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07))); break; case TIOCSDTR: (void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIS); break; case TIOCCDTR: (void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIC); break; case TIOCMSET: (void) dzmctl(dev, dmtodz(*(int *)data), DMSET); break; case TIOCMBIS: (void) dzmctl(dev, dmtodz(*(int *)data), DMBIS); break; case TIOCMBIC: (void) dzmctl(dev, dmtodz(*(int *)data), DMBIC); break; case TIOCMGET: *(int *)data = dztodm(dzmctl(dev, 0, DMGET)); break; default: return (ENOTTY); } return (0); } static dmtodz(bits) register int bits; { register int b; b = (bits >>1) & 0370; if (bits & DML_ST) b |= DZ_ST; if (bits & DML_RTS) b |= DZ_RTS; if (bits & DML_DTR) b |= DZ_DTR; if (bits & DML_LE) b |= DZ_LE; return(b); } static dztodm(bits) register int bits; { register int b; b = (bits << 1) & 0360; if (bits & DZ_DSR) b |= DML_DSR; if (bits & DZ_DTR) b |= DML_DTR; if (bits & DZ_ST) b |= DML_ST; if (bits & DZ_RTS) b |= DML_RTS; return(b); } dzparam(unit) int unit; { register struct tty *tp; register struct dzdevice *dzaddr; register int lpr; tp = &dz_tty[unit]; dzaddr = dzpdma[unit].pd_addr; if (dzsilos & (1 << (unit >> 3))) dzaddr->dzcsr = DZ_IEN | DZ_SAE; else dzaddr->dzcsr = DZ_IEN; dzact |= (1<<(unit>>3)); if (tp->t_ispeed == 0) { (void) dzmctl(unit, DZ_OFF, DMSET); /* hang up line */ return; } lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07); if (tp->t_flags & (RAW|LITOUT|PASS8)) lpr |= BITS8; else lpr |= (BITS7|PENABLE); if ((tp->t_flags & EVENP) == 0) lpr |= OPAR; if (tp->t_ispeed == B110) lpr |= TWOSB; dzaddr->dzlpr = lpr; } dzxint(tp) register struct tty *tp; { register struct pdma *dp; dp = (struct pdma *)tp->t_addr; tp->t_state &= ~TS_BUSY; if (tp->t_state & TS_FLUSH) tp->t_state &= ~TS_FLUSH; else { ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); dp->p_end = dp->p_mem = tp->t_outq.c_cf; } if (tp->t_line) (*linesw[tp->t_line].l_start)(tp); else dzstart(tp); if ((tp->t_outq.c_cc == 0) || (tp->t_state&TS_BUSY)==0) dp->pd_addr->dztcr &= ~(1 << (UNIT(tp->t_dev) & 07)); } dzstart(tp) register struct tty *tp; { register struct pdma *dp; struct dzdevice *dzaddr; register int cc; int s; dp = (struct pdma *)tp->t_addr; dzaddr = dp->pd_addr; s = spl5(); if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) goto out; if (tp->t_outq.c_cc <= TTLOWAT(tp)) { if (tp->t_state&TS_ASLEEP) { tp->t_state &= ~TS_ASLEEP; wakeup((caddr_t) &tp->t_outq); } if (tp->t_wsel) { selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); tp->t_wsel = 0; tp->t_state &= ~TS_WCOLL; } } if (tp->t_outq.c_cc == 0) goto out; if (tp->t_flags & (RAW|LITOUT)) cc = ndqb(&tp->t_outq, 0); else { cc = ndqb(&tp->t_outq, 0200); if (cc == 0) { cc = getc(&tp->t_outq); timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6); tp->t_state |= TS_TIMEOUT; goto out; } } tp->t_state |= TS_BUSY; dp->p_end = dp->p_mem = tp->t_outq.c_cf; dp->p_end += cc; dzaddr->dztcr |= (1 << (UNIT(tp->t_dev) & 7)); out: splx(s); } /* * Stop output on a line. */ /*ARGSUSED*/ dzstop(tp, flag) register struct tty *tp; { register struct pdma *dp; register int s; dp = (struct pdma *)tp->t_addr; s = spl5(); if (tp->t_state & TS_BUSY) { dp->p_end = dp->p_mem; if ((tp->t_state & TS_TTSTOP)==0) tp->t_state |= TS_FLUSH; } splx(s); } static dzmctl(dev, bits, how) dev_t dev; int bits, how; { register struct dzdevice *dzaddr; register int unit, mbits; int b, s; unit = UNIT(dev); b = 1<<(unit&7); dzaddr = dzpdma[unit].pd_addr; s = spl5(); mbits = (dzaddr->dzdtr & b) ? DZ_DTR : 0; mbits |= (dzaddr->dzmsr & b) ? DZ_CD : 0; mbits |= (dzaddr->dztbuf & b) ? DZ_RI : 0; switch (how) { case DMSET: mbits = bits; break; case DMBIS: mbits |= bits; break; case DMBIC: mbits &= ~bits; break; case DMGET: (void) splx(s); return(mbits); } if (mbits & DZ_DTR) dzaddr->dzdtr |= b; else dzaddr->dzdtr &= ~b; (void) splx(s); return(mbits); } int dztransitions, dzfasttimers; /*DEBUG*/ dzscan() { register i; register struct dzdevice *dzaddr; register bit; register struct tty *tp; register car; int olddzsilos = dzsilos; int dztimer(); for (i = 0; i < NDZLINE; i++) { dzaddr = dzpdma[i].pd_addr; if (dzaddr == 0) continue; tp = &dz_tty[i]; bit = 1<<(i&07); car = 0; if (dzsoftCAR[i>>3]&bit) car = 1; else if (dzaddr->dzcsr & DZ_32) { dzaddr->dzlcs = i&07; dzwait(dzaddr); car = dzaddr->dzlcs & DZ_CD; } else car = dzaddr->dzmsr&bit; if (car) { /* carrier present */ if ((tp->t_state & TS_CARR_ON) == 0) (void)(*linesw[tp->t_line].l_modem)(tp, 1); } else if ((tp->t_state&TS_CARR_ON) && (*linesw[tp->t_line].l_modem)(tp, 0) == 0) dzaddr->dzdtr &= ~bit; } for (i = 0; i < NDZ; i++) { ave(dzrate[i], dzchars[i], 8); if (dzchars[i] > dzhighrate && ((dzsilos & (1 << i)) == 0)) { dzpdma[i << 3].pd_addr->dzcsr = DZ_IEN | DZ_SAE; dzsilos |= (1 << i); dztransitions++; /*DEBUG*/ } else if ((dzsilos & (1 << i)) && (dzrate[i] < dzlowrate)) { dzpdma[i << 3].pd_addr->dzcsr = DZ_IEN; dzsilos &= ~(1 << i); } dzchars[i] = 0; } if (dzsilos && !olddzsilos) timeout(dztimer, (caddr_t)0, dztimerintvl); timeout(dzscan, (caddr_t)0, LINEHZ); } dztimer() { register int dz; register int s; if (dzsilos == 0) return; s = spl5(); dzfasttimers++; /*DEBUG*/ for (dz = 0; dz < NDZ; dz++) if (dzsilos & (1 << dz)) dzrint(dz); splx(s); timeout(dztimer, (caddr_t) 0, dztimerintvl); } #endif YS) && (bp->b_flags & B_READ) && (tmaddr->tmer & (TMER_HARD | TMER_SOFT)) == TMER_RLE) goto ignoreerr; /* * If error is not hard, and this was an i/o operation * retry up to 8 times. */ if ((tmaddr->tmer & TMER_HARD) == 0 && state == SIO) { if (++tmtab.b_errcnt < 7) { sc->sc_blkno++; goto opcont; } } else /* * Hard or non-i/o errors on non-raw tape * cause it to close. */ if (sc->sc_openf > 0 && !(bp->b_flags & B_PHYS)) sc->sc_openf = -1; /* sys/pdpuba/dzreg.h 444 0 12 4674 4001577602 7417 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dzreg.h 7.1 (Berkeley) 6/5/86 */ /* * DZ-11/DZ-32 Registers and bits. */ struct dzdevice { short dzcsr; short dzrbuf; union { struct { char dztcr0; char dzdtr0; char dztbuf0; char dzbrk0; } dz11; struct { short dzlcs0; char dztbuf0; char dzlnen0; } dz32; } dzun; }; #define dzlpr dzrbuf #define dzmsr dzun.dz11.dzbrk0 #define dztcr dzun.dz11.dztcr0 #define dzdtr dzun.dz11.dzdtr0 #define dztbuf dzun.dz11.dztbuf0 #define dzlcs dzun.dz32.dzlcs0 #define dzbrk dzmsr #define dzlnen dzun.dz32.dzlnen0 #define dzmtsr dzun.dz32.dztbuf0 /* bits in dzlpr */ #define BITS7 0020 #define BITS8 0030 #define TWOSB 0040 #define PENABLE 0100 #define OPAR 0200 /* bits in dzrbuf */ #define DZ_PE 010000 #define DZ_FE 020000 #define DZ_DO 040000 /* bits in dzcsr */ #define DZ_32 000001 /* DZ32 mode */ #define DZ_MIE 000002 /* Modem Interrupt Enable */ #define DZ_CLR 000020 /* Reset dz */ #define DZ_MSE 000040 /* Master Scan Enable */ #define DZ_RIE 000100 /* Receiver Interrupt Enable */ #define DZ_MSC 004000 /* Modem Status Change */ #define DZ_SAE 010000 /* Silo Alarm Enable */ #define DZ_TIE 040000 /* Transmit Interrupt Enable */ #define DZ_IEN (DZ_32|DZ_MIE|DZ_MSE|DZ_RIE|DZ_TIE) /* flags for modem-control */ #define DZ_ON DZ_DTR #define DZ_OFF 0 /* bits in dzlcs */ #define DZ_ACK 0100000 /* ACK bit in dzlcs */ #define DZ_RTS 0010000 /* Request To Send */ #define DZ_ST 0004000 /* Secondary Transmit */ #define DZ_BRK 0002000 /* Break */ #define DZ_DTR 0001000 /* Data Terminal Ready */ #define DZ_LE 0000400 /* Line Enable */ #define DZ_DSR 0000200 /* Data Set Ready */ #define DZ_RI 0000100 /* Ring Indicate */ #define DZ_CD 0000040 /* Carrier Detect */ #define DZ_CTS 0000020 /* Clear To Send */ #define DZ_SR 0000010 /* Secondary Receive */ /* bits in dm lsr, copied from dmreg.h */ #define DML_DSR 0000400 /* data set ready, not a real DM bit */ #define DML_RNG 0000200 /* ring */ #define DML_CAR 0000100 /* carrier detect */ #define DML_CTS 0000040 /* clear to send */ #define DML_SR 0000020 /* secondary receive */ #define DML_ST 0000010 /* secondary transmit */ #define DML_RTS 0000004 /* request to send */ #define DML_DTR 0000002 /* data terminal ready */ #define DML_LE 0000001 /* line enable */ dzlcs0; char dztbuf0; char dzlnen0; } dz32; } dzun; }; #desys/pdpuba/rl.c 444 0 12 44135 6007572144 6734 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)rl.c 1.6 (2.11BSD GTE) 1995/08/01 */ /* * RL01/RL02 disk driver * Date: August 1, 1995 * Fix bug which prevented labeling disks with no label or a corrupted label. * Correct typographical error, the raclose() routine was being called by * mistake in the rlsize() routine. * * Date: June 15, 1995. * Modified to handle disklabels. This provides the ability to partition * a drive. An RL02 can hold a root and swap partition quite easily and is * useful for maintenance. */ #include "rl.h" #if NRL > 0 #if NRL > 4 error to have more than 4 drives - only 1 controller is supported. #endif #include "param.h" #include "buf.h" #include "user.h" #include "systm.h" #include "conf.h" #include "dk.h" #include "file.h" #include "ioctl.h" #include "stat.h" #include "map.h" #include "uba.h" #include "disklabel.h" #include "disk.h" #include "syslog.h" #include "rlreg.h" #define RL01_NBLKS 10240 /* Number of UNIX blocks for an RL01 drive */ #define RL02_NBLKS 20480 /* Number of UNIX blocks for an RL02 drive */ #define RL_CYLSZ 10240 /* bytes per cylinder */ #define RL_SECSZ 256 /* bytes per sector */ #define rlwait(r) while (((r)->rlcs & RL_CRDY) == 0) #define RLUNIT(x) ((minor(x) >> 3) & 7) struct rldevice *RLADDR; static int q22bae = 1; daddr_t rlsize(); int rlstrategy(); void rldfltlbl(); struct buf rlutab[NRL]; /* Seek structure for each device */ struct buf rltab; struct rl_softc { short cn[4]; /* location of heads for each drive */ short nblks[4]; /* number of blocks on drive */ short dn; /* drive number */ short com; /* read or write command word */ short chn; /* cylinder and head number */ u_short bleft; /* bytes left to be transferred */ u_short bpart; /* number of bytes transferred */ short sn; /* sector number */ union { short w[2]; long l; } rl_un; /* address of memory for transfer */ } rl = {-1,-1,-1,-1}; /* initialize cn[] */ struct dkdevice rl_dk[NRL]; #ifdef UCB_METER static int rl_dkn = -1; /* number for iostat */ #endif rlroot() { rlattach((struct rldevice *)0174400, 0); } rlattach(addr, unit) struct rldevice *addr; { #ifdef UCB_METER if (rl_dkn < 0) { dk_alloc(&rl_dkn, NRL+1, "rl", 20L * 10L * 512L); if (rl_dkn >= 0) dk_wps[rl_dkn+NRL] = 0L; } #endif if (unit != 0) return (0); if ((addr != (struct rldevice *)NULL) && (fioword(addr) != -1)) { RLADDR = addr; return (1); } RLADDR = (struct rldevice *)NULL; return (0); } rlopen(dev, flag, mode) dev_t dev; int flag; int mode; { int i, mask; int drive = RLUNIT(dev); register struct dkdevice *disk; if (drive >= NRL || !RLADDR) return (ENXIO); disk = &rl_dk[drive]; if ((disk->dk_flags & DKF_ALIVE) == 0) { if (rlgsts(drive) < 0) return(ENXIO); } /* * The drive has responded to a GETSTATUS (is alive). Now we read the * label. Allocate an external label structure if one has not already * been assigned to this drive. First wait for any pending opens/closes * to complete. */ while (disk->dk_flags & (DKF_OPENING | DKF_CLOSING)) sleep(disk, PRIBIO); /* * Next if an external label buffer has not already been allocated do so now. * This "can not fail" because if the initial pool of label buffers has * been exhausted the allocation takes place from main memory. The return * value is the 'click' address to be used when mapping in the label. */ if (disk->dk_label == 0) disk->dk_label = disklabelalloc(); /* * On first open get label and partition info. We may block reading the * label so be careful to stop any other opens. */ if (disk->dk_openmask == 0) { disk->dk_flags |= DKF_OPENING; rlgetinfo(disk, dev); disk->dk_flags &= ~DKF_OPENING; wakeup(disk); } /* * Need to make sure the partition is not out of bounds. This requires * mapping in the external label. This only happens when a partition * is opened (at mount time) and isn't an efficiency problem. */ mapseg5(disk->dk_label, LABELDESC); i = ((struct disklabel *)SEG5)->d_npartitions; normalseg5(); if (dkpart(dev) >= i) return(ENXIO); mask = 1 << dkpart(dev); dkoverlapchk(disk->dk_openmask, dev, disk->dk_label, "rl"); if (mode == S_IFCHR) disk->dk_copenmask |= mask; else if (mode == S_IFBLK) disk->dk_bopenmask |= mask; else return(EINVAL); disk->dk_openmask |= mask; return(0); } /* * Disk drivers now have to have close entry points in order to keep * track of what partitions are still active on a drive. */ rlclose(dev, flag, mode) register dev_t dev; int flag, mode; { int s, drive = RLUNIT(dev); register int mask; register struct dkdevice *disk; disk = &rl_dk[drive]; mask = 1 << dkpart(dev); if (mode == S_IFCHR) disk->dk_copenmask &= ~mask; else if (mode == S_IFBLK) disk->dk_bopenmask &= ~mask; else return(EINVAL); disk->dk_openmask = disk->dk_bopenmask | disk->dk_copenmask; if (disk->dk_openmask == 0) { disk->dk_flags |= DKF_CLOSING; s = splbio(); while (rlutab[drive].b_actf) { disk->dk_flags |= DKF_WANTED; sleep(&rlutab[drive], PRIBIO); } splx(s); disk->dk_flags &= ~(DKF_CLOSING | DKF_WANTED); wakeup(disk); } return(0); } /* * This code was moved from rlgetinfo() because it is fairly large and used * twice - once to initialize for reading the label and a second time if * there is no valid label present on the drive and the default one must be * used. */ void rldfltlbl(disk, lp, dev) struct dkdevice *disk; register struct disklabel *lp; dev_t dev; { register struct partition *pi = &lp->d_partitions[0]; bzero(lp, sizeof (*lp)); lp->d_type = DTYPE_DEC; lp->d_secsize = 512; /* XXX */ lp->d_nsectors = 20; lp->d_ntracks = 2; lp->d_secpercyl = 2 * 20; lp->d_npartitions = 1; /* 'a' */ pi->p_size = rl.nblks[dkunit(dev)]; /* entire volume */ pi->p_fstype = FS_V71K; pi->p_frag = 1; pi->p_fsize = 1024; /* * Put where rlstrategy() will look. */ bcopy(pi, disk->dk_parts, sizeof (lp->d_partitions)); } /* * Read disklabel. It is tempting to generalize this routine so that * all disk drivers could share it. However by the time all of the * necessary parameters are setup and passed the savings vanish. Also, * each driver has a different method of calculating the number of blocks * to use if one large partition must cover the disk. * * This routine used to always return success and callers carefully checked * the return status. Silly. This routine will fake a label (a single * partition spanning the drive) if necessary but will never return an error. * * It is the caller's responsibility to check the validity of partition * numbers, etc. */ void rlgetinfo(disk, dev) register struct dkdevice *disk; dev_t dev; { struct disklabel locallabel; char *msg; register struct disklabel *lp = &locallabel; /* * NOTE: partition 0 ('a') is used to read the label. Therefore 'a' must * start at the beginning of the disk! If there is no label or the label * is corrupted then 'a' will span the entire disk */ rldfltlbl(disk, lp, dev); msg = readdisklabel((dev & ~7) | 0, rlstrategy, lp); /* 'a' */ if (msg != 0) { log(LOG_NOTICE, "rl%da is entire disk: %s\n", dkunit(dev), msg); rldfltlbl(disk, lp, dev); } mapseg5(disk->dk_label, LABELDESC) bcopy(lp, (struct disklabel *)SEG5, sizeof (struct disklabel)); normalseg5(); bcopy(lp->d_partitions, disk->dk_parts, sizeof (lp->d_partitions)); return; } rlstrategy(bp) register struct buf *bp; { int drive, part; int s, ctr; daddr_t sz; register struct dkdevice *disk; register struct partition *pi; drive = RLUNIT(bp->b_dev); part = dkpart(bp->b_dev); disk = &rl_dk[drive]; if (drive >= NRL || !RLADDR || !(disk->dk_flags & DKF_ALIVE)) { bp->b_error = ENXIO; goto bad; } pi = &disk->dk_parts[part]; /* Valid block in device partition */ sz = (bp->b_bcount + 511) >> 9; if (bp->b_blkno < 0 || bp->b_blkno + sz > pi->p_size) { sz = pi->p_size - bp->b_blkno; /* if exactly at end of disk, return an EOF */ if (sz == 0) { bp->b_resid = bp->b_bcount; goto done; } /* or truncate if part of it fits */ if (sz < 0) { bp->b_error = EINVAL; goto bad; } bp->b_bcount = dbtob(sz); /* compute byte count */ } /* * Check for write to write-protected label area. This does not include * sector 0 which is the boot block. */ if (bp->b_blkno + pi->p_offset <= LABELSECTOR && bp->b_blkno + pi->p_offset + sz > LABELSECTOR && !(bp->b_flags & B_READ) && !(disk->dk_flags & DKF_WLABEL)) { bp->b_error = EROFS; goto bad; } mapalloc(bp); bp->av_forw = NULL; bp->b_cylin = (int)(bp->b_blkno/20L); s = splbio(); disksort(&rlutab[drive], bp); /* Put the request on drive Q */ if (rltab.b_active == 0) rlstart(); splx(s); return; bad: bp->b_flags |= B_ERROR; done: iodone(bp); return; } rlstart() { register struct rl_softc *rlp = &rl; register struct buf *bp, *dp; struct dkdevice *disk; int unit; if((bp = rltab.b_actf) == NULL) { for(unit = 0;unit < NRL;unit++) { /* Start seeks */ dp = &rlutab[unit]; if (dp->b_actf == NULL) { /* * No more requests in the drive queue. If a close is pending waiting * for activity to be done on the drive then issue a wakeup and clear the * flag. */ disk = &rl_dk[unit]; if (disk->dk_flags & DKF_WANTED) { disk->dk_flags &= ~DKF_WANTED; wakeup(dp); } continue; } rlseek((int)(dp->b_actf->b_blkno/20l),unit); } rlgss(); /* Put shortest seek on Q */ if((bp = rltab.b_actf) == NULL) /* No more work */ return; } rltab.b_active++; rlp->dn = RLUNIT(bp->b_dev); rlp->chn = bp->b_blkno / 20; rlp->sn = (bp->b_blkno % 20) << 1; rlp->bleft = bp->b_bcount; rlp->rl_un.w[0] = bp->b_xmem & 077; rlp->rl_un.w[1] = (int) bp->b_un.b_addr; rlp->com = (rlp->dn << 8) | RL_IE; if (bp->b_flags & B_READ) rlp->com |= RL_RCOM; else rlp->com |= RL_WCOM; rlio(); } rlintr() { register struct buf *bp; register struct rldevice *rladdr = RLADDR; register status; if (rltab.b_active == NULL) return; bp = rltab.b_actf; #ifdef UCB_METER if (rl_dkn >= 0) dk_busy &= ~((1 << (rl_dkn + rl.dn)) | (1 << (rl_dkn + NRL))); #endif if (rladdr->rlcs & RL_CERR) { if (rladdr->rlcs & RL_HARDERR && rltab.b_errcnt > 2) { harderr(bp, "rl"); printf("cs=%b da=%b\n", rladdr->rlcs, RL_BITS, rladdr->rlda, RLDA_BITS); } if (rladdr->rlcs & RL_DRE) { rladdr->rlda = RLDA_GS; rladdr->rlcs = (rl.dn << 8) | RL_GETSTATUS; rlwait(rladdr); status = rladdr->rlmp; if(rltab.b_errcnt > 2) { harderr(bp, "rl"); printf("mp=%b da=%b\n", status, RLMP_BITS, rladdr->rlda, RLDA_BITS); } rladdr->rlda = RLDA_RESET | RLDA_GS; rladdr->rlcs = (rl.dn << 8) | RL_GETSTATUS; rlwait(rladdr); if(status & RLMP_VCHK) { rlstart(); return; } } if (++rltab.b_errcnt <= 10) { rl.cn[rl.dn] = -1; rlstart(); return; } else { bp->b_flags |= B_ERROR; rl.bpart = rl.bleft; } } if ((rl.bleft -= rl.bpart) > 0) { rl.rl_un.l += rl.bpart; rl.sn=0; rl.chn++; rlseek(rl.chn,rl.dn); /* Seek to new position */ rlio(); return; } bp->b_resid = 0; rltab.b_active = NULL; rltab.b_errcnt = 0; rltab.b_actf = bp->av_forw; #ifdef notdef if((bp != NULL)&&(rlutab[rl.dn].b_actf != NULL)) rlseek((int)(rlutab[rl.dn].b_actf->b_blkno/20l),rl.dn); #endif iodone(bp); rlstart(); } rlio() { register struct rldevice *rladdr = RLADDR; if (rl.bleft < (rl.bpart = RL_CYLSZ - (rl.sn * RL_SECSZ))) rl.bpart = rl.bleft; rlwait(rladdr); rladdr->rlda = (rl.chn << 6) | rl.sn; rladdr->rlba = (caddr_t)rl.rl_un.w[1]; rladdr->rlmp = -(rl.bpart >> 1); if (q22bae == 1) q22bae = (fioword(&rladdr->rlbae) == -1 ? -1 : 0); if (q22bae == 0) rladdr->rlbae = rl.rl_un.w[0]; rladdr->rlcs = rl.com | (rl.rl_un.w[0] & 03) << 4; #ifdef UCB_METER if (rl_dkn >= 0) { int dkn = rl_dkn + NRL; dk_busy |= 1<>6; } #endif } /* * Start a seek on an rl drive * Greg Travis, April 1982 - Adapted to 2.8/2.9 BSD Oct 1982/May 1984 */ static rlseek(cyl, dev) register int cyl; register int dev; { struct rldevice *rp; register int dif; rp = RLADDR; if(rl.cn[dev] < 0) /* Find the frigging heads */ rlfh(dev); dif = (rl.cn[dev] >> 1) - (cyl >> 1); if(dif || ((rl.cn[dev] & 01) != (cyl & 01))) { if(dif < 0) rp->rlda = (-dif << 7) | RLDA_SEEKHI | ((cyl & 01) << 4); else rp->rlda = (dif << 7) | RLDA_SEEKLO | ((cyl & 01) << 4); rp->rlcs = (dev << 8) | RL_SEEK; rl.cn[dev] = cyl; #ifdef UCB_METER if (rl_dkn >= 0) { int dkn = rl_dkn + dev; dk_busy |= 1<rlcs = (dev << 8) | RL_RHDR; rlwait(rp); rl.cn[dev] = ((unsigned)rp->rlmp & 0177700) >> 6; } /* * Find the shortest seek for the current drive and put * it on the activity queue */ static rlgss() { register int unit, dcn; register struct buf *dp; rltab.b_actf = NULL; /* We fill this queue with up to 4 reqs */ for(unit = 0;unit < NRL;unit++) { dp = rlutab[unit].b_actf; if(dp == NULL) continue; rlutab[unit].b_actf = dp->av_forw; /* Out */ dp->av_forw = dp->av_back = NULL; dcn = (dp->b_blkno/20) >> 1; if(rl.cn[unit] < 0) rlfh(unit); if(dcn < rl.cn[unit]) dp->b_cylin = (rl.cn[unit] >> 1) - dcn; else dp->b_cylin = dcn - (rl.cn[unit] >> 1); disksort(&rltab, dp); /* Put the request on the current q */ } } rlioctl(dev, cmd, data, flag) dev_t dev; int cmd; caddr_t data; int flag; { register int error; struct dkdevice *disk = &rl_dk[RLUNIT(dev)]; error = ioctldisklabel(dev, cmd, data, flag, disk, rlstrategy); return(error); } #ifdef RL_DUMP /* * Dump routine for RL01/02 * This routine is stupid (because the rl is stupid) and assumes that * dumplo begins on a track boundary! */ #define DBSIZE 10 /* Half a track of sectors. Can't go higher * because only a single UMR is set for the transfer. */ rldump(dev) dev_t dev; { register struct rldevice *rladdr = RLADDR; struct dkdevice *disk; struct partition *pi; daddr_t bn, dumpsize; long paddr; int count, memblks; u_int com; int ccn, cn, tn, sn, unit, dif, partition; register struct ubmap *ubp; unit = RLUNIT(dev); if (unit >= NRL) return(EINVAL); partition = dkpart(dev); disk = &rl_dk[unit]; pi = &disk->dk_parts[partition]; if (!(disk->dk_flags & DKF_ALIVE)) return(ENXIO); if (pi->p_fstype != FS_SWAP) return(EFTYPE); dumpsize = rlsize(dev) - dumplo; memblks = ctod(physmem); if (dumplo < 0 || dumpsize <= 0) return(EINVAL); if (memblks > dumpsize) memblks = dumpsize; bn = dumplo + pi->p_offset; rladdr->rlcs = (dev << 8) | RL_RHDR; /* Find the heads */ rlwait(rladdr); ccn = ((unsigned)rladdr->rlmp&0177700) >> 6; ubp = &UBMAP[0]; for (paddr = 0L; memblks > 0; ) { count = MIN(memblks, DBSIZE); cn = bn / 20; sn = (unsigned)(bn % 20) << 1; dif = (ccn >> 1) - (cn >> 1); if(dif || ((ccn & 01) != (cn & 01))) { if(dif < 0) rladdr->rlda = (-dif << 7) | RLDA_SEEKHI | ((cn & 01) << 4); else rladdr->rlda = (dif << 7) | RLDA_SEEKLO | ((cn & 01) << 4); rladdr->rlcs = (dev << 8) | RL_SEEK; ccn = cn; rlwait(rladdr); } rladdr->rlda = (cn << 6) | sn; rladdr->rlmp = -(count << (PGSHIFT-1)); com = (dev << 8) | RL_WCOM; /* If there is a map - use it */ if(ubmap) { ubp->ub_lo = loint(paddr); ubp->ub_hi = hiint(paddr); rladdr->rlba = 0; } else { rladdr->rlba = loint(paddr); if (q22bae == 1) q22bae = (fioword(&rladdr->rlbae) == -1 ? -1:0); if (q22bae == 0) rladdr->rlbae = hiint(paddr); com |= (hiint(paddr) & 03) << 4; } rladdr->rlcs = com; rlwait(rladdr); if(rladdr->rlcs & RL_CERR) { if(rladdr->rlcs & RL_NXM) return(0); /* End of memory */ printf("rl%d: dmp err, cs=%b da=%b mp=%b\n", dev,rladdr->rlcs,RL_BITS,rladdr->rlda, RLDA_BITS, rladdr->rlmp, RLMP_BITS); return(EIO); } paddr += (count << PGSHIFT); bn += count; memblks -= count; } return(0); /* Filled the disk */ } #endif RL_DUMP /* * Return the number of blocks in a partition. Call rlopen() to online * the drive if necessary. If an open is necessary then a matching close * will be done. */ daddr_t rlsize(dev) register dev_t dev; { register struct dkdevice *disk; daddr_t psize; int didopen = 0; disk = &rl_dk[RLUNIT(dev)]; /* * This should never happen but if we get called early in the kernel's * life (before opening the swap or root devices) then we have to do * the open here. */ if (disk->dk_openmask == 0) { if (rlopen(dev, FREAD|FWRITE, S_IFBLK)) return(-1); didopen = 1; } psize = disk->dk_parts[dkpart(dev)].p_size; if (didopen) rlclose(dev, FREAD|FWRITE, S_IFBLK); return(psize); } /* * This routine is only called by rlopen() the first time a drive is * touched. Once the number of blocks has been determined the drive is * marked 'alive'. * * For some unknown reason the RL02 (seems to be * only drive 1) does not return a valid drive status * the first time that a GET STATUS request is issued * for the drive, in fact it can take up to three or more * GET STATUS requests to obtain the correct status. * In order to overcome this "HACK" the driver has been * modified to issue a GET STATUS request, validate the * drive status returned, and then use it to determine the * drive type. If a valid status is not returned after eight * attempts, then an error message is printed. */ rlgsts(drive) int drive; { register int ctr = 0; register struct rldevice *rp = RLADDR; do { /* get status and reset when first touching this drive */ rp->rlda = RLDA_RESET | RLDA_GS; rp->rlcs = (drive << 8) | RL_GETSTATUS; /* set up csr */ rlwait(rp); } while (((rp->rlmp & 0177477) != 035) && (++ctr < 16)); if (ctr >= 16) { printf("rl%d: !status cs=%b da=%b\n", drive, rp->rlcs, RL_BITS, rp->rlda, RLDA_BITS); rl_dk[drive].dk_flags &= ~DKF_ALIVE; return(-1); } if (rp->rlmp & RLMP_DTYP) rl.nblks[drive] = RL02_NBLKS; /* drive is RL02 */ else rl.nblks[drive] = RL01_NBLKS; /* drive RL01 */ rl_dk[drive].dk_flags |= DKF_ALIVE; return(0); } #endif /* NRL */ forward */ sc->sc_blkno = bn + (daddr_t) (tmaddr->tmbc); sc->sc_nxrec = sc->sc_blkno - (daddr_t) 1; } return; } /* eof on read */ sc->sc_nxrec = bn; } /*ARGSUSED*/ tmioctl(dev, cmd, data, flag) dev_t dev; u_int cmd; caddr_t data; { register struct buf *bp = &ctmbuf; register struct te_softc *sc = &te_softc[TEUNIT(dev)]; register callcount; u_short fcount; struct mtop *mtop; struct mtget *mtgetsys/pdpuba/hk.c 444 0 12 36576 5743404416 6735 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)hk.c 2.1 (2.11BSD GTE) 1995/04/13 */ /* * RK611/RK0[67] disk driver * * This driver mimics the 4.1bsd rk driver. * It does overlapped seeks, ECC, and bad block handling. * salkind@nyu * * dkunit() takes a 'dev_t' now instead of 'buf *'. 1995/04/13 - sms * * Modified to correctly handle 22 bit addressing available on DILOG * DQ615 controller. 05/31/90 -- tymann@oswego.edu * * Removed ifdefs on both Q22 and UNIBUS_MAP, substituting a runtime * test for presence of a Unibus Map. Reworked the partition logic, * the 'e' partiton no longer overlaps the 'a'+'b' partitions - a separate * 'b' partition is now present. Old root filesystems can still be used * because the size is the same, but user data will have to be saved and * then reloaded. 12/28/92 -- sms@wlv.iipo.gtegsc.com */ #include "hk.h" #if NHK > 0 #include "param.h" #include "systm.h" #include "buf.h" #include "conf.h" #include "user.h" #include "map.h" #include "uba.h" #include "hkreg.h" #include "dkbad.h" #include "dk.h" #include "disklabel.h" #include "disk.h" #include "syslog.h" #define NHK7CYL 815 #define NHK6CYL 411 #define HK_NSECT 22 #define HK_NTRAC 3 #define HK_NSPC (HK_NTRAC*HK_NSECT) struct hkdevice *HKADDR; struct size { daddr_t nblocks; int cyloff; } hk6_sizes[8] = { 8316, 0, /* a: cyl 0 - 125 */ 8316, 90, /* b: cyl 126 - 251 */ 27126, 0, /* c: cyl 0 - 410, whole RK06 */ 0, 0, /* d: Not Defined */ 0, 0, /* e: Not Defined */ 0, 0, /* f: Not Defined */ 10428, 252, /* g: cyl 252 - 409 */ 27126, 0, /* h: cyl 0 - 409, whole RK06 less 1 track */ }, hk7_sizes[8] = { 8316, 0, /* a: cyl 0 - 125 */ 8316, 126, /* b: cyl 126 - 251 */ 53790, 0, /* c: cyl 0 - 814, whole RK07 */ 0, 0, /* d: Not Defined */ 0, 0, /* e: Not Defined */ 0, 0, /* f: Not Defined */ 37092, 0, /* g: cyl 252 - 813 */ 53724, 0 /* h: cyl 0 - 813, whole RK07 less 1 track */ }; /* Can be u_char because all are less than 0377 */ u_char hk_offset[] = { HKAS_P400, HKAS_M400, HKAS_P400, HKAS_M400, HKAS_P800, HKAS_M800, HKAS_P800, HKAS_M800, HKAS_P1200, HKAS_M1200, HKAS_P1200, HKAS_M1200, 0, 0, 0, 0, }; int hk_type[NHK]; int hk_cyl[NHK]; struct size *hk_sizes[NHK]; char hk_pack[NHK]; struct hk_softc { int sc_softas; int sc_recal; } hk; struct buf hktab; struct buf hkutab[NHK]; #ifdef BADSECT struct dkbad hkbad[NHK]; struct buf bhkbuf[NHK]; #endif #ifdef UCB_METER static int hk_dkn = -1; /* number for iostat */ #endif #define hkwait(hkaddr) while ((hkaddr->hkcs1 & HK_CRDY) == 0) #define hkncyl(unit) (hk_type[unit] ? NHK7CYL : NHK6CYL) #define hkunit(dev) (((dev) >> 3) & 07) void hkroot() { hkattach((struct hkdevice *)0177440, 0); } hkattach(addr, unit) struct hkdevice *addr; { #ifdef UCB_METER if (hk_dkn < 0) { dk_alloc(&hk_dkn, NHK+1, "hk", 60L * (long)HK_NSECT * 256L); if (hk_dkn >= 0) dk_wps[hk_dkn+NHK] = 0L; } #endif if (unit != 0) return(0); HKADDR = addr; return(1); } hkopen(dev, flag) dev_t dev; int flag; { register int unit = hkunit(dev); register struct hkdevice *hkaddr = HKADDR; if (unit >= NHK || !HKADDR) return (ENXIO); hk_type[unit] = 0; hkaddr->hkcs1 = HK_CCLR; hkaddr->hkcs2 = unit; hkaddr->hkcs1 = HK_DCLR | HK_GO; hkwait(hkaddr); if((hkaddr->hkcs2&HKCS2_NED) || (hkaddr->hkds&HKDS_SVAL) == 0) { hkaddr->hkcs1 = HK_CCLR; hkwait(hkaddr); return(ENXIO); } if((hkaddr->hkcs1&HK_CERR) && (hkaddr->hker&HKER_DTYE)) { hk_type[unit] = HK_CDT; hkaddr->hkcs1 = HK_CCLR; hkwait(hkaddr); hk_sizes[unit] = hk7_sizes; } else hk_sizes[unit] = hk6_sizes; hk_cyl[unit] = -1; return(0); } hkstrategy(bp) register struct buf *bp; { register struct buf *dp; register unit; int s, part; long bn; long sz; struct size *szp; unit = dkunit(bp->b_dev); part = bp->b_dev & 7; if (unit >= NHK || !HKADDR || !(szp = hk_sizes[unit])) { bp->b_error = ENXIO; goto bad; } sz = (bp->b_bcount + (NBPG-1)) >> PGSHIFT; if (bp->b_blkno < 0 || (bn = bp->b_blkno)+sz > szp[part].nblocks) { bp->b_error = EINVAL; goto bad; } bp->b_cylin = bn / HK_NSPC + szp[part].cyloff; mapalloc(bp); dp = &hkutab[unit]; s = splbio(); disksort(dp, bp); if (dp->b_active == 0) { hkustart(unit); if (hktab.b_active == 0) hkstart(); } splx(s); return; bad: bp->b_flags |= B_ERROR; iodone(bp); } hkustart(unit) int unit; { register struct hkdevice *hkaddr = HKADDR; register struct buf *bp, *dp; int didie = 0; #ifdef UCB_METER if (hk_dkn >= 0) dk_busy &= ~(1 << (hk_dkn + unit)); #endif if (hktab.b_active) { hk.sc_softas |= (1 << unit); return(0); } hkaddr->hkcs1 = HK_CCLR; hkaddr->hkcs2 = unit; hkaddr->hkcs1 = hk_type[unit] | HK_DCLR | HK_GO; hkwait(hkaddr); dp = &hkutab[unit]; if ((bp = dp->b_actf) == NULL) return(0); if (dp->b_active) goto done; dp->b_active = 1; if ((hkaddr->hkds & HKDS_VV) == 0 || hk_pack[unit] == 0) { /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ #ifdef BADSECT struct buf *bbp = &bhkbuf[unit]; #endif hkaddr->hkcs1 = hk_type[unit]|HK_PACK|HK_GO; hk_pack[unit]++; #ifdef BADSECT bbp->b_flags = B_READ|B_BUSY|B_PHYS; bbp->b_dev = bp->b_dev; bbp->b_bcount = sizeof(struct dkbad); bbp->b_un.b_addr = (caddr_t)&hkbad[unit]; bbp->b_blkno = (long)hkncyl(unit)*HK_NSPC - HK_NSECT; bbp->b_cylin = hkncyl(unit) - 1; mapalloc(bbp); dp->b_actf = bbp; bbp->av_forw = bp; bp = bbp; #endif hkwait(hkaddr); } if ((hkaddr->hkds & HKDS_DREADY) != HKDS_DREADY) goto done; #ifdef NHK > 1 if (bp->b_cylin == hk_cyl[unit]) goto done; hkaddr->hkcyl = bp->b_cylin; hk_cyl[unit] = bp->b_cylin; hkaddr->hkcs1 = hk_type[unit] | HK_IE | HK_SEEK | HK_GO; didie = 1; #ifdef UCB_METER if (hk_dkn >= 0) { int dkn = hk_dkn + unit; dk_busy |= 1< 1 done: if (dp->b_active != 2) { dp->b_forw = NULL; if (hktab.b_actf == NULL) hktab.b_actf = dp; else hktab.b_actl->b_forw = dp; hktab.b_actl = dp; dp->b_active = 2; } return (didie); } hkstart() { register struct buf *bp, *dp; register struct hkdevice *hkaddr = HKADDR; daddr_t bn; int sn, tn, cmd, unit; loop: if ((dp = hktab.b_actf) == NULL) return(0); if ((bp = dp->b_actf) == NULL) { hktab.b_actf = dp->b_forw; goto loop; } hktab.b_active++; unit = dkunit(bp->b_dev); bn = bp->b_blkno; sn = bn % HK_NSPC; tn = sn / HK_NSECT; sn %= HK_NSECT; retry: hkaddr->hkcs1 = HK_CCLR; hkaddr->hkcs2 = unit; hkaddr->hkcs1 = hk_type[unit] | HK_DCLR | HK_GO; hkwait(hkaddr); if ((hkaddr->hkds & HKDS_SVAL) == 0) goto nosval; if (hkaddr->hkds & HKDS_PIP) goto retry; if ((hkaddr->hkds&HKDS_DREADY) != HKDS_DREADY) { log(LOG_WARNING, "hk%d: not ready\n", unit); if ((hkaddr->hkds&HKDS_DREADY) != HKDS_DREADY) { printf("\n"); hkaddr->hkcs1 = hk_type[unit] | HK_DCLR | HK_GO; hkwait(hkaddr); hkaddr->hkcs1 = HK_CCLR; hkwait(hkaddr); hktab.b_active = 0; hktab.b_errcnt = 0; dp->b_actf = bp->av_forw; dp->b_active = 0; bp->b_flags |= B_ERROR; iodone(bp); goto loop; } } nosval: hkaddr->hkcyl = bp->b_cylin; hk_cyl[unit] = bp->b_cylin; hkaddr->hkda = (tn << 8) + sn; hkaddr->hkwc = -(bp->b_bcount >> 1); hkaddr->hkba = bp->b_un.b_addr; if (!ubmap) hkaddr->hkxmem=bp->b_xmem; cmd = hk_type[unit] | ((bp->b_xmem & 3) << 8) | HK_IE | HK_GO; if (bp->b_flags & B_READ) cmd |= HK_READ; else cmd |= HK_WRITE; hkaddr->hkcs1 = cmd; #ifdef UCB_METER if (hk_dkn >= 0) { int dkn = hk_dkn + NHK; dk_busy |= 1<b_bcount>>6; } #endif return(1); } hkintr() { register struct hkdevice *hkaddr = HKADDR; register struct buf *bp, *dp; int unit; int as = (hkaddr->hkatt >> 8) | hk.sc_softas; int needie = 1; hk.sc_softas = 0; if (hktab.b_active) { dp = hktab.b_actf; bp = dp->b_actf; unit = dkunit(bp->b_dev); #ifdef UCB_METER if (hk_dkn >= 0) dk_busy &= ~(1 << (hk_dkn + NHK)); #endif #ifdef BADSECT if (bp->b_flags&B_BAD) if (hkecc(bp, CONT)) return; #endif if (hkaddr->hkcs1 & HK_CERR) { int recal; u_short ds = hkaddr->hkds; u_short cs2 = hkaddr->hkcs2; u_short er = hkaddr->hker; if (er & HKER_WLE) { log(LOG_WARNING, "hk%d: write locked\n", unit); bp->b_flags |= B_ERROR; } else if (++hktab.b_errcnt > 28 || ds&HKDS_HARD || er&HKER_HARD || cs2&HKCS2_HARD) { hard: harderr(bp, "hk"); log(LOG_WARNING, "cs2=%b ds=%b er=%b\n", cs2, HKCS2_BITS, ds, HKDS_BITS, er, HKER_BITS); bp->b_flags |= B_ERROR; hk.sc_recal = 0; } else if (er & HKER_BSE) { #ifdef BADSECT if (hkecc(bp, BSE)) return; else #endif goto hard; } else hktab.b_active = 0; if (cs2&HKCS2_MDS) { hkaddr->hkcs2 = HKCS2_SCLR; goto retry; } recal = 0; if (ds&HKDS_DROT || er&(HKER_OPI|HKER_SKI|HKER_UNS) || (hktab.b_errcnt&07) == 4) recal = 1; if ((er & (HKER_DCK|HKER_ECH)) == HKER_DCK) if (hkecc(bp, ECC)) return; hkaddr->hkcs1 = HK_CCLR; hkaddr->hkcs2 = unit; hkaddr->hkcs1 = hk_type[unit]|HK_DCLR|HK_GO; hkwait(hkaddr); if (recal && hktab.b_active == 0) { hkaddr->hkcs1 = hk_type[unit]|HK_IE|HK_RECAL|HK_GO; hk_cyl[unit] = -1; hk.sc_recal = 0; goto nextrecal; } } retry: switch (hk.sc_recal) { case 1: hkaddr->hkcyl = bp->b_cylin; hk_cyl[unit] = bp->b_cylin; hkaddr->hkcs1 = hk_type[unit]|HK_IE|HK_SEEK|HK_GO; goto nextrecal; case 2: if (hktab.b_errcnt < 16 || (bp->b_flags&B_READ) == 0) goto donerecal; hkaddr->hkatt = hk_offset[hktab.b_errcnt & 017]; hkaddr->hkcs1 = hk_type[unit]|HK_IE|HK_OFFSET|HK_GO; /* fall into ... */ nextrecal: hk.sc_recal++; hkwait(hkaddr); hktab.b_active = 1; return; donerecal: case 3: hk.sc_recal = 0; hktab.b_active = 0; break; } if (hktab.b_active) { hktab.b_active = 0; hktab.b_errcnt = 0; hktab.b_actf = dp->b_forw; dp->b_active = 0; dp->b_errcnt = 0; dp->b_actf = bp->av_forw; bp->b_resid = -(hkaddr->hkwc << 1); iodone(bp); if (dp->b_actf) if (hkustart(unit)) needie = 0; } as &= ~(1<>= 1, unit++) if (as & 1) { if (unit < NHK && hk_sizes[unit]) { if (hkustart(unit)) needie = 0; } else { hkaddr->hkcs1 = HK_CCLR; hkaddr->hkcs2 = unit; hkaddr->hkcs1 = HK_DCLR | HK_GO; hkwait(hkaddr); hkaddr->hkcs1 = HK_CCLR; } } if (hktab.b_actf && hktab.b_active == 0) if (hkstart()) needie = 0; if (needie) hkaddr->hkcs1 = HK_IE; } #ifdef HK_DUMP /* * Dump routine for RK06/07 * Dumps from dumplo to end of memory/end of disk section for minor(dev). * It uses the UNIBUS map to dump all of memory if there is a UNIBUS map. */ #define DBSIZE (UBPAGE/NBPG) /* unit of transfer, one UBPAGE */ hkdump(dev) dev_t dev; { register struct hkdevice *hkaddr = HKADDR; daddr_t bn, dumpsize; long paddr; register count; register struct ubmap *ubp; int com, cn, tn, sn, unit; struct size *szp; unit = hkunit(dev); szp = hk_sizes[unit]; if (unit >= NHK || !szp) return(EINVAL); dumpsize = szp[dev & 7]->nblocks; if ((dumplo < 0) || (dumplo >= dumpsize)) return(EINVAL); dumpsize -= dumplo; hkaddr->hkcs1 = HK_CCLR; hkwait(hkaddr); hkaddr->hkcs2 = unit; hkaddr->hkcs1 = hk_type[unit] | HK_DCLR | HK_GO; hkwait(hkaddr); if ((hkaddr->hkds & HKDS_VV) == 0) { hkaddr->hkcs1 = hk_type[unit]|HK_IE|HK_PACK|HK_GO; hkwait(hkaddr); } ubp = &UBMAP[0]; for (paddr = 0L; dumpsize > 0; dumpsize -= count) { count = dumpsize>DBSIZE? DBSIZE: dumpsize; bn = dumplo + (paddr >> PGSHIFT); cn = (bn/HK_NSPC) + szp[dev & 7]->cyloff; sn = bn%HK_NSPC; tn = sn/HK_NSECT; sn = sn%HK_NSECT; hkaddr->hkcyl = cn; hkaddr->hkda = (tn << 8) | sn; hkaddr->hkwc = -(count << (PGSHIFT-1)); com = hk_type[unit]|HK_GO|HK_WRITE; if (ubmap) { ubp->ub_lo = loint(paddr); ubp->ub_hi = hiint(paddr); hkaddr->hkba = 0; } else { /* non UNIBUS map */ hkaddr->hkba = loint(paddr); hkaddr->hkxmem = hiint(paddr); com |= ((paddr >> 8) & (03 << 8)); } hkaddr->hkcs2 = unit; hkaddr->hkcs1 = com; hkwait(hkaddr); if (hkaddr->hkcs1 & HK_CERR) { if (hkaddr->hkcs2 & HKCS2_NEM) return(0); /* made it to end of memory */ return(EIO); } paddr += (DBSIZE << PGSHIFT); } return(0); /* filled disk minor dev */ } #endif HK_DUMP #define exadr(x,y) (((long)(x) << 16) | (unsigned)(y)) /* * Correct an ECC error and restart the i/o to complete * the transfer if necessary. This is quite complicated because * the transfer may be going to an odd memory address base * and/or across a page boundary. */ hkecc(bp, flag) register struct buf *bp; { register struct hkdevice *hkaddr = HKADDR; ubadr_t addr; int npx, wc; int cn, tn, sn; daddr_t bn; unsigned ndone; int cmd; int unit; #ifdef BADSECT if (flag == CONT) { npx = bp->b_error; ndone = npx * NBPG; wc = ((int)(ndone - bp->b_bcount)) / NBPW; } else #endif { wc = hkaddr->hkwc; ndone = (wc * NBPW) + bp->b_bcount; npx = ndone / NBPG; } unit = dkunit(bp->b_dev); bn = bp->b_blkno; cn = bp->b_cylin - bn / HK_NSPC; bn += npx; cn += bn / HK_NSPC; sn = bn % HK_NSPC; tn = sn / HK_NSECT; sn %= HK_NSECT; hktab.b_active++; switch (flag) { case ECC: { register byte; int bit; long mask; ubadr_t bb; unsigned o; struct ubmap *ubp; log(LOG_WARNING, "hk%d%c: soft ecc sn %D\n", unit, 'a' + (bp->b_dev & 07), bp->b_blkno + npx - 1); mask = hkaddr->hkecpt; byte = hkaddr->hkecps - 1; bit = byte & 07; byte >>= 3; mask <<= bit; o = (ndone - NBPG) + byte; bb = exadr(bp->b_xmem, bp->b_un.b_addr); bb += o; if (ubmap && (bp->b_flags & (B_MAP|B_UBAREMAP))) { ubp = UBMAP + ((bb >> 13) & 037); bb = exadr(ubp->ub_hi, ubp->ub_lo) + (bb & 017777); } /* * Correct until mask is zero or until end of * sector or transfer, whichever comes first. */ while (byte < NBPG && o < bp->b_bcount && mask != 0) { putmemc(bb, getmemc(bb) ^ (int)mask); byte++; o++; bb++; mask >>= 8; } if (wc == 0) return(0); break; } #ifdef BADSECT case BSE: if ((bn = isbad(&hkbad[unit], cn, tn, sn)) < 0) return(0); bp->b_flags |= B_BAD; bp->b_error = npx + 1; bn = (long)hkncyl(unit)*HK_NSPC - HK_NSECT - 1 - bn; cn = bn/HK_NSPC; sn = bn%HK_NSPC; tn = sn/HK_NSECT; sn %= HK_NSECT; wc = -(NBPG / NBPW); break; case CONT: bp->b_flags &= ~B_BAD; if (wc == 0) return(0); break; #endif BADSECT } /* * Have to continue the transfer. Clear the drive * and compute the position where the transfer is to continue. * We have completed npx sectors of the transfer already. */ hkaddr->hkcs1 = HK_CCLR; hkwait(hkaddr); hkaddr->hkcs2 = unit; hkaddr->hkcs1 = hk_type[unit] | HK_DCLR | HK_GO; hkwait(hkaddr); addr = exadr(bp->b_xmem, bp->b_un.b_addr); addr += ndone; hkaddr->hkcyl = cn; hkaddr->hkda = (tn << 8) + sn; hkaddr->hkwc = wc; hkaddr->hkba = (caddr_t)addr; if (!ubmap) hkaddr->hkxmem=hiint(addr); cmd = hk_type[unit] | ((hiint(addr) & 3) << 8) | HK_IE | HK_GO; if (bp->b_flags & B_READ) cmd |= HK_READ; else cmd |= HK_WRITE; hkaddr->hkcs1 = cmd; hktab.b_errcnt = 0; /* error has been corrected */ return (1); } /* * Assumes the 'open' entry point has already been called to validate * the unit number. */ daddr_t hksize(dev) register dev_t dev; { register struct size *szp = hk_sizes[hkunit(dev)]; if (!szp) return(-1); return(szp[dev & 7].nblocks); } #endif NHK > 0 mapalloc(bbp); dp->b_actf = bbp; bbp->av_forw = bp; bp = bbp; #endif hkwait(hkaddr); } if ((hkaddr->hkds & HKDS_DREADY) sys/pdpuba/hkreg.h 444 0 12 12013 4711163640 7407 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)hkreg.h 1.1 (2.10BSD Berkeley) 12/1/86 */ struct hkdevice { short hkcs1; /* control status reg 1 */ short hkwc; /* word count */ caddr_t hkba; /* bus address */ short hkda; /* disk address */ short hkcs2; /* control status reg 2 */ short hkds; /* drive status */ short hker; /* driver error register */ short hkatt; /* attention status/offset register */ short hkcyl; /* current cylinder register */ short hkxmem; /* extended memory address register */ short hkdb; /* data buffer register */ short hkmr1; /* maint reg 1 */ short hkecps; /* burst error bit position */ short hkecpt; /* burst error bit pattern */ short hkmr2; /* maint reg 2 */ short hkmr3; /* maint reg 3 */ }; /* hkcs1 */ #define HK_CCLR 0100000 /* controller clear (also error) */ #define HK_CERR HK_CCLR #define HK_DI 0040000 /* drive interrupt */ #define HK_DTCPAR 0020000 /* drive to controller parity */ #define HK_CFMT 0010000 /* 18 bit word format */ #define HK_CTO 0004000 /* controller timeout */ #define HK_CDT 0002000 /* drive type (rk07/rk06) */ /* bits 9 and 8 are the extended bus address */ #define HK_CRDY 0000200 /* controller ready */ #define HK_IE 0000100 /* interrupt enable */ /* bit 5 is unused */ /* bits 4-1 are the function code */ #define HK_GO 0000001 #define HK_BITS \ "\10\20CCLR\17DI\16DTCPAR\15CFMT\14CTO\13CDT\10CRDY\7IE\1GO" /* commands */ #define HK_SELECT 000 /* select drive */ #define HK_PACK 002 /* pack acknowledge */ #define HK_DCLR 004 /* drive clear */ #define HK_UNLOAD 006 /* unload */ #define HK_START 010 /* start spindle */ #define HK_RECAL 012 /* recalibrate */ #define HK_OFFSET 014 /* offset */ #define HK_SEEK 016 /* seek */ #define HK_READ 020 /* read data */ #define HK_WRITE 022 /* write data */ #define HK_RHDR 026 /* read header */ #define HK_WHDR 030 /* write header */ /* hkcs2 */ #define HKCS2_DLT 0100000 /* data late */ #define HKCS2_WCE 0040000 /* write check */ #define HKCS2_UPE 0020000 /* UNIBUS parity */ #define HKCS2_NED 0010000 /* non-existent drive */ #define HKCS2_NEM 0004000 /* non-existent memory */ #define HKCS2_PGE 0002000 /* programming error */ #define HKCS2_MDS 0001000 /* multiple drive select */ #define HKCS2_UFE 0000400 /* unit field error */ #define HKCS2_OR 0000200 /* output ready */ #define HKCS2_IR 0000100 /* input ready */ #define HKCS2_SCLR 0000040 /* subsystem clear */ #define HKCS2_BAI 0000020 /* bus address increment inhibit */ #define HKCS2_RLS 0000010 /* release */ /* bits 2-0 are drive select */ #define HKCS2_BITS \ "\10\20DLT\17WCE\16UPE\15NED\14NEM\13PGE\12MDS\11UFE\ \10OR\7IR\6SCLR\5BAI\4RLS" #define HKCS2_HARD (HKCS2_NED|HKCS2_PGE) /* hkds */ #define HKDS_SVAL 0100000 /* status valid */ #define HKDS_CDA 0040000 /* current drive attention */ #define HKDS_PIP 0020000 /* positioning in progress */ /* bit 12 is unused */ #define HKDS_WRL 0004000 /* write lock */ /* bits 10-9 are unused */ #define HKDS_DDT 0000400 /* disk drive type */ #define HKDS_DRDY 0000200 /* drive ready */ #define HKDS_VV 0000100 /* volume valid */ #define HKDS_DROT 0000040 /* drive off track */ #define HKDS_SPLS 0000020 /* speed loss */ #define HKDS_ACLO 0000010 /* ac low */ #define HKDS_OFF 0000004 /* offset mode */ /* bit 1 is unused */ #define HKDS_DRA 0000001 /* drive available */ #define HKDS_DREADY (HKDS_DRA|HKDS_VV|HKDS_DRDY) #define HKDS_BITS \ "\10\20SVAL\17CDA\16PIP\14WRL\11DDT\10DRDY\7VV\6DROT\5SPLS\4ACLO\3OFF\1DRA" #define HKDS_HARD (HKDS_ACLO|HKDS_SPLS) /* hker */ #define HKER_DCK 0100000 /* data check */ #define HKER_UNS 0040000 /* drive unsafe */ #define HKER_OPI 0020000 /* operation incomplete */ #define HKER_DTE 0010000 /* drive timing error */ #define HKER_WLE 0004000 /* write lock error */ #define HKER_IDAE 0002000 /* invalid disk address error */ #define HKER_COE 0001000 /* cylinder overflow error */ #define HKER_HRVC 0000400 /* header vertical redundancy check */ #define HKER_BSE 0000200 /* bad sector error */ #define HKER_ECH 0000100 /* hard ecc error */ #define HKER_DTYE 0000040 /* drive type error */ #define HKER_FMTE 0000020 /* format error */ #define HKER_DRPAR 0000010 /* control-to-drive parity error */ #define HKER_NXF 0000004 /* non-executable function */ #define HKER_SKI 0000002 /* seek incomplete */ #define HKER_ILF 0000001 /* illegal function */ #define HKER_BITS \ "\10\20DCK\17UNS\16OPI\15DTE\14WLE\13IDAE\12COE\11HRVC\ \10BSE\7ECH\6DTYE\5FMTE\4DRPAR\3NXF\2SKI\1ILF" #define HKER_HARD \ (HKER_WLE|HKER_IDAE|HKER_COE|HKER_DTYE|HKER_FMTE|HKER_ILF) /* offset bits in hkas */ #define HKAS_P400 0020 /* +400 RK06, +200 RK07 */ #define HKAS_M400 0220 /* -400 RK06, -200 RK07 */ #define HKAS_P800 0040 /* +800 RK06, +400 RK07 */ #define HKAS_M800 0240 /* -800 RK06, -400 RK07 */ #define HKAS_P1200 0060 /* +800 RK06, +400 RK07 */ #define HKAS_M1200 0260 /* -1200 RK06, -1200 RK07 */ 0000 /* drive interrupt */ #define HK_DTCPAR 0020000 /* drive to controller parity */ #define HK_CFMT 0010000 /* 18 bit word format */ #define HK_CTO 0004000 /* controller timeout */ #define HK_CDT 0002000 /* drive type (rk07/rk06) */ /* bits 9 and 8 are the extended bus address */ #define HK_CRDY 0000200 /* controller ready */ #define HK_IE 0000100 /* interrupt enable */ /* bit 5 is unused */ /* bits 4-1 are the function code */ #define HK_GO 0000001 #define HK_BITS \ "\10\20CCLR\1sys/pdpuba/htreg.h 444 0 12 16251 4001144575 7426 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)htreg.h 1.1 (2.10BSD Berkeley) 12/1/86 */ struct htdevice { short htcs1; /* control and status 1 register */ short htwc; /* word count register */ caddr_t htba; /* bus address register */ short htfc; /* frame counter */ short htcs2; /* control and status 2 register */ short htfs; /* formatter status register */ short hter; /* error register */ short htas; /* attention summary register */ short htcc; /* check character register */ short htdb; /* data buffer register */ short htmr; /* maintenance register */ short htdt; /* drive type register */ short htsn; /* serial number register */ short httc; /* tape control register */ short htbae; /* bus address extension register (RH70 only) */ short htcs3; /* control and status 3 register (RH70 only) */ }; /* htcs1 */ #define HT_SC 0100000 /* special condition */ #define HT_TRE 0040000 /* transfer error */ #define HT_MCPE 0020000 /* MASSBUS control bus read parity error */ /* bit 12 is unused */ #define HT_DVA 0004000 /* drive available */ /* bit 10 is unused */ /* bits 9-8 are UNIBUS extension bits */ #define HT_RDY 0000200 /* ready */ #define HT_IE 0000100 /* interrupt enable */ #define HT_GO 0000001 /* go bit */ /* bits 5-1 are the command */ #define HTCS1_BITS \ "\10\20SC\17TRE\16MCPE\14DVA\12A17\11A16\10RDY\7IE\1GO" /* commands */ #define HT_SENSE 0000000 /* no operations (sense) */ #define HT_REWOFFL 0000002 /* rewind offline */ #define HT_REW 0000006 /* rewind */ #define HT_DCLR 0000010 /* drive clear */ #define HT_RIP 0000020 /* read in preset */ #define HT_ERASE 0000024 /* erase */ #define HT_WEOF 0000026 /* write tape mark */ #define HT_SFORW 0000030 /* space forward */ #define HT_SREV 0000032 /* space reverse */ #define HT_WCHFWD 0000050 /* write check forward */ #define HT_WCHREV 0000056 /* write check reverse */ #define HT_WCOM 0000060 /* write forward */ #define HT_RCOM 0000070 /* read forward */ #define HT_RREV 0000076 /* read reverse */ /* htcs2 */ #define HTCS2_DLT 0100000 /* data late */ /* * The 1981-1982 DEC peripherals handbook says bit 14 is unused. * The 1980 one says it's WCE. Take your choice. */ #define HTCS2_WCE 0040000 /* write check error */ #define HTCS2_UPE 0020000 /* UNIBUS parity error */ #define HTCS2_NEF 0010000 /* nonexistent formatter */ #define HTCS2_NEM 0004000 /* nonexistent memory */ #define HTCS2_PRE 0002000 /* program error */ #define HTCS2_MXF 0001000 /* missed transfer */ #define HTCS2_MDPE 0000400 /* MASSBUS data read parity error */ #define HTCS2_OR 0000200 /* output ready */ #define HTCS2_IR 0000100 /* input ready */ #define HTCS2_CLR 0000040 /* controller clear */ #define HTCS2_PAT 0000020 /* parity test */ #define HTCS2_MAII 0000010 /* memory address increment inhibit */ /* bits 2-0 select the formatter */ #define HTCS2_BITS \ "\10\20DLT\16UPE\16NEF\14NEM\13PRE\12MXF\11MDPE\10OR\7IR\6CLR\5PAT\4MAII" #define HTCS2_ERR \ (HTCS2_MDPE|HTCS2_MXF|HTCS2_PRE|HTCS2_NEM|HTCS2_NEF|HTCS2_UPE|HTCS2_WCE) /* htfs */ #define HTFS_ATA 0100000 /* attention active */ #define HTFS_ERR 0040000 /* composite error */ #define HTFS_PIP 0020000 /* positioning in progress */ #define HTFS_MOL 0010000 /* medium on line */ #define HTFS_WRL 0004000 /* write lock */ #define HTFS_EOT 0002000 /* end of tape */ /* bit 9 is unused */ #define HTFS_DPR 0000400 /* drive present (always 1) */ #define HTFS_DRY 0000200 /* drive ready */ #define HTFS_SSC 0000100 /* slave status change */ #define HTFS_PES 0000040 /* phase-encoded status */ #define HTFS_SDWN 0000020 /* slowing down */ #define HTFS_IDB 0000010 /* identification burst */ #define HTFS_TM 0000004 /* tape mark */ #define HTFS_BOT 0000002 /* beginning of tape */ #define HTFS_SLA 0000001 /* slave attention */ #define HTFS_BITS \ "\10\20ATA\17ERR\16PIP\15MOL\14WRL\13EOT\11DPR\10DRY\ \7SSC\6PES\5SDWN\4IDB\3TM\2BOT\1SLA" /* hter */ #define HTER_CORCRC 0100000 /* correctible data/crc error */ #define HTER_UNS 0040000 /* unsafe */ #define HTER_OPI 0020000 /* operation incomplete */ #define HTER_CTE 0010000 /* controller timing error */ #define HTER_NEF 0004000 /* non-executable function */ #define HTER_CSITM 0002000 /* correctable skew/illegal tape mark */ #define HTER_FCE 0001000 /* frame count error */ #define HTER_NSG 0000400 /* non-standard gap */ #define HTER_PEFLRC 0000200 /* pe format error/lrc error */ #define HTER_INCVPE 0000100 /* incorrectable data/vertical parity error */ #define HTER_DPAR 0000040 /* MASSBUS data write parity error */ #define HTER_FMT 0000020 /* format select error */ #define HTER_CPAR 0000010 /* MASSBUS control bus write parity error */ #define HTER_RMR 0000004 /* register modification refused */ #define HTER_ILR 0000002 /* illegal register */ #define HTER_ILF 0000001 /* illegal function */ #define HTER_BITS \ "\10\20CORCRC\17UNS\16OPI\15CTE\14NEF\13CSITM\12FCE\11NSG\10PEFLRC\ \7INCVPE\6DPAR\5FMT\4CPAR\3RMR\2ILR\1ILF" #define HTER_HARD \ (HTER_UNS|HTER_OPI|HTER_NEF|HTER_DPAR|HTER_FMT|HTER_CPAR| \ HTER_RMR|HTER_ILR|HTER_ILF) /* htcc */ /* bits 15-9 are unused */ #define HTCC_DTPAR 0000400 /* dead track parity/crc parity */ /* bits 7-0 contain dead track/crc information */ #define HTCC_BITS \ "\10\11DTPAR" /* htmr */ /* bits 15-8 contain lrc/maintenance data */ #define HTMR_MDPB 0000400 /* maintenance data parity bit */ #define HTMR_TSC 0000200 /* tape speed clock */ #define HTMR_MC 0000100 /* maintenance clock */ /* bits 4-1 contain the maintenance operation code */ #define HTMR_MM 0000001 /* maintenance mode */ #define HTMR_BITS \ "\10\10MDPB\7TSC\6MC\1MM" /* htdt */ #define HTDT_NSA 0100000 /* not sector addressed; always 1 */ #define HTDT_TAP 0040000 /* tape; always 1 */ #define HTDT_MOH 0020000 /* moving head; always 0 */ #define HTDT_7CH 0010000 /* 7 channel; always 0 */ #define HTDT_DRQ 0004000 /* drive request required; always 0 */ #define HTDT_SPR 0002000 /* slave present */ /* bit 9 is unused */ /* bits 8-0 are formatter/transport type */ #define HTDT_BITS \ "\10\20NSA\17TAP\16MOH\15SCH\14DRQ\13SPR" /* httc */ #define HTTC_ACCL 0100000 /* transport is not up to speed */ #define HTTC_FCS 0040000 /* frame count status */ #define HTTC_SAC 0020000 /* slave address change */ #define HTTC_EAODTE 0010000 /* enable abort on data xfer errors */ /* bit 11 is unused */ /* bits 10-8 are density select */ #define HTTC_800BPI 0001400 /* in bits 10-8, dens=800 */ #define HTTC_1600BPI 0002000 /* in bits 10-8, dens=1600 */ /* bits 7-4 are format select */ #define HTTC_PDP11 0000300 /* in bits 7-4, pdp11 normal format */ #define HTTC_EVEN 0000010 /* select even parity */ /* bits 2-0 are slave select */ #define HTTC_BITS \ "\10\20ACCL\17FCS\16SAC\15EAODTE\4EVEN" /* htcs3 */ #define HTCS3_APE 0100000 /* address parity error */ /* bits 14-11 are unused */ #define HTCS3_DW 0002000 /* double word */ /* bits 9-7 are unused */ #define HTCS3_IE 0000100 /* interrupt enable */ /* bits 5-4 are unused */ /* bits 3-0 are inverted parity check */ #define HTCS3_BITS \ "\10\20APE\13DW\7IE" #define b_repcnt b_bcount #define b_command b_resid 8) + sn; hkaddr->hkwc = -(bp->b_bcount >> 1); hkaddr->hkba = bp->b_un.b_addr; if (!ubmap) hkaddr->hkxmem=bp->b_xmem; cmd = hk_type[unit] | ((bp->b_xmem & 3) << 8) | HK_IE | HK_GO; if (bp->b_flags & B_READ) cmd |= HK_READ; else cmd |= HK_WRITE; hkaddr->hkcs1 = cmd; #ifdef UCB_METER if (hk_dkn >= 0) { int dkn = hk_dkn + NHK; sys/pdpuba/rxreg.h 444 0 12 10270 4112113673 7435 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)rxreg.h 1.1 (2.10BSD Berkeley) 12/1/86 */ struct rxdevice { short rxcs; /* command and status register */ short rxdb; /* multipurpose register: */ #define rxba rxdb /* bus address register */ #define rxta rxdb /* track address register */ #define rxsa rxdb /* sector address register */ #define rxwc rxdb /* word count register */ #define rxes rxdb /* error and status register */ }; /* bits in rxcs */ #define RX_ERR 0100000 /* error */ #define RX_INIT 0040000 /* initialize */ /* bits 13-12 are the extension bits */ #define RX_RX02 0004000 /* rx02 (read only) */ /* bit 10 is unused (bit 9 is also unused in the standard rx11) */ #define RX_HD 0001000 /* DSD 480 head select */ #define RX_DD 0000400 /* double density */ #define RX_XREQ 0000200 /* transfer request */ #define RX_IE 0000100 /* interrupt enable */ #define RX_DONE 0000040 /* done */ #define RX_UNIT 0000020 /* unit select */ /* bits 3-1 are the function code */ #define RX_GO 0000001 /* go */ /* function codes */ #define RX_FILL 0000000 /* fill buffer */ #define RX_EMPTY 0000002 /* empty */ #define RX_WSECT 0000004 /* write sector */ #define RX_RSECT 0000006 /* read sector */ #define RX_SMD 0000010 /* set media density */ #define RX_RDSTAT 0000012 /* read status */ #define RX_WDDSECT 0000014 /* write deleted data sector */ #define RX_RDEC 0000016 /* read error code */ /* ioctls */ #define RXIOC_FORMAT _IO(r, 1) /* format media */ #define RX_BITS \ "\10\20ERR\17INIT\14RX02\12HD\11DD\10XREQ\7IE\6DONE\5UNIT1\1GO" /* bits in rxes */ /* bits 15-12 are unused in the standard rx11 */ #define RXES_IBMDD 0010000 /* DSD 480 IBM double density select */ #define RXES_NXM 0004000 /* nonexistent memory */ #define RXES_WCOVFL 0002000 /* word count overflow */ /* bit 9 is unused in the standard rx11 */ #define RXES_HD 0001000 /* DSD 480 head select */ #define RXES_UNIT 0000400 /* unit select */ #define RXES_RDY 0000200 /* ready */ #define RXES_DDATA 0000100 /* deleted data */ #define RXES_DD 0000040 /* double density */ #define RXES_DENSERR 0000020 /* density error */ #define RXES_ACLO 0000010 /* ac low */ #define RXES_INITDONE 0000004 /* initialization done */ /* bit 1 is unused in the standard rx11 */ #define RXES_S1RDY 0000002 /* DSD 480 side 1 ready */ #define RXES_CRC 0000001 /* crc error */ #define RXES_BITS \ "\10\15IBMDD\14NXM\13WCOVFL\12HD\11UNIT1\10RDY\7DDATA\ \6DDENS\5DENSERR\4ACLO\3INIT\2S1RDY\1CRC" /* bits in rxes1 */ /* bits 15-8 contain the word count */ /* bits 7-0 contain the error code */ #define RXES1_D0NOHOME 0000010 /* drive 0 failed to see home on init */ #define RXES1_D1NOHOME 0000020 /* drive 1 failed to see home on init */ #define RXES1_XTRK 0000040 /* track number > 076 */ #define RXES1_WRAP 0000050 /* found home before desired track */ #define RXES1_HNF 0000070 /* header not found after 2 revs */ #define RXES1_NSEP 0000110 /* up controller found not SEP clock */ #define RXES1_NOPREAMB 0000120 /* preamble not found */ #define RXES1_NOID 0000130 /* preamble found;ID burst timeout */ #define RXES1_HNEQTRK 0000150 /* track reached doesn't match header */ #define RXES1_XIDAM 0000160 /* up made to many attempts for IDAM */ #define RXES1_NOAM 0000170 /* data AM timeout */ #define RXES1_CRC 0000200 /* crc error reading disk sector */ #define RXES1_OOPS 0000220 /* read/write electronics failed test */ #define RXES1_WCOVFL 0000230 /* word count overflow */ #define RXES1_DENSERR 0000240 /* density error */ #define RXES1_BADKEY 0000250 /* bad key word for Set Media Density */ /* bits in rxes4 */ /* bits 15-8 contain the track address for header track address errors */ #define RXES4_UNIT 0000200 /* unit select */ #define RXES4_D1DENS 0000100 /* drive 1 density */ #define RXES4_HEAD 0000040 /* head loaded */ #define RXES4_D0DENS 0000020 /* drive 0 density */ /* bits 3-1 are unused */ #define RXES4_DD 0000001 /* diskette is double density */ #define RXES4_BITS "\10\10DRIVE1\7D1HIDENS\6HEAD\5D0HIDENS\1DDENS" #define b_seccnt av_back #define b_state b_active CTE 0010000 /* controller timing error */ #define HTER_NEF 0004000 /* non-executable function */ #define HTER_CSITM 0002000 /* correctable skew/illegal tape mark */ #define HTER_FCE 0001000 /* frame count error */ #define HTER_NSG 0000400 /* non-standard gap */ #define HTER_PEFLRC 0000200 /* pe format error/lrc error */ sys/pdpuba/ra.c 644 0 12 112041 6045316236 6733 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ra.c 3.1 (2.11BSD GTE) 1995/10/28 */ /*********************************************************************** * Copyright (c) 1983 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * ***********************************************************************/ /* * ra.c - MSCP Driver * Date: October 28, 1995 * Fix multicontroller support (which was badly broken when disklabels were * added). Accessing drives on the second controller would cause serious * filesystem corruption on the the corresponding drives on the first * controller. * * Date: August 1, 1995 * Fix a bug which prohibited labeling previously disks which were unlabeled * or had a corrupted label. The default ('a' partition spanning the volume) * must be left in place to allow the write of the label. * * Date: July 3, 1995 * Fix a couple bugs and simplify the close protocol. * * Date: June 16, 1995 * Use the common label ioctl routine created today. * * Date: June 15, 1995 * Disklabels work! A few minor changes made - raopen() needed to always * validate the partition number not just when the drive was first brought * online. * * Date: May 20, 1995 * Minor changes before beginning testing. * * Date: May 03, 1995 * Resume adding disklabel support. The past several weeks were spent * porting/rewriting 'newfs', 'disklabel', 'getdiskbyname' and so on. * * Date: Apr 13, 1995 * Begin implementing disklabels. First job was to remove/change references * to dkunit() since that macro has moved from buf.h to disk.h and takes a * 'dev_t' now instead of 'buf *'. * * Date: Jan 11, 1995 * Remove extra parameter to ra_error() call in radump(). * * Date: Dec 1992, Jan 1993 * Add the partition size routine. Remove unibus map ifdefs, the run time * check for 'ubmap' is sufficient and does the right thing. * * Date: Nov 1992 * Add raVec() routine. This is called by autoconfig to set the vector * (from /etc/dtab) for controllers other than the root (1st). The boot/root * controller's vector is always set to 0154. * * Date: Jul 1992 * Major rework of the partition tables. Some old (RA60,80,81,RD53) tables * were retained (the rd54 'c' partition is now 'g' but the sizes stay * the same) for compatibility. RC25, RD51, RA82 entries were removed (unlikely * that the RA82 was used since the disktab entry was wrong). A _brand new_ * scheme utilizing 5 "generic" partition tables was created based on the * size of the disc. This was needed due to the rapid proliferation of * MSCP drive types, it was simply not feasible to have a 64 byte partition * table for each of the (currently 28 to 30) types of MSCP discs. * * More attention is paid to bits in the media id beyond the 7 bit * numeric id. These bits can be used to distinquish between a RZ24 and a * RZ24L for example. * * Some of the diagnostic output was trimmed in an attempt to offset the * growth of an already large drive. * * Date: Dec 18 1991 * The controller number (bits 6 and 7 of the minor device) were not * being masked off after using dkunit(). This caused a crash when * the controller number was other than 0. * * Date: Sep 22 1991 * The read and write entries were removed as part of implementing the * common rawread and rawwrite routines. * * Date: Mar 16 1991 * The command packets were moved to an external heap which is dynamically * allocated in a manner similar to m_ioget in the networking code. * MSCP controllers used too much valuable kernel D space. For UNIBUS * machines sufficient UMRs were allocated to map the heap, removing the * need to allocate a UMR per controller at open time. This has the side * effect of greatly simplifying the physical (Q22) or virtual (UMR) address * calculation of the command packets. It also eliminates the need for * 'struct buf racomphys', saving 24 bytes of D space. * * The error message output was rearranged saving another 82 bytes of * kernel D space. Also, there was an extraneous buffer header allocated, * it was removed, saving a further 24 bytes of D space. * sms@wlv.iipo.gtegsc.com (was wlv.imsd.contel.com at the time). * * Date: Jan 30 1984 * This thing has been beaten beyound belief. * decvax!rich. */ /* * MSCP disk device driver * Tim Tucker, Gould Electronics, Sep 1985 * Note: This driver is based on the UDA50 4.3 BSD source. */ #include "ra.h" #if NRAD > 0 && NRAC > 0 #include "param.h" #include "../machine/seg.h" #include "../machine/mscp.h" #include "systm.h" #include "buf.h" #include "conf.h" #include "map.h" #include "syslog.h" #include "ioctl.h" #include "uba.h" #include "rareg.h" #include "dk.h" #include "disklabel.h" #include "disk.h" #include "errno.h" #include "file.h" #include "stat.h" #ifndef offsetof #define offsetof(type,member) ((size_t)(&((type *)0)->member)) #endif #define RACON(x) ((minor(x) >> 6) & 03) #define RAUNIT(x) ((minor(x) >> 3) & 07) #define NRSPL2 3 /* log2 number of response packets */ #define NCMDL2 3 /* log2 number of command packets */ #define NRSP (1<= NRAC) return(-1); if (sc->sc_ivec == 0) sc->sc_ivec = vector; else if (ctlr) return(-1); return(0); } /* * Attach controller for autoconfig system. */ raattach(addr, unit) register radeviceT *addr; register int unit; { register ra_softcT *sc = &ra_sc[unit]; #ifdef UCB_METER if (ra_dkn < 0) dk_alloc(&ra_dkn, NRAD, "ra", 60L * 31L * 256L); #endif /* Check for bad address (no such controller) */ if (sc->RAADDR == NULL && addr != NULL) { sc->RAADDR = addr; sc->sc_unit = unit; sc->sc_com = (ra_comT *)SEG5; ra_com[unit] = (memaddr)_ioget(sizeof (ra_comT)); return(1); } /* * Binit and autoconfig both attempt to attach unit zero if ra is * rootdev */ return(unit ? 0 : 1); } /* * Return a pointer to a free disk table entry */ ra_infoT * ragetdd() { register int i; register ra_infoT *p; for (i = NRAD, p = ra_disks; i--; p++) if ((p->ra_flags & DKF_ALIVE) == 0) { p->ra_flags = DKF_ALIVE; return(p); } return(NULL); } /* * Open a RA. Initialize the device and set the unit online. */ raopen(dev, flag, mode) dev_t dev; int flag; int mode; { register ra_infoT *disk; register struct mscp *mp; register ra_softcT *sc = &ra_sc[RACON(dev)]; int unit = RAUNIT(dev); int ctlr = RACON(dev); int mask; int s, i; PRINTD(("raopen: dev=%x, flags=%d\n", dev, flag)); /* Check that controller exists */ if (ctlr >= NRAC || sc->RAADDR == NULL) return(ENXIO); /* Open device */ if (sc->sc_state != S_RUN) { s = splbio(); /* initialize controller if idle */ if (sc->sc_state == S_IDLE) { if (rainit(sc)) { splx(s); return(ENXIO); } } /* wait for initialization to complete */ timeout(wakeup, (caddr_t)&sc->sc_ctab, 12 * LINEHZ); sleep((caddr_t)&sc->sc_ctab, PSWP+1); if (sc->sc_state != S_RUN) { splx(s); return(EIO); } splx(s); } /* * Check to see if the device is really there. This code was * taken from Fred Canters 11 driver. */ disk = sc->sc_drives[unit]; if (disk == NULL) { PRINTD(("raopen: opening new disk %d\n", unit)); s = splbio(); /* Allocate disk table entry for disk */ if ((disk = ragetdd()) != NULL) { sc->sc_drives[unit] = disk; disk->ra_unit = ctlr; /* controller number */ } else { printf("ra: !disk structs\n"); splx(s); return(ENXIO); } } /* Try to online disk unit, it might have gone offline */ if ((disk->ra_flags & DKF_ONLINE) == 0) { /* In high kernel, don't saveseg5, just use normalseg5 later on. */ while ((mp = ragetcp(sc)) == 0) { ++sc->sc_cp_wait; sleep(&sc->sc_cp_wait, PSWP+1); --sc->sc_cp_wait; } mapseg5(ra_com[sc->sc_unit], MAPSEGDESC); mp->m_opcode = M_O_ONLIN; mp->m_unit = unit; mp->m_cmdref = (unsigned)&disk->ra_flags; ((Trl *)mp->m_dscptr)->hsh |= RA_OWN|RA_INT; normalseg5(); i = sc->RAADDR->raip; timeout(wakeup, (caddr_t)&disk->ra_flags, 10 * LINEHZ); sleep((caddr_t)&disk->ra_flags, PSWP+1); splx(s); } /* Did it go online? */ if ((disk->ra_flags & DKF_ONLINE) == 0) { PRINTD(("raopen: disk didn't go online\n")); s = splbio(); disk->ra_flags = 0; sc->sc_drives[unit] = NULL; splx(s); return(ENXIO); } /* * Now we read the label. Allocate an external label structure if one has * not already been assigned to this drive. First wait for any pending * opens/closes to complete. */ while (disk->ra_flags & (DKF_OPENING | DKF_CLOSING)) sleep(disk, PRIBIO); /* * Next if an external label buffer has not already been allocated do so * now. This "can not fail" because if the initial pool of label buffers * has been exhausted the allocation takes place from main memory. The * return value is the 'click' address to be used when mapping in the label. */ if (disk->ra_label == 0) disk->ra_label = disklabelalloc(); /* * On first open get label and partition info. We may block reading the * label so be careful to stop any other opens. */ if (disk->ra_open == 0) { disk->ra_flags |= DKF_OPENING; ragetinfo(disk, dev); disk->ra_flags &= ~DKF_OPENING; wakeup(disk); } /* * Need to make sure the partition is not out of bounds. This requires * mapping in the external label. This only happens when a partition * is opened (at mount time) and isn't an efficiency problem. */ mapseg5(disk->ra_label, LABELDESC); i = ((struct disklabel *)SEG5)->d_npartitions; normalseg5(); if (dkpart(dev) >= i) return(ENXIO); mask = 1 << dkpart(dev); dkoverlapchk(disk->ra_open, dev, disk->ra_label, "ra"); if (mode == S_IFCHR) disk->ra_copen |= mask; else if (mode == S_IFBLK) disk->ra_bopen |= mask; else return(EINVAL); disk->ra_open |= mask; PRINTD(("raopen: disk online\n")); return(0); } /* * Disk drivers now have to have close entry points in order to keep * track of what partitions are still active on a drive. */ raclose(dev, flag, mode) register dev_t dev; int flag, mode; { int s, unit = RAUNIT(dev); register int mask; register ra_infoT *disk; ra_softcT *sc = &ra_sc[RACON(dev)]; disk = sc->sc_drives[unit]; mask = 1 << dkpart(dev); if (mode == S_IFCHR) disk->ra_copen &= ~mask; else if (mode == S_IFBLK) disk->ra_bopen &= ~mask; else return(EINVAL); disk->ra_open = disk->ra_bopen | disk->ra_copen; if (disk->ra_open == 0) { disk->ra_flags |= DKF_CLOSING; s = splbio(); while (disk->ra_utab.b_actf) sleep(&disk->ra_utab, PRIBIO); splx(s); disk->ra_flags &= ~DKF_CLOSING; wakeup(disk); } return(0); } /* * This code was moved from ragetinfo() because it is fairly large and used * twice - once to initialize for reading the label and a second time if * there is no valid label present on the drive and the default one must be * used. */ void radfltlbl(disk, lp) ra_infoT *disk; register struct disklabel *lp; { register struct partition *pi = &lp->d_partitions[0]; bzero(lp, sizeof (*lp)); lp->d_type = DTYPE_MSCP; lp->d_secsize = 512; /* XXX */ lp->d_nsectors = 32; lp->d_ntracks = 1; lp->d_secpercyl = 20 * 32; lp->d_npartitions = 1; /* 'a' */ pi->p_size = disk->ra_nblks; /* entire volume */ pi->p_fstype = FS_V71K; pi->p_frag = 1; pi->p_fsize = 1024; /* * Put where rastrategy() will look. */ bcopy(pi, disk->ra_parts, sizeof (lp->d_partitions)); } /* * Read disklabel. It is tempting to generalize this routine so that * all disk drivers could share it. However by the time all of the * necessary parameters are setup and passed the savings vanish. Also, * each driver has a different method of calculating the number of blocks * to use if one large partition must cover the disk. * * This routine used to always return success and callers carefully checked * the return status. Silly. This routine will fake a label (a single * partition spanning the drive) if necessary but will never return an error. * * It is the caller's responsibility to check the validity of partition * numbers, etc. */ void ragetinfo(disk, dev) register ra_infoT *disk; dev_t dev; { struct disklabel locallabel; char *msg; register struct disklabel *lp = &locallabel; /* * NOTE: partition 0 ('a') is used to read the label. Therefore 'a' must * start at the beginning of the disk! If there is no label or the label * is corrupted then 'a' will span the entire disk */ radfltlbl(disk, lp); /* set up default/fake label */ msg = readdisklabel((dev & ~7) | 0, rastrategy, lp); /* 'a' */ if (msg != 0) { log(LOG_NOTICE, "ra%da is entire disk: %s\n", dkunit(dev), msg); radfltlbl(disk, lp); } mapseg5(disk->ra_label, LABELDESC); bcopy(lp, (struct disklabel *)SEG5, sizeof (struct disklabel)); normalseg5(); bcopy(lp->d_partitions, disk->ra_parts, sizeof (lp->d_partitions)); return; } /* * Initialize controller, data structures, and start hardware * initialization sequence. */ rainit(sc) register ra_softcT *sc; { long adr; /* * Cold init of controller */ ++sc->sc_ctab.b_active; PRINTD(("rainit: unit=%d, vec=%o\n", sc->sc_unit, sc->sc_ivec)); /* * Get physical address of RINGBASE */ adr = _iomap(ra_com[sc->sc_unit]) + RINGBASE; /* * Get individual controller RINGBASE physical address */ sc->sc_ctab.b_un.b_addr = (caddr_t)loint(adr); sc->sc_ctab.b_xmem = hiint(adr); /* * Start the hardware initialization sequence. */ sc->RAADDR->raip = 0; while ((sc->RAADDR->rasa & RA_STEP1) == 0) if (sc->RAADDR->rasa & RA_ERR) return(1); sc->RAADDR->rasa = RA_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | RA_IE | (sc->sc_ivec / 4); /* * Initialization continues in interrupt routine. */ sc->sc_state = S_STEP1; sc->sc_credits = 0; return(0); } rastrategy(bp) register struct buf *bp; { register ra_infoT *disk; register struct buf *dp; ra_softcT *sc = &ra_sc[RACON(bp->b_dev)]; int unit = RAUNIT(bp->b_dev); int part = dkpart(bp->b_dev); struct partition *pi; daddr_t sz, maxsz; int s; /* Is disk online */ if ((disk = sc->sc_drives[unit]) == NULL || !(disk->ra_flags & (DKF_ONLINE | DKF_ALIVE))) goto bad; pi = &disk->ra_parts[part]; /* Valid block in device partition */ sz = (bp->b_bcount + 511) >> 9; if (bp->b_blkno < 0 || bp->b_blkno + sz > pi->p_size) { sz = pi->p_size - bp->b_blkno; /* if exactly at end of disk, return an EOF */ if (sz == 0) { bp->b_resid = bp->b_bcount; goto done; } /* or truncate if part of it fits */ if (sz < 0) { bp->b_error = EINVAL; goto bad; } bp->b_bcount = dbtob(sz); /* compute byte count */ } /* * Check for write to write-protected label area. This does not include * sector 0 which is the boot block. */ if (bp->b_blkno + pi->p_offset <= LABELSECTOR && bp->b_blkno + pi->p_offset + sz > LABELSECTOR && !(bp->b_flags & B_READ) && !(disk->ra_flags & DKF_WLABEL)) { bp->b_error = EROFS; goto bad; } mapalloc(bp); /* Unibus Map buffer if required */ /* * Link the buffer onto the drive queue */ s = splbio(); dp = &disk->ra_utab; if (dp->b_actf == 0) dp->b_actf = bp; else dp->b_actl->av_forw = bp; dp->b_actl = bp; bp->av_forw = 0; /* * Link the drive onto the controller queue */ if (dp->b_active == 0) { dp->b_forw = NULL; if (sc->sc_ctab.b_actf == NULL) sc->sc_ctab.b_actf = dp; else sc->sc_ctab.b_actl->b_forw = dp; sc->sc_ctab.b_actl = dp; dp->b_active = 1; } /* * Start controller if idle. */ if (sc->sc_ctab.b_active == 0) { rastart(sc); } splx(s); return; bad: bp->b_flags |= B_ERROR; done: iodone(bp); return; } /* Start i/o, must be called at level splbio */ rastart(sc) register ra_softcT *sc; { register struct mscp *mp; register struct buf *bp; struct buf *dp; struct partition *pi; ra_infoT *disk; int i; long temp; segm seg5; saveseg5(seg5); /* save it just once */ loop: /* * Anything left to do on this controller? */ if ((dp = sc->sc_ctab.b_actf) == NULL) { sc->sc_ctab.b_active = 0; /* * Check for response ring transitions lost in race * condition */ mapseg5(ra_com[sc->sc_unit], MAPSEGDESC); rarspring(sc); restorseg5(seg5); return(0); } /* Get first request waiting on queue */ if ((bp = dp->b_actf) == NULL) { /* * No more requests for this drive, remove * from controller queue and look at next drive. * We know we're at the head of the controller queue. * The drive may not need anything, in which case it might * be shutting down in raclose() and a wakeup is needed. */ dp->b_active = 0; sc->sc_ctab.b_actf = dp->b_forw; i = offsetof(ra_infoT, ra_utab); disk = (ra_infoT *)((int)dp - i); if (disk->ra_open == 0) wakeup(dp); /* finish close protocol */ goto loop; } ++sc->sc_ctab.b_active; if (sc->RAADDR->rasa & RA_ERR || sc->sc_state != S_RUN) { harderr(bp, "ra"); log(LOG_INFO, "rasa %o state %d\n", sc->RAADDR->rasa, sc->sc_state); /* Should requeue outstanding requests somehow */ rainit(sc); out: restorseg5(seg5); return(0); } /* Issue command */ mapseg5(ra_com[sc->sc_unit], MAPSEGDESC); if ((mp = ragetcp(sc)) == NULL) goto out; mp->m_cmdref = (unsigned)bp; /* pointer to get back */ mp->m_opcode = bp->b_flags & B_READ ? M_O_READ : M_O_WRITE; mp->m_unit = RAUNIT(bp->b_dev); disk = sc->sc_drives[mp->m_unit]; pi = &disk->ra_parts[dkpart(bp->b_dev)]; temp = bp->b_blkno + pi->p_offset; mp->m_lbn_l = loint(temp); mp->m_lbn_h = hiint(temp); mp->m_bytecnt = bp->b_bcount; mp->m_buf_l = (u_short)bp->b_un.b_addr; mp->m_buf_h = bp->b_xmem; PRINTD(("ra: unit=%d op=0%o lbn=%d,%d len=%d buf=0%o,0%o\n", mp->m_unit, mp->m_opcode, mp->m_lbn_h, mp->m_lbn_l, mp->m_bytecnt, mp->m_buf_h, mp->m_buf_l)); ((Trl *)mp->m_dscptr)->hsh |= RA_OWN|RA_INT; if (sc->RAADDR->rasa & RA_ERR) printf("ra: Err %d\n", sc->RAADDR->rasa); i = sc->RAADDR->raip; /* initiate polling */ #ifdef UCB_METER if (ra_dkn >= 0) { int dkn = ra_dkn + mp->m_unit; /* Messy, should do something better than this. Ideas? */ ++dp->b_qsize; dk_busy |= 1<b_bcount>>6; } #endif /* * Move drive to the end of the controller queue */ if (dp->b_forw != NULL) { sc->sc_ctab.b_actf = dp->b_forw; sc->sc_ctab.b_actl->b_forw = dp; sc->sc_ctab.b_actl = dp; dp->b_forw = NULL; } /* * Move buffer to I/O wait queue */ dp->b_actf = bp->av_forw; dp = &sc->sc_wtab; bp->av_forw = dp; bp->av_back = dp->av_back; dp->av_back->av_forw = bp; dp->av_back = bp; goto loop; } /* * RA interrupt routine. */ raintr(unit) int unit; { register ra_softcT *sc = &ra_sc[unit]; register struct mscp *mp; register struct buf *bp; u_int i; segm seg5; PRINTD(("raintr%d: state %d, rasa %o\n", unit, sc->sc_state, sc->RAADDR->rasa)); saveseg5(seg5); /* save it just once */ switch (sc->sc_state) { case S_STEP1: #define STEP1MASK 0174377 #define STEP1GOOD (RA_STEP2|RA_IE|(NCMDL2<<3)|NRSPL2) if ((sc->RAADDR->rasa & STEP1MASK) != STEP1GOOD) { sc->sc_state = S_IDLE; sc->sc_ctab.b_active = 0; wakeup((caddr_t)&sc->sc_ctab); return; } sc->RAADDR->rasa = (short)sc->sc_ctab.b_un.b_addr; sc->sc_state = S_STEP2; return; case S_STEP2: #define STEP2MASK 0174377 #define STEP2GOOD (RA_STEP3|RA_IE|(sc->sc_ivec/4)) if ((sc->RAADDR->rasa & STEP2MASK) != STEP2GOOD) { sc->sc_state = S_IDLE; sc->sc_ctab.b_active = 0; wakeup((caddr_t)&sc->sc_ctab); return; } sc->RAADDR->rasa = sc->sc_ctab.b_xmem; sc->sc_state = S_STEP3; return; case S_STEP3: #define STEP3MASK 0174000 #define STEP3GOOD RA_STEP4 if ((sc->RAADDR->rasa & STEP3MASK) != STEP3GOOD) { sc->sc_state = S_IDLE; sc->sc_ctab.b_active = 0; wakeup((caddr_t)&sc->sc_ctab); return; } i = sc->RAADDR->rasa; PRINTD(("ra: Version %d model %d\n", i & 0xf, (i >> 4) & 0xf)); sc->RAADDR->rasa = RA_GO; sc->sc_state = S_SCHAR; /* * Initialize the data structures. */ mapseg5(ra_com[sc->sc_unit], MAPSEGDESC); ramsginit(sc, sc->sc_com->ra_ca.ca_rsp, sc->sc_com->ra_rsp, 0, NRSP, RA_INT | RA_OWN); ramsginit(sc, sc->sc_com->ra_ca.ca_cmd, sc->sc_com->ra_cmd, NRSP, NCMD, RA_INT); bp = &sc->sc_wtab; bp->av_forw = bp->av_back = bp; sc->sc_lastcmd = 1; sc->sc_lastrsp = 0; mp = sc->sc_com->ra_cmd; ramsgclear(mp); mp->m_opcode = M_O_STCON; mp->m_cntflgs = M_C_ATTN | M_C_MISC | M_C_THIS; ((Trl *)mp->m_dscptr)->hsh |= RA_OWN|RA_INT; i = sc->RAADDR->raip; restorseg5(seg5); return; case S_SCHAR: case S_RUN: break; default: printf("ra: state %d ign\n", sc->sc_state); return; } /* * If this happens we are in BIG trouble! */ if (sc->RAADDR->rasa & RA_ERR) { printf("ra: fatal err %o\n", sc->RAADDR->rasa); sc->sc_state = S_IDLE; sc->sc_ctab.b_active = 0; wakeup((caddr_t)&sc->sc_ctab); } mapseg5(ra_com[sc->sc_unit], MAPSEGDESC); /* * Check for buffer purge request */ if (sc->sc_com->ra_ca.ca_bdp) { sc->sc_com->ra_ca.ca_bdp = 0; sc->RAADDR->rasa = 0; } /* * Check for response ring transition. */ if (sc->sc_com->ra_ca.ca_rspint) { rarspring(sc); } /* * Check for command ring transition (Should never happen!) */ if (sc->sc_com->ra_ca.ca_cmdint) sc->sc_com->ra_ca.ca_cmdint = 0; restorseg5(seg5); /* Waiting for command? */ if (sc->sc_cp_wait) wakeup((caddr_t)&sc->sc_cp_wait); rastart(sc); } /* * Init mscp communications area */ ramsginit(sc, com, msgs, offset, length, flags) register ra_softcT *sc; register Trl *com; register struct mscp *msgs; int offset, length, flags; { long vaddr; /* * Figure out Unibus or physical(Q22) address of message * skip comm area and mscp messages header and previous messages */ vaddr = _iomap(ra_com[sc->sc_unit]); /* base adr in heap */ vaddr += sizeof(struct raca) /* skip comm area */ +sizeof(struct mscp_header); /* m_cmdref disp */ vaddr += offset * sizeof(struct mscp); /* skip previous */ while (length--) { com->lsh = loint(vaddr); com->hsh = flags | hiint(vaddr); msgs->m_dscptr = (long *)com; msgs->m_header.ra_msglen = sizeof(struct mscp); ++com; ++msgs; vaddr += sizeof(struct mscp); } } /* * Try and find an unused command packet */ struct mscp * ragetcp(sc) register ra_softcT *sc; { register struct mscp *mp = NULL; register int i; int s; segm seg5; s = splbio(); saveseg5(seg5); mapseg5(ra_com[sc->sc_unit], MAPSEGDESC); i = sc->sc_lastcmd; if ((sc->sc_com->ra_ca.ca_cmd[i].hsh & (RA_OWN|RA_INT)) == RA_INT && sc->sc_credits >= 2) { --sc->sc_credits; sc->sc_com->ra_ca.ca_cmd[i].hsh &= ~RA_INT; mp = &sc->sc_com->ra_cmd[i]; ramsgclear(mp); sc->sc_lastcmd = (i + 1) % NCMD; } restorseg5(seg5); splx(s); return(mp); } /* Clear a mscp command packet */ ramsgclear(mp) register struct mscp *mp; { mp->m_unit = mp->m_modifier = mp->m_flags = mp->m_bytecnt = mp->m_buf_l = mp->m_buf_h = mp->m_elgfll = mp->m_copyspd = mp->m_elgflh = mp->m_opcode = mp->m_cntflgs = 0; } /* Scan for response messages */ rarspring(sc) register ra_softcT *sc; { register int i; sc->sc_com->ra_ca.ca_rspint = 0; i = sc->sc_lastrsp; for (;;) { i %= NRSP; if (sc->sc_com->ra_ca.ca_rsp[i].hsh & RA_OWN) break; rarsp(&sc->sc_com->ra_rsp[i], sc); sc->sc_com->ra_ca.ca_rsp[i].hsh |= RA_OWN; ++i; } sc->sc_lastrsp = i; } /* * Process a response packet */ rarsp(mp, sc) register struct mscp *mp; register ra_softcT *sc; { register struct buf *dp; struct buf *bp; ra_infoT *disk; int st; /* * Reset packet length and check controller credits */ mp->m_header.ra_msglen = sizeof(struct mscp); sc->sc_credits += mp->m_header.ra_credits & 0xf; if ((mp->m_header.ra_credits & 0xf0) > 0x10) return; /* * If it's an error log message (datagram), * pass it on for more extensive processing. */ if ((mp->m_header.ra_credits & 0xf0) == 0x10) { ra_error((struct mslg *)mp); return; } /* * The controller interrupts as drive ZERO so check for it first. */ st = mp->m_status & M_S_MASK; if (mp->m_opcode == (M_O_STCON|M_O_END)) { if (st == M_S_SUCC) sc->sc_state = S_RUN; else sc->sc_state = S_IDLE; sc->sc_ctab.b_active = 0; wakeup((caddr_t)&sc->sc_ctab); return; } /* * Check drive and then decode response and take action. */ switch (mp->m_opcode) { case M_O_ONLIN|M_O_END: if ((disk = sc->sc_drives[mp->m_unit]) == NULL) { log(LOG_NOTICE,"ra%d !ONLINE\n", sc->sc_unit * 8 + mp->m_unit); break; } dp = &disk->ra_utab; if (st == M_S_SUCC) { /* Link the drive onto the controller queue */ dp->b_forw = NULL; if (sc->sc_ctab.b_actf == NULL) sc->sc_ctab.b_actf = dp; else sc->sc_ctab.b_actl->b_forw = dp; sc->sc_ctab.b_actl = dp; /* mark it online */ radisksetup(disk, mp); dp->b_active = 1; } else { printf("ra%d: OFFLINE\n", sc->sc_unit * 8 + mp->m_unit); while (bp = dp->b_actf) { dp->b_actf = bp->av_forw; bp->b_flags |= B_ERROR; iodone(bp); } } /* Wakeup in open if online came from there */ if (mp->m_cmdref != NULL) wakeup((caddr_t)mp->m_cmdref); break; case M_O_AVATN: /* it went offline and we didn't notice */ PRINTD(("ra%d: attention\n", sc->sc_unit * 8 + mp->m_unit)); if ((disk = sc->sc_drives[mp->m_unit]) != NULL) disk->ra_flags &= ~DKF_ONLINE; break; case M_O_END: /* controller incorrectly returns code 0200 instead of 0241 */ PRINTD(("ra: back logical block request\n")); bp = (struct buf *)mp->m_cmdref; bp->b_flags |= B_ERROR; case M_O_READ | M_O_END: case M_O_WRITE | M_O_END: /* normal termination of read/write request */ if ((disk = sc->sc_drives[mp->m_unit]) == NULL) break; bp = (struct buf *)mp->m_cmdref; /* * Unlink buffer from I/O wait queue. */ bp->av_back->av_forw = bp->av_forw; bp->av_forw->av_back = bp->av_back; dp = &disk->ra_utab; #ifdef UCB_METER if (ra_dkn >= 0) { /* Messy, Should come up with a good way to do this */ if (--dp->b_qsize == 0) dk_busy &= ~(1 << (ra_dkn + mp->m_unit)); } #endif if (st == M_S_OFFLN || st == M_S_AVLBL) { /* mark unit offline */ disk->ra_flags &= ~DKF_ONLINE; /* Link the buffer onto the front of the drive queue */ if ((bp->av_forw = dp->b_actf) == 0) dp->b_actl = bp; dp->b_actf = bp; /* Link the drive onto the controller queue */ if (dp->b_active == 0) { dp->b_forw = NULL; if (sc->sc_ctab.b_actf == NULL) sc->sc_ctab.b_actf = dp; else sc->sc_ctab.b_actl->b_forw = dp; sc->sc_ctab.b_actl = dp; dp->b_active = 1; } return; } if (st != M_S_SUCC) { harderr(bp, "ra"); log(LOG_INFO, "status %o\n", mp->m_status); bp->b_flags |= B_ERROR; } bp->b_resid = bp->b_bcount - mp->m_bytecnt; iodone(bp); break; case M_O_GTUNT|M_O_END: break; default: log(LOG_INFO,"ra: op %o\n", mp->m_opcode); ra_error((caddr_t)mp); } } /* * Init disk info structure from data in mscp packet */ radisksetup(disk, mp) register ra_infoT *disk; register struct mscp *mp; { int nameid, numid; nameid = (((loint(mp->m_mediaid) & 0x3f) << 9) | ((hiint(mp->m_mediaid) >> 7) & 0x1ff)); numid = hiint(mp->m_mediaid) & 0x7f; /* Get unit total block count */ disk->ra_nblks = mp->m_uslow + ((long)mp->m_ushigh << 16); /* spill the beans about what we have brought online */ log(LOG_NOTICE, "ra%d: %c%c%d%c size=%D\n", disk->ra_unit * 8 + mp->m_unit, mx(nameid,2), mx(nameid,1), numid, mx(nameid,0), disk->ra_nblks); disk->ra_flags |= DKF_ONLINE; } /* * this is a routine rather than a macro to save space - shifting, etc * generates a lot of code. */ mx(l, i) int l, i; { register int c; c = (l >> (5 * i)) & 0x1f; if (c == 0) c = ' ' - '@'; return(c + '@'); } raioctl(dev, cmd, data, flag) dev_t dev; int cmd; caddr_t data; int flag; { ra_softcT *sc = &ra_sc[RACON(dev)]; ra_infoT *disk = sc->sc_drives[RAUNIT(dev)]; int error; error = ioctldisklabel(dev, cmd, data, flag, disk, rastrategy); return(error); } /* * Process an error log message * * For now, just log the error on the console. Only minimal decoding is done, * only "useful" information is printed. Eventually should send message to * an error logger. At least 90 bytes of D space were saved without losing * functionality. */ ra_error(mp) register struct mslg *mp; { printf("ra: %s err, ", mp->me_flags & (M_LF_SUCC|M_LF_CONT) ? "soft" : "hard"); switch (mp->me_format) { case M_F_CNTERR: printf("ctlr"); break; case M_F_BUSADDR: printf("M_F_BUSADDR %o", mp->me_busaddr); break; case M_F_DISKTRN: printf("disk xfr, unit %d grp x%x hdr x%x", mp->me_unit, mp->me_group, mp->me_hdr); break; case M_F_SDI: printf("SDI unit %d hdr x%x", mp->me_unit, mp->me_hdr); break; case M_F_SMLDSK: printf("small disk unit %d cyl %d", mp->me_unit, mp->me_sdecyl); break; default: printf("?, unit %d format %o",mp->me_unit,mp->me_format); } printf(", event 0%o\n", mp->me_event); #ifdef RADEBUG /* If error debug on, do hex dump */ { register char *p = (char *)mp; register int i; for (i = mp->me_header.ra_msglen; i--; /*void*/) printf("%x ", *p++ & 0xff); printf("\n"); } #endif } /* * RA dump routines (act like stand alone driver) */ #ifdef RA_DUMP #define DBSIZE 16 /* number of blocks to write */ radump(dev) dev_t dev; { register ra_softcT *sc; register ra_infoT *disk; register struct mscp *mp; struct mscp *racmd(); struct partition *pi; daddr_t bn, dumpsize; long paddr, maddr; int count, memblks; struct ubmap *ubp; int unit, partition; segm seg5; /* paranoia, space hack */ unit = RAUNIT(dev); sc = &ra_sc[RACON(dev)]; partition = dkpart(dev); if (sc->RAADDR == NULL) return(EINVAL); disk = sc->sc_drives[unit]; /* * The drive to which we dump must be present and alive. */ if (!disk || !(disk->ra_flags & DKF_ALIVE)) return(ENXIO); pi = &disk->ra_parts[partition]; /* * Paranoia - we do not dump to a partition if it has not been declared as * a 'swap' type of filesystem. */ if (pi->p_fstype != FS_SWAP) return(EFTYPE); /* Init RA controller */ paddr = _iomap(ra_com[sc->sc_unit]); if (ubmap) { ubp = UBMAP; ubp->ub_lo = loint(paddr); ubp->ub_hi = hiint(paddr); } /* Get communications area and clear out packets */ paddr += RINGBASE; saveseg5(seg5); mapseg5(ra_com[sc->sc_unit], MAPSEGDESC); mp = sc->sc_com->ra_rsp; sc->sc_com->ra_ca.ca_cmdint = sc->sc_com->ra_ca.ca_rspint = 0; bzero((caddr_t)mp, 2 * sizeof(*mp)); /* Init controller */ sc->RAADDR->raip = 0; while ((sc->RAADDR->rasa & RA_STEP1) == 0) /*void*/; sc->RAADDR->rasa = RA_ERR; while ((sc->RAADDR->rasa & RA_STEP2) == 0) /*void*/; sc->RAADDR->rasa = loint(paddr); while ((sc->RAADDR->rasa & RA_STEP3) == 0) /*void*/; sc->RAADDR->rasa = hiint(paddr); while ((sc->RAADDR->rasa & RA_STEP4) == 0) /*void*/; sc->RAADDR->rasa = RA_GO; ramsginit(sc, sc->sc_com->ra_ca.ca_rsp, mp, 0, 2, 0); if (!racmd(M_O_STCON, unit, sc)) { PRINTB(("radump: failed start controller\n")); return(EFAULT); } PRINTB(("radump: controller up\n")); /* Bring disk for dump online */ if (!(mp = racmd(M_O_ONLIN, unit, sc))) { PRINTB(("radump: failed online\n")); return(EFAULT); } dumpsize = rasize(dev) - dumplo; memblks = ctod(physmem); PRINTB(("radump: disk up, size=%D, type=%d\n", dumpsize, hiint(mp->m_mediaid) & 0xff)); /* Check if dump ok on this disk */ if (dumplo < 0 || dumpsize <= 0) return(EINVAL); if (memblks > dumpsize) memblks = dumpsize; bn = dumplo + pi->p_offset; /* Save core to dump partition */ ubp = &UBMAP[1]; for (paddr = 0L; memblks > 0; ) { count = MIN(memblks, DBSIZE); maddr = paddr; if (ubmap) { ubp->ub_lo = loint(paddr); ubp->ub_hi = hiint(paddr); maddr = (u_int)(1 << 13); } /* Write it to the disk */ mp = &sc->sc_com->ra_rsp[1]; mp->m_lbn_l = loint(bn); mp->m_lbn_h = hiint(bn); mp->m_bytecnt = count * NBPG; mp->m_buf_l = loint(maddr); mp->m_buf_h = hiint(maddr); if (racmd(M_O_WRITE, unit, sc) == 0) return(EIO); paddr += (count << PGSHIFT); bn += count; memblks -= count; } restorseg5(seg5); return(0); } struct mscp * racmd(op, unit, sc) int op, unit; register ra_softcT *sc; { register struct mscp *cmp, *rmp; Trl *rlp; int i; cmp = &sc->sc_com->ra_rsp[1]; rmp = &sc->sc_com->ra_rsp[0]; rlp = &sc->sc_com->ra_ca.ca_rsp[0]; cmp->m_opcode = op; cmp->m_unit = unit; cmp->m_header.ra_msglen = rmp->m_header.ra_msglen = sizeof(struct mscp); rlp[0].hsh &= ~RA_INT; rlp[1].hsh &= ~RA_INT; rlp[0].hsh &= ~RA_INT; rlp[1].hsh &= ~RA_INT; rlp[0].hsh |= RA_OWN; rlp[1].hsh |= RA_OWN; i = sc->RAADDR->raip; while ((rlp[1].hsh & RA_INT) == 0) /*void*/; while ((rlp[0].hsh & RA_INT) == 0) /*void*/; sc->sc_com->ra_ca.ca_rspint = 0; sc->sc_com->ra_ca.ca_cmdint = 0; if (rmp->m_opcode != (op | M_O_END) || (rmp->m_status & M_S_MASK) != M_S_SUCC) { ra_error(rmp); return(0); } return(rmp); } #endif RA_DUMP /* * Return the number of blocks in a partition. Call raopen() to online * the drive if necessary. If an open is necessary then a matching close * will be done. */ daddr_t rasize(dev) register dev_t dev; { ra_softcT *sc = &ra_sc[RACON(dev)]; register ra_infoT *disk; daddr_t psize; int didopen = 0; disk = sc->sc_drives[RAUNIT(dev)]; /* * This should never happen but if we get called early in the kernel's * life (before opening the swap or root devices) then we have to do * the open here. */ if (disk->ra_open == 0) { if (raopen(dev, FREAD|FWRITE, S_IFBLK)) return(-1); didopen = 1; } psize = disk->ra_parts[dkpart(dev)].p_size; if (didopen) raclose(dev, FREAD|FWRITE, S_IFBLK); return(psize); } #endif NRAC > 0 && NRAD > 0 length and check controller credits */ mp->m_header.ra_msglen = sizeof(struct mscp); sc->sc_credits += mp->m_header.ra_credits & 0xf; if ((mp->m_header.ra_credits & 0xf0) > 0x10) return; /* * If it's an error log message (datagram), * pass it on for more extensive processing. */ if ((mp->m_header.ra_credits & 0xf0) == 0x10) { ra_error((struct mslg *)mp); return; } /* * The controller interrupts as drive ZERO so check for it first. */ st = mp->m_stsys/pdpuba/rareg.h 444 0 12 1234 5303102153 7360 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)rareg.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * RA disk controller device registers */ typedef struct radevice { short raip; /* init and polling */ short rasa; /* status and addresses */ } radeviceT; #define RA_ERR 0100000 #define RA_STEP4 0040000 #define RA_STEP3 0020000 #define RA_STEP2 0010000 #define RA_STEP1 0004000 #define RA_NV 0002000 #define RA_QB 0001000 #define RA_DI 0000400 #define RA_IE 0000200 #define RA_PI 0000001 #define RA_GO 0000001 c_com->ra_rsp[0]; rlp = &sc->sc_com->ra_ca.ca_rsp[0]; cmp->m_opcode = op; cmp->m_unit = unit; cmp->m_header.ra_msglen = rmp->m_header.ra_msglen = sizeof(struct mscp); rlp[0].hsh &= ~RA_INT; rlp[1].hsh &= ~RA_INT; rlp[0].hsh &= ~RA_INT; rlp[1].hsh &= ~RA_INT; rlp[0].hsh |= RA_OWN; rlp[1].hsh |= RA_OWN; i = sc->RAADDR->raip; while ((rlp[1].hsh sys/pdpuba/si.c 444 0 12 23305 5743411431 6723 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)si.c 1.5 (2.11BSD GTE) 1995/04/13 */ /* * SI 9500 driver for CDC 9766 disks */ #include "si.h" #if NSI > 0 #include "param.h" #include "../machine/seg.h" #include "systm.h" #include "buf.h" #include "conf.h" #include "sireg.h" #include "map.h" #include "uba.h" #include "dk.h" #include "disklabel.h" #include "disk.h" #include "xp.h" #include "errno.h" #define SI_NSECT 32 #define SI_NTRAC 19 #if NXPD > 0 extern struct size { daddr_t nblocks; int cyloff; } rm5_sizes[8]; #else !NXPD /* * We reserve room for bad block forwarding information even though this * driver doesn't support bad block forwarding. This allows us to simply * copy the table from xp.c. */ struct size { daddr_t nblocks; int cyloff; } rm5_sizes[8] = { /* RM05, CDC 9766 */ 9120, 0, /* a: cyl 0 - 14 */ 9120, 15, /* b: cyl 15 - 29 */ 234080, 30, /* c: cyl 30 - 414 */ 247906, 415, /* d: cyl 415 - 822, reserve 1 track + 126 */ 164160, 30, /* e: cyl 30 - 299 */ 152000, 300, /* f: cyl 300 - 549 */ 165826, 550, /* g: cyl 550 - 822, reserve 1 track + 126 */ 500384, 0, /* h: cyl 0 - 822 */ }; #endif NXPD struct sidevice *SIADDR; int si_offset[] = { SI_OFP, SI_OFM }; struct buf sitab; struct buf siutab[NSI]; int sicc[NSI]; /* Current cylinder */ int dualsi = 0; /* dual port flag */ #ifdef UCB_METER static int si_dkn = -1; /* number for iostat */ #endif void siroot() { siattach((struct sidevice *)0176700, 0); } siattach(addr, unit) register struct sidevice *addr; { #ifdef UCB_METER if (si_dkn < 0) { dk_alloc(&si_dkn, NSI+1, "si", 60L * 32L * 256L); if (si_dkn >= 0) dk_wps[si_dkn+NSI] = 0L; } #endif if (unit != 0) return(0); if ((addr != (struct sidevice *) NULL) && (fioword(addr) != -1)) { SIADDR = addr; if(addr ->siscr != 0) dualsi++; /* dual port controller */ if((addr->sierr & (SIERR_ERR | SIERR_CNT)) == (SIERR_ERR | SIERR_CNT)) dualsi++; return(1); } SIADDR = (struct sidevice *) NULL; return(0); } siopen(dev, flag) dev_t dev; int flag; { register int unit; unit = minor(dev) & 077; if (unit >= (NSI << 3) || !SIADDR) return (ENXIO); return (0); } sistrategy(bp) register struct buf *bp; { register struct buf *dp; register int unit; long bn; int s; unit = minor(bp->b_dev) & 077; if (unit >= (NSI << 3) || (SIADDR == (struct sidevice *) NULL)) { bp->b_error = ENXIO; goto errexit; } if (bp->b_blkno < 0 || (bn = bp->b_blkno) + (long) ((bp->b_bcount + 511) >> 9) > rm5_sizes[unit & 07].nblocks) { bp->b_error = EINVAL; errexit: bp->b_flags |= B_ERROR; iodone(bp); return; } mapalloc(bp); bp->b_cylin = bn / (SI_NSECT * SI_NTRAC) + rm5_sizes[unit & 07].cyloff; unit = dkunit(bp->b_dev); dp = &siutab[unit]; s = splbio(); disksort(dp, bp); if (dp->b_active == 0) { siustart(unit); if (sitab.b_active == 0) sistart(); } splx(s); } /* * Unit start routine. * Seek the drive to where the data is * and then generate another interrupt * to actually start the transfer. * If there is only one drive on the controller * or we are very close to the data, don't * bother with the search. If called after * searching once, don't bother to look * where we are, just queue for transfer (to avoid * positioning forever without transferring). */ siustart(unit) register unit; { register struct sidevice *siaddr = SIADDR; register struct buf *dp; struct buf *bp; daddr_t bn; int sn, cn, csn; if (unit >= NSI) return; #ifdef UCB_METER if (si_dkn >= 0) dk_busy &= ~(1 << (si_dkn + unit)); #endif dp = &siutab[unit]; if ((bp = dp->b_actf) == NULL) return; /* * If we have already positioned this drive, * then just put it on the ready queue. */ if (dp->b_active) goto done; dp->b_active++; #if NSI > 1 /* * If drive is not ready, forget about positioning. */ if(dualsi) getsi(); if ((siaddr->sissr >> (unit*4)) & SISSR_NRDY) goto done; /* * Figure out where this transfer is going to * and see if we are close enough to justify not searching. */ bn = bp->b_blkno; cn = bp->b_cylin; sn = bn % (SI_NSECT * SI_NTRAC); sn = (sn + SI_NSECT) % SI_NSECT; if (sicc[unit] == cn) goto done; search: siaddr->sisar = (unit << 10) | cn; if(dualsi) SIADDR->siscr = 0; sicc[unit] = cn; #ifdef UCB_METER /* * Mark unit busy for iostat. */ if (si_dkn >= 0) { int dkn = si_dkn + unit; dk_busy |= 1< 1 done: /* * Device is ready to go. * Put it on the ready queue for the controller. */ dp->b_forw = NULL; if (sitab.b_actf == NULL) sitab.b_actf = dp; else sitab.b_actl->b_forw = dp; sitab.b_actl = dp; } /* * Start up a transfer on a drive. */ sistart() { register struct sidevice *siaddr = SIADDR; register struct buf *bp; register unit; struct buf *dp; daddr_t bn; int dn, sn, tn, cn; int offset; loop: /* * Pull a request off the controller queue. */ if ((dp = sitab.b_actf) == NULL) return; if ((bp = dp->b_actf) == NULL) { sitab.b_actf = dp->b_forw; goto loop; } /* * Mark controller busy and * determine destination of this request. */ sitab.b_active++; unit = minor(bp->b_dev) & 077; dn = dkunit(bp->b_dev); bn = bp->b_blkno; cn = bn / (SI_NSECT * SI_NTRAC) + rm5_sizes[unit & 07].cyloff; sn = bn % (SI_NSECT * SI_NTRAC); tn = sn / SI_NSECT; sn = sn % SI_NSECT; /* * Check that drive is ready. */ if(dualsi) getsi(); if ((siaddr->sissr >> (dn*4)) & SISSR_NRDY) { sitab.b_active = 0; sitab.b_errcnt = 0; dp->b_actf = bp->av_forw; bp->b_flags |= B_ERROR; iodone(bp); goto loop; } offset = 0; if (sitab.b_errcnt >= 16 && (bp->b_flags & B_READ)) offset = si_offset[sitab.b_errcnt & 1]; siaddr->sipcr = (dn << 10) | cn; siaddr->sihsr = (tn << 5) + sn; siaddr->simar = bp->b_un.b_addr; siaddr->siwcr = bp->b_bcount >> 1; /* * Warning: unit is being used as a temporary. */ unit = offset | ((bp->b_xmem & 3) << 4) | SI_IE | SI_GO; if (bp->b_flags & B_READ) unit |= SI_READ; else unit |= SI_WRITE; siaddr->sicnr = unit; #ifdef UCB_METER if (si_dkn >= 0) { int dkn = si_dkn + NSI; dk_busy |= 1<b_bcount >> 6; } #endif } /* * Handle a disk interrupt. */ siintr() { register struct sidevice *siaddr = SIADDR; register struct buf *dp; register unit; struct buf *bp; int ss, ssr; ssr = siaddr->sissr; if (sitab.b_active) { #ifdef UCB_METER if (si_dkn >= 0) dk_busy &= ~(1 << (si_dkn + NSI)); #endif /* * Get device and block structures. */ dp = sitab.b_actf; bp = dp->b_actf; unit = dkunit(bp->b_dev); /* * Check for and process errors. */ if (siaddr->sierr & SIERR_ERR) { /* * After 18 retries (16 without offset and * 2 with offset positioning), give up. */ if (++sitab.b_errcnt > 18) { bp->b_flags |= B_ERROR; harderr(bp, "si"); printf("cnr=%b err=%b\n", siaddr->sicnr, SI_BITS, siaddr->sierr, SIERR_BITS); } else sitab.b_active = 0; siaddr->sicnr = SI_RESET; if(dualsi) getsi(); siaddr->sicnr = SI_IE; sicc[unit] = -1; } if(dualsi) SIADDR->siscr = 0; if (sitab.b_active) { sitab.b_active = 0; sitab.b_errcnt = 0; sitab.b_actf = dp->b_forw; dp->b_active = 0; dp->b_actf = bp->av_forw; bp->b_resid = ~siaddr->siwcr; if (bp->b_resid == 0xffff) bp->b_resid = 0; bp->b_resid <<= 1; iodone(bp); if (dp->b_actf) siustart(unit); } } for (unit = 0; unit < NSI; unit++) { ss = (ssr >> unit*4) & 017; if (ss & (SISSR_BUSY|SISSR_ERR)) { harderr(bp, "si"); printf("ssr=%b err=%b\n", ssr, SISSR_BITS, siaddr->sierr, SIERR_BITS); sicc[unit] = -1; siustart(unit); } else if (ss & SISSR_DONE) siustart(unit); } sistart(); } #ifdef SI_DUMP /* * Dump routine for SI 9500 * Dumps from dumplo to end of memory/end of disk section for minor(dev). */ #define DBSIZE 16 /* number of blocks to write */ sidump(dev) dev_t dev; { register struct sidevice *siaddr = SIADDR; daddr_t bn, dumpsize; long paddr; register count; register struct ubmap *ubp; int cn, tn, sn, unit; unit = minor(dev) >> 3; if ((bdevsw[major(dev)].d_strategy != sistrategy) /* paranoia */ || unit > NSI) return(EINVAL); dumpsize = rm5_sizes[dev & 07].nblocks; if ((dumplo < 0) || (dumplo >= dumpsize)) return(EINVAL); dumpsize -= dumplo; /* * reset the 9500 */ siaddr->sicnr = SI_RESET; ubp = &UBMAP[0]; for (paddr = 0L; dumpsize > 0; dumpsize -= count) { count = dumpsize>DBSIZE? DBSIZE: dumpsize; bn = dumplo + (paddr >> PGSHIFT); cn = (bn/(SI_NSECT*SI_NTRAC)) + rm5_sizes[minor(dev)&07].cyloff; sn = bn % (SI_NSECT * SI_NTRAC); tn = sn / SI_NSECT; sn = sn % SI_NSECT; if(dualsi) getsi(); siaddr->sipcr = (unit << 10) | cn; siaddr->sihsr = (tn << 5) + sn; siaddr->siwcr = count << (PGSHIFT-1); if (ubmap) { ubp->ub_lo = loint(paddr); ubp->ub_hi = hiint(paddr); siaddr->simar = 0; siaddr->sicnr = SI_WRITE | SI_GO; } else { siaddr->simar = loint(paddr); siaddr->sicnr = SI_WRITE|SI_GO|((paddr >> 8)&(03 << 4)); } while (!(siaddr->sicnr & SI_DONE)) ; if (siaddr->sierr & SIERR_ERR) { if (siaddr->sierr & SIERR_TIMO) return(0); /* made it to end of memory */ return(EIO); } paddr += (DBSIZE << PGSHIFT); } return(0); /* filled disk minor dev */ } #endif SI_DUMP getsi() { register struct sidevice *siaddr = SIADDR; while(!(siaddr->siscr & 0200)) { siaddr->sicnr = SI_RESET; siaddr->siscr = 1; } } /* * Simple minded but effective. Likely none of these are still around or in use. */ daddr_t sisize(dev) dev_t dev; { return(rm5_sizes[dev & 07].nblocks); } #endif NSI sn + SI_NSECT) % SI_NSECT; if (sicc[unit] == cn) goto done; search: siaddr->sisar = (unit << 10) | cn; if(dualsi) SIADDR->siscr = 0; sicc[unit] = cn; #ifdef UCB_METER /* * Mark unit busy for iostat. */ if (si_dkn >= 0) { int dkn = si_dkn + unit; dk_busy |= 1<sicnr = SI_RESET; ubp = &UBMAP[0]; for (paddr = 0L; dumpsize > 0; dumsys/pdpuba/rlreg.h 444 0 12 5726 5005450215 7411 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)rlreg.h 1.1 (2.10BSD Berkeley) 12/1/86 */ struct rldevice { short rlcs; caddr_t rlba; short rlda; short rlmp; short rlbae; }; /* bits in rlcs */ #define RL_CERR 0100000 /* composite error */ #define RL_DRE 0040000 /* drive error */ #define RL_NXM 0020000 /* nonexistent memory */ #define RL_DLHNF 0010000 /* data late or header not found */ #define RL_CRC 0004000 /* data crc or header check or write check */ #define RL_OPI 0002000 /* operation incomplete */ /* bits 9-8 are drive select */ #define RL_CRDY 0000200 /* controller ready */ #define RL_IE 0000100 /* interrupt enable */ /* bits 5-4 are the UNIBUS address extension bits */ /* bits 3-0 is the function code */ #define RL_HARDERR (RL_NXM|RL_DLHNF|RL_CRC|RL_OPI) /* commands */ #define RL_NOP 0000000 /* no operation */ #define RL_WCHK 0000002 /* write check data */ #define RL_GETSTATUS 0000004 /* get status */ #define RL_SEEK 0000006 /* seek */ #define RL_RHDR 0000010 /* read header */ #define RL_WCOM 0000012 /* write data */ #define RL_RCOM 0000014 /* read data */ #define RL_RWHCHK 0000016 /* read data without header check */ #define RL_BITS \ "\10\20CERR\17DRE\16NXM\15DLHNF\14CRC\13OPI\10CRDY\7IE" /* bits in rlda: just be thankful there's a one to one correspondence */ #define RLDA_RW_HSEL 0000100 /* head select during read or write */ #define RLDA_SEEK_HSEL 0000020 /* head select during seek*/ #define RLDA_RESET 0000011 /* reset during get status */ #define RLDA_SEEKHI 0000005 /* seek to higher address */ #define RLDA_SEEKLO 0000001 /* seek to lower address */ #define RLDA_GS 0000003 /* get status */ #define RLDA_BITS \ "\10\7RW_HSEL\5SEEK_HSEL\4GS_RESET\3SEEK_DIR" /* bits in rlmp */ #define RLMP_WDE 0100000 /* write data error */ #define RLMP_HCE 0040000 /* head current error */ #define RLMP_WLE 0020000 /* write lock */ #define RLMP_STIMO 0010000 /* seek timeout */ #define RLMP_SPE 0004000 /* spin error */ #define RLMP_WGE 0002000 /* write gate error */ #define RLMP_VCHK 0001000 /* volume check */ #define RLMP_DSE 0000400 /* drive select error */ #define RLMP_DTYP 0000200 /* drive type: 0 == RL01, 1 == RL02 */ #define RLMP_HSEL 0000100 /* head select */ #define RLMP_CO 0000040 /* cover open */ #define RLMP_HO 0000020 /* heads out */ #define RLMP_BH 0000010 /* brush home */ /* bits 2-0 are the state */ /* status bits */ #define RLMP_LOAD 0000000 /* load cartridge */ #define RLMP_SU 0000001 /* spin up */ #define RLMP_BC 0000002 /* brush cycle */ #define RLMP_LH 0000003 /* load heads */ #define RLMP_SEEK 0000004 /* seek */ #define RLMP_LCKON 0000005 /* lock on */ #define RLMP_UH 0000006 /* unload heads */ #define RLMP_SD 0000007 /* spin down */ #define RLMP_BITS \ "\10\20WDE\17HCE\16WLE\15STIMO\14SPE\13WGE\12VCHK\11DSE\10DTYP\ \7HSEL\6CO\5HO\4BH" A_RW_HSEL 0000100 /* head select during rsys/pdpuba/sireg.h 444 0 12 3541 4001144701 7373 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)sireg.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * Definitions for Systems Industries 9500 controller. */ /* * Controller registers and bits */ struct sidevice { short sicnr; /* control register */ short siwcr; /* word count register */ short sipcr; /* port/cylinder address register */ short sihsr; /* head/sector address register */ caddr_t simar; /* UNIBUS memory address register */ short sierr; /* error register */ short sissr; /* seek status register */ short sisar; /* seek address register */ short sidbr; /* data buffer register (unused) */ short sicom; /* communications register */ short siscr; /* shared computer option register */ }; /* Other bits of sicnr */ #define SI_OFP 0040000 /* offset+ */ #define SI_OFM 0020000 /* offset- */ #define SI_DONE 0000200 /* done */ #define SI_IE 0000100 /* interrupt enable */ #define SI_READ 0000004 /* read command */ #define SI_WRITE 0000002 /* write command */ #define SI_GO 0000001 #define SI_RESET 0000000 /* logic master clear */ #define SI_BITS \ "\10\10DONE\7IE\3READ\2WRITE\1GO" /* sierr */ #define SIERR_ERR 0100000 /* error */ #define SIERR_CNT 0140000 /* contention error */ #define SIERR_TIMO 0020000 /* timeout error */ #define SIERR_BITS \ "\10\20ERR\17CNT\16TMO\15SEL\14FLT\13WLK\12BSE\11FMT\10SKI\ \7AVE\6CRC\5VFY\4TMG\2OSE\1OSC" /* sissr */ #define SISSR_DONE 010 /* Seek complete */ #define SISSR_ERR 004 /* Hardware seek error */ #define SISSR_BUSY 002 /* Busy error */ #define SISSR_NRDY 001 /* Not ready to seek */ #define SISSR_BITS \ "\10\20DONE4\17ERR4\16BUSY4\15NRDY4\ \14DONE3\13ERR3\12BUSY3\11NRDY3\ \10DONE2\7ERR2\6BUSY2\5NRDY2\ \4DONE1\3ERR1\2BUSY1\1NRDY1" * search complete */ /* bit 12 is unused */ #define RKCS_INHBA 0004000 /* inhibit bus address increment */ #define RKCS_FMT 0002000 /* format */ /* bit 9 is sys/pdpuba/tmreg.h 444 0 12 4760 4302663051 7414 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)tmreg.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * TM11 controller registers */ struct tmdevice { u_short tmer; /* error register, per drive */ u_short tmcs; /* control-status register */ short tmbc; /* byte/frame count */ caddr_t tmba; /* address */ short tmdb; /* data buffer */ short tmrd; /* read lines */ short tmmr; /* maintenance register */ }; #define b_repcnt b_bcount #define b_command b_resid /* bits in tmcs */ #define TM_GO 0000001 #define TM_OFFL 0000000 /* offline */ #define TM_RCOM 0000002 /* read */ #define TM_WCOM 0000004 /* write */ #define TM_WEOF 0000006 /* write-eof */ #define TM_SFORW 0000010 /* space forward */ #define TM_SREV 0000012 /* space backwards */ #define TM_WIRG 0000014 /* write with xtra interrecord gap */ #define TM_REW 0000016 /* rewind */ #define TM_SENSE TM_IE /* sense (internal to driver) */ /* TM_SENSE is a pseudo-op used to get tape status */ #define TM_IE 0000100 /* interrupt enable */ #define TM_CUR 0000200 /* control unit is ready */ #define TM_DCLR 0010000 /* drive clear */ #define TM_D800 0060000 /* select 800 bpi density */ #define TM_D1600 0000000 /* 1600 bpi (AVIV only) */ #define TM_D6250 0020000 /* 6250 bpi (AVIV only) */ #define TM_ERR 0100000 /* drive error summary */ /* bits in tmer */ #define TMER_ILC 0100000 /* illegal command */ #define TMER_EOF 0040000 /* end of file */ #define TMER_CRE 0020000 /* cyclic redundancy error */ #define TMER_PAE 0010000 /* parity error */ #define TMER_BGL 0004000 /* bus grant late */ #define TMER_EOT 0002000 /* at end of tape */ #define TMER_RLE 0001000 /* record length error */ #define TMER_BTE 0000400 /* bad tape error */ #define TMER_NXM 0000200 /* non-existent memory */ #define TMER_SELR 0000100 /* tape unit properly selected */ #define TMER_BOT 0000040 /* at beginning of tape */ #define TMER_CH7 0000020 /* 7 channel tape */ #define TMER_SDWN 0000010 /* gap settling down */ #define TMER_WRL 0000004 /* tape unit write protected */ #define TMER_RWS 0000002 /* tape unit rewinding */ #define TMER_TUR 0000001 /* tape unit ready */ #define TMER_BITS \ "\10\20ILC\17EOF\16CRE\15PAE\14BGL\13EOT\12RLE\11BTE\10NXM\ \7SELR\6BOT\5CH7\4SDWN\3WRL\2RWS\1TUR" #define TMER_HARD (TMER_ILC|TMER_EOT|TMER_NXM) #define TMER_SOFT (TMER_CRE|TMER_PAE|TMER_BGL|TMER_RLE|TMER_BTE) efine RKCS_WCHK sys/pdpuba/tsreg.h 444 0 12 14166 4001144717 7442 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)tsreg.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * TS11 controller registers */ struct tsdevice { u_short tsdb; /* data buffer */ u_short tssr; /* status register */ }; /* Bits in (UNIBUS) status register */ #define TS_SC 0100000 /* special condition (error) */ #define TS_UPE 0040000 /* UNIBUS parity error */ #define TS_SPE 0020000 /* serial bus parity error */ #define TS_RMR 0010000 /* register modification refused */ #define TS_NXM 0004000 /* nonexistent memory */ #define TS_NBA 0002000 /* need buffer address */ #define TS_XMEM 0001400 /* UNIBUS xmem bits */ #define TS_SSR 0000200 /* subsytem ready */ #define TS_OFL 0000100 /* off-line */ #define TS_FTC 0000060 /* fatal termination class mask */ #define TS_TC 0000016 /* termination class mask */ /* termination class */ #define TS_SUCC 0000000 /* successful termination */ #define TS_ATTN 0000002 /* attention */ #define TS_ALERT 0000004 /* tape status alert */ #define TS_REJECT 0000006 /* function reject */ #define TS_RECOV 0000010 /* recoverable error */ #define TS_RECNM 0000012 /* recoverable error, no tape motion */ #define TS_UNREC 0000014 /* unrecoverable error */ #define TS_FATAL 0000016 /* fatal error */ #define TSSR_BITS \ "\10\20SC\17UPE\16SPE\15RMR\14NXM\13NBA\12A17\11A16\10SSR\ \7OFL\6FC1\5FC0\4TC2\3TC1\2TC0\1-" #define b_repcnt b_bcount #define b_command b_resid /* status message */ struct ts_sts { u_short s_sts; /* packet header */ u_short s_len; /* packet length */ u_short s_rbpcr; /* residual frame count */ u_short s_xs0; /* extended status 0 - 3 */ u_short s_xs1; u_short s_xs2; u_short s_xs3; }; /* Error codes in xstat 0 */ #define TS_TMK 0100000 /* tape mark detected */ #define TS_RLS 0040000 /* record length short */ #define TS_LET 0020000 /* logical end of tape */ #define TS_RLL 0010000 /* record length long */ #define TS_WLE 0004000 /* write lock error */ #define TS_NEF 0002000 /* non-executable function */ #define TS_ILC 0001000 /* illegal command */ #define TS_ILA 0000400 /* illegal address */ #define TS_MOT 0000200 /* capstan is moving */ #define TS_ONL 0000100 /* on-line */ #define TS_IES 0000040 /* interrupt enable status */ #define TS_VCK 0000020 /* volume check */ #define TS_PED 0000010 /* phase-encoded drive */ #define TS_WLK 0000004 /* write locked */ #define TS_BOT 0000002 /* beginning of tape */ #define TS_EOT 0000001 /* end of tape */ #define TSXS0_BITS \ "\10\20TMK\17RLS\16LET\15RLL\14WLE\13NEF\12ILC\11ILA\10MOT\ \7ONL\6IES\5VCK\4PED\3WLK\2BOT\1EOT" /* Error codes in xstat 1 */ #define TS_DLT 0100000 /* data late */ #define TS_COR 0020000 /* correctable data */ #define TS_CRS 0010000 /* crease detected */ #define TS_TIG 0004000 /* trash in the gap */ #define TS_DBF 0002000 /* deskew buffer full */ #define TS_SCK 0001000 /* speed check */ #define TS_IPR 0000200 /* invalid preamble */ #define TS_SYN 0000100 /* synchronization failure */ #define TS_IPO 0000040 /* invalid postamble */ #define TS_IED 0000020 /* invalid end of data */ #define TS_POS 0000010 /* postamble short */ #define TS_POL 0000004 /* postamble long */ #define TS_UNC 0000002 /* uncorrectable data */ #define TS_MTE 0000001 /* multitrack error */ #define TSXS1_BITS \ "\10\20DLT\17-\16COR\15CRS\14TIG\13DBF\12SCK\11-\10IPR\ \7SYN\6IPO\5IED\4POS\3POL\2UNC\1MTE" /* Error codes in xstat 2 */ #define TS_OPM 0100000 /* operation in progress */ #define TS_SIP 0040000 /* silo parity error */ #define TS_BPE 0020000 /* serial bus parity error */ #define TS_CAF 0010000 /* capstan acceleration failure */ #define TS_WCF 0002000 /* write card fail */ #define TS_DTP 0000400 /* dead track parity */ #define TS_DT 0000377 /* dead tracks */ #define TSXS2_BITS \ "\10\20OPM\17SIP\16BPE\15CAF\14-\13WCF\12-\11DTP" /* Error codes in xstat 3 */ #define TS_MEC 0177400 /* microdiagnostic error code */ #define TS_LMX 0000200 /* limit exceeded */ #define TS_OPI 0000100 /* operation incomplete */ #define TS_REV 0000040 /* reverse */ #define TS_CRF 0000020 /* capstan response fail */ #define TS_DCK 0000010 /* density check */ #define TS_NOI 0000004 /* noise record */ #define TS_LXS 0000002 /* limit exceeded statically */ #define TS_RIB 0000001 /* reverse into BOT */ #define TSXS3_BITS \ "\10\10LMX\7OPI\6REV\5CRF\4DCK\3NOI\2LXS\1RIB" /* command message */ struct ts_cmd { u_short c_cmd; /* command */ u_short c_loba; /* low order buffer address */ u_short c_hiba; /* high order buffer address */ #define c_repcnt c_loba u_short c_size; /* byte count */ }; /* commands and command bits */ #define TS_ACK 0100000 /* ack - release command packet */ #define TS_CVC 0040000 /* clear volume check */ #define TS_OPP 0020000 /* opposite. reverse recovery */ #define TS_SWB 0010000 /* swap bytes */ #define TS_IE 0000200 /* interrupt enable */ #define TS_RCOM 0000001 /* read */ #define TS_REREAD 0001001 /* read data retry */ #define TS_SETCHR 0000004 /* set characteristics */ #define TS_WCOM 0000005 /* write */ #define TS_REWRITE 0001005 /* write data retry */ #define TS_RETRY 0001000 /* retry bit for read and write */ #define TS_SFORW 0000010 /* forward space record */ #define TS_SREV 0000410 /* reverse space record */ #define TS_SFORWF 0001010 /* forward space file */ #define TS_SREVF 0001410 /* reverse space file */ #define TS_REW 0002010 /* rewind */ #define TS_OFFL 0000412 /* unload */ #define TS_WEOF 0000011 /* write tape mark */ #define TS_INIT 0000013 /* initialize */ #define TS_SENSE 0000017 /* get status */ /* characteristics data */ struct ts_char { u_short char_bptr; /* low word address of status packet */ u_short char_bae; /* bus address extension bits */ u_short char_size; /* its size */ u_short char_mode; /* characteristics */ }; /* characteristics */ #define TS_ESS 0200 /* enable space files stop */ #define TS_ENB 0100 /* enable space files stop at bot */ #define TS_EAI 0040 /* enable attention interrupt */ #define TS_ERI 0020 /* enable status buffer release interrupt */ while (!(siaddr->sicnr & SI_DONE)) ; if (siaddr->sierr & SIERR_ERR) { if (siaddr->sierr & SIERR_TIMO) return(0); /* made it to end of memory */ return(EIO); } paddr += (DBSIZE << PGSHIFT); } return(0); /* filled disk minor dev */ } #endif SI_DUMP getsi() { register struct sidevice *siaddr = SIADDR; while(!(siaddr->siscr & 0200)) { siaddr->sicnr = SI_RESET; siasys/pdpuba/ubavar.h 444 0 12 3526 4116703623 7560 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ubavar.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * Per ``device'' structure. * * This structure contains all the information necessary to run * a unibus device such as a dz or a dh. It also contains information * for slaves of unibus controllers as to which device on the slave * this is. A flags field here can also be given in the system specification * and is used to tell which dz lines are hard wired or other device * specific parameters. */ struct uba_device { struct uba_driver *ui_driver; short ui_unit; /* unit number on the system */ short ui_ubanum; /* the uba it is on */ caddr_t ui_addr; /* address of device in i/o space */ long ui_flags; /* parameter from system specification */ short ui_alive; /* device exists */ }; /* * Per-driver structure. * * Each unibus driver defines entries for a set of routines * as well as an array of types which are acceptable to it. * * This is silly; clean it up. KB */ struct uba_driver { int (*ud_probe)(); /* see if a driver is really there */ int (*ud_slave)(); /* see if a slave is there */ int (*ud_attach)(); /* setup driver for a slave */ int (*ud_dgo)(); /* fill csr/ba to start transfer */ u_short *ud_addr; /* device csr addresses */ char *ud_dname; /* name of a device */ struct uba_device **ud_dinfo; /* backpointers to ubdinit structs */ }; /* * Flags to UBA map/bdp allocation routines */ #define UBA_NEEDBDP 0x01 /* transfer needs a bdp */ #define UBA_CANTWAIT 0x02 /* don't block me */ #define UBA_NEED16 0x04 /* need 16 bit addresses only */ #define UBA_HAVEBDP 0x08 /* use bdp specified in high bits */ ubadr_t uballoc(); #define ubarelse(a,b) ubadr_t ubmalloc(); 0001 /* reverse into BOT */ #define TSXS3_BITS \ "\10\10LMX\7OPI\6REV\5CRF\4DCK\3NOI\2LXS\1RIB" /* command message */ struct ts_cmd { u_short c_cmd; /* command */ sys/pdpuba/br.c 644 0 12 24636 5743411121 6721 /* * BR disk driver * modified from the UNIX RP03 driver for BR disk drive -JM * 11/11/84 - Added dump routine for taking 2.9 crash dumps in swap. -SMS * 9/28/85 - Use brreg.h so as to look more like a 2.9 disk handler. -SMS * 2/16/86 - Rewrite! Drop the bropen, brclose and brgch functions. Do * initialization on a per drive basis rather than controller. * The bropen and brclose functions were only used to perform * the init'ing of a drive, and there was a problem in single * user mode where a 'umount' could close the device before all * data for that filesystem was written out thereby giving offline * errors and causing corruption of the disc. Also defined a * disc slice that encompassed the whole drive for ease in copying, * several other mods made because this was done. Overall, several * pages of code were removed. -SMS * Just discovered that bropen() and brclose() were defined as * nulldev() in c.c! Wasted code all this time! The offline errors * observed were a result of entry into brstrategy() during a * 'umount' when bropen() had never been called in the first place!!! * 12/6/87 - Changes to run under 2.10bsd. Still single controller only. * Considering we don't make the controller any more that's fairly * safe to assume. Partitions drastically changed to allow room * on T300 and T200 to hold the source distribution. * Autoconfigure logic finally added though. -SMS * 2/17/89 - For 2.10.1BSD added old 2.9BSD /usr,/userfiles, and /minkie * partitions as partitions 'e', 'f', and 'g' as an aid in * converting the systems. BE CAREFUL! For T300 only. * 8/4/89 - Use the log() function to record soft errors. * 9/22/91 - remove read and write entry - use common raw read/write routine. * 12/23/92 - add the partition size routine. * 1/2/93 - remove unibus map ifdefs, the run time check using 'ubmap' is * sufficient and does the right thing. * 1995/04/13 - change reference to dkunit. */ #include "br.h" #if NBR > 0 #include "param.h" #include "../machine/seg.h" #include "systm.h" #include "buf.h" #include "conf.h" #include "user.h" #include "brreg.h" #include "dk.h" #include "disklabel.h" #include "disk.h" #include "syslog.h" #include "map.h" #include "uba.h" #define BRADDR ((struct brdevice *) 0176710) #define brunit(dev) ((dev >> 3) & 7) #define SECTRK brc->sectrk #define TRKCYL brc->trkcyl struct br_char { struct br_dsz { daddr_t nblocks; int cyloff; } br_sizes[8]; int sectrk, trkcyl; } br_chars[] = { /* T300 */ 18240, 0, /* cyl 000 - 029 */ 12160, 30, /* cyl 030 - 049 */ 232256, 50, /* cyl 050 - 431 */ 232256, 432, /* cyl 432 - 813 */ 154432, 50, /* 'e' is old 2.9 'c' partition */ 154432, 304, /* 'f' is old 2.9 'd' partition */ 154432, 558, /* 'g' is old 2.9 'e' partition */ 495520, 0, /* cyl 000 - 814 */ 32, 19, /* 32 sectrk, 19 trkcyl */ /* T200 */ 18392, 0, /* cyl 000 - 043 */ 12122, 43, /* cyl 044 - 072 */ 231990, 73, /* cyl 073 - 627 */ 78166, 443, /* cyl 628 - 814 */ 0, 0, 0, 0, 0, 0, 340670, 0, /* cyl 000 - 814 */ 22, 19, /* 22 sectrk, 19 trkcyl */ /* T80 */ 18400, 0, /* cyl 000 - 114 */ 12320, 115, /* cyl 115 - 190 */ 99840, 191, /* cyl 191 - 814 */ 0, 0, 0, 0, 0, 0, 0, 0, 130300, 0, 32, 5, /* 32 sectrk, 5 trkcyl */ /* T50 */ 18260, 0, /* cyl 000 - 165 */ 12210, 166, /* cyl 166 - 276 */ 59180, 277, /* cyl 277 - 814 */ 0, 0, 0, 0, 0, 0, 0, 0, 89650, 0, 22, 5, /* 22 sectrk, 5 trkcyl */ }; /* * Define the recovery strobes and offsets in br_da */ static int br_offs[] = { 0, 0, 0, STBE, STBE, STBL, STBL, OFFP+STBL, OFFP+STBL, OFFP, OFFP, OFFP+STBE, OFFP+STBE, OFFM+STBE, OFFM+STBE, OFFP, OFFP, OFFP+STBL, OFFP+STBL, 0 }; #ifdef UCB_METER static int br_dkn = -1; #endif struct buf brtab; struct br_char *br_disk[NBR]; struct brdevice *Br_addr; brroot() { brattach((struct brdevice *)BRADDR, 0); } brattach(braddr, unit) register struct brdevice *braddr; int unit; { #ifdef UCB_METER if (br_dkn < 0) dk_alloc(&br_dkn, NBR, "br", 0L); #endif if (unit >= NBR) return(0); if (braddr && (fioword(braddr) != -1)) { Br_addr = braddr; return(1); } return(0); } bropen(dev, flag) dev_t dev; int flag; { register int dn = brunit(dev); if (dn >= NBR || !Br_addr) return(ENXIO); if (!br_disk[dn]) brinit(dn); if (!br_disk[dn]) return(EIO); return(0); } brstrategy(bp) register struct buf *bp; { register struct buf *dp; register int unit; struct br_char *brc; struct br_dsz *brz; long sz; int drive, s; unit = bp->b_dev & 07; drive = brunit(bp->b_dev); if (!(brc = br_disk[drive])) { brinit(drive); if (!(brc = br_disk[drive])) { bp->b_error = ENODEV; bp->b_flags |= B_ERROR; iodone(bp); return; } } brz = &brc->br_sizes[unit]; sz = (bp->b_bcount + 511L) >> 9; if (bp->b_blkno == brz->nblocks) { bp->b_resid = bp->b_bcount; iodone(bp); return; } if (bp->b_blkno + sz > brz->nblocks) { bp->b_error = EINVAL; bp->b_flags |= B_ERROR; iodone(bp); return; } if (Br_addr->brae >= 0) mapalloc(bp); bp->b_cylin = bp->b_blkno/(SECTRK*TRKCYL) + brz->cyloff; s = splbio(); dp = &brtab; disksort(dp, bp); if (dp->b_active == NULL) brstart(); splx(s); } static brstart() { register struct buf *bp; register int unit; int com,cn,tn,sn,dn; daddr_t bn; struct br_char *brc; struct br_dsz *brz; if ((bp = brtab.b_actf) == NULL) return; Br_addr->brds = -1; brtab.b_active++; if (!(Br_addr->brcs.w & BR_RDY)) { timeout(brstart, 0, 4); return; } unit = bp->b_dev & 07; dn = brunit(bp->b_dev); if (!(brc = br_disk[dn])) { brinit(dn); if (!(brc = br_disk[dn])) { bp->b_flags |= B_ERROR; brdone(bp); return; } } brz = &brc->br_sizes[unit]; bn = bp->b_blkno; cn = bn/(SECTRK*TRKCYL) + brz->cyloff; sn = bn%(SECTRK*TRKCYL); tn = sn/SECTRK; sn = sn%SECTRK; if (Br_addr->brae < 0) Br_addr->brae = bp->b_xmem; Br_addr->brcs.w = (dn<<8); Br_addr->brda = (tn<<8) | sn; cn |= br_offs[brtab.b_errcnt]; Br_addr->brca = cn; Br_addr->brba = bp->b_un.b_addr; Br_addr->brwc = -(bp->b_bcount>>1); com = ((bp->b_xmem&3)<<4) | BR_IDE | BR_GO; if (bp->b_flags & B_READ) com |= BR_RCOM; else com |= BR_WCOM; Br_addr->brcs.w |= com; #ifdef UCB_METER if (br_dkn >= 0) { dk_busy |= 1 << (br_dkn + dn); dk_xfer[br_dkn + dn]++; dk_seek[br_dkn + dn]++; dk_wds[br_dkn + dn] += (bp->b_bcount >> 6); } #endif } static brinit(drive) register int drive; { register int ctr = 0; register struct br_char **br = &br_disk[drive]; /* * Clear the drive's entry in br_disk. Select the unit. If the * unit exists, switch on the spindle type. and set the br_disk * table entry */ *br = (struct br_char *)NULL; do { Br_addr->brcs.w = (drive << 8) | BR_HSEEK | BR_GO; while ((Br_addr->brcs.w & BR_RDY) == 0 && --ctr) ; } while (Br_addr->brer & BRER_SUBUSY); if ((Br_addr->brcs.w & BR_HE) == 0) { switch (Br_addr->brae & AE_DTYP) { case AE_T300: *br = &br_chars[0]; break; case AE_T200: *br = &br_chars[1]; break; case AE_T80: *br = &br_chars[2]; break; case AE_T50: *br = &br_chars[3]; break; } #ifdef UCB_METER if (br_dkn >= 0) dk_wps[br_dkn + drive] = (long)(*br)->sectrk * (60L * 256L); #endif } } brintr(dev) int dev; { register struct buf *bp; register int ctr = 0; struct brdevice brsave; if (brtab.b_active == NULL) return; brsave = *Br_addr; bp = brtab.b_actf; if (!(brsave.brcs.w & BR_RDY)) return; #ifdef UCB_METER if (br_dkn >= 0) dk_busy &= ~(1<<(br_dkn + dev)); #endif if (brsave.brcs.w < 0) { if (brsave.brer & BRER_SUBUSY) { timeout(brstart, 0, 5); return; } if (brsave.brds & (BRDS_SUFU|BRDS_SUSI|BRDS_HNF)) { Br_addr->brcs.c[0] = BR_HSEEK|BR_GO; while (((Br_addr->brds&BRDS_SURDY) == 0) && --ctr); } Br_addr->brcs.w = BR_IDLE|BR_GO; ctr = 0; while (((Br_addr->brcs.w&BR_RDY) == 0) && --ctr) ; if (brtab.b_errcnt == 0) { log(LOG_WARNING,"br%d%c ds:%b er:%b cs:%b wc:%o ba:%o ca:%o da:%o bae:%o\n", dkunit(bp->b_dev), 'a'+ dkpart(bp->b_dev), brsave.brds, BRDS_BITS, brsave.brer, BRER_BITS, brsave.brcs.w, BR_BITS, brsave.brwc,brsave.brba, brsave.brca, brsave.brda, brsave.brae); } brtab.b_errcnt++; if (brtab.b_errcnt < 20) { brstart(); return; } harderr(bp,"br"); bp->b_flags |= B_ERROR; } brdone(bp); } static brdone (bp) register struct buf *bp; { brtab.b_active = NULL; brtab.b_errcnt = 0; brtab.b_actf = bp->av_forw; bp->b_resid = 0; iodone(bp); brstart(); } #ifdef BR_DUMP /* * Dump routine. Dumps from dumplo to end of memory/end of disk section for * minor(dev). */ #define DBSIZE 16 /* unit of transfer, same number */ brdump(dev) dev_t dev; { struct br_char *brc; struct ubmap *ubp; daddr_t bn, dumpsize; long paddr; int count, cyl, dn, cn, tn, sn, unit, com; unit = dev & 07; dn = brunit(dev); if ((bdevsw[major(dev)].d_strategy != brstrategy) || dn >= NBR) return(EINVAL); if (!Br_addr || !(brc = br_disk[dn])) return(ENXIO); dumpsize = brc->br_sizes[unit].nblocks; cyl = brc->br_sizes[unit].cyloff; if ((dumplo < 0) || (dumplo >= dumpsize)) return(EINVAL); dumpsize -= dumplo; while (!(Br_addr->brcs.w & BR_RDY)); ubp = &UBMAP[0]; for (paddr = 0L; dumpsize > 0; dumpsize -= count) { count = dumpsize > DBSIZE ? DBSIZE : dumpsize; bn = dumplo + (paddr >> PGSHIFT); cn = (bn / (SECTRK * TRKCYL)) + cyl; sn = bn % (SECTRK * TRKCYL); tn = sn / SECTRK; sn = sn % SECTRK; Br_addr->brca = cn; Br_addr->brda = (tn << 8) | sn; Br_addr->brwc = -(count << (PGSHIFT-1)); com = (dn << 8) | BR_GO | BR_WCOM; if (ubmap && Br_addr->brae >= 0) { ubp->ub_lo = loint(paddr); ubp->ub_hi = hiint(paddr); Br_addr->brba = 0; } else { Br_addr->brba = (caddr_t)loint(paddr); Br_addr->brae = hiint(paddr); com |= ((hiint(paddr) & 3) << 4); } Br_addr->brcs.w = com; while (!(Br_addr->brcs.w & BR_RDY)); if (Br_addr->brcs.w < 0) { if (Br_addr->brer & BRER_NXME) return(0); /* end of memory */ return(EIO); } paddr += (DBSIZE << PGSHIFT); } return(0); /* filled disk */ } #endif /* BR_DUMP */ /* * Assumes the 'open' entry point has been called to validate the unit * number and fill in the drive type structure. */ daddr_t brsize(dev) register dev_t dev; { register struct br_char *brc; brc = br_disk[brunit(dev)]; return(brc->br_sizes[dev & 7].nblocks); } #endif /* NBR */ hex dump */ { register char *p = (char *)mp; register int i; for (i = mp->me_header.ra_msgsys/pdpuba/dhv.c 644 0 12 40564 5667262000 7102 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dhv.c 2.1 (2.11BSD Berkeley) 11/29/94 */ /* * ported to 2.11BSD (uio logic added) 12/22/91 - SMS * based on dh.c 6.3 84/03/15 * and on dmf.c 6.2 84/02/16 * * REAL(tm) dhv driver derived from dhu.c by * Steve Nuchia at Baylor 22 November 1987 * steve@eyeball.bcm.tmc.edu * * Dave Johnson, Brown University Computer Science * ddj%brown@csnet-relay */ #include "dhv.h" #if NDHV > 0 /* * DHV-11 driver */ #include "param.h" #include "dhvreg.h" #include "conf.h" #include "user.h" #include "file.h" #include "proc.h" #include "ioctl.h" #include "tty.h" #include "ttychars.h" #include "clist.h" #include "map.h" #include "uba.h" #include "ubavar.h" #include "systm.h" struct uba_device dhvinfo[NDHV]; #define NDHVLINE (NDHV*8) #define UNIT(x) (minor(x) & 077) #define CDWAIT(x) (!(minor(x) & 0200)) #define HWFLOW(x) (minor(x) & 0100) #define ISPEED B9600 #define IFLAGS (EVENP|ODDP|ECHO) /* * DHV's don't have a very good interrupt facility - you get an * interrupt when the first character is put into the silo * and nothing after that. Previously an attempt was made to * delay a couple of clock ticks with receive interrupts disabled. * * Unfortunately the code was ineffective because the number of ticks * to delay was decremented if a full (90%) or overrun silo was encountered. * After two such events the driver was back in interrupt per character * mode thus wasting/negating the whole effort. */ char dhv_hwxon[NDHVLINE]; /* hardware xon/xoff enabled, per line */ /* * Baud rates: no 50, 200, or 38400 baud; all other rates are from "Group B". * EXTA => 19200 baud * EXTB => 2000 baud */ char dhv_speeds[] = { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 8, 10, 11, 13, 14, 9 }; struct tty dhv_tty[NDHVLINE]; int ndhv = NDHVLINE; int dhvact; /* mask of active dhv's */ int dhv_rcnt[16]; int dhvstart(), ttrstrt(); long dhvmctl(),dmtodhv(); #if defined(UCB_CLIST) extern ubadr_t clstaddr; #define cpaddr(x) (clstaddr + (ubadr_t)((x) - (char *)cfree)) #else #define cpaddr(x) ((u_short)(x)) #endif /* * Routine called to attach a dhv. */ dhvattach(addr,unit) register caddr_t addr; register u_int unit; { if (addr && unit < NDHV && !dhvinfo[unit].ui_addr) { dhvinfo[unit].ui_unit = unit; dhvinfo[unit].ui_addr = addr; dhvinfo[unit].ui_alive = 1; return (1); } return (0); } /* * Open a DHV11 line, mapping the clist onto the uba if this * is the first dhv on this uba. Turn on this dhv if this is * the first use of it. */ /*ARGSUSED*/ dhvopen(dev, flag) dev_t dev; { register struct tty *tp; register int unit, dhv; register struct dhvdevice *addr; register struct uba_device *ui; int i, s; unit = UNIT(dev); dhv = unit >> 3; if (unit >= NDHVLINE || (ui = &dhvinfo[dhv])->ui_alive == 0) return (ENXIO); tp = &dhv_tty[unit]; if (tp->t_state & TS_XCLUDE && u.u_uid != 0) return (EBUSY); addr = (struct dhvdevice *)ui->ui_addr; tp->t_addr = (caddr_t)addr; tp->t_oproc = dhvstart; if ((dhvact&(1<dhvcsr = DHV_SELECT(0) | DHV_IE; dhvact |= (1<t_state&TS_ISOPEN) && tp->t_dev == dev ) { i = (*linesw[tp->t_line].l_open)(dev, tp); (void) splx(s); return(i); } /* * Wait for carrier, then process line discipline specific open. */ while ( (tp->t_state&TS_ISOPEN) == 0 || tp->t_dev != dev ) { if ( tp->t_state & TS_ISOPEN ) { sleep ( (caddr_t)&tp->t_state, TTIPRI ); continue; } tp->t_dev = dev; addr->dhvcsr = DHV_SELECT(dev) | DHV_IE; if ( addr->dhvstat & DHV_ST_DCD ) tp->t_state |= TS_CARR_ON; else tp->t_state &= ~TS_CARR_ON; if ( CDWAIT(dev) && (tp->t_state & TS_CARR_ON) == 0 || HWFLOW(dev) && (addr->dhvstat & DHV_ST_DSR) == 0 ) { dhvmctl ( dev, (long)DHV_ON, DMSET ); tp->t_state |= TS_WOPEN; sleep ( (caddr_t)&tp->t_rawq, TTIPRI ); continue; } dhvmctl ( dev, (long)DHV_ON, DMSET ); break; } if ( !(tp->t_state&TS_ISOPEN) ) { ttychars(tp); tp->t_state |= TS_HUPCLS; tp->t_ispeed = ISPEED; tp->t_ospeed = ISPEED; tp->t_flags = IFLAGS | (HWFLOW(dev) ? TANDEM : 0); tp->t_dev = dev; } if ( !CDWAIT(dev) ) tp->t_state |= TS_CARR_ON; dhvparam(unit); i = (*linesw[tp->t_line].l_open)(dev, tp); (void) splx(s); return ( i ); } /* * Close a DHV11 line, turning off the modem control. */ /*ARGSUSED*/ dhvclose(dev, flag) dev_t dev; int flag; { register struct tty *tp; register unit, s; unit = UNIT(dev); tp = &dhv_tty[unit]; s = spltty(); if ( !(tp->t_state & TS_ISOPEN) || tp->t_dev != dev ) return; (*linesw[tp->t_line].l_close)(tp, flag); (void) dhvmctl(unit, (long)DHV_BRK, DMBIC); (void) dhvmctl(unit, (long)DHV_OFF, DMSET); if ( CDWAIT(tp->t_dev) || (tp->t_state&(TS_HUPCLS|TS_WOPEN)) || (tp->t_state&TS_ISOPEN)==0 ) { extern int wakeup(); /* Hold DTR low for 0.5 seconds */ timeout(wakeup, (caddr_t) &tp->t_dev, LINEHZ/2); sleep((caddr_t) &tp->t_dev, PZERO); } ttyclose(tp); splx(s); wakeup ( (caddr_t) &tp->t_state ); } dhvselect ( dev, rw ) /* filter the minor device number */ dev_t dev; int rw; { return ( ttselect ( dev & ~0300, rw ) ); } dhvread(dev, uio, flag) dev_t dev; struct uio *uio; int flag; { register struct tty *tp = &dhv_tty[UNIT(dev)]; return((*linesw[tp->t_line].l_read) (tp, uio, flag)); } dhvwrite(dev, uio, flag) dev_t dev; struct uio *uio; int flag; { register struct tty *tp = &dhv_tty[UNIT(dev)]; return((*linesw[tp->t_line].l_write) (tp, uio, flag)); } /* * DHV11 receiver interrupt. */ int dhvwait; dhvrint(dhv) int dhv; { register struct tty *tp; register c; register struct dhvdevice *addr; register struct tty *tp0; register struct uba_device *ui; int line, rcnt; int overrun; ui = &dhvinfo[dhv]; if (ui->ui_alive == 0) return; addr = (struct dhvdevice *)ui->ui_addr; tp0 = &dhv_tty[dhv<<3]; /* * Loop fetching characters from the silo for this * dhv until there are no more in the silo. */ rcnt = 0; overrun = 0; while ((c = addr->dhvrbuf) & DHV_RB_VALID ) { rcnt++; line = DHV_RX_LINE(c); tp = tp0 + line; if ((c & DHV_RB_STAT) == DHV_RB_STAT) { /* * modem changed or diag info */ if (c & DHV_RB_DIAG) { if ( (c & 0xff) > 0201 ) printf ( "dhv%d: diagnostic %o\n", dhv, c & 0xff ); continue; } if ( CDWAIT(tp->t_dev) || (tp->t_flags & MDMBUF) ) (*linesw[tp->t_line].l_modem) ( tp, (c & DHV_ST_DCD) != 0 ); if ( HWFLOW(tp->t_dev) ) { if ( c & DHV_ST_DSR ) { tp->t_state &= ~TS_TTSTOP; ttstart(tp); } else { tp->t_state |= TS_TTSTOP; dhvstop (tp, 0); } } continue; } if ((tp->t_state&TS_ISOPEN) == 0) { wakeup((caddr_t)&tp->t_rawq); continue; } if ( c & (DHV_RB_PE|DHV_RB_DO|DHV_RB_FE) ) { if (c & DHV_RB_PE) if ((tp->t_flags&(EVENP|ODDP)) == EVENP || (tp->t_flags&(EVENP|ODDP)) == ODDP) continue; if ( (c & DHV_RB_DO) && !overrun ) { overrun = 1; /* bit-bucket the que to free the cpu */ while ( addr->dhvrbuf & DHV_RB_VALID ); break; } if (c & DHV_RB_FE) /* * At framing error (break) generate * an interrupt (in cooked/cbreak mode) * or let the char through in RAW mode * for autobauding getty's. */ if ( !(tp->t_flags&RAW) ) c = tp->t_intrc; } #if NBK > 0 if (tp->t_line == NETLDISC) { c &= 0x7f; BKINPUT(c, tp); } else #endif { if ( !(c & DHV_RB_PE) && dhv_hwxon[(dhv<<3)+line] && ((c & 0x7f) == CSTOP || (c & 0x7f) == CSTART) ) continue; (*linesw[tp->t_line].l_rint)(c, tp); } } if (overrun) printf("dhv%d: silo overflow\n", dhv); else if (rcnt) { for (line = 0; rcnt; line++) rcnt >>= 1; dhv_rcnt[line]++; #ifdef notnow /* * If 16 or less characters were processed from the silo we drop * priority to 4 which will block further DHV interrupts but allow * clock and most disc interrupts to occur. Then a small (~ 1ms) * delay is done and the interrupt dismissed. Best that can be done * since delaying for any number of whole clock ticks seems to cause * problems. */ if (line <= 4) { c = spl4(); /* DHV is a spl4 device */ delay(1000L); /* try a 1 ms delay */ dhvwait++; splx(c); } #endif } } /* * Ioctl for DHV11. */ /*ARGSUSED*/ dhvioctl(dev, cmd, data, flag) register dev_t dev; u_int cmd; caddr_t data; { register struct tty *tp; register int unit = UNIT(dev); int error; tp = &dhv_tty[unit]; error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); if (error >= 0) return (error); error = ttioctl(tp, cmd, data, flag); if (error >= 0) { if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLSET || cmd == TIOCLBIC || cmd == TIOCLBIS || cmd == TIOCSETD || cmd == TIOCSETC) dhvparam(unit); return (error); } switch (cmd) { case TIOCSBRK: (void) dhvmctl(unit, (long)DHV_BRK, DMBIS); break; case TIOCCBRK: (void) dhvmctl(unit, (long)DHV_BRK, DMBIC); break; case TIOCSDTR: (void) dhvmctl(unit, (long)DHV_DTR|DHV_RTS, DMBIS); break; case TIOCCDTR: (void) dhvmctl(unit, (long)DHV_DTR|DHV_RTS, DMBIC); break; case TIOCMSET: (void) dhvmctl(dev, dmtodhv(*(int *)data), DMSET); break; case TIOCMBIS: (void) dhvmctl(dev, dmtodhv(*(int *)data), DMBIS); break; case TIOCMBIC: (void) dhvmctl(dev, dmtodhv(*(int *)data), DMBIC); break; case TIOCMGET: *(int *)data = dhvtodm(dhvmctl(dev, 0L, DMGET)); break; default: return (ENOTTY); } return (0); } static long dmtodhv(bits) register int bits; { long b = 0; if (bits & DML_RTS) b |= DHV_RTS; if (bits & DML_DTR) b |= DHV_DTR; if (bits & DML_LE) b |= DHV_LE; return(b); } static dhvtodm(bits) long bits; { register int b = 0; if (bits & DHV_DSR) b |= DML_DSR; if (bits & DHV_RNG) b |= DML_RNG; if (bits & DHV_CAR) b |= DML_CAR; if (bits & DHV_CTS) b |= DML_CTS; if (bits & DHV_RTS) b |= DML_RTS; if (bits & DHV_DTR) b |= DML_DTR; if (bits & DHV_LE) b |= DML_LE; return(b); } /* * Set parameters from open or stty into the DHV hardware * registers. */ static dhvparam(unit) register int unit; { register struct tty *tp; register struct dhvdevice *addr; register int lpar; int s; tp = &dhv_tty[unit]; addr = (struct dhvdevice *)tp->t_addr; /* * Block interrupts so parameters will be set * before the line interrupts. */ s = spltty(); if ((tp->t_ispeed) == 0) { tp->t_state |= TS_HUPCLS; (void)dhvmctl(unit, (long)DHV_OFF, DMSET); splx(s); return; } lpar = (dhv_speeds[tp->t_ospeed]<<12) | (dhv_speeds[tp->t_ispeed]<<8); if ((tp->t_ispeed) == B134) lpar |= DHV_LP_BITS6|DHV_LP_PENABLE; else if (tp->t_flags & (RAW|L001000|LITOUT|PASS8)) lpar |= DHV_LP_BITS8; else lpar |= DHV_LP_BITS7|DHV_LP_PENABLE; if (tp->t_flags&EVENP) lpar |= DHV_LP_EPAR; if ( (tp->t_flags & EVENP) && (tp->t_flags & ODDP) ) { /* hack alert. assume "allow both" means don't care */ /* trying to make xon/xoff work with evenp+oddp */ lpar |= DHV_LP_BITS8; lpar &= ~DHV_LP_PENABLE; } if ((tp->t_ospeed) == B110) lpar |= DHV_LP_TWOSB; addr->dhvcsr = DHV_SELECT(unit) | DHV_IE; addr->dhvlpr = lpar; dhv_hwxon[unit] = !(tp->t_flags & RAW) && (tp->t_line == OTTYDISC || tp->t_line == NTTYDISC) && tp->t_stopc == CSTOP && tp->t_startc == CSTART; if ( dhv_hwxon[unit] ) addr->dhvlcr |= DHV_LC_OAUTOF; else { addr->dhvlcr &= ~DHV_LC_OAUTOF; delay(25L); /* see the dhv manual, sec 3.3.6 */ addr->dhvlcr2 |= DHV_LC2_TXEN; } splx(s); } /* * DHV11 transmitter interrupt. * Restart each line which used to be active but has * terminated transmission since the last interrupt. */ dhvxint(dhv) int dhv; { register struct tty *tp; register struct dhvdevice *addr; register struct tty *tp0; register struct uba_device *ui; register int line, t; u_short cntr; ubadr_t base; ui = &dhvinfo[dhv]; tp0 = &dhv_tty[dhv<<4]; addr = (struct dhvdevice *)ui->ui_addr; while ((t = addr->dhvcsrh) & DHV_CSH_TI) { line = DHV_TX_LINE(t); tp = tp0 + line; tp->t_state &= ~TS_BUSY; if (t & DHV_CSH_NXM) { printf("dhv(%d,%d): NXM fault\n", dhv, line); /* SHOULD RESTART OR SOMETHING... */ } if (tp->t_state&TS_FLUSH) tp->t_state &= ~TS_FLUSH; else { addr->dhvcsrl = DHV_SELECT(line) | DHV_IE; base = (ubadr_t) addr->dhvbar1; /* * Clists are either: * 1) in kernel virtual space, * which in turn lies in the * first 64K of physical memory or * 2) at UNIBUS virtual address 0. * * In either case, the extension bits are 0. */ if (!ubmap) base |= (ubadr_t)((addr->dhvbar2 & 037) << 16); cntr = base - cpaddr(tp->t_outq.c_cf); ndflush(&tp->t_outq,cntr); } if (tp->t_line) (*linesw[tp->t_line].l_start)(tp); else dhvstart(tp); } } /* * Start (restart) transmission on the given DHV11 line. */ dhvstart(tp) register struct tty *tp; { register struct dhvdevice *addr; register int unit, nch; ubadr_t car; int s; unit = UNIT(tp->t_dev); addr = (struct dhvdevice *)tp->t_addr; /* * Must hold interrupts in following code to prevent * state of the tp from changing. */ s = spltty(); /* * If it's currently active, or delaying, no need to do anything. */ if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) goto out; /* * If there are sleepers, and output has drained below low * water mark, wake up the sleepers.. */ if (tp->t_outq.c_cc<=TTLOWAT(tp)) { if (tp->t_state&TS_ASLEEP) { tp->t_state &= ~TS_ASLEEP; wakeup((caddr_t)&tp->t_outq); } if (tp->t_wsel) { selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); tp->t_wsel = 0; tp->t_state &= ~TS_WCOLL; } } /* * Now restart transmission unless the output queue is * empty. */ if (tp->t_outq.c_cc == 0) goto out; if (tp->t_flags & (RAW|L001000|LITOUT)) nch = ndqb(&tp->t_outq, 0); else { nch = ndqb(&tp->t_outq, 0200); /* * If first thing on queue is a delay process it. */ if (nch == 0) { nch = getc(&tp->t_outq); timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6); tp->t_state |= TS_TIMEOUT; goto out; } } /* * If characters to transmit, restart transmission. */ if (nch) { car = cpaddr(tp->t_outq.c_cf); addr->dhvcsrl = DHV_SELECT(unit) | DHV_IE; addr->dhvlcr &= ~DHV_LC_TXABORT; addr->dhvbcr = nch; addr->dhvbar1 = loint(car); if (ubmap) addr->dhvbar2 = (hiint(car) & DHV_BA2_XBA) | DHV_BA2_DMAGO; else addr->dhvbar2 = (hiint(car) & 037) | DHV_BA2_DMAGO; tp->t_state |= TS_BUSY; } out: splx(s); } /* * Stop output on a line, e.g. for ^S/^Q or output flush. */ /*ARGSUSED*/ dhvstop(tp, flag) register struct tty *tp; { register struct dhvdevice *addr; register int unit, s; addr = (struct dhvdevice *)tp->t_addr; /* * Block input/output interrupts while messing with state. */ s = spltty(); if (tp->t_state & TS_BUSY) { /* * Device is transmitting; stop output * by selecting the line and setting the * abort xmit bit. We will get an xmit interrupt, * where we will figure out where to continue the * next time the transmitter is enabled. If * TS_FLUSH is set, the outq will be flushed. * In either case, dhvstart will clear the TXABORT bit. */ unit = UNIT(tp->t_dev); addr->dhvcsrl = DHV_SELECT(unit) | DHV_IE; addr->dhvlcr |= DHV_LC_TXABORT; delay(25L); /* see the dhv manual, sec 3.3.6 */ addr->dhvlcr2 |= DHV_LC2_TXEN; if ((tp->t_state&TS_TTSTOP)==0) tp->t_state |= TS_FLUSH; } (void) splx(s); } /* * DHV11 modem control */ static long dhvmctl(dev, bits, how) dev_t dev; long bits; int how; { register struct dhvdevice *dhvaddr; register int unit; register struct tty *tp; long mbits; int s; unit = UNIT(dev); tp = dhv_tty + unit; dhvaddr = (struct dhvdevice *) tp->t_addr; s = spltty(); dhvaddr->dhvcsr = DHV_SELECT(unit) | DHV_IE; /* * combine byte from stat register (read only, bits 16..23) * with lcr register (read write, bits 0..15). */ mbits = (u_short)dhvaddr->dhvlcr | ((long)dhvaddr->dhvstat << 16); switch (how) { case DMSET: mbits = (mbits & 0xff0000L) | bits; break; case DMBIS: mbits |= bits; break; case DMBIC: mbits &= ~bits; break; case DMGET: (void) splx(s); return(mbits); } dhvaddr->dhvlcr = (mbits & 0xffff) | DHV_LC_RXEN; if ( dhv_hwxon[unit] ) dhvaddr->dhvlcr |= DHV_LC_OAUTOF; dhvaddr->dhvlcr2 = DHV_LC2_TXEN; (void) splx(s); return(mbits); } #endif printf ( "dhv%d: diagnostic %o\n", dhv, c & 0xff ); continue; } if ( CDWAIT(tp->t_dev) || (tp->t_flags & MDMBUF) ) sys/pdpuba/dhvreg.h 644 3 12 11304 4307336635 7604 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dhvreg.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * DHV-11 device register definitions. */ struct dhvdevice { union { u_short csr; /* control-status register */ struct { char csrl; /* low byte for line select */ char csrh; /* high byte for tx line */ } cb; } un1; #define dhvcsr un1.csr #define dhvcsrl un1.cb.csrl #define dhvcsrh un1.cb.csrh union { u_short rbuf; /* recv.char/ds.change register (R) */ u_short timo; /* delay between recv -> intr (W) */ } un2; #define dhvrbuf un2.rbuf #define dhvtimo un2.timo u_short dhvlpr; /* line parameter register */ union { char fbyte[1]; /* fifo data byte (low byte only) (W) */ u_short fdata; /* fifo data word (W) */ char sbyte[2]; /* line status/fifo size (R) */ } un3; #define dhvbyte un3.fbyte[0] #define dhvfifo un3.fdata #define dhvsize un3.sbyte[0] #define dhvstat un3.sbyte[1] u_short dhvlcr; /* line control register */ u_short dhvbar1; /* buffer address register 1 */ char dhvbar2; /* buffer address register 2 */ char dhvlcr2; /* xmit enable bit */ short dhvbcr; /* buffer count register */ }; /* Bits in dhvcsr */ #define DHV_CS_TIE 0x4000 /* transmit interrupt enable */ #define DHV_CS_DFAIL 0x2000 /* diagnostic fail */ #define DHV_CS_RI 0x0080 /* receiver interrupt */ #define DHV_CS_RIE 0x0040 /* receiver interrupt enable */ #define DHV_CS_MCLR 0x0020 /* master clear */ #define DHV_CS_IAP 0x0007 /* indirect address pointer */ #define DHV_IE (DHV_CS_TIE|DHV_CS_RIE) /* map unit into iap register select */ #define DHV_SELECT(unit) ((unit) & DHV_CS_IAP) /* Transmitter bits in high byte of dhvcsr */ #define DHV_CSH_TI 0x80 /* transmit interrupt */ #define DHV_CSH_NXM 0x10 /* transmit dma err: non-exist-mem */ #define DHV_CSH_TLN 0x0f /* transmit line number */ /* map csrh line bits into line */ #define DHV_TX_LINE(csrh) ((csrh) & DHV_CSH_TLN) /* Bits in dhvrbuf */ #define DHV_RB_VALID 0x8000 /* data valid */ #define DHV_RB_STAT 0x7000 /* status bits */ #define DHV_RB_DO 0x4000 /* data overrun */ #define DHV_RB_FE 0x2000 /* framing error */ #define DHV_RB_PE 0x1000 /* parity error */ #define DHV_RB_RLN 0x0f00 /* receive line number */ #define DHV_RB_RDS 0x00ff /* receive data/status */ #define DHV_RB_DIAG 0x0001 /* if DHV_RB_STAT -> diag vs modem */ /* map rbuf line bits into line */ #define DHV_RX_LINE(rbuf) (((rbuf) & DHV_RB_RLN) >> 8) /* Bits in dhvlpr */ #define DHV_LP_TSPEED 0xf000 #define DHV_LP_RSPEED 0x0f00 #define DHV_LP_TWOSB 0x0080 #define DHV_LP_EPAR 0x0040 #define DHV_LP_PENABLE 0x0020 #define DHV_LP_BITS8 0x0018 #define DHV_LP_BITS7 0x0010 #define DHV_LP_BITS6 0x0008 /* Bits in dhvstat */ #define DHV_ST_DSR 0x80 /* data set ready */ #define DHV_ST_RI 0x20 /* ring indicator */ #define DHV_ST_DCD 0x10 /* carrier detect */ #define DHV_ST_CTS 0x04 /* clear to send */ #define DHV_ST_DHU 0x01 /* always one on a dhu, zero on dhv */ /* Bits in dhvlcr */ #define DHV_LC_RTS 0x1000 /* request to send */ #define DHV_LC_DTR 0x0200 /* data terminal ready */ #define DHV_LC_MODEM 0x0100 /* modem control enable */ #define DHV_LC_MAINT 0x00c0 /* maintenance mode */ #define DHV_LC_FXOFF 0x0020 /* force xoff */ #define DHV_LC_OAUTOF 0x0010 /* output auto flow */ #define DHV_LC_BREAK 0x0008 /* break control */ #define DHV_LC_RXEN 0x0004 /* receiver enable */ #define DHV_LC_IAUTOF 0x0002 /* input auto flow */ #define DHV_LC_TXABORT 0x0001 /* transmitter abort */ /* Bits in dhvlcr2 */ #define DHV_LC2_TXEN 0x80 /* transmitter enable */ /* Bits in dhvbar2 */ #define DHV_BA2_DMAGO 0x80 /* transmit dma start */ #define DHV_BA2_XBA 0x03 /* top two bits of dma address */ #define DHV_XBA_SHIFT 16 /* amount to shift xba bits */ /* Bits for dhvmctl only: stat bits are shifted up 16 */ #define DHV_ON (DHV_LC_DTR|DHV_LC_RTS|DHV_LC_MODEM) #define DHV_OFF DHV_LC_MODEM #define DHV_DSR ((long)DHV_ST_DSR << 16) #define DHV_RNG ((long)DHV_ST_RI << 16) #define DHV_CAR ((long)DHV_ST_DCD << 16) #define DHV_CTS ((long)DHV_ST_CTS << 16) #define DHV_RTS DHV_LC_RTS #define DHV_DTR DHV_LC_DTR #define DHV_BRK DHV_LC_BREAK #define DHV_LE DHV_LC_MODEM /* bits in dm lsr, copied from dmreg.h */ #define DML_DSR 0000400 /* data set ready, not a real DM bit */ #define DML_RNG 0000200 /* ring */ #define DML_CAR 0000100 /* carrier detect */ #define DML_CTS 0000040 /* clear to send */ #define DML_SR 0000020 /* secondary receive */ #define DML_ST 0000010 /* secondary transmit */ #define DML_RTS 0000004 /* request to send */ #define DML_DTR 0000002 /* data terminal ready */ #define DML_LE 0000001 /* line enable */ else { tp->t_state |= TS_TTSTOP; dhvstop (tp, 0); } } continue; } if ((tp->t_state&TS_ISOPEN) == 0) { wakeup((caddr_t)&tp->t_rawq); continue; } if ( c & (DHV_RB_PE|DHV_RB_DO|DHV_RB_FE) ) { if (c & DHV_RB_PE) if ((tp->t_flags&(EVENP|ODDP)) == Esys/pdpuba/dnreg.h 444 0 12 1332 4166274452 7400 struct dndevice { short dnisr[4]; }; /* bits in dnisr */ #define DN_PWI 0100000 /* power indicate */ #define DN_ACR 0040000 /* abandon call and retry */ /* bit 13 is unused */ #define DN_FDLO 0010000 /* data line occupied */ /* bits 11-8 are the digit bits */ #define DN_DONE 0000200 /* done */ #define DN_INTENB 0000100 /* interrupt enable */ #define DN_DSS 0000040 /* data set status */ #define DN_FPND 0000020 /* present next digit */ #define DN_MAINT 0000010 /* maintenance */ #define DN_MINAB 0000004 /* master enable */ #define DN_FDPR 0000002 /* digit present */ #define DN_FCRQ 0000001 /* call request */ #define DN_BITS \ "\10\20PWI\17ACR\15FDLO\10DONE\7INTENB\6DSS\5FPND\4MAINT\3MINAB\2FDPR\1FCRQ" timo u_short dhvlpr; /* line parameter register */ union { char fbyte[1]; /* fifo data byte (low byte only) (W) */ u_short fdata; /* fifo data word (W) */ char sbyte[2]; /* line status/fifo size (R) */ } un3; #define dhvbyte un3.fbyte[0] #define dhvfifo un3.fdata #define dhvsize unsys/pdpuba/dn.c 444 0 12 3260 5667260060 6674 /* * SCCS id @(#)dn.c 2.2 (2.11BSD GTE) 11/29/94 */ /* * DN-11 ACU interface */ #include "dn.h" #if NDN > 0 #include "param.h" #include "user.h" #include "kernel.h" #include "dnreg.h" #define DNPRI (PZERO+5) struct dndevice *dn_addr[NDN]; dnattach(addr, unit) struct dndevice *addr; { if ((unsigned)unit >= NDN) return 0; dn_addr[unit] = addr; return 1; } /*ARGSUSED*/ dnopen(dev, flag) register dev_t dev; { register struct dndevice *dp; dev = minor(dev); if (dev >= NDN << 2 || (dp = dn_addr[dev >> 2]) == NULL || (dp->dnisr[dev & 03] & (DN_PWI | DN_FDLO | DN_FCRQ))) return(ENXIO); else { dp->dnisr[0] |= DN_MINAB; dp->dnisr[dev & 03] = DN_INTENB | DN_MINAB | DN_FCRQ; } return(0); } dnclose(dev, flag) register dev_t dev; { dev = minor(dev); dn_addr[dev >> 2]->dnisr[dev & 03] = DN_MINAB; return(0); } dnwrite(dev, uio, flag) register dev_t dev; register struct uio *uio; int flag; { register int c, *dp; int s; dev = minor(dev); dp = (int *)&(dn_addr[dev >> 2]->dnisr[dev & 03]); while ((*dp & (DN_PWI | DN_ACR | DN_DSS)) == 0) { s = spl4(); if ((*dp & DN_FPND) == 0 || !uio->uio_resid || (c = uwritec(uio)) < 0) sleep((caddr_t) dp, DNPRI); else if (c == '-') { sleep((caddr_t) &lbolt, DNPRI); sleep((caddr_t) &lbolt, DNPRI); } else { *dp = (c << 8) | DN_INTENB|DN_MINAB|DN_FDPR|DN_FCRQ; sleep((caddr_t) dp, DNPRI); } splx(s); } if (*dp & (DN_PWI | DN_ACR)) return(EIO); return(0); } dnint(dn11) { register int *dp, *ep; dp = (int *)&(dn_addr[dn11]->dnisr[0]); *dp &= ~DN_MINAB; for (ep = dp; ep < dp + 4; ep++) if (*ep & DN_DONE) { *ep &= ~DN_DONE; wakeup((caddr_t)ep); } *dp |= DN_MINAB; } #endif /* NDN */ r select */ #define DHV_SELECT(unit) ((unit) & DHV_CS_IAP) /* Transmitter bits in high byte of dhvcsr */ #define DHV_CSH_TI 0x80 /* transmit interrupt */ #define DHV_CSH_NXM 0x10 /* transmit dma err: non-exist-mem */ #define DHV_CSH_TLN 0x0f /* transmit line number */ /* map csrh line bits into line */ #define DHV_TX_LINE(csrh) (sys/pdpuba/brreg.h 444 0 12 5563 4305353722 7405 struct brdevice { short brds; short brer; union { short w; char c[2]; } brcs; short brwc; caddr_t brba; short brca; short brda; short brae; }; /* bits in brds */ #define BRDS_SURDY 0100000 /* selected unit ready */ #define BRDS_SUOL 0040000 /* selected unit on line */ #define BRDS_TOE 0020000 /* selected unit BR */ #define BRDS_HNF 0010000 /* header not found */ #define BRDS_SUSI 0004000 /* selected unit seek incomplete */ #define BRDS_SUFU 0001000 /* selected unit file unsafe */ #define BRDS_SUWP 0000400 /* selected unit write protected */ /* bits 7-0 are attention bits */ #define BRDS_BITS "\10\20SURDY\17SUOL\16BR\15HNF\14SUSI\12SUFU\11SUWP" /* bits in brer */ #define BRER_WPV 0100000 /* write protect violation */ #define BRER_FUV 0040000 /* file unsafe violation */ #define BRER_NXC 0020000 /* nonexistent cylinder */ #define BRER_NXT 0010000 /* nonexistent track */ #define BRER_SUBUSY 0004000 /* selected unit busy */ #define BRER_PROG 0002000 /* program error */ #define BRER_FMTE 0001000 /* format error */ #define BRER_BSE 0000400 /* bad sector */ #define BRER_ATE 0000200 /* aborted transfer error */ #define BRER_DCE 0000100 /* data check error */ #define BRER_DSE 0000040 /* data sync error */ #define BRER_SBPE 0000020 /* system bad parity error */ #define BRER_WCE 0000010 /* write check error */ #define BRER_NXME 0000004 /* nonexistent memory */ #define BRER_EOP 0000002 /* end of pack */ #define BRER_DSKERR 0000001 /* disk error */ #define BRER_BITS \ "\10\20WPV\17FUV\16NXC\15NXT\14SUBUSY\13PROG\12FMTE\11BSE\10ATE\ \7DCE\6DSE\5SBPE\4WCE\3NXME\2EOP\1DSKERR" /* bits in brcs */ #define BR_ERR 0100000 /* error */ #define BR_HE 0040000 /* hard error */ #define BR_AIE 0020000 /* attention interrupt enable */ #define BR_HDB 0010000 /* hold drive busy */ #define BR_HDR 0004000 /* header */ /* bits 10-8 are drive select */ #define BR_RDY 0000200 /* ready */ #define BR_IDE 0000100 /* interrupt on done (error) enable */ /* bits 5-4 are the UNIBUS extension bits */ /* bits 3-1 are the function */ #define BR_GO 0000001 /* go */ #define BR_BITS "\10\20ERR\17HE\16AIE\15HDB\14HDR\10RDY\7IDE\1GO" /* commands */ #define BR_IDLE 0000000 /* idle */ #define BR_WCOM 0000002 /* write */ #define BR_RCOM 0000004 /* read */ #define BR_WCHK 0000006 /* write check */ #define BR_SEEK 0000010 /* seek */ #define BR_WNS 0000012 /* write (no seek) */ #define BR_HSEEK 0000014 /* home seek */ #define BR_RNS 0000016 /* read (no seek) */ #define STBE 0000100 /* Strobe early */ #define STBL 0000200 /* Strobe late */ #define OFFP 0140000 /* Positive offset */ #define OFFM 0100000 /* Negative offset */ /* Bits in br_ae */ #define AE_DTYP 0007400 /* Disk type */ #define AE_T50 0000400 /* T-50 drive */ #define AE_T80 0001000 /* T-80 drive */ #define AE_T200 0002000 /* T-200 drive */ #define AE_T300 0004000 /* T-300 drive */ ng indicator */ #define DHV_ST_DCD 0x10 /* carrier detect */ #define DHV_ST_CTS 0x04 /* clear to send */ #define DHV_ST_DHU 0x01 /* alwayssys/pdpuba/tmscpreg.h 444 0 12 6031 4662055572 10127 /* @(#)tmscpreg.h 7.1 (Berkeley) 6/5/86 */ /* @(#)tmscpreg.h 1.1 11/2/84 84/09/25 */ /**************************************************************** * * * Licensed from Digital Equipment Corporation * * Copyright (c) * * Digital Equipment Corporation * * Maynard, Massachusetts * * 1985, 1986 * * All rights reserved. * * * * The Information in this software is subject to change * * without notice and should not be construed as a commitment * * by Digital Equipment Corporation. Digital makes no * * representations about the suitability of this software for * * any purpose. It is supplied "As Is" without expressed or * * implied warranty. * * * * If the Regents of the University of California or its * * licensees modify the software in a manner creating * * diriviative copyright rights, appropriate copyright * * legends may be placed on the drivative work in addition * * to that set forth above. * * * ****************************************************************/ /* * TMSCP registers and structures */ struct tmscpdevice { short tmscpip; /* initialization and polling */ short tmscpsa; /* status and address */ }; #define TMSCP_ERR 0100000 /* error bit */ #define TMSCP_STEP4 0040000 /* step 4 has started */ #define TMSCP_STEP3 0020000 /* step 3 has started */ #define TMSCP_STEP2 0010000 /* step 2 has started */ #define TMSCP_STEP1 0004000 /* step 1 has started */ #define TMSCP_NV 0002000 /* no host settable interrupt vector */ #define TMSCP_QB 0001000 /* controller supports Q22 bus */ #define TMSCP_DI 0000400 /* controller implements diagnostics */ #define TMSCP_OD 0000200 /* port allows odd host addr's in the buffer descriptor */ #define TMSCP_IE 0000200 /* interrupt enable */ #define TMSCP_MP 0000100 /* port supports address mapping */ #define TMSCP_LF 0000002 /* host requests last fail response packet */ #define TMSCP_PI 0000001 /* host requests adapter purge interrupts */ #define TMSCP_GO 0000001 /* start operation, after init */ typedef struct { /* swap shorts for TMSCP controller */ short lsh; short hsh; } Trl; /* * TMSCP Communications Area */ struct tmscpca { short ca_xxx1; /* unused */ char ca_xxx2; /* unused */ char ca_bdp; /* BDP to purge */ short ca_cmdint; /* command queue transition interrupt flag */ short ca_rspint; /* response queue transition interrupt flag */ Trl ca_rspdsc[NRSP];/* response descriptors */ Trl ca_cmddsc[NCMD];/* command descriptors */ }; #define ca_ringbase ca_rspdsc[0] #define TMSCP_OWN 0x8000 /* port owns descriptor (else host owns it) */ #define TMSCP_INT 0x4000 /* allow interrupt on ring transition */ /* * TMSCP packet info (same as MSCP) */ struct mscp_header { short tmscp_msglen; /* length of MSCP packet */ char tmscp_credits; /* low 4 bits: credits, high 4 bits: msgtype */ char tmscp_vcid; /* virtual circuit id (connection id) */ }; be placed on the drivative work in addition * * to that set forth above. * * * ****************************************************************/ /* * TMSCP registers and structures */ struct tmscpdevice { short tmscpip; /* initialization and polling */ short tmscpsa; /* status and address */ }; #define TMSCP_ERR 0100000 /* error bit */ #define TMSCP_STEP4 0040000 /* step 4 has started */ #define TMSCP_STEP3 0020000 /* step 3 has started */ #define TMSCP_sys/pdpuba/tmscp.c 644 0 12 143632 5672252157 7477 /* @(#)tmscp.c 1.4 (2.11BSD GTE) 12/9/94 */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)tmscp.c 1.24 (ULTRIX) 1/21/86"; #endif /************************************************************************ * * * Licensed from Digital Equipment Corporation * * Copyright (c) * * Digital Equipment Corporation * * Maynard, Massachusetts * * 1985, 1986 * * All rights reserved. * * * * The Information in this software is subject to change * * without notice and should not be construed as a commitment * * by Digital Equipment Corporation. Digital makes no * * representations about the suitability of this software for * * any purpose. It is supplied "As Is" without expressed or * * implied warranty. * * * * If the Regents of the University of California or its * * licensees modify the software in a manner creating * * diriviative copyright rights, appropriate copyright * * legends may be placed on the drivative work in addition * * to that set forth above. * * * ************************************************************************ * * tmscp.c - TMSCP (TK50/TU81) tape device driver * * Modification History: * 02-Jan-93 - sms@wlv. [2.11BSD] * Remove unibus map ifdefs and rely on run time testing of 'ubmap' which * does the right thing and makes kernels easier to move between machines. * * 20-Nov-92 - sms@wlv.iipo.gtegsc.com [2.11BSD] * Add tmsVec() for autoconfig to use in passing the vector from /etc/dtab * to this driver. The previous scheme of having a fixed vector with * all TMSCP vectors contiguous has been removed. * * 23-May-91 - sms@wlv.iipo.gtegsc.com [2.11BSD] * Minor typo in the multicontroller support fixed. Major overhaul * of the density selection, apparently some TMSCP controllers * do not treat 0 in the mscp_format word as meaning the highest * density, instead leaving the drive in the current/last-used * density. * * 29-Mar-91 - sms@wlv.iipo.gtegsc.com [2.11BSD] * Major changes to 1) support multiple drives per controller * (the maximum number of drives per controller is 4 for now in order * to maximize compatibility with existing minor device numbers - the * norewind and density bit stay in the same place) and 2) more * importantly reduce the bloat of this driver. The command * packet area is now allocated from an external heap setup at boot * time (the MSCP, ra.c driver also does this). Allocating from an * external arena save approximately 2kb of kernel D space PER CONTROLLER * and costs little in speed because the amount of remapping involved is * quite small. * * The 'errinfo' routine was removed in the interest of space savings, * the error code was already being printed out in hex and it's not * worth eating up another 250 or so bytes of kernel D space to pretty * print messages for which tmscp.h provides the cross reference (I space * is also saved by not printing the messages). Besides, the ra.c (MSCP) * driver doesn't do it and it is worth a degree of non 4.3BSD verisimility * to save a significant amount of space. * * The tms_type field should have been a 'long' (mediatype). Since the * drives are not probed at autoconfigure time a GTUNT (TMS_SENSE) command * is done at open() time to fetch the format/density menu and unit flags. * iodone() proccessing was missing for the GTUNT function in tmscprsp() * causing hangs in both open and ioctl functions. * * Multiple controller support made to work, the top 2 bits of the minor * device number are used to designate the controller, thus there is * a maximum of 4 TMSCP controllers per system. * * 17-Jun-90,14Aug90 - sms@wlv.iipo.gtegsc.com * Began porting to 2.10.1BSD/2.11BSD. Multiple drives per controller * NOT supported, although multiple controllers are (maybe). Programmable * vectors don't work very well with the autoconfigure scheme in use. * the define TMSCP_VEC will have to be adjusted in tms.h (see * conf/config and the sample config files). For patching purposes * the global "TMSvec" is declared and initialized with TMSCP_VEC. * * 06-Jan-86 - afd * Changed the probe routine to use DELAY (not TODR). This now * works for MicroVAXen as well. This eliminates the busy-wait * for MicroVAXen so a dead TK50 controller will not hang autoconf. * * 06-Dec-85 - afd * Fixed a bug in density selection. The "set unit characteristics" * command to select density, was clearing the "unit flags" field * where the CACHE bit was for TU81-E. Now the unit's "format" and * "unitflgs" are saved in tms_info struct. And are used on STUNT * commands. * * 19-Oct-85 - afd * Added support to the open routine to allow drives to be opened * for low density (800 or 1600 bpi) use. When the slave routine * initiates a "get-unit-char" cmd, the format menu for the unit * is saved in the tms_info structure. The format menu is used in the * start routine to select the proper low density. * * 02-Oct-85 - afd * When a tmscp-type controller is initializing, it is possible for * the sa reg to become 0 between states. Thus the init code in * the interrupt routine had to be modified to reflect this. * * 21-Sep-85 - afd * The TK50 declares a serious exception when a tape mark is encountered. * This causes problems to dd (& other UN*X utilities). So a flag * is set in the rsp() routine when a tape mark is encountered. If * this flag is set, the start() routine appends the Clear Serious * Exception modifier to the next command. * * 03-Sep-85 -- jaw * messed up previous edit.. * * 29-Aug-85 - jaw * fixed bugs in 8200 and 750 buffered datapath handling. * * 06-Aug-85 - afd * 1. When repositioning records or files, the count of items skipped * does NOT HAVE to be returned by controllers (& the TU81 doesn't). * So tmscprsp() had to be modified to stop reporting * residual count errors on reposition commands. * * 2. Fixed bug in the open routine which allowed multiple opens. * * 18-Jul-85 - afd * 1. Need to return status when mt status (or corresponding ioctl) is done. * Save resid, flags, endcode & status in tmscprsp() routine (except on * clear serious exception no-op). Return these fields when status * ioctl is done (in tmscpcommand()). How they are returned: * mt_resid = resid * mt_dsreg = flags|endcode * mt_erreg = status * * 2. Added latent support for enabling/disabling caching. This is * handled along with all other ioctl commands. * * 3. Need to issue a no-op on unrecognized ioctl in tmsstart(), since * we have already commited to issuing a command at that point. * * 4. In tmscprsp() routine if encode is 0200 (invalid command issued); * We need to: Unlink the buffer from the I/O wait queue, * and signal iodone, so the higher level command can exit! * Just as if it were a valid command. * * 11-jul-85 -- jaw * fix bua/bda map registers. * * 19-Jun-85 -- jaw * VAX8200 name change. * * 06-Jun-85 - jaw * fixes for 8200. * * 9-Apr-85 - afd * Added timeout code to the probe routine, so if the controller * fails to init in 10 seconds we return failed status. * * 13-Mar-85 -jaw * Changes for support of the VAX8200 were merged in. * * 27-Feb-85 -tresvik * Changes for support of the VAX8600 were merged in. * */ #include "tms.h" #if NTMSCP > 0 #include "param.h" #include "systm.h" #include "buf.h" #include "conf.h" #include "user.h" #include "file.h" #include "map.h" #include "ioctl.h" #include "syslog.h" #include "mtio.h" #include "uio.h" #include "tty.h" #include "uba.h" #define TMS_PRI LOG_INFO #define NRSPL2 3 /* log2 number of response packets */ #define NCMDL2 3 /* log2 number of command packets */ #define NRSP (1<> 6) & 3) #define TMSDENS(dev) ((minor(dev) >> 3) & 3) #define FMTMASK (M_TF_800|M_TF_PE|M_TF_GCR) /* = 7 */ #define T_NOREWIND 04 /* Size to map in when mapping a controller's command packet area */ #define MAPBUFDESC (((btoc(sizeof (struct tmscp)) - 1) << 8) | RW) /* * Internal (ioctl) command codes (these must also be declared in the * tmscpioctl routine). These correspond to ioctls in mtio.h */ #define TMS_WRITM 0 /* write tape mark */ #define TMS_FSF 1 /* forward space file */ #define TMS_BSF 2 /* backward space file */ #define TMS_FSR 3 /* forward space record */ #define TMS_BSR 4 /* backward space record */ #define TMS_REW 5 /* rewind tape */ #define TMS_OFFL 6 /* rewind tape & mark unit offline */ #define TMS_SENSE 7 /* noop - do a get unit status */ #define TMS_CACHE 8 /* enable cache */ #define TMS_NOCACHE 9 /* disable cache */ /* These go last: after all real mt cmds, just bump the numbers up */ #define TMS_CSE 10 /* clear serious exception */ #define TMS_SETDENSITY 11 /* set unit density */ /* * Controller states */ #define S_IDLE 0 /* hasn't been initialized */ #define S_STEP1 1 /* doing step 1 init */ #define S_STEP2 2 /* doing step 2 init */ #define S_STEP3 3 /* doing step 3 init */ #define S_SCHAR 4 /* doing "set controller characteristics" */ #define S_RUN 5 /* running */ static char *tmscpstepfailed = "step%d init failed: sa 0x%x\n"; static char *tmscpfatalerr = "tms%d,%d: fatal error 0%o\n"; int tmscperror = 0; /* causes hex dump of packets */ int tmscp_cp_wait = 0; /* Something to wait on for command */ /* packets and or credits. */ int wakeup(); extern int hz; /* Should find the right include */ extern long _iomap(); #ifdef TMSCP_DEBUG #define printd if (tmscpdebug) printf int tmscpdebug = 1; #define printd10 if(tmscpdebug >= 10) printf #endif struct mscp *tmscpgetcp(); #define b_qsize b_resid /* queue size per drive, in tmsutab */ tmsVec(ctlr, vector) int ctlr, vector; { register struct tmscp_softc *sc = &tmscp_softc[ctlr]; if (ctlr >= NTMSCP || sc->sc_ivec) return(-1); sc->sc_ivec = vector; return(0); } /* * Open routine will issue the online command, later. * * This routine attaches controllers, not drives - sc_unit and 'unit' are * the controller number not a drive unit number. sc_com is initialized * to SEG5 because all communication areas are mapped to the same virtual * address now. */ tmsattach(addr, unit) struct tmscpdevice *addr; register int unit; { register struct tmscp_softc *sc = &tmscp_softc[unit]; if (unit >= NTMSCP) return(0); if (sc->sc_addr == NULL && addr != NULL) { tmscp[unit] = (memaddr)_ioget(sizeof (struct tmscp)); if (tmscp[unit] == NULL) return(0); sc->sc_addr = addr; sc->sc_unit = unit; sc->sc_com = (struct tmscp *)SEG5; return (1); } return(0); } struct tms_info * getdd() { register int i; register struct tms_info *p; for (i = NTMS, p = tms_info; i--; p++) { if (p->tms_online == 0) return(p); } log(TMS_PRI, "tms: no drive descriptors\n"); return(NULL); } /* * TMSCP interrupt routine. */ tmsintr(dev) dev_t dev; { register struct tmscpdevice *tmscpaddr; struct buf *bp; register int i; register struct tmscp_softc *sc = &tmscp_softc[dev]; register struct tmscp *tm = sc->sc_com; struct mscp *mp; segm seg5; tmscpaddr = sc->sc_addr; #ifdef TMSCP_DEBUG printd10("tmscpintr: state %d, tmscpsa %o\n", sc->sc_state, tmscpaddr->tmscpsa); #endif /* * How the interrupt is handled depends on the state of the controller. */ switch (sc->sc_state) { case S_IDLE: printf("tms%d: random intr ignored\n", dev); return; /* Controller was in step 1 last, see if its gone to step 2 */ case S_STEP1: # define STEP1MASK 0174377 # define STEP1GOOD (TMSCP_STEP2|TMSCP_IE|(NCMDL2<<3)|NRSPL2) for (i = 0; i < 150; i++) { if ((tmscpaddr->tmscpsa&STEP1MASK) != STEP1GOOD) { /* still in step 1 (wait 1/100 sec) */ delay(10000L); #ifdef TMSCP_DEBUG printd("still in step 1, delaying\n"); #endif } else break; } if (i > 149) { sc->sc_state = S_IDLE; sc->sc_ctab.b_active = 0; printf(tmscpstepfailed,sc->sc_state,tmscpaddr->tmscpsa); wakeup((caddr_t)&sc->sc_ctab); return; } tmscpaddr->tmscpsa = (short)sc->sc_ctab.b_un.b_addr; sc->sc_state = S_STEP2; return; /* Controller was in step 2 last, see if its gone to step 3 */ case S_STEP2: # define STEP2MASK 0174377 # define STEP2GOOD (TMSCP_STEP3|TMSCP_IE|(sc->sc_ivec/4)) for (i = 0; i < 150; i++) { if ((tmscpaddr->tmscpsa&STEP2MASK) != STEP2GOOD) { /* still in step 2 (wait 1/100 sec) */ delay(10000L); #ifdef TMSCP_DEBUG printd("still in step 2, delaying\n"); #endif } else break; } if (i > 149) { sc->sc_state = S_IDLE; sc->sc_ctab.b_active = 0; printf(tmscpstepfailed,sc->sc_state,tmscpaddr->tmscpsa); wakeup((caddr_t)&sc->sc_ctab); return; } tmscpaddr->tmscpsa = sc->sc_ctab.b_xmem; sc->sc_state = S_STEP3; return; /* Controller was in step 3 last, see if its gone to step 4 */ case S_STEP3: # define STEP3MASK 0174000 # define STEP3GOOD TMSCP_STEP4 for (i = 0; i < 150; i++) { if ((tmscpaddr->tmscpsa&STEP3MASK) != STEP3GOOD) { /* still in step 3 (wait 1/100 sec) */ delay(10000L); #ifdef TMSCP_DEBUG printd("still in step 3, delaying\n"); #endif } else break; } if (i > 149) { sc->sc_state = S_IDLE; sc->sc_ctab.b_active = 0; printf(tmscpstepfailed,sc->sc_state,tmscpaddr->tmscpsa); wakeup((caddr_t)&sc->sc_ctab); return; } /* * Get microcode version and model number of controller; * Signal initialization complete (_GO) (to the controller); * ask for Last Fail response if tmscperror is set; * Set state to "set controller characteristics". */ i = tmscpaddr->tmscpsa; tmscpaddr->tmscpsa = TMSCP_GO | (tmscperror? TMSCP_LF : 0); sc->sc_state = S_SCHAR; #ifdef TMSCP_DEBUG printd("tmscpintr: completed state %d \n", sc->sc_state); printd("tmscp%d Version: %d model %d\n", dev, i & 0xf, (i >> 4) & 0xf); #endif /* * Initialize the data structures (response and command queues). */ saveseg5(seg5); mapseg5(tmscp[sc->sc_unit], MAPBUFDESC); tmsginit(sc, sc->sc_com->tmscp_ca.ca_rspdsc, sc->sc_com->tmscp_rsp, 0, NRSP, TMSCP_OWN|TMSCP_INT); tmsginit(sc, sc->sc_com->tmscp_ca.ca_cmddsc, sc->sc_com->tmscp_cmd, NRSP, NCMD, TMSCP_INT); bp = &sc->sc_wtab; bp->av_forw = bp->av_back = bp; sc->sc_lastcmd = 1; sc->sc_lastrsp = 0; mp = sc->sc_com->tmscp_cmd; mp->mscp_unit = mp->mscp_modifier = 0; mp->mscp_flags = 0; mp->mscp_version = 0; mp->mscp_cntflgs = M_CF_ATTN|M_CF_MISC|M_CF_THIS; /* * A host time out value of 0 means that the controller will not * time out. This is ok for the TK50. */ mp->mscp_hsttmo = 0; bzero(&mp->mscp_time, sizeof (mp->mscp_time)); mp->mscp_cntdep = 0; mp->mscp_opcode = M_OP_STCON; ((Trl *)mp->mscp_dscptr)->hsh |= TMSCP_OWN|TMSCP_INT; i = tmscpaddr->tmscpip; /* initiate polling */ restorseg5(seg5); return; case S_SCHAR: case S_RUN: break; default: printf("tms%d: intr unknown state %d ignored\n",dev,sc->sc_state); return; } /* end switch */ /* * The controller state is S_SCHAR or S_RUN */ /* * If the error bit is set in the SA register then print an error * message and reinitialize the controller. */ if (tmscpaddr->tmscpsa&TMSCP_ERR) { printf(tmscpfatalerr, dev, sc->sc_unit, tmscpaddr->tmscpsa); tmscpaddr->tmscpip = 0; sc->sc_state = S_IDLE; sc->sc_ctab.b_active = 0; wakeup((caddr_t)&sc->sc_ctab); } /* * Check for a buffer purge request. (Won't happen w/ TK50 on Q22 bus) */ saveseg5(seg5); mapseg5(tmscp[sc->sc_unit], MAPBUFDESC); if (tm->tmscp_ca.ca_bdp) { tm->tmscp_ca.ca_bdp = 0; tmscpaddr->tmscpsa = 0; /* signal purge complete */ } /* * Check for response ring transition. */ if (tm->tmscp_ca.ca_rspint) { tm->tmscp_ca.ca_rspint = 0; for (i = sc->sc_lastrsp;; i++) { i %= NRSP; if (tm->tmscp_ca.ca_rspdsc[i].hsh&TMSCP_OWN) break; tmscprsp(sc, i); tm->tmscp_ca.ca_rspdsc[i].hsh |= TMSCP_OWN; } sc->sc_lastrsp = i; } /* * Check for command ring transition. (Should never happen!) */ if (tm->tmscp_ca.ca_cmdint) { #ifdef TMSCP_DEBUG printd("tmscpintr: command ring transition\n"); #endif tm->tmscp_ca.ca_cmdint = 0; } restorseg5(seg5); if (tmscp_cp_wait) wakeup((caddr_t)&tmscp_cp_wait); (void) tmsstart(sc); } /* * Open a tmscp device and set the unit online. If the controller is not * in the run state, call init to initialize the tmscp controller first. */ /* ARGSUSED */ tmscpopen(dev, flag) dev_t dev; int flag; { register int unit = TMSUNIT(dev); int ctlr = TMSCTLR(dev); register struct tmscp_softc *sc; register struct tms_info *tms; register struct mscp *mp; struct tmscpdevice *tmscpaddr; int s,i; #ifdef TMSCP_DEBUG printd("tmscpopen %d,%d\n", ctlr, unit); if (tmscpdebug) delay(10000L); #endif if (ctlr >= NTMSCP) return (ENXIO); sc = &tmscp_softc[ctlr]; if (sc->sc_addr == NULL) return (ENXIO); if ((tms = sc->sc_drives[unit]) == NULL) { tms = getdd(); if (!tms) return(ENXIO); tms->tms_online = -1; sc->sc_drives[unit] = tms; } if (tms->tms_openf) return(EBUSY); tms->tms_openf = 1; tms->tms_ttyp = u.u_ttyp; s = spl5(); if (sc->sc_state != S_RUN) { if (sc->sc_state == S_IDLE) if(!tkini(sc)) { printf("tms%d init failed\n", ctlr); (void) splx(s); return(ENXIO); } /* * Wait for initialization to complete */ timeout(wakeup,(caddr_t)&sc->sc_ctab,11*hz); /* to be sure*/ sleep((caddr_t)&sc->sc_ctab, PSWP+1); if (sc->sc_state != S_RUN) { sc->sc_drives[unit] = NULL; tms->tms_online = tms->tms_openf = 0; (void) splx(s); return (EIO); } } /* * Check to see if the device is really there. * this code was taken from Fred Canters 11 driver */ tmscpaddr = (struct tmscpdevice *) sc->sc_addr; (void) splx(s); if(tms->tms_online == -1) { s = spl5(); while ((mp = tmscpgetcp(sc)) == 0) { tmscp_cp_wait++; sleep((caddr_t)&tmscp_cp_wait,PSWP+1); tmscp_cp_wait--; } (void) splx(s); mapseg5(tmscp[sc->sc_unit], MAPBUFDESC); mp->mscp_opcode = M_OP_ONLIN; mp->mscp_unit = unit; /* unit? */ mp->mscp_cmdref = (u_short)&tms->tms_type; /* need to sleep on something */ #ifdef TMSCP_DEBUG printd("tmscpopen: bring unit %d,%d online\n",ctlr, unit); #endif ((Trl *)mp->mscp_dscptr)->hsh |= TMSCP_OWN | TMSCP_INT; normalseg5(); i = tmscpaddr->tmscpip; /* * To make sure we wake up, timeout in 240 seconds. * Wakeup in tmscprsp routine. * 240 seconds (4 minutes) is necessary since a rewind * can take a few minutes. */ timeout(wakeup,(caddr_t) &tms->tms_type,240 * hz); sleep((caddr_t) &tms->tms_type,PSWP+1); } if (tms->tms_online == -1) { oops: tms->tms_online = tms->tms_openf = 0; sc->sc_drives[unit] = NULL; return(ENXIO); /* Didn't go online */ } /* * Get the unit characteristics (GTUNT). Done here because we * do not check for slave units at autoconfigure time. This really * only need be done once, but it's easier to do it on each open. * tmscpcommand() is used since the iodone() handling for GTUNT has * been fixed. */ tms->tms_type = 0; tmscpcommand(dev, TMS_SENSE, 1); if (tms->tms_type == 0) goto oops; tms->tms_lastiow = 0; /* * Set unit density using the density matrix. * This is done as an "internal" ioctl command so * that the command setup and response handling * is done thru "regular" command routines. */ tmscpcommand(dev, TMS_SETDENSITY, 1); return (0); } /* * Close tape device. * * If tape was open for writing or last operation was * a write, then write two EOF's and backspace over the last one. * Unless this is a non-rewinding special file, rewind the tape. * * NOTE: * We want to be sure that any serious exception is cleared on the * close. A Clear Serious Exception (CSE) modifier is always done on * the rewind command. For the non-rewind case we check to see if the * "serex" field is set in the softc struct; if it is then issue a noop * command with the CSE modifier. * Make the tape available to others, by clearing openf flag. */ tmscpclose(dev, flag) register dev_t dev; register flag; { struct tmscp_softc *sc; register struct tms_info *tms; int unit = TMSUNIT(dev); #ifdef TMSCP_DEBUG printd("tmscpclose: %d,%d\n", TMSCTLR(dev), unit); if(tmscpdebug)delay(10000L); #endif sc = &tmscp_softc[TMSCTLR(dev)]; tms = sc->sc_drives[unit]; if (flag == FWRITE || (flag&FWRITE) && tms->tms_lastiow) { /* device, command, count */ tmscpcommand (dev, TMS_WRITM, 1); tmscpcommand (dev, TMS_WRITM, 1); tmscpcommand (dev, TMS_BSR, 1); } if ((minor(dev)&T_NOREWIND) == 0) /* * Don't hang waiting for rewind complete. */ tmscpcommand(dev, TMS_REW, 0); else if (tms->tms_serex) { #ifdef TMSCP_DEBUG printd("tmscpclose: clearing serex\n"); if (tmscpdebug)delay(10000L); #endif tmscpcommand(dev, TMS_CSE, 1); } tms->tms_openf = 0; } /* * Execute a command on the tape drive a specified number of times. * This routine sets up a buffer and calls the strategy routine which * links the buffer onto the drive's buffer queue. * The start routine will take care of creating a tmscp command packet * with the command. The start routine is called by the strategy or the * interrupt routine. */ tmscpcommand(dev, com, count) register dev_t dev; int com, count; { register struct buf *bp; register int s; int unit = TMSUNIT(dev); bp = &tmscp_softc[TMSCTLR(dev)].sc_cmdbuf; s = spl5(); while (bp->b_flags&B_BUSY) { /* * This special check is because B_BUSY never * gets cleared in the non-waiting rewind case. */ if (bp->b_bcount == 0 && (bp->b_flags&B_DONE)) break; bp->b_flags |= B_WANTED; sleep((caddr_t)bp, PRIBIO); } bp->b_flags = B_BUSY|B_READ; splx(s); /* * Load the buffer. The b_count field gets used to hold the command * count. the b_resid field gets used to hold the command mneumonic. * These 2 fields are "known" to be "safe" to use for this purpose. * (Most other drivers also use these fields in this way.) */ bp->b_dev = dev; bp->b_bcount = count; bp->b_resid = com; bp->b_blkno = 0; tmscpstrategy(bp); /* * In case of rewind from close, don't wait. * This is the only case where count can be 0. */ if (count == 0) return; iowait(bp); if (bp->b_flags&B_WANTED) wakeup((caddr_t)bp); bp->b_flags &= B_ERROR; } /* * Init mscp communications area */ tmsginit(sc, com, msgs, offset, length, flags) register struct tmscp_softc *sc; register Trl *com; register struct mscp *msgs; int offset; int length; int flags; { long vaddr; /* * Figure out virtual address of message * skip comm area and mscp messages header and previous messages * * N.B. Assumes SEG5 has been remapped to the comm area for this * controller. */ vaddr = _iomap(tmscp[sc->sc_unit]); vaddr += sizeof(struct tmscpca) /* skip comm area */ +sizeof(struct mscp_header); /* m_cmdref disp */ vaddr += offset * sizeof(struct mscp); /* skip previous */ while (length--) { com->lsh = loint(vaddr); com->hsh = flags | hiint(vaddr); msgs->mscp_dscptr = (long *)com; msgs->mscp_header.tmscp_msglen = sizeof(struct mscp); msgs->mscp_header.tmscp_vcid = 1; /* tape VCID = 1 */ ++com; ++msgs; vaddr += sizeof(struct mscp); } } /* * Find an unused command packet */ struct mscp * tmscpgetcp(sc) register struct tmscp_softc *sc; { register struct mscp *mp = NULL; struct tmscpca *cp; register int i; int s; segm seg5; s = spl5(); saveseg5(seg5); mapseg5(tmscp[sc->sc_unit], MAPBUFDESC); cp = &sc->sc_com->tmscp_ca; /* * If no credits, can't issue any commands * until some outstanding commands complete. */ i = sc->sc_lastcmd; #ifdef TMSCP_DEBUG printd10("tmscpgetcp: %d credits remain\n", sc->sc_credits); #endif if(((cp->ca_cmddsc[i].hsh&(TMSCP_OWN|TMSCP_INT))==TMSCP_INT) && (sc->sc_credits >= 2)) { sc->sc_credits--; /* This commits to issuing a command */ cp->ca_cmddsc[i].hsh &= ~TMSCP_INT; mp = &sc->sc_com->tmscp_cmd[i]; mp->mscp_unit = mp->mscp_modifier = 0; mp->mscp_opcode = mp->mscp_flags = 0; mp->mscp_bytecnt = 0; mp->mscp_buffer_h = mp->mscp_buffer_l = 0; mp->mscp_zzz2 = 0; sc->sc_lastcmd = (i + 1) % NCMD; } restorseg5(seg5); (void) splx(s); return(mp); } /* * Initialize a TMSCP device. Set up UBA mapping registers, * initialize data structures, and start hardware * initialization sequence. */ tkini(sc) register struct tmscp_softc *sc; { register struct tmscpdevice *tmscpaddr; long adr; sc->sc_ctab.b_active++; adr = _iomap(tmscp[sc->sc_unit]) + (u_int)RINGBASE; sc->sc_ctab.b_un.b_addr = (caddr_t)loint(adr); sc->sc_ctab.b_xmem = hiint(adr); tmscpaddr = sc->sc_addr; /* * Start the hardware initialization sequence. */ tmscpaddr->tmscpip = 0; /* start initialization */ while((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0) { #ifdef TMSCP_DEBUG printd("tkini: tmscpsa = 0%o\n",tmscpaddr->tmscpsa); delay(100000L); #endif if(tmscpaddr->tmscpsa & TMSCP_ERR) return(0); /* CHECK */ } tmscpaddr->tmscpsa=TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8)|TMSCP_IE|(sc->sc_ivec/4); /* * Initialization continues in the interrupt routine. */ sc->sc_state = S_STEP1; sc->sc_credits = 0; return(1); } /* * Start I/O operation * This code is convoluted. The majority of it was copied from the uda driver. */ tmsstart(sc) register struct tmscp_softc *sc; { register struct mscp *mp; register struct buf *bp, *dp; register struct tms_info *tms; struct tmscpdevice *tmscpaddr; int i, unit; segm seg5; saveseg5(seg5); /* save just once at top */ for(;;) { if ((dp = sc->sc_ctab.b_actf) == NULL) { /* * Release unneeded UBA resources and return * (drive was inactive) */ sc->sc_ctab.b_active = 0; break; } if ((bp = dp->b_actf) == NULL) { /* * No more requests for this drive, remove * from controller queue and look at next drive. * We know we're at the head of the controller queue. */ dp->b_active = 0; sc->sc_ctab.b_actf = dp->b_forw; continue; /* Need to check for loop */ } sc->sc_ctab.b_active++; unit = TMSUNIT(bp->b_dev); tmscpaddr = (struct tmscpdevice *)sc->sc_addr; tms = sc->sc_drives[unit]; if ((tmscpaddr->tmscpsa&TMSCP_ERR) || sc->sc_state != S_RUN) { tprintf(tms->tms_ttyp, "tms%d,%d: hard error bn%ld\n", sc->sc_unit, unit, bp->b_blkno); log(TMS_PRI, "tms%d,%d: sa 0%o state %d\n", sc->sc_unit, unit, tmscpaddr->tmscpsa, sc->sc_state); (void)tkini(sc); /* SHOULD REQUEUE OUTSTANDING REQUESTS, LIKE TMSCPRESET */ break; } /* * Default is that last command was NOT a write command; * if a write command is done it will be detected in tmscprsp. */ tms->tms_lastiow = 0; if (tms->tms_online == -1) { /* not online */ if ((mp = tmscpgetcp(sc)) == NULL) break; mapseg5(tmscp[sc->sc_unit], MAPBUFDESC); mp->mscp_opcode = M_OP_ONLIN; mp->mscp_unit = unit; dp->b_active = 2; sc->sc_ctab.b_actf = dp->b_forw; /* remove from controller q */ ((Trl *)mp->mscp_dscptr)->hsh |= TMSCP_OWN|TMSCP_INT; if (tmscpaddr->tmscpsa&TMSCP_ERR) printf(tmscpfatalerr, sc->sc_unit, TMSUNIT(bp->b_dev), tmscpaddr->tmscpsa); restorseg5(seg5); i = tmscpaddr->tmscpip; continue; } if ((mp = tmscpgetcp(sc)) == NULL) break; mapseg5(tmscp[sc->sc_unit], MAPBUFDESC); mp->mscp_cmdref = (u_short)bp; /* pointer to get back */ mp->mscp_unit = unit; /* * If its an ioctl-type command then set up the appropriate * tmscp command; by doing a switch on the "b_resid" field where * the command mneumonic is stored. */ if (bp == &sc->sc_cmdbuf) { #ifdef TMSCP_DEBUG printd("tmsstart: doing ioctl cmd %d\n", bp->b_resid); #endif /* * The reccnt and tmkcnt fields are set to zero by the getcp * routine (as bytecnt and buffer fields). Thus reccnt and * tmkcnt are only modified here if they need to be set to * a non-zero value. */ switch ((int)bp->b_resid) { case TMS_WRITM: mp->mscp_opcode = M_OP_WRITM; break; case TMS_FSF: mp->mscp_opcode = M_OP_REPOS; mp->mscp_tmkcnt = bp->b_bcount; break; case TMS_BSF: mp->mscp_opcode = M_OP_REPOS; mp->mscp_modifier = M_MD_REVRS; mp->mscp_tmkcnt = bp->b_bcount; break; case TMS_FSR: mp->mscp_opcode = M_OP_REPOS; mp->mscp_modifier = M_MD_OBJCT; mp->mscp_reccnt = bp->b_bcount; break; case TMS_BSR: mp->mscp_opcode = M_OP_REPOS; mp->mscp_modifier = M_MD_REVRS | M_MD_OBJCT; mp->mscp_reccnt = bp->b_bcount; break; /* * Clear serious exception is done for Rewind & Available cmds */ case TMS_REW: mp->mscp_opcode = M_OP_REPOS; mp->mscp_modifier = M_MD_REWND | M_MD_CLSEX; if (bp->b_bcount == 0) mp->mscp_modifier |= M_MD_IMMED; tms->tms_serex = 0; break; case TMS_OFFL: mp->mscp_opcode = M_OP_AVAIL; mp->mscp_modifier = M_MD_UNLOD | M_MD_CLSEX; tms->tms_serex = 0; break; case TMS_SENSE: mp->mscp_opcode = M_OP_GTUNT; break; case TMS_CACHE: mp->mscp_opcode = M_OP_STUNT; tms->tms_unitflgs |= M_UF_WBKNV; mp->mscp_unitflgs = tms->tms_unitflgs; mp->mscp_format = tms->tms_format; /* default device dependant parameters */ mp->mscp_mediaid = 0; break; case TMS_NOCACHE: mp->mscp_opcode = M_OP_STUNT; tms->tms_unitflgs &= ~(M_UF_WBKNV); mp->mscp_unitflgs = tms->tms_unitflgs; mp->mscp_format = tms->tms_format; /* default device dependant parameters */ mp->mscp_mediaid = 0; break; case TMS_CSE: /* * This is a no-op command. It performs a * clear serious exception only. (Done on a * non-rewinding close after a serious exception.) */ mp->mscp_opcode = M_OP_REPOS; mp->mscp_modifier = M_MD_CLSEX; tms->tms_serex = 0; tms->tms_clserex = 1; break; case TMS_SETDENSITY: /* * Set the unit density */ mp->mscp_opcode = M_OP_STUNT; mp->mscp_unitflgs = tms->tms_unitflgs; mp->mscp_mediaid = 0; /* default device dependant parameters */ mp->mscp_format = Dmatrix[TMSDENS(bp->b_dev)][tms->tms_fmtmenu & FMTMASK]; #ifdef TMSCP_DEBUG printd("b_dev: 0%o fmtmenu: 0%o format: 0%o\n", bp->b_dev, tms->tms_fmtmenu, mp->mscp_format); delay(4000000L); #endif tms->tms_format = mp->mscp_format; break; default: printf("tms%d,%d bad ioctl\n",sc->sc_unit,mp->mscp_unit); /* Need a no-op. Reposition no amount */ mp->mscp_opcode = M_OP_REPOS; break; } /* end switch (bp->b_resid) */ } else /* Its a read/write command (not an ioctl) */ { mp->mscp_opcode = bp->b_flags&B_READ ? M_OP_READ : M_OP_WRITE; mp->mscp_bytecnt = bp->b_bcount; mp->mscp_buffer_l = (u_short) bp->b_un.b_addr; mp->mscp_buffer_h = bp->b_xmem; } if (tms->tms_serex == 2) /* if tape mark read */ { mp->mscp_modifier |= M_MD_CLSEX; /* clear serious exc */ tms->tms_serex = 0; } ((Trl *)mp->mscp_dscptr)->hsh |= TMSCP_OWN|TMSCP_INT; #ifdef TMSCP_DEBUG printd("tmsstart: opcode 0%o mod %o unit %d cnt %d\n",mp->mscp_opcode,mp->mscp_modifier,mp->mscp_unit,mp->mscp_bytecnt); if(tmscpdebug)delay(100000L); #endif i = tmscpaddr->tmscpip; /* initiate polling */ dp->b_qsize++; /* * Move drive to the end of the controller queue */ if (dp->b_forw != NULL) { sc->sc_ctab.b_actf = dp->b_forw; sc->sc_ctab.b_actl->b_forw = dp; sc->sc_ctab.b_actl = dp; dp->b_forw = NULL; } /* * Move buffer to I/O wait queue */ dp->b_actf = bp->av_forw; dp = &sc->sc_wtab; bp->av_forw = dp; bp->av_back = dp->av_back; dp->av_back->av_forw = bp; dp->av_back = bp; if (tmscpaddr->tmscpsa&TMSCP_ERR) { printf(tmscpfatalerr,sc->sc_unit, mp->mscp_unit, tmscpaddr->tmscpsa); (void)tkini(sc); break; } } /* end for */ /* * Check for response ring transitions lost in the * Race condition. Map SEG5 in case we escaped early from the for(). */ mapseg5(tmscp[sc->sc_unit], MAPBUFDESC); for (i = sc->sc_lastrsp;; i++) { i %= NRSP; if (sc->sc_com->tmscp_ca.ca_rspdsc[i].hsh&TMSCP_OWN) break; tmscprsp(sc, i); sc->sc_com->tmscp_ca.ca_rspdsc[i].hsh |= TMSCP_OWN; } sc->sc_lastrsp = i; restorseg5(seg5); } /* * Process a response packet. N.B. Assumes SEG5 maps comm area for controller */ tmscprsp(sc, i) register struct tmscp_softc *sc; int i; { register struct mscp *mp; register struct tms_info *tms; struct buf *dp, *bp; int st; mp = &sc->sc_com->tmscp_rsp[i]; mp->mscp_header.tmscp_msglen = mscp_msglen; sc->sc_credits += mp->mscp_header.tmscp_credits & 0xf; /* low 4 bits */ if ((mp->mscp_header.tmscp_credits & 0xf0) > 0x10) /* Check */ return; #ifdef TMSCP_DEBUG printd("tmscprsp, opcode 0%o status 0%o\n",mp->mscp_opcode,mp->mscp_status&M_ST_MASK); printd(" SEG5: 0%o sc: 0%o mp: 0%o i: %d\n",*KDSA5, sc, mp, i); #endif /* * If it's an error log message (datagram), * pass it on for more extensive processing. */ if ((mp->mscp_header.tmscp_credits & 0xf0) == 0x10) { /* check */ tmserror(sc->sc_unit, (struct mslg *)mp); return; } st = mp->mscp_status&M_ST_MASK; /* * The controller interrupts as drive 0. * This means that you must check for controller interrupts * before you check to see if there is a drive 0. */ if((M_OP_STCON|M_OP_END) == mp->mscp_opcode) { if (st == M_ST_SUCC) { #ifdef TMSCP_DEBUG printd("ctlr has %d credits\n", mp->mscp_header.tmscp_credits & 0xf); printd("ctlr timeout = %d\n", mp->mscp_cnttmo); #endif sc->sc_state = S_RUN; } else sc->sc_state = S_IDLE; sc->sc_ctab.b_active = 0; wakeup((caddr_t)&sc->sc_ctab); return; } if (mp->mscp_unit >= 4) return; tms = sc->sc_drives[mp->mscp_unit]; if (!tms) /* unopened unit coming online - ignore it */ return; /* * Save endcode, endflags, and status for mtioctl get unit status. * NOTE: Don't do this on Clear serious exception (reposition no-op); * which is done on close since this would * overwrite the real status we want. */ if (tms->tms_clserex != 1) { tms->tms_endcode = mp->mscp_opcode; tms->tms_flags = mp->mscp_flags; tms->tms_status = st; } else tms->tms_clserex = 0; switch (mp->mscp_opcode) { case M_OP_ONLIN|M_OP_END: tms->tms_type = mp->mscp_mediaid; dp = &tms->tms_dtab; if (st == M_ST_SUCC) { /* * Link the drive onto the controller queue */ dp->b_forw = NULL; if (sc->sc_ctab.b_actf == NULL) sc->sc_ctab.b_actf = dp; else sc->sc_ctab.b_actl->b_forw = dp; sc->sc_ctab.b_actl = dp; tms->tms_online = 1; /* mark it online */ tms->tms_dsize=(daddr_t)mp->mscp_maxwrt; /* * This define decodes the Media type identifier */ #ifdef TMSCP_DEBUG printd("tmscprsp: %d,%d online mediaid 0x%lx format 0x%x\n", sc->sc_unit, mp->mscp_unit, mp->mscp_mediaid, mp->mscp_format); #endif dp->b_active = 1; } /* end if st == M_ST_SUCC */ else { if (bp = dp->b_actf) tprintf(tms->tms_ttyp, "tms%d,%d: hard error bn%ld: OFFLINE\n", sc->sc_unit, mp->mscp_unit, bp->b_blkno); else tprintf(tms->tms_ttyp, "tms%d,%d: hard error: OFFLINE\n", sc->sc_unit, mp->mscp_unit); while (bp = dp->b_actf) { dp->b_actf = bp->av_forw; bp->b_flags |= B_ERROR; iodone(bp); } } if(mp->mscp_cmdref!=NULL) /* Seems to get lost sometimes in uda */ wakeup((caddr_t)mp->mscp_cmdref); break; /* * The AVAILABLE ATTENTION message occurs when the * unit becomes available after loading, * marking the unit offline (tms_online = -1) will force an * online command prior to using the unit. */ case M_OP_AVATN: tms->tms_online = -1; tms->tms_type = mp->mscp_mediaid; break; case M_OP_END: /* * An endcode without an opcode (0200) is an invalid command. * The mscp specification states that this would be a protocol * type error, such as illegal opcodes. The mscp spec. also * states that parameter error type of invalid commands should * return the normal end message for the command. This does not appear * to be the case. An invalid logical block number returned an endcode * of 0200 instead of the 0241 (read) that was expected. */ printf("tms%d,%d: invalid cmd endcode = %o status=%o\n", sc->sc_unit, mp->mscp_unit, mp->mscp_opcode, st); common: /* GTUNT finishes up thru here too */ bp = (struct buf *)mp->mscp_cmdref; /* * Unlink buffer from I/O wait queue. * And signal iodone, so the higher level command can exit! * */ bp->av_back->av_forw = bp->av_forw; bp->av_forw->av_back = bp->av_back; dp = &tms->tms_dtab; dp->b_qsize--; iodone(bp); break; case M_OP_WRITE|M_OP_END: /* mark the last io op as a write */ tms->tms_lastiow = 1; case M_OP_READ|M_OP_END: case M_OP_WRITM|M_OP_END: case M_OP_REPOS|M_OP_END: case M_OP_STUNT|M_OP_END: /* * The AVAILABLE message occurs when the mt ioctl "rewoffl" is * issued. For the ioctl, "rewoffl", a tmscp AVAILABLE command is * done with the UNLOAD modifier. This performs a rewind, followed * by marking the unit offline. So mark the unit offline * software wise as well (tms->tms_online = -1 and tms_open = 0). */ case M_OP_AVAIL|M_OP_END: #ifdef TMSCP_DEBUG printd("tmscprsp: position = %u,%u\n", mp->mscp_lbn_h,mp->mscp_lbn_l); #endif bp = (struct buf *)mp->mscp_cmdref; /* * Unlink buffer from I/O wait queue. */ bp->av_back->av_forw = bp->av_forw; bp->av_forw->av_back = bp->av_back; dp = &tms->tms_dtab; dp->b_qsize--; if (st == M_ST_OFFLN || st == M_ST_AVLBL) { tms->tms_online = -1; /* mark unit offline */ tms->tms_openf = 0; tms->tms_type = mp->mscp_mediaid; /* * Link the buffer onto the front of the drive queue */ if ((bp->av_forw = dp->b_actf) == 0) dp->b_actl = bp; dp->b_actf = bp; /* * Link the drive onto the controller queue */ if (dp->b_active == 0) { dp->b_forw = NULL; if (sc->sc_ctab.b_actf == NULL) sc->sc_ctab.b_actf = dp; else sc->sc_ctab.b_actl->b_forw = dp; sc->sc_ctab.b_actl = dp; dp->b_active = 1; } return; } if (st != M_ST_SUCC) { if (mp->mscp_flags & M_EF_SEREX) tms->tms_serex = 1; if (st != M_ST_TAPEM) { tprintf(tms->tms_ttyp, "tms%d,%d: hard err bn%ld status:0%o flags:0%o\n", sc->sc_unit, mp->mscp_unit, bp->b_blkno, mp->mscp_status, mp->mscp_flags); bp->b_flags |= B_ERROR; } else /* Hit a tape mark - Set serex flag to * a special value so we can clear the * serious exception on the next command. */ tms->tms_serex = 2; } /* * The tmscp spec states that controllers do not have to * report the number of records or files skipped. So on * reposition commands we go strictly by cmd status. */ if (mp->mscp_opcode != (M_OP_REPOS|M_OP_END)) bp->b_resid = bp->b_bcount - mp->mscp_bytecnt; else bp->b_resid = 0; tms->tms_resid = bp->b_resid; iodone(bp); break; case M_OP_GTUNT|M_OP_END: #ifdef TMSCP_DEBUG printd("tmscprsp: GTUNT end packet status = 0%o\n",st); printd("tmscprsp: %d,%d mediaid 0x%lx 0x%lx 0x%lx format=%d speed = %d\n", sc->sc_unit,mp->mscp_unit, mp->mscp_mediaid ,mp->mscp_unitid.val[0] ,mp->mscp_unitid.val[1] ,mp->mscp_format, mp->mscp_speed); #endif tms->tms_type = mp->mscp_mediaid; tms->tms_fmtmenu = mp->mscp_fmtmenu; tms->tms_unitflgs = mp->mscp_unitflgs; goto common; /* need to dequeue buffer and do iodone() */ default: printf("tms%d,%d unknown packet\n", sc->sc_unit,mp->mscp_unit); tmserror(sc->sc_unit, (struct mslg *)mp); } /* end switch mp->mscp_opcode */ } /* * Manage buffers and perform block mode read and write operations. */ tmscpstrategy (bp) register struct buf *bp; { register struct buf *dp; register struct tmscp_softc *sc; struct tms_info *tms; int ctlr = TMSCTLR(bp->b_dev); int s; sc = &tmscp_softc[ctlr]; tms = sc->sc_drives[TMSUNIT(bp->b_dev)]; if (!tms || tms->tms_online != 1) { bp->b_flags |= B_ERROR; iodone(bp); return; } mapalloc(bp); s = spl5(); /* * Link the buffer onto the drive queue */ dp = &tms->tms_dtab; if (dp->b_actf == 0) dp->b_actf = bp; else dp->b_actl->av_forw = bp; dp->b_actl = bp; bp->av_forw = 0; /* * Link the drive onto the controller queue */ if (dp->b_active == 0) { dp->b_forw = NULL; if (sc->sc_ctab.b_actf == NULL) sc->sc_ctab.b_actf = dp; else sc->sc_ctab.b_actl->b_forw = dp; sc->sc_ctab.b_actl = dp; dp->b_active = 1; } /* * If the controller is not active, start it. */ if (sc->sc_ctab.b_active == 0) { #ifdef TMSCP_DEBUG printd10("tmscpstrategy: Controller not active, starting it\n"); #endif (void) tmsstart(sc); } splx(s); return; } #ifdef TMSCP_DUMP #define DBSIZE 16 tmsdump(dev) dev_t dev; { register struct tmscpdevice *tmscpaddr; register struct tmscp_softc *sc; register struct mscp *mp; daddr_t bn, dumpsize; long paddr, maddr; int unit = TMSUNIT(dev), count, ctlr = TMSCTLR(dev); struct ubmap *ubp; segm seg5; if (ctlr >= NTMSCP) return (ENXIO); sc = &tmscp_softc[ctlr]; tmscpaddr = sc->sc_addr; if (tmscpaddr == NULL) return(ENXIO); paddr = _iomap(tmscp[sc->sc_unit]); if (ubmap) { ubp = UBMAP; ubp->ub_lo = loint(paddr); ubp->ub_hi = hiint(paddr); } paddr += RINGBASE; saveseg5(seg5); mapseg5(tmscp[sc->sc_unit], MAPBUFDESC); mp = sc->sc_com->tmscp_rsp; sc->sc_com->tmscp_ca.ca_cmdint = sc->sc_com->tmscp_ca.ca_rspint = 0; bzero(mp, 2 * sizeof (*mp)); tmscpaddr->tmscpip = 0; while ((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0) if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); tmscpaddr->tmscpsa = TMSCP_ERR; while ((tmscpaddr->tmscpsa & TMSCP_STEP2) == 0) if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); tmscpaddr->tmscpsa = loint(paddr); while ((tmscpaddr->tmscpsa & TMSCP_STEP3) == 0) if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); tmscpaddr->tmscpsa = hiint(paddr); while ((tmscpaddr->tmscpsa & TMSCP_STEP4) == 0) if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); tmscpaddr->tmscpsa = TMSCP_GO; tmsginit(sc, sc->sc_com->tmscp_ca.ca_rspdsc, mp, 0, 2, 0); if (tmscpcmd(M_OP_STCON, unit, sc) == 0) { return(EFAULT); } sc->sc_com->tmscp_cmd[0].mscp_unit = unit; if (tmscpcmd(M_OP_ONLIN, unit, sc) == 0) { return(EFAULT); } dumpsize = 8 * 1024L; /* XXX */ ubp = &UBMAP[1]; for (paddr = 0; dumpsize > 0; dumpsize -= count) { count = MIN(dumpsize, DBSIZE); bn = paddr >> PGSHIFT; maddr = paddr; if (ubmap) { ubp->ub_lo = loint(paddr); ubp->ub_hi = hiint(paddr); maddr = (u_int)(1 << 13); } /* write it to the tape */ mp = &sc->sc_com->tmscp_rsp[1]; mp->mscp_lbn_l = loint(bn); mp->mscp_lbn_h = hiint(bn); mp->mscp_bytecnt = count * NBPG; mp->mscp_buffer_l = loint(maddr); mp->mscp_buffer_h = hiint(maddr); if (tmscpcmd(M_OP_WRITE, unit, sc) == 0) return(EIO); paddr += (DBSIZE << PGSHIFT); } restorseg5(seg5); return (0); } /* * Perform a standalone tmscp command. This routine is only used by tmscpdump. */ tmscpcmd(op, unit, sc) int op; int unit; register struct tmscp_softc *sc; { int i; register struct mscp *cmp, *rmp; Trl *rlp; cmp = &sc->sc_com->tmscp_rsp[1]; rmp = &sc->sc_com->tmscp_rsp[0]; rlp = &sc->sc_com->tmscp_ca.ca_rspdsc[0]; cmp->mscp_opcode = op; cmp->mscp_unit = unit; cmp->mscp_header.tmscp_msglen = mscp_msglen; rmp->mscp_header.tmscp_msglen = mscp_msglen; rlp[0].hsh |= TMSCP_OWN|TMSCP_INT; rlp[1].hsh |= TMSCP_OWN|TMSCP_INT; if (sc->sc_addr->tmscpsa&TMSCP_ERR) printf(tmscpfatalerr, sc->sc_unit, unit, sc->sc_addr->tmscpsa); i = sc->sc_addr->tmscpip; while ((rlp[1].hsh & TMSCP_INT) == 0) ; while ((rlp[0].hsh & TMSCP_INT) == 0) ; sc->sc_com->tmscp_ca.ca_rspint = 0; sc->sc_com->tmscp_ca.ca_cmdint = 0; if (rmp->mscp_opcode != (op|M_OP_END) || (rmp->mscp_status&M_ST_MASK) != M_ST_SUCC) { printf("err: com %d opc 0x%x stat 0x%x\ndump ", op, rmp->mscp_opcode, rmp->mscp_status); return(0); } return(1); } #endif TMSCP_DUMP /* * Catch ioctl commands, and call the "command" routine to do them. */ /* ARGSUSED */ tmscpioctl(dev, cmd, data, flag) dev_t dev; int cmd; caddr_t data; int flag; { struct tmscp_softc *sc = &tmscp_softc[TMSCTLR(dev)]; register struct buf *bp = &sc->sc_cmdbuf; register callcount; /* number of times to call cmd routine */ register struct tms_info *tms; int fcount; /* number of files (or records) to space */ register struct mtop *mtop; /* mag tape cmd op to perform */ register struct mtget *mtget; /* mag tape struct to get info in */ /* we depend of the values and order of the TMS ioctl codes here */ static u_char tmsops[] = {TMS_WRITM,TMS_FSF,TMS_BSF,TMS_FSR,TMS_BSR,TMS_REW,TMS_OFFL,TMS_SENSE, TMS_CACHE,TMS_NOCACHE}; switch (cmd) { case MTIOCTOP: /* tape operation */ mtop = (struct mtop *)data; switch (mtop->mt_op) { case MTWEOF: callcount = mtop->mt_count; fcount = 1; break; case MTFSF: case MTBSF: case MTFSR: case MTBSR: callcount = 1; fcount = mtop->mt_count; break; case MTREW: case MTOFFL: case MTNOP: case MTCACHE: case MTNOCACHE: callcount = 1; fcount = 1; /* wait for this rewind */ break; default: return (ENXIO); } /* end switch mtop->mt_op */ if (callcount <= 0 || fcount <= 0) return (EINVAL); while (--callcount >= 0) { tmscpcommand(dev, tmsops[mtop->mt_op], fcount); if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && bp->b_resid) return (EIO); if (bp->b_flags & B_ERROR) /* like hitting BOT */ break; } return (geterror(bp)); case MTIOCGET: /* * Return status info associated with the particular UNIT. */ tms = sc->sc_drives[TMSUNIT(dev)]; if (!tms) return(ENXIO); mtget = (struct mtget *)data; mtget->mt_type = MT_ISTMSCP; mtget->mt_dsreg = tms->tms_flags << 8; mtget->mt_dsreg |= tms->tms_endcode; mtget->mt_erreg = tms->tms_status; mtget->mt_resid = tms->tms_resid; break; default: return (ENXIO); } return (0); } /* * Process an error log message * * Only minimal decoding is done, only "useful" * information is printed. Eventually should * send message to an error logger. */ tmserror(ctlr, mp) register int ctlr; register struct mslg *mp; { register i; #ifdef TMSCP_DEBUG printd("tmserror:\n"); #endif if(!(mp->mslg_flags & (M_LF_SUCC | M_LF_CONT))) log(TMS_PRI, "tms%d,%d: %s err ", ctlr, mp->mslg_unit, mp->mslg_flags & ( M_LF_SUCC | M_LF_CONT ) ? "soft" : "hard"); switch (mp->mslg_format) { case M_FM_CNTERR: log(TMS_PRI, "ctlr err event 0%o\n", mp->mslg_event); break; case M_FM_BUSADDR: log(TMS_PRI, "host memory access err, event 0%o, addr 0%o\n", mp->mslg_event, mp->mslg_busaddr); break; case M_FM_TAPETRN: log(TMS_PRI, "tape transfer err unit %d grp 0x%x event 0%o\n", mp->mslg_unit, mp->mslg_group, mp->mslg_event); break; case M_FM_STIERR: log(TMS_PRI, "STI err unit %d event 0%o\n", mp->mslg_unit, mp->mslg_event); #ifdef notdef /* too painful to do with log() */ for(i = 0; i < 62;i++) mprintf("\t0x%x",mp->mslg_stiunsucc[i] & 0xff); mprintf("\n"); #endif break; case M_FM_STIDEL: log(TMS_PRI, "STI Drive ErrorLog unit %d event 0%o\n", mp->mslg_unit, mp->mslg_event); break; case M_FM_STIFEL: log(TMS_PRI, "STI Formatter ErrorLog unit %d event 0%o\n", mp->mslg_unit, mp->mslg_event); break; default: log(TMS_PRI, "unknown err %d,%d format 0%o event 0%o\n", ctlr,mp->mslg_unit, mp->mslg_format, mp->mslg_event); } if (tmscperror) { register long *p = (long *)mp; for (i = 0; i < mp->mslg_header.tmscp_msglen; i += sizeof(*p)) printf("%x ", *p++); printf("\n"); } } #endif NTMSCP -; if (st == M_ST_OFFLN || st == M_ST_AVLBL) { tms->tms_online = -1; /* mark unit offlinsys/bootrom/ 755 0 12 0 4011550004 6227 sys/bootrom/siboot.s 444 0 12 2734 3565564004 10025 /********** / / boot rom for si 9500 disk drive / /********** reset = 5 nop = 240 / name code of boot rom 0176 / offset to next rom sec / entry point, unit 0, no diagnostics mov $0,r0 / entry point, unit 0, with diagnostics mov $176700,r1 / load csr into r1 mov pc,r4 / for link bcc diag / go do diagnostics if C set br begin / skip next stuff 0173000 / pc on power up boot 0340 / psw on power up boot begin: reset / reset unibus devices mov r0,r3 / move unit to r3 bis $01300,sp / get some stack mov 24(r1),r0 / load shared computer register to r0 bit $200,r0 / see if grant bit is set bne 1f / set, is dual ported mov 12(r1),r0 / move error register to r0 bic $037777,r0 / clear all but error and contention cmp $140000,r0 / see if contention error bne 2f / nope, must be normal 9500 1: bit $200,24(r1) / test for grant bne 2f / got it clr (r1) / issue login master clear to 9500 mov $1,24(r1) / set request br 1b / loop until grant 2: mov $400,2(r1) / set for 512 bytes clr 6(r1) / set for head 0, sector 0 clr 10(r1) / set to read at zero bic $177774,r3 / clear all but bottom bits ash $12,r3 / shift unit number mov r3,4(r1) / set unit number mov $5,(r1) / start the read 3: tstb (r1) / test for done bpl 3b / wait for it tst 12(r1) / see if error occured bpl 4f / nope, all ok br begin / try again 4: clr pc / jump to zero diag: jmp *$165564 / go do diagnostics nop nop ); break; case M_FM_STIFEL: logsys/bootrom/tags 751 0 12 0 6045324647 11061 2../sys/tagssys/conf/ 755 0 12 0 6046604513 5512 sys/conf/boot/ 755 0 12 0 5553146462 6463 sys/conf/boot/dvhpboot.s 440 0 12 4143 5003736572 10552 /* * SCCS id @(#)dvhpboot.s 2.0 (2.11BSD) 4/13/91 */ #include "localopts.h" / The boot options and device are placed in the last SZFLAGS bytes / at the end of core for the bootstrap. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 / boot unit CHECKWORD= 6 .globl _doboot, hardboot, _bootcsr .text _doboot: mov 4(sp),r4 / boot options mov 2(sp),r3 / boot device #ifndef KERN_NONSEP / If running separate I/D, need to turn off memory management. / Call the routine unmap in low text, after setting up a jump / in low data where the PC will be pointing. .globl unmap mov $137,*$unmap+2 / jmp *$hardboot mov $hardboot,*$unmap+4 jmp unmap / "return" from unmap will be to hardboot in data .data #else / Reset to turn off memory management reset #endif / On power fail, hardboot is the entry point (map is already off) / and the args are in r4 (RB_POWRFAIL), r3 (rootdev) hardboot: mov r4, ENDCORE-BOOTOPTS ash $-3,r3 / shift out the partition number bic $!7,r3 / save only the drive number mov r3, ENDCORE-BOOTDEV com r4 / if CHECKWORD == ~bootopts, flags are believed mov r4, ENDCORE-CHECKWORD 1: reset / The remainder of the code is dependent on the boot device. / If you have a bootstrap ROM, just jump to the correct entry. / Otherwise, use a BOOT opcode, if available; / if necessary, read in block 0 to location 0 "by hand". / / Bootstrap for DIVA Comp/V controller without boot opcode / HPCSR= 0 / offset from base csr HPCS2= 10 / Control/status register 2 HPDC= 34 / Desired cylinder HPBAE= 50 / Bus extension address (RH70) READIT= 71 mov _bootcsr,r1 / boot device csr 1: tstb (r1) / wait for ready (HPCSR is offset 0) bpl 1b clr HPDC(r1) / Cylinder 0 clr HPBAE / Bus extension address = 0 add $HPCS2,r1 mov ENDCORE-BOOTDEV,(r1) / unit number clr -(r1) / hpda = 0 (desired address 0) clr -(r1) / hpba = 0 (buf address 0) mov $-256.,-(r1) / hpwc = -256 (one block) mov $READIT,-(r1) / hpcs1 = HP_RCOM|HP_GO 1: tstb (r1) / wait for done bpl 1b mov ENDCORE-BOOTDEV,r0 clr pc he front of the drive queue */ if ((bp->av_forw = dp->b_actf) == 0) dp->b_actl = bp; dp->b_actf = bp; /* * Link the drive onto the controller queue */ if (dp->b_active == 0) { dp->b_forw = NULL; if (sc->sc_ctab.b_actf == NULL) sc->sc_ctab.b_actf = dp; else sc->sc_ctab.b_actl->b_forw = dp; sc->sc_ctab.b_actl = dp; dp->b_active = 1; } return; sys/conf/boot/NONEboot.s 440 0 12 436 4016741660 10326 /* * SCCS id @(#)NONEboot.s 1.2 (Berkeley) 2/19/87 */ / The intention is for this file to be used if a boot program isn't / available for a particulare drive/controller, or the autoboot / feature isn't desired. halt = 0 .globl _doboot, hardboot _doboot: hardboot: halt / die ... sys/conf/boot/rlboot.s 440 0 12 4077 5003736626 10234 /* * SCCS id @(#)rlboot.s 2.0 (2.11BSD) 4/13/91 */ #include "localopts.h" / The boot options and device are placed in the last SZFLAGS bytes / at the end of core for the bootstrap. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 / boot unit CHECKWORD= 6 .globl _doboot, hardboot, _bootcsr .text _doboot: mov 4(sp),r4 / boot options mov 2(sp),r3 / boot device #ifndef KERN_NONSEP / If running separate I/D, need to turn off memory management. / Call the routine unmap in low text, after setting up a jump / in low data where the PC will be pointing. .globl unmap mov $137,*$unmap+2 / jmp *$hardboot mov $hardboot,*$unmap+4 jmp unmap / "return" from unmap will be to hardboot in data .data #else / Reset to turn off memory management reset #endif / On power fail, hardboot is the entry point (map is already off) / and the args are in r4 (RB_POWRFAIL), r3 (rootdev) hardboot: mov r4, ENDCORE-BOOTOPTS ash $-3,r3 / shift out the partition number bic $!7,r3 / save only the drive number mov r3, ENDCORE-BOOTDEV com r4 / if CHECKWORD == ~bootopts, flags are believed mov r4, ENDCORE-CHECKWORD 1: reset / The remainder of the code is dependent on the boot device. / If you have a bootstrap ROM, just jump to the correct entry. / Otherwise, use a BOOT opcode, if available; / if necessary, read in block 0 to location 0 "by hand". / Bootstrap for rl01/02 drive - salkind@nyu WC = -256. READ = 6\<1 SEEK = 3\<1 RDHDR = 4\<1 rlcs = 0 rlba = 2 rlda = 4 rlmp = 6 mov _bootcsr,r1 mov ENDCORE-BOOTDEV,r2 bis $RDHDR,r2 mov r2,rlcs(r1) /find out where we are (cyl) 1: tstb rlcs(r1) bpl 1b mov rlmp(r1),r0 bic $!77600,r0 bis $1,r0 mov r0,rlda(r1) mov ENDCORE-BOOTDEV,r2 bis $SEEK,r2 mov r2,rlcs(r1) / move it 1: tstb rlcs(r1) bpl 1b / add $rlmp,r1 mov $WC,(r1) /wc into rlmp clr -(r1) /da into rlda clr -(r1) /ba mov ENDCORE-BOOTDEV,r2 bis $READ,r2 mov r2,-(r0) /cmd into rlcs 1: tstb rlcs(r1) bpl 1b / mov ENDCORE-BOOTDEV,r0 clr pc / and away we go 1b mov ENDCORE-BOOTDEV,r0 clr pc he front of the drive queue */ if ((bp->av_forw = dp->b_actf) == 0) dp->b_actl = bp; dp->b_actf = bp; /* * Link the drive onto the controller queue */ if (dp->b_active == 0) { dp->b_forw = NULL; if (sc->sc_ctab.b_actf == NULL) sc->sc_ctab.b_actf = dp; else sc->sc_ctab.b_actl->b_forw = dp; sc->sc_ctab.b_actl = dp; dp->b_active = 1; } return; sys/conf/boot/rmboot.s 440 0 12 3601 5003736637 10227 /* * SCCS id @(#)rmboot.s 2.0 (2.11BSD) 4/13/91 */ #include "localopts.h" / The boot options and device are placed in the last SZFLAGS bytes / at the end of core for the bootstrap. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 / boot unit CHECKWORD= 6 .globl _doboot, hardboot, _bootcsr .text _doboot: mov 4(sp),r4 / boot options mov 2(sp),r3 / boot device #ifndef KERN_NONSEP / If running separate I/D, need to turn off memory management. / Call the routine unmap in low text, after setting up a jump / in low data where the PC will be pointing. .globl unmap mov $137,*$unmap+2 / jmp *$hardboot mov $hardboot,*$unmap+4 jmp unmap / "return" from unmap will be to hardboot in data .data #else / Reset to turn off memory management reset #endif / On power fail, hardboot is the entry point (map is already off) / and the args are in r4 (RB_POWRFAIL), r3 (rootdev) hardboot: mov r4, ENDCORE-BOOTOPTS ash $-3,r3 / shift out the partition number bic $!7,r3 / save only the drive number mov r3, ENDCORE-BOOTDEV com r4 / if CHECKWORD == ~bootopts, flags are believed mov r4, ENDCORE-CHECKWORD 1: reset / The remainder of the code is dependent on the boot device. / If you have a bootstrap ROM, just jump to the correct entry. / Otherwise, use a BOOT opcode, if available; / if necessary, read in block 0 to location 0 "by hand". / rm02/3/5 bootstrap - salkind@nyu WC = -256. READ = 70 GO = 1 PRESET = 20 FMT22 = 10000 DRIVE = 0 rmcs1 = 0 rmda = rmcs1+6 rmcs2 = rmcs1+10 rmds = rmcs1+12 rmof = rmcs1+32 rmca = rmcs1+34 mov _bootcsr,r1 mov ENDCORE-BOOTDEV,rmcs2(r1) mov $PRESET+GO,rmcs1(r1) mov $FMT22,rmof(r1) clr rmca(r1) add $rmcs2,r1 mov ENDCORE-BOOTDEV,(r1) clr -(r1) clr -(r1) mov $WC,-(r1) mov $READ+GO,-(r1) 1: tstb (r1) bge 1b mov ENDCORE-BOOTDEV,r0 clr pc mp clr -(r1) /da into rlda clr -(r1) /ba mov ENDCORE-BOOTDEV,r2 bis $READ,r2 mov r2,-(r0) /cmd into rlcs 1: tstb rlcs(rsys/conf/boot/sc11boot.s 440 0 12 3305 5003736645 10360 /* * SCCS id @(#)sc11boot.s 2.0 (2.11BSD) 4/13/91 */ #include "localopts.h" / The boot options and device are placed in the last SZFLAGS bytes / at the end of core for the bootstrap. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 / boot unit CHECKWORD= 6 .globl _doboot, hardboot, _bootcsr .text _doboot: mov 4(sp),r4 / boot options mov 2(sp),r3 / boot device #ifndef KERN_NONSEP / If running separate I/D, need to turn off memory management. / Call the routine unmap in low text, after setting up a jump / in low data where the PC will be pointing. .globl unmap mov $137,*$unmap+2 / jmp *$hardboot mov $hardboot,*$unmap+4 jmp unmap / "return" from unmap will be to hardboot in data .data #else / Reset to turn off memory management reset #endif / On power fail, hardboot is the entry point (map is already off) / and the args are in r4 (RB_POWRFAIL), r3 (rootdev) hardboot: mov r4, ENDCORE-BOOTOPTS ash $-3,r3 / shift out the partition number bic $!7,r3 / save only the drive number mov r3, ENDCORE-BOOTDEV com r4 / if CHECKWORD == ~bootopts, flags are believed mov r4, ENDCORE-CHECKWORD 1: reset / The remainder of the code is dependent on the boot device. / If you have a bootstrap ROM, just jump to the correct entry. / Otherwise, use a BOOT opcode, if available; / if necessary, read in block 0 to location 0 "by hand". / Bootstrap for Emulex SC11/B with boot opcode RMCS1= 0 RMCS2= 10 BOOT= 75 mov _bootcsr,r1 mov ENDCORE-BOOTDEV, RMCS2(r1) mov $BOOT,(r1) 2: tstb (r1) bpl 2b / wait for done (RDY) tst (r1) bmi 1b / try again on error (TRE) mov ENDCORE-BOOTDEV,r0 clr pc mov $FMT22,rmof(r1) clr rmca(r1) add $rmcs2,r1 mov ENDCORE-BOOTDEV,(r1) clr -(r1) clr -(r1) mov $WC,-(r1) mov $READ+GO,-(r1) 1: tstb (r1) bge 1b mov ENDCORE-BOOTDEV,r0 clr pc mp clr -(r1) /da into rlda clr -(r1) /ba mov ENDCORE-BOOTDEV,r2 bis $READ,r2 mov r2,-(r0) /cmd into rlcs 1: tstb rlcs(rsys/conf/boot/sc21boot.s 440 0 12 3372 5003736653 10364 /* * SCCS id @(#)sc21boot.s 2.0 (2.11BSD) 4/13/91 */ #include "localopts.h" / The boot options and device are placed in the last SZFLAGS bytes / at the end of core for the bootstrap. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 / boot unit CHECKWORD= 6 .globl _doboot, hardboot, _bootcsr .text _doboot: mov 4(sp),r4 / boot options mov 2(sp),r3 / boot device #ifndef KERN_NONSEP / If running separate I/D, need to turn off memory management. / Call the routine unmap in low text, after setting up a jump / in low data where the PC will be pointing. .globl unmap mov $137,*$unmap+2 / jmp *$hardboot mov $hardboot,*$unmap+4 jmp unmap / "return" from unmap will be to hardboot in data .data #else / Reset to turn off memory management reset #endif / On power fail, hardboot is the entry point (map is already off) / and the args are in r4 (RB_POWRFAIL), r3 (rootdev) hardboot: mov r4, ENDCORE-BOOTOPTS ash $-3,r3 / shift out the partition number bic $!7,r3 / save only the drive number mov r3, ENDCORE-BOOTDEV com r4 / if CHECKWORD == ~bootopts, flags are believed mov r4, ENDCORE-CHECKWORD 1: reset / The remainder of the code is dependent on the boot device. / If you have a bootstrap ROM, just jump to the correct entry. / Otherwise, use a BOOT opcode, if available; / if necessary, read in block 0 to location 0 "by hand". / Bootstrap for Emulex SC21 with boot opcode RMCS1= 0 RMCS2= 10 RMHR= 36 BOOT= 75 mov _bootcsr,r1 mov ENDCORE-BOOTDEV, RMCS2(r1) mov $-1, RMHR(r1) / enable extended opcodes mov $BOOT,(r1) 2: tstb (r1) bpl 2b / wait for done (RDY) tst (r1) bmi 1b / try again on error (TRE) mov ENDCORE-BOOTDEV,r0 clr pc / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 / boot unit CHECKWORD= 6 .globl _doboot, hardboot, _bootcsr .text _doboot: mov 4(sp),r4 / boot options mov 2(sp),r3 / boot device #ifndef KERN_NONSEP / If running sepsys/conf/boot/siboot.s 440 0 12 4504 5003736661 10224 /* * SCCS id @(#)siboot.s 2.0 (2.11BSD) 4/13/91 */ #include "localopts.h" / The boot options and device are placed in the last SZFLAGS bytes / at the end of core for the bootstrap. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 / boot unit CHECKWORD= 6 .globl _doboot, hardboot, _bootcsr .text _doboot: mov 4(sp),r4 / boot options mov 2(sp),r3 / boot device #ifndef KERN_NONSEP / If running separate I/D, need to turn off memory management. / Call the routine unmap in low text, after setting up a jump / in low data where the PC will be pointing. .globl unmap mov $137,*$unmap+2 / jmp *$hardboot mov $hardboot,*$unmap+4 jmp unmap / "return" from unmap will be to hardboot in data .data #else / Reset to turn off memory management reset #endif / On power fail, hardboot is the entry point (map is already off) / and the args are in r4 (RB_POWRFAIL), r3 (rootdev) hardboot: mov r4, ENDCORE-BOOTOPTS ash $-3,r3 / shift out the partition number bic $!7,r3 / save only the drive number mov r3, ENDCORE-BOOTDEV com r4 / if CHECKWORD == ~bootopts, flags are believed mov r4, ENDCORE-CHECKWORD 1: reset / The remainder of the code is dependent on the boot device. / If you have a bootstrap ROM, just jump to the correct entry. / Otherwise, use a BOOT opcode, if available; / if necessary, read in block 0 to location 0 "by hand". / si 9500 bootstrap - bmarsh@nosc WC = 256. READ = 4 GO = 1 sicnr = 0 siwcr = sicnr+2 sipcr = sicnr+4 sihsr = sicnr+6 simar = sicnr+10 sierr = sicnr+12 siscr = sicnr+24 mov _bootcsr,r1 bit $200,siscr(r1) / see if grant set bne 1f / if set, is dual ported controller mov sierr(r1),r0 / load error register bic $037777,r0 / clear all but contention and error bits cmp $140000,r0 / see if we have a contention error bne 2f / if not, controller is not dual ported 1: bit $200,siscr(r1) / test for grant bne 2f / if set, ok for read clr sicnr(r1) / send logic master clear mov $1,siscr(r1) / request grant br 1b / loop until grant 2: mov ENDCORE-BOOTDEV,r0 ash $10.,r0 mov r0,sipcr(r1) / port 0 cylinder 0, unit clr sihsr(r1) / head 0 sector 0 clr simar(r1) / address 0 mov $WC,siwcr(r1) / word count mov $READ+GO,sicnr(r1) 1: tstb sicnr(r1) bge 1b mov ENDCORE-BOOTDEV,r0 clr pc NULL; if (sc->sc_ctab.b_actf == NULL) sc->sc_ctab.b_actf = dp; else sc->sc_ctab.b_actl->b_forw = dp; sc->sc_ctab.b_actl = dp; dp->b_active = 1; } return; sys/conf/boot/raboot.s 440 0 12 10651 5003736621 10227 /* * SCCS id @(#)raboot.s 2.0 (2.11BSD) 4/13/91 */ #include "localopts.h" / The boot options and device are placed in the last SZFLAGS bytes / at the end of core for the bootstrap. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 / boot unit CHECKWORD= 6 .globl _doboot, hardboot, _bootcsr .text _doboot: mov 4(sp),r4 / boot options mov 2(sp),r3 / boot device #ifndef KERN_NONSEP / If running separate I/D, need to turn off memory management. / Call the routine unmap in low text, after setting up a jump / in low data where the PC will be pointing. .globl unmap mov $137,*$unmap+2 / jmp *$hardboot mov $hardboot,*$unmap+4 jmp unmap / "return" from unmap will be to hardboot in data .data #else / Reset to turn off memory management reset #endif / On power fail, hardboot is the entry point (map is already off) / and the args are in r4 (RB_POWRFAIL), r3 (rootdev) hardboot: mov r4, ENDCORE-BOOTOPTS ash $-3,r3 / shift out the partition number bic $!7,r3 / save only the drive number mov r3, ENDCORE-BOOTDEV com r4 / if CHECKWORD == ~bootopts, flags are believed mov r4, ENDCORE-CHECKWORD 1: reset / The remainder of the code is dependent on the boot device. / If you have a bootstrap ROM, just jump to the correct entry. / Otherwise, use a BOOT opcode, if available; / if necessary, read in block 0 to location 0 "by hand". / / RA bootstrap. / / Note: this is a complex boot, but then MSCP is complex!!!! / / Bootstrap for mscp disk controller tucker@gswd-vms / MSCPSIZE = 64. / One MSCP command packet is 64bytes long (need 2) RASEMAP = 140000 / RA controller owner semaphore RAERR = 100000 / error bit RASTEP1 = 04000 / step1 has started RAGO = 01 / start operation, after init RASTCON = 4 / Setup controller info RAONLIN = 11 / Put unit on line RAREAD = 41 / Read command code RAWRITE = 42 / Write command code RAEND = 200 / End command code RACMDI = 4. / Command Interrupt RARSPI = 6. / Response Interrupt RARING = 8. / Ring base RARSPL = 8. / Response Command low RARSPH = 10. / Response Command high RACMDL = 12. / Command to controller low RACMDH = 14. / Command to controller high RARSPS = 16. / Response packet length (location) RARSPREF = 20. / Response reference number RACMDS = 80. / Command packet length (location) RACMDREF = 84. / Command reference number RAUNIT = 88. / Command packet unit RAOPCODE = 92. / Command opcode offset RABYTECT = 96. / Transfer byte count RABUFL = 100. / Buffer location (16 bit addressing only) RABUFH = 102. / Buffer location high 6 bits RALBNL = 112. / Logical block number low RALBNH = 114. / Logical block number high BSIZE = 512. / Size of boot block / / Clear RA MSCP command area! / mov $ra,r0 mov $BSIZE,r1 mov r0,sp add r1,sp 1: clr (r0)+ sob r1,1b / / RA initialize controller / mov $RASTEP1,r0 mov _bootcsr,r1 / get csr of boot controller clr (r1)+ / go through controller init seq. mov $icons,r2 1: bit r0,(r1) beq 1b mov (r2)+,(r1) asl r0 bpl 1b mov $ra+RARSPREF,*$ra+RARSPL / set controller characteristics mov $ra+RACMDREF,*$ra+RACMDL mov $RASTCON,r0 jsr pc,racmd mov ENDCORE-BOOTDEV,*$ra+RAUNIT / bring boot unit online mov $RAONLIN,r0 jsr pc,racmd / / Read in block zero and jump to it / / / RA MSCP read block routine. This is very primative, so don't expect / too much from it. Note that MSCP requires large data communications / space at end of ADDROFF for command area. / / Load block zero into memory location zero. / BSIZE -> size of block to read / / Tim Tucker, Gould Electronics, August 23rd 1985 / clr *$ra+RALBNL / Put in logical block number mov $BSIZE,*$ra+RABYTECT / Put in byte to transfer clr *$ra+RABUFL / Put in disk buffer location mov $RAREAD,r0 jsr pc,racmd mov ENDCORE-BOOTDEV,r0 / put unit and mov _bootcsr,r1 / csr where bootblock expects them clr pc / and away we go / / perform MSCP command -> response poll version / racmd: movb r0,*$ra+RAOPCODE / fill in command type mov $MSCPSIZE,*$ra+RARSPS / give controller struct sizes mov $MSCPSIZE,*$ra+RACMDS mov $RASEMAP,*$ra+RARSPH / set mscp semaphores mov $RASEMAP,*$ra+RACMDH mov *_bootcsr,r0 / tap controllers shoulder mov $ra+RACMDI,r0 1: tst (r0) beq 1b / Wait till command read clr (r0)+ / Tell controller we saw it, ok. 2: tst (r0) beq 2b / Wait till response written clr (r0) / Tell controller we got it rts pc icons: RAERR ra+RARING 0 RAGO ra: 0 loc(bp); s = spl5(); /* * Link the buffer onto the drive queue */ dp = &tms->tmssys/conf/boot/hk6boot.s 440 0 12 4144 5003736602 10274 /* * SCCS id @(#)hk6boot.s 2.0 (2.11BSD) 4/13/91 */ #include "localopts.h" / The boot options and device are placed in the last SZFLAGS bytes / at the end of core for the bootstrap. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 / boot unit CHECKWORD= 6 .globl _doboot, hardboot, _bootcsr .text _doboot: mov 4(sp),r4 / boot options mov 2(sp),r3 / boot device #ifndef KERN_NONSEP / If running separate I/D, need to turn off memory management. / Call the routine unmap in low text, after setting up a jump / in low data where the PC will be pointing. .globl unmap mov $137,*$unmap+2 / jmp *$hardboot mov $hardboot,*$unmap+4 jmp unmap / "return" from unmap will be to hardboot in data .data #else / Reset to turn off memory management reset #endif / On power fail, hardboot is the entry point (map is already off) / and the args are in r4 (RB_POWRFAIL), r3 (rootdev) hardboot: mov r4, ENDCORE-BOOTOPTS ash $-3,r3 / shift out the partition number bic $!7,r3 / save only the drive number mov r3, ENDCORE-BOOTDEV com r4 / if CHECKWORD == ~bootopts, flags are believed mov r4, ENDCORE-CHECKWORD 1: reset / The remainder of the code is dependent on the boot device. / If you have a bootstrap ROM, just jump to the correct entry. / Otherwise, use a BOOT opcode, if available; / if necessary, read in block 0 to location 0 "by hand". / rk06 disk driver WC = -256. hkcs1 = 0 / offsets from base csr, control & status 1 hkda = 6 / desired track/sector address hkcs2 = 10 / control & status 2 hkca = 20 / desired cylinder / RK06 constants. ack = 03 / pack acknowledge clear = 040 / subsystem clear iocom = 021 / read + go / initialize hk mov _bootcsr,r1 mov $clear,hkcs2(r1) mov $ack,hkcs1(r1) 0: tstb hkcs1(r1) bpl 0b / wait for acknowledge to complete clr hkca(r1) add $hkcs2,r1 mov ENDCORE-BOOTDEV,(r1) clr -(r1) / sector and track (hkda) clr -(r1) / bus address mov $WC,-(r1) / word count mov $iocom,-(r1) 1: tstb (r1) bge 1b / wait for iocom to complete mov ENDCORE-BOOTDEV,r0 clr pc ENDCORE-BOOTDEV com r4 / if CHECKWORD == ~bootopts, flags are believed mov r4, ENDCORE-CHECKWORD 1: reset / The remainder of the code is dependent on the boot device. / If you have a bootstrap ROM, just jump to the correct entry. / Otherwise, use a BOOT opcode, if available; / if necessary, read in block 0 to location 0 "by hand". / / RA bootstrap. / / Note: this is a complex boot, but then MSCP is sys/conf/boot/hk7boot.s 440 0 12 4147 5003736611 10300 /* * SCCS id @(#)hk7boot.s 2.0 (2.11BSD) 4/13/91 */ #include "localopts.h" / The boot options and device are placed in the last SZFLAGS bytes / at the end of core for the bootstrap. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 / boot unit CHECKWORD= 6 .globl _doboot, hardboot, _bootcsr .text _doboot: mov 4(sp),r4 / boot options mov 2(sp),r3 / boot device #ifndef KERN_NONSEP / If running separate I/D, need to turn off memory management. / Call the routine unmap in low text, after setting up a jump / in low data where the PC will be pointing. .globl unmap mov $137,*$unmap+2 / jmp *$hardboot mov $hardboot,*$unmap+4 jmp unmap / "return" from unmap will be to hardboot in data .data #else / Reset to turn off memory management reset #endif / On power fail, hardboot is the entry point (map is already off) / and the args are in r4 (RB_POWRFAIL), r3 (rootdev) hardboot: mov r4, ENDCORE-BOOTOPTS ash $-3,r3 / shift out the partition number bic $!7,r3 / save only the drive number mov r3, ENDCORE-BOOTDEV com r4 / if CHECKWORD == ~bootopts, flags are believed mov r4, ENDCORE-CHECKWORD 1: reset / The remainder of the code is dependent on the boot device. / If you have a bootstrap ROM, just jump to the correct entry. / Otherwise, use a BOOT opcode, if available; / if necessary, read in block 0 to location 0 "by hand". / rk07 disk driver WC = -256. hkcs1 = 0 / offsets from base csr, control & status 1 hkda = 6 / desired track/sector address hkcs2 = 10 / control & status 2 hkca = 20 / desired cylinder / RK07 constants ack = 02003 / pack acknowledge clear = 040 / subsystem clear iocom = 2021 / read + go / initialize hk mov _bootcsr,r1 mov $clear,hkcs2(r1) mov $ack,hkcs1(r1) 0: tstb hkcs1(r1) bpl 0b / wait for acknowledge to complete clr hkca(r1) add $hkcs2,r1 mov ENDCORE-BOOTDEV,(r1) clr -(r1) / sector and track (hkda) clr -(r1) / bus address mov $WC,-(r1) / word count mov $iocom,-(r1) 1: tstb (r1) bge 1b / wait for iocom to complete mov ENDCORE-BOOTDEV,r0 clr pc and high RACMDL = 12. / Command to controller low RACMDH = 14. / Command to controller high RARSPS = 16. / Response packet length (location) RARSPREF = 20. / Response reference number RACMDS = 80. / Command packet length (location) RACMDREF = 84. / Command reference number RAUNIT = 88. / Command packet unit RAOPCODE = 92. / Command opcode offset RABYTECT = 96. / Transfer byte count RABUFL = 100. / Buffersys/conf/boot/brboot.s 440 0 12 3605 5005076136 10211 /* * SCCS id @(#)brboot.s 2.0 (2.11BSD) 4/13/91 */ #include "localopts.h" / The boot options and device are placed in the last SZFLAGS bytes / at the end of core for the bootstrap. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 / boot unit CHECKWORD= 6 .globl _doboot, hardboot, _bootcsr .text _doboot: mov 4(sp),r4 / boot options mov 2(sp),r3 / boot device #ifndef KERN_NONSEP / If running separate I/D, need to turn off memory management. / Call the routine unmap in low text, after setting up a jump / in low data where the PC will be pointing. .globl unmap mov $137,*$unmap+2 / jmp *$hardboot mov $hardboot,*$unmap+4 jmp unmap / "return" from unmap will be to hardboot in data .data #else / Reset to turn off memory management reset #endif / On power fail, hardboot is the entry point (map is already off) / and the args are in r4 (RB_POWRFAIL), r3 (rootdev) hardboot: mov r4, ENDCORE-BOOTOPTS ash $-3,r3 / shift out the partition number bic $!7,r3 / save only the drive number mov r3, ENDCORE-BOOTDEV com r4 / if CHECKWORD == ~bootopts, flags are believed mov r4, ENDCORE-CHECKWORD 1: reset / The remainder of the code is dependent on the boot device. / If you have a bootstrap ROM, just jump to the correct entry. / Otherwise, use a BOOT opcode, if available; / if necessary, read in block 0 to location 0 "by hand". / BR bootstrap brda = 10 mov _bootcsr, r1 / csr of boot device add $brda,r1 clr (r1) / disk address clr -(r1) / cylinder address clr -(r1) / bus address mov $-256.,-(r1) / wc mov ENDCORE-BOOTDEV,r0 swab r0 / unit number to high byte bis $5,r0 / read+go mov r0,-(r1) / cs: read+go 1: tstb (r1) / wait for ready bge 1b mov _bootcsr,r1 / put csr and mov ENDCORE-BOOTDEV,r0 / unit where bootblock expects them clr pc / transfer to zero s2,r1 mov ENDCORE-BOOTDEV,(r1) clr -(r1) / sector and track (hkda) clr -(r1) / bus address mov $WC,-(r1) / word countsys/conf/boot/Makefile 644 0 12 377 5551450520 10166 # 2.11BSD 1.0 April 8, 1994 H= /sys/h DEFS= -DKERNEL -I. -I${H} CPP= /lib/cpp -P ${DEFS} AS= /bin/as -V all: NONEboot.o brboot.o dvhpboot.o hk6boot.o hk7boot.o raboot.o rlboot.o rmboot.o sc11boot.o sc21boot.o siboot.o .s.o: ${CPP} $< | ${AS} -o $@ sys/conf/LONEX.ra 640 0 24 23643 5732465632 7047 # Machine configuration file for 2.11BSD distributed kernel. # # Format: # name value comments # An item's value may be either numerical, boolean or a string; if it's # boolean, use "YES" or "NO" to set it or unset it, respectively. Use # the default value and the comments field as indicators of the type of # field it is. ######################################### # MACHINE DEPENDENT PARAMETERS # ######################################### # Machine type # Split I/D and hardware floating point are required. # UNIBUS support is always included, it only cost 1kb of text space and # 94 bytes of D space for Qbus systems (obviously Unibus systems incur # no penalty). # The define Q22 has been removed. The references to it were incorrect # (i.e. using it to distinguish between an Emulex CS02 and a DH11) or # inappropriate (the if_il.c driver should have been checking if a Unibus # Map was present at runtime). #LINEHZ 50 # clock frequency European LINEHZ 60 # clock frequency USA # PDP-11 machine type; allowable values are GENERIC, 44, 70, 73. GENERIC # should only be used to build a distribution kernel. The only use of this # option is to select the proper in-line PS instructions (references to the # PSW use 'spl', 'mfps/mtps' or 'movb' instructions depending on the cpu type). #PDP11 GENERIC # distribution kernel PDP11 44 # PDP-11/44 #PDP11 70 # PDP-11/70,45,50,55 #PDP11 73 # PDP-11/73,53,83,93,84,94 ######################################### # GENERAL SYSTEM PARAMETERS # ######################################### IDENT LONEX # machine name MAXUSERS 22 # maxusers on machine # BOOTDEV is the letter combination denoting the autoboot device, # or NONE if not using the autoboot feature. #BOOTDEV NONE # don't autoboot #BOOTDEV dvhp # DIVA Comp/V boot device #BOOTDEV hk6 # rk06 boot device #BOOTDEV hk7 # rk07 boot device BOOTDEV ra # MSCP boot device #BOOTDEV rl # rl01/02 boot device #BOOTDEV rm # rm02/03/05 boot device #BOOTDEV br # Eaton BR1537/BR1711 boot device #BOOTDEV sc11 # Emulex SC11/B boot device #BOOTDEV sc21 # Emulex SC21 boot device #BOOTDEV si # si 9500 boot device # Timezone, in minutes west of GMT #TIMEZONE 300 # EST #TIMEZONE 360 # CST #TIMEZONE 420 # WST TIMEZONE 480 # PST DST 1 # Daylight Savings Time (1 or 0) # Filesystem configuration # Rootdev, swapdev etc. should be in terms of makedev. For example, # if you have an SMD drive using the xp driver, rootdev would be xp0a, # or "makedev(10,0)". Swapdev would be the b partition, xp0b, or # "makedev(10,1)". The 10 is the major number of the device (the offset # in the bdevsw table in conf.c) and the 0 and 1 are the minor numbers # which correspond to the partitions as described in the section 4 manual # pages. You can also get the major numbers from the MAKEDEV script in # /dev. PIPEDEV makedev(5,0) # makedev(5,0) ra0a ROOTDEV makedev(5,0) # makedev(10,0) ra0a SWAPDEV makedev(5,1) # makedev(10,1) ra0b # DUMPROUTINE indicates which dump routine should be used. DUMPDEV # should be in terms of makedev. If DUMPDEV is NODEV no automatic # dumps will be taken, and DUMPROUTINE needs to be set to "nulldev" to # resolve the reference. See param.h and ioconf.c for more information. # DUMPLO should leave room for the kernel to start swapping without # overwriting the dump. DUMPLO 1024 # dump start address DUMPDEV makedev(5,1) # makedev(5,1) ra0b #DUMPROUTINE nulldev # no dump routine. #DUMPROUTINE hkdump # hk driver dump routine #DUMPROUTINE hpdump # hp driver dump routine DUMPROUTINE radump # ra driver dump routine #DUMPROUTINE rldump # rl driver dump routine #DUMPROUTINE rmdump # rm driver dump routine #DUMPROUTINE brdump # br driver dump routine #DUMPROUTINE sidump # si driver dump routine #DUMPROUTINE xpdump # xp driver dump routine #DUMPROUTINE tmsdump # tms driver dump routine ######################################### # KERNEL CONFIGURATION # ######################################### BADSECT NO # bad-sector forwarding EXTERNALITIMES YES # map out inode time values UCB_CLIST YES # clists moved from kernel data space QUOTA YES # dynamic file system quotas # NOTE -- *very* expensive # UCB_METER is fairly expensive, but various programs (iostat, vmstat, etc) # use it. UCB_METER YES # vmstat performance metering # NBUF is the size of the buffer cache, and is directly related to the UNIBUS # mapping registers. There are 32 total mapping registers, of which 30 are # available. The 0'th is used for CLISTS, and the 31st is used for the I/O # page on some PDP's. It's suggested that you allow 7 mapping registers # per UNIBUS character device so that you can move 56K of data on each device # simultaneously. The rest should be assigned to the block buffer pool. So, # if you have a DR-11 and a TM-11, you would leave 14 unassigned for them and # allocate 16 to the buffer pool. Since each mapping register addresses 8 # buffers for a 1K file system, NBUF would be 128. A possible exception would # be to reduce the buffers to save on data space, as they were 24 bytes each # Should be 'small' for GENERIC, so room for kernel + large program to run. NBUF 72 # buffer cache, *must* be <= 240 # DIAGNOSTIC does various run-time checks, some of which are pretty # expensive and at a high priority. Suggested use is when the kernel # is crashing and you don't know why, otherwise run with it off. DIAGNOSTIC NO # misc. diagnostic loops and checks ######################################### # PERIPHERALS: DISK DRIVES # ######################################### NBR 0 # EATON BR1537/BR1711, BR1538A, B, C, D NHK 0 # RK611, RK06/07 NRAC 1 # NRAD controllers NRAD 2 # RX50, RC25, RD51/52/53, RA60/80/81 NRK 0 # RK05 NRL 2 # RL01/02 NRX 0 # RX02 NSI 0 # SI 9500 driver for CDC 9766 disks # Because the disk drive type registers conflict with other DEC # controllers, you cannot use XP_PROBE for the Ampex 9300 and # Diva drives. Read through /sys/pdpuba/hpreg.h and /sys/pdpuba/xp.c # for information on how to initialize for these drives. NXPC 0 # NXPD controllers (RH70/RH11 style) NXPD 0 # RM02/03/05, RP04/05/06, CDC 9766, # Ampex 9300, Diva, Fuji 160, SI Eagle. XP_PROBE YES # check drive types at boot NRAM 0 # RAM disk size (512-byte blocks) ######################################### # PERIPHERALS: TAPE DRIVES # ######################################### NHT 0 # TE16, TU45, TU77 # Setting AVIVTM configures the TM driver for the AVIV 800/1600/6250 # controller (the standard DEC TM only supports 800BPI). For more details, # see /sys/pdpuba/tm.c. NTM 0 # TM11 AVIVTM YES # AVIV 800/1600/6250 controller NTS 2 # TS11 NTMSCP 0 # TMSCP controllers NTMS 0 # TMSCP drives TMSCP_DEBUG NO # debugging code in TMSCP drive (EXPENSIVE) ######################################### # PERIPHERALS: TERMINALS # ######################################### # NKL includes both KL11's and DL11's. # It should always be at least 1, for the console. NKL 1 # KL11, DL11 NDH 3 # DH11; NDH is in units of boards (16 each) CS02 NO # DH units above are really Emulex CS02 # boards on a 22bit Qbus. NDM 3 # DM11; NDM is in units of boards (16 each) NDHU 0 # DHU11 NDHV 0 # DHV11 NDZ 0 # DZ11; NDZ is in units of boards (8 each) ######################################### # PERIPHERALS: OTHER # ######################################### NDN 0 # DN11 dialer NLP 2 # Line Printer LP_MAXCOL 132 # Maximum number of columns on line printers NDR 0 # DR11-W ######################################### # PSEUDO DEVICES, PROTOCOLS, NETWORKING # ######################################### # Networking only works with split I/D and SUPERVISOR space, i.e. with the # 11/44/53/70/73/83/84/93,94. NETHER should be non-zero for networking # systems using any ethernet. CHECKSTACK makes sure the networking stack # pointer and the kernel stack pointer don't collide; it's *very* expensive # at 4 extra instructions for EVERY function call AND return, always left # NO unless doing serious debugging. INET YES # TCP/IP CHECKSTACK NO # Kernel & Supervisor stack pointer checking NETHER 1 # ether pseudo-device # Note, PTY's and the select(2) system call do not require the kernel to # be configured for networking (INET). Note that you can allocate PTY's # in any number (multiples of 8, of 16, even, odd, prime, whatever). Nothing # in the kernel cares. PTY's cost 78 bytes apiece in kernel data space. You # should probably have at least 8-10 since several applications use them: # script, jove, window, rlogin, ... NPTY 8 # pseudo-terminals - GENERIC sys needs NONE NEC 1 # 3Com Ethernet NDE 0 # DEUNA/DELUA NIL 0 # Interlan Ethernet NSL 0 # Serial Line IP NQE 0 # DEQNA NQT 0 # DEQTA (DELQA-YM, DELQA-PLUS) NVV 0 # V2LNI (Pronet) NACC 0 # ACC LH/DH ARPAnet IMP interface PLI NO # LH/DH is connected to a PLI NIMP 0 # ARPAnet IMP 1822 interface # The following are untested in 2.11BSD; some are untested since before 2.9BSD # Some won't even compile. Most will require modification. Good luck. ENABLE34 NO # if have the ENABLE34 board NCSS 0 # DEC/CSS IMP11-A ARPAnet IMP interface NDMC 0 # DMC11 NEN 0 # Xerox prototype (3 Mb) Ethernet NHY 0 # Hyperchannel NS 0 # Xerox NS (XNS) NSRI 0 # SRI DR11c ARPAnet IMP NTB 0 # RS232 interface for Genisco/Hitachi tablets # Defining FPSIM to YES compiles a floating point simulator into the kernel # which will catch floating point instruction traps from user space. This # doesn't work at present. FPSIM NO # floating point simulator # To enable profiling, the :splfix script must be changed to use spl6 instead # of spl7 (see conf/:splfix.profile), also, you have to have a machine with a # supervisor PAR/PDR pair, i.e. an 11/44/45/50/53/55/70/73/83/84, as well # as both a KW11-L and a KW11-P. # # Note that profiling is not currently working. We don't have any plans on # fixing it, so this is essentially a non-supported feature. PROFILE NO # system profiling with KW11P clock INGRES NO # include the Ingres lock driver md, data, flag) dev_t dev; int cmd; caddr_t data; int flag; { struct tmscp_softc *sc = &sys/conf/ioconf.c 640 0 12 722 5316274611 7176 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ioconf.c 2.0 (2.11BSD GTE) 12/24/92 */ #include "param.h" #include "systm.h" dev_t rootdev = %ROOTDEV%, swapdev = %SWAPDEV%, pipedev = %PIPEDEV%; dev_t dumpdev = %DUMPDEV%; daddr_t dumplo = (daddr_t)%DUMPLO%; int %DUMPROUTINE%(); int (*dump)() = %DUMPROUTINE%; sys/conf/QT 640 0 12 23241 6004073127 6057 # 1995/07/21 - XP_PROBE removed. # # Machine configuration file for 2.11BSD distributed kernel. # # Format: # name value comments # An item's value may be either numerical, boolean or a string; if it's # boolean, use "YES" or "NO" to set it or unset it, respectively. Use # the default value and the comments field as indicators of the type of # field it is. ######################################### # MACHINE DEPENDENT PARAMETERS # ######################################### # Machine type # Split I/D and hardware floating point are required. # UNIBUS support is always included, it only cost 1kb of text space and # 94 bytes of D space for Qbus systems (obviously Unibus systems incur # no penalty). # The define Q22 has been removed. The references to it were incorrect # (i.e. using it to distinguish between an Emulex CS02 and a DH11) or # inappropriate (the if_il.c driver should have been checking if a Unibus # Map was present at runtime). #LINEHZ 50 # clock frequency European LINEHZ 60 # clock frequency USA # PDP-11 machine type; allowable values are GENERIC, 44, 70, 73. GENERIC # should only be used to build a distribution kernel. The only use of this # option is to select the proper in-line PS instructions (references to the # PSW use 'spl', 'mfps/mtps' or 'movb' instructions depending on the cpu type). #PDP11 GENERIC # distribution kernel #PDP11 44 # PDP-11/44 #PDP11 70 # PDP-11/70,45,50,55 PDP11 73 # PDP-11/73,53,83,93,84,94 ######################################### # GENERAL SYSTEM PARAMETERS # ######################################### IDENT SMS # machine name MAXUSERS 20 # maxusers on machine # BOOTDEV is the letter combination denoting the autoboot device, # or NONE if not using the autoboot feature. #BOOTDEV NONE # don't autoboot #BOOTDEV dvhp # DIVA Comp/V boot device #BOOTDEV hk6 # rk06 boot device #BOOTDEV hk7 # rk07 boot device BOOTDEV ra # MSCP boot device #BOOTDEV rl # rl01/02 boot device #BOOTDEV rm # rm02/03/05 boot device #BOOTDEV br # Eaton BR1537/BR1711 boot device #BOOTDEV sc11 # Emulex SC11/B boot device #BOOTDEV sc21 # Emulex SC21 boot device #BOOTDEV si # si 9500 boot device # Timezone, in minutes west of GMT #TIMEZONE 300 # EST #TIMEZONE 360 # CST #TIMEZONE 420 # WST TIMEZONE 480 # PST DST 1 # Daylight Savings Time (1 or 0) # Filesystem configuration # Rootdev, swapdev etc. should be in terms of makedev. For example, # if you have an SMD drive using the xp driver, rootdev would be xp0a, # or "makedev(10,0)". Swapdev would be the b partition, xp0b, or # "makedev(10,1)". The 10 is the major number of the device (the offset # in the bdevsw table in conf.c) and the 0 and 1 are the minor numbers # which correspond to the partitions as described in the section 4 manual # pages. You can also get the major numbers from the MAKEDEV script in # /dev. PIPEDEV makedev(5,0) # makedev(10,0) ra0a ROOTDEV makedev(5,0) # makedev(10,0) ra0a SWAPDEV makedev(5,1) # makedev(10,1) ra0b # DUMPROUTINE indicates which dump routine should be used. DUMPDEV # should be in terms of makedev. If DUMPDEV is NODEV no automatic # dumps will be taken, and DUMPROUTINE needs to be set to "nulldev" to # resolve the reference. See param.h and ioconf.c for more information. # DUMPLO should leave room for the kernel to start swapping without # overwriting the dump. DUMPLO 512 # dump start address DUMPDEV makedev(5,1) # makedev(10,1) xp0b #DUMPROUTINE nulldev # no dump routine. #DUMPROUTINE hkdump # hk driver dump routine #DUMPROUTINE hpdump # hp driver dump routine DUMPROUTINE radump # ra driver dump routine #DUMPROUTINE rldump # rl driver dump routine #DUMPROUTINE rmdump # rm driver dump routine #DUMPROUTINE brdump # br driver dump routine #DUMPROUTINE sidump # si driver dump routine #DUMPROUTINE xpdump # xp driver dump routine #DUMPROUTINE tmsdump # tms driver dump routine ######################################### # KERNEL CONFIGURATION # ######################################### BADSECT NO # bad-sector forwarding EXTERNALITIMES YES # map out inode time values UCB_CLIST YES # clists moved from kernel data space QUOTA YES # dynamic file system quotas # NOTE -- *very* expensive # UCB_METER is fairly expensive, but various programs (iostat, vmstat, etc) # use it. UCB_METER YES # vmstat performance metering # NBUF is the size of the buffer cache, and is directly related to the UNIBUS # mapping registers. There are 32 total mapping registers, of which 30 are # available. The 0'th is used for CLISTS, and the 31st is used for the I/O # page on some PDP's. It's suggested that you allow 7 mapping registers # per UNIBUS character device so that you can move 56K of data on each device # simultaneously. The rest should be assigned to the block buffer pool. So, # if you have a DR-11 and a TM-11, you would leave 14 unassigned for them and # allocate 16 to the buffer pool. Since each mapping register addresses 8 # buffers for a 1K file system, NBUF would be 128. A possible exception would # be to reduce the buffers to save on data space, as they were 24 bytes each # Should be 'small' for GENERIC, so room for kernel + large program to run. NBUF 128 # buffer cache, *must* be <= 240 # DIAGNOSTIC does various run-time checks, some of which are pretty # expensive and at a high priority. Suggested use is when the kernel # is crashing and you don't know why, otherwise run with it off. DIAGNOSTIC NO # misc. diagnostic loops and checks ######################################### # PERIPHERALS: DISK DRIVES # ######################################### NBR 0 # EATON BR1537/BR1711, BR1538A, B, C, D NHK 0 # RK611, RK06/07 NRAC 2 # NRAD controllers NRAD 4 # RX50, RC25, RD51/52/53, RA60/80/81 NRK 0 # RK05 NRL 0 # RL01/02 NRX 0 # RX02 NSI 0 # SI 9500 driver for CDC 9766 disks NXPC 0 # NXPD controllers (RH70/RH11 style) NXPD 0 # RM02/03/05, RP04/05/06, CDC 9766, # Ampex 9300, Diva, Fuji 160, SI Eagle. NRAM 0 # RAM disk size (512-byte blocks) ######################################### # PERIPHERALS: TAPE DRIVES # ######################################### NHT 0 # TE16, TU45, TU77 # Setting AVIVTM configures the TM driver for the AVIV 800/1600/6250 # controller (the standard DEC TM only supports 800BPI). For more details, # see /sys/pdpuba/tm.c. NTM 0 # TM11 AVIVTM YES # AVIV 800/1600/6250 controller NTS 1 # TS11 NTMSCP 0 # TMSCP controllers NTMS 0 # TMSCP drives TMSCP_DEBUG NO # debugging code in TMSCP drive (EXPENSIVE) ######################################### # PERIPHERALS: TERMINALS # ######################################### # NKL includes both KL11's and DL11's. # It should always be at least 1, for the console. NKL 8 # KL11, DL11 NDH 0 # DH11; NDH is in units of boards (16 each) CS02 NO # DH units above are really Emulex CS02 # boards on a 22bit Qbus. NDM 0 # DM11; NDM is in units of boards (16 each) NDHU 0 # DHU11 NDHV 0 # DHV11 NDZ 0 # DZ11; NDZ is in units of boards (8 each) ######################################### # PERIPHERALS: OTHER # ######################################### NDN 0 # DN11 dialer NLP 0 # Line Printer LP_MAXCOL 132 # Maximum number of columns on line printers NDR 0 # DR11-W ######################################### # PSEUDO DEVICES, PROTOCOLS, NETWORKING # ######################################### # Networking only works with split I/D and SUPERVISOR space, i.e. with the # 11/44/53/70/73/83/84/93/94. NETHER should be non-zero for networking # systems using any ethernet. CHECKSTACK makes sure the networking stack # pointer and the kernel stack pointer don't collide; it's fairly expensive # at 4 extra instructions for EVERY function call AND return, always left # NO unless doing serious debugging. INET YES # TCP/IP CHECKSTACK NO # Kernel & Supervisor stack pointer checking NETHER 1 # ether pseudo-device # Note, PTY's and the select(2) system call do not require the kernel to # be configured for networking (INET). Note that you can allocate PTY's # in any number (multiples of 8, of 16, even, odd, prime, whatever). Nothing # in the kernel cares. PTY's cost 78 bytes apiece in kernel data space. You # should probably have at least 8-10 since several applications use them: # script, jove, window, rlogin, ... NPTY 12 # pseudo-terminals - GENERIC sys needs NONE NEC 0 # 3Com Ethernet NDE 0 # DEUNA/DELUA NIL 0 # Interlan Ethernet NSL 1 # Serial Line IP NQE 0 # DEQNA NQT 1 # DEQTA (DELQA-YM, DELQA-PLUS) NVV 0 # V2LNI (Pronet) NACC 0 # ACC LH/DH ARPAnet IMP interface PLI NO # LH/DH is connected to a PLI NIMP 0 # ARPAnet IMP 1822 interface # The following are untested in 2.11BSD; some are untested since before 2.9BSD # Some won't even compile. Most will require modification. Good luck. ENABLE34 NO # if have the ENABLE34 board NCSS 0 # DEC/CSS IMP11-A ARPAnet IMP interface NDMC 0 # DMC11 NEN 0 # Xerox prototype (3 Mb) Ethernet NHY 0 # Hyperchannel NS 0 # Xerox NS (XNS) NSRI 0 # SRI DR11c ARPAnet IMP NTB 0 # RS232 interface for Genisco/Hitachi tablets # Defining FPSIM to YES compiles a floating point simulator into the kernel # which will catch floating point instruction traps from user space. This # doesn't work at present. FPSIM NO # floating point simulator # To enable profiling, the :splfix script must be changed to use spl6 instead # of spl7 (see conf/:splfix.profile), also, you have to have a machine with a # supervisor PAR/PDR pair, i.e. an 11/44/45/50/53/55/70/73/83/84, as well # as both a KW11-L and a KW11-P. # # Note that profiling is not currently working. We don't have any plans on # fixing it, so this is essentially a non-supported feature. PROFILE NO # system profiling with KW11P clock INGRES YES # include the Ingres lock driver if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && bp->b_resid) return (EIO); if (bp->b_flags & B_ERROR) /* like hitting BOT */ break; } return (geterror(bp)); case MTIOCGET: /* * Return status info associated with the particular UNIT. */ tms = sc->sc_drives[TMSUNIT(dev)]; if (!tms) return(ENXIO); mtgetsys/conf/Make.pdpmba 664 0 12 1466 4263626577 7667 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # %W% (Berkeley) %G% # U= ../pdpmba VPATH= ../pdpmba CFILES= OBJS= .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s all: ${OBJS} depend: mkdep -f Make.pdpmba ${CFLAGS} ${CFILES} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. n Emulex CS02 and a DH11) or # inappropriate (the if_il.c driver should have been checking if a Unibus # Map was present at runtime). #LINEHZ 50 # clock frequency European LINEHZ 60 # clock frequsys/conf/newvers.sh 644 3 12 1222 5665761046 7637 #!/bin/sh - # # Copyright (c) 1980 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)newvers.sh 1.6 (2.11BSD GTE) 11/26/94 # if [ ! -r version ]; then echo 0 > version; fi touch version echo `cat version` ${USER-root} `pwd` `date` `hostname` | \ awk ' { version = $1 + 1; user = $2; host = $10; dir = $3; \ date = $4 " " $5 " " $6 " " $7 " " $8 " " $9; }\ END { printf "char version[] = \"2.11 BSD UNIX #%d: %s\\n", \ version, date; \ printf " %s@%s:%s\\n\";\n", user, host, dir; printf "%d\n", version > "version"; }' > vers.c : ${OBJS} depend: mkdep -f Make.pdpmba ${CFLAGS} ${CFILES} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. n Emulex CS02 and a DH11) or # inappropriate (the if_il.c driver should have been checking if a Unibus # Map was present at runtime). #LINEHZ 50 # clock frequency European LINEHZ 60 # clock frequsys/conf/:comm-to-bss 440 0 12 356 3775017671 7743 /^\.comm _PROC,/s/comm \(.*\),\([0-9]*\)/globl _proc;.bss;_proc:.=.+\2;.data/ /^\.comm _TEXT,/s/comm \(.*\),\([0-9]*\)/globl _text;.bss;_text:.=.+\2;.data/ /^\.comm _FILE,/s/comm \(.*\),\([0-9]*\)/globl _file;.bss;_file:.=.+\2;.data/ w q Make.sunixHGENERICixG Make.unixFMake.netEMake.pdpD Make.pdpubaCMake.sysbB checksys.cA netbind.c@ spln9spl_3como2 SMSi1\NONET0P WLONEX.desys/conf/Make.nsunix 644 0 12 15370 5754044713 7755 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # 2.3 (2.11BSD GTE) 1995/05/09 # ######################################################### # Networking, separate I/D kernel # ######################################################### H= ../h I= /usr/include M= ../machine N1= ../net N2= ../netimp N3= ../netinet N4= ../netns N6= ../pdpif S= ../sys U= ../pdpuba MB= ../pdpmba DEFS= -DKERNEL ${OPTS} -I. -I${H} CFLAGS= -O ${DEFS} CPP= /lib/cpp -P ${DEFS} AS= /bin/as -V ED= /bin/ed SUB= sys pdp pdpuba pdpmba net pdpnet # GENERAL RULES: # scb.o MUST be loaded first, param.o MUST be loaded last, # boot.o must be loaded in the base well above 0 data. # enable34.o must be in the base segment for overlaid kernels. # Don't forget the "-i" flag for split I/D, use "-n" otherwise. # # CONF Non-network assembly binaries. scb.o must be first! # boot.o should be close to the end. # NCONF Network (network space) assembly binaries. net_scb.o # doesn't have to be first. CONF= scb.o libc_bcmp.o libc_bcopy.o libc_bzero.o libc_ffs.o \ libc_insque.o libc_ldiv.o libc_lmul.o libc_lrem.o libc_remque.o \ libc_udiv.o libc_uldiv.o libc_ulsh.o \ libc_strlen.o mch_backup.o mch_click.o mch_copy.o mch_csv.o \ mch_dump.o mch_dzpdma.o mch_KScall.o mch_profile.o \ mch_start.o mch_trap.o mch_vars.o mch_xxx.o conf.o ioconf.o boot.o NCONF= libc_bcmp.o libc_bcopy.o libc_bzero.o libc_ffs.o libc_htonl.o \ libc_htons.o libc_insque.o libc_ldiv.o libc_lmul.o libc_lrem.o \ libc_uldiv.o libc_ulsh.o \ libc_remque.o libc_strlen.o libc_udiv.o net_copy.o net_csv.o \ net_mbuf.o net_scb.o net_SKcall.o net_trap.o net_xxx.o BASE= br.o cons.o dh.o dhu.o dhv.o dr.o dz.o hk.o ht.o init_sysent.o \ kern_clock.o kern_descrip.o kern_mman.o kern_proc.o kern_prot.o \ kern_subr.o kern_synch.o kern_xxx.o lp.o machdep.o ra.o ram.o \ rk.o rl.o rx.o si.o subr_rmap.o sys_inode.o sys_kern.o \ tm.o ts.o tty.o tty_conf.o tty_subr.o tty_tb.o ufs_alloc.o \ ufs_bio.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_namei.o \ vm_proc.o vm_sched.o vm_swap.o vm_swp.o vm_text.o xp.o quota_subr.o OV1= sys_generic.o ufs_syscalls.o OV2= kern_acct.o kern_exec.o kern_exit.o kern_fork.o kern_resource.o OV3= kern_time.o sys_process.o ufs_mount.o ufs_subr.o uipc_syscalls.o OV4= dkbad.o kern_sig.o mem.o subr_xxx.o trap.o tty_pty.o tty_tty.o OV5= quota_kern.o quota_ufs.o quota_sys.o ufs_bmap.o \ sys_pipe.o # OV6 gets the (hopefully) never used routines OV6= clock.o dn.o init_main.o kern_pdp.o machdep2.o subr_prf.o syscalls.o \ subr_log.o toy.o OV7= tmscp.o kern_sysctl.o OV8= mch_fpsim.o ingreslock.o ufs_disksubr.o KERNOBJ=${CONF} ${BASE} ${OV1} ${OV2} ${OV3} ${OV4} ${OV5} \ ${OV6} ${OV7} ${OV8} ${OV9} ${OV10} ${OV11} ${OV12} \ ${OV13} ${OV14} ${OV15} \ enable34.o vers.o param.o # param.o must be last! enable34.o must be in base. LD_KOBJ=${CONF} ${BASE} \ -Z ${OV1} -Z ${OV2} -Z ${OV3} -Z ${OV4} -Z ${OV5} -Z ${OV6} \ -Z ${OV7} -Z ${OV8} -Z ${OV9} -Z ${OV10} -Z ${OV11} -Z ${OV12} \ -Z ${OV13} -Z ${OV14} -Z ${OV15} -Y \ enable34.o vers.o param.o NETOBJ= ${NCONF} af.o idp_usrreq.o if.o if_acc.o if_css.o if_de.o \ if_dmc.o if_ec.o if_en.o if_ether.o if_il.o if_imp.o if_imphost.o \ if_loop.o if_qe.o if_qt.o if_sl.o if_sri.o if_uba.o if_vv.o in.o \ in_cksum.o in_pcb.o in_proto.o ip_icmp.o ip_input.o ip_output.o \ ns.o ns_error.o ns_input.o ns_ip.o ns_output.o ns_pcb.o \ ns_proto.o raw_cb.o raw_imp.o raw_ip.o \ raw_usrreq.o route.o spp_debug.o spp_usrreq.o sys_socket.o \ sys_net.o tcp_debug.o tcp_input.o tcp_output.o tcp_subr.o \ tcp_timer.o tcp_usrreq.o udp_usrreq.o uipc_domain.o uipc_mbuf.o \ uipc_proto.o uipc_socket.o uipc_socket2.o uipc_usrreq.o all: unix netnix # d.unix.o must be last object file in the dependency list! unix: ${SUB} ${KERNOBJ} d.unix.o checksys ld -X -i -o unix ${LD_KOBJ} d.unix.o size unix @echo Compacting symbol table -symcompact unix @echo Compacting strings table - this will take a few minutes -strcompact unix @echo rearranging symbols -symorder ../pdp/symbols.sort unix ./checksys unix # d.netnix.o must be the last object file in the dependency list! netnix: d.netnix.o -ld -X -i -o netnix ${NETOBJ} d.netnix.o @echo Compacting symbol table -symcompact netnix @echo Compacting strings table - this will take a few minutes -strcompact netnix @echo rearranging symbols -symorder ../pdp/symbols.sort netnix size netnix # Resolve all references between the kernel and the net. Always regenerate!!! # This was a constant source of problems during development. Should really # include ${NETOBJ} and ${KERNOBJ} on dependency line, but the pdp make doesn't # have enough table space. d.unix.o d.netnix.o: netbind FRC ld -q -r -d -X -i -o unix.o ${LD_KOBJ} ld -q -r -d -X -o netnix.o ${NETOBJ} ./netbind unix.o netnix.o rm unix.o netnix.o ${AS} - -o d.unix.o d.unix.s ${AS} - -o d.netnix.o d.netnix.s vers.o: FRC sh ../conf/newvers.sh ${CC} -c vers.c boot.o: boot.s ${CPP} boot.s > boot.i ${AS} -o boot.o boot.i rm -f boot.i param.o: ${CC} -S ${CFLAGS} param.c ${ED} - param.s < ../conf/:comm-to-bss ${AS} - -o param.o param.s rm -f param.s ioconf.o: ioconf.c ${CC} -c ${CFLAGS} ioconf.c checksys: ../conf/checksys.c ${CC} ${CFLAGS} -o $@ ../conf/checksys.c netbind: ../conf/netbind.c ${CC} ${CFLAGS} -o $@ ../conf/netbind.c sys pdp pdpuba pdpmba: make -f Make.$@ I=${I} H=${H} M=${M} AS="${AS}" CPP="${CPP}" \ CFLAGS="${CFLAGS}" ED="${ED}" net pdpnet: make -f Make.$@ I=${I} H=${H} M=${M} AS="${AS}" \ CPP="${CPP} -DSUPERVISOR" CFLAGS="${CFLAGS} -DSUPERVISOR" \ ED="${ED}" clean: rm -f unix core mklog *.o *.i assym.h genassym checksys rm -f netnix netbind d.unix.s d.netnix.s install: install -c -o root -g kmem -m 744 unix ${DESTDIR}/unix install -c -o root -g kmem -m 744 netnix ${DESTDIR}/netnix depend: FRC for i in ${SUB}; do \ make -f Make.$$i CFLAGS="${CFLAGS}" depend; done mkdep ${CFLAGS} param.c ioconf.c ../conf/checksys.c ../conf/netbind.c TAGSFILE= ${S}/tags TLIST= ${H} ${I} ${N1} ${N2} ${N3} ${N4} ${N5} ${N6} ${M} ${S} ${U} ${MB} ${SS} tags: FRC rm -f ${TAGSFILE} for i in ${TLIST}; do \ (cd ${S}; /usr/ucb/ctags -a -t $$i/*.[ch]); done /usr/bin/egrep "^ASENTRY|^ENTRY" ${M}/*.s | \ /bin/sed 's;\([^:]*\):\([^(]*\)(\([^)]*\));\3 \1 /^\2(\3)$$/;' \ >> ${TAGSFILE} /usr/bin/sort -o ${TAGSFILE} ${TAGSFILE} FRC: # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. scb.o must be first! # boot.o should be close to the end. # NCONF Network (network space) assembly binaries. net_scb.o # doesn't have to be first. CONF= scb.o libc_bcmp.o libc_bcopy.o libc_bzero.o libc_ffs.o \ libc_insque.o libc_ldiv.o libc_lmul.o libc_lrem.osys/conf/Make.pdpnet 664 0 12 2701 5757757237 7716 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # 2.0 (2.11BSD GTE) 1995/05/21 # M= ../machine VPATH= ../machine CFILES= ${M}/enable34.c ${M}/in_cksum.c COBJS= enable34.o in_cksum.o SFILES= ${M}/libc_htonl.s ${M}/libc_htons.s ${M}/net_copy.s \ ${M}/net_csv.s ${M}/net_mbuf.s ${M}/net_scb.s ${M}/net_SKcall.s \ ${M}/net_trap.s ${M}/net_xxx.s SOBJS= libc_htonl.o libc_htons.o mch_KScall.o net_copy.o net_csv.o \ net_mbuf.o net_scb.o net_SKcall.o net_trap.o net_xxx.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < NETSPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s .s.o: ${CPP} $*.s | ${AS} -u -o $*.o all: ${COBJS} ${SOBJS} in_cksum.o: ${CC} ${CFLAGS} -S ${M}/in_cksum.c ${ED} - < ${M}/cksum-fix > /dev/null in_cksum.s ${ED} - < NETSPLFIX in_cksum.s ${AS} - -o $@ in_cksum.s rm -f in_cksum.s depend: assym.h mkdep -f Make.pdpnet ${CFLAGS} ${CFILES} ${SFILES} assym.h: make -f Make.pdp CFLAGS="${CFLAGS}" assym.h # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. libc_ffs.o \ libc_insque.o libc_ldiv.o libc_lmul.o libc_lrem.osys/conf/param.c 440 0 12 7345 5707361136 7052 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)param.c 2.1 (2.11BSD GTE) 1/18/95 */ #include "../h/param.h" #include "../h/systm.h" #include "../h/buf.h" #include "../h/time.h" #include "../h/resource.h" #include "../h/proc.h" #include "../h/text.h" #include "../h/file.h" #include "../h/dir.h" #include "../h/inode.h" #include "../h/fs.h" #include "../h/mount.h" #include "../h/callout.h" #include "../h/map.h" #include "../h/clist.h" #include "../machine/seg.h" /* * System parameter formulae. * * This file is copied into each directory where we compile * the kernel; it should be modified there to suit local taste * if necessary. * */ #define MAXUSERS %MAXUSERS% #define NBUF %NBUF% int hz = LINEHZ; struct timezone tz = { %TIMEZONE%, %DST% }; #define NPROC (10 + 7 * MAXUSERS) int nproc = NPROC; #define NTEXT (26 + MAXUSERS) int ntext = NTEXT; #define NINODE ((NPROC + 16 + MAXUSERS) + 22) int ninode = NINODE; #define NFILE ((8 * NINODE / 10) + 20) int nfile = NFILE; #define NCALL (16 + MAXUSERS) int ncallout = NCALL; int nbuf = NBUF; #define NCLIST (20 + 8 * MAXUSERS) #if NCLIST > (8192 / 32) /* 8K / sizeof(struct cblock) */ #undef NCLIST #define NCLIST (8192 / 32) #endif int nclist = NCLIST; /* * These have to be allocated somewhere; allocating * them here forces loader errors if this file is omitted * (if they've been externed everywhere else; hah!). */ struct proc *procNPROC; struct text *textNTEXT; struct inode inode[NINODE], *inodeNINODE; struct file *fileNFILE; struct callout callout[NCALL]; struct mount mount[NMOUNT]; struct buf buf[NBUF], bfreelist[BQUEUES]; struct bufhd bufhash[BUFHSZ]; /* * Remove the ifdef/endif to run the kernel in unsecure mode even when in * a multiuser state. Normally 'init' raises the security level to 1 * upon transitioning to multiuser. Setting the securelevel to -1 prevents * the secure level from being raised by init. */ #ifdef PERMANENTLY_INSECURE int securelevel = -1; #endif #ifdef UCB_CLIST u_int clstdesc = ((((btoc(NCLIST*sizeof(struct cblock)))-1) << 8) | RW); int ucb_clist = 1; #else struct cblock cfree[NCLIST]; int ucb_clist = 0; #endif #define CMAPSIZ NPROC /* size of core allocation map */ #define SMAPSIZ ((9 * NPROC) / 10) /* size of swap allocation map */ struct mapent _coremap[CMAPSIZ]; struct map coremap[1] = { _coremap, &_coremap[CMAPSIZ], "coremap", }; struct mapent _swapmap[SMAPSIZ]; struct map swapmap[1] = { _swapmap, &_swapmap[SMAPSIZ], "swapmap", }; #ifdef QUOTA #include "../h/quota.h" struct BigQ { struct quota xquota[NQUOTA]; /* the quotas themselves */ struct dquot *ixdquot[NINODE]; /* 2.11 equiv of i_dquot */ struct dquot xdquot[NDQUOT]; /* the dquots themselves */ struct qhash xqhash[NQHASH]; struct dqhead xdqhash[NDQHASH]; }; QUOini() { extern struct qhash *qhash; extern struct dqhead *dqhead; quota = ((struct BigQ *)SEG5)->xquota; dquot = ((struct BigQ *)SEG5)->xdquot; qhash = ((struct BigQ *)SEG5)->xqhash; dqhead = ((struct BigQ *)SEG5)->xdqhash; ndquot = NDQUOT; nquota = NQUOTA; ix_dquot = ((struct BigQ *)SEG5)->ixdquot; dquotNDQUOT = &dquot[ndquot]; quotaNQUOTA = "a[nquota]; } #endif /* * Declarations of structures loaded last and allowed to reside in the * 0120000-140000 range (where buffers and clists are mapped). These * structures must be extern everywhere else, and the asm output of cc * is edited to move these structures from comm to bss (which is last) * (see the script :comm-to-bss). They are in capital letters so that * the edit script doesn't find some other occurrence. */ struct proc PROC[NPROC]; struct file FILE[NFILE]; struct text TEXT[NTEXT]; \ ns_proto.o raw_cb.o raw_imp.o raw_ip.o \ raw_usrreq.o route.o spp_debug.o spp_usrreq.o sys_socket.o \ sys_net.o tcp_debug.o tcp_input.o tcp_output.o tcp_subr.o \ tcp_timer.o tcp_usrreq.o udp_usrreq.o uipc_domain.o uipc_mbuf.o \ uipc_proto.o uipc_socket.o uipc_socket2.o uipc_usys/conf/config 551 0 12 15517 6004073271 7010 #! /bin/sh # 2.11BSD script to set up a new kernel configuration directory. # # 1995/07/21 - remove XP_PROBE, the kernel no longer probes for disk # type because that information is obtained from the # disklabel. # 2/28/95 - fixed errors introduced earlier. remove the chmod at the # end, rely instead on the system administrator's choice of # umask. # 2/14/95 - added ingres lock driver. removed vax cruft. LO=../h/localopts.h if [ $# -ne 1 ]; then echo "usage: $0 machinename" exit 1 fi MACHINE=$1 if [ ! -s $MACHINE ]; then echo "$0: unable to read $MACHINE." exit 1 fi if mkdir ../$MACHINE; then echo "Creating ../$MACHINE." chmod 775 ../$MACHINE fi # read in specification file eval `awk '/^#/ || /^$/ || /^ / {next} $1 != "" { printf "%s=\\"%s\\"\\n", $1, $2 }' $MACHINE` if [ ! "$MAXUSERS" ]; then MAXUSERS=1 exit 1 fi if [ ! "$TIMEZONE" ]; then TIMEZONE=480 fi if [ ! "$DST" ]; then DST=1 fi cat << EOF > $LO /* * This file is generated by the configuration script sys/conf/config. * * It contains a list the kernel options not prepended to the Makefile * as -Dxxxx commands to the compiler. MAXMEM was moved to param.h leaving * only LINEHZ and EXTERNALITIMES to be placed in localopts.h */ EOF case $PDP11 in GENERIC) KERN_NONSEP=NO NETFIX=:splfix.movb SPLFIX=:splfix.movb;; 53|73|83|84|93|94) KERN_NONSEP=NO NETFIX=:splfix.movb+mfps SPLFIX=:splfix.mfps;; 44|45|50|55|70) KERN_NONSEP=NO NETFIX=:splfix.movb SPLFIX=:splfix.spl;; *) echo "$0: unrecognized PDP11 type $PDP11." echo 'use GENERIC, 44, 70, 73' exit 1;; esac if [ $NKL -lt 1 ]; then NKL=1 fi # Copy in the standard configuration files, boot program, # makefiles, and cpu-dependent files. echo "Copying standard files to ../$MACHINE." if [ $NEC = 0 ]; then if [ $INET = YES ]; then cp spl/$NETFIX ../$MACHINE/NETSPLFIX fi cp spl/$SPLFIX ../$MACHINE/SPLFIX else if [ $INET = YES ]; then cp spl_3com/$NETFIX ../$MACHINE/NETSPLFIX fi cp spl_3com/$SPLFIX ../$MACHINE/SPLFIX fi cp boot/${BOOTDEV}boot.s ../$MACHINE/boot.s sed -e "s/%ROOTDEV%/$ROOTDEV/" \ -e "s/%SWAPDEV%/$SWAPDEV/" \ -e "s/%PIPEDEV%/$PIPEDEV/" \ -e "s/%DUMPDEV%/$DUMPDEV/" \ -e "s/%DUMPLO%/$DUMPLO/" \ -e "s/%DUMPROUTINE%/$DUMPROUTINE/" < ioconf.c > ../$MACHINE/ioconf.c sed -e "s/%TIMEZONE%/$TIMEZONE/" \ -e "s/%DST%/$DST/" \ -e "s/%NBUF%/$NBUF/" \ -e "s/%MAXUSERS%/$MAXUSERS/" < param.c > ../$MACHINE/param.c echo "Setting configuration options for $MACHINE." OPTS="-D${IDENT}" echo "#define LINEHZ $LINEHZ" >> $LO if [ $FPSIM = YES ]; then OPTS="$OPTS -DFPSIM" fi if [ $KERN_NONSEP = YES ]; then OPTS="$OPTS -DKERN_NONSEP" fi if [ $EXTERNALITIMES = YES ]; then echo "#define EXTERNALITIMES 1" >> $LO fi if [ $UCB_METER = YES ]; then OPTS="$OPTS -DUCB_METER" fi if [ $INET = YES ]; then OPTS="$OPTS -DINET" echo "#define NLOOP 1" > ../$MACHINE/loop.h else echo "#define NLOOP 0" > ../$MACHINE/loop.h fi if [ $BADSECT = YES ]; then OPTS="$OPTS -DBADSECT" fi if [ $CHECKSTACK = YES ]; then OPTS="$OPTS -DCHECKSTACK" fi if [ $DIAGNOSTIC = YES ]; then OPTS="$OPTS -DDIAGNOSTIC -DICMPPRINTFS" fi if [ $QUOTA = YES ]; then OPTS="$OPTS -DQUOTA" fi if [ $UCB_CLIST = YES ]; then OPTS="$OPTS -DUCB_CLIST" fi if [ $PROFILE = YES ]; then OPTS="$OPTS -DPROFILE" fi echo "Creating device header files." echo "#define NCSS $NCSS" > ../$MACHINE/css.h echo "#define NDE $NDE" > ../$MACHINE/de.h echo "#define NDH $NDH" > ../$MACHINE/dh.h if [ $CS02 = YES ]; then echo "#define CS02 1" >> ../$MACHINE/dh.h fi echo "#define NDM $NDM" >> ../$MACHINE/dh.h echo "#define NDN $NDN" > ../$MACHINE/dn.h echo "#define NDHU $NDHU" > ../$MACHINE/dhu.h echo "#define NDHV $NDHV" > ../$MACHINE/dhv.h echo "#define NDMC $NDMC" > ../$MACHINE/dmc.h echo "#define NDR $NDR" > ../$MACHINE/dr.h echo "#define NDZ $NDZ" > ../$MACHINE/dz.h echo "#define NEC $NEC" > ../$MACHINE/ec.h echo "#define NEN $NEN" > ../$MACHINE/en.h echo "#define NETHER $NETHER" > ../$MACHINE/ether.h echo "#define NHT $NHT" > ../$MACHINE/ht.h echo "#define NHY $NHY" > ../$MACHINE/hy.h echo "#define NIL $NIL" > ../$MACHINE/il.h echo "#define NIMP $NIMP" > ../$MACHINE/imp.h echo "#define NKL $NKL" > ../$MACHINE/cn.h echo "#define NLP $NLP" > ../$MACHINE/lp.h echo "#define LP_MAXCOL $LP_MAXCOL" >> ../$MACHINE/lp.h echo "#define NPTY $NPTY" > ../$MACHINE/pty.h if [ $INGRES = YES ]; then echo "#define NINGRES 1" > ../$MACHINE/ingres.h else echo "#define NINGRES 0" > ../$MACHINE/ingres.h fi echo "#define NQE $NQE" > ../$MACHINE/qe.h echo "#define NQT $NQT" > ../$MACHINE/qt.h echo "#define NRAM $NRAM" > ../$MACHINE/ram.h echo "#define NRK $NRK" > ../$MACHINE/rk.h echo "#define NRX $NRX" > ../$MACHINE/rx.h echo "#define NSL $NSL" > ../$MACHINE/sl.h echo "#define NSRI $NSRI" > ../$MACHINE/sri.h echo "#define NTB $NTB" > ../$MACHINE/tb.h echo "#define NTS $NTS" > ../$MACHINE/ts.h echo "#define NTMSCP $NTMSCP" > ../$MACHINE/tms.h echo "#define NTMS $NTMS" >> ../$MACHINE/tms.h if [ $TMSCP_DEBUG = YES ]; then echo "#define TMSCP_DEBUG" >> ../$MACHINE/tms.h fi if [ $DUMPROUTINE = tmsdump ]; then echo "#define TMSCP_DUMP 1" >> ../$MACHINE/tms.h fi echo "#define NVV $NVV" > ../$MACHINE/vv.h echo "#define NACC $NACC" > ../$MACHINE/acc.h if [ $PLI = YES ]; then echo "#define PLI 1" >> ../$MACHINE/acc.h fi echo "#define NHK $NHK" > ../$MACHINE/hk.h if [ $DUMPROUTINE = hkdump ]; then echo "#define HK_DUMP 1" >> ../$MACHINE/hk.h fi echo "#define NRAC $NRAC" > ../$MACHINE/ra.h echo "#define NRAD $NRAD" >> ../$MACHINE/ra.h if [ $DUMPROUTINE = radump ]; then echo "#define RA_DUMP 1" >> ../$MACHINE/ra.h fi echo "#define NRL $NRL" > ../$MACHINE/rl.h if [ $DUMPROUTINE = rldump ]; then echo "#define RL_DUMP 1" >> ../$MACHINE/rl.h fi echo "#define NBR $NBR" > ../$MACHINE/br.h if [ $DUMPROUTINE = brdump ]; then echo "#define BR_DUMP 1" >> ../$MACHINE/br.h fi echo "#define NSI $NSI" > ../$MACHINE/si.h if [ $DUMPROUTINE = sidump ]; then echo "#define SI_DUMP 1" >> ../$MACHINE/si.h fi echo "#define NTM $NTM" > ../$MACHINE/tm.h if [ $AVIVTM = YES ] ; then echo "#define AVIVTM 1" >> ../$MACHINE/tm.h fi echo "#define NXPD $NXPD" > ../$MACHINE/xp.h echo "#define NXPC $NXPC" >> ../$MACHINE/xp.h if [ $DUMPROUTINE = xpdump ]; then echo "#define XP_DUMP 1" >> ../$MACHINE/xp.h fi echo "Creating Makefile for $MACHINE". if [ -s ../$MACHINE/Makefile ]; then echo "Saving ../$MACHINE/Makefile to ../$MACHINE/Makefile.old" cp -p ../$MACHINE/Makefile ../$MACHINE/Makefile.old fi echo "OPTS=$OPTS" > ../$MACHINE/Makefile cp Make.sys Make.pdp Make.pdpuba Make.pdpmba ../$MACHINE if [ $INET = YES ]; then cat Make.nsunix >> ../$MACHINE/Makefile cp Make.net Make.pdpnet ../$MACHINE elif [ $KERN_NONSEP = NO ]; then cat Make.sunix >> ../$MACHINE/Makefile else cat Make.unix >> ../$MACHINE/Makefile fi # install copy of localopts.h and make it readable for applications cp $LO ../$MACHINE chmod a+r ../$MACHINE } -S ${CFLAGS} param.c ${ED} - param.s < ../conf/:comm-to-bss ${AS} - -o param.o param.s rm -f param.s ioconf.o: ioconf.c ${CC} -c ${CFLAGS} ioconf.c checksys: ../conf/chesys/conf/README 440 0 12 7431 5321173263 6454 This directory contains prototypes of the files necessary to remaking the kernel. The kernel is not compiled or loaded in this directory, but in individual directories per machine. To set up a directory for a new machine, copy the file GENERIC to a file with the same name as the machine, and edit it to describe the desired kernel and the machine's hardware configuration. Then, run the script "./config", giving it the file name as an argument. Config will create a directory ../machinename and will copy or create the necessary files in it. When creating a GENERIC system remember to copy /sys/pdpdist/dtab to /etc/dtab before creating the dump(8) of the root filesystem. This is so 'autoconfig' will find the tape and disc devices when the GENERIC kernel is booted. You will probably need to change the overlay definitions in the Makefile, if you are going to run an overlaid kernel, but most of the work of configuring a system will be done. OVERLAY notes: Almost none of the CONF modules can be placed in overlays. In general assembly language modules (source files ending in .s) may not be placed in overlays because they do not observe the overlay calling sequence used by the .c modules. Other than that restriction modules may be placed in overlays in any order subject to the size constraints mentioned below. It is a good idea to attempt to group modules which call each other in the same overlay when possible, this saves overlay switching overhead. It is a very good idea to keep the frequently/constantly called modules (such as ufs_namei.o or tty.o) in the BASE segment. If the system has a large amount of memory and swapping does not occur often then the swap (vm_swap.o, etc) modules are good candidates for being placed in overlays. Maximum size of the BASE is 56kb, maximum size of each overlay segment is 8kb - the 'checksys' program will warn of segments (root/base, overlays and data) which are too large. There is a limit of 15 overlays at present, however there is a lower limit on the size of a kernel which may be loaded. /boot can not deal with kernels larger than about 192kb (sum of text and data) because that is where /boot relocates himself to while loading /unix. See the comments in /sys/pdpstand/M.s for more information and a workaround (which will not work with the 3Com ethernet board installed in the system). There is one possible problem that you need to be aware of. Running the shell script config generates the file localopts.h in the system include files directory, "../h". If you change your configuration, config will overwrite your old version of that file. Therefore, if you want to return to the old version of your system, you'll have to recover the file before you try and remake the old system. To make this easy, config saves a copy in the kernel directory. Almost no applications depend on localopts.h now, pstat.c, mkfs.c and sa.c are the only ones which come to mind. 'pstat' and 'mkfs' need the EXTERNALITIMES define and the accounting program 'sa' needs the LINEHZ definition. ALL other options have either been deleted (obsolete) or made standard. The few remaining options have been moved into the kernel Makefile as "-Dxxx" flags to the compiler. If EXTERNALITIMES changes you will need to recompile anything which looks at the kernel's incore inode table. The directory VAX.compile contains a C preprocessor that defines "pdp11" and a C compiler that knows where to find said preprocessor. If you compile and install VAX.compile/cpp as VAX.compile/CPP and VAX.compile/cc.c as VAX.compile/CC, then do "./config VAX", you can compile the entire kernel on a larger machine; obviously, this is more of a test for syntax/load errors than anything else. If you're interested, it usually took me about 5 minutes to compile the entire networking kernel on a VAX 8600. MPROUTINE = hkdump ]; then echo "#define HK_DUMP 1" >> ../$MACHINE/hk.h fi echo "#define NRAC $NRAC" > ../$MACHINE/ra.h echo "#define NRAD $NRAD" >> ../$MACHINE/ra.h if [ $DUMPROUTINE = radump ]; then echo "#define RA_DUMP 1" sys/conf/Make.sunix 644 0 12 10443 5754563467 7607 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # 2.2 (2.11BSD GTE) 1995/05/11 # ######################################################### # Non-network, but separate I/D kernel # ######################################################### H= ../h I= /usr/include M= ../machine S= ../sys U= ../pdpuba MB= ../pdpmba DEFS= -DKERNEL ${OPTS} -I. -I${H} CFLAGS= -O ${DEFS} CPP= /lib/cpp -P ${DEFS} AS= /bin/as -V ED= /bin/ed SUB= sys pdp pdpuba pdpmba # GENERAL RULES: # scb.o MUST be loaded first, param.o MUST be loaded last, # boot.o must be loaded in the base well above 0 data. # Don't forget the "-i" flag for split I/D, use "-n" otherwise. # # CONF Non-network assembly binaries. scb.o must be first! # boot.o should be close to the end. CONF= scb.o libc_bcmp.o libc_bcopy.o libc_bzero.o libc_ffs.o \ libc_insque.o libc_ldiv.o libc_lmul.o libc_lrem.o libc_remque.o \ libc_udiv.o libc_uldiv.o libc_ulsh.o \ libc_strlen.o mch_backup.o mch_click.o mch_copy.o mch_csv.o \ mch_dump.o mch_dzpdma.o mch_profile.o mch_start.o \ mch_trap.o mch_vars.o mch_xxx.o conf.o ioconf.o boot.o BASE= br.o dh.o dhu.o dhv.o dkbad.o dr.o dz.o init_sysent.o kern_clock.o \ kern_descrip.o kern_mman.o kern_proc.o kern_sig.o kern_subr.o \ kern_synch.o lp.o machdep.o ra.o ram.o rk.o rl.o rx.o si.o \ subr_rmap.o subr_xxx.o sys_inode.o sys_pipe.o trap.o tty.o \ tty_conf.o tty_subr.o tty_tb.o tty_tty.o ufs_alloc.o ufs_bio.o \ ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_namei.o \ ufs_subr.o vm_sched.o xp.o OV1= sys_generic.o ufs_syscalls.o mem.o OV2= kern_acct.o kern_exec.o kern_exit.o kern_fork.o kern_resource.o OV3= clock.o cons.o kern_pdp.o kern_time.o \ kern_xxx.o machdep2.o quota_sys.o subr_prf.o sys_process.o \ syscalls.o ufs_mount.o OV4= hk.o init_main.o kern_prot.o tty_pty.o quota_kern.o quota_subr.o \ quota_ufs.o subr_log.o vm_swp.o vm_swap.o vm_proc.o toy.o OV5= ht.o tm.o ts.o OV6= tmscp.o kern_sysctl.o OV7= mch_fpsim.o ingreslock.o ufs_disksubr.o OV8= vm_text.o KERNOBJ=${CONF} ${BASE} ${OV1} ${OV2} ${OV3} ${OV4} ${OV5} \ ${OV6} ${OV7} ${OV8} ${OV9} ${OV10} ${OV11} ${OV12} \ ${OV13} ${OV14} ${OV15} \ vers.o param.o # param.o must be last! LD_KOBJ=${CONF} ${BASE} \ -Z ${OV1} -Z ${OV2} -Z ${OV3} -Z ${OV4} -Z ${OV5} -Z ${OV6} \ -Z ${OV7} -Z ${OV8} -Z ${OV9} -Z ${OV10} -Z ${OV11} -Z ${OV12} \ -Z ${OV13} -Z ${OV14} -Z ${OV15} -Y \ vers.o param.o all: unix unix: ${SUB} ${KERNOBJ} checksys ld -X -i -o unix ${LD_KOBJ} size unix @echo Compacting symbol table -symcompact unix @echo Compacting strings table - this will take a few minutes -strcompact unix @echo rearranging symbols -symorder ../pdp/symbols.sort unix ./checksys unix vers.o: FRC sh ../conf/newvers.sh ${CC} -c vers.c boot.o: boot.s ${CPP} boot.s > boot.i ${AS} -o boot.o boot.i rm -f boot.i param.o: ${CC} -S ${CFLAGS} param.c ${ED} - param.s < ../conf/:comm-to-bss ${AS} - -o param.o param.s rm -f param.s ioconf.o: ioconf.c ${CC} -c ${CFLAGS} ioconf.c sys pdp pdpuba pdpmba: make -f Make.$@ I=${I} H=${H} M=${M} AS="${AS}" CPP="${CPP}" \ CFLAGS="${CFLAGS}" ED="${ED}" checksys: ../conf/checksys.c ${CC} ${CFLAGS} -o $@ ../conf/checksys.c clean: rm -f unix core mklog *.o *.i assym.h genassym checksys install: install -c -o root -g kmem -m 744 unix ${DESTDIR}/unix depend: FRC for i in ${SUB}; do \ make -f Make.$$i CFLAGS="${CFLAGS}" depend; done mkdep ${CFLAGS} param.c ioconf.c ../conf/checksys.c TAGSFILE= ${S}/tags TLIST= ${H} ${I} ${N1} ${N2} ${N3} ${N4} ${N5} ${N6} ${M} ${S} ${U} ${MB} ${SS} tags: FRC rm -f ${TAGSFILE} for i in ${TLIST}; do \ (cd ${S}; /usr/ucb/ctags -a -t $$i/*.[ch]); done /usr/bin/egrep "^ASENTRY|^ENTRY" ${M}/*.s | \ /bin/sed 's;\([^:]*\):\([^(]*\)(\([^)]*\));\3 \1 /^\2(\3)$$/;' \ >> ${TAGSFILE} /usr/bin/sort -o ${TAGSFILE} ${TAGSFILE} FRC: # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. fine NSI $NSI" > ../$MACHINE/si.h if [ $DUMPROUTINE = sidump ]; then echo "#define SI_DUMP 1" >> ../$MACHINE/si.h fi echo "#define NTM $NTM" > ../$MACHINE/tm.h if [ $AVIVTM = YES ] ; then echo "#define AVIVTM 1" >> sys/conf/GENERIC 644 3 12 23231 6004073007 6612 # 1995/07/21 - XP_PROBE removed. # # Machine configuration file for 2.11BSD distributed kernel. # # Format: # name value comments # An item's value may be either numerical, boolean or a string; if it's # boolean, use "YES" or "NO" to set it or unset it, respectively. Use # the default value and the comments field as indicators of the type of # field it is. ######################################### # MACHINE DEPENDENT PARAMETERS # ######################################### # Machine type # Split I/D and hardware floating point are required. # UNIBUS support is always included, it only cost 1kb of text space and # 94 bytes of D space for Qbus systems (obviously Unibus systems incur # no penalty). # The define Q22 has been removed. The references to it were incorrect # (i.e. using it to distinguish between an Emulex CS02 and a DH11) or # inappropriate (the if_il.c driver should have been checking if a Unibus # Map was present at runtime). #LINEHZ 50 # clock frequency European LINEHZ 60 # clock frequency USA # PDP-11 machine type; allowable values are GENERIC, 44, 70, 73. GENERIC # should only be used to build a distribution kernel. The only use of this # option is to select the proper in-line PS instructions (references to the # PSW use 'spl', 'mfps/mtps' or 'movb' instructions depending on the cpu type). PDP11 GENERIC # distribution kernel #PDP11 44 # PDP-11/44 #PDP11 70 # PDP-11/70,45,50,55 #PDP11 73 # PDP-11/73,53,83,93,84,94 ######################################### # GENERAL SYSTEM PARAMETERS # ######################################### IDENT GENERIC # machine name MAXUSERS 4 # maxusers on machine # BOOTDEV is the letter combination denoting the autoboot device, # or NONE if not using the autoboot feature. BOOTDEV NONE # don't autoboot #BOOTDEV dvhp # DIVA Comp/V boot device #BOOTDEV hk6 # rk06 boot device #BOOTDEV hk7 # rk07 boot device #BOOTDEV ra # MSCP boot device #BOOTDEV rl # rl01/02 boot device #BOOTDEV rm # rm02/03/05 boot device #BOOTDEV br # Eaton BR1537/BR1711 boot device #BOOTDEV sc11 # Emulex SC11/B boot device #BOOTDEV sc21 # Emulex SC21 boot device #BOOTDEV si # si 9500 boot device # Timezone, in minutes west of GMT #TIMEZONE 300 # EST #TIMEZONE 360 # CST #TIMEZONE 420 # WST TIMEZONE 480 # PST DST 1 # Daylight Savings Time (1 or 0) # Filesystem configuration # Rootdev, swapdev etc. should be in terms of makedev. For example, # if you have an SMD drive using the xp driver, rootdev would be xp0a, # or "makedev(10,0)". Swapdev would be the b partition, xp0b, or # "makedev(10,1)". The 10 is the major number of the device (the offset # in the bdevsw table in conf.c) and the 0 and 1 are the minor numbers # which correspond to the partitions as described in the section 4 manual # pages. You can also get the major numbers from the MAKEDEV script in # /dev. PIPEDEV makedev(10,0) # makedev(10,0) xp0a ROOTDEV makedev(10,0) # makedev(10,0) xp0a SWAPDEV makedev(10,1) # makedev(10,1) xp0b # DUMPROUTINE indicates which dump routine should be used. DUMPDEV # should be in terms of makedev. If DUMPDEV is NODEV no automatic # dumps will be taken, and DUMPROUTINE needs to be set to "nulldev" to # resolve the reference. See param.h and ioconf.c for more information. # DUMPLO should leave room for the kernel to start swapping without # overwriting the dump. DUMPLO 512 # dump start address DUMPDEV NODEV # makedev(10,1) xp0b DUMPROUTINE nulldev # no dump routine. #DUMPROUTINE hkdump # hk driver dump routine #DUMPROUTINE hpdump # hp driver dump routine #DUMPROUTINE radump # ra driver dump routine #DUMPROUTINE rldump # rl driver dump routine #DUMPROUTINE rmdump # rm driver dump routine #DUMPROUTINE brdump # br driver dump routine #DUMPROUTINE sidump # si driver dump routine #DUMPROUTINE xpdump # xp driver dump routine #DUMPROUTINE tmsdump # tms driver dump routine ######################################### # KERNEL CONFIGURATION # ######################################### BADSECT NO # bad-sector forwarding EXTERNALITIMES YES # map out inode time values UCB_CLIST NO # clists moved from kernel data space QUOTA NO # dynamic file system quotas # NOTE -- *very* expensive # UCB_METER is fairly expensive, but various programs (iostat, vmstat, etc) # use it. UCB_METER NO # vmstat performance metering # NBUF is the size of the buffer cache, and is directly related to the UNIBUS # mapping registers. There are 32 total mapping registers, of which 30 are # available. The 0'th is used for CLISTS, and the 31st is used for the I/O # page on some PDP's. It's suggested that you allow 7 mapping registers # per UNIBUS character device so that you can move 56K of data on each device # simultaneously. The rest should be assigned to the block buffer pool. So, # if you have a DR-11 and a TM-11, you would leave 14 unassigned for them and # allocate 16 to the buffer pool. Since each mapping register addresses 8 # buffers for a 1K file system, NBUF would be 128. A possible exception would # be to reduce the buffers to save on data space, as they were 24 bytes each # Should be 'small' for GENERIC, so room for kernel + large program to run. NBUF 32 # buffer cache, *must* be <= 240 # DIAGNOSTIC does various run-time checks, some of which are pretty # expensive and at a high priority. Suggested use is when the kernel # is crashing and you don't know why, otherwise run with it off. DIAGNOSTIC NO # misc. diagnostic loops and checks ######################################### # PERIPHERALS: DISK DRIVES # ######################################### NBR 0 # EATON BR1537/BR1711, BR1538A, B, C, D NHK 2 # RK611, RK06/07 NRAC 2 # NRAD controllers NRAD 3 # RX50, RC25, RD51/52/53, RA60/80/81 NRK 0 # RK05 NRL 2 # RL01/02 NRX 0 # RX02 NSI 0 # SI 9500 driver for CDC 9766 disks NXPC 1 # NXPD controllers (RH70/RH11 style) NXPD 2 # RM02/03/05, RP04/05/06, CDC 9766, # Ampex 9300, Diva, Fuji 160, SI Eagle. NRAM 0 # RAM disk size (512-byte blocks) ######################################### # PERIPHERALS: TAPE DRIVES # ######################################### NHT 2 # TE16, TU45, TU77 # Setting AVIVTM configures the TM driver for the AVIV 800/1600/6250 # controller (the standard DEC TM only supports 800BPI). For more details, # see /sys/pdpuba/tm.c. NTM 2 # TM11 AVIVTM YES # AVIV 800/1600/6250 controller NTS 2 # TS11 NTMSCP 2 # TMSCP controllers NTMS 2 # TMSCP drives TMSCP_DEBUG NO # debugging code in TMSCP drive (EXPENSIVE) ######################################### # PERIPHERALS: TERMINALS # ######################################### # NKL includes both KL11's and DL11's. # It should always be at least 1, for the console. NKL 1 # KL11, DL11 NDH 0 # DH11; NDH is in units of boards (16 each) CS02 NO # DH units above are really Emulex CS02 # boards on a 22bit Qbus. NDM 0 # DM11; NDM is in units of boards (16 each) NDHU 0 # DHU11 NDHV 0 # DHV11 NDZ 0 # DZ11; NDZ is in units of boards (8 each) ######################################### # PERIPHERALS: OTHER # ######################################### NDN 0 # DN11 dialer NLP 0 # Line Printer LP_MAXCOL 132 # Maximum number of columns on line printers NDR 0 # DR11-W ######################################### # PSEUDO DEVICES, PROTOCOLS, NETWORKING # ######################################### # Networking only works with split I/D and SUPERVISOR space, i.e. with the # 11/44/53/70/73/83/84/93,94. NETHER should be non-zero for networking # systems using any ethernet. CHECKSTACK makes sure the networking stack # pointer and the kernel stack pointer don't collide; it's *very* expensive # at 4 extra instructions for EVERY function call AND return, always left # NO unless doing serious debugging. INET NO # TCP/IP CHECKSTACK NO # Kernel & Supervisor stack pointer checking NETHER 0 # ether pseudo-device # Note, PTY's and the select(2) system call do not require the kernel to # be configured for networking (INET). Note that you can allocate PTY's # in any number (multiples of 8, of 16, even, odd, prime, whatever). Nothing # in the kernel cares. PTY's cost 78 bytes apiece in kernel data space. You # should probably have at least 8-10 since several applications use them: # script, jove, window, rlogin, ... NPTY 0 # pseudo-terminals - GENERIC sys needs NONE NEC 0 # 3Com Ethernet NDE 0 # DEUNA/DELUA NIL 0 # Interlan Ethernet NSL 0 # Serial Line IP NQE 0 # DEQNA NQT 0 # DEQTA (DELQA-YM, DELQA-PLUS) NVV 0 # V2LNI (Pronet) NACC 0 # ACC LH/DH ARPAnet IMP interface PLI NO # LH/DH is connected to a PLI NIMP 0 # ARPAnet IMP 1822 interface # The following are untested in 2.11BSD; some are untested since before 2.9BSD # Some won't even compile. Most will require modification. Good luck. ENABLE34 NO # if have the ENABLE34 board NCSS 0 # DEC/CSS IMP11-A ARPAnet IMP interface NDMC 0 # DMC11 NEN 0 # Xerox prototype (3 Mb) Ethernet NHY 0 # Hyperchannel NS 0 # Xerox NS (XNS) NSRI 0 # SRI DR11c ARPAnet IMP NTB 0 # RS232 interface for Genisco/Hitachi tablets # Defining FPSIM to YES compiles a floating point simulator into the kernel # which will catch floating point instruction traps from user space. This # doesn't work at present. FPSIM NO # floating point simulator # To enable profiling, the :splfix script must be changed to use spl6 instead # of spl7 (see conf/:splfix.profile), also, you have to have a machine with a # supervisor PAR/PDR pair, i.e. an 11/44/45/50/53/55/70/73/83/84, as well # as both a KW11-L and a KW11-P. # # Note that profiling is not currently working. We don't have any plans on # fixing it, so this is essentially a non-supported feature. PROFILE NO # system profiling with KW11P clock INGRES NO # include the Ingres lock driver ../$MACHINE/Makefile else cat Make.unix >> ../$MACHINE/Makefile fi # install copy of localopts.h and make it readable for applications cp $LO ../$MACHINE chmod a+r ../$MACHINE } -S ${CFLAGS} param.c ${ED} - param.s < ../conf/:comm-to-bss ${AS} - -o param.o param.s rm -f param.s ioconf.o: ioconf.c ${CC} -c ${CFLAGS} ioconf.c checksys: ../conf/chesys/conf/Make.unix 644 0 12 10662 5743377265 7424 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # 2.2 (2.11BSD GTE) 1995/04/13 # ######################################################### # Non-networking, non-separate I/D kernel # ######################################################### H= ../h I= /usr/include M= ../machine S= ../sys U= ../pdpuba MB= ../pdpmba DEFS= -DKERNEL ${OPTS} -I. -I${H} CFLAGS= -O ${DEFS} CPP= /lib/cpp -P ${DEFS} AS= /bin/as -V ED= /bin/ed SUB= sys pdp pdpuba pdpmba # GENERAL RULES: # scb.o MUST be loaded first, param.o MUST be loaded last, # boot.o must be loaded in the base well above 0 data. # Don't forget the "-i" flag for split I/D, use "-n" otherwise. # # CONF Non-network assembly binaries. scb.o must be first! # boot.o should be close to the end. CONF= scb.o libc_bcmp.o libc_bcopy.o libc_bzero.o libc_ffs.o \ libc_insque.o libc_ldiv.o libc_lmul.o libc_lrem.o libc_remque.o \ libc_uldiv.o libc_ulsh.o \ libc_strlen.o mch_backup.o mch_click.o mch_copy.o mch_csv.o \ mch_dump.o mch_dzpdma.o mch_fpsim.o mch_profile.o mch_start.o \ mch_trap.o mch_vars.o mch_xxx.o conf.o ioconf.o boot.o # This overlay setup is far too configuration dependent, with both text # and data trying to share one address space. You're on you're own here ... # BASE= br.o clock.o cons.o dh.o dhu.o dhv.o dkbad.o dn.o dr.o dz.o hk.o ht.o \ init_main.o init_sysent.o kern_acct.o kern_clock.o kern_descrip.o \ kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_pdp.o \ kern_proc.o kern_prot.o kern_resource.o kern_sig.o \ kern_subr.o kern_synch.o kern_time.o kern_xxx.o lp.o machdep.o \ machdep2.o mem.o quota_kern.o quota_subr.o quota_sys.o \ quota_ufs.o ra.o ram.o rk.o rl.o rx.o si.o subr_prf.o subr_rmap.o \ subr_xxx.o sys_generic.o sys_inode.o sys_kern.o toy.o \ sys_pipe.o sys_process.o syscalls.o tm.o trap.o tmscp.o ts.o tty.o \ tty_conf.o tty_pty.o tty_subr.o tty_tb.o tty_tty.o ufs_alloc.o \ ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o \ ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o \ vm_proc.o vm_sched.o vm_swap.o vm_swp.o vm_text.o xp.o subr_log.o \ kern_sysctl.o ingreslock.o ufs_disksubr.o OV1= OV2= KERNOBJ=${CONF} ${BASE} ${OV1} ${OV2} ${OV3} ${OV4} ${OV5} \ ${OV6} ${OV7} ${OV8} ${OV9} ${OV10} ${OV11} ${OV12} \ ${OV13} ${OV14} ${OV15} \ vers.o param.o # param.o must be last! LD_KOBJ=${CONF} ${BASE} \ -Z ${OV1} -Z ${OV2} -Z ${OV3} -Z ${OV4} -Z ${OV5} -Z ${OV6} \ -Z ${OV7} -Z ${OV8} -Z ${OV9} -Z ${OV10} -Z ${OV11} -Z ${OV12} \ -Z ${OV13} -Z ${OV14} -Z ${OV15} -Y \ vers.o param.o all: unix unix: ${SUB} ${KERNOBJ} checksys ld -X -i -o unix ${LD_KOBJ} size unix @echo Compacting symbol table -symcompact unix @echo Compacting strings table - this will take a few minutes -strcompact unix @echo rearranging symbols -symorder ../pdp/symbols.sort unix ./checksys unix vers.o: FRC sh ../conf/newvers.sh ${CC} -c vers.c boot.o: boot.s ${CPP} boot.s > boot.i ${AS} -o boot.o boot.i rm -f boot.i param.o: ${CC} -S ${CFLAGS} param.c ${ED} - param.s < ../conf/:comm-to-bss ${AS} - -o param.o param.s rm -f param.s ioconf.o: ioconf.c ${CC} -c ${CFLAGS} ioconf.c sys pdp pdpuba pdpmba: make -f Make.$@ I=${I} H=${H} M=${M} AS="${AS}" CPP="${CPP}" \ CFLAGS="${CFLAGS}" ED="${ED}" checksys: ../conf/checksys.c ${CC} ${CFLAGS} -o $@ ../conf/checksys.c clean: rm -f unix core mklog *.o *.i assym.h genassym checksys install: install -c -o root -g kmem -m 744 unix ${DESTDIR}/unix depend: FRC for i in ${SUB}; do \ make -f Make.$$i CFLAGS="${CFLAGS}" depend; done mkdep ${CFLAGS} param.c ioconf.c ../conf/checksys.c TAGSFILE= ${S}/tags TLIST= ${H} ${I} ${N1} ${N2} ${N3} ${N4} ${N5} ${N6} ${M} ${S} ${U} ${MB} ${SS} tags: FRC rm -f ${TAGSFILE} for i in ${TLIST}; do \ (cd ${S}; /usr/ucb/ctags -a -t $$i/*.[ch]); done /usr/bin/egrep "^ASENTRY|^ENTRY" ${M}/*.s | \ /bin/sed 's;\([^:]*\):\([^(]*\)(\([^)]*\));\3 \1 /^\2(\3)$$/;' \ >> ${TAGSFILE} /usr/bin/sort -o ${TAGSFILE} ${TAGSFILE} FRC: # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. # is provided ``as is'' without express or implied warranty. # # 2.2 (2.11BSD sys/conf/Make.net 664 0 12 5022 5266714304 7170 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # %W% (Berkeley) %G% # N1= ../net N1C= ${N1}/af.c ${N1}/if.c ${N1}/if_loop.c ${N1}/if_sl.c \ ${N1}/raw_cb.c ${N1}/raw_usrreq.c ${N1}/route.c N1O= af.o if.o if_loop.o if_sl.o raw_cb.o raw_usrreq.o route.o N2= ../netimp N2C= ${N2}/if_imp.c ${N2}/if_imphost.c ${N2}/raw_imp.c N2O= if_imp.o if_imphost.o raw_imp.o N3= ../netinet N3C= ${N3}/if_ether.c ${N3}/in.c ${N3}/in_pcb.c ${N3}/in_proto.c \ ${N3}/ip_icmp.c ${N3}/ip_input.c ${N3}/ip_output.c \ ${N3}/raw_ip.c ${N3}/tcp_debug.c ${N3}/tcp_input.c \ ${N3}/tcp_output.c ${N3}/tcp_subr.c ${N3}/tcp_timer.c \ ${N3}/tcp_usrreq.c ${N3}/udp_usrreq.c N3O= if_ether.o in.o in_pcb.o in_proto.o ip_icmp.o ip_input.o \ ip_output.o raw_ip.o tcp_debug.o tcp_input.o tcp_output.o \ tcp_subr.o tcp_timer.o tcp_usrreq.o udp_usrreq.o N5= ../netns N5C= ${N5}/ns.c ${N5}/ns_pcb.c ${N5}/ns_proto.c ${N5}/ns_error.c \ ${N5}/ns_ip.c ${N5}/ns_input.c ${N5}/ns_output.c \ ${N5}/idp_usrreq.c ${N5}/spp_usrreq.c ${N5}/spp_debug.c N5O= ns.o ns_pcb.o ns_proto.o ns_error.o ns_ip.o ns_input.o \ ns_output.o idp_usrreq.o spp_usrreq.o spp_debug.o N6= ../pdpif N6C= ${N6}/if_acc.c ${N6}/if_css.c ${N6}/if_de.c ${N6}/if_dmc.c \ ${N6}/if_ec.c ${N6}/if_en.c ${N6}/if_il.c ${N6}/if_qe.c \ ${N6}/if_qt.c ${N6}/if_sri.c ${N6}/if_uba.c ${N6}/if_vv.c N6O= if_acc.o if_css.o if_de.o if_dmc.o if_ec.o if_en.o if_il.o \ if_qe.o if_qt.o if_sri.o if_uba.o if_vv.o S= ../sys SC= ${S}/sys_socket.c ${S}/sys_net.c ${S}/uipc_domain.c \ ${S}/uipc_mbuf.c ${S}/uipc_proto.c ${S}/uipc_socket.c \ ${S}/uipc_socket2.c ${S}/uipc_usrreq.c SO= sys_socket.o sys_net.o uipc_domain.o uipc_mbuf.o uipc_proto.o \ uipc_socket.o uipc_socket2.o uipc_usrreq.o VPATH= ../net:../netimp:../netinet:../netns:../pdpif:../sys SRCS= ${N1C} ${N2C} ${N3C} ${N5C} ${N6C} ${SC} OBJS= ${N1O} ${N2O} ${N3O} ${N5O} ${N6O} ${SO} .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < NETSPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s all: ${OBJS} depend: mkdep -f Make.net ${CFLAGS} ${SRCS} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. KERNOBJ=${CONF} ${BASE} ${OV1} ${OV2} ${OV3} ${OV4} ${OV5} \ ${OV6} ${OV7} ${OV8} ${OV9} ${OV10} ${OV11} ${OV12} \ ${OV13} ${OV14} ${OV15} \ vers.o param.o # param.o must be last! LD_KOBJ=${CONF} ${BASE} \ -Z ${OV1} -Z ${OV2} -Z ${OV3} -Z ${OV4} -Z ${OV5} -Z ${OV6} \ -Z ${OV7} -Z ${OV8} -Z ${OV9} -Z ${OV10} -Z ${OV11} -Z ${OV12} \ -Z ${OV13} -Z ${OV14} -Z ${OV15} -Y \ vers.o param.o all: unix unix: ${SUB} ${KERNOBJ} checksys ld -X -i -o unix ${LD_KOBJ} size unix @echo Compacsys/conf/Make.pdp 664 0 12 5036 5757755537 7214 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # 2.0 (2.11BSD GTE) 1995/05/21 # M= ../machine VPATH= ../machine CFILES= ${M}/clock.c ${M}/conf.c ${M}/cons.c ${M}/kern_pdp.c \ ${M}/machdep.c ${M}/machdep2.c ${M}/mem.c ${M}/ram.c ${M}/trap.c COBJS= clock.o conf.o cons.o kern_pdp.o machdep.o machdep2.o mem.o \ ram.o trap.o # We compile mch_KScall here rather than in Make.pdpnet so that it gets # compiled with the right flags. This means that it gets compiled for all # kernel, but is only included in the networking kernel. As it only takes # a few seconds to compile it, it isn't worth trashing up Make.pdpnet to # compile it there. SFILES= ${M}/libc_bcmp.s ${M}/libc_bcopy.s ${M}/libc_bzero.s \ ${M}/libc_ffs.s ${M}/libc_insque.s ${M}/libc_ldiv.s \ ${M}/libc_lmul.s ${M}/libc_lrem.s ${M}/libc_remque.s \ ${M}/libc_uldiv.s ${M}/libc_ulsh.s \ ${M}/libc_strlen.s ${M}/libc_udiv.s ${M}/mch_backup.s \ ${M}/mch_click.s ${M}/mch_copy.s ${M}/mch_csv.s ${M}/mch_dump.s \ ${M}/mch_dzpdma.s ${M}/mch_fpsim.s ${M}/mch_KScall.s \ ${M}/mch_profile.s ${M}/mch_start.s ${M}/mch_trap.s \ ${M}/mch_vars.s ${M}/mch_xxx.s ${M}/scb.s ${M}/toy.s SOBJS= libc_bcmp.o libc_bcopy.o libc_bzero.o libc_ffs.o libc_insque.o \ libc_ldiv.o libc_lmul.o libc_lrem.o libc_remque.o libc_strlen.o \ libc_uldiv.o libc_ulsh.o \ libc_udiv.o mch_backup.o mch_click.o mch_copy.o mch_csv.o \ mch_dump.o mch_dzpdma.o mch_fpsim.o mch_KScall.o mch_profile.o \ mch_start.o mch_trap.o mch_vars.o mch_xxx.o scb.o toy.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s .s.o: ${CPP} $*.s | ${AS} -u -o $*.o all: assym.h ${COBJS} ${SOBJS} ../pdp/symbols.sort assym.h: genassym ./genassym > $@ genassym: ${CC} -O ${CFLAGS} ${M}/genassym.c -o $@ # it's a tab character in the sed statement below not a space. ../pdp/symbols.sort: ../pdp/symbols.raw grep -v '^#' ../pdp/symbols.raw \ | sed 's/^ //' | sort -u > ../pdp/symbols.sort depend: assym.h mkdep -f Make.pdp ${CFLAGS} ${CFILES} ${SFILES} ${M}/genassym.c # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. CONF} ${BASE} ${OV1} ${OV2} ${OV3} ${OV4} ${OV5} \ ${OV6} ${OV7} ${OV8} ${OV9} ${OV10} ${OV11} ${OV12} \ ${OV13} ${OV14} ${OV15} \ vers.o param.o # param.o must be last! LD_KOBJ=${CONF} ${BASE} \ -Z ${OV1} -Z ${OV2} -Z ${OV3} -Z ${OV4} -Z ${OV5} -Z ${OV6} \ -Z ${OV7} -Z ${OV8} -Z ${OV9} -Z ${OV10} -Z ${OV11} -Z ${OV12} \ -Z ${OV13} -Z ${OV14} -Z ${OV15} -Y \ vers.o param.o all: unix unix: ${SUB} ${KERNOBJ} checksys ld -X -i -o unix ${LD_KOBJ} size unix @echo Compacsys/conf/Make.pdpuba 664 0 12 2200 5125225325 7642 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # %W% (Berkeley) %G% # U= ../pdpuba VPATH= ../pdpuba CFILES= ${U}/br.c ${U}/dh.c ${U}/dn.c ${U}/dhu.c ${U}/dhv.c ${U}/dkbad.c \ ${U}/dr.c ${U}/dz.c ${U}/hk.c ${U}/ht.c ${U}/lp.c ${U}/ra.c ${U}/rk.c \ ${U}/rl.c ${U}/rx.c ${U}/si.c ${U}/tm.c ${U}/tmscp.c ${U}/ts.c ${U}/xp.c OBJS= br.o dh.o dhu.o dhv.o dkbad.o dn.o dr.o dz.o hk.o ht.o lp.o ra.o rk.o \ rl.o rx.o si.o tm.o tmscp.o ts.o xp.o dn.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s all: ${OBJS} depend: mkdep -f Make.pdpuba ${CFLAGS} ${CFILES} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. \ ${M}/libc_ffs.s ${M}/libc_insque.s ${M}/libc_ldiv.s \ ${M}/libc_lmul.s ${M}/libc_lrem.s ${M}/libc_remque.s \ ${M}/libc_uldiv.s ${M}/libc_ulsh.s \ ${M}/libc_strlen.s ${M}/libc_udiv.s ${M}/mch_backup.s \ ${M}/mch_click.s ${M}/mch_copy.s ${M}/mch_csv.s ${M}/mch_dump.s \ ${M}/mch_dzpdma.s ${M}/mch_fpsim.s ${M}/mch_KScall.s \ ${M}/mch_profile.s ${M}/mch_start.s ${M}/mch_trap.ssys/conf/Make.sys 664 0 12 5010 5743376776 7236 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # 2.2 (2.11BSD GTE) 1994/04/13 # S= ../sys VPATH= ../sys CFILES= ${S}/init_main.c ${S}/init_sysent.c ${S}/kern_acct.c \ ${S}/kern_clock.c ${S}/kern_descrip.c ${S}/kern_exec.c \ ${S}/kern_exit.c ${S}/kern_fork.c ${S}/kern_mman.c \ ${S}/kern_proc.c ${S}/kern_prot.c ${S}/kern_resource.c \ ${S}/kern_sig.c ${S}/kern_subr.c ${S}/kern_sysctl.c \ ${S}/kern_synch.c ${S}/kern_time.c ${S}/kern_xxx.c \ ${S}/quota_sys.c ${S}/quota_kern.c ${S}/quota_ufs.c \ ${S}/quota_subr.c ${S}/subr_log.c ${S}/subr_prf.c ${S}/subr_rmap.c \ ${S}/subr_xxx.c ${S}/sys_generic.c ${S}/sys_inode.c \ ${S}/sys_kern.c ${S}/sys_pipe.c \ ${S}/ingreslock.c \ ${S}/sys_process.c ${S}/syscalls.c ${S}/tty.c ${S}/tty_conf.c \ ${S}/tty_pty.c ${S}/tty_subr.c ${S}/tty_tb.c ${S}/tty_tty.c \ ${S}/ufs_alloc.c ${S}/ufs_bio.c ${S}/ufs_bmap.c \ ${S}/ufs_dsort.c ${S}/ufs_fio.c ${S}/ufs_inode.c \ ${S}/ufs_mount.c ${S}/ufs_namei.c ${S}/ufs_subr.c \ ${S}/ufs_disksubr.c \ ${S}/ufs_syscalls.c ${S}/uipc_syscalls.c ${S}/vm_proc.c \ ${S}/vm_sched.c ${S}/vm_swap.c ${S}/vm_swp.c ${S}/vm_text.c OBJS= init_main.o init_sysent.o kern_acct.o kern_clock.o \ kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o \ kern_proc.o kern_prot.o kern_resource.o kern_sig.o kern_sysctl.o \ kern_subr.o kern_synch.o kern_time.o kern_xxx.o quota_sys.o \ quota_kern.o quota_ufs.o quota_subr.o subr_log.o subr_prf.o subr_rmap.o \ ingreslock.o \ subr_xxx.o sys_generic.o sys_inode.o sys_kern.o \ sys_pipe.o sys_process.o syscalls.o tty.o tty_conf.o tty_pty.o \ tty_subr.o tty_tb.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o \ ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o \ ufs_subr.o ufs_syscalls.o uipc_syscalls.o vm_proc.o vm_sched.o \ ufs_disksubr.o \ vm_swap.o vm_swp.o vm_text.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s all: ${OBJS} depend: mkdep -f Make.sys ${CFLAGS} ${CFILES} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. NE, IT WILL GO AWAY. CONF} ${BASE} ${OV1} ${OV2} ${OV3} ${OV4} ${OV5} \ ${OV6} ${OV7} ${OV8} ${OV9} ${OV10} ${OV11} ${OV12} \ ${OV13} ${OV14} ${OV15} \ vers.o param.o # param.o must be last! LD_KOBJ=${CONF} ${BASE} \ -Z ${OV1} -Z ${OV2} -Z ${OV3} -Z ${OV4} -Z ${OV5} -Z ${OV6} \ -Z ${OV7} -Z ${OV8} -Z ${OV9} -Z ${OV10} -Z ${OV11} -Z ${OV12} \ -Z ${OV13} -Z ${OV14} -Z ${OV15} -Y \ vers.o param.o all: unix unix: ${SUB} ${KERNOBJ} checksys ld -X -i -o unix ${LD_KOBJ} size unix @echo Compacsys/conf/checksys.c 440 0 12 15313 5630147442 7575 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)checksys.c 1.5 (2.11BSD GTE) 8/28/94 */ /* * checksys * checks the system size and reports any limits exceeded. */ #include "param.h" #include "user.h" #include "file.h" #include "ioctl.h" #include "clist.h" #include "a.out.h" #include "stdio.h" #include "namei.h" /* Round up to a click boundary. */ #define cround(bytes) ((bytes + ctob(1) - 1) / ctob(1) * ctob(1)); #define round(x) (ctob(stoc(ctos(btoc(x))))) #define KB(val) ((u_int)(val * 1024)) #define N_END 0 #define N_NBUF 1 #define N_PROC 4 #define N_NINODE 9 #define N_CLIST 14 #define N_RAM 15 #define N_XITDESC 16 #define N_QUOTDESC 17 #define N_NAMECACHE 18 #define N_IOSIZE 19 #define N_NUMSYMS 20 struct nlist nl[N_NUMSYMS]; char *names[] = { "_end", /* 0 */ "_nbuf", /* 1 */ "_buf", /* 2 */ "_nproc", /* 3 */ "_proc", /* 4 */ "_ntext", /* 5 */ "_text", /* 6 */ "_nfile", /* 7 */ "_file", /* 8 */ "_ninode", /* 9 */ "_inode", /* 10 */ "_ncallout", /* 11 */ "_callout", /* 12 */ "_ucb_clist", /* 13 */ "_nclist", /* 14 */ "_ram_size", /* 15 */ "_xitdesc", /* 16 */ "_quotdesc", /* 17 */ "_namecache", /* 18 */ "__iosize" /* 19 */ }; static struct exec obj; static struct ovlhdr ovlhdr; static int fi; main(argc, argv) int argc; char **argv; { register int i; long size, totsize, ramdisk, getval(); int errs = 0, texterrs = 0, ninode; if (argc != 2) { fputs("usage: checksys unix-binary\n", stderr); exit(-1); } /* * Can't (portably) initialize unions, so we do it at run time */ for (i = 0; i < N_NUMSYMS; i++) nl[i].n_un.n_name = names[i]; if ((fi = open(argv[1], O_RDONLY)) < 0) { perror(argv[1]); exit(-1); } if (read(fi, &obj, sizeof(obj)) != sizeof(obj)) { fputs("checksys: can't read object header.\n", stderr); exit(-1); } if (obj.a_magic == A_MAGIC5 || obj.a_magic == A_MAGIC6) if (read(fi, &ovlhdr, sizeof(ovlhdr)) != sizeof(ovlhdr)) { fputs("checksys: can't read overlay header.\n", stderr); exit(-1); } switch(obj.a_magic) { /* * 0407-- nonseparate I/D "vanilla" */ case A_MAGIC1: case A_MAGIC2: size = obj.a_text + obj.a_data + obj.a_bss; if (size > KB(48)) { printf("total size is %ld, max is %u, too large by %ld bytes.\n", size, KB(48), size - KB(48)); errs++; } totsize = cround(size); break; /* * 0411-- separate I/D */ case A_MAGIC3: size = obj.a_data + obj.a_bss; if (size > KB(48)) { printf("data is %ld, max is %u, too large by %ld bytes.\n", size, KB(48), size - KB(48)); errs++; } totsize = obj.a_text + cround(size); break; /* * 0430-- overlaid nonseparate I/D */ case A_MAGIC5: if (obj.a_text > KB(16)) { printf("base segment is %u, max is %u, too large by %u bytes.\n", obj.a_text, KB(16), obj.a_text - KB(16)); errs++; texterrs++; } if (obj.a_text <= KB(8)) { printf("base segment is %u, minimum is %u, too small by %u bytes.\n", obj.a_text, KB(8), KB(8) - obj.a_text); errs++; } size = obj.a_data + obj.a_bss; if (size > KB(24)) { printf("data is %ld, max is %u, too large by %ld bytes.\n", size, KB(24), size - KB(24)); errs++; } /* * Base and overlay 1 occupy 16K and 8K of physical * memory, respectively, regardless of actual size. */ totsize = KB(24) + cround(size); /* * Subtract the first overlay, it will be added below * and it has already been included. */ totsize -= ovlhdr.ov_siz[0]; goto checkov; break; /* * 0431-- overlaid separate I/D */ case A_MAGIC6: if (obj.a_text > KB(56)) { printf("base segment is %u, max is %u, too large by %u bytes.\n", obj.a_text, KB(56), obj.a_text - KB(56)); errs++; } if (obj.a_text <= KB(48)) { printf("base segment is %u, min is %u, too small by %u bytes.\n", obj.a_text, KB(48), KB(48) - obj.a_text); errs++; } size = obj.a_data + obj.a_bss; if (size > KB(48)) { printf("data is %ld, max is %u, too large by %ld bytes.\n", size, KB(48), size - KB(48)); errs++; } totsize = obj.a_text + cround(size); checkov: for (i = 0;i < NOVL;i++) { totsize += ovlhdr.ov_siz[i]; if (ovlhdr.ov_siz[i] > KB(8)) { printf("overlay %d is %u, max is %u, too large by %u bytes.\n", i + 1, ovlhdr.ov_siz[i], KB(8), ovlhdr.ov_siz[i] - KB(8)); errs++; texterrs++; } /* * check for zero length overlay in the middle of * non-zero length overlays (boot croaks when faced * with this) ... */ if (i < NOVL-1 && ovlhdr.ov_siz[i] == 0 && ovlhdr.ov_siz[i+1] > 0) { printf("overlay %d is empty and there are non-empty overlays following it.\n", i + 1); errs++; texterrs++; } } break; default: printf("magic number 0%o not recognized.\n", obj.a_magic); exit(-1); } (void)nlist(argv[1], nl); if (!nl[N_NINODE].n_type) { puts("\"ninode\" not found in namelist."); exit(-1); } ninode = getval(N_NINODE); if (!texterrs) { if (nl[N_PROC].n_value >= 0120000) { printf("The remapping area (0120000-0140000, KDSD5)\n\tcontains data other than the proc, text and file tables.\n\tReduce other data by %u bytes.\n", nl[N_PROC].n_value - 0120000); errs++; } } totsize += (getval(N_NBUF) * MAXBSIZE); if (nl[N_CLIST].n_value) totsize += cround(getval(N_CLIST) * (long)sizeof(struct cblock)); if (nl[N_RAM].n_type) totsize += getval(N_RAM)*512; if (nl[N_QUOTDESC].n_type) totsize += 8192; if (nl[N_XITDESC].n_type) totsize += (ninode * 3 * sizeof (long)); if (nl[N_NAMECACHE].n_type) totsize += (ninode * sizeof(struct namecache)); if (nl[N_IOSIZE].n_type) totsize += getval(N_IOSIZE); totsize += ctob(USIZE); printf("System will occupy %ld bytes of memory (including buffers and clists).\n", totsize); for (i = 0; i < N_NUMSYMS; i++) { if (!(i % 3)) putchar('\n'); printf("\t%10.10s {0%06o}", nl[i].n_un.n_name+1, nl[i].n_value); } putchar('\n'); if (errs) puts("**** SYSTEM IS NOT BOOTABLE. ****"); exit(errs); } /* * Get the value of an initialized variable from the object file. */ static long getval(indx) int indx; { register int novl; u_int ret; off_t offst; if ((nl[indx].n_type&N_TYPE) == N_BSS) return((long)0); offst = nl[indx].n_value; offst += obj.a_text; offst += sizeof(obj); if (obj.a_magic == A_MAGIC2 || obj.a_magic == A_MAGIC5) offst -= (off_t)round(obj.a_text); if (obj.a_magic == A_MAGIC5 || obj.a_magic == A_MAGIC6) { offst += sizeof ovlhdr; if (obj.a_magic == A_MAGIC5) offst -= (off_t)round(ovlhdr.max_ovl); for (novl = 0;novl < NOVL;novl++) offst += (off_t)ovlhdr.ov_siz[novl]; } (void)lseek(fi, offst, L_SET); read(fi, &ret, sizeof(ret)); return((long)ret); } ksys.c 1.5 (2.11BSD GTE) 8/28/94 */ /* * checksys * checks the system size and reports any limits exceeded. */ #include "param.h" #include "user.h" #include "file.h" #include "ioctl.h" #include "clist.h" #include "a.out.h" #include "stdio.h" #include "namei.h" /* Round up to a click boundary. */ #defisys/conf/netbind.c 644 0 12 15233 5703426760 7417 /* * netbind * * 1/6/95 -- remove 8 character limit on undefined symbol printf. sms. * 1/8/94 -- revised for new object file format. sms. * * Resolve undefined inter-address-space references. * * Usage: * netbind unix.o netnix.o * * Produces two files as output: * * d.unix.s -- definitions of all symbols referenced by * unix.o but defined in netnix.o * d.netnix.s -- definitions of all symbols referenced by * netnix.o but defined in unix.o */ #include #include #include #include extern char *strdup(), *rindex(); struct xexec refExec, defExec; #define MAXSYMLEN 32 #define NSYMS 200 struct symbol { char *s_name; u_int s_value; u_int s_type; } symtab[NSYMS], *symfree; main(argc, argv) int argc; char **argv; { if (argc != 3) { printf("usage: %s unix.bo netnix.bo\n", *argv); exit(2); } resolve(argv[1], argv[2]); /* Produces d.unix.s */ resolve(argv[2], argv[1]); /* Produces d.netnix.s */ exit(0); } /* * resolve -- * * Resolve references made by ref to symbols defined in def. * * Side effects: * Prints a list of undefined symbols if there are any. * Produces the .s file corresponding to ref. * Adds the number of undefined symbols encountered to undef. */ resolve(ref, def) char *ref; /* Name of file referencing symbols */ char *def; /* Name of file defining symbols */ { FILE *refIN, *defIN, *refSTR, *defSTR, *refOUT, *openobj(); struct nlist syment; off_t stroff_ref, stroff_def; int nundef; char *rp, refout[MAXPATHLEN], name[MAXSYMLEN + 2]; bzero(name, sizeof (name)); if (rp = rindex(ref, '.')) *rp = '\0'; (void)sprintf(refout, "d.%s.s", ref); if (rp) *rp = '.'; if ((refIN = openobj(ref, &refExec, &refSTR)) == NULL) return; if ((defIN = openobj(def, &defExec, &defSTR)) == NULL) { fclose(refIN); fclose(refSTR); return; } if ((refOUT = fopen(refout, "w")) == NULL) { perror(refout); fclose(refIN); fclose(refSTR); fclose(defIN); fclose(defSTR); return; } /* * Actually generate the .s file needed. * Assumes that refExec and defExec have been set up to * hold the a.out headers for the reference and definition * object files. * * Algorithm: * Build a table of undefined symbols in refIN. * Define them by reading the symbol table of defIN. * Generate the .s file to refOUT. */ syminit(); nundef = 0; /* Find the undefined symbols */ stroff_ref = N_STROFF(refExec); fseek(refIN, N_SYMOFF(refExec), L_SET); while (fread(&syment, sizeof(syment), 1, refIN) > 0) { if (syment.n_type == (N_EXT|N_UNDF) && syment.n_value == 0) { fseek(refSTR, stroff_ref + syment.n_un.n_strx, L_SET); fread(name, sizeof (name), 1, refSTR); if (strcmp(name, "_end") && strcmp(name, "_etext") && strcmp(name, "_edata")) { nundef++; syment.n_un.n_name = name; symadd(&syment); } } } /* Define the undefined symbols */ stroff_def = N_STROFF(defExec); fseek(defIN, N_SYMOFF(defExec), L_SET); while (fread(&syment, sizeof(syment), 1, defIN) > 0) { if ((syment.n_type & N_EXT) == 0) continue; fseek(defSTR, stroff_def + syment.n_un.n_strx, L_SET); fread(name, sizeof (name), 1, defSTR); syment.n_un.n_name = name; nundef -= symdef(&syment, &defExec.e); } /* Any undefined symbols left? */ if (nundef > 0) { printf("%s: %d symbols undefined:\n", ref, nundef); symundef(); } symprdef(refOUT); fclose(refSTR); fclose(defSTR); fclose(refIN); fclose(defIN); fclose(refOUT); } /* * openobj -- * * Open the indicated file, check to make sure that it is a * valid object file with a symbol table, and read in the a.out header. * * Returns a pointer to an open FILE if successful, NULL if not. * Prints its own error messages. */ FILE * openobj(filename, exechdr, strfp) char *filename; struct xexec *exechdr; FILE **strfp; { register FILE *f; if (!(f = fopen(filename, "r"))) { perror(filename); return((FILE *)NULL); } *strfp = fopen(filename, "r"); /* for strings */ if (fread(exechdr, sizeof(*exechdr), 1, f) <= 0) { printf("%s: no a.out header\n", filename); goto bad; } if (N_BADMAG(exechdr->e)) { printf("%s: bad magic number\n", filename); goto bad; } if (exechdr->e.a_syms == 0) { printf("%s: no symbol table\n", filename); goto bad; } return(f); bad: fclose(f); fclose(*strfp); return((FILE *)NULL); } /* -------------------- Symbol table management ----------------------- */ /* * syminit -- * * Clear and initialize the symbol table. */ syminit() { symfree = symtab; } /* * symadd -- * * Add a symbol to the table. * We store both the symbol name and the symbol number. */ symadd(np) struct nlist *np; { if (symfree >= &symtab[NSYMS]) { printf("Symbol table overflow. Increase NSYMS.\n"); exit (1); } symfree->s_name = strdup(np->n_un.n_name); if (!symfree->s_name) { printf("netbind: out of memory for symbol strings\n"); exit(1); } symfree->s_type = N_UNDF; symfree->s_value = 0; symfree++; } /* * symdef -- * * Use the supplied symbol to define an undefined entry in * the symbol table. * * Returns 1 if the name of the symbol supplied was found in * the table, 0 otherwise. */ symdef(np, ep) struct nlist *np; struct exec *ep; { register struct symbol *sp; for (sp = symtab; sp < symfree; sp++) if (!strcmp(sp->s_name, np->n_un.n_name)) { int type = (np->n_type & N_TYPE); switch (type) { case N_TEXT: case N_ABS: sp->s_type = N_EXT|N_ABS; sp->s_value = np->n_value; break; case N_DATA: case N_BSS: sp->s_type = N_EXT|N_ABS; if (ep->a_flag) sp->s_value = np->n_value; else sp->s_value = np->n_value - ep->a_text; break; case N_UNDF: return(0); default: printf("netbind: symbol %s, bad type 0x%x\n", np->n_un.n_name, np->n_type); exit(1); } return (1); } return(0); } /* * symundef -- * * Print all undefined symbols in the symbol table. * First sorts the table before printing it. */ symundef() { register struct symbol *sp; int scmp(); qsort(symtab, symfree - symtab, sizeof(struct symbol), scmp); for (sp = symtab; sp < symfree; sp++) if ((sp->s_type & N_TYPE) == N_UNDF) printf("%s\n", sp->s_name); } scmp(s1, s2) register struct symbol *s1, *s2; { return(strcmp(s1->s_name, s2->s_name)); } /* * symprdef -- * * Output all defined symbols in the symbol table. * First sorts the table before printing it. */ symprdef(refOUT) FILE *refOUT; { register struct symbol *sp; int scmp(); qsort(symtab, symfree - symtab, sizeof (struct symbol), scmp); for (sp = symtab; sp < symfree; sp++) if ((sp->s_type & N_TYPE) != N_UNDF) { fprintf(refOUT, ".globl %s\n", sp->s_name); fprintf(refOUT, "%s = %o\n", sp->s_name, sp->s_value); } } DL11 NDH 0 # DH11; NDH is in units of boards (16 each) CS02 NO # DH units above are really Emulex CS02 # boards on a 22bit Qbus. NDM 0 # DM11; NDM is in units of boards (16 each) NDHU 0 # DHU11 NDHV 0 # DHV11 NDZ 0 # DZ11; NDZ is in units of boards (8 each) ######################################### # PERIPHERALS: OTHER # #############sys/conf/spl/ 755 0 12 0 5526060204 6303 sys/conf/spl/:splfix.movb 440 0 12 1542 5520356274 10661 g/jsr pc,__spl0/s//clrb 177776/ g/jsr pc,__spl\([1-7]\)/s//movb $40*\1, 177776/ g/jsr pc,__splsoftclock/s//movb $40, 177776/ g/jsr pc,__splnet/s//movb $100, 177776/ g/jsr pc,__splimp/s//movb $240, 177776/ g/jsr pc,__splbio/s//movb $240, 177776/ g/jsr pc,__spltty/s//movb $240, 177776/ g/jsr pc,__splclock/s//movb $300, 177776/ g/jsr pc,__splhigh/s//movb $340, 177776/ g/jsr pc,_spl0/s//movb 177776,r0;clrb 177776/ g/jsr pc,_spl\([1-7]\)/s//movb 177776,r0;movb $40*\1, 177776/ g/jsr pc,_splsoftclock/s//movb 177776,r0;movb $40, 177776/ g/jsr pc,_splnet/s//movb 177776,r0;movb $100, 177776/ g/jsr pc,_splbio/s//movb 177776,r0;movb $240, 177776/ g/jsr pc,_splimp/s//movb 177776,r0;movb $240, 177776/ g/jsr pc,_spltty/s//movb 177776,r0;movb $240, 177776/ g/jsr pc,_splclock/s//movb 177776,r0;movb $300, 177776/ g/jsr pc,_splhigh/s//movb 177776,r0;movb $340, 177776/ w q exit(2); } resolve(argv[1], argv[2]); /* Produces d.unix.s */ resolve(argv[2], argv[1]); /* Produces d.netnix.s */ exit(0); } /* * resolve -- * * Rsys/conf/spl/:splfix.mtps 440 0 12 1200 5520356100 10654 g/jsr pc,__spl\([0-7]\)/s//mtps $40*\1/ g/jsr pc,__splsoftclock/s//mtps $40/ g/jsr pc,__splnet/s//mtps $100/ g/jsr pc,__splbio/s//mtps $240/ g/jsr pc,__splimp/s//mtps $240/ g/jsr pc,__spltty/s//mtps $240/ g/jsr pc,__splclock/s//mtps $300/ g/jsr pc,__splhigh/s//mtps $340/ g/jsr pc,_spl\([0-7]\)/s//mfps r0;mtps $40*\1/ g/jsr pc,_splsoftclock/s//mfps r0;mtps $40/ g/jsr pc,_splnet/s//mfps r0;mtps $100/ g/jsr pc,_splbio/s//mfps r0;mtps $240/ g/jsr pc,_splimp/s//mfps r0;mtps $240/ g/jsr pc,_spltty/s//mfps r0;mtps $240/ g/jsr pc,_splclock/s//mfps r0;mtps $300/ g/jsr pc,_splhigh/s//mfps r0;mtps $340/ g/movb \(.*[^,]\),\*$-2/s//mtps \1/ w q 6/ g/jsr pc,_splimp/s//movb 177776,r0;movb $240, 177776/ g/jsr pc,_spltty/s//movb 177776,r0;movb $240, 177776/ g/jsr pc,_splclock/s//movb 177776,r0;movb $300, 177776/ g/jsr pc,_splhigh/s//movb 177776,r0;movb $340, 177776/ w q exit(2); } resolve(argv[1], argv[2]); /* Produces d.unix.s */ resolve(argv[2], argv[1]); /* Produces d.netnix.s */ exit(0); } /* * resolve -- * * Rsys/conf/spl/:splfix.profil 440 0 12 1226 5520356146 11206 g/jsr pc,__spl\([0-6]\)/s//spl \1/ g/jsr pc,__splsoftclock/s//spl 1/ g/jsr pc,__splnet/s//spl 2/ g/jsr pc,__splbio/s//spl 5/ g/jsr pc,__splimp/s//spl 5/ g/jsr pc,__spltty/s//spl 5/ g/jsr pc,__splclock/s//spl 6/ g/jsr pc,__spl7/s//spl 6/ g/jsr pc,__splhigh/s//spl 6/ g/jsr pc,_spl\([0-6]\)/s//movb 177776,r0;spl \1/ g/jsr pc,_splsoftclock/s//movb 177776,r0;spl 1/ g/jsr pc,_splnet/s//movb 177776,r0;spl 2/ g/jsr pc,_splbio/s//movb 177776,r0;spl 5/ g/jsr pc,_splimp/s//movb 177776,r0;spl 5/ g/jsr pc,_spltty/s//movb 177776,r0;spl 5/ g/jsr pc,_splclock/s//movb 177776,r0;spl 6/ g/jsr pc,_spl7/s//movb 177776,r0;spl 6/ g/jsr pc,_splhigh/s//movb 177776,r0;spl 6/ w q /movb 177776,r0;movb $240, 177776/ g/jsr pc,_spltty/s//movb 177776,r0;movb $240, 177776/ g/jsr pc,_splclock/s//movb 177776,r0;movb $300, 177776/ g/jsr pc,_splhigh/s//movb 177776,r0;movb $340, 177776/ w q exit(2); } resolve(argv[1], argv[2]); /* Produces d.unix.s */ resolve(argv[2], argv[1]); /* Produces d.netnix.s */ exit(0); } /* * resolve -- * * Rsys/conf/spl/:splfix.spl 440 0 12 1124 5520356214 10502 g/jsr pc,__spl\([0-7]\)/s//spl \1/ g/jsr pc,__splsoftclock/s//spl 1/ g/jsr pc,__splnet/s//spl 2/ g/jsr pc,__splbio/s//spl 5/ g/jsr pc,__splimp/s//spl 5/ g/jsr pc,__spltty/s//spl 5/ g/jsr pc,__splclock/s//spl 6/ g/jsr pc,__splhigh/s//spl 7/ g/jsr pc,_spl\([0-7]\)/s//movb 177776,r0;spl \1/ g/jsr pc,_splsoftclock/s//movb 177776,r0;spl 1/ g/jsr pc,_splnet/s//movb 177776,r0;spl 2/ g/jsr pc,_splbio/s//movb 177776,r0;spl 5/ g/jsr pc,_splimp/s//movb 177776,r0;spl 5/ g/jsr pc,_spltty/s//movb 177776,r0;spl 5/ g/jsr pc,_splclock/s//movb 177776,r0;spl 6/ g/jsr pc,_splhigh/s//movb 177776,r0;spl 7/ w q b 177776,r0;spl 6/ g/jsr pc,_splhigh/s//movb 177776,r0;spl 6/ w q /movb 177776,r0;movb $240, 177776/ g/jsr pc,_spltty/s//movb 177776,r0;movb $240, 177776/ g/jsr pc,_splclock/s//movb 177776,r0;movb $300, 177776/ g/jsr pc,_splhigh/s//movb 177776,r0;movb $340, 177776/ w q exit(2); } resolve(argv[1], argv[2]); /* Produces d.unix.s */ resolve(argv[2], argv[1]); /* Produces d.netnix.s */ exit(0); } /* * resolve -- * * Rsys/conf/spl/:splfix.mfps 440 0 12 1100 5520355674 10654 g/jsr pc,__spl\([0-7]\)/s//spl \1/ g/jsr pc,__splsoftclock/s//spl 1/ g/jsr pc,__splnet/s//spl 2/ g/jsr pc,__splbio/s//spl 5/ g/jsr pc,__splimp/s//spl 5/ g/jsr pc,__spltty/s//spl 5/ g/jsr pc,__splclock/s//spl 6/ g/jsr pc,__splhigh/s//spl 7/ g/jsr pc,_spl\([0-7]\)/s//mfps r0;spl \1/ g/jsr pc,_splsoftclock/s//mfps r0;spl 1/ g/jsr pc,_splnet/s//mfps r0;spl 2/ g/jsr pc,_splbio/s//mfps r0;spl 5/ g/jsr pc,_splimp/s//mfps r0;spl 5/ g/jsr pc,_spltty/s//mfps r0;spl 5/ g/jsr pc,_splclock/s//mfps r0;spl 6/ g/jsr pc,_splhigh/s//mfps r0;spl 7/ g/movb \(.*[^,]\),\*$-2/s//mtps \1/ w q 77776,r0;spl 7/ q b 177776,r0;spl 6/ g/jsr pc,_splhigh/s//movb 177776,r0;spl 6/ w q /movb 177776,r0;movb $240, 177776/ g/jsr pc,_spltty/s//movb 177776,r0;movb $240, 177776/ g/jsr pc,_splclock/s//movb 177776,r0;movb $300, 177776/ g/jsr pc,_splhigh/s//movb 177776,r0;movb $340, 177776/ w q exit(2); } resolve(argv[1], argv[2]); /* Produces d.unix.s */ resolve(argv[2], argv[1]); /* Produces d.netnix.s */ exit(0); } /* * resolve -- * * Rsys/conf/spl/:splfix.movb+mfps 440 0 12 1443 5520356017 11615 g/jsr pc,__spl0/s//clrb 177776/ g/jsr pc,__spl\([1-7]\)/s//movb $40*\1, 177776/ g/jsr pc,__splsoftclock/s//movb $40, 177776/ g/jsr pc,__splnet/s//movb $100, 177776/ g/jsr pc,__splimp/s//movb $240, 177776/ g/jsr pc,__splbio/s//movb $240, 177776/ g/jsr pc,__spltty/s//movb $240, 177776/ g/jsr pc,__splclock/s//movb $300, 177776/ g/jsr pc,__splhigh/s//movb $340, 177776/ g/jsr pc,_spl0/s//mfps r0;clrb 177776/ g/jsr pc,_spl\([1-7]\)/s//mfps r0;movb $40*\1, 177776/ g/jsr pc,_splsoftclock/s//mfps r0;movb $40, 177776/ g/jsr pc,_splnet/s//mfps r0;movb $100, 177776/ g/jsr pc,_splbio/s//mfps r0;movb $240, 177776/ g/jsr pc,_splimp/s//mfps r0;movb $240, 177776/ g/jsr pc,_spltty/s//mfps r0;movb $240, 177776/ g/jsr pc,_splclock/s//mfps r0;movb $300, 177776/ g/jsr pc,_splhigh/s//mfps r0;movb $340, 177776/ w q 76/ g/jsr pc,_splhigh/s//movb 177776,r0;movb $340, 177776/ w q exit(2); } resolve(argv[1], argv[2]); /* Produces d.unix.s */ resolve(argv[2], argv[1]); /* Produces d.netnix.s */ exit(0); } /* * resolve -- * * Rsys/conf/spl_3com/ 755 0 12 0 5526060206 7226 sys/conf/spl_3com/:splfix.movb 640 0 12 1542 5520356551 11602 g/jsr pc,__spl0/s//clrb 177776/ g/jsr pc,__spl\([1-7]\)/s//movb $40*\1, 177776/ g/jsr pc,__splsoftclock/s//movb $40, 177776/ g/jsr pc,__splnet/s//movb $100, 177776/ g/jsr pc,__splimp/s//movb $300, 177776/ g/jsr pc,__splbio/s//movb $240, 177776/ g/jsr pc,__spltty/s//movb $240, 177776/ g/jsr pc,__splclock/s//movb $300, 177776/ g/jsr pc,__splhigh/s//movb $340, 177776/ g/jsr pc,_spl0/s//movb 177776,r0;clrb 177776/ g/jsr pc,_spl\([1-7]\)/s//movb 177776,r0;movb $40*\1, 177776/ g/jsr pc,_splsoftclock/s//movb 177776,r0;movb $40, 177776/ g/jsr pc,_splnet/s//movb 177776,r0;movb $100, 177776/ g/jsr pc,_splbio/s//movb 177776,r0;movb $240, 177776/ g/jsr pc,_splimp/s//movb 177776,r0;movb $300, 177776/ g/jsr pc,_spltty/s//movb 177776,r0;movb $240, 177776/ g/jsr pc,_splclock/s//movb 177776,r0;movb $300, 177776/ g/jsr pc,_splhigh/s//movb 177776,r0;movb $340, 177776/ w q exit(2); } resolve(argv[1], argv[2]); /* Produces d.unix.s */ resolve(argv[2], argv[1]); /* Produces d.netnix.s */ exit(0); } /* * resolve -- * * Rsys/conf/spl_3com/:splfix.mtps 640 0 12 1200 5520356650 11611 g/jsr pc,__spl\([0-7]\)/s//mtps $40*\1/ g/jsr pc,__splsoftclock/s//mtps $40/ g/jsr pc,__splnet/s//mtps $100/ g/jsr pc,__splbio/s//mtps $240/ g/jsr pc,__splimp/s//mtps $300/ g/jsr pc,__spltty/s//mtps $240/ g/jsr pc,__splclock/s//mtps $300/ g/jsr pc,__splhigh/s//mtps $340/ g/jsr pc,_spl\([0-7]\)/s//mfps r0;mtps $40*\1/ g/jsr pc,_splsoftclock/s//mfps r0;mtps $40/ g/jsr pc,_splnet/s//mfps r0;mtps $100/ g/jsr pc,_splbio/s//mfps r0;mtps $240/ g/jsr pc,_splimp/s//mfps r0;mtps $300/ g/jsr pc,_spltty/s//mfps r0;mtps $240/ g/jsr pc,_splclock/s//mfps r0;mtps $300/ g/jsr pc,_splhigh/s//mfps r0;mtps $340/ g/movb \(.*[^,]\),\*$-2/s//mtps \1/ w q 6/ g/jsr pc,_splimp/s//movb 177776,r0;movb $300, 177776/ g/jsr pc,_spltty/s//movb 177776,r0;movb $240, 177776/ g/jsr pc,_splclock/s//movb 177776,r0;movb $300, 177776/ g/jsr pc,_splhigh/s//movb 177776,r0;movb $340, 177776/ w q exit(2); } resolve(argv[1], argv[2]); /* Produces d.unix.s */ resolve(argv[2], argv[1]); /* Produces d.netnix.s */ exit(0); } /* * resolve -- * * Rsys/conf/spl_3com/:splfix.profil 640 0 12 1226 5520356711 12127 g/jsr pc,__spl\([0-6]\)/s//spl \1/ g/jsr pc,__splsoftclock/s//spl 1/ g/jsr pc,__splnet/s//spl 2/ g/jsr pc,__splbio/s//spl 5/ g/jsr pc,__splimp/s//spl 6/ g/jsr pc,__spltty/s//spl 5/ g/jsr pc,__splclock/s//spl 6/ g/jsr pc,__spl7/s//spl 6/ g/jsr pc,__splhigh/s//spl 6/ g/jsr pc,_spl\([0-6]\)/s//movb 177776,r0;spl \1/ g/jsr pc,_splsoftclock/s//movb 177776,r0;spl 1/ g/jsr pc,_splnet/s//movb 177776,r0;spl 2/ g/jsr pc,_splbio/s//movb 177776,r0;spl 5/ g/jsr pc,_splimp/s//movb 177776,r0;spl 6/ g/jsr pc,_spltty/s//movb 177776,r0;spl 5/ g/jsr pc,_splclock/s//movb 177776,r0;spl 6/ g/jsr pc,_spl7/s//movb 177776,r0;spl 6/ g/jsr pc,_splhigh/s//movb 177776,r0;spl 6/ w q /movb 177776,r0;movb $300, 177776/ g/jsr pc,_spltty/s//movb 177776,r0;movb $240, 177776/ g/jsr pc,_splclock/s//movb 177776,r0;movb $300, 177776/ g/jsr pc,_splhigh/s//movb 177776,r0;movb $340, 177776/ w q exit(2); } resolve(argv[1], argv[2]); /* Produces d.unix.s */ resolve(argv[2], argv[1]); /* Produces d.netnix.s */ exit(0); } /* * resolve -- * * Rsys/conf/spl_3com/:splfix.spl 640 0 12 1124 5520356752 11434 g/jsr pc,__spl\([0-7]\)/s//spl \1/ g/jsr pc,__splsoftclock/s//spl 1/ g/jsr pc,__splnet/s//spl 2/ g/jsr pc,__splbio/s//spl 5/ g/jsr pc,__splimp/s//spl 6/ g/jsr pc,__spltty/s//spl 5/ g/jsr pc,__splclock/s//spl 6/ g/jsr pc,__splhigh/s//spl 7/ g/jsr pc,_spl\([0-7]\)/s//movb 177776,r0;spl \1/ g/jsr pc,_splsoftclock/s//movb 177776,r0;spl 1/ g/jsr pc,_splnet/s//movb 177776,r0;spl 2/ g/jsr pc,_splbio/s//movb 177776,r0;spl 5/ g/jsr pc,_splimp/s//movb 177776,r0;spl 6/ g/jsr pc,_spltty/s//movb 177776,r0;spl 5/ g/jsr pc,_splclock/s//movb 177776,r0;spl 6/ g/jsr pc,_splhigh/s//movb 177776,r0;spl 7/ w q b 177776,r0;spl 6/ g/jsr pc,_splhigh/s//movb 177776,r0;spl 6/ w q /movb 177776,r0;movb $300, 177776/ g/jsr pc,_spltty/s//movb 177776,r0;movb $240, 177776/ g/jsr pc,_splclock/s//movb 177776,r0;movb $300, 177776/ g/jsr pc,_splhigh/s//movb 177776,r0;movb $340, 177776/ w q exit(2); } resolve(argv[1], argv[2]); /* Produces d.unix.s */ resolve(argv[2], argv[1]); /* Produces d.netnix.s */ exit(0); } /* * resolve -- * * Rsys/conf/spl_3com/:splfix.mfps 640 0 12 1100 5520356505 11571 g/jsr pc,__spl\([0-7]\)/s//spl \1/ g/jsr pc,__splsoftclock/s//spl 1/ g/jsr pc,__splnet/s//spl 2/ g/jsr pc,__splbio/s//spl 5/ g/jsr pc,__splimp/s//spl 6/ g/jsr pc,__spltty/s//spl 5/ g/jsr pc,__splclock/s//spl 6/ g/jsr pc,__splhigh/s//spl 7/ g/jsr pc,_spl\([0-7]\)/s//mfps r0;spl \1/ g/jsr pc,_splsoftclock/s//mfps r0;spl 1/ g/jsr pc,_splnet/s//mfps r0;spl 2/ g/jsr pc,_splbio/s//mfps r0;spl 5/ g/jsr pc,_splimp/s//mfps r0;spl 6/ g/jsr pc,_spltty/s//mfps r0;spl 5/ g/jsr pc,_splclock/s//mfps r0;spl 6/ g/jsr pc,_splhigh/s//mfps r0;spl 7/ g/movb \(.*[^,]\),\*$-2/s//mtps \1/ w q 77776,r0;spl 7/ q b 177776,r0;spl 6/ g/jsr pc,_splhigh/s//movb 177776,r0;spl 6/ w q /movb 177776,r0;movb $300, 177776/ g/jsr pc,_spltty/s//movb 177776,r0;movb $240, 177776/ g/jsr pc,_splclock/s//movb 177776,r0;movb $300, 177776/ g/jsr pc,_splhigh/s//movb 177776,r0;movb $340, 177776/ w q exit(2); } resolve(argv[1], argv[2]); /* Produces d.unix.s */ resolve(argv[2], argv[1]); /* Produces d.netnix.s */ exit(0); } /* * resolve -- * * Rsys/conf/spl_3com/:splfix.movb+mfps 640 0 12 1443 5520356612 12541 g/jsr pc,__spl0/s//clrb 177776/ g/jsr pc,__spl\([1-7]\)/s//movb $40*\1, 177776/ g/jsr pc,__splsoftclock/s//movb $40, 177776/ g/jsr pc,__splnet/s//movb $100, 177776/ g/jsr pc,__splimp/s//movb $300, 177776/ g/jsr pc,__splbio/s//movb $240, 177776/ g/jsr pc,__spltty/s//movb $240, 177776/ g/jsr pc,__splclock/s//movb $300, 177776/ g/jsr pc,__splhigh/s//movb $340, 177776/ g/jsr pc,_spl0/s//mfps r0;clrb 177776/ g/jsr pc,_spl\([1-7]\)/s//mfps r0;movb $40*\1, 177776/ g/jsr pc,_splsoftclock/s//mfps r0;movb $40, 177776/ g/jsr pc,_splnet/s//mfps r0;movb $100, 177776/ g/jsr pc,_splbio/s//mfps r0;movb $240, 177776/ g/jsr pc,_splimp/s//mfps r0;movb $300, 177776/ g/jsr pc,_spltty/s//mfps r0;movb $240, 177776/ g/jsr pc,_splclock/s//mfps r0;movb $300, 177776/ g/jsr pc,_splhigh/s//mfps r0;movb $340, 177776/ w q 76/ g/jsr pc,_splhigh/s//movb 177776,r0;movb $340, 177776/ w q exit(2); } resolve(argv[1], argv[2]); /* Produces d.unix.s */ resolve(argv[2], argv[1]); /* Produces d.netnix.s */ exit(0); } /* * resolve -- * * Rsys/conf/SMS 640 0 12 23241 6004073155 6176 # 1995/07/21 - XP_PROBE removed. # # Machine configuration file for 2.11BSD distributed kernel. # # Format: # name value comments # An item's value may be either numerical, boolean or a string; if it's # boolean, use "YES" or "NO" to set it or unset it, respectively. Use # the default value and the comments field as indicators of the type of # field it is. ######################################### # MACHINE DEPENDENT PARAMETERS # ######################################### # Machine type # Split I/D and hardware floating point are required. # UNIBUS support is always included, it only cost 1kb of text space and # 94 bytes of D space for Qbus systems (obviously Unibus systems incur # no penalty). # The define Q22 has been removed. The references to it were incorrect # (i.e. using it to distinguish between an Emulex CS02 and a DH11) or # inappropriate (the if_il.c driver should have been checking if a Unibus # Map was present at runtime). #LINEHZ 50 # clock frequency European LINEHZ 60 # clock frequency USA # PDP-11 machine type; allowable values are GENERIC, 44, 70, 73. GENERIC # should only be used to build a distribution kernel. The only use of this # option is to select the proper in-line PS instructions (references to the # PSW use 'spl', 'mfps/mtps' or 'movb' instructions depending on the cpu type). #PDP11 GENERIC # distribution kernel #PDP11 44 # PDP-11/44 #PDP11 70 # PDP-11/70,45,50,55 PDP11 73 # PDP-11/73,53,83,93,84,94 ######################################### # GENERAL SYSTEM PARAMETERS # ######################################### IDENT SMS # machine name MAXUSERS 20 # maxusers on machine # BOOTDEV is the letter combination denoting the autoboot device, # or NONE if not using the autoboot feature. #BOOTDEV NONE # don't autoboot #BOOTDEV dvhp # DIVA Comp/V boot device #BOOTDEV hk6 # rk06 boot device #BOOTDEV hk7 # rk07 boot device BOOTDEV ra # MSCP boot device #BOOTDEV rl # rl01/02 boot device #BOOTDEV rm # rm02/03/05 boot device #BOOTDEV br # Eaton BR1537/BR1711 boot device #BOOTDEV sc11 # Emulex SC11/B boot device #BOOTDEV sc21 # Emulex SC21 boot device #BOOTDEV si # si 9500 boot device # Timezone, in minutes west of GMT #TIMEZONE 300 # EST #TIMEZONE 360 # CST #TIMEZONE 420 # WST TIMEZONE 480 # PST DST 1 # Daylight Savings Time (1 or 0) # Filesystem configuration # Rootdev, swapdev etc. should be in terms of makedev. For example, # if you have an SMD drive using the xp driver, rootdev would be xp0a, # or "makedev(10,0)". Swapdev would be the b partition, xp0b, or # "makedev(10,1)". The 10 is the major number of the device (the offset # in the bdevsw table in conf.c) and the 0 and 1 are the minor numbers # which correspond to the partitions as described in the section 4 manual # pages. You can also get the major numbers from the MAKEDEV script in # /dev. PIPEDEV makedev(5,0) # makedev(10,0) ra0a ROOTDEV makedev(5,0) # makedev(10,0) ra0a SWAPDEV makedev(5,1) # makedev(10,1) ra0b # DUMPROUTINE indicates which dump routine should be used. DUMPDEV # should be in terms of makedev. If DUMPDEV is NODEV no automatic # dumps will be taken, and DUMPROUTINE needs to be set to "nulldev" to # resolve the reference. See param.h and ioconf.c for more information. # DUMPLO should leave room for the kernel to start swapping without # overwriting the dump. DUMPLO 1024 # dump start address DUMPDEV makedev(5,1) # makedev(10,1) xp0b #DUMPROUTINE nulldev # no dump routine. #DUMPROUTINE hkdump # hk driver dump routine #DUMPROUTINE hpdump # hp driver dump routine DUMPROUTINE radump # ra driver dump routine #DUMPROUTINE rldump # rl driver dump routine #DUMPROUTINE rmdump # rm driver dump routine #DUMPROUTINE brdump # br driver dump routine #DUMPROUTINE sidump # si driver dump routine #DUMPROUTINE xpdump # xp driver dump routine #DUMPROUTINE tmsdump # tms driver dump routine ######################################### # KERNEL CONFIGURATION # ######################################### BADSECT NO # bad-sector forwarding EXTERNALITIMES YES # map out inode time values UCB_CLIST YES # clists moved from kernel data space QUOTA YES # dynamic file system quotas # NOTE -- *very* expensive # UCB_METER is fairly expensive, but various programs (iostat, vmstat, etc) # use it. UCB_METER YES # vmstat performance metering # NBUF is the size of the buffer cache, and is directly related to the UNIBUS # mapping registers. There are 32 total mapping registers, of which 30 are # available. The 0'th is used for CLISTS, and the 31st is used for the I/O # page on some PDP's. It's suggested that you allow 7 mapping registers # per UNIBUS character device so that you can move 56K of data on each device # simultaneously. The rest should be assigned to the block buffer pool. So, # if you have a DR-11 and a TM-11, you would leave 14 unassigned for them and # allocate 16 to the buffer pool. Since each mapping register addresses 8 # buffers for a 1K file system, NBUF would be 128. A possible exception would # be to reduce the buffers to save on data space, as they were 24 bytes each # Should be 'small' for GENERIC, so room for kernel + large program to run. NBUF 128 # buffer cache, *must* be <= 240 # DIAGNOSTIC does various run-time checks, some of which are pretty # expensive and at a high priority. Suggested use is when the kernel # is crashing and you don't know why, otherwise run with it off. DIAGNOSTIC NO # misc. diagnostic loops and checks ######################################### # PERIPHERALS: DISK DRIVES # ######################################### NBR 0 # EATON BR1537/BR1711, BR1538A, B, C, D NHK 0 # RK611, RK06/07 NRAC 2 # NRAD controllers NRAD 4 # RX50, RC25, RD51/52/53, RA60/80/81 NRK 0 # RK05 NRL 0 # RL01/02 NRX 0 # RX02 NSI 0 # SI 9500 driver for CDC 9766 disks NXPC 0 # NXPD controllers (RH70/RH11 style) NXPD 0 # RM02/03/05, RP04/05/06, CDC 9766, # Ampex 9300, Diva, Fuji 160, SI Eagle. NRAM 0 # RAM disk size (512-byte blocks) ######################################### # PERIPHERALS: TAPE DRIVES # ######################################### NHT 0 # TE16, TU45, TU77 # Setting AVIVTM configures the TM driver for the AVIV 800/1600/6250 # controller (the standard DEC TM only supports 800BPI). For more details, # see /sys/pdpuba/tm.c. NTM 0 # TM11 AVIVTM YES # AVIV 800/1600/6250 controller NTS 0 # TS11 NTMSCP 2 # TMSCP controllers NTMS 3 # TMSCP drives TMSCP_DEBUG NO # debugging code in TMSCP drive (EXPENSIVE) ######################################### # PERIPHERALS: TERMINALS # ######################################### # NKL includes both KL11's and DL11's. # It should always be at least 1, for the console. NKL 2 # KL11, DL11 NDH 0 # DH11; NDH is in units of boards (16 each) CS02 NO # DH units above are really Emulex CS02 # boards on a 22bit Qbus. NDM 0 # DM11; NDM is in units of boards (16 each) NDHU 0 # DHU11 NDHV 1 # DHV11 NDZ 0 # DZ11; NDZ is in units of boards (8 each) ######################################### # PERIPHERALS: OTHER # ######################################### NDN 0 # DN11 dialer NLP 0 # Line Printer LP_MAXCOL 132 # Maximum number of columns on line printers NDR 0 # DR11-W ######################################### # PSEUDO DEVICES, PROTOCOLS, NETWORKING # ######################################### # Networking only works with split I/D and SUPERVISOR space, i.e. with the # 11/44/53/70/73/83/84/93/94. NETHER should be non-zero for networking # systems using any ethernet. CHECKSTACK makes sure the networking stack # pointer and the kernel stack pointer don't collide; it's fairly expensive # at 4 extra instructions for EVERY function call AND return, always left # NO unless doing serious debugging. INET YES # TCP/IP CHECKSTACK NO # Kernel & Supervisor stack pointer checking NETHER 1 # ether pseudo-device # Note, PTY's and the select(2) system call do not require the kernel to # be configured for networking (INET). Note that you can allocate PTY's # in any number (multiples of 8, of 16, even, odd, prime, whatever). Nothing # in the kernel cares. PTY's cost 78 bytes apiece in kernel data space. You # should probably have at least 8-10 since several applications use them: # script, jove, window, rlogin, ... NPTY 12 # pseudo-terminals - GENERIC sys needs NONE NEC 0 # 3Com Ethernet NDE 0 # DEUNA/DELUA NIL 0 # Interlan Ethernet NSL 1 # Serial Line IP NQE 1 # DEQNA NQT 0 # DEQTA (DELQA-YM, DELQA-PLUS) NVV 0 # V2LNI (Pronet) NACC 0 # ACC LH/DH ARPAnet IMP interface PLI NO # LH/DH is connected to a PLI NIMP 0 # ARPAnet IMP 1822 interface # The following are untested in 2.11BSD; some are untested since before 2.9BSD # Some won't even compile. Most will require modification. Good luck. ENABLE34 NO # if have the ENABLE34 board NCSS 0 # DEC/CSS IMP11-A ARPAnet IMP interface NDMC 0 # DMC11 NEN 0 # Xerox prototype (3 Mb) Ethernet NHY 0 # Hyperchannel NS 0 # Xerox NS (XNS) NSRI 0 # SRI DR11c ARPAnet IMP NTB 0 # RS232 interface for Genisco/Hitachi tablets # Defining FPSIM to YES compiles a floating point simulator into the kernel # which will catch floating point instruction traps from user space. This # doesn't work at present. FPSIM NO # floating point simulator # To enable profiling, the :splfix script must be changed to use spl6 instead # of spl7 (see conf/:splfix.profile), also, you have to have a machine with a # supervisor PAR/PDR pair, i.e. an 11/44/45/50/53/55/70/73/83/84, as well # as both a KW11-L and a KW11-P. # # Note that profiling is not currently working. We don't have any plans on # fixing it, so this is essentially a non-supported feature. PROFILE NO # system profiling with KW11P clock INGRES YES # include the Ingres lock driver ################################ # PSEUDO DEVICES, PROTOCOLS, NETWORKING # ######################################### # Networking only works with split I/D and SUPERVISOR space, i.e. with the # 11/44/53/70/73/83/84/93/94. NETHER should be non-zero for networking # systems using any ethernet. CHECKSTACK makes sure the networking stack # pointer andsys/conf/NONET 640 0 12 23240 6004073100 6404 # 1995/07/21 - XP_PROBE removed. # # Machine configuration file for 2.11BSD distributed kernel. # # Format: # name value comments # An item's value may be either numerical, boolean or a string; if it's # boolean, use "YES" or "NO" to set it or unset it, respectively. Use # the default value and the comments field as indicators of the type of # field it is. ######################################### # MACHINE DEPENDENT PARAMETERS # ######################################### # Machine type # Split I/D and hardware floating point are required. # UNIBUS support is always included, it only cost 1kb of text space and # 94 bytes of D space for Qbus systems (obviously Unibus systems incur # no penalty). # The define Q22 has been removed. The references to it were incorrect # (i.e. using it to distinguish between an Emulex CS02 and a DH11) or # inappropriate (the if_il.c driver should have been checking if a Unibus # Map was present at runtime). #LINEHZ 50 # clock frequency European LINEHZ 60 # clock frequency USA # PDP-11 machine type; allowable values are GENERIC, 44, 70, 73. GENERIC # should only be used to build a distribution kernel. The only use of this # option is to select the proper in-line PS instructions (references to the # PSW use 'spl', 'mfps/mtps' or 'movb' instructions depending on the cpu type). #PDP11 GENERIC # distribution kernel #PDP11 44 # PDP-11/44 #PDP11 70 # PDP-11/70,45,50,55 PDP11 73 # PDP-11/73,53,83,93,84,94 ######################################### # GENERAL SYSTEM PARAMETERS # ######################################### IDENT NONET # machine name MAXUSERS 16 # maxusers on machine # BOOTDEV is the letter combination denoting the autoboot device, # or NONE if not using the autoboot feature. #BOOTDEV NONE # don't autoboot #BOOTDEV dvhp # DIVA Comp/V boot device #BOOTDEV hk6 # rk06 boot device #BOOTDEV hk7 # rk07 boot device BOOTDEV ra # MSCP boot device #BOOTDEV rl # rl01/02 boot device #BOOTDEV rm # rm02/03/05 boot device #BOOTDEV br # Eaton BR1537/BR1711 boot device #BOOTDEV sc11 # Emulex SC11/B boot device #BOOTDEV sc21 # Emulex SC21 boot device #BOOTDEV si # si 9500 boot device # Timezone, in minutes west of GMT #TIMEZONE 300 # EST #TIMEZONE 360 # CST #TIMEZONE 420 # WST TIMEZONE 480 # PST DST 1 # Daylight Savings Time (1 or 0) # Filesystem configuration # Rootdev, swapdev etc. should be in terms of makedev. For example, # if you have an SMD drive using the xp driver, rootdev would be xp0a, # or "makedev(10,0)". Swapdev would be the b partition, xp0b, or # "makedev(10,1)". The 10 is the major number of the device (the offset # in the bdevsw table in conf.c) and the 0 and 1 are the minor numbers # which correspond to the partitions as described in the section 4 manual # pages. You can also get the major numbers from the MAKEDEV script in # /dev. PIPEDEV makedev(5,0) # makedev(10,0) ra0a ROOTDEV makedev(5,0) # makedev(10,0) ra0a SWAPDEV makedev(5,1) # makedev(10,1) ra0b # DUMPROUTINE indicates which dump routine should be used. DUMPDEV # should be in terms of makedev. If DUMPDEV is NODEV no automatic # dumps will be taken, and DUMPROUTINE needs to be set to "nulldev" to # resolve the reference. See param.h and ioconf.c for more information. # DUMPLO should leave room for the kernel to start swapping without # overwriting the dump. DUMPLO 1024 # dump start address DUMPDEV makedev(5,1) # makedev(10,1) xp0b #DUMPROUTINE nulldev # no dump routine. #DUMPROUTINE hkdump # hk driver dump routine #DUMPROUTINE hpdump # hp driver dump routine DUMPROUTINE radump # ra driver dump routine #DUMPROUTINE rldump # rl driver dump routine #DUMPROUTINE rmdump # rm driver dump routine #DUMPROUTINE brdump # br driver dump routine #DUMPROUTINE sidump # si driver dump routine #DUMPROUTINE xpdump # xp driver dump routine #DUMPROUTINE tmsdump # tms driver dump routine ######################################### # KERNEL CONFIGURATION # ######################################### BADSECT NO # bad-sector forwarding EXTERNALITIMES YES # map out inode time values UCB_CLIST YES # clists moved from kernel data space QUOTA NO # dynamic file system quotas # NOTE -- *very* expensive # UCB_METER is fairly expensive, but various programs (iostat, vmstat, etc) # use it. UCB_METER YES # vmstat performance metering # NBUF is the size of the buffer cache, and is directly related to the UNIBUS # mapping registers. There are 32 total mapping registers, of which 30 are # available. The 0'th is used for CLISTS, and the 31st is used for the I/O # page on some PDP's. It's suggested that you allow 7 mapping registers # per UNIBUS character device so that you can move 56K of data on each device # simultaneously. The rest should be assigned to the block buffer pool. So, # if you have a DR-11 and a TM-11, you would leave 14 unassigned for them and # allocate 16 to the buffer pool. Since each mapping register addresses 8 # buffers for a 1K file system, NBUF would be 128. A possible exception would # be to reduce the buffers to save on data space, as they were 24 bytes each # Should be 'small' for GENERIC, so room for kernel + large program to run. NBUF 128 # buffer cache, *must* be <= 240 # DIAGNOSTIC does various run-time checks, some of which are pretty # expensive and at a high priority. Suggested use is when the kernel # is crashing and you don't know why, otherwise run with it off. DIAGNOSTIC NO # misc. diagnostic loops and checks ######################################### # PERIPHERALS: DISK DRIVES # ######################################### NBR 0 # EATON BR1537/BR1711, BR1538A, B, C, D NHK 0 # RK611, RK06/07 NRAC 2 # NRAD controllers NRAD 4 # RX50, RC25, RD51/52/53, RA60/80/81 NRK 0 # RK05 NRL 0 # RL01/02 NRX 0 # RX02 NSI 0 # SI 9500 driver for CDC 9766 disks NXPC 0 # NXPD controllers (RH70/RH11 style) NXPD 0 # RM02/03/05, RP04/05/06, CDC 9766, # Ampex 9300, Diva, Fuji 160, SI Eagle. NRAM 0 # RAM disk size (512-byte blocks) ######################################### # PERIPHERALS: TAPE DRIVES # ######################################### NHT 0 # TE16, TU45, TU77 # Setting AVIVTM configures the TM driver for the AVIV 800/1600/6250 # controller (the standard DEC TM only supports 800BPI). For more details, # see /sys/pdpuba/tm.c. NTM 0 # TM11 AVIVTM YES # AVIV 800/1600/6250 controller NTS 0 # TS11 NTMSCP 2 # TMSCP controllers NTMS 4 # TMSCP drives TMSCP_DEBUG NO # debugging code in TMSCP drive (EXPENSIVE) ######################################### # PERIPHERALS: TERMINALS # ######################################### # NKL includes both KL11's and DL11's. # It should always be at least 1, for the console. NKL 2 # KL11, DL11 NDH 0 # DH11; NDH is in units of boards (16 each) CS02 NO # DH units above are really Emulex CS02 # boards on a 22bit Qbus. NDM 0 # DM11; NDM is in units of boards (16 each) NDHU 0 # DHU11 NDHV 1 # DHV11 NDZ 0 # DZ11; NDZ is in units of boards (8 each) ######################################### # PERIPHERALS: OTHER # ######################################### NDN 0 # DN11 dialer NLP 0 # Line Printer LP_MAXCOL 132 # Maximum number of columns on line printers NDR 0 # DR11-W ######################################### # PSEUDO DEVICES, PROTOCOLS, NETWORKING # ######################################### # Networking only works with split I/D and SUPERVISOR space, i.e. with the # 11/44/53/70/73/83/84/93/94. NETHER should be non-zero for networking # systems using any ethernet. CHECKSTACK makes sure the networking stack # pointer and the kernel stack pointer don't collide; it's fairly expensive # at 4 extra instructions for EVERY function call AND return, always left # NO unless doing serious debugging. INET NO # TCP/IP CHECKSTACK NO # Kernel & Supervisor stack pointer checking NETHER 0 # ether pseudo-device # Note, PTY's and the select(2) system call do not require the kernel to # be configured for networking (INET). Note that you can allocate PTY's # in any number (multiples of 8, of 16, even, odd, prime, whatever). Nothing # in the kernel cares. PTY's cost 78 bytes apiece in kernel data space. You # should probably have at least 8-10 since several applications use them: # script, jove, window, rlogin, ... NPTY 8 # pseudo-terminals - GENERIC sys needs NONE NEC 0 # 3Com Ethernet NDE 0 # DEUNA/DELUA NIL 0 # Interlan Ethernet NSL 0 # Serial Line IP NQE 0 # DEQNA NQT 0 # DEQTA (DELQA-YM, DELQA-PLUS) NVV 0 # V2LNI (Pronet) NACC 0 # ACC LH/DH ARPAnet IMP interface PLI NO # LH/DH is connected to a PLI NIMP 0 # ARPAnet IMP 1822 interface # The following are untested in 2.11BSD; some are untested since before 2.9BSD # Some won't even compile. Most will require modification. Good luck. ENABLE34 NO # if have the ENABLE34 board NCSS 0 # DEC/CSS IMP11-A ARPAnet IMP interface NDMC 0 # DMC11 NEN 0 # Xerox prototype (3 Mb) Ethernet NHY 0 # Hyperchannel NS 0 # Xerox NS (XNS) NSRI 0 # SRI DR11c ARPAnet IMP NTB 0 # RS232 interface for Genisco/Hitachi tablets # Defining FPSIM to YES compiles a floating point simulator into the kernel # which will catch floating point instruction traps from user space. This # doesn't work at present. FPSIM NO # floating point simulator # To enable profiling, the :splfix script must be changed to use spl6 instead # of spl7 (see conf/:splfix.profile), also, you have to have a machine with a # supervisor PAR/PDR pair, i.e. an 11/44/45/50/53/55/70/73/83/84, as well # as both a KW11-L and a KW11-P. # # Note that profiling is not currently working. We don't have any plans on # fixing it, so this is essentially a non-supported feature. PROFILE NO # system profiling with KW11P clock INGRES NO # include the Ingres lock driver us debugging. INET YES # TCP/IP CHECKSTACK NO # Kernel & Supervisor stack pointer checking NETHER 1 # ether pseudo-device # Note, PTY's and the select(2) system call do not require the kernel to # be configured for networking (INET). Note that you can allocate PTY's # in any number (multiples of 8, of 16, even, odd, prime, whatever). Nothing sys/sys/ 755 0 12 0 6046604203 5377 sys/sys/kern_proc.c 440 0 12 4120 5350253760 7606 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)kern_proc.c 2.0 (2.11BSD GTE) 3/12/93 */ #include "param.h" #include "user.h" #include "proc.h" #include "systm.h" #define bit(a) (1L<<(a-1)) /* * This version is not the 4.XBSD spgrp() for a couple of very good reasons. * The 4.2 one didn't work and the 4.3 one requires the child pointers in * the proc structure. This one is pretty simple and loses *big* for several * levels of processes since it recursively handles children of children. * We don't bother to return the number of processes found as 4.X does since * no one ever uses it. Note, if you have enough processes and unlimited * processes per user, someone can crash your system by running you out of * kernel stack space. An alternative method would be to run inferior * against every process in the proc structure. This method is probably * faster for most systems. */ spgrp(top) register struct proc *top; { register struct proc *p; top->p_sig &= ~(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU)); top->p_flag |= SDETACH; for (p = allproc; p; p = p->p_nxt) if (p->p_pptr == top) spgrp(p); for (p = zombproc; p; p = p->p_nxt) if (p->p_pptr == top) spgrp(p); } /* * Is p an inferior of the current process? */ inferior(p) register struct proc *p; { for (; p != u.u_procp; p = p->p_pptr) if (p->p_ppid == 0) return (0); return (1); } struct proc * pfind(pid) register int pid; { register struct proc *p = pidhash[PIDHASH(pid)]; for (; p; p = p->p_hash) if (p->p_pid == pid) return (p); return ((struct proc *)0); } /* * init the process queues */ pqinit() { register struct proc *p; /* * most procs are initially on freequeue * nb: we place them there in their "natural" order. */ freeproc = NULL; for (p = procNPROC; --p > proc; freeproc = p) p->p_nxt = freeproc; /* * but proc[0] is special ... */ allproc = p; p->p_nxt = NULL; p->p_prev = &allproc; zombproc = NULL; } tomatic # dumps will be taken, and DUMPROUTINE needs to be set to "nulldev" to # resolve the reference. See param.h and ioconf.c for more information. # DUMPLO should leave room for the kernel to start swapping without # overwriting the dump. DUMPLO 1024 # dump start address DUMPDEV makedev(5,1) # makedev(10,1) xp0b #DUMPROUTINE nulldev # no dump routine. #DUMPROUTINE hkdump # hk driver dump routine #DUMPROUTINE hpdumpsys/sys/uipc_proto.c 440 0 12 2571 4236460010 10005 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)uipc_proto.c 7.2 (Berkeley) 12/30/87 */ #include "param.h" #include "socket.h" #include "protosw.h" #include "domain.h" #include "mbuf.h" /* * Definitions of protocols supported in the UNIX domain. */ int uipc_usrreq(); int raw_init(),raw_usrreq(),raw_input(),raw_ctlinput(); extern struct domain unixdomain; /* or at least forward */ struct protosw unixsw[] = { { SOCK_STREAM, &unixdomain, 0, PR_CONNREQUIRED|PR_WANTRCVD|PR_RIGHTS, 0, 0, 0, 0, uipc_usrreq, 0, 0, 0, 0, }, { SOCK_DGRAM, &unixdomain, 0, PR_ATOMIC|PR_ADDR|PR_RIGHTS, 0, 0, 0, 0, uipc_usrreq, 0, 0, 0, 0, }, { 0, 0, 0, 0, raw_input, 0, raw_ctlinput, 0, raw_usrreq, raw_init, 0, 0, 0, } }; int unp_externalize(), unp_dispose(); struct domain unixdomain = { AF_UNIX, "unix", 0, unp_externalize, unp_dispose, unixsw, &unixsw[sizeof(unixsw)/sizeof(unixsw[0])] }; 5,1) # makedev(10,1) xp0b #DUMPROUTINE nulldev # no dump routine. #DUMPROUTINE hkdump # hk driver dump routine #DUMPROUTINE hpdumpsys/sys/tags 640 0 12 272616 5752063265 6431 ACCUNIT ../pdpif/if_acc.c /^#define ACCUNIT(x) minor(x)$/ ADDDOMAIN ../sys/uipc_domain.c /^#define ADDDOMAIN(x) { \\$/ ALLOC ../sys/vm_text.c /^#define ALLOC(xp) { \\$/ ARPTAB_HASH ../netinet/if_ether.c /^#define ARPTAB_HASH(a) \\$/ ARPTAB_LOOK ../netinet/if_ether.c /^#define ARPTAB_LOOK(at,addr) { \\$/ ASENTRY ../machine/DEFS.h /^#define ASENTRY(x) .globl x; x:;$/ ASOQREMQUE ../machine/net_mac.h /^#define ASOQREMQUE(so, n) \\$/ BASEPRI ../machine/machparam.h /^#define BASEPRI(ps) (((ps) & PSL_IPL) == 0)$/ BUFHASH ../h/buf.h /^#define BUFHASH(dev,blkno) ((struct buf *)&bufhash/ B_TO_Q ../machine/net_mac.h /^#define B_TO_Q(cp, cc, q) \\$/ CBAD ../machine/scb.s /^ASENTRY(CBAD)$/ CDWAIT ../pdpuba/dhv.c /^#define CDWAIT(x) (!(minor(x) & 0200))$/ CGOOD ../machine/scb.s /^ASENTRY(CGOOD)$/ CHAR ../machine/DEFS.h /^#define CHAR(s, x, v) .data; DEC_\/**\/s(x); x:; .by/ CLBYTES/sizeo ../sys/uipc_mbuf.c /^struct mbuf xmbutl[(NMBCLUSTERS*CLBYTES\/sizeof (st/ CONNWHILE ../machine/net_mac.h /^#define CONNWHILE(so) \\$/ CONST ../machine/DEFS.h /^#define CONST(s, x, v) DEC_\/**\/s(x); x=v;$/ CSSUNIT ../pdpif/if_css.c /^#define CSSUNIT(x) minor(x)$/ CTRL ../h/ttychars.h /^#define CTRL(c) ('c'&037)$/ Copy ../machine/seg.h /^* raising processor priority by calling these macr/ DBM /usr/include/ndbm.h 33 DEC_GLOBAL ../machine/DEFS.h /^#define DEC_GLOBAL(x) .globl x;$/ DEC_LOCAL ../machine/DEFS.h /^#define DEC_LOCAL(x)$/ DELAY ../machine/machparam.h /^#define DELAY(n) { long N = ((long)(n))<<1; while / DHU_RX_LINE ../pdpuba/dhureg.h /^#define DHU_RX_LINE(rbuf) (((rbuf) & DHU_RB_RLN) >/ DHU_SELECT ../pdpuba/dhureg.h /^#define DHU_SELECT(unit) ((unit) & DHU_CS_IAP)$/ DHU_TX_LINE ../pdpuba/dhureg.h /^#define DHU_TX_LINE(csrh) ((csrh) & DHU_CSH_TLN)$/ DHV_RX_LINE ../pdpuba/dhvreg.h /^#define DHV_RX_LINE(rbuf) (((rbuf) & DHV_RB_RLN) >/ DHV_SELECT ../pdpuba/dhvreg.h /^#define DHV_SELECT(unit) ((unit) & DHV_CS_IAP)$/ DHV_TX_LINE ../pdpuba/dhvreg.h /^#define DHV_TX_LINE(csrh) ((csrh) & DHV_CSH_TLN)$/ DIRSIZ ../h/dir.h /^#define DIRSIZ(dp) \\$/ DQHASH ../sys/quota_kern.c /^#define DQHASH(uid, dev) \\$/ DQptr ../sys/quota_kern.c 85 DV_INIT ../pdpuba/xp.c /^#define DV_INIT(c,u) \\$/ ENTRY ../machine/DEFS.h /^#define ENTRY(x) .globl _\/**\/x; _\/**\/x:;$/ ENUNIT ../pdpif/if_en.c /^#define ENUNIT(x) minor(x)$/ FBLKP ../sys/ufs_alloc.c 22 FD_CLR ../h/types.h /^#define FD_CLR(n, p) ((p)->fds_bits[(n)\/NFDBITS] &/ FD_ISSET ../h/types.h /^#define FD_ISSET(n, p) ((p)->fds_bits[(n)\/NFDBITS]/ FD_SET ../h/types.h /^#define FD_SET(n, p) ((p)->fds_bits[(n)\/NFDBITS] |/ FD_ZERO ../h/types.h /^#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))/ FFLAGS /usr/include/fcntl.h /^#define FFLAGS(oflags) ((oflags) + 1)$/ FPFETCH ../machine/net_mac.h /^#define FPFETCH(fp, fpp) \\$/ FPFLAGS ../machine/net_mac.h /^#define FPFLAGS(fp, set, clear) \\$/ FREE /usr/include/mp.h /^#define FREE(x) {if(x.len!=0) {free((char *)x.val)/ FREE_AT_HEAD ../sys/vm_text.c /^#define FREE_AT_HEAD(xp) { \\$/ FREE_AT_TAIL ../sys/vm_text.c /^#define FREE_AT_TAIL(xp) { \\$/ GETF ../h/file.h /^#define GETF(fp, fd) { \\$/ GSIGNAL ../machine/net_mac.h /^#define GSIGNAL(pgrp, sig) \\$/ HASH ../sys/kern_synch.c /^#define HASH(x) (((int)x >> 5) & (SQSIZE - 1))$/ HOSTHASH ../netimp/if_imphost.h /^#define HOSTHASH(a) ((((a).s_addr>>8)+(a).s_net) %/ HOST_DEQUE ../netimp/if_imphost.h /^#define HOST_DEQUE(hp, m) { \\$/ HOST_ENQUE ../netimp/if_imphost.h /^#define HOST_ENQUE(hp, m) { \\$/ HWFLOW ../pdpuba/dhv.c /^#define HWFLOW(x) (minor(x) & 0100)$/ IA_SIN ../netinet/in_var.h /^#define IA_SIN(ia) ((struct sockaddr_in *)(&((stru/ IA_SNS ../netns/ns_if.h /^#define IA_SNS(ia) ((struct sockaddr_ns *)(&((stru/ ICMP_ADVLEN ../netinet/ip_icmp.h /^#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl <ifq_drops++)$/ IF_ENQUEUE ../net/if.h /^#define IF_ENQUEUE(ifq, m) { \\$/ IF_PREPEND ../net/if.h /^#define IF_PREPEND(ifq, m) { \\$/ IF_QFULL ../net/if.h /^#define IF_QFULL(ifq) ((ifq)->ifq_len >= (ifq)->i/ ILOCK ../h/inode.h /^#define ILOCK(ip) { \\$/ ILUNIT ../pdpif/if_il.c /^#define ILUNIT(x) minor(x)$/ INOHASH ../sys/ufs_inode.c /^#define INOHASH(dev,ino) (((dev)+(ino))&(INOHSZ-1)/ INT ../machine/DEFS.h /^#define INT(s, x, v) .data; .even; DEC_\/**\/s(x); x/ IN_BADCLASS ../netinet/in.h /^#define IN_BADCLASS(i) (((long)(i) & 0xf0000000L)/ IN_CLASSA ../netinet/in.h /^#define IN_CLASSA(i) (((long)(i) & 0x80000000L) =/ IN_CLASSB ../netinet/in.h /^#define IN_CLASSB(i) (((long)(i) & 0xc0000000L) =/ IN_CLASSC ../netinet/in.h /^#define IN_CLASSC(i) (((long)(i) & 0xe0000000L) =/ IN_CLASSD ../netinet/in.h /^#define IN_CLASSD(i) (((long)(i) & 0xf0000000L) =/ IN_EXPERIMENTAL ../netinet/in.h /^#define IN_EXPERIMENTAL(i) (((long)(i) & 0xe000000/ IN_MULTICAST ../netinet/in.h /^#define IN_MULTICAST(i) IN_CLASSD(i)$/ IPOPT_CLASS ../netinet/ip.h /^#define IPOPT_CLASS(o) ((o)&0x60)$/ IPOPT_COPIED ../netinet/ip.h /^#define IPOPT_COPIED(o) ((o)&0x80)$/ IPOPT_NUMBER ../netinet/ip.h /^#define IPOPT_NUMBER(o) ((o)&0x1f)$/ IPUT ../machine/net_mac.h /^#define IPUT(ip) \\$/ ISSIG ../h/param.h /^#define ISSIG(p) \\$/ ISSUPERADD ../machine/machparam.h /^#define ISSUPERADD(add) ((int)(add)&01)$/ ITIMES ../h/inode.h /^#define ITIMES(ip, t1, t2) { \\$/ IUNLOCK ../h/inode.h /^#define IUNLOCK(ip) { \\$/ IUPDAT ../h/inode.h /^#define IUPDAT(ip, t1, t2, waitfor) { \\$/ KERNELADD ../machine/machparam.h /^#define KERNELADD(add) ((int)(add)&~01)$/ KScall ../machine/mch_KScall.s /^ENTRY(KScall)$/ Kretu ../machine/mch_KScall.s /^ASENTRY(Kretu)$/ LOG_FAC ../h/syslog.h /^#define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3)$/ LOG_FAC /usr/include/syslog.h /^#define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3)$/ LOG_MAKEPRI ../h/syslog.h /^#define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri/ LOG_MAKEPRI /usr/include/syslog.h /^#define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri/ LOG_MASK ../h/syslog.h /^#define LOG_MASK(pri) (1 << (pri)) \/* mask for on/ LOG_MASK /usr/include/syslog.h /^#define LOG_MASK(pri) (1 << (pri)) \/* mask for on/ LOG_PRI ../h/syslog.h /^#define LOG_PRI(p) ((p) & LOG_PRIMASK)$/ LOG_PRI /usr/include/syslog.h /^#define LOG_PRI(p) ((p) & LOG_PRIMASK)$/ LOG_UPTO ../h/syslog.h /^#define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1) \/* al/ LOG_UPTO /usr/include/syslog.h /^#define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1) \/* al/ LPUNIT ../pdpuba/lp.c /^#define LPUNIT(dev) (minor(dev) >> 3)$/ M15 ../pdpuba/ra.c /^#define M15(a,b,c) ((((((a - '@') & 0x1f) << 10) |/ MALLOC ../machine/net_mac.h /^#define MALLOC(map, size) \\$/ MAX ../h/param.h /^#define MAX(a,b) (((a)>(b))?(a):(b))$/ MBZAP ../sys/uipc_syscalls.c /^MBZAP(m, len, type)$/ MCLALLOC ../h/mbuf.h /^#define MCLALLOC(m, i) \\$/ MCLFREE ../h/mbuf.h /^#define MCLFREE(m) { \\$/ MCLGET ../h/mbuf.h /^#define MCLGET(m) \\$/ MFREE ../h/mbuf.h /^#define MFREE(m, n) \\$/ MGET ../h/mbuf.h /^#define MGET(m, i, t) \\$/ MIN ../h/param.h /^#define MIN(a,b) (((a)<(b))?(a):(b))$/ MTOCL ../h/mbuf.h /^#define MTOCL(m) ((struct mbuf *)(mtod((m), int) &/ M_FREE ../machine/net_mac.h /^#define M_FREE(m) \\$/ M_FREEM ../machine/net_mac.h /^#define M_FREEM(m) \\$/ M_HASCL ../h/mbuf.h /^#define M_HASCL(m) ((m)->m_off >= MSIZE)$/ Mgenassym ../machine/genassym.c /^main()$/ Minit_main ../sys/init_main.c /^main()$/ NCYL ../pdpuba/xp.c /^#define NCYL(x) (x)$/ NETCOPYOUT ../machine/net_mac.h /^#define NETCOPYOUT(from, to, len) \\$/ NETCRASH ../machine/net_mac.h /^#define NETCRASH() \\$/ NETPFIND ../machine/net_mac.h /^#define NETPFIND(pid) \\$/ NETPSIGNAL ../machine/net_mac.h /^#define NETPSIGNAL(p, sig) \\$/ NETSTART ../machine/net_mac.h /^#define NETSTART() \\$/ NHASH ../sys/ufs_namei.c /^#define NHASH(h, i, d) ((unsigned)((h) + (i) + 13 / N_BADMAG /usr/include/a.out.h /^#define N_BADMAG(x) \\$/ N_DATOFF /usr/include/a.out.h /^#define N_DATOFF(e) (n_datoff(&e))$/ N_DRELOC /usr/include/a.out.h /^#define N_DRELOC(e) (n_dreloc(&e))$/ N_STROFF /usr/include/a.out.h /^#define N_STROFF(e) (n_stroff(&e))$/ N_SYMOFF /usr/include/a.out.h /^#define N_SYMOFF(e) (n_symoff(&e))$/ N_TRELOC /usr/include/a.out.h /^#define N_TRELOC(e) (n_treloc(&e))$/ N_TXTOFF /usr/include/a.out.h /^#define N_TXTOFF(x) \\$/ OFLAGS /usr/include/fcntl.h /^#define OFLAGS(fflags) ((fflags) - 1)$/ PCCM_ADDTYPE /usr/include/pcc.h /^# define PCCM_ADDTYPE(t, m) \\$/ PCCM_TEXT /usr/include/pcc.h /^# define PCCM_TEXT(s) \\$/ PCCM_TRIPLE /usr/include/pcc.h /^# define PCCM_TRIPLE(op, var, type) \\$/ PIDHASH ../h/proc.h /^#define PIDHASH(pid) ((pid) & (PIDHSZ - 1))$/ PRC_IS_REDIRECT ../h/protosw.h /^#define PRC_IS_REDIRECT(cmd) \\$/ PRINTB ../pdpuba/ra.c /^#define PRINTB(x) printf x $/ PRINTD ../pdpuba/ra.c /^#define PRINTD(x) printf x $/ PUTC ../machine/net_mac.h /^#define PUTC(c, p) \\$/ P_ASENTRY ../machine/DEFS.h /^#define P_ASENTRY(x) .globl x; x:; PROFCODE;$/ P_ENTRY ../machine/DEFS.h /^#define P_ENTRY(x) .globl _\/**\/x; _\/**\/x:; PROFCOD/ QEUNIT ../pdpif/if_qe.c /^#define QEUNIT(x) minor(x)$/ QHASH ../sys/quota_kern.c /^#define QHASH(uid) ((unsigned)(uid) & (NQHASH-1))$/ QUOTAMAP ../h/quota.h /^#define QUOTAMAP() mapseg5(quotreg, quotdesc)$/ QUOTAUNMAP ../h/quota.h /^#define QUOTAUNMAP() normalseg5()$/ Qptr ../sys/quota_kern.c 59 RACON ../pdpuba/ra.c /^#define RACON(x) ((minor(x) >> 6) & 03)$/ RAUNIT ../pdpuba/ra.c /^#define RAUNIT(x) ((minor(x) >> 3) & 07)$/ RM02_INIT ../pdpuba/xp.c /^#define RM02_INIT(c,u) \\$/ RM03_INIT ../pdpuba/xp.c /^#define RM03_INIT(c,u) \\$/ RM05X_INIT ../pdpuba/xp.c /^#define RM05X_INIT(c,u) \\$/ RM05_INIT ../pdpuba/xp.c /^#define RM05_INIT(c,u) \\$/ RM2X_INIT ../pdpuba/xp.c /^#define RM2X_INIT(c,u) \\$/ ROUNDDOWN ../h/gprof.h /^#define ROUNDDOWN(x,y) (((x)\/(y))*(y))$/ ROUNDUP ../h/gprof.h /^#define ROUNDUP(x,y) ((((x)+(y)-1)\/(y))*(y))$/ RP04_INIT ../pdpuba/xp.c /^#define RP04_INIT(c,u) \\$/ RP05_INIT ../pdpuba/xp.c /^#define RP05_INIT(c,u) \\$/ RP06_INIT ../pdpuba/xp.c /^#define RP06_INIT(c,u) \\$/ RTFREE ../net/route.h /^#define RTFREE(rt) \\$/ RTHASHMOD ../net/route.h /^#define RTHASHMOD(h) ((h) & (RTHASHSIZ - 1))$/ SELWAKEUP ../machine/net_mac.h /^#define SELWAKEUP(p, coll) \\$/ SEQ_GEQ ../netinet/tcp_seq.h /^#define SEQ_GEQ(a,b) ((long)((a)-(b)) >= 0)$/ SEQ_GT ../netinet/tcp_seq.h /^#define SEQ_GT(a,b) ((long)((a)-(b)) > 0)$/ SEQ_LEQ ../netinet/tcp_seq.h /^#define SEQ_LEQ(a,b) ((long)((a)-(b)) <= 0)$/ SEQ_LT ../netinet/tcp_seq.h /^#define SEQ_LT(a,b) ((long)((a)-(b)) < 0)$/ SGTTY /usr/include/curses.h 34 SI ../netns/spidp.h /^#define SI(x) ((struct spidp *)x)$/ SI_INIT ../pdpuba/xp.c /^#define SI_INIT(c,u) \\$/ SKcall ../machine/net_SKcall.s /^ENTRY(SKcall)$/ SLCLOSE ../sys/tty_conf.c /^SLCLOSE(tp, flag)$/ SLEEP ../machine/net_mac.h /^#define SLEEP(chan, pri) \\$/ SLINPUT ../sys/tty_conf.c /^SLINPUT(c, tp)$/ SLOPEN ../sys/tty_conf.c /^SLOPEN(dev, tp)$/ SLSTART ../sys/tty_conf.c /^SLSTART(tp)$/ SLTIOCTL ../sys/tty_conf.c /^SLTIOCTL(tp, cmd, data, flag)$/ SOACC1 ../machine/net_mac.h /^#define SOACC1(so) \\$/ SOACCEPT ../machine/net_mac.h /^#define SOACCEPT(so, nam) \\$/ SOBIND ../machine/net_mac.h /^#define SOBIND(so, nam) \\$/ SOCLOSE ../machine/net_mac.h /^#define SOCLOSE(so) \\$/ SOCON1 ../machine/net_mac.h /^#define SOCON1(so, nam) \\$/ SOCON2 ../machine/net_mac.h /^#define SOCON2(so1, so2) \\$/ SOCREATE ../machine/net_mac.h /^#define SOCREATE(dom, aso, type, proto) \\$/ SOGETNAM ../machine/net_mac.h /^#define SOGETNAM(so, m) \\$/ SOGETOPT ../machine/net_mac.h /^#define SOGETOPT(so, level, optname, mp) \\$/ SOGETPEER ../machine/net_mac.h /^#define SOGETPEER(so, m) \\$/ SOLISTEN ../machine/net_mac.h /^#define SOLISTEN(so, backlog) \\$/ SOO_IOCTL ../machine/net_mac.h /^#define SOO_IOCTL(fp, cmd, data) \\$/ SOO_SELECT ../machine/net_mac.h /^#define SOO_SELECT(fp, which) \\$/ SOO_STAT ../machine/net_mac.h /^#define SOO_STAT(so, ub) \\$/ SORECEIVE ../machine/net_mac.h /^#define SORECEIVE(so, aname, uiop, flags, rightsp)/ SOSEND ../machine/net_mac.h /^#define SOSEND(so, nam, uiop, flags, rights) \\$/ SOSETOPT ../machine/net_mac.h /^#define SOSETOPT(so, level, optname, m0) \\$/ SOSHUTDOWN ../machine/net_mac.h /^#define SOSHUTDOWN(so, how) \\$/ SPACE ../machine/DEFS.h /^#define SPACE(s, x, n) .bss; .even; DEC_\/**\/s(x);/ SPPT_RANGESET ../netns/spp_timer.h /^#define SPPT_RANGESET(tv, value, tvmin, tvmax) { \\/ SRIUNIT ../pdpif/if_sri.c /^#define SRIUNIT(x) minor(x)$/ SSEQ_GEQ ../netns/spp_var.h /^#define SSEQ_GEQ(a,b) ((xnsCbug = (short)((a)-(b))/ SSEQ_GT ../netns/spp_var.h /^#define SSEQ_GT(a,b) ((xnsCbug = (short)((a)-(b)))/ SSEQ_LEQ ../netns/spp_var.h /^#define SSEQ_LEQ(a,b) ((xnsCbug = (short)((a)-(b))/ SSEQ_LT ../netns/spp_var.h /^#define SSEQ_LT(a,b) ((xnsCbug = (short)((a)-(b)))/ STRING ../machine/DEFS.h /^#define STRING(s, x, v) .data; DEC_\/**\/s(x); x:; v/ SUPERADD ../machine/machparam.h /^#define SUPERADD(add) ((int)(add)|01)$/ SUPVMODE ../machine/machparam.h /^#define SUPVMODE(ps) (((ps) & PSL_CURMOD) == PSL_C/ Sretu ../machine/net_SKcall.s /^ASENTRY(Sretu)$/ TCPS_HAVERCVDFIN ../netinet/tcp_fsm.h /^#define TCPS_HAVERCVDFIN(s) ((s) >= TCPS_TIME_WAIT/ TCPS_HAVERCVDSYN ../netinet/tcp_fsm.h /^#define TCPS_HAVERCVDSYN(s) ((s) >= TCPS_SYN_RECEI/ TCPT_RANGESET ../netinet/tcp_timer.h /^#define TCPT_RANGESET(tv, value, tvmin, tvmax) { \\/ TCP_REASS ../netinet/tcp_input.c /^#define TCP_REASS(tp, ti, m, so, flags) { \\$/ TEDENS ../pdpuba/tm.c /^#define TEDENS(dev) ((minor(dev) & 030) >> 3)$/ TEUNIT ../pdpuba/tm.c /^#define TEUNIT(dev) (minor(dev) & 03)$/ TIMEOUT ../machine/net_mac.h /^#define TIMEOUT(fun, arg, t) \\$/ TMSCTLR ../pdpuba/tmscp.c /^#define TMSCTLR(dev) ((minor(dev) >> 6) & 3)$/ TMSDENS ../pdpuba/tmscp.c /^#define TMSDENS(dev) ((minor(dev) >> 3) & 3)$/ TMSUNIT ../pdpuba/tmscp.c /^#define TMSUNIT(dev) (minor(dev)&03)$/ TSCTLR ../pdpuba/ts.c /^#define TSCTLR(dev) ((minor(dev) >> 6) & 3)$/ TSUNIT ../pdpuba/ts.c /^#define TSUNIT(dev) (minor(dev)&03) \/* not used */ TTHIWAT ../h/tty.h /^#define TTHIWAT(tp) tthiwat[(tp)->t_ospeed&TTMASK]/ TTLOWAT ../h/tty.h /^#define TTLOWAT(tp) ttlowat[(tp)->t_ospeed&TTMASK]/ TTSTART ../machine/net_mac.h /^#define TTSTART(tp) \\$/ TTYFLUSH ../machine/net_mac.h /^#define TTYFLUSH(tp, rw) \\$/ TTYWFLUSH ../machine/net_mac.h /^#define TTYWFLUSH(tp) \\$/ TUUNIT ../pdpuba/ht.c /^#define TUUNIT(dev) (minor(dev) & 03)$/ Trl ../pdpuba/ra.c 226 UCHAR ../netinet/in_systm.h /^#define UCHAR(a) ((u_int)((a)&0xff))$/ UIOCCMD ../h/ioctl.h /^#define UIOCCMD(n) _IO(u, n) \/* usr cntl op "n" / UNIT ../pdpuba/dh.c /^#define UNIT(x) (minor(x) & 0177)$/ UNPBIND ../machine/net_mac.h /^#define UNPBIND(path, len, ipp, unpsock) \\$/ UNPCONN ../machine/net_mac.h /^#define UNPCONN(path, len, so2, ipp) \\$/ UNPDET ../machine/net_mac.h /^#define UNPDET(ip) \\$/ UNPUTC ../machine/net_mac.h /^#define UNPUTC(p) \\$/ USERMODE ../machine/machparam.h /^#define USERMODE(ps) (((ps) & PSL_USERSET) == PSL_/ VADDR /usr/include/vmf.h 61 VATTR_NULL ../h/inode.h /^#define VATTR_NULL(vp) (vattr_null(vp))$/ VMMODIFY /usr/include/vmf.h /^#define VMMODIFY(seg) (seg->s_flags |= S_DIRTY)$/ VOFF /usr/include/vmf.h /^#define VOFF(va) ((u_short)va % BYTESPERSEG)$/ VOID /usr/include/curses.h /^# define VOID(x) (__void__ = (int) (x))$/ VSEG /usr/include/vmf.h /^#define VSEG(va) ((short)(va >> LOG2BPS))$/ VVUNIT ../pdpif/if_vv.c /^#define VVUNIT(x) minor(x)$/ WAKEUP ../machine/net_mac.h /^#define WAKEUP(chan) \\$/ WIFEXITED ../h/wait.h /^#define WIFEXITED(x) ((x).w_stopval != WSTOPPED &&/ WIFSIGNALED ../h/wait.h /^#define WIFSIGNALED(x) ((x).w_stopval != WSTOPPED / WIFSTOPPED ../h/wait.h /^#define WIFSTOPPED(x) ((x).w_stopval == WSTOPPED)$/ W_EXITCODE ../h/wait.h /^#define W_EXITCODE(ret,sig) ((ret << 8) | (sig))$/ W_STOPCODE ../h/wait.h /^#define W_STOPCODE(sig) ((sig << 8) | WSTOPPED)$/ XUNLOCK ../sys/vm_text.c /^#define XUNLOCK(xp) { \\$/ X_LOCK ../sys/vm_text.c /^#define X_LOCK(xp) { \\$/ _IO ../h/ioctl.h /^#define _IO(x,y) (('x'<<8)|y)$/ _IOR ../h/ioctl.h /^#define _IOR(x,y,t) (('x'<<8)|y)$/ _IOW ../h/ioctl.h /^#define _IOW(x,y,t) (('x'<<8)|y)$/ _IOWR ../h/ioctl.h /^#define _IOWR(x,y,t) (('x'<<8)|y)$/ __sysctl ../sys/kern_sysctl.c /^__sysctl()$/ _assert /usr/include/assert.h /^# define _assert(ex) {if (!(ex)){fprintf(stderr,"A/ _ioget ../machine/machdep2.c /^_ioget(size)$/ _iomap ../machine/machdep2.c /^_iomap(addr)$/ _pchar ../sys/sys_net.c /^_pchar(c, flg)$/ _puts /usr/include/curses.h /^# define _puts(s) tputs(s, 0, _putchar)$/ accattach ../pdpif/if_acc.c /^accattach(ui)$/ accept ../sys/uipc_syscalls.c /^accept()$/ access ../sys/ufs_fio.c /^access(ip, mode)$/ accinit ../pdpif/if_acc.c /^accinit(unit)$/ accinputreset ../pdpif/if_acc.c /^accinputreset(addr, unit)$/ accprobe ../pdpif/if_acc.c /^accprobe(reg)$/ accreset ../pdpif/if_acc.c /^accreset(unit, uban)$/ accrint ../pdpif/if_acc.c /^accrint(unit)$/ accstart ../pdpif/if_acc.c /^accstart(dev)$/ acct ../sys/kern_acct.c /^acct()$/ acctwatch ../sys/kern_acct.c /^acctwatch(resettime)$/ accxint ../pdpif/if_acc.c /^accxint(unit)$/ addch /usr/include/curses.h /^# define addch(ch) VOID(waddch(stdscr, ch))$/ addstr /usr/include/curses.h /^# define addstr(str) VOID(waddstr(stdscr, str))$/ addupc ../machine/mch_xxx.s /^ENTRY(addupc)$/ adjtime ../sys/kern_time.c /^adjtime()$/ alloc ../sys/ufs_alloc.c /^alloc(ip, clrflg)$/ arpinput ../netinet/if_ether.c /^arpinput(ac, m)$/ arpioctl ../netinet/if_ether.c /^arpioctl(cmd, data)$/ arpresolve ../netinet/if_ether.c /^arpresolve(ac, m, destip, desten, usetrailers)$/ arptfree ../netinet/if_ether.c /^arptfree(at)$/ arptimer ../netinet/if_ether.c /^arptimer()$/ arptnew ../netinet/if_ether.c /^arptnew(addr)$/ arpwhohas ../netinet/if_ether.c /^arpwhohas(ac, addr)$/ asoqremque ../sys/uipc_socket.c /^asoqremque(so, n)$/ assert /usr/include/assert.h /^# define assert(ex) _assert(ex)$/ ave ../h/vmmac.h /^#define ave(smooth, cnt, time) \\$/ b_to_q ../sys/tty_subr.c /^b_to_q(cp, cc, q)$/ backup ../machine/mch_backup.s /^ENTRY(backup)$/ backup ../machine/mch_backup.s /^ENTRY(backup)$/ badaddr ../machine/net_xxx.s /^ENTRY(badaddr)$/ badblock ../sys/ufs_subr.c /^badblock(fp, bn)$/ baudrate /usr/include/curses.h /^#define baudrate() (_tty.sg_ospeed)$/ bawrite ../h/buf.h /^#define bawrite(bp) {(bp)->b_flags |= B_ASYNC; bwr/ bcmp ../machine/libc_bcmp.s /^ENTRY(bcmp)$/ bcopy ../machine/libc_bcopy.s /^ENTRY(bcopy)$/ bcopy ../sys/ufs_inode.c /^ bcopy(dp->di_addr, ip->i_addr, NADDR * sizeof (da/ bdwrite ../sys/ufs_bio.c /^bdwrite(bp)$/ bflush ../sys/ufs_bio.c /^bflush(dev)$/ bfree ../h/buf.h /^#define bfree(bp) (bp)->b_bcount = 0$/ bftopaddr ../h/buf.h /^#define bftopaddr(bp) ((u_int)(bp)->b_un.b_addr >>/ bhinit ../sys/init_main.c /^bhinit()$/ bind ../sys/uipc_syscalls.c /^bind()$/ binit ../sys/init_main.c /^binit()$/ binshash ../h/buf.h /^#define binshash(bp, dp) { \\$/ binsheadfree ../h/buf.h /^#define binsheadfree(bp, dp) { \\$/ binstailfree ../h/buf.h /^#define binstailfree(bp, dp) { \\$/ binval ../sys/ufs_bio.c /^binval(dev)$/ biodone ../sys/ufs_bio.c /^biodone(bp)$/ biowait ../sys/ufs_bio.c /^biowait(bp)$/ bit ../sys/kern_proc.c /^#define bit(a) (1L<<(a-1))$/ blkatoff ../sys/ufs_namei.c /^blkatoff(ip, offset, res)$/ blkflush ../sys/ufs_bio.c /^blkflush(dev, blkno)$/ blkoff ../h/fs.h /^#define blkoff(loc) \/* calculates (loc % fs->fs_b/ bmap ../sys/ufs_bmap.c /^bmap(ip, bn, rwflg, clrflg)$/ bool_t ../h/types.h 77 boot ../machine/machdep2.c /^boot(dev, howto)$/ brattach ../pdpuba/br.c /^brattach(braddr, unit)$/ brdone ../pdpuba/br.c /^brdone (bp)$/ brdump ../pdpuba/br.c /^brdump(dev)$/ bread ../sys/ufs_bio.c /^bread(dev, blkno)$/ breada ../sys/ufs_bio.c /^breada(dev, blkno, rablkno)$/ brelse ../sys/ufs_bio.c /^brelse(bp)$/ bremfree ../h/buf.h /^#define bremfree(bp) { \\$/ bremhash ../h/buf.h /^#define bremhash(bp) { \\$/ brinit ../pdpuba/br.c /^brinit(drive) $/ brintr ../pdpuba/br.c /^brintr(dev)$/ bropen ../pdpuba/br.c /^bropen(dev, flag)$/ brroot ../pdpuba/br.c /^brroot()$/ brsize ../pdpuba/br.c /^brsize(dev)$/ brstart ../pdpuba/br.c /^brstart()$/ brstrategy ../pdpuba/br.c /^brstrategy(bp)$/ brunit ../pdpuba/br.c /^#define brunit(dev) ((dev >> 3) & 7)$/ btoc ../machine/machparam.h /^#define btoc(x) ((((unsigned)(x)+63)>>6))$/ btodb ../machine/machparam.h /^#define btodb(bytes) \/* calculates (bytes \/ DEV_B/ btoub ../h/uba.h /^#define btoub(b) ((((long)(b)) + ((long)(UBPAGE - / bwrite ../sys/ufs_bio.c /^bwrite(bp)$/ bzero ../machine/libc_bzero.s /^ENTRY(bzero)$/ bzero ../sys/vm_sched.c /^ bzero(textcounted, ntext * sizeof(char));$/ cacheinval ../h/inode.h /^#define cacheinval(ip) \\$/ cacheinvalall ../sys/ufs_namei.c /^cacheinvalall()$/ caddr_t ../h/types.h 39 call ../machine/mch_trap.s /^ASENTRY(call)$/ call ../machine/net_trap.s /^ASENTRY(call)$/ catq ../sys/tty_subr.c /^catq(from, to)$/ cbreak /usr/include/curses.h /^#define cbreak() (_tty.sg_flags |= CBREAK, _rawmod/ char ../h/types.h 25 chdir ../sys/ufs_syscalls.c /^chdir()$/ chdirec ../sys/ufs_syscalls.c /^chdirec(ipp)$/ checkpath ../sys/ufs_namei.c /^checkpath(source, target)$/ chflags ../sys/ufs_syscalls.c /^chflags()$/ chflags1 ../sys/ufs_syscalls.c /^chflags1(ip, flags)$/ chkdq ../sys/quota_ufs.c /^chkdq(ip, change, force)$/ chkiq ../sys/quota_ufs.c /^chkiq(dev, ip, uid, force)$/ chmod ../sys/ufs_syscalls.c /^chmod()$/ chmod1 ../sys/ufs_syscalls.c /^chmod1(ip, mode)$/ choverlay ../sys/kern_mman.c /^choverlay(xrw)$/ chown ../sys/ufs_syscalls.c /^chown()$/ chown1 ../sys/ufs_syscalls.c /^chown1(ip, uid, gid)$/ chroot ../sys/ufs_syscalls.c /^chroot()$/ chrtoblk ../machine/conf.c /^chrtoblk(dev)$/ cinit ../sys/init_main.c /^cinit()$/ claligned ../h/param.h /^#define claligned(x) ((((int)(x))&CLOFSET)==0)$/ clear ../machine/mch_click.s /^ENTRY(clear)$/ clear /usr/include/curses.h /^# define clear() VOID(wclear(stdscr))$/ clearerr /usr/include/stdio.h /^#define clearerr(p) ((p)->_flag &= ~(_IOERR|_IOEOF/ clearok /usr/include/curses.h /^#define clearok(win,bf) (win->_clear = bf)$/ clkstart ../machine/clock.c /^clkstart()$/ close ../sys/kern_descrip.c /^close()$/ closedq ../sys/quota_kern.c /^closedq(mp)$/ closef ../sys/kern_descrip.c /^closef(fp)$/ clrbuf ../machine/mch_xxx.s /^ENTRY(clrbuf)$/ clrnd ../h/param.h /^#define clrnd(i) (((i) + (CLSIZE-1)) &~ ((long)(CL/ clrtobot /usr/include/curses.h /^# define clrtobot() VOID(wclrtobot(stdscr))$/ clrtoeol /usr/include/curses.h /^# define clrtoeol() VOID(wclrtoeol(stdscr))$/ cltom ../h/mbuf.h /^#define cltom(x) ((struct mbuf *)((int)mbutl + ((x/ cnattach ../machine/cons.c /^cnattach(addr, unit)$/ cnclose ../machine/cons.c /^cnclose(dev, flag)$/ cnioctl ../machine/cons.c /^cnioctl(dev, cmd, addr, flag)$/ cnopen ../machine/cons.c /^cnopen(dev, flag)$/ cnputc ../machine/cons.c /^cnputc(c)$/ cnread ../machine/cons.c /^cnread(dev, uio, flag)$/ cnrint ../machine/cons.c /^cnrint(dev)$/ cnstart ../machine/cons.c /^cnstart(tp)$/ cnwrite ../machine/cons.c /^cnwrite(dev, uio, flag)$/ cnxint ../machine/cons.c /^cnxint(dev)$/ comp_t ../h/acct.h 15 compress ../sys/kern_acct.c /^compress(t)$/ connect ../sys/uipc_syscalls.c /^connect()$/ connwhile ../sys/uipc_socket.c /^connwhile(so)$/ copen ../sys/ufs_syscalls.c /^copen(mode, arg, fname)$/ copy ../machine/mch_click.s /^ENTRY(copy)$/ copyiin ../machine/mch_copy.s /^ENTRY(copyiin)$/ copyin ../machine/mch_copy.s /^ENTRY(copyin)$/ copyin ../machine/net_copy.s /^ENTRY(copyin)$/ copyinstr ../machine/mch_copy.s /^ENTRY(copyinstr)$/ copyiout ../machine/mch_copy.s /^ENTRY(copyiout)$/ copyout ../machine/mch_copy.s /^ENTRY(copyout)$/ copyout ../machine/net_copy.s /^ENTRY(copyout)$/ copyoutstr ../machine/mch_copy.s /^ENTRY(copyoutstr)$/ copystr ../machine/mch_xxx.s /^ENTRY(copystr)$/ copyv ../machine/mch_click.s /^ENTRY(copyv)$/ core ../sys/kern_sig.c /^core()$/ cpaddr ../pdpuba/dh.c /^#define cpaddr(x) (clstaddr + (ubadr_t)((x) - (cha/ cpfromkern ../machine/net_copy.s /^ENTRY(cpfromkern)$/ cptokern ../machine/net_copy.s /^ENTRY(cptokern)$/ cpu2str ../sys/kern_sysctl.c /^cpu2str(buf, len)$/ cpu_sysctl ../sys/kern_sysctl.c /^cpu_sysctl(name, namelen, oldp, oldlenp, newp, new/ creat ../sys/ufs_syscalls.c /^creat()$/ crmode /usr/include/curses.h /^#define crmode() cbreak() \/* backwards compatabili/ cssattach ../pdpif/if_css.c /^cssattach(ui)$/ cssinit ../pdpif/if_css.c /^cssinit(unit)$/ cssprobe ../pdpif/if_css.c /^cssprobe(reg)$/ cssreset ../pdpif/if_css.c /^cssreset(unit, uban)$/ cssrint ../pdpif/if_css.c /^cssrint(unit)$/ cssstart ../pdpif/if_css.c /^cssstart(dev)$/ cssxint ../pdpif/if_css.c /^cssxint(unit)$/ ctob ../machine/machparam.h /^#define ctob(x) ((x)<<6)$/ ctod ../machine/machparam.h /^#define ctod(x) (((x)+7)>>3)$/ ctok ../machine/machparam.h /^#define ctok(x) (((x)>>4)&07777)$/ ctos ../machine/machparam.h /^#define ctos(x) (((x)+127)\/128)$/ daddr_t ../h/types.h 38 datum /usr/include/ndbm.h 51 dbm_clearerr /usr/include/ndbm.h /^#define dbm_clearerr(db) ((db)->dbm_flags &= ~_DBM/ dbm_dirfno /usr/include/ndbm.h /^#define dbm_dirfno(db) ((db)->dbm_dirf)$/ dbm_error /usr/include/ndbm.h /^#define dbm_error(db) ((db)->dbm_flags & _DBM_IOER/ dbm_pagfno /usr/include/ndbm.h /^#define dbm_pagfno(db) ((db)->dbm_pagf)$/ dbm_rdonly /usr/include/ndbm.h /^#define dbm_rdonly(db) ((db)->dbm_flags & _DBM_RDO/ dbtob ../machine/machparam.h /^#define dbtob(db) \/* calculates (db * DEV_BSIZE) / dbtofsb ../h/fs.h /^#define dbtofsb(b) ((daddr_t)((daddr_t)(b)>>1))$/ de_setaddr ../pdpif/if_de.c /^de_setaddr(physaddr, unit)$/ de_ubainit ../pdpif/if_de.c /^de_ubainit(ifu, uban, hlen, nmr)$/ deattach ../pdpif/if_de.c /^deattach(ui)$/ debug_sysctl ../sys/kern_sysctl.c /^debug_sysctl(name, namelen, oldp, oldlenp, newp, n/ deget ../pdpif/if_de.c /^deget(ifu, ifrw, totlen, off0, ifp)$/ deinit ../pdpif/if_de.c /^deinit(unit)$/ deintr ../pdpif/if_de.c /^deintr(unit)$/ deioctl ../pdpif/if_de.c /^deioctl(ifp, cmd, data)$/ delay ../machine/mch_xxx.s /^ENTRY(delay)$/ delay ../machine/net_xxx.s /^ENTRY(delay)$/ delch /usr/include/curses.h /^# define delch() VOID(wdelch(stdscr))$/ deleteln /usr/include/curses.h /^# define deleteln() VOID(wdeleteln(stdscr))$/ deloopback ../pdpif/if_de.c /^deloopback(ifp, ds, addr, lb_ctl )$/ delquota ../sys/quota_kern.c /^delquota(q)$/ deoutput ../pdpif/if_de.c /^deoutput(ifp, m0, dst)$/ deprobe ../pdpif/if_de.c /^deprobe(reg)$/ deput ../pdpif/if_de.c /^deput(ifu, n, m)$/ deread ../pdpif/if_de.c /^deread(ds, ifrw, len)$/ derecv ../pdpif/if_de.c /^derecv(unit)$/ destart ../pdpif/if_de.c /^destart(unit)$/ dev_t ../h/types.h 44 dewait ../pdpif/if_de.c /^dewait(ui, fn, no_port, only_dni)$/ dhattach ../pdpuba/dh.c /^dhattach(addr, unit)$/ dhclose ../pdpuba/dh.c /^dhclose(dev, flag)$/ dhioctl ../pdpuba/dh.c /^dhioctl(dev, cmd, data, flag)$/ dhopen ../pdpuba/dh.c /^dhopen(dev, flag)$/ dhparam ../pdpuba/dh.c /^dhparam(unit)$/ dhread ../pdpuba/dh.c /^dhread(dev, uio, flag)$/ dhrint ../pdpuba/dh.c /^dhrint(dh)$/ dhstart ../pdpuba/dh.c /^dhstart(tp)$/ dhstop ../pdpuba/dh.c /^dhstop(tp, flag)$/ dhtimer ../pdpuba/dh.c /^dhtimer()$/ dhuclose ../pdpuba/dhu.c /^dhuclose(dev, flag)$/ dhuioctl ../pdpuba/dhu.c /^dhuioctl(dev, cmd, data, flag)$/ dhumctl ../pdpuba/dhu.c /^dhumctl(dev, bits, how)$/ dhuopen ../pdpuba/dhu.c /^dhuopen(dev, flag)$/ dhuparam ../pdpuba/dhu.c /^dhuparam(unit)$/ dhuread ../pdpuba/dhu.c /^dhuread(dev, uio, flag)$/ dhurint ../pdpuba/dhu.c /^dhurint(dhu)$/ dhustart ../pdpuba/dhu.c /^dhustart(tp)$/ dhustop ../pdpuba/dhu.c /^dhustop(tp, flag)$/ dhutodm ../pdpuba/dhu.c /^dhutodm(bits)$/ dhuwrite ../pdpuba/dhu.c /^dhuwrite(dev, uio, flag)$/ dhuxint ../pdpuba/dhu.c /^dhuxint(dhu)$/ dhvattach ../pdpuba/dhv.c /^dhvattach(addr,unit)$/ dhvclose ../pdpuba/dhv.c /^dhvclose(dev, flag)$/ dhvioctl ../pdpuba/dhv.c /^dhvioctl(dev, cmd, data, flag)$/ dhvmctl ../pdpuba/dhv.c /^dhvmctl(dev, bits, how)$/ dhvopen ../pdpuba/dhv.c /^dhvopen(dev, flag)$/ dhvparam ../pdpuba/dhv.c /^dhvparam(unit)$/ dhvread ../pdpuba/dhv.c /^dhvread(dev, uio, flag)$/ dhvrint ../pdpuba/dhv.c /^dhvrint(dhv)$/ dhvselect ../pdpuba/dhv.c /^dhvselect ( dev, rw ) \/* filter the minor device n/ dhvstart ../pdpuba/dhv.c /^dhvstart(tp)$/ dhvstop ../pdpuba/dhv.c /^dhvstop(tp, flag)$/ dhvtodm ../pdpuba/dhv.c /^dhvtodm(bits)$/ dhvwrite ../pdpuba/dhv.c /^dhvwrite(dev, uio, flag)$/ dhvxint ../pdpuba/dhv.c /^dhvxint(dhv)$/ dhwrite ../pdpuba/dh.c /^dhwrite(dev, uio, flag)$/ dhxint ../pdpuba/dh.c /^dhxint(dh)$/ dirbad ../sys/ufs_namei.c /^dirbad(ip, offset, how)$/ dirbadentry ../sys/ufs_namei.c /^dirbadentry(ep, entryoffsetinblock)$/ dirempty ../sys/ufs_namei.c /^dirempty(ip, parentino)$/ direnter ../sys/ufs_namei.c /^direnter(ip, ndp)$/ dirfd ../h/dir.h /^#define dirfd(dirp) ((dirp)->dd_fd)$/ dirremove ../sys/ufs_namei.c /^dirremove(ndp)$/ dirrewrite ../sys/ufs_namei.c /^dirrewrite(dp, ip, ndp)$/ discquota ../sys/quota_kern.c /^discquota(uid, ip)$/ disklabelalloc ../machine/machdep2.c /^disklabelalloc()$/ disksort ../sys/ufs_dsort.c /^disksort(dp, bp)$/ dk_alloc ../sys/ufs_dsort.c /^dk_alloc(dkn, slots, name, wps)$/ dkcksum ../sys/ufs_disksubr.c /^dkcksum(lp)$/ dkminor ../h/disk.h /^#define dkminor(unit, part) (((unit) << 3) | (part/ dkoverlapchk ../sys/ufs_disksubr.c /^dkoverlapchk(openmask, dev, label, name)$/ dkpart ../h/disk.h /^#define dkpart(dev) (minor(dev) & 07)$/ dkunit ../h/disk.h /^#define dkunit(dev) (minor(dev) >> 3)$/ dmattach ../pdpuba/dh.c /^dmattach(addr, unit)$/ dmcattach ../pdpif/if_dmc.c /^dmcattach(ui)$/ dmcinit ../pdpif/if_dmc.c /^dmcinit(unit)$/ dmcload ../pdpif/if_dmc.c /^dmcload(sc, type, w0, w1)$/ dmcoutput ../pdpif/if_dmc.c /^dmcoutput(ifp, m, dst)$/ dmcprobe ../pdpif/if_dmc.c /^dmcprobe(reg)$/ dmcrint ../pdpif/if_dmc.c /^dmcrint(unit)$/ dmcstart ../pdpif/if_dmc.c /^dmcstart(dev)$/ dmctl ../pdpuba/dh.c /^dmctl(unit, bits, how)$/ dmcxint ../pdpif/if_dmc.c /^dmcxint(unit)$/ dmintr ../pdpuba/dh.c /^dmintr(dm)$/ dmopen ../pdpuba/dh.c /^dmopen(dev)$/ dmtodhu ../pdpuba/dhu.c /^dmtodhu(bits)$/ dmtodhv ../pdpuba/dhv.c /^dmtodhv(bits)$/ dmtodz ../pdpuba/dz.c /^dmtodz(bits)$/ dnattach ../pdpuba/dn.c /^dnattach(addr, unit)$/ dnclose ../pdpuba/dn.c /^dnclose(dev, flag)$/ dnint ../pdpuba/dn.c /^dnint(dn11)$/ dnopen ../pdpuba/dn.c /^dnopen(dev, flag)$/ dnwrite ../pdpuba/dn.c /^dnwrite(dev, uio, flag)$/ domaininit ../sys/uipc_domain.c /^domaininit()$/ donice ../sys/kern_resource.c /^donice(p, n)$/ dowarn ../sys/quota_sys.c /^dowarn(q, dev)$/ dqalloc ../sys/quota_kern.c /^dqalloc(uid, dev)$/ dqp ../sys/quota_subr.c /^dqp(q, dev)$/ dqrele ../sys/quota_kern.c /^dqrele(dq)$/ drabort ../pdpuba/dr.c /^drabort(drptr)$/ drattach ../pdpuba/dr.c /^drattach(addr, unit)$/ drclose ../pdpuba/dr.c /^drclose(dev, flag)$/ drintr ../pdpuba/dr.c /^drintr(unit)$/ drioctl ../pdpuba/dr.c /^drioctl(dev, cmd, data, flag)$/ dropen ../pdpuba/dr.c /^dropen(dev)$/ drstart ../pdpuba/dr.c /^drstart(drptr)$/ drstrategy ../pdpuba/dr.c /^drstrategy(bp)$/ drtimeout ../pdpuba/dr.c /^drtimeout(ptr)$/ dtom ../h/mbuf.h /^#define dtom(x) ((struct mbuf *)((int)x & ~(MSIZE/ duattach ../pdpuba/dhu.c /^duattach(addr,unit)$/ dump ../machine/mch_dump.s /^ASENTRY(dump)$/ dumpsys ../machine/machdep2.c /^dumpsys()$/ dup ../sys/kern_descrip.c /^dup()$/ dup2 ../sys/kern_descrip.c /^dup2()$/ dupit ../sys/kern_descrip.c /^dupit(fd, fp, flags)$/ dzattach ../pdpuba/dz.c /^dzattach(addr, unit)$/ dzclose ../pdpuba/dz.c /^dzclose(dev, flag)$/ dzdma ../machine/mch_dzpdma.s /^ASENTRY(dzdma)$/ dzioctl ../pdpuba/dz.c /^dzioctl(dev, cmd, data, flag)$/ dzmctl ../pdpuba/dz.c /^dzmctl(dev, bits, how)$/ dzopen ../pdpuba/dz.c /^dzopen(dev, flag)$/ dzparam ../pdpuba/dz.c /^dzparam(unit)$/ dzread ../pdpuba/dz.c /^dzread(dev, uio, flag)$/ dzrint ../pdpuba/dz.c /^dzrint(dz)$/ dzscan ../pdpuba/dz.c /^dzscan()$/ dzstart ../pdpuba/dz.c /^dzstart(tp)$/ dzstop ../pdpuba/dz.c /^dzstop(tp, flag)$/ dztimer ../pdpuba/dz.c /^dztimer()$/ dztodm ../pdpuba/dz.c /^dztodm(bits)$/ dzwait ../pdpuba/dz.c /^#define dzwait(x) while (((x)->dzlcs & DZ_ACK) == / dzwrite ../pdpuba/dz.c /^dzwrite(dev, uio, flag)$/ dzxint ../pdpuba/dz.c /^dzxint(tp)$/ ec_setaddr ../pdpif/if_ec.c /^ec_setaddr(physaddr,unit)$/ ecattach ../pdpif/if_ec.c /^ecattach(ui)$/ eccollide ../pdpif/if_ec.c /^eccollide(unit)$/ ecget ../pdpif/if_ec.c /^ecget(ecbuf, totlen, off0, ifp)$/ echo /usr/include/curses.h /^#define echo() (_tty.sg_flags |= ECHO, _echoit = / ecinit ../pdpif/if_ec.c /^ecinit(unit)$/ ecioctl ../pdpif/if_ec.c /^ecioctl(ifp, cmd, data)$/ ecoutput ../pdpif/if_ec.c /^ecoutput(ifp, m0, dst)$/ ecput ../pdpif/if_ec.c /^ecput(ecbuf, m)$/ ecread ../pdpif/if_ec.c /^ecread(unit)$/ ecrint ../pdpif/if_ec.c /^ecrint(unit)$/ ecstart ../pdpif/if_ec.c /^ecstart(unit)$/ ecunjam ../pdpif/if_ec.c /^ecunjam(addr)$/ ecxint ../pdpif/if_ec.c /^ecxint(unit)$/ emt ../machine/mch_trap.s /^ASENTRY(emt)$/ enableon ../machine/enable34.c /^enableon()$/ enattach ../pdpif/if_en.c /^enattach(ui)$/ encollide ../pdpif/if_en.c /^encollide(unit)$/ endocoll ../pdpif/if_en.c /^endocoll(unit)$/ endvfork ../sys/kern_exit.c /^endvfork()$/ eninit ../pdpif/if_en.c /^eninit(unit)$/ enoutput ../pdpif/if_en.c /^enoutput(ifp, m0, dst)$/ enprobe ../pdpif/if_en.c /^enprobe(reg)$/ enreset ../pdpif/if_en.c /^enreset(unit, uban)$/ enrint ../pdpif/if_en.c /^enrint(unit)$/ enstart ../pdpif/if_en.c /^enstart(dev)$/ entergroup ../sys/kern_prot.c /^entergroup(gid)$/ enxint ../pdpif/if_en.c /^enxint(unit)$/ erase /usr/include/curses.h /^# define erase() VOID(werase(stdscr))$/ erasechar /usr/include/curses.h /^#define erasechar() (_tty.sg_erase)$/ errnet ../sys/init_sysent.c /^#define errnet(narg, name) narg, name$/ estabur ../sys/kern_mman.c /^estabur(nt, nd, ns, sep, xrw)$/ ether_sprintf ../netinet/if_ether.c /^ether_sprintf(ap)$/ exadr ../pdpuba/hk.c /^#define exadr(x,y) (((long)(x) << 16) | (unsigned)/ execv ../sys/kern_exec.c /^execv()$/ execve ../sys/kern_exec.c /^execve()$/ execve1 ../sys/kern_exec.c /^execve1()$/ exit ../sys/kern_exit.c /^exit(rv)$/ expand ../sys/vm_proc.c /^expand(newsize,segment)$/ fadjust ../sys/sys_kern.c /^fadjust(fp, msg, cnt)$/ falloc ../sys/kern_descrip.c /^falloc()$/ fchdir ../sys/ufs_syscalls.c /^fchdir()$/ fchflags ../sys/ufs_syscalls.c /^fchflags()$/ fchmod ../sys/ufs_syscalls.c /^fchmod()$/ fchown ../sys/ufs_syscalls.c /^fchown()$/ fcntl ../sys/kern_descrip.c /^fcntl()$/ fd_mask ../h/types.h 62 feof /usr/include/stdio.h /^#define feof(p) (((p)->_flag&_IOEOF)!=0)$/ ferror /usr/include/stdio.h /^#define ferror(p) (((p)->_flag&_IOERR)!=0)$/ fetchi ../machine/kern_pdp.c /^fetchi()$/ ffs ../machine/libc_ffs.s /^ENTRY(ffs)$/ fgetown ../sys/kern_descrip.c /^fgetown(fp, valuep)$/ fileno /usr/include/stdio.h /^#define fileno(p) ((p)->_file)$/ fill_eproc ../sys/kern_sysctl.c /^fill_eproc(p, ep)$/ fill_from_u ../sys/kern_sysctl.c /^fill_from_u(p, rup, ttp, tdp)$/ fiobyte ../machine/enable34.c /^fiobyte (addr)$/ fioctl ../sys/kern_descrip.c /^fioctl(fp, cmd, value)$/ fioword ../machine/enable34.c /^fioword (addr)$/ fioword ../machine/mch_xxx.s /^ENTRY(fioword)$/ fldoff /usr/include/struct.h /^#define fldoff(str, fld) ((int)&(((struct str *)0)/ fldsiz /usr/include/struct.h /^#define fldsiz(str, fld) (sizeof(((struct str *)0)/ flock ../sys/kern_descrip.c /^flock()$/ flushok /usr/include/curses.h /^#define flushok(win,bf) (bf ? (win->_flags |= _FL/ fmove ../machine/mch_click.s /^ENTRY(fmove)$/ for ../sys/vm_sched.c /^ for (p = allproc; p != NULL; p = p->p_nxt) {$/ forceclose ../sys/sys_inode.c /^forceclose(dev)$/ fork ../sys/kern_fork.c /^fork()$/ fork1 ../sys/kern_fork.c /^fork1(isvfork)$/ fperr ../machine/kern_pdp.c /^fperr()$/ fpfetch ../sys/sys_kern.c /^fpfetch(fp, fpp)$/ fpflags ../sys/sys_kern.c /^fpflags(fp, set, clear)$/ fptrap ../machine/mch_fpsim.s /^ENTRY(fptrap)$/ free ../sys/ufs_alloc.c /^free(ip, bno)$/ freespace ../h/fs.h /^#define freespace(fs, percentreserved) \\$/ fsbtodb ../h/fs.h /^#define fsbtodb(b) ((daddr_t)((daddr_t)(b)<<1))$/ fserr ../sys/ufs_alloc.c /^fserr(fp, cp)$/ fset ../sys/kern_descrip.c /^fset(fp, bit, value)$/ fsetown ../sys/kern_descrip.c /^fsetown(fp, value)$/ fstat ../sys/kern_descrip.c /^fstat()$/ fsync ../sys/ufs_syscalls.c /^fsync()$/ ftruncate ../sys/ufs_syscalls.c /^ftruncate()$/ fubyte ../machine/mch_copy.s /^ENTRY(fubyte)$/ fubyte ../machine/net_copy.s /^ENTRY(fubyte)$/ fuibyte ../machine/mch_copy.s /^ENTRY(fuibyte)$/ fuiword ../machine/mch_copy.s /^ENTRY(fuiword)$/ fuword ../machine/mch_copy.s /^ENTRY(fuword)$/ fuword ../machine/net_copy.s /^ENTRY(fuword)$/ gatherstats ../sys/kern_clock.c /^gatherstats(pc, ps)$/ getblk ../sys/ufs_bio.c /^getblk(dev, blkno)$/ getc ../sys/tty_subr.c /^getc(p)$/ getc /usr/include/stdio.h /^#define getc(p) (--(p)->_cnt>=0? (int)(*(unsigned/ getch /usr/include/curses.h /^# define getch() VOID(wgetch(stdscr))$/ getchar /usr/include/stdio.h /^#define getchar() getc(stdin)$/ getdd ../pdpuba/tmscp.c /^getdd()$/ getdlim ../sys/quota_sys.c /^getdlim(q, dev, addr)$/ getdtablesize ../sys/kern_descrip.c /^getdtablesize()$/ geteblk ../sys/ufs_bio.c /^geteblk()$/ geterror ../sys/ufs_bio.c /^geterror(bp)$/ getf ../sys/kern_descrip.c /^getf(f)$/ getfs ../sys/ufs_subr.c /^getfs(dev)$/ getfsx ../sys/ufs_subr.c /^getfsx(dev)$/ getgid ../sys/kern_prot.c /^getgid()$/ getgroups ../sys/kern_prot.c /^getgroups()$/ gethostid ../sys/kern_xxx.c /^gethostid()$/ gethostname ../sys/kern_xxx.c /^gethostname()$/ getinode ../sys/ufs_syscalls.c /^getinode(fdes)$/ getitimer ../sys/kern_time.c /^getitimer()$/ getmdev ../sys/ufs_mount.c /^getmdev(pdev, fname)$/ getmemc ../machine/mem.c /^getmemc(addr)$/ getnewbuf ../sys/ufs_bio.c /^getnewbuf()$/ getpagesize ../sys/kern_mman.c /^getpagesize()$/ getpeername ../sys/uipc_syscalls.c /^getpeername()$/ getpgrp ../sys/kern_prot.c /^getpgrp()$/ getpid ../sys/kern_prot.c /^getpid()$/ getpriority ../sys/kern_resource.c /^getpriority()$/ getquota ../sys/quota_kern.c /^getquota(uid, lookuponly, nodq)$/ getrlimit ../sys/kern_resource.c /^getrlimit()$/ getrusage ../sys/kern_resource.c /^getrusage()$/ getsi ../pdpuba/si.c /^getsi()$/ getsockname ../sys/uipc_syscalls.c /^getsockname()$/ getsockopt ../sys/uipc_syscalls.c /^getsockopt()$/ getstr /usr/include/curses.h /^# define getstr(str) VOID(wgetstr(stdscr, str))$/ gettimeofday ../sys/kern_time.c /^gettimeofday()$/ getuid ../sys/kern_prot.c /^getuid()$/ getw ../sys/tty_subr.c /^getw(p)$/ getxfile ../sys/kern_exec.c /^getxfile(ip, ep, nargc, uid, gid)$/ getyx /usr/include/curses.h /^#define getyx(win,y,x) y = win->_cury, x = win->_/ gid_t ../h/types.h 47 gldav ../machine/kern_pdp.c /^gldav()$/ groupmember ../sys/kern_prot.c /^groupmember(gid)$/ grow ../sys/kern_mman.c /^grow(sp)$/ gsignal ../sys/kern_sig.c /^gsignal(pgrp, sig)$/ gtcodecode ../sys/tty_tb.c /^gtcodecode(cp, tbpos)$/ gtsockf ../sys/uipc_syscalls.c /^gtsockf(fdes)$/ halt ../machine/scb.s /^ENTRY(halt)$/ hardclock ../sys/kern_clock.c /^hardclock(dev,sp,r1,ov,nps,r0,pc,ps)$/ harderr ../sys/subr_prf.c /^harderr(bp, cp)$/ hiint ../machine/machparam.h /^#define hiint(long) (((int *)&(long))[0])$/ hiword ../pdpif/if_dmc.c /^#define hiword(x) ((short *)&x)[1]$/ hkattach ../pdpuba/hk.c /^hkattach(addr, unit)$/ hkdump ../pdpuba/hk.c /^hkdump(dev)$/ hkecc ../pdpuba/hk.c /^hkecc(bp, flag)$/ hkintr ../pdpuba/hk.c /^hkintr()$/ hkncyl ../pdpuba/hk.c /^#define hkncyl(unit) (hk_type[unit] ? NHK7CYL : N/ hkopen ../pdpuba/hk.c /^hkopen(dev, flag)$/ hkroot ../pdpuba/hk.c /^hkroot()$/ hksize ../pdpuba/hk.c /^hksize(dev)$/ hkstart ../pdpuba/hk.c /^hkstart()$/ hkstrategy ../pdpuba/hk.c /^hkstrategy(bp)$/ hkunit ../pdpuba/hk.c /^#define hkunit(dev) (((dev) >> 3) & 07)$/ hkustart ../pdpuba/hk.c /^hkustart(unit)$/ hkwait ../pdpuba/hk.c /^#define hkwait(hkaddr) while ((hkaddr->hkcs1 & HK/ hostdeque ../netimp/if_imphost.c /^hostdeque(hp)$/ hostenter ../netimp/if_imphost.c /^hostenter(addr) $/ hostfree ../netimp/if_imphost.c /^hostfree(hp) $/ hostlookup ../netimp/if_imphost.c /^hostlookup(addr)$/ hostrelease ../netimp/if_imphost.c /^hostrelease(hp)$/ hostreset ../netimp/if_imphost.c /^hostreset(net)$/ hostslowtimo ../netimp/if_imphost.c /^hostslowtimo()$/ howmany ../h/param.h /^#define howmany(x, y) (((x)+((y)-1))\/(y))$/ htattach ../pdpuba/ht.c /^htattach(addr, unit)$/ htclose ../pdpuba/ht.c /^htclose(dev, flag)$/ htcommand ../pdpuba/ht.c /^htcommand(dev, com, count)$/ htinit ../pdpuba/ht.c /^htinit()$/ htintr ../pdpuba/ht.c /^htintr()$/ htioctl ../pdpuba/ht.c /^htioctl(dev, cmd, data, flag)$/ htonl ../machine/machparam.h /^#define htonl(x) (x)$/ htons ../machine/machparam.h /^#define htons(x) (x)$/ htopen ../pdpuba/ht.c /^htopen(dev, flag)$/ htstart ../pdpuba/ht.c /^htstart()$/ htstrategy ../pdpuba/ht.c /^htstrategy(bp)$/ hw_sysctl ../sys/kern_sysctl.c /^hw_sysctl(name, namelen, oldp, oldlenp, newp, newl/ hzto ../sys/kern_clock.c /^hzto(tv)$/ ialloc ../sys/ufs_alloc.c /^ialloc(pip)$/ icmp_error ../netinet/ip_icmp.c /^icmp_error(oip, type, code, ifp, dest)$/ icmp_input ../netinet/ip_icmp.c /^icmp_input(m, ifp)$/ icmp_reflect ../netinet/ip_icmp.c /^icmp_reflect(ip, ifp)$/ icmp_send ../netinet/ip_icmp.c /^icmp_send(ip, opts)$/ icode ../machine/mch_start.s /^ENTRY(icode)$/ idle ../machine/mch_xxx.s /^ENTRY(idle)$/ idp_abort ../netns/idp_usrreq.c /^idp_abort(nsp)$/ idp_ctlinput ../netns/ns_input.c /^idp_ctlinput(cmd, arg)$/ idp_ctloutput ../netns/idp_usrreq.c /^idp_ctloutput(req, so, level, name, value)$/ idp_do_route ../netns/ns_input.c /^idp_do_route(src, ro)$/ idp_drop ../netns/idp_usrreq.c /^idp_drop(nsp, errno)$/ idp_forward ../netns/ns_input.c /^idp_forward(idp)$/ idp_input ../netns/idp_usrreq.c /^idp_input(m, nsp, ifp)$/ idp_output ../netns/idp_usrreq.c /^idp_output(nsp, m0)$/ idp_raw_usrreq ../netns/idp_usrreq.c /^idp_raw_usrreq(so, req, m, nam, rights)$/ idp_undo_route ../netns/ns_input.c /^idp_undo_route(ro)$/ idp_usrreq ../netns/idp_usrreq.c /^idp_usrreq(so, req, m, nam, rights)$/ idpip_input ../netns/ns_ip.c /^idpip_input(m, ifp)$/ if ../sys/ufs_inode.c /^ if (ip->i_mode == 0)$/ if_attach ../net/if.c /^if_attach(ifp)$/ if_down ../net/if.c /^if_down(ifp)$/ if_qflush ../net/if.c /^if_qflush(ifq)$/ if_rubaget ../pdpif/if_uba.c /^if_rubaget(ifu, totlen, off0, ifp)$/ if_slowtimo ../net/if.c /^if_slowtimo()$/ if_ubainit ../pdpif/if_uba.c /^if_ubainit(ifu, uban, hlen, nmr)$/ if_wubaput ../pdpif/if_uba.c /^if_wubaput(ifu, m)$/ ifa_ifwithaddr ../net/if.c /^ifa_ifwithaddr(addr)$/ ifa_ifwithaf ../net/if.c /^ifa_ifwithaf(af)$/ ifa_ifwithdstaddr ../net/if.c /^ifa_ifwithdstaddr(addr)$/ ifa_ifwithnet ../net/if.c /^ifa_ifwithnet(addr)$/ ifconf ../net/if.c /^ifconf(cmd, data)$/ ifind ../sys/ufs_inode.c /^ifind(dev, ino)$/ ifinit ../net/if.c /^ifinit()$/ ifioctl ../net/if.c /^ifioctl(so, cmd, data)$/ iflush ../sys/ufs_inode.c /^iflush(dev, iq)$/ ifnet ../sys/init_sysent.c /^#define ifnet(narg, name) narg, name$/ ifptoia ../netinet/ip_icmp.c /^ifptoia(ifp)$/ ifree ../sys/ufs_alloc.c /^ifree(ip, ino)$/ ifubareset ../net/if.c /^ifubareset(uban)$/ ifunit ../net/if.c /^ifunit(name)$/ iget ../sys/ufs_inode.c /^iget(dev, fs, ino)$/ igrab ../sys/ufs_inode.c /^igrab(ip)$/ ihinit ../sys/ufs_inode.c /^ihinit()$/ il_setaddr ../pdpif/if_il.c /^il_setaddr(physaddr, unit)$/ ilattach ../pdpif/if_il.c /^ilattach(ui)$/ ilcint ../pdpif/if_il.c /^ilcint(unit)$/ ilinit ../pdpif/if_il.c /^ilinit(unit)$/ ilioctl ../pdpif/if_il.c /^ilioctl(ifp, cmd, data)$/ ilock ../sys/ufs_inode.c /^ilock(ip)$/ iloutput ../pdpif/if_il.c /^iloutput(ifp, m0, dst)$/ ilprobe ../pdpif/if_il.c /^ilprobe(reg)$/ ilrint ../pdpif/if_il.c /^ilrint(unit)$/ ilstart ../pdpif/if_il.c /^ilstart(dev)$/ iltotal ../pdpif/if_il.c /^iltotal(is)$/ ilwait ../pdpif/if_il.c /^ilwait(ui, op)$/ ilwatch ../pdpif/if_il.c /^ilwatch(unit)$/ imp_addr_to_leader ../netimp/if_imp.c /^imp_addr_to_leader(imp, a)$/ imp_leader_to_addr ../netimp/if_imp.c /^imp_leader_to_addr(ap, ip, ifp)$/ impattach ../netimp/if_imp.c /^impattach(ui, reset)$/ impdown ../netimp/if_imp.c /^impdown(sc)$/ impinit ../netimp/if_imp.c /^impinit(unit)$/ impinput ../netimp/if_imp.c /^impinput(unit, m)$/ impintr ../netimp/if_imp.c /^impintr()$/ impioctl ../netimp/if_imp.c /^impioctl(ifp, cmd, data)$/ impmsg ../netimp/if_imp.c /^impmsg(sc, fmt, a1, a2, a3)$/ impnoops ../netimp/if_imp.c /^impnoops(sc) $/ impoutput ../netimp/if_imp.c /^impoutput(ifp, m0, dst)$/ impsnd ../netimp/if_imp.c /^impsnd(ifp, m) $/ in_arpinput ../netinet/if_ether.c /^in_arpinput(ac, m)$/ in_broadcast ../netinet/in.c /^in_broadcast(in)$/ in_canforward ../netinet/in.c /^in_canforward(in)$/ in_cksum ../machine/in_cksum.c /^in_cksum(m, len)$/ in_control ../netinet/in.c /^in_control(so, cmd, data, ifp)$/ in_iaonnetof ../netinet/in.c /^in_iaonnetof(net)$/ in_ifinit ../netinet/in.c /^in_ifinit(ifp, ia, sin)$/ in_lnaof ../netinet/in.c /^in_lnaof(in)$/ in_localaddr ../netinet/in.c /^in_localaddr(in)$/ in_losing ../netinet/in_pcb.c /^in_losing(inp)$/ in_makeaddr ../netinet/in.c /^in_makeaddr(net, host)$/ in_netof ../netinet/in.c /^in_netof(in)$/ in_pcballoc ../netinet/in_pcb.c /^in_pcballoc(so, head)$/ in_pcbbind ../netinet/in_pcb.c /^in_pcbbind(inp, nam)$/ in_pcbconnect ../netinet/in_pcb.c /^in_pcbconnect(inp, nam)$/ in_pcbdetach ../netinet/in_pcb.c /^in_pcbdetach(inp)$/ in_pcbdisconnect ../netinet/in_pcb.c /^in_pcbdisconnect(inp)$/ in_pcblookup ../netinet/in_pcb.c /^in_pcblookup(head, faddr, fport, laddr, lport, fla/ in_pcbnotify ../netinet/in_pcb.c /^in_pcbnotify(head, dst, fport, laddr, lport, cmd, / in_rtchange ../netinet/in_pcb.c /^in_rtchange(inp)$/ in_setpeeraddr ../netinet/in_pcb.c /^in_setpeeraddr(inp, nam)$/ in_setsockaddr ../netinet/in_pcb.c /^in_setsockaddr(inp, nam)$/ inch /usr/include/curses.h /^# define inch() VOID(winch(stdscr))$/ incore ../sys/ufs_bio.c /^incore(dev, blkno)$/ indirtrunc ../sys/ufs_inode.c /^indirtrunc(ip, bn, lastbn, level)$/ inet_hash ../netinet/in.c /^inet_hash(sin, hp)$/ inet_netmatch ../netinet/in.c /^inet_netmatch(sin1, sin2)$/ inferior ../sys/kern_proc.c /^inferior(p)$/ ingres_abt ../sys/ingreslock.c /^ingres_abt()$/ ingres_enter ../sys/ingreslock.c /^ingres_enter(ll)$/ ingres_find ../sys/ingreslock.c /^ingres_find(q)$/ ingres_maplock ../h/ingreslock.h /^#define ingres_maplock() mapseg5(Locktabseg.se_add/ ingres_open ../sys/ingreslock.c /^ingres_open(dev, flag, mode)$/ ingres_rm ../sys/ingreslock.c /^ingres_rm(l,llpid)$/ ingres_rma ../sys/ingreslock.c /^ingres_rma(pd)$/ ingres_unique ../sys/ingreslock.c /^ingres_unique(q)$/ ingres_write ../sys/ingreslock.c /^ingres_write(dev, uio, flag)$/ initdisklabels ../machine/machdep2.c /^initdisklabels()$/ ino_close ../sys/sys_inode.c /^ino_close(fp)$/ ino_ioctl ../sys/sys_inode.c /^ino_ioctl(fp, com, data)$/ ino_lock ../sys/sys_inode.c /^ino_lock(fp, cmd)$/ ino_rw ../sys/sys_inode.c /^ino_rw(fp, uio)$/ ino_select ../sys/sys_inode.c /^ino_select(fp, which)$/ ino_stat ../sys/sys_inode.c /^ino_stat(ip, sb)$/ ino_t ../h/types.h 40 ino_unlock ../sys/sys_inode.c /^ino_unlock(fp, kind)$/ inoquota ../sys/quota_ufs.c /^inoquota(ip)$/ insch /usr/include/curses.h /^# define insch(c) VOID(winsch(stdscr,c))$/ insertln /usr/include/curses.h /^# define insertln() VOID(winsertln(stdscr))$/ insque ../h/systm.h /^#define insque(q,p) _insque((caddr_t)q,(caddr_t)p)/ insque ../machine/libc_insque.s /^ENTRY(insque)$/ int ../h/types.h 27 intotcpcb ../netinet/tcp_var.h /^#define intotcpcb(ip) ((struct tcpcb *)(ip)->inp_p/ ioctl ../sys/sys_generic.c /^ioctl()$/ iothndlr ../machine/mch_trap.s /^ASENTRY(iothndlr)$/ ip_ctloutput ../netinet/ip_output.c /^ip_ctloutput(op, so, level, optname, m)$/ ip_deq ../netinet/ip_input.c /^ip_deq(p)$/ ip_dooptions ../netinet/ip_input.c /^ip_dooptions(ip, ifp)$/ ip_drain ../netinet/ip_input.c /^ip_drain()$/ ip_enq ../netinet/ip_input.c /^ip_enq(p, prev)$/ ip_forward ../netinet/ip_input.c /^ip_forward(ip, ifp)$/ ip_freef ../netinet/ip_input.c /^ip_freef(fp)$/ ip_init ../netinet/ip_input.c /^ip_init()$/ ip_insertoptions ../netinet/ip_output.c /^ip_insertoptions(m, opt, phlen)$/ ip_optcopy ../netinet/ip_output.c /^ip_optcopy(ip, jp)$/ ip_output ../netinet/ip_output.c /^ip_output(m0, opt, ro, flags)$/ ip_pcbopts ../netinet/ip_output.c /^ip_pcbopts(pcbopt, m)$/ ip_reass ../netinet/ip_input.c /^ip_reass(ip, fp)$/ ip_rtaddr ../netinet/ip_input.c /^ip_rtaddr(dst)$/ ip_slowtimo ../netinet/ip_input.c /^ip_slowtimo()$/ ip_srcroute ../netinet/ip_input.c /^ip_srcroute()$/ ip_stripoptions ../netinet/ip_input.c /^ip_stripoptions(ip, mopt)$/ ipintr ../netinet/ip_input.c /^ipintr()$/ iptime ../netinet/ip_icmp.c /^iptime()$/ iput ../sys/ufs_inode.c /^iput(ip)$/ irele ../sys/ufs_inode.c /^irele(ip)$/ isalnum /usr/include/ctype.h /^#define isalnum(c) ((_ctype_+1)[c]&(_U|_L|_N))$/ isalpha /usr/include/ctype.h /^#define isalpha(c) ((_ctype_+1)[c]&(_U|_L))$/ isascii /usr/include/ctype.h /^#define isascii(c) ((unsigned)(c)<=0177)$/ isbad ../pdpuba/dkbad.c /^isbad(bt, cyl, trk, sec)$/ iscntrl /usr/include/ctype.h /^#define iscntrl(c) ((_ctype_+1)[c]&_C)$/ isdigit /usr/include/ctype.h /^#define isdigit(c) ((_ctype_+1)[c]&_N)$/ isdisk ../machine/conf.c /^isdisk(dev, type)$/ isgraph /usr/include/ctype.h /^#define isgraph(c) ((_ctype_+1)[c]&(_P|_U|_L|_N))$/ iskmemdev ../machine/conf.c /^iskmemdev(dev)$/ isleap /usr/include/tzfile.h /^#define isleap(y) (((y) % 4) == 0 && ((y) % 100) !/ islower /usr/include/ctype.h /^#define islower(c) ((_ctype_+1)[c]&_L)$/ isprint /usr/include/ctype.h /^#define isprint(c) ((_ctype_+1)[c]&(_P|_U|_L|_N|_B/ isprof ../machine/clock.c /^isprof()$/ ispunct /usr/include/ctype.h /^#define ispunct(c) ((_ctype_+1)[c]&_P)$/ issig ../sys/kern_sig.c /^issig()$/ isspace /usr/include/ctype.h /^#define isspace(c) ((_ctype_+1)[c]&_S)$/ isupper /usr/include/ctype.h /^#define isupper(c) ((_ctype_+1)[c]&_U)$/ isxdigit /usr/include/ctype.h /^#define isxdigit(c) ((_ctype_+1)[c]&(_N|_X))$/ itimerdecr ../sys/kern_time.c /^itimerdecr(itp, usec)$/ itimerfix ../sys/kern_time.c /^itimerfix(tv)$/ itod ../h/fs.h /^#define itod(x) ((daddr_t)((((u_int)(x) + 2 * INO/ itoo ../h/fs.h /^#define itoo(x) ((int)(((x) + 2 * INOPB - 1) % IN/ itrunc ../sys/ufs_inode.c /^itrunc(oip,length)$/ iunlock ../sys/ufs_inode.c /^iunlock(ip)$/ iupdat ../sys/ufs_inode.c /^iupdat(ip, ta, tm, waitfor)$/ jmp_buf /usr/include/setjmp.h 3 kern_sysctl ../sys/kern_sysctl.c /^kern_sysctl(name, namelen, oldp, oldlenp, newp, ne/ keycomp ../sys/ingreslock.c /^#define keycomp(a,b) bcmp(a,b,KEYSIZE)$/ kill ../sys/kern_sig.c /^kill()$/ killchar /usr/include/curses.h /^#define killchar() (_tty.sg_kill)$/ killpg ../sys/kern_sig.c /^killpg()$/ killpg1 ../sys/kern_sig.c /^killpg1(signo, pgrp, all)$/ lblkno ../h/fs.h /^#define lblkno(loc) \/* calculates (loc \/ fs->fs_b/ ldiv ../machine/libc_ldiv.s /^ASENTRY(ldiv)$/ ldiv ../machine/libc_ldiv.s /^ASENTRY(ldiv)$/ leavegroup ../sys/kern_prot.c /^leavegroup(gid)$/ leaveok /usr/include/curses.h /^#define leaveok(win,bf) (win->_leave = bf)$/ link ../sys/ufs_syscalls.c /^link()$/ listen ../sys/uipc_syscalls.c /^listen()$/ lmul ../machine/libc_lmul.s /^ASENTRY(lmul)$/ loadav ../sys/vm_sched.c /^loadav(avg, n)$/ loattach ../net/if_loop.c /^loattach()$/ locc ../machine/mch_xxx.s /^ENTRY(locc)$/ locc ../machine/net_xxx.s /^ENTRY(locc)$/ locc ../sys/ufs_subr.c /^locc(mask, size, cp)$/ lock ../machine/kern_pdp.c /^lock()$/ log ../sys/subr_prf.c /^log(level, fmt, x1)$/ logclose ../sys/subr_log.c /^logclose(dev, flag)$/ logioctl ../sys/subr_log.c /^logioctl(com, data, flag)$/ logopen ../sys/subr_log.c /^logopen(dev, mode)$/ logpri ../sys/subr_prf.c /^logpri(level)$/ logread ../sys/subr_log.c /^logread(dev, uio, flag)$/ logselect ../sys/subr_log.c /^logselect(dev, rw)$/ logwakeup ../sys/subr_log.c /^logwakeup()$/ loint ../machine/machparam.h /^#define loint(long) (((int *)&(long))[1])$/ loioctl ../net/if_loop.c /^loioctl(ifp, cmd, data)$/ long ../h/types.h 28 longjmp ../machine/mch_xxx.s /^ENTRY(longjmp)$/ lookc ../sys/tty_subr.c /^lookc(cp)$/ looutput ../net/if_loop.c /^looutput(ifp, m0, dst)$/ loword ../pdpif/if_dmc.c /^#define loword(x) ((short *)&x)[0]$/ lpattach ../pdpuba/lp.c /^lpattach(addr, unit)$/ lpcanon ../pdpuba/lp.c /^lpcanon(dev, c)$/ lpclose ../pdpuba/lp.c /^lpclose(dev, flag)$/ lpintr ../pdpuba/lp.c /^lpintr(lp11)$/ lpopen ../pdpuba/lp.c /^lpopen(dev, flag)$/ lpoutput ../pdpuba/lp.c /^lpoutput(dev, c)$/ lptout ../pdpuba/lp.c /^lptout(dev)$/ lpwrite ../pdpuba/lp.c /^lpwrite(dev, uio, flag)$/ lrem ../machine/libc_lrem.s /^ASENTRY(lrem)$/ lrem ../machine/libc_lrem.s /^ASENTRY(lrem)$/ lseek ../sys/ufs_syscalls.c /^lseek()$/ lstat ../sys/ufs_syscalls.c /^lstat()$/ m_adj ../sys/uipc_mbuf.c /^m_adj(mp, len)$/ m_cat ../sys/uipc_mbuf.c /^m_cat(m, n)$/ m_copy ../sys/uipc_mbuf.c /^m_copy(m, off, len)$/ m_expand ../sys/uipc_mbuf.c /^m_expand(canwait)$/ m_free ../sys/uipc_mbuf.c /^m_free(m)$/ m_freem ../sys/uipc_mbuf.c /^m_freem(m)$/ m_get ../sys/uipc_mbuf.c /^m_get(canwait, type)$/ m_getclr ../sys/uipc_mbuf.c /^m_getclr(canwait, type)$/ m_ioget ../sys/uipc_mbuf.c /^m_ioget(size)$/ m_more ../sys/uipc_mbuf.c /^m_more(canwait, type)$/ m_pullup ../sys/uipc_mbuf.c /^m_pullup(n, len)$/ major ../h/types.h /^#define major(x) ((int)(((int)(x)>>8)&0377))$/ makedev ../h/types.h /^#define makedev(x,y) ((dev_t)(((x)<<8) | (y)))$/ maknode ../sys/ufs_syscalls.c /^maknode(mode, ndp)$/ malloc ../sys/subr_rmap.c /^malloc(mp, size)$/ malloc3 ../sys/subr_rmap.c /^malloc3(mp, d_size, s_size, u_size, a)$/ mapalloc ../machine/machdep.c /^mapalloc(bp)$/ mapfree ../machine/machdep.c /^mapfree(bp)$/ mapin ../machine/mch_xxx.s /^ENTRY(mapin)$/ mapinfo ../machine/seg.h 127 mapout ../machine/mch_xxx.s /^ENTRY(mapout)$/ mapout ../machine/seg.h /^# define mapout(bp) normalseg5()$/ mapseg5 ../machine/seg.h /^#define mapseg5(addr,desc) { \\$/ mbcopyin ../machine/net_mbuf.s /^ENTRY(mbcopyin)$/ mbcopyout ../machine/net_mbuf.s /^ENTRY(mbcopyout)$/ mbinit ../sys/uipc_mbuf.c /^mbinit()$/ mbinit2 ../sys/uipc_mbuf.c /^mbinit2(mem, how, num)$/ mem_parity ../machine/machdep2.c /^mem_parity()$/ memaddr ../h/types.h 78 mfkd ../machine/net_copy.s /^ENTRY(mfkd)$/ mfree ../sys/subr_rmap.c /^mfree(mp, size, addr)$/ mfsd ../machine/mch_copy.s /^ENTRY(mfsd)$/ minor ../h/types.h /^#define minor(x) ((int)((x)&0377))$/ mkdir ../sys/ufs_syscalls.c /^mkdir()$/ mknod ../sys/ufs_syscalls.c /^mknod()$/ mmrw ../machine/mem.c /^mmrw(dev, uio, flag)$/ mode_t ../h/types.h 49 mountfs ../sys/ufs_mount.c /^mountfs(dev, flags, ip)$/ move /usr/include/curses.h /^# define move(y, x) VOID(wmove(stdscr, y, x))$/ msprof ../machine/machdep2.c /^msprof()$/ mtkd ../machine/net_copy.s /^ENTRY(mtkd)$/ mtocl ../h/mbuf.h /^#define mtocl(x) (((int)x - (int)mbutl) >> MCLSHIF/ mtod ../h/mbuf.h /^#define mtod(x,t) ((t)((int)(x) + (x)->m_off))$/ mtsd ../machine/mch_copy.s /^ENTRY(mtsd)$/ mvaddch /usr/include/curses.h /^#define mvaddch(y,x,ch) mvwaddch(stdscr,y,x,ch)$/ mvaddstr /usr/include/curses.h /^#define mvaddstr(y,x,str) mvwaddstr(stdscr,y,x,str/ mvdelch /usr/include/curses.h /^#define mvdelch(y,x) mvwdelch(stdscr,y,x)$/ mvgetch /usr/include/curses.h /^#define mvgetch(y,x) mvwgetch(stdscr,y,x)$/ mvgetstr /usr/include/curses.h /^#define mvgetstr(y,x,str) mvwgetstr(stdscr,y/ mvinch /usr/include/curses.h /^#define mvinch(y,x) mvwinch(stdscr,y,x)$/ mvinsch /usr/include/curses.h /^#define mvinsch(y,x,c) mvwinsch(stdscr,y,x,c)$/ mvwaddch /usr/include/curses.h /^#define mvwaddch(win,y,x,ch) VOID(wmove(win,y,x)==/ mvwaddstr /usr/include/curses.h /^#define mvwaddstr(win,y,x,str) VOID(wmove(win,y,x)/ mvwdelch /usr/include/curses.h /^#define mvwdelch(win,y,x) VOID(wmove(win,y,x) == E/ mvwgetch /usr/include/curses.h /^#define mvwgetch(win,y,x) VOID(wmove(win,y,x)==ERR/ mvwgetstr /usr/include/curses.h /^#define mvwgetstr(win,y,x,str) VOID(wmove(win,y,x/ mvwinch /usr/include/curses.h /^#define mvwinch(win,y,x) VOID(wmove(win,y,x) == ER/ mvwinsch /usr/include/curses.h /^#define mvwinsch(win,y,x,c) VOID(wmove(win,y,x) ==/ mx ../pdpuba/ra.c /^mx(l, i)$/ n_long ../netinet/in_systm.h 29 n_short ../netinet/in_systm.h 28 n_time ../netinet/in_systm.h 31 namei ../sys/ufs_namei.c /^namei(ndp)$/ nchinit ../sys/ufs_namei.c /^nchinit()$/ nchinval ../sys/ufs_namei.c /^nchinval(dev)$/ ndflush ../sys/tty_subr.c /^ndflush(q, cc)$/ ndqb ../sys/tty_subr.c /^ndqb(q, flag)$/ net_sysctl ../sys/kern_sysctl.c /^net_sysctl(name, namelen, oldp, oldlenp, newp, new/ netcopyout ../sys/sys_net.c /^netcopyout(m, to, len)$/ netcrash ../sys/sys_kern.c /^netcrash()$/ netinit ../sys/init_main.c /^netinit()$/ netintr ../machine/net_trap.s /^ENTRY(netintr)$/ netpfind ../sys/sys_kern.c /^netpfind(pid)$/ netpsignal ../sys/sys_kern.c /^netpsignal(p, sig) \/* XXX? sosend, sohasoutofband/ netstart ../sys/sys_net.c /^netstart()$/ newproc ../sys/kern_fork.c /^newproc(isvfork)$/ nextc ../sys/tty_subr.c /^nextc(p, cp, store)$/ nextiv ../machine/mch_xxx.s /^ENTRY(nextiv)$/ nl /usr/include/curses.h /^#define nl() (_tty.sg_flags |= CRMOD,_pfast = _ra/ nocbreak /usr/include/curses.h /^#define nocbreak() (_tty.sg_flags &= ~CBREAK,_rawm/ nocrmode /usr/include/curses.h /^#define nocrmode() nocbreak() \/* backwards compata/ nodev ../sys/subr_xxx.c /^nodev()$/ noecho /usr/include/curses.h /^#define noecho() (_tty.sg_flags &= ~ECHO, _echoit / nonet ../sys/subr_xxx.c /^nonet()$/ nonl /usr/include/curses.h /^#define nonl() (_tty.sg_flags &= ~CRMOD, _pfast =/ noop ../machine/mch_xxx.s /^ENTRY(noop)$/ noraw /usr/include/curses.h /^#define noraw() (_tty.sg_flags&=~RAW,_rawmode=FAL/ normalseg5 ../machine/seg.h /^#define normalseg5() restorseg5(seg5)$/ nostk ../machine/kern_pdp.c /^nostk()$/ nosys ../machine/trap.c /^nosys()$/ notavail ../h/buf.h /^#define notavail(bp) { \\$/ ns_control ../netns/ns.c /^ns_control(so, cmd, data, ifp)$/ ns_echo ../netns/ns_error.c /^ns_echo(idp)$/ ns_err_input ../netns/ns_error.c /^ns_err_input(m)$/ ns_err_x ../netns/ns_error.c /^ns_err_x(c)$/ ns_error ../netns/ns_error.c /^ns_error(om, type, param)$/ ns_hash ../netns/ns.c /^ns_hash(sns, hp)$/ ns_hosteq ../netns/ns.h /^#define ns_hosteq(s,t) (ns_hosteqnh((s).x_host,(t)/ ns_hosteqnh ../netns/ns.h /^#define ns_hosteqnh(s,t) ((s).s_host[0] == (t).s_h/ ns_iaonnetof ../netns/ns.c /^ns_iaonnetof(dst)$/ ns_ifinit ../netns/ns.c /^ns_ifinit(ifp, ia, sns)$/ ns_init ../netns/ns_input.c /^ns_init()$/ ns_neteq ../netns/ns.h /^#define ns_neteq(a,b) ns_neteqnn((a).x_net, (b).x_/ ns_neteqnn ../netns/ns.h /^#define ns_neteqnn(a,b) (((a).s_net[0]==(b).s_net[/ ns_netmatch ../netns/ns.c /^ns_netmatch(sns1, sns2)$/ ns_netof ../netns/ns.h /^#define ns_netof(a) (*(long *) & ((a).x_net)) \/* X/ ns_nullhost ../netns/ns.h /^#define ns_nullhost(x) (((x).x_host.s_host[0]==0) / ns_output ../netns/ns_output.c /^ns_output(m0, ro, flags)$/ ns_pcballoc ../netns/ns_pcb.c /^ns_pcballoc(so, head)$/ ns_pcbbind ../netns/ns_pcb.c /^ns_pcbbind(nsp, nam)$/ ns_pcbconnect ../netns/ns_pcb.c /^ns_pcbconnect(nsp, nam)$/ ns_pcbdetach ../netns/ns_pcb.c /^ns_pcbdetach(nsp)$/ ns_pcbdisconnect ../netns/ns_pcb.c /^ns_pcbdisconnect(nsp)$/ ns_pcblookup ../netns/ns_pcb.c /^ns_pcblookup(faddr, lport, wildp)$/ ns_pcbnotify ../netns/ns_pcb.c /^ns_pcbnotify(dst, errno, notify, param)$/ ns_printhost ../netns/ns_error.c /^ns_printhost(p)$/ ns_rtchange ../netns/ns_pcb.c /^ns_rtchange(nsp)$/ ns_setpeeraddr ../netns/ns_pcb.c /^ns_setpeeraddr(nsp, nam)$/ ns_setsockaddr ../netns/ns_pcb.c /^ns_setsockaddr(nsp, nam)$/ ns_watch_output ../netns/ns_input.c /^ns_watch_output(m, ifp)$/ nsintr ../netns/ns_input.c /^nsintr()$/ nsip_ctlinput ../netns/ns_ip.c /^nsip_ctlinput(cmd, sa)$/ nsip_free ../netns/ns_ip.c /^nsip_free(ifp)$/ nsip_route ../netns/ns_ip.c /^nsip_route(m)$/ nsip_rtchange ../netns/ns_ip.c /^nsip_rtchange(dst)$/ nsipattach ../netns/ns_ip.c /^nsipattach()$/ nsipioctl ../netns/ns_ip.c /^nsipioctl(ifp, cmd, data)$/ nsipoutput ../netns/ns_ip.c /^nsipoutput(ifn, m0, dst)$/ nstime ../netns/ns_error.c /^nstime()$/ nstosppcb ../netns/spp_var.h /^#define nstosppcb(np) ((struct sppcb *)(np)->nsp_p/ ntohl ../machine/machparam.h /^#define ntohl(x) (x)$/ ntohs ../machine/machparam.h /^#define ntohs(x) (x)$/ nubreg ../h/uba.h /^#define nubreg(n,s) (((long) (n) * (long) (s) + \\/ null_hash ../net/af.c /^null_hash(addr, hp)$/ null_init ../net/af.c /^null_init()$/ null_netmatch ../net/af.c /^null_netmatch(a1, a2)$/ nulldev ../sys/subr_xxx.c /^nulldev()$/ nullioctl ../sys/tty_conf.c /^nullioctl(tp, cmd, data, flags)$/ nullmodem ../sys/tty.c /^nullmodem(tp, flag)$/ off_t ../h/types.h 45 open ../sys/ufs_syscalls.c /^open()$/ opendq ../sys/quota_kern.c /^opendq(mp, fname)$/ openi ../sys/sys_inode.c /^openi(ip, mode)$/ ovbcopy ../netinet/ip_output.c /^#define ovbcopy(a,b,c) bcopy(a,b,c)$/ owait ../sys/kern_exit.c /^owait()$/ panic ../sys/subr_prf.c /^panic(s)$/ pfctlinput ../sys/uipc_domain.c /^pfctlinput(cmd, sa)$/ pffasttimo ../sys/uipc_domain.c /^pffasttimo()$/ pffindproto ../sys/uipc_domain.c /^pffindproto(family, protocol, type)$/ pffindtype ../sys/uipc_domain.c /^pffindtype(family, type)$/ pfind ../sys/kern_proc.c /^pfind(pid)$/ pfslowtimo ../sys/uipc_domain.c /^pfslowtimo()$/ phys ../machine/kern_pdp.c /^phys()$/ physio ../sys/vm_swp.c /^physio(strat, bp, dev, rw, uio)$/ pid_t ../h/types.h 48 pipe ../sys/sys_pipe.c /^pipe()$/ pipe_rw ../sys/sys_pipe.c /^pipe_rw(fp, uio, flag)$/ pipe_select ../sys/sys_pipe.c /^pipe_select(fp, which)$/ pointubreg ../h/uba.h /^#define pointubreg(v,sep) { ubadr_t x; \\$/ poldecode ../sys/tty_tb.c /^poldecode(cp, polpos)$/ powrdown ../machine/mch_trap.s /^ASENTRY(powrdown)$/ pqinit ../sys/kern_proc.c /^pqinit()$/ prf ../sys/subr_prf.c /^prf(fmt, adx, flags, ttyp)$/ printbyte ../netimp/if_imp.c /^printbyte(cp, n)$/ printf ../sys/subr_prf.c /^printf(fmt, x1)$/ printleader ../netimp/if_imp.c /^printleader(routine, ip)$/ printn ../sys/subr_prf.c /^printn(n, b, flags, ttyp)$/ procxmt ../sys/sys_process.c /^procxmt()$/ profil ../sys/kern_clock.c /^profil()$/ psig ../sys/kern_sig.c /^psig()$/ psignal ../sys/kern_sig.c /^psignal(p, sig)$/ ptcclose ../sys/tty_pty.c /^ptcclose(dev, flag)$/ ptcopen ../sys/tty_pty.c /^ptcopen(dev, flag)$/ ptcread ../sys/tty_pty.c /^ptcread(dev, uio, flag)$/ ptcselect ../sys/tty_pty.c /^ptcselect(dev, rw)$/ ptcwakeup ../sys/tty_pty.c /^ptcwakeup(tp, flag)$/ ptcwrite ../sys/tty_pty.c /^ptcwrite(dev, uio, flag)$/ ptrace ../sys/sys_process.c /^ptrace()$/ ptsclose ../sys/tty_pty.c /^ptsclose(dev, flag)$/ ptsopen ../sys/tty_pty.c /^ptsopen(dev, flag)$/ ptsread ../sys/tty_pty.c /^ptsread(dev, uio, flag)$/ ptsstart ../sys/tty_pty.c /^ptsstart(tp)$/ ptsstop ../sys/tty_pty.c /^ptsstop(tp, flush)$/ ptswrite ../sys/tty_pty.c /^ptswrite(dev, uio, flag)$/ ptyioctl ../sys/tty_pty.c /^ptyioctl(dev, cmd, data, flag)$/ putc ../sys/tty_subr.c /^putc(c, p)$/ putc /usr/include/stdio.h /^#define putc(x, p) (--(p)->_cnt >= 0 ?\\$/ putchar ../sys/subr_prf.c /^putchar(c, flags, tp)$/ putchar /usr/include/stdio.h /^#define putchar(x) putc(x,stdout)$/ putdq ../sys/quota_kern.c /^putdq(mp, dq, free)$/ putmemc ../machine/mem.c /^putmemc(addr,contents)$/ putw ../sys/tty_subr.c /^putw(c, p)$/ q_to_b ../sys/tty_subr.c /^q_to_b(q, cp, cc)$/ qbaini ../pdpif/if_qe.c /^qbaini(ifuba, num)$/ qclean ../sys/quota_subr.c /^qclean()$/ qe_setaddr ../pdpif/if_qe.c /^qe_setaddr(physaddr, unit)$/ qeattach ../pdpif/if_qe.c /^qeattach(ui)$/ qefoo ../pdpif/if_qe.c /^static int qefoo()$/ qeinit ../pdpif/if_qe.c /^qeinit(unit)$/ qeinitdesc ../pdpif/if_qe.c /^qeinitdesc(rp, addr, len)$/ qeintr ../pdpif/if_qe.c /^qeintr(unit)$/ qeioctl ../pdpif/if_qe.c /^qeioctl(ifp, cmd, data)$/ qeoutput ../pdpif/if_qe.c /^qeoutput(ifp, m0, dst)$/ qeread ../pdpif/if_qe.c /^qeread(sc, ifuba, len)$/ qerestart ../pdpif/if_qe.c /^qerestart(sc)$/ qerint ../pdpif/if_qe.c /^qerint(unit)$/ qesetup ../pdpif/if_qe.c /^qesetup( sc )$/ qestart ../pdpif/if_qe.c /^qestart(dev)$/ qetint ../pdpif/if_qe.c /^qetint(unit)$/ qewatch ../pdpif/if_qe.c /^qewatch()$/ qfind ../sys/quota_kern.c /^qfind(uid)$/ qquota ../sys/quota_sys.c /^qquota()$/ qsetuid ../sys/quota_sys.c /^qsetuid(uid, noquota)$/ qstart ../sys/quota_subr.c /^qstart(q)$/ qsync ../sys/quota_sys.c /^qsync(dev)$/ qt_ns ../pdpif/if_qt.c /^qt_ns(cp)$/ qtattach ../pdpif/if_qt.c /^qtattach(ui)$/ qtfoo ../pdpif/if_qt.c /^static int qtfoo()$/ qtinit ../pdpif/if_qt.c /^qtinit(unit)$/ qtinit ../sys/quota_kern.c /^qtinit()$/ qtintr ../pdpif/if_qt.c /^qtintr(unit)$/ qtioctl ../pdpif/if_qt.c /^qtioctl(ifp, cmd, data)$/ qtoutput ../pdpif/if_qt.c /^qtoutput(ifp, m0, dst)$/ qtread ../pdpif/if_qt.c /^qtread(sc, ifuba, len)$/ qtrestart ../pdpif/if_qt.c /^qtrestart(sc)$/ qtrint ../pdpif/if_qt.c /^qtrint(unit)$/ qtsrr ../pdpif/if_qt.c /^qtsrr(unit, srrbits)$/ qtstart ../pdpif/if_qt.c /^qtstart(unit)$/ qttint ../pdpif/if_qt.c /^qttint(unit)$/ qtturbo ../pdpif/if_qt.c /^qtturbo(sc)$/ qwarn ../sys/quota_subr.c /^qwarn(dq)$/ raVec ../pdpuba/ra.c /^raVec(ctlr, vector)$/ ra_comT ../pdpuba/ra.c 250 ra_error ../pdpuba/ra.c /^ra_error(mp)$/ ra_softcT ../pdpuba/ra.c 272 raattach ../pdpuba/ra.c /^raattach(addr, unit)$/ racmd ../pdpuba/ra.c /^racmd(op, unit, sc)$/ radisksetup ../pdpuba/ra.c /^radisksetup(disk, mp)$/ radump ../pdpuba/ra.c /^radump(dev)$/ ragetcp ../pdpuba/ra.c /^ragetcp(sc)$/ ragetdd ../pdpuba/ra.c /^ragetdd()$/ rainit ../pdpuba/ra.c /^rainit(sc)$/ raintr ../pdpuba/ra.c /^raintr(unit)$/ raminit ../machine/ram.c /^raminit()$/ ramopen ../machine/ram.c /^ramopen(dev)$/ ramsgclear ../pdpuba/ra.c /^ramsgclear(mp)$/ ramsginit ../pdpuba/ra.c /^ramsginit(sc, com, msgs, offset, length, flags)$/ ramstart ../machine/ram.c /^ramstart(ramaddr, bp)$/ ramstrategy ../machine/ram.c /^ramstrategy(bp)$/ raopen ../pdpuba/ra.c /^raopen(dev, flag)$/ raroot ../pdpuba/ra.c /^raroot(csr)$/ rarsp ../pdpuba/ra.c /^rarsp(mp, sc)$/ rarspring ../pdpuba/ra.c /^rarspring(sc)$/ rasize ../pdpuba/ra.c /^rasize(dev)$/ rastart ../pdpuba/ra.c /^rastart(sc)$/ rastrategy ../pdpuba/ra.c /^rastrategy(bp)$/ raw /usr/include/curses.h /^#define raw() (_tty.sg_flags|=RAW, _pfast=_rawmod/ raw_attach ../net/raw_cb.c /^raw_attach(so, proto)$/ raw_bind ../net/raw_cb.c /^raw_bind(so, nam)$/ raw_connaddr ../net/raw_cb.c /^raw_connaddr(rp, nam)$/ raw_ctlinput ../net/raw_usrreq.c /^raw_ctlinput(cmd, arg)$/ raw_detach ../net/raw_cb.c /^raw_detach(rp)$/ raw_disconnect ../net/raw_cb.c /^raw_disconnect(rp)$/ raw_init ../net/raw_usrreq.c /^raw_init()$/ raw_input ../net/raw_usrreq.c /^raw_input(m0, proto, src, dst)$/ raw_usrreq ../net/raw_usrreq.c /^raw_usrreq(so, req, m, nam, rights)$/ rawintr ../net/raw_usrreq.c /^rawintr()$/ rawrw ../sys/vm_swp.c /^rawrw(dev, uio, flag)$/ rdwri ../sys/sys_inode.c /^rdwri(rw, ip, base, len, offset, segflg, ioflg, ar/ read ../sys/sys_generic.c /^read()$/ readdisklabel ../sys/ufs_disksubr.c /^readdisklabel(dev, strat, lp)$/ readlink ../sys/ufs_syscalls.c /^readlink()$/ readp ../sys/sys_pipe.c /^readp(fp, uio, flag)$/ readv ../sys/sys_generic.c /^readv()$/ reboot ../sys/kern_xxx.c /^reboot()$/ recv ../sys/uipc_syscalls.c /^recv()$/ recvfrom ../sys/uipc_syscalls.c /^recvfrom()$/ recvit ../sys/uipc_syscalls.c /^recvit(s, mp, flags, namelenp, rightslenp)$/ recvmsg ../sys/uipc_syscalls.c /^recvmsg()$/ refresh /usr/include/curses.h /^# define refresh() VOID(wrefresh(stdscr))$/ remque ../h/systm.h /^#define remque(q) _remque((caddr_t)q)$/ remque ../machine/libc_remque.s /^ENTRY(remque)$/ remrq ../sys/kern_synch.c /^remrq(p)$/ rename ../sys/ufs_syscalls.c /^rename()$/ resetty /usr/include/curses.h /^#define resetty() (_tty.sg_flags = _res_flg, (void/ restfp ../machine/mch_xxx.s /^ENTRY(restfp)$/ restormap ../machine/mch_xxx.s /^ENTRY(restormap)$/ restorseg5 ../machine/seg.h /^#define restorseg5(save) { \\$/ resume ../machine/mch_xxx.s /^ENTRY(resume)$/ rewinddir ../h/dir.h /^#define rewinddir(dirp) seekdir((dirp), (long)0)$/ rexit ../sys/kern_exit.c /^rexit()$/ rimp_output ../netimp/raw_imp.c /^rimp_output(m, so)$/ rip_ctloutput ../netinet/raw_ip.c /^rip_ctloutput(op, so, level, optname, m)$/ rip_input ../netinet/raw_ip.c /^rip_input(m)$/ rip_output ../netinet/raw_ip.c /^rip_output(m, so)$/ rkattach ../pdpuba/rk.c /^rkattach(addr, unit)$/ rkintr ../pdpuba/rk.c /^rkintr()$/ rkopen ../pdpuba/rk.c /^rkopen(dev, flag)$/ rksize ../pdpuba/rk.c /^rksize(dev)$/ rkstart ../pdpuba/rk.c /^rkstart()$/ rkstrategy ../pdpuba/rk.c /^rkstrategy(bp)$/ rkunit ../pdpuba/rk.c /^#define rkunit(dev) minor(dev)$/ rlattach ../pdpuba/rl.c /^rlattach(addr, unit)$/ rldump ../pdpuba/rl.c /^rldump(dev)$/ rlfh ../pdpuba/rl.c /^rlfh(dev)$/ rlgss ../pdpuba/rl.c /^rlgss()$/ rlgsts ../pdpuba/rl.c /^rlgsts(drive)$/ rlintr ../pdpuba/rl.c /^rlintr()$/ rlio ../pdpuba/rl.c /^rlio()$/ rlopen ../pdpuba/rl.c /^rlopen(dev, flag)$/ rlroot ../pdpuba/rl.c /^rlroot()$/ rlseek ../pdpuba/rl.c /^rlseek(cyl, dev)$/ rlsize ../pdpuba/rl.c /^rlsize(dev)$/ rlstart ../pdpuba/rl.c /^rlstart()$/ rlstrategy ../pdpuba/rl.c /^rlstrategy(bp)$/ rlwait ../pdpuba/rl.c /^#define rlwait(r) while (((r)->rlcs & RL_CRDY) == / rmdir ../sys/ufs_syscalls.c /^rmdir()$/ roundup ../h/param.h /^#define roundup(x, y) ((((x)+((y)-1))\/(y))*(y))$/ rtalloc ../net/route.c /^rtalloc(ro)$/ rtfree ../net/route.c /^rtfree(rt)$/ rtinit ../net/route.c /^rtinit(dst, gateway, cmd, flags)$/ rtioctl ../net/route.c /^rtioctl(cmd, data)$/ rtredirect ../net/route.c /^rtredirect(dst, gateway, flags, src)$/ rtrequest ../net/route.c /^rtrequest(req, entry)$/ ruadd ../sys/kern_resource.c /^ruadd(ru, ru2)$/ rucvt ../sys/kern_resource.c /^rucvt(rup, krup)$/ rwip ../sys/sys_inode.c /^rwip(ip, uio, ioflag)$/ rwuio ../sys/sys_generic.c /^rwuio(uio)$/ rxaddr ../pdpuba/rx.c /^rxaddr(bp, addr, xmem)$/ rxattach ../pdpuba/rx.c /^rxattach(addr, unit)$/ rxfactr ../pdpuba/rx.c /^rxfactr(sectr, psectr, ptrck)$/ rxintr ../pdpuba/rx.c /^rxintr()$/ rxioctl ../pdpuba/rx.c /^rxioctl(dev, cmd, addr, flag)$/ rxopen ../pdpuba/rx.c /^rxopen(dev, flag)$/ rxstart ../pdpuba/rx.c /^rxstart()$/ rxstrategy ../pdpuba/rx.c /^rxstrategy(bp)$/ rxwait ../pdpuba/rx.c /^#define rxwait() while (((RXADDR->rxcs) & RX_XREQ)/ saccess ../sys/ufs_syscalls.c /^saccess()$/ satons_addr ../netns/ns.h /^#define satons_addr(sa) (((struct sockaddr_ns *)&(/ save_rte ../netinet/ip_input.c /^save_rte(option, dst)$/ savemap ../machine/mch_xxx.s /^ENTRY(savemap)$/ savemap ../machine/seg.h /^* or the u. must call savemap (in machdep.c) to sa/ saveregs ../machine/mch_dump.s /^ENTRY(saveregs)$/ saveseg5 ../machine/seg.h /^#define saveseg5(save) { \\$/ savestate ../machine/mch_dump.s /^ENTRY(savestate)$/ savetty /usr/include/curses.h /^#define savetty() ((void) gtty(_tty_ch, &_tty), _r/ savfp ../machine/mch_xxx.s /^ENTRY(savfp)$/ sballoc ../h/socketvar.h /^#define sballoc(sb, m) { \\$/ sbappend ../sys/uipc_socket2.c /^sbappend(sb, m)$/ sbappendaddr ../sys/uipc_socket2.c /^sbappendaddr(sb, asa, m0, rights0)$/ sbappendrecord ../sys/uipc_socket2.c /^sbappendrecord(sb, m0)$/ sbappendrights ../sys/uipc_socket2.c /^sbappendrights(sb, m0, rights)$/ sbcompress ../sys/uipc_socket2.c /^sbcompress(sb, m, n)$/ sbdrop ../sys/uipc_socket2.c /^sbdrop(sb, len)$/ sbdroprecord ../sys/uipc_socket2.c /^sbdroprecord(sb)$/ sbflush ../sys/uipc_socket2.c /^sbflush(sb)$/ sbfree ../h/socketvar.h /^#define sbfree(sb, m) { \\$/ sblock ../h/socketvar.h /^#define sblock(sb) { \\$/ sbrelease ../sys/uipc_socket2.c /^sbrelease(sb)$/ sbreserve ../sys/uipc_socket2.c /^sbreserve(sb, cc)$/ sbrk ../sys/kern_mman.c /^sbrk()$/ sbselqueue ../sys/uipc_socket2.c /^sbselqueue(sb)$/ sbspace ../h/socketvar.h /^#define sbspace(sb) \\$/ sbunlock ../h/socketvar.h /^#define sbunlock(sb) { \\$/ sbwait ../sys/uipc_socket2.c /^sbwait(sb)$/ sbwakeup ../sys/uipc_socket2.c /^sbwakeup(sb)$/ scanc ../machine/mch_xxx.s /^ENTRY(scanc)$/ scanc ../sys/ufs_subr.c /^scanc(size, cp, table, mask)$/ sched ../sys/vm_sched.c /^sched()$/ schedcpu ../sys/kern_synch.c /^schedcpu()$/ schednetisr ../net/netisr.h /^#define schednetisr(anisr) { netisr |= 1<<(anisr);/ scrollok /usr/include/curses.h /^#define scrollok(win,bf) (win->_scroll = bf)$/ seccnt ../pdpuba/rx.c /^#define seccnt(bp) ((int)((bp)->b_seccnt))$/ segm ../machine/seg.h 126 select ../sys/sys_generic.c /^select()$/ selscan ../sys/sys_generic.c /^selscan(ibits, obits, nfd)$/ seltrue ../sys/sys_generic.c /^seltrue(dev, flag)$/ selwakeup ../sys/sys_generic.c /^selwakeup(p, coll)$/ send ../sys/uipc_syscalls.c /^send()$/ sendit ../sys/uipc_syscalls.c /^sendit(s, mp, flags)$/ sendmsg ../sys/uipc_syscalls.c /^sendmsg()$/ sendsig ../machine/machdep.c /^sendsig(p, sig, mask)$/ sendto ../sys/uipc_syscalls.c /^sendto()$/ setdisklabel ../sys/ufs_disksubr.c /^setdisklabel(olp, nlp, openmask)$/ setdlim ../sys/quota_sys.c /^setdlim(q, dev, addr)$/ setduse ../sys/quota_sys.c /^setduse(q, dev, addr)$/ setgroups ../sys/kern_prot.c /^setgroups()$/ sethostid ../sys/kern_xxx.c /^sethostid()$/ sethostname ../sys/kern_xxx.c /^sethostname()$/ setitimer ../sys/kern_time.c /^setitimer()$/ setjmp ../machine/mch_xxx.s /^ENTRY(setjmp)$/ setpgrp ../sys/kern_prot.c /^setpgrp()$/ setpri ../sys/kern_synch.c /^setpri(pp)$/ setpriority ../sys/kern_resource.c /^setpriority()$/ setquota ../sys/quota_sys.c /^setquota()$/ setregid ../sys/kern_prot.c /^setregid()$/ setregs ../machine/machdep.c /^setregs(entry)$/ setreuid ../sys/kern_prot.c /^setreuid()$/ setrlimit ../sys/kern_resource.c /^setrlimit()$/ setrq ../sys/kern_synch.c /^setrq(p)$/ setrun ../sys/kern_synch.c /^setrun(p)$/ setsigvec ../sys/kern_sig.c /^setsigvec(sig, sv)$/ setsockopt ../sys/uipc_syscalls.c /^setsockopt()$/ setsoftnet ../net/netisr.h /^#define setsoftnet() mtpr(SIRR, 12)$/ setthetime ../sys/kern_time.c /^setthetime(tv)$/ settimeofday ../sys/kern_time.c /^settimeofday()$/ setubregno ../h/uba.h /^#define setubregno(r,p) { \\$/ setwarn ../sys/quota_sys.c /^setwarn(q, dev, addr)$/ shfree /usr/include/mp.h /^#define shfree(u) free((char *)u)$/ short ../h/types.h 26 shutdown ../sys/uipc_syscalls.c /^shutdown()$/ siattach ../pdpuba/si.c /^siattach(addr, unit)$/ sidump ../pdpuba/si.c /^sidump(dev)$/ sigblock ../sys/kern_sig.c /^sigblock()$/ sigmask ../h/signal.h /^#define sigmask(m) ((long)1 << ((m)-1))$/ sigmask /usr/include/signal.h /^#define sigmask(m) ((long)1 << ((m)-1))$/ signal ../h/signal.h /^int (*signal())();$/ signal /usr/include/signal.h /^int (*signal())();$/ sigpause ../sys/kern_sig.c /^sigpause()$/ sigreturn ../machine/machdep.c /^sigreturn()$/ sigsetmask ../sys/kern_sig.c /^sigsetmask()$/ sigstack ../sys/kern_sig.c /^sigstack()$/ sigvec ../sys/kern_sig.c /^sigvec()$/ siintr ../pdpuba/si.c /^siintr()$/ siopen ../pdpuba/si.c /^siopen(dev, flag)$/ siroot ../pdpuba/si.c /^siroot()$/ sisize ../pdpuba/si.c /^sisize(dev)$/ sistart ../pdpuba/si.c /^sistart()$/ sistrategy ../pdpuba/si.c /^sistrategy(bp)$/ siustart ../pdpuba/si.c /^siustart(unit)$/ size_t ../h/types.h 42 sizeof ../machine/conf.c /^int nblkdev = sizeof(bdevsw) \/ sizeof(bdevsw[0]);$/ sizeof ../netinet/udp_usrreq.c /^int udp_recvspace = 4 * (1024+sizeof(struct sockad/ sizeof ../pdpuba/ts.c /^u_short softspace[NTS][(sizeof(struct ts_softc)\/2)/ sizeof ../sys/init_sysent.c /^int nsysent = sizeof (sysent) \/ sizeof (sysent[0])/ sl_btom ../net/if_sl.c /^sl_btom(sc, len, ifp)$/ slattach ../net/if_sl.c /^slattach()$/ slclose ../net/if_sl.c /^slclose(tp)$/ sleep ../sys/kern_synch.c /^sleep(chan, pri)$/ slinit ../net/if_sl.c /^slinit(sc)$/ slinput ../net/if_sl.c /^slinput(c, tp)$/ slioctl ../net/if_sl.c /^slioctl(ifp, cmd, data)$/ slopen ../net/if_sl.c /^slopen(dev, tp)$/ sloutput ../net/if_sl.c /^sloutput(ifp, m, dst)$/ slstart ../net/if_sl.c /^slstart(tp)$/ sltioctl ../net/if_sl.c /^sltioctl(tp, cmd, data, flag)$/ smount ../sys/ufs_mount.c /^smount()$/ soabort ../sys/uipc_socket.c /^soabort(so)$/ soacc1 ../sys/uipc_socket.c /^soacc1(so)$/ soaccept ../sys/uipc_socket.c /^soaccept(so, nam)$/ sobind ../sys/uipc_socket.c /^sobind(so, nam)$/ socantrcvmore ../sys/uipc_socket2.c /^socantrcvmore(so)$/ socantsendmore ../sys/uipc_socket2.c /^socantsendmore(so)$/ sockargs ../sys/uipc_syscalls.c /^sockargs(aname, name, namelen, type)$/ socket ../sys/uipc_syscalls.c /^socket()$/ socketpair ../sys/uipc_syscalls.c /^socketpair()$/ soclose ../sys/uipc_socket.c /^soclose(so)$/ socls ../sys/sys_generic.c /^socls(fp)$/ soconnect ../sys/uipc_socket.c /^soconnect(so, nam)$/ soconnect2 ../sys/uipc_socket.c /^soconnect2(so1, so2)$/ socreate ../sys/uipc_socket.c /^socreate(dom, aso, type, proto)$/ soctl ../sys/sys_generic.c /^soctl(fp, com, data)$/ sodisconnect ../sys/uipc_socket.c /^sodisconnect(so)$/ sofree ../sys/uipc_socket.c /^sofree(so)$/ softclock ../sys/kern_clock.c /^softclock(pc, ps)$/ sogetnam ../sys/uipc_socket.c /^sogetnam(so, m)$/ sogetopt ../sys/uipc_socket.c /^sogetopt(so, level, optname, mp)$/ sogetpeer ../sys/uipc_socket.c /^sogetpeer(so, m)$/ sohasoutofband ../sys/uipc_socket.c /^sohasoutofband(so)$/ soisconnected ../sys/uipc_socket2.c /^soisconnected(so)$/ soisconnecting ../sys/uipc_socket2.c /^soisconnecting(so)$/ soisdisconnected ../sys/uipc_socket2.c /^soisdisconnected(so)$/ soisdisconnecting ../sys/uipc_socket2.c /^soisdisconnecting(so)$/ solisten ../sys/uipc_socket.c /^solisten(so, backlog)$/ sonewconn ../sys/uipc_socket2.c /^sonewconn(head)$/ soo_ioctl ../sys/sys_socket.c /^soo_ioctl(so, cmd, data)$/ soo_select ../sys/sys_socket.c /^soo_select(so, which)$/ soo_stat ../sys/sys_socket.c /^soo_stat(so, ub)$/ soqinsque ../sys/uipc_socket2.c /^soqinsque(head, so, q)$/ soqremque ../sys/uipc_socket2.c /^soqremque(so, q)$/ soreadable ../h/socketvar.h /^#define soreadable(so) \\$/ soreceive ../sys/uipc_socket.c /^soreceive(so, aname, uio, flags, rightsp)$/ soreserve ../sys/uipc_socket2.c /^soreserve(so, sndcc, rcvcc)$/ sorflush ../sys/uipc_socket.c /^sorflush(so)$/ sorw ../sys/sys_generic.c /^sorw(fp, uio)$/ sorwakeup ../h/socketvar.h /^#define sorwakeup(so) sowakeup((so), &(so)->so_rcv/ sosel ../sys/sys_generic.c /^sosel(fp, flag)$/ sosend ../sys/uipc_socket.c /^sosend(so, nam, uio, flags, rights)$/ sosendallatonce ../h/socketvar.h /^#define sosendallatonce(so) \\$/ sosetopt ../sys/uipc_socket.c /^sosetopt(so, level, optname, m0)$/ soshutdown ../sys/uipc_socket.c /^soshutdown(so, how)$/ sotoinpcb ../netinet/in_pcb.h /^#define sotoinpcb(so) ((struct inpcb *)(so)->so_pc/ sotonspcb ../netns/ns_pcb.h /^#define sotonspcb(so) ((struct nspcb *)((so)->so_/ sotorawcb ../net/raw_cb.h /^#define sotorawcb(so) ((struct rawcb *)(so)->so_p/ sotosppcb ../netns/spp_var.h /^#define sotosppcb(so) (nstosppcb(sotonspcb(so)))$/ sototcpcb ../netinet/tcp_var.h /^#define sototcpcb(so) (intotcpcb(sotoinpcb(so)))$/ sotounpcb ../h/unpcb.h /^#define sotounpcb(so) ((struct unpcb *)((so)->so_p/ sowakeup ../sys/uipc_socket2.c /^sowakeup(so, sb)$/ sowriteable ../h/socketvar.h /^#define sowriteable(so) \\$/ sowwakeup ../h/socketvar.h /^#define sowwakeup(so) sowakeup((so), &(so)->so_snd/ spgrp ../sys/kern_proc.c /^spgrp(top)$/ spl_enet ../pdpif/if_enreg.h /^#define spl_enet() spl5()$/ splx ../machine/machparam.h /^#define splx(ops) (*PS_LOBYTE = ((char)(ops)))$/ spp_abort ../netns/spp_usrreq.c /^spp_abort(nsp)$/ spp_close ../netns/spp_usrreq.c /^spp_close(cb)$/ spp_ctlinput ../netns/spp_usrreq.c /^spp_ctlinput(cmd, arg)$/ spp_ctloutput ../netns/spp_usrreq.c /^spp_ctloutput(req, so, level, name, value)$/ spp_disconnect ../netns/spp_usrreq.c /^spp_disconnect(cb)$/ spp_drop ../netns/spp_usrreq.c /^spp_drop(cb, errno)$/ spp_fasttimo ../netns/spp_usrreq.c /^spp_fasttimo()$/ spp_fixmtu ../netns/spp_usrreq.c /^spp_fixmtu(nsp)$/ spp_init ../netns/spp_usrreq.c /^spp_init()$/ spp_input ../netns/spp_usrreq.c /^spp_input(m, nsp, ifp)$/ spp_output ../netns/spp_usrreq.c /^spp_output(cb, m0)$/ spp_quench ../netns/spp_usrreq.c /^spp_quench(nsp)$/ spp_reass ../netns/spp_usrreq.c /^spp_reass(cb, si)$/ spp_setpersist ../netns/spp_usrreq.c /^spp_setpersist(cb)$/ spp_slowtimo ../netns/spp_usrreq.c /^spp_slowtimo()$/ spp_template ../netns/spp_usrreq.c /^spp_template(cb)$/ spp_timers ../netns/spp_usrreq.c /^spp_timers(cb, timer)$/ spp_trace ../netns/spp_debug.c /^spp_trace(act, ostate, sp, si, req)$/ spp_usrclosed ../netns/spp_usrreq.c /^spp_usrclosed(cb)$/ spp_usrreq ../netns/spp_usrreq.c /^spp_usrreq(so, req, m, nam, rights)$/ spp_usrreq_sp ../netns/spp_usrreq.c /^spp_usrreq_sp(so, req, m, nam, rights)$/ sprof ../machine/mch_profile.s /^ENTRY(sprof)$/ sriattach ../pdpif/if_sri.c /^sriattach(ui)$/ sridebug ../pdpif/if_sri.c /^sridebug()$/ sridump ../pdpif/if_sri.c /^sridump(str,aba,abc)$/ sriinit ../pdpif/if_sri.c /^sriinit(unit)$/ sriprobe ../pdpif/if_sri.c /^sriprobe(reg)$/ srireset ../pdpif/if_sri.c /^srireset(unit, uban)$/ srirint ../pdpif/if_sri.c /^srirint(unit)$/ sristart ../pdpif/if_sri.c /^sristart(dev)$/ srixint ../pdpif/if_sri.c /^srixint(unit)$/ stackbas ../machine/machparam.h /^#define stackbas(siz) (0x10000L-(siz))$/ stacktop ../machine/machparam.h /^#define stacktop(siz) (0x10000L)$/ standend /usr/include/curses.h /^# define standend() VOID(wstandend(stdscr))$/ standout /usr/include/curses.h /^# define standout() VOID(wstandout(stdscr))$/ start ../machine/mch_start.s /^ASENTRY(start)$/ startup ../machine/machdep2.c /^startup()$/ stat ../sys/ufs_syscalls.c /^stat()$/ stat1 ../sys/ufs_syscalls.c /^stat1(follow)$/ stoc ../machine/machparam.h /^#define stoc(x) ((x)*128)$/ stop ../sys/kern_sig.c /^stop(p)$/ strbase /usr/include/struct.h /^#define strbase(str, ptr, fld) ((struct str *)((ch/ strlen ../machine/libc_strlen.s /^ENTRY(strlen)$/ stst ../machine/mch_xxx.s /^ENTRY(stst)$/ subyte ../machine/mch_copy.s /^ENTRY(subyte)$/ subyte ../machine/net_copy.s /^ENTRY(subyte)$/ suibyte ../machine/mch_copy.s /^ENTRY(suibyte)$/ suiword ../machine/mch_copy.s /^ENTRY(suiword)$/ sureg ../sys/kern_mman.c /^sureg()$/ suser ../sys/sys_net.c /^suser()$/ suword ../machine/mch_copy.s /^ENTRY(suword)$/ suword ../machine/net_copy.s /^ENTRY(suword)$/ swap ../sys/vm_swp.c /^swap(blkno, coreaddr, count, rdflg)$/ swapin ../sys/vm_swap.c /^swapin(p)$/ swapout ../sys/vm_swap.c /^swapout(p, freecore, odata, ostack)$/ swblk_t ../h/types.h 41 swkill ../sys/vm_swp.c /^swkill(p, rout)$/ swtch ../sys/kern_synch.c /^swtch()$/ syioctl ../sys/tty_tty.c /^syioctl(dev, cmd, addr, flag)$/ symlink ../sys/ufs_syscalls.c /^symlink()$/ sync ../sys/ufs_syscalls.c /^sync()$/ syncip ../sys/ufs_subr.c /^syncip(ip)$/ syopen ../sys/tty_tty.c /^syopen(dev, flag)$/ syread ../sys/tty_tty.c /^syread(dev, uio, flag)$/ sysacct ../sys/kern_acct.c /^sysacct()$/ syscall ../machine/mch_trap.s /^ASENTRY(syscall)$/ syscall ../machine/trap.c /^syscall(dev, sp, r1, ov, nps, r0, pc, ps)$/ sysctl_clockrate ../sys/kern_sysctl.c /^sysctl_clockrate(where, sizep)$/ sysctl_doproc ../sys/kern_sysctl.c /^sysctl_doproc(name, namelen, where, sizep)$/ sysctl_file ../sys/kern_sysctl.c /^sysctl_file(where, sizep)$/ sysctl_inode ../sys/kern_sysctl.c /^sysctl_inode(where, sizep)$/ sysctl_int ../sys/kern_sysctl.c /^sysctl_int(oldp, oldlenp, newp, newlen, valp)$/ sysctl_long ../sys/kern_sysctl.c /^sysctl_long(oldp, oldlenp, newp, newlen, valp)$/ sysctl_rdint ../sys/kern_sysctl.c /^sysctl_rdint(oldp, oldlenp, newp, val)$/ sysctl_rdlong ../sys/kern_sysctl.c /^sysctl_rdlong(oldp, oldlenp, newp, val)$/ sysctl_rdstring ../sys/kern_sysctl.c /^sysctl_rdstring(oldp, oldlenp, newp, str)$/ sysctl_rdstruct ../sys/kern_sysctl.c /^sysctl_rdstruct(oldp, oldlenp, newp, sp, len)$/ sysctl_string ../sys/kern_sysctl.c /^sysctl_string(oldp, oldlenp, newp, newlen, str, ma/ sysctl_struct ../sys/kern_sysctl.c /^sysctl_struct(oldp, oldlenp, newp, newlen, sp, len/ sysctl_text ../sys/kern_sysctl.c /^sysctl_text(where, sizep)$/ sysctlfn ../h/sysctl.h 272 syselect ../sys/tty_tty.c /^syselect(dev, flag)$/ sywrite ../sys/tty_tty.c /^sywrite(dev, uio, flag)$/ tablefull ../sys/subr_prf.c /^tablefull(tab)$/ tbclose ../sys/tty_tb.c /^tbclose(tp, flag)$/ tbdecode ../sys/tty_tb.c /^tbdecode(cp, tbpos)$/ tbhresdecode ../sys/tty_tb.c /^tbhresdecode(cp, tbpos)$/ tbinput ../sys/tty_tb.c /^tbinput(c, tp)$/ tbioctl ../sys/tty_tb.c /^tbioctl(tp, cmd, data, flag)$/ tblresdecode ../sys/tty_tb.c /^tblresdecode(cp, tbpos)$/ tbopen ../sys/tty_tb.c /^tbopen(dev, tp)$/ tbread ../sys/tty_tb.c /^tbread(tp, uio, flag)$/ tcp_attach ../netinet/tcp_usrreq.c /^tcp_attach(so)$/ tcp_canceltimers ../netinet/tcp_timer.c /^tcp_canceltimers(tp)$/ tcp_close ../netinet/tcp_subr.c /^tcp_close(tp)$/ tcp_ctlinput ../netinet/tcp_subr.c /^tcp_ctlinput(cmd, sa, ip)$/ tcp_ctloutput ../netinet/tcp_usrreq.c /^tcp_ctloutput(op, so, level, optname, mp)$/ tcp_disconnect ../netinet/tcp_usrreq.c /^tcp_disconnect(tp)$/ tcp_dooptions ../netinet/tcp_input.c /^tcp_dooptions(tp, om, ti)$/ tcp_drain ../netinet/tcp_subr.c /^tcp_drain()$/ tcp_drop ../netinet/tcp_subr.c /^tcp_drop(tp, errno)$/ tcp_fasttimo ../netinet/tcp_timer.c /^tcp_fasttimo()$/ tcp_init ../netinet/tcp_subr.c /^tcp_init()$/ tcp_input ../netinet/tcp_input.c /^tcp_input(m0)$/ tcp_mss ../netinet/tcp_input.c /^tcp_mss(tp)$/ tcp_newtcpcb ../netinet/tcp_subr.c /^tcp_newtcpcb(inp)$/ tcp_notify ../netinet/tcp_subr.c /^tcp_notify(inp, error)$/ tcp_output ../netinet/tcp_output.c /^tcp_output(tp)$/ tcp_pulloutofband ../netinet/tcp_input.c /^tcp_pulloutofband(so, ti)$/ tcp_quench ../netinet/tcp_subr.c /^tcp_quench(inp)$/ tcp_rcvseqinit ../netinet/tcp_seq.h /^#define tcp_rcvseqinit(tp) \\$/ tcp_reass ../netinet/tcp_input.c /^tcp_reass(tp, ti)$/ tcp_respond ../netinet/tcp_subr.c /^tcp_respond(tp, ti, ack, seq, flags)$/ tcp_sendseqinit ../netinet/tcp_seq.h /^#define tcp_sendseqinit(tp) \\$/ tcp_seq ../netinet/tcp.h 34 tcp_setpersist ../netinet/tcp_output.c /^tcp_setpersist(tp)$/ tcp_slowtimo ../netinet/tcp_timer.c /^tcp_slowtimo()$/ tcp_template ../netinet/tcp_subr.c /^tcp_template(tp)$/ tcp_timers ../netinet/tcp_timer.c /^tcp_timers(tp, timer)$/ tcp_trace ../netinet/tcp_debug.c /^tcp_trace(act, ostate, tp, ti, req)$/ tcp_usrclosed ../netinet/tcp_usrreq.c /^tcp_usrclosed(tp)$/ tcp_usrreq ../netinet/tcp_usrreq.c /^tcp_usrreq(so, req, m, nam, rights)$/ time_t ../h/types.h 43 timeout ../sys/kern_clock.c /^timeout(fun, arg, t)$/ timerclear ../h/time.h /^#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv/ timercmp ../h/time.h /^#define timercmp(tvp, uvp, cmp) \\$/ timerisset ../h/time.h /^#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->/ timevaladd ../sys/kern_time.c /^timevaladd(t1, t2)$/ timevalfix ../sys/kern_time.c /^timevalfix(t1)$/ timevalsub ../sys/kern_time.c /^timevalsub(t1, t2)$/ tkini ../pdpuba/tmscp.c /^tkini(sc)$/ tmattach ../pdpuba/tm.c /^tmattach(addr, unit)$/ tmclose ../pdpuba/tm.c /^tmclose(dev, flag)$/ tmcommand ../pdpuba/tm.c /^tmcommand(dev, com, count)$/ tmintr ../pdpuba/tm.c /^tmintr()$/ tmioctl ../pdpuba/tm.c /^tmioctl(dev, cmd, data, flag)$/ tmopen ../pdpuba/tm.c /^tmopen(dev, flag)$/ tmsVec ../pdpuba/tmscp.c /^tmsVec(ctlr, vector)$/ tmsattach ../pdpuba/tmscp.c /^tmsattach(addr, unit)$/ tmscpclose ../pdpuba/tmscp.c /^tmscpclose(dev, flag)$/ tmscpcmd ../pdpuba/tmscp.c /^tmscpcmd(op, unit, sc)$/ tmscpcommand ../pdpuba/tmscp.c /^tmscpcommand(dev, com, count)$/ tmscpgetcp ../pdpuba/tmscp.c /^tmscpgetcp(sc)$/ tmscpioctl ../pdpuba/tmscp.c /^tmscpioctl(dev, cmd, data, flag)$/ tmscpopen ../pdpuba/tmscp.c /^tmscpopen(dev, flag)$/ tmscprsp ../pdpuba/tmscp.c /^tmscprsp(sc, i)$/ tmscpstrategy ../pdpuba/tmscp.c /^tmscpstrategy (bp)$/ tmsdump ../pdpuba/tmscp.c /^tmsdump(dev)$/ tmserror ../pdpuba/tmscp.c /^tmserror(ctlr, mp)$/ tmseteof ../pdpuba/tm.c /^tmseteof(bp)$/ tmsginit ../pdpuba/tmscp.c /^tmsginit(sc, com, msgs, offset, length, flags)$/ tmsintr ../pdpuba/tmscp.c /^tmsintr(dev)$/ tmsstart ../pdpuba/tmscp.c /^tmsstart(sc)$/ tmstart ../pdpuba/tm.c /^tmstart()$/ tmstrategy ../pdpuba/tm.c /^tmstrategy(bp)$/ tmtimer ../pdpuba/tm.c /^tmtimer(dev)$/ toascii /usr/include/ctype.h /^#define toascii(c) ((c)&0177)$/ tolower /usr/include/ctype.h /^#define tolower(c) ((c)-'A'+'a')$/ toupper /usr/include/ctype.h /^#define toupper(c) ((c)-'a'+'A')$/ tprintf ../sys/subr_prf.c /^tprintf(tp, fmt, x1)$/ trace ../h/trace.h /^#define trace(a) tracebuf[a]++;$/ trap ../machine/mch_trap.s /^ASENTRY(trap)$/ trap ../machine/trap.c /^trap(dev, sp, r1, ov, nps, r0, pc, ps)$/ trsingle ../sys/ufs_inode.c /^trsingle(ip, bp,last)$/ truncate ../sys/ufs_syscalls.c /^truncate()$/ tsattach ../pdpuba/ts.c /^tsattach(addr, unit)$/ tsclose ../pdpuba/ts.c /^tsclose(dev, flag)$/ tscommand ../pdpuba/ts.c /^tscommand(dev, com, count)$/ tsinit ../pdpuba/ts.c /^tsinit(ts11)$/ tsintr ../pdpuba/ts.c /^tsintr(dev)$/ tsioctl ../pdpuba/ts.c /^tsioctl(dev, cmd, data, flag)$/ tsopen ../pdpuba/ts.c /^tsopen(dev, flag)$/ tsseteof ../pdpuba/ts.c /^tsseteof(bp)$/ tsstart ../pdpuba/ts.c /^tsstart(ts11)$/ tsstrategy ../pdpuba/ts.c /^tsstrategy(bp)$/ ttbreakc ../sys/tty.c /^ttbreakc(c, tp)$/ ttioctl ../sys/tty.c /^ttioctl(tp, com, data, flag)$/ ttnread ../sys/tty.c /^ttnread(tp)$/ ttread ../sys/tty.c /^ttread(tp, uio, flag)$/ ttrstrt ../sys/tty.c /^ttrstrt(tp)$/ ttselect ../sys/tty.c /^ttselect(dev, rw)$/ ttstart ../sys/tty.c /^ttstart(tp)$/ ttwakeup ../sys/tty.c /^ttwakeup(tp)$/ ttwrite ../sys/tty.c /^ttwrite(tp, uio, flag)$/ ttyblock ../sys/tty.c /^ttyblock(tp)$/ ttychars ../sys/tty.c /^ttychars(tp)$/ ttycheckoutq ../sys/tty.c /^ttycheckoutq(tp, wait)$/ ttyclose ../sys/tty.c /^ttyclose(tp)$/ ttyecho ../sys/tty.c /^ttyecho(c, tp)$/ ttyflush ../sys/tty.c /^ttyflush(tp, rw)$/ ttyinput ../sys/tty.c /^ttyinput(c, tp)$/ ttylclose ../sys/tty.c /^ttylclose(tp, flag)$/ ttymodem ../sys/tty.c /^ttymodem(tp, flag)$/ ttyopen ../sys/tty.c /^ttyopen(dev, tp)$/ ttyout ../sys/tty.c /^ttyout(cp, tp)$/ ttyoutput ../sys/tty.c /^ttyoutput(c, tp)$/ ttypend ../sys/tty.c /^ttypend(tp)$/ ttyretype ../sys/tty.c /^ttyretype(tp)$/ ttyrub ../sys/tty.c /^ttyrub(c, tp)$/ ttyrubo ../sys/tty.c /^ttyrubo(tp, cnt)$/ ttywait ../sys/tty.c /^ttywait(tp)$/ ttywflush ../sys/tty.c /^ttywflush(tp)$/ u_char ../h/types.h 25 u_int ../h/types.h 27 u_long ../h/types.h 28 u_short ../h/types.h 26 ualdiv ../machine/libc_uldiv.s /^ENTRY(ualdiv)$/ ualsh ../machine/libc_ulsh.s /^ENTRY(ualsh)$/ ubadr_t ../h/types.h 79 uballoc ../pdpif/if_uba.c /^uballoc(addr, size)$/ ubarelse ../pdpif/if_uba.h /^#define ubarelse(a,b)$/ ubarelse ../pdpuba/ubavar.h /^#define ubarelse(a,b)$/ ubinit ../machine/machdep2.c /^ubinit()$/ ubmalloc ../pdpif/if_uba.c /^ubmalloc(addr)$/ ucall ../machine/kern_pdp.c /^ucall()$/ udiv ../machine/libc_udiv.s /^ASENTRY(udiv)$/ udp_ctlinput ../netinet/udp_usrreq.c /^udp_ctlinput(cmd, sa, ip)$/ udp_detach ../netinet/udp_usrreq.c /^udp_detach(inp)$/ udp_init ../netinet/udp_usrreq.c /^udp_init()$/ udp_input ../netinet/udp_usrreq.c /^udp_input(m0, ifp)$/ udp_notify ../netinet/udp_usrreq.c /^udp_notify(inp, errno)$/ udp_output ../netinet/udp_usrreq.c /^udp_output(inp, m0, addr, control)$/ udp_usrreq ../netinet/udp_usrreq.c /^udp_usrreq(so, req, m, nam, rights)$/ ufalloc ../sys/kern_descrip.c /^ufalloc(i)$/ ufavail ../sys/kern_descrip.c /^ufavail()$/ ufs_mountedon ../sys/ufs_fio.c /^ufs_mountedon(dev)$/ ufs_setattr ../sys/ufs_fio.c /^ufs_setattr(ip, vap)$/ uid_t ../h/types.h 46 uiofmove ../sys/kern_subr.c /^uiofmove(cp, n, uio, iov)$/ uiomove ../sys/kern_subr.c /^uiomove(cp, n, uio)$/ uipc_usrreq ../sys/uipc_usrreq.c /^uipc_usrreq(so, req, m, nam, rights)$/ uldiv ../machine/libc_uldiv.s /^ENTRY(uldiv)$/ uldiv ../machine/libc_uldiv.s /^ENTRY(uldiv)$/ ulsh ../machine/libc_ulsh.s /^ASENTRY(ulsh)$/ ulsh ../machine/libc_ulsh.s /^ENTRY(ulsh)$/ umask ../sys/ufs_syscalls.c /^umask()$/ umount ../sys/ufs_mount.c /^umount()$/ unctrl /usr/include/curses.h /^#define unctrl(c) _unctrl[(c) & 0177]$/ unlink ../sys/ufs_syscalls.c /^unlink()$/ unmap ../machine/scb.s /^ASENTRY(unmap)$/ unmount1 ../sys/ufs_mount.c /^unmount1(fname)$/ unp_abort ../sys/uipc_usrreq.c /^unp_abort(unp)$/ unp_attach ../sys/uipc_usrreq.c /^unp_attach(so)$/ unp_bind ../sys/uipc_usrreq.c /^unp_bind(unp, nam)$/ unp_connect ../sys/uipc_usrreq.c /^unp_connect(so, nam)$/ unp_connect2 ../sys/uipc_usrreq.c /^unp_connect2(so, so2)$/ unp_detach ../sys/uipc_usrreq.c /^unp_detach(unp)$/ unp_discard ../sys/uipc_usrreq.c /^unp_discard(fp)$/ unp_disconnect ../sys/uipc_usrreq.c /^unp_disconnect(unp)$/ unp_dispose ../sys/uipc_usrreq.c /^unp_dispose(m)$/ unp_drain ../sys/uipc_usrreq.c /^unp_drain()$/ unp_drop ../sys/uipc_usrreq.c /^unp_drop(unp, errno)$/ unp_externalize ../sys/uipc_usrreq.c /^unp_externalize(rights)$/ unp_gc ../sys/uipc_usrreq.c /^unp_gc()$/ unp_internalize ../sys/uipc_usrreq.c /^unp_internalize(rights)$/ unp_mark ../sys/uipc_usrreq.c /^unp_mark(fp)$/ unp_scan ../sys/uipc_usrreq.c /^unp_scan(m0, op)$/ unp_usrclosed ../sys/uipc_usrreq.c /^unp_usrclosed(unp)$/ unpbind ../sys/sys_kern.c /^unpbind(path, len, ipp, unpsock)$/ unpconn ../sys/sys_kern.c /^unpconn(path, len, so2, ipp)$/ unpdet ../sys/sys_kern.c /^unpdet(ip)$/ unpdisc ../sys/sys_kern.c /^unpdisc(fp)$/ unpgc1 ../sys/sys_kern.c /^unpgc1(beginf, endf)$/ unputc ../sys/tty_subr.c /^unputc(p)$/ unselect ../sys/sys_generic.c /^unselect(p)$/ unsleep ../sys/kern_synch.c /^unsleep(p)$/ untimeout ../sys/kern_clock.c /^untimeout(fun, arg)$/ update ../sys/ufs_subr.c /^update()$/ updatepri ../sys/kern_synch.c /^updatepri(p)$/ uprintf ../sys/subr_prf.c /^uprintf(fmt, x1)$/ ureadc ../sys/kern_subr.c /^ureadc(c, uio)$/ urem ../machine/libc_udiv.s /^ASENTRY(urem)$/ ushort ../h/types.h 29 utimes ../sys/ufs_syscalls.c /^utimes()$/ uwritec ../sys/kern_subr.c /^uwritec(uio)$/ va_end /usr/include/varargs.h /^# define va_end(list)$/ va_list /usr/include/varargs.h 3 va_start /usr/include/varargs.h /^# define va_start(list) list = (char *) &va_alist$/ vattr_null ../machine/mch_xxx.s /^ENTRY(vattr_null)$/ vcopyin ../machine/mch_copy.s /^ENTRY(vcopyin)$/ vcopyout ../machine/mch_copy.s /^ENTRY(vcopyout)$/ vfork ../sys/kern_fork.c /^vfork()$/ vhangup ../sys/sys_inode.c /^vhangup()$/ vm_sysctl ../sys/kern_sysctl.c /^vm_sysctl(name, namelen, oldp, oldlenp, newp, newl/ vmmeter ../sys/vm_sched.c /^vmmeter()$/ vmtotal ../sys/vm_sched.c /^vmtotal()$/ vvattach ../pdpif/if_vv.c /^vvattach(ui)$/ vvidentify ../pdpif/if_vv.c /^vvidentify(unit)$/ vvinit ../pdpif/if_vv.c /^vvinit(unit)$/ vvioctl ../pdpif/if_vv.c /^vvioctl(ifp, cmd, data)$/ vvoutput ../pdpif/if_vv.c /^vvoutput(ifp, m0, dst)$/ vvprobe ../pdpif/if_vv.c /^vvprobe(reg)$/ vvprt_hdr ../pdpif/if_vv.c /^vvprt_hdr(s, v)$/ vvreset ../pdpif/if_vv.c /^vvreset(unit, uban)$/ vvrint ../pdpif/if_vv.c /^vvrint(unit)$/ vvstart ../pdpif/if_vv.c /^vvstart(dev)$/ vvwatchdog ../pdpif/if_vv.c /^vvwatchdog(unit)$/ vvxint ../pdpif/if_vv.c /^vvxint(unit)$/ wait1 ../sys/kern_exit.c /^wait1(q, uap, retval)$/ wait4 ../sys/kern_exit.c /^wait4()$/ wakeup ../sys/kern_synch.c /^wakeup(chan)$/ winch /usr/include/curses.h /^#define winch(win) (win->_y[win->_cury][win->_cur/ word_t ../sys/tty_subr.c 530 write ../sys/sys_generic.c /^write()$/ writedisklabel ../sys/ufs_disksubr.c /^writedisklabel(dev, strat, lp)$/ writep ../sys/sys_pipe.c /^writep(fp, uio, flag)$/ writev ../sys/sys_generic.c /^writev()$/ xalloc ../sys/vm_text.c /^xalloc(ip, ep)$/ xccdec ../sys/vm_text.c /^xccdec(xp)$/ xexpand ../sys/vm_text.c /^xexpand(xp)$/ xfree ../sys/vm_text.c /^xfree()$/ xinit ../sys/vm_text.c /^xinit()$/ xlock ../sys/vm_text.c /^xlock(xp)$/ xpattach ../pdpuba/xp.c /^xpattach(xpaddr, unit)$/ xpdump ../pdpuba/xp.c /^xpdump(dev)$/ xpecc ../pdpuba/xp.c /^xpecc(bp, flag)$/ xpintr ../pdpuba/xp.c /^xpintr(dev)$/ xpmaptype ../pdpuba/xp.c /^xpmaptype(xd, hpsn)$/ xpopen ../pdpuba/xp.c /^xpopen(dev)$/ xproot ../pdpuba/xp.c /^xproot()$/ xpsize ../pdpuba/xp.c /^xpsize(dev)$/ xpslave ../pdpuba/xp.c /^xpslave(xpaddr, xc)$/ xpstart ../pdpuba/xp.c /^xpstart(xc)$/ xpstrategy ../pdpuba/xp.c /^xpstrategy(bp)$/ xpunit ../pdpuba/xp.c /^#define xpunit(dev) ((minor(dev) >> 3) & 07)$/ xpustart ../pdpuba/xp.c /^xpustart(unit)$/ xumount ../sys/vm_text.c /^xumount(dev)$/ xuncore ../sys/vm_text.c /^xuncore(size)$/ xunlock ../sys/vm_text.c /^xunlock(xp)$/ xuntext ../sys/vm_text.c /^xuntext(xp)$/ xwait ../sys/vm_text.c /^xwait(xp)$/ r.c /^tcp_template(tp)$/ tcp_timers ../netinet/tcp_timer.c /^tcp_timers(tp, timer)$/ tcp_trace ../netinet/tcp_debusys/sys/tty.c 440 0 12 102063 5671776322 6523 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)tty.c 1.4 (2.11BSD GTE) 12/8/94 */ #include "param.h" #include "user.h" #include "ioctl.h" #include "tty.h" #include "proc.h" #include "file.h" #include "conf.h" #include "dk.h" #include "uio.h" #include "kernel.h" #include "systm.h" #include "inode.h" /* * Table giving parity for characters and indicating * character classes to tty driver. In particular, * if the low 6 bits are 0, then the character needs * no special processing on output. */ char partab[] = { 0001,0201,0201,0001,0201,0001,0001,0201, 0202,0004,0003,0201,0005,0206,0201,0001, 0201,0001,0001,0201,0001,0201,0201,0001, 0001,0201,0201,0001,0201,0001,0001,0201, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0200, 0000,0200,0200,0000,0200,0000,0000,0200, 0200,0000,0000,0200,0000,0200,0200,0000, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0200, 0000,0200,0200,0000,0200,0000,0000,0200, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0200, 0200,0000,0000,0200,0000,0200,0200,0000, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0201, /* * 7 bit ascii ends with the last character above, * but we contine through all 256 codes for the sake * of the tty output routines which use special vax * instructions which need a 256 character trt table. */ 0007,0007,0007,0007,0007,0007,0007,0007, 0007,0007,0007,0007,0007,0007,0007,0007, 0007,0007,0007,0007,0007,0007,0007,0007, 0007,0007,0007,0007,0007,0007,0007,0007, 0007,0007,0007,0007,0007,0007,0007,0007, 0007,0007,0007,0007,0007,0007,0007,0007, 0007,0007,0007,0007,0007,0007,0007,0007, 0007,0007,0007,0007,0007,0007,0007,0007, 0007,0007,0007,0007,0007,0007,0007,0007, 0007,0007,0007,0007,0007,0007,0007,0007, 0007,0007,0007,0007,0007,0007,0007,0007, 0007,0007,0007,0007,0007,0007,0007,0007, 0007,0007,0007,0007,0007,0007,0007,0007, 0007,0007,0007,0007,0007,0007,0007,0007, 0007,0007,0007,0007,0007,0007,0007,0007, 0007,0007,0007,0007,0007,0007,0007,0007 }; short tthiwat[16] = { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,1300,2000 }; short ttlowat[16] = { 30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 }; struct ttychars ttydefaults = { CERASE, CKILL, CINTR, CQUIT, CSTART, CSTOP, CEOF, CBRK, CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE,CLNEXT }; ttychars(tp) struct tty *tp; { tp->t_chars = ttydefaults; } /* * Wait for output to drain, then flush input waiting. */ ttywflush(tp) register struct tty *tp; { ttywait(tp); ttyflush(tp, FREAD); } ttywait(tp) register struct tty *tp; { register int s = spltty(); while ((tp->t_outq.c_cc || tp->t_state&TS_BUSY) && tp->t_state&TS_CARR_ON && tp->t_oproc) { (*tp->t_oproc)(tp); tp->t_state |= TS_ASLEEP; sleep((caddr_t)&tp->t_outq, TTOPRI); } splx(s); } /* * Flush all TTY queues */ ttyflush(tp, rw) register struct tty *tp; { register s; s = spltty(); if (rw & FREAD) { while (getc(&tp->t_canq) >= 0) ; wakeup((caddr_t)&tp->t_rawq); } if (rw & FWRITE) { wakeup((caddr_t)&tp->t_outq); tp->t_state &= ~TS_TTSTOP; (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw); while (getc(&tp->t_outq) >= 0) ; } if (rw & FREAD) { while (getc(&tp->t_rawq) >= 0) ; tp->t_rocount = 0; tp->t_rocol = 0; tp->t_state &= ~TS_LOCAL; } splx(s); } /* * Send stop character on input overflow. */ ttyblock(tp) register struct tty *tp; { register x; x = tp->t_rawq.c_cc + tp->t_canq.c_cc; if (tp->t_rawq.c_cc > TTYHOG) { ttyflush(tp, FREAD|FWRITE); tp->t_state &= ~TS_TBLOCK; } /* * Block further input iff: * Current input > threshold AND input is available to user program */ if (x >= TTYHOG/2 && ((tp->t_flags & (RAW|CBREAK)) || (tp->t_canq.c_cc > 0)) && (tp->t_state&TS_TBLOCK) == 0) { if (putc(tp->t_stopc, &tp->t_outq)==0) { tp->t_state |= TS_TBLOCK; ttstart(tp); } } } /* * Restart typewriter output following a delay * timeout. * The name of the routine is passed to the timeout * subroutine and it is called during a clock interrupt. */ ttrstrt(tp) register struct tty *tp; { #ifdef DIAGNOSTIC if (tp == 0) panic("ttrstrt"); #endif tp->t_state &= ~TS_TIMEOUT; ttstart(tp); } /* * Start output on the typewriter. It is used from the top half * after some characters have been put on the output queue, * from the interrupt routine to transmit the next * character, and after a timeout has finished. */ ttstart(tp) register struct tty *tp; { register s; s = spltty(); if ((tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0 && tp->t_oproc) /* kludge for pty */ (*tp->t_oproc)(tp); splx(s); } /* * Common code for tty ioctls. */ /*ARGSUSED*/ ttioctl(tp, com, data, flag) register struct tty *tp; u_int com; caddr_t data; int flag; { int dev = tp->t_dev; extern int nldisp; int s; long newflags; /* * If the ioctl involves modification, * hang if in the background. */ switch (com) { case TIOCSETD: case TIOCSETP: case TIOCSETN: case TIOCFLUSH: case TIOCSETC: case TIOCSLTC: case TIOCSPGRP: case TIOCLBIS: case TIOCLBIC: case TIOCLSET: case TIOCSTI: case TIOCSWINSZ: while (tp->t_line == NTTYDISC && u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp && (u.u_procp->p_flag&SVFORK) == 0 && !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) && !(u.u_procp->p_sigmask & sigmask(SIGTTOU))) { gsignal(u.u_procp->p_pgrp, SIGTTOU); sleep((caddr_t)&lbolt, TTOPRI); } break; } /* * Process the ioctl. */ switch (com) { /* get discipline number */ case TIOCGETD: *(int *)data = tp->t_line; break; /* set line discipline */ case TIOCSETD: { register int t = *(int *)data; int error = 0; if ((unsigned) t >= nldisp) return (ENXIO); if (t != tp->t_line) { s = spltty(); (*linesw[tp->t_line].l_close)(tp, flag); error = (*linesw[t].l_open)(dev, tp); if (error) { (void) (*linesw[tp->t_line].l_open)(dev, tp); splx(s); return (error); } tp->t_line = t; splx(s); } break; } /* prevent more opens on channel */ case TIOCEXCL: tp->t_state |= TS_XCLUDE; break; case TIOCNXCL: tp->t_state &= ~TS_XCLUDE; break; /* hang up line on last close */ case TIOCHPCL: tp->t_state |= TS_HUPCLS; break; case TIOCFLUSH: { register int flags = *(int *)data; if (flags == 0) flags = FREAD|FWRITE; else flags &= FREAD|FWRITE; ttyflush(tp, flags); break; } /* return number of characters immediately available */ case FIONREAD: *(off_t *)data = ttnread(tp); break; case TIOCOUTQ: *(int *)data = tp->t_outq.c_cc; break; case TIOCSTOP: s = spltty(); if ((tp->t_state&TS_TTSTOP) == 0) { tp->t_state |= TS_TTSTOP; (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); } splx(s); break; case TIOCSTART: s = spltty(); if ((tp->t_state&TS_TTSTOP) || (tp->t_flags&FLUSHO)) { tp->t_state &= ~TS_TTSTOP; tp->t_flags &= ~FLUSHO; ttstart(tp); } splx(s); break; /* * Simulate typing of a character at the terminal. */ case TIOCSTI: if (u.u_uid && (flag & FREAD) == 0) return (EPERM); if (u.u_uid && u.u_ttyp != tp) return (EACCES); (*linesw[tp->t_line].l_rint)(*(char *)data, tp); break; case TIOCSETP: case TIOCSETN: { register struct sgttyb *sg = (struct sgttyb *)data; tp->t_erase = sg->sg_erase; tp->t_kill = sg->sg_kill; tp->t_ispeed = sg->sg_ispeed; tp->t_ospeed = sg->sg_ospeed; newflags = (tp->t_flags&0xffff0000) | (sg->sg_flags&0xffffL); s = spltty(); if (tp->t_flags&RAW || newflags&RAW || com == TIOCSETP) { ttywait(tp); ttyflush(tp, FREAD); } else if ((tp->t_flags&CBREAK) != (newflags&CBREAK)) { if (newflags&CBREAK) { struct clist tq; catq(&tp->t_rawq, &tp->t_canq); tq = tp->t_rawq; tp->t_rawq = tp->t_canq; tp->t_canq = tq; } else { tp->t_flags |= PENDIN; newflags |= PENDIN; ttwakeup(tp); } } tp->t_flags = newflags; if (tp->t_flags&RAW) { tp->t_state &= ~TS_TTSTOP; ttstart(tp); } splx(s); break; } /* send current parameters to user */ case TIOCGETP: { register struct sgttyb *sg = (struct sgttyb *)data; sg->sg_ispeed = tp->t_ispeed; sg->sg_ospeed = tp->t_ospeed; sg->sg_erase = tp->t_erase; sg->sg_kill = tp->t_kill; sg->sg_flags = tp->t_flags; break; } case FIONBIO: break; /* XXX remove */ case FIOASYNC: if (*(int *)data) tp->t_state |= TS_ASYNC; else tp->t_state &= ~TS_ASYNC; break; case TIOCGETC: bcopy((caddr_t)&tp->t_intrc, data, sizeof (struct tchars)); break; case TIOCSETC: bcopy(data, (caddr_t)&tp->t_intrc, sizeof (struct tchars)); break; /* set/get local special characters */ case TIOCSLTC: bcopy(data, (caddr_t)&tp->t_suspc, sizeof (struct ltchars)); break; case TIOCGLTC: bcopy((caddr_t)&tp->t_suspc, data, sizeof (struct ltchars)); break; /* * Modify local mode word. */ case TIOCLBIS: tp->t_flags |= (long)*(u_int *)data << 16; break; case TIOCLBIC: tp->t_flags &= ~((long)*(u_int *)data << 16); break; case TIOCLSET: tp->t_flags &= 0xffffL; tp->t_flags |= (long)*(u_int *)data << 16; break; case TIOCLGET: *(int *)data = tp->t_flags >> 16; break; /* * Allow SPGRP only if tty is open for reading. * Quick check: if we can find a process in the new pgrp, * this user must own that process. * SHOULD VERIFY THAT PGRP IS IN USE AND IS THIS USER'S. */ case TIOCSPGRP: { struct proc *p; short pgrp = *(int *)data; if (u.u_uid && (flag & FREAD) == 0) return (EPERM); p = pfind(pgrp); if (p && p->p_pgrp == pgrp && p->p_uid != u.u_uid && u.u_uid && !inferior(p)) return (EPERM); tp->t_pgrp = pgrp; break; } case TIOCGPGRP: *(int *)data = tp->t_pgrp; break; case TIOCSWINSZ: if (bcmp((caddr_t)&tp->t_winsize, data, sizeof (struct winsize))) { tp->t_winsize = *(struct winsize *)data; gsignal(tp->t_pgrp, SIGWINCH); } break; case TIOCGWINSZ: *(struct winsize *)data = tp->t_winsize; break; default: return (-1); } return (0); } ttnread(tp) struct tty *tp; { int nread = 0; if (tp->t_flags & PENDIN) ttypend(tp); nread = tp->t_canq.c_cc; if (tp->t_flags & (RAW|CBREAK)) nread += tp->t_rawq.c_cc; return (nread); } ttselect(dev, rw) dev_t dev; int rw; { #ifdef pdp11 register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)&0177]; #else register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)]; #endif int nread; int s = spltty(); switch (rw) { case FREAD: nread = ttnread(tp); if ((nread > 0) || ((tp->t_state & TS_CARR_ON) == 0)) goto win; if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait) tp->t_state |= TS_RCOLL; else tp->t_rsel = u.u_procp; break; case FWRITE: if (tp->t_outq.c_cc <= TTLOWAT(tp)) goto win; if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait) tp->t_state |= TS_WCOLL; else tp->t_wsel = u.u_procp; break; } splx(s); return (0); win: splx(s); return (1); } /* * Initial open of tty, or (re)entry to line discipline. * Establish a process group for distribution of * quits and interrupts from the tty. */ ttyopen(dev, tp) dev_t dev; register struct tty *tp; { register struct proc *pp; pp = u.u_procp; tp->t_dev = dev; if (pp->p_pgrp == 0) { u.u_ttyp = tp; u.u_ttyd = dev; if (tp->t_pgrp == 0) tp->t_pgrp = pp->p_pid; pp->p_pgrp = tp->t_pgrp; } tp->t_state &= ~TS_WOPEN; if ((tp->t_state & TS_ISOPEN) == 0) { tp->t_state |= TS_ISOPEN; bzero((caddr_t)&tp->t_winsize, sizeof(tp->t_winsize)); if (tp->t_line != NTTYDISC) ttywflush(tp); } return (0); } /* * "close" a line discipline */ ttylclose(tp, flag) register struct tty *tp; { /* * 4.4 has IO_NDELAY but I think that is a mistake because the upper level * 'close' routines all pass 'fp->f_flags' down. This was verified with a * printf here - the F* flags are received rather than the IO_* flags! */ if (flag & FNDELAY) ttyflush(tp, FREAD|FWRITE); else ttywflush(tp); tp->t_line = 0; } /* * clean tp on last close */ ttyclose(tp) register struct tty *tp; { ttyflush(tp, FREAD|FWRITE); tp->t_pgrp = 0; tp->t_state = 0; } /* * Handle modem control transition on a tty. * Flag indicates new state of carrier. * Returns 0 if the line should be turned off, otherwise 1. */ ttymodem(tp, flag) register struct tty *tp; { if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_flags & MDMBUF)) { /* * MDMBUF: do flow control according to carrier flag */ if (flag) { tp->t_state &= ~TS_TTSTOP; ttstart(tp); } else if ((tp->t_state&TS_TTSTOP) == 0) { tp->t_state |= TS_TTSTOP; (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); } } else if (flag == 0) { /* * Lost carrier. */ tp->t_state &= ~TS_CARR_ON; if (tp->t_state & TS_ISOPEN) { if ((tp->t_flags & NOHANG) == 0) { gsignal(tp->t_pgrp, SIGHUP); gsignal(tp->t_pgrp, SIGCONT); ttyflush(tp, FREAD|FWRITE); return (0); } } } else { /* * Carrier now on. */ tp->t_state |= TS_CARR_ON; wakeup((caddr_t)&tp->t_rawq); } return (1); } /* * Default modem control routine (for other line disciplines). * Return argument flag, to turn off device on carrier drop. */ nullmodem(tp, flag) register struct tty *tp; int flag; { if (flag) tp->t_state |= TS_CARR_ON; else tp->t_state &= ~TS_CARR_ON; return (flag); } /* * reinput pending characters after state switch * call at spltty(). */ ttypend(tp) register struct tty *tp; { struct clist tq; register c; tp->t_flags &= ~PENDIN; tp->t_state |= TS_TYPEN; tq = tp->t_rawq; tp->t_rawq.c_cc = 0; tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0; while ((c = getc(&tq)) >= 0) ttyinput(c, tp); tp->t_state &= ~TS_TYPEN; } /* * Place a character on raw TTY input queue, * putting in delimiters and waking up top * half as needed. Also echo if required. * The arguments are the character and the * appropriate tty structure. */ ttyinput(c, tp) register c; register struct tty *tp; { long t_flags = tp->t_flags; int i; /* * If input is pending take it first. */ if (t_flags&PENDIN) ttypend(tp); #ifdef UCB_METER tk_nin++; #endif c &= 0377; /* * In tandem mode, check high water mark. */ if (t_flags&TANDEM) ttyblock(tp); if (t_flags&RAW) { /* * Raw mode, just put character * in input q w/o interpretation. */ if (tp->t_rawq.c_cc > TTYHOG) ttyflush(tp, FREAD|FWRITE); else { if (putc(c, &tp->t_rawq) >= 0) ttwakeup(tp); ttyecho(c, tp); } goto endcase; } /* * Ignore any high bit added during * previous ttyinput processing. */ if ((tp->t_state&TS_TYPEN) == 0 && (t_flags&PASS8) == 0) c &= 0177; /* * Check for literal nexting very first */ if (tp->t_state&TS_LNCH) { c |= 0200; tp->t_state &= ~TS_LNCH; } /* * Scan for special characters. This code * is really just a big case statement with * non-constant cases. The bottom of the * case statement is labeled ``endcase'', so goto * it after a case match, or similar. */ if (tp->t_line == NTTYDISC) { if (c == tp->t_lnextc) { if (t_flags&ECHO) ttyout("^\b", tp); tp->t_state |= TS_LNCH; goto endcase; } if (c == tp->t_flushc) { if (t_flags&FLUSHO) tp->t_flags &= ~FLUSHO; else { ttyflush(tp, FWRITE); ttyecho(c, tp); if (tp->t_rawq.c_cc + tp->t_canq.c_cc) ttyretype(tp); tp->t_flags |= FLUSHO; } goto startoutput; } if (c == tp->t_suspc) { if ((t_flags&NOFLSH) == 0) ttyflush(tp, FREAD); ttyecho(c, tp); gsignal(tp->t_pgrp, SIGTSTP); goto endcase; } } /* * Handle start/stop characters. */ if (c == tp->t_stopc) { if ((tp->t_state&TS_TTSTOP) == 0) { tp->t_state |= TS_TTSTOP; (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); return; } if (c != tp->t_startc) return; goto endcase; } if (c == tp->t_startc) goto restartoutput; /* * Look for interrupt/quit chars. */ if (c == tp->t_intrc || c == tp->t_quitc) { if ((t_flags&NOFLSH) == 0) ttyflush(tp, FREAD|FWRITE); ttyecho(c, tp); gsignal(tp->t_pgrp, c == tp->t_intrc ? SIGINT : SIGQUIT); goto endcase; } /* * Cbreak mode, don't process line editing * characters; check high water mark for wakeup. */ if (t_flags&CBREAK) { if (tp->t_rawq.c_cc > TTYHOG) { if (tp->t_outq.c_cc < TTHIWAT(tp) && tp->t_line == NTTYDISC) (void) ttyoutput(CTRL(g), tp); } else if (putc(c, &tp->t_rawq) >= 0) { ttwakeup(tp); ttyecho(c, tp); } goto endcase; } /* * From here on down cooked mode character * processing takes place. */ if ((tp->t_state&TS_QUOT) && (c == tp->t_erase || c == tp->t_kill)) { ttyrub(unputc(&tp->t_rawq), tp); c |= 0200; } if (c == tp->t_erase) { if (tp->t_rawq.c_cc) ttyrub(unputc(&tp->t_rawq), tp); goto endcase; } if (c == tp->t_kill) { if (t_flags&CRTKIL && tp->t_rawq.c_cc == tp->t_rocount) { while (tp->t_rawq.c_cc) ttyrub(unputc(&tp->t_rawq), tp); } else { ttyecho(c, tp); ttyecho('\n', tp); while (getc(&tp->t_rawq) > 0) ; tp->t_rocount = 0; } tp->t_state &= ~TS_LOCAL; goto endcase; } /* * New line discipline, * check word erase/reprint line. */ if (tp->t_line == NTTYDISC) { if (c == tp->t_werasc) { if (tp->t_rawq.c_cc == 0) goto endcase; do { c = unputc(&tp->t_rawq); if (c != ' ' && c != '\t') goto erasenb; ttyrub(c, tp); } while (tp->t_rawq.c_cc); goto endcase; erasenb: do { ttyrub(c, tp); if (tp->t_rawq.c_cc == 0) goto endcase; c = unputc(&tp->t_rawq); } while (c != ' ' && c != '\t'); (void) putc(c, &tp->t_rawq); goto endcase; } if (c == tp->t_rprntc) { ttyretype(tp); goto endcase; } } /* * Check for input buffer overflow */ if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) { if (tp->t_line == NTTYDISC) (void) ttyoutput(CTRL(g), tp); goto endcase; } /* * Put data char in q for user and * wakeup on seeing a line delimiter. */ if (putc(c, &tp->t_rawq) >= 0) { if (ttbreakc(c, tp)) { tp->t_rocount = 0; catq(&tp->t_rawq, &tp->t_canq); ttwakeup(tp); } else if (tp->t_rocount++ == 0) tp->t_rocol = tp->t_col; tp->t_state &= ~TS_QUOT; if (c == '\\') tp->t_state |= TS_QUOT; if (tp->t_state&TS_ERASE) { tp->t_state &= ~TS_ERASE; (void) ttyoutput('/', tp); } i = tp->t_col; ttyecho(c, tp); if (c == tp->t_eofc && t_flags&ECHO) { i = MIN(2, tp->t_col - i); while (i > 0) { (void) ttyoutput('\b', tp); i--; } } } endcase: /* * If DEC-style start/stop is enabled don't restart * output until seeing the start character. */ if (t_flags&DECCTQ && tp->t_state&TS_TTSTOP && tp->t_startc != tp->t_stopc) return; restartoutput: tp->t_state &= ~TS_TTSTOP; tp->t_flags &= ~FLUSHO; startoutput: ttstart(tp); } /* * Put character on TTY output queue, adding delays, * expanding tabs, and handling the CR/NL bit. * This is called both from the top half for output, * and from interrupt level for echoing. * The arguments are the character and the tty structure. * Returns < 0 if putc succeeds, otherwise returns char to resend * Must be recursive. */ ttyoutput(c, tp) register c; register struct tty *tp; { register char *colp; register ctype; if (tp->t_flags & (RAW|LITOUT)) { if (tp->t_flags&FLUSHO) return (-1); if (putc(c, &tp->t_outq)) return (c); #ifdef UCB_METER tk_nout++; #endif return (-1); } /* * Ignore EOT in normal mode to avoid * hanging up certain terminals. */ c &= 0177; if (c == CEOT && (tp->t_flags&CBREAK) == 0) return (-1); /* * Turn tabs to spaces as required */ if (c == '\t' && (tp->t_flags&TBDELAY) == XTABS) { register int s; c = 8 - (tp->t_col&7); if ((tp->t_flags&FLUSHO) == 0) { s = spltty(); /* don't interrupt tabs */ c -= b_to_q(" ", c, &tp->t_outq); #ifdef UCB_METER tk_nout += c; #endif splx(s); } tp->t_col += c; return (c ? -1 : '\t'); } #ifdef UCB_METER tk_nout++; #endif /* * turn to if desired. */ if (c == '\n' && tp->t_flags&CRMOD) if (ttyoutput('\r', tp) >= 0) return (c); if ((tp->t_flags&FLUSHO) == 0 && putc(c, &tp->t_outq)) return (c); /* * Calculate delays. * The numbers here represent clock ticks * and are not necessarily optimal for all terminals. * The delays are indicated by characters above 0200. * In raw mode there are no delays and the * transmission path is 8 bits wide. * * SHOULD JUST ALLOW USER TO SPECIFY DELAYS */ colp = &tp->t_col; ctype = partab[c]; c = 0; switch (ctype&077) { case ORDINARY: (*colp)++; case CONTROL: break; case BACKSPACE: if (*colp) (*colp)--; break; /* * This macro is close enough to the correct thing; * it should be replaced by real user settable delays * in any event... */ #define mstohz(ms) (((ms) * hz) >> 10) case NEWLINE: ctype = (tp->t_flags >> 8) & 03L; if (ctype == 1) { /* tty 37 */ if (*colp > 0) { c = (((unsigned)*colp) >> 4) + 3; if ((unsigned)c > 6) c = 6; } } else if (ctype == 2) /* vt05 */ c = mstohz(100); *colp = 0; break; case TAB: ctype = (tp->t_flags >> 10) & 03L; if (ctype == 1) { /* tty 37 */ c = 1 - (*colp | ~07); if (c < 5) c = 0; } *colp |= 07; (*colp)++; break; case VTAB: if (tp->t_flags&VTDELAY) /* tty 37 */ c = 0177; break; case RETURN: ctype = (tp->t_flags >> 12) & 03L; if (ctype == 1) /* tn 300 */ c = mstohz(83); else if (ctype == 2) /* ti 700 */ c = mstohz(166); else if (ctype == 3) { /* concept 100 */ int i; if ((i = *colp) >= 0) for (; i < 9; i++) (void) putc(0177, &tp->t_outq); } *colp = 0; } if (c && (tp->t_flags&FLUSHO) == 0) (void) putc(c|0200, &tp->t_outq); return (-1); } #undef mstohz /* * Called from device's read routine after it has * calculated the tty-structure given as argument. */ ttread(tp, uio, flag) register struct tty *tp; struct uio *uio; { register struct clist *qp; register c; long t_flags; int s, first, error = 0; loop: /* * Take any pending input first. */ s = spltty(); if (tp->t_flags&PENDIN) ttypend(tp); splx(s); if ((tp->t_state&TS_CARR_ON)==0) return (EIO); /* * Hang process if it's in the background. */ if (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) { if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || u.u_procp->p_flag&SVFORK) return (EIO); gsignal(u.u_procp->p_pgrp, SIGTTIN); sleep((caddr_t)&lbolt, TTIPRI); goto loop; } t_flags = tp->t_flags; /* * In raw mode take characters directly from the * raw queue w/o processing. Interlock against * device interrupts when interrogating rawq. */ if (t_flags&RAW) { s = spltty(); if (tp->t_rawq.c_cc <= 0) { if ((tp->t_state&TS_CARR_ON) == 0 || (flag & IO_NDELAY)) { splx(s); return (EWOULDBLOCK); } sleep((caddr_t)&tp->t_rawq, TTIPRI); splx(s); goto loop; } splx(s); while (!error && tp->t_rawq.c_cc && uio->uio_resid) error = ureadc(getc(&tp->t_rawq), uio); goto checktandem; } /* * In cbreak mode use the rawq, otherwise * take characters from the canonicalized q. */ qp = t_flags&CBREAK ? &tp->t_rawq : &tp->t_canq; /* * No input, sleep on rawq awaiting hardware * receipt and notification. */ s = spltty(); if (qp->c_cc <= 0) { if ((tp->t_state&TS_CARR_ON) == 0 || (flag & IO_NDELAY)) { splx(s); return (EWOULDBLOCK); } sleep((caddr_t)&tp->t_rawq, TTIPRI); splx(s); goto loop; } splx(s); /* * Input present, perform input mapping * and processing (we're not in raw mode). */ first = 1; while ((c = getc(qp)) >= 0) { if (t_flags&CRMOD && c == '\r') c = '\n'; /* * Check for delayed suspend character. */ if (tp->t_line == NTTYDISC && c == tp->t_dsuspc) { gsignal(tp->t_pgrp, SIGTSTP); if (first) { sleep((caddr_t)&lbolt, TTIPRI); goto loop; } break; } /* * Interpret EOF only in cooked mode. */ if (c == tp->t_eofc && (t_flags&CBREAK) == 0) break; /* * Give user character. */ error = ureadc(t_flags&PASS8 ? c : c & 0177, uio); if (error) break; if (uio->uio_resid == 0) break; /* * In cooked mode check for a "break character" * marking the end of a "line of input". */ if ((t_flags&CBREAK) == 0 && ttbreakc(c, tp)) break; first = 0; } checktandem: /* * Look to unblock output now that (presumably) * the input queue has gone down. */ if (tp->t_state&TS_TBLOCK && (tp->t_rawq.c_cc+tp->t_canq.c_cc < TTYHOG/5 || (t_flags&(RAW|CBREAK)) == 0 && tp->t_canq.c_cc == 0)) if (putc(tp->t_startc, &tp->t_outq) == 0) { tp->t_state &= ~TS_TBLOCK; ttstart(tp); } return (error); } /* * Check the output queue on tp for space for a kernel message * (from uprintf/tprintf). Allow some space over the normal * hiwater mark so we don't lose messages due to normal flow * control, but don't let the tty run amok. * Sleeps here are not interruptible, but we return prematurely * if new signals come in. */ ttycheckoutq(tp, wait) register struct tty *tp; int wait; { int hiwat, s, oldsig; int wakeup(); hiwat = TTHIWAT(tp); s = spltty(); oldsig = u.u_procp->p_sig; if (tp->t_outq.c_cc > hiwat + 200) while (tp->t_outq.c_cc > hiwat) { ttstart(tp); if (wait == 0 || u.u_procp->p_sig != oldsig) { splx(s); return (0); } timeout(wakeup, (caddr_t)&tp->t_outq, hz); tp->t_state |= TS_ASLEEP; sleep((caddr_t)&tp->t_outq, PZERO - 1); } splx(s); return (1); } /* * Called from the device's write routine after it has * calculated the tty-structure given as argument. */ ttwrite(tp, uio, flag) register struct tty *tp; register struct uio *uio; { char *cp; register int cc, ce, c; int i, hiwat, cnt, error, s; char obuf[OBUFSIZ]; hiwat = TTHIWAT(tp); cnt = uio->uio_resid; error = 0; cc = 0; loop: s = spltty(); if (!(tp->t_state&TS_CARR_ON)) { if (tp->t_state & TS_ISOPEN) { splx(s); return(EIO); } else if (flag & IO_NDELAY) { splx(s); error = EWOULDBLOCK; goto out; } else { /* Sleep awaiting carrier. */ sleep((caddr_t)&tp->t_rawq, TTIPRI); goto loop; } } splx(s); /* * Hang the process if it's in the background. */ if (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp && (tp->t_flags&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 && !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) && !(u.u_procp->p_sigmask & sigmask(SIGTTOU))) { gsignal(u.u_procp->p_pgrp, SIGTTOU); sleep((caddr_t)&lbolt, TTIPRI); goto loop; } /* * Process the user's data in at most OBUFSIZ * chunks. Perform lower case simulation and * similar hacks. Keep track of high water * mark, sleep on overflow awaiting device aid * in acquiring new space. */ while (uio->uio_resid || cc > 0) { if (tp->t_flags&FLUSHO) { uio->uio_resid = 0; return(0); } if (tp->t_outq.c_cc > hiwat) goto ovhiwat; /* * Grab a hunk of data from the user, unless we have some * leftover from last time. */ if (cc == 0) { cc = MIN(uio->uio_resid, OBUFSIZ); cp = obuf; error = uiomove(cp, cc, uio); if (error) { cc = 0; break; } } /* * If nothing fancy need be done, grab those characters we * can handle without any of ttyoutput's processing and * just transfer them to the output q. For those chars * which require special processing (as indicated by the * bits in partab), call ttyoutput. After processing * a hunk of data, look for FLUSHO so ^O's will take effect * immediately. */ while (cc > 0) { if (tp->t_flags & (RAW|LITOUT)) ce = cc; else { ce = cc - scanc((unsigned)cc, (caddr_t)cp, (caddr_t)partab, 077); /* * If ce is zero, then we're processing * a special character through ttyoutput. */ if (ce == 0) { tp->t_rocount = 0; if (ttyoutput(*cp, tp) >= 0) { /* no c-lists, wait a bit */ ttstart(tp); sleep((caddr_t)&lbolt, TTOPRI); goto loop; } cp++, cc--; if (tp->t_flags&FLUSHO || tp->t_outq.c_cc > hiwat) goto ovhiwat; continue; } } /* * A bunch of normal characters have been found, * transfer them en masse to the output queue and * continue processing at the top of the loop. * If there are any further characters in this * <= OBUFSIZ chunk, the first should be a character * requiring special handling by ttyoutput. */ tp->t_rocount = 0; i = b_to_q(cp, ce, &tp->t_outq); ce -= i; tp->t_col += ce; cp += ce, cc -= ce; #ifdef UCB_METER tk_nout += ce; #endif if (i > 0) { /* out of c-lists, wait a bit */ ttstart(tp); sleep((caddr_t)&lbolt, TTOPRI); goto loop; } if (tp->t_flags&FLUSHO || tp->t_outq.c_cc > hiwat) break; } /* while (cc > 0) */ ttstart(tp); } /* while (uio->uio_resid || cc > 0) */ out: /* * If cc is nonzero, we leave the uio structure inconsistent, as the * offset and iov pointers have moved forward, but it doesn't matter * (the call will either return short or restart with a new uio). */ uio->uio_resid += cc; return (error); ovhiwat: s = spltty(); /* * This can only occur if FLUSHO is also set in t_flags, * or if ttstart/oproc is synchronous (or very fast). */ if (tp->t_outq.c_cc <= hiwat) { splx(s); goto loop; } ttstart(tp); if (flag & IO_NDELAY) { splx(s); uio->uio_resid += cc; return (uio->uio_resid == cnt ? EWOULDBLOCK : 0); } tp->t_state |= TS_ASLEEP; sleep((caddr_t)&tp->t_outq, TTOPRI); splx(s); goto loop; } /* * Rubout one character from the rawq of tp * as cleanly as possible. */ ttyrub(c, tp) register c; register struct tty *tp; { register char *cp; register int savecol; int s; char *nextc(); if ((tp->t_flags&ECHO) == 0) return; tp->t_flags &= ~FLUSHO; c &= 0377; if (tp->t_flags&CRTBS) { if (tp->t_rocount == 0) { /* * Screwed by ttwrite; retype */ ttyretype(tp); return; } if (c == ('\t'|0200) || c == ('\n'|0200)) ttyrubo(tp, 2); else switch (partab[c&=0177]&0177) { case ORDINARY: ttyrubo(tp, 1); break; case VTAB: case BACKSPACE: case CONTROL: case RETURN: if (tp->t_flags&CTLECH) ttyrubo(tp, 2); break; case TAB: if (tp->t_rocount < tp->t_rawq.c_cc) { ttyretype(tp); return; } s = spltty(); savecol = tp->t_col; tp->t_state |= TS_CNTTB; tp->t_flags |= FLUSHO; tp->t_col = tp->t_rocol; cp = tp->t_rawq.c_cf; #ifdef UCB_CLIST { char store; if (cp) store = lookc(cp); for (; cp; cp = nextc(&tp->t_rawq, cp, &store)) ttyecho(store, tp); } #else for (; cp; cp = nextc(&tp->t_rawq, cp)) ttyecho(*cp, tp); #endif tp->t_flags &= ~FLUSHO; tp->t_state &= ~TS_CNTTB; splx(s); /* * savecol will now be length of the tab */ savecol -= tp->t_col; tp->t_col += savecol; if (savecol > 8) savecol = 8; /* overflow screw */ while (--savecol >= 0) (void) ttyoutput('\b', tp); break; default: panic("ttyrub"); } } else if (tp->t_flags&PRTERA) { if ((tp->t_state&TS_ERASE) == 0) { (void) ttyoutput('\\', tp); tp->t_state |= TS_ERASE; } ttyecho(c, tp); } else ttyecho(tp->t_erase, tp); tp->t_rocount--; } /* * Crt back over cnt chars perhaps * erasing them. */ ttyrubo(tp, cnt) register struct tty *tp; int cnt; { register char *rubostring = tp->t_flags&CRTERA ? "\b \b" : "\b"; while (--cnt >= 0) ttyout(rubostring, tp); } /* * Reprint the rawq line. * We assume c_cc has already been checked. */ ttyretype(tp) register struct tty *tp; { register char *cp; char *nextc(); int s; if (tp->t_rprntc != 0377) ttyecho(tp->t_rprntc, tp); (void) ttyoutput('\n', tp); s = spltty(); #ifdef UCB_CLIST { char store; if (cp = tp->t_canq.c_cf) store = lookc(cp); for (; cp; cp = nextc(&tp->t_canq, cp, &store)) ttyecho(store, tp); if (cp = tp->t_rawq.c_cf) store = lookc(cp); for (; cp; cp = nextc(&tp->t_rawq, cp, &store)) ttyecho(store, tp); } #else for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp)) ttyecho(*cp, tp); for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp)) ttyecho(*cp, tp); #endif tp->t_state &= ~TS_ERASE; splx(s); tp->t_rocount = tp->t_rawq.c_cc; tp->t_rocol = 0; } /* * Echo a typed character to the terminal */ ttyecho(c, tp) register c; register struct tty *tp; { if ((tp->t_state&TS_CNTTB) == 0) tp->t_flags &= ~FLUSHO; if ((tp->t_flags&ECHO) == 0) return; c &= 0377; if (tp->t_flags&RAW) { (void) ttyoutput(c, tp); return; } if (c == '\r' && tp->t_flags&CRMOD) c = '\n'; if (tp->t_flags&CTLECH) { if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) { (void) ttyoutput('^', tp); c &= 0177; if (c == 0177) c = '?'; else c += 'A' - 1; } } (void) ttyoutput(c&0177, tp); } /* * Is c a break char for tp? */ ttbreakc(c, tp) register c; register struct tty *tp; { return (c == '\n' || c == tp->t_eofc || c == tp->t_brkc || c == '\r' && (tp->t_flags&CRMOD)); } /* * send string cp to tp */ ttyout(cp, tp) register char *cp; register struct tty *tp; { register char c; while (c = *cp++) (void) ttyoutput(c, tp); } ttwakeup(tp) struct tty *tp; { if (tp->t_rsel) { selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL); tp->t_state &= ~TS_RCOLL; tp->t_rsel = 0; } if (tp->t_state & TS_ASYNC) gsignal(tp->t_pgrp, SIGIO); wakeup((caddr_t)&tp->t_rawq); } rdware * receipt and notification. */ s = spltty(); if (qp->c_cc <= 0) { if ((tp->t_state&TS_CARR_ON) == 0 || (flag & IO_NDELAY)) { splx(s); return (EWOULDBLOCK); } sleep((caddr_t)&tp->t_rawq, TTIPRI); splx(s); goto loop; } splx(s); /* * Input present, perform input mapping * and processing (we're not in raw mode). */ first = 1; while ((c = getc(qp)) >= 0) { if (t_flags&CRMOD && c == '\r') c = '\n'; /* * Check forsys/sys/vm_swp.c 440 0 12 13370 5667245613 7177 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)vm_swp.c 2.3 (2.11BSD) 11/30/94 */ #include "param.h" #include "../machine/seg.h" #include "user.h" #include "proc.h" #include "buf.h" #include "conf.h" #include "systm.h" #include "vm.h" #include "trace.h" #include "uio.h" /* * swap I/O */ swap(blkno, coreaddr, count, rdflg) memaddr blkno, coreaddr; register int count; int rdflg; { register struct buf *bp; register int tcount; int s; #ifdef UCB_METER if (rdflg) { cnt.v_pswpin += count; cnt.v_pgin++; } else { cnt.v_pswpout += count; cnt.v_pgout++; } #endif bp = geteblk(); /* allocate a buffer header */ while (count) { bp->b_flags = B_BUSY | B_PHYS | B_INVAL | rdflg; bp->b_dev = swapdev; tcount = count; if (tcount >= 01700) /* prevent byte-count wrap */ tcount = 01700; bp->b_bcount = ctob(tcount); bp->b_blkno = blkno; bp->b_un.b_addr = (caddr_t)(coreaddr<<6); bp->b_xmem = (coreaddr>>10) & 077; trace(TR_SWAPIO); (*bdevsw[major(swapdev)].d_strategy)(bp); s = splbio(); while ((bp->b_flags & B_DONE) == 0) sleep((caddr_t)bp, PSWP); splx(s); if ((bp->b_flags & B_ERROR) || bp->b_resid) panic("hard err: swap"); count -= tcount; coreaddr += tcount; blkno += ctod(tcount); } brelse(bp); } /* * rout is the name of the routine where we ran out of swap space. */ swkill(p, rout) register struct proc *p; char *rout; { tprintf(u.u_ttyp, "sorry, pid %d killed in %s: no swap space\n", p->p_pid, rout); /* * To be sure no looping (e.g. in vmsched trying to * swap out) mark process locked in core (as though * done by user) after killing it so noone will try * to swap it out. */ psignal(p, SIGKILL); p->p_flag |= SULOCK; } /* * Raw I/O. The arguments are * The strategy routine for the device * A buffer, which may be a special buffer header * owned exclusively by the device for this purpose or * NULL if one is to be allocated. * The device number * Read/write flag * Essentially all the work is computing physical addresses and * validating them. * * rewritten to use the iov/uio mechanism from 4.3bsd. the physbuf routine * was inlined. essentially the chkphys routine performs the same task * as the useracc routine on a 4.3 system. 3/90 sms * * If the buffer pointer is NULL then one is allocated "dynamically" from * the system cache. the 'invalid' flag is turned on so that the brelse() * done later doesn't place the buffer back in the cache. the 'phys' flag * is left on so that the address of the buffer is recalcuated in getnewbuf(). * The BYTE/WORD stuff began to be removed after testing proved that either * 1) the underlying hardware gives an error or 2) nothing bad happens. * besides, 4.3BSD doesn't do the byte/word check and noone could remember * why the byte/word check was added in the first place - likely historical * paranoia. chkphys() inlined. 5/91 sms * * Refined (and streamlined) the flow by using a 'for' construct * (a la 4.3Reno). Avoid allocating/freeing the buffer for each iovec * element (i must have been confused at the time). 6/91-sms * * Finished removing the BYTE/WORD code as part of implementing the common * raw read&write routines , systems had been running fine for several * months with it ifdef'd out. 9/91-sms */ physio(strat, bp, dev, rw, uio) int (*strat)(); register struct buf *bp; dev_t dev; int rw; register struct uio *uio; { int error = 0, s, nb, ts, c, allocbuf = 0; register struct iovec *iov; if (!bp) { allocbuf++; bp = geteblk(); } u.u_procp->p_flag |= SLOCK; for ( ; uio->uio_iovcnt; uio->uio_iov++, uio->uio_iovcnt--) { iov = uio->uio_iov; if (iov->iov_base >= iov->iov_base + iov->iov_len) { error = EFAULT; break; } if (u.u_sep) ts = 0; else ts = (u.u_tsize + 127) & ~0177; nb = ((int)iov->iov_base >> 6) & 01777; /* * Check overlap with text. (ts and nb now * in 64-byte clicks) */ if (nb < ts) { error = EFAULT; break; } /* * Check that transfer is either entirely in the * data or in the stack: that is, either * the end is in the data or the start is in the stack * (remember wraparound was already checked). */ if (((((int)iov->iov_base + iov->iov_len) >> 6) & 01777) >= ts + u.u_dsize && nb < 1024 - u.u_ssize) { error = EFAULT; break; } if (!allocbuf) { s = splbio(); while (bp->b_flags & B_BUSY) { bp->b_flags |= B_WANTED; sleep((caddr_t)bp, PRIBIO+1); } splx(s); } bp->b_error = 0; while (iov->iov_len) { bp->b_flags = B_BUSY|B_PHYS|B_INVAL|rw; bp->b_dev = dev; nb = ((int)iov->iov_base >> 6) & 01777; ts = (u.u_sep ? UDSA : UISA)[nb >> 7] + (nb & 0177); bp->b_un.b_addr = (caddr_t)((ts << 6) + ((int)iov->iov_base & 077)); bp->b_xmem = (ts >> 10) & 077; bp->b_blkno = uio->uio_offset >> PGSHIFT; bp->b_bcount = iov->iov_len; c = bp->b_bcount; (*strat)(bp); s = splbio(); while ((bp->b_flags & B_DONE) == 0) sleep((caddr_t)bp, PRIBIO); if (bp->b_flags & B_WANTED) /* rare */ wakeup((caddr_t)bp); splx(s); c -= bp->b_resid; iov->iov_base += c; iov->iov_len -= c; uio->uio_resid -= c; uio->uio_offset += c; /* temp kludge for tape drives */ if (bp->b_resid || (bp->b_flags & B_ERROR)) break; } bp->b_flags &= ~(B_BUSY|B_WANTED); error = geterror(bp); /* temp kludge for tape drives */ if (bp->b_resid || error) break; } if (allocbuf) brelse(bp); u.u_procp->p_flag &= ~SLOCK; return(error); } rawrw(dev, uio, flag) dev_t dev; register struct uio *uio; int flag; { return(physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, dev, uio->uio_rw == UIO_READ ? B_READ : B_WRITE, uio)); } if (tp->t_flags&FLUSHO || tp->t_outq.c_cc > hiwat) goto ovhiwat; continue; } } /* * A bunch of normal characters have been found, * transfer them en masse to the output queue and * continue processing at the top of the loosys/sys/init_sysent.c 440 0 12 21570 5753577735 10246 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)init_sysent.c 1.8 (2.11BSD GTE) 1995/05/08 */ /* * System call switch table. */ #include "param.h" #include "systm.h" int nosys(); /* 1.1 processes and protection */ int sethostid(),gethostid(),sethostname(),gethostname(),getpid(); int getppid(), fork(),rexit(),execv(),execve(),owait(),wait4(); int getuid(),setreuid(),getgid(),getgroups(),setregid(),setgroups(); int geteuid(), getegid(); int getpgrp(),setpgrp(); int ucall(); /* 2BSD calls */ /* 1.2 memory management */ int sbrk(); int getpagesize(); int lock(),phys(),fetchi(),nostk(),fperr(); /* 2BSD calls */ /* 1.3 signals */ int sigvec(),sigblock(),sigsetmask(),sigpause(),sigstack(),sigreturn(); int kill(), killpg(); /* 1.4 timing and statistics */ int gettimeofday(),settimeofday(); int getitimer(),setitimer(); int adjtime(); int gldav(); /* 2BSD calls */ /* 1.5 descriptors */ int getdtablesize(),dup(),dup2(),close(); int select(),fcntl(),flock(); /* 1.6 resource controls */ int getpriority(),setpriority(),getrusage(),getrlimit(),setrlimit(); int setquota(),qquota(); /* 1.7 system operation support */ int umount(),smount(); int sync(),reboot(),sysacct(), __sysctl(); /* 2.1 generic operations */ int read(),write(),readv(),writev(),ioctl(); /* 2.2 file system */ int chdir(), fchdir(), chroot(); int mkdir(),rmdir(), chflags(), fchflags(); int creat(),open(),mknod(),unlink(),stat(),fstat(),lstat(); int chown(),fchown(),chmod(),fchmod(),utimes(); int link(),symlink(),readlink(),rename(); int lseek(),truncate(),ftruncate(),saccess(),fsync(); /* 2.3 communications */ int socket(),bind(),listen(),accept(),connect(); int socketpair(),sendto(),send(),recvfrom(),recv(); int sendmsg(),recvmsg(),shutdown(),setsockopt(),getsockopt(); int getsockname(),getpeername(),pipe(); int umask(); /* XXX */ /* 2.4 processes */ int ptrace(); /* 2.5 terminals */ #ifdef INET #define ifnet(narg, name) narg, name #define errnet(narg, name) narg, name #else int nonet(); #define ifnet(narg, name) 0, nosys #define errnet(narg, name) 0, nonet #endif /* BEGIN JUNK */ int profil(); /* 'cuz sys calls are interruptible */ int vhangup(); /* should just do in exit() */ int vfork(); /* awaiting fork w/ copy on write */ /* END JUNK */ /* * Reserved/unimplemented system calls in the range 0-150 inclusive * are reserved for use in future Berkeley releases. * Additional system calls implemented in vendor and other * redistributions should be placed in the reserved range at the end * of the current calls. */ /* * This table is the switch used to transfer to the appropriate routine for * processing a system call. Each row contains the number of words of * arguments expected in registers, how many on the stack, and a pointer to * the routine. * * The maximum number of direct system calls is 255 since system call numbers * are encoded in the lower byte of the trap instruction -- see trap.c. */ struct sysent sysent[] = { 1, nosys, /* 0 = indir or out-of-range */ 1, rexit, /* 1 = exit */ 0, fork, /* 2 = fork */ 3, read, /* 3 = read */ 3, write, /* 4 = write */ 3, open, /* 5 = open */ 1, close, /* 6 = close */ 4, wait4, /* 7 = wait4 */ 2, creat, /* 8 = creat */ 2, link, /* 9 = link */ 1, unlink, /* 10 = unlink */ 2, execv, /* 11 = execv */ 1, chdir, /* 12 = chdir */ 1, fchdir, /* 13 = fchdir */ 3, mknod, /* 14 = mknod */ 2, chmod, /* 15 = chmod */ 3, chown, /* 16 = chown; now 3 args */ 2, chflags, /* 17 = chflags */ 2, fchflags, /* 18 = fchflags */ 4, lseek, /* 19 = lseek */ 0, getpid, /* 20 = getpid */ 3, smount, /* 21 = mount */ 1, umount, /* 22 = umount */ 6, __sysctl, /* 23 = __sysctl */ 0, getuid, /* 24 = getuid */ 0, geteuid, /* 25 = geteuid */ 4, ptrace, /* 26 = ptrace */ 0, getppid, /* 27 = getppid */ 0, nosys, /* 28 = old fstat */ 0, nosys, /* 29 = old pause */ 0, nosys, /* 30 = old utime */ 0, nosys, /* 31 = was stty */ 0, nosys, /* 32 = was gtty */ 2, saccess, /* 33 = access */ 0, nosys, /* 34 = old nice */ 0, nosys, /* 35 = old ftime */ 0, sync, /* 36 = sync */ 2, kill, /* 37 = kill */ 2, stat, /* 38 = stat */ 0, nosys, /* 39 = old setpgrp */ 2, lstat, /* 40 = lstat */ 1, dup, /* 41 = dup */ 0, pipe, /* 42 = pipe */ 0, nosys, /* 43 = old times */ 4, profil, /* 44 = profil */ 0, nosys, /* 45 = nosys */ 0, nosys, /* 46 = old setgid */ 0, getgid, /* 47 = getgid */ 0, getegid, /* 48 = getegid */ 0, nosys, /* 49 = reserved for USG */ 0, nosys, /* 50 = reserved for USG */ 1, sysacct, /* 51 = turn acct off/on */ 3, phys, /* 52 = (2.9) set phys addr */ 1, lock, /* 53 = (2.9) lock in core */ 4, ioctl, /* 54 = ioctl */ 1, reboot, /* 55 = reboot */ 0, nosys, /* 56 = old mpxchan */ 2, symlink, /* 57 = symlink */ 3, readlink, /* 58 = readlink */ 3, execve, /* 59 = execve */ 1, umask, /* 60 = umask */ 1, chroot, /* 61 = chroot */ 2, fstat, /* 62 = fstat */ 0, nosys, /* 63 = reserved */ 0, getpagesize, /* 64 = getpagesize */ 0, nosys, /* 65 = (4.3) mremap */ 0, vfork, /* 66 = vfork */ 0, nosys, /* 67 = (4.3) old vread */ 0, nosys, /* 68 = (4.3) old vwrite */ 1, sbrk, /* 69 = sbrk */ 0, nosys, /* 70 = (4.3) sstk */ 0, nosys, /* 71 = (4.3) mmap */ 0, nosys, /* 72 = (4.3) old vadvise */ 0, nosys, /* 73 = (4.3) munmap */ 0, nosys, /* 74 = (4.3) mprotect */ 0, nosys, /* 75 = (4.3) madvise */ 0, vhangup, /* 76 = vhangup */ 0, nosys, /* 77 = (4.3) old vlimit */ 0, nosys, /* 78 = (4.3) mincore */ 2, getgroups, /* 79 = getgroups */ 2, setgroups, /* 80 = setgroups */ 1, getpgrp, /* 81 = getpgrp */ 2, setpgrp, /* 82 = setpgrp */ 3, setitimer, /* 83 = setitimer */ 0, owait, /* 84 = wait,wait3 (compatibility) */ 0, nosys, /* 85 = (4.3) swapon */ 2, getitimer, /* 86 = getitimer */ 2, gethostname, /* 87 = gethostname */ 2, sethostname, /* 88 = sethostname */ 0, getdtablesize, /* 89 = getdtablesize */ 2, dup2, /* 90 = dup2 */ 0, nosys, /* 91 = unused */ 3, fcntl, /* 92 = fcntl */ 5, select, /* 93 = select */ 0, nosys, /* 94 = unused */ 1, fsync, /* 95 = fsync */ 3, setpriority, /* 96 = setpriority */ errnet(3, socket), /* 97 = socket */ ifnet(3, connect), /* 98 = connect */ ifnet(3, accept), /* 99 = accept */ 2, getpriority, /* 100 = getpriority */ ifnet(4, send), /* 101 = send */ ifnet(4, recv), /* 102 = recv */ 1, sigreturn, /* 103 = sigreturn */ ifnet(3, bind), /* 104 = bind */ ifnet(5, setsockopt), /* 105 = setsockopt */ ifnet(2, listen), /* 106 = listen */ 0, nosys, /* 107 = (4.3) old vtimes */ 4, sigvec, /* 108 = sigvec */ 2, sigblock, /* 109 = sigblock */ 2, sigsetmask, /* 110 = sigsetmask */ 2, sigpause, /* 111 = sigpause */ 2, sigstack, /* 112 = sigstack */ ifnet(3, recvmsg), /* 113 = recvmsg */ ifnet(3, sendmsg), /* 114 = sendmsg */ 0, nosys, /* 115 = (4.3) vtrace */ 2, gettimeofday, /* 116 = gettimeofday */ 2, getrusage, /* 117 = getrusage */ ifnet(5, getsockopt), /* 118 = getsockopt */ 0, nosys, /* 119 = (4.3) (vax) resuba */ 3, readv, /* 120 = readv */ 3, writev, /* 121 = writev */ 2, settimeofday, /* 122 = settimeofday */ 3, fchown, /* 123 = fchown */ 2, fchmod, /* 124 = fchmod */ ifnet(6, recvfrom), /* 125 = recvfrom */ 2, setreuid, /* 126 = setreuid */ 2, setregid, /* 127 = setregid */ 2, rename, /* 128 = rename */ 3, truncate, /* 129 = truncate */ 3, ftruncate, /* 130 = ftruncate */ 2, flock, /* 131 = flock */ 0, nosys, /* 132 = nosys */ ifnet(6, sendto), /* 133 = sendto */ ifnet(2, shutdown), /* 134 = shutdown */ errnet(4, socketpair), /* 135 = socketpair */ 2, mkdir, /* 136 = mkdir */ 1, rmdir, /* 137 = rmdir */ 2, utimes, /* 138 = utimes */ 0, nosys, /* 139 = internal (4.2 sigreturn) */ 2, adjtime, /* 140 = adjtime */ ifnet(3, getpeername), /* 141 = getpeername */ 0, gethostid, /* 142 = gethostid */ 2, sethostid, /* 143 = sethostid */ 2, getrlimit, /* 144 = getrlimit */ 2, setrlimit, /* 145 = setrlimit */ 2, killpg, /* 146 = killpg */ 0, nosys, /* 147 = nosys */ 2, setquota, /* 148 = quota */ 4, qquota, /* 149 = qquota */ ifnet(3, getsockname), /* 150 = getsockname */ /* * Syscalls 151-180 inclusive are reserved for vendor-specific * system calls. (This includes various calls added for compatibity * with other Unix variants.) */ /* * 2BSD special calls */ 0, nosys, /* 151 = unused (old 2.9 rtp) */ 0, nostk, /* 152 = nostk */ 1, fetchi, /* 153 = fetchi */ 4, ucall, /* 154 = ucall */ 0, fperr, /* 155 = fperr */ 1, gldav, /* 156 = gldav */ }; int nsysent = sizeof (sysent) / sizeof (sysent[0]); tty *tp; { register char *cp; register int savecol; int s; char *nextc(); if ((tp->t_flags&ECHO) == 0) return; tp->t_flags &= ~sys/sys/tty_subr.c 440 0 12 26203 4115141416 7515 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)tty_subr.c 1.1 (2.10BSD Berkeley) 12/1/86 */ #include "param.h" #include "../machine/seg.h" #include "clist.h" #include "ioctl.h" #include "tty.h" #ifdef UCB_CLIST /* * Modification to move clists out of kernel data space. * Clist space is allocated by startup. */ memaddr clststrt; /* physical click address of clist */ struct cblock *cfree = (struct cblock *)SEG5; #endif char cwaiting; /* * Character list get/put */ getc(p) register struct clist *p; { register struct cblock *bp; register int c, s; #ifdef UCB_CLIST segm sav5; #endif s = spltty(); #ifdef UCB_CLIST saveseg5(sav5); mapseg5(clststrt, clstdesc); #endif if (p->c_cc <= 0) { c = -1; p->c_cc = 0; p->c_cf = p->c_cl = NULL; } else { c = *p->c_cf++ & 0377; if (--p->c_cc<=0) { bp = (struct cblock *)(p->c_cf-1); bp = (struct cblock *)((int)bp & ~CROUND); p->c_cf = NULL; p->c_cl = NULL; bp->c_next = cfreelist; cfreelist = bp; cfreecount += CBSIZE; if (cwaiting) { wakeup(&cwaiting); cwaiting = 0; } } else if (((int)p->c_cf & CROUND) == 0){ bp = (struct cblock *)(p->c_cf); bp--; p->c_cf = bp->c_next->c_info; bp->c_next = cfreelist; cfreelist = bp; cfreecount += CBSIZE; if (cwaiting) { wakeup(&cwaiting); cwaiting = 0; } } } #ifdef UCB_CLIST restorseg5(sav5); #endif splx(s); return (c); } /* * copy clist to buffer. * return number of bytes moved. */ q_to_b(q, cp, cc) register struct clist *q; char *cp; { register struct cblock *bp; register nc; int s; char *acp; #ifdef UCB_CLIST segm sav5; #endif if (cc <= 0) return (0); s = spltty(); #ifdef UCB_CLIST saveseg5(sav5); mapseg5(clststrt, clstdesc); #endif if (q->c_cc <= 0) { q->c_cc = 0; q->c_cf = q->c_cl = NULL; #ifdef UCB_CLIST restorseg5(sav5); #endif splx(s); return (0); } acp = cp; while (cc) { nc = sizeof (struct cblock) - ((int)q->c_cf & CROUND); nc = MIN(nc, cc); nc = MIN(nc, q->c_cc); (void) bcopy(q->c_cf, cp, (unsigned)nc); q->c_cf += nc; q->c_cc -= nc; cc -= nc; cp += nc; if (q->c_cc <= 0) { bp = (struct cblock *)(q->c_cf - 1); bp = (struct cblock *)((int)bp & ~CROUND); q->c_cf = q->c_cl = NULL; bp->c_next = cfreelist; cfreelist = bp; cfreecount += CBSIZE; if (cwaiting) { wakeup(&cwaiting); cwaiting = 0; } break; } if (((int)q->c_cf & CROUND) == 0) { bp = (struct cblock *)(q->c_cf); bp--; q->c_cf = bp->c_next->c_info; bp->c_next = cfreelist; cfreelist = bp; cfreecount += CBSIZE; if (cwaiting) { wakeup(&cwaiting); cwaiting = 0; } } } #ifdef UCB_CLIST restorseg5(sav5); #endif splx(s); return (cp-acp); } /* * Return count of contiguous characters * in clist starting at q->c_cf. * Stop counting if flag&character is non-null. */ ndqb(q, flag) register struct clist *q; { int cc; int s; #ifdef UCB_CLIST segm sav5; #endif s = spltty(); if (q->c_cc <= 0) { cc = -q->c_cc; goto out; } cc = ((int)q->c_cf + CBSIZE) & ~CROUND; cc -= (int)q->c_cf; if (q->c_cc < cc) cc = q->c_cc; if (flag) { register char *p, *end; #ifdef UCB_CLIST saveseg5(sav5); mapseg5(clststrt, clstdesc); #endif p = q->c_cf; end = p; end += cc; while (p < end) { if (*p & flag) { cc = (int)p; cc -= (int)q->c_cf; break; } p++; } #ifdef UCB_CLIST restorseg5(sav5); #endif } out: splx(s); return (cc); } /* * Flush cc bytes from q. */ ndflush(q, cc) register struct clist *q; register cc; { register struct cblock *bp; char *end; int rem, s; #ifdef UCB_CLIST segm sav5; #endif s = spltty(); if (q->c_cc <= 0) goto out; #ifdef UCB_CLIST saveseg5(sav5); mapseg5(clststrt, clstdesc); #endif while (cc>0 && q->c_cc) { bp = (struct cblock *)((int)q->c_cf & ~CROUND); if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) { end = q->c_cl; } else { end = (char *)((int)bp + sizeof (struct cblock)); } rem = end - q->c_cf; if (cc >= rem) { cc -= rem; q->c_cc -= rem; q->c_cf = bp->c_next->c_info; bp->c_next = cfreelist; cfreelist = bp; cfreecount += CBSIZE; if (cwaiting) { wakeup(&cwaiting); cwaiting = 0; } } else { q->c_cc -= cc; q->c_cf += cc; if (q->c_cc <= 0) { bp->c_next = cfreelist; cfreelist = bp; cfreecount += CBSIZE; if (cwaiting) { wakeup(&cwaiting); cwaiting = 0; } } break; } } #ifdef UCB_CLIST restorseg5(sav5); #endif if (q->c_cc <= 0) { q->c_cf = q->c_cl = NULL; q->c_cc = 0; } out: splx(s); } putc(c, p) register struct clist *p; { register struct cblock *bp; register char *cp; register s; #ifdef UCB_CLIST segm sav5; #endif s = spltty(); #ifdef UCB_CLIST saveseg5(sav5); mapseg5(clststrt, clstdesc); #endif if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { if ((bp = cfreelist) == NULL) { splx(s); #ifdef UCB_CLIST restorseg5(sav5); #endif return (-1); } cfreelist = bp->c_next; cfreecount -= CBSIZE; bp->c_next = NULL; p->c_cf = cp = bp->c_info; } else if (((int)cp & CROUND) == 0) { bp = (struct cblock *)cp - 1; if ((bp->c_next = cfreelist) == NULL) { splx(s); #ifdef UCB_CLIST restorseg5(sav5); #endif return (-1); } bp = bp->c_next; cfreelist = bp->c_next; cfreecount -= CBSIZE; bp->c_next = NULL; cp = bp->c_info; } *cp++ = c; p->c_cc++; p->c_cl = cp; #ifdef UCB_CLIST restorseg5(sav5); #endif splx(s); return (0); } /* * copy buffer to clist. * return number of bytes not transfered. */ b_to_q(cp, cc, q) register char *cp; struct clist *q; register int cc; { register char *cq; register struct cblock *bp; register s, nc; int acc; #ifdef UCB_CLIST segm sav5; #endif if (cc <= 0) return (0); acc = cc; s = spltty(); #ifdef UCB_CLIST saveseg5(sav5); mapseg5(clststrt, clstdesc); #endif if ((cq = q->c_cl) == NULL || q->c_cc < 0) { if ((bp = cfreelist) == NULL) goto out; cfreelist = bp->c_next; cfreecount -= CBSIZE; bp->c_next = NULL; q->c_cf = cq = bp->c_info; } while (cc) { if (((int)cq & CROUND) == 0) { bp = (struct cblock *)cq - 1; if ((bp->c_next = cfreelist) == NULL) goto out; bp = bp->c_next; cfreelist = bp->c_next; cfreecount -= CBSIZE; bp->c_next = NULL; cq = bp->c_info; } nc = MIN(cc, sizeof (struct cblock) - ((int)cq & CROUND)); (void) bcopy(cp, cq, (unsigned)nc); cp += nc; cq += nc; cc -= nc; } out: q->c_cl = cq; q->c_cc += acc - cc; #ifdef UCB_CLIST restorseg5(sav5); #endif splx(s); return (cc); } /* * Given a non-NULL pointter into the list (like c_cf which * always points to a real character if non-NULL) return the pointer * to the next character in the list or return NULL if no more chars. * * Callers must not allow getc's to happen between nextc's so that the * pointer becomes invalid. Note that interrupts are NOT masked. */ char * #ifdef UCB_CLIST nextc(p, cp, store) register struct clist *p; register char *cp; char *store; { register char *rcp; segm sav5; saveseg5(sav5); mapseg5(clststrt, clstdesc); #else nextc(p, cp) register struct clist *p; register char *cp; { register char *rcp; #endif if (p->c_cc && ++cp != p->c_cl) { if (((int)cp & CROUND) == 0) rcp = ((struct cblock *)cp)[-1].c_next->c_info; else rcp = cp; #ifdef UCB_CLIST *store = *rcp; #endif } else rcp = (char *)NULL; #ifdef UCB_CLIST restorseg5(sav5); #endif return (rcp); } #ifdef UCB_CLIST char lookc(cp) char *cp; { register char rc; segm sav5; saveseg5(sav5); mapseg5(clststrt, clstdesc); rc = *cp; restorseg5(sav5); return(rc); } #endif /* * Remove the last character in the list and return it. */ unputc(p) register struct clist *p; { register struct cblock *bp; register int c, s; struct cblock *obp; #ifdef UCB_CLIST segm sav5; #endif s = spltty(); #ifdef UCB_CLIST saveseg5(sav5); mapseg5(clststrt, clstdesc); #endif if (p->c_cc <= 0) c = -1; else { c = *--p->c_cl; if (--p->c_cc <= 0) { bp = (struct cblock *)p->c_cl; bp = (struct cblock *)((int)bp & ~CROUND); p->c_cl = p->c_cf = NULL; bp->c_next = cfreelist; cfreelist = bp; cfreecount += CBSIZE; } else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) { p->c_cl = (char *)((int)p->c_cl & ~CROUND); bp = (struct cblock *)p->c_cf; bp = (struct cblock *)((int)bp & ~CROUND); while (bp->c_next != (struct cblock *)p->c_cl) bp = bp->c_next; obp = bp; p->c_cl = (char *)(bp + 1); bp = bp->c_next; bp->c_next = cfreelist; cfreelist = bp; cfreecount += CBSIZE; obp->c_next = NULL; } } #ifdef UCB_CLIST restorseg5(sav5); #endif splx(s); return (c); } /* * Put the chars in the from que * on the end of the to que. */ catq(from, to) register struct clist *from, *to; { char bbuf[CBSIZE*4]; register c; int s; s = spltty(); if (to->c_cc == 0) { *to = *from; from->c_cc = 0; from->c_cf = NULL; from->c_cl = NULL; splx(s); return; } splx(s); while (from->c_cc > 0) { c = q_to_b(from, bbuf, sizeof bbuf); (void) b_to_q(bbuf, c, to); } } #ifdef unneeded /* * Integer (short) get/put using clists. * Note dependency on byte order. */ typedef u_short word_t; getw(p) register struct clist *p; { register int s, c; register struct cblock *bp; if (p->c_cc <= 1) return(-1); if (p->c_cc & 01) { c = getc(p); #if defined(vax) return (c | (getc(p)<<8)); #else return (getc(p) | (c<<8)); #endif } s = spltty(); #if defined(vax) c = *((word_t *)p->c_cf); #else c = (((u_char *)p->c_cf)[1] << 8) | ((u_char *)p->c_cf)[0]; #endif p->c_cf += sizeof (word_t); p->c_cc -= sizeof (word_t); if (p->c_cc <= 0) { bp = (struct cblock *)(p->c_cf-1); bp = (struct cblock *)((int)bp & ~CROUND); p->c_cf = NULL; p->c_cl = NULL; bp->c_next = cfreelist; cfreelist = bp; cfreecount += CBSIZE; if (cwaiting) { wakeup(&cwaiting); cwaiting = 0; } } else if (((int)p->c_cf & CROUND) == 0) { bp = (struct cblock *)(p->c_cf); bp--; p->c_cf = bp->c_next->c_info; bp->c_next = cfreelist; cfreelist = bp; cfreecount += CBSIZE; if (cwaiting) { wakeup(&cwaiting); cwaiting = 0; } } splx(s); return (c); } putw(c, p) register struct clist *p; word_t c; { register s; register struct cblock *bp; register char *cp; s = spltty(); if (cfreelist==NULL) { splx(s); return(-1); } if (p->c_cc & 01) { #if defined(vax) (void) putc(c, p); (void) putc(c>>8, p); #else (void) putc(c>>8, p); (void) putc(c, p); #endif } else { if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { if ((bp = cfreelist) == NULL) { splx(s); return (-1); } cfreelist = bp->c_next; cfreecount -= CBSIZE; bp->c_next = NULL; p->c_cf = cp = bp->c_info; } else if (((int)cp & CROUND) == 0) { bp = (struct cblock *)cp - 1; if ((bp->c_next = cfreelist) == NULL) { splx(s); return (-1); } bp = bp->c_next; cfreelist = bp->c_next; cfreecount -= CBSIZE; bp->c_next = NULL; cp = bp->c_info; } #if defined(vax) *(word_t *)cp = c; #else ((u_char *)cp)[0] = c>>8; ((u_char *)cp)[1] = c; #endif p->c_cl = cp + sizeof (word_t); p->c_cc += sizeof (word_t); } splx(s); return (0); } #endif unneeded /* * Reprint the rawq line. * We assume c_cc has already been checked. */ ttyretype(tp) register struct tty *tp; { register char *cp; char *nextc(); int s; if (tp->t_rprntc != 0377) ttyecho(tp->t_rprntc, tp); (void) ttyoutput('\n', tp); s = spltty(); #ifdef UCB_CLIST { char store; if (cp = tp->t_canq.c_cf) store = lookc(cp); for (; cp; cp = nextc(&tp->t_canqsys/sys/init_main.c 440 0 12 26424 5760252227 7630 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)init_main.c 1.9 (2.11BSD GTE) 1995/05/22 */ #include "param.h" #include "../machine/seg.h" #include "user.h" #include "fs.h" #include "mount.h" #include "map.h" #include "proc.h" #include "ioctl.h" #include "inode.h" #include "conf.h" #include "buf.h" #include "fcntl.h" #include "vm.h" #include "clist.h" #include "uba.h" #include "reboot.h" #include "systm.h" #include "kernel.h" #include "namei.h" #include "disklabel.h" #include "stat.h" #ifdef QUOTA #include "quota.h" #endif int netoff = 1; int cmask = CMASK; int securelevel; extern size_t physmem; extern struct mapent _coremap[]; /* * Initialization code. * Called from cold start routine as * soon as a stack and segmentation * have been established. * Functions: * clear and free user core * turn on clock * hand craft 0th process * call all initialization routines * fork - process 0 to schedule * - process 1 execute bootstrap */ main() { extern dev_t bootdev; extern caddr_t bootcsr; register struct proc *p; register int i; register struct fs *fs; time_t toytime, toyclk(); daddr_t swsize; int (*ioctl)(); struct partinfo dpart; startup(); /* * set up system process 0 (swapper) */ p = &proc[0]; p->p_addr = *ka6; p->p_stat = SRUN; p->p_flag |= SLOAD|SSYS; p->p_nice = NZERO; u.u_procp = p; /* init user structure */ u.u_ap = u.u_arg; u.u_nd.ni_iov = &u.u_nd.ni_iovec; u.u_nd.ni_iovcnt = 1; u.u_cmask = cmask; u.u_lastfile = -1; for (i = 1; i < NGROUPS; i++) u.u_groups[i] = NOGROUP; for (i = 0; i < sizeof(u.u_rlimit)/sizeof(u.u_rlimit[0]); i++) u.u_rlimit[i].rlim_cur = u.u_rlimit[i].rlim_max = RLIM_INFINITY; /* * Initialize tables, protocols, and set up well-known inodes. */ cinit(); pqinit(); xinit(); ihinit(); bhinit(); binit(); ubinit(); #ifdef QUOTA QUOTAMAP(); qtinit(); u.u_quota = getquota(0, 0, Q_NDQ); QUOTAUNMAP(); #endif nchinit(); clkstart(); #ifdef GENERIC /* * If this is the GENERIC kernel we set 'rootdev' to be the same as * the device booted from. 'swapdev' is set to the the 'b' partition * of 'bootdev'. Set 'pipedev' to be 'rootdev'. The 077 in the first * statement removes the controller number (bits 6 and 7) - those bits * are passed thru from /boot but would only greatly confuse the rest * of the kernel. */ rootdev = makedev(major(bootdev), minor(bootdev) & 077); swapdev = rootdev | 1; /* partition 'b' */ pipedev = rootdev; dumpdev = NODEV; /* paranoia */ #endif /* * Need to attach the root device. The CSR is passed thru because this * may be a 2nd or 3rd controller rather than the 1st. NOTE: This poses * a big problem if 'swapdev' is not on the same controller as 'rootdev' * _or_ if 'swapdev' itself is on a 2nd or 3rd controller. Short of moving * autconfigure back in to the kernel it is not known what can be done about * this. * * One solution (for now) is to call swapdev's attach routine with a zero * address. The MSCP driver treats the 0 as a signal to perform the * old (fixed address) attach. Drivers (all the rest at this point) which * do not support alternate controller booting always attach the first * (primary) CSR and do not expect an argument to be passed. */ (void)(*bdevsw[major(bootdev)].d_root)(bootcsr); (void)(*bdevsw[major(swapdev)].d_root)((caddr_t) 0); /* XXX */ /* * Now we find out how much swap space is available. Since 'nswap' is * a "u_int" we have to restrict the amount of swap to 65535 sectors (~32mb). * Considering that 4mb is the maximum physical memory capacity of a pdp-11 * 32mb swap should be enough ;-) * * The initialization of the swap map was moved here from machdep2.c because * 'nswap' was no longer statically defined and this is where the swap dev * is opened/initialized. * * Also, we toss away/ignore .5kb (1 sector) of swap space (because a 0 value * can not be placed in a resource map). * * 'swplo' was a hack which has _finally_ gone away! It was never anything * but 0 and caused a number of double word adds in the kernel. */ (*bdevsw[major(swapdev)].d_open)(swapdev, FREAD|FWRITE, S_IFBLK); swsize = (*bdevsw[major(swapdev)].d_psize)(swapdev); if (swsize <= 0) panic("swsiz"); /* don't want to panic, but what ? */ /* * Next we make sure that we do not swap on a partition unless it is of * type FS_SWAP. If the driver does not have an ioctl entry point or if * retrieving the partition information fails then the driver does not * support labels and we proceed normally, otherwise the partition must be * a swap partition (so that we do not swap on top of a filesystem by mistake). */ ioctl = cdevsw[major(swapdev)].d_ioctl; if (ioctl && !(*ioctl)(swapdev, DIOCGPART, (caddr_t)&dpart, FREAD)) { if (dpart.part->p_fstype != FS_SWAP) panic("swtyp"); } if (swsize > (daddr_t)65535) swsize = 65535; nswap = swsize; mfree(swapmap, --nswap, 1); fs = mountfs(rootdev, boothowto & RB_RDONLY ? MNT_RDONLY : 0, (struct inode *)0); if (!fs) panic("iinit"); mount[0].m_inodp = (struct inode *)1; /* XXX */ fs->fs_fsmnt[0] = '/'; fs->fs_fsmnt[1] = '\0'; time.tv_sec = fs->fs_time; if (toytime = toyclk()) time.tv_sec = toytime; boottime = time; /* kick off timeout driven events by calling first time */ schedcpu(); /* set up the root file system */ rootdir = iget(rootdev, &mount[0].m_filsys, (ino_t)ROOTINO); iunlock(rootdir); u.u_cdir = iget(rootdev, &mount[0].m_filsys, (ino_t)ROOTINO); iunlock(u.u_cdir); u.u_rdir = NULL; #ifdef INET if (netoff = netinit()) printf("netinit failed\n"); else NETSTART(); #endif /* * This came from pdp/machdep2.c because the memory available statements * were being made _before_ memory for the networking code was allocated. * A side effect of moving this code is that network "attach" and MSCP * "online" messages can appear before the memory sizes. The (currently * safe) assumption is made that no 'free' calls are made so that the * size in the first entry of the core map is correct. */ printf("\nphys mem = %D\n", ctob((long)physmem)); printf("avail mem = %D\n", ctob((long)_coremap[0].m_size)); maxmem = MAXMEM; printf("user mem = %D\n", ctob((long)MAXMEM)); #if NRAM > 0 printf("ram disk = %D\n", ctob((long)ramsize)); #endif printf("\n"); /* * make init process */ if (newproc(0)) { expand((int)btoc(szicode), S_DATA); expand((int)1, S_STACK); /* one click of stack */ estabur((u_int)0, (u_int)btoc(szicode), (u_int)1, 0, RO); copyout((caddr_t)icode, (caddr_t)0, szicode); /* * return goes to location 0 of user init code * just copied out. */ return; } else sched(); } /* * Initialize hash links for buffers. */ static bhinit() { register int i; register struct bufhd *bp; for (bp = bufhash, i = 0; i < BUFHSZ; i++, bp++) bp->b_forw = bp->b_back = (struct buf *)bp; } memaddr bpaddr; /* physical click-address of buffers */ /* * Initialize the buffer I/O system by freeing * all buffers and setting all device buffer lists to empty. */ static binit() { register struct buf *bp; register int i; long paddr; for (bp = bfreelist; bp < &bfreelist[BQUEUES]; bp++) bp->b_forw = bp->b_back = bp->av_forw = bp->av_back = bp; paddr = ((long)bpaddr) << 6; for (i = 0; i < nbuf; i++, paddr += MAXBSIZE) { bp = &buf[i]; bp->b_dev = NODEV; bp->b_bcount = 0; bp->b_un.b_addr = (caddr_t)loint(paddr); bp->b_xmem = hiint(paddr); binshash(bp, &bfreelist[BQ_AGE]); bp->b_flags = B_BUSY|B_INVAL; brelse(bp); } } /* * Initialize clist by freeing all character blocks, then count * number of character devices. (Once-only routine) */ static cinit() { register int ccp; register struct cblock *cp; ccp = (int)cfree; #ifdef UCB_CLIST mapseg5(clststrt, clstdesc); /* don't save, we know it's normal */ #else ccp = (ccp + CROUND) & ~CROUND; #endif for (cp = (struct cblock *)ccp; cp <= &cfree[nclist - 1]; cp++) { cp->c_next = cfreelist; cfreelist = cp; cfreecount += CBSIZE; } #ifdef UCB_CLIST normalseg5(); #endif } #ifdef INET memaddr netdata; /* click address of start of net data */ /* * We are called here after all the other init routines (clist, inode, * unibusmap, etc...) have been called. Open the * file NETNIX and read the a.out header, based on that go allocate * memory and read the text+data into the memory. Set up supervisor page * registers, SDSA6 and SDSA7 have already been set up in mch_start.s. */ static char NETNIX[] = "/netnix"; static netinit() { register u_short *ap, *dp; register int i; struct exec ex; struct inode *ip; memaddr nettext; long lsize; off_t off; int initdata, netdsize, nettsize, ret, err, resid; char oneclick[ctob(1)]; register struct nameidata *ndp = &u.u_nd; ret = 1; ndp->ni_nameiop = LOOKUP | FOLLOW; ndp->ni_segflg = UIO_SYSSPACE; ndp->ni_dirp = NETNIX; if (!(ip = namei(ndp))) { printf("%s not found\n", NETNIX); goto leave; } if ((ip->i_mode & IFMT) != IFREG || !ip->i_size) { printf("%s bad inode\n", NETNIX); goto leave; } err = rdwri(UIO_READ, ip, &ex, sizeof (ex), (off_t)0, UIO_SYSSPACE, IO_UNIT, &resid); if (err || resid) { printf("%s header err %d\n", NETNIX, ret); goto leave; } if (ex.a_magic != A_MAGIC3) { printf("%s bad magic %o\n", NETNIX, ex.a_magic); goto leave; } lsize = (long)ex.a_data + (long)ex.a_bss; if (lsize > 48L * 1024L) { printf("%s too big %ld\n", NETNIX, lsize); goto leave; } nettsize = btoc(ex.a_text); nettext = (memaddr)malloc(coremap, nettsize); netdsize = btoc(ex.a_data + ex.a_bss); netdata = (memaddr)malloc(coremap, netdsize); initdata = ex.a_data >> 6; off = sizeof (ex); for (i = 0; i < nettsize; i++) { err = rdwri(UIO_READ, ip, oneclick, ctob(1), off, UIO_SYSSPACE, IO_UNIT, &resid); if (err || resid) goto release; mapseg5(nettext + i, 077406); bcopy(oneclick, SEG5, ctob(1)); off += ctob(1); normalseg5(); } for (i = 0; i < initdata; i++) { err = rdwri(UIO_READ, ip, oneclick, ctob(1), off, UIO_SYSSPACE, IO_UNIT, &resid); if (err || resid) goto release; mapseg5(netdata + i, 077406); bcopy(oneclick, SEG5, ctob(1)); normalseg5(); off += ctob(1); } if (ex.a_data & 077) { err = rdwri(UIO_READ, ip, oneclick, ex.a_data & 077, off, UIO_SYSSPACE, IO_UNIT, &resid); if (err || resid) { release: printf("%s err %d\n", NETNIX, err); mfree(coremap, nettsize, nettext); mfree(coremap, netdsize, netdata); nettsize = netdsize = 0; netdata = nettext = 0; goto leave; } mapseg5(netdata + i, 077406); /* i is set from above loop */ bcopy(oneclick, SEG5, ex.a_data & 077); normalseg5(); } for (i = 0, ap = SISA0, dp = SISD0; i < nettsize; i += stoc(1)) { *ap++ = nettext + i; *dp++ = ((stoc(1) - 1) << 8) | RO; } /* might have over run the length on the last one, patch it now */ if (i > nettsize) *--dp -= ((i - nettsize) << 8); for (i = 0, ap = SDSA0, dp = SDSD0; i < netdsize; i += stoc(1)) { *ap++ = netdata + i; *dp++ = ((stoc(1) - 1) << 8) | RW; } if (i > netdsize) *--dp -= ((i - netdsize) << 8); ret = 0; leave: if (ip) iput(ip); u.u_error = 0; ndp->ni_dirp = 0; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_endoff = 0; bzero(&u.u_ncache, sizeof(u.u_ncache)); bzero(&ndp->ni_dent, sizeof(ndp->ni_dent)); if (ndp->ni_pdir) { iput(ndp->ni_pdir); ndp->ni_pdir = 0; } return(ret); } #endif ; struct partinfo dpart; startup(); /* * set up system process 0 (swapper) */ p = &proc[0]; p->p_addr = *ka6; p->p_stat = SRUN; p->p_flag |= SLOAD|SSYS; p->p_nice = NZERO; u.u_procp = p; /* init user structure */ u.u_sys/sys/ufs_namei.c 440 0 0 105614 5666032262 7623 /* * Copyright (c) 1982 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ufs_namei.c 1.3 (2.11BSD GTE) 11/26/94 */ #include "param.h" #include "../machine/seg.h" #include "systm.h" #include "dir.h" #include "inode.h" #include "fs.h" #include "mount.h" #include "user.h" #include "buf.h" #include "namei.h" struct buf *blkatoff(); int dirchk = 0; /* * Structures associated with name cacheing. */ #define NCHHASH 16 /* size of hash table */ #if ((NCHHASH)&((NCHHASH)-1)) != 0 #define NHASH(h, i, d) ((unsigned)((h) + (i) + 13 * (int)(d)) % (NCHHASH)) #else #define NHASH(h, i, d) ((unsigned)((h) + (i) + 13 * (int)(d)) & ((NCHHASH)-1)) #endif union nchash { union nchash *nch_head[2]; struct namecache *nch_chain[2]; } nchash[NCHHASH]; #define nch_forw nch_chain[0] #define nch_back nch_chain[1] struct namecache *nchhead, **nchtail; /* LRU chain pointers */ struct nchstats nchstats; /* cache effectiveness statistics */ /* * Convert a pathname into a pointer to a locked inode. * This is a very central and rather complicated routine. * If the file system is not maintained in a strict tree hierarchy, * this can result in a deadlock situation (see comments in code below). * * The flag argument is LOOKUP, CREATE, or DELETE depending on whether * the name is to be looked up, created, or deleted. When CREATE or * DELETE is specified, information usable in creating or deleteing a * directory entry is also calculated. If flag has LOCKPARENT or'ed * into it and the target of the pathname exists, namei returns both * the target and its parent directory locked. When creating and * LOCKPARENT is specified, the target may not be ".". When deleting * and LOCKPARENT is specified, the target may be ".", but the caller * must check to insure it does an irele and iput instead of two iputs. * * The FOLLOW flag is set when symbolic links are to be followed * when they occur at the end of the name translation process. * Symbolic links are always followed for all other pathname * components other than the last. * * Name caching works as follows: * * Names found by directory scans are retained in a cache * for future reference. It is managed LRU, so frequently * used names will hang around. Cache is indexed by hash value * obtained from (ino,dev,name) where ino & dev refer to the * directory containing name. * * For simplicity (and economy of storage), names longer than * a maximum length of NCHNAMLEN are not cached; they occur * infrequently in any case, and are almost never of interest. * * Upon reaching the last segment of a path, if the reference * is for DELETE, or NOCACHE is set (rewrite), and the * name is located in the cache, it will be dropped. * * Overall outline of namei: * * copy in name * get starting directory * dirloop: * check accessibility of directory * dirloop2: * copy next component of name to ndp->ni_dent * handle degenerate case where name is null string * look for name in cache, if found, then if at end of path * and deleting or creating, drop it, else to haveino * search for name in directory, to found or notfound * notfound: * if creating, return locked directory, leaving info on avail. slots * else return error * found: * if at end of path and deleting, return information to allow delete * if at end of path and rewriting (CREATE and LOCKPARENT), lock target * inode and return info to allow rewrite * if .. and on mounted filesys, look in mount table for parent * if not at end, add name to cache; if at end and neither creating * nor deleting, add name to cache * haveino: * if symbolic link, massage name in buffer and continue at dirloop * if more components of name, do next level at dirloop * return the answer as locked inode * * NOTE: (LOOKUP | LOCKPARENT) currently returns the parent inode, * but unlocked. */ struct inode * namei(ndp) register struct nameidata *ndp; { register char *cp; /* pointer into pathname argument */ /* these variables refer to things which must be freed or unlocked */ struct inode *dp = 0; /* the directory we are searching */ struct namecache *ncp; /* cache slot for entry */ struct fs *fs; /* file system that directory is in */ struct buf *bp = 0; /* a buffer of directory entries */ struct direct *ep; /* the current directory entry */ int entryoffsetinblock; /* offset of ep in bp's buffer */ /* these variables hold information about the search for a slot */ enum {NONE, COMPACT, FOUND} slotstatus; off_t slotoffset = -1; /* offset of area with free space */ int slotsize; /* size of area at slotoffset */ int slotfreespace; /* amount of space free in slot */ int slotneeded; /* size of the entry we're seeking */ /* */ int numdirpasses; /* strategy for directory search */ off_t endsearch; /* offset to end directory search */ off_t prevoff; /* ndp->ni_offset of previous entry */ int nlink = 0; /* number of symbolic links taken */ struct inode *pdp; /* saved dp during symlink work */ register int i; int error; int lockparent; int docache; /* == 0 do not cache last component */ int makeentry; /* != 0 if name to be added to cache */ unsigned hash; /* value of name hash for entry */ union nchash *nhp; /* cache chain head for entry */ int isdotdot; /* != 0 if current name is ".." */ int flag; /* op ie, LOOKUP, CREATE, or DELETE */ off_t enduseful; /* pointer past last used dir slot */ char path[MAXPATHLEN]; /* current path */ segm seg5; /* save area for kernel seg5 */ lockparent = ndp->ni_nameiop & LOCKPARENT; docache = (ndp->ni_nameiop & NOCACHE) ^ NOCACHE; flag = ndp->ni_nameiop &~ (LOCKPARENT|NOCACHE|FOLLOW); if (flag == DELETE || lockparent) docache = 0; /* * Copy the name into the buffer. */ if (ndp->ni_segflg == UIO_SYSSPACE) error = copystr(ndp->ni_dirp, path, MAXPATHLEN, (u_int *)0); else error = copyinstr(ndp->ni_dirp, path, MAXPATHLEN, (u_int *)0); if (error) { u.u_error = error; return (NULL); } /* * Get starting directory. */ cp = path; if (*cp == '/') { while (*cp == '/') cp++; if ((dp = u.u_rdir) == NULL) dp = rootdir; } else dp = u.u_cdir; fs = dp->i_fs; ILOCK(dp); dp->i_count++; ndp->ni_endoff = 0; /* * We come to dirloop to search a new directory. * The directory must be locked so that it can be * iput, and fs must be already set to dp->i_fs. */ dirloop: /* * Check accessibility of directory. */ if ((dp->i_mode&IFMT) != IFDIR) { u.u_error = ENOTDIR; goto bad; } if (access(dp, IEXEC)) goto bad; dirloop2: /* * Copy next component of name to ndp->ni_dent. */ hash = 0; for (i = 0; *cp != 0 && *cp != '/'; cp++) { if (i >= MAXNAMLEN) { u.u_error = ENAMETOOLONG; goto bad; } if (*cp & 0200) if ((*cp&0377) == ('/'|0200) || flag != DELETE) { u.u_error = EINVAL; goto bad; } ndp->ni_dent.d_name[i++] = *cp; hash += (unsigned char)*cp * i; } ndp->ni_dent.d_namlen = i; ndp->ni_dent.d_name[i] = '\0'; isdotdot = (i == 2 && ndp->ni_dent.d_name[0] == '.' && ndp->ni_dent.d_name[1] == '.'); makeentry = 1; if (*cp == '\0' && docache == 0) makeentry = 0; /* * Check for degenerate name (e.g. / or "") * which is a way of talking about a directory, * e.g. like "/." or ".". */ if (ndp->ni_dent.d_name[0] == '\0') { if (flag != LOOKUP || lockparent) { u.u_error = EISDIR; goto bad; } return (dp); } /* * We now have a segment name to search for, and a directory to search. * * Before tediously performing a linear scan of the directory, * check the name cache to see if the directory/name pair * we are looking for is known already. We don't do this * if the segment name is long, simply so the cache can avoid * holding long names (which would either waste space, or * add greatly to the complexity). */ saveseg5(seg5); mapseg5(nmidesc.se_addr, nmidesc.se_desc); if (ndp->ni_dent.d_namlen > NCHNAMLEN) { nchstats.ncs_long++; makeentry = 0; } else { nhp = &nchash[NHASH(hash, dp->i_number, dp->i_dev)]; for (ncp = nhp->nch_forw; ncp != (struct namecache *)nhp; ncp = ncp->nc_forw) { if (ncp->nc_ino == dp->i_number && ncp->nc_dev == dp->i_dev && ncp->nc_nlen == ndp->ni_dent.d_namlen && !bcmp(ncp->nc_name, ndp->ni_dent.d_name, (unsigned)ncp->nc_nlen)) break; } if (ncp == (struct namecache *)nhp) { nchstats.ncs_miss++; ncp = NULL; } else { if (ncp->nc_id != ncp->nc_ip->i_id) nchstats.ncs_falsehits++; else if (!makeentry) nchstats.ncs_badhits++; else { /* * move this slot to end of LRU * chain, if not already there */ if (ncp->nc_nxt) { /* remove from LRU chain */ *ncp->nc_prev = ncp->nc_nxt; ncp->nc_nxt->nc_prev = ncp->nc_prev; /* and replace at end of it */ ncp->nc_nxt = NULL; ncp->nc_prev = nchtail; *nchtail = ncp; nchtail = &ncp->nc_nxt; } /* * Get the next inode in the path. * See comment above other `IUNLOCK' code for * an explaination of the locking protocol. */ pdp = dp; if (!isdotdot || dp != u.u_rdir) dp = ncp->nc_ip; if (dp == NULL) panic("namei: null cache ino"); if (pdp == dp) dp->i_count++; else if (isdotdot) { restorseg5(seg5); IUNLOCK(pdp); igrab(dp); mapseg5(nmidesc.se_addr,nmidesc.se_desc); } else { restorseg5(seg5); igrab(dp); IUNLOCK(pdp); mapseg5(nmidesc.se_addr,nmidesc.se_desc); } /* * Verify that the inode that we got * did not change while we were waiting * for it to be locked. */ if (ncp->nc_id != ncp->nc_ip->i_id) { restorseg5(seg5); iput(dp); ILOCK(pdp); mapseg5(nmidesc.se_addr,nmidesc.se_desc); dp = pdp; nchstats.ncs_falsehits++; } else { ndp->ni_dent.d_ino = dp->i_number; /* ni_dent.d_reclen is garbage ... */ nchstats.ncs_goodhits++; restorseg5(seg5); goto haveino; } } /* * Last component and we are renaming or deleting, * the cache entry is invalid, or otherwise don't * want cache entry to exist. */ /* remove from LRU chain */ *ncp->nc_prev = ncp->nc_nxt; if (ncp->nc_nxt) ncp->nc_nxt->nc_prev = ncp->nc_prev; else nchtail = ncp->nc_prev; remque(ncp); /* remove from hash chain */ /* insert at head of LRU list (first to grab) */ ncp->nc_nxt = nchhead; ncp->nc_prev = &nchhead; nchhead->nc_prev = &ncp->nc_nxt; nchhead = ncp; /* and make a dummy hash chain */ ncp->nc_forw = ncp; ncp->nc_back = ncp; ncp = NULL; } } restorseg5(seg5); /* * Suppress search for slots unless creating * file and at end of pathname, in which case * we watch for a place to put the new file in * case it doesn't already exist. */ slotstatus = FOUND; if (flag == CREATE && *cp == 0) { slotstatus = NONE; slotfreespace = 0; slotneeded = DIRSIZ(&ndp->ni_dent); } /* * If this is the same directory that this process * previously searched, pick up where we last left off. * We cache only lookups as these are the most common * and have the greatest payoff. Caching CREATE has little * benefit as it usually must search the entire directory * to determine that the entry does not exist. Caching the * location of the last DELETE has not reduced profiling time * and hence has been removed in the interest of simplicity. */ if (flag != LOOKUP || dp->i_number != u.u_ncache.nc_inumber || dp->i_dev != u.u_ncache.nc_dev) { ndp->ni_offset = 0; numdirpasses = 1; } else { if (u.u_ncache.nc_prevoffset > dp->i_size) u.u_ncache.nc_prevoffset = 0; ndp->ni_offset = u.u_ncache.nc_prevoffset; entryoffsetinblock = blkoff(ndp->ni_offset); if (entryoffsetinblock != 0) { bp = blkatoff(dp, ndp->ni_offset, (char **)0); if (bp == 0) goto bad; } numdirpasses = 2; nchstats.ncs_2passes++; } endsearch = roundup(dp->i_size, DIRBLKSIZ); enduseful = 0; searchloop: while (ndp->ni_offset < endsearch) { /* * If offset is on a block boundary, * read the next directory block. * Release previous if it exists. */ if (blkoff(ndp->ni_offset) == 0) { if (bp != NULL) { mapout(bp); brelse(bp); } bp = blkatoff(dp, ndp->ni_offset, (char **)0); if (bp == 0) goto bad; entryoffsetinblock = 0; } /* * If still looking for a slot, and at a DIRBLKSIZE * boundary, have to start looking for free space again. */ if (slotstatus == NONE && (entryoffsetinblock&(DIRBLKSIZ-1)) == 0) { slotoffset = -1; slotfreespace = 0; } /* * Get pointer to next entry. * Full validation checks are slow, so we only check * enough to insure forward progress through the * directory. Complete checks can be run by patching * "dirchk" to be true. */ mapout(bp); /* XXX - avoid double mapin */ ep = (struct direct *)((caddr_t)mapin(bp)+ entryoffsetinblock); if (ep->d_reclen == 0 || dirchk && dirbadentry(ep, entryoffsetinblock)) { dirbad(dp, ndp->ni_offset, "mangled entry"); i = DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)); ndp->ni_offset += i; entryoffsetinblock += i; continue; } /* * If an appropriate sized slot has not yet been found, * check to see if one is available. Also accumulate space * in the current block so that we can determine if * compaction is viable. */ if (slotstatus != FOUND) { int size = ep->d_reclen; if (ep->d_ino != 0) size -= DIRSIZ(ep); if (size > 0) { if (size >= slotneeded) { slotstatus = FOUND; slotoffset = ndp->ni_offset; slotsize = ep->d_reclen; } else if (slotstatus == NONE) { slotfreespace += size; if (slotoffset == -1) slotoffset = ndp->ni_offset; if (slotfreespace >= slotneeded) { slotstatus = COMPACT; slotsize = ndp->ni_offset + ep->d_reclen - slotoffset; } } } } /* * Check for a name match. */ if (ep->d_ino) { if (ep->d_namlen == ndp->ni_dent.d_namlen && !bcmp(ndp->ni_dent.d_name, ep->d_name, (unsigned)ep->d_namlen)) goto found; } prevoff = ndp->ni_offset; ndp->ni_offset += ep->d_reclen; entryoffsetinblock += ep->d_reclen; if (ep->d_ino) enduseful = ndp->ni_offset; } /* notfound: */ /* * If we started in the middle of the directory and failed * to find our target, we must check the beginning as well. */ if (numdirpasses == 2) { numdirpasses--; ndp->ni_offset = 0; endsearch = u.u_ncache.nc_prevoffset; goto searchloop; } /* * If creating, and at end of pathname and current * directory has not been removed, then can consider * allowing file to be created. */ if (flag == CREATE && *cp == 0 && dp->i_nlink != 0) { /* * Access for write is interpreted as allowing * creation of files in the directory. */ if (access(dp, IWRITE)) goto bad; /* * Return an indication of where the new directory * entry should be put. If we didn't find a slot, * then set ndp->ni_count to 0 indicating that the new * slot belongs at the end of the directory. If we found * a slot, then the new entry can be put in the range * [ndp->ni_offset .. ndp->ni_offset + ndp->ni_count) */ if (slotstatus == NONE) { ndp->ni_offset = roundup(dp->i_size, DIRBLKSIZ); ndp->ni_count = 0; enduseful = ndp->ni_offset; } else { ndp->ni_offset = slotoffset; ndp->ni_count = slotsize; if (enduseful < slotoffset + slotsize) enduseful = slotoffset + slotsize; } ndp->ni_endoff = roundup(enduseful, DIRBLKSIZ); dp->i_flag |= IUPD|ICHG; if (bp) { mapout(bp); brelse(bp); } /* * We return with the directory locked, so that * the parameters we set up above will still be * valid if we actually decide to do a direnter(). * We return NULL to indicate that the entry doesn't * currently exist, leaving a pointer to the (locked) * directory inode in ndp->ni_pdir. */ ndp->ni_pdir = dp; return (NULL); } u.u_error = ENOENT; goto bad; found: if (numdirpasses == 2) nchstats.ncs_pass2++; /* * Check that directory length properly reflects presence * of this entry. */ if (entryoffsetinblock + DIRSIZ(ep) > dp->i_size) { dirbad(dp, ndp->ni_offset, "i_size too small"); dp->i_size = entryoffsetinblock + DIRSIZ(ep); dp->i_flag |= IUPD|ICHG; } /* * Found component in pathname. * If the final component of path name, save information * in the cache as to where the entry was found. */ if (*cp == '\0' && flag == LOOKUP) { u.u_ncache.nc_prevoffset = ndp->ni_offset &~ (DIRBLKSIZ - 1); u.u_ncache.nc_inumber = dp->i_number; u.u_ncache.nc_dev = dp->i_dev; } /* * Save directory entry's inode number and reclen in ndp->ni_dent, * and release directory buffer. */ ndp->ni_dent.d_ino = ep->d_ino; ndp->ni_dent.d_reclen = ep->d_reclen; mapout(bp); brelse(bp); bp = NULL; /* * If deleting, and at end of pathname, return * parameters which can be used to remove file. * If the lockparent flag isn't set, we return only * the directory (in ndp->ni_pdir), otherwise we go * on and lock the inode, being careful with ".". */ if (flag == DELETE && *cp == 0) { /* * Write access to directory required to delete files. */ if (access(dp, IWRITE)) goto bad; ndp->ni_pdir = dp; /* for dirremove() */ /* * Return pointer to current entry in ndp->ni_offset, * and distance past previous entry (if there * is a previous entry in this block) in ndp->ni_count. * Save directory inode pointer in ndp->ni_pdir for dirremove(). */ if ((ndp->ni_offset&(DIRBLKSIZ-1)) == 0) ndp->ni_count = 0; else ndp->ni_count = ndp->ni_offset - prevoff; if (lockparent) { if (dp->i_number == ndp->ni_dent.d_ino) dp->i_count++; else { dp = iget(dp->i_dev, fs, ndp->ni_dent.d_ino); if (dp == NULL) { iput(ndp->ni_pdir); goto bad; } /* * If directory is "sticky", then user must own * the directory, or the file in it, else he * may not delete it (unless he's root). This * implements append-only directories. */ if ((ndp->ni_pdir->i_mode & ISVTX) && u.u_uid != 0 && u.u_uid != ndp->ni_pdir->i_uid && dp->i_uid != u.u_uid) { iput(ndp->ni_pdir); u.u_error = EPERM; goto bad; } } } return (dp); } /* * Special handling for ".." allowing chdir out of mounted * file system: indirect .. in root inode to reevaluate * in directory file system was mounted on. */ if (isdotdot) { if (dp == u.u_rdir) { ndp->ni_dent.d_ino = dp->i_number; makeentry = 0; } else if (ndp->ni_dent.d_ino == ROOTINO && dp->i_number == ROOTINO) { register struct mount *mp; register dev_t d; d = dp->i_dev; for (mp = &mount[1]; mp < &mount[NMOUNT]; mp++) if (mp->m_inodp && mp->m_dev == d) { iput(dp); dp = mp->m_inodp; ILOCK(dp); dp->i_count++; fs = dp->i_fs; cp -= 2; /* back over .. */ goto dirloop2; } } } /* * If rewriting (rename), return the inode and the * information required to rewrite the present directory * Must get inode of directory entry to verify it's a * regular file, or empty directory. */ if ((flag == CREATE && lockparent) && *cp == 0) { if (access(dp, IWRITE)) goto bad; ndp->ni_pdir = dp; /* for dirrewrite() */ /* * Careful about locking second inode. * This can only occur if the target is ".". */ if (dp->i_number == ndp->ni_dent.d_ino) { u.u_error = EISDIR; /* XXX */ goto bad; } dp = iget(dp->i_dev, fs, ndp->ni_dent.d_ino); if (dp == NULL) { iput(ndp->ni_pdir); goto bad; } return (dp); } /* * Check for symbolic link, which may require us to massage the * name before we continue translation. We do not `iput' the * directory because we may need it again if the symbolic link * is relative to the current directory. Instead we save it * unlocked as "pdp". We must get the target inode before unlocking * the directory to insure that the inode will not be removed * before we get it. We prevent deadlock by always fetching * inodes from the root, moving down the directory tree. Thus * when following backward pointers ".." we must unlock the * parent directory before getting the requested directory. * There is a potential race condition here if both the current * and parent directories are removed before the `iget' for the * inode associated with ".." returns. We hope that this occurs * infrequently since we cannot avoid this race condition without * implementing a sophisticated deadlock detection algorithm. * Note also that this simple deadlock detection scheme will not * work if the file system has any hard links other than ".." * that point backwards in the directory structure. */ pdp = dp; if (isdotdot) { IUNLOCK(pdp); /* race to get the inode */ dp = iget(dp->i_dev, fs, ndp->ni_dent.d_ino); if (dp == NULL) goto bad2; } else if (dp->i_number == ndp->ni_dent.d_ino) { dp->i_count++; /* we want ourself, ie "." */ } else { dp = iget(dp->i_dev, fs, ndp->ni_dent.d_ino); IUNLOCK(pdp); if (dp == NULL) goto bad2; } /* * Insert name into cache if appropriate. */ if (makeentry) { if (ncp != NULL) panic("namei: duplicating cache"); /* * Free the cache slot at head of lru chain. */ if (ncp = nchhead) { saveseg5(seg5); mapseg5(nmidesc.se_addr, nmidesc.se_desc); /* remove from lru chain */ *ncp->nc_prev = ncp->nc_nxt; if (ncp->nc_nxt) ncp->nc_nxt->nc_prev = ncp->nc_prev; else nchtail = ncp->nc_prev; remque(ncp); /* remove from old hash chain */ /* grab the inode we just found */ ncp->nc_ip = dp; /* fill in cache info */ ncp->nc_ino = pdp->i_number; /* parents inum */ ncp->nc_dev = pdp->i_dev; /* & device */ ncp->nc_idev = dp->i_dev; /* our device */ ncp->nc_id = dp->i_id; /* identifier */ ncp->nc_nlen = ndp->ni_dent.d_namlen; bcopy(ndp->ni_dent.d_name, ncp->nc_name, (unsigned)ncp->nc_nlen); /* link at end of lru chain */ ncp->nc_nxt = NULL; ncp->nc_prev = nchtail; *nchtail = ncp; nchtail = &ncp->nc_nxt; /* and insert on hash chain */ insque(ncp, nhp); restorseg5(seg5); } } haveino: fs = dp->i_fs; /* * Check for symbolic link */ if ((dp->i_mode & IFMT) == IFLNK && ((ndp->ni_nameiop & FOLLOW) || *cp == '/')) { u_int pathlen = strlen(cp) + 1; if (dp->i_size + pathlen >= MAXPATHLEN - 1) { u.u_error = ENAMETOOLONG; goto bad2; } if (++nlink > MAXSYMLINKS) { u.u_error = ELOOP; goto bad2; } bp = bread(dp->i_dev, bmap(dp, (daddr_t)0, B_READ, 0)); if (bp->b_flags & B_ERROR) { brelse(bp); bp = NULL; goto bad2; } /* * Shift the rest of path further down the buffer, then * copy link path into the first part of the buffer. */ bcopy(cp, path + (u_int)dp->i_size, pathlen); bcopy(mapin(bp), path, (u_int)dp->i_size); mapout(bp); brelse(bp); bp = NULL; cp = path; iput(dp); if (*cp == '/') { irele(pdp); while (*cp == '/') cp++; if ((dp = u.u_rdir) == NULL) dp = rootdir; ILOCK(dp); dp->i_count++; } else { dp = pdp; ILOCK(dp); } fs = dp->i_fs; goto dirloop; } /* * Not a symbolic link. If more pathname, * continue at next component, else return. */ if (*cp == '/') { while (*cp == '/') cp++; irele(pdp); goto dirloop; } if (lockparent) ndp->ni_pdir = pdp; else irele(pdp); return (dp); bad2: irele(pdp); bad: if (bp) { mapout(bp); brelse(bp); } if (dp) iput(dp); return (NULL); } dirbad(ip, offset, how) struct inode *ip; off_t offset; char *how; { printf("%s: bad dir ino %u at offset %ld: %s\n", ip->i_fs->fs_fsmnt, ip->i_number, offset, how); } /* * Do consistency checking on a directory entry: * record length must be multiple of 4 * entry must fit in rest of its DIRBLKSIZ block * record must be large enough to contain entry * name is not longer than MAXNAMLEN * name must be as long as advertised, and null terminated */ dirbadentry(ep, entryoffsetinblock) register struct direct *ep; int entryoffsetinblock; { register int i; if ((ep->d_reclen & 0x3) != 0 || ep->d_reclen > DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)) || ep->d_reclen < DIRSIZ(ep) || ep->d_namlen > MAXNAMLEN) return (1); for (i = 0; i < ep->d_namlen; i++) if (ep->d_name[i] == '\0') return (1); return (ep->d_name[i]); } /* * Write a directory entry after a call to namei, using the parameters * which it left in the u. area. The argument ip is the inode which * the new directory entry will refer to. The u. area field ndp->ni_pdir is * a pointer to the directory to be written, which was left locked by * namei. Remaining parameters (ndp->ni_offset, ndp->ni_count) indicate * how the space for the new entry is to be gotten. */ direnter(ip, ndp) struct inode *ip; register struct nameidata *ndp; { register struct direct *ep, *nep; register struct inode *dp = ndp->ni_pdir; struct buf *bp; int loc, spacefree, error = 0; u_int dsize; int newentrysize; char *dirbuf; ndp->ni_dent.d_ino = ip->i_number; newentrysize = DIRSIZ(&ndp->ni_dent); if (ndp->ni_count == 0) { /* * If ndp->ni_count is 0, then namei could find no space in the * directory. In this case ndp->ni_offset will be on a directory * block boundary and we will write the new entry into a fresh * block. */ if (ndp->ni_offset&(DIRBLKSIZ-1)) panic("wdir: newblk"); ndp->ni_dent.d_reclen = DIRBLKSIZ; error = rdwri(UIO_WRITE, dp, (caddr_t)&ndp->ni_dent, newentrysize, ndp->ni_offset, UIO_SYSSPACE, IO_UNIT|IO_SYNC, (int *)0); dp->i_size = roundup(dp->i_size, DIRBLKSIZ); iput(dp); return (error); } /* * If ndp->ni_count is non-zero, then namei found space for the new * entry in the range ndp->ni_offset to ndp->ni_offset + ndp->ni_count. * in the directory. To use this space, we may have to compact * the entries located there, by copying them together towards * the beginning of the block, leaving the free space in * one usable chunk at the end. */ /* * Increase size of directory if entry eats into new space. * This should never push the size past a new multiple of * DIRBLKSIZE. * * N.B. - THIS IS AN ARTIFACT OF 4.2 AND SHOULD NEVER HAPPEN. */ if (ndp->ni_offset + ndp->ni_count > dp->i_size) dp->i_size = ndp->ni_offset + ndp->ni_count; /* * Get the block containing the space for the new directory * entry. Should return error by result instead of u.u_error. */ bp = blkatoff(dp, ndp->ni_offset, (char **)&dirbuf); if (bp == 0) { iput(dp); return (u.u_error); } /* * Find space for the new entry. In the simple case, the * entry at offset base will have the space. If it does * not, then namei arranged that compacting the region * ndp->ni_offset to ndp->ni_offset+ndp->ni_count would yield the space. */ ep = (struct direct *)dirbuf; dsize = DIRSIZ(ep); spacefree = ep->d_reclen - dsize; for (loc = ep->d_reclen; loc < ndp->ni_count; ) { nep = (struct direct *)(dirbuf + loc); if (ep->d_ino) { /* trim the existing slot */ ep->d_reclen = dsize; ep = (struct direct *)((char *)ep + dsize); } else { /* overwrite; nothing there; header is ours */ spacefree += dsize; } dsize = DIRSIZ(nep); spacefree += nep->d_reclen - dsize; loc += nep->d_reclen; bcopy((caddr_t)nep, (caddr_t)ep, dsize); } /* * Update the pointer fields in the previous entry (if any), * copy in the new entry, and write out the block. */ if (ep->d_ino == 0) { if (spacefree + dsize < newentrysize) panic("wdir: compact1"); ndp->ni_dent.d_reclen = spacefree + dsize; } else { if (spacefree < newentrysize) panic("wdir: compact2"); ndp->ni_dent.d_reclen = spacefree; ep->d_reclen = dsize; ep = (struct direct *)((char *)ep + dsize); } bcopy((caddr_t)&ndp->ni_dent, (caddr_t)ep, (u_int)newentrysize); mapout(bp); bwrite(bp); dp->i_flag |= IUPD|ICHG; if (ndp->ni_endoff && ndp->ni_endoff < dp->i_size) itrunc(dp, (u_long)ndp->ni_endoff); iput(dp); return (error); } /* * Remove a directory entry after a call to namei, using the * parameters which it left in the u. area. The u. entry * ni_offset contains the offset into the directory of the * entry to be eliminated. The ni_count field contains the * size of the previous record in the directory. If this * is 0, the first entry is being deleted, so we need only * zero the inode number to mark the entry as free. If the * entry isn't the first in the directory, we must reclaim * the space of the now empty record by adding the record size * to the size of the previous entry. */ dirremove(ndp) register struct nameidata *ndp; { register struct inode *dp = ndp->ni_pdir; register struct buf *bp; struct direct *ep; if (ndp->ni_count == 0) { /* * First entry in block: set d_ino to zero. */ ndp->ni_dent.d_ino = 0; (void) rdwri(UIO_WRITE, dp, (caddr_t)&ndp->ni_dent, (int)DIRSIZ(&ndp->ni_dent), ndp->ni_offset, UIO_SYSSPACE, IO_UNIT|IO_SYNC, (int *)0); } else { /* * Collapse new free space into previous entry. */ bp = blkatoff(dp, ndp->ni_offset - ndp->ni_count, (char **)&ep); if (bp == 0) return (0); ep->d_reclen += ndp->ni_dent.d_reclen; mapout(bp); bwrite(bp); dp->i_flag |= IUPD|ICHG; } return (1); } /* * Rewrite an existing directory entry to point at the inode * supplied. The parameters describing the directory entry are * set up by a call to namei. */ dirrewrite(dp, ip, ndp) register struct inode *dp; struct inode *ip; register struct nameidata *ndp; { ndp->ni_dent.d_ino = ip->i_number; u.u_error = rdwri(UIO_WRITE, dp, (caddr_t)&ndp->ni_dent, (int)DIRSIZ(&ndp->ni_dent), ndp->ni_offset, UIO_SYSSPACE, IO_UNIT|IO_SYNC, (int *)0); iput(dp); } /* * Return buffer with contents of block "offset" * from the beginning of directory "ip". If "res" * is non-zero, fill it in with a pointer to the * remaining space in the directory. * * A mapin() of the buffer is done even if "res" is zero so that the * mapout() done later will have something to work with. */ struct buf * blkatoff(ip, offset, res) struct inode *ip; off_t offset; char **res; { register struct fs *fs = ip->i_fs; daddr_t lbn = lblkno(offset); register struct buf *bp; daddr_t bn; char *junk; bn = bmap(ip, lbn, B_READ, 0); if (u.u_error) return (0); if (bn == (daddr_t)-1) { dirbad(ip, offset, "hole in dir"); return (0); } bp = bread(ip->i_dev, bn); if (bp->b_flags & B_ERROR) { brelse(bp); return (0); } junk = (caddr_t)mapin(bp); if (res) *res = junk + (u_int)blkoff(offset); return (bp); } /* * Check if a directory is empty or not. * Inode supplied must be locked. * * Using a struct dirtemplate here is not precisely * what we want, but better than using a struct direct. * * NB: does not handle corrupted directories. */ dirempty(ip, parentino) register struct inode *ip; ino_t parentino; { register off_t off; struct dirtemplate dbuf; register struct direct *dp = (struct direct *)&dbuf; int error, count; #define MINDIRSIZ (sizeof (struct dirtemplate) / 2) for (off = 0; off < ip->i_size; off += dp->d_reclen) { error = rdwri(UIO_READ, ip, (caddr_t)dp, MINDIRSIZ, off, UIO_SYSSPACE, IO_UNIT, &count); /* * Since we read MINDIRSIZ, residual must * be 0 unless we're at end of file. */ if (error || count != 0) return (0); /* avoid infinite loops */ if (dp->d_reclen == 0) return (0); /* skip empty entries */ if (dp->d_ino == 0) continue; /* accept only "." and ".." */ if (dp->d_namlen > 2) return (0); if (dp->d_name[0] != '.') return (0); /* * At this point d_namlen must be 1 or 2. * 1 implies ".", 2 implies ".." if second * char is also "." */ if (dp->d_namlen == 1) continue; if (dp->d_name[1] == '.' && dp->d_ino == parentino) continue; return (0); } return (1); } /* * Check if source directory is in the path of the target directory. * Target is supplied locked, source is unlocked. * The target is always iput() before returning. */ checkpath(source, target) struct inode *source, *target; { struct dirtemplate dirbuf; register struct inode *ip; register int error = 0; ip = target; if (ip->i_number == source->i_number) { error = EEXIST; goto out; } if (ip->i_number == ROOTINO) goto out; for (;;) { if ((ip->i_mode&IFMT) != IFDIR) { error = ENOTDIR; break; } error = rdwri(UIO_READ, ip, (caddr_t)&dirbuf, sizeof(struct dirtemplate), (off_t)0, UIO_SYSSPACE, IO_UNIT, (int *)0); if (error != 0) break; if (dirbuf.dotdot_namlen != 2 || dirbuf.dotdot_name[0] != '.' || dirbuf.dotdot_name[1] != '.') { error = ENOTDIR; break; } if (dirbuf.dotdot_ino == source->i_number) { error = EINVAL; break; } if (dirbuf.dotdot_ino == ROOTINO) break; iput(ip); ip = iget(ip->i_dev, ip->i_fs, dirbuf.dotdot_ino); if (ip == NULL) { error = u.u_error; break; } } out: if (error == ENOTDIR) printf("checkpath: .. not a directory\n"); if (ip != NULL) iput(ip); return (error); } /* * Name cache initialization, from main() when we are booting */ nchinit() { register union nchash *nchp; register struct namecache *ncp; segm seg5; saveseg5(seg5); mapseg5(nmidesc.se_addr,nmidesc.se_desc); nchhead = 0; nchtail = &nchhead; for (ncp = namecache; ncp < &namecache[nchsize]; ncp++) { ncp->nc_forw = ncp; /* hash chain */ ncp->nc_back = ncp; ncp->nc_nxt = NULL; /* lru chain */ *nchtail = ncp; ncp->nc_prev = nchtail; nchtail = &ncp->nc_nxt; /* all else is zero already */ } for (nchp = nchash; nchp < &nchash[NCHHASH]; nchp++) { nchp->nch_head[0] = nchp; nchp->nch_head[1] = nchp; } restorseg5(seg5); } /* * Cache flush, called when filesys is umounted to * remove entries that would now be invalid * * The line "nxtcp = nchhead" near the end is to avoid potential problems * if the cache lru chain is modified while we are dumping the * inode. This makes the algorithm O(n^2), but do you think I care? */ nchinval(dev) register dev_t dev; { register struct namecache *ncp, *nxtcp; segm seg5; saveseg5(seg5); mapseg5(nmidesc.se_addr,nmidesc.se_desc); for (ncp = nchhead; ncp; ncp = nxtcp) { nxtcp = ncp->nc_nxt; if (ncp->nc_ip == NULL || (ncp->nc_idev != dev && ncp->nc_dev != dev)) continue; /* free the resources we had */ ncp->nc_idev = NODEV; ncp->nc_dev = NODEV; ncp->nc_id = NULL; ncp->nc_ino = 0; ncp->nc_ip = NULL; remque(ncp); /* remove entry from its hash chain */ ncp->nc_forw = ncp; /* and make a dummy one */ ncp->nc_back = ncp; /* delete this entry from LRU chain */ *ncp->nc_prev = nxtcp; if (nxtcp) nxtcp->nc_prev = ncp->nc_prev; else nchtail = ncp->nc_prev; /* cause rescan of list, it may have altered */ nxtcp = nchhead; /* put the now-free entry at head of LRU */ ncp->nc_nxt = nxtcp; ncp->nc_prev = &nchhead; nxtcp->nc_prev = &ncp->nc_nxt; nchhead = ncp; } restorseg5(seg5); } /* * Name cache invalidation of all entries. */ cacheinvalall() { register struct namecache *ncp, *encp = &namecache[nchsize]; segm seg5; saveseg5(seg5); mapseg5(nmidesc.se_addr, nmidesc.se_desc); for (ncp = namecache; ncp < encp; ncp++) ncp->nc_id = 0; restorseg5(seg5); } if (ndp->ni_count == 0) { /* * If ndp->ni_count is 0, then namei could find no space in the * directory. Isys/sys/sys_pipe.c 440 0 12 12363 5667014317 7513 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)sys_pipe.c 1.3 (2.11BSD GTE) 11/26/94 */ #include "param.h" #include "systm.h" #include "user.h" #include "proc.h" #include "inode.h" #include "file.h" #include "fs.h" #include "mount.h" extern int ino_ioctl(), ino_close(); int pipe_rw(), pipe_select(); struct fileops pipeops = { pipe_rw, ino_ioctl, pipe_select, ino_close }; /* * The sys-pipe entry. * Allocate an inode on the root device. Allocate 2 * file structures. Put it all together with flags. */ pipe() { register struct inode *ip; register struct file *rf, *wf; static struct mount *mp; struct inode itmp; int r; /* * if pipedev not yet found, or not available, get it; if can't * find it, use rootdev. It would be cleaner to wander around * and fix it so that this and getfs() only check m_dev OR * m_inodp, but hopefully the mount table isn't scanned enough * to make it a problem. Besides, 4.3's is just as bad. Basic * fantasy is that if m_inodp is set, m_dev *will* be okay. */ if (!mp || !mp->m_inodp || mp->m_dev != pipedev) { for (mp = &mount[0];;++mp) { if (mp == &mount[NMOUNT]) { mp = &mount[0]; /* use root */ break; } if (mp->m_inodp == NULL || mp->m_dev != pipedev) continue; break; } if (mp->m_filsys.fs_ronly) { u.u_error = EROFS; return; } } itmp.i_fs = &mp->m_filsys; itmp.i_dev = mp->m_dev; ip = ialloc(&itmp); if (ip == NULL) return; rf = falloc(); if (rf == NULL) { iput(ip); return; } r = u.u_r.r_val1; wf = falloc(); if (wf == NULL) { rf->f_count = 0; u.u_ofile[r] = NULL; iput(ip); return; } u.u_r.r_val2 = u.u_r.r_val1; u.u_r.r_val1 = r; wf->f_flag = FWRITE; rf->f_flag = FREAD; rf->f_type = wf->f_type = DTYPE_PIPE; rf->f_data = wf->f_data = (caddr_t)ip; ip->i_count = 2; ip->i_mode = IFREG; ip->i_flag = IACC|IUPD|ICHG|IPIPE; } pipe_rw(fp, uio, flag) register struct file *fp; register struct uio *uio; int flag; { if (uio->uio_rw == UIO_READ) return (readp(fp, uio, flag)); return (writep(fp, uio, flag)); } readp(fp, uio, flag) register struct file *fp; register struct uio *uio; int flag; { register struct inode *ip; int error; ip = (struct inode *)fp->f_data; loop: /* Very conservative locking. */ ILOCK(ip); /* If nothing in the pipe, wait (unless FNONBLOCK is set). */ if (ip->i_size == 0) { /* * If there are not both reader and writer active, * return without satisfying read. */ IUNLOCK(ip); if (ip->i_count != 2) return (0); if (fp->f_flag & FNONBLOCK) return (EWOULDBLOCK); ip->i_mode |= IREAD; sleep((caddr_t)ip+2, PPIPE); goto loop; } uio->uio_offset = fp->f_offset; error = rwip(ip, uio, flag); fp->f_offset = uio->uio_offset; /* * If reader has caught up with writer, reset * offset and size to 0. */ if (fp->f_offset == ip->i_size) { fp->f_offset = 0; ip->i_size = 0; if (ip->i_mode & IWRITE) { ip->i_mode &= ~IWRITE; wakeup((caddr_t)ip+1); } if (ip->i_wsel) { selwakeup(ip->i_wsel, (long)(ip->i_flag & IWCOLL)); ip->i_wsel = 0; ip->i_flag &= ~IWCOLL; } } IUNLOCK(ip); return (error); } writep(fp, uio, flag) struct file *fp; register struct uio *uio; int flag; { register struct inode *ip; register int c; int error = 0; ip = (struct inode *)fp->f_data; c = uio->uio_resid; ILOCK(ip); if ((fp->f_flag & FNONBLOCK) && ip->i_size + c >= MAXPIPSIZ) { error = EWOULDBLOCK; goto done; } loop: /* If all done, return. */ if (c == 0) { uio->uio_resid = 0; goto done; } /* * If there are not both read and write sides of the pipe active, * return error and signal too. */ if (ip->i_count != 2) { psignal(u.u_procp, SIGPIPE); error = EPIPE; done: IUNLOCK(ip); return (error); } /* * If the pipe is full, wait for reads to deplete * and truncate it. */ if (ip->i_size >= MAXPIPSIZ) { ip->i_mode |= IWRITE; IUNLOCK(ip); sleep((caddr_t)ip+1, PPIPE); ILOCK(ip); goto loop; } /* * Write what is possible and loop back. * If writing less than MAXPIPSIZ, it always goes. * One can therefore get a file > MAXPIPSIZ if write * sizes do not divide MAXPIPSIZ. */ uio->uio_offset = ip->i_size; uio->uio_resid = MIN((u_int)c, (u_int)MAXPIPSIZ); c -= uio->uio_resid; error = rwip(ip, uio, flag); if (ip->i_mode&IREAD) { ip->i_mode &= ~IREAD; wakeup((caddr_t)ip+2); } if (ip->i_rsel) { selwakeup(ip->i_rsel, (long)(ip->i_flag & IRCOLL)); ip->i_rsel = 0; ip->i_flag &= ~IRCOLL; } goto loop; } pipe_select(fp, which) struct file *fp; int which; { register struct inode *ip = (struct inode *)fp->f_data; register struct proc *p; register int retval = 0; extern int selwait; ILOCK(ip); if (ip->i_count != 2) retval = 1; else switch (which) { case FREAD: if (ip->i_size) { retval = 1; break; } if ((p = ip->i_rsel) && p->p_wchan == (caddr_t)&selwait) ip->i_flag |= IRCOLL; else ip->i_rsel = u.u_procp; break; case FWRITE: if (ip->i_size < MAXPIPSIZ) { retval = 1; break; } if ((p = ip->i_wsel) && p->p_wchan == (caddr_t)&selwait) ip->i_flag |= IWCOLL; else ip->i_wsel = u.u_procp; break; } IUNLOCK(ip); return(retval); } sizeof (struct dirtemplate) / 2) for (off = 0; off < ip->i_size; off += dp->d_reclen) { error = rdwri(UIO_READ, ip, (caddr_t)dp, MINDIRSIZ, off, UIO_SYSSPACE, IO_UNIT, &count); /* * Since we read MINDIRSIZ, residual must * be 0 unless we're at end of sys/sys/quota_sys.c 440 0 12 20254 5514434305 7677 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)quota_sys.c 7.1.1 (2.11BSD GTE) 12/31/93 */ /* * MELBOURNE QUOTAS * * System calls. */ #include "param.h" #include "systm.h" #include "user.h" #include "proc.h" #include "inode.h" #include "quota.h" #include "fs.h" #include "mount.h" #include "uio.h" /* * The sys call that tells the system about a quota file. */ setquota() { register struct a { char *fblk; char *fname; } *uap = (struct a *)u.u_ap; register struct mount *mp; dev_t dev; #ifdef QUOTA u.u_error = getmdev(&dev, uap->fblk); if (u.u_error) return; for (mp = mount; mp < &mount[NMOUNT]; mp++) #ifdef pdp11 if (mp->m_inodp && mp->m_dev == dev) { #else if (mp->m_bufp && mp->m_dev == dev) { #endif #ifdef pdp11 QUOTAMAP(); #endif if (uap->fname == NULL) closedq(mp); else opendq(mp, (caddr_t)uap->fname); #ifdef pdp11 QUOTAUNMAP(); #endif return; } #else u.u_error = EINVAL; #endif } /* * Sys call to allow users to find out * their current position wrt quota's * and to allow super users to alter it. */ qquota() { register struct a { int cmd; int uid; int arg; caddr_t addr; } *uap = (struct a *)u.u_ap; register struct quota *q; #ifdef QUOTA if (uap->uid < 0) uap->uid = u.u_ruid; #ifdef pdp11 QUOTAMAP(); #endif if (uap->uid != u.u_ruid && uap->uid != u.u_quota->q_uid && !suser()) #ifdef pdp11 { QUOTAUNMAP(); return; } #else return; #endif if (uap->cmd != Q_SYNC && uap->cmd != Q_SETUID) { q = getquota((uid_t)uap->uid, uap->cmd == Q_DOWARN, 0); if (q == NOQUOTA) { #ifdef pdp11 QUOTAUNMAP(); #endif u.u_error = ESRCH; return; } if (u.u_error) goto bad; } switch (uap->cmd) { case Q_SETDLIM: u.u_error = setdlim(q, (dev_t)uap->arg, uap->addr); break; case Q_GETDLIM: u.u_error = getdlim(q, (dev_t)uap->arg, uap->addr); break; case Q_SETDUSE: u.u_error = setduse(q, (dev_t)uap->arg, uap->addr); break; case Q_SETWARN: u.u_error = setwarn(q, (dev_t)uap->arg, uap->addr); break; case Q_DOWARN: u.u_error = dowarn(q, (dev_t)uap->arg); break; case Q_SYNC: u.u_error = qsync((dev_t)uap->arg); #ifdef pdp11 QUOTAUNMAP(); #endif return; case Q_SETUID: u.u_error = qsetuid((uid_t)uap->uid, uap->arg); #ifdef pdp11 QUOTAUNMAP(); #endif return; default: u.u_error = EINVAL; break; } bad: delquota(q); #ifdef pdp11 QUOTAUNMAP(); #endif #else u.u_error = EINVAL; #endif } #ifdef QUOTA /* * Q_SETDLIM - assign an entire dqblk structure. */ setdlim(q, dev, addr) register struct quota *q; dev_t dev; caddr_t addr; { register struct inode *ip; register struct dquot *dq, *odq; struct dqblk newlim; int index, error = 0; if (!suser()) return (u.u_error); /* XXX */ index = getfsx(dev); if (index < 0 || index >= NMOUNT) return (ENODEV); dq = dqp(q, dev); if (dq == NODQUOT) { dq = dqalloc(q->q_uid, dev); if (dq == NODQUOT) return (error); dq->dq_cnt++; dq->dq_own = q; q->q_dq[index] = dq; odq = NODQUOT; } else odq = dq; if (dq->dq_uid != q->q_uid) panic("setdlim"); while (dq->dq_flags & DQ_LOCK) { dq->dq_flags |= DQ_WANT; #ifdef pdp11 QUOTAUNMAP(); sleep((caddr_t)dq, PINOD+1); QUOTAMAP(); #else sleep((caddr_t)dq, PINOD+1); #endif } error = copyin(addr, (caddr_t)&newlim, sizeof (struct dqblk)); if (error) { if (dq != odq) { q->q_dq[index] = odq; dq->dq_cnt--; } dqrele(dq); return (error); } #ifdef pdp11 /* we speak bytes not blocks, so convert the structure here */ newlim.dqb_bsoftlimit = (long)dbtob(newlim.dqb_bsoftlimit); newlim.dqb_bhardlimit = (long)dbtob(newlim.dqb_bhardlimit); newlim.dqb_curblocks = (long)dbtob(newlim.dqb_curblocks); #endif dq->dq_dqb = newlim; dq->dq_flags |= DQ_MOD; dqrele(dq); if (dq->dq_isoftlimit == 0 && dq->dq_bsoftlimit == 0) { q->q_dq[index] = NODQUOT; dq->dq_own = NOQUOTA; dqrele(dq); if (dq->dq_cnt == 0) /* no files open using quota */ return (error); dq = NODQUOT; } if (dq == odq) return (error); for (ip = inode; ip < inodeNINODE; ip++) if (ip->i_uid == q->q_uid && ip->i_dev == dev && ip->i_mode) { if (dq == NODQUOT) #ifdef pdp11 dqrele(ix_dquot[ip - inode]); #else dqrele(ip->i_dquot); #endif else dq->dq_cnt++; #ifdef pdp11 ix_dquot[ip - inode] = dq; #else ip->i_dquot = dq; #endif } return (error); } /* * Q_GETDLIM - return current values in a dqblk structure. */ getdlim(q, dev, addr) struct quota *q; dev_t dev; caddr_t addr; { register struct dquot *dq; int error; dq = dqp(q, dev); if (dq == NODQUOT) return (ESRCH); #ifdef pdp11 /* we do bytes not blocks, so convert the structure here */ { struct dqblk dqb; dqb = dq->dq_dqb; dqb.dqb_bhardlimit = (long)btodb(dqb.dqb_bhardlimit); dqb.dqb_bsoftlimit = (long)btodb(dqb.dqb_bsoftlimit); dqb.dqb_curblocks = (long)btodb(dqb.dqb_curblocks); error = copyout((caddr_t)&dqb, addr, sizeof(struct dqblk)); } #else error = copyout((caddr_t)&dq->dq_dqb, addr, sizeof (struct dqblk)); #endif dqrele(dq); return (error); } /* * Q_SETDUSE - set current inode and disc block totals. * Resets warnings and associated flags. */ setduse(q, dev, addr) register struct quota *q; dev_t dev; caddr_t addr; { register struct dquot *dq; struct dqusage usage; int error = 0; if (!suser()) return (u.u_error); dq = dqp(q, dev); if (dq == NODQUOT) return (ESRCH); while (dq->dq_flags & DQ_LOCK) { dq->dq_flags |= DQ_WANT; #ifdef pdp11 QUOTAUNMAP(); sleep((caddr_t)dq, PINOD+1); QUOTAMAP(); #else sleep((caddr_t)dq, PINOD+1); #endif } if (dq->dq_uid != q->q_uid) panic("setduse"); error = copyin(addr, (caddr_t)&usage, sizeof (usage)); if (error == 0) { dq->dq_curinodes = usage.du_curinodes; #ifdef pdp11 dq->dq_curblocks = dbtob(usage.du_curblocks); #else dq->dq_curblocks = usage.du_curblocks; #endif if (dq->dq_curinodes < dq->dq_isoftlimit) dq->dq_iwarn = MAX_IQ_WARN; if (dq->dq_curblocks < dq->dq_bsoftlimit) dq->dq_bwarn = MAX_DQ_WARN; dq->dq_flags &= ~(DQ_INODS | DQ_BLKS); dq->dq_flags |= DQ_MOD; } dqrele(dq); return (error); } /* * Q_SETWARN - set warning counters. */ setwarn(q, dev, addr) register struct quota *q; dev_t dev; caddr_t addr; { register struct dquot *dq; int error = 0; struct dqwarn warn; if (!suser()) return (u.u_error); /* XXX */ dq = dqp(q, dev); if (dq == NODQUOT) return (ESRCH); while (dq->dq_flags & DQ_LOCK) { dq->dq_flags |= DQ_WANT; #ifdef pdp11 QUOTAUNMAP(); sleep((caddr_t)dq, PINOD+1); QUOTAMAP(); #else sleep((caddr_t)dq, PINOD+1); #endif } if (dq->dq_uid != q->q_uid) panic("setwarn"); error = copyin(addr, (caddr_t)&warn, sizeof (warn)); if (error == 0) { dq->dq_iwarn = warn.dw_iwarn; dq->dq_bwarn = warn.dw_bwarn; dq->dq_flags &= ~(DQ_INODS | DQ_BLKS); dq->dq_flags |= DQ_MOD; } dqrele(dq); return (error); } /* * Q_DOWARN - force warning(s) to user(s). */ dowarn(q, dev) register struct quota *q; dev_t dev; { register struct dquot *dq, **dqq; if (!suser() || u.u_ttyp == NULL) return (u.u_error); /* XXX */ if (dev != NODEV) { dq = dqp(q, dev); if (dq != NODQUOT) { qwarn(dq); dqrele(dq); } return (0); } for (dqq = q->q_dq; dqq < &q->q_dq[NMOUNT]; dqq++) { dq = *dqq; if (dq != NODQUOT && dq != LOSTDQUOT) qwarn(dq); } return (0); } /* * Q_SYNC - sync quota files to disc. */ qsync(dev) dev_t dev; { register struct quota *q; register struct mount *mp; register index; if (!suser()) return (u.u_error); /* XXX */ for (mp = mount, index = 0; mp < &mount[NMOUNT]; mp++, index++) #ifdef pdp11 if (mp->m_inodp && mp->m_qinod && #else if (mp->m_bufp && mp->m_qinod && #endif (dev == NODEV || dev == mp->m_dev)) { for (q = quota; q < quotaNQUOTA; q++) if (q->q_cnt) { q->q_cnt++; putdq(mp, q->q_dq[index], 0); delquota(q); } } return (0); } /* * Q_SETUID - change quota to a particular uid. */ qsetuid(uid, noquota) uid_t uid; int noquota; { register struct quota *q; if (uid == u.u_quota->q_uid) return (0); if (!suser()) return (u.u_error); /* XXX */ q = getquota(uid, 0, noquota ? Q_NDQ : 0); qclean(); qstart(q); return (0); } #endif f (q == NOQUOTA) { #ifdef pdp11 QUOTAUNMAP(); #endif u.u_error = ESRCH; return; } if (u.u_error) goto bad; } switch (uap->cmd) { case Q_SETDLIM: u.u_error = setdlim(q, (dev_t)uap->arg, uap->addr); break; case Q_GETDLIM: u.u_error = getdlim(q, (dev_t)uap->arg, uap->addr); break; case Q_SETDUSE: u.u_error =sys/sys/kern_acct.c 440 0 12 6756 5666030152 7574 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)kern_acct.c 2.2 (2.11BSD) 11/26/94 */ #include "param.h" #include "systm.h" #include "fs.h" #include "dir.h" #include "inode.h" #include "user.h" #include "proc.h" #include "acct.h" #include "kernel.h" #include "syslog.h" /* * SHOULD REPLACE THIS WITH A DRIVER THAT CAN BE READ TO SIMPLIFY. */ int acctsuspend = 2; /* stop accounting when < 2% free space left */ int acctresume = 4; /* resume when free space risen to > 4% */ struct timeval chk = {15, 0}; /* frequency to check space for accounting */ struct inode *acctp; struct inode *savacctp; /* * Perform process accounting functions. */ sysacct() { register struct inode *ip; register struct a { char *fname; } *uap = (struct a *)u.u_ap; register struct nameidata *ndp = &u.u_nd; int acctwatch(); if (suser()) { if (savacctp) { acctp = savacctp; savacctp = NULL; } if (uap->fname==NULL) { if (ip = acctp) { irele(ip); acctp = NULL; chk.tv_usec = 0; untimeout(acctwatch, &chk); } return; } ndp->ni_nameiop = LOOKUP | FOLLOW; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->fname; ip = namei(ndp); if (ip == NULL) return; if ((ip->i_mode&IFMT) != IFREG) { u.u_error = EACCES; iput(ip); return; } if (ip->i_fs->fs_ronly) { u.u_error = EROFS; iput(ip); return; } if (acctp && (acctp->i_number != ip->i_number || acctp->i_dev != ip->i_dev)) irele(acctp); acctp = ip; iunlock(ip); if (chk.tv_usec == 0) { chk.tv_usec = 1; /* usec is timer enabled flag */ timeout(acctwatch, &chk, chk.tv_sec * hz); } } } acctwatch(resettime) register struct timeval *resettime; { register struct fs *fs; if (savacctp) { fs = savacctp->i_fs; if (freespace(fs, acctresume) > 0) { acctp = savacctp; savacctp = NULL; log(LOG_NOTICE, "Accounting resumed\n"); /* return; /* XXX - fall thru and refresh timer */ } } if (acctp == NULL) return; /* do not refresh timer */ fs = acctp->i_fs; if (freespace(fs, acctsuspend) <= 0) { savacctp = acctp; acctp = NULL; log(LOG_NOTICE, "Accounting suspended\n"); } timeout(acctwatch, resettime, resettime->tv_sec * hz); } /* * On exit, write a record on the accounting file. */ acct() { struct acct acctbuf; register struct inode *ip; off_t siz; register struct acct *ap = &acctbuf; if ((ip = acctp) == NULL) return; ilock(ip); bcopy(u.u_comm, ap->ac_comm, sizeof(acctbuf.ac_comm)); ap->ac_utime = compress(u.u_ru.ru_utime); ap->ac_stime = compress(u.u_ru.ru_stime); ap->ac_etime = compress(time.tv_sec - u.u_start); ap->ac_btime = u.u_start; ap->ac_uid = u.u_ruid; ap->ac_gid = u.u_rgid; ap->ac_mem = (u.u_dsize+u.u_ssize) / 16; /* fast ctok() */ ap->ac_io = compress(u.u_ru.ru_inblock + u.u_ru.ru_oublock); if (u.u_ttyp) ap->ac_tty = u.u_ttyd; else ap->ac_tty = NODEV; ap->ac_flag = u.u_acflag; siz = ip->i_size; u.u_error = rdwri(UIO_WRITE, ip, ap, sizeof(acctbuf), siz, UIO_SYSSPACE, IO_UNIT|IO_APPEND, (int *)0); if (u.u_error) itrunc(ip, (u_long)siz); iunlock(ip); } /* * Produce a pseudo-floating point representation * with 3 bits base-8 exponent, 13 bits fraction. */ compress(t) register time_t t; { register exp = 0, round = 0; while (t >= 8192) { exp++; round = t&04L; t >>= 3; } if (round) { t++; if (t >= 8192) { t >>= 3; exp++; } } return((exp<<13) + t); } dq); return (errsys/sys/kern_fork.c 440 0 12 15420 5511223003 7613 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)kern_fork.c 1.4 (2.11BSD GTE) 12/31/93 */ #include "param.h" #include "../machine/reg.h" #include "../machine/seg.h" #include "systm.h" #include "map.h" #include "user.h" #include "proc.h" #include "inode.h" #include "acct.h" #include "file.h" #include "vm.h" #include "text.h" #include "kernel.h" #ifdef QUOTA #include "quota.h" #endif /* * fork -- * fork system call */ fork() { fork1(0); } /* * vfork -- * vfork system call, fast version of fork */ vfork() { fork1(1); } fork1(isvfork) { register int a; register struct proc *p1, *p2; a = 0; if (u.u_uid != 0) { for (p1 = allproc; p1; p1 = p1->p_nxt) if (p1->p_uid == u.u_uid) a++; for (p1 = zombproc; p1; p1 = p1->p_nxt) if (p1->p_uid == u.u_uid) a++; } /* * Disallow if * No processes at all; * not su and too many procs owned; or * not su and would take last slot. */ p2 = freeproc; if (p2==NULL) tablefull("proc"); if (p2==NULL || (u.u_uid!=0 && (p2->p_nxt == NULL || a>MAXUPRC))) { u.u_error = EAGAIN; goto out; } p1 = u.u_procp; if (newproc(isvfork)) { u.u_r.r_val1 = p1->p_pid; #ifndef pdp11 u.u_r.r_val2 = 1; /* child */ #endif u.u_start = time.tv_sec; u.u_acflag = AFORK; bzero(&u.u_ru, sizeof(u.u_ru)); bzero(&u.u_cru, sizeof(u.u_cru)); return; } u.u_r.r_val1 = p2->p_pid; out: #ifdef pdp11 /* see libc/pdp/sys/fork.s */ u.u_ar0[R7] += NBPW; #else u.u_r.r_val2 = 0; #endif } /* * newproc -- * Create a new process -- the internal version of system call fork. * It returns 1 in the new process, 0 in the old. */ newproc(isvfork) int isvfork; { register struct proc *rpp, *rip; register int n; static int pidchecked = 0; struct file *fp; int a1, s; memaddr a[3]; /* * First, just locate a slot for a process * and copy the useful info from this process into it. * The panic "cannot happen" because fork has already * checked for the existence of a slot. */ mpid++; retry: if (mpid >= 30000) { mpid = 100; pidchecked = 0; } if (mpid >= pidchecked) { int doingzomb = 0; pidchecked = 30000; /* * Scan the proc table to check whether this pid * is in use. Remember the lowest pid that's greater * than mpid, so we can avoid checking for a while. */ rpp = allproc; again: for (; rpp != NULL; rpp = rpp->p_nxt) { if (rpp->p_pid == mpid || rpp->p_pgrp == mpid) { mpid++; if (mpid >= pidchecked) goto retry; } if (rpp->p_pid > mpid && pidchecked > rpp->p_pid) pidchecked = rpp->p_pid; if (rpp->p_pgrp > mpid && pidchecked > rpp->p_pgrp) pidchecked = rpp->p_pgrp; } if (!doingzomb) { doingzomb = 1; rpp = zombproc; goto again; } } if ((rpp = freeproc) == NULL) panic("no procs"); freeproc = rpp->p_nxt; /* off freeproc */ /* * Make a proc table entry for the new process. */ rip = u.u_procp; #ifdef QUOTA QUOTAMAP(); u.u_quota->q_cnt++; QUOTAUNMAP(); #endif rpp->p_stat = SIDL; rpp->p_realtimer.it_value = 0; rpp->p_flag = SLOAD | (rip->p_flag & SDETACH); rpp->p_uid = rip->p_uid; rpp->p_pgrp = rip->p_pgrp; rpp->p_nice = rip->p_nice; rpp->p_textp = rip->p_textp; rpp->p_pid = mpid; rpp->p_ppid = rip->p_pid; rpp->p_pptr = rip; rpp->p_time = 0; rpp->p_cpu = 0; rpp->p_sigmask = rip->p_sigmask; rpp->p_sigcatch = rip->p_sigcatch; rpp->p_sigignore = rip->p_sigignore; /* take along any pending signals like stops? */ #ifdef UCB_METER if (isvfork) { forkstat.cntvfork++; forkstat.sizvfork += rip->p_dsize + rip->p_ssize; } else { forkstat.cntfork++; forkstat.sizfork += rip->p_dsize + rip->p_ssize; } #endif rpp->p_wchan = 0; rpp->p_slptime = 0; { struct proc **hash = &pidhash[PIDHASH(rpp->p_pid)]; rpp->p_hash = *hash; *hash = rpp; } /* * some shuffling here -- in most UNIX kernels, the allproc assign * is done after grabbing the struct off of the freeproc list. We * wait so that if the clock interrupts us and vmtotal walks allproc * the text pointer isn't garbage. */ rpp->p_nxt = allproc; /* onto allproc */ rpp->p_nxt->p_prev = &rpp->p_nxt; /* (allproc is never NULL) */ rpp->p_prev = &allproc; allproc = rpp; /* * Increase reference counts on shared objects. */ for (n = 0; n <= u.u_lastfile; n++) { fp = u.u_ofile[n]; if (fp == NULL) continue; fp->f_count++; } if ((rip->p_textp != NULL) && !isvfork) { rip->p_textp->x_count++; rip->p_textp->x_ccount++; } u.u_cdir->i_count++; if (u.u_rdir) u.u_rdir->i_count++; /* * When the longjmp is executed for the new process, * here's where it will resume. */ if (setjmp(&u.u_ssave)) { sureg(); return(1); } rpp->p_dsize = rip->p_dsize; rpp->p_ssize = rip->p_ssize; rpp->p_daddr = rip->p_daddr; rpp->p_saddr = rip->p_saddr; a1 = rip->p_addr; if (isvfork) a[2] = malloc(coremap,USIZE); else a[2] = malloc3(coremap, rip->p_dsize, rip->p_ssize, USIZE, a); /* * Partially simulate the environment of the new process so that * when it is actually created (by copying) it will look right. */ u.u_procp = rpp; /* * If there is not enough core for the new process, swap out the * current process to generate the copy. */ if (a[2] == NULL) { rip->p_stat = SIDL; rpp->p_addr = a1; rpp->p_stat = SRUN; swapout(rpp, X_DONTFREE, X_OLDSIZE, X_OLDSIZE); rip->p_stat = SRUN; u.u_procp = rip; } else { /* * There is core, so just copy. */ rpp->p_addr = a[2]; copy(a1, rpp->p_addr, USIZE); u.u_procp = rip; if (isvfork == 0) { rpp->p_daddr = a[0]; copy(rip->p_daddr, rpp->p_daddr, rpp->p_dsize); rpp->p_saddr = a[1]; copy(rip->p_saddr, rpp->p_saddr, rpp->p_ssize); } s = splhigh(); rpp->p_stat = SRUN; setrq(rpp); splx(s); } rpp->p_flag |= SSWAP; if (isvfork) { /* * Set the parent's sizes to 0, since the child now * has the data and stack. * (If we had to swap, just free parent resources.) * Then wait for the child to finish with it. */ if (a[2] == NULL) { mfree(coremap,rip->p_dsize,rip->p_daddr); mfree(coremap,rip->p_ssize,rip->p_saddr); } rip->p_dsize = 0; rip->p_ssize = 0; rip->p_textp = NULL; rpp->p_flag |= SVFORK; rip->p_flag |= SVFPRNT; while (rpp->p_flag & SVFORK) sleep((caddr_t)rpp,PSWP+1); if ((rpp->p_flag & SLOAD) == 0) panic("newproc vfork"); u.u_dsize = rip->p_dsize = rpp->p_dsize; rip->p_daddr = rpp->p_daddr; rpp->p_dsize = 0; u.u_ssize = rip->p_ssize = rpp->p_ssize; rip->p_saddr = rpp->p_saddr; rpp->p_ssize = 0; rip->p_textp = rpp->p_textp; rpp->p_textp = NULL; rpp->p_flag |= SVFDONE; wakeup((caddr_t)rip); /* must do estabur if dsize/ssize are different */ estabur(u.u_tsize,u.u_dsize,u.u_ssize,u.u_sep,RO); rip->p_flag &= ~SVFPRNT; } return(0); } mpid; rpp->p_ppid = rip->p_pid; rpp->p_pptr = rip; rpp->p_time = 0; rpp->p_cpu = 0; rpp->p_sigmask = rip->p_sigmask; rpp->p_sigcatch = rip->p_sigcatch; rpp->p_sigignore = rip->p_sigignore; /* take along any pending signals like stopsys/sys/sys_inode.c 440 0 12 37522 5757752425 7671 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)sys_inode.c 1.5 (2.11BSD GTE) 1995/05/21 */ #include "param.h" #include "../machine/seg.h" #include "user.h" #include "proc.h" #include "inode.h" #include "buf.h" #include "fs.h" #include "file.h" #include "stat.h" #include "mount.h" #include "conf.h" #include "uio.h" #include "ioctl.h" #include "tty.h" #include "kernel.h" #include "systm.h" #include "syslog.h" #ifdef QUOTA #include "quota.h" #endif int ino_rw(), ino_ioctl(), ino_select(), ino_close(); struct fileops inodeops = { ino_rw, ino_ioctl, ino_select, ino_close }; ino_rw(fp, uio) struct file *fp; register struct uio *uio; { register struct inode *ip = (struct inode *)fp->f_data; u_int count, error; int ioflag; if ((ip->i_mode&IFMT) != IFCHR) ILOCK(ip); uio->uio_offset = fp->f_offset; count = uio->uio_resid; if (uio->uio_rw == UIO_READ) { error = rwip(ip, uio, fp->f_flag & FNONBLOCK ? IO_NDELAY : 0); fp->f_offset += (count - uio->uio_resid); } else { ioflag = 0; if ((ip->i_mode&IFMT) == IFREG && (fp->f_flag & FAPPEND)) ioflag |= IO_APPEND; if (fp->f_flag & FNONBLOCK) ioflag |= IO_NDELAY; error = rwip(ip, uio, ioflag); if (ioflag & IO_APPEND) fp->f_offset = uio->uio_offset; else fp->f_offset += (count - uio->uio_resid); } if ((ip->i_mode&IFMT) != IFCHR) IUNLOCK(ip); return (error); } rdwri(rw, ip, base, len, offset, segflg, ioflg, aresid) enum uio_rw rw; struct inode *ip; caddr_t base; int len; off_t offset; enum uio_seg segflg; int ioflg; register int *aresid; { struct uio auio; struct iovec aiov; register int error; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; aiov.iov_base = base; aiov.iov_len = len; auio.uio_rw = rw; auio.uio_resid = len; auio.uio_offset = offset; auio.uio_segflg = segflg; error = rwip(ip, &auio, ioflg); if (aresid) *aresid = auio.uio_resid; else if (auio.uio_resid) error = EIO; return (error); } rwip(ip, uio, ioflag) register struct inode *ip; register struct uio *uio; int ioflag; { dev_t dev = (dev_t)ip->i_rdev; register struct buf *bp; off_t osize; daddr_t lbn, bn; int n, on, type, resid; int error = 0; #ifdef DIAGNOSTIC if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE) panic("rwip"); #endif if (uio->uio_offset < 0) return (EINVAL); type = ip->i_mode&IFMT; /* * The write case below checks that i/o is done synchronously to directories * and that i/o to append only files takes place at the end of file. The * 'log()' statements below should be ifdef'd. Also, we do not panic on * non-sync directory i/o - the sync bit is forced on. */ if (uio->uio_rw == UIO_READ) ip->i_flag |= IACC; else { switch (type) { case IFREG: if (ioflag & IO_APPEND) uio->uio_offset = ip->i_size; if (ip->i_flags & APPEND && uio->uio_offset != ip->i_size) return(EPERM); break; case IFDIR: if ((ioflag & IO_SYNC) == 0) { log(LOG_ERR, "rwip sync\n"); ioflag |= IO_SYNC; } break; case IFLNK: case IFBLK: case IFCHR: break; default: log(LOG_ERR, "rwip: %d\n", type); return(EFTYPE); } } if (type == IFCHR) { if (uio->uio_rw == UIO_READ) error = (*cdevsw[major(dev)].d_read)(dev, uio, ioflag); else { ip->i_flag |= IUPD|ICHG; error = (*cdevsw[major(dev)].d_write)(dev, uio, ioflag); } return (error); } if (uio->uio_resid == 0) return (0); if (uio->uio_rw == UIO_WRITE && type == IFREG && uio->uio_offset + uio->uio_resid > u.u_rlimit[RLIMIT_FSIZE].rlim_cur) { psignal(u.u_procp, SIGXFSZ); return (EFBIG); } #ifdef QUOTA /* * we do bytes, see the comment on 'blocks' in ino_stat(). * * the simplfying assumption is made that the entire write will * succeed, otherwise we have to check the quota on each block. * can you say slow? i knew you could. SMS */ if ((type == IFREG || type == IFDIR || type == IFLNK) && uio->uio_rw == UIO_WRITE && !(ip->i_flag & IPIPE)) { if (uio->uio_offset + uio->uio_resid > ip->i_size) { QUOTAMAP(); error = chkdq(ip, uio->uio_offset+uio->uio_resid - ip->i_size,0); QUOTAUNMAP(); if (error) return (error); } } #endif if (type != IFBLK) dev = ip->i_dev; resid = uio->uio_resid; osize = ip->i_size; do { lbn = lblkno(uio->uio_offset); on = blkoff(uio->uio_offset); n = MIN((u_int)(DEV_BSIZE - on), uio->uio_resid); if (type != IFBLK) { if (uio->uio_rw == UIO_READ) { off_t diff = ip->i_size - uio->uio_offset; if (diff <= 0) return (0); if (diff < n) n = diff; bn = bmap(ip, lbn, B_READ, 0); } else bn = bmap(ip,lbn,B_WRITE,n == DEV_BSIZE ? 0: 1); if (u.u_error || uio->uio_rw == UIO_WRITE && (long)bn<0) return (u.u_error); if (uio->uio_rw == UIO_WRITE && uio->uio_offset + n > ip->i_size && (type == IFDIR || type == IFREG || type == IFLNK)) ip->i_size = uio->uio_offset + n; } else { bn = lbn; rablock = bn + 1; } if (uio->uio_rw == UIO_READ) { if ((long)bn<0) { bp = geteblk(); clrbuf(bp); } else if (ip->i_lastr + 1 == lbn) bp = breada(dev, bn, rablock); else bp = bread(dev, bn); ip->i_lastr = lbn; } else { if (n == DEV_BSIZE) bp = getblk(dev, bn); else bp = bread(dev, bn); /* * 4.3 didn't do this, but 2.10 did. not sure why. * something about tape drivers don't clear buffers on end-of-tape * any longer (clrbuf can't be called from interrupt). */ if (bp->b_resid == DEV_BSIZE) { bp->b_resid = 0; clrbuf(bp); } } n = MIN(n, DEV_BSIZE - bp->b_resid); if (bp->b_flags & B_ERROR) { error = EIO; brelse(bp); break; } u.u_error = uiomove(mapin(bp)+on, n, uio); mapout(bp); if (uio->uio_rw == UIO_READ) { if (n + on == DEV_BSIZE || uio->uio_offset == ip->i_size) { bp->b_flags |= B_AGE; if (ip->i_flag & IPIPE) bp->b_flags &= ~B_DELWRI; } brelse(bp); } else { if (ioflag & IO_SYNC) bwrite(bp); else if (n + on == DEV_BSIZE && !(ip->i_flag & IPIPE)) { bp->b_flags |= B_AGE; bawrite(bp); } else bdwrite(bp); ip->i_flag |= IUPD|ICHG; if (u.u_ruid != 0) ip->i_mode &= ~(ISUID|ISGID); } } while (u.u_error == 0 && uio->uio_resid && n != 0); if (error == 0) /* XXX */ error = u.u_error; /* XXX */ if (error && (uio->uio_rw == UIO_WRITE) && (ioflag & IO_UNIT) && (type != IFBLK)) { itrunc(ip, osize); uio->uio_offset -= (resid - uio->uio_resid); uio->uio_resid = resid; /* * Should back out the change to the quota here but that would be a lot * of work for little benefit. Besides we've already made the assumption * that the entire write would succeed and users can't turn on the IO_UNIT * bit for their writes anyways. */ } #ifdef whybother if (!error && (ioflag & IO_SYNC)) IUPDAT(ip, &time, &time, 1); #endif return (error); } ino_ioctl(fp, com, data) register struct file *fp; register u_int com; caddr_t data; { register struct inode *ip = ((struct inode *)fp->f_data); dev_t dev; switch (ip->i_mode & IFMT) { case IFREG: case IFDIR: if (com == FIONREAD) { if (fp->f_type==DTYPE_PIPE && !(fp->f_flag&FREAD)) *(off_t *)data = 0; else *(off_t *)data = ip->i_size - fp->f_offset; return (0); } if (com == FIONBIO || com == FIOASYNC) /* XXX */ return (0); /* XXX */ /* fall into ... */ default: return (ENOTTY); case IFCHR: dev = ip->i_rdev; u.u_r.r_val1 = 0; if (setjmp(&u.u_qsave)) { if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) return(EINTR); u.u_eosys = RESTARTSYS; return (0); } return((*cdevsw[major(dev)].d_ioctl)(dev,com,data,fp->f_flag)); } } ino_select(fp, which) struct file *fp; int which; { register struct inode *ip = (struct inode *)fp->f_data; register dev_t dev; switch (ip->i_mode & IFMT) { default: return (1); /* XXX */ case IFCHR: dev = ip->i_rdev; return (*cdevsw[major(dev)].d_select)(dev, which); } } ino_stat(ip, sb) register struct inode *ip; register struct stat *sb; { register struct icommon2 *ic2; #ifdef EXTERNALITIMES mapseg5(xitimes, xitdesc); ic2 = &((struct icommon2 *)SEG5)[ip - inode]; #else ic2 = &ip->i_ic2; #endif /* * inlined ITIMES which takes advantage of the common times pointer. */ if (ip->i_flag & (IUPD|IACC|ICHG)) { ip->i_flag |= IMOD; if (ip->i_flag & IACC) ic2->ic_atime = time.tv_sec; if (ip->i_flag & IUPD) ic2->ic_mtime = time.tv_sec; if (ip->i_flag & ICHG) ic2->ic_ctime = time.tv_sec; ip->i_flag &= ~(IUPD|IACC|ICHG); } sb->st_dev = ip->i_dev; sb->st_ino = ip->i_number; sb->st_mode = ip->i_mode; sb->st_nlink = ip->i_nlink; sb->st_uid = ip->i_uid; sb->st_gid = ip->i_gid; sb->st_rdev = (dev_t)ip->i_rdev; sb->st_size = ip->i_size; sb->st_atime = ic2->ic_atime; sb->st_spare1 = 0; sb->st_mtime = ic2->ic_mtime; sb->st_spare2 = 0; sb->st_ctime = ic2->ic_ctime; sb->st_spare3 = 0; sb->st_blksize = MAXBSIZE; /* * blocks are too tough to do; it's not worth the effort. */ sb->st_blocks = btodb(ip->i_size + MAXBSIZE - 1); sb->st_flags = ip->i_flags; sb->st_spare4[0] = 0; sb->st_spare4[1] = 0; sb->st_spare4[2] = 0; #ifdef EXTERNALITIMES normalseg5(); #endif return (0); } ino_close(fp) register struct file *fp; { register struct inode *ip = (struct inode *)fp->f_data; register struct mount *mp; int flag, mode; dev_t dev; int (*cfunc)(); if (fp->f_flag & (FSHLOCK | FEXLOCK)) ino_unlock(fp, FSHLOCK | FEXLOCK); flag = fp->f_flag; dev = (dev_t)ip->i_rdev; mode = ip->i_mode & IFMT; ilock(ip); if (fp->f_type == DTYPE_PIPE) { if (ip->i_rsel) { selwakeup(ip->i_rsel, (long)(ip->i_flag & IRCOLL)); ip->i_rsel = 0; ip->i_flag &= ~IRCOLL; } if (ip->i_wsel) { selwakeup(ip->i_wsel, (long)(ip->i_flag & IWCOLL)); ip->i_wsel = 0; ip->i_flag &= ~IWCOLL; } ip->i_mode &= ~(IREAD|IWRITE); wakeup((caddr_t)ip+1); wakeup((caddr_t)ip+2); } iput(ip); fp->f_data = (caddr_t) 0; /* XXX */ switch (mode) { case IFCHR: cfunc = cdevsw[major(dev)].d_close; break; case IFBLK: /* * We don't want to really close the device if it is mounted */ /* MOUNT TABLE SHOULD HOLD INODE */ for (mp = mount; mp < &mount[NMOUNT]; mp++) if (mp->m_inodp != NULL && mp->m_dev == dev) return; cfunc = bdevsw[major(dev)].d_close; break; default: return; } /* * Check that another inode for the same device isn't active. * This is because the same device can be referenced by two * different inodes. */ for (fp = file; fp < fileNFILE; fp++) { if (fp->f_type != DTYPE_INODE) continue; if (fp->f_count && (ip = (struct inode *)fp->f_data) && ip->i_rdev == dev && (ip->i_mode&IFMT) == mode) return; } if (mode == IFBLK) { /* * On last close of a block device (that isn't mounted) * we must invalidate any in core blocks, so that * we can, for instance, change floppy disks. */ bflush(dev); binval(dev); } if (setjmp(&u.u_qsave)) { /* * If device close routine is interrupted, * must return so closef can clean up. */ if (u.u_error == 0) u.u_error = EINTR; /* ??? */ return; } (*cfunc)(dev, flag, mode); } /* * Place an advisory lock on an inode. */ ino_lock(fp, cmd) register struct file *fp; int cmd; { register int priority = PLOCK; register struct inode *ip = (struct inode *)fp->f_data; if ((cmd & LOCK_EX) == 0) priority += 4; if (setjmp(&u.u_qsave)) { if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) return(EINTR); u.u_eosys = RESTARTSYS; return (0); } /* * If there's a exclusive lock currently applied * to the file, then we've gotta wait for the * lock with everyone else. */ again: while (ip->i_flag & IEXLOCK) { /* * If we're holding an exclusive * lock, then release it. */ if (fp->f_flag & FEXLOCK) { ino_unlock(fp, FEXLOCK); continue; } if (cmd & LOCK_NB) return (EWOULDBLOCK); ip->i_flag |= ILWAIT; sleep((caddr_t)&ip->i_exlockc, priority); } if ((cmd & LOCK_EX) && (ip->i_flag & ISHLOCK)) { /* * Must wait for any shared locks to finish * before we try to apply a exclusive lock. * * If we're holding a shared * lock, then release it. */ if (fp->f_flag & FSHLOCK) { ino_unlock(fp, FSHLOCK); goto again; } if (cmd & LOCK_NB) return (EWOULDBLOCK); ip->i_flag |= ILWAIT; sleep((caddr_t)&ip->i_shlockc, PLOCK); goto again; } #ifdef DIAGNOSTIC if (fp->f_flag & FEXLOCK) panic("ino_lock"); #endif if (cmd & LOCK_EX) { cmd &= ~LOCK_SH; ip->i_exlockc++; ip->i_flag |= IEXLOCK; fp->f_flag |= FEXLOCK; } if ((cmd & LOCK_SH) && (fp->f_flag & FSHLOCK) == 0) { ip->i_shlockc++; ip->i_flag |= ISHLOCK; fp->f_flag |= FSHLOCK; } return (0); } /* * Unlock a file. */ ino_unlock(fp, kind) register struct file *fp; int kind; { register struct inode *ip = (struct inode *)fp->f_data; register int flags; kind &= fp->f_flag; if (ip == NULL || kind == 0) return; flags = ip->i_flag; if (kind & FSHLOCK) { if ((flags & ISHLOCK) == 0) panic("SHLOCK"); if (--ip->i_shlockc == 0) { ip->i_flag &= ~ISHLOCK; if (flags & ILWAIT) wakeup((caddr_t)&ip->i_shlockc); } fp->f_flag &= ~FSHLOCK; } if (kind & FEXLOCK) { if ((flags & IEXLOCK) == 0) panic("EXLOCK"); if (--ip->i_exlockc == 0) { ip->i_flag &= ~(IEXLOCK|ILWAIT); if (flags & ILWAIT) wakeup((caddr_t)&ip->i_exlockc); } fp->f_flag &= ~FEXLOCK; } } /* * Openi called to allow handler of special files to initialize and * validate before actual IO. */ openi(ip, mode) register struct inode *ip; { register dev_t dev = ip->i_rdev; register int maj = major(dev); dev_t bdev; int error; if (ip->i_fs->fs_flags & MNT_NODEV) return(ENXIO); switch (ip->i_mode&IFMT) { case IFCHR: if ((u_int)maj >= nchrdev) return (ENXIO); if (mode & FWRITE) { /* * When running in very secure mode, do not allow * opens for writing of any disk character devices. */ if (securelevel >= 2 && isdisk(dev, IFCHR)) return(EPERM); /* * When running in secure mode, do not allow opens * for writing of /dev/mem, /dev/kmem, or character * devices whose corresponding block devices are * currently mounted. */ if (securelevel >= 1) { if ((bdev = chrtoblk(dev)) != NODEV && (error = ufs_mountedon(bdev))) return(error); if (iskmemdev(dev)) return(EPERM); } } return ((*cdevsw[maj].d_open)(dev, mode, S_IFCHR)); case IFBLK: if ((u_int)maj >= nblkdev) return (ENXIO); /* * When running in very secure mode, do not allow * opens for writing of any disk block devices. */ if (securelevel >= 2 && (mode & FWRITE) && isdisk(dev, IFBLK)) return(EPERM); #ifdef notyet /* * Do not allow opens of block devices that are * currently mounted. * * 2.11BSD must relax this restriction to allow 'fsck' to * open the root filesystem (which is always mounted) during * a reboot. Once in secure or very secure mode the * above restriction is fully effective. * * Also, 'df' on 2.11BSD opens the device - this check can * not be enabled until the 'statfs' capability is present. */ if (securelevel > 0 && (error = ufs_mountedon(dev))) return(error); #endif return ((*bdevsw[maj].d_open)(dev, mode, S_IFBLK)); } return (0); } /* * Revoke access the current tty by all processes. * Used only by the super-user in init * to give ``clean'' terminals at login. */ vhangup() { if (!suser()) return; if (u.u_ttyp == NULL) return; forceclose(u.u_ttyd); if ((u.u_ttyp->t_state) & TS_ISOPEN) gsignal(u.u_ttyp->t_pgrp, SIGHUP); } forceclose(dev) register dev_t dev; { register struct file *fp; register struct inode *ip; for (fp = file; fp < fileNFILE; fp++) { if (fp->f_count == 0) continue; if (fp->f_type != DTYPE_INODE) continue; ip = (struct inode *)fp->f_data; if (ip == 0) continue; if ((ip->i_mode & IFMT) != IFCHR) continue; if (ip->i_rdev != dev) continue; fp->f_flag &= ~(FREAD|FWRITE); } } parameters which it left in the u. area. The u. entry * ni_offset contains the offset into the directory of the * entry to be eliminated. The ni_count field contains the sys/sys/kern_clock.c 440 0 12 20662 5511223031 7752 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)kern_clock.c 1.3 (2.11BSD GTE) 12/31/93 */ #include "param.h" #include "../machine/psl.h" #include "../machine/seg.h" #include "user.h" #include "proc.h" #include "callout.h" #include "dk.h" #include "kernel.h" #include "systm.h" /* * The hz hardware interval timer. * We update the events relating to real time. * Also gather statistics. * * reprime clock * implement callouts * maintain user/system times * maintain date * profile */ /*ARGSUSED*/ hardclock(dev,sp,r1,ov,nps,r0,pc,ps) dev_t dev; caddr_t sp, pc; int r1, ov, nps, r0, ps; { register struct callout *p1; register struct proc *p; register int needsoft = 0; mapinfo map; savemap(map); /* ensure normal mapping of kernel data */ /* * Update real-time timeout queue. * At front of queue are some number of events which are ``due''. * The time to these is <= 0 and if negative represents the * number of ticks which have passed since it was supposed to happen. * The rest of the q elements (times > 0) are events yet to happen, * where the time for each is given as a delta from the previous. * Decrementing just the first of these serves to decrement the time * to all events. */ p1 = calltodo.c_next; while (p1) { if (--p1->c_time > 0) break; needsoft = 1; if (p1->c_time == 0) break; p1 = p1->c_next; } /* * Charge the time out based on the mode the cpu is in. * Here again we fudge for the lack of proper interval timers * assuming that the current state has been around at least * one tick. */ if (USERMODE(ps)) { if (u.u_prof.pr_scale) needsoft = 1; /* * CPU was in user state. Increment * user time counter, and process process-virtual time * interval timer. */ u.u_ru.ru_utime++; if (u.u_timer[ITIMER_VIRTUAL - 1].it_value && !--u.u_timer[ITIMER_VIRTUAL - 1].it_value) { psignal(u.u_procp, SIGVTALRM); u.u_timer[ITIMER_VIRTUAL - 1].it_value = u.u_timer[ITIMER_VIRTUAL - 1].it_interval; } } else { /* * CPU was in system state. */ if (!noproc) u.u_ru.ru_stime++; } /* * If the cpu is currently scheduled to a process, then * charge it with resource utilization for a tick, updating * statistics which run in (user+system) virtual time, * such as the cpu time limit and profiling timers. * This assumes that the current process has been running * the entire last tick. */ if (noproc == 0) { p = u.u_procp; if (++p->p_cpu == 0) p->p_cpu--; if ((u.u_ru.ru_utime+u.u_ru.ru_stime+1) > u.u_rlimit[RLIMIT_CPU].rlim_cur) { psignal(p, SIGXCPU); if (u.u_rlimit[RLIMIT_CPU].rlim_cur < u.u_rlimit[RLIMIT_CPU].rlim_max) u.u_rlimit[RLIMIT_CPU].rlim_cur += 5 * LINEHZ; } if (u.u_timer[ITIMER_PROF - 1].it_value && !--u.u_timer[ITIMER_PROF - 1].it_value) { psignal(p, SIGPROF); u.u_timer[ITIMER_PROF - 1].it_value = u.u_timer[ITIMER_PROF - 1].it_interval; } } #ifdef UCB_METER gatherstats(pc,ps); #endif /* * Increment the time-of-day, process callouts at a very * low cpu priority, so we don't keep the relatively high * clock interrupt priority any longer than necessary. */ if (adjdelta) if (adjdelta > 0) { ++lbolt; --adjdelta; } else { --lbolt; ++adjdelta; } if (++lbolt >= LINEHZ) { lbolt -= LINEHZ; ++time.tv_sec; } if (needsoft && BASEPRI(ps)) { /* if ps is high, just return */ (void) _splsoftclock(); softclock(pc,ps); } restormap(map); } #ifdef UCB_METER int dk_ndrive = DK_NDRIVE; /* * Gather statistics on resource utilization. * * We make a gross assumption: that the system has been in the * state it is in (user state, kernel state, interrupt state, * or idle state) for the entire last time interval, and * update statistics accordingly. */ /*ARGSUSED*/ gatherstats(pc, ps) caddr_t pc; int ps; { register int cpstate, s; /* * Determine what state the cpu is in. */ if (USERMODE(ps)) { /* * CPU was in user state. */ if (u.u_procp->p_nice > NZERO) cpstate = CP_NICE; else cpstate = CP_USER; } else { /* * CPU was in system state. If profiling kernel * increment a counter. If no process is running * then this is a system tick if we were running * at a non-zero IPL (in a driver). If a process is running, * then we charge it with system time even if we were * at a non-zero IPL, since the system often runs * this way during processing of system calls. * This is approximate, but the lack of true interval * timers makes doing anything else difficult. */ cpstate = CP_SYS; if (noproc && BASEPRI(ps)) cpstate = CP_IDLE; } /* * We maintain statistics shown by user-level statistics * programs: the amount of time in each cpu state, and * the amount of time each of DK_NDRIVE ``drives'' is busy. */ cp_time[cpstate]++; for (s = 0; s < DK_NDRIVE; s++) if (dk_busy & (1 << s)) dk_time[s]++; } #endif UCB_METER /* * Software priority level clock interrupt. * Run periodic events from timeout queue. */ softclock(pc, ps) caddr_t pc; int ps; { for (;;) { register struct callout *p1; register caddr_t arg; register int (*func)(); register int a, s; s = splhigh(); if ((p1 = calltodo.c_next) == 0 || p1->c_time > 0) { splx(s); break; } arg = p1->c_arg; func = p1->c_func; a = p1->c_time; calltodo.c_next = p1->c_next; p1->c_next = callfree; callfree = p1; splx(s); #ifdef INET if (ISSUPERADD(func)) KScall(KERNELADD(func), sizeof(arg) + sizeof(a), arg, a); else #endif (*func)(arg, a); } /* * If trapped user-mode and profiling, give it * a profiling tick. */ if (USERMODE(ps)) { register struct proc *p = u.u_procp; if (u.u_prof.pr_scale) addupc(pc, &u.u_prof, 1); /* * Check to see if process has accumulated * more than 10 minutes of user time. If so * reduce priority to give others a chance. */ if (p->p_uid && p->p_nice == NZERO && u.u_ru.ru_utime > 10L * 60L * LINEHZ) { p->p_nice = NZERO+4; (void) setpri(p); } } } /* * Arrange that (*fun)(arg) is called in t/hz seconds. */ timeout(fun, arg, t) int (*fun)(); caddr_t arg; register int t; { register struct callout *p1, *p2, *pnew; register int s = splclock(); if (t <= 0) t = 1; pnew = callfree; if (pnew == NULL) panic("timeout table overflow"); callfree = pnew->c_next; pnew->c_arg = arg; pnew->c_func = fun; for (p1 = &calltodo; (p2 = p1->c_next) && p2->c_time < t; p1 = p2) if (p2->c_time > 0) t -= p2->c_time; p1->c_next = pnew; pnew->c_next = p2; pnew->c_time = t; if (p2) p2->c_time -= t; splx(s); } /* * untimeout is called to remove a function timeout call * from the callout structure. */ untimeout(fun, arg) int (*fun)(); caddr_t arg; { register struct callout *p1, *p2; register int s; s = splclock(); for (p1 = &calltodo; (p2 = p1->c_next) != 0; p1 = p2) { if (p2->c_func == fun && p2->c_arg == arg) { if (p2->c_next && p2->c_time > 0) p2->c_next->c_time += p2->c_time; p1->c_next = p2->c_next; p2->c_next = callfree; callfree = p2; break; } } splx(s); } profil() { register struct a { short *bufbase; unsigned bufsize; unsigned pcoffset; unsigned pcscale; } *uap = (struct a *)u.u_ap; register struct uprof *upp = &u.u_prof; upp->pr_base = uap->bufbase; upp->pr_size = uap->bufsize; upp->pr_off = uap->pcoffset; upp->pr_scale = uap->pcscale; } /* * Compute number of hz until specified time. * Used to compute third argument to timeout() from an * absolute time. */ hzto(tv) register struct timeval *tv; { register long ticks; register long sec; register int s = splhigh(); /* * If number of milliseconds will fit in 32 bit arithmetic, * then compute number of milliseconds to time and scale to * ticks. Otherwise just compute number of hz in time, rounding * times greater than representible to maximum value. * * Delta times less than 25 days can be computed ``exactly''. * Maximum value for any timeout in 10ms ticks is 250 days. */ sec = tv->tv_sec - time.tv_sec; if (sec <= 0x7fffffff / 1000 - 1000) ticks = ((tv->tv_sec - time.tv_sec) * 1000 + (tv->tv_usec - time.tv_usec) / 1000) / (1000/hz); else if (sec <= 0x7fffffff / hz) ticks = sec * hz; else ticks = 0x7fffffff; splx(s); #ifdef pdp11 /* stored in an "int", so 16-bit max */ if (ticks > 0x7fff) ticks = 0x7fff; #endif return ((int)ticks); } any disk block devices. */ if (securelevel >= 2 && (mode & FWRITE) && isdsys/sys/kern_xxx.c 440 0 12 2305 4236460005 7467 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)kern_xxx.c 1.1 (2.10BSD Berkeley) 12/1/86 */ #include "param.h" #include "user.h" #include "signal.h" #include "reboot.h" #include "kernel.h" #include "systm.h" #include "fs.h" gethostid() { u.u_r.r_off = hostid; } sethostid() { struct a { long hostid; } *uap = (struct a *)u.u_ap; if (suser()) hostid = uap->hostid; } gethostname() { register struct a { char *hostname; int len; } *uap = (struct a *)u.u_ap; register int len; len = uap->len; if (len > hostnamelen + 1) len = hostnamelen + 1; u.u_error = vcopyout((caddr_t)hostname, (caddr_t)uap->hostname, len); } sethostname() { register struct a { char *hostname; int len; } *uap = (struct a *)u.u_ap; if (!suser()) return; if (uap->len > sizeof (hostname) - 1) { u.u_error = EINVAL; return; } hostnamelen = uap->len; u.u_error = vcopyin((caddr_t)uap->hostname, hostname, uap->len); hostname[hostnamelen] = 0; } reboot() { register struct a { int opt; }; if (suser()) boot(rootdev, ((struct a *)u.u_ap)->opt); } ; caddr_t sp, pc; int r1, ov, nps, r0, ps; { register struct callout *p1; register struct proc *p; register int needsoft = 0; mapinfo map; savemap(map); /* ensure normal mapping of kernel data */ /* * Update real-time timeout queue. * At front of queue are some number of events which are ``due''. sys/sys/kern_descrip.c 440 0 12 15563 5666771415 10345 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)kern_descrip.c 1.3 (2.11BSD GTE) 11/26/94 */ #include "param.h" #include "user.h" #include "proc.h" #include "file.h" #include "systm.h" #include "inode.h" #include "ioctl.h" #include "stat.h" #include "conf.h" #ifdef INET #include "socket.h" #include "socketvar.h" #endif /* * Descriptor management. */ /* * System calls on descriptors. */ getdtablesize() { u.u_r.r_val1 = NOFILE; } dup() { register struct a { int i; } *uap = (struct a *) u.u_ap; register struct file *fp; register int j; if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */ GETF(fp, uap->i); j = ufalloc(0); if (j < 0) return; dupit(j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE); } dup2() { register struct a { int i, j; } *uap = (struct a *) u.u_ap; register struct file *fp; GETF(fp, uap->i); if (uap->j < 0 || uap->j >= NOFILE) { u.u_error = EBADF; return; } u.u_r.r_val1 = uap->j; if (uap->i == uap->j) return; if (u.u_ofile[uap->j]) { closef(u.u_ofile[uap->j]); if (u.u_error) return; } dupit(uap->j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE); } dupit(fd, fp, flags) register int fd; register struct file *fp; int flags; { u.u_ofile[fd] = fp; u.u_pofile[fd] = flags; fp->f_count++; if (fd > u.u_lastfile) u.u_lastfile = fd; } /* * The file control system call. */ fcntl() { register struct file *fp; register struct a { int fdes; int cmd; int arg; } *uap; register i; register char *pop; uap = (struct a *)u.u_ap; if ((fp = getf(uap->fdes)) == NULL) return; pop = &u.u_pofile[uap->fdes]; switch(uap->cmd) { case F_DUPFD: i = uap->arg; if (i < 0 || i >= NOFILE) { u.u_error = EINVAL; return; } if ((i = ufalloc(i)) < 0) return; dupit(i, fp, *pop &~ UF_EXCLOSE); break; case F_GETFD: u.u_r.r_val1 = *pop & 1; break; case F_SETFD: *pop = (*pop &~ 1) | (uap->arg & 1); break; case F_GETFL: u.u_r.r_val1 = OFLAGS(fp->f_flag); break; case F_SETFL: fp->f_flag &= ~FCNTLFLAGS; fp->f_flag |= (FFLAGS(uap->arg)) & ~FCNTLFLAGS; u.u_error = fset(fp, FNONBLOCK, fp->f_flag & FNONBLOCK); if (u.u_error) break; u.u_error = fset(fp, FASYNC, fp->f_flag & FASYNC); if (u.u_error) (void) fset(fp, FNONBLOCK, 0); break; case F_GETOWN: u.u_error = fgetown(fp, &u.u_r.r_val1); break; case F_SETOWN: u.u_error = fsetown(fp, uap->arg); break; default: u.u_error = EINVAL; } } fset(fp, bit, value) register struct file *fp; int bit, value; { if (value) fp->f_flag |= bit; else fp->f_flag &= ~bit; return (fioctl(fp, (u_int)(bit == FNONBLOCK ? FIONBIO : FIOASYNC), (caddr_t)&value)); } fgetown(fp, valuep) register struct file *fp; register int *valuep; { register int error; #ifdef INET if (fp->f_type == DTYPE_SOCKET) { *valuep = mfsd(&fp->f_socket->so_pgrp); return (0); } #endif error = fioctl(fp, (u_int)TIOCGPGRP, (caddr_t)valuep); *valuep = -*valuep; return (error); } fsetown(fp, value) register struct file *fp; int value; { #ifdef INET if (fp->f_type == DTYPE_SOCKET) { mtsd(&fp->f_socket->so_pgrp, value); return (0); } #endif if (value > 0) { register struct proc *p = pfind(value); if (p == 0) return (ESRCH); value = p->p_pgrp; } else value = -value; return (fioctl(fp, (u_int)TIOCSPGRP, (caddr_t)&value)); } extern struct fileops *Fops[]; fioctl(fp, cmd, value) register struct file *fp; u_int cmd; caddr_t value; { return ((*Fops[fp->f_type]->fo_ioctl)(fp, cmd, value)); } close() { register struct a { int i; } *uap = (struct a *)u.u_ap; register struct file *fp; GETF(fp, uap->i); u.u_ofile[uap->i] = NULL; while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL) u.u_lastfile--; closef(fp); /* WHAT IF u.u_error ? */ } fstat() { register struct file *fp; register struct a { int fdes; struct stat *sb; } *uap; struct stat ub; uap = (struct a *)u.u_ap; if ((fp = getf(uap->fdes)) == NULL) return; switch (fp->f_type) { case DTYPE_PIPE: case DTYPE_INODE: u.u_error = ino_stat((struct inode *)fp->f_data, &ub); if (fp->f_type == DTYPE_PIPE) ub.st_size -= fp->f_offset; break; #ifdef INET case DTYPE_SOCKET: u.u_error = SOO_STAT(fp->f_socket, &ub); break; #endif default: u.u_error = EINVAL; break; } if (u.u_error == 0) u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub)); } /* copied, for supervisory networking, to sys_net.c */ /* * Allocate a user file descriptor. */ ufalloc(i) register int i; { for (; i < NOFILE; i++) if (u.u_ofile[i] == NULL) { u.u_r.r_val1 = i; u.u_pofile[i] = 0; if (i > u.u_lastfile) u.u_lastfile = i; return (i); } u.u_error = EMFILE; return (-1); } /* moved, for supervisory networking, to sys_net.c */ #ifdef notdef ufavail() { register int i, avail = 0; for (i = 0; i < NOFILE; i++) if (u.u_ofile[i] == NULL) avail++; return (avail); } #endif struct file *lastf; /* * Allocate a user file descriptor * and a file structure. * Initialize the descriptor * to point at the file structure. */ struct file * falloc() { register struct file *fp; register i; i = ufalloc(0); if (i < 0) return (NULL); if (lastf == 0) lastf = file; for (fp = lastf; fp < fileNFILE; fp++) if (fp->f_count == 0) goto slot; for (fp = file; fp < lastf; fp++) if (fp->f_count == 0) goto slot; tablefull("file"); u.u_error = ENFILE; return (NULL); slot: u.u_ofile[i] = fp; fp->f_count = 1; fp->f_data = 0; fp->f_offset = 0; lastf = fp + 1; return (fp); } /* * Convert a user supplied file descriptor into a pointer * to a file structure. Only task is to check range of the descriptor. * Critical paths should use the GETF macro unless code size is a * consideration. */ struct file * getf(f) register int f; { register struct file *fp; if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { u.u_error = EBADF; return (NULL); } return (fp); } /* * Internal form of close. * Decrement reference count on file structure. */ closef(fp) register struct file *fp; { if (fp == NULL) return; if (fp->f_count > 1) { fp->f_count--; return; } (*Fops[fp->f_type]->fo_close)(fp); fp->f_count = 0; } /* * Apply an advisory lock on a file descriptor. */ flock() { register struct a { int fd; int how; } *uap = (struct a *)u.u_ap; register struct file *fp; if ((fp = getf(uap->fd)) == NULL) return; if (fp->f_type != DTYPE_INODE) { u.u_error = EOPNOTSUPP; return; } if (uap->how & LOCK_UN) { ino_unlock(fp, FSHLOCK | FEXLOCK); return; } if ((uap->how & (LOCK_SH | LOCK_EX)) == 0) return; /* error? */ if (uap->how & LOCK_EX) uap->how &= ~LOCK_SH; /* avoid work... */ if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) || (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH)) return; u.u_error = ino_lock(fp, uap->how); } k(); for (p1 = &calltodo; (p2 = p1->c_next) != 0; p1 = p2) { if (p2->c_func == fun && p2->c_arg == arg) { if (p2->c_next && p2->c_time sys/sys/ufs_fio.c 444 0 12 10444 5700661327 7311 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ufs_fio.c 1.3 (2.11BSD GTE) 12/29/94 */ #include "param.h" #include "user.h" #include "fs.h" #include "inode.h" #include "mount.h" #include "namei.h" #include "systm.h" #include "acct.h" #include "stat.h" /* * Check mode permission on inode pointer. * Mode is READ, WRITE or EXEC. * In the case of WRITE, the * read-only status of the file * system is checked. * Also in WRITE, prototype text * segments cannot be written. * The mode is shifted to select * the owner/group/other fields. * The super user is granted all * permissions. */ access(ip, mode) register struct inode *ip; int mode; { register m; register gid_t *gp; m = mode; if (m == IWRITE) { if (ip->i_flags & IMMUTABLE) { u.u_error = EPERM; return(1); } /* * Disallow write attempts on read-only * file systems; unless the file is a block * or character device resident on the * file system. */ if (ip->i_fs->fs_ronly != 0) { if ((ip->i_mode & IFMT) != IFCHR && (ip->i_mode & IFMT) != IFBLK) { u.u_error = EROFS; return (1); } } /* * If there's shared text associated with * the inode, try to free it up once. If * we fail, we can't allow writing. */ if (ip->i_flag&ITEXT) xuntext(ip->i_text); if (ip->i_flag & ITEXT) { u.u_error = ETXTBSY; return (1); } } /* * If you're the super-user, * you always get access. */ if (u.u_uid == 0) return (0); /* * Access check is based on only * one of owner, group, public. * If not owner, then check group. * If not a member of the group, then * check public access. */ if (u.u_uid != ip->i_uid) { m >>= 3; if (u.u_gid == ip->i_gid) goto found; gp = u.u_groups; for (; gp < &u.u_groups[NGROUPS] && *gp != NOGROUP; gp++) if (ip->i_gid == *gp) goto found; m >>= 3; found: ; } if ((ip->i_mode&m) != 0) return (0); u.u_error = EACCES; return (1); } /* copied, for supervisory networking, to sys_net.c */ /* * Test if the current user is the * super user. */ suser() { if (u.u_uid == 0) { u.u_acflag |= ASU; return (1); } u.u_error = EPERM; return (0); } /* * Set the attributes on a file. This was placed here because ufs_syscalls * is too large already (it will probably be split into two files eventually). */ ufs_setattr(ip, vap) register struct inode *ip; register struct vattr *vap; { int error; struct timeval atimeval, mtimeval; if (ip->i_fs->fs_ronly) /* can't change anything on a RO fs */ return(EROFS); if (vap->va_flags != VNOVAL) { if (u.u_uid != ip->i_uid && !suser()) return(u.u_error); if (u.u_uid == 0) { if ((ip->i_flags & (SF_IMMUTABLE|SF_APPEND)) && securelevel > 0) return(EPERM); ip->i_flags = vap->va_flags; } else { if (ip->i_flags & (SF_IMMUTABLE|SF_APPEND)) return(EPERM); ip->i_flags &= SF_SETTABLE; ip->i_flags |= (vap->va_flags & UF_SETTABLE); } ip->i_flag |= ICHG; if (vap->va_flags & (IMMUTABLE|APPEND)) return(0); } if (ip->i_flags & (IMMUTABLE|APPEND)) return(EPERM); /* * Go thru the fields (other than 'flags') and update iff not VNOVAL. */ if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) if (error = chown1(ip, vap->va_uid, vap->va_gid)) return(error); if (vap->va_size != (off_t)VNOVAL) { if ((ip->i_mode & IFMT) == IFDIR) return(EISDIR); itrunc(ip, vap->va_size); if (u.u_error) return(u.u_error); } if (vap->va_atime != (time_t)VNOVAL || vap->va_mtime != (time_t)VNOVAL) { if (u.u_uid != ip->i_uid && !suser() && ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || access(ip, IWRITE))) return(u.u_error); if (vap->va_atime != (time_t)VNOVAL) ip->i_flag |= IACC; if (vap->va_mtime != (time_t)VNOVAL) ip->i_flag |= (IUPD|ICHG); atimeval.tv_sec = vap->va_atime; mtimeval.tv_sec = vap->va_mtime; iupdat(ip, &atimeval, &mtimeval, 1); } if (vap->va_mode != (mode_t)VNOVAL) return(chmod1(ip, vap->va_mode)); return(0); } ufs_mountedon(dev) dev_t dev; { register struct mount *mp; for (mp = mount; mp < &mount[NMOUNT]; mp++) { if (mp->m_inodp == NULL) continue; if (mp->m_dev == dev) return(EBUSY); } return(0); } return (ESRCH); value = p->p_pgrp; } else value = -value; return (fioctl(fp, (u_int)TIOCSPGRP, (caddr_t)&value)); } extern struct fileops *Fops[]; fioctl(fp, cmd, value) register struct file *fp; u_int cmd; sys/sys/kern_prot.c 440 0 12 10667 5753600404 7662 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)kern_prot.c 1.2 (2.11BSD GTE) 1995/05/08 */ /* * System calls related to processes and protection */ #include "param.h" #include "user.h" #include "proc.h" #include "systm.h" #ifdef QUOTA #include "quota.h" #endif getpid() { u.u_r.r_val1 = u.u_procp->p_pid; u.u_r.r_val2 = u.u_procp->p_ppid; /* XXX - compatibility */ } getppid() { u.u_r.r_val1 = u.u_procp->p_ppid; } getpgrp() { register struct a { int pid; } *uap = (struct a *)u.u_ap; register struct proc *p; if (uap->pid == 0) /* silly... */ uap->pid = u.u_procp->p_pid; p = pfind(uap->pid); if (p == 0) { u.u_error = ESRCH; return; } u.u_r.r_val1 = p->p_pgrp; } getuid() { u.u_r.r_val1 = u.u_ruid; u.u_r.r_val2 = u.u_uid; /* XXX */ } geteuid() { u.u_r.r_val1 = u.u_uid; } getgid() { u.u_r.r_val1 = u.u_rgid; u.u_r.r_val2 = u.u_gid; /* XXX */ } getegid() { u.u_r.r_val1 = u.u_gid; } /* * getgroups and setgroups differ from 4.X because the VAX stores group * entries in the user structure as shorts and has to convert them to ints. */ getgroups() { register struct a { u_int gidsetsize; int *gidset; } *uap = (struct a *)u.u_ap; register gid_t *gp; for (gp = &u.u_groups[NGROUPS]; gp > u.u_groups; gp--) if (gp[-1] != NOGROUP) break; if (uap->gidsetsize < gp - u.u_groups) { u.u_error = EINVAL; return; } uap->gidsetsize = gp - u.u_groups; u.u_error = copyout((caddr_t)u.u_groups, (caddr_t)uap->gidset, uap->gidsetsize * sizeof(u.u_groups[0])); if (u.u_error) return; u.u_r.r_val1 = uap->gidsetsize; } setpgrp() { register struct proc *p; register struct a { int pid; int pgrp; } *uap = (struct a *)u.u_ap; if (uap->pid == 0) /* silly... */ uap->pid = u.u_procp->p_pid; p = pfind(uap->pid); if (p == 0) { u.u_error = ESRCH; return; } /* need better control mechanisms for process groups */ if (p->p_uid != u.u_uid && u.u_uid && !inferior(p)) { u.u_error = EPERM; return; } p->p_pgrp = uap->pgrp; } setreuid() { struct a { int ruid; int euid; } *uap; register int ruid, euid; uap = (struct a *)u.u_ap; ruid = uap->ruid; if (ruid == -1) ruid = u.u_ruid; if (u.u_ruid != ruid && u.u_uid != ruid && !suser()) return; euid = uap->euid; if (euid == -1) euid = u.u_uid; if (u.u_ruid != euid && u.u_uid != euid && !suser()) return; /* * Everything's okay, do it. */ #ifdef QUOTA QUOTAMAP(); if (u.u_quota->q_uid != ruid) { qclean(); qstart(getquota((uid_t)ruid, 0, 0)); } QUOTAUNMAP(); #endif u.u_procp->p_uid = euid; u.u_ruid = ruid; u.u_uid = euid; } setregid() { register struct a { int rgid; int egid; } *uap; register int rgid, egid; uap = (struct a *)u.u_ap; rgid = uap->rgid; if (rgid == -1) rgid = u.u_rgid; if (u.u_rgid != rgid && u.u_gid != rgid && !suser()) return; egid = uap->egid; if (egid == -1) egid = u.u_gid; if (u.u_rgid != egid && u.u_gid != egid && !suser()) return; if (u.u_rgid != rgid) { leavegroup(u.u_rgid); (void) entergroup(rgid); u.u_rgid = rgid; } u.u_gid = egid; } setgroups() { register struct a { u_int gidsetsize; int *gidset; } *uap = (struct a *)u.u_ap; register gid_t *gp; if (!suser()) return; if (uap->gidsetsize > sizeof (u.u_groups) / sizeof (u.u_groups[0])) { u.u_error = EINVAL; return; } u.u_error = copyin((caddr_t)uap->gidset, (caddr_t)u.u_groups, uap->gidsetsize * sizeof (u.u_groups[0])); if (u.u_error) return; for (gp = &u.u_groups[uap->gidsetsize]; gp < &u.u_groups[NGROUPS]; gp++) *gp = NOGROUP; } /* * Group utility functions. */ /* * Delete gid from the group set. */ leavegroup(gid) int gid; { register gid_t *gp; for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++) if (*gp == gid) goto found; return; found: for (; gp < &u.u_groups[NGROUPS-1]; gp++) *gp = *(gp+1); *gp = NOGROUP; } /* * Add gid to the group set. */ entergroup(gid) int gid; { register gid_t *gp; for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++) { if (*gp == gid) return (0); if (*gp == NOGROUP) { *gp = gid; return (0); } } return (-1); } /* * Check if gid is a member of the group set. */ groupmember(gid) gid_t gid; { register gid_t *gp; if (u.u_gid == gid) return (1); for (gp = u.u_groups; gp < &u.u_groups[NGROUPS] && *gp != NOGROUP; gp++) if (*gp == gid) return (1); return (0); } b)); } /* copied, for supervisory networking, to sys_net.c */ /* * Allosys/sys/vm_swap.c 440 0 12 7253 5347537475 7330 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)vm_swap.c 1.3 (2.11BSD GTE) 3/10/93 */ #include "param.h" #include "../machine/seg.h" #include "user.h" #include "proc.h" #include "text.h" #include "map.h" #include "buf.h" #include "systm.h" #include "vm.h" /* * Swap a process in. * Allocate data and possible text separately. It would be better * to do largest first. Text, data, stack and u. are allocated in * that order, as that is likely to be in order of size. */ swapin(p) register struct proc *p; { register struct text *xp; register memaddr x = NULL; memaddr a[3]; /* Malloc the text segment first, as it tends to be largest. */ xp = p->p_textp; if (xp) { xlock(xp); if (!xp->x_caddr && !xp->x_ccount) { x = malloc(coremap, xp->x_size); if (!x) { xunlock(xp); return(0); } } } if (malloc3(coremap, p->p_dsize, p->p_ssize, USIZE, a) == NULL) { if (x) mfree(coremap, xp->x_size, x); if (xp) xunlock(xp); return(0); } if (xp) { if (x) { xp->x_caddr = x; if ((xp->x_flag & XLOAD) == 0) swap(xp->x_daddr, x, xp->x_size, B_READ); } xp->x_ccount++; xunlock(xp); } if (p->p_dsize) { swap(p->p_daddr, a[0], p->p_dsize, B_READ); mfree(swapmap, ctod(p->p_dsize), p->p_daddr); } if (p->p_ssize) { swap(p->p_saddr, a[1], p->p_ssize, B_READ); mfree(swapmap, ctod(p->p_ssize), p->p_saddr); } swap(p->p_addr, a[2], USIZE, B_READ); mfree(swapmap, ctod(USIZE), p->p_addr); p->p_daddr = a[0]; p->p_saddr = a[1]; p->p_addr = a[2]; if (p->p_stat == SRUN) setrq(p); p->p_flag |= SLOAD; p->p_time = 0; #ifdef UCB_METER cnt.v_swpin++; #endif return(1); } /* * Swap out process p. * odata and ostack are the old data size and the stack size * of the process, and are supplied during core expansion swaps. * The freecore flag causes its core to be freed -- it may be * off when called to create an image for a child process * in newproc. * * panic: out of swap space */ swapout(p, freecore, odata, ostack) register struct proc *p; int freecore; register u_int odata, ostack; { memaddr a[3]; if (odata == (u_int)X_OLDSIZE) odata = p->p_dsize; if (ostack == (u_int)X_OLDSIZE) ostack = p->p_ssize; if (malloc3(swapmap, ctod(p->p_dsize), ctod(p->p_ssize), ctod(USIZE), a) == NULL) panic("out of swap space"); p->p_flag |= SLOCK; if (p->p_textp) xccdec(p->p_textp); if (odata) { swap(a[0], p->p_daddr, odata, B_WRITE); if (freecore == X_FREECORE) mfree(coremap, odata, p->p_daddr); } if (ostack) { swap(a[1], p->p_saddr, ostack, B_WRITE); if (freecore == X_FREECORE) mfree(coremap, ostack, p->p_saddr); } /* * Increment u_ru.ru_nswap for process being tossed out of core. * We can be called to swap out a process other than the current * process, so we have to map in the victim's u structure briefly. * Note, savekdsa6 *must* be a static, because we remove the stack * in the next instruction. The splclock is to prevent the clock * from coming in and doing accounting for the wrong process, plus * we don't want to come through here twice. Why are we doing * this, anyway? */ { static u_short savekdsa6; int s; s = splclock(); savekdsa6 = *KDSA6; *KDSA6 = p->p_addr; u.u_ru.ru_nswap++; *KDSA6 = savekdsa6; splx(s); } swap(a[2], p->p_addr, USIZE, B_WRITE); if (freecore == X_FREECORE) mfree(coremap, USIZE, p->p_addr); p->p_daddr = a[0]; p->p_saddr = a[1]; p->p_addr = a[2]; p->p_flag &= ~(SLOAD|SLOCK); p->p_time = 0; #ifdef UCB_METER cnt.v_swpout++; #endif if (runout) { runout = 0; wakeup((caddr_t)&runout); } } .u_uid = euid; } setregid() { register struct a { int rgid; int egid; } *uap; register int rgid, egid; uap = (struct a *)u.u_ap; rgid = uap->rgid; if (rgid == -1) rgid = u.u_rgid; if (u.u_rgid != rgid && u.u_gid != rgid && !suser()) return; egid = uap->egid; if (egid == -1) egid = u.u_gid; if (u.u_rgid != egid && u.u_sys/sys/kern_time.c 440 0 12 15733 5511223066 7630 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)kern_time.c 1.3 (2.11BSD GTE) 12/31/93 */ #include "param.h" #include "user.h" #include "proc.h" #include "kernel.h" /* * Time of day and interval timer support. * * These routines provide the kernel entry points to get and set * the time-of-day. */ gettimeofday() { register struct a { struct timeval *tp; struct timezone *tzp; } *uap = (struct a *)u.u_ap; struct timeval atv; int s; register u_int ms; if (uap->tp) { /* * We don't resolve the milliseconds on every clock tick; it's * easier to do it here. Long casts are out of paranoia. */ s = splhigh(); atv = time; ms = lbolt; splx(s); atv.tv_usec = (long)ms * 1000000L / (long)LINEHZ; u.u_error = copyout((caddr_t)&atv, (caddr_t)(uap->tp), sizeof(atv)); if (u.u_error) return; } if (uap->tzp) u.u_error = copyout((caddr_t)&tz, (caddr_t)uap->tzp, sizeof (tz)); } settimeofday() { register struct a { struct timeval *tv; struct timezone *tzp; } *uap = (struct a *)u.u_ap; struct timeval atv; struct timezone atz; if (uap->tv) { u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof (struct timeval)); if (u.u_error) return; setthetime(&atv); } if (uap->tzp && suser()) { u.u_error = copyin((caddr_t)uap->tzp, (caddr_t)&atz, sizeof (atz)); if (u.u_error == 0) tz = atz; } } setthetime(tv) struct timeval *tv; { int s; if (!suser()) return; /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ boottime.tv_sec += tv->tv_sec - time.tv_sec; s = splhigh(); time = *tv; lbolt = time.tv_usec / (1000000L / LINEHZ); splx(s); #ifndef pdp11 /* * if you have a time of day board, use it here */ resettodr(); #endif } adjtime() { register struct a { struct timeval *delta; struct timeval *olddelta; } *uap = (struct a *)u.u_ap; struct timeval atv; register int s; long adjust; if (!suser()) return; u.u_error = copyin((caddr_t)uap->delta, (caddr_t)&atv, sizeof (struct timeval)); if (u.u_error) return; adjust = atv.tv_sec * LINEHZ + atv.tv_usec / (1000000L / LINEHZ); /* if unstoreable values, just set the clock */ if (adjust > 0x7fff || adjust < 0x8000) { s = splclock(); time.tv_sec += atv.tv_sec; lbolt += atv.tv_usec / (1000000L / LINEHZ); while (lbolt >= LINEHZ) { lbolt -= LINEHZ; ++time.tv_sec; } splx(s); if (!uap->olddelta) return; atv.tv_sec = atv.tv_usec = 0; } else { if (!uap->olddelta) { adjdelta = adjust; return; } atv.tv_sec = adjdelta / LINEHZ; atv.tv_usec = (adjdelta % LINEHZ) * (1000000L / LINEHZ); adjdelta = adjust; } (void) copyout((caddr_t)&atv, (caddr_t)uap->olddelta, sizeof (struct timeval)); } getitimer() { register struct a { u_int which; struct itimerval *itv; } *uap = (struct a *)u.u_ap; struct itimerval aitv; register int s; if (uap->which > ITIMER_PROF) { u.u_error = EINVAL; return; } aitv.it_interval.tv_usec = 0; aitv.it_value.tv_usec = 0; s = splclock(); if (uap->which == ITIMER_REAL) { register struct proc *p = u.u_procp; aitv.it_interval.tv_sec = p->p_realtimer.it_interval; aitv.it_value.tv_sec = p->p_realtimer.it_value; } else { register struct k_itimerval *t = &u.u_timer[uap->which - 1]; aitv.it_interval.tv_sec = t->it_interval / LINEHZ; aitv.it_value.tv_sec = t->it_value / LINEHZ; } splx(s); u.u_error = copyout((caddr_t)&aitv, (caddr_t)uap->itv, sizeof (struct itimerval)); } setitimer() { register struct a { u_int which; struct itimerval *itv, *oitv; } *uap = (struct a *)u.u_ap; struct itimerval aitv; register struct itimerval *aitvp; int s; if (uap->which > ITIMER_PROF) { u.u_error = EINVAL; return; } aitvp = uap->itv; if (uap->oitv) { uap->itv = uap->oitv; getitimer(); } if (aitvp == 0) return; u.u_error = copyin((caddr_t)aitvp, (caddr_t)&aitv, sizeof (struct itimerval)); if (u.u_error) return; s = splclock(); if (uap->which == ITIMER_REAL) { register struct proc *p = u.u_procp; p->p_realtimer.it_value = aitv.it_value.tv_sec; if (aitv.it_value.tv_usec) ++p->p_realtimer.it_value; p->p_realtimer.it_interval = aitv.it_interval.tv_sec; if (aitv.it_interval.tv_usec) ++p->p_realtimer.it_interval; } else { register struct k_itimerval *t = &u.u_timer[uap->which - 1]; t->it_value = aitv.it_value.tv_sec * LINEHZ; if (aitv.it_value.tv_usec) t->it_value += LINEHZ; t->it_interval = aitv.it_interval.tv_sec * LINEHZ; if (aitv.it_interval.tv_usec) t->it_interval += LINEHZ; } splx(s); } /* * Check that a proposed value to load into the .it_value or * .it_interval part of an interval timer is acceptable, and * fix it to have at least minimal value (i.e. if it is less * than the resolution of the clock, round it up.) */ itimerfix(tv) struct timeval *tv; { if (tv->tv_sec < 0 || tv->tv_sec > 100000000L || tv->tv_usec < 0 || tv->tv_usec >= 1000000L) return (EINVAL); if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < (1000/hz)) tv->tv_usec = 1000/hz; return (0); } #ifdef NOT_CURRENTLY_IN_USE /* * Decrement an interval timer by a specified number * of microseconds, which must be less than a second, * i.e. < 1000000. If the timer expires, then reload * it. In this case, carry over (usec - old value) to * reducint the value reloaded into the timer so that * the timer does not drift. This routine assumes * that it is called in a context where the timers * on which it is operating cannot change in value. */ itimerdecr(itp, usec) register struct itimerval *itp; int usec; { if (itp->it_value.tv_usec < usec) { if (itp->it_value.tv_sec == 0) { /* expired, and already in next interval */ usec -= itp->it_value.tv_usec; goto expire; } itp->it_value.tv_usec += 1000000; itp->it_value.tv_sec--; } itp->it_value.tv_usec -= usec; usec = 0; if (timerisset(&itp->it_value)) return (1); /* expired, exactly at end of interval */ expire: if (timerisset(&itp->it_interval)) { itp->it_value = itp->it_interval; itp->it_value.tv_usec -= usec; if (itp->it_value.tv_usec < 0) { itp->it_value.tv_usec += 1000000L; itp->it_value.tv_sec--; } } else itp->it_value.tv_usec = 0; /* sec is already 0 */ return (0); } #endif /* NOT_CURRENTLY_IN_USE */ #define timevalfix tvfix /* * Add and subtract routines for timevals. * N.B.: subtract routine doesn't deal with * results which are before the beginning, * it just gets very confused in this case. * Caveat emptor. */ timevaladd(t1, t2) struct timeval *t1, *t2; { t1->tv_sec += t2->tv_sec; t1->tv_usec += t2->tv_usec; timevalfix(t1); } #ifdef NOT_CURRENTLY_IN_USE timevalsub(t1, t2) struct timeval *t1, *t2; { t1->tv_sec -= t2->tv_sec; t1->tv_usec -= t2->tv_usec; timevalfix(t1); } #endif timevalfix(t1) struct timeval *t1; { if (t1->tv_usec < 0) { t1->tv_sec--; t1->tv_usec += 1000000; } if (t1->tv_usec >= 1000000) { t1->tv_sec++; t1->tv_usec -= 1000000; } } register struct a { struct timevasys/sys/ufs_inode.c 440 0 12 41652 5666527434 7646 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ufs_inode.c 1.4 (2.11BSD GTE) 11/26/94 */ #include "param.h" #include "../machine/seg.h" #include "user.h" #include "proc.h" #include "inode.h" #include "fs.h" #include "mount.h" #include "kernel.h" #include "buf.h" #include "text.h" #include "systm.h" #ifdef QUOTA #include "quota.h" #endif #include "syslog.h" #define INOHSZ 16 /* must be power of two */ #define INOHASH(dev,ino) (((dev)+(ino))&(INOHSZ-1)) union ihead { /* inode LRU cache, stolen */ union ihead *ih_head[2]; struct inode *ih_chain[2]; } ihead[INOHSZ]; struct inode *ifreeh, **ifreet; /* * Initialize hash links for inodes * and build inode free list. */ ihinit() { register int i; register struct inode *ip = inode; register union ihead *ih = ihead; for (i = INOHSZ; --i >= 0; ih++) { ih->ih_head[0] = ih; ih->ih_head[1] = ih; } ifreeh = ip; ifreet = &ip->i_freef; ip->i_freeb = &ifreeh; ip->i_forw = ip; ip->i_back = ip; for (i = ninode; --i > 0; ) { ++ip; ip->i_forw = ip; ip->i_back = ip; *ifreet = ip; ip->i_freeb = ifreet; ifreet = &ip->i_freef; } ip->i_freef = NULL; } /* * Find an inode if it is incore. */ struct inode * ifind(dev, ino) register dev_t dev; register ino_t ino; { register struct inode *ip; union ihead *ih; ih = &ihead[INOHASH(dev, ino)]; for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw) if (ino == ip->i_number && dev == ip->i_dev) return(ip); return((struct inode *)NULL); } /* * Look up an inode by device,inumber. * If it is in core (in the inode structure), * honor the locking protocol. * If it is not in core, read it in from the * specified device. * If the inode is mounted on, perform * the indicated indirection. * In all cases, a pointer to a locked * inode structure is returned. * * panic: no imt -- if the mounted file * system is not in the mount table. * "cannot happen" */ struct inode * iget(dev, fs, ino) dev_t dev; register struct fs *fs; ino_t ino; { register struct inode *ip; union ihead *ih; struct buf *bp; struct dinode *dp; #ifdef EXTERNALITIMES struct icommon2 xic2; #endif #ifdef QUOTA struct dquot **xdq; #endif loop: ih = &ihead[INOHASH(dev, ino)]; for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw) if (ino == ip->i_number && dev == ip->i_dev) { /* * Following is essentially an inline expanded * copy of igrab(), expanded inline for speed, * and so that the test for a mounted on inode * can be deferred until after we are sure that * the inode isn't busy. */ if ((ip->i_flag&ILOCKED) != 0) { ip->i_flag |= IWANT; sleep((caddr_t)ip, PINOD); goto loop; } if ((ip->i_flag&IMOUNT) != 0) { register struct mount *mp; for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) if(mp->m_inodp == ip) { dev = mp->m_dev; fs = &mp->m_filsys; ino = ROOTINO; goto loop; } panic("no imt"); } if (ip->i_count == 0) { /* ino on free list */ register struct inode *iq; if (iq = ip->i_freef) iq->i_freeb = ip->i_freeb; else ifreet = ip->i_freeb; *ip->i_freeb = iq; ip->i_freef = NULL; ip->i_freeb = NULL; } ip->i_count++; ip->i_flag |= ILOCKED; return(ip); } if ((ip = ifreeh) == NULL) { tablefull("inode"); u.u_error = ENFILE; return(NULL); } if (ip->i_count) panic("free inode isn't"); { register struct inode *iq; if (iq = ip->i_freef) iq->i_freeb = &ifreeh; ifreeh = iq; } ip->i_freef = NULL; ip->i_freeb = NULL; /* * Now to take inode off the hash chain it was on * (initially, or after an iflush, it is on a "hash chain" * consisting entirely of itself, and pointed to by no-one, * but that doesn't matter), and put it on the chain for * its new (ino, dev) pair */ remque(ip); insque(ip, ih); ip->i_dev = dev; ip->i_fs = fs; ip->i_number = ino; cacheinval(ip); ip->i_flag = ILOCKED; ip->i_count++; ip->i_lastr = 0; #ifdef QUOTA QUOTAMAP(); xdq = &ix_dquot[ip - inode]; dqrele(*xdq); QUOTAUNMAP(); #endif bp = bread(dev, itod(ino)); /* * Check I/O errors */ if ((bp->b_flags&B_ERROR) != 0) { brelse(bp); /* * the inode doesn't contain anything useful, so it would * be misleading to leave it on its hash chain. * 'iput' will take care of putting it back on the free list. */ remque(ip); ip->i_forw = ip; ip->i_back = ip; /* * we also loose its inumber, just in case (as iput * doesn't do that any more) - but as it isn't on its * hash chain, I doubt if this is really necessary .. kre * (probably the two methods are interchangable) */ ip->i_number = 0; #ifdef QUOTA QUOTAMAP(); *xdq = NODQUOT; QUOTAUNMAP(); #endif iput(ip); return(NULL); } dp = (struct dinode *)mapin(bp); dp += itoo(ino); ip->i_ic1 = dp->di_ic1; ip->i_flags = dp->di_flags; #ifdef EXTERNALITIMES xic2 = dp->di_ic2; #else ip->i_ic2 = dp->di_ic2; #endif bcopy(dp->di_addr, ip->i_addr, NADDR * sizeof (daddr_t)); mapout(bp); brelse(bp); #ifdef EXTERNALITIMES mapseg5(xitimes, xitdesc); ((struct icommon2 *)SEG5)[ip-inode] = xic2; normalseg5(); #endif #ifdef QUOTA QUOTAMAP(); if (ip->i_mode == 0) *xdq = NODQUOT; else *xdq = inoquota(ip); QUOTAUNMAP(); #endif return (ip); } /* * Convert a pointer to an inode into a reference to an inode. * * This is basically the internal piece of iget (after the * inode pointer is located) but without the test for mounted * filesystems. It is caller's responsibility to check that * the inode pointer is valid. */ igrab(ip) register struct inode *ip; { while ((ip->i_flag&ILOCKED) != 0) { ip->i_flag |= IWANT; sleep((caddr_t)ip, PINOD); } if (ip->i_count == 0) { /* ino on free list */ register struct inode *iq; if (iq = ip->i_freef) iq->i_freeb = ip->i_freeb; else ifreet = ip->i_freeb; *ip->i_freeb = iq; ip->i_freef = NULL; ip->i_freeb = NULL; } ip->i_count++; ip->i_flag |= ILOCKED; } /* * Decrement reference count of * an inode structure. * On the last reference, * write the inode out and if necessary, * truncate and deallocate the file. */ iput(ip) register struct inode *ip; { #ifndef notnow /* * This code requires a lot of workarounds, you have to change * lots of places to gratuitously lock just so we can unlock it. * Not worth it. -- KB */ if ((ip->i_flag & ILOCKED) == 0) panic("iput"); #endif IUNLOCK(ip); irele(ip); } irele(ip) register struct inode *ip; { if (ip->i_count == 1) { ip->i_flag |= ILOCKED; if (ip->i_nlink <= 0 && ip->i_fs->fs_ronly == 0) { itrunc(ip, (u_long)0); ip->i_mode = 0; ip->i_rdev = 0; ip->i_flag |= IUPD|ICHG; ifree(ip, ip->i_number); #ifdef QUOTA QUOTAMAP(); (void) chkiq(ip->i_dev, ip, ip->i_uid, 0); dqrele(ix_dquot[ip - inode]); ix_dquot[ip - inode] = NODQUOT; QUOTAUNMAP(); #endif } IUPDAT(ip, &time, &time, 0); IUNLOCK(ip); ip->i_flag = 0; /* * Put the inode on the end of the free list. * Possibly in some cases it would be better to * put the inode at the head of the free list, * (eg: where i_mode == 0 || i_number == 0) * but I will think about that later .. kre * (i_number is rarely 0 - only after an i/o error in iget, * where i_mode == 0, the inode will probably be wanted * again soon for an ialloc, so possibly we should keep it) */ if (ifreeh) { *ifreet = ip; ip->i_freeb = ifreet; } else { ifreeh = ip; ip->i_freeb = &ifreeh; } ip->i_freef = NULL; ifreet = &ip->i_freef; } else if (!(ip->i_flag & ILOCKED)) ITIMES(ip, &time, &time); ip->i_count--; } /* * Check accessed and update flags on * an inode structure. * If any are on, update the inode * with the current time. * If waitfor set, then must insure * i/o order so wait for the write to complete. */ iupdat(ip, ta, tm, waitfor) struct inode *ip; struct timeval *ta, *tm; int waitfor; { register struct buf *bp; register struct dinode *dp; #ifdef EXTERNALITIMES struct icommon2 xic2, *xicp2; #endif register struct inode *tip = ip; if ((tip->i_flag & (IUPD|IACC|ICHG|IMOD)) == 0) return; if (tip->i_fs->fs_ronly) return; bp = bread(tip->i_dev, itod(tip->i_number)); if (bp->b_flags & B_ERROR) { brelse(bp); return; } #ifdef EXTERNALITIMES mapseg5(xitimes, xitdesc); xicp2 = &((struct icommon2 *)SEG5)[ip - inode]; if (tip->i_flag & IACC) xicp2->ic_atime = ta->tv_sec; if (tip->i_flag & IUPD) xicp2->ic_mtime = tm->tv_sec; if (tip->i_flag & ICHG) xicp2->ic_ctime = time.tv_sec; xic2 = *xicp2; normalseg5(); #else if (tip->i_flag&IACC) tip->i_atime = ta->tv_sec; if (tip->i_flag&IUPD) tip->i_mtime = tm->tv_sec; if (tip->i_flag&ICHG) tip->i_ctime = time.tv_sec; #endif tip->i_flag &= ~(IUPD|IACC|ICHG|IMOD); dp = (struct dinode *)mapin(bp) + itoo(tip->i_number); dp->di_ic1 = tip->i_ic1; dp->di_flags = tip->i_flags; #ifdef EXTERNALITIMES dp->di_ic2 = xic2; #else dp->di_ic2 = tip->i_ic2; #endif bcopy(ip->i_addr, dp->di_addr, NADDR * sizeof (daddr_t)); mapout(bp); if (waitfor) bwrite(bp); else bdwrite(bp); } #define SINGLE 0 /* index of single indirect block */ #define DOUBLE 1 /* index of double indirect block */ #define TRIPLE 2 /* index of triple indirect block */ /* * Truncate the inode ip to at most * length size. Free affected disk * blocks -- the blocks of the file * are removed in reverse order. * * NB: triple indirect blocks are untested. */ itrunc(oip,length) register struct inode *oip; u_long length; { daddr_t lastblock; register int i; register struct inode *ip; daddr_t bn, lastiblock[NIADDR]; struct buf *bp; int offset, level; struct inode tip; #ifdef QUOTA long bytesreleased; #endif /* * special hack for pipes, since size for them isn't the size of * the file, it's the amount currently waiting for transfer. It's * unclear that this will work, though, because pipes can (although * rarely do) get bigger than MAXPIPSIZ. Don't think it worked * in V7 either, I don't really understand what's going on. */ if (oip->i_flag & IPIPE) oip->i_size = MAXPIPSIZ; else if (oip->i_size <= length) { oip->i_flag |= ICHG|IUPD; iupdat(oip, &time, &time, 1); return; } /* * Calculate index into inode's block list of * last direct and indirect blocks (if any) * which we want to keep. Lastblock is -1 when * the file is truncated to 0. */ lastblock = lblkno(length + DEV_BSIZE - 1) - 1; lastiblock[SINGLE] = lastblock - NDADDR; lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR; lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR * NINDIR; /* * Update the size of the file. If the file is not being * truncated to a block boundry, the contents of the * partial block following the end of the file must be * zero'ed in case it ever become accessable again because * of subsequent file growth. */ offset = blkoff(length); if (offset) { bn = bmap(oip, lblkno(length), B_WRITE, 1); if (u.u_error || bn < 0) return; bp = bread(oip->i_dev, bn); if (bp->b_flags & B_ERROR) { u.u_error = EIO; brelse(bp); return; } bzero(mapin(bp) + offset, (u_int)(DEV_BSIZE - offset)); mapout(bp); bdwrite(bp); } /* * Update file and block pointers * on disk before we start freeing blocks. * If we crash before free'ing blocks below, * the blocks will be returned to the free list. * lastiblock values are also normalized to -1 * for calls to indirtrunc below. */ tip = *oip; #ifdef QUOTA bytesreleased = oip->i_size - length; #endif oip->i_size = length; for (level = TRIPLE; level >= SINGLE; level--) if (lastiblock[level] < 0) { oip->i_ib[level] = 0; lastiblock[level] = -1; } for (i = NDADDR - 1; i > lastblock; i--) oip->i_db[i] = 0; oip->i_flag |= ICHG|IUPD; iupdat(oip, &time, &time, 1); /* * Indirect blocks first. */ ip = &tip; for (level = TRIPLE; level >= SINGLE; level--) { bn = ip->i_ib[level]; if (bn != 0) { indirtrunc(ip, bn, lastiblock[level], level); if (lastiblock[level] < 0) { ip->i_ib[level] = 0; free(ip, bn); } } if (lastiblock[level] >= 0) goto done; } /* * All whole direct blocks. */ for (i = NDADDR - 1; i > lastblock; i--) { bn = ip->i_db[i]; if (bn == 0) continue; ip->i_db[i] = 0; free(ip, bn); } if (lastblock < 0) goto done; done: #ifdef DIAGNOSTIC /* BEGIN PARANOIA */ for (level = SINGLE; level <= TRIPLE; level++) if (ip->i_ib[level] != oip->i_ib[level]) panic("itrunc1"); for (i = 0; i < NDADDR; i++) if (ip->i_db[i] != oip->i_db[i]) panic("itrunc2"); /* END PARANOIA */ #endif oip->i_flag |= ICHG; #ifdef QUOTA QUOTAMAP(); (void)chkdq(oip, -bytesreleased, 0); QUOTAUNMAP(); #endif } /* * Release blocks associated with the inode ip and * stored in the indirect block bn. Blocks are free'd * in LIFO order up to (but not including) lastbn. If * level is greater than SINGLE, the block is an indirect * block and recursive calls to indirtrunc must be used to * cleanse other indirect blocks. * * NB: triple indirect blocks are untested. */ indirtrunc(ip, bn, lastbn, level) struct inode *ip; daddr_t bn, lastbn; int level; { register struct buf *bp; daddr_t nb, last; long factor; /* * Calculate index in current block of last * block to be kept. -1 indicates the entire * block so we need not calculate the index. */ switch(level) { case SINGLE: factor = 1; break; case DOUBLE: factor = NINDIR; break; case TRIPLE: factor = NINDIR * NINDIR; break; } last = lastbn; if (lastbn > 0) last = last / factor; /* * Get buffer of block pointers, zero those * entries corresponding to blocks to be free'd, * and update on disk copy first. */ { register daddr_t *bap; register struct buf *cpy; bp = bread(ip->i_dev, bn); if (bp->b_flags&B_ERROR) { brelse(bp); return; } cpy = geteblk(); copy(bftopaddr(bp), bftopaddr(cpy), btoc(DEV_BSIZE)); bap = (daddr_t *)mapin(bp); bzero((caddr_t)&bap[last + 1], (u_int)(NINDIR - (last + 1)) * sizeof(daddr_t)); mapout(bp); bwrite(bp); bp = cpy; } /* * Optimized for single indirect blocks, i.e. until a file is * greater than 4K + 256K you don't have to do a mapin/mapout * for every entry. The mapin/mapout is required since free() * may have to map an item in. Have to use another routine * since it requires 1K of kernel stack to get around the problem * and that doesn't work well with recursion. */ if (level == SINGLE) trsingle(ip, bp, last); else { register daddr_t *bstart, *bstop; bstart = (daddr_t *)mapin(bp); bstop = &bstart[last]; bstart += NINDIR - 1; /* * Recursively free totally unused blocks. */ for (;bstart > bstop;--bstart) { nb = *bstart; if (nb) { mapout(bp); indirtrunc(ip, nb, (daddr_t)-1, level - 1); free(ip, nb); mapin(bp); } } mapout(bp); /* * Recursively free last partial block. */ if (lastbn >= 0) { mapin(bp); nb = *bstop; mapout(bp); last = lastbn % factor; if (nb != 0) indirtrunc(ip, nb, last, level - 1); } } brelse(bp); } static trsingle(ip, bp,last) register struct inode *ip; caddr_t bp; daddr_t last; { register daddr_t *bstart, *bstop; daddr_t blarray[NINDIR]; bcopy(mapin(bp),blarray,NINDIR * sizeof(daddr_t)); mapout(bp); bstart = &blarray[NINDIR - 1]; bstop = &blarray[last]; for (;bstart > bstop;--bstart) if (*bstart) free(ip, *bstart); } /* * remove any inodes in the inode cache belonging to dev * * There should not be any active ones, return error if any are found * (nb: this is a user error, not a system err) * * Also, count the references to dev by block devices - this really * has nothing to do with the object of the procedure, but as we have * to scan the inode table here anyway, we might as well get the * extra benefit. * * this is called from sumount() when dev is being unmounted */ #ifdef QUOTA iflush(dev, iq) struct inode *iq; #else iflush(dev) #endif dev_t dev; { register struct inode *ip; register int open = 0; for (ip = inode; ip < inodeNINODE; ip++) { #ifdef QUOTA if (ip != iq && ip->i_dev == dev) #else if (ip->i_dev == dev) #endif if (ip->i_count) return(-1); else { remque(ip); ip->i_forw = ip; ip->i_back = ip; /* * as i_count == 0, the inode was on the free * list already, just leave it there, it will * fall off the bottom eventually. We could * perhaps move it to the head of the free * list, but as umounts are done so * infrequently, we would gain very little, * while making the code bigger. */ #ifdef QUOTA QUOTAMAP(); dqrele(ix_dquot[ip - inode]); ix_dquot[ip - inode] = NODQUOT; QUOTAUNMAP(); #endif } else if (ip->i_count && (ip->i_mode&IFMT)==IFBLK && ip->i_rdev == dev) open++; } return (open); } /* * Lock an inode. If its already locked, set the WANT bit and sleep. */ ilock(ip) register struct inode *ip; { ILOCK(ip); } /* * Unlock an inode. If WANT bit is on, wakeup. */ iunlock(ip) register struct inode *ip; { IUNLOCK(ip); } ster struct buf *bp; register struct dinode *dp; #ifdef EXTERNALITIMES struct icommosys/sys/kern_exit.c 440 0 12 16140 5720314415 7635 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)kern_exit.c 2.1 (2.11BSD GTE) 2/14/95 */ #include "param.h" #include "../machine/psl.h" #include "../machine/reg.h" #include "systm.h" #include "map.h" #include "user.h" #include "proc.h" #include "inode.h" #include "vm.h" #include "file.h" #include "wait.h" #include "kernel.h" #ifdef QUOTA #include "quota.h" #endif #include "ingres.h" /* * exit system call: pass back caller's arg */ rexit() { register struct a { int rval; } *uap = (struct a *)u.u_ap; exit(W_EXITCODE(uap->rval, 0)); /* NOTREACHED */ } /* * Exit: deallocate address space and other resources, * change proc state to zombie, and unlink proc from allproc * list. Save exit status and rusage for wait(). * Check for child processes and orphan them. */ exit(rv) { register int i; register struct proc *p; struct proc **pp; p = u.u_procp; p->p_flag &= ~(STRC|SULOCK); p->p_sigignore = ~0; p->p_sig = 0; /* * 2.11 doesn't need to do this and it gets overwritten anyway. * p->p_realtimer.it_value = 0; */ for (i = 0; i <= u.u_lastfile; i++) { register struct file *f; f = u.u_ofile[i]; u.u_ofile[i] = NULL; u.u_pofile[i] = 0; closef(f); } ilock(u.u_cdir); iput(u.u_cdir); if (u.u_rdir) { ilock(u.u_rdir); iput(u.u_rdir); } u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; (void) acct(); #ifdef QUOTA QUOTAMAP(); qclean(); QUOTAUNMAP(); #endif /* * Freeing the user structure and kernel stack * for the current process: have to run a bit longer * using the slots which are about to be freed... */ if (p->p_flag & SVFORK) endvfork(); else { xfree(); mfree(coremap, p->p_dsize, p->p_daddr); mfree(coremap, p->p_ssize, p->p_saddr); } mfree(coremap, USIZE, p->p_addr); if (p->p_pid == 1) panic("init died"); if (*p->p_prev = p->p_nxt) /* off allproc queue */ p->p_nxt->p_prev = p->p_prev; if (p->p_nxt = zombproc) /* onto zombproc */ p->p_nxt->p_prev = &p->p_nxt; p->p_prev = &zombproc; zombproc = p; p->p_stat = SZOMB; #if NINGRES > 0 ingres_rma(p->p_pid); /* Remove any ingres locks */ #endif noproc = 1; for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash) if (*pp == p) { *pp = p->p_hash; goto done; } panic("exit"); done: /* * Overwrite p_alive substructure of proc - better not be anything * important left! */ p->p_xstat = rv; p->p_ru = u.u_ru; ruadd(&p->p_ru, &u.u_cru); { register struct proc *q; int doingzomb = 0; q = allproc; again: for(; q; q = q->p_nxt) if (q->p_pptr == p) { q->p_pptr = &proc[1]; q->p_ppid = 1; wakeup((caddr_t)&proc[1]); if (q->p_flag&STRC) { q->p_flag &= ~STRC; psignal(q, SIGKILL); } else if (q->p_stat == SSTOP) { psignal(q, SIGHUP); psignal(q, SIGCONT); } /* * Protect this process from future * tty signals, clear TSTP/TTIN/TTOU if pending. * 2.11 also sets SDETACH bit. */ spgrp(q); } if (!doingzomb) { doingzomb = 1; q = zombproc; goto again; } } psignal(p->p_pptr, SIGCHLD); wakeup((caddr_t)p->p_pptr); swtch(); /* NOTREACHED */ } struct args { int pid; int *status; int options; struct rusage *rusage; int compat; }; owait() { int retval[2]; register struct args *uap = (struct args *)u.u_ap; if ((u.u_ar0[RPS] & PSL_ALLCC) != PSL_ALLCC) { uap->options = 0; uap->rusage = 0; } else { uap->options = u.u_ar0[R0]; uap->rusage = (struct rusage *)u.u_ar0[R1]; } uap->pid = WAIT_ANY; uap->status = 0; uap->compat = 1; u.u_error = wait1(u.u_procp, uap, retval); if (!u.u_error) { u.u_r.r_val1 = retval[0]; u.u_r.r_val2 = retval[1]; } } wait4() { int retval[2]; register struct args *uap = (struct args *)u.u_ap; uap->compat = 0; u.u_error = wait1(u.u_procp, uap, retval); if (!u.u_error) u.u_r.r_val1 = retval[0]; } /* * Wait: check child processes to see if any have exited, * stopped under trace or (optionally) stopped by a signal. * Pass back status and make available for reuse the exited * child's proc structure. */ wait1(q, uap, retval) struct proc *q; register struct args *uap; int retval[]; { int nfound, status; struct rusage ru; /* used for local conversion */ register struct proc *p; register int error; if (uap->pid == WAIT_MYPGRP) /* == 0 */ uap->pid = -q->p_pgrp; loop: nfound = 0; /* * 4.X has child links in the proc structure, so they consolidate * these two tests into one loop. We only have the zombie chain * and the allproc chain, so we check for ZOMBIES first, then for * children that have changed state. We check for ZOMBIES first * because they are more common, and, as the list is typically small, * a faster check. */ for (p = zombproc; p;p = p->p_nxt) { if (p->p_pptr != q) /* are we the parent of this process? */ continue; if (uap->pid != WAIT_ANY && p->p_pid != uap->pid && p->p_pgrp != -uap->pid) continue; retval[0] = p->p_pid; retval[1] = p->p_xstat; if (uap->status && (error = copyout(&p->p_xstat, uap->status, sizeof (uap->status)))) return(error); if (uap->rusage) { rucvt(&ru, &p->p_ru); if (error = copyout(&ru, uap->rusage, sizeof (ru))) return(error); } ruadd(&u.u_cru, &p->p_ru); p->p_xstat = 0; p->p_stat = NULL; p->p_pid = 0; p->p_ppid = 0; if (*p->p_prev = p->p_nxt) /* off zombproc */ p->p_nxt->p_prev = p->p_prev; p->p_nxt = freeproc; /* onto freeproc */ freeproc = p; p->p_pptr = 0; p->p_sig = 0; p->p_sigcatch = 0; p->p_sigignore = 0; p->p_sigmask = 0; p->p_pgrp = 0; p->p_flag = 0; p->p_wchan = 0; p->p_cursig = 0; return (0); } for (p = allproc; p;p = p->p_nxt) { if (p->p_pptr != q) continue; if (uap->pid != WAIT_ANY && p->p_pid != uap->pid && p->p_pgrp != -uap->pid) continue; ++nfound; if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 && (p->p_flag&STRC || uap->options&WUNTRACED)) { p->p_flag |= SWTED; retval[0] = p->p_pid; error = 0; if (uap->compat) retval[1] = W_STOPCODE(p->p_cursig); else if (uap->status) { status = W_STOPCODE(p->p_cursig); error = copyout(&status, uap->status, sizeof (status)); } return (error); } } if (nfound == 0) return (ECHILD); if (uap->options&WNOHANG) { retval[0] = 0; return (0); } if (setjmp(&u.u_qsave)) { if ((u.u_sigintr & sigmask(q->p_cursig)) != 0) return(EINTR); u.u_eosys = RESTARTSYS; return (0); } sleep((caddr_t)q, PWAIT); goto loop; } /* * Notify parent that vfork child is finished with parent's data. Called * during exit/exec(getxfile); must be called before xfree(). The child * must be locked in core so it will be in core when the parent runs. */ endvfork() { register struct proc *rip, *rpp; rpp = u.u_procp; rip = rpp->p_pptr; rpp->p_flag &= ~SVFORK; rpp->p_flag |= SLOCK; wakeup((caddr_t)rpp); while(!(rpp->p_flag&SVFDONE)) sleep((caddr_t)rip,PZERO-1); /* * The parent has taken back our data+stack, set our sizes to 0. */ u.u_dsize = rpp->p_dsize = 0; u.u_ssize = rpp->p_ssize = 0; rpp->p_flag &= ~(SVFDONE | SLOCK); } art; if (nb) { mapout(bp); indirtrunc(ip, nb, (daddr_t)-1, level - 1); free(ip, nb); mapin(bp); } } mapout(bp); /* * Recursively free last partial block. */ if (lastbn >= 0) { mapin(bp); nb = *bstop; mapout(bp); last = lastbn % factor; if (nb != 0) indirtrunc(ip, nb, last, level - 1); } } brelse(bp); } static trsingle(ip, bp,last) register struct inodsys/sys/vm_proc.c 440 0 12 5130 5317200762 7270 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)vm_proc.c 1.2 (2.11BSD GTE) 12/24/92 */ #include "param.h" #include "user.h" #include "proc.h" #include "text.h" #include "map.h" #include "kernel.h" /* * Change the size of the data+stack regions of the process. * If the size is shrinking, it's easy -- just release the extra core. * If it's growing, and there is core, just allocate it and copy the * image, taking care to reset registers to account for the fact that * the system's stack has moved. If there is no core, arrange for the * process to be swapped out after adjusting the size requirement -- when * it comes in, enough core will be allocated. After the expansion, the * caller will take care of copying the user's stack towards or away from * the data area. The data and stack segments are separated from each * other. The second argument to expand specifies which to change. The * stack segment will not have to be copied again after expansion. */ expand(newsize,segment) int newsize, segment; { register struct proc *p; register int i, n; int a1, a2; p = u.u_procp; if (segment == S_DATA) { n = p->p_dsize; p->p_dsize = newsize; a1 = p->p_daddr; if(n >= newsize) { n -= newsize; mfree(coremap, n, a1+newsize); return; } } else { n = p->p_ssize; p->p_ssize = newsize; a1 = p->p_saddr; if(n >= newsize) { n -= newsize; p->p_saddr += n; mfree(coremap, n, a1); /* * Since the base of stack is different, * segmentation registers must be repointed. */ sureg(); return; } } if (setjmp(&u.u_ssave)) { /* * If we had to swap, the stack needs moving up. */ if (segment == S_STACK) { a1 = p->p_saddr; i = newsize - n; a2 = a1 + i; /* * i is the amount of growth. Copy i clicks * at a time, from the top; do the remainder * (n % i) separately. */ while (n >= i) { n -= i; copy(a1+n, a2+n, i); } copy(a1, a2, n); } sureg(); return; } if (u.u_fpsaved == 0) { savfp(&u.u_fps); u.u_fpsaved = 1; } a2 = malloc(coremap, newsize); if (a2 == NULL) { if (segment == S_DATA) swapout(p, X_FREECORE, n, X_OLDSIZE); else swapout(p, X_FREECORE, X_OLDSIZE, n); p->p_flag |= SSWAP; swtch(); /* NOTREACHED */ } if (segment == S_STACK) { p->p_saddr = a2; /* * Make the copy put the stack at the top of the new area. */ a2 += newsize - n; } else p->p_daddr = a2; copy(a1, a2, n); mfree(coremap, n, a1); sureg(); } d * child's proc structure. */ wait1(q, uap, retval) struct proc *q; register struct args *uap; int retval[]; { int nfound, status; struct rusage ru; /* used for local conversion */ register struct proc *p; register int error; if (uap->pid == WAIT_MYPGRP) /* == 0 */ uap->pid = -q->p_pgrp; loop: nfound = 0; /* * 4.X has child links in the proc structure, so they consolidate * these two tests into onesys/sys/kern_mman.c 440 0 12 14414 4066540476 7630 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)kern_mman.c 1.1 (2.10BSD Berkeley) 12/1/86 */ #include "param.h" #include "../machine/seg.h" #include "user.h" #include "proc.h" #include "vm.h" #include "text.h" #include "systm.h" getpagesize() { u.u_r.r_val1 = NBPG * CLSIZE; } sbrk() { struct a { char *nsiz; }; register int n, d; /* set n to new data size */ n = btoc((int)((struct a *)u.u_ap)->nsiz); if (!u.u_sep) if (u.u_ovdata.uo_ovbase) n -= u.u_ovdata.uo_dbase; else n -= ctos(u.u_tsize) * stoc(1); if (n < 0) n = 0; if (estabur(u.u_tsize, n, u.u_ssize, u.u_sep, RO)) return; expand(n, S_DATA); /* set d to (new - old) */ d = n - u.u_dsize; if (d > 0) clear(u.u_procp->p_daddr + u.u_dsize, d); u.u_dsize = n; } /* * grow the stack to include the SP * true return if successful. */ grow(sp) register unsigned sp; { register int si; if (sp >= -ctob(u.u_ssize)) return (0); si = (-sp) / ctob(1) - u.u_ssize + SINCR; /* * Round the increment back to a segment boundary if necessary. */ if (ctos(si + u.u_ssize) > ctos(((-sp) + ctob(1) - 1) / ctob(1))) si = stoc(ctos(((-sp) + ctob(1) - 1) / ctob(1))) - u.u_ssize; if (si <= 0) return (0); if (estabur(u.u_tsize, u.u_dsize, u.u_ssize + si, u.u_sep, RO)) return (0); /* * expand will put the stack in the right place; * no copy required here. */ expand(u.u_ssize + si, S_STACK); u.u_ssize += si; clear(u.u_procp->p_saddr, si); return (1); } /* * Set up software prototype segmentation registers to implement the 3 * pseudo text, data, stack segment sizes passed as arguments. The * argument sep specifies if the text and data+stack segments are to be * separated. The last argument determines whether the text segment is * read-write or read-only. */ estabur(nt, nd, ns, sep, xrw) u_int nt, nd, ns; int sep, xrw; { register int a; register short *ap, *dp; u_int ts; if (u.u_ovdata.uo_ovbase && nt) ts = u.u_ovdata.uo_dbase; else ts = nt; if (sep) { #ifndef NONSEPARATE if (!sep_id) goto nomem; if (ctos(ts) > 8 || ctos(nd)+ctos(ns) > 8) #endif !NONSEPARATE goto nomem; } else if (ctos(ts) + ctos(nd) + ctos(ns) > 8) goto nomem; if (u.u_ovdata.uo_ovbase && nt) ts = u.u_ovdata.uo_ov_offst[NOVL]; if (ts + nd + ns + USIZE > maxmem) { nomem: u.u_error = ENOMEM; return (-1); } a = 0; ap = &u.u_uisa[0]; dp = &u.u_uisd[0]; while (nt >= 128) { *dp++ = (127 << 8) | xrw | TX; *ap++ = a; a += 128; nt -= 128; } if (nt) { *dp++ = ((nt - 1) << 8) | xrw | TX; *ap++ = a; } #ifdef NONSEPARATE if (u.u_ovdata.uo_ovbase && ts) #else !NONSEPARATE if ((u.u_ovdata.uo_ovbase && ts) && !sep) #endif NONSEPARATE /* * overlay process, adjust accordingly. * The overlay segment's registers will be set by * choverlay() from sureg(). */ for (a = 0; a < u.u_ovdata.uo_nseg; a++) { *ap++ = 0; *dp++ = 0; } #ifndef NONSEPARATE if (sep) while(ap < &u.u_uisa[8]) { *ap++ = 0; *dp++ = 0; } #endif !NONSEPARATE a = 0; while (nd >= 128) { *dp++ = (127 << 8) | RW; *ap++ = a; a += 128; nd -= 128; } if (nd) { *dp++ = ((nd - 1) << 8) | RW; *ap++ = a; a += nd; } while (ap < &u.u_uisa[8]) { if (*dp & ABS) { dp++; ap++; continue; } *dp++ = 0; *ap++ = 0; } #ifndef NONSEPARATE if (sep) while (ap < &u.u_uisa[16]) { if(*dp & ABS) { dp++; ap++; continue; } *dp++ = 0; *ap++ = 0; } #endif !NONSEPARATE a = ns; while (ns >= 128) { a -= 128; ns -= 128; *--dp = (0 << 8) | RW | ED; *--ap = a; } if (ns) { *--dp = ((128 - ns) << 8) | RW | ED; *--ap = a - 128; } #ifndef NONSEPARATE if (!sep) { ap = &u.u_uisa[0]; dp = &u.u_uisa[8]; while(ap < &u.u_uisa[8]) *dp++ = *ap++; ap = &u.u_uisd[0]; dp = &u.u_uisd[8]; while(ap < &u.u_uisd[8]) *dp++ = *ap++; } #endif !NONSEPARATE sureg(); return(0); } /* * Load the user hardware segmentation registers from the software * prototype. The software registers must have been setup prior by * estabur. */ sureg() { register int *rdp; register short *uap, *udp; short *limudp; int *rap; int taddr, daddr, saddr; struct text *tp; taddr = daddr = u.u_procp->p_daddr; saddr = u.u_procp->p_saddr; if ((tp = u.u_procp->p_textp) != NULL) taddr = tp->x_caddr; #ifndef NONSEPARATE limudp = &u.u_uisd[16]; if (!sep_id) #endif !NONSEPARATE limudp = &u.u_uisd[8]; rap = (int *) UISA; rdp = (int *) UISD; uap = &u.u_uisa[0]; for (udp = &u.u_uisd[0]; udp < limudp;) { *rap++ = *uap++ + (*udp & TX? taddr: (*udp & ED ? saddr: (*udp & ABS ? 0 : daddr))); *rdp++ = *udp++; } /* * Since software prototypes are not maintained for overlay * segments, force overlay change. The test for TX is because * there is no text if called from core(). */ if (u.u_ovdata.uo_ovbase && (u.u_uisd[0] & TX)) choverlay(u.u_uisd[0] & ACCESS); } /* * Routine to change overlays. Only hardware registers are changed; must be * called from sureg since the software prototypes will be out of date. */ choverlay(xrw) int xrw; { register u_short *rap, *rdp; register int nt; int addr; u_short *limrdp; rap = &(UISA[u.u_ovdata.uo_ovbase]); rdp = &(UISD[u.u_ovdata.uo_ovbase]); limrdp = &(UISD[u.u_ovdata.uo_ovbase + u.u_ovdata.uo_nseg]); if (u.u_ovdata.uo_curov) { addr = u.u_ovdata.uo_ov_offst[u.u_ovdata.uo_curov - 1]; nt = u.u_ovdata.uo_ov_offst[u.u_ovdata.uo_curov] - addr; addr += u.u_procp->p_textp->x_caddr; while (nt >= 128) { *rap++ = addr; *rdp++ = (127 << 8) | xrw; addr += 128; nt -= 128; } if (nt) { *rap++ = addr; *rdp++ = ((nt-1) << 8) | xrw; } } while (rdp < limrdp) { *rap++ = 0; *rdp++ = 0; } #ifndef NONSEPARATE /* * This section copies the UISA/UISD registers to the * UDSA/UDSD registers. It is only needed for data fetches * on the overlaid segment, which normally don't happen. */ if (!u.u_sep && sep_id) { rdp = &(UISD[u.u_ovdata.uo_ovbase]); rap = rdp + 8; /* limrdp is still correct */ while (rdp < limrdp) *rap++ = *rdp++; rdp = &(UISA[u.u_ovdata.uo_ovbase]); rap = rdp + 8; limrdp = &(UISA[u.u_ovdata.uo_ovbase + u.u_ovdata.uo_nseg]); while (rdp < limrdp) *rap++ = *rdp++; } #endif !NONSEPARATE } free(ip, *bstart); } /* * remove any inodes in the inode cache belonging to dev * * There should not be any active ones, return error if any are found * (nb: this is a user error, not a system err) * * Also, count the references to desys/sys/subr_rmap.c 440 0 12 15466 5317677447 7674 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)subr_rmap.c 1.2 (2.11BSD GTE) 12/24/92 */ #include "param.h" #include "systm.h" #include "map.h" #include "vm.h" /* * Resource map handling routines. * * A resource map is an array of structures each of which describes a * segment of the address space of an available resource. The segments * are described by their base address and length, and sorted in address * order. Each resource map has a fixed maximum number of segments * allowed. Resources are allocated by taking part or all of one of the * segments of the map. * * Returning of resources will require another segment if the returned * resources are not adjacent in the address space to an existing segment. * If the return of a segment would require a slot which is not available, * then one of the resource map segments is discarded after a warning is * printed. * * Returning of resources may also cause the map to collapse by coalescing * two existing segments and the returned space into a single segment. In * this case the resource map is made smaller by copying together to fill * the resultant gap. * * N.B.: the current implementation uses a dense array and does not admit * the value ``0'' as a legal address or size, since that is used as a * delimiter. */ /* * Allocate 'size' units from the given map. Return the base of the * allocated space. In a map, the addresses are increasing and the * list is terminated by a 0 size. * * Algorithm is first-fit. */ memaddr malloc(mp, size) struct map *mp; register size_t size; { register struct mapent *bp, *ep; memaddr addr; int retry; if (!size) panic("malloc: size = 0"); /* * Search for a piece of the resource map which has enough * free space to accomodate the request. */ retry = 0; again: for (bp = mp->m_map; bp->m_size; ++bp) if (bp->m_size >= size) { /* * Allocate from the map. If we allocated the entire * piece, move the rest of the map to the left. */ addr = bp->m_addr; bp->m_size -= size; if (bp->m_size) bp->m_addr += size; else for (ep = bp;; ++ep) { *ep = *++bp; if (!bp->m_size) break; } #ifdef UCB_METER if (mp == coremap) freemem -= size; #endif return(addr); } /* no entries big enough */ if (!retry++) { if (mp == swapmap) { printf("short of swap\n"); xumount(NODEV); goto again; } else if (mp == coremap) { xuncore(size); goto again; } } return((memaddr)NULL); } /* * Free the previously allocated size units at addr into the specified * map. Sort addr into map and combine on one or both ends if possible. */ mfree(mp, size, addr) struct map *mp; size_t size; register memaddr addr; { register struct mapent *bp, *ep; struct mapent *start; if (!size) return; /* the address must not be 0, or the protocol has broken down. */ if (!addr) panic("mfree: addr = 0"); if (mp == coremap) { if (runin) { runin = 0; wakeup((caddr_t)&runin); } #ifdef UCB_METER freemem += size; #endif } /* * locate the piece of the map which starts after the * returned space (or the end of the map). */ for (bp = mp->m_map; bp->m_size && bp->m_addr <= addr; ++bp); /* if there is a piece on the left abutting us, combine with it. */ ep = bp - 1; if (bp != mp->m_map && ep->m_addr + ep->m_size >= addr) { #ifdef DIAGNOSTIC /* any overlap is an internal error */ if (ep->m_addr + ep->m_size > addr) panic("mfree overlap #1"); #endif /* add into piece on the left by increasing its size. */ ep->m_size += size; /* * if the combined piece abuts the piece on the right now, * compress it in also, by shifting the remaining pieces * of the map over. */ if (bp->m_size && addr + size >= bp->m_addr) { #ifdef DIAGNOSTIC if (addr + size > bp->m_addr) panic("mfree overlap #2"); #endif ep->m_size += bp->m_size; do { *++ep = *++bp; } while (bp->m_size); } return; } /* if doesn't abut on the left, check for abutting on the right. */ if (bp->m_size && addr + size >= bp->m_addr) { #ifdef DIAGNOSTIC if (addr + size > bp->m_addr) panic("mfree overlap #3"); #endif bp->m_addr = addr; bp->m_size += size; return; } /* doesn't abut. Make a new entry and check for map overflow. */ for (start = bp; bp->m_size; ++bp); if (++bp > mp->m_limit) /* * too many segments; if this happens, the correct fix * is to make the map bigger; you can't afford to lose * chunks of the map. If you need to implement recovery, * use the above "for" loop to find the smallest entry * and toss it. */ printf("%s: overflow, lost %u clicks at 0%o\n", mp->m_name, size, addr); else { for (ep = bp - 1; ep >= start; *bp-- = *ep--); start->m_addr = addr; start->m_size = size; } } /* * Allocate resources for the three segments of a process (data, stack * and u.), attempting to minimize the cost of failure part-way through. * Since the segments are located successively, it is best for the sizes * to be in decreasing order; generally, data, stack, then u. will be * best. Returns NULL on failure, address of u. on success. */ memaddr malloc3(mp, d_size, s_size, u_size, a) struct map *mp; size_t d_size, s_size, u_size; memaddr a[3]; { register struct mapent *bp, *remap; register int next; struct mapent *madd[3]; size_t sizes[3]; int found, retry; sizes[0] = d_size; sizes[1] = s_size; sizes[2] = u_size; retry = 0; again: /* * note, this has to work for d_size and s_size of zero, * since init() comes in that way. */ madd[0] = madd[1] = madd[2] = remap = NULL; for (found = 0, bp = mp->m_map; bp->m_size; ++bp) for (next = 0; next < 3; ++next) if (!madd[next] && sizes[next] <= bp->m_size) { madd[next] = bp; bp->m_size -= sizes[next]; if (!bp->m_size && !remap) remap = bp; if (++found == 3) goto resolve; } /* couldn't get it all; restore the old sizes, try again */ for (next = 0; next < 3; ++next) if (madd[next]) madd[next]->m_size += sizes[next]; if (!retry++) if (mp == swapmap) { printf("short of swap\n"); xumount(NODEV); goto again; } else if (mp == coremap) { xuncore(sizes[2]); /* smallest to largest; */ xuncore(sizes[1]); /* free up minimum space */ xuncore(sizes[0]); goto again; } return((memaddr)NULL); resolve: /* got it all, update the addresses. */ for (next = 0; next < 3; ++next) { bp = madd[next]; a[next] = bp->m_addr; bp->m_addr += sizes[next]; } #ifdef UCB_METER if (mp == coremap) freemem -= d_size + s_size + u_size; #endif /* remove any entries of size 0; addr of 0 terminates */ if (remap) for (bp = remap + 1;; ++bp) if (bp->m_size || !bp->m_addr) { *remap++ = *bp; if (!bp->m_addr) break; } return(a[2]); } *dp++ = *ap++; ap = &u.u_uisd[0]; dp = &u.u_uisd[8]; while(ap < &u.u_uisd[8]) *dp++ = *ap++; } #endif !NONSEPARATE sureg(); return(0); } /* * Load the user hardware segmentation registersys/sys/subr_xxx.c 440 0 12 1235 5316467526 7523 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)subr_xxx.c 1.1 (2.10BSD Berkeley) 12/1/86 */ #include "param.h" #include "user.h" /* * Routine placed in illegal entries in the bdevsw and cdevsw tables. */ nodev() { return (ENODEV); } /* * Null routine; placed in insignificant entries * in the bdevsw and cdevsw tables. */ nulldev() { return (0); } /* * socket(2) and socketpair(2) if networking not available. */ #ifndef INET nonet() { u.u_error = EPROTONOSUPPORT; return(EPROTONOSUPPORT); } #endif f the combined piece abuts the piece on the right now, * compress it in also, by shifting the remaining pieces * of the map over. */ if (bp->m_size && addr + size >= bp->m_addr) { #ifdef DIAGNOSTIC if (addr + size > bp->m_addr) panic("mfree overlap #2"); #endif ep->m_size += bp->m_size; do { *++ep = *++bp; } while (bp->m_ssys/sys/sys_generic.c 440 0 12 23143 5670007436 10166 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)sys_generic.c 1.4 (2.11BSD GTE) 11/26/94 */ #include "param.h" #include "../machine/seg.h" #include "user.h" #include "proc.h" #include "inode.h" #include "file.h" #include "ioctl.h" #include "conf.h" #include "uio.h" #include "pty.h" #include "kernel.h" #include "systm.h" /* * this is consolidated here rather than being scattered all over the * place. the socketops table has to be in kernel space, but since * networking might not be defined an appropriate error has to be set */ int sorw(), soctl(), sosel(), socls(); struct fileops socketops = { sorw, soctl, sosel, socls }; extern struct fileops inodeops, pipeops; struct fileops *Fops[] = { NULL, &inodeops, &socketops, &pipeops }; /* * Read system call. */ read() { register struct a { int fdes; char *cbuf; unsigned count; } *uap = (struct a *)u.u_ap; struct uio auio; struct iovec aiov; aiov.iov_base = (caddr_t)uap->cbuf; aiov.iov_len = uap->count; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_rw = UIO_READ; rwuio(&auio); } readv() { register struct a { int fdes; struct iovec *iovp; unsigned iovcnt; } *uap = (struct a *)u.u_ap; struct uio auio; struct iovec aiov[16]; /* XXX */ if (uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) { u.u_error = EINVAL; return; } auio.uio_iov = aiov; auio.uio_iovcnt = uap->iovcnt; auio.uio_rw = UIO_READ; u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov, uap->iovcnt * sizeof (struct iovec)); if (u.u_error) return; rwuio(&auio); } /* * Write system call */ write() { register struct a { int fdes; char *cbuf; unsigned count; } *uap = (struct a *)u.u_ap; struct uio auio; struct iovec aiov; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_rw = UIO_WRITE; aiov.iov_base = uap->cbuf; aiov.iov_len = uap->count; rwuio(&auio); } writev() { register struct a { int fdes; struct iovec *iovp; unsigned iovcnt; } *uap = (struct a *)u.u_ap; struct uio auio; struct iovec aiov[16]; /* XXX */ if (uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) { u.u_error = EINVAL; return; } auio.uio_iov = aiov; auio.uio_iovcnt = uap->iovcnt; auio.uio_rw = UIO_WRITE; u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov, uap->iovcnt * sizeof (struct iovec)); if (u.u_error) return; rwuio(&auio); } static rwuio(uio) register struct uio *uio; { struct a { int fdes; }; register struct file *fp; register struct iovec *iov; u_int i, count; off_t total; GETF(fp, ((struct a *)u.u_ap)->fdes); if ((fp->f_flag & (uio->uio_rw == UIO_READ ? FREAD : FWRITE)) == 0) { u.u_error = EBADF; return; } total =(off_t)0; uio->uio_resid = 0; uio->uio_segflg = UIO_USERSPACE; iov = uio->uio_iov; for (i = 0; i < uio->uio_iovcnt; i++) { #ifdef pdp11 total += iov->iov_len; #else if (iov->iov_len < 0) { u.u_error = EINVAL; return; } uio->uio_resid += iov->iov_len; if (uio->uio_resid < 0) { u.u_error = EINVAL; return; } #endif iov++; } #ifdef pdp11 uio->uio_resid = total; if (uio->uio_resid != total) { /* check wraparound */ u.u_error = EINVAL; return; } #endif count = uio->uio_resid; if (setjmp(&u.u_qsave)) { if (uio->uio_resid == count) { if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) u.u_error = EINTR; else u.u_eosys = RESTARTSYS; } } else u.u_error = (*Fops[fp->f_type]->fo_rw)(fp, uio); u.u_r.r_val1 = count - uio->uio_resid; } /* * Ioctl system call */ ioctl() { register struct file *fp; register struct a { int fdes; long cmd; caddr_t cmarg; } *uap; long com; u_int k_com; register u_int size; char data[IOCPARM_MASK+1]; uap = (struct a *)u.u_ap; if ((fp = getf(uap->fdes)) == NULL) return; if ((fp->f_flag & (FREAD|FWRITE)) == 0) { u.u_error = EBADF; return; } com = uap->cmd; /* THE 2.11 KERNEL STILL THINKS THAT IOCTL COMMANDS ARE 16 BITS */ k_com = (u_int)com; if (k_com == FIOCLEX) { u.u_pofile[uap->fdes] |= UF_EXCLOSE; return; } if (k_com == FIONCLEX) { u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; return; } /* * Interpret high order word to find * amount of data to be copied to/from the * user's address space. */ size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16; if (size > sizeof (data)) { u.u_error = EFAULT; return; } if (com&IOC_IN) { if (size) { if (((u_int)uap->cmarg|size)&1) u.u_error = vcopyin(uap->cmarg, (caddr_t)data, size); else u.u_error = copyin(uap->cmarg, (caddr_t)data, size); if (u.u_error) return; } else *(caddr_t *)data = uap->cmarg; } else if ((com&IOC_OUT) && size) /* * Zero the buffer on the stack so the user * always gets back something deterministic. */ bzero((caddr_t)data, size); else if (com&IOC_VOID) *(caddr_t *)data = uap->cmarg; switch (k_com) { case FIONBIO: u.u_error = fset(fp, FNONBLOCK, *(int *)data); return; case FIOASYNC: u.u_error = fset(fp, FASYNC, *(int *)data); return; case FIOSETOWN: u.u_error = fsetown(fp, *(int *)data); return; case FIOGETOWN: u.u_error = fgetown(fp, (int *)data); return; } u.u_error = (*Fops[fp->f_type]->fo_ioctl)(fp, k_com, data); /* * Copy any data to user, size was * already set and checked above. */ if (u.u_error == 0 && (com&IOC_OUT) && size) if (((u_int)uap->cmarg|size)&1) u.u_error = vcopyout(data, uap->cmarg, size); else u.u_error = copyout(data, uap->cmarg, size); } int unselect(); int nselcoll; /* * Select system call. */ select() { register struct uap { int nd; fd_set *in, *ou, *ex; struct timeval *tv; } *uap = (struct uap *)u.u_ap; fd_set ibits[3], obits[3]; struct timeval atv; register int s, ni; int ncoll; label_t lqsave; bzero((caddr_t)ibits, sizeof(ibits)); bzero((caddr_t)obits, sizeof(obits)); if (uap->nd > NOFILE) uap->nd = NOFILE; /* forgiving, if slightly wrong */ ni = howmany(uap->nd, NFDBITS); #define getbits(name, x) \ if (uap->name) { \ u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ (unsigned)(ni * sizeof(fd_mask))); \ if (u.u_error) \ goto done; \ } getbits(in, 0); getbits(ou, 1); getbits(ex, 2); #undef getbits if (uap->tv) { u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof (atv)); if (u.u_error) goto done; if (itimerfix(&atv)) { u.u_error = EINVAL; goto done; } s = splhigh(); time.tv_usec = lbolt * 1000000L / LINEHZ; timevaladd(&atv, &time); splx(s); } retry: ncoll = nselcoll; u.u_procp->p_flag |= SSEL; u.u_r.r_val1 = selscan(ibits, obits, uap->nd); if (u.u_error || u.u_r.r_val1) goto done; s = splhigh(); /* this should be timercmp(&time, &atv, >=) */ if (uap->tv && (time.tv_sec > atv.tv_sec || (time.tv_sec == atv.tv_sec && lbolt * 1000000L / LINEHZ >= atv.tv_usec))) { splx(s); goto done; } if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { u.u_procp->p_flag &= ~SSEL; splx(s); goto retry; } u.u_procp->p_flag &= ~SSEL; if (uap->tv) { lqsave = u.u_qsave; if (setjmp(&u.u_qsave)) { untimeout(unselect, (caddr_t)u.u_procp); u.u_error = EINTR; splx(s); goto done; } timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); } sleep((caddr_t)&selwait, PZERO+1); if (uap->tv) { u.u_qsave = lqsave; untimeout(unselect, (caddr_t)u.u_procp); } splx(s); goto retry; done: #define putbits(name, x) \ if (uap->name) { \ int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ (unsigned)(ni * sizeof(fd_mask))); \ if (error) \ u.u_error = error; \ } if (u.u_error == 0) { putbits(in, 0); putbits(ou, 1); putbits(ex, 2); #undef putbits } } unselect(p) register struct proc *p; { register int s = splhigh(); switch (p->p_stat) { case SSLEEP: setrun(p); break; case SSTOP: unsleep(p); break; } splx(s); } selscan(ibits, obits, nfd) fd_set *ibits, *obits; int nfd; { register int i, j; fd_mask bits; register int which, flag; struct file *fp; int n = 0; for (which = 0; which < 3; which++) { switch (which) { case 0: flag = FREAD; break; case 1: flag = FWRITE; break; case 2: flag = 0; break; } for (i = 0; i < nfd; i += NFDBITS) { bits = ibits[which].fds_bits[i/NFDBITS]; while ((j = ffs(bits)) && i + --j < nfd) { bits &= ~(1L << j); fp = u.u_ofile[i + j]; if (fp == NULL) { u.u_error = EBADF; break; } if ((*Fops[fp->f_type]->fo_select)(fp,flag)) { FD_SET(i + j, &obits[which]); n++; } } } } return (n); } /*ARGSUSED*/ seltrue(dev, flag) dev_t dev; int flag; { return (1); } selwakeup(p, coll) register struct proc *p; long coll; { mapinfo map; savemap(map); if (coll) { nselcoll++; wakeup((caddr_t)&selwait); } if (p) { register int s = splhigh(); if (p->p_wchan == (caddr_t)&selwait) { if (p->p_stat == SSLEEP) setrun(p); else unsleep(p); } else if (p->p_flag & SSEL) p->p_flag &= ~SSEL; splx(s); } restormap(map); } sorw(fp, uio) register struct file *fp; register struct uio *uio; { #ifdef INET if (uio->uio_rw == UIO_READ) return(SORECEIVE((struct socket *)fp->f_socket, 0, uio, 0, 0)); return(SOSEND((struct socket *)fp->f_socket, 0, uio, 0, 0)); #else return (EOPNOTSUPP); #endif } soctl(fp, com, data) struct file *fp; u_int com; char *data; { #ifdef INET return (SOO_IOCTL(fp, com, data)); #else return (EOPNOTSUPP); #endif } sosel(fp, flag) struct file *fp; int flag; { #ifdef INET return (SOO_SELECT(fp, flag)); #else return (EOPNOTSUPP); #endif } socls(fp) register struct file *fp; { #ifdef INET return (SOCLOSE((struct socket *)fp->f_socket)); #else return (EOPNOTSUPP); #endif } 28; } if (nt) { *rap++ = addr; *rdp++ = ((nt-1) << 8) | xrw; } } while (rdp < limrdp) { *rap++ = 0; *rdp++ = 0; } #ifndef NONSEPARATE /* * This section copies the UISA/UISD registers to the * UDSA/UDSD registers. It is only needed for data fetches * on the overlaid segment, which normally don't happen. */ if (!u.u_sep && sep_id) { rdp = &(UISD[u.u_ovdata.uo_ovbase]); rap = rdpsys/sys/tty_conf.c 440 0 12 5617 5674211137 7466 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)tty_conf.c 1.2 (2.11BSD GTE) 11/30/94 */ #include "param.h" #include "../pdp/seg.h" #include "file.h" #include "ioctl.h" #include "tty.h" #include "errno.h" #include "conf.h" int nodev(); int nulldev(); int ttyopen(),ttylclose(),ttread(),ttwrite(),nullioctl(),ttstart(); int ttymodem(), nullmodem(), ttyinput(); /* #include "bk.h" */ #if NBK > 0 int bkopen(),bkclose(),bkread(),bkinput(),bkioctl(); #endif /* #include "tb.h" */ #if NTB > 0 int tbopen(),tbclose(),tbread(),tbinput(),tbioctl(); #endif #include "sl.h" #if NSL > 0 int SLOPEN(),SLCLOSE(),SLINPUT(),SLTIOCTL(),SLSTART(); #endif struct linesw linesw[] = { ttyopen, ttylclose, ttread, ttwrite, nullioctl, /* 0- OTTYDISC */ ttyinput, nodev, nulldev, ttstart, ttymodem, #if NBK > 0 bkopen, bkclose, bkread, ttwrite, bkioctl, /* 1- NETLDISC */ bkinput, nodev, nulldev, ttstart, nullmodem, #else nodev, nodev, nodev, nodev, nodev, nodev, nodev, nodev, nodev, nodev, #endif ttyopen, ttylclose, ttread, ttwrite, nullioctl, /* 2- NTTYDISC */ ttyinput, nodev, nulldev, ttstart, ttymodem, #if NTB > 0 tbopen, tbclose, tbread, nodev, tbioctl, tbinput, nodev, nulldev, ttstart, nullmodem, /* 3- TABLDISC */ #else nodev, nodev, nodev, nodev, nodev, nodev, nodev, nodev, nodev, nodev, #endif #if NSL > 0 SLOPEN, SLCLOSE, nodev, nodev, SLTIOCTL, SLINPUT, nodev, nulldev, SLSTART, nulldev, /* 4- SLIPDISC */ #else nodev, nodev, nodev, nodev, nodev, nodev, nodev, nodev, nodev, nodev, #endif }; int nldisp = sizeof (linesw) / sizeof (linesw[0]); /* * Do nothing specific version of line * discipline specific ioctl command. */ /*ARGSUSED*/ nullioctl(tp, cmd, data, flags) struct tty *tp; u_int cmd; char *data; int flags; { #ifdef lint tp = tp; data = data; flags = flags; #endif return (-1); } #if NSL > 0 SLOPEN(dev, tp) dev_t dev; struct tty *tp; { int error, slopen(); if (!suser()) return (EPERM); if (tp->t_line == SLIPDISC) return (EBUSY); error = KScall(slopen, sizeof(dev_t) + sizeof(struct tty *), dev, tp); if (!error) ttyflush(tp, FREAD | FWRITE); return(error); } SLCLOSE(tp, flag) struct tty *tp; int flag; { int slclose(); ttywflush(tp); tp->t_line = 0; KScall(slclose, sizeof(struct tty *), tp); } SLTIOCTL(tp, cmd, data, flag) struct tty *tp; int cmd, flag; caddr_t data; { int sltioctl(); return(KScall(sltioctl, sizeof(struct tty *) + sizeof(int) + sizeof(caddr_t) + sizeof(int), tp, cmd, data, flag)); } SLSTART(tp) struct tty *tp; { mapinfo map; void slstart(); savemap(map); KScall(slstart, sizeof(struct tty *), tp); restormap(map); } SLINPUT(c, tp) int c; struct tty *tp; { mapinfo map; void slinput(); savemap(map); KScall(slinput, sizeof(int) + sizeof(struct tty *), c, tp); restormap(map); } #endif ocp->p_flag &= ~SSEL; splx(s); goto retry; } u.u_procp->p_flag &= ~SSEL; if (uap->tv) { lqsave = u.u_qsasys/sys/ufs_subr.c 640 0 12 12551 5530563331 7503 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ufs_subr.c 1.4 (2.11BSD GTE) 2/15/94 */ #include "param.h" #include "../machine/seg.h" #include "user.h" #include "proc.h" #include "fs.h" #include "inode.h" #include "buf.h" #include "mount.h" #include "kernel.h" #include "systm.h" /* * Update is the internal name of 'sync'. It goes through the disk * queues to initiate sandbagged IO; goes through the inodes to write * modified nodes; and it goes through the mount table to initiate * the writing of the modified super blocks. */ update() { register struct mount *mp; register struct buf *bp; if (updlock) return; updlock++; /* * Write back modified superblocks. * Consistency check that the superblock * of each file system is still in the buffer cache. */ for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { register struct fs *fs; if (mp->m_inodp == NULL || mp->m_dev == NODEV) continue; fs = &mp->m_filsys; if (fs->fs_fmod == 0) continue; if (fs->fs_ronly != 0) { /* XXX */ printf("fs = %s\n", fs->fs_fsmnt); panic("update: rofs mod"); } if (fs->fs_ilock || fs->fs_flock) continue; bp = getblk(mp->m_dev, SUPERB); if (bp->b_flags & B_ERROR) continue; fs->fs_fmod = 0; fs->fs_time = time.tv_sec; bcopy(fs, mapin(bp), sizeof (struct fs)); mapout(bp); bwrite(bp); } /* * Write back each (modified) inode. */ { register struct inode *ip; for (ip = inode; ip < inodeNINODE; ip++) { if ((ip->i_flag & ILOCKED) != 0 || ip->i_count == 0 || (ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0) continue; ip->i_flag |= ILOCKED; ip->i_count++; iupdat(ip, &time, &time, 0); iput(ip); } } updlock = 0; /* * Force stale buffer cache information to be flushed, * for all devices. */ bflush(NODEV); } /* * Flush all the blocks associated with an inode. * There are two strategies based on the size of the file; * large files are those with more than (nbuf / 2) blocks. * Large files * Walk through the buffer pool and push any dirty pages * associated with the device on which the file resides. * Small files * Look up each block in the file to see if it is in the * buffer pool writing any that are found to disk. * Note that we make a more stringent check of * writing out any block in the buffer pool that may * overlap the inode. This brings the inode up to * date with recent mods to the cooked device. */ syncip(ip) struct inode *ip; { register struct buf *bp; register struct buf *lastbufp; long lbn, lastlbn; register int s; daddr_t blkno; lastlbn = howmany(ip->i_size, DEV_BSIZE); if (lastlbn < nbuf / 2) { for (lbn = 0; lbn < lastlbn; lbn++) { blkno = fsbtodb(bmap(ip, lbn, B_READ, 0)); blkflush(ip->i_dev, blkno); } } else { lastbufp = &buf[nbuf]; for (bp = buf; bp < lastbufp; bp++) { if (bp->b_dev != ip->i_dev || (bp->b_flags & B_DELWRI) == 0) continue; s = splbio(); if (bp->b_flags & B_BUSY) { bp->b_flags |= B_WANTED; sleep((caddr_t)bp, PRIBIO+1); splx(s); bp--; continue; } splx(s); notavail(bp); bwrite(bp); } } ip->i_flag |= ICHG; iupdat(ip, &time, &time, 1); } /* * Check that a specified block number is in range. */ badblock(fp, bn) register struct fs *fp; daddr_t bn; { if (bn < fp->fs_isize || bn >= fp->fs_fsize) { printf("bad block %D, ",bn); fserr(fp, "bad block"); return (1); } return (0); } /* * Getfs maps a device number into a pointer to the incore super block. * * The algorithm is a linear search through the mount table. A * consistency check of the super block magic number is performed. * * panic: no fs -- the device is not mounted. * this "cannot happen" */ struct fs * getfs(dev) dev_t dev; { register struct mount *mp; register struct fs *fs; for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { if (mp->m_inodp == NULL || mp->m_dev != dev) continue; fs = &mp->m_filsys; if (fs->fs_nfree > NICFREE || fs->fs_ninode > NICINOD) { fserr(fs, "bad count"); fs->fs_nfree = fs->fs_ninode = 0; } return(fs); } printf("no fs on dev %u/%u\n",major(dev), minor(dev)); return((struct fs *) NULL); } #ifdef QUOTA /* * Getfsx returns the index in the file system * table of the specified device. The swap device * is also assigned a pseudo-index. The index may * be used as a compressed indication of the location * of a block, recording * * rather than * * provided the information need remain valid only * as long as the file system is mounted. */ getfsx(dev) dev_t dev; { register struct mount *mp; if (dev == swapdev) return (0377); for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) if (mp->m_dev == dev) return (mp - &mount[0]); return (-1); } #endif #if (!defined(vax) && !defined(tahoe) && !defined(pdp11)) || defined(VAX630) scanc(size, cp, table, mask) u_int size; register u_char *cp, table[]; register u_char mask; { register u_char *end = &cp[size]; while (cp < end && (table[*cp] & mask) == 0) cp++; return (end - cp); } #endif #if !defined(vax) && !defined(tahoe) && !defined(pdp11) locc(mask, size, cp) register u_char mask; u_int size; register u_char *cp; { register u_char *end = &cp[size]; while (cp < end && *cp != mask) cp++; return (end - cp); } #endif struct file *fp; int flag; { #ifdef INET return (SOO_SELECT(fp, flag)); #else return (EOPNOTSUPP); #endif } socls(fp) register struct file *fp; { sys/sys/kern_sig.c 444 0 24 42464 5666031125 7470 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)kern_sig.c 1.5 (2.11BSD GTE) 11/26/94 */ #include "param.h" #include "../machine/seg.h" #include "systm.h" #include "user.h" #include "inode.h" #include "proc.h" #include "text.h" #include "namei.h" #include "acct.h" #define cantmask (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP)) #define stopsigmask (sigmask(SIGSTOP)|sigmask(SIGTSTP)| \ sigmask(SIGTTIN)|sigmask(SIGTTOU)) /* * Generalized interface signal handler. */ sigvec() { register struct a { #ifdef pdp11 int (*sigtramp)(); #endif pdp11 int signo; struct sigvec *nsv; struct sigvec *osv; } *uap = (struct a *)u.u_ap; struct sigvec vec; register struct sigvec *sv; register int sig; long bit; #ifdef pdp11 /* * Save user trampoline code entry address. */ u.u_pcb.pcb_sigc = uap->sigtramp; #endif pdp11 sig = uap->signo; if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP) { u.u_error = EINVAL; return; } sv = &vec; if (uap->osv) { sv->sv_handler = u.u_signal[sig]; sv->sv_mask = u.u_sigmask[sig]; bit = sigmask(sig); sv->sv_flags = 0; if ((u.u_sigonstack & bit) != 0) sv->sv_flags |= SV_ONSTACK; if ((u.u_sigintr & bit) != 0) sv->sv_flags |= SV_INTERRUPT; u.u_error = copyout((caddr_t)sv, (caddr_t)uap->osv, sizeof (vec)); if (u.u_error) return; } if (uap->nsv) { u.u_error = copyin((caddr_t)uap->nsv, (caddr_t)sv, sizeof (vec)); if (u.u_error) return; if (sig == SIGCONT && sv->sv_handler == SIG_IGN) { u.u_error = EINVAL; return; } setsigvec(sig, sv); } } setsigvec(sig, sv) int sig; register struct sigvec *sv; { register struct proc *p; register long bit; bit = sigmask(sig); p = u.u_procp; /* * Change setting atomically. */ (void) _splhigh(); u.u_signal[sig] = sv->sv_handler; u.u_sigmask[sig] = sv->sv_mask &~ cantmask; if (sv->sv_flags & SV_INTERRUPT) u.u_sigintr |= bit; else u.u_sigintr &= ~bit; if (sv->sv_flags & SV_ONSTACK) u.u_sigonstack |= bit; else u.u_sigonstack &= ~bit; if (sv->sv_handler == SIG_IGN) { p->p_sig &= ~bit; /* never to be seen again */ p->p_sigignore |= bit; p->p_sigcatch &= ~bit; } else { p->p_sigignore &= ~bit; if (sv->sv_handler == SIG_DFL) p->p_sigcatch &= ~bit; else p->p_sigcatch |= bit; } (void) _spl0(); } sigblock() { struct a { long mask; } *uap = (struct a *)u.u_ap; register struct proc *p = u.u_procp; (void) _splhigh(); u.u_r.r_long = p->p_sigmask; p->p_sigmask |= uap->mask &~ cantmask; (void) _spl0(); } sigsetmask() { struct a { long mask; } *uap = (struct a *)u.u_ap; register struct proc *p = u.u_procp; (void) _splhigh(); u.u_r.r_long = p->p_sigmask; p->p_sigmask = uap->mask &~ cantmask; (void) _spl0(); } sigpause() { struct a { long mask; } *uap = (struct a *)u.u_ap; register struct proc *p = u.u_procp; /* * When returning from sigpause, we want * the old mask to be restored after the * signal handler has finished. Thus, we * save it here and mark the proc structure * to indicate this (should be in u.). */ u.u_oldmask = p->p_sigmask; p->p_flag |= SOMASK; p->p_sigmask = uap->mask &~ cantmask; for (;;) sleep((caddr_t)&u, PSLEP); /*NOTREACHED*/ } #undef cantmask sigstack() { register struct a { struct sigstack *nss; struct sigstack *oss; } *uap = (struct a *)u.u_ap; struct sigstack ss; if (uap->oss) { u.u_error = copyout((caddr_t)&u.u_sigstack, (caddr_t)uap->oss, sizeof (struct sigstack)); if (u.u_error) return; } if (uap->nss) { u.u_error = copyin((caddr_t)uap->nss, (caddr_t)&ss, sizeof (ss)); if (u.u_error == 0) u.u_sigstack = ss; } } kill() { register struct a { int pid; int signo; } *uap = (struct a *)u.u_ap; register struct proc *p; #ifdef pdp11 /* * BSD4.3 botches the comparison against NSIG - it's a good thing for * them psignal catches the error - however, since psignal is the * kernel's internel signal mechanism and *should be getting correct * parameters from the rest of the kernel, psignal shouldn't *have* * to check it's parameters for validity. If you feel differently, * feel free to clutter up the entire inner kernel with parameter * checks - start with psig ... */ if (uap->signo < 0 || uap->signo >= NSIG) { #else if (uap->signo < 0 || uap->signo > NSIG) { #endif u.u_error = EINVAL; return; } if (uap->pid > 0) { /* kill single process */ p = pfind(uap->pid); if (p == 0) { u.u_error = ESRCH; return; } #ifdef pdp11 /* * Fix to allow a non-root process to send SIGCONT to * one of its own decendants which happens to be running * with a different uid. (second line of if) "#else" clause * contains original 4.3 code. */ if (u.u_uid && u.u_uid != p->p_uid && (uap->signo != SIGCONT || !inferior(p))) #else if (u.u_uid && u.u_uid != p->p_uid) #endif u.u_error = EPERM; else if (uap->signo) psignal(p, uap->signo); return; } switch (uap->pid) { case -1: /* broadcast signal */ u.u_error = killpg1(uap->signo, 0, 1); break; case 0: /* signal own process group */ u.u_error = killpg1(uap->signo, 0, 0); break; default: /* negative explicit process group */ u.u_error = killpg1(uap->signo, -uap->pid, 0); break; } return; } killpg() { register struct a { int pgrp; int signo; } *uap = (struct a *)u.u_ap; #ifdef pdp11 /* see comment in kill above */ if (uap->signo < 0 || uap->signo >= NSIG) { #else if (uap->signo < 0 || uap->signo > NSIG) { #endif u.u_error = EINVAL; return; } u.u_error = killpg1(uap->signo, uap->pgrp, 0); } /* KILL CODE SHOULDNT KNOW ABOUT PROCESS INTERNALS !?! */ killpg1(signo, pgrp, all) int signo, pgrp, all; { register struct proc *p; int f, error = 0; if (!all && pgrp == 0) { /* * Zero process id means send to my process group. */ pgrp = u.u_procp->p_pgrp; if (pgrp == 0) return (ESRCH); } for (f = 0, p = allproc; p != NULL; p = p->p_nxt) { if ((p->p_pgrp != pgrp && !all) || p->p_ppid == 0 || (p->p_flag&SSYS) || (all && p == u.u_procp)) continue; if (u.u_uid != 0 && u.u_uid != p->p_uid && (signo != SIGCONT || !inferior(p))) { if (!all) error = EPERM; continue; } f++; if (signo) psignal(p, signo); } return (error ? error : (f == 0 ? ESRCH : 0)); } /* * Send the specified signal to * all processes with 'pgrp' as * process group. */ gsignal(pgrp, sig) register int pgrp; { register struct proc *p; mapinfo map; if (pgrp == 0) return; savemap(map); for (p = allproc; p != NULL; p = p->p_nxt) if (p->p_pgrp == pgrp) psignal(p, sig); restormap(map); } /* * Send the specified signal to * the specified process. */ psignal(p, sig) register struct proc *p; register int sig; { register int s; register int (*action)(); long mask; #ifdef DIAGNOSTIC /* see comment in kill above */ if ((unsigned)sig >= NSIG) return; #endif mask = sigmask(sig); /* * If proc is traced, always give parent a chance. */ if (p->p_flag & STRC) action = SIG_DFL; else { /* * If the signal is being ignored, * then we forget about it immediately. */ if (p->p_sigignore & mask) return; if (p->p_sigmask & mask) action = SIG_HOLD; else if (p->p_sigcatch & mask) action = SIG_CATCH; else action = SIG_DFL; } #ifndef pdp11 /* This is nonsense - should simply be ripped out */ if (sig) { #endif p->p_sig |= mask; switch (sig) { case SIGTERM: if ((p->p_flag&STRC) || action != SIG_DFL) break; /* fall into ... */ case SIGKILL: if (p->p_nice > NZERO) p->p_nice = NZERO; break; case SIGCONT: p->p_sig &= ~stopsigmask; break; case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU: p->p_sig &= ~sigmask(SIGCONT); break; } #ifndef pdp11 } #endif /* * Defer further processing for signals which are held. */ if (action == SIG_HOLD) return; s = splhigh(); switch (p->p_stat) { case SSLEEP: /* * If process is sleeping at negative priority * we can't interrupt the sleep... the signal will * be noticed when the process returns through * trap() or syscall(). */ if (p->p_pri <= PZERO) goto out; /* * Process is sleeping and traced... make it runnable * so it can discover the signal in issig() and stop * for the parent. */ if (p->p_flag&STRC) goto run; switch (sig) { case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU: /* * These are the signals which by default * stop a process. */ if (action != SIG_DFL) goto run; /* * Don't clog system with children of init * stopped from the keyboard. */ if (sig != SIGSTOP && p->p_pptr == &proc[1]) { psignal(p, SIGKILL); p->p_sig &= ~mask; splx(s); return; } /* * If a child in vfork(), stopping could * cause deadlock. */ if (p->p_flag&SVFORK) goto out; p->p_sig &= ~mask; p->p_cursig = sig; psignal(p->p_pptr, SIGCHLD); stop(p); goto out; case SIGIO: case SIGURG: case SIGCHLD: case SIGWINCH: /* * These signals are special in that they * don't get propogated... if the process * isn't interested, forget it. */ if (action != SIG_DFL) goto run; p->p_sig &= ~mask; /* take it away */ goto out; default: /* * All other signals cause the process to run */ goto run; } /*NOTREACHED*/ case SSTOP: /* * If traced process is already stopped, * then no further action is necessary. */ if (p->p_flag&STRC) goto out; switch (sig) { case SIGKILL: /* * Kill signal always sets processes running. */ goto run; case SIGCONT: /* * If the process catches SIGCONT, let it handle * the signal itself. If it isn't waiting on * an event, then it goes back to run state. * Otherwise, process goes back to sleep state. */ if (action != SIG_DFL || p->p_wchan == 0) goto run; p->p_stat = SSLEEP; goto out; case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU: /* * Already stopped, don't need to stop again. * (If we did the shell could get confused.) */ p->p_sig &= ~mask; /* take it away */ goto out; default: /* * If process is sleeping interruptibly, then * unstick it so that when it is continued * it can look at the signal. * But don't setrun the process as its not to * be unstopped by the signal alone. */ if (p->p_wchan && p->p_pri > PZERO) unsleep(p); goto out; } /*NOTREACHED*/ default: /* * SRUN, SIDL, SZOMB do nothing with the signal, * other than kicking ourselves if we are running. * It will either never be noticed, or noticed very soon. */ #ifdef vax if (p == u.u_procp && !noproc) #include "../vax/mtpr.h" aston(); #endif vax goto out; } /*NOTREACHED*/ run: /* * Raise priority to at least PUSER. */ if (p->p_pri > PUSER) p->p_pri = PUSER; setrun(p); out: splx(s); } /* * Returns true if the current * process has a signal to process. * The signal to process is put in p_cursig. * This is asked at least once each time a process enters the * system (though this can usually be done without actually * calling issig by checking the pending signal masks.) * A signal does not do anything * directly to a process; it sets * a flag that asks the process to * do something to itself. */ issig() { register struct proc *p; register int sig; long sigbits, mask; p = u.u_procp; for (;;) { sigbits = p->p_sig &~ p->p_sigmask; if ((p->p_flag&STRC) == 0) sigbits &= ~p->p_sigignore; if (p->p_flag&SVFORK) sigbits &= ~stopsigmask; if (sigbits == 0) break; sig = ffs((long)sigbits); mask = sigmask(sig); p->p_sig &= ~mask; /* take the signal! */ p->p_cursig = sig; if (p->p_flag&STRC) { /* * If traced, always stop, and stay * stopped until released by the parent. */ psignal(p->p_pptr, SIGCHLD); do { stop(p); swtch(); } while (!procxmt() && p->p_flag&STRC); /* * If the traced bit got turned off, * then put the signal taken above back into p_sig * and go back up to the top to rescan signals. * This ensures that p_sig* and u_signal are consistent. */ if ((p->p_flag&STRC) == 0) { p->p_sig |= mask; continue; } /* * If parent wants us to take the signal, * then it will leave it in p->p_cursig; * otherwise we just look for signals again. */ sig = p->p_cursig; if (sig == 0) continue; /* * If signal is being masked put it back * into p_sig and look for other signals. */ mask = sigmask(sig); if (p->p_sigmask & mask) { p->p_sig |= mask; continue; } } switch ((int)u.u_signal[sig]) { case SIG_DFL: /* * Don't take default actions on system processes. */ if (p->p_ppid == 0) break; switch (sig) { case SIGTSTP: case SIGTTIN: case SIGTTOU: /* * Children of init aren't allowed to stop * on signals from the keyboard. */ if (p->p_pptr == &proc[1]) { psignal(p, SIGKILL); continue; } /* fall into ... */ case SIGSTOP: if (p->p_flag&STRC) continue; psignal(p->p_pptr, SIGCHLD); stop(p); swtch(); continue; case SIGCONT: case SIGCHLD: case SIGURG: case SIGIO: case SIGWINCH: /* * These signals are normally not * sent if the action is the default. */ continue; /* == ignore */ default: goto send; } /*NOTREACHED*/ case SIG_HOLD: case SIG_IGN: /* * Masking above should prevent us * ever trying to take action on a held * or ignored signal, unless process is traced. */ if ((p->p_flag&STRC) == 0) printf("issig\n"); continue; default: /* * This signal has an action, let * psig process it. */ goto send; } /*NOTREACHED*/ } /* * Didn't find a signal to send. */ p->p_cursig = 0; return (0); send: /* * Let psig process the signal. */ return (sig); } /* * Put the argument process into the stopped * state and notify the parent via wakeup. * Signals are handled elsewhere. */ stop(p) register struct proc *p; { p->p_stat = SSTOP; p->p_flag &= ~SWTED; wakeup((caddr_t)p->p_pptr); } /* * Perform the action specified by * the current signal. * The usual sequence is: * if (issig()) * psig(); * The signal bit has already been cleared by issig, * and the current signal number stored in p->p_cursig. */ psig() { register struct proc *p = u.u_procp; register int sig = p->p_cursig; long mask = sigmask(sig), returnmask; register int (*action)(); #ifdef DIAGNOSTIC /* more nonsense */ if (sig == 0) panic("psig"); #endif if (u.u_fpsaved == 0) { savfp(&u.u_fps); u.u_fpsaved = 1; } action = u.u_signal[sig]; if (action != SIG_DFL) { #ifdef DIAGNOSTIC if (action == SIG_IGN || (p->p_sigmask & mask)) panic("psig action"); #endif u.u_error = 0; /* * Set the new mask value and also defer further * occurences of this signal. * * Special case: user has done a sigpause. Here the * current mask is not of interest, but rather the * mask from before the sigpause is what we want restored * after the signal processing is completed. */ (void) _splhigh(); if (p->p_flag & SOMASK) { returnmask = u.u_oldmask; p->p_flag &= ~SOMASK; } else returnmask = p->p_sigmask; p->p_sigmask |= u.u_sigmask[sig] | mask; (void) _spl0(); u.u_ru.ru_nsignals++; sendsig(action, sig, returnmask); p->p_cursig = 0; return; } u.u_acflag |= AXSIG; switch (sig) { case SIGILL: case SIGIOT: case SIGBUS: case SIGQUIT: case SIGTRAP: case SIGEMT: case SIGFPE: case SIGSEGV: case SIGSYS: u.u_arg[0] = sig; if (core()) sig += 0200; } exit(sig); } /* * Create a core image on the file "core" * If you are looking for protection glitches, * there are probably a wealth of them here * when this occurs to a suid command. * * It writes UPAGES (USIZE for pdp11) block of the * user.h area followed by the entire * data+stack segments. */ core() { register struct inode *ip; register struct nameidata *ndp = &u.u_nd; register char *np; char *cp, name[MAXCOMLEN + 6]; if (u.u_uid != u.u_ruid || u.u_gid != u.u_rgid) return (0); if (ctob(USIZE+u.u_dsize+u.u_ssize) >= u.u_rlimit[RLIMIT_CORE].rlim_cur) return (0); if (u.u_procp->p_textp && access(u.u_procp->p_textp->x_iptr, IREAD)) return (0); cp = u.u_comm; np = name; while (*np++ = *cp++) ; cp = ".core"; np--; while (*np++ = *cp++) ; u.u_error = 0; ndp->ni_nameiop = CREATE | FOLLOW; ndp->ni_segflg = UIO_SYSSPACE; ndp->ni_dirp = name; ip = namei(ndp); if (ip == NULL) { if (u.u_error) return (0); ip = maknode(0644, ndp); if (ip==NULL) return (0); } if (access(ip, IWRITE) || (ip->i_mode&IFMT) != IFREG || ip->i_nlink != 1) { u.u_error = EFAULT; goto out; } itrunc(ip, (u_long)0); u.u_acflag |= ACORE; u.u_error = rdwri(UIO_WRITE, ip, &u, ctob(USIZE), (off_t)0, UIO_SYSSPACE, IO_UNIT, (int *)0); if (u.u_error) goto out; estabur((u_int)0, u.u_dsize, u.u_ssize, 0, RO); u.u_error = rdwri(UIO_WRITE, ip, 0, ctob(u.u_dsize), (off_t)ctob(USIZE), UIO_USERSPACE, IO_UNIT, (int *)0); if (u.u_error) goto out; u.u_error = rdwri(UIO_WRITE, ip, (caddr_t)(-(ctob(u.u_ssize))), ctob(u.u_ssize), (off_t)ctob(USIZE) + (off_t)ctob(u.u_dsize), UIO_USERSPACE, IO_UNIT, (int *)0); out: iput(ip); return (u.u_error == 0); } SIG_DFL; } #ifndef pdp11 /* This is nonsense - should simply be ripped out */ if (sig) { #endif p->p_sig |= mask; switch (sig) { case SIGTERM: if ((p->p_flag&STRC) || action != SIG_DFL) sys/sys/kern_subr.c 440 0 12 10542 5666525624 7656 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)kern_subr.c 1.2 (2.11BSD GTE) 11/26/94 */ #include "param.h" #include "../machine/seg.h" #include "systm.h" #include "user.h" #include "buf.h" #include "uio.h" /* copied, for supervisory networking, to sys_net.c */ uiomove(cp, n, uio) caddr_t cp; u_int n; register struct uio *uio; { register struct iovec *iov; int error = 0; register u_int cnt; while (n > 0 && uio->uio_resid) { iov = uio->uio_iov; cnt = iov->iov_len; if (cnt == 0) { uio->uio_iov++; uio->uio_iovcnt--; continue; } if (cnt > n) cnt = n; switch (uio->uio_segflg) { case UIO_USERSPACE: if (cnt > 100 && cp + cnt < SEG6) error = uiofmove(cp, cnt, uio, iov); else if ((cnt | (int)cp | (int)iov->iov_base) & 1) if (uio->uio_rw == UIO_READ) error = vcopyout(cp,iov->iov_base, cnt); else error = vcopyin(iov->iov_base, cp, cnt); else { if (uio->uio_rw == UIO_READ) error = copyout(cp, iov->iov_base, cnt); else error = copyin(iov->iov_base, cp, cnt); } if (error) return (error); break; case UIO_USERISPACE: if (cnt > 100 && cp + cnt < SEG6) error = uiofmove(cp, cnt, uio, iov); else if (uio->uio_rw == UIO_READ) error = copyiout(cp, iov->iov_base, cnt); else error = copyiin(iov->iov_base, cp, cnt); if (error) return (error); break; case UIO_SYSSPACE: if (uio->uio_rw == UIO_READ) bcopy((caddr_t)cp, iov->iov_base, cnt); else bcopy(iov->iov_base, (caddr_t)cp, cnt); break; } iov->iov_base += cnt; iov->iov_len -= cnt; uio->uio_resid -= cnt; uio->uio_offset += cnt; cp += cnt; n -= cnt; } return (error); } /* copied, for supervisory networking, to sys_net.c */ /* * Give next character to user as result of read. */ ureadc(c, uio) register int c; register struct uio *uio; { register struct iovec *iov; again: if (uio->uio_iovcnt == 0) panic("ureadc"); iov = uio->uio_iov; if (iov->iov_len == 0 || uio->uio_resid == 0) { uio->uio_iovcnt--; uio->uio_iov++; goto again; } switch (uio->uio_segflg) { case UIO_USERSPACE: if (subyte(iov->iov_base, c) < 0) return (EFAULT); break; case UIO_SYSSPACE: *iov->iov_base = c; break; case UIO_USERISPACE: if (suibyte(iov->iov_base, c) < 0) return (EFAULT); break; } iov->iov_base++; iov->iov_len--; uio->uio_resid--; uio->uio_offset++; return (0); } /* copied, for supervisory networking, to sys_net.c */ /* * Get next character written in by user from uio. */ uwritec(uio) register struct uio *uio; { register struct iovec *iov; register int c; if (uio->uio_resid == 0) return (-1); again: if (uio->uio_iovcnt <= 0) panic("uwritec"); iov = uio->uio_iov; if (iov->iov_len == 0) { uio->uio_iov++; if (--uio->uio_iovcnt == 0) return (-1); goto again; } switch (uio->uio_segflg) { case UIO_USERSPACE: c = fubyte(iov->iov_base); break; case UIO_SYSSPACE: c = *iov->iov_base & 0377; break; case UIO_USERISPACE: c = fuibyte(iov->iov_base); break; } if (c < 0) return (-1); iov->iov_base++; iov->iov_len--; uio->uio_resid--; uio->uio_offset++; return (c & 0377); } /* * Copy bytes to/from the kernel and the user. Uiofmove assumes the kernel * area being copied to or from does not overlap segment 6 - the assembly * language helper routine, fmove, uses segment register 6 to map in the * user's memory. */ uiofmove(cp, n, uio, iov) caddr_t cp; register int n; struct uio *uio; struct iovec *iov; { register short c; short on; register short segr; /* seg register (0 - 7) */ u_short *segd; /* PDR map array */ u_short *sega; /* PAR map array */ int error; #ifdef NONSEPARATE segd = UISD; sega = UISA; #else if (uio->uio_segflg == UIO_USERSPACE && u.u_sep) { segd = UDSD; sega = UDSA; } else { segd = UISD; sega = UISA; } #endif segr = (short)iov->iov_base >> 13 & 07; on = (short)iov->iov_base & 017777; c = MIN(n, 8192-on); for (;;) { if (uio->uio_rw == UIO_READ) error = fmove(sega[segr], segd[segr], cp, SEG6+on, c); else error = fmove(sega[segr], segd[segr], SEG6+on, cp, c); if (error) return(error); n -= c; if (!n) return(0); cp += c; segr++; segr &= 07; on = 0; c = MIN(n, 8192); } /*NOTREACHED*/ } (sig) { case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU: /* * These are the signals which by default * stop a process. */ ifsys/sys/kern_synch.c 440 0 12 22242 5350245712 10012 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)kern_synch.c 1.2 (2.11BSD GTE) 1/1/93 */ #include "param.h" #include "../machine/seg.h" #include "user.h" #include "proc.h" #include "buf.h" #include "signal.h" #include "vm.h" #include "kernel.h" #include "systm.h" #define SQSIZE 16 /* Must be power of 2 */ #define HASH(x) (((int)x >> 5) & (SQSIZE - 1)) #define SCHMAG 8/10 struct proc *slpque[SQSIZE]; /* * Recompute process priorities, once a second */ schedcpu() { register struct proc *p; register int a; wakeup((caddr_t)&lbolt); for (p = allproc; p != NULL; p = p->p_nxt) { if (p->p_time != 127) p->p_time++; /* * this is where 2.10 does its real time alarms. 4.X uses * timeouts, since it offers better than second resolution. * Putting it here allows us to continue using use an int * to store the number of ticks in the callout structure, * since the kernel never has a timeout of greater than * around 9 minutes. */ if (p->p_realtimer.it_value && !--p->p_realtimer.it_value) { psignal(p, SIGALRM); p->p_realtimer.it_value = p->p_realtimer.it_interval; } if (p->p_stat == SSLEEP || p->p_stat == SSTOP) if (p->p_slptime != 127) p->p_slptime++; if (p->p_slptime > 1) continue; a = (p->p_cpu & 0377) * SCHMAG + p->p_nice; if (a < 0) a = 0; if (a > 255) a = 255; p->p_cpu = a; if (p->p_pri >= PUSER) setpri(p); } vmmeter(); if (runin!=0) { runin = 0; wakeup((caddr_t)&runin); } ++runrun; /* swtch at least once a second */ timeout(schedcpu, (caddr_t)0, LINEHZ); } /* * Recalculate the priority of a process after it has slept for a while. */ updatepri(p) register struct proc *p; { register int a = p->p_cpu & 0377; p->p_slptime--; /* the first time was done in schedcpu */ while (a && --p->p_slptime) a = (SCHMAG * a) /* + p->p_nice */; if (a < 0) a = 0; if (a > 255) a = 255; p->p_cpu = a; (void) setpri(p); } /* * Give up the processor till a wakeup occurs * on chan, at which time the process * enters the scheduling queue at priority pri. * The most important effect of pri is that when * pri<=PZERO a signal cannot disturb the sleep; * if pri>PZERO signals will be processed. * Callers of this routine must be prepared for * premature return, and check that the reason for * sleeping has gone away. */ sleep(chan, pri) caddr_t chan; int pri; { register struct proc *rp; register struct proc **qp; register s; rp = u.u_procp; s = splhigh(); if (panicstr) { /* * After a panic, just give interrupts a chance, then just * return; don't run any other procs or panic below, in * case this is the idle process and already asleep. The * splnet should be spl0 if the network was being used * by the filesystem, but for now avoid network interrupts * that might cause another panic. */ (void) _splnet(); noop(); splx(s); return; } if (!chan || rp->p_stat != SRUN) panic("sleep"); rp->p_wchan = chan; rp->p_slptime = 0; rp->p_pri = pri; qp = &slpque[HASH(chan)]; rp->p_link = *qp; *qp = rp; if (pri > PZERO) { /* * If we stop in issig(), wakeup may already have happened * when we return (rp->p_wchan will then be 0). */ if (ISSIG(rp)) { if (rp->p_wchan) unsleep(rp); rp->p_stat = SRUN; (void) _spl0(); goto psig; } if (rp->p_wchan == 0) goto out; rp->p_stat = SSLEEP; (void) _spl0(); /* * maybe a very small core memory, give swapped out * processes a chance. */ if (runin != 0) { runin = 0; wakeup((caddr_t)&runin); } u.u_ru.ru_nvcsw++; swtch(); if (ISSIG(rp)) goto psig; } else { rp->p_stat = SSLEEP; (void) _spl0(); u.u_ru.ru_nvcsw++; swtch(); } out: splx(s); return; /* * If priority was low (>PZERO) and there has been a signal, * execute non-local goto through u.u_qsave, aborting the * system call in progress (see trap.c) */ psig: longjmp(u.u_procp->p_addr, &u.u_qsave); /*NOTREACHED*/ } /* * Remove a process from its wait queue */ unsleep(p) register struct proc *p; { register struct proc **hp; register int s; s = splhigh(); if (p->p_wchan) { hp = &slpque[HASH(p->p_wchan)]; while (*hp != p) hp = &(*hp)->p_link; *hp = p->p_link; p->p_wchan = 0; } splx(s); } /* * Wake up all processes sleeping on chan. */ wakeup(chan) register caddr_t chan; { register struct proc *p, **q; struct proc **qp; int s; mapinfo map; /* * Since we are called at interrupt time, must insure normal * kernel mapping to access proc. */ savemap(map); s = splclock(); qp = &slpque[HASH(chan)]; restart: for (q = qp; p = *q; ) { if (p->p_stat != SSLEEP && p->p_stat != SSTOP) panic("wakeup"); if (p->p_wchan==chan) { p->p_wchan = 0; *q = p->p_link; if (p->p_stat == SSLEEP) { /* OPTIMIZED INLINE EXPANSION OF setrun(p) */ if (p->p_slptime > 1) updatepri(p); p->p_slptime = 0; p->p_stat = SRUN; if (p->p_flag & SLOAD) setrq(p); /* * Since curpri is a usrpri, * p->p_pri is always better than curpri. */ runrun++; if ((p->p_flag&SLOAD) == 0) { if (runout != 0) { runout = 0; wakeup((caddr_t)&runout); } } /* END INLINE EXPANSION */ goto restart; } p->p_slptime = 0; } else q = &p->p_link; } splx(s); restormap(map); } /* * Set the process running; * arrange for it to be swapped in if necessary. */ setrun(p) register struct proc *p; { register int s; s = splhigh(); switch (p->p_stat) { case 0: case SWAIT: case SRUN: case SZOMB: default: panic("setrun"); case SSTOP: case SSLEEP: unsleep(p); /* e.g. when sending signals */ break; case SIDL: break; } if (p->p_slptime > 1) updatepri(p); p->p_stat = SRUN; if (p->p_flag & SLOAD) setrq(p); splx(s); if (p->p_pri < curpri) runrun++; if ((p->p_flag&SLOAD) == 0) { if (runout != 0) { runout = 0; wakeup((caddr_t)&runout); } } } /* * Set user priority. * The rescheduling flag (runrun) * is set if the priority is better * than the currently running process. */ setpri(pp) register struct proc *pp; { register int p; p = (pp->p_cpu & 0377)/16; p += PUSER + pp->p_nice; if (p > 127) p = 127; if (p < curpri) runrun++; pp->p_pri = p; return (p); } /* * This routine is called to reschedule the CPU. If the calling process is * not in RUN state, arrangements for it to restart must have been made * elsewhere, usually by calling via sleep. There is a race here. A process * may become ready after it has been examined. In this case, idle() will be * called and will return in at most 1hz time, e.g. it's not worth putting an * spl() in. */ swtch() { register struct proc *p, *q; register int n; struct proc *pp, *pq; int s; #ifdef DIAGNOSTIC extern struct buf *hasmap; if (hasmap) panic("swtch hasmap"); #endif #ifdef UCB_METER cnt.v_swtch++; #endif /* If not the idle process, resume the idle process. */ if (u.u_procp != &proc[0]) { if (setjmp(&u.u_rsave)) { sureg(); return; } if (u.u_fpsaved == 0) { savfp(&u.u_fps); u.u_fpsaved = 1; } longjmp(proc[0].p_addr, &u.u_qsave); } /* * The first save returns nonzero when proc 0 is resumed * by another process (above); then the second is not done * and the process-search loop is entered. * * The first save returns 0 when swtch is called in proc 0 * from sched(). The second save returns 0 immediately, so * in this case too the process-search loop is entered. * Thus when proc 0 is awakened by being made runnable, it will * find itself and resume itself at rsave, and return to sched(). */ if (setjmp(&u.u_qsave)==0 && setjmp(&u.u_rsave)) return; loop: s = splhigh(); noproc = 0; runrun = 0; #ifdef DIAGNOSTIC for (p = qs; p; p = p->p_link) if (p->p_stat != SRUN) panic("swtch SRUN"); #endif pp = NULL; q = NULL; n = 128; /* * search for highest-priority runnable process */ for (p = qs; p; p = p->p_link) { if (p->p_flag & SLOAD && p->p_pri < n) { pp = p; pq = q; n = p->p_pri; } q = p; } /* * if no process is runnable, idle. */ p = pp; if (p == NULL) { idle(); goto loop; } if (pq) pq->p_link = p->p_link; else qs = p->p_link; curpri = n; splx(s); /* * the rsave (ssave) contents are interpreted * in the new address space */ n = p->p_flag & SSWAP; p->p_flag &= ~SSWAP; longjmp(p->p_addr, n ? &u.u_ssave: &u.u_rsave); } setrq(p) register struct proc *p; { register int s; s = splhigh(); #ifdef DIAGNOSTIC { /* see if already on the run queue */ register struct proc *q; for (q = qs;q != NULL;q = q->p_link) if (q == p) panic("setrq"); } #endif p->p_link = qs; qs = p; splx(s); } /* * Remove runnable job from run queue. This is done when a runnable job * is swapped out so that it won't be selected in swtch(). It will be * reinserted in the qs with setrq when it is swapped back in. */ remrq(p) register struct proc *p; { register struct proc *q; register int s; s = splhigh(); if (p == qs) qs = p->p_link; else { for (q = qs; q; q = q->p_link) if (q->p_link == p) { q->p_link = p->p_link; goto done; } panic("remrq"); } done: splx(s); } STRC) == 0) { p->p_sig |= mask; continue; } /* * If parent wants us to take the signal, * then it will leave it in p->p_cursig; * otherwise we just look for signals again. */ sig = p->p_cursig; if (sig == 0) continue; /* * If signal is being masked put it back * into p_sig and look for other signsys/sys/subr_prf.c 440 0 12 16033 4627052353 7475 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)subr_prf.c 1.1 (2.10BSD Berkeley) 12/1/86 */ #include "param.h" #include "user.h" #include "machine/seg.h" #include "buf.h" #include "msgbuf.h" #include "conf.h" #include "ioctl.h" #include "tty.h" #include "reboot.h" #include "systm.h" #include "syslog.h" #define TOCONS 0x1 #define TOTTY 0x2 #define TOLOG 0x4 /* * In case console is off, * panicstr contains argument to last * call to panic. */ char *panicstr; /* * Scaled down version of C Library printf. * Used to print diagnostic information directly on console tty. * Since it is not interrupt driven, all system activities are * suspended. Printf should not be used for chit-chat. * * One additional format: %b is supported to decode error registers. * Usage is: * printf("reg=%b\n", regval, "*"); * Where is the output base expressed as a control character, * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of * characters, the first of which gives the bit number to be inspected * (origin 1), and the next characters (up to a control character, i.e. * a character <= 32), give the name of the register. Thus * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); * would produce output: * reg=3 */ /*VARARGS1*/ printf(fmt, x1) char *fmt; unsigned x1; { prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)0); } /* * Uprintf prints to the current user's terminal, * guarantees not to sleep (so could be called by interrupt routines; * but prints on the tty of the current process) * and does no watermark checking - (so no verbose messages). * NOTE: with current kernel mapping scheme, the user structure is * not guaranteed to be accessible at interrupt level (see seg.h); * a savemap/restormap would be needed here or in putchar if uprintf * was to be used at interrupt time. */ /*VARARGS1*/ uprintf(fmt, x1) char *fmt; unsigned x1; { register struct tty *tp; if ((tp = u.u_ttyp) == NULL) return; if (ttycheckoutq(tp, 1)) prf(fmt, &x1, TOTTY, tp); } /* * tprintf prints on the specified terminal (console if none) * and logs the message. It is designed for error messages from * single-open devices, and may be called from interrupt level * (does not sleep). */ /*VARARGS2*/ tprintf(tp, fmt, x1) register struct tty *tp; char *fmt; unsigned x1; { int flags = TOTTY | TOLOG; extern struct tty cons; logpri(LOG_INFO); if (tp == (struct tty *)NULL) tp = &cons; if (ttycheckoutq(tp, 0) == 0) flags = TOLOG; prf(fmt, &x1, flags, tp); logwakeup(); } /* * Log writes to the log buffer, * and guarantees not to sleep (so can be called by interrupt routines). * If there is no process reading the log yet, it writes to the console also. */ /*VARARGS2*/ log(level, fmt, x1) char *fmt; unsigned x1; { register s = splhigh(); extern int log_open; logpri(level); prf(fmt, &x1, TOLOG, (struct tty *)0); splx(s); if (!log_open) prf(fmt, &x1, TOCONS, (struct tty *)0); logwakeup(); } logpri(level) int level; { putchar('<', TOLOG, (struct tty *)0); printn((u_long)level, 10, TOLOG, (struct tty *)0); putchar('>', TOLOG, (struct tty *)0); } prf(fmt, adx, flags, ttyp) register char *fmt; register u_int *adx; int flags; struct tty *ttyp; { register int c; u_int b; char *s; int i, any; loop: while ((c = *fmt++) != '%') { if (c == '\0') return; putchar(c, flags, ttyp); } c = *fmt++; switch (c) { case 'l': c = *fmt++; switch(c) { case 'x': b = 16; goto lnumber; case 'd': b = 10; goto lnumber; case 'o': b = 8; goto lnumber; default: putchar('%', flags, ttyp); putchar('l', flags, ttyp); putchar(c, flags, ttyp); } break; case 'X': b = 16; goto lnumber; case 'D': b = 10; goto lnumber; case 'O': b = 8; lnumber: printn(*(long *)adx, b, flags, ttyp); adx += (sizeof(long) / sizeof(int)) - 1; break; case 'x': b = 16; goto number; case 'd': case 'u': /* what a joke */ b = 10; goto number; case 'o': b = 8; number: printn((long)*adx, b, flags, ttyp); break; case 'c': putchar(*adx, flags, ttyp); break; case 'b': b = *adx++; s = (char *)*adx; printn((long)b, *s++, flags, ttyp); any = 0; if (b) { while (i = *s++) { if (b & (1 << (i - 1))) { putchar(any? ',' : '<', flags, ttyp); any = 1; for (; (c = *s) > 32; s++) putchar(c, flags, ttyp); } else for (; *s > 32; s++) ; } if (any) putchar('>', flags, ttyp); } break; case 's': s = (char *)*adx; while (c = *s++) putchar(c, flags, ttyp); break; case '%': putchar(c, flags, ttyp); break; default: putchar('%', flags, ttyp); putchar(c, flags, ttyp); break; } adx++; goto loop; } /* * Printn prints a number n in base b. * We don't use recursion to avoid deep kernels stacks. */ printn(n, b, flags, ttyp) long n; u_int b; struct tty *ttyp; { char prbuf[12]; register char *cp = prbuf; register int offset = 0; if (n<0) switch(b) { case 8: /* unchecked, but should be like hex case */ case 16: offset = b-1; n++; break; case 10: putchar('-', flags, ttyp); n = -n; break; } do { *cp++ = "0123456789ABCDEF"[offset + n%b]; } while (n = n/b); /* Avoid n /= b, since that requires alrem */ do putchar(*--cp, flags, ttyp); while (cp > prbuf); } /* * Panic is called on unresolvable fatal errors. * It prints "panic: mesg", and then reboots. * If we are called twice, then we avoid trying to * sync the disks as this often leads to recursive panics. */ panic(s) char *s; { int bootopt = RB_AUTOBOOT|RB_DUMP; if (panicstr) bootopt |= RB_NOSYNC; else { panicstr = s; } printf("panic: %s\n", s); boot(rootdev, bootopt); } /* * Warn that a system table is full. */ tablefull(tab) char *tab; { log(LOG_ERR, "%s: table is full\n", tab); } /* * Hard error is the preface to plaintive error messages * about failing disk tranfers. */ harderr(bp, cp) struct buf *bp; char *cp; { printf("%s%d%c: hard error sn%D ", cp, minor(bp->b_dev) >> 3, 'a'+(minor(bp->b_dev) & 07), bp->b_blkno); } /* * Print a character on console or users terminal. * If destination is console then the last MSGBUFS characters * are saved in msgbuf for inspection later. */ putchar(c, flags, tp) register int c; struct tty *tp; { extern char *panicstr; segm s5; if (flags & TOTTY) { register int s = spltty(); if (tp && (tp->t_state & (TS_CARR_ON | TS_ISOPEN)) == (TS_CARR_ON | TS_ISOPEN)) { if (c == '\n') (void) ttyoutput('\r', tp); (void) ttyoutput(c, tp); ttstart(tp); } splx(s); } if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177) { if (msgbuf.msg_magic != MSG_MAGIC) goto docons; saveseg5(s5); mapseg5(msgbuf.msg_click, (btoc(MSG_BSIZE) << 8) | RW); msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) msgbuf.msg_bufx = 0; restorseg5(s5); } docons: if ((flags & TOCONS) && c != '\0') cnputc(c); } ; } if (u.u_fpsaved == 0) { savfp(&u.u_fps); u.u_fpsaved = 1; } longjmp(proc[0].p_addr, &u.u_qsave); } /* * The first save returns nonzero when proc 0 is resumed * by another process (above); then the second is not done * and the process-search loop is entered. * * The first save returns 0 when swtch is called in proc 0 * from sched(). The second save returns 0 immediately, so * in this case too the process-search loop is entered. * Thus when proc sys/sys/ufs_alloc.c 440 0 12 14221 5705125425 7616 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ufs_alloc.c 1.2 (2.11BSD GTE) 1/11/94 */ #include "param.h" #include "../machine/seg.h" #include "fs.h" #include "dir.h" #include "inode.h" #include "buf.h" #include "user.h" #include "kernel.h" #ifdef QUOTA #include "quota.h" #endif typedef struct fblk *FBLKP; /* * Allocate a block in the file system. * * alloc will obtain the next available free disk block from the * free list of the specified device. The super block has up to * NICFREE remembered free blocks; the last of these is read to * obtain NICFREE more... */ struct buf * alloc(ip, clrflg) struct inode *ip; int clrflg; { register struct fs *fs; register struct buf *bp; daddr_t bno; fs = ip->i_fs; while (fs->fs_flock) sleep((caddr_t)&fs->fs_flock, PINOD); do { if (fs->fs_nfree <= 0) goto nospace; if (fs->fs_nfree > NICFREE) { fserr(fs, "bad free count"); goto nospace; } bno = fs->fs_free[--fs->fs_nfree]; if (bno == 0) goto nospace; } while (badblock(fs, bno)); if (fs->fs_nfree <= 0) { fs->fs_flock++; bp = bread(ip->i_dev, bno); if (((bp->b_flags&B_ERROR) == 0) && (bp->b_resid==0)) { register struct fblk *fbp; fbp = (FBLKP) mapin(bp); *((FBLKP)&fs->fs_nfree) = *fbp; mapout(bp); } brelse(bp); /* * Write the superblock back, synchronously, * so that the free list pointer won't point at garbage. * We can still end up with dups in free if we then * use some of the blocks in this freeblock, then crash * without a sync. */ bp = getblk(ip->i_dev, SUPERB); fs->fs_fmod = 0; fs->fs_time = time.tv_sec; { register struct fs *fps; fps = (struct fs *)mapin(bp); *fps = *fs; } mapout(bp); bwrite(bp); fs->fs_flock = 0; wakeup((caddr_t)&fs->fs_flock); if (fs->fs_nfree <=0) goto nospace; } bp = getblk(ip->i_dev, bno); bp->b_resid = 0; if (clrflg) clrbuf(bp); fs->fs_fmod = 1; fs->fs_tfree--; return(bp); nospace: fs->fs_nfree = 0; fs->fs_tfree = 0; fserr(fs, "file system full"); /* * THIS IS A KLUDGE... * SHOULD RATHER SEND A SIGNAL AND SUSPEND THE PROCESS IN A * STATE FROM WHICH THE SYSTEM CALL WILL RESTART */ uprintf("\n%s: write failed, file system full\n", fs->fs_fsmnt); { register int i; for (i = 0; i < 5; i++) sleep((caddr_t)&lbolt, PRIBIO); } u.u_error = ENOSPC; return(NULL); } /* * Allocate an inode in the file system. * * Allocate an unused I node on the specified device. Used with file * creation. The algorithm keeps up to NICINOD spare I nodes in the * super block. When this runs out, a linear search through the I list * is instituted to pick up NICINOD more. */ struct inode * ialloc(pip) struct inode *pip; { register struct fs *fs; register struct buf *bp; register struct inode *ip; int i; struct dinode *dp; ino_t ino; daddr_t adr; ino_t inobas; int first; struct inode *ifind(); char *emsg = "no inodes free"; fs = pip->i_fs; while (fs->fs_ilock) sleep((caddr_t)&fs->fs_ilock, PINOD); #ifdef QUOTA QUOTAMAP(); u.u_error = chkiq(pip->i_dev, NULL, u.u_uid, 0); QUOTAUNMAP(); if (u.u_error) return(NULL); #endif loop: if (fs->fs_ninode > 0) { ino = fs->fs_inode[--fs->fs_ninode]; if (ino <= ROOTINO) goto loop; ip = iget(pip->i_dev, fs, ino); if (ip == NULL) return(NULL); if (ip->i_mode == 0) { bzero((caddr_t)ip->i_addr,sizeof(ip->i_addr)); ip->i_flags = 0; fs->fs_fmod = 1; fs->fs_tinode--; return(ip); } /* * Inode was allocated after all. * Look some more. */ iput(ip); goto loop; } fs->fs_ilock++; if (fs->fs_nbehind < 4 * NICINOD) { first = 1; ino = fs->fs_lasti; #ifdef DIAGNOSTIC if (itoo(ino)) panic("ialloc"); #endif DIAGNOSTIC adr = itod(ino); } else { fromtop: first = 0; ino = 1; adr = SUPERB+1; fs->fs_nbehind = 0; } for (;adr < fs->fs_isize;adr++) { inobas = ino; bp = bread(pip->i_dev, adr); if ((bp->b_flags & B_ERROR) || bp->b_resid) { brelse(bp); ino += INOPB; continue; } dp = (struct dinode *)mapin(bp); for (i = 0;i < INOPB;i++) { if (dp->di_mode != 0) goto cont; if (ifind(pip->i_dev, ino)) goto cont; fs->fs_inode[fs->fs_ninode++] = ino; if (fs->fs_ninode >= NICINOD) break; cont: ino++; dp++; } mapout(bp); brelse(bp); if (fs->fs_ninode >= NICINOD) break; } if (fs->fs_ninode < NICINOD && first) goto fromtop; fs->fs_lasti = inobas; fs->fs_ilock = 0; wakeup((caddr_t)&fs->fs_ilock); if (fs->fs_ninode > 0) goto loop; fserr(fs, emsg); uprintf("\n%s: create/symlink failed, %s\n", fs->fs_fsmnt, emsg); u.u_error = ENOSPC; return(NULL); } /* * Free a block or fragment. * * Place the specified disk block back on the free list of the * specified device. */ free(ip, bno) struct inode *ip; daddr_t bno; { register struct fs *fs; register struct buf *bp; struct fblk *fbp; fs = ip->i_fs; if (badblock(fs, bno)) { printf("bad block %D, ino %d\n", bno, ip->i_number); return; } while (fs->fs_flock) sleep((caddr_t)&fs->fs_flock, PINOD); if (fs->fs_nfree <= 0) { fs->fs_nfree = 1; fs->fs_free[0] = 0; } if (fs->fs_nfree >= NICFREE) { fs->fs_flock++; bp = getblk(ip->i_dev, bno); fbp = (FBLKP)mapin(bp); *fbp = *((FBLKP)&fs->fs_nfree); mapout(bp); fs->fs_nfree = 0; bwrite(bp); fs->fs_flock = 0; wakeup((caddr_t)&fs->fs_flock); } fs->fs_free[fs->fs_nfree++] = bno; fs->fs_tfree++; fs->fs_fmod = 1; } /* * Free an inode. * * Free the specified I node on the specified device. The algorithm * stores up to NICINOD I nodes in the super block and throws away any more. */ ifree(ip, ino) struct inode *ip; ino_t ino; { register struct fs *fs; fs = ip->i_fs; fs->fs_tinode++; if (fs->fs_ilock) return; if (fs->fs_ninode >= NICINOD) { if (fs->fs_lasti > ino) fs->fs_nbehind++; return; } fs->fs_inode[fs->fs_ninode++] = ino; fs->fs_fmod = 1; } /* * Fserr prints the name of a file system with an error diagnostic. * * The form of the error message is: * fs: error message */ fserr(fp, cp) struct fs *fp; char *cp; { printf("%s: %s\n", fp->fs_fsmnt, cp); } break; case 'c': putchar(*adx, flags, ttyp); break; case 'b': b = *adx++; s = (char *)*adx; printn((long)b, *s++, flags, ttyp); any = 0; if (b) { while (i = *s++) { if (b & (1 << (i - 1))) { putchar(any? ',' : '<', flags, ttyp); any = 1; for (; (c = *s) > 32; s++) putchar(c, flags, ttyp); } else for (; *s > 32; ssys/sys/vm_sched.c 440 0 12 17331 5350246013 7435 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)vm_sched.c 1.1 (2.10BSD Berkeley) 12/1/86 */ #include "param.h" #include "user.h" #include "proc.h" #include "text.h" #include "vm.h" #include "kernel.h" #include "systm.h" #define MINFINITY -32767 /* minus infinity */ int maxslp = MAXSLP; /* * The main loop of the scheduling (swapping) process. * The basic idea is: * see if anyone wants to be swapped in * swap out processes until there is room * swap him in * repeat * The runout flag is set whenever someone is swapped out. Sched sleeps on * it awaiting work. Sched sleeps on runin whenever it cannot find enough * core (by swapping out or otherwise) to fit the selected swapped process. * It is awakened when the core situation changes and in any case once per * second. */ sched() { register struct proc *rp; struct proc *p; int inage, maxsize, outpri; /* Find user to swap in; of users ready, select one out longest. */ for (;;) { (void)_splhigh(); { register int l_outpri, rppri; l_outpri = -20000; for (rp = allproc; rp; rp = rp->p_nxt) { if (rp->p_stat != SRUN || rp->p_flag & SLOAD) continue; rppri = rp->p_time - rp->p_nice * 8; /* * Always bring in parents ending a vfork, * to avoid deadlock */ if (rppri > l_outpri || rp->p_flag & SVFPRNT) { p = rp; l_outpri = rppri; if (rp->p_flag & SVFPRNT) break; } } /* If there is no one there, wait. */ if (l_outpri == -20000) { ++runout; sleep((caddr_t)&runout, PSWP); continue; } outpri = l_outpri; } (void)_spl0(); /* See if there is core for that process, if so, swap it in. */ if (swapin(p)) continue; /* * None found. Look around for core: 1) kick out dead wood * (processes asleep longer than maxslp+10); or 2) select out * of the processes sleeping at bad priority the process with * maximum f(size, slptime); or 3) if none, select the oldest. * If we can find someone to swap out we try to swap someone * else (hopefully) in, possibly causing someone else to get * swapped out. * * f(size, slptime) = size + (slptime - maxslp) * 16 * * This weighting is designed to penalize linearly for size * and excessive slptime, but to reward processes which are * executing or have executed recently. */ { register int l_maxsize; (void)_splhigh(); l_maxsize = MINFINITY; inage = -1; for (rp = allproc; rp != NULL; rp = rp->p_nxt) { if (rp->p_stat == SZOMB || (rp->p_flag & (SSYS|SLOCK|SULOCK|SLOAD)) != SLOAD) continue; if (rp->p_textp && rp->p_textp->x_flag & XLOCK) continue; if (rp->p_stat == SSLEEP && rp->p_pri > PZERO || rp->p_stat == SSTOP) { register int size; if (rp->p_slptime > maxslp+10) { p = rp; l_maxsize = 1; break; } size = rp->p_dsize + rp->p_ssize + (rp->p_slptime - maxslp << 4); if (l_maxsize < size) { p = rp; l_maxsize = size; } } else if (l_maxsize == MINFINITY && (rp->p_stat == SRUN || rp->p_stat == SSLEEP)) { register int rppri; rppri = rp->p_time + rp->p_nice; if (rppri > inage) { p = rp; inage = rppri; } } } maxsize = l_maxsize; } (void)_spl0(); noop(); (void)_splhigh(); /* * Swap found user out if sleeping at bad pri, or if he has spent at * least 1 second in core and the swapped-out process has spent at * least 2 seconds out. Otherwise wait a bit and try again. */ if (maxsize != MINFINITY || outpri >= 2 && inage >= 1) { p->p_flag &= ~SLOAD; if (p->p_stat == SRUN) remrq(p); (void)_spl0(); swapout(p, X_FREECORE, X_OLDSIZE, X_OLDSIZE); } else { ++runin; sleep((caddr_t)&runin, PSWP); } } } /* * Count up various things once a second */ vmmeter() { #ifdef UCB_METER register u_short *cp, *rp; register long *sp; ave(avefree, freemem, 5); ave(avefree30, freemem, 30); cp = &cnt.v_first; rp = &rate.v_first; sp = &sum.v_first; while (cp <= &cnt.v_last) { ave(*rp, *cp, 5); *sp += *cp; *cp = 0; rp++, cp++, sp++; } #endif if (time.tv_sec % 5 == 0) { vmtotal(); #ifdef UCB_METER rate.v_swpin = cnt.v_swpin; sum.v_swpin += cnt.v_swpin; cnt.v_swpin = 0; rate.v_swpout = cnt.v_swpout; sum.v_swpout += cnt.v_swpout; cnt.v_swpout = 0; #endif } } vmtotal() { register struct proc *p; register nrun = 0; #ifdef UCB_METER char textcounted[100]; total.t_vmtxt = 0; total.t_avmtxt = 0; total.t_rmtxt = 0; total.t_armtxt = 0; { register struct text *xp; for (xp = text; xp < textNTEXT; xp++) if (xp->x_iptr) { total.t_vmtxt += xp->x_size; if (xp->x_ccount) total.t_rmtxt += xp->x_size; } } total.t_vm = 0; total.t_avm = 0; total.t_rm = 0; total.t_arm = 0; total.t_rq = 0; total.t_dw = 0; total.t_sl = 0; total.t_sw = 0; bzero(textcounted, ntext * sizeof(char)); #endif for (p = allproc; p != NULL; p = p->p_nxt) { if (p->p_flag & SSYS) continue; if (p->p_stat) { #ifdef UCB_METER if (p->p_stat != SZOMB) { total.t_vm += p->p_dsize + p->p_ssize + USIZE; if (p->p_flag & SLOAD) total.t_rm += p->p_dsize + p->p_ssize + USIZE; } #endif switch (p->p_stat) { case SSLEEP: case SSTOP: if (p->p_pri <= PZERO && p->p_stat == SSLEEP) nrun++; #ifdef UCB_METER if (p->p_flag & SLOAD) { if (p->p_pri <= PZERO) total.t_dw++; else if (p->p_slptime < maxslp) total.t_sl++; } else if (p->p_slptime < maxslp) total.t_sw++; if (p->p_slptime < maxslp) goto active; #endif break; case SRUN: case SIDL: nrun++; #ifdef UCB_METER if (p->p_flag & SLOAD) total.t_rq++; else total.t_sw++; active: total.t_avm += p->p_dsize + p->p_ssize + USIZE; if (p->p_flag & SLOAD) total.t_arm += p->p_dsize + p->p_ssize + USIZE; if (p->p_textp) switch (p->p_stat) { case SSTOP: case SSLEEP: if (p->p_slptime >= maxslp) break; /* fall into... */ case SRUN: case SIDL: { register int nt; total.t_avmtxt += p->p_textp->x_size; nt = p->p_textp - text; if (!textcounted[nt]) { textcounted[nt] = 1; if (p->p_textp->x_ccount) total.t_armtxt += p->p_textp->x_size; } } } #endif break; } } } #ifdef UCB_METER total.t_vm += total.t_vmtxt; total.t_avm += total.t_avmtxt; total.t_rm += total.t_rmtxt; total.t_arm += total.t_armtxt; total.t_free = avefree; #endif loadav(avenrun, nrun); } /* * Compute Tenex style load average. This code is adapted from similar code * by Bill Joy on the Vax system. The major change is that we avoid floating * point since not all pdp-11's have it. This makes the code quite hard to * read - it was derived with some algebra. * * "floating point" numbers here are stored in a 16 bit short, with 8 bits on * each side of the decimal point. Some partial products will have 16 bits to * the right. * * The Vax algorithm is: * * /* * * Constants for averages over 1, 5, and 15 minutes * * when sampling at 5 second intervals. * * / * double cexp[3] = { * 0.9200444146293232, /* exp(-1/12) * / * 0.9834714538216174, /* exp(-1/60) * / * 0.9944598480048967, /* exp(-1/180) * / * }; * * /* * * Compute a tenex style load average of a quantity on * * 1, 5 and 15 minute intervals. * * / * loadav(avg, n) * register double *avg; * int n; * { * register int i; * * for (i = 0; i < 3; i++) * avg[i] = cexp[i] * avg[i] + n * (1.0 - cexp[i]); * } */ long cexp[3] = { 0353, /* 256 * exp(-1/12) */ 0373, /* 256 * exp(-1/60) */ 0376, /* 256 * exp(-1/180) */ }; loadav(avg, n) register short *avg; register int n; { register int i; for (i = 0; i < 3; i++) avg[i] = (cexp[i] * (avg[i]-(n<<8)) + (((long)n)<<16)) >> 8; } s, if so, swap it in. */ if (swapin(p)) continue; /* * None found. Look around for core: 1) kick out dead wood * (processes asleep longer than maxslp+10); or 2) select out * of the processes sleeping at bad priority the process with * maximum f(size, slptime); or 3) if none, selecsys/sys/syscalls.c 440 0 12 13001 5753577424 7514 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)syscalls.c 1.5 (2.11BSD GTE) 1995/05/08 */ /* * System call names. */ #ifndef pdp11 char *syscallnames[] = { "indir", /* 0 = indir */ "exit", /* 1 = exit */ "fork", /* 2 = fork */ "read", /* 3 = read */ "write", /* 4 = write */ "open", /* 5 = open */ "close", /* 6 = close */ "old wait - nosys", /* 7 = old wait */ "creat", /* 8 = creat */ "link", /* 9 = link */ "unlink", /* 10 = unlink */ "execv", /* 11 = execv */ "chdir", /* 12 = chdir */ "fchdir", /* 13 = fchdir */ "mknod", /* 14 = mknod */ "chmod", /* 15 = chmod */ "chown", /* 16 = chown; now 3 args */ "chflags", /* 17 = chflags */ "fchflags", /* 18 = fchflags */ "lseek", /* 19 = lseek */ "getpid", /* 20 = getpid */ "mount", /* 21 = mount */ "umount", /* 22 = umount */ "old setuid - nosys", /* 23 = old setuid */ "getuid", /* 24 = getuid */ "geteuid", /* 25 = geteuid */ "ptrace", /* 26 = ptrace */ "getppid", /* 27 = getppid */ "old fstat - nosys", /* 28 = old fstat */ "old pause", /* 29 = old pause */ "old utime - nosys", /* 30 = old utime */ "old stty - nosys", /* 31 = old stty */ "old gtty - nosys", /* 32 = old gtty */ "access", /* 33 = access */ "old nice - nosys", /* 34 = old nice */ "old ftime - nosys", /* 35 = old ftime */ "sync", /* 36 = sync */ "kill", /* 37 = kill */ "stat", /* 38 = stat */ "old setpgrp - nosys", /* 39 = old setpgrp */ "lstat", /* 40 = lstat */ "dup", /* 41 = dup */ "pipe", /* 42 = pipe */ "old times - nosys", /* 43 = old times */ "profil", /* 44 = profil */ "#45", /* 45 = nosys */ "old setgid - nosys", /* 46 = old setgid */ "getgid", /* 47 = getgid */ "getegid", /* 48 = getegid */ "#49", /* 49 = reserved for USG */ "#50", /* 50 = reserved for USG */ "acct", /* 51 = turn acct off/on */ "old phys", /* 52 = old set phys addr */ "old lock", /* 53 = old lock in core */ "ioctl", /* 54 = ioctl */ "reboot", /* 55 = reboot */ "old mpx - nosys", /* 56 = old mpxchan */ "symlink", /* 57 = symlink */ "readlink", /* 58 = readlink */ "execve", /* 59 = execve */ "umask", /* 60 = umask */ "chroot", /* 61 = chroot */ "fstat", /* 62 = fstat */ "#63", /* 63 = used internally */ "getpagesize", /* 64 = getpagesize */ "4.3 mremap - nosys", /* 65 = mremap */ "vfork", /* 66 = vfork */ "old vread - nosys", /* 67 = old vread */ "old vwrite - nosys", /* 68 = old vwrite */ "sbrk", /* 69 = sbrk */ "4.3 sstk - nosys", /* 70 = sstk */ "4.3 mmap - nosys", /* 71 = mmap */ "old vadvise - nosys", /* 72 = old vadvise */ "4.3 munmap - nosys", /* 73 = munmap */ "4.3 mprotect - nosys", /* 74 = mprotect */ "4.3 madvise - nosys", /* 75 = madvise */ "vhangup", /* 76 = vhangup */ "old vlimit - nosys", /* 77 = old vlimit */ "4.3 mincore - nosys", /* 78 = mincore */ "getgroups", /* 79 = getgroups */ "setgroups", /* 80 = setgroups */ "getpgrp", /* 81 = getpgrp */ "setpgrp", /* 82 = setpgrp */ "setitimer", /* 83 = setitimer */ "wait", /* 84 = wait */ "4.3 swapon - nosys", /* 85 = swapon */ "getitimer", /* 86 = getitimer */ "gethostname", /* 87 = gethostname */ "sethostname", /* 88 = sethostname */ "getdtablesize", /* 89 = getdtablesize */ "dup2", /* 90 = dup2 */ "nosys", /* 91 = unused */ "fcntl", /* 92 = fcntl */ "select", /* 93 = select */ "nosys", /* 94 = unused */ "fsync", /* 95 = fsync */ "setpriority", /* 96 = setpriority */ "socket", /* 97 = socket */ "connect", /* 98 = connect */ "accept", /* 99 = accept */ "getpriority", /* 100 = getpriority */ "send", /* 101 = send */ "recv", /* 102 = recv */ "sigreturn", /* 103 = sigreturn */ "bind", /* 104 = bind */ "setsockopt", /* 105 = setsockopt */ "listen", /* 106 = listen */ "old vtimes - nosys", /* 107 = old vtimes */ "sigvec", /* 108 = sigvec */ "sigblock", /* 109 = sigblock */ "sigsetmask", /* 110 = sigsetmask */ "sigpause", /* 111 = sigpause */ "sigstack", /* 112 = sigstack */ "recvmsg", /* 113 = recvmsg */ "sendmsg", /* 114 = sendmsg */ "old vtrace - nosys", /* 115 = old vtrace */ "gettimeofday", /* 116 = gettimeofday */ "getrusage", /* 117 = getrusage */ "getsockopt", /* 118 = getsockopt */ "4.3 resuba - nosys", /* 119 = resuba */ "readv", /* 120 = readv */ "writev", /* 121 = writev */ "settimeofday", /* 122 = settimeofday */ "fchown", /* 123 = fchown */ "fchmod", /* 124 = fchmod */ "recvfrom", /* 125 = recvfrom */ "setreuid", /* 126 = setreuid */ "setregid", /* 127 = setregid */ "rename", /* 128 = rename */ "truncate", /* 129 = truncate */ "ftruncate", /* 130 = ftruncate */ "flock", /* 131 = flock */ "old portal - nosys", /* 132 = old portal */ "sendto", /* 133 = sendto */ "shutdown", /* 134 = shutdown */ "socketpair", /* 135 = socketpair */ "mkdir", /* 136 = mkdir */ "rmdir", /* 137 = rmdir */ "utimes", /* 138 = utimes */ "4.2 sigreturn - nosys", /* 139 = old 4.2 sigreturn */ "adjtime", /* 140 = adjtime */ "getpeername", /* 141 = getpeername */ "gethostid", /* 142 = gethostid */ "sethostid", /* 143 = sethostid */ "getrlimit", /* 144 = getrlimit */ "setrlimit", /* 145 = setrlimit */ "killpg", /* 146 = killpg */ "#147", /* 147 = nosys */ "setquota", /* 148 = setquota */ "quota", /* 149 = quota */ "getsockname", /* 150 = getsockname */ }; #endif ; case SRUN: case SIDL: nrun++; #ifdef UCB_METER if (p->p_flag & SLOAD) total.t_rq++; else total.t_sw++; active: total.t_avm += p->p_dsize + p->p_ssize + USIZE; if (p->p_flag & SLOAD) total.t_arm += p->p_dsize + p->p_ssize + USIZE; if (p->p_textp) switch (p->p_stat) { case SSTOP: case SSLEEP: if (p->p_slptime >= maxslp) break; /* fall into... */ case SRUN: case SIDL: { register int nt; total.t_avmtxt += p->p_sys/sys/ufs_bio.c 640 0 12 24523 5321523625 7303 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ufs_bio.c 2.1 (2.11BSD) 12/26/92 */ #include "param.h" #include "buf.h" #include "user.h" #include "conf.h" #include "fs.h" #include "dk.h" #include "systm.h" #include "map.h" #include "uba.h" #include "trace.h" #include "ram.h" /* * Read in (if necessary) the block and return a buffer pointer. */ struct buf * bread(dev, blkno) dev_t dev; daddr_t blkno; { register struct buf *bp; bp = getblk(dev, blkno); if (bp->b_flags&(B_DONE|B_DELWRI)) { trace(TR_BREADHIT); return (bp); } bp->b_flags |= B_READ; bp->b_bcount = DEV_BSIZE; /* XXX? KB */ (*bdevsw[major(dev)].d_strategy)(bp); trace(TR_BREADMISS); u.u_ru.ru_inblock++; /* pay for read */ biowait(bp); return(bp); } /* * Read in the block, like bread, but also start I/O on the * read-ahead block (which is not allocated to the caller) */ struct buf * breada(dev, blkno, rablkno) register dev_t dev; daddr_t blkno; daddr_t rablkno; { register struct buf *bp, *rabp; bp = NULL; /* * If the block isn't in core, then allocate * a buffer and initiate i/o (getblk checks * for a cache hit). */ if (!incore(dev, blkno)) { bp = getblk(dev, blkno); if ((bp->b_flags&(B_DONE|B_DELWRI)) == 0) { bp->b_flags |= B_READ; bp->b_bcount = DEV_BSIZE; /* XXX? KB */ (*bdevsw[major(dev)].d_strategy)(bp); trace(TR_BREADMISS); u.u_ru.ru_inblock++; /* pay for read */ } else trace(TR_BREADHIT); } /* * If there's a read-ahead block, start i/o * on it also (as above). */ if (rablkno) { if (!incore(dev, rablkno)) { rabp = getblk(dev, rablkno); if (rabp->b_flags & (B_DONE|B_DELWRI)) { brelse(rabp); trace(TR_BREADHITRA); } else { rabp->b_flags |= B_READ|B_ASYNC; rabp->b_bcount = DEV_BSIZE; /* XXX? KB */ (*bdevsw[major(dev)].d_strategy)(rabp); trace(TR_BREADMISSRA); u.u_ru.ru_inblock++; /* pay in advance */ } } else trace(TR_BREADHITRA); } /* * If block was in core, let bread get it. * If block wasn't in core, then the read was started * above, and just wait for it. */ if (bp == NULL) return (bread(dev, blkno)); biowait(bp); return (bp); } /* * Write the buffer, waiting for completion. * Then release the buffer. */ bwrite(bp) register struct buf *bp; { register flag; flag = bp->b_flags; bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI); if ((flag&B_DELWRI) == 0) u.u_ru.ru_oublock++; /* noone paid yet */ trace(TR_BWRITE); bp->b_bcount = DEV_BSIZE; /* XXX? KB */ (*bdevsw[major(bp->b_dev)].d_strategy)(bp); /* * If the write was synchronous, then await i/o completion. * If the write was "delayed", then we put the buffer on * the q of blocks awaiting i/o completion status. */ if ((flag&B_ASYNC) == 0) { biowait(bp); brelse(bp); } else if (flag & B_DELWRI) bp->b_flags |= B_AGE; } /* * Release the buffer, marking it so that if it is grabbed * for another purpose it will be written out before being * given up (e.g. when writing a partial block where it is * assumed that another write for the same block will soon follow). * This can't be done for magtape, since writes must be done * in the same order as requested. */ bdwrite(bp) register struct buf *bp; { if ((bp->b_flags&B_DELWRI) == 0) u.u_ru.ru_oublock++; /* noone paid yet */ if (bdevsw[major(bp->b_dev)].d_flags & B_TAPE) { bawrite(bp); } else { bp->b_flags |= B_DELWRI | B_DONE; brelse(bp); } } /* * Release the buffer, with no I/O implied. */ brelse(bp) register struct buf *bp; { register struct buf *flist; register s; trace(TR_BRELSE); /* * If someone's waiting for the buffer, or * is waiting for a buffer, wake 'em up. */ if (bp->b_flags&B_WANTED) wakeup((caddr_t)bp); if (bfreelist[0].b_flags&B_WANTED) { bfreelist[0].b_flags &= ~B_WANTED; wakeup((caddr_t)bfreelist); } if (bp->b_flags&B_ERROR) if (bp->b_flags & B_LOCKED) bp->b_flags &= ~B_ERROR; /* try again later */ else bp->b_dev = NODEV; /* no assoc */ /* * Stick the buffer back on a free list. */ s = splbio(); if (bp->b_flags & (B_ERROR|B_INVAL)) { /* block has no info ... put at front of most free list */ flist = &bfreelist[BQ_AGE]; binsheadfree(bp, flist); } else { if (bp->b_flags & B_LOCKED) flist = &bfreelist[BQ_LOCKED]; else if (bp->b_flags & B_AGE) flist = &bfreelist[BQ_AGE]; else flist = &bfreelist[BQ_LRU]; binstailfree(bp, flist); } bp->b_flags &= ~(B_WANTED|B_BUSY|B_ASYNC|B_AGE); splx(s); } /* * See if the block is associated with some buffer * (mainly to avoid getting hung up on a wait in breada) */ incore(dev, blkno) register dev_t dev; daddr_t blkno; { register struct buf *bp; register struct buf *dp; dp = BUFHASH(dev, blkno); blkno = fsbtodb(blkno); for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) if (bp->b_blkno == blkno && bp->b_dev == dev && (bp->b_flags & B_INVAL) == 0) return (1); return (0); } /* * Assign a buffer for the given block. If the appropriate * block is already associated, return it; otherwise search * for the oldest non-busy buffer and reassign it. * * We use splx here because this routine may be called * on the interrupt stack during a dump, and we don't * want to lower the ipl back to 0. */ struct buf * getblk(dev, blkno) register dev_t dev; daddr_t blkno; { register struct buf *bp, *dp; daddr_t dblkno; int s; #ifdef DIAGNOSTIC if (major(dev) >= nblkdev) panic("blkdev"); #endif /* * Search the cache for the block. If we hit, but * the buffer is in use for i/o, then we wait until * the i/o has completed. */ dp = BUFHASH(dev, blkno); dblkno = fsbtodb(blkno); loop: for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) { if (bp->b_blkno != dblkno || bp->b_dev != dev || bp->b_flags&B_INVAL) continue; s = splbio(); if (bp->b_flags&B_BUSY) { bp->b_flags |= B_WANTED; sleep((caddr_t)bp, PRIBIO+1); splx(s); goto loop; } splx(s); notavail(bp); return (bp); } bp = getnewbuf(); bfree(bp); bremhash(bp); binshash(bp, dp); bp->b_dev = dev; bp->b_blkno = dblkno; bp->b_error = 0; return (bp); } /* * get an empty block, * not assigned to any particular device */ struct buf * geteblk() { register struct buf *bp, *flist; bp = getnewbuf(); bp->b_flags |= B_INVAL; bfree(bp); bremhash(bp); flist = &bfreelist[BQ_AGE]; binshash(bp, flist); bp->b_dev = (dev_t)NODEV; bp->b_error = 0; return (bp); } /* * Find a buffer which is available for use. * Select something from a free list. * Preference is to AGE list, then LRU list. */ struct buf * getnewbuf() { register struct buf *bp, *dp; int s; loop: s = splbio(); for (dp = &bfreelist[BQ_AGE]; dp > bfreelist; dp--) if (dp->av_forw != dp) break; if (dp == bfreelist) { /* no free blocks */ dp->b_flags |= B_WANTED; sleep((caddr_t)dp, PRIBIO+1); splx(s); goto loop; } splx(s); bp = dp->av_forw; notavail(bp); if (bp->b_flags & B_DELWRI) { bp->b_flags |= B_ASYNC; bwrite(bp); goto loop; } if(bp->b_flags & (B_RAMREMAP|B_PHYS)) { register memaddr paddr; /* click address of real buffer */ extern memaddr bpaddr; #ifdef DIAGNOSTIC if ((bp < &buf[0]) || (bp >= &buf[nbuf])) panic("getnewbuf: RAMREMAP bp addr"); #endif paddr = bpaddr + btoc(DEV_BSIZE) * (bp - buf); bp->b_un.b_addr = (caddr_t)(paddr << 6); bp->b_xmem = (paddr >> 10) & 077; } trace(TR_BRELSE); bp->b_flags = B_BUSY; return (bp); } /* * Wait for I/O completion on the buffer; return errors * to the user. */ biowait(bp) register struct buf *bp; { register int s; s = splbio(); while ((bp->b_flags&B_DONE)==0) sleep((caddr_t)bp, PRIBIO); splx(s); if (!u.u_error) /* XXX */ u.u_error = geterror(bp); } /* * Mark I/O complete on a buffer. * Wake up anyone waiting for it. */ biodone(bp) register struct buf *bp; { if (bp->b_flags & B_DONE) panic("dup biodone"); if (bp->b_flags & (B_MAP|B_UBAREMAP)) mapfree(bp); bp->b_flags |= B_DONE; if (bp->b_flags&B_ASYNC) brelse(bp); else { bp->b_flags &= ~B_WANTED; wakeup((caddr_t)bp); } } /* * Insure that no part of a specified block is in an incore buffer. */ blkflush(dev, blkno) register dev_t dev; daddr_t blkno; { register struct buf *ep; struct buf *dp; register int s; dp = BUFHASH(dev, blkno); blkno = fsbtodb(blkno); loop: for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) { if (ep->b_blkno != blkno || ep->b_dev != dev || (ep->b_flags&B_INVAL)) continue; s = splbio(); if (ep->b_flags&B_BUSY) { ep->b_flags |= B_WANTED; sleep((caddr_t)ep, PRIBIO+1); splx(s); goto loop; } if (ep->b_flags & B_DELWRI) { splx(s); notavail(ep); bwrite(ep); goto loop; } splx(s); } } /* * Make sure all write-behind blocks * on dev (or NODEV for all) * are flushed out. * (from umount and update) */ bflush(dev) register dev_t dev; { register struct buf *bp; register struct buf *flist; int s; loop: s = splbio(); for (flist = bfreelist; flist < &bfreelist[BQ_EMPTY]; flist++) for (bp = flist->av_forw; bp != flist; bp = bp->av_forw) { if ((bp->b_flags & B_DELWRI) == 0) continue; if (dev == NODEV || dev == bp->b_dev) { bp->b_flags |= B_ASYNC; notavail(bp); bwrite(bp); splx(s); goto loop; } } splx(s); } /* * Pick up the device's error number and pass it to the user; * if there is an error but the number is 0 set a generalized code. */ geterror(bp) register struct buf *bp; { register int error = 0; if (bp->b_flags&B_ERROR) if ((error = bp->b_error)==0) return(EIO); return (error); } /* * Invalidate in core blocks belonging to closed or umounted filesystem * * This is not nicely done at all - the buffer ought to be removed from the * hash chains & have its dev/blkno fields clobbered, but unfortunately we * can't do that here, as it is quite possible that the block is still * being used for i/o. Eventually, all disc drivers should be forced to * have a close routine, which ought ensure that the queue is empty, then * properly flush the queues. Until that happy day, this suffices for * correctness. ... kre */ binval(dev) register dev_t dev; { register struct buf *bp; register struct bufhd *hp; #define dp ((struct buf *)hp) for (hp = bufhash; hp < &bufhash[BUFHSZ]; hp++) for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) if (bp->b_dev == dev) bp->b_flags |= B_INVAL; } ntinue; /* == ignore */ default: goto send; } /*NOTREACHED*/ case SIG_HOLD: case SIG_IGN: /* * Masking above should prevent us * ever trying tsys/sys/tty_pty.c 440 0 12 30164 5671755545 7405 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)tty_pty.c 1.2 (2.11BSD GTE) 12/8/94 */ /* * Pseudo-teletype Driver * (Actually two drivers, requiring two entries in 'cdevsw') */ #include "pty.h" #if NPTY > 0 #include "param.h" #include "systm.h" #include "ioctl.h" #include "tty.h" #include "user.h" #include "conf.h" #include "file.h" #include "proc.h" #include "uio.h" #include "kernel.h" #include "inode.h" #if NPTY == 1 #undef NPTY #define NPTY 16 /* crude XXX */ #endif #define BUFSIZ 100 /* Chunk size iomoved to/from user */ /* * pts == /dev/tty[pqrs]? * ptc == /dev/pty[pqrs]? */ struct tty pt_tty[NPTY]; struct pt_ioctl { int pt_flags; struct proc *pt_selr, *pt_selw; u_char pt_send; u_char pt_ucntl; } pt_ioctl[NPTY]; int npty = NPTY; /* for pstat -t */ #define PF_RCOLL 0x01 #define PF_WCOLL 0x02 #define PF_PKT 0x08 /* packet mode */ #define PF_STOPPED 0x10 /* user told stopped */ #define PF_REMOTE 0x20 /* remote and flow controlled input */ #define PF_NOSTOP 0x40 #define PF_UCNTL 0x80 /* user control mode */ /*ARGSUSED*/ ptsopen(dev, flag) dev_t dev; { register struct tty *tp; int error; #ifdef lint npty = npty; #endif if (minor(dev) >= NPTY) return (ENXIO); tp = &pt_tty[minor(dev)]; if ((tp->t_state & TS_ISOPEN) == 0) { ttychars(tp); /* Set up default chars */ tp->t_ispeed = tp->t_ospeed = EXTB; tp->t_flags = 0; /* No features (nor raw mode) */ } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) return (EBUSY); if (tp->t_oproc) /* Ctrlr still around. */ tp->t_state |= TS_CARR_ON; while ((tp->t_state & TS_CARR_ON) == 0) { tp->t_state |= TS_WOPEN; sleep((caddr_t)&tp->t_rawq, TTIPRI); } error = (*linesw[tp->t_line].l_open)(dev, tp); ptcwakeup(tp, FREAD|FWRITE); return (error); } ptsclose(dev, flag) dev_t dev; int flag; { register struct tty *tp; tp = &pt_tty[minor(dev)]; (*linesw[tp->t_line].l_close)(tp, flag); ttyclose(tp); ptcwakeup(tp, FREAD|FWRITE); } ptsread(dev, uio, flag) dev_t dev; register struct uio *uio; int flag; { register struct tty *tp = &pt_tty[minor(dev)]; register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; int error = 0; again: if (pti->pt_flags & PF_REMOTE) { while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) { if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || u.u_procp->p_flag&SVFORK) return (EIO); gsignal(u.u_procp->p_pgrp, SIGTTIN); sleep((caddr_t)&lbolt, TTIPRI); } if (tp->t_canq.c_cc == 0) { if (flag & IO_NDELAY) return (EWOULDBLOCK); sleep((caddr_t)&tp->t_canq, TTIPRI); goto again; } while (tp->t_canq.c_cc > 1 && uio->uio_resid) if (ureadc(getc(&tp->t_canq), uio) < 0) { error = EFAULT; break; } if (tp->t_canq.c_cc == 1) (void) getc(&tp->t_canq); if (tp->t_canq.c_cc) return (error); } else if (tp->t_oproc) error = (*linesw[tp->t_line].l_read)(tp, uio, flag); ptcwakeup(tp, FWRITE); return (error); } /* * Write to pseudo-tty. * Wakeups of controlling tty will happen * indirectly, when tty driver calls ptsstart. */ ptswrite(dev, uio, flag) dev_t dev; register struct uio *uio; int flag; { register struct tty *tp; tp = &pt_tty[minor(dev)]; if (tp->t_oproc == 0) return (EIO); return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); } /* * Start output on pseudo-tty. * Wake up process selecting or sleeping for input from controlling tty. */ ptsstart(tp) struct tty *tp; { register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; if (tp->t_state & TS_TTSTOP) return; if (pti->pt_flags & PF_STOPPED) { pti->pt_flags &= ~PF_STOPPED; pti->pt_send = TIOCPKT_START; } ptcwakeup(tp, FREAD); } ptcwakeup(tp, flag) struct tty *tp; { struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; if (flag & FREAD) { if (pti->pt_selr) { selwakeup(pti->pt_selr, (long)(pti->pt_flags & PF_RCOLL)); pti->pt_selr = 0; pti->pt_flags &= ~PF_RCOLL; } wakeup((caddr_t)&tp->t_outq.c_cf); } if (flag & FWRITE) { if (pti->pt_selw) { selwakeup(pti->pt_selw, (long)(pti->pt_flags & PF_WCOLL)); pti->pt_selw = 0; pti->pt_flags &= ~PF_WCOLL; } wakeup((caddr_t)&tp->t_rawq.c_cf); } } /*ARGSUSED*/ ptcopen(dev, flag) dev_t dev; int flag; { register struct tty *tp; struct pt_ioctl *pti; if (minor(dev) >= NPTY) return (ENXIO); tp = &pt_tty[minor(dev)]; if (tp->t_oproc) return (EIO); tp->t_oproc = ptsstart; (void)(*linesw[tp->t_line].l_modem)(tp, 1); pti = &pt_ioctl[minor(dev)]; pti->pt_flags = 0; pti->pt_send = 0; pti->pt_ucntl = 0; return (0); } ptcclose(dev, flag) dev_t dev; int flag; { register struct tty *tp; tp = &pt_tty[minor(dev)]; (void)(*linesw[tp->t_line].l_modem)(tp, 0); tp->t_state &= ~TS_CARR_ON; tp->t_oproc = 0; /* mark closed */ } ptcread(dev, uio, flag) dev_t dev; register struct uio *uio; int flag; { register struct tty *tp = &pt_tty[minor(dev)]; struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; char buf[BUFSIZ]; int error = 0, cc; /* * We want to block until the slave * is open, and there's something to read; * but if we lost the slave or we're NBIO, * then return the appropriate error instead. */ for (;;) { if (tp->t_state&TS_ISOPEN) { if (pti->pt_flags&PF_PKT && pti->pt_send) { error = ureadc((int)pti->pt_send, uio); if (error) return (error); pti->pt_send = 0; return (0); } if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { error = ureadc((int)pti->pt_ucntl, uio); if (error) return (error); pti->pt_ucntl = 0; return (0); } if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) break; } if ((tp->t_state&TS_CARR_ON) == 0) return (0); /* EOF */ if (flag & IO_NDELAY) return (EWOULDBLOCK); sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); } if (pti->pt_flags & (PF_PKT|PF_UCNTL)) error = ureadc(0, uio); while (uio->uio_resid && error == 0) { cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ)); if (cc <= 0) break; error = uiomove(buf, cc, uio); } if (tp->t_outq.c_cc <= TTLOWAT(tp)) { if (tp->t_state&TS_ASLEEP) { tp->t_state &= ~TS_ASLEEP; wakeup((caddr_t)&tp->t_outq); } if (tp->t_wsel) { selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); tp->t_wsel = 0; tp->t_state &= ~TS_WCOLL; } } return (error); } ptsstop(tp, flush) register struct tty *tp; int flush; { struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; int flag; /* note: FLUSHREAD and FLUSHWRITE already ok */ if (flush == 0) { flush = TIOCPKT_STOP; pti->pt_flags |= PF_STOPPED; } else pti->pt_flags &= ~PF_STOPPED; pti->pt_send |= flush; /* change of perspective */ flag = 0; if (flush & FREAD) flag |= FWRITE; if (flush & FWRITE) flag |= FREAD; ptcwakeup(tp, flag); } ptcselect(dev, rw) dev_t dev; int rw; { register struct tty *tp = &pt_tty[minor(dev)]; struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; struct proc *p; int s; if ((tp->t_state&TS_CARR_ON) == 0) return (1); switch (rw) { case FREAD: /* * Need to block timeouts (ttrstart). */ s = spltty(); if ((tp->t_state&TS_ISOPEN) && tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) { splx(s); return (1); } splx(s); /* FALLTHROUGH */ case 0: /* exceptional */ if ((tp->t_state&TS_ISOPEN) && (pti->pt_flags&PF_PKT && pti->pt_send || pti->pt_flags&PF_UCNTL && pti->pt_ucntl)) return (1); if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait) pti->pt_flags |= PF_RCOLL; else pti->pt_selr = u.u_procp; break; case FWRITE: if (tp->t_state&TS_ISOPEN) { if (pti->pt_flags & PF_REMOTE) { if (tp->t_canq.c_cc == 0) return (1); } else { if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) return (1); if (tp->t_canq.c_cc == 0 && (tp->t_flags & (RAW|CBREAK)) == 0) return (1); } } if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait) pti->pt_flags |= PF_WCOLL; else pti->pt_selw = u.u_procp; break; } return (0); } ptcwrite(dev, uio, flag) dev_t dev; register struct uio *uio; int flag; { register struct tty *tp = &pt_tty[minor(dev)]; register char *cp; register int cc = 0; char locbuf[BUFSIZ]; int cnt = 0; struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; int error = 0; again: if ((tp->t_state&TS_ISOPEN) == 0) goto block; if (pti->pt_flags & PF_REMOTE) { if (tp->t_canq.c_cc) goto block; while (uio->uio_resid && tp->t_canq.c_cc < TTYHOG - 1) { if (cc == 0) { cc = MIN(uio->uio_resid, BUFSIZ); cc = MIN(cc, TTYHOG - 1 - tp->t_canq.c_cc); cp = locbuf; error = uiomove(cp, cc, uio); if (error) return (error); /* check again for safety */ if ((tp->t_state&TS_ISOPEN) == 0) return (EIO); } if (cc) (void) b_to_q(cp, cc, &tp->t_canq); cc = 0; } (void) putc(0, &tp->t_canq); ttwakeup(tp); wakeup((caddr_t)&tp->t_canq); return (0); } while (uio->uio_resid > 0) { if (cc == 0) { cc = MIN(uio->uio_resid, BUFSIZ); cp = locbuf; error = uiomove(cp, cc, uio); if (error) return (error); /* check again for safety */ if ((tp->t_state&TS_ISOPEN) == 0) return (EIO); } while (cc > 0) { if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && (tp->t_canq.c_cc > 0 || tp->t_flags & (RAW|CBREAK))) { wakeup((caddr_t)&tp->t_rawq); goto block; } (*linesw[tp->t_line].l_rint)(*cp++, tp); cnt++; cc--; } cc = 0; } return (0); block: /* * Come here to wait for slave to open, for space * in outq, or space in rawq. */ if ((tp->t_state&TS_CARR_ON) == 0) return (EIO); if (flag & IO_NDELAY) { /* adjust for data copied in but not written */ uio->uio_resid += cc; if (cnt == 0) return (EWOULDBLOCK); return (0); } sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI); goto again; } /*ARGSUSED*/ ptyioctl(dev, cmd, data, flag) caddr_t data; u_int cmd; dev_t dev; int flag; { register struct tty *tp = &pt_tty[minor(dev)]; register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; int stop, error; extern ttyinput(); /* * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. * ttywflush(tp) will hang if there are characters in the outq. */ if (cdevsw[major(dev)].d_open == ptcopen) switch (cmd) { case TIOCPKT: if (*(int *)data) { if (pti->pt_flags & PF_UCNTL) return (EINVAL); pti->pt_flags |= PF_PKT; } else pti->pt_flags &= ~PF_PKT; return (0); case TIOCUCNTL: if (*(int *)data) { if (pti->pt_flags & PF_PKT) return (EINVAL); pti->pt_flags |= PF_UCNTL; } else pti->pt_flags &= ~PF_UCNTL; return (0); case TIOCREMOTE: if (*(int *)data) pti->pt_flags |= PF_REMOTE; else pti->pt_flags &= ~PF_REMOTE; ttyflush(tp, FREAD|FWRITE); return (0); case TIOCSETP: case TIOCSETN: case TIOCSETD: while (getc(&tp->t_outq) >= 0) ; break; } /* * Unsure if the comment below still applies or not. For now put the * new code in ifdef'd out. */ #ifdef four_four_bsd error = (*linesw[t->t_line].l_ioctl(tp, cmd, data, flag); if (error < 0) error = ttioctl(tp, cmd, data, flag); #else error = ttioctl(tp, cmd, data, flag); /* * Since we use the tty queues internally, * pty's can't be switched to disciplines which overwrite * the queues. We can't tell anything about the discipline * from here... */ if (linesw[tp->t_line].l_rint != ttyinput) { (*linesw[tp->t_line].l_close)(tp, flag); tp->t_line = 0; (void)(*linesw[tp->t_line].l_open)(dev, tp); error = ENOTTY; } #endif if (error < 0) { if (pti->pt_flags & PF_UCNTL && (cmd & ~0xff) == UIOCCMD(0)) { if (cmd & 0xff) { pti->pt_ucntl = (u_char)cmd; ptcwakeup(tp, FREAD); } return (0); } error = ENOTTY; } stop = (tp->t_flags & RAW) == 0 && tp->t_stopc == CTRL(s) && tp->t_startc == CTRL(q); if (pti->pt_flags & PF_NOSTOP) { if (stop) { pti->pt_send &= ~TIOCPKT_NOSTOP; pti->pt_send |= TIOCPKT_DOSTOP; pti->pt_flags &= ~PF_NOSTOP; ptcwakeup(tp, FREAD); } } else { if (!stop) { pti->pt_send &= ~TIOCPKT_DOSTOP; pti->pt_send |= TIOCPKT_NOSTOP; pti->pt_flags |= PF_NOSTOP; ptcwakeup(tp, FREAD); } } return (error); } #endif uio; int flag; { register struct tty *tp = &pt_tty[minor(dev)]; register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; int error = 0; again: if (pti->pt_flags & PF_REMOTE) { while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) { if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || u.u_procp->p_flag&SVFORK) return (EIOsys/sys/vm_text.c 640 0 12 20243 5666032602 7340 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)vm_text.c 1.2 (2.11BSD GTE) 11/26/94 */ #include "param.h" #include "../machine/seg.h" #include "map.h" #include "user.h" #include "proc.h" #include "text.h" #include "inode.h" #include "buf.h" #include "uio.h" #include "systm.h" #define X_LOCK(xp) { \ while ((xp)->x_flag & XLOCK) { \ (xp)->x_flag |= XWANT; \ sleep((caddr_t)(xp), PSWP); \ } \ (xp)->x_flag |= XLOCK; \ } #define XUNLOCK(xp) { \ if ((xp)->x_flag & XWANT) \ wakeup((caddr_t)(xp)); \ (xp)->x_flag &= ~(XLOCK|XWANT); \ } #define FREE_AT_HEAD(xp) { \ (xp)->x_forw = xhead; \ xhead = (xp); \ (xp)->x_back = &xhead; \ if (xtail == &xhead) \ xtail = &(xp)->x_forw; \ else \ (xp)->x_forw->x_back = &(xp)->x_forw; \ } #define FREE_AT_TAIL(xp) { \ (xp)->x_back = xtail; \ *xtail = (xp); \ xtail = &(xp)->x_forw; \ /* x_forw is NULL */ \ } #define ALLOC(xp) { \ *((xp)->x_back) = (xp)->x_forw; \ if ((xp)->x_forw) \ (xp)->x_forw->x_back = (xp)->x_back; \ else \ xtail = (xp)->x_back; \ (xp)->x_forw = NULL; \ (xp)->x_back = NULL; \ } /* * We place free text table entries on a free list. * All text images are treated as "sticky," * and are placed on the free list (as an LRU cache) when unused. * They may be reclaimed from the free list until reused. * Files marked sticky are locked into the table, and are never freed. */ struct text *xhead, **xtail; /* text table free list */ #ifdef UCB_METER struct xstats xstats; /* cache statistics */ #endif /* * initialize text table */ xinit() { register struct text *xp; xtail = &xhead; for (xp = text; xp < textNTEXT; xp++) FREE_AT_TAIL(xp); } /* * Decrement loaded reference count of text object. If not sticky and * count of zero, attach to LRU cache, at the head if traced or the * inode has a hard link count of zero, otherwise at the tail. */ xfree() { register struct text *xp; if ((xp = u.u_procp->p_textp) == NULL) return; #ifdef UCB_METER xstats.free++; #endif X_LOCK(xp); /* * Don't add the following test to the "if" below: * * (xp->x_iptr->i_mode & ISVTX) == 0 * * all text under 2.10 is sticky in an LRU cache. Putting the * above test in makes sticky text objects ``gluey'' and nearly * impossible to flush from memory. */ if (--xp->x_count == 0) { if (xp->x_flag & XTRC || xp->x_iptr->i_nlink == 0) { xp->x_flag &= ~XLOCK; xuntext(xp); FREE_AT_HEAD(xp); } else { #ifdef UCB_METER if (xp->x_flag & XWRIT) { xstats.free_cacheswap++; xp->x_flag |= XUNUSED; } xstats.free_cache++; #endif --xp->x_ccount; FREE_AT_TAIL(xp); } } else { --xp->x_ccount; #ifdef UCB_METER xstats.free_inuse++; #endif } XUNLOCK(xp); u.u_procp->p_textp = NULL; } /* * Attach to a shared text segment. If there is no shared text, just * return. If there is, hook up to it. If it is not available from * core or swap, it has to be read in from the inode (ip); the written * bit is set to force it to be written out as appropriate. If it is * not available from core, a swap has to be done to get it back. */ xalloc(ip, ep) struct exec *ep; register struct inode *ip; { register struct text *xp; register u_int count; off_t offset; size_t ts; if (ep->a_text == 0) return; #ifdef UCB_METER xstats.alloc++; #endif while ((xp = ip->i_text) != NULL) { if (xp->x_flag&XLOCK) { /* * Wait for text to be unlocked, * then start over (may have changed state). */ xwait(xp); continue; } X_LOCK(xp); if (xp->x_back) { ALLOC(xp); #ifdef UCB_METER xstats.alloc_cachehit++; xp->x_flag &= ~XUNUSED; #endif } #ifdef UCB_METER else xstats.alloc_inuse++; #endif xp->x_count++; u.u_procp->p_textp = xp; if (!xp->x_caddr && !xp->x_ccount) xexpand(xp); else ++xp->x_ccount; XUNLOCK(xp); return; } xp = xhead; if (xp == NULL) { tablefull("text"); psignal(u.u_procp, SIGKILL); return; } ALLOC(xp); if (xp->x_iptr) { #ifdef UCB_METER xstats.alloc_cacheflush++; if (xp->x_flag & XUNUSED) xstats.alloc_unused++; #endif xuntext(xp); } xp->x_flag = XLOAD|XLOCK; ts = btoc(ep->a_text); if (u.u_ovdata.uo_ovbase) xp->x_size = u.u_ovdata.uo_ov_offst[NOVL]; else xp->x_size = ts; if ((xp->x_daddr = malloc(swapmap, (size_t)ctod(xp->x_size))) == NULL) { swkill(u.u_procp, "xalloc"); return; } xp->x_count = 1; xp->x_ccount = 0; xp->x_iptr = ip; ip->i_flag |= ITEXT; ip->i_text = xp; ip->i_count++; u.u_procp->p_textp = xp; xexpand(xp); estabur(ts, (u_int)0, (u_int)0, 0, RW); offset = sizeof(struct exec); if (u.u_ovdata.uo_ovbase) offset += (NOVL + 1) * sizeof(u_int); u.u_procp->p_flag |= SLOCK; u.u_error = rdwri(UIO_READ, ip, (caddr_t)0, ep->a_text & ~1, offset, UIO_USERISPACE, IO_UNIT, (int *)0); if (u.u_ovdata.uo_ovbase) { /* read in overlays if necessary */ register int i; offset += (off_t)(ep->a_text & ~1); for (i = 1; i <= NOVL; i++) { u.u_ovdata.uo_curov = i; count = ctob(u.u_ovdata.uo_ov_offst[i] - u.u_ovdata.uo_ov_offst[i-1]); if (count) { choverlay(RW); u.u_error = rdwri(UIO_READ, ip, (caddr_t)(ctob(stoc(u.u_ovdata.uo_ovbase))), count, offset, UIO_USERISPACE, IO_UNIT, (int *)0); offset += (off_t) count; } } } u.u_ovdata.uo_curov = 0; u.u_procp->p_flag &= ~SLOCK; xp->x_flag |= XWRIT; xp->x_flag &= ~XLOAD; } /* * Assure core for text segment. If there isn't enough room to get process * in core, swap self out. x_ccount must be 0. Text must be locked to keep * someone else from freeing it in the meantime. Don't change the locking, * it's correct. */ xexpand(xp) register struct text *xp; { if ((xp->x_caddr = malloc(coremap, xp->x_size)) != NULL) { if ((xp->x_flag & XLOAD) == 0) swap(xp->x_daddr, xp->x_caddr, xp->x_size, B_READ); xp->x_ccount++; XUNLOCK(xp); return; } if (setjmp(&u.u_ssave)) { sureg(); return; } swapout(u.u_procp, X_FREECORE, X_OLDSIZE, X_OLDSIZE); XUNLOCK(xp); u.u_procp->p_flag |= SSWAP; swtch(); /* NOTREACHED */ } /* * Lock and unlock a text segment from swapping */ xlock(xp) register struct text *xp; { X_LOCK(xp); } /* * Wait for xp to be unlocked if it is currently locked. */ xwait(xp) register struct text *xp; { X_LOCK(xp); XUNLOCK(xp); } xunlock(xp) register struct text *xp; { XUNLOCK(xp); } /* * Decrement the in-core usage count of a shared text segment. * When it drops to zero, free the core space. Write the swap * copy of the text if as yet unwritten. */ xccdec(xp) register struct text *xp; { if (!xp->x_ccount) return; X_LOCK(xp); if (--xp->x_ccount == 0) { if (xp->x_flag & XWRIT) { swap(xp->x_daddr, xp->x_caddr, xp->x_size, B_WRITE); xp->x_flag &= ~XWRIT; } mfree(coremap, xp->x_size, xp->x_caddr); xp->x_caddr = NULL; } XUNLOCK(xp); } /* * Free the swap image of all unused saved-text text segments which are from * device dev (used by umount system call). If dev is NODEV, do all devices * (used when rebooting or malloc of swapmap failed). */ xumount(dev) register dev_t dev; { register struct text *xp; for (xp = text; xp < textNTEXT; xp++) if (xp->x_iptr != NULL && (dev == xp->x_iptr->i_dev || dev == NODEV)) xuntext(xp); } /* * Remove text image from the text table. * the use count must be zero. */ xuntext(xp) register struct text *xp; { register struct inode *ip; X_LOCK(xp); if (xp->x_count == 0) { ip = xp->x_iptr; xp->x_iptr = NULL; mfree(swapmap, ctod(xp->x_size), xp->x_daddr); if (xp->x_caddr) mfree(coremap, xp->x_size, xp->x_caddr); ip->i_flag &= ~ITEXT; ip->i_text = NULL; irele(ip); } XUNLOCK(xp); } /* * Free up "size" core; if swap copy of text has not yet been written, * do so. */ xuncore(size) register size_t size; { register struct text *xp; for (xp = xhead; xp; xp = xp->x_forw) { if (!xp->x_iptr) continue; X_LOCK(xp); if (!xp->x_ccount && xp->x_caddr) { if (xp->x_flag & XWRIT) { swap(xp->x_daddr, xp->x_caddr, xp->x_size, B_WRITE); xp->x_flag &= ~XWRIT; } mfree(coremap, xp->x_size, xp->x_caddr); xp->x_caddr = NULL; if (xp->x_size >= size) { XUNLOCK(xp); return; } } XUNLOCK(xp); } } rw = NULL; \ (xp)->x_back = NULL; \ } /* * We place free text table entries on a free list. * All text images are treated as "sticky," * and are placed on the free list (as an LRU cache) when unused. * They may be reclaimed from the free list until reused. * Files marked sticky are locked into the table, and are never freed. */ struct textsys/sys/tty_tb.c 440 0 12 16732 5667261154 7174 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)tty_tb.c 1.2 (2.11BSD GTE) 11/29/94 */ #include "tb.h" #if NTB > 0 /* * Line discipline for RS232 tablets; * supplies binary coordinate data. */ #include "param.h" #include "systm.h" #include "user.h" #include "tablet.h" #include "tty.h" #include "proc.h" #include "inode.h" #include "file.h" #include "buf.h" #include "uio.h" /* * Tablet configuration table. */ struct tbconf { short tbc_recsize; /* input record size in bytes */ short tbc_uiosize; /* size of data record returned user */ int tbc_sync; /* mask for finding sync byte/bit */ int (*tbc_decode)();/* decoding routine */ char *tbc_run; /* enter run mode sequence */ char *tbc_point; /* enter point mode sequence */ char *tbc_stop; /* stop sequence */ char *tbc_start; /* start/restart sequence */ int tbc_flags; #define TBF_POL 0x1 /* polhemus hack */ }; static int tbdecode(), gtcodecode(), poldecode(); static int tblresdecode(), tbhresdecode(); struct tbconf tbconf[TBTYPE] = { { 0 }, { 5, sizeof (struct tbpos), 0200, tbdecode, "6", "4" }, { 5, sizeof (struct tbpos), 0200, tbdecode, "\1CN", "\1RT", "\2", "\4" }, { 8, sizeof (struct gtcopos), 0200, gtcodecode }, {17, sizeof (struct polpos), 0200, poldecode, 0, 0, "\21", "\5\22\2\23", TBF_POL }, { 5, sizeof (struct tbpos), 0100, tblresdecode, "\1CN", "\1PT", "\2", "\4"}, { 6, sizeof (struct tbpos), 0200, tbhresdecode, "\1CN", "\1PT", "\2", "\4"}, }; /* * Tablet state */ struct tb { int tbflags; /* mode & type bits */ #define TBMAXREC 17 /* max input record size */ char cbuf[TBMAXREC]; /* input buffer */ union { struct tbpos tbpos; struct gtcopos gtcopos; struct polpos polpos; } rets; /* processed state */ #define NTBS 16 } tb[NTBS]; /* * Open as tablet discipline; called on discipline change. */ /*ARGSUSED*/ tbopen(dev, tp) dev_t dev; register struct tty *tp; { register struct tb *tbp; if (tp->t_line == TABLDISC) return (ENODEV); ttywflush(tp); for (tbp = tb; tbp < &tb[NTBS]; tbp++) if (tbp->tbflags == 0) break; if (tbp >= &tb[NTBS]) return (EBUSY); tbp->tbflags = TBTIGER|TBPOINT; /* default */ tp->t_cp = tbp->cbuf; tp->t_inbuf = 0; bzero((caddr_t)&tbp->rets, sizeof (tbp->rets)); tp->T_LINEP = (caddr_t)tbp; tp->t_flags |= LITOUT; return (0); } /* * Line discipline change or last device close. */ tbclose(tp, flag) register struct tty *tp; int flag; { register int s; int modebits = TBPOINT|TBSTOP; tbioctl(tp, (u_int)(BIOSMODE), &modebits, 0); s = spl5(); ((struct tb *)tp->T_LINEP)->tbflags = 0; tp->t_cp = 0; tp->t_inbuf = 0; tp->t_rawq.c_cc = 0; /* clear queues -- paranoid */ tp->t_canq.c_cc = 0; tp->t_line = 0; /* paranoid: avoid races */ splx(s); } /* * Read from a tablet line. * Characters have been buffered in a buffer and decoded. */ tbread(tp, uio, flag) register struct tty *tp; struct uio *uio; { register struct tb *tbp = (struct tb *)tp->T_LINEP; register struct tbconf *tc = &tbconf[tbp->tbflags & TBTYPE]; int ret; if ((tp->t_state&TS_CARR_ON) == 0) return (EIO); ret = uiomove(&tbp->rets, tc->tbc_uiosize, uio); if (tc->tbc_flags&TBF_POL) tbp->rets.polpos.p_key = ' '; return (ret); } /* * Low level character input routine. * Stuff the character in the buffer, and decode * if all the chars are there. * * This routine could be expanded in-line in the receiver * interrupt routine to make it run as fast as possible. */ tbinput(c, tp) register int c; register struct tty *tp; { register struct tb *tbp = (struct tb *)tp->T_LINEP; register struct tbconf *tc = &tbconf[tbp->tbflags & TBTYPE]; if (tc->tbc_recsize == 0 || tc->tbc_decode == 0) /* paranoid? */ return; /* * Locate sync bit/byte or reset input buffer. */ if (c&tc->tbc_sync || tp->t_inbuf == tc->tbc_recsize) { tp->t_cp = tbp->cbuf; tp->t_inbuf = 0; } *tp->t_cp++ = c&0177; /* * Call decode routine only if a full record has been collected. */ if (++tp->t_inbuf == tc->tbc_recsize) (*tc->tbc_decode)(tbp->cbuf, &tbp->rets); } /* * Decode GTCO 8 byte format (high res, tilt, and pressure). */ static gtcodecode(cp, tbpos) register char *cp; register struct gtcopos *tbpos; { tbpos->pressure = *cp >> 2; tbpos->status = (tbpos->pressure > 16) | TBINPROX; /* half way down */ tbpos->xpos = (*cp++ & 03) << 14; tbpos->xpos |= *cp++ << 7; tbpos->xpos |= *cp++; tbpos->ypos = (*cp++ & 03) << 14; tbpos->ypos |= *cp++ << 7; tbpos->ypos |= *cp++; tbpos->xtilt = *cp++; tbpos->ytilt = *cp++; tbpos->scount++; } /* * Decode old Hitachi 5 byte format (low res). */ static tbdecode(cp, tbpos) register char *cp; register struct tbpos *tbpos; { register char byte; byte = *cp++; tbpos->status = (byte&0100) ? TBINPROX : 0; byte &= ~0100; if (byte > 036) tbpos->status |= 1 << ((byte-040)/2); tbpos->xpos = *cp++ << 7; tbpos->xpos |= *cp++; if (tbpos->xpos < 256) /* tablet wraps around at 256 */ tbpos->status &= ~TBINPROX; /* make it out of proximity */ tbpos->ypos = *cp++ << 7; tbpos->ypos |= *cp++; tbpos->scount++; } /* * Decode new Hitach 5-byte format (low res). */ static tblresdecode(cp, tbpos) register char *cp; register struct tbpos *tbpos; { *cp &= ~0100; /* mask sync bit */ tbpos->status = (*cp++ >> 2) | TBINPROX; tbpos->xpos = *cp++; tbpos->xpos |= *cp++ << 6; tbpos->ypos = *cp++; tbpos->ypos |= *cp++ << 6; tbpos->scount++; } /* * Decode new Hitach 6-byte format (high res). */ static tbhresdecode(cp, tbpos) register char *cp; register struct tbpos *tbpos; { char byte; byte = *cp++; tbpos->xpos = (byte & 03) << 14; tbpos->xpos |= *cp++ << 7; tbpos->xpos |= *cp++; tbpos->ypos = *cp++ << 14; tbpos->ypos |= *cp++ << 7; tbpos->ypos |= *cp++; tbpos->status = (byte >> 2) | TBINPROX; tbpos->scount++; } /* * Polhemus decode. */ static poldecode(cp, polpos) register char *cp; register struct polpos *polpos; { polpos->p_x = cp[4] | cp[3]<<7 | (cp[9] & 0x03) << 14; polpos->p_y = cp[6] | cp[5]<<7 | (cp[9] & 0x0c) << 12; polpos->p_z = cp[8] | cp[7]<<7 | (cp[9] & 0x30) << 10; polpos->p_azi = cp[11] | cp[10]<<7 | (cp[16] & 0x03) << 14; polpos->p_pit = cp[13] | cp[12]<<7 | (cp[16] & 0x0c) << 12; polpos->p_rol = cp[15] | cp[14]<<7 | (cp[16] & 0x30) << 10; polpos->p_stat = cp[1] | cp[0]<<7; if (cp[2] != ' ') polpos->p_key = cp[2]; } /*ARGSUSED*/ tbioctl(tp, cmd, data, flag) struct tty *tp; u_int cmd; caddr_t data; { register struct tb *tbp = (struct tb *)tp->T_LINEP; switch (cmd) { case BIOGMODE: *(int *)data = tbp->tbflags & TBMODE; break; case BIOSTYPE: if (tbconf[*(int *)data & TBTYPE].tbc_recsize == 0 || tbconf[*(int *)data & TBTYPE].tbc_decode == 0) return (EINVAL); tbp->tbflags &= ~TBTYPE; tbp->tbflags |= *(int *)data & TBTYPE; /* fall thru... to set mode bits */ case BIOSMODE: { register struct tbconf *tc; tbp->tbflags &= ~TBMODE; tbp->tbflags |= *(int *)data & TBMODE; tc = &tbconf[tbp->tbflags & TBTYPE]; if (tbp->tbflags&TBSTOP) { if (tc->tbc_stop) ttyout(tc->tbc_stop, tp); } else if (tc->tbc_start) ttyout(tc->tbc_start, tp); if (tbp->tbflags&TBPOINT) { if (tc->tbc_point) ttyout(tc->tbc_point, tp); } else if (tc->tbc_run) ttyout(tc->tbc_run, tp); ttstart(tp); break; } case BIOGTYPE: *(int *)data = tbp->tbflags & TBTYPE; break; case TIOCSETD: case TIOCGETD: case TIOCGETP: case TIOCGETC: return (-1); /* pass thru... */ default: return (ENOTTY); } return (0); } #endif ags |= PF_RCOLL; else pti->pt_selsys/sys/ufs_mount.c 440 0 12 11046 5757754126 7705 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ufs_mount.c 1.5 (2.11BSD GTE) 1995/05/21 */ #include "param.h" #include "../machine/seg.h" #include "systm.h" #include "user.h" #include "inode.h" #include "fs.h" #include "buf.h" #include "mount.h" #include "file.h" #include "namei.h" #include "conf.h" #include "stat.h" #ifdef QUOTA #include "quota.h" #endif smount() { register struct a { char *fspec; char *freg; int flags; } *uap = (struct a *)u.u_ap; dev_t dev; register struct inode *ip; register struct fs *fs; register struct nameidata *ndp = &u.u_nd; u_int len; u.u_error = getmdev(&dev, uap->fspec); if (u.u_error) return; ndp->ni_nameiop = LOOKUP | FOLLOW; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = (caddr_t)uap->freg; ip = namei(ndp); if (ip == NULL) return; if (ip->i_count != 1) { iput(ip); u.u_error = EBUSY; return; } if ((ip->i_mode&IFMT) != IFDIR) { iput(ip); u.u_error = ENOTDIR; return; } if (ip->i_number == ROOTINO) { iput(ip); u.u_error = EBUSY; return; } fs = mountfs(dev, uap->flags, ip); if (fs == 0) return; (void) copyinstr(uap->freg, fs->fs_fsmnt, sizeof(fs->fs_fsmnt)-1, &len); bzero(fs->fs_fsmnt + len, sizeof (fs->fs_fsmnt) - len); } /* this routine has races if running twice */ struct fs * mountfs(dev, flags, ip) dev_t dev; int flags; struct inode *ip; { register struct mount *mp = 0; struct buf *tp = 0; register struct fs *fs; register int error; int ronly = flags & MNT_RDONLY; int needclose = 0; error = (*bdevsw[major(dev)].d_open)(dev, ronly ? FREAD : FREAD|FWRITE, S_IFBLK); if (error) goto out; needclose = 1; tp = bread(dev, SBLOCK); if (tp->b_flags & B_ERROR) goto out; for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) if (mp->m_inodp != 0 && dev == mp->m_dev) { mp = 0; error = EBUSY; needclose = 0; goto out; } for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) if (mp->m_inodp == 0) goto found; mp = 0; error = EMFILE; /* needs translation */ goto out; found: mp->m_inodp = ip; /* reserve slot */ mp->m_dev = dev; fs = &mp->m_filsys; bcopy(mapin(tp), (caddr_t)fs, sizeof(struct fs)); mapout(tp); brelse(tp); tp = 0; fs->fs_ronly = (ronly != 0); if (ronly == 0) fs->fs_fmod = 1; fs->fs_ilock = 0; fs->fs_flock = 0; fs->fs_nbehind = 0; fs->fs_lasti = 1; fs->fs_flags = flags; if (ip) { ip->i_flag |= IMOUNT; cacheinval(ip); IUNLOCK(ip); } return (fs); out: if (error == 0) error = EIO; if (ip) iput(ip); if (mp) mp->m_inodp = 0; if (tp) brelse(tp); if (needclose) { (*bdevsw[major(dev)].d_close)(dev, ronly? FREAD : FREAD|FWRITE, S_IFBLK); binval(dev); } u.u_error = error; return (0); } umount() { struct a { char *fspec; } *uap = (struct a *)u.u_ap; u.u_error = unmount1(uap->fspec); } unmount1(fname) caddr_t fname; { dev_t dev; register struct mount *mp; register struct inode *ip; register int error; error = getmdev(&dev, fname); if (error) return (error); for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) if (mp->m_inodp != NULL && dev == mp->m_dev) goto found; return (EINVAL); found: xumount(dev); /* remove unused sticky files from text table */ nchinval(dev); /* flush the name cache */ update(); #ifdef QUOTA if (iflush(dev, mp->m_qinod) < 0) #else if (iflush(dev) < 0) #endif return (EBUSY); #ifdef QUOTA QUOTAMAP(); closedq(mp); QUOTAUNMAP(); /* * Here we have to iflush again to get rid of the quota inode. * A drag, but it would be ugly to cheat, & this doesn't happen often */ (void)iflush(dev, (struct inode *)NULL); #endif ip = mp->m_inodp; ip->i_flag &= ~IMOUNT; irele(ip); mp->m_inodp = 0; mp->m_dev = 0; (*bdevsw[major(dev)].d_close)(dev, 0, S_IFBLK); binval(dev); return (0); } /* * Common code for mount and umount. * Check that the user's argument is a reasonable * thing on which to mount, otherwise return error. */ getmdev(pdev, fname) caddr_t fname; dev_t *pdev; { register dev_t dev; register struct inode *ip; register struct nameidata *ndp = &u.u_nd; if (!suser()) return (u.u_error); ndp->ni_nameiop = LOOKUP | FOLLOW; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = fname; ip = namei(ndp); if (ip == NULL) { if (u.u_error == ENOENT) return (ENODEV); /* needs translation */ return (u.u_error); } if ((ip->i_mode&IFMT) != IFBLK) { iput(ip); return (ENOTBLK); } dev = (dev_t)ip->i_rdev; iput(ip); if (major(dev) >= nblkdev) return (ENXIO); *pdev = dev; return (0); } tilt = *cp++; tbpos->scount++; } /* * Decode old Hitachi 5 byte format (low res). */ static tbdecode(cp, tbpos) register char *cp; register struct tbpos *tbpos; { register char byte; byte = *cp++; tbpos->status = (byte&0100) ? TBINPROX : 0; byte &= ~0100; if (byte > 036) tbpos->status |= 1 << ((byte-040)/2); tbpos->xpos = *cp++ << 7; tbpos->xpos |= *cp++; if (tbpos->xpos < 256) /* tablet wraps around at 256 */ tbpos->status &= ~TBINPROX; /* make it sys/sys/ufs_bmap.c 440 0 12 6161 4607606215 7430 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ufs_bmap.c 1.1 (2.10BSD Berkeley) 12/1/86 */ #include "param.h" #include "../machine/seg.h" #include "systm.h" #include "conf.h" #include "dir.h" #include "inode.h" #include "user.h" #include "buf.h" #include "fs.h" #include "uio.h" /* * Bmap defines the structure of file system storage * by returning the physical block number on a device given the * inode and the logical block number in a file. * When convenient, it also leaves the physical * block number of the next block of the file in rablock * for use in read-ahead. */ daddr_t bmap(ip, bn, rwflg, clrflg) register struct inode *ip; daddr_t bn; int rwflg, clrflg; { register int i; register struct buf *bp; struct buf *nbp; int j, sh; daddr_t nb, *bap, ra; if (bn < 0) { u.u_error = EFBIG; return((daddr_t)0); } ra = rablock = 0; /* * blocks 0..NADDR-4 are direct blocks */ if (bn < NADDR-3) { i = bn; nb = ip->i_addr[i]; if (nb == 0) { if (rwflg == B_READ || (bp = alloc(ip, clrflg)) == NULL) return((daddr_t)-1); nb = dbtofsb(bp->b_blkno); if ((ip->i_mode&IFMT) == IFDIR) /* * Write directory blocks synchronously * so they never appear with garbage in * them on the disk. */ bwrite(bp); else bdwrite(bp); ip->i_addr[i] = nb; ip->i_flag |= IUPD|ICHG; } if (i < NADDR-4) rablock = ip->i_addr[i+1]; return(nb); } /* * addresses NADDR-3, NADDR-2, and NADDR-1 * have single, double, triple indirect blocks. * the first step is to determine * how many levels of indirection. */ sh = 0; nb = 1; bn -= NADDR-3; for (j = 3;j > 0;j--) { sh += NSHIFT; nb <<= NSHIFT; if (bn < nb) break; bn -= nb; } if (j == 0) { u.u_error = EFBIG; return((daddr_t)0); } /* * fetch the first indirect block */ nb = ip->i_addr[NADDR-j]; if (nb == 0) { if (rwflg == B_READ || (bp = alloc(ip, 1)) == NULL) return((daddr_t) -1); nb = dbtofsb(bp->b_blkno); /* * Write synchronously so that indirect blocks * never point at garbage. */ bwrite(bp); ip->i_addr[NADDR-j] = nb; ip->i_flag |= IUPD|ICHG; } /* * fetch through the indirect blocks */ for(;j <= 3;j++) { bp = bread(ip->i_dev, nb); if ((bp->b_flags & B_ERROR) || bp->b_resid) { brelse(bp); return((daddr_t)0); } bap = (daddr_t *) mapin(bp); sh -= NSHIFT; i = (bn>>sh) & NMASK; nb = bap[i]; /* * calculate read-ahead */ if (i < NINDIR-1) ra = bap[i+1]; mapout(bp); if (nb == 0) { if (rwflg == B_READ || (nbp = alloc(ip, 1)) == NULL) { brelse(bp); return((daddr_t) -1); } nb = dbtofsb(nbp->b_blkno); if (j < 3 || (ip->i_mode&IFMT) == IFDIR) /* * Write synchronously so indirect blocks * never point at garbage and blocks * in directories never contain garbage. */ bwrite(nbp); else bdwrite(nbp); bap = (daddr_t *) mapin(bp); bap[i] = nb; mapout(bp); bdwrite(bp); } else brelse(bp); } rablock = ra; return(nb); } +) if (mp->m_inodp != NULL && dev == mp->m_dev) goto found; return (EINVAL); found: xumount(dev); /* remove unused sticky files from text table */ nchinval(dev); /* flush the name cache */ update(); #ifdef QUOTA if (iflush(dev, mp->m_qinod) < 0) #else if (iflush(dev) < 0) #endif return (EBUSY); #ifdef QUOTA QUOTAMAP(); closedq(mp); QUOTAUNMAP(); /* * Here we have to iflush agaisys/sys/tty_tty.c 440 0 12 2624 5667000425 7352 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)tty_tty.c 1.2 (2.11BSD GTE) 11/29/94 */ /* * Indirect driver for controlling tty. * */ #include "param.h" #include "user.h" #include "proc.h" #include "ioctl.h" #include "tty.h" #include "conf.h" /*ARGSUSED*/ syopen(dev, flag) dev_t dev; int flag; { if (u.u_ttyp == NULL) return (ENXIO); return((*cdevsw[major(u.u_ttyd)].d_open)(u.u_ttyd, flag)); } /*ARGSUSED*/ syread(dev, uio, flag) dev_t dev; struct uio *uio; int flag; { if (u.u_ttyp == NULL) return (ENXIO); return ((*cdevsw[major(u.u_ttyd)].d_read)(u.u_ttyd, uio, flag)); } /*ARGSUSED*/ sywrite(dev, uio, flag) dev_t dev; struct uio *uio; { if (u.u_ttyp == NULL) return (ENXIO); return ((*cdevsw[major(u.u_ttyd)].d_write)(u.u_ttyd, uio, flag)); } /*ARGSUSED*/ syioctl(dev, cmd, addr, flag) dev_t dev; u_int cmd; caddr_t addr; int flag; { if (cmd == TIOCNOTTY) { u.u_ttyp = 0; u.u_ttyd = 0; u.u_procp->p_pgrp = 0; return (0); } if (u.u_ttyp == NULL) return (ENXIO); return ((*cdevsw[major(u.u_ttyd)].d_ioctl)(u.u_ttyd, cmd, addr, flag)); } /*ARGSUSED*/ syselect(dev, flag) dev_t dev; int flag; { if (u.u_ttyp == NULL) { u.u_error = ENXIO; return (0); } return ((*cdevsw[major(u.u_ttyd)].d_select)(u.u_ttyd, flag)); } dr_t nb, *bap, ra; if (bn < 0) { u.u_error = EFBIG; return((daddr_t)0); } ra = rablock = 0; /* *sys/sys/ufs_dsort.c 440 0 12 3404 4112412203 7620 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ufs_dsort.c 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * generalized seek sort for disk */ #include "param.h" #include "systm.h" #include "buf.h" #include "dk.h" disksort(dp, bp) register struct buf *dp, *bp; { register struct buf *ap; struct buf *tp; ap = dp->b_actf; if (ap == NULL) { dp->b_actf = bp; dp->b_actl = bp; bp->av_forw = NULL; return; } tp = NULL; for (; ap != NULL; ap = ap->av_forw) { if ((bp->b_flags&B_READ) && (ap->b_flags&B_READ) == 0) { if (tp == NULL) tp = ap; break; } if ((bp->b_flags&B_READ) == 0 && (ap->b_flags&B_READ)) continue; if (ap->b_cylin <= bp->b_cylin) if (tp == NULL || ap->b_cylin >= tp->b_cylin) tp = ap; } if (tp == NULL) tp = dp->b_actl; bp->av_forw = tp->av_forw; tp->av_forw = bp; if (tp == dp->b_actl) dp->b_actl = bp; } #ifdef UCB_METER /* * Allocate iostat disk monitoring slots for a driver. If slots already * allocated (*dkn >= 0) or not enough slots left to satisfy request simply * ignore it. */ dk_alloc(dkn, slots, name, wps) int *dkn; /* pointer to number for iostat */ int slots; /* number of iostat slots requested */ char *name; /* name of device */ long wps; /* words per second transfer rate */ { int i; register char **np; register int *up; register long *wp; if (*dkn < 0 && dk_n + slots <= DK_NDRIVE) { /* * Allocate and initialize the slots */ *dkn = dk_n; np = &dk_name[dk_n]; up = &dk_unit[dk_n]; wp = &dk_wps[dk_n]; dk_n += slots; for (i = 0; i < slots; i++) { *np++ = name; *up++ = i; *wp++ = wps; } } } #endif /* UCB_METER */ j > 0;j--) { sh += NSHIFT; nb <<= NSHIFT; if (bn < nb) break; bn -= nb; } if (j == 0) { u.u_error = EFBIG; return((daddr_t)0); } /* * fetch the first indirect block */ nb = ip->i_addr[NADDR-j]; if (nb == 0) { if (rwflg == B_sys/sys/sys_process.c 440 0 12 10030 4264261732 10216 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)sys_process.c 1.1 (2.10BSD Berkeley) 6/12/88 */ #include "param.h" #include "../machine/psl.h" #include "../machine/reg.h" #include "../machine/seg.h" #include "systm.h" #include "user.h" #include "proc.h" #include "inode.h" #include "text.h" #include "vm.h" #include "ptrace.h" /* * Priority for tracing */ #define IPCPRI PZERO /* * Tracing variables. * Used to pass trace command from * parent to child being traced. * This data base cannot be * shared and is locked * per user. */ struct { int ip_lock; int ip_req; int *ip_addr; int ip_data; } ipc; /* * sys-trace system call. */ ptrace() { register struct proc *p; register struct a { int req; int pid; int *addr; int data; } *uap; uap = (struct a *)u.u_ap; if (uap->req <= 0) { u.u_procp->p_flag |= STRC; return; } p = pfind(uap->pid); if (p == 0 || p->p_stat != SSTOP || p->p_ppid != u.u_procp->p_pid || !(p->p_flag & STRC)) { u.u_error = ESRCH; return; } while (ipc.ip_lock) sleep((caddr_t)&ipc, IPCPRI); ipc.ip_lock = p->p_pid; ipc.ip_data = uap->data; ipc.ip_addr = uap->addr; ipc.ip_req = uap->req; p->p_flag &= ~SWTED; setrun(p); while (ipc.ip_req > 0) sleep((caddr_t)&ipc, IPCPRI); u.u_r.r_val1 = (short)ipc.ip_data; if (ipc.ip_req < 0) u.u_error = EIO; ipc.ip_lock = 0; wakeup((caddr_t)&ipc); } /* * Code that the child process * executes to implement the command * of the parent process in tracing. */ procxmt() { register int i; register *p; register struct text *xp; if (ipc.ip_lock != u.u_procp->p_pid) return(0); u.u_procp->p_slptime = 0; i = ipc.ip_req; ipc.ip_req = 0; wakeup((caddr_t)&ipc); switch (i) { /* read user I */ case PT_READ_I: #ifndef NONSEPARATE if (fuibyte((caddr_t)ipc.ip_addr) == -1) goto error; ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); break; #endif /* !NONSEPARATE */ /* read user D */ case PT_READ_D: if (fubyte((caddr_t)ipc.ip_addr) == -1) goto error; ipc.ip_data = fuword((caddr_t)ipc.ip_addr); break; /* read u */ case PT_READ_U: i = (int)ipc.ip_addr; if (i<0 || i >= ctob(USIZE)) goto error; ipc.ip_data = ((physadr)&u)->r[i/sizeof(int)]; break; /* write user I */ /* Must set up to allow writing */ case PT_WRITE_I: /* * If text, must assure exclusive use */ if (xp = u.u_procp->p_textp) { if (xp->x_count!=1 || xp->x_iptr->i_mode&ISVTX) goto error; xp->x_flag |= XTRC; } estabur(u.u_tsize, u.u_dsize, u.u_ssize, u.u_sep, RW); i = suiword((caddr_t)ipc.ip_addr, 0); suiword((caddr_t)ipc.ip_addr, ipc.ip_data); estabur(u.u_tsize, u.u_dsize, u.u_ssize, u.u_sep, RO); if (i<0) goto error; if (xp) xp->x_flag |= XWRIT; break; /* write user D */ case PT_WRITE_D: if (suword((caddr_t)ipc.ip_addr, 0) < 0) goto error; suword((caddr_t)ipc.ip_addr, ipc.ip_data); break; /* write u */ case PT_WRITE_U: i = (int)ipc.ip_addr; p = (int *)&((physadr)&u)->r[i/sizeof(int)]; if (p >= (int *)&u.u_fps && p < (int *)&u.u_fps.u_fpregs[6]) goto ok; for (i=0; i<8; i++) if (p == &u.u_ar0[regloc[i]]) goto ok; if (p == &u.u_ar0[RPS]) { ipc.ip_data |= PSL_USERSET; /* user space */ ipc.ip_data &= ~PSL_USERCLR; /* priority 0 */ goto ok; } if ((p == (int *)&u.u_ovdata.uo_curov) && ((ipc.ip_data >= 0) && (ipc.ip_data <= NOVL) && u.u_ovdata.uo_ovbase)) { u.u_ovdata.uo_curov = ipc.ip_data; choverlay(RW); break; } goto error; ok: *p = ipc.ip_data; break; /* set signal and continue */ /* one version causes a trace-trap */ case PT_STEP: u.u_ar0[RPS] |= PSL_T; /* FALL THROUGH TO ... */ case PT_CONTINUE: if ((int)ipc.ip_addr != 1) u.u_ar0[PC] = (int)ipc.ip_addr; if (ipc.ip_data > NSIG) goto error; u.u_procp->p_cursig = ipc.ip_data; return(1); /* force exit */ case PT_KILL: exit(u.u_procp->p_cursig); /*NOTREACHED*/ default: error: ipc.ip_req = -1; } return(0); } ev_t dev; register struct inode *ip; register struct nameidata *ndp = &u.u_nd; if (!suser()) return (u.u_error); ndp->ni_nameiop = LOOKUP | FOLLOW; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = fname; ip = namei(ndp); if (ip == NULL) { if (u.u_error == ENOENT) return (ENODEV); /* needs translation */ return (u.u_error); } if ((ip->i_mode&IFMT) != IFBLK) { iput(ip); return (ENOTBLK); } dev = (dev_t)ip->i_rdev; iput(ip); if (major(dev) >= nblkdev) return sys/sys/uipc_mbuf.c 440 0 12 17760 5316453551 7635 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)uipc_mbuf.c 2.0 (2.11BSD) 12/24/92 */ #include "param.h" #ifdef INET #include "user.h" #include "mbuf.h" #include "kernel.h" #include "domain.h" #include "protosw.h" struct mbuf *mbuf, *mbutl, xmbuf[NMBUFS + 1]; struct mbuf xmbutl[(NMBCLUSTERS*CLBYTES/sizeof (struct mbuf))+7]; memaddr miobase; /* click address of dma region */ /* this is altered during allocation */ memaddr miostart; /* click address of dma region */ /* this stays unchanged */ ubadr_t mioumr; /* base UNIBUS virtual address */ /* miostart and mioumr stay 0 for */ /* non-UNIBUS machines */ u_short miosize = 16384; /* two umr's worth */ mbinit() { register int s; s = splimp(); nmbclusters = NMBCLUSTERS; /* * if the following two lines look strange, it's because they are. * mbufs are aligned on a MSIZE byte boundary and clusters are * aligned on CLBYTES byte boundary. extra room has been allocated * in the arrays to allow for the array origin not being aligned, * in which case we move part way thru and start there. */ mbutl = (struct mbuf *)(((int)xmbutl | CLBYTES-1) + 1); mbuf = (struct mbuf *)(((int)xmbuf | MSIZE-1) + 1); mbinit2(mbuf, MPG_MBUFS, NMBUFS); mbinit2(mbutl, MPG_CLUSTERS, NMBCLUSTERS); splx(s); return; } mbinit2(mem, how, num) char *mem; int how; register int num; { register struct mbuf *m; register int i; m = (struct mbuf *)mem; switch (how) { case MPG_CLUSTERS: for (i = 0; i < num; i++) { m->m_off = 0; m->m_next = mclfree; mclfree = m; m += NMBPCL; mbstat.m_clfree++; } mbstat.m_clusters = num; break; case MPG_MBUFS: for (i = num; i > 0; i--) { m->m_off = 0; m->m_type = MT_DATA; mbstat.m_mtypes[MT_DATA]++; (void) m_free(m); m++; } mbstat.m_mbufs = NMBUFS; break; } } /* * Allocate a contiguous buffer for DMA IO. Called from if_ubainit(). * TODO: fix net device drivers to handle scatter/gather to mbufs * on their own; thus avoiding the copy to/from this area. */ u_int m_ioget(size) u_int size; /* Number of bytes to allocate */ { memaddr base; u_int csize; csize = btoc(size); /* size in clicks */ size = ctob(csize); /* round up byte size */ if (size > miosize) return(0); miosize -= size; base = miobase; miobase += csize; return (base); } /* * Must be called at splimp. */ m_expand(canwait) int canwait; { register struct domain *dp; register struct protosw *pr; register int tries; for (tries = 0;; ) { #ifdef pdp11 if (mfree) return (1); #else if (m_clalloc(1, MPG_MBUFS, canwait)) return (1); #endif if (canwait == M_DONTWAIT || tries++) return (0); /* ask protocols to free space */ for (dp = domains; dp; dp = dp->dom_next) for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_drain) (*pr->pr_drain)(); mbstat.m_drain++; } } /* NEED SOME WAY TO RELEASE SPACE */ /* * Space allocation routines. * These are also available as macros * for critical paths. */ struct mbuf * m_get(canwait, type) int canwait, type; { register struct mbuf *m; MGET(m, canwait, type); return (m); } struct mbuf * m_getclr(canwait, type) int canwait, type; { register struct mbuf *m; MGET(m, canwait, type); if (m == 0) return (0); bzero(mtod(m, caddr_t), MLEN); return (m); } struct mbuf * m_free(m) struct mbuf *m; { register struct mbuf *n; MFREE(m, n); return (n); } /* * Get more mbufs; called from MGET macro if mfree list is empty. * Must be called at splimp. */ /*ARGSUSED*/ struct mbuf * m_more(canwait, type) int canwait, type; { register struct mbuf *m; while (m_expand(canwait) == 0) { if (canwait == M_WAIT) { mbstat.m_wait++; m_want++; SLEEP((caddr_t)&mfree, PZERO - 1); } else { mbstat.m_drops++; return (NULL); } } #define m_more(x,y) (panic("m_more"), (struct mbuf *)0) MGET(m, canwait, type); #undef m_more return (m); } m_freem(m) register struct mbuf *m; { register struct mbuf *n; register int s; if (m == NULL) return; s = splimp(); do { MFREE(m, n); } while (m = n); splx(s); } /* * Mbuffer utility routines. */ /* * Make a copy of an mbuf chain starting "off" bytes from the beginning, * continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf. * Should get M_WAIT/M_DONTWAIT from caller. */ struct mbuf * m_copy(m, off, len) register struct mbuf *m; int off; register int len; { register struct mbuf *n, **np; struct mbuf *top, *p; if (len == 0) return (0); if (off < 0 || len < 0) panic("m_copy"); while (off > 0) { if (m == 0) panic("m_copy"); if (off < m->m_len) break; off -= m->m_len; m = m->m_next; } np = ⊤ top = 0; while (len > 0) { if (m == 0) { if (len != M_COPYALL) panic("m_copy"); break; } MGET(n, M_DONTWAIT, m->m_type); *np = n; if (n == 0) goto nospace; n->m_len = MIN(len, m->m_len - off); if (m->m_off > MMAXOFF) { p = mtod(m, struct mbuf *); n->m_off = ((int)p - (int)n) + off; mclrefcnt[mtocl(p)]++; } else bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t), (unsigned)n->m_len); if (len != M_COPYALL) len -= n->m_len; off = 0; m = m->m_next; np = &n->m_next; } return (top); nospace: m_freem(top); return (0); } m_cat(m, n) register struct mbuf *m, *n; { while (m->m_next) m = m->m_next; while (n) { if (m->m_off >= MMAXOFF || m->m_off + m->m_len + n->m_len > MMAXOFF) { /* just join the two chains */ m->m_next = n; return; } /* splat the data from one into the other */ bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, (u_int)n->m_len); m->m_len += n->m_len; n = m_free(n); } } m_adj(mp, len) struct mbuf *mp; register int len; { register struct mbuf *m; register count; if ((m = mp) == NULL) return; if (len >= 0) { while (m != NULL && len > 0) { if (m->m_len <= len) { len -= m->m_len; m->m_len = 0; m = m->m_next; } else { m->m_len -= len; m->m_off += len; break; } } } else { /* * Trim from tail. Scan the mbuf chain, * calculating its length and finding the last mbuf. * If the adjustment only affects this mbuf, then just * adjust and return. Otherwise, rescan and truncate * after the remaining size. */ len = -len; count = 0; for (;;) { count += m->m_len; if (m->m_next == (struct mbuf *)0) break; m = m->m_next; } if (m->m_len >= len) { m->m_len -= len; return; } count -= len; /* * Correct length for chain is "count". * Find the mbuf with last data, adjust its length, * and toss data from remaining mbufs on chain. */ for (m = mp; m; m = m->m_next) { if (m->m_len >= count) { m->m_len = count; break; } count -= m->m_len; } while (m = m->m_next) m->m_len = 0; } } /* * Rearange an mbuf chain so that len bytes are contiguous * and in the data area of an mbuf (so that mtod and dtom * will work for a structure of size len). Returns the resulting * mbuf chain on success, frees it and returns null on failure. * If there is room, it will add up to MPULL_EXTRA bytes to the * contiguous region in an attempt to avoid being called next time. */ struct mbuf * m_pullup(n, len) register struct mbuf *n; int len; { register struct mbuf *m; register int count; int space; if (n->m_off + len <= MMAXOFF && n->m_next) { m = n; n = n->m_next; len -= m->m_len; } else { if (len > MLEN) goto bad; MGET(m, M_DONTWAIT, n->m_type); if (m == 0) goto bad; m->m_len = 0; } space = MMAXOFF - m->m_off; do { count = MIN(MIN(space - m->m_len, len + MPULL_EXTRA), n->m_len); bcopy(mtod(n, caddr_t), mtod(m, caddr_t)+m->m_len, (unsigned)count); len -= count; m->m_len += count; n->m_len -= count; if (n->m_len) n->m_off += count; else n = m_free(n); } while (len > 0 && n); if (len > 0) { (void) m_free(m); goto bad; } m->m_next = n; return (m); bad: m_freem(n); return (0); } #endif f (tc->tbc_stop)sys/sys/ufs_syscalls.c 440 0 0 73602 5671522157 10353 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ufs_syscalls.c 1.5 (2.11BSD GTE) 12/7/94 */ #include "param.h" #include "systm.h" #include "user.h" #include "inode.h" #include "namei.h" #include "fs.h" #include "file.h" #include "stat.h" #include "kernel.h" #ifdef QUOTA #include "quota.h" #endif static void copen(); static struct inode *getinode(); /* * Change current working directory (``.''). */ chdir() { chdirec(&u.u_cdir); } fchdir() { register struct a { int fd; } *uap = (struct a *)u.u_ap; register struct inode *ip; if ((ip = getinode(uap->fd)) == NULL) return; ilock(ip); if ((ip->i_mode & IFMT) != IFDIR) { u.u_error = ENOTDIR; goto bad; } if (access(ip, IEXEC)) goto bad; iunlock(ip); ip->i_count++; irele(u.u_cdir); u.u_cdir = ip; return; bad: iunlock(ip); return; } /* * Change notion of root (``/'') directory. */ chroot() { if (suser()) chdirec(&u.u_rdir); } /* * Common routine for chroot and chdir. */ chdirec(ipp) register struct inode **ipp; { register struct inode *ip; struct a { char *fname; } *uap = (struct a *)u.u_ap; register struct nameidata *ndp = &u.u_nd; ndp->ni_nameiop = LOOKUP | FOLLOW; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->fname; ip = namei(ndp); if (ip == NULL) return; if ((ip->i_mode&IFMT) != IFDIR) { u.u_error = ENOTDIR; goto bad; } if (access(ip, IEXEC)) goto bad; iunlock(ip); if (*ipp) irele(*ipp); *ipp = ip; return; bad: iput(ip); } /* * Open system call. */ open() { register struct a { char *fname; int mode; int crtmode; } *uap = (struct a *) u.u_ap; copen(uap->mode, uap->crtmode, uap->fname); } /* * Creat system call. */ creat() { register struct a { char *fname; int fmode; } *uap = (struct a *)u.u_ap; copen(O_WRONLY|O_CREAT|O_TRUNC, uap->fmode, uap->fname); } /* * Common code for open and creat. * Check permissions, allocate an open file structure, * and call the device open routine if any. */ static void copen(mode, arg, fname) int mode; int arg; caddr_t fname; { register struct inode *ip; register struct file *fp; register struct nameidata *ndp = &u.u_nd; int indx, type; mode = FFLAGS(mode); /* convert from open to kernel flags */ fp = falloc(); if (fp == NULL) return; indx = u.u_r.r_val1; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = fname; if (mode & O_CREAT) { if (mode & O_EXCL) ndp->ni_nameiop = CREATE; else ndp->ni_nameiop = CREATE | FOLLOW; ip = namei(ndp); if (ip == NULL) { if (u.u_error) goto bad1; ip = maknode(arg&07777&(~ISVTX), ndp); if (ip == NULL) goto bad1; mode &= ~O_TRUNC; } else { if (mode & O_EXCL) { u.u_error = EEXIST; goto bad; } mode &= ~O_CREAT; } } else { ndp->ni_nameiop = LOOKUP | FOLLOW; ip = namei(ndp); if (ip == NULL) goto bad1; } if ((ip->i_mode & IFMT) == IFSOCK) { u.u_error = EOPNOTSUPP; goto bad; } if ((ip->i_flags & APPEND) && (mode & (FWRITE|O_APPEND)) == FWRITE) { u.u_error = EPERM; goto bad; } if ((mode& O_CREAT) == 0) { if (mode&FREAD) if (access(ip, IREAD)) goto bad; if (mode&(FWRITE|O_TRUNC)) { if (access(ip, IWRITE)) goto bad; if ((ip->i_mode&IFMT) == IFDIR) { u.u_error = EISDIR; goto bad; } } } if (mode & O_TRUNC) itrunc(ip, (u_long)0); iunlock(ip); fp->f_flag = mode&FMASK; fp->f_type = DTYPE_INODE; fp->f_data = (caddr_t)ip; if (setjmp(&u.u_qsave)) { if (u.u_error == 0) u.u_error = EINTR; bad2: u.u_ofile[indx] = NULL; closef(fp); return; } u.u_error = openi(ip, mode); if (u.u_error == 0) { if (mode & O_EXLOCK) mode &= ~O_SHLOCK; type = 0; if (mode & O_SHLOCK) type |= LOCK_SH; if (mode & O_EXLOCK) type |= LOCK_EX; if (!type) return; if (mode & O_NONBLOCK) type |= LOCK_NB; u.u_error = ino_lock(fp, type); if (u.u_error == 0) return; goto bad2; } ilock(ip); bad: iput(ip); bad1: u.u_ofile[indx] = NULL; fp->f_count--; } /* * Mknod system call */ mknod() { register struct inode *ip; register struct a { char *fname; int fmode; int dev; } *uap = (struct a *)u.u_ap; register struct nameidata *ndp = &u.u_nd; if (!suser()) return; ndp->ni_nameiop = CREATE; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->fname; ip = namei(ndp); if (ip != NULL) { u.u_error = EEXIST; goto out; } if (u.u_error) return; ip = maknode(uap->fmode, ndp); if (ip == NULL) return; switch (ip->i_mode & IFMT) { case IFMT: /* used by badsect to flag bad sectors */ case IFCHR: case IFBLK: if (uap->dev) { /* * Want to be able to use this to make badblock * inodes, so don't truncate the dev number. */ ip->i_rdev = uap->dev; ip->i_dummy = 0; ip->i_flag |= IACC|IUPD|ICHG; } } out: iput(ip); } /* * link system call */ link() { register struct inode *ip, *xp; register struct a { char *target; char *linkname; } *uap = (struct a *)u.u_ap; register struct nameidata *ndp = &u.u_nd; ndp->ni_nameiop = LOOKUP | FOLLOW; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->target; ip = namei(ndp); /* well, this routine is doomed anyhow */ if (ip == NULL) return; if ((ip->i_mode&IFMT) == IFDIR && !suser()) { iput(ip); return; } if (ip->i_flags & (IMMUTABLE|APPEND)) { u.u_error = EPERM; iput(ip); return; } ip->i_nlink++; ip->i_flag |= ICHG; iupdat(ip, &time, &time, 1); iunlock(ip); ndp->ni_nameiop = CREATE; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = (caddr_t)uap->linkname; xp = namei(ndp); if (xp != NULL) { u.u_error = EEXIST; iput(xp); goto out; } if (u.u_error) goto out; if (ndp->ni_pdir->i_dev != ip->i_dev) { iput(ndp->ni_pdir); u.u_error = EXDEV; goto out; } u.u_error = direnter(ip, ndp); out: if (u.u_error) { ip->i_nlink--; ip->i_flag |= ICHG; } irele(ip); } /* * symlink -- make a symbolic link */ symlink() { register struct a { char *target; char *linkname; } *uap = (struct a *)u.u_ap; register struct inode *ip; char *tp; int c, nc; register struct nameidata *ndp = &u.u_nd; tp = uap->target; nc = 0; while (c = fubyte(tp)) { if (c < 0) { u.u_error = EFAULT; return; } tp++; nc++; } ndp->ni_nameiop = CREATE; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->linkname; ip = namei(ndp); if (ip) { iput(ip); u.u_error = EEXIST; return; } if (u.u_error) return; ip = maknode(IFLNK | 0777, ndp); if (ip == NULL) return; u.u_error = rdwri(UIO_WRITE, ip, uap->target, nc, (off_t)0, UIO_USERSPACE, IO_UNIT, (int *)0); /* handle u.u_error != 0 */ iput(ip); } /* * Unlink system call. * Hard to avoid races here, especially * in unlinking directories. */ unlink() { register struct a { char *fname; } *uap = (struct a *)u.u_ap; register struct inode *ip, *dp; register struct nameidata *ndp = &u.u_nd; ndp->ni_nameiop = DELETE | LOCKPARENT; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->fname; ip = namei(ndp); if (ip == NULL) return; dp = ndp->ni_pdir; if ((ip->i_mode&IFMT) == IFDIR && !suser()) goto out; /* * Don't unlink a mounted file. */ if (ip->i_dev != dp->i_dev) { u.u_error = EBUSY; goto out; } if ((ip->i_flags & (IMMUTABLE|APPEND)) || (dp->i_flags & APPEND)) { u.u_error = EPERM; goto out; } if (ip->i_flag&ITEXT) xuntext(ip->i_text); /* try once to free text */ if (dirremove(ndp)) { ip->i_nlink--; ip->i_flag |= ICHG; } out: if (dp == ip) irele(ip); else iput(ip); iput(dp); } /* * Seek system call */ lseek() { register struct file *fp; register struct a { int fd; off_t off; int sbase; } *uap = (struct a *)u.u_ap; if ((fp = getf(uap->fd)) == NULL) return; if (fp->f_type != DTYPE_INODE) { u.u_error = ESPIPE; return; } switch (uap->sbase) { case L_INCR: fp->f_offset += uap->off; break; case L_XTND: fp->f_offset = uap->off + ((struct inode *)fp->f_data)->i_size; break; case L_SET: fp->f_offset = uap->off; break; default: u.u_error = EINVAL; return; } u.u_r.r_off = fp->f_offset; } /* * Access system call */ saccess() { uid_t svuid; gid_t svgid; register struct inode *ip; register struct a { char *fname; int fmode; } *uap = (struct a *)u.u_ap; register struct nameidata *ndp = &u.u_nd; svuid = u.u_uid; svgid = u.u_gid; u.u_uid = u.u_ruid; u.u_gid = u.u_rgid; ndp->ni_nameiop = LOOKUP | FOLLOW; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->fname; ip = namei(ndp); if (ip != NULL) { if ((uap->fmode&R_OK) && access(ip, IREAD)) goto done; if ((uap->fmode&W_OK) && access(ip, IWRITE)) goto done; if ((uap->fmode&X_OK) && access(ip, IEXEC)) goto done; done: iput(ip); } u.u_uid = svuid; u.u_gid = svgid; } /* * Stat system call. This version follows links. */ stat() { stat1(FOLLOW); } /* * Lstat system call. This version does not follow links. */ lstat() { stat1(NOFOLLOW); } stat1(follow) int follow; { register struct inode *ip; register struct a { char *fname; struct stat *ub; } *uap = (struct a *)u.u_ap; struct stat sb; register struct nameidata *ndp = &u.u_nd; ndp->ni_nameiop = LOOKUP | follow; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->fname; ip = namei(ndp); if (ip == NULL) return; (void) ino_stat(ip, &sb); iput(ip); u.u_error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); } /* * Return target name of a symbolic link */ readlink() { register struct inode *ip; register struct a { char *name; char *buf; int count; } *uap = (struct a *)u.u_ap; register struct nameidata *ndp = &u.u_nd; int resid; ndp->ni_nameiop = LOOKUP; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->name; ip = namei(ndp); if (ip == NULL) return; if ((ip->i_mode&IFMT) != IFLNK) { u.u_error = EINVAL; goto out; } u.u_error = rdwri(UIO_READ, ip, uap->buf, uap->count, (off_t)0, UIO_USERSPACE, IO_UNIT, &resid); out: iput(ip); u.u_r.r_val1 = uap->count - resid; } /* * change flags of a file given pathname. */ chflags() { register struct inode *ip; register struct a { char *fname; u_short flags; } *uap = (struct a *)u.u_ap; register struct nameidata *ndp = &u.u_nd; ndp->ni_nameiop = LOOKUP|FOLLOW; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->fname; if ((ip = namei(ndp)) == NULL) return; u.u_error = chflags1(ip, uap->flags); iput(ip); } /* * change flags of a file given file descriptor. */ fchflags() { register struct a { int fd; u_short flags; } *uap = (struct a *)u.u_ap; register struct inode *ip; if ((ip = getinode(uap->fd)) == NULL) return; ilock(ip); u.u_error = chflags1(ip, uap->flags); iunlock(ip); } chflags1(ip, flags) register struct inode *ip; u_short flags; { struct vattr vattr; VATTR_NULL(&vattr); vattr.va_flags = flags; return(ufs_setattr(ip, &vattr)); } /* * Change mode of a file given path name. */ chmod() { register struct inode *ip; register struct a { char *fname; int fmode; } *uap = (struct a *)u.u_ap; struct vattr vattr; register struct nameidata *ndp = &u.u_nd; ndp->ni_nameiop = LOOKUP|FOLLOW; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->fname; ip = namei(ndp); if (!ip) return; VATTR_NULL(&vattr); vattr.va_mode = uap->fmode & 07777; u.u_error = ufs_setattr(ip, &vattr); iput(ip); } /* * Change mode of a file given a file descriptor. */ fchmod() { register struct a { int fd; int fmode; } *uap = (struct a *)u.u_ap; register struct inode *ip; struct vattr vattr; if ((ip = getinode(uap->fd)) == NULL) return; ilock(ip); VATTR_NULL(&vattr); vattr.va_mode = uap->fmode & 07777; u.u_error = ufs_setattr(ip, &vattr); iunlock(ip); } /* * Change the mode on a file. This routine is called from ufs_setattr. * Inode must be locked before calling. */ chmod1(ip, mode) register struct inode *ip; register int mode; { if (u.u_uid != ip->i_uid && !suser()) return(u.u_error); if (u.u_uid) { if ((ip->i_mode & IFMT) != IFDIR && (mode & ISVTX)) return(EFTYPE); if (!groupmember(ip->i_gid) && (mode & ISGID)) return(EPERM); } ip->i_mode &= ~07777; /* why? */ ip->i_mode |= mode&07777; ip->i_flag |= ICHG; if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) xuntext(ip->i_text); return (0); } /* * Set ownership given a path name. */ chown() { register struct inode *ip; register struct a { char *fname; int uid; int gid; } *uap = (struct a *)u.u_ap; register struct nameidata *ndp = &u.u_nd; struct vattr vattr; ndp->ni_nameiop = LOOKUP | NOFOLLOW; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->fname; ip = namei(ndp); if (ip == NULL) return; VATTR_NULL(&vattr); vattr.va_uid = uap->uid; vattr.va_gid = uap->gid; u.u_error = ufs_setattr(ip, &vattr); iput(ip); } /* * Set ownership given a file descriptor. */ fchown() { register struct a { int fd; int uid; int gid; } *uap = (struct a *)u.u_ap; register struct inode *ip; struct vattr vattr; if ((ip = getinode(uap->fd)) == NULL) return; ilock(ip); VATTR_NULL(&vattr); vattr.va_uid = uap->uid; vattr.va_gid = uap->gid; u.u_error = ufs_setattr(ip, &vattr); iunlock(ip); } /* * Perform chown operation on inode ip. This routine called from ufs_setattr. * inode must be locked prior to call. */ chown1(ip, uid, gid) register struct inode *ip; register int uid, gid; { int ouid, ogid; #ifdef QUOTA struct dquot **xdq; long change; #endif if (uid == -1) uid = ip->i_uid; if (gid == -1) gid = ip->i_gid; /* * If we don't own the file, are trying to change the owner * of the file, or are not a member of the target group, * the caller must be superuser or the call fails. */ if ((u.u_uid != ip->i_uid || uid != ip->i_uid || !groupmember((gid_t)gid)) && !suser()) return (u.u_error); ouid = ip->i_uid; ogid = ip->i_gid; #ifdef QUOTA QUOTAMAP(); if (ip->i_uid == uid) change = 0; else change = ip->i_size; (void) chkdq(ip, -change, 1); (void) chkiq(ip->i_dev, ip, ip->i_uid, 1); xdq = &ix_dquot[ip - inode]; dqrele(*xdq); #endif ip->i_uid = uid; ip->i_gid = gid; #ifdef QUOTA *xdq = inoquota(ip); (void) chkdq(ip, change, 1); (void) chkiq(ip->i_dev, (struct inode *)NULL, (uid_t)uid, 1); QUOTAUNMAP(); #endif if (ouid != uid || ogid != gid) ip->i_flag |= ICHG; if (ouid != uid && u.u_uid != 0) ip->i_mode &= ~ISUID; if (ogid != gid && u.u_gid != 0) ip->i_mode &= ~ISGID; return (0); } utimes() { register struct a { char *fname; struct timeval *tptr; } *uap = (struct a *)u.u_ap; register struct inode *ip; register struct nameidata *ndp = &u.u_nd; struct timeval tv[2]; struct vattr vattr; VATTR_NULL(&vattr); if (uap->tptr == NULL) { tv[0].tv_sec = tv[1].tv_sec = time.tv_sec; vattr.va_vaflags |= VA_UTIMES_NULL; } else if (u.u_error = copyin((caddr_t)uap->tptr,(caddr_t)tv,sizeof(tv))) return; ndp->ni_nameiop = LOOKUP|FOLLOW; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->fname; if ((ip = namei(ndp)) == NULL) return; vattr.va_atime = tv[0].tv_sec; vattr.va_mtime = tv[1].tv_sec; u.u_error = ufs_setattr(ip, &vattr); iput(ip); } /* * Flush any pending I/O. */ sync() { update(); } /* * Truncate a file given its path name. */ truncate() { register struct a { char *fname; off_t length; } *uap = (struct a *)u.u_ap; register struct inode *ip; register struct nameidata *ndp = &u.u_nd; struct vattr vattr; ndp->ni_nameiop = LOOKUP | FOLLOW; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->fname; ip = namei(ndp); if (ip == NULL) return; if (access(ip, IWRITE)) goto bad; VATTR_NULL(&vattr); vattr.va_size = uap->length; u.u_error = ufs_setattr(ip, &vattr); bad: iput(ip); } /* * Truncate a file given a file descriptor. */ ftruncate() { register struct a { int fd; off_t length; } *uap = (struct a *)u.u_ap; register struct inode *ip; register struct file *fp; struct vattr vattr; if ((fp = getf(uap->fd)) == NULL) return; if (!(fp->f_flag&FWRITE) || (fp->f_type != DTYPE_INODE)) { u.u_error = EINVAL; return; } ip = (struct inode *)fp->f_data; ilock(ip); VATTR_NULL(&vattr); vattr.va_size = uap->length; u.u_error = ufs_setattr(ip, &vattr); iunlock(ip); } /* * Synch an open file. */ fsync() { register struct a { int fd; } *uap = (struct a *)u.u_ap; register struct inode *ip; if ((ip = getinode(uap->fd)) == NULL) return; ilock(ip); syncip(ip); iunlock(ip); } /* * Rename system call. * rename("foo", "bar"); * is essentially * unlink("bar"); * link("foo", "bar"); * unlink("foo"); * but ``atomically''. Can't do full commit without saving state in the * inode on disk which isn't feasible at this time. Best we can do is * always guarantee the target exists. * * Basic algorithm is: * * 1) Bump link count on source while we're linking it to the * target. This also insure the inode won't be deleted out * from underneath us while we work (it may be truncated by * a concurrent `trunc' or `open' for creation). * 2) Link source to destination. If destination already exists, * delete it first. * 3) Unlink source reference to inode if still around. If a * directory was moved and the parent of the destination * is different from the source, patch the ".." entry in the * directory. * * Source and destination must either both be directories, or both * not be directories. If target is a directory, it must be empty. */ rename() { struct a { char *from; char *to; } *uap = (struct a *)u.u_ap; register struct inode *ip, *xp, *dp; struct dirtemplate dirbuf; int doingdirectory = 0, oldparent = 0, newparent = 0; register struct nameidata *ndp = &u.u_nd; int error = 0; ndp->ni_nameiop = DELETE | LOCKPARENT; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->from; ip = namei(ndp); if (ip == NULL) return; dp = ndp->ni_pdir; /* * 'from' file can not be renamed if it is immutable/appendonly or if its * parent directory is append only. */ if ((ip->i_flags & (IMMUTABLE|APPEND)) || (dp->i_flags & APPEND)) { iput(dp); if (dp == ip) irele(ip); else iput(ip); u.u_error = EPERM; return; } if ((ip->i_mode&IFMT) == IFDIR) { register struct direct *d; d = &ndp->ni_dent; /* * Avoid ".", "..", and aliases of "." for obvious reasons. */ if ((d->d_namlen == 1 && d->d_name[0] == '.') || (d->d_namlen == 2 && bcmp(d->d_name, "..", 2) == 0) || (dp == ip) || (ip->i_flag & IRENAME)) { iput(dp); if (dp == ip) irele(ip); else iput(ip); u.u_error = EINVAL; return; } ip->i_flag |= IRENAME; oldparent = dp->i_number; doingdirectory++; } iput(dp); /* * 1) Bump link count while we're moving stuff * around. If we crash somewhere before * completing our work, the link count * may be wrong, but correctable. */ ip->i_nlink++; ip->i_flag |= ICHG; iupdat(ip, &time, &time, 1); iunlock(ip); /* * When the target exists, both the directory * and target inodes are returned locked. */ ndp->ni_nameiop = CREATE | LOCKPARENT | NOCACHE; ndp->ni_dirp = (caddr_t)uap->to; xp = namei(ndp); if (u.u_error) { error = u.u_error; goto out; } dp = ndp->ni_pdir; /* * rename can not be done if 'to' file exists and is immutable/appendonly * or if the directory is append only (this is because an existing 'to' * has to be deleted first and that is illegal in an appendonly directory). */ if (xp && ((xp->i_flags & (IMMUTABLE|APPEND)) || (dp->i_flags & APPEND))) { error = EPERM; goto bad; } /* * If ".." must be changed (ie the directory gets a new * parent) then the source directory must not be in the * directory heirarchy above the target, as this would * orphan everything below the source directory. Also * the user must have write permission in the source so * as to be able to change "..". We must repeat the call * to namei, as the parent directory is unlocked by the * call to checkpath(). */ if (oldparent != dp->i_number) newparent = dp->i_number; if (doingdirectory && newparent) { if (access(ip, IWRITE)) goto bad; do { dp = ndp->ni_pdir; if (xp != NULL) iput(xp); u.u_error = checkpath(ip, dp); if (u.u_error) goto out; xp = namei(ndp); if (u.u_error) { error = u.u_error; goto out; } } while (dp != ndp->ni_pdir); } /* * 2) If target doesn't exist, link the target * to the source and unlink the source. * Otherwise, rewrite the target directory * entry to reference the source inode and * expunge the original entry's existence. */ if (xp == NULL) { if (dp->i_dev != ip->i_dev) { error = EXDEV; goto bad; } /* * Account for ".." in new directory. * When source and destination have the same * parent we don't fool with the link count. */ if (doingdirectory && newparent) { dp->i_nlink++; dp->i_flag |= ICHG; iupdat(dp, &time, &time, 1); } error = direnter(ip, ndp); if (error) goto out; } else { if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev) { error = EXDEV; goto bad; } /* * Short circuit rename(foo, foo). */ if (xp->i_number == ip->i_number) goto bad; /* * If the parent directory is "sticky", then the user must * own the parent directory, or the destination of the rename, * otherwise the destination may not be changed (except by * root). This implements append-only directories. */ if ((dp->i_mode & ISVTX) && u.u_uid != 0 && u.u_uid != dp->i_uid && xp->i_uid != u.u_uid) { error = EPERM; goto bad; } /* * Target must be empty if a directory * and have no links to it. * Also, insure source and target are * compatible (both directories, or both * not directories). */ if ((xp->i_mode&IFMT) == IFDIR) { if (!dirempty(xp, dp->i_number) || xp->i_nlink > 2) { error = ENOTEMPTY; goto bad; } if (!doingdirectory) { error = ENOTDIR; goto bad; } cacheinval(dp); } else if (doingdirectory) { error = EISDIR; goto bad; } dirrewrite(dp, ip, ndp); if (u.u_error) { error = u.u_error; goto bad1; } /* * Adjust the link count of the target to * reflect the dirrewrite above. If this is * a directory it is empty and there are * no links to it, so we can squash the inode and * any space associated with it. We disallowed * renaming over top of a directory with links to * it above, as the remaining link would point to * a directory without "." or ".." entries. */ xp->i_nlink--; if (doingdirectory) { if (--xp->i_nlink != 0) panic("rename: lnk dir"); itrunc(xp, (u_long)0); } xp->i_flag |= ICHG; iput(xp); xp = NULL; } /* * 3) Unlink the source. */ ndp->ni_nameiop = DELETE | LOCKPARENT; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->from; xp = namei(ndp); if (xp != NULL) dp = ndp->ni_pdir; else dp = NULL; /* * Insure that the directory entry still exists and has not * changed while the new name has been entered. If the source is * a file then the entry may have been unlinked or renamed. In * either case there is no further work to be done. If the source * is a directory then it cannot have been rmdir'ed; its link * count of three would cause a rmdir to fail with ENOTEMPTY. * The IRENAME flag insures that it cannot be moved by another * rename. */ if (xp != ip) { if (doingdirectory) panic("rename: lost dir entry"); } else { /* * If the source is a directory with a * new parent, the link count of the old * parent directory must be decremented * and ".." set to point to the new parent. */ if (doingdirectory && newparent) { dp->i_nlink--; dp->i_flag |= ICHG; error = rdwri(UIO_READ, xp, (caddr_t)&dirbuf, sizeof(struct dirtemplate), (off_t)0, UIO_SYSSPACE, IO_UNIT, (int *)0); if (error == 0) { if (dirbuf.dotdot_namlen != 2 || dirbuf.dotdot_name[0] != '.' || dirbuf.dotdot_name[1] != '.') { printf("rename: mangled dir\n"); } else { dirbuf.dotdot_ino = newparent; (void) rdwri(UIO_WRITE, xp, (caddr_t)&dirbuf, sizeof(struct dirtemplate), (off_t)0, UIO_SYSSPACE, IO_UNIT|IO_SYNC, (int *)0); cacheinval(dp); } } } if (dirremove(ndp)) { xp->i_nlink--; xp->i_flag |= ICHG; } xp->i_flag &= ~IRENAME; if (error == 0) /* XXX conservative */ error = u.u_error; } if (dp) iput(dp); if (xp) iput(xp); irele(ip); if (error) u.u_error = error; return; bad: iput(dp); bad1: if (xp) iput(xp); out: ip->i_nlink--; ip->i_flag |= ICHG; irele(ip); if (error) u.u_error = error; } /* * Make a new file. */ struct inode * maknode(mode, ndp) int mode; register struct nameidata *ndp; { register struct inode *ip; register struct inode *pdir = ndp->ni_pdir; #ifdef QUOTA struct dquot **xdq; #endif ip = ialloc(pdir); if (ip == NULL) { iput(pdir); return (NULL); } #ifdef QUOTA QUOTAMAP(); xdq = &ix_dquot[ip - inode]; if (*xdq != NODQUOT) panic("maknode"); #endif ip->i_flag |= IACC|IUPD|ICHG; if ((mode & IFMT) == 0) mode |= IFREG; ip->i_mode = mode & ~u.u_cmask; ip->i_nlink = 1; ip->i_uid = u.u_uid; ip->i_gid = pdir->i_gid; if (ip->i_mode & ISGID && !groupmember(ip->i_gid)) ip->i_mode &= ~ISGID; #ifdef QUOTA *xdq = inoquota(ip); QUOTAUNMAP(); #endif /* * Make sure inode goes to disk before directory entry. */ iupdat(ip, &time, &time, 1); u.u_error = direnter(ip, ndp); if (u.u_error) { /* * Write error occurred trying to update directory * so must deallocate the inode. */ ip->i_nlink = 0; ip->i_flag |= ICHG; iput(ip); return (NULL); } return (ip); } /* * A virgin directory (no blushing please). */ struct dirtemplate mastertemplate = { 0, 8, 1, ".", 0, DIRBLKSIZ - 8, 2, ".." }; /* * Mkdir system call */ mkdir() { register struct a { char *name; int dmode; } *uap = (struct a *)u.u_ap; register struct inode *ip, *dp; struct dirtemplate dirtemplate; register struct nameidata *ndp = &u.u_nd; #ifdef QUOTA struct dquot **xdq; #endif ndp->ni_nameiop = CREATE; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->name; ip = namei(ndp); if (u.u_error) return; if (ip != NULL) { iput(ip); u.u_error = EEXIST; return; } dp = ndp->ni_pdir; uap->dmode &= 0777; uap->dmode |= IFDIR; /* * Must simulate part of maknode here * in order to acquire the inode, but * not have it entered in the parent * directory. The entry is made later * after writing "." and ".." entries out. */ ip = ialloc(dp); if (ip == NULL) { iput(dp); return; } #ifdef QUOTA QUOTAMAP(); xdq = &ix_dquot[ip - inode]; if (*xdq != NODQUOT) panic("mkdir"); #endif ip->i_flag |= IACC|IUPD|ICHG; ip->i_mode = uap->dmode & ~u.u_cmask; ip->i_nlink = 2; ip->i_uid = u.u_uid; ip->i_gid = dp->i_gid; #ifdef QUOTA *xdq = inoquota(ip); QUOTAUNMAP(); #endif iupdat(ip, &time, &time, 1); /* * Bump link count in parent directory * to reflect work done below. Should * be done before reference is created * so reparation is possible if we crash. */ dp->i_nlink++; dp->i_flag |= ICHG; iupdat(dp, &time, &time, 1); /* * Initialize directory with "." * and ".." from static template. */ dirtemplate = mastertemplate; dirtemplate.dot_ino = ip->i_number; dirtemplate.dotdot_ino = dp->i_number; u.u_error = rdwri(UIO_WRITE, ip, (caddr_t)&dirtemplate, sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE, IO_UNIT|IO_SYNC, (int *)0); if (u.u_error) { dp->i_nlink--; dp->i_flag |= ICHG; goto bad; } ip->i_size = DIRBLKSIZ; /* * Directory all set up, now * install the entry for it in * the parent directory. */ u.u_error = direnter(ip, ndp); dp = NULL; if (u.u_error) { ndp->ni_nameiop = LOOKUP | NOCACHE; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->name; dp = namei(ndp); if (dp) { dp->i_nlink--; dp->i_flag |= ICHG; } } bad: /* * No need to do an explicit itrunc here, * irele will do this for us because we set * the link count to 0. */ if (u.u_error) { ip->i_nlink = 0; ip->i_flag |= ICHG; } if (dp) iput(dp); iput(ip); } /* * Rmdir system call. */ rmdir() { struct a { char *name; } *uap = (struct a *)u.u_ap; register struct inode *ip, *dp; register struct nameidata *ndp = &u.u_nd; ndp->ni_nameiop = DELETE | LOCKPARENT; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->name; ip = namei(ndp); if (ip == NULL) return; dp = ndp->ni_pdir; /* * No rmdir "." please. */ if (dp == ip) { irele(dp); iput(ip); u.u_error = EINVAL; return; } if ((ip->i_mode&IFMT) != IFDIR) { u.u_error = ENOTDIR; goto out; } /* * Don't remove a mounted on directory. */ if (ip->i_dev != dp->i_dev) { u.u_error = EBUSY; goto out; } /* * Verify the directory is empty (and valid). * (Rmdir ".." won't be valid since * ".." will contain a reference to * the current directory and thus be * non-empty.) */ if (ip->i_nlink != 2 || !dirempty(ip, dp->i_number)) { u.u_error = ENOTEMPTY; goto out; } if ((dp->i_flags & APPEND) || (ip->i_flags & (IMMUTABLE|APPEND))) { u.u_error = EPERM; goto out; } /* * Delete reference to directory before purging * inode. If we crash in between, the directory * will be reattached to lost+found, */ if (dirremove(ndp) == 0) goto out; dp->i_nlink--; dp->i_flag |= ICHG; cacheinval(dp); iput(dp); dp = NULL; /* * Truncate inode. The only stuff left * in the directory is "." and "..". The * "." reference is inconsequential since * we're quashing it. The ".." reference * has already been adjusted above. We've * removed the "." reference and the reference * in the parent directory, but there may be * other hard links so decrement by 2 and * worry about them later. */ ip->i_nlink -= 2; itrunc(ip, (u_long)0); cacheinval(ip); out: if (dp) iput(dp); iput(ip); } static struct inode * getinode(fdes) int fdes; { register struct file *fp; if ((unsigned)fdes >= NOFILE || (fp = u.u_ofile[fdes]) == NULL) { u.u_error = EBADF; return ((struct inode *)0); } if (fp->f_type != DTYPE_INODE) { u.u_error = EINVAL; return ((struct inode *)0); } return((struct inode *)fp->f_data); } /* * mode mask for creation of files */ umask() { register struct a { int mask; } *uap = (struct a *)u.u_ap; u.u_r.r_val1 = u.u_cmask; u.u_cmask = uap->mask & 07777; } namei(ndp); if (u.u_error) { error = u.u_error; goto out; } } while (dp != ndp->ni_pdir); } /* * 2) If tarsys/sys/uipc_socket.c 440 0 12 46745 5666035213 10200 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)uipc_socket.c 7.8.1 (2.11BSD GTE) 11/26/94 */ #include "param.h" #ifdef INET #include "user.h" #include "proc.h" #include "file.h" #include "mbuf.h" #include "domain.h" #include "protosw.h" #include "socket.h" #include "socketvar.h" #include "uio.h" /* * Socket operation routines. * These routines are called by the routines in * sys_socket.c or from a system process, and * implement the semantics of socket operations by * switching out to the protocol specific routines. * * TODO: * test socketpair * clean up async * out-of-band is a kludge */ /*ARGSUSED*/ socreate(dom, aso, type, proto) struct socket **aso; register int type; int proto; { register struct protosw *prp; register struct socket *so; register struct mbuf *m; register int error; if (proto) prp = pffindproto(dom, proto, type); else prp = pffindtype(dom, type); if (prp == 0) return (EPROTONOSUPPORT); if (prp->pr_type != type) return (EPROTOTYPE); m = m_getclr(M_WAIT, MT_SOCKET); so = mtod(m, struct socket *); so->so_options = 0; so->so_state = 0; so->so_type = type; if (u.u_uid == 0) so->so_state = SS_PRIV; so->so_proto = prp; error = (*prp->pr_usrreq)(so, PRU_ATTACH, (struct mbuf *)0, (struct mbuf *)proto, (struct mbuf *)0); if (error) { so->so_state |= SS_NOFDREF; sofree(so); return (error); } *aso = so; return (0); } sobind(so, nam) struct socket *so; struct mbuf *nam; { int s = splnet(); int error; error = (*so->so_proto->pr_usrreq)(so, PRU_BIND, (struct mbuf *)0, nam, (struct mbuf *)0); splx(s); return (error); } solisten(so, backlog) register struct socket *so; int backlog; { int s = splnet(), error; error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); if (error) { splx(s); return (error); } if (so->so_q == 0) { so->so_q = so; so->so_q0 = so; so->so_options |= SO_ACCEPTCONN; } if (backlog < 0) backlog = 0; so->so_qlimit = MIN(backlog, SOMAXCONN); splx(s); return (0); } sofree(so) register struct socket *so; { if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) return; if (so->so_head) { if (!soqremque(so, 0) && !soqremque(so, 1)) panic("sofree dq"); so->so_head = 0; } sbrelease(&so->so_snd); sorflush(so); (void) m_free(dtom(so)); } /* * Close a socket on last file table reference removal. * Initiate disconnect if connected. * Free socket when disconnect complete. */ soclose(so) register struct socket *so; { int s = splnet(); /* conservative */ int error = 0; if (so->so_options & SO_ACCEPTCONN) { while (so->so_q0 != so) (void) soabort(so->so_q0); while (so->so_q != so) (void) soabort(so->so_q); } if (so->so_pcb == 0) goto discard; if (so->so_state & SS_ISCONNECTED) { if ((so->so_state & SS_ISDISCONNECTING) == 0) { error = sodisconnect(so); if (error) goto drop; } if (so->so_options & SO_LINGER) { if ((so->so_state & SS_ISDISCONNECTING) && (so->so_state & SS_NBIO)) goto drop; while (so->so_state & SS_ISCONNECTED) SLEEP((caddr_t)&so->so_timeo, PZERO+1); } } drop: if (so->so_pcb) { int error2 = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); if (error == 0) error = error2; } discard: if (so->so_state & SS_NOFDREF) panic("soclose: NOFDREF"); so->so_state |= SS_NOFDREF; sofree(so); splx(s); return(error); } /* * Must be called at splnet... */ soabort(so) struct socket *so; { return ( (*so->so_proto->pr_usrreq)(so, PRU_ABORT, (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); } soaccept(so, nam) register struct socket *so; struct mbuf *nam; { int s = splnet(); int error; if ((so->so_state & SS_NOFDREF) == 0) panic("soaccept: !NOFDREF"); so->so_state &= ~SS_NOFDREF; error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, (struct mbuf *)0, nam, (struct mbuf *)0); splx(s); return (error); } soconnect(so, nam) register struct socket *so; struct mbuf *nam; { int s; int error; /* * this is done here in supervisor mode since the kernel can't access the * socket or its options. */ if (so->so_options & SO_ACCEPTCONN) return (EOPNOTSUPP); if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) return(EALREADY); s = splnet(); /* * If protocol is connection-based, can only connect once. * Otherwise, if connected, try to disconnect first. * This allows user to disconnect by connecting to, e.g., * a null address. */ if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) && ((so->so_proto->pr_flags & PR_CONNREQUIRED) || (error = sodisconnect(so)))) error = EISCONN; else error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, (struct mbuf *)0, nam, (struct mbuf *)0); /* * this is done here because the kernel mode can't get at this info without * a lot of trouble. */ if (!error) { if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) error = EINPROGRESS; } else so->so_state &= ~SS_ISCONNECTING; splx(s); return (error); } soconnect2(so1, so2) register struct socket *so1; struct socket *so2; { int s = splnet(); int error; error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2, (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0); splx(s); return (error); } sodisconnect(so) register struct socket *so; { int s = splnet(); int error; if ((so->so_state & SS_ISCONNECTED) == 0) { error = ENOTCONN; goto bad; } if (so->so_state & SS_ISDISCONNECTING) { error = EALREADY; goto bad; } error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); bad: splx(s); return (error); } /* * Send on a socket. * If send must go all at once and message is larger than * send buffering, then hard error. * Lock against other senders. * If must go all at once and not enough room now, then * inform user that this would block and do nothing. * Otherwise, if nonblocking, send as much as possible. */ sosend(so, nam, uio, flags, rights) register struct socket *so; struct mbuf *nam; register struct uio *uio; int flags; struct mbuf *rights; { struct mbuf *top = 0; register struct mbuf *m, **mp; register int space; int len, rlen = 0, error = 0, s, dontroute, first = 1; if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) return (EMSGSIZE); dontroute = (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 && (so->so_proto->pr_flags & PR_ATOMIC); u.u_ru.ru_msgsnd++; if (rights) rlen = rights->m_len; #define snderr(errno) { error = errno; splx(s); goto release; } restart: sblock(&so->so_snd); do { s = splnet(); if (so->so_state & SS_CANTSENDMORE) snderr(EPIPE); if (so->so_error) { error = so->so_error; so->so_error = 0; /* ??? */ splx(s); goto release; } if ((so->so_state & SS_ISCONNECTED) == 0) { if (so->so_proto->pr_flags & PR_CONNREQUIRED) snderr(ENOTCONN); if (nam == 0) snderr(EDESTADDRREQ); } if (flags & MSG_OOB) space = 1024; else { space = sbspace(&so->so_snd); if (space <= rlen || (sosendallatonce(so) && space < uio->uio_resid + rlen) || (uio->uio_resid >= CLBYTES && space < CLBYTES && so->so_snd.sb_cc >= CLBYTES && (so->so_state & SS_NBIO) == 0)) { if (so->so_state & SS_NBIO) { if (first) error = EWOULDBLOCK; splx(s); goto release; } sbunlock(&so->so_snd); sbwait(&so->so_snd); splx(s); goto restart; } } splx(s); mp = ⊤ space -= rlen; while (space > 0) { MGET(m, M_WAIT, MT_DATA); if (uio->uio_resid >= CLBYTES / 2 && space >= CLBYTES) { MCLGET(m); if (m->m_len != CLBYTES) goto nopages; len = MIN(CLBYTES, uio->uio_resid); space -= CLBYTES; } else { nopages: len = MIN(MIN(MLEN, uio->uio_resid), space); space -= len; } error = uiomove(mtod(m, caddr_t), len, uio); m->m_len = len; *mp = m; if (error) goto release; mp = &m->m_next; if (uio->uio_resid == 0) break; } if (dontroute) so->so_options |= SO_DONTROUTE; s = splnet(); /* XXX */ error = (*so->so_proto->pr_usrreq)(so, (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND, top, (caddr_t)nam, rights); splx(s); if (dontroute) so->so_options &= ~SO_DONTROUTE; rights = 0; rlen = 0; top = 0; first = 0; if (error) break; } while (uio->uio_resid); release: sbunlock(&so->so_snd); if (top) m_freem(top); if (error == EPIPE) NETPSIGNAL(u.u_procp, SIGPIPE); return (error); } /* * Implement receive operations on a socket. * We depend on the way that records are added to the sockbuf * by sbappend*. In particular, each record (mbufs linked through m_next) * must begin with an address if the protocol so specifies, * followed by an optional mbuf containing access rights if supported * by the protocol, and then zero or more mbufs of data. * In order to avoid blocking network interrupts for the entire time here, * we splx() while doing the actual copy to user space. * Although the sockbuf is locked, new data may still be appended, * and thus we must maintain consistency of the sockbuf during that time. */ soreceive(so, aname, uio, flags, rightsp) register struct socket *so; struct mbuf **aname; register struct uio *uio; int flags; struct mbuf **rightsp; { register struct mbuf *m; register int len, error = 0, s, offset; struct protosw *pr = so->so_proto; struct mbuf *nextrecord; int moff; if (rightsp) *rightsp = 0; if (aname) *aname = 0; if (flags & MSG_OOB) { m = m_get(M_WAIT, MT_DATA); error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m, (struct mbuf *)(flags & MSG_PEEK), (struct mbuf *)0); if (error) goto bad; do { len = uio->uio_resid; if (len > m->m_len) len = m->m_len; error = uiomove(mtod(m, caddr_t), (int)len, uio); m = m_free(m); } while (uio->uio_resid && error == 0 && m); bad: if (m) m_freem(m); return (error); } restart: sblock(&so->so_rcv); s = splnet(); if (so->so_rcv.sb_cc == 0) { if (so->so_error) { error = so->so_error; so->so_error = 0; goto release; } if (so->so_state & SS_CANTRCVMORE) goto release; if ((so->so_state & SS_ISCONNECTED) == 0 && (so->so_proto->pr_flags & PR_CONNREQUIRED)) { error = ENOTCONN; goto release; } if (uio->uio_resid == 0) goto release; if (so->so_state & SS_NBIO) { error = EWOULDBLOCK; goto release; } sbunlock(&so->so_rcv); sbwait(&so->so_rcv); splx(s); goto restart; } u.u_ru.ru_msgrcv++; m = so->so_rcv.sb_mb; if (m == 0) panic("receive 1"); nextrecord = m->m_act; if (pr->pr_flags & PR_ADDR) { if (m->m_type != MT_SONAME) panic("receive 1a"); if (flags & MSG_PEEK) { if (aname) *aname = m_copy(m, 0, m->m_len); m = m->m_next; } else { sbfree(&so->so_rcv, m); if (aname) { *aname = m; m = m->m_next; (*aname)->m_next = 0; so->so_rcv.sb_mb = m; } else { MFREE(m, so->so_rcv.sb_mb); m = so->so_rcv.sb_mb; } if (m) m->m_act = nextrecord; } } if (m && m->m_type == MT_RIGHTS) { if ((pr->pr_flags & PR_RIGHTS) == 0) panic("receive 2"); if (flags & MSG_PEEK) { if (rightsp) *rightsp = m_copy(m, 0, m->m_len); m = m->m_next; } else { sbfree(&so->so_rcv, m); if (rightsp) { *rightsp = m; so->so_rcv.sb_mb = m->m_next; m->m_next = 0; m = so->so_rcv.sb_mb; } else { MFREE(m, so->so_rcv.sb_mb); m = so->so_rcv.sb_mb; } if (m) m->m_act = nextrecord; } } moff = 0; offset = 0; while (m && uio->uio_resid && error == 0) { if (m->m_type != MT_DATA && m->m_type != MT_HEADER) panic("receive 3"); len = uio->uio_resid; so->so_state &= ~SS_RCVATMARK; if (so->so_oobmark && len > so->so_oobmark - offset) len = so->so_oobmark - offset; if (len > m->m_len - moff) len = m->m_len - moff; splx(s); error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio); s = splnet(); if (len == m->m_len - moff) { if (flags & MSG_PEEK) { m = m->m_next; moff = 0; } else { nextrecord = m->m_act; sbfree(&so->so_rcv, m); MFREE(m, so->so_rcv.sb_mb); m = so->so_rcv.sb_mb; if (m) m->m_act = nextrecord; } } else { if (flags & MSG_PEEK) moff += len; else { m->m_off += len; m->m_len -= len; so->so_rcv.sb_cc -= len; } } if (so->so_oobmark) { if ((flags & MSG_PEEK) == 0) { so->so_oobmark -= len; if (so->so_oobmark == 0) { so->so_state |= SS_RCVATMARK; break; } } else offset += len; } } if ((flags & MSG_PEEK) == 0) { if (m == 0) so->so_rcv.sb_mb = nextrecord; else if (pr->pr_flags & PR_ATOMIC) (void) sbdroprecord(&so->so_rcv); if (pr->pr_flags & PR_WANTRCVD && so->so_pcb) (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); if (error == 0 && rightsp && *rightsp && pr->pr_domain->dom_externalize) error = (*pr->pr_domain->dom_externalize)(*rightsp); } release: sbunlock(&so->so_rcv); splx(s); return (error); } soshutdown(so, how) register struct socket *so; register int how; { register struct protosw *pr = so->so_proto; how++; if (how & FREAD) sorflush(so); if (how & FWRITE) return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN, (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); return (0); } sorflush(so) register struct socket *so; { register struct sockbuf *sb = &so->so_rcv; register struct protosw *pr = so->so_proto; register int s; struct sockbuf asb; sblock(sb); s = splimp(); socantrcvmore(so); sbunlock(sb); asb = *sb; bzero((caddr_t)sb, sizeof (*sb)); splx(s); if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose) (*pr->pr_domain->dom_dispose)(asb.sb_mb); sbrelease(&asb); } sosetopt(so, level, optname, m0) register struct socket *so; int level, optname; struct mbuf *m0; { int error = 0; register struct mbuf *m = m0; /* we make a copy because the kernel is faking the m0 mbuf and we have to * have something for the m_free's to work with */ if (m0) m = m0 = m_copy(m0, 0, M_COPYALL); if (level != SOL_SOCKET) { if (so->so_proto && so->so_proto->pr_ctloutput) return ((*so->so_proto->pr_ctloutput) (PRCO_SETOPT, so, level, optname, &m0)); error = ENOPROTOOPT; } else { switch (optname) { case SO_LINGER: if (m == NULL || m->m_len != sizeof (struct linger)) { error = EINVAL; goto bad; } so->so_linger = mtod(m, struct linger *)->l_linger; /* fall thru... */ case SO_DEBUG: case SO_KEEPALIVE: case SO_DONTROUTE: case SO_USELOOPBACK: case SO_BROADCAST: case SO_REUSEADDR: case SO_OOBINLINE: if (m == NULL || m->m_len < sizeof (int)) { error = EINVAL; goto bad; } if (*mtod(m, int *)) so->so_options |= optname; else so->so_options &= ~optname; break; case SO_SNDBUF: case SO_RCVBUF: case SO_SNDLOWAT: case SO_RCVLOWAT: case SO_SNDTIMEO: case SO_RCVTIMEO: if (m == NULL || m->m_len < sizeof (int)) { error = EINVAL; goto bad; } switch (optname) { case SO_SNDBUF: case SO_RCVBUF: if (sbreserve(optname == SO_SNDBUF ? &so->so_snd : &so->so_rcv, *mtod(m, int *)) == 0) { error = ENOBUFS; goto bad; } break; case SO_SNDLOWAT: so->so_snd.sb_lowat = *mtod(m, int *); break; case SO_RCVLOWAT: so->so_rcv.sb_lowat = *mtod(m, int *); break; case SO_SNDTIMEO: so->so_snd.sb_timeo = *mtod(m, int *); break; case SO_RCVTIMEO: so->so_rcv.sb_timeo = *mtod(m, int *); break; } break; default: error = ENOPROTOOPT; break; } } bad: if (m) (void) m_free(m); return (error); } sogetopt(so, level, optname, mp) register struct socket *so; int level, optname; struct mbuf **mp; { register struct mbuf *m; if (level != SOL_SOCKET) { if (so->so_proto && so->so_proto->pr_ctloutput) { return ((*so->so_proto->pr_ctloutput) (PRCO_GETOPT, so, level, optname, mp)); } else return (ENOPROTOOPT); } else { m = m_get(M_WAIT, MT_SOOPTS); m->m_len = sizeof (int); switch (optname) { case SO_LINGER: m->m_len = sizeof (struct linger); mtod(m, struct linger *)->l_onoff = so->so_options & SO_LINGER; mtod(m, struct linger *)->l_linger = so->so_linger; break; case SO_USELOOPBACK: case SO_DONTROUTE: case SO_DEBUG: case SO_KEEPALIVE: case SO_REUSEADDR: case SO_BROADCAST: case SO_OOBINLINE: *mtod(m, int *) = so->so_options & optname; break; case SO_TYPE: *mtod(m, int *) = so->so_type; break; case SO_ERROR: *mtod(m, int *) = so->so_error; so->so_error = 0; break; case SO_SNDBUF: *mtod(m, int *) = so->so_snd.sb_hiwat; break; case SO_RCVBUF: *mtod(m, int *) = so->so_rcv.sb_hiwat; break; case SO_SNDLOWAT: *mtod(m, int *) = so->so_snd.sb_lowat; break; case SO_RCVLOWAT: *mtod(m, int *) = so->so_rcv.sb_lowat; break; case SO_SNDTIMEO: *mtod(m, int *) = so->so_snd.sb_timeo; break; case SO_RCVTIMEO: *mtod(m, int *) = so->so_rcv.sb_timeo; break; default: (void)m_free(m); return (ENOPROTOOPT); } *mp = m; return (0); } } sohasoutofband(so) register struct socket *so; { register struct proc *p; if (so->so_pgrp < 0) GSIGNAL(-so->so_pgrp, SIGURG); else if (so->so_pgrp > 0 && (p = (struct proc *)NETPFIND(so->so_pgrp)) != 0) NETPSIGNAL(p, SIGURG); if (so->so_rcv.sb_sel) { SELWAKEUP(so->so_rcv.sb_sel, (long)(so->so_rcv.sb_flags & SB_COLL)); so->so_rcv.sb_sel = 0; so->so_rcv.sb_flags &= ~SB_COLL; } } /* * this routine was extracted from the accept() call in uipc_sys.c to * do the initial accept processing in the supervisor rather than copying * the socket struct back and forth. */ soacc1(so) register struct socket *so; { if ((so->so_options & SO_ACCEPTCONN) == 0) return(u.u_error = EINVAL); if ((so->so_state & SS_NBIO) && so->so_qlen == 0) return(u.u_error = EWOULDBLOCK); while (so->so_qlen == 0 && so->so_error == 0) { if (so->so_state & SS_CANTRCVMORE) { so->so_error = ECONNABORTED; break; } SLEEP(&so->so_timeo, PZERO+1); } if (so->so_error) { u.u_error = so->so_error; so->so_error = 0; return(u.u_error); } return(0); } /* * used to dequeue a connection request. the panic on nothing left is * done in the kernel when we return 0. */ struct socket * asoqremque(so, n) struct socket *so; int n; { register struct socket *aso; aso = so->so_q; if (soqremque(aso, n) == 0) return(0); return(aso); } /* * this is the while loop from connect(), the setjmp has been done in * kernel, so we just wait for isconnecting to go away. */ connwhile(so) register struct socket *so; { while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) SLEEP(&so->so_timeo, PZERO+1); u.u_error = so->so_error; so->so_error = 0; so->so_state &= ~SS_ISCONNECTING; return(u.u_error); } sogetnam(so, m) register struct socket *so; struct mbuf *m; { return(u.u_error=(*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0)); } sogetpeer(so, m) register struct socket *so; struct mbuf *m; { if ((so->so_state & SS_ISCONNECTED) == 0) return(u.u_error = ENOTCONN); return(u.u_error=(*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0)); } #endif nded, * and thus we must msys/sys/uipc_socket2.c 440 0 12 35621 4236457740 10256 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)uipc_socket2.c 7.3 (Berkeley) 1/28/88 */ #include "param.h" #include "systm.h" #include "user.h" #include "proc.h" #include "file.h" #include "inode.h" #include "buf.h" #include "mbuf.h" #include "protosw.h" #include "socket.h" #include "socketvar.h" /* * Primitive routines for operating on sockets and socket buffers */ /* * Procedures to manipulate state flags of socket * and do appropriate wakeups. Normal sequence from the * active (originating) side is that soisconnecting() is * called during processing of connect() call, * resulting in an eventual call to soisconnected() if/when the * connection is established. When the connection is torn down * soisdisconnecting() is called during processing of disconnect() call, * and soisdisconnected() is called when the connection to the peer * is totally severed. The semantics of these routines are such that * connectionless protocols can call soisconnected() and soisdisconnected() * only, bypassing the in-progress calls when setting up a ``connection'' * takes no time. * * From the passive side, a socket is created with * two queues of sockets: so_q0 for connections in progress * and so_q for connections already made and awaiting user acceptance. * As a protocol is preparing incoming connections, it creates a socket * structure queued on so_q0 by calling sonewconn(). When the connection * is established, soisconnected() is called, and transfers the * socket structure to so_q, making it available to accept(). * * If a socket is closed with sockets on either * so_q0 or so_q, these sockets are dropped. * * If higher level protocols are implemented in * the kernel, the wakeups done here will sometimes * cause software-interrupt process scheduling. */ soisconnecting(so) register struct socket *so; { so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING); so->so_state |= SS_ISCONNECTING; WAKEUP((caddr_t)&so->so_timeo); } soisconnected(so) register struct socket *so; { register struct socket *head = so->so_head; if (head) { if (soqremque(so, 0) == 0) panic("soisconnected"); soqinsque(head, so, 1); sorwakeup(head); WAKEUP((caddr_t)&head->so_timeo); } so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING); so->so_state |= SS_ISCONNECTED; WAKEUP((caddr_t)&so->so_timeo); sorwakeup(so); sowwakeup(so); } soisdisconnecting(so) register struct socket *so; { so->so_state &= ~SS_ISCONNECTING; so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE); WAKEUP((caddr_t)&so->so_timeo); sowwakeup(so); sorwakeup(so); } soisdisconnected(so) register struct socket *so; { so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE); WAKEUP((caddr_t)&so->so_timeo); sowwakeup(so); sorwakeup(so); } /* * When an attempt at a new connection is noted on a socket * which accepts connections, sonewconn is called. If the * connection is possible (subject to space constraints, etc.) * then we allocate a new structure, properly linked into the * data structure of the original socket, and return this. */ struct socket * sonewconn(head) register struct socket *head; { register struct socket *so; register struct mbuf *m; if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2) goto bad; m = m_getclr(M_DONTWAIT, MT_SOCKET); if (m == NULL) goto bad; so = mtod(m, struct socket *); so->so_type = head->so_type; so->so_options = head->so_options &~ SO_ACCEPTCONN; so->so_linger = head->so_linger; so->so_state = head->so_state | SS_NOFDREF; so->so_proto = head->so_proto; so->so_timeo = head->so_timeo; so->so_pgrp = head->so_pgrp; soqinsque(head, so, 0); if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH, (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)) { (void) soqremque(so, 0); (void) m_free(m); goto bad; } return (so); bad: return ((struct socket *)0); } soqinsque(head, so, q) register struct socket *head, *so; int q; { so->so_head = head; if (q == 0) { head->so_q0len++; so->so_q0 = head->so_q0; head->so_q0 = so; } else { head->so_qlen++; so->so_q = head->so_q; head->so_q = so; } } soqremque(so, q) register struct socket *so; int q; { register struct socket *head, *prev, *next; head = so->so_head; prev = head; for (;;) { next = q ? prev->so_q : prev->so_q0; if (next == so) break; if (next == head) return (0); prev = next; } if (q == 0) { prev->so_q0 = next->so_q0; head->so_q0len--; } else { prev->so_q = next->so_q; head->so_qlen--; } next->so_q0 = next->so_q = 0; next->so_head = 0; return (1); } /* * Socantsendmore indicates that no more data will be sent on the * socket; it would normally be applied to a socket when the user * informs the system that no more data is to be sent, by the protocol * code (in case PRU_SHUTDOWN). Socantrcvmore indicates that no more data * will be received, and will normally be applied to the socket by a * protocol when it detects that the peer will send no more data. * Data queued for reading in the socket may yet be read. */ socantsendmore(so) struct socket *so; { so->so_state |= SS_CANTSENDMORE; sowwakeup(so); } socantrcvmore(so) struct socket *so; { so->so_state |= SS_CANTRCVMORE; sorwakeup(so); } /* * Socket select/wakeup routines. */ /* * Queue a process for a select on a socket buffer. */ sbselqueue(sb) register struct sockbuf *sb; { register struct proc *p; extern int selwait; if ((p = sb->sb_sel) && (caddr_t)mfkd(&p->p_wchan) == (caddr_t)&selwait) sb->sb_flags |= SB_COLL; else sb->sb_sel = u.u_procp; } /* * Wait for data to arrive at/drain from a socket buffer. */ sbwait(sb) register struct sockbuf *sb; { sb->sb_flags |= SB_WAIT; SLEEP((caddr_t)&sb->sb_cc, PZERO+1); } /* * Wakeup processes waiting on a socket buffer. */ sbwakeup(sb) register struct sockbuf *sb; { if (sb->sb_sel) { SELWAKEUP(sb->sb_sel, (long)(sb->sb_flags & SB_COLL)); sb->sb_sel = 0; sb->sb_flags &= ~SB_COLL; } if (sb->sb_flags & SB_WAIT) { sb->sb_flags &= ~SB_WAIT; WAKEUP((caddr_t)&sb->sb_cc); } } /* * Wakeup socket readers and writers. * Do asynchronous notification via SIGIO * if the socket has the SS_ASYNC flag set. */ sowakeup(so, sb) register struct socket *so; struct sockbuf *sb; { register struct proc *p; sbwakeup(sb); if (so->so_state & SS_ASYNC) { if (so->so_pgrp < 0) GSIGNAL(-so->so_pgrp, SIGIO); else if (so->so_pgrp > 0 && (p = (struct proc *)NETPFIND(so->so_pgrp)) != 0) NETPSIGNAL(p, SIGIO); } } /* * Socket buffer (struct sockbuf) utility routines. * * Each socket contains two socket buffers: one for sending data and * one for receiving data. Each buffer contains a queue of mbufs, * information about the number of mbufs and amount of data in the * queue, and other fields allowing select() statements and notification * on data availability to be implemented. * * Data stored in a socket buffer is maintained as a list of records. * Each record is a list of mbufs chained together with the m_next * field. Records are chained together with the m_act field. The upper * level routine soreceive() expects the following conventions to be * observed when placing information in the receive buffer: * * 1. If the protocol requires each message be preceded by the sender's * name, then a record containing that name must be present before * any associated data (mbuf's must be of type MT_SONAME). * 2. If the protocol supports the exchange of ``access rights'' (really * just additional data associated with the message), and there are * ``rights'' to be received, then a record containing this data * should be present (mbuf's must be of type MT_RIGHTS). * 3. If a name or rights record exists, then it must be followed by * a data record, perhaps of zero length. * * Before using a new socket structure it is first necessary to reserve * buffer space to the socket, by calling sbreserve(). This should commit * some of the available buffer space in the system buffer pool for the * socket (currently, it does nothing but enforce limits). The space * should be released by calling sbrelease() when the socket is destroyed. */ soreserve(so, sndcc, rcvcc) register struct socket *so; int sndcc, rcvcc; { if (sbreserve(&so->so_snd, sndcc) == 0) goto bad; if (sbreserve(&so->so_rcv, rcvcc) == 0) goto bad2; return (0); bad2: sbrelease(&so->so_snd); bad: return (ENOBUFS); } /* * Allot mbufs to a sockbuf. * Attempt to scale cc so that mbcnt doesn't become limiting * if buffering efficiency is near the normal case. */ sbreserve(sb, cc) struct sockbuf *sb; { #ifdef FIX_43 if ((unsigned) cc > (unsigned)SB_MAX * CLBYTES / (2 * MSIZE + CLBYTES)) return (0); #else if ((unsigned) cc > (unsigned)SB_MAX) return (0); #endif sb->sb_hiwat = cc; sb->sb_mbmax = MIN(cc * 2, SB_MAX); return (1); } /* * Free mbufs held by a socket, and reserved mbuf space. */ sbrelease(sb) struct sockbuf *sb; { sbflush(sb); sb->sb_hiwat = sb->sb_mbmax = 0; } /* * Routines to add and remove * data from an mbuf queue. * * The routines sbappend() or sbappendrecord() are normally called to * append new mbufs to a socket buffer, after checking that adequate * space is available, comparing the function sbspace() with the amount * of data to be added. sbappendrecord() differs from sbappend() in * that data supplied is treated as the beginning of a new record. * To place a sender's address, optional access rights, and data in a * socket receive buffer, sbappendaddr() should be used. To place * access rights and data in a socket receive buffer, sbappendrights() * should be used. In either case, the new data begins a new record. * Note that unlike sbappend() and sbappendrecord(), these routines check * for the caller that there will be enough space to store the data. * Each fails if there is not enough space, or if it cannot find mbufs * to store additional information in. * * Reliable protocols may use the socket send buffer to hold data * awaiting acknowledgement. Data is normally copied from a socket * send buffer in a protocol with m_copy for output to a peer, * and then removing the data from the socket buffer with sbdrop() * or sbdroprecord() when the data is acknowledged by the peer. */ /* * Append mbuf chain m to the last record in the * socket buffer sb. The additional space associated * the mbuf chain is recorded in sb. Empty mbufs are * discarded and mbufs are compacted where possible. */ sbappend(sb, m) struct sockbuf *sb; struct mbuf *m; { register struct mbuf *n; if (m == 0) return; if (n = sb->sb_mb) { while (n->m_act) n = n->m_act; while (n->m_next) n = n->m_next; } sbcompress(sb, m, n); } /* * As above, except the mbuf chain * begins a new record. */ sbappendrecord(sb, m0) register struct sockbuf *sb; register struct mbuf *m0; { register struct mbuf *m; if (m0 == 0) return; if (m = sb->sb_mb) while (m->m_act) m = m->m_act; /* * Put the first mbuf on the queue. * Note this permits zero length records. */ sballoc(sb, m0); if (m) m->m_act = m0; else sb->sb_mb = m0; m = m0->m_next; m0->m_next = 0; sbcompress(sb, m, m0); } /* * Append address and data, and optionally, rights * to the receive queue of a socket. Return 0 if * no space in sockbuf or insufficient mbufs. */ sbappendaddr(sb, asa, m0, rights0) register struct sockbuf *sb; struct sockaddr *asa; struct mbuf *rights0, *m0; { register struct mbuf *m, *n; int space = sizeof (*asa); for (m = m0; m; m = m->m_next) space += m->m_len; if (rights0) space += rights0->m_len; if (space > sbspace(sb)) return (0); MGET(m, M_DONTWAIT, MT_SONAME); if (m == 0) return (0); *mtod(m, struct sockaddr *) = *asa; m->m_len = sizeof (*asa); if (rights0 && rights0->m_len) { m->m_next = m_copy(rights0, 0, rights0->m_len); if (m->m_next == 0) { m_freem(m); return (0); } sballoc(sb, m->m_next); } sballoc(sb, m); if (n = sb->sb_mb) { while (n->m_act) n = n->m_act; n->m_act = m; } else sb->sb_mb = m; if (m->m_next) m = m->m_next; if (m0) sbcompress(sb, m0, m); return (1); } sbappendrights(sb, m0, rights) struct sockbuf *sb; struct mbuf *rights, *m0; { register struct mbuf *m, *n; int space = 0; if (rights == 0) panic("sbappendrights"); for (m = m0; m; m = m->m_next) space += m->m_len; space += rights->m_len; if (space > sbspace(sb)) return (0); m = m_copy(rights, 0, rights->m_len); if (m == 0) return (0); sballoc(sb, m); if (n = sb->sb_mb) { while (n->m_act) n = n->m_act; n->m_act = m; } else sb->sb_mb = m; if (m0) sbcompress(sb, m0, m); return (1); } /* * Compress mbuf chain m into the socket * buffer sb following mbuf n. If n * is null, the buffer is presumed empty. */ sbcompress(sb, m, n) register struct sockbuf *sb; register struct mbuf *m, *n; { while (m) { if (m->m_len == 0) { m = m_free(m); continue; } if (n && n->m_off <= MMAXOFF && m->m_off <= MMAXOFF && (n->m_off + n->m_len + m->m_len) <= MMAXOFF && n->m_type == m->m_type) { bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len, (unsigned)m->m_len); n->m_len += m->m_len; sb->sb_cc += m->m_len; m = m_free(m); continue; } sballoc(sb, m); if (n) n->m_next = m; else sb->sb_mb = m; n = m; m = m->m_next; n->m_next = 0; } } /* * Free all mbufs in a sockbuf. * Check that all resources are reclaimed. */ sbflush(sb) register struct sockbuf *sb; { if (sb->sb_flags & SB_LOCK) panic("sbflush"); while (sb->sb_mbcnt) sbdrop(sb, (int)sb->sb_cc); if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb) panic("sbflush 2"); } /* * Drop data from (the front of) a sockbuf. */ sbdrop(sb, len) register struct sockbuf *sb; register int len; { register struct mbuf *m, *mn; struct mbuf *next; next = (m = sb->sb_mb) ? m->m_act : 0; while (len > 0) { if (m == 0) { if (next == 0) panic("sbdrop"); m = next; next = m->m_act; continue; } if (m->m_len > len) { m->m_len -= len; m->m_off += len; sb->sb_cc -= len; break; } len -= m->m_len; sbfree(sb, m); MFREE(m, mn); m = mn; } while (m && m->m_len == 0) { sbfree(sb, m); MFREE(m, mn); m = mn; } if (m) { sb->sb_mb = m; m->m_act = next; } else sb->sb_mb = next; } /* * Drop a record off the front of a sockbuf * and move the next record to the front. */ sbdroprecord(sb) register struct sockbuf *sb; { register struct mbuf *m, *mn; m = sb->sb_mb; if (m) { sb->sb_mb = m->m_act; do { sbfree(sb, m); MFREE(m, mn); } while (m = mn); } } ad->so_q0len--; } else { prev->so_q = next->so_q; head->so_qlen--; } next->so_q0 = next->so_q = 0; nextsys/sys/uipc_domain.c 440 0 12 7726 6036410124 10121 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)uipc_domain.c 7.2.1 (2.11BSD) 1995/10/09 */ #include "param.h" #ifdef INET #include "socket.h" #include "protosw.h" #include "domain.h" #include "time.h" #include "kernel.h" #include "errno.h" #define ADDDOMAIN(x) { \ extern struct domain x/**/domain; \ x/**/domain.dom_next = domains; \ domains = &x/**/domain; \ } domaininit() { register struct domain *dp; register struct protosw *pr; #ifndef lint ADDDOMAIN(unix); #ifdef INET ADDDOMAIN(inet); #endif #ifdef NS ADDDOMAIN(ns); #endif #include "imp.h" #if NIMP > 0 ADDDOMAIN(imp); #endif #endif for (dp = domains; dp; dp = dp->dom_next) { if (dp->dom_init) (*dp->dom_init)(); for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_init) (*pr->pr_init)(); } null_init(); pffasttimo(); pfslowtimo(); } struct protosw * pffindtype(family, type) int family, type; { register struct domain *dp; register struct protosw *pr; for (dp = domains; dp; dp = dp->dom_next) if (dp->dom_family == family) goto found; return (0); found: for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_type && pr->pr_type == type) return (pr); return (0); } struct protosw * pffindproto(family, protocol, type) int family, protocol, type; { register struct domain *dp; register struct protosw *pr; struct protosw *maybe = 0; if (family == 0) return (0); for (dp = domains; dp; dp = dp->dom_next) if (dp->dom_family == family) goto found; return (0); found: for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) { if ((pr->pr_protocol == protocol) && (pr->pr_type == type)) return (pr); if (type == SOCK_RAW && pr->pr_type == SOCK_RAW && pr->pr_protocol == 0 && maybe == (struct protosw *)0) maybe = pr; } return (maybe); } net_sysctl(name, namelen, oldp, oldlenp, newp, newlen) int *name; u_int namelen; void *oldp; size_t *oldlenp; void *newp; size_t newlen; { register struct domain *dp; register struct protosw *pr; int family, protocol; /* * All sysctl names at this level are nonterminal; * next two components are protocol family and protocol number, * then at least one addition component. */ if (namelen < 3) return (EISDIR); /* overloaded */ family = name[0]; protocol = name[1]; if (family == 0) return (0); for (dp = domains; dp; dp = dp->dom_next) if (dp->dom_family == family) goto found; return (ENOPROTOOPT); found: for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_protocol == protocol && pr->pr_sysctl) return ((*pr->pr_sysctl)(name + 2, namelen - 2, oldp, oldlenp, newp, newlen)); return (ENOPROTOOPT); } pfctlinput(cmd, sa) int cmd; struct sockaddr *sa; { register struct domain *dp; register struct protosw *pr; for (dp = domains; dp; dp = dp->dom_next) for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_ctlinput) (*pr->pr_ctlinput)(cmd, sa); } extern int hz; pfslowtimo() { register struct domain *dp; register struct protosw *pr; for (dp = domains; dp; dp = dp->dom_next) for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_slowtimo) (*pr->pr_slowtimo)(); TIMEOUT(pfslowtimo, (caddr_t)0, hz/PR_SLOWHZ); } pffasttimo() { register struct domain *dp; register struct protosw *pr; for (dp = domains; dp; dp = dp->dom_next) for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_fasttimo) (*pr->pr_fasttimo)(); TIMEOUT(pffasttimo, (caddr_t)0, hz/PR_FASTHZ); } #endif |= SB_COLL; else sb->sb_sel = u.u_procsys/sys/sys_socket.c 440 0 12 5333 5316454037 10023 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)sys_socket.c 7.2 (Berkeley) 3/31/88 */ #include "param.h" #ifdef INET #include "systm.h" #include "user.h" #include "file.h" #include "mbuf.h" #include "protosw.h" #include "socket.h" #include "socketvar.h" #include "ioctl.h" #include "stat.h" #include "../net/if.h" #include "../net/route.h" /*ARGSUSED*/ soo_ioctl(so, cmd, data) struct socket *so; /* remember to have the kentry routine pass */ /* a socket NOT a file pointer */ int cmd; register caddr_t data; { switch (cmd) { case FIONBIO: if (*(int *)data) so->so_state |= SS_NBIO; else so->so_state &= ~SS_NBIO; return (0); case FIOASYNC: if (*(int *)data) so->so_state |= SS_ASYNC; else so->so_state &= ~SS_ASYNC; return (0); case FIONREAD: *(long *)data = so->so_rcv.sb_cc; return (0); case SIOCSPGRP: so->so_pgrp = *(int *)data; return (0); case SIOCGPGRP: *(int *)data = so->so_pgrp; return (0); case SIOCATMARK: *(int *)data = (so->so_state&SS_RCVATMARK) != 0; return (0); } /* * Interface/routing/protocol specific ioctls: * interface and routing ioctls should have a * different entry since a socket's unnecessary */ #define cmdbyte(x) (((x) >> 8) & 0xff) if (cmdbyte(cmd) == 'i') return(u.u_error = ifioctl(so, cmd, data)); if (cmdbyte(cmd) == 'r') return(u.u_error = rtioctl(cmd, data)); return(u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_CONTROL, (struct mbuf *)cmd, (struct mbuf *)data, (struct mbuf *)0)); } soo_select(so, which) register struct socket *so; /* kentry() must pass socket not file */ int which; { register int s = splnet(); switch (which) { case FREAD: if (soreadable(so)) { splx(s); return (1); } sbselqueue(&so->so_rcv); break; case FWRITE: if (sowriteable(so)) { splx(s); return (1); } sbselqueue(&so->so_snd); break; case 0: if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) { splx(s); return (1); } sbselqueue(&so->so_rcv); break; } splx(s); return (0); } /*ARGSUSED*/ soo_stat(so, ub) register struct socket *so; register struct stat *ub; { bzero((caddr_t)ub, sizeof (*ub)); return ((*so->so_proto->pr_usrreq)(so, PRU_SENSE, (struct mbuf *)ub, (struct mbuf *)0, (struct mbuf *)0)); } #endif include "ioctl.h" #include "stat.h" #include "../net/if.h" #include "../net/route.h" /*ARGSUSED*/ soo_ioctl(so, cmd, data) struct socket *so; /* remember to have the kentry routine pass */ /* a socket NOT a file pointer */ int cmd; register caddr_t data; { switch (cmd) { case sys/sys/uipc_usrreq.c 440 0 12 34564 5514434374 10230 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)uipc_usrreq.c 7.1.1 (2.11BSD GTE) 12/31/93 */ #include "param.h" #include "user.h" #include "mbuf.h" #include "domain.h" #include "protosw.h" #include "socket.h" #include "socketvar.h" #include "namei.h" #include "unpcb.h" #include "un.h" #include "inode.h" #include "file.h" #include "stat.h" /* * Unix communications domain. * * TODO: * SEQPACKET, RDM * rethink name space problems * need a proper out-of-band */ struct sockaddr sun_noname = { AF_UNIX }; ino_t unp_ino; /* prototype for fake inode numbers */ #ifdef pdp11 extern void unpdisc(), unpgc1(); extern int fadjust(); #endif /*ARGSUSED*/ uipc_usrreq(so, req, m, nam, rights) struct socket *so; int req; struct mbuf *m, *nam, *rights; { struct unpcb *unp = sotounpcb(so); register struct socket *so2; int error = 0; if (req == PRU_CONTROL) return (EOPNOTSUPP); if (req != PRU_SEND && rights && rights->m_len) { error = EOPNOTSUPP; goto release; } if (unp == 0 && req != PRU_ATTACH) { error = EINVAL; goto release; } switch (req) { case PRU_ATTACH: if (unp) { error = EISCONN; break; } error = unp_attach(so); break; case PRU_DETACH: unp_detach(unp); break; case PRU_BIND: error = unp_bind(unp, nam); break; case PRU_LISTEN: if (unp->unp_inode == 0) error = EINVAL; break; case PRU_CONNECT: error = unp_connect(so, nam); break; case PRU_CONNECT2: error = unp_connect2(so, (struct socket *)nam); break; case PRU_DISCONNECT: unp_disconnect(unp); break; case PRU_ACCEPT: /* * Pass back name of connected socket, * if it was bound and we are still connected * (our peer may have closed already!). */ if (unp->unp_conn && unp->unp_conn->unp_addr) { nam->m_len = unp->unp_conn->unp_addr->m_len; bcopy(mtod(unp->unp_conn->unp_addr, caddr_t), mtod(nam, caddr_t), (unsigned)nam->m_len); } else { nam->m_len = sizeof(sun_noname); *(mtod(nam, struct sockaddr *)) = sun_noname; } break; case PRU_SHUTDOWN: socantsendmore(so); unp_usrclosed(unp); break; case PRU_RCVD: switch (so->so_type) { case SOCK_DGRAM: panic("uipc 1"); /*NOTREACHED*/ case SOCK_STREAM: #define rcv (&so->so_rcv) #define snd (&so2->so_snd) if (unp->unp_conn == 0) break; so2 = unp->unp_conn->unp_socket; /* * Adjust backpressure on sender * and wakeup any waiting to write. */ snd->sb_mbmax += unp->unp_mbcnt - rcv->sb_mbcnt; unp->unp_mbcnt = rcv->sb_mbcnt; snd->sb_hiwat += unp->unp_cc - rcv->sb_cc; unp->unp_cc = rcv->sb_cc; sowwakeup(so2); #undef snd #undef rcv break; default: panic("uipc 2"); } break; case PRU_SEND: if (rights) { error = unp_internalize(rights); if (error) break; } switch (so->so_type) { case SOCK_DGRAM: { struct sockaddr *from; if (nam) { if (unp->unp_conn) { error = EISCONN; break; } error = unp_connect(so, nam); if (error) break; } else { if (unp->unp_conn == 0) { error = ENOTCONN; break; } } so2 = unp->unp_conn->unp_socket; if (unp->unp_addr) from = mtod(unp->unp_addr, struct sockaddr *); else from = &sun_noname; if (sbspace(&so2->so_rcv) > 0 && sbappendaddr(&so2->so_rcv, from, m, rights)) { sorwakeup(so2); m = 0; } else error = ENOBUFS; if (nam) unp_disconnect(unp); break; } case SOCK_STREAM: #define rcv (&so2->so_rcv) #define snd (&so->so_snd) if (so->so_state & SS_CANTSENDMORE) { error = EPIPE; break; } if (unp->unp_conn == 0) panic("uipc 3"); so2 = unp->unp_conn->unp_socket; /* * Send to paired receive port, and then reduce * send buffer hiwater marks to maintain backpressure. * Wake up readers. */ if (rights) (void)sbappendrights(rcv, m, rights); else sbappend(rcv, m); snd->sb_mbmax -= rcv->sb_mbcnt - unp->unp_conn->unp_mbcnt; unp->unp_conn->unp_mbcnt = rcv->sb_mbcnt; snd->sb_hiwat -= rcv->sb_cc - unp->unp_conn->unp_cc; unp->unp_conn->unp_cc = rcv->sb_cc; sorwakeup(so2); m = 0; #undef snd #undef rcv break; default: panic("uipc 4"); } break; case PRU_ABORT: unp_drop(unp, ECONNABORTED); break; case PRU_SENSE: ((struct stat *) m)->st_blksize = so->so_snd.sb_hiwat; if (so->so_type == SOCK_STREAM && unp->unp_conn != 0) { so2 = unp->unp_conn->unp_socket; ((struct stat *) m)->st_blksize += so2->so_rcv.sb_cc; } ((struct stat *) m)->st_dev = NODEV; if (unp->unp_ino == 0) unp->unp_ino = unp_ino++; ((struct stat *) m)->st_ino = unp->unp_ino; return (0); case PRU_RCVOOB: return (EOPNOTSUPP); case PRU_SENDOOB: error = EOPNOTSUPP; break; case PRU_SOCKADDR: break; case PRU_PEERADDR: if (unp->unp_conn && unp->unp_conn->unp_addr) { nam->m_len = unp->unp_conn->unp_addr->m_len; bcopy(mtod(unp->unp_conn->unp_addr, caddr_t), mtod(nam, caddr_t), (unsigned)nam->m_len); } break; case PRU_SLOWTIMO: break; default: panic("piusrreq"); } release: if (m) m_freem(m); return (error); } /* * Both send and receive buffers are allocated PIPSIZ bytes of buffering * for stream sockets, although the total for sender and receiver is * actually only PIPSIZ. * Datagram sockets really use the sendspace as the maximum datagram size, * and don't really want to reserve the sendspace. Their recvspace should * be large enough for at least one max-size datagram plus address. */ #define PIPSIZ 4096 int unpst_sendspace = PIPSIZ; int unpst_recvspace = PIPSIZ; int unpdg_sendspace = 2*1024; /* really max datagram size */ int unpdg_recvspace = 4*1024; int unp_rights; /* file descriptors in flight */ unp_attach(so) struct socket *so; { register struct mbuf *m; register struct unpcb *unp; int error; switch (so->so_type) { case SOCK_STREAM: error = soreserve(so, unpst_sendspace, unpst_recvspace); break; case SOCK_DGRAM: error = soreserve(so, unpdg_sendspace, unpdg_recvspace); break; } if (error) return (error); m = m_getclr(M_DONTWAIT, MT_PCB); if (m == NULL) return (ENOBUFS); unp = mtod(m, struct unpcb *); so->so_pcb = (caddr_t)unp; unp->unp_socket = so; return (0); } unp_detach(unp) register struct unpcb *unp; { if (unp->unp_inode) { #ifdef pdp11 UNPDET(unp->unp_inode); #else unp->unp_inode->i_socket = 0; irele(unp->unp_inode); #endif unp->unp_inode = 0; } if (unp->unp_conn) unp_disconnect(unp); while (unp->unp_refs) unp_drop(unp->unp_refs, ECONNRESET); soisdisconnected(unp->unp_socket); unp->unp_socket->so_pcb = 0; m_freem(unp->unp_addr); (void) m_free(dtom(unp)); if (unp_rights) unp_gc(); } unp_bind(unp, nam) struct unpcb *unp; struct mbuf *nam; { struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *); struct inode *ip; int error; if (unp->unp_inode != NULL || nam->m_len >= MLEN) return (EINVAL); *(mtod(nam, caddr_t) + nam->m_len) = 0; #ifdef pdp11 error = UNPBIND(soun->sun_path, nam->m_len, &ip, unp->unp_socket); if (error) return(error); if (!ip) panic("unp_bind"); unp->unp_inode = ip; unp->unp_addr = m_copy(nam, 0, M_COPYALL); #else ndp->ni_nameiop = CREATE | FOLLOW; ndp->ni_segflg = UIO_SYSSPACE; ndp->ni_dirp = soun->sun_path; ndp->ni_dirp[nam->m_len-2] = 0; ip = namei(ndp); if (ip) { iput(ip); return (EADDRINUSE); } if (error = u.u_error) { u.u_error = 0; /* XXX */ return (error); } ip = maknode(IFSOCK | 0777, ndp); if (ip == NULL) { error = u.u_error; /* XXX */ u.u_error = 0; /* XXX */ return (error); } ip->i_socket = unp->unp_socket; unp->unp_inode = ip; unp->unp_addr = m_copy(nam, 0, (int)M_COPYALL); iunlock(ip); /* but keep reference */ #endif return (0); } unp_connect(so, nam) struct socket *so; struct mbuf *nam; { register struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *); struct inode *ip; int error; struct socket *so2; if (nam->m_len + (nam->m_off - MMINOFF) == MLEN) return (EMSGSIZE); *(mtod(nam, caddr_t) + nam->m_len) = 0; #ifdef pdp11 error = UNPCONN(soun->sun_path, nam->m_len, &so2, &ip); if (error || !so2 || !ip) goto bad; if (so->so_type != so2->so_type) { error = EPROTOTYPE; goto bad; } if (so->so_proto->pr_flags & PR_CONNREQUIRED && ((so2->so_options&SO_ACCEPTCONN) == 0 || (so2 = sonewconn(so2)) == 0)) { error = ECONNREFUSED; goto bad; } error = unp_connect2(so, so2); bad: if (ip) IPUT(ip); #else ndp->ni_nameiop = LOOKUP | FOLLOW; ndp->ni_segflg = UIO_SYSSPACE; ndp->ni_dirp = soun->sun_path; ndp->ni_dirp[nam->m_len-2] = 0; ip = namei(ndp); if (ip == 0) { error = u.u_error; u.u_error = 0; return (error); /* XXX */ } if (access(ip, IWRITE)) { error = u.u_error; u.u_error = 0; /* XXX */ goto bad; } if ((ip->i_mode&IFMT) != IFSOCK) { error = ENOTSOCK; goto bad; } so2 = ip->i_socket; if (so2 == 0) { error = ECONNREFUSED; goto bad; } if (so->so_type != so2->so_type) { error = EPROTOTYPE; goto bad; } if (so->so_proto->pr_flags & PR_CONNREQUIRED && ((so2->so_options&SO_ACCEPTCONN) == 0 || (so2 = sonewconn(so2)) == 0)) { error = ECONNREFUSED; goto bad; } error = unp_connect2(so, so2); bad: iput(ip); #endif return (error); } unp_connect2(so, so2) register struct socket *so; register struct socket *so2; { register struct unpcb *unp = sotounpcb(so); register struct unpcb *unp2; if (so2->so_type != so->so_type) return (EPROTOTYPE); unp2 = sotounpcb(so2); unp->unp_conn = unp2; switch (so->so_type) { case SOCK_DGRAM: unp->unp_nextref = unp2->unp_refs; unp2->unp_refs = unp; soisconnected(so); break; case SOCK_STREAM: unp2->unp_conn = unp; soisconnected(so2); soisconnected(so); break; default: panic("unp_connect2"); } return (0); } unp_disconnect(unp) struct unpcb *unp; { register struct unpcb *unp2 = unp->unp_conn; if (unp2 == 0) return; unp->unp_conn = 0; switch (unp->unp_socket->so_type) { case SOCK_DGRAM: if (unp2->unp_refs == unp) unp2->unp_refs = unp->unp_nextref; else { unp2 = unp2->unp_refs; for (;;) { if (unp2 == 0) panic("unp_disconnect"); if (unp2->unp_nextref == unp) break; unp2 = unp2->unp_nextref; } unp2->unp_nextref = unp->unp_nextref; } unp->unp_nextref = 0; unp->unp_socket->so_state &= ~SS_ISCONNECTED; break; case SOCK_STREAM: soisdisconnected(unp->unp_socket); unp2->unp_conn = 0; soisdisconnected(unp2->unp_socket); break; } } #ifdef notdef unp_abort(unp) struct unpcb *unp; { unp_detach(unp); } #endif /*ARGSUSED*/ unp_usrclosed(unp) struct unpcb *unp; { } unp_drop(unp, errno) struct unpcb *unp; int errno; { struct socket *so = unp->unp_socket; so->so_error = errno; unp_disconnect(unp); if (so->so_head) { so->so_pcb = (caddr_t) 0; m_freem(unp->unp_addr); (void) m_free(dtom(unp)); sofree(so); } } #ifdef notdef unp_drain() { } #endif unp_externalize(rights) struct mbuf *rights; { int newfds = rights->m_len / sizeof (int); register int i; register struct file **rp = mtod(rights, struct file **); register struct file *fp; int f; printf("unp_externalize(0%o)\n",rights); if (newfds > ufavail()) { for (i = 0; i < newfds; i++) { fp = *rp; unp_discard(fp); *rp++ = 0; } return (EMSGSIZE); } for (i = 0; i < newfds; i++) { f = ufalloc(0); if (f < 0) panic("unp_externalize"); fp = *rp; u.u_ofile[f] = fp; #ifdef pdp11 /* -1 added to msgcount, 0 to count */ SKcall(fadjust, sizeof(fp) + sizeof(int) + sizeof(int), fp, -1, 0); #else fp->f_msgcount--; #endif unp_rights--; *(int *)rp++ = f; } return (0); } unp_internalize(rights) struct mbuf *rights; { register struct file **rp; int oldfds = rights->m_len / sizeof (int); register int i; register struct file *fp; printf("unp_internalize(0%o)\n",rights); rp = mtod(rights, struct file **); for (i = 0; i < oldfds; i++, rp++) GETF(fp, *(int *)rp); rp = mtod(rights, struct file **); for (i = 0; i < oldfds; i++) { GETF(fp, *(int *)rp); *rp++ = fp; #ifdef pdp11 /* bump both the message count and reference count of fp */ SKcall(fadjust, sizeof(fp) + sizeof(int) + sizeof(int), fp, 1, 1); #else fp->f_count++; fp->f_msgcount++; #endif unp_rights++; } return (0); } int unp_defer, unp_gcing; int unp_mark(); extern struct domain unixdomain; /* * What I did to the next routine isn't pretty, feel free to redo it, but * I doubt it'd be worth it since this isn't used very much. SMS */ unp_gc() { register struct file *fp; register struct socket *so; struct file *file, *fileNFILE, xf; if (unp_gcing) return; unp_gcing = 1; restart: unp_defer = 0; /* get limits AND clear FMARK|FDEFER in all file table entries */ SKcall(unpgc1, sizeof(file) + sizeof(fileNFILE), &file, &fileNFILE); do { for (fp = file; fp < fileNFILE; fp++) { /* get file table entry, the return value is f_count */ if (FPFETCH(fp, &xf) == 0) continue; if (xf.f_flag & FDEFER) { FPFLAGS(fp, 0, FDEFER); unp_defer--; } else { if (xf.f_flag & FMARK) continue; if (xf.f_count == xf.f_msgcount) continue; FPFLAGS(fp, FMARK, 0); } if (xf.f_type != DTYPE_SOCKET) continue; so = xf.f_socket; if (so->so_proto->pr_domain != &unixdomain || (so->so_proto->pr_flags&PR_RIGHTS) == 0) continue; if (so->so_rcv.sb_flags & SB_LOCK) { sbwait(&so->so_rcv); goto restart; } unp_scan(so->so_rcv.sb_mb, unp_mark); } } while (unp_defer); for (fp = file; fp < fileNFILE; fp++) { if (FPFETCH(fp, &xf) == 0) continue; if (xf.f_count == xf.f_msgcount && (xf.f_flag & FMARK) == 0) while (FPFETCH(fp, &xf) && xf.f_msgcount) unp_discard(fp); } unp_gcing = 0; } unp_dispose(m) struct mbuf *m; { int unp_discard(); if (m) unp_scan(m, unp_discard); } unp_scan(m0, op) register struct mbuf *m0; int (*op)(); { register struct mbuf *m; register struct file **rp; register int i; int qfds; while (m0) { for (m = m0; m; m = m->m_next) if (m->m_type == MT_RIGHTS && m->m_len) { qfds = m->m_len / sizeof (struct file *); rp = mtod(m, struct file **); for (i = 0; i < qfds; i++) (*op)(*rp++); break; /* XXX, but saves time */ } m0 = m0->m_act; } } unp_mark(fp) struct file *fp; { struct file xf; FPFETCH(fp, &xf); if (xf.f_flag & FMARK) return; unp_defer++; FPFLAGS(fp, FMARK|FDEFER, 0); } unp_discard(fp) struct file *fp; { unp_rights--; SKcall(unpdisc, sizeof(fp), fp); } tch (so->so_type) { case SOCK_STREAM: error = soreserve(so, unpst_sendspace, unpst_recvspace); break; case SOCK_DGRAM: error = sorsys/sys/quota_kern.c 440 0 12 42374 5666031477 10042 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)quota_kern.c 7.1.2 (2.11BSD GTE) 11/26/94 * * I'll say it here and not every other place i've had to hack: * Mike Karels was right - " just buy a vax...". i have traded cpu cycles * for kernel D space - if enough space ever becomes available then the * p_quota, i_dquot members can be added to their respective structures, * and the quota[] array might possibly be moved into the kernel, it is * highly doubtful the dquot structures can ever be moved into the kernel * D space. Then too, the mapping of the out of kernel quota space is * swamped by the overhead of doing the quotas, and quotas sure as heck * beat doing 'du's all the time! * Steven M. Schultz 1/12/88 */ /* * MELBOURNE QUOTAS * * Code pertaining to management of the in-core data structures. */ #include "param.h" #ifdef QUOTA #include "systm.h" #include "user.h" #include "proc.h" #include "inode.h" #include "quota.h" #include "fs.h" #include "mount.h" #include "uio.h" /* * Quota cache - hash chain headers. */ #ifndef pdp11 #define NQHASH 32 /* small power of two */ #endif #define QHASH(uid) ((unsigned)(uid) & (NQHASH-1)) #ifndef pdp11 struct qhash { struct qhash *qh_forw; /* MUST be first */ struct qhash *qh_back; /* MUST be second */ }; struct qhash qhash[NQHASH]; #else struct qhash *qhash; #endif /* * Quota free list. */ struct quota *qfreelist, **qfreetail; typedef struct quota *Qptr; /* * Dquot cache - hash chain headers. */ #ifndef pdp11 /* and 51 isn't even prime, see quota.h */ #define NDQHASH 51 /* a smallish prime */ #endif #define DQHASH(uid, dev) \ ((unsigned)(((int)(dev) * 4) + (uid)) % NDQHASH) #ifndef pdp11 struct dqhead { struct dqhead *dqh_forw; /* MUST be first */ struct dqhead *dqh_back; /* MUST be second */ }; struct dqhead dqhead[NDQHASH]; #else struct dqhead *dqhead; #endif /* * Dquot free list. */ struct dquot *dqfreel, **dqback; typedef struct dquot *DQptr; /* * Initialize quota caches. */ qtinit() { register i; register struct quota *q = quota; register struct qhash *qh = qhash; register struct dquot *dq = dquot; register struct dqhead *dh = dqhead; /* * First the cache of structures assigned users. */ for (i = NQHASH; --i >= 0; qh++) qh->qh_forw = qh->qh_back = qh; qfreelist = q; qfreetail = &q->q_freef; q->q_freeb = &qfreelist; q->q_forw = q; q->q_back = q; for (i = nquota; --i > 0; ) { ++q; q->q_forw = q; q->q_back = q; *qfreetail = q; q->q_freeb = qfreetail; qfreetail = &q->q_freef; } q->q_freef = NOQUOTA; /* * Next, the cache between the in-core structures * and the per-filesystem quota files on disk. */ for (i = NDQHASH; --i >= 0; dh++) dh->dqh_forw = dh->dqh_back = dh; dqfreel = dq; dqback = &dq->dq_freef; dq->dq_freeb = &dqfreel; dq->dq_forw = dq; dq->dq_back = dq; for (i = ndquot; --i > 0; ) { ++dq; dq->dq_forw = dq; dq->dq_back = dq; *dqback = dq; dq->dq_freeb = dqback; dqback = &dq->dq_freef; } dq->dq_freef = NODQUOT; } /* * Find an incore quota structure for a particular uid, * or make one. If lookuponly is non-zero, just the lookup is performed. * If nodq is non-zero, the dquot structures are left uninitialized. */ struct quota * getquota(uid, lookuponly, nodq) register uid_t uid; int lookuponly, nodq; { register struct quota *q; register struct qhash *qh; register struct dquot **dqq; register struct mount *mp; register struct quota *qq; /* * Fast check to see if an existing structure * can be reused with just a reference count change. */ q = u.u_quota; if (q != NOQUOTA && q->q_uid == uid) goto quick; /* * Search the quota chache for a hit. */ qh = &qhash[QHASH(uid)]; for (q = (Qptr)qh->qh_forw; q != (Qptr)qh; q = q->q_forw) { if (q->q_uid == uid) { if (q->q_cnt == 0) { if (lookuponly) return (NOQUOTA); /* * Take it off the free list. */ if ((qq = q->q_freef) != NOQUOTA) qq->q_freeb = q->q_freeb; else qfreetail = q->q_freeb; *q->q_freeb = qq; /* * Recover any lost dquot structs. */ if (!nodq) for (dqq = q->q_dq, mp = mount; dqq < &q->q_dq[NMOUNT]; dqq++, mp++) #ifdef pdp11 if (*dqq == LOSTDQUOT && mp->m_inodp) { #else if (*dqq == LOSTDQUOT && mp->m_bufp) { #endif *dqq = discquota(uid, mp->m_qinod); if (*dqq != NODQUOT) (*dqq)->dq_own = q; } } quick: q->q_cnt++; while (q->q_flags & Q_LOCK) { q->q_flags |= Q_WANT; #ifdef pdp11 QUOTAUNMAP(); sleep((caddr_t) q, PINOD+1); QUOTAMAP(); #else sleep((caddr_t) q, PINOD+1); #endif } if (q->q_cnt == 1) q->q_flags |= Q_NEW | nodq; return (q); } } if (lookuponly) return (NOQUOTA); /* * Take the quota that is at the head of the free list * (the longest unused quota). */ q = qfreelist; if (q == NOQUOTA) { tablefull("quota"); u.u_error = EUSERS; q = quota; /* the su's slot - we must have one */ q->q_cnt++; return (q); } /* * There is one - it is free no longer. */ qq = q->q_freef; if (qq != NOQUOTA) qq->q_freeb = &qfreelist; qfreelist = qq; /* * Now we are about to change this from one user to another * Must take this off hash chain for old user immediately, in * case some other process claims it before we are done. * We must then put it on the hash chain for the new user, * to make sure that we don't make two quota structs for one uid. * (the quota struct will then be locked till we are done). */ remque(q); insque(q, qh); q->q_uid = uid; q->q_flags = Q_LOCK; q->q_cnt++; /* q->q_cnt = 1; */ /* * Next, before filling in info for the new owning user, * we must get rid of any dquot structs that we own. */ for (mp = mount, dqq = q->q_dq; mp < &mount[NMOUNT]; mp++, dqq++) if (*dqq != NODQUOT && *dqq != LOSTDQUOT) { (*dqq)->dq_own = NOQUOTA; putdq(mp, *dqq, 1); } for (mp = mount, dqq = q->q_dq; dqq < &q->q_dq[NMOUNT]; mp++, dqq++) #ifdef pdp11 if (!nodq && mp->m_inodp) { #else if (!nodq && mp->m_bufp) { #endif *dqq = discquota(uid, mp->m_qinod); if (*dqq != NODQUOT) { if ((*dqq)->dq_uid != uid) panic("got bad quota uid"); (*dqq)->dq_own = q; } } else *dqq = NODQUOT; if (q->q_flags & Q_WANT) wakeup((caddr_t)q); q->q_flags = Q_NEW | nodq; return (q); } /* * Delete a quota, wakeup anyone waiting. */ delquota(q) register struct quota *q; { register struct dquot **dqq; register struct mount *mp; top: if (q->q_cnt != 1) { q->q_cnt--; return; } if (q->q_flags & Q_LOCK) { q->q_flags |= Q_WANT; #ifdef pdp11 QUOTAUNMAP(); sleep((caddr_t)q, PINOD+2); QUOTAMAP(); #else sleep((caddr_t)q, PINOD+2); #endif /* * Just so we don't sync dquots if not needed; * 'if' would be 'while' if this was deleted. */ goto top; } /* * If we own dquot structs, sync them to disc, but don't release * them - we might be recalled from the LRU chain. * As we will sit on the free list while we are waiting for that, * if dquot structs run out, ours will be taken away. */ q->q_flags = Q_LOCK; if ((q->q_flags & Q_NDQ) == 0) { mp = mount; for (dqq = q->q_dq; dqq < &q->q_dq[NMOUNT]; dqq++, mp++) #ifdef pdp11 if (mp->m_inodp) #else if (mp->m_bufp) #endif putdq(mp, *dqq, 0); } if (q->q_flags & Q_WANT) wakeup((caddr_t)q); /* * This test looks unnecessary, but someone might have claimed this * quota while we have been getting rid of the dquot info */ if (--q->q_cnt == 0) { /* now able to be reallocated */ if (qfreelist != NOQUOTA) { *qfreetail = q; q->q_freeb = qfreetail; } else { qfreelist = q; q->q_freeb = &qfreelist; } q->q_freef = NOQUOTA; qfreetail = &q->q_freef; q->q_flags = 0; } else q->q_flags &= ~(Q_LOCK|Q_WANT); } /* * Obtain the user's on-disk quota limit * from the file specified. */ struct dquot * discquota(uid, ip) uid_t uid; register struct inode *ip; { register struct dquot *dq; register struct dqhead *dh; register struct dquot *dp; int fail; if (ip == NULL) return (NODQUOT); /* * Check the cache first. */ dh = &dqhead[DQHASH(uid, ip->i_dev)]; for (dq = (DQptr)dh->dqh_forw; dq != (DQptr)dh; dq = dq->dq_forw) { if (dq->dq_uid != uid || dq->dq_dev != ip->i_dev) continue; /* * Cache hit with no references. Take * the structure off the free list. */ if (dq->dq_cnt++ == 0) { dp = dq->dq_freef; if (dp != NODQUOT) dp->dq_freeb = dq->dq_freeb; else dqback = dq->dq_freeb; *dq->dq_freeb = dp; dq->dq_own = NOQUOTA; } /* * We do this test after the previous one so that * the dquot will be moved to the end of the free * list - frequently accessed ones ought to hang around. */ if (dq->dq_isoftlimit == 0 && dq->dq_bsoftlimit == 0) { dqrele(dq); return (NODQUOT); } return (dq); } /* * Not in cache, allocate a new one and * bring info in off disk. */ dq = dqalloc(uid, ip->i_dev); if (dq == NODQUOT) return (dq); dq->dq_flags = DQ_LOCK; #ifdef pdp11 { struct dqblk xq; QUOTAUNMAP(); ILOCK(ip); fail = rdwri(UIO_READ, ip, &xq, sizeof (xq), (off_t)uid * sizeof (xq), UIO_SYSSPACE, IO_UNIT,(int *)0); QUOTAMAP(); dq->dq_dqb = xq; } #else ILOCK(ip); fail = rdwri(UIO_READ, ip, (caddr_t)&dq->dq_dqb, sizeof (struct dqblk), (off_t)uid * sizeof(struct dqblk), UIO_SYSSPACE, IO_UNIT, (int *)0); #endif IUNLOCK(ip); if (dq->dq_flags & DQ_WANT) wakeup((caddr_t)dq); dq->dq_flags = 0; /* * I/O error in reading quota file, release * quota structure and reflect problem to caller. */ if (fail) { remque(dq); dq->dq_forw = dq; /* on a private, unfindable hash list */ dq->dq_back = dq; /* dqrele() (just below) will put dquot back on free list */ } /* no quota exists */ if (fail || dq->dq_isoftlimit == 0 && dq->dq_bsoftlimit == 0) { dqrele(dq); return (NODQUOT); } return (dq); } /* * Allocate a dquot structure. If there are * no free slots in the cache, flush LRU entry from * the cache to the appropriate quota file on disk. */ struct dquot * dqalloc(uid, dev) uid_t uid; dev_t dev; { register struct dquot *dq; register struct dqhead *dh; register struct dquot *dp; register struct quota *q; register struct mount *mp; static struct dqblk zdqb = { 0 }; top: /* * Locate inode of quota file for * indicated file system in case i/o * is necessary in claiming an entry. */ for (mp = mount; mp < &mount[NMOUNT]; mp++) { #ifdef pdp11 if (mp->m_dev == dev && mp->m_inodp) { #else if (mp->m_dev == dev && mp->m_bufp) { #endif if (mp->m_qinod == NULL) { u.u_error = EINVAL; return (NODQUOT); } break; } } if (mp >= &mount[NMOUNT]) { u.u_error = EINVAL; return (NODQUOT); } /* * Check free list. If table is full, pull entries * off the quota free list and flush any associated * dquot references until something frees up on the * dquot free list. */ if ((dq = dqfreel) == NODQUOT && (q = qfreelist) != NOQUOTA) { do { register struct dquot **dqq; register struct mount *mountp = mount; dqq = q->q_dq; while (dqq < &q->q_dq[NMOUNT]) { if ((dq = *dqq) != NODQUOT && dq != LOSTDQUOT) { /* * Mark entry as "lost" due to * scavenging operation. */ if (dq->dq_cnt == 1) { *dqq = LOSTDQUOT; putdq(mountp, dq, 1); goto top; } } mountp++; dqq++; } q = q->q_freef; } while ((dq = dqfreel) == NODQUOT && q != NOQUOTA); } if (dq == NODQUOT) { tablefull("dquot"); u.u_error = EUSERS; return (dq); } /* * This shouldn't happen, as we sync * dquot before freeing it up. */ if (dq->dq_flags & DQ_MOD) panic("discquota"); /* * Now take the dquot off the free list, */ dp = dq->dq_freef; if (dp != NODQUOT) dp->dq_freeb = &dqfreel; dqfreel = dp; /* * and off the hash chain it was on, & onto the new one. */ dh = &dqhead[DQHASH(uid, dev)]; remque(dq); insque(dq, dh); dq->dq_cnt = 1; dq->dq_flags = 0; dq->dq_uid = uid; dq->dq_dev = dev; dq->dq_dqb = zdqb; dq->dq_own = NOQUOTA; return (dq); } /* * dqrele - layman's interface to putdq. */ dqrele(dq) register struct dquot *dq; { register struct mount *mp; if (dq == NODQUOT || dq == LOSTDQUOT) return; if (dq->dq_cnt > 1) { dq->dq_cnt--; return; } /* * I/O required, find appropriate file system * to sync the quota information to. */ for (mp = mount; mp < &mount[NMOUNT]; mp++) #ifdef pdp11 if (mp->m_inodp && mp->m_dev == dq->dq_dev) { #else if (mp->m_bufp && mp->m_dev == dq->dq_dev) { #endif putdq(mp, dq, 1); return; } panic("dqrele"); } /* * Update the disc quota in the quota file. */ putdq(mp, dq, free) register struct mount *mp; register struct dquot *dq; { register struct inode *ip; if (dq == NODQUOT || dq == LOSTDQUOT) return; if (free && dq->dq_cnt > 1) { dq->dq_cnt--; return; } /* * Disk quota not modified, just discard * or return (having adjusted the reference * count), as indicated by the "free" param. */ if ((dq->dq_flags & DQ_MOD) == 0) { if (free) { dq->dq_cnt = 0; release: if (dqfreel != NODQUOT) { *dqback = dq; dq->dq_freeb = dqback; } else { dqfreel = dq; dq->dq_freeb = &dqfreel; } dq->dq_freef = NODQUOT; dqback = &dq->dq_freef; } return; } /* * Quota modified, write back to disk. */ while (dq->dq_flags & DQ_LOCK) { dq->dq_flags |= DQ_WANT; #ifdef pdp11 QUOTAUNMAP(); sleep((caddr_t)dq, PINOD+2); QUOTAMAP(); #else sleep((caddr_t)dq, PINOD+2); #endif /* someone could sneak in and grab it */ if (free && dq->dq_cnt > 1) { dq->dq_cnt--; return; } } dq->dq_flags |= DQ_LOCK; if ((ip = mp->m_qinod) == NULL) panic("lost quota file"); #ifdef pdp11 { struct dqblk xq; uid_t uid; xq = dq->dq_dqb; uid = dq->dq_uid; QUOTAUNMAP(); ILOCK(ip); (void)rdwri(UIO_WRITE, ip, &xq, sizeof (xq), (off_t)uid * sizeof (xq), UIO_SYSSPACE, IO_UNIT, (int *)0); QUOTAMAP(); } #else ILOCK(ip); (void) rdwri(UIO_WRITE, ip, (caddr_t)&dq->dq_dqb, sizeof (struct dqblk), (off_t)dq->dq_uid * sizeof (struct dqblk), UIO_SYSSPACE, IO_UNIT, (int *)0); #endif IUNLOCK(ip); if (dq->dq_flags & DQ_WANT) wakeup((caddr_t)dq); dq->dq_flags &= ~(DQ_MOD|DQ_LOCK|DQ_WANT); if (free && --dq->dq_cnt == 0) goto release; } /* * See if there is a quota struct in core for user 'uid'. */ struct quota * qfind(uid) register uid_t uid; { register struct quota *q; register struct qhash *qh; /* * Check common cases first: asking for own quota, * or that of the super user (has reserved slot 0 * in the table). */ q = u.u_quota; if (q != NOQUOTA && q->q_uid == uid) return (q); if (uid == 0) /* the second most likely case */ return (quota); /* * Search cache. */ qh = &qhash[QHASH(uid)]; for (q = (Qptr)qh->qh_forw; q != (Qptr)qh; q = q->q_forw) if (q->q_uid == uid) return (q); return (NOQUOTA); } /* * Set the quota file up for a particular file system. * Called as the result of a setquota system call. */ opendq(mp, fname) register struct mount *mp; caddr_t fname; { register struct inode *ip; register struct quota *q; struct dquot *dq; register struct nameidata *ndp = &u.u_nd; int i; if (mp->m_qinod) closedq(mp); QUOTAUNMAP(); /* paranoia */ ndp->ni_nameiop = LOOKUP | FOLLOW; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = fname; ip = namei(ndp); QUOTAMAP(); if (ip == NULL) return; IUNLOCK(ip); if (ip->i_dev != mp->m_dev) { u.u_error = EACCES; return; } if ((ip->i_mode & IFMT) != IFREG) { u.u_error = EACCES; return; } /* * Flush in-core references to any previous * quota file for this file system. */ mp->m_qinod = ip; i = mp - mount; for (q = quota; q < quotaNQUOTA; q++) if ((q->q_flags & Q_NDQ) == 0) { if (q->q_cnt == 0) q->q_dq[i] = LOSTDQUOT; else { q->q_cnt++; /* cannot be released */ dq = discquota(q->q_uid, ip); q->q_dq[i] = dq; if (dq != NODQUOT) dq->dq_own = q; delquota(q); } } } /* * Close off disc quotas for a file system. */ closedq(mp) register struct mount *mp; { register struct dquot *dq; register i = mp - mount; register struct quota *q; register struct inode *ip; if (mp->m_qinod == NULL) return; /* * Search inode table, delete any references * to quota file being closed. */ for (ip = inode; ip < inodeNINODE; ip++) if (ip->i_dev == mp->m_dev) { #ifdef pdp11 dq = ix_dquot[ip - inode]; ix_dquot[ip - inode] = NODQUOT; #else dq = ip->i_dquot; ip->i_dquot = NODQUOT; #endif putdq(mp, dq, 1); } /* * Search quota table, flush any pending * quota info to disk and also delete * references to closing quota file. */ for (q = quota; q < quotaNQUOTA; q++) { if ((q->q_flags & Q_NDQ) == 0) { if (q->q_cnt) { q->q_cnt++; putdq(mp, q->q_dq[i], 1); delquota(q); } else putdq(mp, q->q_dq[i], 1); } q->q_dq[i] = NODQUOT; } /* * Move all dquot's that used to refer to this quota * file of into the never-never (they will eventually * fall off the head of the free list and be re-used). */ for (dq = dquot; dq < dquotNDQUOT; dq++) if (dq->dq_dev == mp->m_dev) { if (dq->dq_cnt) panic("closedq: stray dquot"); remque(dq); dq->dq_forw = dq; dq->dq_back = dq; dq->dq_dev = NODEV; } QUOTAUNMAP(); irele(mp->m_qinod); QUOTAMAP(); mp->m_qinod = NULL; } #endif inodp) #else if (mp->m_bufp) #endif putdq(mp, *dqq, 0); } if (q->q_flags & Q_WANT) wakeup((caddr_t)q); /* * This test looks unnecessary, but someone might have claimed this * quota while we have been getting rid of the dquot info */ if (--qsys/sys/sys_net.c 640 0 12 22136 6036406273 7342 /* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)sys_net.c 1.4 (2.11BSD GTE) 1995/10/09 * * Change uiomove calling convention. The r/w type is now encapsulated * in the uio structure now. sms - 11/26/94 * * 2.11BSD - map the I/O region with sufficient UMRs. this precludes * drivers such as the DEUNA from allocating a UMR per packet. * sms - 9/8/90 */ #include "param.h" #include "../machine/cons.h" #include "../machine/psl.h" #include "user.h" #include "uio.h" #include "map.h" #include "uba.h" #include "mbuf.h" #include "acct.h" #include "ioctl.h" #include "tty.h" #include "../pdpuba/ubavar.h" #include "acc.h" #if NACC > 0 extern struct uba_driver accdriver; #endif #include "css.h" #if NCSS > 0 extern struct uba_driver cssdriver; #endif #include "de.h" #if NDE > 0 extern struct uba_driver dedriver; #endif #include "ec.h" #if NEC > 0 extern struct uba_driver ecdriver; #endif #include "il.h" #if NIL > 0 extern struct uba_driver ildriver; #endif #include "qe.h" #if NQE > 0 extern struct uba_driver qedriver; #endif #include "qt.h" #if NQT > 0 extern struct uba_driver qtdriver; #endif #include "sri.h" #if NSRI > 0 extern struct uba_driver sridriver; #endif #include "vv.h" #if NVV > 0 extern struct uba_driver vvdriver; #endif static struct uba_device ubdinit[] = { #if NDE > 0 { &dedriver, 0,0, (caddr_t)0174510 }, #endif #if NIL > 0 { &ildriver, 0,0, (caddr_t)0164000 }, #endif #if NQE > 0 { &qedriver, 0,0, (caddr_t)0174440, 0, 0 }, #endif #if NQE > 1 { &qedriver, 1,0, (caddr_t)0174460, 0, 0 }, #endif #if NQT > 0 { &qtdriver, 0,0, (caddr_t)0174440, 0, 0 }, #endif #if NQT > 1 { &qtdriver, 1,0, (caddr_t)0174460, 0, 0 }, #endif #if NSRI > 0 { &sridriver, 0,0, (caddr_t)0167770 }, #endif #if NVV > 0 { &vvdriver, 0,0, (caddr_t)0161000 }, #endif #if NEC > 0 { &ecdriver, 0,0, (caddr_t)0164330 }, #endif #if NACC > 0 { &accdriver, 0,0, (caddr_t)0000000 }, #endif #if NCSS > 0 { &cssdriver, 0,0, (caddr_t)0000000 }, #endif NULL, }; int hz = LINEHZ; long startnet; /* start of network data space */ netstart() { extern memaddr miobase, miostart, netdata; extern ubadr_t mioumr; extern u_short miosize; register struct uba_driver *udp; register struct uba_device *ui = ubdinit; register int s; int first; struct ubmap *ubp; ubadr_t paddr; /* * The networking uses a mapped region as the DMA area for * network interface drivers. Allocate this latter region. */ if ((miobase = MALLOC(coremap, btoc(miosize))) == 0) panic("miobase"); /* * Allocate sufficient UMRs to map the DMA region. Save the * starting click and UNIBUS addresses for use in ubmalloc later. * This is early in the systems life, so there had better be * sufficient UMRs available! */ if (mfkd(&ubmap)) { miostart = miobase; s = (int)btoub(miosize); first = MALLOC(ub_map, s); #ifdef DIAGNOSTIC if (!first) panic("ub_map"); #endif mioumr = (ubadr_t)first << 13; ubp = &UBMAP[first]; paddr = ctob((ubadr_t)miostart); while (s--) { ubp->ub_lo = loint(paddr); ubp->ub_hi = hiint(paddr); ubp++; paddr += (ubadr_t)UBPAGE; } } startnet = ctob((long)mfkd(&netdata)); mbinit(); for (ui = ubdinit; udp = ui->ui_driver; ++ui) { if (badaddr(ui->ui_addr, 2)) continue; ui->ui_alive = 1; udp->ud_dinfo[ui->ui_unit] = ui; printf("attaching %s%d\n", udp->ud_dname, ui->ui_unit); (*udp->ud_attach)(ui); } #include "sl.h" #if NSL > 0 printf("attaching sl\n"); slattach(); #endif #include "loop.h" #if NLOOP > 0 printf("attaching lo0\n"); loattach(); #endif s = splimp(); ifinit(); domaininit(); /* must follow interfaces */ splx(s); } /* * Panic is called on fatal errors. It prints "net panic: mesg" and * then calls the kernel entry netcrash() to bring down the net. */ panic(s) register char *s; { printf("net panic: %s\n", s); NETCRASH(); /* NOTREACHED */ } netcopyout(m, to, len) struct mbuf *m; char *to; int *len; { if (*len > m->m_len) *len = m->m_len; return(copyout(mtod(m, caddr_t), to, *len)); } /* * These routines are copies of various kernel routines that are required in * the supervisor space by the networking. DO NOT MODIFY THESE ROUTINES! * Modify the kernel version and bring a copy here. The "#ifdef notdef" * modifications simplify by eliminating portions of routines not required * by the networking. */ /* copied from kern_descrip.c */ ufavail() { register int i, avail = 0; for (i = 0; i < NOFILE; i++) if (u.u_ofile[i] == NULL) avail++; return (avail); } /* copied from kern_descrip.c */ ufalloc(i) register int i; { for (; i < NOFILE; i++) if (u.u_ofile[i] == NULL) { u.u_r.r_val1 = i; u.u_pofile[i] = 0; if (i > u.u_lastfile) u.u_lastfile = i; return (i); } u.u_error = EMFILE; return (-1); } /* copied from ufs_fio.c */ suser() { if (u.u_uid == 0) { u.u_acflag |= ASU; return (1); } u.u_error = EPERM; return (0); } /* copied from kern_sysctl.c */ sysctl_int(oldp, oldlenp, newp, newlen, valp) void *oldp; size_t *oldlenp; void *newp; size_t newlen; int *valp; { int error = 0; if (oldp && *oldlenp < sizeof(int)) return (ENOMEM); if (newp && newlen != sizeof(int)) return (EINVAL); *oldlenp = sizeof(int); if (oldp) error = copyout(valp, oldp, sizeof(int)); if (error == 0 && newp) error = copyin(newp, valp, sizeof(int)); return (error); } /* * An old version of uiomove, as uiofmove() and vcopy{in,out}() don't * exist in supervisor space. Note, we assume that all transfers will * be to/from user D space. Probably safe, until someone decides to * put NFS into the kernel. * * The 4.3BSD uio/iovec paradigm adopted, ureadc() and uwritec() inlined * at that time to speed things up. 3/90 sms */ uiomove(cp, n, uio) caddr_t cp; u_int n; register struct uio *uio; { register struct iovec *iov; int error, count, ch; register u_int cnt; #ifdef DIAGNOSTIC if (uio->uio_segflg != UIO_USERSPACE) panic("net uiomove"); #endif while (n && uio->uio_resid) { iov = uio->uio_iov; cnt = iov->iov_len; if (cnt == 0) { uio->uio_iov++; uio->uio_iovcnt--; continue; } if (cnt > n) cnt = n; count = cnt; if ((cnt | (int)cp | (int)iov->iov_base) & 1) { if (uio->uio_rw == UIO_READ) { while (cnt--) if (subyte(iov->iov_base++, *cp++) < 0) return (EFAULT); } else { while (cnt--) { if ((ch = fubyte(iov->iov_base++)) < 0) return (EFAULT); *cp++ = ch; } } cnt = count; /* use register */ } else { if (uio->uio_rw == UIO_READ) error = copyout(cp, iov->iov_base, cnt); else error = copyin(iov->iov_base, cp, cnt); if (error) return (error); iov->iov_base += cnt; cp += cnt; } iov->iov_len -= cnt; uio->uio_resid -= cnt; uio->uio_offset += cnt; n -= cnt; } return (0); } #define TOCONS 0x1 #define TOTTY 0x2 #define TOLOG 0x4 /* copied from subr_prf.c */ /*VARARGS1*/ printf(fmt, x1) char *fmt; unsigned x1; { prf(fmt, &x1, TOCONS | TOLOG); } /* copied from subr_prf.c */ prf(fmt, adx, flags) register char *fmt; register u_int *adx; int flags; { register int c; u_int b; char *s; int i, any; loop: while ((c = *fmt++) != '%') { if (c == '\0') return; _pchar(c, flags); } c = *fmt++; switch (c) { case 'l': c = *fmt++; switch(c) { case 'x': b = 16; goto lnumber; case 'd': b = 10; goto lnumber; case 'o': b = 8; goto lnumber; default: _pchar('%', flags); _pchar('l', flags); _pchar(c, flags); } break; case 'X': b = 16; goto lnumber; case 'D': b = 10; goto lnumber; case 'O': b = 8; lnumber: printn(*(long *)adx, b, flags); adx += (sizeof(long) / sizeof(int)) - 1; break; case 'x': b = 16; goto number; case 'd': case 'u': /* what a joke */ b = 10; goto number; case 'o': b = 8; number: printn((long)*adx, b, flags); break; case 'c': _pchar(*adx, flags); break; case 'b': b = *adx++; s = (char *)*adx; printn((long)b, *s++, flags); any = 0; if (b) { while (i = *s++) { if (b & (1 << (i - 1))) { _pchar(any? ',' : '<', flags); any = 1; for (; (c = *s) > 32; s++) _pchar(c, flags); } else for (; *s > 32; s++) ; } if (any) _pchar('>', flags); } break; case 's': s = (char *)*adx; while (c = *s++) _pchar(c, flags); break; case '%': _pchar(c, flags); break; default: _pchar('%', flags); _pchar(c, flags); break; } adx++; goto loop; } /* copied from subr_prf.c */ printn(n, b, flags) long n; u_int b; { char prbuf[12]; register char *cp = prbuf; register int offset = 0; if (n<0) switch(b) { case 8: /* unchecked, but should be like hex case */ case 16: offset = b-1; n++; break; case 10: _pchar('-', flags); n = -n; break; } do { *cp++ = "0123456789ABCDEF"[offset + n%b]; } while (n = n/b); /* Avoid n /= b, since that requires alrem */ do _pchar(*--cp, flags); while (cp > prbuf); } extern int putchar(); _pchar(c, flg) int c, flg; { return(SKcall(putchar, sizeof(int)+sizeof(int)+sizeof(struct tty *), c, flg, (struct tty *)0)); } ching lo0\n"); loattach(); #endif s = splimp(); ifinit(); domaininit(); /* must follow interfaces */ splx(s); } /* * Panic is called on fatal errors. It prints "net panic: mesg" and * then calls the kernel entry netcrash() to bring down the net. */ panic(s) register char *s; { printf("net panic: %s\n", s); NETCRASH(); /* NOTREACHED */ } netcopyout(m, to, len) struct mbuf *m; char *to; int *len;sys/sys/quota_subr.c 440 0 12 5227 5350006632 10013 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)quota_subr.c 7.1 (Berkeley) 6/5/86 */ /* * MELBOURNE QUOTAS * * Miscellaneous subroutines. */ #include "param.h" #ifdef QUOTA #include "systm.h" #include "user.h" #include "proc.h" #include "inode.h" #include "quota.h" #include "fs.h" #include "mount.h" #include "uio.h" struct dquot * dqp(q, dev) struct quota *q; dev_t dev; { register struct dquot **dqq; register i; if (q == NOQUOTA || q->q_flags & Q_NDQ) return (NODQUOT); i = getfsx(dev); if (i < 0 || i >= NMOUNT) return (NODQUOT); dqq = &q->q_dq[i]; if (*dqq == LOSTDQUOT) { *dqq = discquota(q->q_uid, mount[i].m_qinod); if (*dqq != NODQUOT) (*dqq)->dq_own = q; } if (*dqq != NODQUOT) (*dqq)->dq_cnt++; return (*dqq); } /* * Quota cleanup at process exit, or when * switching to another user. */ qclean() { register struct quota *q = u.u_quota; if (q == NOQUOTA) return; /* * Before we rid ourselves of this quota, we must be sure that * we no longer reference it (otherwise clock might do nasties). * But we have to have some quota (or clock will get upset). * (Who is this clock anyway ??). So we will give ourselves * root's quota for a short while, without counting this as * a reference in the ref count (as either this proc is just * about to die, in which case it refers to nothing, or it is * about to be given a new quota, which will just overwrite this * one). */ u.u_quota = quota; delquota(q); } qstart(q) register struct quota *q; { u.u_quota = q; } qwarn(dq) register struct dquot *dq; { register struct fs *fs = NULL; if (dq->dq_isoftlimit && dq->dq_curinodes >= dq->dq_isoftlimit) { dq->dq_flags |= DQ_MOD; fs = getfs(dq->dq_dev); if (dq->dq_iwarn && --dq->dq_iwarn) uprintf( "Warning: too many files on %s, %d warning%s left\n" , fs->fs_fsmnt , dq->dq_iwarn , dq->dq_iwarn > 1 ? "s" : "" ); else uprintf( "WARNING: too many files on %s, NO MORE!!\n" , fs->fs_fsmnt ); } else dq->dq_iwarn = MAX_IQ_WARN; if (dq->dq_bsoftlimit && dq->dq_curblocks >= dq->dq_bsoftlimit) { dq->dq_flags |= DQ_MOD; if (fs == NULL) fs = getfs(dq->dq_dev); if (dq->dq_bwarn && --dq->dq_bwarn) uprintf( "Warning: too much disc space on %s, %d warning%s left\n" , fs->fs_fsmnt , dq->dq_bwarn , dq->dq_bwarn > 1 ? "s" : "" ); else uprintf( "WARNING: too much disc space on %s, NO MORE!!\n" , fs->fs_fsmnt ); } else dq->dq_bwarn = MAX_DQ_WARN; } #endif flags); } else for (; *s > 32; s++) ; } if (any) _pchar('>', flags); } break; case 's': s = (char *)*adx; while (c = *s++) _pchar(c, flags); break; case '%': _pchar(c, flags); break; default: _pchar('%', flags); _pchar(c, flags); break; } adx++; goto loop; } /* copied from subr_prf.c */ printn(n, b, flagssys/sys/quota_ufs.c 440 0 12 13431 5514434447 7664 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)quota_ufs.c 7.1.1 (2.11BSD GTE) 12/31/93 */ /* * MELBOURNE QUOTAS * * Routines used in checking limits on file system usage. */ #include "param.h" #ifdef QUOTA #include "systm.h" #include "user.h" #include "proc.h" #include "inode.h" #include "quota.h" #include "fs.h" #include "mount.h" #include "uio.h" /* * Find the dquot structure that should * be used in checking i/o on inode ip. */ struct dquot * inoquota(ip) register struct inode *ip; { register struct quota *q; register struct dquot **dqq; register struct mount *mp; int index; top: q = qfind(ip->i_uid); if (q == NOQUOTA) { for (mp = mount; mp < &mount[NMOUNT]; mp++) #ifdef pdp11 if (mp->m_inodp && mp->m_dev == ip->i_dev) #else if (mp->m_bufp && mp->m_dev == ip->i_dev) #endif return (discquota(ip->i_uid, mp->m_qinod)); panic("inoquota"); } /* * We have a quota struct in core (most likely our own) that * belongs to the same user as the inode */ if (q->q_flags & Q_NDQ) return (NODQUOT); if (q->q_flags & Q_LOCK) { q->q_flags |= Q_WANT; #ifdef pdp11 QUOTAUNMAP(); sleep((caddr_t)q, PINOD+1); QUOTAMAP(); #else sleep((caddr_t)q, PINOD+1); #endif goto top; /* might just have been freed */ } index = getfsx(ip->i_dev); dqq = &q->q_dq[index]; if (*dqq == LOSTDQUOT) { q->q_flags |= Q_LOCK; *dqq = discquota(q->q_uid, mount[index].m_qinod); if (*dqq != NODQUOT) (*dqq)->dq_own = q; if (q->q_flags & Q_WANT) wakeup((caddr_t)q); q->q_flags &= ~(Q_LOCK | Q_WANT); } if (*dqq != NODQUOT) (*dqq)->dq_cnt++; return (*dqq); } /* * Update disc usage, and take corrective action. */ chkdq(ip, change, force) register struct inode *ip; long change; int force; { register struct dquot *dq; if (change == 0) return (0); #ifdef pdp11 dq = ix_dquot[ip - inode]; #else dq = ip->i_dquot; #endif if (dq == NODQUOT) return (0); if (dq->dq_bsoftlimit == 0) return (0); dq->dq_flags |= DQ_MOD; /* * reset warnings if below disk quota. */ if (dq->dq_bwarn == 0 && dq->dq_bsoftlimit && (dq->dq_curblocks + change) < dq->dq_bsoftlimit) { dq->dq_bwarn = MAX_DQ_WARN; if (dq->dq_own == u.u_quota) { uprintf("\nUNDER DISC QUOTA: (%s) by %d Kbytes\n", ip->i_fs->fs_fsmnt, #ifdef pdp11 (dq->dq_bsoftlimit + 1023L - (dq->dq_curblocks + change)) / 1024); #else dbtob(dq->dq_bsoftlimit - (dq->dq_curblocks + change)) / 1024); #endif } } if (change < 0) { if (dq->dq_curblocks + change >= 0) dq->dq_curblocks += change; else dq->dq_curblocks = 0; dq->dq_flags &= ~DQ_BLKS; return (0); } /* * If user is over quota, or has run out of warnings, then * disallow space allocation (except su's are never stopped). */ if (u.u_uid == 0) force = 1; if (!force && dq->dq_bwarn == 0) { if ((dq->dq_flags & DQ_BLKS) == 0 && dq->dq_own == u.u_quota) { uprintf("\nOVER DISC QUOTA: (%s) NO MORE DISC SPACE\n", ip->i_fs->fs_fsmnt); dq->dq_flags |= DQ_BLKS; } return (EDQUOT); } if (dq->dq_curblocks < dq->dq_bsoftlimit) { dq->dq_curblocks += change; if (dq->dq_curblocks < dq->dq_bsoftlimit) return (0); if (dq->dq_own == u.u_quota) uprintf("\nWARNING: disc quota (%s) exceeded\n", ip->i_fs->fs_fsmnt); return (0); } if (!force && dq->dq_bhardlimit && dq->dq_curblocks + change >= dq->dq_bhardlimit) { if ((dq->dq_flags & DQ_BLKS) == 0 && dq->dq_own == u.u_quota) { uprintf("\nDISC LIMIT REACHED (%s) - WRITE FAILED\n", ip->i_fs->fs_fsmnt); dq->dq_flags |= DQ_BLKS; } return (EDQUOT); } /* * User is over quota, but not over limit * or is over limit, but we have been told * there is nothing we can do. */ dq->dq_curblocks += change; return (0); } /* * Check the inode limit, applying corrective action. */ chkiq(dev, ip, uid, force) dev_t dev; uid_t uid; register struct inode *ip; int force; { register struct dquot *dq; register struct quota *q; if (ip == NULL) { /* allocation */ q = qfind(uid); if (q != NOQUOTA) dq = dqp(q, dev); else dq = discquota(uid, mount[getfsx(dev)].m_qinod); } else { /* free */ #ifdef pdp11 dq = ix_dquot[ip - inode]; #else dq = ip->i_dquot; #endif if (dq != NODQUOT) dq->dq_cnt++; } if (dq == NODQUOT) return (0); if (dq->dq_isoftlimit == 0) { dqrele(dq); return (0); } dq->dq_flags |= DQ_MOD; if (ip) { /* a free */ if (dq->dq_curinodes) dq->dq_curinodes--; dq->dq_flags &= ~DQ_INODS; dqrele(dq); return (0); } /* * The following shouldn't be necessary, as if u.u_uid == 0 * then dq == NODQUOT & we wouldn't get here at all, but * then again, its not going to harm anything ... */ if (u.u_uid == 0) /* su's musn't be stopped */ force = 1; if (!force && dq->dq_iwarn == 0) { if ((dq->dq_flags & DQ_INODS) == 0 && dq->dq_own == u.u_quota) { uprintf("\nOVER FILE QUOTA - NO MORE FILES (%s)\n", getfs(dq->dq_dev)->fs_fsmnt); dq->dq_flags |= DQ_INODS; } dqrele(dq); return (EDQUOT); } if (dq->dq_curinodes < dq->dq_isoftlimit) { if (++dq->dq_curinodes >= dq->dq_isoftlimit && dq->dq_own == u.u_quota) uprintf("\nWARNING - too many files (%s)\n", getfs(dq->dq_dev)->fs_fsmnt); dqrele(dq); return (0); } if (!force && dq->dq_ihardlimit && dq->dq_curinodes + 1 >= dq->dq_ihardlimit) { if ((dq->dq_flags & DQ_INODS) == 0 && dq->dq_own == u.u_quota) { uprintf("\nFILE LIMIT REACHED - CREATE FAILED (%s)\n", getfs(dq->dq_dev)->fs_fsmnt); dq->dq_flags |= DQ_INODS; } dqrele(dq); return (EDQUOT); } /* * Over quota but not at limit; * or over limit, but we aren't * allowed to stop it. */ dq->dq_curinodes++; dqrele(dq); return (0); } #endif " and * then calls the kernel entry netcrash() to bring down the net. */ panic(s) register char *s; { printf("net panic: %s\n", s); NETCRASH(); /* NOTREACHED */ } netcopyout(m, to, len) struct mbuf *m; char *to; int *len;sys/sys/sys_kern.c 440 0 12 5724 5321525002 7461 /* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * %W% (Berkeley) %G% */ #include "param.h" #include "../machine/seg.h" #include "user.h" #include "file.h" #include "socketvar.h" #include "inode.h" #include "proc.h" #include "namei.h" #include "mbuf.h" #include "map.h" int knetisr; netcrash() { panic("Network crashed"); } /* * These next entry points exist to allow the network kernel to * access components of structures that exist in kernel data space. */ netpsignal(p, sig) /* XXX? sosend, sohasoutofband, sowakeup */ struct proc *p; /* if necessary, wrap psignal in save/restor */ int sig; { mapinfo map; savemap(map); psignal(p, sig); restormap(map); } struct proc * netpfind(pid) int pid; { register struct proc *p; mapinfo map; savemap(map); p = pfind(pid); restormap(map); return(p); } void fpflags(fp, set, clear) struct file *fp; int set, clear; { fp->f_flag |= set; fp->f_flag &= ~clear; } void fadjust(fp, msg, cnt) struct file *fp; int msg, cnt; { fp->f_msgcount += msg; fp->f_count += cnt; } fpfetch(fp, fpp) struct file *fp, *fpp; { *fpp = *fp; return(fp->f_count); } void unpdet(ip) struct inode *ip; { ip->i_socket = 0; irele(ip); } unpbind(path, len, ipp, unpsock) char *path; int len; struct inode **ipp; struct socket *unpsock; { /* * As far as I could find out, the 'path' is in the _u area because * a fake mbuf was MBZAP'd in bind(). The inode pointer is in the * kernel stack so we can modify it. SMS */ register struct inode *ip; char pth[MLEN]; int error; register struct nameidata *ndp = &u.u_nd; bcopy(path, pth, len); ndp->ni_nameiop = CREATE | FOLLOW; ndp->ni_segflg = UIO_SYSSPACE; ndp->ni_dirp = pth; ndp->ni_dirp[len - 2] = 0; *ipp = 0; ip = namei(ndp); if (ip) { iput(ip); return(EADDRINUSE); } if (u.u_error || !(ip = maknode(IFSOCK | 0777, ndp))) { error = u.u_error; u.u_error = 0; return(error); } *ipp = ip; ip->i_socket = unpsock; iunlock(ip); return(0); } unpconn(path, len, so2, ipp) char *path; int len; struct socket **so2; struct inode **ipp; { register struct inode *ip; char pth[MLEN]; int error; register struct nameidata *ndp = &u.u_nd; bcopy(path, pth, len); if (!len) return(EINVAL); /* paranoia */ ndp->ni_nameiop = LOOKUP | FOLLOW; ndp->ni_segflg = UIO_SYSSPACE; ndp->ni_dirp = pth; ndp->ni_dirp[len - 2] = 0; ip = namei(ndp); *ipp = ip; if (!ip || access(ip, IWRITE)) { error = u.u_error; u.u_error = 0; return(error); } if ((ip->i_mode & IFMT) != IFSOCK) return(ENOTSOCK); *so2 = ip->i_socket; if (*so2 == 0) return(ECONNREFUSED); return(0); } unpgc1(beginf, endf) struct file **beginf, **endf; { register struct file *fp; for (*beginf = fp = file; fp < fileNFILE; fp++) fp->f_flag &= ~(FMARK|FDEFER); *endf = fileNFILE; } unpdisc(fp) struct file *fp; { --fp->f_msgcount; closef(fp); } ILES (%s)\n", getfs(dq->dq_dev)->fs_fsys/sys/subr_log.c 440 0 12 7336 5667263624 7467 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)subr_log.c 1.3 (2.11BSD GTE) 11/30/94 */ /* * Error log buffer for kernel printf's. */ #include "param.h" #include "user.h" #include "proc.h" #include "ioctl.h" #include "msgbuf.h" #include "file.h" #include "inode.h" #include "errno.h" #include "uio.h" #include "machine/seg.h" #define LOG_RDPRI (PZERO + 1) #define LOG_ASYNC 0x04 #define LOG_RDWAIT 0x08 struct logsoftc { int sc_state; /* see above for possibilities */ struct proc *sc_selp; /* process waiting on select call */ int sc_pgid; /* process/group for async I/O */ } logsoftc; int log_open; /* also used in log() */ /*ARGSUSED*/ logopen(dev, mode) dev_t dev; int mode; { if (log_open) return (EBUSY); log_open = 1; logsoftc.sc_pgid = u.u_procp->p_pid; /* signal process only */ #ifndef pdp11 /* * Potential race here with putchar() but since putchar should be * called by autoconf, msg_magic should be initialized by the time * we get here. */ if (msgbuf.msg_magic != MSG_MAGIC) { register int i; msgbuf.msg_magic = MSG_MAGIC; msgbuf.msg_bufx = msgbuf.msg_bufr = 0; for (i=0; i < MSG_BSIZE; i++) msgbuf.msg_bufc[i] = 0; } #endif return (0); } /*ARGSUSED*/ logclose(dev, flag) dev_t dev; { log_open = 0; logsoftc.sc_state = 0; } /*ARGSUSED*/ logread(dev, uio, flag) dev_t dev; struct uio *uio; int flag; { register int l; register int s; int error = 0; #ifdef pdp11 char buf[ctob(2)]; #endif s = splhigh(); while (msgbuf.msg_bufr == msgbuf.msg_bufx) { if (flag & IO_NDELAY) { splx(s); return (EWOULDBLOCK); } logsoftc.sc_state |= LOG_RDWAIT; sleep((caddr_t)&msgbuf, LOG_RDPRI); } splx(s); logsoftc.sc_state &= ~LOG_RDWAIT; while (uio->uio_resid) { l = msgbuf.msg_bufx - msgbuf.msg_bufr; if (l < 0) l = MSG_BSIZE - msgbuf.msg_bufr; l = MIN(l, uio->uio_resid); if (l == 0) break; #ifdef pdp11 l = MIN(l, sizeof buf); mapseg5(msgbuf.msg_click, (btoc(MSG_BSIZE) << 8) | RW); bcopy(&msgbuf.msg_bufc[msgbuf.msg_bufr], buf, l); normalseg5(); error = uiomove(buf, l, uio); #else error = uiomove((caddr_t)&msgbuf.msg_bufc[msgbuf.msg_bufr], (int)l, uio); #endif if (error) break; msgbuf.msg_bufr += l; if (msgbuf.msg_bufr < 0 || msgbuf.msg_bufr >= MSG_BSIZE) msgbuf.msg_bufr = 0; } return (error); } /*ARGSUSED*/ logselect(dev, rw) dev_t dev; int rw; { register int s = splhigh(); switch (rw) { case FREAD: if (msgbuf.msg_bufr != msgbuf.msg_bufx) { splx(s); return (1); } logsoftc.sc_selp = u.u_procp; break; } splx(s); return (0); } logwakeup() { register struct proc *p; if (!log_open) return; if (logsoftc.sc_selp) { selwakeup(logsoftc.sc_selp, (long) 0); logsoftc.sc_selp = 0; } if (logsoftc.sc_state & LOG_ASYNC) { if (logsoftc.sc_pgid < 0) gsignal(-logsoftc.sc_pgid, SIGIO); else if (p = pfind(logsoftc.sc_pgid)) psignal(p, SIGIO); } if (logsoftc.sc_state & LOG_RDWAIT) { wakeup((caddr_t)&msgbuf); logsoftc.sc_state &= ~LOG_RDWAIT; } } /*ARGSUSED*/ logioctl(com, data, flag) caddr_t data; { long l; register int s; switch (com) { /* return number of characters immediately available */ case FIONREAD: s = splhigh(); l = msgbuf.msg_bufx - msgbuf.msg_bufr; splx(s); if (l < 0) l += MSG_BSIZE; *(off_t *)data = l; break; case FIONBIO: break; case FIOASYNC: if (*(int *)data) logsoftc.sc_state |= LOG_ASYNC; else logsoftc.sc_state &= ~LOG_ASYNC; break; case TIOCSPGRP: logsoftc.sc_pgid = *(int *)data; break; case TIOCGPGRP: *(int *)data = logsoftc.sc_pgid; break; default: return (-1); } return (0); } oftc.sc_state |= LOG_RDWAIT; sleep((caddr_t)&msgbuf, LOG_RDPRI); } splx(s); logsoftc.sc_state &= ~LOG_RDWAIT; while (uio->uio_resid) { l = msgbuf.msg_bufx - msgbuf.msg_bufr; if (l < 0) l = MSG_BSIZE - msgbuf.msg_bufr; l = MIN(l, uio->uio_resid); if (l == 0) break; #ifdsys/sys/kern_resource.c 440 0 12 12525 5347562603 10527 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)kern_resource.c 1.3 (2.11BSD GTE) 3/10/93 */ #include "param.h" #include "user.h" #include "proc.h" #include "systm.h" #include "vm.h" #include "kernel.h" /* * Resource controls and accounting. */ getpriority() { register struct a { int which; int who; } *uap = (struct a *)u.u_ap; register struct proc *p; register int low = PRIO_MAX + 1; switch (uap->which) { case PRIO_PROCESS: if (uap->who == 0) p = u.u_procp; else p = pfind(uap->who); if (p == 0) break; low = p->p_nice; break; case PRIO_PGRP: if (uap->who == 0) uap->who = u.u_procp->p_pgrp; for (p = allproc; p != NULL; p = p->p_nxt) { if (p->p_pgrp == uap->who && p->p_nice < low) low = p->p_nice; } break; case PRIO_USER: if (uap->who == 0) uap->who = u.u_uid; for (p = allproc; p != NULL; p = p->p_nxt) { if (p->p_uid == uap->who && p->p_nice < low) low = p->p_nice; } break; default: u.u_error = EINVAL; return; } if (low == PRIO_MAX + 1) { u.u_error = ESRCH; return; } u.u_r.r_val1 = low; } setpriority() { register struct a { int which; int who; int prio; } *uap = (struct a *)u.u_ap; register struct proc *p; register int found = 0; switch (uap->which) { case PRIO_PROCESS: if (uap->who == 0) p = u.u_procp; else p = pfind(uap->who); if (p == 0) break; donice(p, uap->prio); found++; break; case PRIO_PGRP: if (uap->who == 0) uap->who = u.u_procp->p_pgrp; for (p = allproc; p != NULL; p = p->p_nxt) if (p->p_pgrp == uap->who) { donice(p, uap->prio); found++; } break; case PRIO_USER: if (uap->who == 0) uap->who = u.u_uid; for (p = allproc; p != NULL; p = p->p_nxt) if (p->p_uid == uap->who) { donice(p, uap->prio); found++; } break; default: u.u_error = EINVAL; return; } if (found == 0) u.u_error = ESRCH; } donice(p, n) register struct proc *p; register int n; { if (u.u_uid && u.u_ruid && u.u_uid != p->p_uid && u.u_ruid != p->p_uid) { u.u_error = EPERM; return; } if (n > PRIO_MAX) n = PRIO_MAX; if (n < PRIO_MIN) n = PRIO_MIN; if (n < p->p_nice && !suser()) { u.u_error = EACCES; return; } p->p_nice = n; } setrlimit() { register struct a { u_int which; struct rlimit *lim; } *uap = (struct a *)u.u_ap; struct rlimit alim; register struct rlimit *alimp; extern unsigned maxdmap; if (uap->which >= RLIM_NLIMITS) { u.u_error = EINVAL; return; } alimp = &u.u_rlimit[uap->which]; u.u_error = copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit)); if (u.u_error) return; if (uap->which == RLIMIT_CPU) { /* * 2.11 stores RLIMIT_CPU as ticks to keep from making * hardclock() do long multiplication/division. */ if (alim.rlim_cur >= RLIM_INFINITY / LINEHZ) alim.rlim_cur = RLIM_INFINITY; else alim.rlim_cur = alim.rlim_cur * LINEHZ; if (alim.rlim_max >= RLIM_INFINITY / LINEHZ) alim.rlim_max = RLIM_INFINITY; else alim.rlim_max = alim.rlim_max * LINEHZ; } if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max) if (!suser()) return; *alimp = alim; } getrlimit() { register struct a { u_int which; struct rlimit *rlp; } *uap = (struct a *)u.u_ap; if (uap->which >= RLIM_NLIMITS) { u.u_error = EINVAL; return; } if (uap->which == RLIMIT_CPU) { struct rlimit alim; alim = u.u_rlimit[uap->which]; if (alim.rlim_cur != RLIM_INFINITY) alim.rlim_cur = alim.rlim_cur / LINEHZ; if (alim.rlim_max != RLIM_INFINITY) alim.rlim_max = alim.rlim_max / LINEHZ; u.u_error = copyout((caddr_t)&alim, (caddr_t)uap->rlp,sizeof (struct rlimit)); } else u.u_error = copyout((caddr_t)&u.u_rlimit[uap->which], (caddr_t)uap->rlp,sizeof (struct rlimit)); } getrusage() { register struct a { int who; struct rusage *rusage; } *uap = (struct a *)u.u_ap; register struct k_rusage *rup; struct rusage ru; switch (uap->who) { case RUSAGE_SELF: rup = &u.u_ru; break; case RUSAGE_CHILDREN: rup = &u.u_cru; break; default: u.u_error = EINVAL; return; } rucvt(&ru,rup); u.u_error = copyout((caddr_t)&ru, (caddr_t)uap->rusage, sizeof (struct rusage)); } ruadd(ru, ru2) struct k_rusage *ru, *ru2; { register long *ip, *ip2; register int i; /* * since the kernel timeval structures are single longs, * fold them into the loop. */ ip = &ru->k_ru_first; ip2 = &ru2->k_ru_first; for (i = &ru->k_ru_last - &ru->k_ru_first; i >= 0; i--) *ip++ += *ip2++; } /* * Convert an internal kernel rusage structure into a `real' rusage structure. */ rucvt(rup, krup) register struct rusage *rup; register struct k_rusage *krup; { bzero((caddr_t)rup, sizeof(*rup)); rup->ru_utime.tv_sec = krup->ru_utime / LINEHZ; rup->ru_utime.tv_usec = (krup->ru_utime % LINEHZ * 1000000) / LINEHZ; rup->ru_stime.tv_sec = krup->ru_stime / LINEHZ; rup->ru_stime.tv_usec = (krup->ru_stime % LINEHZ * 1000000) / LINEHZ; rup->ru_ovly = krup->ru_ovly; rup->ru_nswap = krup->ru_nswap; rup->ru_inblock = krup->ru_inblock; rup->ru_oublock = krup->ru_oublock; rup->ru_msgsnd = krup->ru_msgsnd; rup->ru_msgrcv = krup->ru_msgrcv; rup->ru_nsignals = krup->ru_nsignals; rup->ru_nvcsw = krup->ru_nvcsw; rup->ru_nivcsw = krup->ru_nivcsw; } newp) error = copyin(newp, valp, sizeof(int)); return (error); } /* * An old version of uiomove, as uiofmove() and vcopy{in,out}() don't * exist in supervisor space.sys/sys/uipc_syscalls.c 440 0 12 36636 5670016220 10533 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)uipc_syscalls.c 7.1.2 (2.11BSD GTE) 12/2/94 */ #include "param.h" #include "../machine/seg.h" #include "../machine/psl.h" #include "systm.h" #include "user.h" #include "proc.h" #include "file.h" #include "inode.h" #include "buf.h" #include "mbuf.h" #include "protosw.h" #include "socket.h" #include "socketvar.h" #include "uio.h" #include "domain.h" #include "pdpif/if_uba.h" #include "netinet/in.h" #include "netinet/in_systm.h" static void MBZAP(m, len, type) register struct mbuf *m; int len, type; { m->m_next = 0; m->m_off = MMINOFF; m->m_len = len; m->m_type = type; m->m_act = 0; } /* * System call interface to the socket abstraction. */ extern int netoff; struct file *gtsockf(); socket() { register struct a { int domain; int type; int protocol; } *uap = (struct a *)u.u_ap; struct socket *so; register struct file *fp; if (netoff) return(u.u_error = ENETDOWN); if ((fp = falloc()) == NULL) return; fp->f_flag = FREAD|FWRITE; fp->f_type = DTYPE_SOCKET; u.u_error = SOCREATE(uap->domain, &so, uap->type, uap->protocol); if (u.u_error) goto bad; fp->f_socket = so; return; bad: u.u_ofile[u.u_r.r_val1] = 0; fp->f_count = 0; } bind() { register struct a { int s; caddr_t name; u_int namelen; } *uap = (struct a *)u.u_ap; register struct file *fp; register struct mbuf *nam; char sabuf[MSIZE]; if (netoff) return(u.u_error = ENETDOWN); fp = gtsockf(uap->s); if (fp == 0) return; nam = (struct mbuf *)sabuf; MBZAP(nam, uap->namelen, MT_SONAME); if (uap->namelen > MLEN) return (u.u_error = EINVAL); u.u_error = copyin(uap->name, mtod(nam, caddr_t), uap->namelen); if (u.u_error) return; u.u_error = SOBIND(fp->f_socket, nam); } listen() { register struct a { int s; int backlog; } *uap = (struct a *)u.u_ap; register struct file *fp; if (netoff) return(u.u_error = ENETDOWN); fp = gtsockf(uap->s); if (fp == 0) return; u.u_error = SOLISTEN(fp->f_socket, uap->backlog); } accept() { register struct a { int s; caddr_t name; int *anamelen; } *uap = (struct a *)u.u_ap; register struct file *fp; struct mbuf *nam; int namelen; int s; register struct socket *so; char sabuf[MSIZE]; if (netoff) return(u.u_error = ENETDOWN); if (uap->name == 0) goto noname; u.u_error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen, sizeof (namelen)); if (u.u_error) return; #ifndef pdp11 if (useracc((caddr_t)uap->name, (u_int)namelen, B_WRITE) == 0) { u.u_error = EFAULT; return; } #endif noname: fp = gtsockf(uap->s); if (fp == 0) return; s = splnet(); so = fp->f_socket; if (SOACC1(so)) { splx(s); return; } if (ufalloc(0) < 0) { splx(s); return; } fp = falloc(); if (fp == 0) { u.u_ofile[u.u_r.r_val1] = 0; splx(s); return; } if (!(so = (struct socket *)ASOQREMQUE(so, 1))) /* deQ in super */ panic("accept"); fp->f_type = DTYPE_SOCKET; fp->f_flag = FREAD|FWRITE; fp->f_socket = so; nam = (struct mbuf *)sabuf; MBZAP(nam, 0, MT_SONAME); u.u_error = SOACCEPT(so, nam); if (uap->name) { if (namelen > nam->m_len) namelen = nam->m_len; /* SHOULD COPY OUT A CHAIN HERE */ (void) copyout(mtod(nam, caddr_t), (caddr_t)uap->name, (u_int)namelen); (void) copyout((caddr_t)&namelen, (caddr_t)uap->anamelen, sizeof (*uap->anamelen)); } splx(s); } connect() { register struct a { int s; caddr_t name; u_int namelen; } *uap = (struct a *)u.u_ap; register struct file *fp; register struct socket *so; struct mbuf *nam; int s; char sabuf[MSIZE]; struct socket kcopy; if (netoff) return(u.u_error = ENETDOWN); fp = gtsockf(uap->s); if (fp == 0) return; if (uap->namelen > MLEN) return (u.u_error = EINVAL); nam = (struct mbuf *)sabuf; MBZAP(nam, uap->namelen, MT_SONAME); u.u_error = copyin(uap->name, mtod(nam, caddr_t), uap->namelen); if (u.u_error) return; so = fp->f_socket; /* * soconnect was modified to clear the isconnecting bit on errors. * also, it was changed to return the EINPROGRESS error if * nonblocking, etc. */ u.u_error = SOCON1(so, nam); if (u.u_error) return; /* * i don't think the setjmp stuff works too hot in supervisor mode, * so what is done instead is do the setjmp here and then go back * to supervisor mode to do the "while (isconnecting && !error) * sleep()" loop. */ s = splnet(); if (setjmp(&u.u_qsave)) { if (u.u_error == 0) u.u_error = EINTR; goto bad2; } u.u_error = CONNWHILE(so); bad2: splx(s); } socketpair() { register struct a { int domain; int type; int protocol; int *rsv; } *uap = (struct a *)u.u_ap; register struct file *fp1, *fp2; struct socket *so1, *so2; int sv[2]; #ifndef pdp11 if (useracc((caddr_t)uap->rsv, 2 * sizeof (int), B_WRITE) == 0) { u.u_error = EFAULT; return; } #endif if (netoff) return(u.u_error = ENETDOWN); u.u_error = SOCREATE(uap->domain, &so1, uap->type, uap->protocol); if (u.u_error) return; u.u_error = SOCREATE(uap->domain, &so2, uap->type, uap->protocol); if (u.u_error) goto free; fp1 = falloc(); if (fp1 == NULL) goto free2; sv[0] = u.u_r.r_val1; fp1->f_flag = FREAD|FWRITE; fp1->f_type = DTYPE_SOCKET; fp1->f_socket = so1; fp2 = falloc(); if (fp2 == NULL) goto free3; fp2->f_flag = FREAD|FWRITE; fp2->f_type = DTYPE_SOCKET; fp2->f_socket = so2; sv[1] = u.u_r.r_val1; u.u_error = SOCON2(so1, so2); if (u.u_error) goto free4; if (uap->type == SOCK_DGRAM) { /* * Datagram socket connection is asymmetric. */ u.u_error = SOCON2(so2, so1); if (u.u_error) goto free4; } u.u_r.r_val1 = 0; (void) copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int)); return; free4: fp2->f_count = 0; u.u_ofile[sv[1]] = 0; free3: fp1->f_count = 0; u.u_ofile[sv[0]] = 0; free2: (void)SOCLOSE(so2); free: (void)SOCLOSE(so1); } sendto() { register struct a { int s; caddr_t buf; int len; int flags; caddr_t to; int tolen; } *uap = (struct a *)u.u_ap; struct msghdr msg; struct iovec aiov; msg.msg_name = uap->to; msg.msg_namelen = uap->tolen; msg.msg_iov = &aiov; msg.msg_iovlen = 1; aiov.iov_base = uap->buf; aiov.iov_len = uap->len; msg.msg_accrights = 0; msg.msg_accrightslen = 0; sendit(uap->s, &msg, uap->flags); } send() { register struct a { int s; caddr_t buf; int len; int flags; } *uap = (struct a *)u.u_ap; struct msghdr msg; struct iovec aiov; msg.msg_name = 0; msg.msg_namelen = 0; msg.msg_iov = &aiov; msg.msg_iovlen = 1; aiov.iov_base = uap->buf; aiov.iov_len = uap->len; msg.msg_accrights = 0; msg.msg_accrightslen = 0; sendit(uap->s, &msg, uap->flags); } sendmsg() { register struct a { int s; caddr_t msg; int flags; } *uap = (struct a *)u.u_ap; struct msghdr msg; struct iovec aiov[MSG_MAXIOVLEN]; u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg)); if (u.u_error) return; if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) { u.u_error = EMSGSIZE; return; } u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov, (unsigned)(msg.msg_iovlen * sizeof (aiov[0]))); if (u.u_error) return; msg.msg_iov = aiov; sendit(uap->s, &msg, uap->flags); } sendit(s, mp, flags) int s; register struct msghdr *mp; int flags; { register struct file *fp; struct uio auio; register struct iovec *iov; register int i; struct mbuf *to, *rights; int len; char sabuf[MSIZE], ribuf[MSIZE]; if (netoff) return(u.u_error = ENETDOWN); fp = gtsockf(s); if (fp == 0) return; auio.uio_iov = mp->msg_iov; auio.uio_iovcnt = mp->msg_iovlen; auio.uio_segflg = UIO_USERSPACE; auio.uio_offset = 0; /* XXX */ auio.uio_resid = 0; auio.uio_rw = UIO_WRITE; iov = mp->msg_iov; for (i = 0; i < mp->msg_iovlen; i++, iov++) { #ifndef pdp11 if (iov->iov_len < 0) { u.u_error = EINVAL; return; } #endif if (iov->iov_len == 0) continue; #ifndef pdp11 if (useracc(iov->iov_base, (u_int)iov->iov_len, B_READ) == 0) { u.u_error = EFAULT; return; } #endif auio.uio_resid += iov->iov_len; } if (mp->msg_name) { to = (struct mbuf *)sabuf; MBZAP(to, mp->msg_namelen, MT_SONAME); u.u_error = copyin(mp->msg_name, mtod(to, caddr_t), mp->msg_namelen); if (u.u_error) return; } else to = 0; if (mp->msg_accrights) { rights = (struct mbuf *)ribuf; MBZAP(rights, mp->msg_accrightslen, MT_RIGHTS); if (mp->msg_accrightslen > MLEN) return(u.u_error = EINVAL); u.u_error = copyin(mp->msg_accrights, mtod(rights, caddr_t), mp->msg_accrightslen); if (u.u_error) return; } else rights = 0; len = auio.uio_resid; u.u_error = SOSEND(fp->f_socket, to, &auio, flags, rights); u.u_r.r_val1 = len - auio.uio_resid; } recvfrom() { register struct a { int s; caddr_t buf; int len; int flags; caddr_t from; int *fromlenaddr; } *uap = (struct a *)u.u_ap; struct msghdr msg; struct iovec aiov; int len; u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&len, sizeof (len)); if (u.u_error) return; msg.msg_name = uap->from; msg.msg_namelen = len; msg.msg_iov = &aiov; msg.msg_iovlen = 1; aiov.iov_base = uap->buf; aiov.iov_len = uap->len; msg.msg_accrights = 0; msg.msg_accrightslen = 0; recvit(uap->s, &msg, uap->flags, (caddr_t)uap->fromlenaddr, (caddr_t)0); } recv() { register struct a { int s; caddr_t buf; int len; int flags; } *uap = (struct a *)u.u_ap; struct msghdr msg; struct iovec aiov; msg.msg_name = 0; msg.msg_namelen = 0; msg.msg_iov = &aiov; msg.msg_iovlen = 1; aiov.iov_base = uap->buf; aiov.iov_len = uap->len; msg.msg_accrights = 0; msg.msg_accrightslen = 0; recvit(uap->s, &msg, uap->flags, (caddr_t)0, (caddr_t)0); } recvmsg() { register struct a { int s; struct msghdr *msg; int flags; } *uap = (struct a *)u.u_ap; struct msghdr msg; struct iovec aiov[MSG_MAXIOVLEN]; u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg)); if (u.u_error) return; if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) { u.u_error = EMSGSIZE; return; } u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov, (unsigned)(msg.msg_iovlen * sizeof(aiov[0]))); if (u.u_error) return; recvit(uap->s, &msg, uap->flags, (caddr_t)&uap->msg->msg_namelen, (caddr_t)&uap->msg->msg_accrightslen); } recvit(s, mp, flags, namelenp, rightslenp) int s; register struct msghdr *mp; int flags; caddr_t namelenp, rightslenp; { register struct file *fp; struct uio auio; register struct iovec *iov; register int i; struct mbuf *from, *rights; int len, m_freem(); if (netoff) return(u.u_error = ENETDOWN); fp = gtsockf(s); if (fp == 0) return; auio.uio_iov = mp->msg_iov; auio.uio_iovcnt = mp->msg_iovlen; auio.uio_segflg = UIO_USERSPACE; auio.uio_offset = 0; /* XXX */ auio.uio_resid = 0; auio.uio_rw = UIO_READ; iov = mp->msg_iov; for (i = 0; i < mp->msg_iovlen; i++, iov++) { #ifndef pdp11 if (iov->iov_len < 0) { u.u_error = EINVAL; return; } #endif if (iov->iov_len == 0) continue; #ifndef pdp11 if (useracc(iov->iov_base, (u_int)iov->iov_len, B_WRITE) == 0) { u.u_error = EFAULT; return; } #endif auio.uio_resid += iov->iov_len; } len = auio.uio_resid; u.u_error = SORECEIVE((struct socket *)fp->f_data, &from, &auio,flags, &rights); u.u_r.r_val1 = len - auio.uio_resid; if (mp->msg_name) { len = mp->msg_namelen; if (len <= 0 || from == 0) len = 0; else (void) NETCOPYOUT(from, mp->msg_name, &len); (void) copyout((caddr_t)&len, namelenp, sizeof(int)); } if (mp->msg_accrights) { len = mp->msg_accrightslen; if (len <= 0 || rights == 0) len = 0; else (void) NETCOPYOUT(rights, mp->msg_accrights, &len); (void) copyout((caddr_t)&len, rightslenp, sizeof(int)); } if (rights) M_FREEM(rights); if (from) M_FREEM(from); } shutdown() { register struct a { int s; int how; } *uap = (struct a *)u.u_ap; register struct file *fp; if (netoff) return(u.u_error = ENETDOWN); fp = gtsockf(uap->s); if (fp == 0) return; u.u_error = SOSHUTDOWN(fp->f_socket, uap->how); } setsockopt() { register struct a { int s; int level; int name; caddr_t val; u_int valsize; } *uap = (struct a *)u.u_ap; register struct file *fp; register struct mbuf *m = NULL; char optbuf[MSIZE]; if (netoff) return(u.u_error = ENETDOWN); fp = gtsockf(uap->s); if (fp == 0) return; if (uap->valsize > MLEN) { u.u_error = EINVAL; return; } if (uap->val) { m = (struct mbuf *)optbuf; MBZAP(m, uap->valsize, MT_SOOPTS); u.u_error = copyin(uap->val, mtod(m, caddr_t), (u_int)uap->valsize); if (u.u_error) return; } u.u_error = SOSETOPT(fp->f_socket, uap->level, uap->name, m); } getsockopt() { register struct a { int s; int level; int name; caddr_t val; int *avalsize; } *uap = (struct a *)u.u_ap; register struct file *fp; struct mbuf *m = NULL, *m_free(); int valsize; if (netoff) return(u.u_error = ENETDOWN); fp = gtsockf(uap->s); if (fp == 0) return; if (uap->val) { u.u_error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize, sizeof (valsize)); if (u.u_error) return; } else valsize = 0; u.u_error = SOGETOPT(fp->f_socket, uap->level, uap->name, &m); if (u.u_error) goto bad; if (uap->val && valsize && m != NULL) { u.u_error = NETCOPYOUT(m, uap->val, &valsize); if (u.u_error) goto bad; u.u_error = copyout((caddr_t)&valsize, (caddr_t)uap->avalsize, sizeof (valsize)); } bad: if (m != NULL) M_FREE(m); } /* * Get socket name. */ getsockname() { register struct a { int fdes; caddr_t asa; int *alen; } *uap = (struct a *)u.u_ap; register struct file *fp; struct mbuf *m; int len; char sabuf[MSIZE]; if (netoff) return(u.u_error = ENETDOWN); fp = gtsockf(uap->fdes); if (fp == 0) return; u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)); if (u.u_error) return; m = (struct mbuf *)sabuf; MBZAP(m, 0, MT_SONAME); u.u_error = SOGETNAM(fp->f_socket, m); if (u.u_error) return; if (len > m->m_len) len = m->m_len; u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len); if (u.u_error) return; u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len)); } /* * Get name of peer for connected socket. */ getpeername() { register struct a { int fdes; caddr_t asa; int *alen; } *uap = (struct a *)u.u_ap; register struct file *fp; struct mbuf *m; u_int len; char sabuf[MSIZE]; if (netoff) return(u.u_error = ENETDOWN); fp = gtsockf(uap->fdes); if (fp == 0) return; m = (struct mbuf *)sabuf; MBZAP(m, 0, MT_SONAME); u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)); if (u.u_error) return; u.u_error = SOGETPEER(fp->f_socket, m); if (u.u_error) return; if (len > m->m_len) len = m->m_len; u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len); if (u.u_error) return; u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len)); } #ifndef pdp11 sockargs(aname, name, namelen, type) struct mbuf **aname; caddr_t name; int namelen, type; { register struct mbuf *m; int error; struct mbuf *m_free(); if (namelen > MLEN) return (EINVAL); m = m_get(M_WAIT, type); if (m == NULL) return (ENOBUFS); m->m_len = namelen; error = copyin(name, mtod(m, caddr_t), (u_int)namelen); if (error) (void) m_free(m); else *aname = m; return (error); } #endif struct file * gtsockf(fdes) int fdes; { register struct file *fp; fp = getf(fdes); if (fp == NULL) return (0); if (fp->f_type != DTYPE_SOCKET) { u.u_error = ENOTSOCK; return (0); } return (fp); } u.u_error = SOCON2(so1, so2); if (u.u_error) goto free4; if (uap->type == SOCK_DGRAM) { /* sys/sys/kern_exec.c 640 0 12 31634 5705650722 7626 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)kern_exec.c 1.4 (2.11BSD GTE) 1/13/95 */ #include "param.h" #include "../machine/reg.h" #include "../machine/seg.h" #include "systm.h" #include "map.h" #include "user.h" #include "proc.h" #include "buf.h" #include "inode.h" #include "acct.h" #include "namei.h" #include "fs.h" #include "mount.h" #include "file.h" #include "text.h" /* * exec system call, with and without environments. */ struct execa { char *fname; char **argp; char **envp; }; execv() { ((struct execa *)u.u_ap)->envp = NULL; execve(); } execve() { int nc; register char *cp; register struct buf *bp; struct execa *uap; int na, ne, ucp, ap; register int cc; unsigned len; int indir, uid, gid; char *sharg; struct inode *ip; memaddr bno; char cfname[MAXCOMLEN + 1]; #define SHSIZE 32 char cfarg[SHSIZE]; union { char ex_shell[SHSIZE]; /* #! and name of interpreter */ struct exec ex_exec; } exdata; register struct nameidata *ndp = &u.u_nd; int resid, error; ndp->ni_nameiop = LOOKUP | FOLLOW; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = ((struct execa *)u.u_ap)->fname; if ((ip = namei(ndp)) == NULL) return; bno = 0; bp = 0; indir = 0; uid = u.u_uid; gid = u.u_gid; if (ip->i_fs->fs_flags & MNT_NOEXEC) { u.u_error = EACCES; goto bad; } if ((ip->i_fs->fs_flags & MNT_NOSUID) == 0) { if (ip->i_mode & ISUID) uid = ip->i_uid; if (ip->i_mode & ISGID) gid = ip->i_gid; } again: if (access(ip, IEXEC)) goto bad; if ((u.u_procp->p_flag&STRC) && access(ip, IREAD)) goto bad; if ((ip->i_mode & IFMT) != IFREG || (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) { u.u_error = EACCES; goto bad; } /* * Read in first few bytes of file for segment sizes, magic number: * 407 = plain executable * 410 = RO text * 411 = separated I/D * 405 = text overlay * 430 = auto-overlay (nonseparate) * 431 = auto-overlay (separate) * Also an ASCII line beginning with #! is * the file name of a ``shell'' and arguments may be prepended * to the argument list if given here. * * SHELL NAMES ARE LIMITED IN LENGTH. * * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM * THE ASCII LINE. */ exdata.ex_shell[0] = '\0'; /* for zero length files */ u.u_error = rdwri(UIO_READ, ip, &exdata, sizeof(exdata), (off_t)0, UIO_SYSSPACE, IO_UNIT, &resid); if (u.u_error) goto bad; if (resid > sizeof(exdata) - sizeof(exdata.ex_exec) && exdata.ex_shell[0] != '#') { u.u_error = ENOEXEC; goto bad; } switch((int)exdata.ex_exec.a_magic) { case A_MAGIC1: case A_MAGIC2: case A_MAGIC3: case A_MAGIC4: case A_MAGIC5: case A_MAGIC6: break; default: if (exdata.ex_shell[0] != '#' || exdata.ex_shell[1] != '!' || indir) { u.u_error = ENOEXEC; goto bad; } cp = &exdata.ex_shell[2]; /* skip "#!" */ while (cp < &exdata.ex_shell[SHSIZE]) { if (*cp == '\t') *cp = ' '; else if (*cp == '\n') { *cp = '\0'; break; } cp++; } if (*cp != '\0') { u.u_error = ENOEXEC; goto bad; } cp = &exdata.ex_shell[2]; while (*cp == ' ') cp++; ndp->ni_dirp = cp; while (*cp && *cp != ' ') cp++; cfarg[0] = '\0'; if (*cp) { *cp++ = '\0'; while (*cp == ' ') cp++; if (*cp) bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE); } indir = 1; iput(ip); ndp->ni_nameiop = LOOKUP | FOLLOW; ndp->ni_segflg = UIO_SYSSPACE; ip = namei(ndp); if (ip == NULL) return; bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)cfname, MAXCOMLEN); cfname[MAXCOMLEN] = '\0'; goto again; } /* * Collect arguments on "file" in swap space. */ na = 0; ne = 0; nc = 0; cc = 0; uap = (struct execa *)u.u_ap; bno = malloc(swapmap, ctod((int)btoc(NCARGS + MAXBSIZE))); if (bno == 0) { swkill(u.u_procp, "exec"); goto bad; } /* * Copy arguments into file in argdev area. */ if (uap->argp) for (;;) { ap = NULL; sharg = NULL; if (indir && na == 0) { sharg = cfname; ap = (int)sharg; uap->argp++; /* ignore argv[0] */ } else if (indir && (na == 1 && cfarg[0])) { sharg = cfarg; ap = (int)sharg; } else if (indir && (na == 1 || na == 2 && cfarg[0])) ap = (int)uap->fname; else if (uap->argp) { ap = fuword((caddr_t)uap->argp); uap->argp++; } if (ap == NULL && uap->envp) { uap->argp = NULL; if ((ap = fuword((caddr_t)uap->envp)) != NULL) uap->envp++, ne++; } if (ap == NULL) break; na++; if (ap == -1) { u.u_error = EFAULT; break; } do { if (cc <= 0) { /* * We depend on NCARGS being a multiple of * CLSIZE*NBPG. This way we need only check * overflow before each buffer allocation. */ if (nc >= NCARGS-1) { error = E2BIG; break; } if (bp) { mapout(bp); bdwrite(bp); } cc = CLSIZE*NBPG; bp = getblk(swapdev, dbtofsb(clrnd(bno)) + lblkno(nc)); cp = mapin(bp); } if (sharg) { error = copystr(sharg, cp, (unsigned)cc, &len); sharg += len; } else { error = copyinstr((caddr_t)ap, cp, (unsigned)cc, &len); ap += len; } cp += len; nc += len; cc -= len; } while (error == ENOENT); if (error) { u.u_error = error; if (bp) { mapout(bp); bp->b_flags |= B_AGE; bp->b_flags &= ~B_DELWRI; brelse(bp); } bp = 0; goto badarg; } } if (bp) { mapout(bp); bdwrite(bp); } bp = 0; nc = (nc + NBPW-1) & ~(NBPW-1); getxfile(ip, &exdata.ex_exec, nc + (na+4)*NBPW, uid, gid); if (u.u_error) { badarg: for (cc = 0;cc < nc; cc += CLSIZE * NBPG) { daddr_t blkno; blkno = dbtofsb(clrnd(bno)) + lblkno(cc); if (incore(swapdev,blkno)) { bp = bread(swapdev,blkno); bp->b_flags |= B_AGE; /* throw away */ bp->b_flags &= ~B_DELWRI; /* cancel io */ brelse(bp); bp = 0; } } goto bad; } iput(ip); ip = NULL; /* * Copy back arglist. */ ucp = -nc - NBPW; ap = ucp - na*NBPW - 3*NBPW; u.u_ar0[R6] = ap; (void) suword((caddr_t)ap, na-ne); nc = 0; cc = 0; for (;;) { ap += NBPW; if (na == ne) { (void) suword((caddr_t)ap, 0); ap += NBPW; } if (--na < 0) break; (void) suword((caddr_t)ap, ucp); do { if (cc <= 0) { if (bp) { mapout(bp); brelse(bp); } cc = CLSIZE*NBPG; bp = bread(swapdev, dbtofsb(clrnd(bno)) + lblkno(nc)); bp->b_flags |= B_AGE; /* throw away */ bp->b_flags &= ~B_DELWRI; /* cancel io */ cp = mapin(bp); } error = copyoutstr(cp, (caddr_t)ucp, (unsigned)cc, &len); ucp += len; cp += len; nc += len; cc -= len; } while (error == ENOENT); if (error == EFAULT) panic("exec: EFAULT"); } (void) suword((caddr_t)ap, 0); (void) suword((caddr_t)(-NBPW), 0); if (bp) { mapout(bp); bp->b_flags |= B_AGE; brelse(bp); bp = NULL; } execve1(); while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL) u.u_lastfile--; /* * inline expansion of setregs(), found * in ../pdp/machdep.c * * setregs(exdata.ex_exec.a_entry); */ u.u_ar0[PC] = exdata.ex_exec.a_entry & ~01; u.u_fps.u_fpsr = 0; /* * Remember file name for accounting. */ u.u_acflag &= ~AFORK; if (indir) bcopy((caddr_t)cfname, (caddr_t)u.u_comm, MAXCOMLEN); else bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)u.u_comm, MAXCOMLEN); bad: if (bp) { mapout(bp); bp->b_flags |= B_AGE; brelse(bp); } if (bno) mfree(swapmap, ctod((int)btoc(NCARGS + MAXBSIZE)), bno); if (ip) iput(ip); } /* * execve1 is a helper routine to speed up execve. */ static execve1() { /* * 4.3 source * * Reset caught signals. Held signals * remain held through p_sigmask. * * In an effort to avoid exspensive long masking operations * we use two integer loops rather than one long loop. * The constant 16 is the number of bits per int. * * while (u.u_procp->p_sigcatch) { * nc = ffs((long)u.u_procp->p_sigcatch); * u.u_procp->p_sigcatch &= ~sigmask(nc); * u.u_signal[nc] = SIG_DFL; * } */ { register int cnt, imask; register int (**sigp)(); long mask; mask = u.u_procp->p_sigcatch; u.u_procp->p_sigcatch = 0; sigp = &u.u_signal[1]; for (cnt = 16, imask = loint(mask); cnt > 0; cnt--, imask >>= 1, sigp++) if (imask&1) *sigp = SIG_DFL; for (cnt = NSIG-16, imask = hiint(mask); cnt > 0; cnt--, imask >>= 1, sigp++) if (imask&1) *sigp = SIG_DFL; } /* * Reset stack state to the user stack. * Clear set of signals caught on the signal stack. */ u.u_onstack = 0; u.u_sigsp = 0; u.u_sigonstack = 0; /* * for (nc = u.u_lastfile; nc >= 0; --nc) { * if (u.u_pofile[nc] & UF_EXCLOSE) { * closef(u.u_ofile[nc]); * u.u_ofile[nc] = NULL; * u.u_pofile[nc] = 0; * } * u.u_pofile[nc] &= ~UF_MAPPED; * } */ { register int cnt; register struct file **ofilep = u.u_ofile; register char *pofilep = u.u_pofile; for (cnt = u.u_lastfile;cnt >= 0; cnt--, ofilep++, pofilep++) if (*pofilep & UF_EXCLOSE) { closef(*ofilep); *ofilep = NULL; *pofilep = 0; } } } /* * Read in and set up memory for executed file. * u.u_error set on error */ getxfile(ip, ep, nargc, uid, gid) struct inode *ip; register struct exec *ep; int nargc, uid, gid; { struct u_ovd sovdata; long lsize; off_t offset; u_int ds, ts, ss; u_int ovhead[NOVL + 1]; int sep, overlay, ovflag, ovmax, resid; overlay = sep = ovflag = 0; switch(ep->a_magic) { case A_MAGIC1: lsize = (long)ep->a_data + ep->a_text; ep->a_data = (u_int)lsize; if (lsize != ep->a_data) { /* check overflow */ u.u_error = ENOMEM; return; } ep->a_text = 0; break; case A_MAGIC3: sep++; break; case A_MAGIC4: overlay++; break; case A_MAGIC5: ovflag++; break; case A_MAGIC6: sep++; ovflag++; break; } if (ip->i_text && (ip->i_text->x_flag & XTRC)) { u.u_error = ETXTBSY; return; } if (ep->a_text != 0 && (ip->i_flag&ITEXT) == 0 && ip->i_count != 1) { register struct file *fp; for (fp = file; fp < fileNFILE; fp++) { if (fp->f_type == DTYPE_INODE && fp->f_count > 0 && (struct inode *)fp->f_data == ip && (fp->f_flag&FWRITE)) { u.u_error = ETXTBSY; return; } } } /* * find text and data sizes try; them out for possible * overflow of max sizes */ ts = btoc(ep->a_text); lsize = (long)ep->a_data + ep->a_bss; if (lsize != (u_int)lsize) { u.u_error = ENOMEM; return; } ds = btoc(lsize); ss = SSIZE + btoc(nargc); /* * if auto overlay get second header */ sovdata = u.u_ovdata; u.u_ovdata.uo_ovbase = 0; u.u_ovdata.uo_curov = 0; if (ovflag) { u.u_error = rdwri(UIO_READ, ip, ovhead, sizeof(ovhead), (off_t)sizeof(struct exec), UIO_SYSSPACE, IO_UNIT, &resid); if (resid != 0) u.u_error = ENOEXEC; if (u.u_error) { u.u_ovdata = sovdata; return; } /* set beginning of overlay segment */ u.u_ovdata.uo_ovbase = ctos(ts); /* 0th entry is max size of the overlays */ ovmax = btoc(ovhead[0]); /* set max number of segm. registers to be used */ u.u_ovdata.uo_nseg = ctos(ovmax); /* set base of data space */ u.u_ovdata.uo_dbase = stoc(u.u_ovdata.uo_ovbase + u.u_ovdata.uo_nseg); /* * Set up a table of offsets to each of the overlay * segements. The ith overlay runs from ov_offst[i-1] * to ov_offst[i]. */ u.u_ovdata.uo_ov_offst[0] = ts; { register int t, i; /* check if any overlay is larger than ovmax */ for (i = 1; i <= NOVL; i++) { if ((t = btoc(ovhead[i])) > ovmax) { u.u_error = ENOEXEC; u.u_ovdata = sovdata; return; } u.u_ovdata.uo_ov_offst[i] = t + u.u_ovdata.uo_ov_offst[i - 1]; } } } if (overlay) { if (u.u_sep == 0 && ctos(ts) != ctos(u.u_tsize) || nargc) { u.u_error = ENOMEM; return; } ds = u.u_dsize; ss = u.u_ssize; sep = u.u_sep; xfree(); xalloc(ip,ep); u.u_ar0[PC] = ep->a_entry & ~01; } else { if (estabur(ts, ds, ss, sep, RO)) { u.u_ovdata = sovdata; return; } /* * allocate and clear core at this point, committed * to the new image */ u.u_prof.pr_scale = 0; if (u.u_procp->p_flag & SVFORK) endvfork(); else xfree(); expand(ds, S_DATA); { register u_int numc, startc; startc = btoc(ep->a_data); /* clear BSS only */ if (startc != 0) startc--; numc = ds - startc; clear(u.u_procp->p_daddr + startc, numc); } expand(ss, S_STACK); clear(u.u_procp->p_saddr, ss); xalloc(ip, ep); /* * read in data segment */ estabur((u_int)0, ds, (u_int)0, 0, RO); offset = sizeof(struct exec); if (ovflag) { offset += sizeof(ovhead); offset += (((long)u.u_ovdata.uo_ov_offst[NOVL]) << 6); } else offset += ep->a_text; rdwri(UIO_READ, ip, (caddr_t) 0, ep->a_data, offset, UIO_USERSPACE, IO_UNIT, (int *)0); /* * set SUID/SGID protections, if no tracing */ if ((u.u_procp->p_flag&STRC)==0) { u.u_uid = uid; u.u_procp->p_uid = uid; u.u_gid = gid; } else psignal(u.u_procp, SIGTRAP); } u.u_tsize = ts; u.u_dsize = ds; u.u_ssize = ss; u.u_sep = sep; estabur(ts, ds, ss, sep, RO); } zeof (len)); if (u.u_error) return; msg.msg_name = uap->from; msg.msg_namelen = len; msg.msg_isys/sys/ingreslock.c 644 0 12 14475 5722300336 10023 /* * Rewritten for 2.11BSD. Feb 20 1995, Steven Schultz (sms@wlv.iipo.gtegsc.com) * * The lock table is allocated external to the kernel (in pdp/machdep2.c at * kernel startup time) because 8 concurrent Ingres sessions would have cost * over 500 bytes of D space. */ #include "ingres.h" #if NINGRES > 0 #include "param.h" #include #include #include #include #include #include /* * Wait channels for locktable. We need something which is even, unique and * not mapped out to sleep on when waiting for a lock. */ int Locksleep[IL_NLOCKS]; segm Locktabseg; struct Lockform *Locktab = (struct Lockform *)SEG5; /* * array of number of locks which can be set for each lock. * It looks tempting to make this an array of char or u_char. DON'T. The * entries are used as wait channel addresses and must be 'even'. */ int Lockset[] = { IL_NLOCKS, IL_PLOCKS, IL_RLOCKS, IL_DLOCKS }; #define keycomp(a,b) bcmp(a,b,KEYSIZE) ingres_open(dev, flag, mode) dev_t dev; int flag; int mode; { if ((flag & FWRITE) == 0) return(EBADF); if (Locktabseg.se_addr == 0) return(ENOMEM); return(0); } /* * ingres_write() : write driver * 1. copy Lock request info to lockbuf * 2. follow action in l_act * 3. Error return conditions * -1: lockrequest fails(only on act=1) * -2: attempt to release a lock not set * by calling program * -3: illegal action requested * * Install the line "ingres_rma(p->p_pid)" in the routine * "exit" (in sys/kern_exit.c) after "p->p_stat = SZOMB". */ ingres_write(dev, uio, flag) dev_t dev; struct uio *uio; int flag; { struct Lockreq lockbuf; register struct Lockreq *ll; register int i; int error = 0, blockflag; if (uio->uio_resid != sizeof (struct ulock)) return(EINVAL); error = uiomove(&lockbuf.lr_req, sizeof (struct ulock), uio); if (error) return(error); lockbuf.lr_pid = u.u_procp->p_pid; ll = &lockbuf; if ((ll->lr_act < A_RLS1) && ((ll->lr_type < T_CS) || (ll->lr_type > T_DB ) || (ll->lr_mod < M_EXCL) || (ll->lr_mod > M_SHARE ))) return(EINVAL); /* * At this point we are in the high kernel and do not need to save seg5 * before changing it. Making sure that 'normalseg5' is called before doing * a sleep() or return() is sufficient. * * It is simpler to map the lock table once here rather than in each routine * called below. */ ingres_maplock(); switch(ll->lr_act) { case A_RTN: /* * attempt to set lock. * error return if failure. */ blockflag = FALSE; for ( i = 0; i <= ll->lr_type; i++) if (Lockset[i] == 0) blockflag = TRUE; if (blockflag || ingres_unique(ll) >= 0) error = -1; else ingres_enter(ll); break; case A_SLP: /* attempt to set lock. * sleep on blocking address if failure. */ do { do { blockflag = TRUE; for ( i = 0; i <= ll->lr_type; i++) if (Lockset[i] == 0) { normalseg5(); sleep(&Lockset[i],LOCKPRI); ingres_maplock(); blockflag = FALSE; } } while (!blockflag); if (( i = ingres_unique(ll)) >= 0 ) { blockflag = FALSE; Locktab[i].l_wflag = W_ON; normalseg5(); sleep(&Locksleep[i],LOCKPRI); ingres_maplock(); } } while (!blockflag); ingres_enter(ll); break; case A_RLS1: /* remove 1 lock */ if ((i = ingres_find(ll)) >= 0) ingres_rm(i,ll->lr_pid); else error = -2; break; case A_RLSA: /* remove all locks for this process id*/ ingres_rma(ll->lr_pid); /* does a normalseg5() */ break; case A_ABT: /* abort all locks */ ingres_abt(); break; default : error = -3; break; } normalseg5(); return(error); } /* * ingres_unique- check for match on key * * return index of Locktab if match found * else return -1 */ static ingres_unique(q) register struct Lockreq *q; { register int k; register struct Lockform *p = Locktab; for (k = 0; k < IL_NLOCKS; k++, p++) { if ((p->l_mod != M_EMTY) && (keycomp(p->l_key,q->lr_key) == 0) && (p->l_type == q->lr_type) && ((p->l_mod == M_EXCL) || (q->lr_mod == M_EXCL))) return(k); } return(-1); } static ingres_find(q) register struct Lockreq *q; { register int k; register struct Lockform *p = Locktab; for (k = 0; k < IL_NLOCKS; k++, p++) { if ((p->l_mod != M_EMTY) && (keycomp(p->l_key,q->lr_key) == 0) && (p->l_type == q->lr_type) && (p->l_pid == q->lr_pid)) return(k); } return(-1); } /* * remove the lth Lock * if the correct user is requesting the move. */ static void ingres_rm(l,llpid) int l, llpid; { register struct Lockform *a = &Locktab[l]; register int k; if (a->l_pid == llpid && a->l_mod != M_EMTY) { a->l_mod = M_EMTY; a->l_pid = 0; if (a->l_wflag == W_ON) { a->l_wflag = W_OFF; wakeup(&Locksleep[l]); } for (k = 0; k <= a->l_type; k++) { Lockset[k]++; if (Lockset[k] == 1) wakeup(&Lockset[k]); } } } /* * ingres_rma releases all locks for a given process id(pd). */ ingres_rma(pd) int pd; { register int i; register struct Lockform *p = Locktab; /* * Have to map the lock table because we can be called from kern_exit.c * when a process exits. */ ingres_maplock(); /* * Replicate the pid check here to avoid function calls. If this process * has no Ingres locks outstanding then we avoid IL_NLOCKS function calls * and returns. */ for (i = 0; i < IL_NLOCKS; i++, p++) { if (p->l_pid == pd && (p->l_mod != M_EMTY)) ingres_rm(i,pd); } normalseg5(); } /* * enter Lockbuf in locktable * return position in Locktable * error return of -1 */ static ingres_enter(ll) struct Lockreq *ll; { register int k, l; register struct Lockform *p = Locktab; for (k = 0; k < IL_NLOCKS; k++, p++) { if (p->l_mod == M_EMTY) { p->l_pid = ll->lr_pid; p->l_type = ll->lr_type; p->l_mod = ll->lr_mod; bcopy(ll->lr_key, p->l_key, KEYSIZE); for (l = 0; l <= ll->lr_type; l++) Lockset[l]--; return(k); } } return (-1); } /* * ingres_abt - abort all locks */ static void ingres_abt() { register int k; for (k = 0; k < IL_NLOCKS; k++) wakeup( &Locktab[k] ); for (k = 0; k < 4; k++) wakeup( &Lockset[k]); bzero(Locktab, LOCKTABSIZE); Lockset[0] = IL_NLOCKS; Lockset[1] = IL_PLOCKS; Lockset[2] = IL_RLOCKS; Lockset[3] = IL_DLOCKS; } #endif /* NINGRES > 0 */ nt != 1) { register struct file *fp; for (fp = file; fp < fileNFILE; fp++) { if (fp->f_type == DTYPE_INODE && fp->f_count > 0 && (struct inode *)fp->f_data == ip && (sys/sys/kern_sysctl.c 644 0 12 56675 6044624121 10232 /*- * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Mike Karels at Berkeley Software Design, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_sysctl.c 8.4.3 (2.11BSD GTE) 1995/10/29 */ /* * sysctl system call. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include sysctlfn kern_sysctl; sysctlfn hw_sysctl; #ifdef DEBUG sysctlfn debug_sysctl; #endif sysctlfn vm_sysctl; sysctlfn fs_sysctl; #ifdef INET sysctlfn NET_SYSCTL; extern int net_sysctl(); /* In supervisor space */ #endif sysctlfn cpu_sysctl; /* * Locking and stats */ static struct sysctl_lock { int sl_lock; int sl_want; int sl_locked; } memlock; struct sysctl_args { int *name; u_int namelen; void *old; size_t *oldlenp; void *new; size_t newlen; }; int __sysctl() { register struct sysctl_args *uap = (struct sysctl_args *)u.u_ap; int error; u_int savelen, oldlen = 0; sysctlfn *fn; int name[CTL_MAXNAME]; if (uap->new != NULL && !suser()) return (u.u_error); /* XXX */ /* * all top-level sysctl names are non-terminal */ if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) return (u.u_error = EINVAL); if (error = copyin(uap->name, &name, uap->namelen * sizeof(int))) return (u.u_error = error); switch (name[0]) { case CTL_KERN: fn = kern_sysctl; break; case CTL_HW: fn = hw_sysctl; break; case CTL_VM: fn = vm_sysctl; break; #ifdef INET case CTL_NET: fn = NET_SYSCTL; break; #endif #ifdef notyet case CTL_FS: fn = fs_sysctl; break; #endif case CTL_MACHDEP: fn = cpu_sysctl; break; #ifdef DEBUG case CTL_DEBUG: fn = debug_sysctl; break; #endif default: return (u.u_error = EOPNOTSUPP); } if (uap->oldlenp && (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen)))) return (u.u_error = error); if (uap->old != NULL) { while (memlock.sl_lock) { memlock.sl_want = 1; sleep((caddr_t)&memlock, PRIBIO+1); memlock.sl_locked++; } memlock.sl_lock = 1; savelen = oldlen; } error = (*fn)(name + 1, uap->namelen - 1, uap->old, &oldlen, uap->new, uap->newlen); if (uap->old != NULL) { memlock.sl_lock = 0; if (memlock.sl_want) { memlock.sl_want = 0; wakeup((caddr_t)&memlock); } } if (error) return (u.u_error = error); if (uap->oldlenp) { error = copyout(&oldlen, uap->oldlenp, sizeof(oldlen)); if (error) return(u.u_error = error); } u.u_r.r_val1 = oldlen; return (0); } /* * kernel related system variables. */ kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen) int *name; u_int namelen; void *oldp; size_t *oldlenp; void *newp; size_t newlen; { int error, level; u_long longhostid; char bsd[10]; extern char version[]; /* all sysctl names at this level are terminal */ if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF)) return (ENOTDIR); /* overloaded */ switch (name[0]) { case KERN_OSTYPE: case KERN_OSRELEASE: /* code is cheaper than D space */ bsd[0]='2';bsd[1]='.';bsd[2]='1';bsd[3]='1';bsd[4]='B'; bsd[5]='S';bsd[6]='D';bsd[7]='\0'; return (sysctl_rdstring(oldp, oldlenp, newp, bsd)); case KERN_OSREV: return (sysctl_rdlong(oldp, oldlenp, newp, (long)BSD)); case KERN_VERSION: return (sysctl_rdstring(oldp, oldlenp, newp, version)); case KERN_MAXINODES: return(sysctl_rdint(oldp, oldlenp, newp, ninode)); case KERN_MAXPROC: return (sysctl_rdint(oldp, oldlenp, newp, nproc)); case KERN_MAXFILES: return (sysctl_rdint(oldp, oldlenp, newp, nfile)); case KERN_MAXTEXTS: return (sysctl_rdint(oldp, oldlenp, newp, ntext)); case KERN_ARGMAX: return (sysctl_rdint(oldp, oldlenp, newp, NCARGS)); case KERN_SECURELVL: level = securelevel; if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || newp == NULL) return (error); if (level < securelevel && u.u_procp->p_pid != 1) return (EPERM); securelevel = level; return (0); case KERN_HOSTNAME: error = sysctl_string(oldp, oldlenp, newp, newlen, hostname, sizeof(hostname)); if (newp && !error) hostnamelen = newlen; return (error); case KERN_HOSTID: longhostid = hostid; error = sysctl_long(oldp, oldlenp, newp, newlen, &longhostid); hostid = longhostid; return (error); case KERN_CLOCKRATE: return (sysctl_clockrate(oldp, oldlenp)); case KERN_BOOTTIME: return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime, sizeof(struct timeval))); case KERN_INODE: return (sysctl_inode(oldp, oldlenp)); case KERN_PROC: return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp)); case KERN_FILE: return (sysctl_file(oldp, oldlenp)); case KERN_TEXT: return (sysctl_text(oldp, oldlenp)); #ifdef GPROF case KERN_PROF: return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, newp, newlen)); #endif case KERN_NGROUPS: return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS)); case KERN_JOB_CONTROL: return (sysctl_rdint(oldp, oldlenp, newp, 1)); case KERN_POSIX1: case KERN_SAVED_IDS: return (sysctl_rdint(oldp, oldlenp, newp, 0)); default: return (EOPNOTSUPP); } /* NOTREACHED */ } /* * hardware related system variables. */ hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen) int *name; u_int namelen; void *oldp; size_t *oldlenp; void *newp; size_t newlen; { char m[10], c[10]; char *cpu2str(); extern size_t physmem; /* all sysctl names at this level are terminal */ if (namelen != 1) return (ENOTDIR); /* overloaded */ switch (name[0]) { case HW_MACHINE: m[0]='P';m[1]='D';m[2]='P';m[3]='1';m[4]='1';m[5]='\0'; return (sysctl_rdstring(oldp, oldlenp, newp, m)); case HW_MODEL: return (sysctl_rdstring(oldp, oldlenp, newp, cpu2str(c,sizeof (c)))); case HW_NCPU: return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */ case HW_BYTEORDER: return (sysctl_rdint(oldp, oldlenp, newp, ENDIAN)); case HW_PHYSMEM: return (sysctl_rdlong(oldp, oldlenp, newp,ctob((long)physmem))); case HW_USERMEM: return (sysctl_rdlong(oldp, oldlenp, newp,ctob((long)freemem))); case HW_PAGESIZE: return (sysctl_rdint(oldp, oldlenp, newp, NBPG*CLSIZE)); default: return (EOPNOTSUPP); } /* NOTREACHED */ } static char * cpu2str(buf, len) char *buf; int len; { register char *cp = buf + len; register int i = cputype; *--cp = '\0'; do { *--cp = (i % 10) + '0'; } while (i /= 10); return(cp); } #ifdef DEBUG /* * Debugging related system variables. */ struct ctldebug debug0, debug1, debug2, debug3, debug4; struct ctldebug debug5, debug6, debug7, debug8, debug9; struct ctldebug debug10, debug11, debug12, debug13, debug14; struct ctldebug debug15, debug16, debug17, debug18, debug19; static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { &debug0, &debug1, &debug2, &debug3, &debug4, &debug5, &debug6, &debug7, &debug8, &debug9, &debug10, &debug11, &debug12, &debug13, &debug14, &debug15, &debug16, &debug17, &debug18, &debug19, }; int debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen) int *name; u_int namelen; void *oldp; size_t *oldlenp; void *newp; size_t newlen; { struct ctldebug *cdp; /* all sysctl names at this level are name and field */ if (namelen != 2) return (ENOTDIR); /* overloaded */ cdp = debugvars[name[0]]; if (cdp->debugname == 0) return (EOPNOTSUPP); switch (name[1]) { case CTL_DEBUG_NAME: return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); case CTL_DEBUG_VALUE: return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); default: return (EOPNOTSUPP); } /* NOTREACHED */ } #endif /* DEBUG */ #ifdef INET /* * In 4.4BSD-Lite these functions were scattered amoungst the various * subsystems they dealt with. * * In 2.11BSD the kernel is overlaid and adding code to multiple * files would have caused existing overlay structures to break. * This module will be large enough that it will end up in an overlay * by itself. Thus centralizing all sysctl handling in one place makes * a lot of sense. The one exception is the networking related syctl * functions. Because the networking code is not overlaid and runs * in supervisor mode the sysctl handling can not be done here and * will be implemented in the 4.4BSD manner (by modifying the networking * modules). */ int NET_SYSCTL(name, namelen, oldp, oldlenp, newp, newlen) int *name; u_int namelen; void *oldp; size_t *oldlenp; void *newp; size_t newlen; { return(KScall(net_sysctl, 6 * sizeof (int), name, namelen, oldp, oldlenp, newp, newlen)); } #endif /* * Rather useless - but it's not very big so let's do it. */ int cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen) int *name; u_int namelen; void *oldp; size_t *oldlenp; void *newp; size_t newlen; { extern struct tty cons[]; /* all sysctl names at this level are terminal */ if (namelen != 1) return (ENOTDIR); /* overloaded */ switch (name[0]) { case CPU_CONSDEV: return (sysctl_rdstruct(oldp, oldlenp, newp, &cons[0].t_dev, sizeof &cons[0].t_dev)); default: return (EOPNOTSUPP); } /* NOTREACHED */ } /* * Bit of a hack. 2.11 currently uses 'short avenrun[3]' and a fixed scale * of 256. In order not to break all the applications which nlist() for * 'avenrun' we build a local 'averunnable' structure here to return to the * user. Eventually (after all applications which look up the load average * the old way) have been converted we can change things. * * We do not call vmtotal(), that could get rather expensive, rather we rely * on the 5 second update. * * The coremap and swapmap cases are 2.11BSD extensions. */ int vm_sysctl(name, namelen, oldp, oldlenp, newp, newlen) int *name; u_int namelen; void *oldp; size_t *oldlenp; void *newp; size_t newlen; { struct loadavg averunnable; /* loadavg in resource.h */ /* all sysctl names at this level are terminal */ if (namelen != 1) return (ENOTDIR); /* overloaded */ switch (name[0]) { case VM_LOADAVG: averunnable.fscale = 256; averunnable.ldavg[0] = avenrun[0]; averunnable.ldavg[1] = avenrun[1]; averunnable.ldavg[2] = avenrun[2]; return (sysctl_rdstruct(oldp, oldlenp, newp, &averunnable, sizeof(averunnable))); case VM_METER: #ifdef notsure vmtotal(); /* could be expensive to do this every time */ #endif return (sysctl_rdstruct(oldp, oldlenp, newp, &total, sizeof(total))); case VM_SWAPMAP: if (oldp == NULL) { *oldlenp = (char *)swapmap[0].m_limit - (char *)swapmap[0].m_map; return(0); } return (sysctl_rdstruct(oldp, oldlenp, newp, swapmap, (int)swapmap[0].m_limit - (int)swapmap[0].m_map)); case VM_COREMAP: if (oldp == NULL) { *oldlenp = (char *)coremap[0].m_limit - (char *)coremap[0].m_map; return(0); } return (sysctl_rdstruct(oldp, oldlenp, newp, coremap, (int)coremap[0].m_limit - (int)coremap[0].m_map)); default: return (EOPNOTSUPP); } /* NOTREACHED */ } /* * Validate parameters and get old / set new parameters * for an integer-valued sysctl function. */ sysctl_int(oldp, oldlenp, newp, newlen, valp) void *oldp; size_t *oldlenp; void *newp; size_t newlen; int *valp; { int error = 0; if (oldp && *oldlenp < sizeof(int)) return (ENOMEM); if (newp && newlen != sizeof(int)) return (EINVAL); *oldlenp = sizeof(int); if (oldp) error = copyout(valp, oldp, sizeof(int)); if (error == 0 && newp) error = copyin(newp, valp, sizeof(int)); return (error); } /* * As above, but read-only. */ sysctl_rdint(oldp, oldlenp, newp, val) void *oldp; size_t *oldlenp; void *newp; int val; { int error = 0; if (oldp && *oldlenp < sizeof(int)) return (ENOMEM); if (newp) return (EPERM); *oldlenp = sizeof(int); if (oldp) error = copyout((caddr_t)&val, oldp, sizeof(int)); return (error); } /* * Validate parameters and get old / set new parameters * for an long-valued sysctl function. */ sysctl_long(oldp, oldlenp, newp, newlen, valp) void *oldp; size_t *oldlenp; void *newp; size_t newlen; long *valp; { int error = 0; if (oldp && *oldlenp < sizeof(long)) return (ENOMEM); if (newp && newlen != sizeof(long)) return (EINVAL); *oldlenp = sizeof(long); if (oldp) error = copyout(valp, oldp, sizeof(long)); if (error == 0 && newp) error = copyin(newp, valp, sizeof(long)); return (error); } /* * As above, but read-only. */ sysctl_rdlong(oldp, oldlenp, newp, val) void *oldp; size_t *oldlenp; void *newp; long val; { int error = 0; if (oldp && *oldlenp < sizeof(long)) return (ENOMEM); if (newp) return (EPERM); *oldlenp = sizeof(long); if (oldp) error = copyout((caddr_t)&val, oldp, sizeof(long)); return (error); } /* * Validate parameters and get old / set new parameters * for a string-valued sysctl function. */ sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) void *oldp; size_t *oldlenp; void *newp; size_t newlen; char *str; int maxlen; { int len, error = 0; len = strlen(str) + 1; if (oldp && *oldlenp < len) return (ENOMEM); if (newp && newlen >= maxlen) return (EINVAL); if (oldp) { *oldlenp = len; error = vcopyout(str, oldp, len); } if (error == 0 && newp) { error = vcopyin(newp, str, newlen); str[newlen] = 0; } return (error); } /* * As above, but read-only. */ sysctl_rdstring(oldp, oldlenp, newp, str) void *oldp; size_t *oldlenp; void *newp; char *str; { int len, error = 0; len = strlen(str) + 1; if (oldp && *oldlenp < len) return (ENOMEM); if (newp) return (EPERM); *oldlenp = len; if (oldp) error = vcopyout(str, oldp, len); return (error); } /* * Validate parameters and get old / set new parameters * for a structure oriented sysctl function. */ sysctl_struct(oldp, oldlenp, newp, newlen, sp, len) void *oldp; size_t *oldlenp; void *newp; size_t newlen; void *sp; int len; { int error = 0; if (oldp && *oldlenp < len) return (ENOMEM); if (newp && newlen > len) return (EINVAL); if (oldp) { *oldlenp = len; error = copyout(sp, oldp, len); } if (error == 0 && newp) error = copyin(newp, sp, len); return (error); } /* * Validate parameters and get old parameters * for a structure oriented sysctl function. */ sysctl_rdstruct(oldp, oldlenp, newp, sp, len) void *oldp; size_t *oldlenp; void *newp, *sp; int len; { int error = 0; if (oldp && *oldlenp < len) return (ENOMEM); if (newp) return (EPERM); *oldlenp = len; if (oldp) error = copyout(sp, oldp, len); return (error); } /* * Get file structures. */ sysctl_file(where, sizep) char *where; size_t *sizep; { int buflen, error; register struct file *fp; struct file *fpp; char *start = where; register int i; buflen = *sizep; if (where == NULL) { for (i = 0, fp = file; fp < fileNFILE; fp++) if (fp->f_count) i++; #define FPTRSZ sizeof (struct file *) #define FILESZ sizeof (struct file) /* * overestimate by 5 files */ *sizep = (i + 5) * (FILESZ + FPTRSZ); return (0); } /* * array of extended file structures: first the address then the * file structure. */ for (fp = file; fp < fileNFILE; fp++) { if (fp->f_count == 0) continue; if (buflen < (FPTRSZ + FILESZ)) { *sizep = where - start; return (ENOMEM); } fpp = fp; if ((error = copyout(&fpp, where, FPTRSZ)) || (error = copyout(fp, where + FPTRSZ, FILESZ))) return (error); buflen -= (FPTRSZ + FILESZ); where += (FPTRSZ + FILESZ); } *sizep = where - start; return (0); } /* * This one is in kern_clock.c in 4.4 but placed here for the reasons * given earlier (back around line 367). */ int sysctl_clockrate(where, sizep) char *where; size_t *sizep; { struct clockinfo clkinfo; /* * Construct clockinfo structure. */ clkinfo.hz = hz; clkinfo.tick = 1000000L / hz; clkinfo.profhz = 0; clkinfo.stathz = hz; return(sysctl_rdstruct(where, sizep, NULL, &clkinfo, sizeof (clkinfo))); } /* * Dump inode list (via sysctl). * Copyout address of inode followed by inode. */ /* ARGSUSED */ sysctl_inode(where, sizep) char *where; size_t *sizep; { register struct inode *ip; register char *bp = where; struct inode *ipp; char *ewhere; int error, numi; for (numi = 0, ip = inode; ip < inodeNINODE; ip++) if (ip->i_count) numi++; #define IPTRSZ sizeof (struct inode *) #define INODESZ sizeof (struct inode) if (where == NULL) { *sizep = (numi + 5) * (IPTRSZ + INODESZ); return (0); } ewhere = where + *sizep; for (ip = inode; ip < inodeNINODE; ip++) { if (ip->i_count == 0) continue; if (bp + IPTRSZ + INODESZ > ewhere) { *sizep = bp - where; return (ENOMEM); } ipp = ip; if ((error = copyout((caddr_t)&ipp, bp, IPTRSZ)) || (error = copyout((caddr_t)ip, bp + IPTRSZ, INODESZ))) return (error); bp += IPTRSZ + INODESZ; } *sizep = bp - where; return (0); } /* * Get text structures. This is a 2.11BSD extension. sysctl() is supposed * to be extensible... */ sysctl_text(where, sizep) char *where; size_t *sizep; { int buflen, error; register struct text *xp; struct text *xpp; char *start = where; register int i; buflen = *sizep; if (where == NULL) { for (i = 0, xp = text; xp < textNTEXT; xp++) if (xp->x_count) i++; #define TPTRSZ sizeof (struct text *) #define TEXTSZ sizeof (struct text) /* * overestimate by 3 text structures */ *sizep = (i + 3) * (TEXTSZ + TPTRSZ); return (0); } /* * array of extended file structures: first the address then the * file structure. */ for (xp = text; xp < textNTEXT; xp++) { if (xp->x_count == 0) continue; if (buflen < (TPTRSZ + TEXTSZ)) { *sizep = where - start; return (ENOMEM); } xpp = xp; if ((error = copyout(&xpp, where, TPTRSZ)) || (error = copyout(xp, where + TPTRSZ, TEXTSZ))) return (error); buflen -= (TPTRSZ + TEXTSZ); where += (TPTRSZ + TEXTSZ); } *sizep = where - start; return (0); } /* * try over estimating by 5 procs */ #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc)) sysctl_doproc(name, namelen, where, sizep) int *name; u_int namelen; char *where; size_t *sizep; { register struct proc *p; register struct kinfo_proc *dp = (struct kinfo_proc *)where; int needed = 0; int buflen = where != NULL ? *sizep : 0; int doingzomb; struct eproc eproc; int error = 0; dev_t ttyd; uid_t ruid; struct tty *ttyp; if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL)) return (EINVAL); p = (struct proc *)allproc; doingzomb = 0; again: for (; p != NULL; p = p->p_nxt) { /* * Skip embryonic processes. */ if (p->p_stat == SIDL) continue; /* * TODO - make more efficient (see notes below). * do by session. */ switch (name[0]) { case KERN_PROC_PID: /* could do this with just a lookup */ if (p->p_pid != (pid_t)name[1]) continue; break; case KERN_PROC_PGRP: /* could do this by traversing pgrp */ if (p->p_pgrp != (pid_t)name[1]) continue; break; case KERN_PROC_TTY: fill_from_u(p, &ruid, &ttyp, &ttyd); if (!ttyp || ttyd != (dev_t)name[1]) continue; break; case KERN_PROC_UID: if (p->p_uid != (uid_t)name[1]) continue; break; case KERN_PROC_RUID: fill_from_u(p, &ruid, &ttyp, &ttyd); if (ruid != (uid_t)name[1]) continue; break; case KERN_PROC_ALL: break; default: return(EINVAL); } if (buflen >= sizeof(struct kinfo_proc)) { fill_eproc(p, &eproc); if (error = copyout((caddr_t)p, &dp->kp_proc, sizeof(struct proc))) return (error); if (error = copyout((caddr_t)&eproc, &dp->kp_eproc, sizeof(eproc))) return (error); dp++; buflen -= sizeof(struct kinfo_proc); } needed += sizeof(struct kinfo_proc); } if (doingzomb == 0) { p = zombproc; doingzomb++; goto again; } if (where != NULL) { *sizep = (caddr_t)dp - where; if (needed > *sizep) return (ENOMEM); } else { needed += KERN_PROCSLOP; *sizep = needed; } return (0); } /* * Fill in an eproc structure for the specified process. Slightly * inefficient because we have to access the u area again for the * information not kept in the proc structure itself. Can't afford * to expand the proc struct so we take a slight speed hit here. */ void fill_eproc(p, ep) register struct proc *p; register struct eproc *ep; { struct tty *ttyp; ep->e_paddr = p; fill_from_u(p, &ep->e_ruid, &ttyp, &ep->e_tdev); if (ttyp) ep->e_tpgid = ttyp->t_pgrp; else ep->e_tpgid = 0; } /* * Three pieces of information we need about a process are not kept in * the proc table: real uid, controlling terminal device, and controlling * terminal tty struct pointer. For these we must look in either the u * area or the swap area. If the process is still in memory this is * easy but if the process has been swapped out we have to read in the * u area. * * XXX - We rely on the fact that u_ttyp, u_ttyd, and u_ruid are all within * XXX - the first 1kb of the u area. If this ever changes the logic below * XXX - will break (and badly). At the present time (1/19/95) the u area * XXX - is 934 bytes long. */ fill_from_u(p, rup, ttp, tdp) struct proc *p; uid_t *rup; struct tty **ttp; dev_t *tdp; { register struct buf *bp; dev_t ttyd; uid_t ruid; struct tty *ttyp; struct user *up; if (p->p_flag & SLOAD) { mapseg5(p->p_addr, (((USIZE - 1) << 8) | RO)); ttyd = ((struct user *)SEG5)->u_ttyd; ttyp = ((struct user *)SEG5)->u_ttyp; ruid = ((struct user *)SEG5)->u_ruid; normalseg5(); } else { bp = geteblk(); bp->b_dev = swapdev; bp->b_blkno = (daddr_t)p->p_addr; bp->b_bcount = DEV_BSIZE; /* XXX */ bp->b_flags = B_READ; (*bdevsw[major(swapdev)].d_strategy)(bp); biowait(bp); if (u.u_error) { ttyd = NODEV; ttyp = NULL; ruid = (uid_t)-2; } else { up = (struct user *)mapin(bp); ruid = up->u_ruid; /* u_ruid = offset 164 */ ttyd = up->u_ttyd; /* u_ttyd = offset 654 */ ttyp = up->u_ttyp; /* u_ttyp = offset 652 */ mapout(bp); } bp->b_flags |= B_AGE; brelse(bp); u.u_error = 0; /* XXX */ } *rup = ruid; *ttp = ttyp; *tdp = ttyd; } te parameters and get old / set new parameters * for an long-valuesys/sys/ufs_disksubr.c 644 0 12 24403 5770445741 10373 /* * Copyright (c) 1982, 1986, 1988, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ufs_disksubr.c 8.5.3 (2.11BSD GTE) 1995/06/16 */ #include #include #include #include #include #include #include #include #include #include /* * Attempt to read a disk label from a device using the indicated stategy * routine. The label must be partly set up before this: secpercyl and * anything required in the strategy routine (e.g., sector size) must be * filled in before calling us. Returns NULL on success and an error * string on failure. */ char * readdisklabel(dev, strat, lp) dev_t dev; int (*strat)(); register struct disklabel *lp; { register struct buf *bp; struct disklabel *dlp; char *msg = NULL; if (lp->d_secperunit == 0) lp->d_secperunit = 0x1fffffffL; lp->d_npartitions = 1; if (lp->d_partitions[0].p_size == 0) lp->d_partitions[0].p_size = 0x1fffffffL; lp->d_partitions[0].p_offset = 0; bp = geteblk(); bp->b_dev = dev; bp->b_blkno = LABELSECTOR; bp->b_bcount = lp->d_secsize; /* Probably should wire this to 512 */ bp->b_flags = B_BUSY | B_READ; bp->b_cylin = LABELSECTOR / lp->d_secpercyl; (*strat)(bp); biowait(bp); if (u.u_error) msg = "I/O error"; else { dlp = (struct disklabel *)mapin(bp); if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { if (msg == NULL) msg = "no disk label"; } else if (dlp->d_npartitions > MAXPARTITIONS || dkcksum(dlp)) msg = "disk label corrupted"; else bcopy(dlp, lp, sizeof (struct disklabel)); mapout(bp); } bp->b_flags = B_INVAL | B_AGE; brelse(bp); return(msg); } /* * Check new disk label for sensibility before setting it. 'olp' must point * to a kernel resident (or mapped in) label. 'nlp' points to the new label * usually present on the stack (having been passed in via ioctl from an * application). */ int setdisklabel(olp, nlp, openmask) struct disklabel *olp; register struct disklabel *nlp; u_short openmask; { int i; register struct partition *opp, *npp; if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC || dkcksum(nlp) != 0) return (EINVAL); while ((i = ffs((long)openmask)) != 0) { i--; openmask &= ~(1 << i); if (nlp->d_npartitions <= i) return (EBUSY); opp = &olp->d_partitions[i]; npp = &nlp->d_partitions[i]; if (npp->p_offset != opp->p_offset || npp->p_size < opp->p_size) return (EBUSY); /* * Copy internally-set partition information * if new label doesn't include it. XXX */ if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) { npp->p_fstype = opp->p_fstype; npp->p_fsize = opp->p_fsize; npp->p_frag = opp->p_frag; } } nlp->d_checksum = 0; nlp->d_checksum = dkcksum(nlp); bcopy(nlp, olp, sizeof (struct disklabel)); return (0); } /* * Write disk label back to device after modification. */ int writedisklabel(dev, strat, lp) dev_t dev; int (*strat)(); register struct disklabel *lp; { struct buf *bp; struct disklabel *dlp; int labelpart; int error = 0; labelpart = dkpart(dev); if (lp->d_partitions[labelpart].p_offset != 0) { if (lp->d_partitions[0].p_offset != 0) return (EXDEV); /* not quite right */ labelpart = 0; } bp = geteblk(); bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), labelpart)); bp->b_blkno = LABELSECTOR; bp->b_bcount = lp->d_secsize; /* probably should wire to 512 */ bp->b_flags = B_READ; (*strat)(bp); biowait(bp); if (u.u_error) goto done; dlp = (struct disklabel *)mapin(bp); if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC && dkcksum(dlp) == 0) { bcopy(lp, dlp, sizeof (struct disklabel)); mapout(bp); bp->b_flags = B_WRITE; (*strat)(bp); biowait(bp); error = u.u_error; } else { error = ESRCH; mapout(bp); } done: brelse(bp); return(error); } /* * Compute checksum for disk label. */ dkcksum(lp) struct disklabel *lp; { register u_short *start, *end; register u_short sum = 0; start = (u_short *)lp; end = (u_short *)&lp->d_partitions[lp->d_npartitions]; while (start < end) sum ^= *start++; return (sum); } /* * This is new for 2.11BSD. It is a common routine that checks for * opening a partition that overlaps other currently open partitions. * * NOTE: if 'c' is not the entire drive (as is the case with the old, * nonstandard, haphazard and overlapping partition tables) the warning * message will be erroneously issued in some valid situations. */ #define RAWPART 2 /* 'c' */ /* XXX */ dkoverlapchk(openmask, dev, label, name) int openmask; dev_t dev; memaddr label; char *name; { int unit = dkunit(dev); int part = dkpart(dev); int partmask = 1 << part; int i; daddr_t start, end; register struct disklabel *lp = (struct disklabel *)SEG5; register struct partition *pp; if ((openmask & partmask) == 0 && part != RAWPART) { mapseg5(label, LABELDESC); pp = &lp->d_partitions[part]; start = pp->p_offset; end = pp->p_offset + pp->p_size; i = 0; for (pp = lp->d_partitions; i < lp->d_npartitions; pp++,i++) { if (pp->p_offset + pp->p_size <= start || pp->p_offset >= end || i == RAWPART) continue; if (openmask & (1 << i)) log(LOG_WARNING, "%s%d%c: overlaps open part (%c)\n", name, unit, part + 'a', i + 'a'); } normalseg5(); } return(0); } /* * It was noticed that the ioctl processing of disklabels was the same * for every disk driver. Disk drivers should call this routine after * handling ioctls (if any) particular to themselves. */ ioctldisklabel(dev, cmd, data, flag, disk, strat) dev_t dev; int cmd; register caddr_t data; int flag; register struct dkdevice *disk; int (*strat)(); { struct disklabel label; register struct disklabel *lp = &label; int error; int flags; /* * Copy in mapped out label to the local copy on the stack. We're in the * high kernel at this point so saving the mapping is not necessary. */ mapseg5(disk->dk_label, LABELDESC); bcopy((struct disklabel *)SEG5, lp, sizeof (*lp)); normalseg5(); switch (cmd) { case DIOCGDINFO: bcopy(lp, (struct disklabel *)data, sizeof (*lp)); return(0); /* * Used internally by the kernel in init_main to verify that 'swapdev' * is indeed a FS_SWAP partition. * * NOTE: the label address is the external click address! */ case DIOCGPART: ((struct partinfo *)data)->disklab = (struct disklabel *)disk->dk_label; ((struct partinfo *)data)->part = &disk->dk_parts[dkpart(dev)]; return(0); case DIOCWLABEL: if ((flag & FWRITE) == 0) return(EBADF); if (*(int *)data) disk->dk_flags |= DKF_WLABEL; else disk->dk_flags &= ~DKF_WLABEL; return(0); case DIOCSDINFO: if ((flag & FWRITE) == 0) return(EBADF); error = setdisklabel(lp, (struct disklabel *)data, disk->dk_flags & DKF_WLABEL ? 0 : disk->dk_openmask); /* * If no error was encountered setting the disklabel then we must copy * out the new label from the local copy to the mapped out label. Also * update the partition tables (which are resident in the kernel). */ if (error == 0) { mapseg5(disk->dk_label, LABELDESC); bcopy(lp,(struct disklabel *)SEG5,sizeof (*lp)); normalseg5(); bcopy(&lp->d_partitions, &disk->dk_parts, sizeof (lp->d_partitions)); } return(error); case DIOCWDINFO: if ((flag & FWRITE) == 0) return(EBADF); error = setdisklabel(lp, (struct disklabel *)data, disk->dk_flags & DKF_WLABEL ? 0 : disk->dk_openmask); if (error) return(error); /* * Copy to external label. Ah - need to also update the kernel resident * partition tables! */ mapseg5(disk->dk_label, LABELDESC); bcopy(lp,(struct disklabel *)SEG5,sizeof (*lp)); normalseg5(); bcopy(&lp->d_partitions, &disk->dk_parts, sizeof (lp->d_partitions)); /* * We use the 'a' partition to write the label. This probably shouldn't * be wired in here but it's not worth creating another macro for. Is it? * The flags are faked to write enable the label area and that the drive is * alive - it better be at this point or there is a problem in the open routine. */ flags = disk->dk_flags; disk->dk_flags |= (DKF_ALIVE | DKF_WLABEL); error = writedisklabel(dev & ~7, strat, lp); disk->dk_flags = flags; return(error); } return(EINVAL); } return (error); } /* * Validate parameters and get old / set new parameters * for a string-valued sysctl function. */ sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) void *oldp; size_t *oldlenp; void *newp; size_t newlen; char *str; sys/net/ 755 0 12 0 5526060217 5352 sys/net/tags 751 0 12 0 6045324752 10163 2../sys/tagssys/net/af.c 444 12 0 3203 4235404244 6163 /* * Copyright (c) 1983, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)af.c 7.3 (Berkeley) 12/30/87 */ #include "param.h" #include "mbuf.h" #include "protosw.h" #include "socket.h" #include "socketvar.h" #include "af.h" /* * Address family support routines */ int null_hash(), null_netmatch(); #define AFNULL \ { null_hash, null_netmatch } #ifdef INET extern int inet_hash(), inet_netmatch(); #define AFINET \ { inet_hash, inet_netmatch } #else #define AFINET AFNULL #endif #ifdef NS extern int ns_hash(), ns_netmatch(); #define AFNS \ { ns_hash, ns_netmatch } #else #define AFNS AFNULL #endif struct afswitch afswitch[AF_MAX] = { AFNULL, AFNULL, AFINET, AFINET, AFNULL, AFNULL, AFNS, AFNULL, AFNULL, AFNULL, AFNULL, AFNULL, AFNULL, AFNULL, AFNULL, AFNULL, AFNULL, /* through 16 */ }; null_init() { register struct afswitch *af; for (af = afswitch; af < &afswitch[AF_MAX]; af++) if (af->af_hash == (int (*)())NULL) { af->af_hash = null_hash; af->af_netmatch = null_netmatch; } } /*ARGSUSED*/ null_hash(addr, hp) struct sockaddr *addr; struct afhash *hp; { hp->afh_nethash = hp->afh_hosthash = 0; } /*ARGSUSED*/ null_netmatch(a1, a2) struct sockaddr *a1, *a2; { return (0); } NULL on success and an error * string on failure. */ char * readdisklabel(dev, strat, lp) dev_t dev; int (*strat)(); register struct disklabel *lp; { register struct buf *bp; struct disklabel *dlp; char *msg = NULL; if (lp->d_secperunit == 0) lp->d_secperunit = 0x1fffffffL; lp->d_npartitions = 1; if (lp->d_partitions[0].p_size == 0) lp->d_partitions[0].p_size = sys/net/af.h 444 12 0 2126 4235404326 6174 /* * Copyright (c) 1980, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)af.h 7.2 (Berkeley) 12/30/87 */ /* * Address family routines, * used in handling generic sockaddr structures. * * Hash routine is called * af_hash(addr, h); * struct sockaddr *addr; struct afhash *h; * producing an afhash structure for addr. * * Netmatch routine is called * af_netmatch(addr1, addr2); * where addr1 and addr2 are sockaddr *. Returns 1 if network * values match, 0 otherwise. */ struct afswitch { int (*af_hash)(); int (*af_netmatch)(); }; struct afhash { u_int afh_hosthash; u_int afh_nethash; }; #ifdef SUPERVISOR struct afswitch afswitch[]; #endif FINET, AFINET, AFNULL, AFNULL, AFNS, AFNULL, AFNULL, AFNULL, AFNULL, AFNULL, AFNULL, AFNULL, AFNULL, AFNULL, AFNULL, /* through 16 */ }; null_init() { register struct afswitch *af; for (af = afswitch; af < &afswitch[AF_MAX]; af++) if (af->af_hash == (int (*)())NULL) { af->af_hash = null_hash; af->af_netmatch = null_netmatch; } } /*ARGSUSED*/ null_hash(addr, hp) struct sockaddr *addr; struct afhash *sys/net/if.c 444 12 0 17105 4237141557 6230 /* * Copyright (c) 1980, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * %W% (Berkeley) %G% */ #include "param.h" #include "mbuf.h" #include "systm.h" #include "socket.h" #include "socketvar.h" #include "protosw.h" #include "user.h" #include "kernel.h" #include "ioctl.h" #include "errno.h" #include "if.h" #include "af.h" #include "ether.h" int ifqmaxlen = IFQ_MAXLEN; /* * Network interface utility routines. * * Routines with ifa_ifwith* names take sockaddr *'s as * parameters. */ ifinit() { register struct ifnet *ifp; for (ifp = ifnet; ifp; ifp = ifp->if_next) if (ifp->if_snd.ifq_maxlen == 0) ifp->if_snd.ifq_maxlen = ifqmaxlen; if_slowtimo(); } #ifdef vax /* * Call each interface on a Unibus reset. */ ifubareset(uban) int uban; { register struct ifnet *ifp; for (ifp = ifnet; ifp; ifp = ifp->if_next) if (ifp->if_reset) (*ifp->if_reset)(ifp->if_unit, uban); } #endif /* * Attach an interface to the * list of "active" interfaces. */ if_attach(ifp) struct ifnet *ifp; { register struct ifnet **p = &ifnet; while (*p) p = &((*p)->if_next); *p = ifp; } /* * Locate an interface based on a complete address. */ /*ARGSUSED*/ struct ifaddr * ifa_ifwithaddr(addr) struct sockaddr *addr; { register struct ifnet *ifp; register struct ifaddr *ifa; #define equal(a1, a2) \ (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0) for (ifp = ifnet; ifp; ifp = ifp->if_next) for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr.sa_family != addr->sa_family) continue; if (equal(&ifa->ifa_addr, addr)) return (ifa); if ((ifp->if_flags & IFF_BROADCAST) && equal(&ifa->ifa_broadaddr, addr)) return (ifa); } return ((struct ifaddr *)0); } /* * Locate the point to point interface with a given destination address. */ /*ARGSUSED*/ struct ifaddr * ifa_ifwithdstaddr(addr) struct sockaddr *addr; { register struct ifnet *ifp; register struct ifaddr *ifa; for (ifp = ifnet; ifp; ifp = ifp->if_next) if (ifp->if_flags & IFF_POINTOPOINT) for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr.sa_family != addr->sa_family) continue; if (equal(&ifa->ifa_dstaddr, addr)) return (ifa); } return ((struct ifaddr *)0); } /* * Find an interface on a specific network. If many, choice * is first found. */ struct ifaddr * ifa_ifwithnet(addr) register struct sockaddr *addr; { register struct ifnet *ifp; register struct ifaddr *ifa; register u_int af = addr->sa_family; register int (*netmatch)(); if (af >= AF_MAX) return (0); netmatch = afswitch[af].af_netmatch; for (ifp = ifnet; ifp; ifp = ifp->if_next) for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr.sa_family != addr->sa_family) continue; if ((*netmatch)(&ifa->ifa_addr, addr)) return (ifa); } return ((struct ifaddr *)0); } #ifdef notdef /* * Find an interface using a specific address family */ struct ifaddr * ifa_ifwithaf(af) register int af; { register struct ifnet *ifp; register struct ifaddr *ifa; for (ifp = ifnet; ifp; ifp = ifp->if_next) for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) if (ifa->ifa_addr.sa_family == af) return (ifa); return ((struct ifaddr *)0); } #endif /* * Mark an interface down and notify protocols of * the transition. * NOTE: must be called at splnet or eqivalent. */ if_down(ifp) register struct ifnet *ifp; { register struct ifaddr *ifa; ifp->if_flags &= ~IFF_UP; for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) pfctlinput(PRC_IFDOWN, &ifa->ifa_addr); if_qflush(&ifp->if_snd); } /* * Flush an interface queue. */ if_qflush(ifq) register struct ifqueue *ifq; { register struct mbuf *m, *n; n = ifq->ifq_head; while (m = n) { n = m->m_act; m_freem(m); } ifq->ifq_head = 0; ifq->ifq_tail = 0; ifq->ifq_len = 0; } /* * Handle interface watchdog timer routines. Called * from softclock, we decrement timers (if set) and * call the appropriate interface routine on expiration. */ if_slowtimo() { extern int hz; register struct ifnet *ifp; for (ifp = ifnet; ifp; ifp = ifp->if_next) { if (ifp->if_timer == 0 || --ifp->if_timer) continue; if (ifp->if_watchdog) (*ifp->if_watchdog)(ifp->if_unit); } TIMEOUT(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); } /* * Map interface name to * interface structure pointer. */ struct ifnet * ifunit(name) register char *name; { register char *cp; register struct ifnet *ifp; int unit; for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) if (*cp >= '0' && *cp <= '9') break; if (*cp == '\0' || cp == name + IFNAMSIZ) return ((struct ifnet *)0); unit = *cp - '0'; for (ifp = ifnet; ifp; ifp = ifp->if_next) { if (bcmp(ifp->if_name, name, (unsigned)(cp - name))) continue; if (unit == ifp->if_unit) break; } return (ifp); } /* * Interface ioctls. */ ifioctl(so, cmd, data) struct socket *so; int cmd; caddr_t data; { register struct ifnet *ifp; register struct ifreq *ifr; switch (cmd) { case SIOCGIFCONF: return (ifconf(cmd, data)); #if defined(INET) && NETHER > 0 case SIOCSARP: case SIOCDARP: if (!suser()) return (u.u_error); /* FALL THROUGH */ case SIOCGARP: return (arpioctl(cmd, data)); #endif } ifr = (struct ifreq *)data; ifp = ifunit(ifr->ifr_name); if (ifp == 0) return (ENXIO); switch (cmd) { case SIOCGIFFLAGS: ifr->ifr_flags = ifp->if_flags; break; case SIOCGIFMETRIC: ifr->ifr_metric = ifp->if_metric; break; case SIOCSIFFLAGS: if (!suser()) return (u.u_error); if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { int s = splimp(); if_down(ifp); splx(s); } ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | (ifr->ifr_flags &~ IFF_CANTCHANGE); if (ifp->if_ioctl) (void) (*ifp->if_ioctl)(ifp, cmd, data); break; case SIOCSIFMETRIC: if (!suser()) return (u.u_error); ifp->if_metric = ifr->ifr_metric; break; default: if (so->so_proto == 0) return (EOPNOTSUPP); return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, cmd, data, ifp)); } return (0); } /* * Return interface configuration * of system. List may be used * in later ioctl's (above) to get * other information. */ /*ARGSUSED*/ ifconf(cmd, data) int cmd; caddr_t data; { register struct ifconf *ifc = (struct ifconf *)data; register struct ifnet *ifp = ifnet; register struct ifaddr *ifa; register char *cp, *ep; struct ifreq ifr, *ifrp; int space = ifc->ifc_len, error = 0; ifrp = ifc->ifc_req; ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); for (cp = ifr.ifr_name; cp < ep && *cp; cp++) ; *cp++ = '0' + ifp->if_unit; *cp = '\0'; if ((ifa = ifp->if_addrlist) == 0) { bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); if (error) break; space -= sizeof (ifr), ifrp++; } else for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { ifr.ifr_addr = ifa->ifa_addr; error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); if (error) break; space -= sizeof (ifr), ifrp++; } } ifc->ifc_len -= space; return (error); } rlist; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr.sa_family != addr->sa_family) continue; if ((*netmatch)(&ifa->ifa_addr, addr)) return (ifa); } return ((struct ifaddr *)0); } #ifdef notdef /* * Find an interface using a specific address family */ struct ifaddr * ifa_ifwithaf(af) register int af; { register struct ifnet *ifp; register struct ifaddr *ifa; for (ifp = ifnet; ifp; ifp = ifp->if_next) for (ifa = ifp-sys/net/if_loop.c 444 12 0 5600 4235731636 7237 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)if_loop.c 7.3 (Berkeley) 12/30/87 */ /* * Loopback interface driver for protocol testing and timing. */ #include "param.h" #include "systm.h" #include "mbuf.h" #include "socket.h" #include "errno.h" #include "ioctl.h" #include "domain.h" #include "protosw.h" #include "../net/if.h" #include "../net/netisr.h" #include "../net/route.h" #ifdef INET #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netinet/in_var.h" #include "../netinet/ip.h" #endif #ifdef NS #include "../netns/ns.h" #include "../netns/ns_if.h" #endif #define LOMTU (1024+512) struct ifnet loif; int looutput(), loioctl(); loattach() { register struct ifnet *ifp = &loif; ifp->if_name = "lo"; ifp->if_mtu = LOMTU; ifp->if_flags = IFF_LOOPBACK; ifp->if_ioctl = loioctl; ifp->if_output = looutput; if_attach(ifp); } looutput(ifp, m0, dst) struct ifnet *ifp; register struct mbuf *m0; struct sockaddr *dst; { int s; register struct ifqueue *ifq; struct mbuf *m; /* * Place interface pointer before the data * for the receiving protocol. */ if (m0->m_off <= MMAXOFF && m0->m_off >= MMINOFF + sizeof(struct ifnet *)) { m0->m_off -= sizeof(struct ifnet *); m0->m_len += sizeof(struct ifnet *); } else { MGET(m, M_DONTWAIT, MT_HEADER); if (m == (struct mbuf *)0) return (ENOBUFS); m->m_off = MMINOFF; m->m_len = sizeof(struct ifnet *); m->m_next = m0; m0 = m; } *(mtod(m0, struct ifnet **)) = ifp; s = splimp(); ifp->if_opackets++; switch (dst->sa_family) { #ifdef INET case AF_INET: ifq = &ipintrq; if (IF_QFULL(ifq)) { IF_DROP(ifq); m_freem(m0); splx(s); return (ENOBUFS); } IF_ENQUEUE(ifq, m0); schednetisr(NETISR_IP); break; #endif #ifdef NS case AF_NS: ifq = &nsintrq; if (IF_QFULL(ifq)) { IF_DROP(ifq); m_freem(m0); splx(s); return (ENOBUFS); } IF_ENQUEUE(ifq, m0); schednetisr(NETISR_NS); break; #endif default: splx(s); printf("lo%d: can't handle af%d\n", ifp->if_unit, dst->sa_family); m_freem(m0); return (EAFNOSUPPORT); } ifp->if_ipackets++; splx(s); return (0); } /* * Process an ioctl request. */ /* ARGSUSED */ loioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { int error = 0; switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; /* * Everything else is done at a higher level. */ break; default: error = EINVAL; } return (error); } r_addr = ifa->ifa_addr; error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); if (error) break; space -= sizsys/net/route.c 444 12 0 17575 4235652443 7002 /* * Copyright (c) 1980, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)route.c 7.3 (Berkeley) 12/30/87 */ #include "param.h" #include "systm.h" #include "mbuf.h" #include "protosw.h" #include "socket.h" #include "user.h" #include "ioctl.h" #include "errno.h" #include "if.h" #include "af.h" #include "route.h" int rttrash; /* routes not in table but not freed */ struct sockaddr wildcard; /* zero valued cookie for wildcard searches */ int rthashsize = RTHASHSIZ; /* for netstat, etc. */ /* * Packet routing routines. */ rtalloc(ro) register struct route *ro; { register struct rtentry *rt; register struct mbuf *m; register u_int hash; struct sockaddr *dst = &ro->ro_dst; int (*match)(), doinghost, s; struct afhash h; u_int af = dst->sa_family; struct mbuf **table; if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)) return; /* XXX */ if (af >= AF_MAX) return; (*afswitch[af].af_hash)(dst, &h); match = afswitch[af].af_netmatch; hash = h.afh_hosthash, table = rthost, doinghost = 1; s = splnet(); again: for (m = table[RTHASHMOD(hash)]; m; m = m->m_next) { rt = mtod(m, struct rtentry *); if (rt->rt_hash != hash) continue; if ((rt->rt_flags & RTF_UP) == 0 || (rt->rt_ifp->if_flags & IFF_UP) == 0) continue; if (doinghost) { if (bcmp((caddr_t)&rt->rt_dst, (caddr_t)dst, sizeof (*dst))) continue; } else { if (rt->rt_dst.sa_family != af || !(*match)(&rt->rt_dst, dst)) continue; } rt->rt_refcnt++; splx(s); if (dst == &wildcard) rtstat.rts_wildcard++; ro->ro_rt = rt; return; } if (doinghost) { doinghost = 0; hash = h.afh_nethash, table = rtnet; goto again; } /* * Check for wildcard gateway, by convention network 0. */ if (dst != &wildcard) { dst = &wildcard, hash = 0; goto again; } splx(s); rtstat.rts_unreach++; } rtfree(rt) register struct rtentry *rt; { if (rt == 0) panic("rtfree"); rt->rt_refcnt--; if (rt->rt_refcnt == 0 && (rt->rt_flags&RTF_UP) == 0) { rttrash--; (void) m_free(dtom(rt)); } } /* * Force a routing table entry to the specified * destination to go through the given gateway. * Normally called as a result of a routing redirect * message from the network layer. * * N.B.: must be called at splnet or higher * */ rtredirect(dst, gateway, flags, src) struct sockaddr *dst, *gateway, *src; int flags; { struct route ro; register struct rtentry *rt; /* verify the gateway is directly reachable */ if (ifa_ifwithnet(gateway) == 0) { rtstat.rts_badredirect++; return; } ro.ro_dst = *dst; ro.ro_rt = 0; rtalloc(&ro); rt = ro.ro_rt; #define equal(a1, a2) \ (bcmp((caddr_t)(a1), (caddr_t)(a2), sizeof(struct sockaddr)) == 0) /* * If the redirect isn't from our current router for this dst, * it's either old or wrong. If it redirects us to ourselves, * we have a routing loop, perhaps as a result of an interface * going down recently. */ if ((rt && !equal(src, &rt->rt_gateway)) || ifa_ifwithaddr(gateway)) { rtstat.rts_badredirect++; if (rt) rtfree(rt); return; } /* * Create a new entry if we just got back a wildcard entry * or the the lookup failed. This is necessary for hosts * which use routing redirects generated by smart gateways * to dynamically build the routing tables. */ if (rt && (*afswitch[dst->sa_family].af_netmatch)(&wildcard, &rt->rt_dst)) { rtfree(rt); rt = 0; } if (rt == 0) { rtinit(dst, gateway, (int)SIOCADDRT, (flags & RTF_HOST) | RTF_GATEWAY | RTF_DYNAMIC); rtstat.rts_dynamic++; return; } /* * Don't listen to the redirect if it's * for a route to an interface. */ if (rt->rt_flags & RTF_GATEWAY) { if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) { /* * Changing from route to net => route to host. * Create new route, rather than smashing route to net. */ rtinit(dst, gateway, (int)SIOCADDRT, flags | RTF_DYNAMIC); rtstat.rts_dynamic++; } else { /* * Smash the current notion of the gateway to * this destination. */ rt->rt_gateway = *gateway; rt->rt_flags |= RTF_MODIFIED; rtstat.rts_newgateway++; } } else rtstat.rts_badredirect++; rtfree(rt); } /* * Routing table ioctl interface. */ rtioctl(cmd, data) int cmd; caddr_t data; { if (cmd != SIOCADDRT && cmd != SIOCDELRT) return (EINVAL); if (!suser()) return (u.u_error); return (rtrequest(cmd, (struct rtentry *)data)); } /* * Carry out a request to change the routing table. Called by * interfaces at boot time to make their ``local routes'' known, * for ioctl's, and as the result of routing redirects. */ rtrequest(req, entry) int req; register struct rtentry *entry; { register struct mbuf *m, **mprev; struct mbuf **mfirst; register struct rtentry *rt; struct afhash h; int s, error = 0, (*match)(); u_int af; u_int hash; struct ifaddr *ifa; struct ifaddr *ifa_ifwithdstaddr(); af = entry->rt_dst.sa_family; if (af >= AF_MAX) return (EAFNOSUPPORT); (*afswitch[af].af_hash)(&entry->rt_dst, &h); if (entry->rt_flags & RTF_HOST) { hash = h.afh_hosthash; mprev = &rthost[RTHASHMOD(hash)]; } else { hash = h.afh_nethash; mprev = &rtnet[RTHASHMOD(hash)]; } match = afswitch[af].af_netmatch; s = splimp(); for (mfirst = mprev; m = *mprev; mprev = &m->m_next) { rt = mtod(m, struct rtentry *); if (rt->rt_hash != hash) continue; if (entry->rt_flags & RTF_HOST) { if (!equal(&rt->rt_dst, &entry->rt_dst)) continue; } else { if (rt->rt_dst.sa_family != entry->rt_dst.sa_family || (*match)(&rt->rt_dst, &entry->rt_dst) == 0) continue; } if (equal(&rt->rt_gateway, &entry->rt_gateway)) break; } switch (req) { case SIOCDELRT: if (m == 0) { error = ESRCH; goto bad; } *mprev = m->m_next; if (rt->rt_refcnt > 0) { rt->rt_flags &= ~RTF_UP; rttrash++; m->m_next = 0; } else (void) m_free(m); break; case SIOCADDRT: if (m) { error = EEXIST; goto bad; } if ((entry->rt_flags & RTF_GATEWAY) == 0) { /* * If we are adding a route to an interface, * and the interface is a pt to pt link * we should search for the destination * as our clue to the interface. Otherwise * we can use the local address. */ ifa = 0; if (entry->rt_flags & RTF_HOST) ifa = ifa_ifwithdstaddr(&entry->rt_dst); if (ifa == 0) ifa = ifa_ifwithaddr(&entry->rt_gateway); } else { /* * If we are adding a route to a remote net * or host, the gateway may still be on the * other end of a pt to pt link. */ ifa = ifa_ifwithdstaddr(&entry->rt_gateway); } if (ifa == 0) { ifa = ifa_ifwithnet(&entry->rt_gateway); if (ifa == 0) { error = ENETUNREACH; goto bad; } } m = m_get(M_DONTWAIT, MT_RTABLE); if (m == 0) { error = ENOBUFS; goto bad; } m->m_next = *mfirst; *mfirst = m; m->m_off = MMINOFF; m->m_len = sizeof (struct rtentry); rt = mtod(m, struct rtentry *); rt->rt_hash = hash; rt->rt_dst = entry->rt_dst; rt->rt_gateway = entry->rt_gateway; rt->rt_flags = RTF_UP | (entry->rt_flags & (RTF_HOST|RTF_GATEWAY|RTF_DYNAMIC)); rt->rt_refcnt = 0; rt->rt_use = 0; rt->rt_ifp = ifa->ifa_ifp; break; } bad: splx(s); return (error); } /* * Set up a routing table entry, normally * for an interface. */ rtinit(dst, gateway, cmd, flags) struct sockaddr *dst, *gateway; int cmd, flags; { struct rtentry route; bzero((caddr_t)&route, sizeof (route)); route.rt_dst = *dst; route.rt_gateway = *gateway; route.rt_flags = flags; (void) rtrequest(cmd, &route); } verlapping partition tables) the warning * message will be erroneously issued in some valid situations. */ #define RAWPART 2 /* sys/net/raw_cb.c 444 12 0 6224 4235652202 7037 /* * Copyright (c) 1980, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)raw_cb.c 7.4 (Berkeley) 12/30/87 */ #include "param.h" #include "systm.h" #include "mbuf.h" #include "socket.h" #include "socketvar.h" #include "domain.h" #include "protosw.h" #include "errno.h" #include "if.h" #include "route.h" #include "raw_cb.h" #include "../netinet/in.h" /* * Routines to manage the raw protocol control blocks. * * TODO: * hash lookups by protocol family/protocol + address family * take care of unique address problems per AF? * redo address binding to allow wildcards */ /* * Allocate a control block and a nominal amount * of buffer space for the socket. */ raw_attach(so, proto) register struct socket *so; int proto; { struct mbuf *m; register struct rawcb *rp; m = m_getclr(M_DONTWAIT, MT_PCB); if (m == 0) return (ENOBUFS); if (sbreserve(&so->so_snd, RAWSNDQ) == 0) goto bad; if (sbreserve(&so->so_rcv, RAWRCVQ) == 0) goto bad2; rp = mtod(m, struct rawcb *); rp->rcb_socket = so; so->so_pcb = (caddr_t)rp; rp->rcb_pcb = 0; rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family; rp->rcb_proto.sp_protocol = proto; insque(rp, &rawcb); return (0); bad2: sbrelease(&so->so_snd); bad: (void) m_free(m); return (ENOBUFS); } /* * Detach the raw connection block and discard * socket resources. */ raw_detach(rp) register struct rawcb *rp; { struct socket *so = rp->rcb_socket; if (rp->rcb_route.ro_rt) rtfree(rp->rcb_route.ro_rt); so->so_pcb = 0; sofree(so); remque(rp); if (rp->rcb_options) m_freem(rp->rcb_options); m_freem(dtom(rp)); } /* * Disconnect and possibly release resources. */ raw_disconnect(rp) struct rawcb *rp; { rp->rcb_flags &= ~RAW_FADDR; if (rp->rcb_socket->so_state & SS_NOFDREF) raw_detach(rp); } raw_bind(so, nam) register struct socket *so; struct mbuf *nam; { struct sockaddr *addr = mtod(nam, struct sockaddr *); register struct rawcb *rp; if (ifnet == 0) return (EADDRNOTAVAIL); /* BEGIN DUBIOUS */ /* * Should we verify address not already in use? * Some say yes, others no. */ switch (addr->sa_family) { #ifdef INET case AF_IMPLINK: case AF_INET: { if (((struct sockaddr_in *)addr)->sin_addr.s_addr && ifa_ifwithaddr(addr) == 0) return (EADDRNOTAVAIL); break; } #endif default: return (EAFNOSUPPORT); } /* END DUBIOUS */ rp = sotorawcb(so); bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr)); rp->rcb_flags |= RAW_LADDR; return (0); } /* * Associate a peer's address with a * raw connection block. */ raw_connaddr(rp, nam) struct rawcb *rp; struct mbuf *nam; { struct sockaddr *addr = mtod(nam, struct sockaddr *); bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr)); rp->rcb_flags |= RAW_FADDR; } { rt = mtod(m, struct rtentry *); if (rt->rt_hash != hash) continue; if (entry->rt_flags & RTF_HOST) { if (!equal(&rt->rt_dst, &entry->rt_dst)) continue; } else { if (rt->rt_dst.sa_family != entry->rt_dst.sa_family || (*match)(&rt->rt_dst, &entry->rt_dst) == 0) continue; } if (equal(&rt->rt_gateway, &entry->rt_gateway)) bresys/net/raw_usrreq.c 444 12 0 14451 4235652256 10026 /* * Copyright (c) 1980, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)raw_usrreq.c 7.3 (Berkeley) 12/30/87 */ #include "param.h" #include "mbuf.h" #include "domain.h" #include "protosw.h" #include "socket.h" #include "socketvar.h" #include "errno.h" #include "if.h" #include "route.h" #include "netisr.h" #include "raw_cb.h" /* * Initialize raw connection block q. */ raw_init() { rawcb.rcb_next = rawcb.rcb_prev = &rawcb; rawintrq.ifq_maxlen = IFQ_MAXLEN; } /* * Raw protocol interface. */ raw_input(m0, proto, src, dst) struct mbuf *m0; struct sockproto *proto; struct sockaddr *src, *dst; { register struct mbuf *m; struct raw_header *rh; int s; /* * Rip off an mbuf for a generic header. */ m = m_get(M_DONTWAIT, MT_HEADER); if (m == 0) { m_freem(m0); return; } m->m_next = m0; m->m_len = sizeof(struct raw_header); rh = mtod(m, struct raw_header *); rh->raw_dst = *dst; rh->raw_src = *src; rh->raw_proto = *proto; /* * Header now contains enough info to decide * which socket to place packet in (if any). * Queue it up for the raw protocol process * running at software interrupt level. */ s = splimp(); if (IF_QFULL(&rawintrq)) m_freem(m); else IF_ENQUEUE(&rawintrq, m); splx(s); schednetisr(NETISR_RAW); } /* * Raw protocol input routine. Process packets entered * into the queue at interrupt time. Find the socket * associated with the packet(s) and move them over. If * nothing exists for this packet, drop it. */ rawintr() { int s; struct mbuf *m; register struct rawcb *rp; register struct raw_header *rh; struct socket *last; next: s = splimp(); IF_DEQUEUE(&rawintrq, m); splx(s); if (m == 0) return; rh = mtod(m, struct raw_header *); last = 0; for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { if (rp->rcb_proto.sp_family != rh->raw_proto.sp_family) continue; if (rp->rcb_proto.sp_protocol && rp->rcb_proto.sp_protocol != rh->raw_proto.sp_protocol) continue; /* * We assume the lower level routines have * placed the address in a canonical format * suitable for a structure comparison. */ #define equal(a1, a2) \ (bcmp((caddr_t)&(a1), (caddr_t)&(a2), sizeof (struct sockaddr)) == 0) if ((rp->rcb_flags & RAW_LADDR) && !equal(rp->rcb_laddr, rh->raw_dst)) continue; if ((rp->rcb_flags & RAW_FADDR) && !equal(rp->rcb_faddr, rh->raw_src)) continue; if (last) { struct mbuf *n; if (n = m_copy(m->m_next, 0, (int)M_COPYALL)) { if (sbappendaddr(&last->so_rcv, &rh->raw_src, n, (struct mbuf *)0) == 0) /* should notify about lost packet */ m_freem(n); else sorwakeup(last); } } last = rp->rcb_socket; } if (last) { if (sbappendaddr(&last->so_rcv, &rh->raw_src, m->m_next, (struct mbuf *)0) == 0) m_freem(m->m_next); else sorwakeup(last); (void) m_free(m); /* header */ } else m_freem(m); goto next; } /*ARGSUSED*/ raw_ctlinput(cmd, arg) int cmd; struct sockaddr *arg; { if (cmd < 0 || cmd > PRC_NCMDS) return; /* INCOMPLETE */ } /*ARGSUSED*/ raw_usrreq(so, req, m, nam, rights) struct socket *so; int req; struct mbuf *m, *nam, *rights; { register struct rawcb *rp = sotorawcb(so); register int error = 0; if (req == PRU_CONTROL) return (EOPNOTSUPP); if (rights && rights->m_len) { error = EOPNOTSUPP; goto release; } if (rp == 0 && req != PRU_ATTACH) { error = EINVAL; goto release; } switch (req) { /* * Allocate a raw control block and fill in the * necessary info to allow packets to be routed to * the appropriate raw interface routine. */ case PRU_ATTACH: if ((so->so_state & SS_PRIV) == 0) { error = EACCES; break; } if (rp) { error = EINVAL; break; } error = raw_attach(so, (int)nam); break; /* * Destroy state just before socket deallocation. * Flush data or not depending on the options. */ case PRU_DETACH: if (rp == 0) { error = ENOTCONN; break; } raw_detach(rp); break; /* * If a socket isn't bound to a single address, * the raw input routine will hand it anything * within that protocol family (assuming there's * nothing else around it should go to). */ case PRU_CONNECT: if (rp->rcb_flags & RAW_FADDR) { error = EISCONN; break; } raw_connaddr(rp, nam); soisconnected(so); break; case PRU_CONNECT2: error = EOPNOTSUPP; goto release; case PRU_BIND: if (rp->rcb_flags & RAW_LADDR) { error = EINVAL; /* XXX */ break; } error = raw_bind(so, nam); break; case PRU_DISCONNECT: if ((rp->rcb_flags & RAW_FADDR) == 0) { error = ENOTCONN; break; } raw_disconnect(rp); soisdisconnected(so); break; /* * Mark the connection as being incapable of further input. */ case PRU_SHUTDOWN: socantsendmore(so); break; /* * Ship a packet out. The appropriate raw output * routine handles any massaging necessary. */ case PRU_SEND: if (nam) { if (rp->rcb_flags & RAW_FADDR) { error = EISCONN; break; } raw_connaddr(rp, nam); } else if ((rp->rcb_flags & RAW_FADDR) == 0) { error = ENOTCONN; break; } error = (*so->so_proto->pr_output)(m, so); m = NULL; if (nam) rp->rcb_flags &= ~RAW_FADDR; break; case PRU_ABORT: raw_disconnect(rp); sofree(so); soisdisconnected(so); break; case PRU_SENSE: /* * stat: don't bother with a blocksize. */ return (0); /* * Not supported. */ case PRU_RCVOOB: case PRU_RCVD: return(EOPNOTSUPP); case PRU_LISTEN: case PRU_ACCEPT: case PRU_SENDOOB: error = EOPNOTSUPP; break; case PRU_SOCKADDR: bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, caddr_t), sizeof (struct sockaddr)); nam->m_len = sizeof (struct sockaddr); break; case PRU_PEERADDR: bcopy((caddr_t)&rp->rcb_faddr, mtod(nam, caddr_t), sizeof (struct sockaddr)); nam->m_len = sizeof (struct sockaddr); break; default: panic("raw_usrreq"); } release: if (m != NULL) m_freem(m); return (error); } ormalseg5(); } return(0); } /* * It was noticed that the ioctl processing of disklabels was the same * for every disk driver. Disk drivers should call this routine after * handling ioctls (if any) particulasys/net/if.h 444 12 0 16741 5514434534 6241 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)if.h 7.2.1 (2.11BSD GTE) 12/31/93 */ /* * Structures defining a network interface, providing a packet * transport mechanism (ala level 0 of the PUP protocols). * * Each interface accepts output datagrams of a specified maximum * length, and provides higher level routines with input datagrams * received from its medium. * * Output occurs when the routine if_output is called, with three parameters: * (*ifp->if_output)(ifp, m, dst) * Here m is the mbuf chain to be sent and dst is the destination address. * The output routine encapsulates the supplied datagram if necessary, * and then transmits it on its medium. * * On input, each interface unwraps the data received by it, and either * places it on the input queue of a internetwork datagram routine * and posts the associated software interrupt, or passes the datagram to a raw * packet input routine. * * Routines exist for locating interfaces by their addresses * or for locating a interface on a certain network, as well as more general * routing and gateway routines maintaining information used to locate * interfaces. These routines live in the files if.c and route.c */ /* * Structure defining a queue for a network interface. * * (Would like to call this struct ``if'', but C isn't PL/1.) */ struct ifnet { char *if_name; /* name, e.g. ``en'' or ``lo'' */ short if_unit; /* sub-unit for lower level driver */ short if_mtu; /* maximum transmission unit */ short if_flags; /* up/down, broadcast, etc. */ short if_timer; /* time 'til if_watchdog called */ int if_metric; /* routing metric (external only) */ struct ifaddr *if_addrlist; /* linked list of addresses per if */ struct ifqueue { struct mbuf *ifq_head; struct mbuf *ifq_tail; int ifq_len; int ifq_maxlen; int ifq_drops; } if_snd; /* output queue */ /* procedure handles */ int (*if_init)(); /* init routine */ int (*if_output)(); /* output routine */ int (*if_ioctl)(); /* ioctl routine */ int (*if_reset)(); /* bus reset routine */ int (*if_watchdog)(); /* timer routine */ /* generic interface statistics */ long if_ipackets; /* packets received on interface */ long if_ierrors; /* input errors on interface */ long if_opackets; /* packets sent on interface */ long if_oerrors; /* output errors on interface */ long if_collisions; /* collisions on csma interfaces */ /* end statistics */ struct ifnet *if_next; }; #define IFF_UP 0x1 /* interface is up */ #define IFF_BROADCAST 0x2 /* broadcast address valid */ #define IFF_DEBUG 0x4 /* turn on debugging */ #define IFF_LOOPBACK 0x8 /* is a loopback net */ #define IFF_POINTOPOINT 0x10 /* interface is point-to-point link */ #define IFF_NOTRAILERS 0x20 /* avoid use of trailers */ #define IFF_RUNNING 0x40 /* resources allocated */ #define IFF_NOARP 0x80 /* no address resolution protocol */ /* next two not supported now, but reserved: */ #define IFF_PROMISC 0x100 /* receive all packets */ #define IFF_ALLMULTI 0x200 /* receive all multicast packets */ /* flags set internally only: */ #define IFF_CANTCHANGE (IFF_BROADCAST | IFF_POINTOPOINT | IFF_RUNNING) /* * Output queues (ifp->if_snd) and internetwork datagram level (pup level 1) * input routines have queues of messages stored on ifqueue structures * (defined above). Entries are added to and deleted from these structures * by these macros, which should be called with ipl raised to splimp(). */ #define IF_QFULL(ifq) ((ifq)->ifq_len >= (ifq)->ifq_maxlen) #define IF_DROP(ifq) ((ifq)->ifq_drops++) #define IF_ENQUEUE(ifq, m) { \ (m)->m_act = 0; \ if ((ifq)->ifq_tail == 0) \ (ifq)->ifq_head = m; \ else \ (ifq)->ifq_tail->m_act = m; \ (ifq)->ifq_tail = m; \ (ifq)->ifq_len++; \ } #define IF_PREPEND(ifq, m) { \ (m)->m_act = (ifq)->ifq_head; \ if ((ifq)->ifq_tail == 0) \ (ifq)->ifq_tail = (m); \ (ifq)->ifq_head = (m); \ (ifq)->ifq_len++; \ } /* * Packets destined for level-1 protocol input routines * have a pointer to the receiving interface prepended to the data. * IF_DEQUEUEIF extracts and returns this pointer when dequeueing the packet. * IF_ADJ should be used otherwise to adjust for its presence. */ #define IF_ADJ(m) { \ (m)->m_off += sizeof(struct ifnet *); \ (m)->m_len -= sizeof(struct ifnet *); \ if ((m)->m_len == 0) { \ struct mbuf *n; \ MFREE((m), n); \ (m) = n; \ } \ } #define IF_DEQUEUEIF(ifq, m, ifp) { \ (m) = (ifq)->ifq_head; \ if (m) { \ if (((ifq)->ifq_head = (m)->m_act) == 0) \ (ifq)->ifq_tail = 0; \ (m)->m_act = 0; \ (ifq)->ifq_len--; \ (ifp) = *(mtod((m), struct ifnet **)); \ IF_ADJ(m); \ } \ } #define IF_DEQUEUE(ifq, m) { \ (m) = (ifq)->ifq_head; \ if (m) { \ if (((ifq)->ifq_head = (m)->m_act) == 0) \ (ifq)->ifq_tail = 0; \ (m)->m_act = 0; \ (ifq)->ifq_len--; \ } \ } #ifdef pdp11 #define IFQ_MAXLEN 15 #else #define IFQ_MAXLEN 50 #endif #define IFNET_SLOWHZ 1 /* granularity is 1 second */ /* * The ifaddr structure contains information about one address * of an interface. They are maintained by the different address families, * are allocated and attached when an address is set, and are linked * together so all addresses for an interface can be located. */ struct ifaddr { struct sockaddr ifa_addr; /* address of interface */ union { struct sockaddr ifu_broadaddr; struct sockaddr ifu_dstaddr; } ifa_ifu; #define ifa_broadaddr ifa_ifu.ifu_broadaddr /* broadcast address */ #define ifa_dstaddr ifa_ifu.ifu_dstaddr /* other end of p-to-p link */ struct ifnet *ifa_ifp; /* back-pointer to interface */ struct ifaddr *ifa_next; /* next address for interface */ }; /* * Interface request structure used for socket * ioctl's. All interface ioctl's must have parameter * definitions which begin with ifr_name. The * remainder may be interface specific. */ struct ifreq { #define IFNAMSIZ 16 char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */ union { struct sockaddr ifru_addr; struct sockaddr ifru_dstaddr; struct sockaddr ifru_broadaddr; short ifru_flags; int ifru_metric; caddr_t ifru_data; } ifr_ifru; #define ifr_addr ifr_ifru.ifru_addr /* address */ #define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */ #define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ #define ifr_flags ifr_ifru.ifru_flags /* flags */ #define ifr_metric ifr_ifru.ifru_metric /* metric */ #define ifr_data ifr_ifru.ifru_data /* for use by interface */ }; /* * Structure used in SIOCGIFCONF request. * Used to retrieve interface configuration * for machine (useful for programs which * must know all networks accessible). */ struct ifconf { int ifc_len; /* size of associated buffer */ union { caddr_t ifcu_buf; struct ifreq *ifcu_req; } ifc_ifcu; #define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ #define ifc_req ifc_ifcu.ifcu_req /* array of structures returned */ }; #ifdef SUPERVISOR #include "../net/if_arp.h" struct ifqueue rawintrq; /* raw packet input queue */ struct ifnet *ifnet; struct ifaddr *ifa_ifwithaddr(), *ifa_ifwithnet(); struct ifaddr *ifa_ifwithdstaddr(); #else KERNEL #include #endif KERNEL ily (assuming there's * nothisys/net/raw_cb.h 444 12 0 3536 4235407627 7060 /* * Copyright (c) 1980, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)raw_cb.h 7.2 (Berkeley) 12/30/87 */ /* * Raw protocol interface control block. Used * to tie a socket to the generic raw interface. */ struct rawcb { struct rawcb *rcb_next; /* doubly linked list */ struct rawcb *rcb_prev; struct socket *rcb_socket; /* back pointer to socket */ struct sockaddr rcb_faddr; /* destination address */ struct sockaddr rcb_laddr; /* socket's address */ struct sockproto rcb_proto; /* protocol family, protocol */ caddr_t rcb_pcb; /* protocol specific stuff */ struct mbuf *rcb_options; /* protocol specific options */ struct route rcb_route; /* routing information */ short rcb_flags; }; /* * Since we can't interpret canonical addresses, * we mark an address present in the flags field. */ #define RAW_LADDR 01 #define RAW_FADDR 02 #define RAW_DONTROUTE 04 /* no routing, default */ #define sotorawcb(so) ((struct rawcb *)(so)->so_pcb) /* * Nominal space allocated to a raw socket. */ #define RAWSNDQ 2048 #define RAWRCVQ 2048 /* * Format of raw interface header prepended by * raw_input after call from protocol specific * input routine. */ struct raw_header { struct sockproto raw_proto; /* format of packet */ struct sockaddr raw_dst; /* dst address for rawintr */ struct sockaddr raw_src; /* src address for sbappendaddr */ }; #ifdef SUPERVISOR struct rawcb rawcb; /* head of list */ #endif fq)->ifq_head = (m)->m_act) == 0) \ (ifq)->ifq_tail = 0; \ (m)->m_act = 0; \ (ifq)->ifq_len--; \ (ifp) = *(mtod((m), struct ifnet **)); \ IF_ADJ(m); \ sys/net/route.h 444 12 0 5240 4235410340 6735 /* * Copyright (c) 1980, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)route.h 7.3 (Berkeley) 12/30/87 */ /* * Kernel resident routing tables. * * The routing tables are initialized when interface addresses * are set by making entries for all directly connected interfaces. */ /* * A route consists of a destination address and a reference * to a routing entry. These are often held by protocols * in their control blocks, e.g. inpcb. */ struct route { struct rtentry *ro_rt; struct sockaddr ro_dst; }; /* * We distinguish between routes to hosts and routes to networks, * preferring the former if available. For each route we infer * the interface to use from the gateway address supplied when * the route was entered. Routes that forward packets through * gateways are marked so that the output routines know to address the * gateway rather than the ultimate destination. */ struct rtentry { u_int rt_hash; /* to speed lookups */ struct sockaddr rt_dst; /* key */ struct sockaddr rt_gateway; /* value */ short rt_flags; /* up/down?, host/net */ short rt_refcnt; /* # held references */ u_long rt_use; /* raw # packets forwarded */ struct ifnet *rt_ifp; /* the answer: interface to use */ }; #define RTF_UP 0x1 /* route useable */ #define RTF_GATEWAY 0x2 /* destination is a gateway */ #define RTF_HOST 0x4 /* host entry (net otherwise) */ #define RTF_DYNAMIC 0x10 /* created dynamically (by redirect) */ #define RTF_MODIFIED 0x20 /* modified dynamically (by redirect) */ /* * Routing statistics. */ struct rtstat { short rts_badredirect; /* bogus redirect calls */ short rts_dynamic; /* routes created by redirects */ short rts_newgateway; /* routes modified by redirects */ short rts_unreach; /* lookups which failed */ short rts_wildcard; /* lookups satisfied by a wildcard */ }; #ifdef SUPERVISOR #define RTFREE(rt) \ if ((rt)->rt_refcnt == 1) \ rtfree(rt); \ else \ (rt)->rt_refcnt--; #ifdef GATEWAY #define RTHASHSIZ 64 #else #define RTHASHSIZ 8 #endif #if (RTHASHSIZ & (RTHASHSIZ - 1)) == 0 #define RTHASHMOD(h) ((h) & (RTHASHSIZ - 1)) #else #define RTHASHMOD(h) ((h) % RTHASHSIZ) #endif struct mbuf *rthost[RTHASHSIZ]; struct mbuf *rtnet[RTHASHSIZ]; struct rtstat rtstat; #endif itted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. sys/net/if_arp.h 444 12 0 4200 4235405562 7044 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)if_arp.h 7.2 (Berkeley) 12/30/87 */ /* * Address Resolution Protocol. * * See RFC 826 for protocol description. ARP packets are variable * in size; the arphdr structure defines the fixed-length portion. * Protocol type values are the same as those for 10 Mb/s Ethernet. * It is followed by the variable-sized fields ar_sha, arp_spa, * arp_tha and arp_tpa in that order, according to the lengths * specified. Field names used correspond to RFC 826. */ struct arphdr { u_short ar_hrd; /* format of hardware address */ #define ARPHRD_ETHER 1 /* ethernet hardware address */ u_short ar_pro; /* format of protocol address */ u_char ar_hln; /* length of hardware address */ u_char ar_pln; /* length of protocol address */ u_short ar_op; /* one of: */ #define ARPOP_REQUEST 1 /* request to resolve address */ #define ARPOP_REPLY 2 /* response to previous request */ /* * The remaining fields are variable in size, * according to the sizes above. */ /* u_char ar_sha[]; /* sender hardware address */ /* u_char ar_spa[]; /* sender protocol address */ /* u_char ar_tha[]; /* target hardware address */ /* u_char ar_tpa[]; /* target protocol address */ }; /* * ARP ioctl request */ struct arpreq { struct sockaddr arp_pa; /* protocol address */ struct sockaddr arp_ha; /* hardware address */ int arp_flags; /* flags */ }; /* arp_flags and at_flags field values */ #define ATF_INUSE 0x01 /* entry in use */ #define ATF_COM 0x02 /* completed entry (enaddr valid) */ #define ATF_PERM 0x04 /* permanent entry */ #define ATF_PUBL 0x08 /* publish entry (respond for other host) */ #define ATF_USETRAILERS 0x10 /* has requested trailers */ fied by redirects */ short rts_unreach; /* lookups which failed */ short rts_wildcard; /* lookups satisfied by a wildcard */ }; #ifdef SUPERVISOR #define RTFREE(rt) \ if ((rt)->rt_refcnt == 1) \ rtfree(rt); \ else \ (rt)->rt_refcnt--; #ifdef GATEWAY #define RTHASHSIZ 64 #else #define RTHASHSIZ 8 #endif #if (RTHASHSIZ & (RTHASHSIZ - 1)) == 0 #define RTHASHMOD(h) ((h) & (sys/net/if_sl.c 440 12 0 27301 4320001022 6670 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)if_sl.c 7.6.1.1 (Berkeley) 3/15/88 */ /* * Serial Line interface * * Rick Adams * Center for Seismic Studies * 1300 N 17th Street, Suite 1450 * Arlington, Virginia 22209 * (703)276-7900 * rick@seismo.ARPA * seismo!rick * * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris). * N.B.: this belongs in netinet, not net, the way it stands now. * Should have a link-layer type designation, but wouldn't be * backwards-compatible. * * Converted to 4.3BSD Beta by Chris Torek. * Other changes made at Berkeley, based in part on code by Kirk Smith. */ /* $Header: /usr/src/sys/net/RCS/if_sl.c,v 1.1 88/08/18 00:28:00 bin Exp Locker: bin $ */ /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */ #include "sl.h" #if NSL > 0 #include "param.h" #include "mbuf.h" #include "buf.h" #include "dk.h" #include "domain.h" #include "protosw.h" #include "socket.h" #include "ioctl.h" #include "file.h" #include "tty.h" #include "errno.h" #include "if.h" #include "netisr.h" #include "route.h" #if INET #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netinet/in_var.h" #include "../netinet/ip.h" #endif /* * N.B.: SLMTU is now a hard limit on input packet size. * SLMTU must be <= CLBYTES - sizeof(struct ifnet *). */ #define SLMTU 1006 #define SLIP_HIWAT 500 /* don't start a new packet if HIWAT on queue */ #define CLISTRESERVE 200 /* Can't let clists get too low */ struct sl_softc { struct ifnet sc_if; /* network-visible interface */ short sc_flags; /* see below */ short sc_ilen; /* length of input-packet-so-far */ struct tty *sc_ttyp; /* pointer to tty structure */ char *sc_mp; /* pointer to next available buf char */ char *sc_buf; /* input buffer */ } sl_softc[NSL]; /* flags */ #define SC_ESCAPED 0x0001 /* saw a FRAME_ESCAPE */ #define FRAME_END 0300 /* Frame End */ #define FRAME_ESCAPE 0333 /* Frame Esc */ #define TRANS_FRAME_END 0334 /* transposed frame end */ #define TRANS_FRAME_ESCAPE 0335 /* transposed frame esc */ #define t_sc T_LINEP int sloutput(), slioctl(), slopen(), sltioctl(); /* * Called from boot code to establish sl interfaces. */ slattach() { register struct sl_softc *sc; register int i = 0; for (sc = sl_softc; i < NSL; sc++) { sc->sc_if.if_name = "sl"; sc->sc_if.if_unit = i++; sc->sc_if.if_mtu = SLMTU; sc->sc_if.if_flags = IFF_POINTOPOINT; sc->sc_if.if_ioctl = slioctl; sc->sc_if.if_output = sloutput; sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN; if_attach(&sc->sc_if); } } /* * Line specific open routine. * Attach the given tty to the first available sl unit. */ /* ARGSUSED */ slopen(dev, tp) dev_t dev; register struct tty *tp; { struct sl_softc *sc; register int nsl; #ifdef DONE_IN_KERNEL_STUB if (!suser()) return (EPERM); if (tp->t_line == SLIPDISC) return (EBUSY); #endif for (nsl = 0, sc = sl_softc; nsl < NSL; nsl++, sc++) if (sc->sc_ttyp == NULL) { sc->sc_flags = 0; sc->sc_ilen = 0; if (slinit(sc) == 0) return (ENOBUFS); mtkd(&tp->t_sc, sc); sc->sc_ttyp = tp; #ifdef DONE_IN_KERNEL_STUB ttyflush(tp, FREAD | FWRITE); #endif return (0); } return (ENXIO); } /* * Line specific close routine. * Detach the tty from the sl unit. * Mimics part of ttyclose(). */ slclose(tp) struct tty *tp; { register struct sl_softc *sc; int s; #ifdef DONE_IN_KERNEL_STUB ttywflush(tp); tp->t_line = 0; #endif s = splimp(); /* paranoid; splnet probably ok */ sc = (struct sl_softc *)mfkd(&tp->t_sc); if (sc != NULL) { if_down(&sc->sc_if); sc->sc_ttyp = NULL; mtkd(&tp->t_sc, 0); MCLFREE((struct mbuf *)sc->sc_buf); sc->sc_buf = 0; } splx(s); } /* * Line specific (tty) ioctl routine. * Provide a way to get the sl unit number. */ /* ARGSUSED */ sltioctl(tp, cmd, data, flag) struct tty *tp; caddr_t data; { if (cmd == TIOCGETD) { mtkd(data, ((struct sl_softc *)mfkd(&tp->t_sc))->sc_if.if_unit); return (0); } return (-1); } /* * Queue a packet. Start transmission if not active. */ sloutput(ifp, m, dst) register struct ifnet *ifp; register struct mbuf *m; struct sockaddr *dst; { register struct sl_softc *sc; long lval; int s; /* * `Cannot happen' (see slioctl). Someday we will extend * the line protocol to support other address families. */ if (dst->sa_family != AF_INET) { printf("sl%d: af%d not supported\n", ifp->if_unit, dst->sa_family); m_freem(m); return (EAFNOSUPPORT); } sc = &sl_softc[ifp->if_unit]; if (sc->sc_ttyp == NULL) { m_freem(m); return (ENETDOWN); /* sort of */ } cpfromkern(&sc->sc_ttyp->t_state, &lval, 4); if ((lval & TS_CARR_ON) == 0) { m_freem(m); return (EHOSTUNREACH); } s = splimp(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); splx(s); m_freem(m); sc->sc_if.if_oerrors++; return (ENOBUFS); } IF_ENQUEUE(&ifp->if_snd, m); if (mfkd(&sc->sc_ttyp->t_outq.c_cc) == 0) { splx(s); slstart(sc->sc_ttyp); } else splx(s); return (0); } /* * Start output on interface. Get another datagram * to send from the interface queue and map it to * the interface before starting output. */ slstart(tp) register struct tty *tp; { register struct sl_softc *sc; register struct mbuf *m; register int len; register u_char *cp; int nd, np, n, s, t, c_cc; char sup_clist[MLEN]; struct mbuf *m2; extern int cfreecount; sc = (struct sl_softc *)mfkd(&tp->t_sc); for (;;) { /* * If there is more in the output queue, just send it now. * We are being called in lieu of ttstart and must do what * it would. */ if ((c_cc = mfkd(&tp->t_outq.c_cc)) > 0) TTSTART(tp); if (c_cc > SLIP_HIWAT) return; /* * This happens briefly when the line shuts down. */ if (sc == NULL) return; /* * If system is getting low on clists * and we have something running already, stop here. */ if (mfkd(&cfreecount) < CLISTRESERVE + SLMTU && c_cc) return; /* * Get a packet and send it to the interface. */ s = splimp(); IF_DEQUEUE(&sc->sc_if.if_snd, m); splx(s); if (m == NULL) return; /* * The extra FRAME_END will start up a new packet, and thus * will flush any accumulated garbage. We do this whenever * the line may have been idle for some time. */ if (c_cc == 0) (void) PUTC(FRAME_END, &tp->t_outq); while (m) { cp = mtod(m, u_char *); len = m->m_len; while (len > 0) { /* * Find out how many bytes in the string we can * handle without doing something special. */ nd = locc(FRAME_ESCAPE, len, cp); np = locc(FRAME_END, len, cp); n = len - MAX(nd, np); /* * Put n characters into the tty output * queue. We do it in chunks of MLEN, using * the supervisor stack to copy into kernel * space. */ while (n) { t = n > MLEN ? MLEN : n; bcopy((char *)cp, sup_clist, t); if (B_TO_Q(sup_clist, t, &tp->t_outq)) break; len -= t; cp += t; n -= t; } if (n) break; /* * If there are characters left in the mbuf, * the first one must be special.. * Put it out in a different form. */ if (len) { if (PUTC(FRAME_ESCAPE, &tp->t_outq)) break; if (PUTC(*cp == FRAME_ESCAPE ? TRANS_FRAME_ESCAPE : TRANS_FRAME_END, &tp->t_outq)) { (void) UNPUTC(&tp->t_outq); break; } cp++; len--; } } MFREE(m, m2); m = m2; } if (PUTC(FRAME_END, &tp->t_outq)) { /* * Not enough room. Remove a char to make room * and end the packet normally. * If you get many collisions (more than one or two * a day) you probably do not have enough clists * and you should increase "nclist" in param.c. */ (void) UNPUTC(&tp->t_outq); (void) PUTC(FRAME_END, &tp->t_outq); sc->sc_if.if_collisions++; } else sc->sc_if.if_opackets++; } } slinit(sc) register struct sl_softc *sc; { struct mbuf *p; if (sc->sc_buf == (char *) 0) { MCLALLOC(p, 1); if (p) { sc->sc_buf = (char *)p; sc->sc_mp = sc->sc_buf + sizeof(struct ifnet *); } else { printf("sl%d: can't allocate buffer\n", sc - sl_softc); sc->sc_if.if_flags &= ~IFF_UP; return (0); } } return (1); } /* * Copy data buffer to mbuf chain; add ifnet pointer ifp. */ struct mbuf * sl_btom(sc, len, ifp) struct sl_softc *sc; register int len; struct ifnet *ifp; { register caddr_t cp; register struct mbuf *m, **mp; register unsigned count; struct mbuf *top = NULL; cp = sc->sc_buf + sizeof(struct ifnet *); mp = ⊤ while (len > 0) { MGET(m, M_DONTWAIT, MT_DATA); if ((*mp = m) == NULL) { m_freem(top); return (NULL); } if (ifp) m->m_off += sizeof(ifp); /* * If we have at least NBPG bytes, * allocate a new page. Swap the current buffer page * with the new one. We depend on having a space * left at the beginning of the buffer * for the interface pointer. */ if (len >= NBPG) { MCLGET(m); if (m->m_len == CLBYTES) { cp = mtod(m, char *); m->m_off = (int)sc->sc_buf - (int)m; sc->sc_buf = cp; if (ifp) { m->m_off += sizeof(ifp); count = MIN(len, CLBYTES - sizeof(struct ifnet *)); } else count = MIN(len, CLBYTES); goto nocopy; } } if (ifp) count = MIN(len, MLEN - sizeof(ifp)); else count = MIN(len, MLEN); bcopy(cp, mtod(m, caddr_t), count); nocopy: m->m_len = count; if (ifp) { m->m_off -= sizeof(ifp); m->m_len += sizeof(ifp); *mtod(m, struct ifnet **) = ifp; ifp = NULL; } cp += count; len -= count; mp = &m->m_next; } return (top); } /* * tty interface receiver interrupt. */ slinput(c, tp) register int c; register struct tty *tp; { register struct sl_softc *sc; register struct mbuf *m; int s; #ifdef notdef tk_nin++; #endif sc = (struct sl_softc *)mfkd(&tp->t_sc); if (sc == NULL) return; c &= 0xff; if (sc->sc_flags & SC_ESCAPED) { sc->sc_flags &= ~SC_ESCAPED; switch (c) { case TRANS_FRAME_ESCAPE: c = FRAME_ESCAPE; break; case TRANS_FRAME_END: c = FRAME_END; break; default: sc->sc_if.if_ierrors++; sc->sc_mp = sc->sc_buf + sizeof(struct ifnet *); sc->sc_ilen = 0; return; } } else { switch (c) { case FRAME_END: if (sc->sc_ilen == 0) /* ignore */ return; m = sl_btom(sc, sc->sc_ilen, &sc->sc_if); if (m == NULL) { sc->sc_if.if_ierrors++; return; } sc->sc_mp = sc->sc_buf + sizeof(struct ifnet *); sc->sc_ilen = 0; sc->sc_if.if_ipackets++; s = splimp(); if (IF_QFULL(&ipintrq)) { IF_DROP(&ipintrq); sc->sc_if.if_ierrors++; m_freem(m); } else { IF_ENQUEUE(&ipintrq, m); schednetisr(NETISR_IP); } splx(s); return; case FRAME_ESCAPE: sc->sc_flags |= SC_ESCAPED; return; } } if (++sc->sc_ilen > SLMTU) { sc->sc_if.if_ierrors++; sc->sc_mp = sc->sc_buf + sizeof(struct ifnet *); sc->sc_ilen = 0; return; } *sc->sc_mp++ = c; } /* * Process an ioctl request. */ slioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { register struct ifaddr *ifa = (struct ifaddr *)data; int s = splimp(), error = 0; switch (cmd) { case SIOCSIFADDR: if (ifa->ifa_addr.sa_family == AF_INET) ifp->if_flags |= IFF_UP; else error = EAFNOSUPPORT; break; case SIOCSIFDSTADDR: if (ifa->ifa_addr.sa_family != AF_INET) error = EAFNOSUPPORT; break; default: error = EINVAL; } splx(s); return (error); } #endif uf *m2; extern int cfreecount; sc = (struct sl_softc *)mfkd(&tp->t_sc); for (;;) { /* * If there is more in the output queue, just send it now. * We are being called in lieu of ttstart and must do what * it would. */ if ((c_cc = mfkd(&tp->t_outq.c_cc)) > 0) TTSTART(tp); if (c_cc > SLIP_HIWAT) sys/net/netisr.h 444 0 0 3145 4236255036 7074 /* * Copyright (c) 1980, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)netisr.h 7.3 (Berkeley) 12/30/87 */ /* * The networking code runs off software interrupts. * * You can switch into the network by doing splnet() and return by splx(). * The software interrupt level for the network is higher than the software * level for the clock (so you can enter the network in routines called * at timeout time). */ #if defined(vax) || defined(tahoe) #define setsoftnet() mtpr(SIRR, 12) #endif #ifdef pdp11 #define setsoftnet() { extern int knetisr; mtkd(&knetisr, 1); } #endif /* * Each ``pup-level-1'' input queue has a bit in a ``netisr'' status * word which is used to de-multiplex a single software * interrupt used for scheduling the network code to calls * on the lowest level routine of each protocol. */ #define NETISR_RAW 0 /* same as AF_UNSPEC */ #define NETISR_IP 2 /* same as AF_INET */ #define NETISR_IMP 3 /* same as AF_IMPLINK */ #define NETISR_NS 6 /* same as AF_NS */ #define NETISR_CLOCK 15 /* protocol timeout */ #define schednetisr(anisr) { netisr |= 1<<(anisr); setsoftnet(); } #ifdef SUPERVISOR int netisr; /* scheduling bits for network */ #endif END, &tp->t_outq)) { (void) UNPUTC(&tp->t_outq); break; } cp++; len--; } } MFREE(m, m2); m = m2; } if (PUTC(FRAME_END, &tp->t_outq)) { /* * Not enough room. Remove a char to make room * and end the packet normally. * If you get many collisions (more than one or two * a day) you probably do not have enough clists * and you should incsys/h/ 755 0 12 0 6044573436 5023 sys/h/acct.h 444 0 12 2456 5151544303 6165 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)acct.h (2.11BSD) 2/21/92 */ /* * Accounting structures; * these use a comp_t type which is a 3 bits base 8 * exponent, 13 bit fraction ``floating point'' number. * Units are 1/AHZ seconds. */ typedef u_short comp_t; struct acct { char ac_comm[10]; /* Accounting command name */ comp_t ac_utime; /* Accounting user time */ comp_t ac_stime; /* Accounting system time */ comp_t ac_etime; /* Accounting elapsed time */ time_t ac_btime; /* Beginning time */ uid_t ac_uid; /* Accounting user ID */ gid_t ac_gid; /* Accounting group ID */ short ac_mem; /* average memory usage */ comp_t ac_io; /* number of disk IO blocks */ dev_t ac_tty; /* control typewriter */ char ac_flag; /* Accounting flag */ }; #define AFORK 0001 /* has executed fork, but no exec */ #define ASU 0002 /* used super-user privileges */ #define ACOMPAT 0004 /* used compatibility mode */ #define ACORE 0010 /* dumped core */ #define AXSIG 0020 /* killed by a signal */ /* * 1/AHZ is the granularity of the data encoded in the various * comp_t fields. This is not necessarily equal to hz. */ #define AHZ LINEHZ network in routines called * at timeout time). */ #if defined(vax) || defined(tahoe) #define setsoftnet() mtpr(SIRR, 12) #endif #ifdef pdp11 #define setsoftnet() { extern int knetisr; mtkd(&knetisr, 1); } #ensys/h/uio.h 444 0 24 5113 5675641221 6053 /* * Copyright (c) 1982, 1986, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)uio.h 8.5.2 (2.11BSD GTE) 12/20/94 * * Copied from 4.4-Lite and modified for 2.11BSD. Modifications were removal * of prototypes, limits for dynamic allocation of iovec structs and changing * uio_resid to u_short from int. */ #ifndef _SYS_UIO_H_ #define _SYS_UIO_H_ /* * XXX * iov_base should be a void *. */ struct iovec { char *iov_base; /* Base address. */ size_t iov_len; /* Length. */ }; enum uio_rw { UIO_READ, UIO_WRITE }; /* Segment flag values. */ enum uio_seg { UIO_USERSPACE, /* from user data space */ UIO_SYSSPACE, /* from system space */ UIO_USERISPACE /* from user I space */ }; struct uio { struct iovec *uio_iov; int uio_iovcnt; off_t uio_offset; u_short uio_resid; enum uio_seg uio_segflg; enum uio_rw uio_rw; }; #endif /* !_SYS_UIO_H_ */ struct mbuf * sl_btom(sc, len, ifp) struct sl_softc *sc; register int len; struct ifnet *ifp; { register caddr_t cp; register struct mbuf *m, **mp; register unsigned count; struct mbuf *top = NULL; cp = sc->sc_buf + sizeof(struct ifnet *); mp = ⊤ while (len > 0) { MGET(m, M_DONTWAIT, MT_DATA); if ((*mp = m) == NULL) { m_freem(top); return (NULL); } if (ifp) m->m_off += sizeof(ifp); /* * If we havsys/h/buf.h 444 0 12 12673 5743373541 6064 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)buf.h 1.2 (2.11BSD GTE) 1995/04/13 */ /* * The header for buffers in the buffer pool and otherwise used * to describe a block i/o request is given here. * * Each buffer in the pool is usually doubly linked into 2 lists: * hashed into a chain by so it can be located in the cache, * and (usually) on (one of several) queues. These lists are circular and * doubly linked for easy removal. * * There are currently two queues for buffers: * one for buffers containing ``useful'' information (the cache) * one for buffers containing ``non-useful'' information * (and empty buffers, pushed onto the front) * These queues contain the buffers which are available for * reallocation, are kept in lru order. When not on one of these queues, * the buffers are ``checked out'' to drivers which use the available list * pointers to keep track of them in their i/o active queues. */ /* * Bufhd structures used at the head of the hashed buffer queues. * We only need three words for these, so this abbreviated * definition saves some space. */ struct bufhd { short b_flags; /* see defines below */ struct buf *b_forw, *b_back; /* fwd/bkwd pointer in chain */ }; struct buf { short b_flags; /* see defines below */ struct buf *b_forw, *b_back; /* hash chain (2 way street) */ struct buf *av_forw, *av_back; /* position on free list if not BUSY */ #define b_actf av_forw /* alternate names for driver queue */ #define b_actl av_back /* head - isn't history wonderful */ u_short b_bcount; /* transfer count */ #define b_active b_bcount /* driver queue head: drive active */ char b_error; /* returned after I/O */ char b_xmem; /* high order core address */ dev_t b_dev; /* major+minor device name */ union { caddr_t b_addr; /* low order core address */ } b_un; daddr_t b_blkno; /* block # on device */ u_short b_resid; /* words not transferred after error */ #define b_cylin b_resid /* disksort */ #define b_errcnt b_resid /* while i/o in progress: # retries */ }; /* * We never use BQ_LOCKED or BQ_EMPTY, but if you want the 4.X block I/O * code to drop in, you have to have BQ_AGE and BQ_LRU *after* the first * queue, and it only costs 6 bytes of data space. */ #define BQUEUES 3 /* number of free buffer queues */ #define BQ_LOCKED 0 /* super-blocks &c */ #define BQ_LRU 1 /* lru, useful buffers */ #define BQ_AGE 2 /* rubbish */ #define BQ_EMPTY 3 /* buffer headers with no memory */ #define bawrite(bp) {(bp)->b_flags |= B_ASYNC; bwrite(bp);} #define bfree(bp) (bp)->b_bcount = 0 #define bftopaddr(bp) ((u_int)(bp)->b_un.b_addr >> 6 | (bp)->b_xmem << 10) #if defined(KERNEL) && !defined(SUPERVISOR) #define BUFHSZ 16 /* must be power of 2 */ #define BUFHASH(dev,blkno) ((struct buf *)&bufhash[((long)(dev) + blkno) & ((long)(BUFHSZ - 1))]) extern struct buf buf[]; /* the buffer pool itself */ extern int nbuf; /* number of buffer headers */ extern struct bufhd bufhash[]; /* heads of hash lists */ extern struct buf bfreelist[]; /* heads of available lists */ struct buf *alloc(); struct buf *getblk(); struct buf *geteblk(); struct buf *getnewbuf(); struct buf *bread(); struct buf *breada(); #endif /* * These flags are kept in b_flags. */ #define B_WRITE 0x00000 /* non-read pseudo-flag */ #define B_READ 0x00001 /* read when I/O occurs */ #define B_DONE 0x00002 /* transaction finished */ #define B_ERROR 0x00004 /* transaction aborted */ #define B_BUSY 0x00008 /* not on av_forw/back list */ #define B_PHYS 0x00010 /* physical IO */ #define B_MAP 0x00020 /* alloc UNIBUS */ #define B_WANTED 0x00040 /* issue wakeup when BUSY goes off */ #define B_AGE 0x00080 /* delayed write for correct aging */ #define B_ASYNC 0x00100 /* don't wait for I/O completion */ #define B_DELWRI 0x00200 /* write at exit of avail list */ #define B_TAPE 0x00400 /* this is a magtape (no bdwrite) */ #define B_INVAL 0x00800 /* does not contain valid info */ #define B_BAD 0x01000 /* bad block revectoring in progress */ #define B_LOCKED 0x02000 /* locked in core (not reusable) */ #define B_UBAREMAP 0x04000 /* addr UNIBUS virtual, not physical */ #define B_RAMREMAP 0x08000 /* remapped into ramdisk */ /* flag arguments to physio() and chkphys() */ #define WORD 2 /* doing I/O by word */ #define BYTE 1 /* doing I/O by byte */ /* * Insq/Remq for the buffer hash lists. */ #define bremhash(bp) { \ (bp)->b_back->b_forw = (bp)->b_forw; \ (bp)->b_forw->b_back = (bp)->b_back; \ } #define binshash(bp, dp) { \ (bp)->b_forw = (dp)->b_forw; \ (bp)->b_back = (dp); \ (dp)->b_forw->b_back = (bp); \ (dp)->b_forw = (bp); \ } /* * Insq/Remq for the buffer free lists. */ #define bremfree(bp) { \ (bp)->av_back->av_forw = (bp)->av_forw; \ (bp)->av_forw->av_back = (bp)->av_back; \ } #define binsheadfree(bp, dp) { \ (dp)->av_forw->av_back = (bp); \ (bp)->av_forw = (dp)->av_forw; \ (dp)->av_forw = (bp); \ (bp)->av_back = (dp); \ } #define binstailfree(bp, dp) { \ (dp)->av_back->av_forw = (bp); \ (bp)->av_back = (dp)->av_back; \ (dp)->av_back = (bp); \ (bp)->av_forw = (dp); \ } /* * Take a buffer off the free list it's on and * mark it as being use (B_BUSY) by a device. */ #define notavail(bp) { \ register int x = splbio(); \ bremfree(bp); \ (bp)->b_flags |= B_BUSY; \ splx(x); \ } #define iodone biodone #define iowait biowait hain by so it can be located in the cache, * and (usuallsys/h/callout.h 444 0 12 2056 4236254472 6722 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)callout.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * The callout structure is for * a routine arranging * to be called by the clock interrupt * (clock.c) with a specified argument, * in a specified amount of time. * Used, for example, to time tab * delays on typewriters. * * The c_time field is stored in terms of ticks. Therefore, no callout * may be scheduled past around 8 minutes on a 60 HZ machine. This is * good as it avoids long operations on clock ticks. If you are ever * forced to use a long, you might as well start doing the real-time * timer as a timeout like 4.3BSD. */ struct callout { int c_time; /* incremental time */ caddr_t c_arg; /* argument to routine */ int (*c_func)(); /* routine */ struct callout *c_next; }; #if defined(KERNEL) && !defined(SUPERVISOR) struct callout *callfree, callout[], calltodo; int ncallout; #endif in their i/o active queues. */ /* * Bufhd structures used at the head of the hashed buffer queues. * We only need three words for these, so this abbreviated * definition saves some space. */ struct bufhd { short b_flags; /* see defines below */ struct buf *b_forw, *b_back; /* fwd/bkwd pointer in chain */ }; struct buf { short b_flags; /* see defines below */ struct buf *b_forw, *b_back; /* hash chain (2 way street) */ struct buf *av_forw, *av_back;sys/h/conf.h 444 0 12 2461 5316234737 6206 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)conf.h 1.3 (2.11BSD Berkeley) 12/23/92 */ /* * Declaration of block device * switch. Each entry (row) is * the only link between the * main unix code and the driver. * The initialization of the * device switches is in the * file conf.c. */ struct bdevsw { int (*d_open)(); int (*d_close)(); int (*d_strategy)(); int (*d_root)(); /* XXX root attach routine */ daddr_t (*d_psize)(); int d_flags; }; #if defined(KERNEL) && !defined(SUPERVISOR) extern struct bdevsw bdevsw[]; #endif /* * Character device switch. */ struct cdevsw { int (*d_open)(); int (*d_close)(); int (*d_read)(); int (*d_write)(); int (*d_ioctl)(); int (*d_stop)(); struct tty *d_ttys; int (*d_select)(); int (*d_strategy)(); }; #if defined(KERNEL) && !defined(SUPERVISOR) extern struct cdevsw cdevsw[]; #endif /* * tty line control switch. */ struct linesw { int (*l_open)(); int (*l_close)(); int (*l_read)(); int (*l_write)(); int (*l_ioctl)(); int (*l_rint)(); int (*l_rend)(); int (*l_meta)(); int (*l_start)(); int (*l_modem)(); }; #if defined(KERNEL) && !defined(SUPERVISOR) extern struct linesw linesw[]; #endif ct buf *b_forw, *b_back; /* fwd/bkwd pointer in chain */ }; struct buf { short b_flags; /* see defines below */ struct buf *b_forw, *b_back; /* hash chain (2 way street) */ struct buf *av_forw, *av_back;sys/h/tty.h 444 0 24 10475 5671511422 6121 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)tty.h 7.1.1 (2.11BSD GTE) 12/7/94 */ #ifdef KERNEL #include "ttychars.h" #include "ttydev.h" #else #include #include #endif /* * A clist structure is the head of a linked list queue * of characters. The characters are stored in blocks * containing a link and CBSIZE (param.h) characters. * The routines in tty_subr.c manipulate these structures. */ struct clist { int c_cc; /* character count */ char *c_cf; /* pointer to first char */ char *c_cl; /* pointer to last char */ }; /* * Per-tty structure. * * Should be split in two, into device and tty drivers. * Glue could be masks of what to echo and circular buffer * (low, high, timeout). */ struct tty { union { struct { struct clist T_rawq; struct clist T_canq; } t_t; #define t_rawq t_nu.t_t.T_rawq /* raw characters or partial line */ #define t_canq t_nu.t_t.T_canq /* raw characters or partial line */ struct { struct buf *T_bufp; char *T_cp; int T_inbuf; int T_rec; } t_n; #define t_bufp t_nu.t_n.T_bufp /* buffer allocated to protocol */ #define t_cp t_nu.t_n.T_cp /* pointer into the ripped off buffer */ #define t_inbuf t_nu.t_n.T_inbuf /* number chars in the buffer */ #define t_rec t_nu.t_n.T_rec /* have a complete record */ } t_nu; struct clist t_outq; /* device */ int (*t_oproc)(); /* device */ struct proc *t_rsel; /* tty */ struct proc *t_wsel; caddr_t T_LINEP; /* ### */ caddr_t t_addr; /* ??? */ dev_t t_dev; /* device */ long t_flags; /* some of both */ long t_state; /* some of both */ short t_pgrp; /* tty */ char t_delct; /* tty */ char t_line; /* glue */ char t_col; /* tty */ char t_ispeed, t_ospeed; /* device */ char t_rocount, t_rocol; /* tty */ struct ttychars t_chars; /* tty */ struct winsize t_winsize; /* window size */ /* be careful of tchars & co. */ #define t_erase t_chars.tc_erase #define t_kill t_chars.tc_kill #define t_intrc t_chars.tc_intrc #define t_quitc t_chars.tc_quitc #define t_startc t_chars.tc_startc #define t_stopc t_chars.tc_stopc #define t_eofc t_chars.tc_eofc #define t_brkc t_chars.tc_brkc #define t_suspc t_chars.tc_suspc #define t_dsuspc t_chars.tc_dsuspc #define t_rprntc t_chars.tc_rprntc #define t_flushc t_chars.tc_flushc #define t_werasc t_chars.tc_werasc #define t_lnextc t_chars.tc_lnextc }; #define TTIPRI 28 #define TTOPRI 29 /* limits */ #define NSPEEDS 16 #define TTMASK 15 #define OBUFSIZ 100 #define TTYHOG 255 #if defined(KERNEL) && !defined(SUPERVISOR) short tthiwat[NSPEEDS], ttlowat[NSPEEDS]; #define TTHIWAT(tp) tthiwat[(tp)->t_ospeed&TTMASK] #define TTLOWAT(tp) ttlowat[(tp)->t_ospeed&TTMASK] extern struct ttychars ttydefaults; #endif /* internal state bits */ #define TS_TIMEOUT 0x000001L /* delay timeout in progress */ #define TS_WOPEN 0x000002L /* waiting for open to complete */ #define TS_ISOPEN 0x000004L /* device is open */ #define TS_FLUSH 0x000008L /* outq has been flushed during DMA */ #define TS_CARR_ON 0x000010L /* software copy of carrier-present */ #define TS_BUSY 0x000020L /* output in progress */ #define TS_ASLEEP 0x000040L /* wakeup when output done */ #define TS_XCLUDE 0x000080L /* exclusive-use flag against open */ #define TS_TTSTOP 0x000100L /* output stopped by ctl-s */ #define TS_HUPCLS 0x000200L /* hang up upon last close */ #define TS_TBLOCK 0x000400L /* tandem queue blocked */ #define TS_RCOLL 0x000800L /* collision in read select */ #define TS_WCOLL 0x001000L /* collision in write select */ #define TS_ASYNC 0x004000L /* tty in async i/o mode */ /* state for intra-line fancy editing work */ #define TS_BKSL 0x010000L /* state for lowercase \ work */ #define TS_QUOT 0x020000L /* last character input was \ */ #define TS_ERASE 0x040000L /* within a \.../ for PRTRUB */ #define TS_LNCH 0x080000L /* next character is literal */ #define TS_TYPEN 0x100000L /* retyping suspended input (PENDIN) */ #define TS_CNTTB 0x200000L /* counting tab width; leave FLUSHO alone */ #define TS_LOCAL (TS_BKSL|TS_QUOT|TS_ERASE|TS_LNCH|TS_TYPEN|TS_CNTTB) /* define partab character types */ #define ORDINARY 0 #define CONTROL 1 #define BACKSPACE 2 #define NEWLINE 3 #define TAB 4 #define VTAB 5 #define RETURN 6 g arguments to physio() and chkphys() */ #define WORD 2 /* doing I/O by word */ #define BYTE 1 /* doing I/O by byte */ /* * Insq/Remq for the buffer hash lists. */ #define bremhash(bp) { \sys/h/dkbad.h 444 0 12 3716 4113433472 6321 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dkbad.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * Definitions needed to perform bad sector * revectoring ala DEC STD 144. * * The bad sector information is located in the * first 5 even numbered sectors of the last * track of the disk pack. There are five * identical copies of the information, described * by the dkbad structure. * * Replacement sectors are allocated starting with * the first sector before the bad sector information * and working backwards towards the beginning of * the disk. A maximum of 126 bad sectors are supported. * The position of the bad sector in the bad sector table * determines which replacement sector it corresponds to. * * The bad sector information and replacement sectors * are conventionally only accessible through the * 'c' file system partition of the disk. If that * partition is used for a file system, the user is * responsible for making sure that it does not overlap * the bad sector information or any replacement sector.s */ /* * The 2.10BSD system defines MAXBAD as 32, not 126, although there * should be no problem with increasing that value. It's your basic * space tradeoff. Also, 2.10 drivers tend to have the bad sector * information available through the 'h' file system partition, although * there are exceptions to this rule. Note, this value is also present * in the bad144 program. */ #define MAXBAD 32 /* Maximum bad sectors supported */ struct dkbad { long bt_csn; /* cartridge serial number */ u_short bt_mbz; /* unused; should be 0 */ u_short bt_flag; /* -1 => alignment cartridge */ struct bt_bad { u_short bt_cyl; /* cylinder number of bad sector */ u_short bt_trksec; /* track and sector number */ } bt_bad[MAXBAD]; }; #define ECC 0 #define SSE 1 #define BSE 2 #define CONT 3 insize t_winsize; /* window size */ /* be careful sys/h/localopts.h 664 0 12 516 5720304236 7233 /* * This file is generated by the configuration script sys/conf/config. * * It contains a list the kernel options not prepended to the Makefile * as -Dxxxx commands to the compiler. MAXMEM was moved to param.h leaving * only LINEHZ and EXTERNALITIMES to be placed in localopts.h */ #define LINEHZ 60 #define EXTERNALITIMES 1 param.h.proc.h. protosw.hreboot.h resource.hcsignal.hhsocket.hhstat.hhhsyslog.hhsystm.hhtext.hhsys/h/clist.h 444 0 12 1275 4236254471 6376 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)clist.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * Raw structures for the character list routines. */ struct cblock { struct cblock *c_next; char c_info[CBSIZE]; }; #if defined(KERNEL) && !defined(SUPERVISOR) #ifdef UCB_CLIST extern struct cblock *cfree; extern memaddr clststrt; extern u_int clstdesc; /* PDR for clist segment when mapped */ /* virt. addr. of clists (0120000 - 0140000) */ #else extern struct cblock cfree[]; #endif int nclist; struct cblock *cfreelist; int cfreecount; #endif e disk. A maximum of 126 bad sectors are supported. * The position of the bad sector in the bad sector table * determines which replacement sector it corresponds to. * * The bad sector information and replacement sectors * are conventionally only accessible through the * 'c' file system partition of the disk. If tsys/h/file.h 444 0 12 3107 5710101701 6154 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)file.h 1.3 (2.11BSD GTE) 1/19/95 */ #include #ifndef _SYS_FILE_H_ #define _SYS_FILE_H_ /* * Descriptor table entry. * One for each kernel object. */ struct file { int f_flag; /* see below */ char f_type; /* descriptor type */ u_char f_count; /* reference count */ short f_msgcount; /* references from message queue */ union { caddr_t f_Data; struct socket *f_Socket; } f_un; off_t f_offset; }; #ifdef KERNEL struct fileops { int (*fo_rw)(); int (*fo_ioctl)(); int (*fo_select)(); int (*fo_close)(); }; #define f_data f_un.f_Data #define f_socket f_un.f_Socket #ifndef SUPERVISOR extern struct file file[], *fileNFILE; int nfile; #endif struct file *getf(); struct file *falloc(); #endif /* * Access call. */ #define F_OK 0 /* does file exist */ #define X_OK 1 /* is it executable by caller */ #define W_OK 2 /* writable by caller */ #define R_OK 4 /* readable by caller */ /* * Lseek call. */ #define L_SET 0 /* absolute offset */ #define L_INCR 1 /* relative to current offset */ #define L_XTND 2 /* relative to end of file */ #ifdef KERNEL #define GETF(fp, fd) { \ if ((unsigned)(fd) >= NOFILE || ((fp) = u.u_ofile[fd]) == NULL) { \ u.u_error = EBADF; \ return; \ } \ } #define DTYPE_INODE 1 /* file */ #define DTYPE_SOCKET 2 /* communications endpoint */ #define DTYPE_PIPE 3 /* I don't want to hear it, okay? */ #endif #endif /* _SYS_FILE_H_ */ imum bad sectors supported */ struct dkbad { long bt_csn; /* cartridge serial number */ u_short bt_mbz; /* unused; should be 0 */ u_short bt_flag; /* -1 => alignment cartridge */ struct bt_bad { u_short bt_cyl; /* cylinder number of bad sector */ u_short bt_trksec; /* track and sector number */ } bt_bad[MAXBAD]; }; #define ECC 0 #define SSE 1 #define BSE 2 #define CONT 3 insize t_winsize; /* window size */ /* be careful sys/h/fs.h 444 0 12 10354 5665736650 5721 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)fs.h 1.2 (2.11BSD GTE) 11/26/94 */ /* * The root inode is the root of the file system. * Inode 0 can't be used for normal purposes and * historically bad blocks were linked to inode 1, * thus the root inode is 2. (inode 1 is no longer used for * this purpose, however numerous dump tapes make this * assumption, so we are stuck with it) * The lost+found directory is given the next available * inode when it is created by ``mkfs''. */ #define BBSIZE DEV_BSIZE #define SBSIZE DEV_BSIZE #define BBLOCK ((daddr_t)(0)) #define SBLOCK ((daddr_t)(BBLOCK + BBSIZE / DEV_BSIZE)) #define SUPERB ((daddr_t)1) /* block number of the super block */ #define ROOTINO ((ino_t)2) /* i number of all roots */ #define LOSTFOUNDINO (ROOTINO + 1) #define NICINOD 100 /* number of superblock inodes */ #define NICFREE 50 /* number of superblock free blocks */ /* * The path name on which the file system is mounted is maintained * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in * the super block for this name. */ #define MAXMNTLEN 12 /* * Super block for a file system. */ struct fs { u_short fs_isize; /* first block after i-list */ daddr_t fs_fsize; /* size in blocks of entire volume */ short fs_nfree; /* number of addresses in fs_free */ daddr_t fs_free[NICFREE]; /* free block list */ short fs_ninode; /* number of inodes in fs_inode */ ino_t fs_inode[NICINOD]; /* free inode list */ char fs_flock; /* lock during free list manipulation */ char fs_ilock; /* lock during i-list manipulation */ char fs_fmod; /* super block modified flag */ char fs_ronly; /* mounted read-only flag */ time_t fs_time; /* last super block update */ daddr_t fs_tfree; /* total free blocks */ ino_t fs_tinode; /* total free inodes */ short fs_step; /* optimal step in free list pattern */ short fs_cyl; /* number of blocks per pattern */ char fs_fsmnt[MAXMNTLEN]; /* ordinary file mounted on */ ino_t fs_lasti; /* start place for circular search */ ino_t fs_nbehind; /* est # free inodes before s_lasti */ u_short fs_flags; /* mount time flags */ /* actually longer */ }; struct fblk { short df_nfree; /* number of addresses in df_free */ daddr_t df_free[NICFREE]; /* free block list */ }; /* * Turn file system block numbers into disk block addresses. * This maps file system blocks to device size blocks. */ #define fsbtodb(b) ((daddr_t)((daddr_t)(b)<<1)) #define dbtofsb(b) ((daddr_t)((daddr_t)(b)>>1)) /* * Macros for handling inode numbers: * inode number to file system block offset. * inode number to file system block address. */ #define itoo(x) ((int)(((x) + 2 * INOPB - 1) % INOPB)) #define itod(x) ((daddr_t)((((u_int)(x) + 2 * INOPB - 1) / INOPB))) /* * The following macros optimize certain frequently calculated * quantities by using shifts and masks in place of divisions * modulos and multiplications. */ #define blkoff(loc) /* calculates (loc % fs->fs_bsize) */ \ ((loc) & DEV_BMASK) #define lblkno(loc) /* calculates (loc / fs->fs_bsize) */ \ ((loc) >> DEV_BSHIFT) /* * Determine the number of available blocks given a * percentage to hold in reserve */ #define freespace(fs, percentreserved) \ ((fs)->fs_tfree - ((fs)->fs_fsize - \ (fs)->fs_isize) * (percentreserved) / 100) /* * INOPB is the number of inodes in a secondary storage block. */ #define INOPB 16 /* MAXBSIZE / sizeof(dinode) */ /* * NINDIR is the number of indirects in a file system block. */ #define NINDIR (DEV_BSIZE / sizeof(daddr_t)) #define NSHIFT 8 /* log2(NINDIR) */ #define NMASK 0377L /* NINDIR - 1 */ /* * We continue to implement pipes within the file system because it would * be pretty tough for us to handle 10 4K blocked pipes on a 1M machine. * * 4K is the allowable buffering per write on a pipe. This is also roughly * the max size of the file created to implement the pipe. If this size is * bigger than 4096, pipes will be implemented with large files, which is * probably not good. */ #define MAXPIPSIZ (NDADDR * MAXBSIZE) #if defined(KERNEL) && !defined(SUPERVISOR) struct fs *getfs(); struct fs *mountfs(); #endif modified flag */ char fs_ronly; /* mounted read-only flag */ time_t fs_time; /* last super block update */ daddr_t fs_tfree; /* total free blocks */ ino_t fs_tinode; /* total free inodes */ short fs_step; /* optimal step in free list pattern */ short fs_cyl; /* nsys/h/errno.h 444 0 12 10722 5666014112 6414 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)errno.h 7.1.1 (2.11BSD GTE) 11/26/94 */ /* * Error codes */ #define EPERM 1 /* Not owner */ #define ENOENT 2 /* No such file or directory */ #define ESRCH 3 /* No such process */ #define EINTR 4 /* Interrupted system call */ #define EIO 5 /* I/O error */ #define ENXIO 6 /* No such device or address */ #define E2BIG 7 /* Arg list too long */ #define ENOEXEC 8 /* Exec format error */ #define EBADF 9 /* Bad file number */ #define ECHILD 10 /* No children */ #define EAGAIN 11 /* No more processes */ #define ENOMEM 12 /* Not enough core */ #define EACCES 13 /* Permission denied */ #define EFAULT 14 /* Bad address */ #define ENOTBLK 15 /* Block device required */ #define EBUSY 16 /* Mount device busy */ #define EEXIST 17 /* File exists */ #define EXDEV 18 /* Cross-device link */ #define ENODEV 19 /* No such device */ #define ENOTDIR 20 /* Not a directory*/ #define EISDIR 21 /* Is a directory */ #define EINVAL 22 /* Invalid argument */ #define ENFILE 23 /* File table overflow */ #define EMFILE 24 /* Too many open files */ #define ENOTTY 25 /* Not a typewriter */ #define ETXTBSY 26 /* Text file busy */ #define EFBIG 27 /* File too large */ #define ENOSPC 28 /* No space left on device */ #define ESPIPE 29 /* Illegal seek */ #define EROFS 30 /* Read-only file system */ #define EMLINK 31 /* Too many links */ #define EPIPE 32 /* Broken pipe */ /* math software */ #define EDOM 33 /* Argument too large */ #define ERANGE 34 /* Result too large */ /* non-blocking and interrupt i/o */ #define EWOULDBLOCK 35 /* Operation would block */ #define EDEADLK EWOULDBLOCK /* ditto */ #define EINPROGRESS 36 /* Operation now in progress */ #define EALREADY 37 /* Operation already in progress */ /* ipc/network software */ /* argument errors */ #define ENOTSOCK 38 /* Socket operation on non-socket */ #define EDESTADDRREQ 39 /* Destination address required */ #define EMSGSIZE 40 /* Message too long */ #define EPROTOTYPE 41 /* Protocol wrong type for socket */ #define ENOPROTOOPT 42 /* Protocol not available */ #define EPROTONOSUPPORT 43 /* Protocol not supported */ #define ESOCKTNOSUPPORT 44 /* Socket type not supported */ #define EOPNOTSUPP 45 /* Operation not supported on socket */ #define EPFNOSUPPORT 46 /* Protocol family not supported */ #define EAFNOSUPPORT 47 /* Address family not supported by protocol family */ #define EADDRINUSE 48 /* Address already in use */ #define EADDRNOTAVAIL 49 /* Can't assign requested address */ /* operational errors */ #define ENETDOWN 50 /* Network is down */ #define ENETUNREACH 51 /* Network is unreachable */ #define ENETRESET 52 /* Network dropped connection on reset */ #define ECONNABORTED 53 /* Software caused connection abort */ #define ECONNRESET 54 /* Connection reset by peer */ #define ENOBUFS 55 /* No buffer space available */ #define EISCONN 56 /* Socket is already connected */ #define ENOTCONN 57 /* Socket is not connected */ #define ESHUTDOWN 58 /* Can't send after socket shutdown */ #define ETOOMANYREFS 59 /* Too many references: can't splice */ #define ETIMEDOUT 60 /* Connection timed out */ #define ECONNREFUSED 61 /* Connection refused */ /* */ #define ELOOP 62 /* Too many levels of symbolic links */ #define ENAMETOOLONG 63 /* File name too long */ /* should be rearranged */ #define EHOSTDOWN 64 /* Host is down */ #define EHOSTUNREACH 65 /* No route to host */ #define ENOTEMPTY 66 /* Directory not empty */ /* quotas & mush */ #define EPROCLIM 67 /* Too many processes */ #define EUSERS 68 /* Too many users */ #define EDQUOT 69 /* Disc quota exceeded */ /* Network File System */ #define ESTALE 70 /* Stale NFS file handle */ #define EREMOTE 71 /* Too many levels of remote in path */ #define EBADRPC 72 /* RPC struct is bad */ #define ERPCMISMATCH 73 /* RPC version wrong */ #define EPROGUNAVAIL 74 /* RPC prog. not avail */ #define EPROGMISMATCH 75 /* Program version wrong */ #define EPROCUNAVAIL 76 /* Bad procedure for program */ #define ENOLCK 77 /* No locks available */ #define ENOSYS 78 /* Function not implemented */ #define EFTYPE 79 /* Inappropriate file type or format */ #define EAUTH 80 /* Authentication error */ #define ENEEDAUTH 81 /* Need authenticator */ #define ELAST 81 /* Must be equal largest errno */ uffer hash lists. */ #define bremhash(bp) { \sys/h/ttydev.h 444 0 12 1466 4053130002 6555 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ttydev.h 7.1 (Berkeley) 6/4/86 */ /* * Terminal definitions related to underlying hardware. */ #ifndef _TTYDEV_ #define _TTYDEV_ /* * Speeds */ #define B0 0 #define B50 1 #define B75 2 #define B110 3 #define B134 4 #define B150 5 #define B200 6 #define B300 7 #define B600 8 #define B1200 9 #define B1800 10 #define B2400 11 #define B4800 12 #define B9600 13 #define EXTA 14 #define EXTB 15 #ifdef KERNEL /* * Hardware bits. * SHOULD NOT BE HERE. */ #define DONE 0200 #define IENABLE 0100 /* * Modem control commands. */ #define DMSET 0 #define DMBIS 1 #define DMBIC 2 #define DMGET 3 #endif #endif fine EFAULT 14 /* Bad address */ #define ENOTBLK 15 /* Block device required */ #define EBUSY 16 /* Mount device busy */ #define EEXIST 17 /* File exists */ #define EXDEV 18 /* Cross-device lisys/h/dir.h 444 0 12 6366 5656635067 6057 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dir.h 1.2 (2.11BSD GTE) 11/4/94 */ #ifndef _DIR_ #define _DIR_ #ifndef MAXNAMLEN #define MAXNAMLEN 63 #endif #define DIRBLKSIZ 512 /* * inode numbers are ino_t rather than u_long now. before, when v7direct * was used for the kernel, inode numbers were u_short/ino_t anyways, and since * everything had to be recompiled when the fs structure was changed it seemed * like a good idea to change the "real direct structure". SMS */ struct direct { ino_t d_ino; /* inode number of entry */ u_short d_reclen; /* length of this record */ u_short d_namlen; /* length of string in d_name */ char d_name[MAXNAMLEN+1]; /* name must be no longer than this */ }; /* * A directory consists of some number of blocks of DIRBLKSIZ * bytes, where DIRBLKSIZ is chosen such that it can be transferred * to disk in a single atomic operation (e.g. 512 bytes on most machines). * * Each DIRBLKSIZ byte block contains some number of directory entry * structures, which are of variable length. Each directory entry has * a struct direct at the front of it, containing its inode number, * the length of the entry, and the length of the name contained in * the entry. These are followed by the name padded to a 4 byte boundary * with null bytes. All names are guaranteed null terminated. * The maximum length of a name in a directory is MAXNAMLEN. * * The macro DIRSIZ(dp) gives the amount of space required to represent * a directory entry. Free space in a directory is represented by * entries which have dp->d_reclen > DIRSIZ(dp). All DIRBLKSIZ bytes * in a directory block are claimed by the directory entries. This * usually results in the last entry in a directory having a large * dp->d_reclen. When entries are deleted from a directory, the * space is returned to the previous entry in the same directory * block by increasing its dp->d_reclen. If the first entry of * a directory block is free, then its dp->d_ino is set to 0. * Entries other than the first in a directory do not normally have * dp->d_ino set to 0. */ #undef DIRSIZ #define DIRSIZ(dp) \ ((((sizeof (struct direct) - (MAXNAMLEN+1)) + (dp)->d_namlen+1) + 3) &~ 3) /* * Definitions for library routines operating on directories. */ typedef struct _dirdesc { int dd_fd; long dd_loc; long dd_size; char dd_buf[DIRBLKSIZ]; struct direct dd_cur; } DIR; #ifndef NULL #define NULL 0 #endif #ifndef KERNEL extern DIR *opendir(); extern struct direct *readdir(); extern long telldir(); extern void seekdir(); #define rewinddir(dirp) seekdir((dirp), (long)0) #define dirfd(dirp) ((dirp)->dd_fd) extern void closedir(); #endif KERNEL /* * Template for manipulating directories. * Should use struct direct's, but the name field * is MAXNAMLEN - 1, and this just won't do. */ #define dotdot_ino dtdt_ino #define dotdot_reclen dtdt_rec #define dotdot_name dtdt_name struct dirtemplate { ino_t dot_ino; u_short dot_reclen; u_short dot_namlen; char dot_name[2]; /* must be multiple of 4 */ ino_t dotdot_ino; u_short dotdot_reclen; u_short dotdot_namlen; char dotdot_name[6]; /* ditto */ }; #endif _DIR_ vailable */ #define EPROTONOSUPPORT 43 /* Protocol not supported */ #define ESOCKTNOSUPPORT 44 /* Socket type not supported */ #define EOPNOTSUPP 45 /* Operation not supported on socket */ #define EPFNOSUPPORT 46 /* Protocol family not supported */ #define EAFNOsys/h/ioctl.h 444 0 12 26610 5757722335 6422 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ioctl.h 1.3 (2.11BSD GTE) 1995/05/21 */ /* * Ioctl definitions */ #ifndef _IOCTL_ #define _IOCTL_ #ifdef KERNEL #include "ttychars.h" #include "ttydev.h" #else #include #include #endif struct tchars { char t_intrc; /* interrupt */ char t_quitc; /* quit */ char t_startc; /* start output */ char t_stopc; /* stop output */ char t_eofc; /* end-of-file */ char t_brkc; /* input delimiter (like nl) */ }; struct ltchars { char t_suspc; /* stop process signal */ char t_dsuspc; /* delayed stop process signal */ char t_rprntc; /* reprint line */ char t_flushc; /* flush output (toggles) */ char t_werasc; /* word erase */ char t_lnextc; /* literal next character */ }; /* * Structure for TIOCGETP and TIOCSETP ioctls. */ #ifndef _SGTTYB_ #define _SGTTYB_ struct sgttyb { char sg_ispeed; /* input speed */ char sg_ospeed; /* output speed */ char sg_erase; /* erase character */ char sg_kill; /* kill character */ short sg_flags; /* mode flags */ }; #endif /* * Window/terminal size structure. * This information is stored by the kernel * in order to provide a consistent interface, * but is not used by the kernel. * * Type must be "unsigned short" so that types.h not required. */ struct winsize { unsigned short ws_row; /* rows, in characters */ unsigned short ws_col; /* columns, in characters */ unsigned short ws_xpixel; /* horizontal size, pixels */ unsigned short ws_ypixel; /* vertical size, pixels */ }; /* * Pun for SUN. */ struct ttysize { unsigned short ts_lines; unsigned short ts_cols; unsigned short ts_xxx; unsigned short ts_yyy; }; #define TIOCGSIZE TIOCGWINSZ #define TIOCSSIZE TIOCSWINSZ #ifndef _IO /* * Ioctl's have the command encoded in the lower word, * and the size of any in or out parameters in the upper * word. The high 2 bits of the upper word are used * to encode the in/out status of the parameter; for now * we restrict parameters to at most 256 bytes (disklabels are 216 bytes). */ #define IOCPARM_MASK 0xff /* parameters must be < 256 bytes */ #define IOC_VOID 0x20000000 /* no parameters */ #define IOC_OUT 0x40000000 /* copy out parameters */ #define IOC_IN 0x80000000 /* copy in parameters */ #define IOC_INOUT (IOC_IN|IOC_OUT) /* the 0x20000000 is so we can distinguish new ioctl's from old */ #ifdef KERNEL #define _IO(x,y) (('x'<<8)|y) #define _IOR(x,y,t) (('x'<<8)|y) #define _IOW(x,y,t) (('x'<<8)|y) /* this should be _IORW, but stdio got there first */ #define _IOWR(x,y,t) (('x'<<8)|y) #else #define _IO(x,y) (IOC_VOID|('x'<<8)|y) #define _IOR(x,y,t) (IOC_OUT|((long)(sizeof(t)&IOCPARM_MASK)<<16)|('x'<<8)|y) #define _IOW(x,y,t) (IOC_IN|((long)(sizeof(t)&IOCPARM_MASK)<<16)|('x'<<8)|y) /* this should be _IORW, but stdio got there first */ #define _IOWR(x,y,t) (IOC_INOUT|((long)(sizeof(t)&IOCPARM_MASK)<<16)|('x'<<8)|y) #endif #endif /* * tty ioctl commands */ #define TIOCGETD _IOR(t, 0, int) /* get line discipline */ #define TIOCSETD _IOW(t, 1, int) /* set line discipline */ #define TIOCHPCL _IO(t, 2) /* hang up on last close */ #define TIOCMODG _IOR(t, 3, int) /* get modem control state */ #define TIOCMODS _IOW(t, 4, int) /* set modem control state */ #define TIOCM_LE 0001 /* line enable */ #define TIOCM_DTR 0002 /* data terminal ready */ #define TIOCM_RTS 0004 /* request to send */ #define TIOCM_ST 0010 /* secondary transmit */ #define TIOCM_SR 0020 /* secondary receive */ #define TIOCM_CTS 0040 /* clear to send */ #define TIOCM_CAR 0100 /* carrier detect */ #define TIOCM_CD TIOCM_CAR #define TIOCM_RNG 0200 /* ring */ #define TIOCM_RI TIOCM_RNG #define TIOCM_DSR 0400 /* data set ready */ #define TIOCGETP _IOR(t, 8,struct sgttyb)/* get parameters -- gtty */ #define TIOCSETP _IOW(t, 9,struct sgttyb)/* set parameters -- stty */ #define TIOCSETN _IOW(t,10,struct sgttyb)/* as above, but no flushtty */ #define TIOCEXCL _IO(t, 13) /* set exclusive use of tty */ #define TIOCNXCL _IO(t, 14) /* reset exclusive use of tty */ #define TIOCFLUSH _IOW(t, 16, int) /* flush buffers */ #define TIOCSETC _IOW(t,17,struct tchars)/* set special characters */ #define TIOCGETC _IOR(t,18,struct tchars)/* get special characters */ #define TANDEM 0x00000001 /* send stopc on out q full */ #define CBREAK 0x00000002 /* half-cooked mode */ #define LCASE 0x00000004 /* (obsolete) - place holder */ #define ECHO 0x00000008 /* echo input */ #define CRMOD 0x00000010 /* map \r to \r\n on output */ #define RAW 0x00000020 /* no i/o processing */ #define ODDP 0x00000040 /* get/send odd parity */ #define EVENP 0x00000080 /* get/send even parity */ #define ANYP 0x000000c0 /* get any parity/send none */ #define NLDELAY 0x00000300 /* \n delay */ #define NL0 0x00000000 #define NL1 0x00000100 /* tty 37 */ #define NL2 0x00000200 /* vt05 */ #define NL3 0x00000300 #define TBDELAY 0x00000c00 /* horizontal tab delay */ #define TAB0 0x00000000 #define TAB1 0x00000400 /* tty 37 */ #define TAB2 0x00000800 #define XTABS 0x00000c00 /* expand tabs on output */ #define CRDELAY 0x00003000 /* \r delay */ #define CR0 0x00000000 #define CR1 0x00001000 /* tn 300 */ #define CR2 0x00002000 /* tty 37 */ #define CR3 0x00003000 /* concept 100 */ #define VTDELAY 0x00004000 /* vertical tab delay */ #define FF0 0x00000000 #define FF1 0x00004000 /* tty 37 */ #define BSDELAY ((unsigned)0x00008000) /* \b delay */ #define BS0 0x00000000 #define BS1 ((unsigned)0x00008000) #define ALLDELAY (NLDELAY|TBDELAY|CRDELAY|VTDELAY|BSDELAY) #define CRTBS 0x00010000 /* do backspacing for crt */ #define PRTERA 0x00020000 /* \ ... / erase */ #define CRTERA 0x00040000 /* " \b " to wipe out char */ #define TILDE 0x00080000 /* (obsolete) place holder */ #define MDMBUF 0x00100000 /* start/stop output on carrier intr */ #define LITOUT 0x00200000 /* literal output */ #define TOSTOP 0x00400000 /* SIGSTOP on background output */ #define FLUSHO 0x00800000 /* flush output to terminal */ #define NOHANG 0x01000000 /* no SIGHUP on carrier drop */ #define L001000 0x02000000 #define CRTKIL 0x04000000 /* kill line with " \b " */ #define PASS8 0x08000000 #define CTLECH 0x10000000 /* echo control chars as ^X */ #define PENDIN 0x20000000 /* tp->t_rawq needs reread */ #define DECCTQ 0x40000000 /* only ^Q starts after ^S */ #define NOFLSH 0x80000000 /* no output flush on signal */ /* locals, from 127 down */ #define TIOCLBIS _IOW(t, 127, int) /* bis local mode bits */ #define TIOCLBIC _IOW(t, 126, int) /* bic local mode bits */ #define TIOCLSET _IOW(t, 125, int) /* set entire local mode word */ #define TIOCLGET _IOR(t, 124, int) /* get local modes */ #define LCRTBS ((int)(CRTBS>>16)) #define LPRTERA ((int)(PRTERA>>16)) #define LCRTERA ((int)(CRTERA>>16)) #define LTILDE ((int)TILDE>>16)) /* (obsolete) place holder */ #define LMDMBUF ((int)(MDMBUF>>16)) #define LLITOUT ((int)(LITOUT>>16)) #define LTOSTOP ((int)(TOSTOP>>16)) #define LFLUSHO ((int)(FLUSHO>>16)) #define LNOHANG ((int)(NOHANG>>16)) #define LCRTKIL ((int)(CRTKIL>>16)) #define LPASS8 ((int)(PASS8>>16)) #define LCTLECH ((int)(CTLECH>>16)) #define LPENDIN ((int)(PENDIN>>16)) #define LDECCTQ ((int)(DECCTQ>>16)) #define LNOFLSH ((int)(NOFLSH>>16)) #define TIOCSBRK _IO(t, 123) /* set break bit */ #define TIOCCBRK _IO(t, 122) /* clear break bit */ #define TIOCSDTR _IO(t, 121) /* set data terminal ready */ #define TIOCCDTR _IO(t, 120) /* clear data terminal ready */ #define TIOCGPGRP _IOR(t, 119, int) /* get pgrp of tty */ #define TIOCSPGRP _IOW(t, 118, int) /* set pgrp of tty */ #define TIOCSLTC _IOW(t,117,struct ltchars)/* set local special chars */ #define TIOCGLTC _IOR(t,116,struct ltchars)/* get local special chars */ #define TIOCOUTQ _IOR(t, 115, int) /* output queue size */ #define TIOCSTI _IOW(t, 114, char) /* simulate terminal input */ #define TIOCNOTTY _IO(t, 113) /* void tty association */ #define TIOCPKT _IOW(t, 112, int) /* pty: set/clear packet mode */ #define TIOCPKT_DATA 0x00 /* data packet */ #define TIOCPKT_FLUSHREAD 0x01 /* flush packet */ #define TIOCPKT_FLUSHWRITE 0x02 /* flush packet */ #define TIOCPKT_STOP 0x04 /* stop output */ #define TIOCPKT_START 0x08 /* start output */ #define TIOCPKT_NOSTOP 0x10 /* no more ^S, ^Q */ #define TIOCPKT_DOSTOP 0x20 /* now do ^S ^Q */ #define TIOCSTOP _IO(t, 111) /* stop output, like ^S */ #define TIOCSTART _IO(t, 110) /* start output, like ^Q */ #define TIOCMSET _IOW(t, 109, int) /* set all modem bits */ #define TIOCMBIS _IOW(t, 108, int) /* bis modem bits */ #define TIOCMBIC _IOW(t, 107, int) /* bic modem bits */ #define TIOCMGET _IOR(t, 106, int) /* get all modem bits */ #define TIOCREMOTE _IOW(t, 105, int) /* remote input editing */ #define TIOCGWINSZ _IOR(t, 104, struct winsize) /* get window size */ #define TIOCSWINSZ _IOW(t, 103, struct winsize) /* set window size */ #define TIOCUCNTL _IOW(t, 102, int) /* pty: set/clr usr cntl mode */ #define UIOCCMD(n) _IO(u, n) /* usr cntl op "n" */ #define OTTYDISC 0 /* old, v7 std tty driver */ #define NETLDISC 1 /* line discip for berk net */ #define NTTYDISC 2 /* new tty discipline */ #define TABLDISC 3 /* tablet discipline */ #define SLIPDISC 4 /* serial IP discipline */ #define FIOCLEX _IO(f, 1) /* set exclusive use on fd */ #define FIONCLEX _IO(f, 2) /* remove exclusive use */ /* another local */ /* should use off_t for FIONREAD but that would require types.h */ #define FIONREAD _IOR(f, 127, long) /* get # bytes to read */ #define FIONBIO _IOW(f, 126, int) /* set/clear non-blocking i/o */ #define FIOASYNC _IOW(f, 125, int) /* set/clear async i/o */ #define FIOSETOWN _IOW(f, 124, int) /* set owner */ #define FIOGETOWN _IOR(f, 123, int) /* get owner */ /* socket i/o controls */ #define SIOCSHIWAT _IOW(s, 0, int) /* set high watermark */ #define SIOCGHIWAT _IOR(s, 1, int) /* get high watermark */ #define SIOCSLOWAT _IOW(s, 2, int) /* set low watermark */ #define SIOCGLOWAT _IOR(s, 3, int) /* get low watermark */ #define SIOCATMARK _IOR(s, 7, int) /* at oob mark? */ #define SIOCSPGRP _IOW(s, 8, int) /* set process group */ #define SIOCGPGRP _IOR(s, 9, int) /* get process group */ #define SIOCADDRT _IOW(r, 10, struct rtentry) /* add route */ #define SIOCDELRT _IOW(r, 11, struct rtentry) /* delete route */ #define SIOCSIFADDR _IOW(i, 12, struct ifreq) /* set ifnet address */ #define SIOCGIFADDR _IOWR(i,13, struct ifreq) /* get ifnet address */ #define SIOCSIFDSTADDR _IOW(i, 14, struct ifreq) /* set p-p address */ #define SIOCGIFDSTADDR _IOWR(i,15, struct ifreq) /* get p-p address */ #define SIOCSIFFLAGS _IOW(i, 16, struct ifreq) /* set ifnet flags */ #define SIOCGIFFLAGS _IOWR(i,17, struct ifreq) /* get ifnet flags */ #define SIOCGIFBRDADDR _IOWR(i,18, struct ifreq) /* get broadcast addr */ #define SIOCSIFBRDADDR _IOW(i,19, struct ifreq) /* set broadcast addr */ #define SIOCGIFCONF _IOWR(i,20, struct ifconf) /* get ifnet list */ #define SIOCGIFNETMASK _IOWR(i,21, struct ifreq) /* get net addr mask */ #define SIOCSIFNETMASK _IOW(i,22, struct ifreq) /* set net addr mask */ #define SIOCGIFMETRIC _IOWR(i,23, struct ifreq) /* get IF metric */ #define SIOCSIFMETRIC _IOW(i,24, struct ifreq) /* set IF metric */ #define SIOCSARP _IOW(i, 30, struct arpreq) /* set arp entry */ #define SIOCGARP _IOWR(i,31, struct arpreq) /* get arp entry */ #define SIOCDARP _IOW(i, 32, struct arpreq) /* delete arp entry */ #endif 02 /* half-cooked mode */ #define LCASE 0x00000004 /* (obsolete) - place holder */ #define ECHO 0x00000008 /* echo isys/h/map.h 444 0 12 2671 5321523526 6032 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)map.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * Resource Allocation Maps. * * Associated routines manage allocation of an address space using * an array of segment descriptors. * * Malloc and mfree allocate and free the resource described * by the resource map. If the resource map becomes too fragmented * to be described in the available space, then some of the resource * is discarded. This may lead to critical shortages, * but is better than not checking (as the previous versions of * these routines did) or giving up and calling panic(). * * N.B.: The address 0 in the resource address space is not available * as it is used internally by the resource map routines. */ struct map { struct mapent *m_map; /* start of the map */ struct mapent *m_limit; /* address of last slot in map */ char *m_name; /* name of resource */ /* we use m_name when the map overflows, in warning messages */ }; struct mapent { size_t m_size; /* size of this segment of the map */ memaddr m_addr; /* resource-space addr of start of segment */ }; #ifdef KERNEL extern struct map coremap[1]; /* space for core allocation */ extern struct map swapmap[1]; /* space for swap allocation */ extern struct map ub_map[1]; /* space for UNIBUS allocation */ #endif 110) /* start output, like ^Q */ #define TIOCMSET _IOW(t, 109, int) /sys/h/mbuf.h 444 0 0 13657 5514434635 6217 /* * Copyright (c) 1982, 1986, 1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)mbuf.h 7.8.2 (2.11BSD GTE) 12/31/93 */ /* * The default values for NMBUFS and NMBCLUSTERS (160 and 12 respectively) * result in approximately 32K bytes of buffer memory being allocated to * the network. Taking into account the other data used by the network, * this leaves approximately 8K bytes free, so the formula is roughly: * * (NMBUFS / 8) + NMBCLUSTERS < 40 */ #define NMBUFS 170 /* number of mbufs */ #define MSIZE 128 /* size of an mbuf */ #if CLBYTES > 1024 #define MCLBYTES 1024 #define MCLSHIFT 10 #define MCLOFSET (MCLBYTES - 1) #else #define MCLBYTES CLBYTES #define MCLSHIFT CLSHIFT #define MCLOFSET CLOFSET #endif #define MMINOFF 8 /* mbuf header length */ #define MTAIL 2 #define MMAXOFF (MSIZE-MTAIL) /* offset where data ends */ #define MLEN (MSIZE-MMINOFF-MTAIL) /* mbuf data length */ #define NMBCLUSTERS 12 #define NMBPCL (CLBYTES/MSIZE) /* # mbufs per cluster */ /* * Macros for type conversion */ /* network cluster number to virtual address, and back */ #define cltom(x) ((struct mbuf *)((int)mbutl + ((x) << MCLSHIFT))) #define mtocl(x) (((int)x - (int)mbutl) >> MCLSHIFT) /* address in mbuf to mbuf head */ #define dtom(x) ((struct mbuf *)((int)x & ~(MSIZE-1))) /* mbuf head, to typed data */ #define mtod(x,t) ((t)((int)(x) + (x)->m_off)) struct mbuf { struct mbuf *m_next; /* next buffer in chain */ u_short m_off; /* offset of data */ short m_len; /* amount of data in this mbuf */ short m_type; /* mbuf type (0 == free) */ u_char m_dat[MLEN]; /* data storage */ struct mbuf *m_act; /* link in higher-level mbuf list */ }; /* mbuf types */ #define MT_FREE 0 /* should be on free list */ #define MT_DATA 1 /* dynamic (data) allocation */ #define MT_HEADER 2 /* packet header */ #define MT_SOCKET 3 /* socket structure */ #define MT_PCB 4 /* protocol control block */ #define MT_RTABLE 5 /* routing tables */ #define MT_HTABLE 6 /* IMP host tables */ #define MT_ATABLE 7 /* address resolution tables */ #define MT_SONAME 8 /* socket name */ #define MT_ZOMBIE 9 /* zombie proc status */ #define MT_SOOPTS 10 /* socket options */ #define MT_FTABLE 11 /* fragment reassembly header */ #define MT_RIGHTS 12 /* access rights */ #define MT_IFADDR 13 /* interface address */ #define NMBTYPES 16 /* flags to m_get */ #define M_DONTWAIT 0 #define M_WAIT 1 #define M_DONTWAITLONG 2 /* flags to m_pgalloc */ #define MPG_MBUFS 0 /* put new mbufs on free list */ #define MPG_CLUSTERS 1 /* put new clusters on free list */ #define MPG_SPACE 2 /* don't free; caller wants space */ /* length to m_copy to copy all */ #define M_COPYALL 077776 /* * m_pullup will pull up additional length if convenient; * should be enough to hold headers of second-level and higher protocols. */ #define MPULL_EXTRA 32 #define MGET(m, i, t) \ { int ms = splimp(); \ if ((m)=mfree) \ { if ((m)->m_type != MT_FREE) panic("mget"); (m)->m_type = t; \ mbstat.m_mtypes[MT_FREE]--; mbstat.m_mtypes[t]++; \ mfree = (m)->m_next; (m)->m_next = 0; \ (m)->m_off = MMINOFF; } \ else \ (m) = m_more((((ms&0340) <= 0100) && (i==M_DONTWAIT)) ? M_DONTWAITLONG : i, t); \ splx(ms); } /* * Mbuf page cluster macros. * MCLALLOC allocates mbuf page clusters. * Note that it works only with a count of 1 at the moment. * MCLGET adds such clusters to a normal mbuf. * m->m_len is set to MCLBYTES upon success, and to MLEN on failure. * MCLFREE frees clusters allocated by MCLALLOC. */ #ifndef pdp11 #define MCLALLOC(m, i) \ { int ms = splimp(); \ if (mclfree == 0) \ (void)m_clalloc((i), MPG_CLUSTERS, M_DONTWAIT); \ if ((m)=mclfree) \ {++mclrefcnt[mtocl(m)];mbstat.m_clfree--;mclfree = (m)->m_next;} \ splx(ms); } #else #define MCLALLOC(m, i) \ { int ms = splimp(); \ if ((m)=mclfree) \ {++mclrefcnt[mtocl(m)];mbstat.m_clfree--;mclfree = (m)->m_next;} \ splx(ms); } #endif #define M_HASCL(m) ((m)->m_off >= MSIZE) #define MTOCL(m) ((struct mbuf *)(mtod((m), int) &~ MCLOFSET)) #define MCLGET(m) \ { struct mbuf *p; \ MCLALLOC(p, 1); \ if (p) { \ (m)->m_off = (int)p - (int)(m); \ (m)->m_len = MCLBYTES; \ } else \ (m)->m_len = MLEN; \ } #define MCLFREE(m) { \ if (--mclrefcnt[mtocl(m)] == 0) \ { (m)->m_next = mclfree;mclfree = (m);mbstat.m_clfree++;} \ } #define MFREE(m, n) \ { int ms = splimp(); \ if ((m)->m_type == MT_FREE) panic("mfree"); \ mbstat.m_mtypes[(m)->m_type]--; mbstat.m_mtypes[MT_FREE]++; \ (m)->m_type = MT_FREE; \ if (M_HASCL(m)) { \ (n) = MTOCL(m); \ MCLFREE(n); \ } \ (n) = (m)->m_next; (m)->m_next = mfree; \ (m)->m_off = 0; (m)->m_act = 0; mfree = (m); \ splx(ms); \ if (m_want) { \ m_want = 0; \ WAKEUP((caddr_t)&mfree); \ } \ } /* * Mbuf statistics. */ struct mbstat { u_short m_mbufs; /* mbufs obtained from page pool */ u_short m_clusters; /* clusters obtained from page pool */ u_short m_space; /* interface pages obtained from page pool */ u_short m_clfree; /* free clusters */ u_short m_drops; /* times failed to find space */ u_short m_wait; /* times waited for space */ u_short m_drain; /* times drained protocols for space */ u_short m_mtypes[NMBTYPES]; /* type specific mbuf allocations */ }; #ifdef SUPERVISOR extern struct mbuf *mbutl; /* virtual address of net free mem */ struct mbstat mbstat; int nmbclusters; struct mbuf *mfree, *mclfree; char mclrefcnt[NMBCLUSTERS + 1]; int m_want; struct mbuf *m_get(),*m_getclr(),*m_free(),*m_more(),*m_copy(),*m_pullup(); #ifndef pdp11 caddr_t m_clalloc(); #endif #endif ut new clusters on free list */ #define MPG_SPACE 2 /* don't free; caller wants sys/h/mount.h 444 0 12 1774 5665736540 6437 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)mount.h 7.2.1 (2.11BSD GTE) 11/26/94 */ /* * Mount structure. * One allocated on every mount. * Used to find the super block. */ struct mount { dev_t m_dev; /* device mounted */ struct fs m_filsys; /* superblock data */ #define m_flags (m_filsys.fs_flags) struct inode *m_inodp; /* pointer to mounted on inode */ struct inode *m_qinod; /* QUOTA: pointer to quota file */ }; /* * Mount flags. */ #define MNT_RDONLY 0x00000001 /* read only filesystem */ #define MNT_SYNCHRONOUS 0x00000002 /* file system written synchronously */ #define MNT_NOEXEC 0x00000004 /* can't exec from filesystem */ #define MNT_NOSUID 0x00000008 /* don't honor setuid bits on fs */ #define MNT_NODEV 0x00000010 /* don't interpret special files */ #if defined(KERNEL) && !defined(SUPERVISOR) struct mount mount[NMOUNT]; #endif MPG_sys/h/mtio.h 444 0 12 4434 5012667201 6220 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)mtio.h 7.1 (Berkeley) 6/4/86 */ /* * Structures and definitions for mag tape io control commands */ /* structure for MTIOCTOP - mag tape op command */ struct mtop { short mt_op; /* operations defined below */ daddr_t mt_count; /* how many of them */ }; /* operations */ #define MTWEOF 0 /* write an end-of-file record */ #define MTFSF 1 /* forward space file */ #define MTBSF 2 /* backward space file */ #define MTFSR 3 /* forward space record */ #define MTBSR 4 /* backward space record */ #define MTREW 5 /* rewind */ #define MTOFFL 6 /* rewind and put the drive offline */ #define MTNOP 7 /* no operation, sets status only */ #define MTCACHE 8 /* enable controller cache */ #define MTNOCACHE 9 /* disable controller cache */ /* structure for MTIOCGET - mag tape get status command */ struct mtget { short mt_type; /* type of magtape device */ /* the following two registers are grossly device dependent */ short mt_dsreg; /* ``drive status'' register */ short mt_erreg; /* ``error'' register */ /* end device-dependent registers */ short mt_resid; /* residual count */ /* the following two are not yet implemented */ daddr_t mt_fileno; /* file number of current position */ daddr_t mt_blkno; /* block number of current position */ /* end not yet implemented */ }; /* * Constants for mt_type byte. These are the same * for other controllers compatible with the types listed. */ #define MT_ISTS 0x01 /* TS-11 */ #define MT_ISHT 0x02 /* TM03 Massbus: TE16, TU45, TU77 */ #define MT_ISTM 0x03 /* TM11/TE10 Unibus */ #define MT_ISMT 0x04 /* TM78/TU78 Massbus */ #define MT_ISUT 0x05 /* SI TU-45 emulation on Unibus */ #define MT_ISCPC 0x06 /* SUN */ #define MT_ISAR 0x07 /* SUN */ #define MT_ISTMSCP 0x08 /* DEC TMSCP protocol (TU81, TK50) */ /* mag tape io control commands */ #define MTIOCTOP _IOW(m, 1, struct mtop) /* do a mag tape op */ #define MTIOCGET _IOR(m, 2, struct mtget) /* get tape status */ #define MTIOCIEOT _IO(m, 3) /* ignore EOT error */ #define MTIOCEEOT _IO(m, 4) /* enable EOT error */ #ifndef KERNEL #define DEFTAPE "/dev/rmt8" #define MT_DEF "/dev/nrmt8" #endif ool */ u_short m_space; /* interface pages obtained from page pool */ u_short m_clfree; /* free clusters */ u_short m_drops; /* times failed to find space */ u_short m_wait; /* times waited for space */ u_short m_drain; /*sys/h/namei.h 444 0 12 5421 4631301435 6336 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)namei.h 1.2 (2.10BSD Berkeley) 1/26/90 */ #ifndef _NAMEI_ #define _NAMEI_ #ifdef KERNEL #include "uio.h" #else #include #endif /* * Encapsulation of namei parameters. * One of these is located in the u. area to * minimize space allocated on the kernel stack. */ struct nameidata { caddr_t ni_dirp; /* pathname pointer */ short ni_nameiop; /* see below */ short ni_error; /* error return if any */ off_t ni_endoff; /* end of useful stuff in directory */ struct inode *ni_pdir; /* inode of parent directory of dirp */ struct iovec ni_iovec; /* MUST be pointed to by ni_iov */ struct uio ni_uio; /* directory I/O parameters */ struct direct ni_dent; /* current directory entry */ }; #define ni_base ni_iovec.iov_base #define ni_count ni_iovec.iov_len #define ni_iov ni_uio.uio_iov #define ni_iovcnt ni_uio.uio_iovcnt #define ni_offset ni_uio.uio_offset #define ni_segflg ni_uio.uio_segflg #define ni_resid ni_uio.uio_resid /* * namei operations and modifiers */ #define LOOKUP 0 /* perform name lookup only */ #define CREATE 1 /* setup for file creation */ #define DELETE 2 /* setup for file deletion */ #define LOCKPARENT 0x10 /* see the top of namei */ #define NOCACHE 0x20 /* name must not be left in cache */ #define FOLLOW 0x40 /* follow symbolic links */ #define NOFOLLOW 0x0 /* don't follow symbolic links (pseudo) */ /* * This structure describes the elements in the cache of recent * names looked up by namei. */ struct namecache { struct namecache *nc_forw; /* hash chain, MUST BE FIRST */ struct namecache *nc_back; /* hash chain, MUST BE FIRST */ struct namecache *nc_nxt; /* LRU chain */ struct namecache **nc_prev; /* LRU chain */ struct inode *nc_ip; /* inode the name refers to */ ino_t nc_ino; /* ino of parent of name */ dev_t nc_dev; /* dev of parent of name */ dev_t nc_idev; /* dev of the name ref'd */ u_short nc_id; /* referenced inode's id */ char nc_nlen; /* length of name */ #define NCHNAMLEN 15 /* maximum name segment length we bother with */ char nc_name[NCHNAMLEN]; /* segment name */ }; #if defined(KERNEL) && !defined(SUPERVISOR) struct namecache *namecache; int nchsize; #include segm nmidesc; #endif /* * Stats on usefulness of namei caches. */ struct nchstats { long ncs_goodhits; /* hits that we can reall use */ long ncs_badhits; /* hits we must drop */ long ncs_falsehits; /* hits with id mismatch */ long ncs_miss; /* misses */ long ncs_long; /* long names that ignore cache */ long ncs_pass2; /* names found with passes == 2 */ long ncs_2passes; /* number of times we attempt it */ }; #endif ted to by ni_iov */ struct uio ni_uio; /* directory I/O parameters */ struct direct ni_dent; /* current directory entry */ }; #define ni_base ni_iovec.iov_base #define ni_count ni_iovec.iov_len #define ni_iov ni_uio.uio_iov #define sys/h/param.h 444 0 12 6344 5511224530 6350 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)param.h 1.3 (2.11BSD GTE) 12/31/93 */ #define BSD 211 /* 2.11 * 10, as cpp doesn't do floats */ #ifdef KERNEL #include "localopts.h" #else #include #endif /* * Machine type dependent parameters. */ #ifdef KERNEL #include "../machine/machparam.h" #else #include #endif /* * Machine-independent constants */ #define NMOUNT 6 /* number of mountable file systems */ #define MAXUPRC 20 /* max processes per user */ #define NOFILE 30 /* max open files per process */ #define CANBSIZ 256 /* max size of typewriter line */ #define NCARGS 5120 /* # characters in exec arglist */ #define NGROUPS 16 /* max number groups */ #define NOGROUP 65535 /* marker for empty group set member */ /* * Priorities */ #define PSWP 0 #define PINOD 10 #define PRIBIO 20 #define PRIUBA 24 #define PZERO 25 #define PPIPE 26 #define PWAIT 30 #define PLOCK 35 #define PSLEP 40 #define PUSER 50 #define NZERO 0 /* * Signals */ #ifdef KERNEL #include "signal.h" #else #include #endif #define ISSIG(p) \ ((p)->p_sig && ((p)->p_flag&STRC || \ ((p)->p_sig &~ ((p)->p_sigignore | (p)->p_sigmask))) && issig()) #define NBPW sizeof(int) /* number of bytes in an integer */ #define NULL 0 #define CMASK 026 /* default mask for file creation */ #define NODEV (dev_t)(-1) #define CLBYTES (CLSIZE*NBPG) #define CLOFSET (CLBYTES-1) #define claligned(x) ((((int)(x))&CLOFSET)==0) #define CLOFF CLOFSET #define CLSHIFT (PGSHIFT + CLSIZELOG2) /* round a number of clicks up to a whole cluster */ #define clrnd(i) (((i) + (CLSIZE-1)) &~ ((long)(CLSIZE-1))) /* CBLOCK is the size of a clist block, must be power of 2 */ #define CBLOCK 32 #define CBSIZE (CBLOCK - sizeof(struct cblock *)) /* data chars/clist */ #define CROUND (CBLOCK - 1) /* clist rounding */ #ifndef KERNEL #include #else #include "types.h" #endif /* * File system parameters and macros. * * The file system is made out of blocks of most MAXBSIZE units. */ #define MAXBSIZE 1024 /* * MAXPATHLEN defines the longest permissable path length * after expanding symbolic links. It is used to allocate * a temporary buffer from the buffer pool in which to do the * name expansion, hence should be a power of two, and must * be less than or equal to MAXBSIZE. * MAXSYMLINKS defines the maximum number of symbolic links * that may be expanded in a path name. It should be set high * enough to allow all legitimate uses, but halt infinite loops * reasonably quickly. */ #define MAXPATHLEN 256 #define MAXSYMLINKS 8 /* * Macros for fast min/max. */ #define MIN(a,b) (((a)<(b))?(a):(b)) #define MAX(a,b) (((a)>(b))?(a):(b)) /* * Macros for counting and rounding. */ #ifndef howmany #define howmany(x, y) (((x)+((y)-1))/(y)) #endif #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* * Maximum size of hostname recognized and stored in the kernel. */ #define MAXHOSTNAMELEN 64 #if defined(KERNEL) && defined(INET) #include "../machine/net_mac.h" #endif /* * MAXMEM is the maximum core per process is allowed. First number is Kb. */ #define MAXMEM (300*16) */ #define SIOCDELRT _IOW(r, 11, struct rtentry) /* delete route */ #define SIOCSIFADDR _IOW(i, 12, struct ifreq) /* set ifnet address */ #define SIOCGIFADDR _IOWR(i,13, struct ifreq) /* get ifnet address */ #define SIOCSIFDSTADDR _IOW(i, 14, struct ifreq) /* set p-p address */ #defsys/h/proc.h 444 0 12 11332 5710101752 6225 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)proc.h 1.2 (2.11BSD GTE) 1/18/95 */ #ifndef _SYS_PROC_H_ #define _SYS_PROC_H_ /* * One structure allocated per active * process. It contains all data needed * about the process while the * process may be swapped out. * Other per process data (user.h) * is swapped with the process. */ struct proc { struct proc *p_nxt; /* linked list of allocated proc slots */ struct proc **p_prev; /* also zombies, and free proc's */ struct proc *p_pptr; /* pointer to process structure of parent */ short p_flag; short p_uid; /* user id, used to direct tty signals */ short p_pid; /* unique process id */ short p_ppid; /* process id of parent */ long p_sig; /* signals pending to this process */ char p_stat; char p_dummy; /* room for one more, here */ /* * Union to overwrite information no longer needed by ZOMBIED * process with exit information for the parent process. The * two structures have been carefully set up to use the same * amount of memory. Must be very careful that any values in * p_alive are not used for zombies (zombproc). */ union { struct { char P_pri; /* priority, negative is high */ char P_cpu; /* cpu usage for scheduling */ char P_time; /* resident time for scheduling */ char P_nice; /* nice for cpu usage */ char P_slptime; /* secs sleeping */ char P_cursig; struct proc *P_hash; /* hashed based on p_pid */ long P_sigmask; /* current signal mask */ long P_sigignore; /* signals being ignored */ long P_sigcatch; /* signals being caught by user */ short P_pgrp; /* name of process group leader */ struct proc *P_link; /* linked list of running processes */ memaddr P_addr; /* address of u. area */ memaddr P_daddr; /* address of data area */ memaddr P_saddr; /* address of stack area */ size_t P_dsize; /* size of data area (clicks) */ size_t P_ssize; /* size of stack segment (clicks) */ caddr_t P_wchan; /* event process is awaiting */ struct text *P_textp; /* pointer to text structure */ struct k_itimerval P_realtimer; } p_alive; struct { short P_xstat; /* exit status for wait */ struct k_rusage P_ru; /* exit information */ } p_dead; } p_un; }; #define p_pri p_un.p_alive.P_pri #define p_cpu p_un.p_alive.P_cpu #define p_time p_un.p_alive.P_time #define p_nice p_un.p_alive.P_nice #define p_slptime p_un.p_alive.P_slptime #define p_hash p_un.p_alive.P_hash #define p_cursig p_un.p_alive.P_cursig #define p_sigmask p_un.p_alive.P_sigmask #define p_sigignore p_un.p_alive.P_sigignore #define p_sigcatch p_un.p_alive.P_sigcatch #define p_pgrp p_un.p_alive.P_pgrp #define p_link p_un.p_alive.P_link #define p_addr p_un.p_alive.P_addr #define p_daddr p_un.p_alive.P_daddr #define p_saddr p_un.p_alive.P_saddr #define p_dsize p_un.p_alive.P_dsize #define p_ssize p_un.p_alive.P_ssize #define p_wchan p_un.p_alive.P_wchan #define p_textp p_un.p_alive.P_textp #define p_realtimer p_un.p_alive.P_realtimer #define p_clktim p_realtimer.it_value #define p_xstat p_un.p_dead.P_xstat #define p_ru p_un.p_dead.P_ru #define PIDHSZ 16 #define PIDHASH(pid) ((pid) & (PIDHSZ - 1)) #if defined(KERNEL) && !defined(SUPERVISOR) struct proc *pidhash[PIDHSZ]; struct proc *pfind(); struct proc proc[], *procNPROC; /* the proc table itself */ struct proc *freeproc, *zombproc, *allproc, *qs; /* lists of procs in various states */ int nproc; #endif /* stat codes */ #define SSLEEP 1 /* awaiting an event */ #define SWAIT 2 /* (abandoned state) */ #define SRUN 3 /* running */ #define SIDL 4 /* intermediate state in process creation */ #define SZOMB 5 /* intermediate state in process termination */ #define SSTOP 6 /* process being traced */ /* flag codes */ #define SLOAD 0x000001 /* in core */ #define SSYS 0x000002 /* swapper or pager process */ #define SLOCK 0x000004 /* process being swapped out */ #define SSWAP 0x000008 /* save area flag */ #define STRC 0x000010 /* process is being traced */ #define SWTED 0x000020 /* another tracing flag */ #define SULOCK 0x000040 /* user settable lock in core */ #define SOMASK 0x000080 /* restore old mask after taking signal */ #define SVFORK 0x000100 /* process resulted from vfork() */ #define SVFPRNT 0x000200 /* parent in vfork, waiting for child */ #define SVFDONE 0x000400 /* parent has released child in vfork */ #define STIMO 0x000800 /* timing out during sleep */ #define SDETACH 0x001000 /* detached inherited by init */ #define SOUSIG 0x002000 /* using old signal mechanism */ #define SSEL 0x004000 /* selecting; wakeup/waiting danger */ #define S_DATA 0 /* specified segment */ #define S_STACK 1 #endif /* !_SYS_PROC_H_ */ GTE) 1/18/95 */ #ifndef _SYS_PROC_H_ #define _SYS_PROC_H_ /* * One structure allocated per active * process. It contains all data needed * about the process while the * process may be swapped out. * Other per process data (user.h) * is swapped with the process. */ struct proc { strsys/h/protosw.h 444 0 0 17026 6036376513 6775 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)protosw.h 7.2.2 (2.11BSD GTE) 1995/10/09 */ /* * Protocol switch table. * * Each protocol has a handle initializing one of these structures, * which is used for protocol-protocol and system-protocol communication. * * A protocol is called through the pr_init entry before any other. * Thereafter it is called every 200ms through the pr_fasttimo entry and * every 500ms through the pr_slowtimo for timer based actions. * The system will call the pr_drain entry if it is low on space and * this should throw away any non-critical data. * * Protocols pass data between themselves as chains of mbufs using * the pr_input and pr_output hooks. Pr_input passes data up (towards * UNIX) and pr_output passes it down (towards the imps); control * information passes up and down on pr_ctlinput and pr_ctloutput. * The protocol is responsible for the space occupied by any the * arguments to these entries and must dispose it. * * The userreq routine interfaces protocols to the system and is * described below. */ struct protosw { short pr_type; /* socket type used for */ struct domain *pr_domain; /* domain protocol a member of */ short pr_protocol; /* protocol number */ short pr_flags; /* see below */ /* protocol-protocol hooks */ int (*pr_input)(); /* input to protocol (from below) */ int (*pr_output)(); /* output to protocol (from above) */ int (*pr_ctlinput)(); /* control input (from below) */ int (*pr_ctloutput)(); /* control output (from above) */ /* user-protocol hook */ int (*pr_usrreq)(); /* user request: see list below */ /* utility hooks */ int (*pr_init)(); /* initialization hook */ int (*pr_fasttimo)(); /* fast timeout (200ms) */ int (*pr_slowtimo)(); /* slow timeout (500ms) */ int (*pr_drain)(); /* flush any excess space possible */ int (*pr_sysctl)(); /* sysctl for protocol */ }; #define PR_SLOWHZ 2 /* 2 slow timeouts per second */ #define PR_FASTHZ 5 /* 5 fast timeouts per second */ /* * Values for pr_flags */ #define PR_ATOMIC 0x01 /* exchange atomic messages only */ #define PR_ADDR 0x02 /* addresses given with messages */ /* in the current implementation, PR_ADDR needs PR_ATOMIC to work */ #define PR_CONNREQUIRED 0x04 /* connection required by protocol */ #define PR_WANTRCVD 0x08 /* want PRU_RCVD calls */ #define PR_RIGHTS 0x10 /* passes capabilities */ /* * The arguments to usrreq are: * (*protosw[].pr_usrreq)(up, req, m, nam, opt); * where up is a (struct socket *), req is one of these requests, * m is a optional mbuf chain containing a message, * nam is an optional mbuf chain containing an address, * and opt is a pointer to a socketopt structure or nil. * The protocol is responsible for disposal of the mbuf chain m, * the caller is responsible for any space held by nam and opt. * A non-zero return from usrreq gives an * UNIX error number which should be passed to higher level software. */ #define PRU_ATTACH 0 /* attach protocol to up */ #define PRU_DETACH 1 /* detach protocol from up */ #define PRU_BIND 2 /* bind socket to address */ #define PRU_LISTEN 3 /* listen for connection */ #define PRU_CONNECT 4 /* establish connection to peer */ #define PRU_ACCEPT 5 /* accept connection from peer */ #define PRU_DISCONNECT 6 /* disconnect from peer */ #define PRU_SHUTDOWN 7 /* won't send any more data */ #define PRU_RCVD 8 /* have taken data; more room now */ #define PRU_SEND 9 /* send this data */ #define PRU_ABORT 10 /* abort (fast DISCONNECT, DETATCH) */ #define PRU_CONTROL 11 /* control operations on protocol */ #define PRU_SENSE 12 /* return status into m */ #define PRU_RCVOOB 13 /* retrieve out of band data */ #define PRU_SENDOOB 14 /* send out of band data */ #define PRU_SOCKADDR 15 /* fetch socket's address */ #define PRU_PEERADDR 16 /* fetch peer's address */ #define PRU_CONNECT2 17 /* connect two sockets */ /* begin for protocols internal use */ #define PRU_FASTTIMO 18 /* 200ms timeout */ #define PRU_SLOWTIMO 19 /* 500ms timeout */ #define PRU_PROTORCV 20 /* receive from below */ #define PRU_PROTOSEND 21 /* send to below */ #define PRU_NREQ 21 #if defined(PRUREQUESTS) && defined(SUPERVISOR) char *prurequests[] = { "ATTACH", "DETACH", "BIND", "LISTEN", "CONNECT", "ACCEPT", "DISCONNECT", "SHUTDOWN", "RCVD", "SEND", "ABORT", "CONTROL", "SENSE", "RCVOOB", "SENDOOB", "SOCKADDR", "PEERADDR", "CONNECT2", "FASTTIMO", "SLOWTIMO", "PROTORCV", "PROTOSEND", }; #endif /* * The arguments to the ctlinput routine are * (*protosw[].pr_ctlinput)(cmd, sa, arg); * where cmd is one of the commands below, sa is a pointer to a sockaddr, * and arg is an optional caddr_t argument used within a protocol family. */ #define PRC_IFDOWN 0 /* interface transition */ #define PRC_ROUTEDEAD 1 /* select new route if possible */ #define PRC_QUENCH 4 /* some said to slow down */ #define PRC_MSGSIZE 5 /* message size forced drop */ #define PRC_HOSTDEAD 6 /* normally from IMP */ #define PRC_HOSTUNREACH 7 /* ditto */ #define PRC_UNREACH_NET 8 /* no route to network */ #define PRC_UNREACH_HOST 9 /* no route to host */ #define PRC_UNREACH_PROTOCOL 10 /* dst says bad protocol */ #define PRC_UNREACH_PORT 11 /* bad port # */ #define PRC_UNREACH_NEEDFRAG 12 /* IP_DF caused drop */ #define PRC_UNREACH_SRCFAIL 13 /* source route failed */ #define PRC_REDIRECT_NET 14 /* net routing redirect */ #define PRC_REDIRECT_HOST 15 /* host routing redirect */ #define PRC_REDIRECT_TOSNET 16 /* redirect for type of service & net */ #define PRC_REDIRECT_TOSHOST 17 /* redirect for tos & host */ #define PRC_TIMXCEED_INTRANS 18 /* packet lifetime expired in transit */ #define PRC_TIMXCEED_REASS 19 /* lifetime expired on reass q */ #define PRC_PARAMPROB 20 /* header incorrect */ #define PRC_NCMDS 21 #define PRC_IS_REDIRECT(cmd) \ ((cmd) >= PRC_REDIRECT_NET && (cmd) <= PRC_REDIRECT_TOSHOST) #if defined(PRCREQUESTS) && defined(SUPERVISOR) char *prcrequests[] = { "IFDOWN", "ROUTEDEAD", "#2", "#3", "QUENCH", "MSGSIZE", "HOSTDEAD", "HOSTUNREACH", "NET-UNREACH", "HOST-UNREACH", "PROTO-UNREACH", "PORT-UNREACH", "FRAG-UNREACH", "SRCFAIL-UNREACH", "NET-REDIRECT", "HOST-REDIRECT", "TOSNET-REDIRECT", "TOSHOST-REDIRECT", "TX-INTRANS", "TX-REASS", "PARAMPROB" }; #endif /* * The arguments to ctloutput are: * (*protosw[].pr_ctloutput)(req, so, level, optname, optval); * req is one of the actions listed below, so is a (struct socket *), * level is an indication of which protocol layer the option is intended. * optname is a protocol dependent socket option request, * optval is a pointer to a mbuf-chain pointer, for value-return results. * The protocol is responsible for disposal of the mbuf chain *optval * if supplied, * the caller is responsible for any space held by *optval, when returned. * A non-zero return from usrreq gives an * UNIX error number which should be passed to higher level software. */ #define PRCO_GETOPT 0 #define PRCO_SETOPT 1 #define PRCO_NCMDS 2 #if defined(PRCOREQUESTS) && defined(SUPERVISOR) char *prcorequests[] = { "GETOPT", "SETOPT", }; #endif #if defined(KERNEL) && defined(INET) && defined(SUPERVISOR) extern struct protosw *pffindproto(), *pffindtype(); #endif urn(EBADF); if (*(int *)data) disk->dk_flags |= DKF_WLABEL; else disk->dk_flags &= ~DKF_WLABEL; return(0); case DIOCSDINFO: if ((flag & FWRITE) == 0) return(EBADF); error = setdisklabel(lp, (struct disklabel *)data, disk->dk_flags & DKF_WLABEL ? 0 : disk->dk_openmask); /* * If no error was encountered setting the disklabel then we must copy * out the new label from the local copy to the mapped out label. Also * update the partition tables (whsys/h/reboot.h 444 0 12 2074 4060201504 6530 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)reboot.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * Arguments to reboot system call. * These are passed to boot program in r4, * and on to init. */ #define RB_AUTOBOOT 0 /* flags for system auto-booting itself */ #define RB_ASKNAME 0x001 /* ask for file name to reboot from */ #define RB_SINGLE 0x002 /* reboot to single user only */ #define RB_NOSYNC 0x004 /* dont sync before reboot */ #define RB_HALT 0x008 /* don't reboot, just halt */ #define RB_INITNAME 0x010 /* name given for /etc/init */ #define RB_DFLTROOT 0x020 /* use compiled-in rootdev */ #define RB_DUMP 0x040 /* take a dump before rebooting */ #define RB_NOFSCK 0x080 /* don't perform fsck's on reboot */ #define RB_POWRFAIL 0x100 /* reboot caused by power failure */ #define RB_RDONLY 0x200 /* mount root fs read-only */ #define RB_PANIC 0 /* reboot due to panic */ #define RB_BOOT 1 /* reboot due to boot() */ Protocol switch tab. * * Each protocol has a handle initializing one of these structures, * which is used for protocol-protocol and system-protocol communication. * * A protocol is called through the pr_init entry before any other. * Thereafter it is called every 200ms through the pr_fasttimo entry and * every 500ms through the pr_slowtimo for timer based actions. * The system will call the pr_drain entry if it is low on space and * thisys/h/resource.h 444 0 12 4762 5710101772 7104 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)resource.h 1.2 (2.11BSD GTE) 1/14/95 */ #ifndef _SYS_RESOURCE_H_ #define _SYS_RESOURCE_H_ /* * Process priority specifications to get/setpriority. */ #define PRIO_MIN -20 #define PRIO_MAX 20 #define PRIO_PROCESS 0 #define PRIO_PGRP 1 #define PRIO_USER 2 /* * Resource utilization information. */ #define RUSAGE_SELF 0 #define RUSAGE_CHILDREN -1 struct rusage { struct timeval ru_utime; /* user time used */ struct timeval ru_stime; /* system time used */ long ru_maxrss; #define ru_first ru_ixrss long ru_ixrss; /* integral shared memory size */ long ru_idrss; /* integral unshared data " */ long ru_isrss; /* integral unshared stack " */ long ru_minflt; /* page reclaims */ long ru_majflt; /* page faults */ long ru_ovly; /* overlay changes */ long ru_nswap; /* swaps */ long ru_inblock; /* block input operations */ long ru_oublock; /* block output operations */ long ru_msgsnd; /* messages sent */ long ru_msgrcv; /* messages received */ long ru_nsignals; /* signals received */ long ru_nvcsw; /* voluntary context switches */ long ru_nivcsw; /* involuntary " */ #define ru_last ru_nivcsw }; struct k_rusage { /* KERNEL RUSAGE STRUCTURE */ #define k_ru_first ru_utime long ru_utime; /* user time used (LINEHZ ticks) */ long ru_stime; /* system time used (LINEHZ ticks) */ long ru_ovly; /* overlay changes */ long ru_nswap; /* swaps */ long ru_inblock; /* block input operations */ long ru_oublock; /* block output operations */ long ru_msgsnd; /* messages sent */ long ru_msgrcv; /* messages received */ long ru_nsignals; /* signals received */ long ru_nvcsw; /* voluntary context switches */ long ru_nivcsw; /* involuntary " */ #define k_ru_last ru_nivcsw }; /* * Resource limits */ #define RLIMIT_CPU 0 /* cpu time in milliseconds */ #define RLIMIT_FSIZE 1 /* maximum file size */ #define RLIMIT_DATA 2 /* data size */ #define RLIMIT_STACK 3 /* stack size */ #define RLIMIT_CORE 4 /* core file size */ #define RLIMIT_RSS 5 /* resident set size */ #define RLIM_NLIMITS 6 /* number of resource limits */ #define RLIM_INFINITY 0x7fffffff struct rlimit { long rlim_cur; /* current (soft) limit */ long rlim_max; /* maximum value for rlim_cur */ }; /* Load average structure. */ struct loadavg { short ldavg[3]; int fscale; }; #endif /* !_SYS_RESOURCE_H_ */ omic messages sys/h/signal.h 444 0 12 10766 4053130003 6537 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)signal.h 1.1 (2.10BSD Berkeley) 12/1/86 */ #ifndef NSIG #define NSIG 32 #define SIGHUP 1 /* hangup */ #define SIGINT 2 /* interrupt */ #define SIGQUIT 3 /* quit */ #define SIGILL 4 /* illegal instruction (not reset when caught) */ #define ILL_RESAD_FAULT 0x0 /* reserved addressing fault */ #define ILL_PRIVIN_FAULT 0x1 /* privileged instruction fault */ #define ILL_RESOP_FAULT 0x2 /* reserved operand fault */ /* CHME, CHMS, CHMU are not yet given back to users reasonably */ #define SIGTRAP 5 /* trace trap (not reset when caught) */ #define SIGIOT 6 /* IOT instruction */ #define SIGABRT SIGIOT /* compatibility */ #define SIGEMT 7 /* EMT instruction */ #define SIGFPE 8 /* floating point exception */ #define FPE_INTOVF_TRAP 0x1 /* integer overflow */ #define FPE_INTDIV_TRAP 0x2 /* integer divide by zero */ #define FPE_FLTOVF_TRAP 0x3 /* floating overflow */ #define FPE_FLTDIV_TRAP 0x4 /* floating/decimal divide by zero */ #define FPE_FLTUND_TRAP 0x5 /* floating underflow */ #define FPE_DECOVF_TRAP 0x6 /* decimal overflow */ #define FPE_SUBRNG_TRAP 0x7 /* subscript out of range */ #define FPE_FLTOVF_FAULT 0x8 /* floating overflow fault */ #define FPE_FLTDIV_FAULT 0x9 /* divide by zero floating fault */ #define FPE_FLTUND_FAULT 0xa /* floating underflow fault */ #ifdef pdp11 #define FPE_CRAZY 0xb /* illegal return code - FPU crazy */ #define FPE_OPCODE_TRAP 0xc /* bad floating point op code */ #define FPE_OPERAND_TRAP 0xd /* bad floating point operand */ #define FPE_MAINT_TRAP 0xe /* maintenance trap */ #endif #define SIGKILL 9 /* kill (cannot be caught or ignored) */ #define SIGBUS 10 /* bus error */ #define SIGSEGV 11 /* segmentation violation */ #define SIGSYS 12 /* bad argument to system call */ #define SIGPIPE 13 /* write on a pipe with no one to read it */ #define SIGALRM 14 /* alarm clock */ #define SIGTERM 15 /* software termination signal from kill */ #define SIGURG 16 /* urgent condition on IO channel */ #define SIGSTOP 17 /* sendable stop signal not from tty */ #define SIGTSTP 18 /* stop signal from tty */ #define SIGCONT 19 /* continue a stopped process */ #define SIGCHLD 20 /* to parent on child stop or exit */ #define SIGCLD SIGCHLD /* compatibility */ #define SIGTTIN 21 /* to readers pgrp upon background tty read */ #define SIGTTOU 22 /* like TTIN for output if (tp->t_local<OSTOP) */ #define SIGIO 23 /* input/output possible signal */ #define SIGXCPU 24 /* exceeded CPU time limit */ #define SIGXFSZ 25 /* exceeded file size limit */ #define SIGVTALRM 26 /* virtual time alarm */ #define SIGPROF 27 /* profiling time alarm */ #define SIGWINCH 28 /* window size changes */ #define SIGUSR1 30 /* user defined signal 1 */ #define SIGUSR2 31 /* user defined signal 2 */ #ifndef KERNEL int (*signal())(); #endif /* * Signal vector "template" used in sigvec call. */ struct sigvec { int (*sv_handler)(); /* signal handler */ long sv_mask; /* signal mask to apply */ int sv_flags; /* see signal options below */ }; #define SV_ONSTACK 0x0001 /* take signal on signal stack */ #define SV_INTERRUPT 0x0002 /* do not restart system on signal return */ #define sv_onstack sv_flags /* isn't compatibility wonderful! */ /* * Structure used in sigstack call. */ struct sigstack { char *ss_sp; /* signal stack pointer */ int ss_onstack; /* current status */ }; /* * Information pushed on stack when a signal is delivered. * This is used by the kernel to restore state following * execution of the signal handler. It is also made available * to the handler to allow it to properly restore state if * a non-standard exit is performed. */ struct sigcontext { int sc_onstack; /* sigstack state to restore */ long sc_mask; /* signal mask to restore */ int sc_sp; /* sp to restore */ int sc_fp; /* fp to restore */ int sc_r1; /* r1 to restore */ int sc_r0; /* r0 to restore */ int sc_pc; /* pc to restore */ int sc_ps; /* psl to restore */ int sc_ovno /* overlay to restore */ }; #define BADSIG (int (*)())-1 #define SIG_DFL (int (*)())0 #define SIG_IGN (int (*)())1 #ifdef KERNEL #define SIG_CATCH (int (*)())2 #define SIG_HOLD (int (*)())3 #endif #endif /* * Macro for converting signal number to a mask suitable for * sigblock(). */ #define sigmask(m) ((long)1 << ((m)-1)) #ifndef KERNEL extern long sigblock(), sigsetmask(); #endif below */ sys/h/socket.h 444 0 0 12522 6037103714 6534 /* * Copyright (c) 1982, 1985, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)socket.h 7.2.2 (2.11BSD GTE) 1995/10/11 */ #ifndef _SYS_SOCKET_H_ #define _SYS_SOCKET_H_ /* * Definitions related to sockets: types, address families, options. */ /* * Types */ #define SOCK_STREAM 1 /* stream socket */ #define SOCK_DGRAM 2 /* datagram socket */ #define SOCK_RAW 3 /* raw-protocol interface */ #define SOCK_RDM 4 /* reliably-delivered message */ #define SOCK_SEQPACKET 5 /* sequenced packet stream */ /* * Option flags per-socket. */ #define SO_DEBUG 0x0001 /* turn on debugging info recording */ #define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ #define SO_REUSEADDR 0x0004 /* allow local address reuse */ #define SO_KEEPALIVE 0x0008 /* keep connections alive */ #define SO_DONTROUTE 0x0010 /* just use interface addresses */ #define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */ #define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */ #define SO_LINGER 0x0080 /* linger on close if data present */ #define SO_OOBINLINE 0x0100 /* leave received OOB data in line */ /* * Additional options, not kept in so_options. */ #define SO_SNDBUF 0x1001 /* send buffer size */ #define SO_RCVBUF 0x1002 /* receive buffer size */ #define SO_SNDLOWAT 0x1003 /* send low-water mark */ #define SO_RCVLOWAT 0x1004 /* receive low-water mark */ #define SO_SNDTIMEO 0x1005 /* send timeout */ #define SO_RCVTIMEO 0x1006 /* receive timeout */ #define SO_ERROR 0x1007 /* get error status and clear */ #define SO_TYPE 0x1008 /* get socket type */ /* * Structure used for manipulating linger option. */ struct linger { int l_onoff; /* option on/off */ int l_linger; /* linger time */ }; /* * Level number for (get/set)sockopt() to apply to socket itself. */ #define SOL_SOCKET 0xffff /* options for socket level */ /* * Address families. */ #define AF_UNSPEC 0 /* unspecified */ #define AF_UNIX 1 /* local to host (pipes, portals) */ #define AF_INET 2 /* internetwork: UDP, TCP, etc. */ #define AF_IMPLINK 3 /* arpanet imp addresses */ #define AF_PUP 4 /* pup protocols: e.g. BSP */ #define AF_CHAOS 5 /* mit CHAOS protocols */ #define AF_NS 6 /* XEROX NS protocols */ #define AF_NBS 7 /* nbs protocols */ #define AF_ECMA 8 /* european computer manufacturers */ #define AF_DATAKIT 9 /* datakit protocols */ #define AF_CCITT 10 /* CCITT protocols, X.25 etc */ #define AF_SNA 11 /* IBM SNA */ #define AF_DECnet 12 /* DECnet */ #define AF_DLI 13 /* Direct data link interface */ #define AF_LAT 14 /* LAT */ #define AF_HYLINK 15 /* NSC Hyperchannel */ #define AF_APPLETALK 16 /* Apple Talk */ #define AF_MAX 17 /* * Structure used by kernel to store most * addresses. */ struct sockaddr { u_short sa_family; /* address family */ char sa_data[14]; /* up to 14 bytes of direct address */ }; /* * Structure used by kernel to pass protocol * information in raw sockets. */ struct sockproto { u_short sp_family; /* address family */ u_short sp_protocol; /* protocol */ }; /* * Protocol families, same as address families for now. */ #define PF_UNSPEC AF_UNSPEC #define PF_UNIX AF_UNIX #define PF_INET AF_INET #define PF_IMPLINK AF_IMPLINK #define PF_PUP AF_PUP #define PF_CHAOS AF_CHAOS #define PF_NS AF_NS #define PF_NBS AF_NBS #define PF_ECMA AF_ECMA #define PF_DATAKIT AF_DATAKIT #define PF_CCITT AF_CCITT #define PF_SNA AF_SNA #define PF_DECnet AF_DECnet #define PF_DLI AF_DLI #define PF_LAT AF_LAT #define PF_HYLINK AF_HYLINK #define PF_APPLETALK AF_APPLETALK #define PF_MAX AF_MAX /* * Definitions for network related sysctl, CTL_NET. * * Second level is protocol family. * Third level is protocol number. * * Further levels are defined by the individual families below. */ #define NET_MAXID AF_MAX #ifndef KERNEL #define CTL_NET_NAMES { \ { 0, 0 }, \ { "unix", CTLTYPE_NODE }, \ { "inet", CTLTYPE_NODE }, \ { "implink", CTLTYPE_NODE }, \ { "pup", CTLTYPE_NODE }, \ { "chaos", CTLTYPE_NODE }, \ { "xerox_ns", CTLTYPE_NODE }, \ { "iso", CTLTYPE_NODE }, \ { "emca", CTLTYPE_NODE }, \ { "datakit", CTLTYPE_NODE }, \ { "ccitt", CTLTYPE_NODE }, \ { "ibm_sna", CTLTYPE_NODE }, \ { "decnet", CTLTYPE_NODE }, \ { "dec_dli", CTLTYPE_NODE }, \ { "lat", CTLTYPE_NODE }, \ { "hylink", CTLTYPE_NODE }, \ { "appletalk", CTLTYPE_NODE }, \ } #endif /* * Maximum queue length specifiable by listen. */ #define SOMAXCONN 5 /* * Message header for recvmsg and sendmsg calls. */ struct msghdr { caddr_t msg_name; /* optional address */ int msg_namelen; /* size of address */ struct iovec *msg_iov; /* scatter/gather array */ int msg_iovlen; /* # elements in msg_iov */ caddr_t msg_accrights; /* access rights sent/received */ int msg_accrightslen; }; #define MSG_OOB 0x1 /* process out-of-band data */ #define MSG_PEEK 0x2 /* peek at incoming message */ #define MSG_DONTROUTE 0x4 /* send without using routing tables */ #define MSG_MAXIOVLEN 16 #endif /* _SYS_SOCKET_H_ */ , }; #endif /* * The arguments to the ctlinput routine are * (*protosw[].pr_ctlinput)(cmd, sa, arg); * where cmd is one of the commands below, sa is a pointer to a sockadsys/h/stat.h 444 0 12 5555 5731222142 6227 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)stat.h 7.1.4 (2.11BSD) 1995/03/13 */ #ifndef _STAT_H_ #define _STAT_H_ struct stat { dev_t st_dev; ino_t st_ino; unsigned short st_mode; short st_nlink; uid_t st_uid; gid_t st_gid; dev_t st_rdev; off_t st_size; time_t st_atime; int st_spare1; time_t st_mtime; int st_spare2; time_t st_ctime; int st_spare3; long st_blksize; long st_blocks; u_short st_flags; u_short st_spare4[3]; }; #define S_IFMT 0170000 /* type of file */ #define S_IFDIR 0040000 /* directory */ #define S_IFCHR 0020000 /* character special */ #define S_IFBLK 0060000 /* block special */ #define S_IFREG 0100000 /* regular */ #define S_IFLNK 0120000 /* symbolic link */ #define S_IFSOCK 0140000/* socket */ #define S_ISUID 0004000 /* set user id on execution */ #define S_ISGID 0002000 /* set group id on execution */ #define S_ISVTX 0001000 /* save swapped text even after use */ #define S_IREAD 0000400 /* read permission, owner */ #define S_IWRITE 0000200 /* write permission, owner */ #define S_IEXEC 0000100 /* execute/search permission, owner */ /* * Definitions of flags in mode that are 4.4 compatible. */ #define S_IFIFO 0010000 /* named pipe (fifo) - Not used by 2.11BSD */ #define S_IRWXU 0000700 /* RWX mask for owner */ #define S_IRUSR 0000400 /* R for owner */ #define S_IWUSR 0000200 /* W for owner */ #define S_IXUSR 0000100 /* X for owner */ #define S_IRWXG 0000070 /* RWX mask for group */ #define S_IRGRP 0000040 /* R for group */ #define S_IWGRP 0000020 /* W for group */ #define S_IXGRP 0000010 /* X for group */ #define S_IRWXO 0000007 /* RWX mask for other */ #define S_IROTH 0000004 /* R for other */ #define S_IWOTH 0000002 /* W for other */ #define S_IXOTH 0000001 /* X for other */ /* * Definitions of flags stored in file flags word. Different from 4.4 because * 2.11BSD only could afford a u_short for the flags. It is not a great * inconvenience since there are still 5 bits in each byte available for * future use. * * Super-user and owner changeable flags. */ #define UF_SETTABLE 0x00ff /* mask of owner changeable flags */ #define UF_NODUMP 0x0001 /* do not dump file */ #define UF_IMMUTABLE 0x0002 /* file may not be changed */ #define UF_APPEND 0x0004 /* writes to file may only append */ /* * Super-user changeable flags. */ #define SF_SETTABLE 0xff00 /* mask of superuser changeable flags */ #define SF_ARCHIVED 0x0100 /* file is archived */ #define SF_IMMUTABLE 0x0200 /* file may not be changed */ #define SF_APPEND 0x0400 /* writes to file may only append */ #ifdef KERNEL /* * Shorthand abbreviations of above. */ #define APPEND (UF_APPEND | SF_APPEND) #define IMMUTABLE (UF_IMMUTABLE | SF_IMMUTABLE) #endif #endif /* !_STAT_H_ */ family; /* address family */ u_short sp_protocol; /* protocol */ }; /* * Protocol families, same as address families for now. */ #define PF_Usys/h/syslog.h 644 0 12 14216 5737437526 6634 /* * Copyright (c) 1982, 1986, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)syslog.h 8.1.1 (2.11BSD) 1995/04/01 * $Id: syslog.h,v 1.4 1994/08/21 04:42:00 paul Exp $ */ #ifndef _SYS_SYSLOG_H_ #define _SYS_SYSLOG_H_ #define _PATH_LOG "/dev/log" /* * priorities/facilities are encoded into a single 16-bit quantity, where the * bottom 3 bits are the priority (0-7) and the top 13 bits are the facility * (0-big number). Both the priorities and the facilities map roughly * one-to-one to strings in the syslogd(8) source code. This mapping is * included in this file. * * priorities (these are ordered) */ #define LOG_EMERG 0 /* system is unusable */ #define LOG_ALERT 1 /* action must be taken immediately */ #define LOG_CRIT 2 /* critical conditions */ #define LOG_ERR 3 /* error conditions */ #define LOG_WARNING 4 /* warning conditions */ #define LOG_NOTICE 5 /* normal but significant condition */ #define LOG_INFO 6 /* informational */ #define LOG_DEBUG 7 /* debug-level messages */ #define LOG_PRIMASK 0x07 /* mask to extract priority part (internal) */ /* extract priority */ #define LOG_PRI(p) ((p) & LOG_PRIMASK) #define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri)) #ifdef SYSLOG_NAMES #define INTERNAL_NOPRI 0x10 /* the "no priority" priority */ /* mark "facility" */ #define INTERNAL_MARK LOG_MAKEPRI(LOG_NFACILITIES, 0) typedef struct _code { char *c_name; int c_val; } CODE; CODE prioritynames[] = { "alert", LOG_ALERT, "crit", LOG_CRIT, "debug", LOG_DEBUG, "emerg", LOG_EMERG, "err", LOG_ERR, "error", LOG_ERR, /* DEPRECATED */ "info", LOG_INFO, "none", INTERNAL_NOPRI, /* INTERNAL */ "notice", LOG_NOTICE, "panic", LOG_EMERG, /* DEPRECATED */ "warn", LOG_WARNING, /* DEPRECATED */ "warning", LOG_WARNING, NULL, -1, }; #endif /* facility codes */ #define LOG_KERN (0<<3) /* kernel messages */ #define LOG_USER (1<<3) /* random user-level messages */ #define LOG_MAIL (2<<3) /* mail system */ #define LOG_DAEMON (3<<3) /* system daemons */ #define LOG_AUTH (4<<3) /* security/authorization messages */ #define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */ #define LOG_LPR (6<<3) /* line printer subsystem */ #define LOG_NEWS (7<<3) /* network news subsystem */ #define LOG_UUCP (8<<3) /* UUCP subsystem */ #define LOG_CRON (9<<3) /* clock daemon */ #define LOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */ #define LOG_FTP (11<<3) /* ftp daemon */ /* other codes through 15 reserved for system use */ #define LOG_LOCAL0 (16<<3) /* reserved for local use */ #define LOG_LOCAL1 (17<<3) /* reserved for local use */ #define LOG_LOCAL2 (18<<3) /* reserved for local use */ #define LOG_LOCAL3 (19<<3) /* reserved for local use */ #define LOG_LOCAL4 (20<<3) /* reserved for local use */ #define LOG_LOCAL5 (21<<3) /* reserved for local use */ #define LOG_LOCAL6 (22<<3) /* reserved for local use */ #define LOG_LOCAL7 (23<<3) /* reserved for local use */ #define LOG_NFACILITIES 24 /* current number of facilities */ #define LOG_FACMASK 0x03f8 /* mask to extract facility part */ /* facility of pri */ #define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3) #ifdef SYSLOG_NAMES CODE facilitynames[] = { "auth", LOG_AUTH, "authpriv", LOG_AUTHPRIV, "cron", LOG_CRON, "daemon", LOG_DAEMON, "ftp", LOG_FTP, "kern", LOG_KERN, "lpr", LOG_LPR, "mail", LOG_MAIL, "mark", INTERNAL_MARK, /* INTERNAL */ "news", LOG_NEWS, "security", LOG_AUTH, /* DEPRECATED */ "syslog", LOG_SYSLOG, "user", LOG_USER, "uucp", LOG_UUCP, "local0", LOG_LOCAL0, "local1", LOG_LOCAL1, "local2", LOG_LOCAL2, "local3", LOG_LOCAL3, "local4", LOG_LOCAL4, "local5", LOG_LOCAL5, "local6", LOG_LOCAL6, "local7", LOG_LOCAL7, NULL, -1, }; #endif #ifdef KERNEL #define LOG_PRINTF -1 /* pseudo-priority to indicate use of printf */ #endif /* * arguments to setlogmask. */ #define LOG_MASK(pri) (1 << (pri)) /* mask for one priority */ #define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1) /* all priorities through pri */ /* * Option flags for openlog. * * LOG_ODELAY no longer does anything. * LOG_NDELAY is the inverse of what it used to be. */ #define LOG_PID 0x01 /* log the pid with each message */ #define LOG_CONS 0x02 /* log on the console if errors in sending */ #define LOG_ODELAY 0x04 /* delay open until first syslog() (default) */ #define LOG_NDELAY 0x08 /* don't delay open */ #define LOG_NOWAIT 0x10 /* don't wait for console forks: DEPRECATED */ #define LOG_PERROR 0x20 /* log to stderr as well */ #endif _ROUTEDEAD 1 /* select new route if possible */ #define PRC_QUENCH 4 /* some said to slow down */ #define PRC_MSGSIZE 5 /* message size forced drop */ #define PRC_HOSTDEAD 6 /* normally from IMP */ #define PRC_HOSTUNREACH 7 /* ditto */ #define PRC_UNREACH_NET 8 /* no route to network */ #define PRC_UNREACH_HOST 9 /* no route to host */ #define PRC_UNREACH_PROTOCsys/h/systm.h 444 0 12 6423 5710102140 6416 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)systm.h 1.2 (2.11BSD GTE) 12/29/94 */ #ifndef SUPERVISOR /* * The `securelevel' variable controls the security level of the system. * It can only be decreased by process 1 (/sbin/init). * * Security levels are as follows: * -1 permannently insecure mode - always run system in level 0 mode. * 0 insecure mode - immutable and append-only flags make be turned off. * All devices may be read or written subject to permission modes. * 1 secure mode - immutable and append-only flags may not be changed; * raw disks of mounted filesystems, /dev/mem, and /dev/kmem are * read-only. * 2 highly secure mode - same as (1) plus raw disks are always * read-only whether mounted or not. This level precludes tampering * with filesystems by unmounting them, but also inhibits running * newfs while the system is secured. * * In normal operation, the system runs in level 0 mode while single user * and in level 1 mode while multiuser. If level 2 mode is desired while * running multiuser, it can be set in the multiuser startup script * (/etc/rc.local) using sysctl(8). If it is desired to run the system * in level 0 mode while multiuser, initialize the variable securelevel * in /sys/kern/kern_sysctl.c to -1. Note that it is NOT initialized to * zero as that would allow the vmunix binary to be patched to -1. * Without initialization, securelevel loads in the BSS area which only * comes into existence when the kernel is loaded and hence cannot be * patched by a stalking hacker. */ extern int securelevel; /* system security level */ extern char version[]; /* system version */ /* * Nblkdev is the number of entries (rows) in the block switch. * Used in bounds checking on major device numbers. */ int nblkdev; /* * Number of character switch entries. */ int nchrdev; int mpid; /* generic for unique process id's */ char runin; /* scheduling flag */ char runout; /* scheduling flag */ int runrun; /* scheduling flag */ char curpri; /* more scheduling */ u_int maxmem; /* actual max memory per process */ u_int nswap; /* size of swap space */ int updlock; /* lock for sync */ daddr_t rablock; /* block to be read ahead */ dev_t rootdev; /* device of the root */ dev_t dumpdev; /* device to take dumps on */ long dumplo; /* offset into dumpdev */ dev_t swapdev; /* swapping device */ dev_t pipedev; /* pipe device */ extern int icode[]; /* user init code */ extern int szicode; /* its size */ daddr_t bmap(); ubadr_t clstaddr; /* UNIBUS virtual address of clists */ extern int cputype; /* type of cpu = 40, 44, 45, 60, or 70 */ /* * Structure of the system-entry table */ extern struct sysent { char sy_narg; /* total number of arguments */ int (*sy_call)(); /* handler */ } sysent[]; int noproc; /* no one is running just now */ char *panicstr; int boothowto; /* reboot flags, from boot */ int selwait; /* casts to keep lint happy */ #ifdef lint #define insque(q,p) _insque((caddr_t)q,(caddr_t)p) #define remque(q) _remque((caddr_t)q) #endif extern bool_t sep_id; /* separate I/D */ extern char regloc[]; /* offsets of saved user registers (trap.c) */ #endif ved for local use */ #define LOG_LOCAL2 (18<<3) /* reserved for local use */ #define LOG_LOCAL3 (19<<3) /* reserved for local use */ #define LOG_LOCAL4 (20<<3) /* reserved for local use */ #define LOG_LOCAL5 (21<<3) /* reserved for localsys/h/text.h 444 0 12 4074 5710102161 6226 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)text.h 1.2 (2.11BSD GTE) 1/19/95 */ #ifndef _SYS_TEXT_H_ #define _SYS_TEXT_H_ /* * Text structure. XXX REF COUNT should be short * One allocated per pure * procedure on swap device. * Manipulated by text.c */ struct text { struct text *x_forw; /* forward link in free list */ struct text **x_back; /* backward link in free list */ short x_daddr; /* segment's disk address */ short x_caddr; /* core address, if loaded */ size_t x_size; /* size (clicks) */ struct inode *x_iptr; /* inode of prototype */ u_char x_count; /* reference count */ u_char x_ccount; /* number of loaded references */ u_char x_flag; /* traced, written flags */ char dummy; /* room for one more */ }; #if defined(KERNEL) && !defined(SUPERVISOR) extern struct text text[], *textNTEXT; int ntext; #endif #define XTRC 0x01 /* Text may be written, exclusive use */ #define XWRIT 0x02 /* Text written into, must swap out */ #define XLOAD 0x04 /* Currently being read from file */ #define XLOCK 0x08 /* Being swapped in or out */ #define XWANT 0x10 /* Wanted for swapping */ #define XPAGI 0x20 /* Page in on demand from inode */ #define XUNUSED 0x40 /* unused since swapped out for cache */ /* arguments to xswap: */ #define X_OLDSIZE (-1) /* the old size is the same as current */ #define X_DONTFREE 0 /* save core image (for parent in newproc) */ #define X_FREECORE 1 /* free core space after swap */ /* * Text table statistics */ struct xstats { u_long alloc; /* calls to xalloc */ u_long alloc_inuse; /* found in use/sticky */ u_long alloc_cachehit; /* found in cache */ u_long alloc_cacheflush; /* flushed cached text */ u_long alloc_unused; /* flushed unused cached text */ u_long free; /* calls to xfree */ u_long free_inuse; /* still in use/sticky */ u_long free_cache; /* placed in cache */ u_long free_cacheswap; /* swapped out to place in cache */ }; #endif /* _SYS_TEXT_H_ */ t; /* scheduling flag */ int runrun; /* scheduling flag */ char curpri; /* more scheduling */ u_int maxmem; /* actual max memory per process */ u_int nswap; /* size of swap space */ int updlock; /* lock for sync */ daddr_t rablock; /* block to be read ahead */ dev_t rootdev; /* device of the root */ dev_t dumpdev; /* device to take dumps on */ long dumplo; /* offset into dumpdev */ dev_t swapdev; /* swapping device */ dev_t pipedsys/h/uba.h 444 0 12 3566 5321523454 6030 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)uba.h 1.2 (2.11BSD GTE) 1/3/93 */ /* * Structure to access UNIBUS map registers. */ struct ubmap { short ub_lo; short ub_hi; }; #ifdef UCB_METER /* * Structure for metering mapalloc performance. */ struct ubmeter { long ub_calls; /* total # of calls to mapalloc */ long ub_remaps; /* total # of buffer remappings */ long ub_fails; /* total # of allocation failures */ long ub_pages; /* total # of pages allocated */ }; #endif #define UBMAP ((struct ubmap *) 0170200) #define UBPAGE 020000 /* size of UNIBUS map segment */ /* * BUF_UBADDR is the UNIBUS address of buffers * if we have a UNIBUS map, as distinguished from bpaddr, * which is the physical address in clicks. */ #define BUF_UBADDR 020000 /* * Bytes to UNIBUS pages. */ #define btoub(b) ((((long)(b)) + ((long)(UBPAGE - 1))) / ((long)UBPAGE)) /* * Number of UNIBUS registers required by n objects of size s. */ #define nubreg(n,s) (((long) (n) * (long) (s) + \ ((long) (UBPAGE - 1))) / (long) UBPAGE) /* * Set UNIBUS register r to point at physical address p (in bytes). */ #define setubregno(r,p) { \ UBMAP[r].ub_lo = loint(p); \ UBMAP[r].ub_hi = hiint(p); \ } /* * Point the appropriate UNIBUS register at a kernel * virtual data address (in clicks). V must be less * than btoc(248K). */ #define pointubreg(v,sep) { ubadr_t x; \ short regno; \ regno = ((v) >> 7) & 037; \ x = (ubadr_t) (v) & ~01; \ UBMAP[regno].ub_lo = loint (x); \ UBMAP[regno].ub_hi = hiint (x); \ } #ifdef KERNEL extern short ubmap; /* Do we have UNIBUS registers? */ extern memaddr bpaddr; /* physical click-address of buffers */ extern struct map ub_map[]; extern int ub_wantmr; #endif calls to xfree */ u_long free_inuse; /* still in use/sticky */ u_long free_cache; /* placed in cache */ u_long free_cacheswap; /* swsys/h/time.h 444 0 12 3551 5710102176 6205 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)time.h 1.2 (2.11BSD GTE) 1/14/95 */ #ifndef _SYS_TIME_H_ #define _SYS_TIME_H_ /* * Structure returned by gettimeofday(2) system call, * and used in other calls. */ struct timeval { long tv_sec; /* seconds */ long tv_usec; /* and microseconds */ }; struct timezone { int tz_minuteswest; /* minutes west of Greenwich */ int tz_dsttime; /* type of dst correction */ }; #define DST_NONE 0 /* not on dst */ #define DST_USA 1 /* USA style dst */ #define DST_AUST 2 /* Australian style dst */ #define DST_WET 3 /* Western European dst */ #define DST_MET 4 /* Middle European dst */ #define DST_EET 5 /* Eastern European dst */ #define DST_CAN 6 /* Canada */ /* * Operations on timevals. * * NB: timercmp does not work for >= or <=. */ #define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) #define timercmp(tvp, uvp, cmp) \ ((tvp)->tv_sec cmp (uvp)->tv_sec || \ (tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec) #define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 /* * Names of the interval timers, and structure * defining a timer setting. */ #define ITIMER_REAL 0 #define ITIMER_VIRTUAL 1 #define ITIMER_PROF 2 struct k_itimerval { long it_interval; /* timer interval */ long it_value; /* current value */ }; struct itimerval { struct timeval it_interval; /* timer interval */ struct timeval it_value; /* current value */ }; #ifndef KERNEL #include #endif /* * Getkerninfo clock information structure */ struct clockinfo { int hz; /* clock frequency */ int tick; /* micro-seconds per hz tick */ int stathz; /* statistics clock frequency */ int profhz; /* profiling clock frequency */ }; #endif /* !_SYS_TIME_H_ */ ntmr; #endif calls to xfree */ u_long free_inuse; /* still in use/sticky */ u_long free_cache; /* placed in cache */ u_long free_cacheswap; /* swsys/h/timeb.h 444 0 12 574 4053130004 6317 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)timeb.h 7.1 (Berkeley) 6/4/86 */ /* * Structure returned by ftime system call */ struct timeb { time_t time; unsigned short millitm; short timezone; short dstflag; }; tags.ldisk.hh3 vmmeter.h2 vmsystm.h1 vmparam.h0trace.hh/ ttydefaults.h.inode.hlt- disksys/h/ttychars.h 444 0 12 2465 4053130004 7101 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ttychars.h 7.1 (Berkeley) 6/4/86 */ /* * User visible structures and constants * related to terminal handling. */ #ifndef _TTYCHARS_ #define _TTYCHARS_ struct ttychars { char tc_erase; /* erase last character */ char tc_kill; /* erase entire line */ char tc_intrc; /* interrupt */ char tc_quitc; /* quit */ char tc_startc; /* start output */ char tc_stopc; /* stop output */ char tc_eofc; /* end-of-file */ char tc_brkc; /* input delimiter (like nl) */ char tc_suspc; /* stop process signal */ char tc_dsuspc; /* delayed stop process signal */ char tc_rprntc; /* reprint line */ char tc_flushc; /* flush output (toggles) */ char tc_werasc; /* word erase */ char tc_lnextc; /* literal next character */ }; #define CTRL(c) ('c'&037) /* default special characters */ #define CERASE 0177 #define CKILL CTRL(u) #define CINTR CTRL(c) #define CQUIT 034 /* FS, ^\ */ #define CSTART CTRL(q) #define CSTOP CTRL(s) #define CEOF CTRL(d) #define CEOT CEOF #define CBRK 0377 #define CSUSP CTRL(z) #define CDSUSP CTRL(y) #define CRPRNT CTRL(r) #define CFLUSH CTRL(o) #define CWERASE CTRL(w) #define CLNEXT CTRL(v) #endif handling. */ #ifndef _TTYCHARS_ #define _TTYCHARS_ struct ttychars { char tc_erase; /* erase last character */ char tc_kill; /* erase entire line */ char tc_intrc; /* interrupt */ char tc_quitc; /*sys/h/types.h 444 0 12 4251 5666030262 6417 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)types.h 1.3 (2.11BSD Berkeley) 11/26/94 */ #ifndef _TYPES_ #define _TYPES_ /* * Basic system types and major/minor device constructing/busting macros. */ /* major part of a device */ #define major(x) ((int)(((int)(x)>>8)&0377)) /* minor part of a device */ #define minor(x) ((int)((x)&0377)) /* make a device number */ #define makedev(x,y) ((dev_t)(((x)<<8) | (y))) typedef unsigned char u_char; typedef unsigned short u_short; typedef unsigned int u_int; typedef unsigned long u_long; /* see this! unsigned longs at last! */ typedef unsigned short ushort; /* sys III compat */ #ifdef pdp11 typedef struct _physadr { short r[1]; } *physadr; typedef struct label_t { int val[8]; /* regs 2-7, __ovno and super SP */ } label_t; #endif typedef struct _quad { long val[2]; } quad; typedef long daddr_t; typedef char * caddr_t; typedef u_short ino_t; typedef long swblk_t; typedef u_int size_t; typedef long time_t; typedef short dev_t; typedef long off_t; typedef u_short uid_t; typedef u_short gid_t; typedef int pid_t; typedef u_short mode_t; #define NBBY 8 /* number of bits in a byte */ /* * Select uses bit masks of file descriptors in longs. * These macros manipulate such bit fields (the filesystem macros use chars). * FD_SETSIZE may be defined by the user, but the default here * should be >= NOFILE (param.h). */ #ifndef FD_SETSIZE #define FD_SETSIZE 32 #endif typedef long fd_mask; #define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ #ifndef howmany #define howmany(x, y) (((x)+((y)-1))/(y)) #endif typedef struct fd_set { fd_mask fds_bits[1]; } fd_set; #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1L << ((n) % NFDBITS))) #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1L << ((n) % NFDBITS))) #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1L << ((n) % NFDBITS))) #define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) typedef char bool_t; /* boolean */ typedef u_int memaddr; /* core or swap address */ typedef long ubadr_t; /* unibus address */ #endif xmem; /* actual max memory per process */ u_int nswap; /* size of swap space */ int updlock; /* lock for sync */ daddr_t rablock; /* block to be read ahead */ dev_t rootdev; /* device of the root */ dev_t dumpdev; /* device to take dumps on */ long dumplo; /* offset into dumpdev */ dev_t swapdev; /* swapping device */ dev_t pipedsys/h/user.h 444 0 12 12155 4607016765 6261 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)user.h 1.1 (2.10BSD Berkeley) 12/1/86 */ #ifdef KERNEL #include "../machine/fperr.h" #include "dir.h" #include "exec.h" #include "time.h" #include "resource.h" #include "namei.h" #else #include #include #include #include #include #include #endif /* * data that doesn't need to be referenced while the process is swapped. * The user block is USIZE*64 bytes long; resides at virtual kernel loc * 0140000; contains the system stack (and possibly network stack) per * user; is cross referenced with the proc structure for the same process. */ #define MAXCOMLEN MAXNAMLEN /* <= MAXNAMLEN, >= sizeof(ac_comm) */ struct pcb { /* fake pcb structure */ int (*pcb_sigc)(); /* pointer to trampoline code in user space */ }; struct fps { short u_fpsr; /* FP status register */ double u_fpregs[6]; /* FP registers */ }; struct user { struct pcb u_pcb; struct fps u_fps; short u_fpsaved; /* FP regs saved for this proc */ struct fperr u_fperr; /* floating point error save */ struct proc *u_procp; /* pointer to proc structure */ int *u_ar0; /* address of users saved R0 */ char u_comm[MAXCOMLEN + 1]; /* syscall parameters, results and catches */ int u_arg[6]; /* arguments to current system call */ int *u_ap; /* pointer to arglist */ label_t u_qsave; /* for non-local gotos on interrupts */ union { /* syscall return values */ struct { int R_val1; int R_val2; } u_rv; #define r_val1 u_rv.R_val1 #define r_val2 u_rv.R_val2 long r_long; off_t r_off; time_t r_time; } u_r; char u_error; /* return error code */ char u_eosys; /* special action on end of syscall */ /* 1.1 - processes and protection */ uid_t u_uid; /* effective user id */ uid_t u_ruid; /* real user id */ gid_t u_gid; /* effective group id */ gid_t u_rgid; /* real group id */ gid_t u_groups[NGROUPS]; /* groups, 0 terminated */ /* 1.2 - memory management */ size_t u_tsize; /* text size (clicks) */ size_t u_dsize; /* data size (clicks) */ size_t u_ssize; /* stack size (clicks) */ label_t u_ssave; /* label variable for swapping */ label_t u_rsave; /* save info when exchanging stacks */ short u_uisa[16]; /* segmentation address prototypes */ short u_uisd[16]; /* segmentation descriptor prototypes */ char u_sep; /* flag for I and D separation */ char dummy1; /* room for another char */ /* overlay information */ struct u_ovd { /* automatic overlay data */ short uo_curov; /* current overlay */ short uo_ovbase; /* base of overlay area, seg. */ u_short uo_dbase; /* start of data, clicks */ u_short uo_ov_offst[NOVL+1]; /* overlay offsets in text */ short uo_nseg; /* number of overlay seg. regs. */ } u_ovdata; /* 1.3 - signal management */ int (*u_signal[NSIG])(); /* disposition of signals */ long u_sigmask[NSIG]; /* signals to be blocked */ long u_sigonstack; /* signals to take on sigstack */ long u_sigintr; /* signals that interrupt syscalls */ long u_oldmask; /* saved mask from before sigpause */ int u_code; /* ``code'' to trap */ struct sigstack u_sigstack; /* sp & on stack state variable */ #define u_onstack u_sigstack.ss_onstack #define u_sigsp u_sigstack.ss_sp /* 1.4 - descriptor management */ struct file *u_ofile[NOFILE]; /* file structures for open files */ char u_pofile[NOFILE]; /* per-process flags of open files */ int u_lastfile; /* high-water mark of u_ofile */ #define UF_EXCLOSE 0x1 /* auto-close on exec */ #define UF_MAPPED 0x2 /* mapped from device */ struct inode *u_cdir; /* current directory */ struct inode *u_rdir; /* root directory of current process */ struct tty *u_ttyp; /* controlling tty pointer */ dev_t u_ttyd; /* controlling tty dev */ short u_cmask; /* mask for file creation */ /* 1.5 - timing and statistics */ struct k_rusage u_ru; /* stats for this proc */ struct k_rusage u_cru; /* sum of stats for reaped children */ struct k_itimerval u_timer[2]; /* profile/virtual timers */ long u_start; char u_acflag; char dummy2; /* room for another char */ struct uprof { /* profile arguments */ short *pr_base; /* buffer base */ unsigned pr_size; /* buffer size */ unsigned pr_off; /* pc offset */ unsigned pr_scale; /* pc scaling */ } u_prof; /* 1.6 - resource controls */ struct rlimit u_rlimit[RLIM_NLIMITS]; struct quota *u_quota; /* user's quota structure */ /* namei & co. */ struct nameicache { /* last successful directory search */ off_t nc_prevoffset; /* offset at which last entry found */ ino_t nc_inumber; /* inum of cached directory */ dev_t nc_dev; /* dev of cached directory */ } u_ncache; struct nameidata u_nd; short u_stack[1]; /* kernel stack per user * extends from u + USIZE*64 * backward not to reach here */ }; #define JUSTRETURN 1 #define RESTARTSYS 2 #define NORMALRETURN 3 /* u_error codes */ #ifdef KERNEL #include "errno.h" #else #include #endif #ifdef KERNEL extern struct user u; #endif log to stderr as well */ #endif _ROUTEDEAD 1 /* select new route if possible */ #define PRC_QUENCH 4 /* some said to slow down */ #define PRC_MSGSIZE 5 /* message size forced drop */ #define PRC_HOSTDEAD 6 /* normally from IMP */ #define PRC_HOSTUNREACH 7 /* ditto */ #define PRC_UNREACH_NET 8 /* no route to network */ #define PRC_UNREACH_HOST 9 /* no route to host */ #define PRC_UNREACH_PROTOCsys/h/vm.h 444 0 12 1073 4053451227 5671 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)vm.h 7.1 (Berkeley) 6/4/86 */ /* * #include "../h/vm.h" * or #include in a user program * is a quick way to include all the vm header files. */ #ifdef KERNEL #include "vmparam.h" #include "vmmac.h" #include "vmmeter.h" #include "vmsystm.h" #else #include #include #include #include #endif eferenced while the pcess is swapped. * The user block is USIZE*64 bytes long; resides at virtual kernel loc * 0140000; contains the system stack (and possibly network stack) per * user; is cross referenced with the proc structure for the same process. */ #define MAXCOMLEN MAXNAMLEN /* <= MAXNAMLEN, >= sizeof(ac_comm) */ struct pcb { /* fake pcb structure */ int (*pcb_sigc)(); /* pointer to trampoline code in user space */ }; struct fps {sys/h/wait.h 444 0 12 5110 5772704636 6225 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)wait.h 7.2.1 (2.11BSD GTE) 1995/06/23 */ /* * This file holds definitions relevent to the wait system call. * Some of the options here are available only through the ``wait3'' * entry point; the old entry point with one argument has more fixed * semantics, never returning status of unstopped children, hanging until * a process terminates if any are outstanding, and never returns * detailed information about process resource utilization (). */ /* * Structure of the information in the first word returned by both * wait and wait3. If w_stopval==WSTOPPED, then the second structure * describes the information returned, else the first. See WUNTRACED below. */ union wait { int w_status; /* used in syscall */ /* * Terminated process status. */ struct { unsigned short w_Termsig:7; /* termination signal */ unsigned short w_Coredump:1; /* core dump indicator */ unsigned short w_Retcode:8; /* exit code if w_termsig==0 */ } w_T; /* * Stopped process status. Returned * only for traced children unless requested * with the WUNTRACED option bit. */ struct { unsigned short w_Stopval:8; /* == W_STOPPED if stopped */ unsigned short w_Stopsig:8; /* signal that stopped us */ } w_S; }; #define w_termsig w_T.w_Termsig #define w_coredump w_T.w_Coredump #define w_retcode w_T.w_Retcode #define w_stopval w_S.w_Stopval #define w_stopsig w_S.w_Stopsig #define WSTOPPED 0177 /* value of s.stopval if process is stopped */ /* * Option bits for the second argument of wait3. WNOHANG causes the * wait to not hang if there are no stopped or terminated processes, rather * returning an error indication in this case (pid==0). WUNTRACED * indicates that the caller should receive status about untraced children * which stop due to signals. If children are stopped and a wait without * this option is done, it is as though they were still running... nothing * about them is returned. */ #define WNOHANG 1 /* dont hang in wait */ #define WUNTRACED 2 /* tell about stopped, untraced children */ #define WIFSTOPPED(x) ((x).w_stopval == WSTOPPED) #define WIFSIGNALED(x) ((x).w_stopval != WSTOPPED && (x).w_termsig != 0) #define WIFEXITED(x) ((x).w_stopval != WSTOPPED && (x).w_termsig == 0) #define WEXITSTATUS(x) ((x).w_retcode) #define W_STOPCODE(sig) ((sig << 8) | WSTOPPED) #define W_EXITCODE(ret,sig) ((ret << 8) | (sig)) #define WAIT_ANY (-1) #define WAIT_MYPGRP 0 /* overlay information */ struct u_ovd { /* automatic overlay data */ short uo_curov; /* current overlay */ short uo_ovbase; /* base of overlay area, seg. */ u_short uo_dbase; /* start of data, clicks */ u_short uo_ov_offst[NOVL+1]; /* overlay offsets in text */ short uo_nseg; /* number of overlay seg. regs. */ } u_ovdata; /* 1.3 - signal management */ int (*u_signal[NSIG])(); /* disposition of signals */ long u_sigmasksys/h/kernel.h 444 0 12 1206 5350245515 6527 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)kernel.h 1.2 (2.11BSD GTE) 12/24/92 */ /* * Global variables for the kernel */ #ifdef SUPERVISOR long startnet; /* start of network data space */ #else memaddr malloc(); /* 1.1 */ long hostid; char hostname[MAXHOSTNAMELEN]; int hostnamelen; /* 1.2 */ struct timeval boottime; struct timeval time; struct timezone tz; /* XXX */ int adjdelta; int hz; int lbolt; /* awoken once a second */ int realitexpire(); short avenrun[3]; #endif zation (). */ /* * Structure of the information in the first word returned by both * wait and wait3. If w_stopval==WSTOPPED, then the second structure * describes the information returned, else the first. See WUNTRACED below. */ union wait { int w_status; /* used in syscall */ /* * Terminated process status. */ struct { unsigned short w_Termsig:7; sys/h/ptrace.h 444 0 12 1505 4053130006 6512 /* * Copyright (c) 1980, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ptrace.h 7.1 (Berkeley) 6/4/86 */ #ifndef _PTRACE_ #define _PTRACE_ #define PT_TRACE_ME 0 /* child declares it's being traced */ #define PT_READ_I 1 /* read word in child's I space */ #define PT_READ_D 2 /* read word in child's D space */ #define PT_READ_U 3 /* read word in child's user structure */ #define PT_WRITE_I 4 /* write word in child's I space */ #define PT_WRITE_D 5 /* write word in child's D space */ #define PT_WRITE_U 6 /* write word in child's user structure */ #define PT_CONTINUE 7 /* continue the child */ #define PT_KILL 8 /* kill the child process */ #define PT_STEP 9 /* single step the child */ #endif ion returned, else the first. See WUNTRACED below. */ union wait { int w_status; /* used in syscall */ /* * Terminated process status. */ struct { unsigned short w_Termsig:7; sys/h/dk.h 444 0 12 2227 4304046452 5646 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dk.h 7.1 (Berkeley) 6/4/86 */ /* * Instrumentation */ #define CPUSTATES 4 #define CP_USER 0 #define CP_NICE 1 #define CP_SYS 2 #define CP_IDLE 3 #define DK_NDRIVE 10 #if defined(KERNEL) && defined(UCB_METER) && !defined(SUPERVISOR) long cp_time[CPUSTATES]; /* number of ticks spent in each cpu state */ int dk_ndrive; /* number of drives being monitored */ int dk_busy; /* bit array of drive busy flags */ long dk_time[DK_NDRIVE]; /* ticks spent with drive busy */ long dk_seek[DK_NDRIVE]; /* number of seeks */ long dk_xfer[DK_NDRIVE]; /* number of transfers */ long dk_wds[DK_NDRIVE]; /* number of clicks transfered */ long dk_wps[DK_NDRIVE]; /* words per second */ char *dk_name[DK_NDRIVE]; /* names of monitored drives */ int dk_unit[DK_NDRIVE]; /* unit numbers of monitored drives */ int dk_n; /* number of dk numbers assigned so far */ long tk_nin; /* number of tty characters input */ long tk_nout; /* number of tty characters output */ #endif /* * Stopped process status. Returned * only for traced children unless requested * with the WUNTRACED option bit. */ struct { unsigned short w_Stopval:8; /* == W_STOPPED if stopped */ unsigned short w_Stopsig:8; /* signal that stopped us */ } w_S; }; #define w_termsig w_T.w_Termsig #define w_coredump w_T.w_Coredump #define w_retcode w_T.w_Resys/h/times.h 444 0 12 722 4053130006 6335 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)times.h 7.1 (Berkeley) 6/4/86 */ /* * Structure returned by times() */ struct tms { time_t tms_utime; /* user time */ time_t tms_stime; /* system time */ time_t tms_cutime; /* user time, children */ time_t tms_cstime; /* system time, children */ }; / ttydefaults.h.inode.hlt- disksys/h/vmmac.h 444 0 12 566 4053130006 6325 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)vmmac.h 1.1 (2.10 Berkeley) 12/1/86 */ /* Average new into old with aging factor time */ #define ave(smooth, cnt, time) \ smooth = ((time - 1) * (smooth) + (cnt)) / (time) m tags.ldisk.hh3 vmmeter.h2 vmsystm.h1 vmparam.h0trace.hh/ ttydefaults.h.inode.hlt- disksys/h/exec.h 444 0 12 2354 5513434046 6200 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)exec.h 1.2 (2.11BSD GTE) 10/31/93 */ #ifndef _EXEC_ #define _EXEC_ /* * Header prepended to each a.out file. */ struct exec { int a_magic; /* magic number */ unsigned int a_text; /* size of text segment */ unsigned int a_data; /* size of initialized data */ unsigned int a_bss; /* size of uninitialized data */ unsigned int a_syms; /* size of symbol table */ unsigned int a_entry; /* entry point */ unsigned int a_unused; /* not used */ unsigned int a_flag; /* relocation info stripped */ }; #define NOVL 15 /* number of overlays */ struct ovlhdr { int max_ovl; /* maximum overlay size */ unsigned int ov_siz[NOVL]; /* size of i'th overlay */ }; /* * eXtended header definition for use with the new macros in a.out.h */ struct xexec { struct exec e; struct ovlhdr o; }; #define A_MAGIC1 0407 /* normal */ #define A_MAGIC2 0410 /* read-only text */ #define A_MAGIC3 0411 /* separated I&D */ #define A_MAGIC4 0405 /* overlay */ #define A_MAGIC5 0430 /* auto-overlay (nonseparate) */ #define A_MAGIC6 0431 /* auto-overlay (separate) */ #endif ted * with the WUNTRACED option bit. */ struct { unsigned short w_Stopval:8; /* == W_STOPPED if stopped */ unsigned short w_Stopsig:8; /* signal that stopped us */ } w_S; }; #define w_termsig w_T.w_Termsig #define w_coredump w_T.w_Coredump #define w_retcode w_T.w_Resys/h/msgbuf.h 444 0 12 727 4467464054 6532 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)msgbuf.h 1.1 (2.10BSD Berkeley) 12/1/86 */ #define MSG_MAGIC 0x063061 #define MSG_BSIZE 4096 struct msgbuf { long msg_magic; int msg_bufx; int msg_bufr; u_short msg_click; char *msg_bufc; }; #if defined(KERNEL) && !defined(SUPERVISOR) struct msgbuf msgbuf; #endif ttydefaults.h.inode.hlt- disksys/h/domain.h 444 0 0 1725 4263751575 6513 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)domain.h 7.2 (Berkeley) 12/30/87 */ /* * Structure per communications domain. */ struct domain { int dom_family; /* AF_xxx */ char *dom_name; int (*dom_init)(); /* initialize domain data structures */ int (*dom_externalize)(); /* externalize access rights */ int (*dom_dispose)(); /* dispose of internalized rights */ struct protosw *dom_protosw, *dom_protoswNPROTOSW; struct domain *dom_next; }; #ifdef SUPERVISOR struct domain *domains; #endif o; }; #define A_MAGIC1 0407 /* normal */ sys/h/gprof.h 444 0 12 4264 4053130006 6356 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)gprof.h 7.1 (Berkeley) 6/4/86 */ struct phdr { char *lpc; char *hpc; int ncnt; }; /* * histogram counters are unsigned shorts (according to the kernel). */ #define HISTCOUNTER unsigned short /* * fraction of text space to allocate for histogram counters * here, 1/2 */ #define HISTFRACTION 2 /* * Fraction of text space to allocate for from hash buckets. * The value of HASHFRACTION is based on the minimum number of bytes * of separation between two subroutine call points in the object code. * Given MIN_SUBR_SEPARATION bytes of separation the value of * HASHFRACTION is calculated as: * * HASHFRACTION = MIN_SUBR_SEPARATION / (2 * sizeof(short) - 1); * * For the VAX, the shortest two call sequence is: * * calls $0,(r0) * calls $0,(r0) * * which is separated by only three bytes, thus HASHFRACTION is * calculated as: * * HASHFRACTION = 3 / (2 * 2 - 1) = 1 * * Note that the division above rounds down, thus if MIN_SUBR_FRACTION * is less than three, this algorithm will not work! * * NB: for the kernel we assert that the shortest two call sequence is: * * calls $0,_name * calls $0,_name * * which is separated by seven bytes, thus HASHFRACTION is calculated as: * * HASHFRACTION = 7 / (2 * 2 - 1) = 2 */ #define HASHFRACTION 2 /* * percent of text space to allocate for tostructs * with a minimum. */ #define ARCDENSITY 2 #define MINARCS 50 struct tostruct { char *selfpc; long count; unsigned short link; }; /* * a raw arc, * with pointers to the calling site and the called site * and a count. */ struct rawarc { unsigned long raw_frompc; unsigned long raw_selfpc; long raw_count; }; /* * general rounding functions. */ #define ROUNDDOWN(x,y) (((x)/(y))*(y)) #define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y)) pped, untraced children */ #define WIFSTOPPED(x) ((x).w_stopval == WSTOPPED) #define WIFSIGNALED(x) ((x).w_stopval != WSTOPPED && (x).w_termsig != 0) #define WIFEXITED(x) ((x).w_stopval != WSTOPPED && (x).w_termsig == 0) #define WEXITSTATUS(x) ((x).w_retcode) #define W_STOPCODE(sig) ((sig << 8) | WSTOPPED) #define W_EXITCODE(retsys/h/socketvar.h 444 0 0 12465 5514434711 7256 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)socketvar.h 7.3.1 (2.11BSD GTE) 12/31/93 */ /* * Kernel structure per socket. * Contains send and receive buffer queues, * handle on protocol and pointer to protocol * private data and error information. */ struct socket { short so_type; /* generic type, see socket.h */ short so_options; /* from socket call, see socket.h */ short so_linger; /* time to linger while closing */ short so_state; /* internal state flags SS_*, below */ caddr_t so_pcb; /* protocol control block */ struct protosw *so_proto; /* protocol handle */ /* * Variables for connection queueing. * Socket where accepts occur is so_head in all subsidiary sockets. * If so_head is 0, socket is not related to an accept. * For head socket so_q0 queues partially completed connections, * while so_q is a queue of connections ready to be accepted. * If a connection is aborted and it has so_head set, then * it has to be pulled out of either so_q0 or so_q. * We allow connections to queue up based on current queue lengths * and limit on number of queued connections for this socket. */ struct socket *so_head; /* back pointer to accept socket */ struct socket *so_q0; /* queue of partial connections */ struct socket *so_q; /* queue of incoming connections */ short so_q0len; /* partials on so_q0 */ short so_qlen; /* number of connections on so_q */ short so_qlimit; /* max number queued connections */ short so_timeo; /* connection timeout */ u_short so_error; /* error affecting connection */ short so_pgrp; /* pgrp for signals */ u_short so_oobmark; /* chars to oob mark */ /* * Variables for socket buffering. */ struct sockbuf { u_short sb_cc; /* actual chars in buffer */ u_short sb_hiwat; /* max actual char count */ u_short sb_mbcnt; /* chars of mbufs used */ u_short sb_mbmax; /* max chars of mbufs to use */ u_short sb_lowat; /* low water mark (not used yet) */ struct mbuf *sb_mb; /* the mbuf chain */ struct proc *sb_sel; /* process selecting read/write */ short sb_timeo; /* timeout (not used yet) */ short sb_flags; /* flags, see below */ } so_rcv, so_snd; #ifdef pdp11 #define SB_MAX 8192 /* max chars in sockbuf */ #else #define SB_MAX (64*1024) /* max chars in sockbuf */ #endif #define SB_LOCK 0x01 /* lock on data queue (so_rcv only) */ #define SB_WANT 0x02 /* someone is waiting to lock */ #define SB_WAIT 0x04 /* someone is waiting for data/space */ #define SB_SEL 0x08 /* buffer is selected */ #define SB_COLL 0x10 /* collision selecting */ }; /* * Socket state bits. */ #define SS_NOFDREF 0x001 /* no file table ref any more */ #define SS_ISCONNECTED 0x002 /* socket connected to a peer */ #define SS_ISCONNECTING 0x004 /* in process of connecting to peer */ #define SS_ISDISCONNECTING 0x008 /* in process of disconnecting */ #define SS_CANTSENDMORE 0x010 /* can't send more data to peer */ #define SS_CANTRCVMORE 0x020 /* can't receive more data from peer */ #define SS_RCVATMARK 0x040 /* at mark on input */ #define SS_PRIV 0x080 /* privileged for broadcast, raw... */ #define SS_NBIO 0x100 /* non-blocking ops */ #define SS_ASYNC 0x200 /* async i/o notify */ /* * Macros for sockets and socket buffering. */ /* how much space is there in a socket buffer (so->so_snd or so->so_rcv) */ #define sbspace(sb) \ (MIN((int)((sb)->sb_hiwat - (sb)->sb_cc),\ (int)((sb)->sb_mbmax - (sb)->sb_mbcnt))) /* do we have to send all at once on a socket? */ #define sosendallatonce(so) \ ((so)->so_proto->pr_flags & PR_ATOMIC) /* can we read something from so? */ #define soreadable(so) \ ((so)->so_rcv.sb_cc || ((so)->so_state & SS_CANTRCVMORE) || \ (so)->so_qlen || (so)->so_error) /* can we write something to so? */ #define sowriteable(so) \ (sbspace(&(so)->so_snd) > 0 && \ (((so)->so_state&SS_ISCONNECTED) || \ ((so)->so_proto->pr_flags&PR_CONNREQUIRED)==0) || \ ((so)->so_state & SS_CANTSENDMORE) || \ (so)->so_error) /* adjust counters in sb reflecting allocation of m */ #define sballoc(sb, m) { \ (sb)->sb_cc += (m)->m_len; \ (sb)->sb_mbcnt += MSIZE; \ if ((m)->m_off > MMAXOFF) \ (sb)->sb_mbcnt += CLBYTES; \ } /* adjust counters in sb reflecting freeing of m */ #define sbfree(sb, m) { \ (sb)->sb_cc -= (m)->m_len; \ (sb)->sb_mbcnt -= MSIZE; \ if ((m)->m_off > MMAXOFF) \ (sb)->sb_mbcnt -= CLBYTES; \ } /* set lock on sockbuf sb */ #define sblock(sb) { \ while ((sb)->sb_flags & SB_LOCK) { \ (sb)->sb_flags |= SB_WANT; \ SLEEP((caddr_t)&(sb)->sb_flags, PZERO+1); \ } \ (sb)->sb_flags |= SB_LOCK; \ } /* release lock on sockbuf sb */ #define sbunlock(sb) { \ (sb)->sb_flags &= ~SB_LOCK; \ if ((sb)->sb_flags & SB_WANT) { \ (sb)->sb_flags &= ~SB_WANT; \ WAKEUP((caddr_t)&(sb)->sb_flags); \ } \ } #define sorwakeup(so) sowakeup((so), &(so)->so_rcv) #define sowwakeup(so) sowakeup((so), &(so)->so_snd) #ifdef SUPERVISOR struct socket *sonewconn(); #endif tack[1]; /* kernel stack per user * extends from u + USIZE*64 * backward not to reach here */ }; #define JUSTRETURN 1 #define RESTARTSYS 2 #define NORMALRETURN 3 /* u_error codes */ sys/h/tablet.h 444 0 12 4111 4053130007 6504 /* * Copyright (c) 1985, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)tablet.h 7.1 (Berkeley) 6/4/86 */ #ifndef _TABLET_ /* * Tablet line discipline. */ #ifdef KERNEL #include "../h/ioctl.h" #else #include #endif /* * Reads on the tablet return one of the following * structures, depending on the underlying tablet type. * The first two are defined such that a read of * sizeof (gtcopos) on a non-gtco tablet will return * meaningful info. The in-proximity bit is simulated * where the tablet does not directly provide the information. */ struct tbpos { int xpos, ypos; /* raw x-y coordinates */ short status; /* buttons/pen down */ #define TBINPROX 0100000 /* pen in proximity of tablet */ short scount; /* sample count */ }; struct gtcopos { int xpos, ypos; /* raw x-y coordinates */ short status; /* as above */ short scount; /* sample count */ short xtilt, ytilt; /* raw tilt */ short pressure; short pad; /* pad to longword boundary */ }; struct polpos { short p_x, p_y, p_z; /* raw 3-space coordinates */ short p_azi, p_pit, p_rol; /* azimuth, pitch, and roll */ short p_stat; /* status, as above */ char p_key; /* calculator input keyboard */ }; #define BIOSMODE _IOW(b, 1, int) /* set mode bit(s) */ #define BIOGMODE _IOR(b, 2, int) /* get mode bit(s) */ #define TBMODE 0xfff0 /* mode bits: */ #define TBPOINT 0x0010 /* single point */ #define TBRUN 0x0000 /* runs contin. */ #define TBSTOP 0x0020 /* shut-up */ #define TBGO 0x0000 /* ~TBSTOP */ #define TBTYPE 0x000f /* tablet type: */ #define TBUNUSED 0x0000 #define TBHITACHI 0x0001 /* hitachi tablet */ #define TBTIGER 0x0002 /* hitachi tiger */ #define TBGTCO 0x0003 /* gtco */ #define TBPOL 0x0004 /* polhemus 3space */ #define TBHDG 0x0005 /* hdg-1111b, low res */ #define TBHDGHIRES 0x0006 /* hdg-1111b, high res */ #define BIOSTYPE _IOW(b, 3, int) /* set tablet type */ #define BIOGTYPE _IOR(b, 4, int) /* get tablet type*/ #endif def pdp11 #define SB_MAX 8192 /* max chars in sockbuf */ #else #define SB_MAX (64*1024) /* max chars in sockbuf */ #endif #define SB_LOCK 0x01 /* lock on data queue (so_rcv only) */ #define SB_WANT 0x02 /* someone is waiting to lock */ #define SB_WAIT 0x04 /* someone is waiting for data/space */ #define SB_SEL 0x08 /* buffer is selected */ #define SB_COLL 0x10 /* collision selecting */ }; /* * Socket state bits. */ #defsys/h/un.h 444 0 0 1351 4235404065 5645 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)un.h 7.2 (Berkeley) 12/30/87 */ /* * Definitions for UNIX IPC domain. */ struct sockaddr_un { short sun_family; /* AF_UNIX */ char sun_path[108]; /* path name (gag) */ }; #ifdef SUPERVISOR int unp_discard(); #endif oordinates */ short status; /* buttons/pen down */ #define TBINPROX 0100000 /* pen in proximity of tablet */ short scount; /* sample count */ }; struct gtcopos { int xpos, ypos; /* raw x-y coordinates */ short status; /* as above */ short scount; /* sample count */ ssys/h/unpcb.h 444 0 0 4206 4235404146 6334 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)unpcb.h 7.2 (Berkeley) 1/7/88 */ /* * Protocol control block for an active * instance of a UNIX internal protocol. * * A socket may be associated with an inode in the * file system. If so, the unp_inode pointer holds * a reference count to this inode, which should be irele'd * when the socket goes away. * * A socket may be connected to another socket, in which * case the control block of the socket to which it is connected * is given by unp_conn. * * A socket may be referenced by a number of sockets (e.g. several * sockets may be connected to a datagram socket.) These sockets * are in a linked list starting with unp_refs, linked through * unp_nextref and null-terminated. Note that a socket may be referenced * by a number of other sockets and may also reference a socket (not * necessarily one which is referencing it). This generates * the need for unp_refs and unp_nextref to be separate fields. * * Stream sockets keep copies of receive sockbuf sb_cc and sb_mbcnt * so that changes in the sockbuf may be computed to modify * back pressure on the sender accordingly. */ struct unpcb { struct socket *unp_socket; /* pointer back to socket */ struct inode *unp_inode; /* if associated with file */ ino_t unp_ino; /* fake inode number */ struct unpcb *unp_conn; /* control block of connected socket */ struct unpcb *unp_refs; /* referencing socket linked list */ struct unpcb *unp_nextref; /* link in unp_refs list */ struct mbuf *unp_addr; /* bound address of socket */ int unp_cc; /* copy of rcv.sb_cc */ int unp_mbcnt; /* copy of rcv.sb_mbcnt */ }; #define sotounpcb(so) ((struct unpcb *)((so)->so_pcb)) lse #define SB_MAX (64*1024) /* max chars in sockbuf */ #endif #define SB_LOCK 0x01 /* lock on data queue (so_rcv only) */ #define SB_WANT 0x02 /* someone is waiting to lock */ #define SB_WAIT 0x04 /* someone is waiting for data/space */ #define SB_SEL 0x08 /* buffer is selected */ #define SB_COLL 0x10 /* collision selecting */ }; /* * Socket state bits. */ #defsys/h/vcmd.h 444 0 12 722 4107661132 6156 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)vcmd.h 7.1 (Berkeley) 6/4/86 */ #ifndef _IOCTL_ #ifdef KERNEL #include "ioctl.h" #else #include #endif #endif #define VPRINT 0100 #define VPLOT 0200 #define VPRINTPLOT 0400 #define VGETSTATE _IOR(v, 0, int) #define VSETSTATE _IOW(v, 1, int) / ttydefaults.h.inode.hlt- disksys/h/utsname.h 444 0 12 4366 5715072613 6737 /*- * Copyright (c) 1994 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chuck Karish of Mindcraft, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)utsname.h 8.1.1 (2.11BSD GTE) 2/4/95 */ #ifndef _SYS_UTSNAME_H #define _SYS_UTSNAME_H struct utsname { char sysname[128]; /* Name of this OS. */ char nodename[128]; /* Name of this network node. */ char release[128]; /* Release level. */ char version[128]; /* Version level. */ char machine[128]; /* Hardware type. */ }; #endif /* !_SYS_UTSNAME_H */ _rcv only) */ #define SB_WANT 0x02 /* someone is waiting to lock */ #define SB_WAIT 0x04 /* someone is waiting for data/space */ #define SB_SEL 0x08 /* buffer is selected */ #define SB_COLL 0x10 /* collision selecting */ }; /* * Socket state bits. */ #defsys/h/quota.h 444 0 12 13054 5350005713 6416 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)quota.h 7.1 (Berkeley) 6/4/86 */ /* * MELBOURNE DISC QUOTAS * * Various junk to do with various quotas (etc) imposed upon * the average user (big brother finally hits UNIX). * * The following structure exists in core for each logged on user. * It contains global junk relevant to that user's quotas. * * The u_quota field of each user struct contains a pointer to * the quota struct relevant to the current process, this is changed * by 'setuid' sys call, &/or by the Q_SETUID quota() call. */ struct quota { struct quota *q_forw, *q_back; /* hash chain, MUST be first */ short q_cnt; /* ref count (# processes) */ uid_t q_uid; /* real uid of owner */ int q_flags; /* struct management flags */ #define Q_LOCK 0x01 /* quota struct locked (for disc i/o) */ #define Q_WANT 0x02 /* issue a wakeup when lock goes off */ #define Q_NEW 0x04 /* new quota - no proc1 msg sent yet */ #define Q_NDQ 0x08 /* account has NO disc quota */ struct quota *q_freef, **q_freeb; struct dquot *q_dq[NMOUNT]; /* disc quotas for mounted filesys's */ }; #define NOQUOTA ((struct quota *) 0) #if defined(KERNEL) && defined(QUOTA) && !defined(SUPERVISOR) struct quota *quota, *quotaNQUOTA; int nquota; struct quota *getquota(), *qfind(); #endif /* * The following structure defines the format of the disc quota file * (as it appears on disc) - the file is an array of these structures * indexed by user number. The setquota sys call establishes the inode * for each quota file (a pointer is retained in the mount structure). * * The following constants define the number of warnings given a user * before the soft limits are treated as hard limits (usually resulting * in an allocation failure). The warnings are normally manipulated * each time a user logs in through the Q_DOWARN quota call. If * the user logs in and is under the soft limit the warning count * is reset to MAX_*_WARN, otherwise a message is printed and the * warning count is decremented. This makes MAX_*_WARN equivalent to * the number of logins before soft limits are treated as hard limits. */ #define MAX_IQ_WARN 3 #define MAX_DQ_WARN 3 struct dqblk { u_long dqb_bhardlimit; /* absolute limit on disc blks alloc */ u_long dqb_bsoftlimit; /* preferred limit on disc blks */ u_long dqb_curblocks; /* current block count */ u_short dqb_ihardlimit; /* maximum # allocated inodes + 1 */ u_short dqb_isoftlimit; /* preferred inode limit */ u_short dqb_curinodes; /* current # allocated inodes */ u_char dqb_bwarn; /* # warnings left about excessive disc use */ u_char dqb_iwarn; /* # warnings left about excessive inodes */ }; /* * The following structure records disc usage for a user on a filesystem. * There is one allocated for each quota that exists on any filesystem * for the current user. A cache is kept of other recently used entries. */ struct dquot { struct dquot *dq_forw, *dq_back;/* MUST be first entry */ union { struct quota *Dq_own; /* the quota that points to this */ struct { /* free list */ struct dquot *Dq_freef, **Dq_freeb; } dq_f; } dq_u; short dq_flags; #define DQ_LOCK 0x01 /* this quota locked (no MODS) */ #define DQ_WANT 0x02 /* wakeup on unlock */ #define DQ_MOD 0x04 /* this quota modified since read */ #define DQ_FAKE 0x08 /* no limits here, just usage */ #define DQ_BLKS 0x10 /* has been warned about blk limit */ #define DQ_INODS 0x20 /* has been warned about inode limit */ short dq_cnt; /* count of active references */ uid_t dq_uid; /* user this applies to */ dev_t dq_dev; /* filesystem this relates to */ struct dqblk dq_dqb; /* actual usage & quotas */ }; #define dq_own dq_u.Dq_own #define dq_freef dq_u.dq_f.Dq_freef #define dq_freeb dq_u.dq_f.Dq_freeb #define dq_bhardlimit dq_dqb.dqb_bhardlimit #define dq_bsoftlimit dq_dqb.dqb_bsoftlimit #define dq_curblocks dq_dqb.dqb_curblocks #define dq_ihardlimit dq_dqb.dqb_ihardlimit #define dq_isoftlimit dq_dqb.dqb_isoftlimit #define dq_curinodes dq_dqb.dqb_curinodes #define dq_bwarn dq_dqb.dqb_bwarn #define dq_iwarn dq_dqb.dqb_iwarn #define NODQUOT ((struct dquot *) 0) #define LOSTDQUOT ((struct dquot *) 1) #if defined(KERNEL) && defined(QUOTA) && !defined(SUPERVISOR) struct dquot *dquot, *dquotNDQUOT; int ndquot; struct dquot *discquota(), *inoquota(), *dqalloc(), *dqp(); #endif /* * Definitions for the 'quota' system call. */ #define Q_SETDLIM 1 /* set disc limits & usage */ #define Q_GETDLIM 2 /* get disc limits & usage */ #define Q_SETDUSE 3 /* set disc usage only */ #define Q_SYNC 4 /* update disc copy of quota usages */ #define Q_SETUID 16 /* change proc to use quotas for uid */ #define Q_SETWARN 25 /* alter inode/block warning counts */ #define Q_DOWARN 26 /* warn user about excessive space/inodes */ /* * Used in Q_SETDUSE. */ struct dqusage { u_short du_curinodes; u_long du_curblocks; }; /* * Used in Q_SETWARN. */ struct dqwarn { u_char dw_bwarn; u_char dw_iwarn; }; #if defined(KERNEL) && defined(QUOTA) && !defined(SUPERVISOR) #include "../machine/seg.h" struct qhash { struct qhash *qh_forw; struct qhash *qh_back; }; struct dqhead { struct dqhead *dqh_forw; struct dqhead *dqh_back; }; #define QUOTAMAP() mapseg5(quotreg, quotdesc) #define QUOTAUNMAP() normalseg5() memaddr quotreg; u_short quotdesc; struct dquot **ix_dquot; #define NQHASH 16 /* small power of 2 */ #define NDQHASH 37 /* 4.3bsd used 51 which isn't even prime */ #define NQUOTA 40 #define NDQUOT 150 #endif _isoftlimit; /* preferred inode limit */ u_short dqb_curinodes; /* current # allocated inodes */ u_char dqb_bwarn; /* # warnings left about excessive disc use */ u_char dqb_iwarn; /* # warnings left about excessive inodes */ }; /* * The following structure records disc usage for a user on a filesystem. * There is one allocated for each quota that exists on any filesystem * for the current user. A cache is kept of other recently used entries. */ struct dquosys/h/tags 751 0 12 0 6045325004 7613 2../sys/tagssys/h/disk.h 444 0 12 12052 5770221410 6214 /* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Lawrence Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)disk.h 8.1.2 (2.11BSD GTE) 1995/05/21 * * from: $Header: disk.h,v 1.5 92/11/19 04:33:03 torek Exp $ (LBL) */ #ifndef _SYS_DISK_H_ #define _SYS_DISK_H_ #include /* * Disk device structures. * * Note that this is only a preliminary outline. The final disk structures * may be somewhat different. * * Note: the 2.11BSD version is very different. The 4.4 version served * as the inspiration. I needed something similar but for slightly * different purposes. */ /* * Disk device structures. Rather than replicate driver specific variations * of the following in each driver it was made common here. * * Some of the flags are specific to various drivers. For example ALIVE and * ONLINE apply to MSCP devices more than to SMD devices while the SEEK flag * applies to the SMD (xp) driver but not to the MSCP driver. The rest * of the flags as well as the open partition bitmaps are usable by any disk * driver. One 'dkdevice' structure is needed for each disk drive supported * by a driver. * * The entire disklabel is not resident in the kernel address space. Only * the partition table is directly accessible by the kernel. The MSCP driver * does not care (or know) about the geometry of the disk. Not holding * the entire label in the kernel saved quite a bit of D space. Other drivers * which need geometry information from the label will have to map in the * label and copy out the geometry data they require. This is unlikely to * cause much overhead since labels are read and written infrequently - when * mounting a drive, assigning a label, running newfs, etc. */ struct dkdevice { int dk_bopenmask; /* block devices open */ int dk_copenmask; /* character devices open */ int dk_openmask; /* composite (bopen|copen) */ int dk_flags; /* label state see below */ memaddr dk_label; /* sector containing label */ struct partition dk_parts[MAXPARTITIONS]; /* inkernel portion */ }; #define DKF_OPENING 0x0001 /* drive is being opened */ #define DKF_CLOSING 0x0002 /* drive is being closed */ #define DKF_WANTED 0x0004 /* drive is being waited for */ #define DKF_ALIVE 0x0008 /* drive is alive */ #define DKF_ONLINE 0x0010 /* drive is online */ #define DKF_WLABEL 0x0020 /* label area is being written */ #define DKF_SEEK 0x0040 /* drive is seeking */ #define DKF_SWAIT 0x0080 /* waiting for seek to complete */ /* encoding of disk minor numbers, should be elsewhere... but better * here than in ufs_disksubr.c * * Note: the controller number in bits 6 and 7 of the minor device are NOT * removed. It is the responsibility of the driver to extract or mask * these bits. */ #define dkunit(dev) (minor(dev) >> 3) #define dkpart(dev) (minor(dev) & 07) #define dkminor(unit, part) (((unit) << 3) | (part)) #ifdef KERNEL char *readdisklabel(); int setdisklabel(); int writedisklabel(); #endif #endif /* _SYS_DISK_H_ */ clude #endif #ifdef KERNEL extern struct user u; #endif log to stderr as well */ #endif _ROUTEDEAD 1 /* select new route if possible */ #define PRC_QUENCH 4 /* some said to slow down */ #define PRC_MSGSIZE 5 /* message size forced drop */ #define PRC_HOSTDEAD 6 /* normally from IMP */ #define PRC_HOSTUNREACH 7 /* ditto */ #define PRC_UNREACH_NET 8 /* no route to network */ #define PRC_UNREACH_HOST 9 /* no route to host */ #define PRC_UNREACH_PROTOCsys/h/vmmeter.h 444 0 12 4545 4236254456 6745 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)vmmeter.h 7.1 (Berkeley) 6/4/86 */ /* * Virtual memory related instrumentation */ struct vmrate { #define v_first v_swtch u_short v_swtch; /* context switches */ u_short v_trap; /* calls to trap */ u_short v_syscall; /* calls to syscall() */ u_short v_intr; /* device interrupts */ u_short v_soft; /* software interrupts */ u_short v_pdma; /* pseudo-dma interrupts */ u_short v_ovly; /* overlay emts */ u_short v_fpsim; /* floating point simulator faults */ u_short v_pswpin; /* pages swapped in */ u_short v_pswpout; /* pages swapped out */ u_short v_pgin; /* pageins */ u_short v_pgout; /* pageouts */ #define v_last v_pswpout u_short v_swpin; /* swapins */ u_short v_swpout; /* swapouts */ }; struct vmsum { long v_swtch; /* context switches */ long v_trap; /* calls to trap */ long v_syscall; /* calls to syscall() */ long v_intr; /* device interrupts */ long v_soft; /* software interrupts */ long v_pdma; /* pseudo-dma interrupts */ long v_ovly; /* overlay emts */ long v_fpsim; /* floating point simulator faults */ long v_pswpin; /* pages swapped in */ long v_pswpout; /* pages swapped out */ long v_pgin; /* pageins */ long v_pgout; /* pageouts */ long v_swpin; /* swapins */ long v_swpout; /* swapouts */ }; #if defined(KERNEL) && defined(UCB_METER) && !defined(SUPERVISOR) struct vmrate cnt, rate; struct vmsum sum; #endif /* systemwide totals computed every five seconds */ struct vmtotal { short t_rq; /* length of the run queue */ short t_dw; /* jobs in ``disk wait'' (neg priority) */ short t_sl; /* jobs sleeping in core */ short t_sw; /* swapped out runnable/short block jobs */ long t_vm; /* total virtual memory, clicks */ long t_avm; /* active virtual memory, clicks */ size_t t_rm; /* total real memory, clicks */ size_t t_arm; /* active real memory, clicks */ long t_vmtxt; /* virtual memory used by text, clicks */ long t_avmtxt; /* active virtual memory used by text, clicks */ size_t t_rmtxt; /* real memory used by text, clicks */ size_t t_armtxt; /* active real memory used by text, clicks */ size_t t_free; /* free memory, kb */ }; #if defined(KERNEL) && !defined(SUPERVISOR) struct vmtotal total; #endif e /* * Disk device structures. * * Note that this is only a preliminary outline. The final disk structures * may be somewhat differsys/h/vmsystm.h 444 0 12 1574 5706400266 7002 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)vmsystm.h 7.2.1 (2.11BSD GTE) 1/15/95 */ /* * Miscellaneous virtual memory subsystem variables and structures. */ size_t freemem; /* remaining clicks of free memory */ #if defined(KERNEL) && defined(UCB_METER) && !defined(SUPERVISOR) u_short avefree; /* moving average of remaining free clicks */ u_short avefree30; /* 30 sec (avefree is 5 sec) moving average */ /* writable copies of tunables */ int maxslp; /* max sleep time before very swappable */ #endif /* * Fork/vfork accounting. */ struct forkstat { long cntfork; long cntvfork; long sizfork; long sizvfork; }; #if defined(KERNEL) && defined(UCB_METER) && !defined(SUPERVISOR) struct forkstat forkstat; #endif hort v_swpout; /* swapouts */ }; struct vmsum { long v_swtch; /* context switches */ long v_trap; /* calls to trap */ long v_syssys/h/vmparam.h 444 0 12 1512 5707631656 6725 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)vmparam.h 7.1.1 (2.11BSD GTE) 1/14/95 */ /* * Machine dependent constants */ #ifdef KERNEL #include "../machine/vmparam.h" #else #include #endif /* * CTL_VM identifiers */ #define VM_METER 1 /* struct vmmeter */ #define VM_LOADAVG 2 /* struct loadavg */ #define VM_SWAPMAP 3 /* struct mapent _swapmap[] */ #define VM_COREMAP 4 /* struct mapent _coremap[] */ #define VM_MAXID 5 /* number of valid vm ids */ #ifndef KERNEL #define CTL_VM_NAMES { \ { 0, 0 }, \ { "vmmeter", CTLTYPE_STRUCT }, \ { "loadavg", CTLTYPE_STRUCT }, \ { "swapmap", CTLTYPE_STRUCT }, \ { "coremap", CTLTYPE_STRUCT }, \ } #endif ined(SUPERVISOR) struct forkstat forkstat; #endif hort v_swpout; /* swapouts */ }; struct vmsum { long v_swtch; /* context switches */ long v_trap; /* calls to trap */ long v_syssys/h/trace.h 444 0 12 5460 4177667547 6376 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)trace.h 7.1 (Berkeley) 6/4/86 */ /* * File system buffer tracing points; all trace * * Slipped into 2.10 in about 15 minutes. Bears only a casual * relationship to the 4.X code, we just used the same names so * someone could do it right if they felt like it. Note that * the #defines aren't even sequentially numbered. */ #define TR_BREADHIT 0 /* buffer read found in cache */ #define TR_BREADMISS 1 /* buffer read not in cache */ #define TR_BWRITE 2 /* buffer written */ #define TR_BREADHITRA 3 /* buffer read-ahead found in cache */ #define TR_BREADMISSRA 4 /* buffer read-ahead not in cache */ #define TR_BRELSE 5 /* brelse */ #define TR_SWAPIO 6 /* swap i/o request arrives */ #define TR_NUM_210 7 /* size of array for 2.10BSD #define TR_XFODMISS 5 /* exe fod read */ #define TR_XFODHIT 6 /* exe fod read */ #define TR_BREALLOC 8 /* expand/contract a buffer */ /* * Memory allocator trace points; all trace the amount of memory involved */ #define TR_MALL 10 /* memory allocated */ /* * Paging trace points: all are */ #define TR_INTRANS 20 /* page intransit block */ #define TR_EINTRANS 21 /* page intransit wait done */ #define TR_FRECLAIM 22 /* reclaim from free list */ #define TR_RECLAIM 23 /* reclaim from loop */ #define TR_XSFREC 24 /* reclaim from free list instead of drum */ #define TR_XIFREC 25 /* reclaim from free list instead of fsys */ #define TR_WAITMEM 26 /* wait for memory in pagein */ #define TR_EWAITMEM 27 /* end memory wait in pagein */ #define TR_ZFOD 28 /* zfod page fault */ #define TR_EXFOD 29 /* exec fod page fault */ #define TR_VRFOD 30 /* vread fod page fault */ #define TR_CACHEFOD 31 /* fod in file system cache */ #define TR_SWAPIN 32 /* drum page fault */ #define TR_PGINDONE 33 /* page in done */ /* * System call trace points. */ #define TR_VADVISE 40 /* vadvise occurred with */ /* * Miscellaneous */ #define TR_STAMP 45 /* user said vtrace(VTR_STAMP, value); */ /* * This defines the size of the trace flags array. */ #define TR_NFLAGS 100 /* generous */ #define TRCSIZ 4096 /* * Specifications of the vtrace() system call, which takes one argument. */ #define VTRACE 64+51 #define VTR_DISABLE 0 /* set a trace flag to 0 */ #define VTR_ENABLE 1 /* set a trace flag to 1 */ #define VTR_VALUE 2 /* return value of a trace flag */ #define VTR_UALARM 3 /* set alarm to go off (sig 16) */ /* in specified number of hz */ #define VTR_STAMP 4 /* user specified stamp */ #if defined(KERNEL) && defined(UCB_METER) && !defined(SUPERVISOR) u_long tracebuf[TR_NUM_210]; #define trace(a) tracebuf[a]++; #else #define trace(a) ; #endif was made common here. * * Some of the flags are specific to various drivers. For example ALIVE and * ONLINE apply to MSCP devices more than to SMD devices while the SEEK flag * applies to the SMD (xp) drsys/h/ttydefaults.h 444 0 12 3120 4317617436 7623 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ttydefaults.h 1.1 (Berkeley) 3/25/88 */ /* * System wide defaults of terminal state. */ #ifndef _TTYDEFAULTS_ #define _TTYDEFAULTS_ #define CTRL(x) ('x'&037) /* * Control Character Defaults */ #define CEOF CTRL(d) #define CEOL POSIX_V_DISABLE #ifdef DECSTYLE_DEFAULTS #define CERASE 0177 #define CINTR CTRL(c) #define CKILL CTRL(u) #else #define CERASE CTRL(h) #define CINTR 0177 #define CKILL CTRL(x) #endif #define CMIN 1 #define CQUIT 034 /* FS, ^\ */ #define CSUSP CTRL(z) #define CTIME 1 #define CDSUSP CTRL(y) #define CSTART CTRL(q) #define CSTOP CTRL(s) #define CLNEXT CTRL(v) #define CFLUSHO CTRL(o) #define CWERASE CTRL(w) #define CREPRINT CTRL(r) #define CQUOTE '\\' #define CEOT CEOF #ifdef COMPAT_43 #define CBRK CEOL #define CRPRNT CREPRINT #define CFLUSH CFLUSHO #endif /* * Settings on first open of a tty. */ #define TTYDEF_IFLAG (BRKINT | ISTRIP | IMAXBEL | IEXTEN) #define TTYDEF_OFLAG (0) #define TTYDEF_LFLAG (ECHO | ICANON | ISIG) #define TTYDEF_CFLAG (CREAD | CS7 | PARENB) #define TTYDEF_SPEED (B9600) #endif /*_TTYDEFAULTS_*/ /* * Define TTYDEFCHARS to include an array of default control characters. */ #ifdef TTYDEFCHARS u_char ttydefchars[NCC] = { CEOF, CEOL, CEOL, CERASE, CWERASE, CKILL, CREPRINT, CQUOTE, CINTR, CQUIT, CSUSP, CDSUSP, CSTART, CSTOP, CLNEXT, CFLUSHO, CMIN, CTIME, POSIX_V_DISABLE, POSIX_V_DISABLE }; #endif /*TTYDEFCHARS*/ /* * Memory allocator trace points; all trace the amount of memory involved */ #define TR_MALL 10 /* memory allocated */ /* * Paging trace points: all are */ #define TR_INTRANS 20 /* page intransit block */ #define TR_EINTRANS 21 /* page intransit wait done */ #define TR_FRECLAIM 22 /* reclaim from free list */ #define TR_RECLAIM 23 /* reclaim from loop */ #define TR_XSFREC 24 /* reclaim from free list insteasys/h/inode.h 444 0 12 22214 5665561461 6401 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)inode.h 1.3 (2.11BSD GTE) 11/25/94 */ /* * The I node is the focus of all file activity in UNIX. * There is a unique inode allocated for each active file, * each current directory, each mounted-on file, text file, and the root. * An inode is 'named' by its dev/inumber pair. (iget/iget.c) * Data in icommon1 and icommon2 is read in from permanent inode on volume. */ /* * 28 of the di_addr address bytes are used; 7 addresses of 4 * bytes each: 4 direct (4Kb directly accessible) and 3 indirect. */ #define NDADDR 4 /* direct addresses in inode */ #define NIADDR 3 /* indirect addresses in inode */ #define NADDR (NDADDR + NIADDR) /* total addresses in inode */ struct icommon2 { time_t ic_atime; /* time last accessed */ time_t ic_mtime; /* time last modified */ time_t ic_ctime; /* time created */ }; struct inode { struct inode *i_chain[2]; /* must be first */ u_short i_flag; u_short i_count; /* reference count */ dev_t i_dev; /* device where inode resides */ ino_t i_number; /* i number, 1-to-1 with device address */ u_short i_id; /* unique identifier */ struct fs *i_fs; /* file sys associated with this inode */ union { struct { u_char I_shlockc; /* count of shared locks */ u_char I_exlockc; /* count of exclusive locks */ } i_l; struct proc *I_rsel; /* pipe read select */ } i_un0; union { struct text *I_text; /* text entry, if any */ struct proc *I_wsel; /* pipe write select */ } i_un1; union { daddr_t I_addr[NADDR]; /* normal file/directory */ struct { daddr_t I_db[NDADDR]; /* normal file/directory */ daddr_t I_ib[NIADDR]; } i_f; struct { /* * the dummy field is here so that the de/compression * part of the iget/iput routines works for special * files. */ u_short I_dummy; dev_t I_rdev; /* dev type */ } i_d; } i_un2; union { daddr_t if_lastr; /* last read (read-ahead) */ struct socket *is_socket; struct { struct inode *if_freef; /* free list forward */ struct inode **if_freeb; /* free list back */ } i_fr; } i_un3; struct icommon1 { u_short ic_mode; /* mode and type of file */ u_short ic_nlink; /* number of links to file */ uid_t ic_uid; /* owner's user id */ gid_t ic_gid; /* owner's group id */ off_t ic_size; /* number of bytes in file */ } i_ic1; /* * Can't afford another 4 bytes and mapping the flags out would be prohibitively * expensive. So, a 'u_short' is used for the flags - see the comments in * stat.h for more information. */ u_short i_flags; /* user changeable flags */ #ifndef EXTERNALITIMES struct icommon2 i_ic2; #endif }; /* * Inode structure as it appears on * a disk block. */ struct dinode { struct icommon1 di_icom1; daddr_t di_addr[7]; /* 7 block addresses 4 bytes each */ u_short di_reserved[5]; /* pad of 10 to make total size 64 */ u_short di_flags; struct icommon2 di_icom2; }; #define i_mode i_ic1.ic_mode #define i_nlink i_ic1.ic_nlink #define i_uid i_ic1.ic_uid #define i_gid i_ic1.ic_gid #define i_size i_ic1.ic_size #define i_shlockc i_un0.i_l.I_shlockc #define i_exlockc i_un0.i_l.I_exlockc #define i_rsel i_un0.I_rsel #define i_text i_un1.I_text #define i_wsel i_un1.I_wsel #define i_db i_un2.i_f.I_db #define i_ib i_un2.i_f.I_ib #ifndef EXTERNALITIMES #define i_atime i_ic2.ic_atime #define i_mtime i_ic2.ic_mtime #define i_ctime i_ic2.ic_ctime #endif #define i_rdev i_un2.i_d.I_rdev #define i_addr i_un2.I_addr #define i_dummy i_un2.i_d.I_dummy #define i_lastr i_un3.if_lastr #define i_socket i_un3.is_socket #define i_forw i_chain[0] #define i_back i_chain[1] #define i_freef i_un3.i_fr.if_freef #define i_freeb i_un3.i_fr.if_freeb #define di_ic1 di_icom1 #define di_ic2 di_icom2 #define di_mode di_ic1.ic_mode #define di_nlink di_ic1.ic_nlink #define di_uid di_ic1.ic_uid #define di_gid di_ic1.ic_gid #define di_size di_ic1.ic_size #define di_atime di_ic2.ic_atime #define di_mtime di_ic2.ic_mtime #define di_ctime di_ic2.ic_ctime #if defined(KERNEL) && !defined(SUPERVISOR) /* * Invalidate an inode. Used by the namei cache to detect stale * information. In order to save space and also reduce somewhat the * overhead - the i_id field is made into a u_short. If a pdp-11 can * invalidate 100 inodes per second, the cache will have to be invalidated * in about 11 minutes. Ha! * Assumes the cacheinvalall routine will map the namei cache. */ #define cacheinvalall _cinvall #define cacheinval(ip) \ (ip)->i_id = ++nextinodeid; \ if (nextinodeid == 0) \ cacheinvalall(); u_short nextinodeid; /* unique id generator */ #ifdef EXTERNALITIMES memaddr xitimes; u_int xitdesc; #endif struct inode inode[]; /* the inode table itself */ struct inode *inodeNINODE; /* the end of the inode table */ int ninode; /* the number of slots in the table */ struct inode *rootdir; /* pointer to inode of root directory */ struct inode *ialloc(); struct inode *iget(); struct inode *owner(); struct inode *maknode(); struct inode *namei(); #endif /* i_flag */ #define ILOCKED 0x1 /* inode is locked */ #define IUPD 0x2 /* file has been modified */ #define IACC 0x4 /* inode access time to be updated */ #define IMOUNT 0x8 /* inode is mounted on */ #define IWANT 0x10 /* some process waiting on lock */ #define ITEXT 0x20 /* inode is pure text prototype */ #define ICHG 0x40 /* inode has been changed */ #define ISHLOCK 0x80 /* file has shared lock */ #define IEXLOCK 0x100 /* file has exclusive lock */ #define ILWAIT 0x200 /* someone waiting on file lock */ #define IMOD 0x400 /* inode has been modified */ #define IRENAME 0x800 /* inode is being renamed */ #define IPIPE 0x1000 /* inode is a pipe */ #define IRCOLL 0x2000 /* read select collision on pipe */ #define IWCOLL 0x4000 /* write select collision on pipe */ #define IXMOD 0x8000 /* inode is text, but impure (XXX) */ /* i_mode */ #define IFMT 0170000 /* type of file */ #define IFCHR 0020000 /* character special */ #define IFDIR 0040000 /* directory */ #define IFBLK 0060000 /* block special */ #define IFREG 0100000 /* regular */ #define IFLNK 0120000 /* symbolic link */ #define IFSOCK 0140000 /* socket */ #define ISUID 04000 /* set user id on execution */ #define ISGID 02000 /* set group id on execution */ #define ISVTX 01000 /* save swapped text even after use */ #define IREAD 0400 /* read, write, execute permissions */ #define IWRITE 0200 #define IEXEC 0100 #if defined(KERNEL) && !defined(SUPERVISOR) /* * Flags for va_cflags. */ #define VA_UTIMES_NULL 0x01 /* utimes argument was NULL */ /* * Flags for ioflag. */ #define IO_UNIT 0x01 /* do I/O as atomic unit */ #define IO_APPEND 0x02 /* append write to end */ #define IO_SYNC 0x04 /* do I/O synchronously */ /* #define IO_NODELOCKED 0x08 /* not implemented */ #define IO_NDELAY 0x10 /* FNDELAY flag set in file table */ /* * Token indicating no attribute value yet assigned. */ #define VNOVAL (-1) #define VATTR_NULL(vp) (vattr_null(vp)) /* * This is a bit of a misnomer. 2.11BSD does not have 'vnodes' but it was * easier/simpler to keep the name 'vattr' than changing the name to something * like 'iattr'. * * This structure is a _subset_ of 4.4BSD's vnode attribute structure. ONLY * those attributes which can be *changed by the user* are present. Since we * do not have vnodes why initialize (and carry around) un-used members. * * NOTE: For reasons of speed the function 'vattr_null()' was written in * very compact assembly code and placed in pdp/mch_xxx.s. If you change * the 'vattr' structure be sure and change vattr_null in pdp/mch_xxx.s! */ struct vattr { mode_t va_mode; uid_t va_uid; gid_t va_gid; off_t va_size; time_t va_atime; time_t va_mtime; u_short va_flags; u_short va_vaflags; }; /* * N.B: If the above structure changes be sure to modify the function * vattr_null in pdp/mch_xxx.s! */ #endif #ifndef SUPERVISOR #define ILOCK(ip) { \ while ((ip)->i_flag & ILOCKED) { \ (ip)->i_flag |= IWANT; \ sleep((caddr_t)(ip), PINOD); \ } \ (ip)->i_flag |= ILOCKED; \ } #define IUNLOCK(ip) { \ (ip)->i_flag &= ~ILOCKED; \ if ((ip)->i_flag&IWANT) { \ (ip)->i_flag &= ~IWANT; \ wakeup((caddr_t)(ip)); \ } \ } #define IUPDAT(ip, t1, t2, waitfor) { \ if (ip->i_flag&(IUPD|IACC|ICHG|IMOD)) \ iupdat(ip, t1, t2, waitfor); \ } #ifdef EXTERNALITIMES #define ITIMES(ip, t1, t2) { \ if ((ip)->i_flag&(IUPD|IACC|ICHG)) { \ struct icommon2 *ic2= &((struct icommon2 *)SEG5)[ip-inode]; \ mapseg5(xitimes, xitdesc); \ (ip)->i_flag |= IMOD; \ if ((ip)->i_flag&IACC) \ ic2->ic_atime = (t1)->tv_sec; \ if ((ip)->i_flag&IUPD) \ ic2->ic_mtime = (t2)->tv_sec; \ if ((ip)->i_flag&ICHG) \ ic2->ic_ctime = time.tv_sec; \ (ip)->i_flag &= ~(IACC|IUPD|ICHG); \ normalseg5(); \ } \ } #else #define ITIMES(ip, t1, t2) { \ if ((ip)->i_flag&(IUPD|IACC|ICHG)) { \ (ip)->i_flag |= IMOD; \ if ((ip)->i_flag&IACC) \ (ip)->i_atime = (t1)->tv_sec; \ if ((ip)->i_flag&IUPD) \ (ip)->i_mtime = (t2)->tv_sec; \ if ((ip)->i_flag&ICHG) \ (ip)->i_ctime = time.tv_sec; \ (ip)->i_flag &= ~(IACC|IUPD|ICHG); \ } \ } #endif #endif evice where inode resides */ ino_t i_number; /* i number, 1-to-1 with device address */ u_short i_id; /* unique identifier */ struct fs *i_fs; /* file sys associated with this inode */ union { struct { u_char I_shlockc; /* count of shared locks */ u_char I_exlockc; /* count of exclusive locks */ } i_l; struct proc *I_rsel; /* pipe read select */ } i_unsys/h/disklabel.h 644 0 12 25222 5752055744 7240 /* * Copyright (c) 1987, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)disklabel.h 8.1.1 (2.11BSD) 1995/04/13 */ #ifndef _SYS_DISKLABEL_H_ #define _SYS_DISKLABEL_H_ /* * Disk description table, see disktab(5) */ #define _PATH_DISKTAB "/etc/disktab" #define DISKTAB "/etc/disktab" /* deprecated */ /* * Each disk has a label which includes information about the hardware * disk geometry, filesystem partitions, and drive specific information. * The label is in block 0 or 1, possibly offset from the beginning * to leave room for a bootstrap, etc. */ /* XXX these should be defined per controller (or drive) elsewhere, not here! */ #define LABELSECTOR 1 /* sector containing label */ #define LABELOFFSET 0 /* offset of label in sector */ #define DISKMAGIC ((u_long) 0x82564557) /* The disk magic number */ #define MAXPARTITIONS 8 /* * 2.11BSD's disklabels are different than 4.4BSD for a couple reasons: * * 1) D space is precious in the 2.11 kernel. Many of the fields do * not need to be a 'long' (or even a 'short'), a 'short' (or 'char') * is more than adequate. If anyone ever ports the FFS to a PDP11 * changing the label format will be the least of the problems. * * 2) There is no need to support a bootblock more than 512 bytes long. * The hardware (disk bootroms) only read the first sector, thus the * label is always at sector 1 (the second half of the first filesystem * block). * * Almost all of the fields have been retained but with reduced sizes. This * is for future expansion and to ease the porting of the various utilities * which use the disklabel structure. The 2.11 kernel uses very little other * than the partition tables. Indeed only the partition tables are resident * in the kernel address space, the actual label block is allocated external to * the kernel and mapped in as needed. */ struct disklabel { u_long d_magic; /* the magic number */ u_char d_type; /* drive type */ u_char d_subtype; /* controller/d_type specific */ char d_typename[16]; /* type name, e.g. "eagle" */ /* * d_packname contains the pack identifier and is returned when * the disklabel is read off the disk or in-core copy. * d_boot0 is the (optional) name of the primary (block 0) bootstrap * as found in /mdec. This is returned when using * getdiskbyname(3) to retrieve the values from /etc/disktab. */ #if defined(KERNEL) || defined(STANDALONE) char d_packname[16]; /* pack identifier */ #else union { char un_d_packname[16]; /* pack identifier */ char *un_d_boot0; /* primary bootstrap name */ } d_un; #define d_packname d_un.un_d_packname #define d_boot0 d_un.un_d_boot0 #endif /* ! KERNEL or STANDALONE */ /* disk geometry: */ u_short d_secsize; /* # of bytes per sector */ u_short d_nsectors; /* # of data sectors per track */ u_short d_ntracks; /* # of tracks per cylinder */ u_short d_ncylinders; /* # of data cylinders per unit */ u_short d_secpercyl; /* # of data sectors per cylinder */ u_long d_secperunit; /* # of data sectors per unit */ /* * Spares (bad sector replacements) below * are not counted in d_nsectors or d_secpercyl. * Spare sectors are assumed to be physical sectors * which occupy space at the end of each track and/or cylinder. */ u_short d_sparespertrack; /* # of spare sectors per track */ u_short d_sparespercyl; /* # of spare sectors per cylinder */ /* * Alternate cylinders include maintenance, replacement, * configuration description areas, etc. */ u_short d_acylinders; /* # of alt. cylinders per unit */ /* hardware characteristics: */ /* * d_interleave, d_trackskew and d_cylskew describe perturbations * in the media format used to compensate for a slow controller. * Interleave is physical sector interleave, set up by the formatter * or controller when formatting. When interleaving is in use, * logically adjacent sectors are not physically contiguous, * but instead are separated by some number of sectors. * It is specified as the ratio of physical sectors traversed * per logical sector. Thus an interleave of 1:1 implies contiguous * layout, while 2:1 implies that logical sector 0 is separated * by one sector from logical sector 1. * d_trackskew is the offset of sector 0 on track N * relative to sector 0 on track N-1 on the same cylinder. * Finally, d_cylskew is the offset of sector 0 on cylinder N * relative to sector 0 on cylinder N-1. */ u_short d_rpm; /* rotational speed */ u_char d_interleave; /* hardware sector interleave */ u_char d_trackskew; /* sector 0 skew, per track */ u_char d_cylskew; /* sector 0 skew, per cylinder */ u_char d_headswitch; /* head swith time, usec */ u_short d_trkseek; /* track-to-track seek, msec */ u_short d_flags; /* generic flags */ #define NDDATA 5 u_long d_drivedata[NDDATA]; /* drive-type specific information */ #define NSPARE 5 u_long d_spare[NSPARE]; /* reserved for future use */ u_long d_magic2; /* the magic number (again) */ u_short d_checksum; /* xor of data incl. partitions */ /* filesystem and partition information: */ u_short d_npartitions; /* number of partitions in following */ u_short d_bbsize; /* size of boot area at sn0, bytes */ u_short d_sbsize; /* max size of fs superblock, bytes */ struct partition { /* the partition table */ u_long p_size; /* number of sectors in partition */ u_long p_offset; /* starting sector */ u_short p_fsize; /* filesystem basic fragment size */ u_char p_fstype; /* filesystem type, see below */ u_char p_frag; /* filesystem fragments per block */ } d_partitions[MAXPARTITIONS]; /* actually may be more */ }; /* d_type values: */ #define DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */ #define DTYPE_MSCP 2 /* MSCP */ #define DTYPE_DEC 3 /* other DEC (rk, rl) */ #define DTYPE_SCSI 4 /* SCSI */ #define DTYPE_ESDI 5 /* ESDI interface */ #define DTYPE_ST506 6 /* ST506 etc. */ #define DTYPE_FLOPPY 7 /* floppy */ #ifdef DKTYPENAMES static char *dktypenames[] = { "unknown", "SMD", "MSCP", "old DEC", "SCSI", "ESDI", "ST506", "floppy", 0 }; #define DKMAXTYPES (sizeof(dktypenames) / sizeof(dktypenames[0]) - 1) #endif /* * Filesystem type and version. * Used to interpret other filesystem-specific * per-partition information. */ #define FS_UNUSED 0 /* unused */ #define FS_SWAP 1 /* swap */ #define FS_V6 2 /* Sixth Edition */ #define FS_V7 3 /* Seventh Edition */ #define FS_SYSV 4 /* System V */ /* * 2.11BSD uses type 5 filesystems even though block numbers are 4 bytes * (rather than the packed 3 byte format) and the directory structure is * that of 4.3BSD (long filenames). */ #define FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9, 2.11) */ #define FS_V8 6 /* Eighth Edition, 4K blocks */ #define FS_BSDFFS 7 /* 4.2BSD fast file system */ #define FS_MSDOS 8 /* MSDOS file system */ #define FS_BSDLFS 9 /* 4.4BSD log-structured file system */ #define FS_OTHER 10 /* in use, but unknown/unsupported */ #define FS_HPFS 11 /* OS/2 high-performance file system */ #define FS_ISO9660 12 /* ISO 9660, normally CD-ROM */ #ifdef DKTYPENAMES static char *fstypenames[] = { "unused", "swap", "Version 6", "Version 7", "System V", "2.11BSD", "Eighth Edition", "4.2BSD", "MSDOS", "4.4LFS", "unknown", "HPFS", "ISO9660", 0 }; #define FSMAXTYPES (sizeof(fstypenames) / sizeof(fstypenames[0]) - 1) #endif /* * flags shared by various drives: */ #define D_REMOVABLE 0x01 /* removable media */ #define D_ECC 0x02 /* supports ECC */ #define D_BADSECT 0x04 /* supports bad sector forw. */ #define D_RAMDISK 0x08 /* disk emulator */ /* * Structure used to perform a format * or other raw operation, returning data * and/or register values. * Register identification and format * are device- and driver-dependent. */ struct format_op { char *df_buf; int df_count; /* value-result */ daddr_t df_startblk; int df_reg[8]; /* result */ }; /* * Structure used internally to retrieve * information about a partition on a disk. */ struct partinfo { struct disklabel *disklab; struct partition *part; }; /* * Disk-specific ioctls. */ /* get and set disklabel; DIOCGPART used internally */ #define DIOCGDINFO _IOR(d, 101, struct disklabel) /* get */ #define DIOCSDINFO _IOW(d, 102, struct disklabel) /* set */ #define DIOCWDINFO _IOW(d, 103, struct disklabel) /* set, update disk */ #define DIOCGPART _IOW(d, 104, struct partinfo) /* get partition */ /* do format operation, read or write */ #define DIOCRFORMAT _IOWR(d, 105, struct format_op) #define DIOCWFORMAT _IOWR(d, 106, struct format_op) #define DIOCSSTEP _IOW(d, 107, int) /* set step rate */ #define DIOCSRETRIES _IOW(d, 108, int) /* set # of retries */ #define DIOCWLABEL _IOW(d, 109, int) /* write en/disable label */ #define DIOCSBAD _IOW(d, 110, struct dkbad) /* set kernel dkbad */ #ifndef KERNEL struct disklabel *getdiskbyname(); #endif #if defined(KERNEL) && !defined(SUPERVISOR) memaddr disklabelalloc(); #define LABELDESC (((btoc(sizeof (struct disklabel)) - 1) << 8) | RW) #endif #endif /* !_SYS_DISKLABEL_H_ */ space is precious in the 2.11 kernel. Many of the fields do * not need to be a 'long' (or even a 'short'), a 'short' (or 'char') * is more than adequate. If anyone ever ports the FFS to a PDP11 * changing the label format will be the least of the problems. * * 2) There is no need to support a bootblock more than 512 bytes long. * The hardwaresys/h/sysctl.h 644 0 12 30124 5707644062 6621 /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Mike Karels at Berkeley Software Design, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)sysctl.h 8.1.2 (2.11BSD GTE) 1/19/95 */ #ifndef _SYS_SYSCTL_H_ #define _SYS_SYSCTL_H_ /* * These are for the eproc, etext, einode, efile and map structures. */ #ifndef KERNEL #include #include #include #include #include #include #include #include #endif /* * Definitions for sysctl call. The sysctl call uses a hierarchical name * for objects that can be examined or modified. The name is expressed as * a sequence of integers. Like a file path name, the meaning of each * component depends on its place in the hierarchy. The top-level and kern * identifiers are defined here, and other identifiers are defined in the * respective subsystem header files. */ #define CTL_MAXNAME 12 /* largest number of components supported */ /* * Each subsystem defined by sysctl defines a list of variables * for that subsystem. Each name is either a node with further * levels defined below it, or it is a leaf of some particular * type given below. Each sysctl level defines a set of name/type * pairs to be used by sysctl(1) in manipulating the subsystem. */ struct ctlname { char *ctl_name; /* subsystem name */ int ctl_type; /* type of name */ }; #define CTLTYPE_NODE 1 /* name is a node */ #define CTLTYPE_INT 2 /* name describes a 16-bit integer */ #define CTLTYPE_STRING 3 /* name describes a string */ #define CTLTYPE_LONG 4 /* name describes a 32-bit number */ #define CTLTYPE_STRUCT 5 /* name describes a structure */ /* * Top-level identifiers */ #define CTL_UNSPEC 0 /* unused */ #define CTL_KERN 1 /* "high kernel": proc, limits */ #define CTL_VM 2 /* virtual memory */ #define CTL_FS 3 /* file system, mount type is next */ #define CTL_NET 4 /* network, see socket.h */ #define CTL_DEBUG 5 /* debugging parameters */ #define CTL_HW 6 /* generic cpu/io */ #define CTL_MACHDEP 7 /* machine dependent */ #define CTL_USER 8 /* user-level */ #define CTL_MAXID 9 /* number of valid top-level ids */ #ifndef KERNEL #define CTL_NAMES { \ { 0, 0 }, \ { "kern", CTLTYPE_NODE }, \ { "vm", CTLTYPE_NODE }, \ { "fs", CTLTYPE_NODE }, \ { "net", CTLTYPE_NODE }, \ { "debug", CTLTYPE_NODE }, \ { "hw", CTLTYPE_NODE }, \ { "machdep", CTLTYPE_NODE }, \ { "user", CTLTYPE_NODE }, \ } #endif /* * CTL_KERN identifiers */ #define KERN_OSTYPE 1 /* string: system version */ #define KERN_OSRELEASE 2 /* string: system release */ #define KERN_OSREV 3 /* int: system revision */ #define KERN_VERSION 4 /* string: compile time info */ #define KERN_MAXINODES 5 /* int: max inodes */ #define KERN_MAXPROC 6 /* int: max processes */ #define KERN_MAXFILES 7 /* int: max open files */ #define KERN_ARGMAX 8 /* int: max arguments to exec */ #define KERN_SECURELVL 9 /* int: system security level */ #define KERN_HOSTNAME 10 /* string: hostname */ #define KERN_HOSTID 11 /* int: host identifier */ #define KERN_CLOCKRATE 12 /* struct: struct clockrate */ #define KERN_INODE 13 /* struct: inode structures */ #define KERN_PROC 14 /* struct: process entries */ #define KERN_FILE 15 /* struct: file entries */ #define KERN_PROF 16 /* node: kernel profiling info */ #define KERN_POSIX1 17 /* int: POSIX.1 version */ #define KERN_NGROUPS 18 /* int: # of supplemental group ids */ #define KERN_JOB_CONTROL 19 /* int: is job control available */ #define KERN_SAVED_IDS 20 /* int: saved set-user/group-ID */ #define KERN_BOOTTIME 21 /* struct: time kernel was booted */ #define KERN_MAXTEXTS 22 /* int: # of text entries */ #define KERN_TEXT 23 /* struct: text entries */ #define KERN_MAXID 24 /* number of valid kern ids */ #ifndef KERNEL #define CTL_KERN_NAMES { \ { 0, 0 }, \ { "ostype", CTLTYPE_STRING }, \ { "osrelease", CTLTYPE_STRING }, \ { "osrevision", CTLTYPE_LONG }, \ { "version", CTLTYPE_STRING }, \ { "maxinodes", CTLTYPE_INT }, \ { "maxproc", CTLTYPE_INT }, \ { "maxfiles", CTLTYPE_INT }, \ { "argmax", CTLTYPE_INT }, \ { "securelevel", CTLTYPE_INT }, \ { "hostname", CTLTYPE_STRING }, \ { "hostid", CTLTYPE_LONG }, \ { "clockrate", CTLTYPE_STRUCT }, \ { "inode", CTLTYPE_STRUCT }, \ { "proc", CTLTYPE_STRUCT }, \ { "file", CTLTYPE_STRUCT }, \ { "profiling", CTLTYPE_NODE }, \ { "posix1version", CTLTYPE_INT }, \ { "ngroups", CTLTYPE_INT }, \ { "job_control", CTLTYPE_INT }, \ { "saved_ids", CTLTYPE_INT }, \ { "boottime", CTLTYPE_STRUCT }, \ { "maxtexts", CTLTYPE_INT }, \ { "text", CTLTYPE_STRUCT }, \ } #endif /* * KERN_PROC subtypes */ #define KERN_PROC_ALL 0 /* everything */ #define KERN_PROC_PID 1 /* by process id */ #define KERN_PROC_PGRP 2 /* by process group id */ #define KERN_PROC_SESSION 3 /* by session of pid - NOT IN 2.11 */ #define KERN_PROC_TTY 4 /* by controlling tty */ #define KERN_PROC_UID 5 /* by effective uid */ #define KERN_PROC_RUID 6 /* by real uid */ /* * KERN_PROC subtype ops return arrays of augmented proc structures: */ struct kinfo_proc { struct proc kp_proc; /* proc structure */ struct eproc { struct proc *e_paddr; /* address of proc */ dev_t e_tdev; /* controlling tty dev */ pid_t e_tpgid; /* tty process group id */ uid_t e_ruid; /* real uid */ } kp_eproc; }; /* * KERN_TEXT op returns array of augmented text structures: */ struct kinfo_text { struct text *kp_textp; /* address of text */ struct text kp_text; /* text structure */ }; /* * KERN_INODE returns an array of augmented inode structures: */ struct kinfo_inode { struct inode *kp_inodep; /* address of inode */ struct inode kp_inode; /* inode structure */ }; /* * KERN_FILE returns an array of augmented file structures: */ struct kinfo_file { struct file *kp_filep; /* address of file */ struct file kp_file; /* file structure */ }; /* * CTL_HW identifiers */ #define HW_MACHINE 1 /* string: machine class */ #define HW_MODEL 2 /* string: specific machine model */ #define HW_NCPU 3 /* int: number of cpus */ #define HW_BYTEORDER 4 /* int: machine byte order */ #define HW_PHYSMEM 5 /* int: total memory */ #define HW_USERMEM 6 /* int: non-kernel memory */ #define HW_PAGESIZE 7 /* int: software page size */ #define HW_DISKNAMES 8 /* strings: disk drive names */ #define HW_DISKSTATS 9 /* struct: diskstats[] */ #define HW_MAXID 10 /* number of valid hw ids */ #ifndef KERNEL #define CTL_HW_NAMES { \ { 0, 0 }, \ { "machine", CTLTYPE_STRING }, \ { "model", CTLTYPE_STRING }, \ { "ncpu", CTLTYPE_INT }, \ { "byteorder", CTLTYPE_INT }, \ { "physmem", CTLTYPE_LONG }, \ { "usermem", CTLTYPE_LONG }, \ { "pagesize", CTLTYPE_INT }, \ { "disknames", CTLTYPE_STRUCT }, \ { "diskstats", CTLTYPE_STRUCT }, \ } #endif #ifndef KERNEL /* * CTL_USER definitions */ #define USER_CS_PATH 1 /* string: _CS_PATH */ #define USER_BC_BASE_MAX 2 /* int: BC_BASE_MAX */ #define USER_BC_DIM_MAX 3 /* int: BC_DIM_MAX */ #define USER_BC_SCALE_MAX 4 /* int: BC_SCALE_MAX */ #define USER_BC_STRING_MAX 5 /* int: BC_STRING_MAX */ #define USER_COLL_WEIGHTS_MAX 6 /* int: COLL_WEIGHTS_MAX */ #define USER_EXPR_NEST_MAX 7 /* int: EXPR_NEST_MAX */ #define USER_LINE_MAX 8 /* int: LINE_MAX */ #define USER_RE_DUP_MAX 9 /* int: RE_DUP_MAX */ #define USER_POSIX2_VERSION 10 /* int: POSIX2_VERSION */ #define USER_POSIX2_C_BIND 11 /* int: POSIX2_C_BIND */ #define USER_POSIX2_C_DEV 12 /* int: POSIX2_C_DEV */ #define USER_POSIX2_CHAR_TERM 13 /* int: POSIX2_CHAR_TERM */ #define USER_POSIX2_FORT_DEV 14 /* int: POSIX2_FORT_DEV */ #define USER_POSIX2_FORT_RUN 15 /* int: POSIX2_FORT_RUN */ #define USER_POSIX2_LOCALEDEF 16 /* int: POSIX2_LOCALEDEF */ #define USER_POSIX2_SW_DEV 17 /* int: POSIX2_SW_DEV */ #define USER_POSIX2_UPE 18 /* int: POSIX2_UPE */ #define USER_STREAM_MAX 19 /* int: POSIX2_STREAM_MAX */ #define USER_TZNAME_MAX 20 /* int: POSIX2_TZNAME_MAX */ #define USER_MAXID 21 /* number of valid user ids */ #define CTL_USER_NAMES { \ { 0, 0 }, \ { "cs_path", CTLTYPE_STRING }, \ { "bc_base_max", CTLTYPE_INT }, \ { "bc_dim_max", CTLTYPE_INT }, \ { "bc_scale_max", CTLTYPE_INT }, \ { "bc_string_max", CTLTYPE_INT }, \ { "coll_weights_max", CTLTYPE_INT }, \ { "expr_nest_max", CTLTYPE_INT }, \ { "line_max", CTLTYPE_INT }, \ { "re_dup_max", CTLTYPE_INT }, \ { "posix2_version", CTLTYPE_INT }, \ { "posix2_c_bind", CTLTYPE_INT }, \ { "posix2_c_dev", CTLTYPE_INT }, \ { "posix2_char_term", CTLTYPE_INT }, \ { "posix2_fort_dev", CTLTYPE_INT }, \ { "posix2_fort_run", CTLTYPE_INT }, \ { "posix2_localedef", CTLTYPE_INT }, \ { "posix2_sw_dev", CTLTYPE_INT }, \ { "posix2_upe", CTLTYPE_INT }, \ { "stream_max", CTLTYPE_INT }, \ { "tzname_max", CTLTYPE_INT }, \ } #endif /* * CTL_DEBUG definitions * * Second level identifier specifies which debug variable. * Third level identifier specifies which stucture component. */ #define CTL_DEBUG_NAME 0 /* string: variable name */ #define CTL_DEBUG_VALUE 1 /* int: variable value */ #define CTL_DEBUG_MAXID 20 #ifdef KERNEL #ifdef DEBUG /* * CTL_DEBUG variables. * * These are declared as separate variables so that they can be * individually initialized at the location of their associated * variable. The loader prevents multiple use by issuing errors * if a variable is initialized in more than one place. They are * aggregated into an array in debug_sysctl(), so that it can * conveniently locate them when querried. If more debugging * variables are added, they must also be declared here and also * entered into the array. */ struct ctldebug { char *debugname; /* name of debugging variable */ int *debugvar; /* pointer to debugging variable */ }; extern struct ctldebug debug0, debug1, debug2, debug3, debug4; extern struct ctldebug debug5, debug6, debug7, debug8, debug9; extern struct ctldebug debug10, debug11, debug12, debug13, debug14; extern struct ctldebug debug15, debug16, debug17, debug18, debug19; #endif /* DEBUG */ /* * Internal sysctl function calling convention: * * (*sysctlfn)(name, namelen, oldval, oldlenp, newval, newlen); * * The name parameter points at the next component of the name to be * interpreted. The namelen parameter is the number of integers in * the name. */ typedef int (sysctlfn)(); int sysctl_int(); int sysctl_rdint(); int sysctl_string(); int sysctl_rdstring(); int sysctl_rdstruct(); void fill_eproc(); #else /* !KERNEL */ int sysctl(); #endif /* KERNEL */ #endif /* !_SYS_SYSCTL_H_ */ YPE_STRING }, \ { "osrelease", CTLTYPE_STRING }, \ { "osrevision", CTLTYPE_LONG }, \ { "version", CTLTYPE_STRING }, \ { "maxinodes", CTLTYPE_INT }, \ { "maxproc", CTLTYPE_INT }, \ { "maxfiles", CTLTYPE_INT }, \ { "argmax", CTLTYPE_INT }, \ { "securelevel", CTLTYPE_INT }, \ { "hostname", CTLTYPE_STRING }, \ { "hostid", CTLTYPE_LONG }, \ { "clockrate", CTLTYPE_STRUCT }, \ { "inode", CTLTYPE_STRUCT }, \ { "proc", Csys/h/ingreslock.h 644 0 12 4574 5722262440 7423 #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)ildr.h 1.0 (2.11BSD GTE) 2/14/95"; #endif lint /* * This is the include file for the Ingres concurrency (lock) driver. * Only the parameters NLOCKS, PLOCKS, RLOCKS and DLOCKS may be changed. * * The initial values allow for 10 simultaneous Ingres users on the system. * This should be enough but if you wish to raise that limit then change * _only_ the 'IL_DLOCKS' parameter below. */ #define KEYSIZE 12 /* max number of data base locks (max # of Ingreses) */ #define IL_DLOCKS 10 #define IL_RLOCKS ((2*IL_DLOCKS) + 6) #define IL_PLOCKS (IL_RLOCKS + 3) #define IL_NLOCKS (IL_PLOCKS + 1) /* * Do not change anything below this line unless you are modifying the * driver. */ #define LOCKPRI 1 #define TRUE 1 #define FALSE 0 #define M_EMTY 0 #define M_SHARE 2 #define M_EXCL 1 #define T_CS 0 #define T_PAGE 1 #define T_REL 2 #define T_DB 3 #define A_RTN 1 #define A_SLP 2 #define A_RLS1 3 #define A_RLSA 4 #define A_ABT 5 #define W_ON 1 #define W_OFF 0 /* * data structure for Lock table */ struct Lockform { int l_pid; char l_wflag; /* wait flag: = 1 a process is waiting*/ char l_type; /* type of lock: = 0 for critical section = 1 for page = 2 for logical = 3 for data base */ char l_mod; /* mod of Lock or lock action requested * = 0 slot empty * = 1 exclusive lock * = 2 shared lock */ char l_pad; char l_key[KEYSIZE]; }; /* * This is the structure written by Ingres programs. * * This structure _must_ agree in size and alignment with the 'lockreq' * structure defined in /usr/ingres/source/lock.h */ struct ulock { char _act; /* requested action: * =1 request lock, err return * =2 request lock, sleep * =3 release lock * =4 release all locks for pid */ char _type; /* same as Locktab l_type */ char _mod; /* same as Locktab l_mod */ char _pad; /* Pad byte to align key on word boundary */ char _key[KEYSIZE]; /* requested key */ }; struct Lockreq { int lr_pid; /* requesting process id */ struct ulock lr_req; /* The structure written by the user */ }; #define lr_act lr_req._act #define lr_type lr_req._type #define lr_mod lr_req._mod #define lr_key lr_req._key #define ingres_maplock() mapseg5(Locktabseg.se_addr, Locktabseg.se_desc) #define LOCKTABSIZE (IL_NLOCKS * sizeof (struct Lockform)) extern segm Locktabseg; e USER_LINE_MAX 8 /* int: LINE_MAX */ #define USER_RE_DUP_MAX 9 /* int: RE_DUP_MAX */ #define USER_POSIX2_VERSION 10 /* int: POSsys/netimp/ 755 0 12 0 5526060265 6063 sys/netimp/if_imp.h 444 0 12 12673 4066565413 7616 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_imp.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * Structure of IMP 1822 long leader. */ struct control_leader { u_char dl_format; /* leader format */ u_char dl_network; /* src/dest network */ u_char dl_flags; /* leader flags */ u_char dl_mtype; /* message type */ u_char dl_htype; /* handling type */ u_char dl_host; /* host number */ u_short dl_imp; /* imp field */ u_char dl_link; /* link number */ u_char dl_subtype; /* message subtype */ }; struct imp_leader { struct control_leader il_dl; #define il_format il_dl.dl_format #define il_network il_dl.dl_network #define il_flags il_dl.dl_flags #define il_mtype il_dl.dl_mtype #define il_htype il_dl.dl_htype #define il_host il_dl.dl_host #define il_imp il_dl.dl_imp #define il_link il_dl.dl_link #define il_subtype il_dl.dl_subtype u_short il_length; /* message length */ }; #define IMP_DROPCNT 2 /* # of noops from imp to ignore */ /* insure things are even... */ #define IMPMTU ((8159 / NBBY) & ~01) /* * IMP-host flags */ #define IMP_NFF 0xf /* 96-bit (new) format */ #define IMP_TRACE 0x8 /* trace message route */ #define IMP_DMASK 0x3 /* host going down mask */ /* * IMP-host message types. */ #define IMPTYPE_DATA 0 /* data for protocol */ #define IMPTYPE_BADLEADER 1 /* leader error */ #define IMPTYPE_DOWN 2 /* imp going down */ #define IMPTYPE_NOOP 4 /* noop seen during initialization */ #define IMPTYPE_RFNM 5 /* request for new messages */ #define IMPTYPE_HOSTDEAD 6 /* host doesn't respond */ #define IMPTYPE_HOSTUNREACH 7 /* host unreachable */ #define IMPTYPE_BADDATA 8 /* data error */ #define IMPTYPE_INCOMPLETE 9 /* incomplete message, send rest */ #define IMPTYPE_RESET 10 /* reset complete */ /* non-blocking IMP interface */ #define IMPTYPE_RETRY 11 /* IMP refused, try again */ #define IMPTYPE_NOTIFY 12 /* IMP refused, will notify */ #define IMPTYPE_TRYING 13 /* IMP refused, still rexmt'ng */ #define IMPTYPE_READY 14 /* ready for next message */ /* * IMPTYPE_DOWN subtypes. */ #define IMPDOWN_GOING 0 /* 30 secs */ #define IMPDOWN_PM 1 /* hardware PM */ #define IMPDOWN_RELOAD 2 /* software reload */ #define IMPDOWN_RESTART 3 /* emergency restart */ /* * IMPTYPE_BADLEADER subtypes. */ #define IMPLEADER_ERR 0 /* error flip-flop set */ #define IMPLEADER_SHORT 1 /* leader < 80 bits */ #define IMPLEADER_TYPE 2 /* illegal type field */ #define IMPLEADER_OPPOSITE 3 /* opposite leader type */ /* * IMPTYPE_HOSTDEAD subtypes. */ #define IMPHOST_NORDY 1 /* ready-line negated */ #define IMPHOST_TARDY 2 /* tardy receiving mesgs */ #define IMPHOST_NOEXIST 3 /* NCC doesn't know host */ #define IMPHOST_IMPSOFT 4 /* IMP software won't allow mesgs */ #define IMPHOST_PM 5 /* host down for scheduled PM */ #define IMPHOST_HARDSCHED 6 /* " " " " hardware work */ #define IMPHOST_SOFTSCHED 7 /* " " " " software work */ #define IMPHOST_RESTART 8 /* host down for emergency restart */ #define IMPHOST_POWER 9 /* down because of power outage */ #define IMPHOST_BREAKPOINT 10 /* host stopped at a breakpoint */ #define IMPHOST_HARDWARE 11 /* hardware failure */ #define IMPHOST_NOTUP 12 /* host not scheduled to be up */ /* 13-14 currently unused */ #define IMPHOST_COMINGUP 15 /* host in process of coming up */ /* * IMPTYPE_HOSTUNREACH subtypes. */ #define IMPREACH_IMP 0 /* destination IMP can't be reached */ #define IMPREACH_HOSTUP 1 /* destination host isn't up */ #define IMPREACH_LEADER 2 /* host doesn't support long leader */ #define IMPREACH_PROHIBITED 3 /* communication is prohibited */ /* * IMPTYPE_INCOMPLETE subtypes. */ #define IMPCOMPLETE_SLOW 0 /* host didn't take data fast enough */ #define IMPCOMPLETE_TOOLONG 1 /* message was too long */ #define IMPCOMPLETE_TIMEOUT 2 /* mesg transmission time > 15 sec. */ #define IMPCOMPLETE_FAILURE 3 /* IMP/circuit failure */ #define IMPCOMPLETE_NOSPACE 4 /* no resources within 15 sec. */ #define IMPCOMPLETE_IMPIO 5 /* src IMP I/O failure during receipt */ /* * IMPTYPE_RETRY subtypes. */ #define IMPRETRY_BUFFER 0 /* IMP buffer wasn't available */ #define IMPRETRY_BLOCK 1 /* connection block unavailable */ /* * Data structure shared between IMP protocol module and hardware * interface driver. Used to allow layering of IMP routines on top * of varying device drivers. NOTE: there's a possible problem * with ambiguity in the ``unit'' definition which is implicitly * shared by the both IMP and device code. If we have two IMPs, * with each on top of a device of the same unit, things won't work. * The assumption is if you've got multiple IMPs, then they all run * on top of the same type of device, or they must have different units. */ struct impcb { char ic_oactive; /* output in progress */ int (*ic_init)(); /* hardware init routine */ int (*ic_start)(); /* hardware start output routine */ }; /* * State of an IMP. */ #define IMPS_DOWN 0 /* unavailable, don't use */ #define IMPS_GOINGDOWN 1 /* been told we go down soon */ #define IMPS_INIT 2 /* coming up */ #define IMPS_UP 3 /* ready to go */ #define IMPS_RESET 4 /* reset in progress */ #define IMPTV_DOWN (30*60) /* going down timer 30 secs */ #ifdef IMPLEADERS char *impleaders[IMPTYPE_READY+1] = { "DATA", "BADLEADER", "DOWN", "bad", "NOOP", "RFNM", "HOSTDEAD", "HOSTUNREACH", "BADDATA", "INCOMPLETE", "RESET", "RETRY", "NOTIFY", "TRYING", "READY" }; #endif ); int sysctl_rdstring(); int sysctl_rdstruct(); void fill_eproc(); sys/netimp/if_imphost.h 440 0 12 4731 4610734560 10460 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_imphost.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * Host structure used with IMP's. * Used to hold outgoing packets which * would exceed allowed RFNM count. * * These structures are packed into * mbuf's and kept as small as possible. */ struct host { struct mbuf *h_q; /* holding queue */ struct in_addr h_addr; /* host's address */ u_char h_qcnt; /* size of holding q */ u_char h_timer; /* used to stay off deletion */ u_char h_rfnm; /* # outstanding rfnm's */ u_char h_flags; /* see below */ }; /* * A host structure is kept around (even when there are no * references to it) for a spell to avoid constant reallocation * and also to reflect IMP status back to sites which aren't * directly connected to the IMP. When structures are marked * free, a timer is started; when the timer expires the structure * is scavenged. */ #define HF_INUSE 0x1 #define HF_DEAD (1<>8)+(a).s_net) % HPMBUF) /* * In-line expansions for queuing operations on * host message holding queue. Queue is maintained * as circular list with the head pointing to the * last message in the queue. */ #define HOST_ENQUE(hp, m) { \ register struct mbuf *n; \ (hp)->h_qcnt++; \ if ((n = (hp)->h_q) == 0) \ (hp)->h_q = (m)->m_act = (m); \ else { \ (m)->m_act = n->m_act; \ (hp)->h_q = n->m_act = (m); \ } \ } #define HOST_DEQUE(hp, m) { \ if ((m) = (hp)->h_q) { \ if ((m)->m_act == (m)) \ (hp)->h_q = 0; \ else { \ (m) = (m)->m_act; \ (hp)->h_q->m_act = (m)->m_act; \ } \ (hp)->h_qcnt--; \ (m)->m_act = 0; \ } \ } struct hmbuf { int hm_count; /* # of struct's in use */ struct host hm_hosts[HPMBUF]; /* data structures proper */ }; #if defined(KERNEL) && defined(SUPERVISOR) struct host *hostlookup(); struct host *hostenter(); struct mbuf *hostdeque(); #endif IMPLEADER_TYPE 2 /* illegal type fieldsys/netimp/if_imp.c 444 0 12 43116 5511224653 7577 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_imp.c 1.2 (2.11BSD Berkeley) 12/31/93 */ #include "imp.h" #if NIMP > 0 /* * ARPANET IMP interface driver. * * The IMP-host protocol is handled here, leaving * hardware specifics to the lower level interface driver. */ #include "param.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "domain.h" #include "protosw.h" #include "socket.h" #include "pdpuba/ubavar.h" #include "ioctl.h" #include #include #include #include #include #include #include #include /* define IMPLEADERS here to get leader printing code */ #include #include #include #ifdef pdp11 #define putchar _pchar #endif /* * IMP software status per interface. * (partially shared with the hardware specific module) * * Each interface is referenced by a network interface structure, * imp_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its * address, ... IMP specific structures used in connecting the * IMP software modules to the hardware specific interface routines * are stored here. The common structures are made visible to the * interface driver by passing a pointer to the hardware routine * at "attach" time. * * NOTE: imp_if and imp_cb are assumed adjacent in hardware code. */ struct imp_softc { struct ifnet imp_if; /* network visible interface */ struct impcb imp_cb; /* hooks to hardware module */ u_char imp_state; /* current state of IMP */ char imp_dropcnt; /* used during initialization */ } imp_softc[NIMP]; extern int hz; struct ifqueue impintrq; int impqmaxlen = IFQ_MAXLEN; /* * Messages from IMP regarding why * it's going down. */ static char *impmessage[] = { "in 30 seconds", "for hardware PM", "to reload software", "for emergency reset" }; #define HOSTDEADTIMER 10 /* How long to wait when down */ int impdown(), impinit(), impioctl(), impoutput(); /* * IMP attach routine. Called from hardware device attach routine * at configuration time with a pointer to the UNIBUS device structure. * Sets up local state and returns pointer to base of ifnet+impcb * structures. This is then used by the device's attach routine * set up its back pointers. */ impattach(ui, reset) struct uba_device *ui; int (*reset)(); { struct imp_softc *sc; register struct ifnet *ifp; #ifdef lint impintr(); #endif if (ui->ui_unit >= NIMP) { printf("imp%d: not configured\n", ui->ui_unit); return (0); } sc = &imp_softc[ui->ui_unit]; ifp = &sc->imp_if; /* UNIT COULD BE AMBIGUOUS */ ifp->if_unit = ui->ui_unit; ifp->if_name = "imp"; ifp->if_mtu = IMPMTU - sizeof(struct imp_leader); ifp->if_reset = reset; ifp->if_init = impinit; ifp->if_ioctl = impioctl; ifp->if_output = impoutput; /* reset is handled at the hardware level */ if_attach(ifp); return ((int)ifp); } /* * IMP initialization routine: call hardware module to * setup UNIBUS resources, init state and get ready for * NOOPs the IMP should send us, and that we want to drop. */ impinit(unit) int unit; { int s = splimp(); register struct imp_softc *sc = &imp_softc[unit]; if (sc->imp_if.if_addrlist == 0) return; if ((*sc->imp_cb.ic_init)(unit) == 0) { sc->imp_state = IMPS_DOWN; sc->imp_if.if_flags &= ~IFF_UP; splx(s); return; } sc->imp_state = IMPS_INIT; impnoops(sc); impintrq.ifq_maxlen = impqmaxlen; splx(s); } #ifdef IMPLEADERS int impprintfs = 0; #endif /* * ARPAnet 1822 input routine. * Called from hardware input interrupt routine to handle 1822 * IMP-host messages. Type 0 messages (non-control) are * passed to higher level protocol processors on the basis * of link number. Other type messages (control) are handled here. */ impinput(unit, m) int unit; register struct mbuf *m; { register struct imp_leader *ip; register struct imp_softc *sc = &imp_softc[unit]; struct ifnet *ifp; register struct host *hp; register struct ifqueue *inq; struct control_leader *cp; struct in_addr addr; struct mbuf *next; struct sockaddr_in *sin; /* * Pull the interface pointer out of the mbuf * and save for later; adjust mbuf to look at rest of data. */ ifp = *(mtod(m, struct ifnet **)); IF_ADJ(m); /* verify leader length. */ if (m->m_len < sizeof(struct control_leader) && (m = m_pullup(m, sizeof(struct control_leader))) == 0) return; cp = mtod(m, struct control_leader *); if (cp->dl_mtype == IMPTYPE_DATA) if (m->m_len < sizeof(struct imp_leader) && (m = m_pullup(m, sizeof(struct imp_leader))) == 0) return; ip = mtod(m, struct imp_leader *); #ifdef IMPLEADERS if (impprintfs) printleader("impinput", ip); #endif inq = &impintrq; /* check leader type */ if (ip->il_format != IMP_NFF) { sc->imp_if.if_collisions++; /* XXX */ goto rawlinkin; } if (ip->il_mtype != IMPTYPE_DATA) { /* If not data packet, build IP addr from leader (BRL) */ imp_leader_to_addr(&addr, ip, &sc->imp_if); } switch (ip->il_mtype) { case IMPTYPE_DATA: /* * Data for a protocol. Dispatch to the appropriate * protocol routine (running at software interrupt). * If this isn't a raw interface, advance pointer * into mbuf past leader. */ switch (ip->il_link) { case IMPLINK_IP: m->m_len -= sizeof(struct imp_leader); m->m_off += sizeof(struct imp_leader); schednetisr(NETISR_IP); inq = &ipintrq; break; default: break; } break; /* * IMP leader error. Reset the IMP and discard the packet. */ case IMPTYPE_BADLEADER: /* * According to 1822 document, this message * will be generated in response to the * first noop sent to the IMP after * the host resets the IMP interface. */ if (sc->imp_state != IMPS_INIT) { impmsg(sc, "leader error"); hostreset(((struct in_ifaddr *)&sc->imp_if.if_addrlist)->ia_net); impnoops(sc); } break; /* * IMP going down. Print message, and if not immediate, * set off a timer to insure things will be reset at the * appropriate time. */ case IMPTYPE_DOWN: if (sc->imp_state < IMPS_INIT) break; if ((ip->il_link & IMP_DMASK) == 0) { sc->imp_state = IMPS_GOINGDOWN; TIMEOUT(impdown, (caddr_t)sc, 30 * hz); } impmsg(sc, "going down %s", (u_int)impmessage[ip->il_link&IMP_DMASK]); break; /* * A NOP usually seen during the initialization sequence. * Compare the local address with that in the message. * Reset the local address notion if it doesn't match. */ case IMPTYPE_NOOP: if (sc->imp_state == IMPS_DOWN) { sc->imp_state = IMPS_INIT; sc->imp_dropcnt = IMP_DROPCNT; } if (sc->imp_state == IMPS_INIT && --sc->imp_dropcnt > 0) break; sin = (struct sockaddr_in *)&sc->imp_if.if_addrlist->ifa_addr; if (ip->il_imp != 0) { struct in_addr leader_addr; imp_leader_to_addr(&leader_addr, ip, &sc->imp_if); if (sin->sin_addr.s_addr != leader_addr.s_addr) { impmsg(sc, "address reset to x%x (%d/%d)", ntohl(leader_addr.s_addr), (u_int)ip->il_host, ntohs(ip->il_imp)); sin->sin_addr.s_addr = leader_addr.s_addr; } } sc->imp_state = IMPS_UP; sc->imp_if.if_flags |= IFF_UP; break; /* * RFNM or INCOMPLETE message, send next * message on the q. We could pass incomplete's * up to the next level, but this currently isn't * needed. */ case IMPTYPE_RFNM: case IMPTYPE_INCOMPLETE: if (hp = hostlookup(addr)) { hp->h_timer = HOSTTIMER; if (hp->h_rfnm == 0) hp->h_flags &= ~HF_INUSE; else if (next = hostdeque(hp)) (void) impsnd(&sc->imp_if, next); } goto drop; /* * Host or IMP can't be reached. Flush any packets * awaiting transmission and release the host structure. * Enqueue for notifying protocols at software interrupt time. */ case IMPTYPE_HOSTDEAD: case IMPTYPE_HOSTUNREACH: if (hp = hostlookup(addr)) { hp->h_flags |= (1 << (int)ip->il_mtype); hostfree(hp); hp->h_timer = HOSTDEADTIMER; } break; /* * Error in data. Clear RFNM status for this host and send * noops to the IMP to clear the interface. */ case IMPTYPE_BADDATA: impmsg(sc, "data error"); if (hp = hostlookup(addr)) hp->h_rfnm = 0; impnoops(sc); break; /* * Interface reset. */ case IMPTYPE_RESET: impmsg(sc, "interface reset"); /* clear RFNM counts */ hostreset(((struct in_ifaddr *)&sc->imp_if.if_addrlist)->ia_net); impnoops(sc); break; default: sc->imp_if.if_collisions++; /* XXX */ break; } rawlinkin: if (inq == &impintrq) schednetisr(NETISR_IMP); /* * Re-insert interface pointer in the mbuf chain * for the next protocol up. */ if (M_HASCL(m) && (mtod(m, int) & CLOFSET) < sizeof(struct ifnet *)) { struct mbuf *n; MGET(n, M_DONTWAIT, MT_HEADER); if (n == 0) goto drop; n->m_next = m; m = n; m->m_len = 0; m->m_off = MMINOFF + sizeof(struct ifnet *); } m->m_off -= sizeof(struct ifnet *); m->m_len += sizeof(struct ifnet *); *(mtod(m, struct ifnet **)) = ifp; if (IF_QFULL(inq)) { IF_DROP(inq); goto drop; } IF_ENQUEUE(inq, m); return; drop: m_freem(m); } /* * Bring the IMP down after notification. */ impdown(sc) struct imp_softc *sc; { int s = splimp(); sc->imp_state = IMPS_DOWN; impmsg(sc, "marked down"); hostreset(((struct in_ifaddr *)&sc->imp_if.if_addrlist)->ia_net); if_down(&sc->imp_if); splx(s); } /*VARARGS2*/ impmsg(sc, fmt, a1, a2, a3) struct imp_softc *sc; char *fmt; u_int a1; { printf("imp%d: ", sc->imp_if.if_unit); printf(fmt, a1, a2, a3); printf("\n"); } struct sockproto impproto = { PF_IMPLINK }; struct sockaddr_in impdst = { AF_IMPLINK }; struct sockaddr_in impsrc = { AF_IMPLINK }; /* * Pick up the IMP "error" messages enqueued earlier, * passing these up to the higher level protocol * and the raw interface. */ impintr() { register struct mbuf *m; register struct control_leader *cp; struct ifnet *ifp; int s; for (;;) { s = splimp(); IF_DEQUEUEIF(&impintrq, m, ifp); splx(s); if (m == 0) return; cp = mtod(m, struct control_leader *); imp_leader_to_addr(&impsrc.sin_addr, (struct imp_leader *)cp, ifp); impproto.sp_protocol = cp->dl_link; impdst.sin_addr = IA_SIN(ifp->if_addrlist)->sin_addr; if (cp->dl_mtype == IMPTYPE_HOSTDEAD || cp->dl_mtype == IMPTYPE_HOSTUNREACH) switch (cp->dl_link) { case IMPLINK_IP: pfctlinput((int)cp->dl_mtype, (struct sockaddr *)&impsrc); break; default: raw_ctlinput((int)cp->dl_mtype, (struct sockaddr *)&impsrc); break; } raw_input(m, &impproto, (struct sockaddr *)&impsrc, (struct sockaddr *)&impdst); } } /* * ARPAnet 1822 output routine. * Called from higher level protocol routines to set up messages for * transmission to the imp. Sets up the header and calls impsnd to * enqueue the message for this IMP's hardware driver. */ impoutput(ifp, m0, dst) register struct ifnet *ifp; struct mbuf *m0; struct sockaddr *dst; { register struct imp_leader *imp; register struct mbuf *m = m0; int dlink, len; int error = 0; /* * Don't even try if the IMP is unavailable. */ if (imp_softc[ifp->if_unit].imp_state != IMPS_UP) { error = ENETDOWN; goto drop; } switch (dst->sa_family) { case AF_INET: { struct ip *ip = mtod(m, struct ip *); dlink = IMPLINK_IP; len = ntohs((u_short)ip->ip_len); break; } case AF_IMPLINK: len = 0; do len += m->m_len; while (m = m->m_next); m = m0; goto leaderexists; default: printf("imp%d: can't handle af%d\n", ifp->if_unit, dst->sa_family); error = EAFNOSUPPORT; goto drop; } /* * Add IMP leader. If there's not enough space in the * first mbuf, allocate another. If that should fail, we * drop this sucker. */ if (m->m_off > MMAXOFF || MMINOFF + sizeof(struct imp_leader) > m->m_off) { m = m_get(M_DONTWAIT, MT_HEADER); if (m == 0) { error = ENOBUFS; goto drop; } m->m_next = m0; m->m_len = sizeof(struct imp_leader); } else { m->m_off -= sizeof(struct imp_leader); m->m_len += sizeof(struct imp_leader); } imp = mtod(m, struct imp_leader *); imp->il_format = IMP_NFF; imp->il_mtype = IMPTYPE_DATA; imp_addr_to_leader(imp, ((struct sockaddr_in *)dst)->sin_addr.s_addr); /* BRL */ imp->il_length = htons((u_short)len << 3); /* BRL */ imp->il_link = dlink; imp->il_flags = imp->il_htype = imp->il_subtype = 0; leaderexists: return (impsnd(ifp, m)); drop: m_freem(m0); return (error); } /* * Put a message on an interface's output queue. * Perform RFNM counting: no more than 8 message may be * in flight to any one host. */ impsnd(ifp, m) struct ifnet *ifp; struct mbuf *m; { register struct imp_leader *ip; register struct host *hp; struct impcb *icp; int s, error; ip = mtod(m, struct imp_leader *); /* * Do RFNM counting for data messages * (no more than 8 outstanding to any host) */ s = splimp(); if (ip->il_mtype == IMPTYPE_DATA) { struct in_addr addr; imp_leader_to_addr(&addr, ip, ifp); /* BRL */ if ((hp = hostlookup(addr)) == 0) hp = hostenter(addr); if (hp && (hp->h_flags & (HF_DEAD|HF_UNREACH))) { error = hp->h_flags&HF_DEAD ? EHOSTDOWN : EHOSTUNREACH; hp->h_flags &= ~HF_INUSE; goto bad; } /* * If IMP would block, queue until RFNM */ if (hp) { #ifndef NORFNM if (hp->h_rfnm < 8) #endif { hp->h_timer = HOSTTIMER; hp->h_rfnm++; goto enque; } if (hp->h_qcnt < 8) { /* high water mark */ HOST_ENQUE(hp, m); goto start; } } error = ENOBUFS; goto bad; } enque: if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); error = ENOBUFS; if (ip->il_mtype == IMPTYPE_DATA) hp->h_rfnm--; bad: m_freem(m); splx(s); return (error); } IF_ENQUEUE(&ifp->if_snd, m); start: icp = &imp_softc[ifp->if_unit].imp_cb; if (icp->ic_oactive == 0) (*icp->ic_start)(ifp->if_unit); splx(s); return (0); } /* * Put three 1822 NOOPs at the head of the output queue. * Part of host-IMP initialization procedure. * (Should return success/failure, but noone knows * what to do with this, so why bother?) * This routine is always called at splimp, so we don't * protect the call to IF_PREPEND. */ impnoops(sc) register struct imp_softc *sc; { register i; register struct mbuf *m; register struct control_leader *cp; sc->imp_dropcnt = IMP_DROPCNT; for (i = 0; i < IMP_DROPCNT + 1; i++) { if ((m = m_getclr(M_DONTWAIT, MT_HEADER)) == 0) return; m->m_len = sizeof(struct control_leader); cp = mtod(m, struct control_leader *); cp->dl_format = IMP_NFF; cp->dl_link = i; cp->dl_mtype = IMPTYPE_NOOP; IF_PREPEND(&sc->imp_if.if_snd, m); } if (sc->imp_cb.ic_oactive == 0) (*sc->imp_cb.ic_start)(sc->imp_if.if_unit); } /* * Process an ioctl request. */ impioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { struct ifaddr *ifa = (struct ifaddr *) data; int s = splimp(), error = 0; switch (cmd) { case SIOCSIFADDR: if (ifa->ifa_addr.sa_family != AF_INET) { error = EINVAL; break; } if ((ifp->if_flags & IFF_RUNNING) == 0) impinit(ifp->if_unit); break; default: error = EINVAL; } splx(s); return (error); } #ifdef IMPLEADERS printleader(routine, ip) char *routine; register struct imp_leader *ip; { printf("%s: ", routine); printbyte((char *)ip, 12); printf("il_format, ip->il_network, ip->il_flags); if (UCHAR(ip->il_mtype) <= IMPTYPE_READY) printf("%s,", impleaders[ip->il_mtype]); else printf("%x,", ip->il_mtype); printf("htype=%x,host=%x,imp=%x,link=", ip->il_htype, ip->il_host, ntohs(ip->il_imp)); if (UCHAR(ip->il_link) == IMPLINK_IP) printf("ip,"); else printf("%x,", ip->il_link); printf("subtype=%x,len=%x>\n",ip->il_subtype,ntohs(ip->il_length)>>3); } printbyte(cp, n) register char *cp; int n; { register i, j, c; for (i=0; i>((1-j)*4))&0xf], 0); putchar(' ', 0); } putchar('\n', 0); } #endif /* * Routine to convert from IMP Leader to InterNet Address. * * This procedure is necessary because IMPs may be assigned Class A, B, or C * network numbers, but only have 8 bits in the leader to reflect the * IMP "network number". The strategy is to take the network number from * the ifnet structure, and blend in the host-on-imp and imp-on-net numbers * from the leader. * * There is no support for "Logical Hosts". * * Class A: Net.Host.0.Imp * Class B: Net.net.Host.Imp * Class C: Net.net.net.(Host4|Imp4) */ imp_leader_to_addr(ap, ip, ifp) struct in_addr *ap; register struct imp_leader *ip; struct ifnet *ifp; { u_long final; register struct sockaddr_in *sin; int imp = ntohs(ip->il_imp); sin = (struct sockaddr_in *)(&ifp->if_addrlist->ifa_addr); final = ntohl(sin->sin_addr.s_addr); if (IN_CLASSA(final)) { final &= IN_CLASSA_NET; final |= (imp & 0xFF) | ((ip->il_host & 0xFF)<<16); } else if (IN_CLASSB(final)) { final &= IN_CLASSB_NET; final |= (imp & 0xFF) | ((ip->il_host & 0xFF)<<8); } else { final &= IN_CLASSC_NET; final |= (imp & 0x0F) | ((ip->il_host & 0x0F)<<4); } ap->s_addr = htonl(final); } /* * Function to take InterNet address and fill in IMP leader fields. */ imp_addr_to_leader(imp, a) register struct imp_leader *imp; u_long a; { u_long addr = ntohl(a); imp->il_network = 0; /* !! */ if (IN_CLASSA(addr)) { imp->il_host = ((addr>>16) & 0xFF); imp->il_imp = addr & 0xFF; } else if (IN_CLASSB(addr)) { imp->il_host = ((addr>>8) & 0xFF); imp->il_imp = addr & 0xFF; } else { imp->il_host = ((addr>>4) & 0xF); imp->il_imp = addr & 0xF; } imp->il_imp = htons(imp->il_imp); } #endif INUSE; else if (next = hostdeque(hp)) (void) impsnd(&sc->imp_if, next); } goto drop; /* * Host or IMP can't be reached. Flush any packets * awaiting transmission and release the host structure. * Enqueue for notifying protocols at software interrupt time. */ case IMPTYPE_HOSTDEAD: case IMPTYPE_HOSTUNREACH: if (hp = hostlookup(addr)) { hp->h_flags |= (1 << (int)ip->il_mtype); hostfree(hp); hp->h_tsys/netimp/if_imphost.c 444 0 12 10714 4610670334 10473 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_imphost.c 1.1 (2.10BSD Berkeley) 12/1/86 */ #include "imp.h" #if NIMP > 0 /* * Host table manipulation routines. * Only needed when shipping stuff through an IMP. * * Everything in here is called at splimp from * from the IMP protocol code (if_imp.c), or * interlocks with the code at splimp. */ #include "param.h" #include "mbuf.h" #include "domain.h" #include "protosw.h" #include #include #include #include /* * Head of host table hash chains. */ struct mbuf *hosts; /* * Given an internet address * return a host structure (if it exists). */ struct host * hostlookup(addr) struct in_addr addr; { register struct host *hp; register struct mbuf *m; register int hash = HOSTHASH(addr); for (m = hosts; m; m = m->m_next) { hp = &mtod(m, struct hmbuf *)->hm_hosts[hash]; if (hp->h_addr.s_addr == addr.s_addr) { hp->h_flags |= HF_INUSE; return (hp); } } return ((struct host *)0); } /* * Enter a reference to this host's internet * address. If no host structure exists, create * one and hook it into the host database. */ struct host * hostenter(addr) struct in_addr addr; { register struct mbuf *m, **mprev; register struct host *hp, *hp0 = 0; register int hash = HOSTHASH(addr); mprev = &hosts; while (m = *mprev) { mprev = &m->m_next; hp = &mtod(m, struct hmbuf *)->hm_hosts[hash]; if ((hp->h_flags & HF_INUSE) == 0) { if (hp->h_addr.s_addr == addr.s_addr) goto foundhost; if (hp0 == 0) hp0 = hp; continue; } if (hp->h_addr.s_addr == addr.s_addr) goto foundhost; } /* * No current host structure, make one. * If our search ran off the end of the * chain of mbuf's, allocate another. */ if (hp0 == 0) { m = m_getclr(M_DONTWAIT, MT_HTABLE); if (m == NULL) return ((struct host *)0); *mprev = m; hp0 = &mtod(m, struct hmbuf *)->hm_hosts[hash]; } mtod(dtom(hp0), struct hmbuf *)->hm_count++; hp = hp0; hp->h_addr = addr; hp->h_timer = 0; hp->h_flags = 0; foundhost: hp->h_flags |= HF_INUSE; return (hp); } /* * Mark a host structure free and set it's * timer going. */ hostfree(hp) register struct host *hp; { hp->h_flags &= ~HF_INUSE; hp->h_timer = HOSTTIMER; hp->h_rfnm = 0; } /* * Reset a given network's host entries. */ hostreset(net) u_long net; { register struct mbuf *m; register struct host *hp, *lp; struct hmbuf *hm; struct mbuf *mnext; for (m = hosts; m; m = mnext) { mnext = m->m_next; hm = mtod(m, struct hmbuf *); hp = hm->hm_hosts; lp = hp + HPMBUF; while (hm->hm_count > 0 && hp < lp) { if (in_netof(hp->h_addr) == net) { hp->h_flags &= ~HF_INUSE; hostrelease(hp); } hp++; } } } /* * Remove a host structure and release * any resources it's accumulated. */ hostrelease(hp) register struct host *hp; { register struct mbuf *m, **mprev, *mh = dtom(hp); /* * Discard any packets left on the waiting q */ if (m = hp->h_q) { register struct mbuf *n; do { n = m->m_act; m_freem(m); m = n; } while (m != hp->h_q); hp->h_q = 0; } hp->h_flags = 0; hp->h_rfnm = 0; if (--mtod(mh, struct hmbuf *)->hm_count) return; mprev = &hosts; while ((m = *mprev) != mh) mprev = &m->m_next; *mprev = m_free(mh); } /* * Remove a packet from the holding q. * The RFNM counter is also bumped. */ struct mbuf * hostdeque(hp) register struct host *hp; { register struct mbuf *m; hp->h_rfnm--; HOST_DEQUE(hp, m); if (m) return (m); if (hp->h_rfnm == 0) hostfree(hp); return (0); } /* * Host data base timer routine. * Decrement timers on structures which are * waiting to be deallocated. On expiration * release resources, possibly deallocating * mbuf associated with structure. */ hostslowtimo() { register struct mbuf *m; register struct host *hp, *lp; struct hmbuf *hm; struct mbuf *mnext; int s = splimp(); for (m = hosts; m; m = mnext) { mnext = m->m_next; hm = mtod(m, struct hmbuf *); hp = hm->hm_hosts; lp = hp + HPMBUF; for (; hm->hm_count > 0 && hp < lp; hp++) { if (hp->h_timer && --hp->h_timer == 0) { if (hp->h_rfnm) printf("imp?: host %x, lost %d rfnms\n", ntohl(hp->h_addr.s_addr), hp->h_rfnm); hostrelease(hp); } } } splx(s); } #endif p0 == 0) { m = m_getclr(M_DONTWAIT, MT_HTABLE); sys/netimp/raw_imp.c 444 0 12 4751 4177133331 7753 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)raw_imp.c 1.1 (2.10BSD Berkeley) 12/1/86 */ #include "imp.h" #if NIMP > 0 #include "param.h" #include "mbuf.h" #include "domain.h" #include "protosw.h" #include "socket.h" #include "socketvar.h" #include #include #include #include #include #include #include #include /* * Raw interface to IMP. */ /* * Generate IMP leader and pass packet to impoutput. * The user must create a skeletal leader in order to * communicate message type, message subtype, etc. * We fill in holes where needed and verify parameters * supplied by user. */ rimp_output(m, so) register struct mbuf *m; struct socket *so; { struct mbuf *n; int len, error = 0; register struct imp_leader *ip; register struct sockaddr_in *sin; register struct rawcb *rp = sotorawcb(so); struct in_ifaddr *ia; struct control_leader *cp; /* * Verify user has supplied necessary space * for the leader and check parameters in it. */ if ((m->m_off > MMAXOFF || m->m_len < sizeof(struct control_leader)) && (m = m_pullup(m, sizeof(struct control_leader))) == 0) { error = EMSGSIZE; /* XXX */ goto bad; } cp = mtod(m, struct control_leader *); if (cp->dl_mtype == IMPTYPE_DATA) if (m->m_len < sizeof(struct imp_leader) && (m = m_pullup(m, sizeof(struct imp_leader))) == 0) { error = EMSGSIZE; /* XXX */ goto bad; } ip = mtod(m, struct imp_leader *); if (ip->il_format != IMP_NFF) { error = EMSGSIZE; /* XXX */ goto bad; } #ifdef notdef if (UCHAR(ip->il_link) != IMPLINK_IP && (UCHAR(ip->il_link)il_link)>IMPLINK_HIGHEXPER)) { error = EPERM; goto bad; } #endif /* * Fill in IMP leader -- impoutput refrains from rebuilding * the leader when it sees the protocol family PF_IMPLINK. * (message size calculated by walking through mbuf's) */ for (len = 0, n = m; n; n = n->m_next) len += n->m_len; ip->il_length = htons((u_short)(len << 3)); sin = (struct sockaddr_in *)&rp->rcb_faddr; imp_addr_to_leader(ip, sin->sin_addr.s_addr); /* BRL */ /* no routing here */ ia = in_iaonnetof(in_netof(sin->sin_addr)); if (ia) return (impoutput(ia->ia_ifp, m, (struct sockaddr *)sin)); error = ENETUNREACH; bad: m_freem(m); return (error); } #endif } /* * Reset a givensys/netimp/tags 751 0 12 0 6045325014 10661 2../sys/tagssys/autoconfig/ 755 0 12 0 5676753404 6737 sys/autoconfig/tags 640 0 12 3307 5676753405 7705 Mmain main.c /^main(argc,argv)$/ STRSAVE read_dtab.c /^#define STRSAVE(str) (strcpy(malloc((u_int)(strlen/ add_nlist read_nlist.c /^add_nlist(name)$/ addent read_dtab.c /^addent(listp, cp)$/ attach attach.c /^attach(dp)$/ auto_config do_config.c /^auto_config()$/ brprobe brauto.c /^brprobe(addr, vector)$/ clear_vec do_config.c /^clear_vec(dp)$/ cnprobe cnauto.c /^cnprobe(addr, vector)$/ dhprobe dhauto.c /^dhprobe(addr,vector)$/ dhuprobe dhuauto.c /^dhuprobe(addr,vector)$/ dhvprobe dhvauto.c /^dhvprobe(addr,vector)$/ dmprobe dhauto.c /^dmprobe(addr,vector)$/ dnprobe dnauto.c /^dnprobe(addr,vector)$/ do_probe do_config.c /^do_probe(dp)$/ drprobe drauto.c /^drprobe(addr,vector)$/ dzprobe dzauto.c /^dzprobe(addr,vector)$/ expect_intr do_config.c /^expect_intr(dp)$/ find_unit attach.c /^find_unit(dp)$/ grab do_config.c /^grab(where)$/ have_set attach.c /^have_set(vec)$/ hkprobe hkauto.c /^hkprobe(addr,vector)$/ htprobe htauto.c /^htprobe(addr,vector)$/ init_lowcore do_config.c /^init_lowcore(val)$/ intval do_config.c /^intval()$/ lpprobe lpauto.c /^lpprobe(addr,vector)$/ prdev do_config.c /^prdev(dp)$/ pry attach.c /^pry(dp)$/ raprobe raauto.c /^raprobe(addr,vector)$/ read_dtab read_dtab.c /^read_dtab()$/ read_nlist read_nlist.c /^read_nlist()$/ rkprobe rkauto.c /^rkprobe(addr,vector)$/ rlprobe rlauto.c /^rlprobe(addr,vector)$/ rxprobe rxauto.c /^rxprobe(addr,vector)$/ set_unused do_config.c /^set_unused()$/ siprobe siauto.c /^siprobe(addr,vector)$/ stuff do_config.c /^stuff(var, where)$/ tmprobe tmauto.c /^tmprobe(addr,vector)$/ tmsprobe tmsauto.c /^tmsprobe(addr,vector)$/ tsprobe tsauto.c /^tsprobe(addr,vector)$/ write_vector attach.c /^write_vector(addr,value,pri)$/ xpprobe xpauto.c /^xpprobe(addr,vector)$/ /* XXX */ goto bad; } #ifdef notdef if (UCHAR(ip->il_link) != IMPLINK_IP && (UCHAR(ip->il_link)il_link)>IMPLINK_HIGHEXPER)) { error = EPERM; goto bad; } #endif /* * Fill in IMP leader -- impoutput refrains from rebuilding * the leader when it sees the protocol fsys/autoconfig/Makefile 640 0 12 2451 5125223276 10446 # # Makefile for the system autoconfiguration program # DESTDIR= OBJS= attach.o do_config.o main.o read_dtab.o read_nlist.o uprobe.o \ brauto.o cnauto.o dhauto.o dhuauto.o drauto.o dzauto.o \ hkauto.o htauto.o lpauto.o raauto.o rkauto.o rlauto.o siauto.o \ tmauto.o tsauto.o xpauto.o rxauto.o dnauto.o tmsauto.o dhvauto.o SRCS= attach.c do_config.c main.c read_dtab.c read_nlist.c uprobe.c \ brauto.c cnauto.c dhauto.c dhuauto.c \ drauto.c dzauto.c hkauto.c htauto.c \ lpauto.c raauto.c rkauto.c rlauto.c \ siauto.c tmauto.c tsauto.c xpauto.c \ rxauto.c dnauto.c tmsauto.c dhvauto.c CFLAGS= -O -I. -I../h -I../pdpuba -I../pdp LFLAG= -i autoconfig: ${OBJS} ${CC} ${OBJS} -o $@ install: install -s -m 700 autoconfig ${DESTDIR}/etc depend: ${CC} -M ${CFLAGS} ${SRCS} | \ sed -e ':loop' \ -e 's/\.\.\/[^ /]*\/\.\./../' \ -e 't loop' | \ awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \ else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \ else rec = rec " " $$2 } } \ END { print rec } ' > makedep echo '/^# DO NOT DELETE THIS LINE/+1,$$d' >eddep echo '$$r makedep' >>eddep echo 'w' >>eddep ex - Makefile < eddep rm eddep makedep tags: FRC rm -f tags /usr/ucb/ctags ${SRCS} clean: FRC rm -f autoconfig *.o FRC: # DO NOT DELETE THIS LINE dnauto.o tmsauto.o dhvauto.o SRCS= attach.c do_config.c main.c read_dtab.c read_nlist.c uprobe.c \ brauto.c cnauto.c dhauto.c dhuauto.c \ drauto.c dzauto.c hkauto.c htauto.c \ lpauto.c raauto.c rkauto.c rlauto.sys/autoconfig/attach.c 640 0 12 7454 5514426503 10426 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)attach.c 2.1 (2.11BSD GTE) 1/10/94 */ /* * Attach the passed device: * Patch the interrupt vector * Call the device attach routine * * Call (if present) the vector setting routine, passing the * vector from /etc/dtab to the driver. At present only the * MSCP and TMSCP drivers have routines to do this. The detach() * routine was removed because it was superfluous. The kernel no * longer calls every driver's XXroot() entry point at start up time, * thus there is nothing to detach any more. */ #include #include #include #include #include #include "dtab.h" #include "ivec.h" extern int debug; int vec_set[NVECTOR], num_vec; attach(dp) DTAB *dp; { extern int errno; int unit, addr, ret; register HAND *sp; if ((unit = find_unit(dp)) == -1) { prdev(dp); printf(" unit already in use\n"); return; } /* first attach the device */ if (debug) printf("attach: ucall %o(PSL_BR0, %o, %o)\n",dp->dt_attach->n_value,dp->dt_addr,unit); else { errno = 0; if (!(ret = ucall(PSL_BR0, dp->dt_attach->n_value, dp->dt_addr, unit)) || ret == -1) { prdev(dp); if (ret == -1 && errno) { perror("ucall"); exit(AC_SINGLE); } printf(" attach failed\n"); return; } } /* then fill the interrupt vector */ addr = dp->dt_vector; for (sp = (HAND *)dp->dt_handlers;sp;sp = sp->s_next) { if (!sp->s_nl->n_value) { prdev(dp); printf(" no address found for %s\n", sp->s_str); exit(AC_SINGLE); } write_vector(addr, sp->s_nl->n_value, pry(dp) + unit); if (num_vec == NVECTOR - 1) { printf("Too many vectors to configure\n"); exit(AC_SINGLE); } else vec_set[num_vec++] = addr; addr += IVSIZE; } prdev(dp); if (dp->dt_setvec && dp->dt_setvec->n_value) { ret = ucall(PSL_BR0,dp->dt_setvec->n_value,unit,dp->dt_vector); if (ret == -1) { printf(" vectorset failed\n"); exit(AC_SINGLE); } printf(" vectorset"); } printf(" attached\n"); } have_set(vec) { int cnt_vec; for (cnt_vec = 0;cnt_vec < num_vec;++cnt_vec) if (vec_set[cnt_vec] == vec) return(1); return(0); } pry(dp) DTAB *dp; { switch(dp->dt_br) { case 4: return(PSL_BR4); case 5: return(PSL_BR5); case 6: return(PSL_BR6); default: prdev(dp); printf(": br%d is not supported. Assuming 7\n", dp->dt_br); case 7: return(PSL_BR7); } } write_vector(addr,value,pri) int addr, value, pri; { stuff(value,addr); stuff(pri,addr + sizeof(int)); } /* * find_unit -- Add this device to the list of devices if it isn't already * in the list somewhere. If it has an explicit unit number then use that, * else fill in the wildcard with next biggest number. */ find_unit(dp) DTAB *dp; { typedef struct done_s { char *d_name; /* device name */ int d_unit; /* current unit for wildcarding */ struct done_s *d_next; } DONE; static DONE *done, *dn; int want_unit; char *malloc(); if (!done) { /* initialize list */ done = dn = (DONE *)malloc((u_int)(sizeof(DONE))); dn->d_name = dp->dt_name; dn->d_next = NULL; if ((dn->d_unit = dp->dt_unit - 1) < -1) dn->d_unit = -1; } else for (dn = done;;dn = dn->d_next) /* search list */ if (!strcmp(dn->d_name,dp->dt_name)) break; else if (!dn->d_next) { dn->d_next = (DONE *)malloc((u_int)sizeof(DONE)); dn = dn->d_next; dn->d_next = NULL; dn->d_name = dp->dt_name; if ((dn->d_unit = dp->dt_unit - 1) < -1) dn->d_unit = -1; break; } /* fill in wildcards */ if ((want_unit = dp->dt_unit) == -1) want_unit = dn->d_unit + 1; else if (want_unit <= dn->d_unit) return(ERR); return(dn->d_unit = dp->dt_unit = want_unit); } struct ifaddr *ifa = (struct ifaddr *) data; int s = splimp(), error = 0; switch (cmd) { case SIOCSIFADDR: if (ifa->ifa_addr.sa_family != AF_INET) { error = EINVAL; break; } if ((ifp->if_flags &sys/autoconfig/do_config.c 640 0 12 20607 5516037772 11134 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)do_config.c 2.1 (2.11BSD GTE) 12/30/92 */ /* * Now with all our information, make a configuration * Devices without both attach and probe routines will * not be configured into the system */ #include #include #include #include #include #include #include #include "dtab.h" #include "ivec.h" extern int kmem, verbose, debug, errno, complain; extern NLIST *bad_nl, *good_nl, *int_nl, *end_vector, *trap_nl, *sep_nl; extern NLIST *next_nl; grab(where) u_int where; { int var; lseek(kmem,((long) where) & 0xffffL,0); read(kmem,&var,sizeof(var)); if (debug) printf("Grab %o = %o",where, var); return(var); } stuff(var, where) unsigned int where; { char s[20]; if (debug) { printf("Stuff %o @ %o\n", var, where); return; } lseek(kmem, ((long) where) & 0xffffL, 0); if (write(kmem, &var, sizeof var) < sizeof var) { sprintf(s, "stuff 0%o", where); perror(s); } } prdev(dp) DTAB *dp; { printf("%s ", dp->dt_name); if (dp->dt_unit == -1) putchar('?'); else printf("%d", dp->dt_unit); printf(" csr %o vector %o", dp->dt_addr, dp->dt_vector); } /* * Go through the configuration table and probe all the devices. Call * attach for ones which exist. Probe routines should return * ACP_NXDEV No such device * ACP_IFINTR Device exists if interrupts ok * ACP_EXISTS Device exists * All interrupt vectors are poked to either point to conf_goodvec or * conf_badvec which change the value of conf_int. Values of this * variable are: * ACI_BADINTR Device interrupted through wrong vector * ACI_NOINTR Device didn't interrupt * ACI_GOODINTR Interrupt ok */ auto_config() { register DTAB *dp; int ret; if (intval() != CONF_MAGIC) { fputs(myname,stderr); fputs(": namelist doesn't match running kernel.\n",stderr); exit(AC_SETUP); } init_lowcore(bad_nl->n_value); for (dp = devs; dp != NULL; dp = dp->dt_next) { /* * Make sure we have both a probe and attach routine */ if (!((dp->dt_uprobe || (dp->dt_probe && dp->dt_probe->n_value)) && (dp->dt_attach && dp->dt_attach->n_value))) { if (debug || verbose) { prdev(dp); puts(" skipped: No autoconfig routines."); } continue; } /* Make sure the CSR is there */ errno = 0; grab(dp->dt_addr); if (errno) { if (errno != EFAULT && errno != ENXIO) perror("Reading CSR"); if (debug || verbose) { prdev(dp); puts(" skipped: No CSR."); } continue; } /* Ok, try a probe now */ if (expect_intr(dp)) { if (complain) { prdev(dp); puts(" interrupt vector already in use."); } continue; } ret = do_probe(dp); clear_vec(dp); switch (ret) { case ACP_NXDEV: if (debug || verbose) { prdev(dp); puts(" does not exist."); } break; case ACP_IFINTR: switch (intval()) { case ACI_BADINTR: if (debug || verbose || complain) { prdev(dp); puts(" interrupt vector wrong."); } break; case ACI_NOINTR: if (complain) { prdev(dp); puts(" didn't interrupt."); } break; case ACI_GOODINTR: attach(dp); break; default: prdev(dp); printf(" bad interrupt value %d.\n", intval()); break; } break; case ACP_EXISTS: attach(dp); break; default: prdev(dp); printf(" bad probe value %d.\n", ret); break; } } set_unused(); } /* * Return the current value of the interrupt return flag. * Initial value is the magic number */ static int conf_int = CONF_MAGIC; intval() { if (debug) return conf_int; else return grab(int_nl->n_value); } static int save_vec[9][2], save_p; /* * Fill all interrupt vectors of this device with pointers to * the good interrupt vector routine. Also save values to * later restore them. Since we init_lowcore() everything to * conf_badint, anything not equalling that indicates a vector * which is already in use; unless the vector was initialized in l.s, * this device should be skipped. */ expect_intr(dp) DTAB *dp; { HAND *hp; register int addr = dp->dt_vector; /* * A vector of 0 has special meaning for devices which support programmable * (settable) vectors. If a xxVec() entry point is present in the driver and * /etc/dtab has a value of 0 for the vector then 'autoconfig' will allocate * one by calling the kernel routine 'nextiv'. * * If multiple handlers are declared for a device (at present there are no * progammable vector devices with more than 1 handler) the vector passed * to the driver will be the lowest one (the first handle corresponds to * the lowest vector). */ if (!addr) { if (dp->dt_setvec == 0) { prdev(dp); printf(" vector = 0, %sVec undefined\n", dp->dt_name); return(1); } /* * Now count the number of vectors needed. This has the side effect of * allocating the vectors even if an error occurs later. At the end of * the scan the last vector assigned will be the lowest one. In order to * assure adjacency of multiple vectors BR7 is used in the call to the * kernel and it is assumed that at this point in the system's life * nothing else is allocating vectors (the networking has already grabbed the * ones it needs by the time autoconfig is run). */ for (hp = dp->dt_handlers; hp; hp = hp->s_next) { addr = ucall(PSL_BR7, next_nl->n_value, 0, 0); if (addr <= 0) { printf("'nextiv' error for %s\n", dp->dt_name); return(1); } } /* * Now set the lowest vector allocated into the device entry for further * processing. From this point on the vector will behave just as if it * had been read from /etc/dtab. */ dp->dt_vector = addr; } for (save_p = 0, hp = (HAND *)dp->dt_handlers;hp;hp = hp->s_next) { save_vec[save_p][1] = grab(addr + sizeof(int)); if (((save_vec[save_p][0] = grab(addr)) != bad_nl->n_value) && ((save_vec[save_p][0] != hp->s_nl->n_value) || have_set(addr))) { clear_vec(dp); return 1; } save_p++; write_vector(addr, good_nl->n_value, PSL_BR7); addr += IVSIZE; } return 0; } clear_vec(dp) register DTAB *dp; { register int addr = dp->dt_vector, n; for (n = 0; n < save_p; n++) { write_vector(addr, save_vec[n][0], save_vec[n][1]); addr += IVSIZE; } } init_lowcore(val) { int addr; if (debug) return; for (addr = 0; addr < end_vector->n_value; addr += IVSIZE) { if (grab(addr) || grab(addr + 2)) continue; write_vector(addr, val, PSL_BR7); } } do_probe(dp) register DTAB *dp; { int func; int ret; func = dp->dt_probe->n_value; if (debug) { char line[80]; if (func) printf("ucall %o(PSL_BR0, %o, 0):", func, dp->dt_addr); else printf("probe %s:", dp->dt_name); fputs(" return conf_int:",stdout); gets(line); sscanf(line, "%o%o", &ret, &conf_int); return ret; } stuff(0, int_nl->n_value); /* Clear conf_int */ /* * use the kernel's probe routine if it exists, * otherwise use our internal probe. Pass it the first (lowest) * vector assigned to the device. */ if (func) { errno = 0; ret = ucall(PSL_BR0, func, dp->dt_addr, dp->dt_vector); if (errno) perror("ucall"); return(ret); } return((*(dp->dt_uprobe))(dp->dt_addr, dp->dt_vector)); } set_unused() { int addr; if (debug) return; if (sep_nl->n_value) { /* * On non-separate I/D kernel, attempt to set up catcher * at 0 for both jumps and traps to 0. * On traps, set PS for randomtrap, with the catcher at 0444. * On jumps, branch to 0112, then to 050 (where there's space). * The handler at 50 is already in place. * The funny numbers are due to attempts to find vectors * that are unlikely to be used, and the need for the value * at 0 to serve as both a vector and an instruction * (br 112 is octal 444). */ if ((grab(0110) == bad_nl->n_value) && (grab(0112) == PSL_BR7) && (grab(0444) == bad_nl->n_value) && (grab(0446) == PSL_BR7)) { stuff(0444, 0); /* br 0112 */ stuff(PSL_BR7 + T_ZEROTRAP, 2); stuff(trap_nl->n_value, 0110); /* trap; 756 (br7+14.)*/ stuff(0756, 0112); /* br 050 */ stuff(0137, 0444); /* jmp $*trap */ stuff(trap_nl->n_value, 0446); } } for (addr = 0; addr < end_vector->n_value; addr += IVSIZE) { if (grab(addr) != bad_nl->n_value) continue; write_vector(addr, trap_nl->n_value, PSL_BR7+T_RANDOMTRAP); } } inters to * the good interrupt vector routine. Also save values to * later restore them. Since we init_lowcore() eversys/autoconfig/dtab.h 640 0 12 2210 5303075623 10061 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dtab.h 2.0 (2.11BSD GTE) 11/20/92 */ /* * Internal structure used to store info from the device table */ typedef struct nlist NLIST; typedef struct handler_s { struct handler_s *s_next; char *s_str; NLIST *s_nl; } HAND; typedef struct dtab_s { struct dtab_s *dt_next; /* Next device in list */ char *dt_name; /* Two character device name */ int dt_unit; /* Unit number, -1 is wildcard */ int dt_addr; /* CSR address */ int dt_vector; /* Interrupt vector */ HAND *dt_handlers; /* Interrupt handlers */ int dt_br; /* Priority */ int (*dt_uprobe)(); /* User-level (internal) probe */ NLIST *dt_probe, /* Address of probe function */ *dt_setvec, /* Address of vector set function */ *dt_attach; /* Address of attach function */ } DTAB; DTAB *devs; /* Head of device list */ #define EOS '\0' /* end of string */ #define ERR -1 /* general error */ extern char *myname, /* program name */ *dtab_name; /* dtab file name */ evice entry for further * processing. From this point on the vector will behave just as if it * had been read from /etc/dtab. */ dp->dt_vector = addr; } for (save_p = 0, hp = (HAND *)dp->dt_handlers;hp;hp = hp->s_next) { save_vec[save_p][1] = grab(addr + sizeof(int)); if (((save_vec[save_p][0] = grab(addr)) != bad_nl->n_value) && ((save_vec[save_p][0] != hsys/autoconfig/ivec.h 640 0 12 772 5320444226 10066 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ivec.h 1.2 (2.11BSD Berkeley) 12/30/92 */ struct vec_s { int v_func; int v_br; } ivec; #define IVSIZE (sizeof ivec) /* * increased from 100 to 128 to allow for vectors to be allocated * backwards from 01000 (512) via calls to 'nextiv' */ #define NVECTOR 128 /* max. number of vectors we can set */ cnausys/autoconfig/main.c 640 0 12 3631 4021263265 10073 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)main.c 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * sysconfig -- Program to auto configure a kernel to the devices which * are present. Needs the ucall() system call and special kernel to work. */ #include #include char *nlist_name = "/unix", /* kernel */ *dtab_name = "/etc/dtab", /* dtab file */ *myname; /* program name */ int kmem, verbose = NO, debug = NO, complain = NO, pflag = NO; main(argc,argv) int argc; char **argv; { extern char *optarg; static char *kmem_name = "/dev/kmem"; int c; char *C, *rindex(); setbuf(stdout, NULL); myname = (C = rindex(*argv,'/')) ? ++C : *argv; while((c = getopt(argc,argv,"Pcdi:k:n:v")) != EOF) switch((char)c) { case 'P': /* pflag, ask Mike */ pflag = YES; break; case 'c': /* complain about bad vectors */ complain = YES; break; case 'd': /* debugging run */ debug = YES; break; case 'i': /* not dtab, different file */ dtab_name = optarg; break; case 'k': /* not /dev/kmem, different file */ kmem_name = optarg; break; case 'n': /* not /unix, different file */ nlist_name = optarg; break; case 'v': /* verbose output */ verbose = YES; break; default: fputs("usage: ",stderr); fputs(myname,stderr); fputs(" [-c] [-d] [-v] [-i file] [-k file] [-n file]\n",stderr); exit(AC_SETUP); } if ((kmem = open(kmem_name, 2)) < 0) { perror(kmem_name); exit(AC_SETUP); } /* Read the dtab into internal tables so we can play with it */ read_dtab(); /* Now set up for and call nlist so we can get kernel symbols */ read_nlist(); /* And at last change the kernel to suit ourselves */ auto_config(); /* All done go bye bye now */ exit(AC_OK); } eturn; for (addr = 0; addr < end_vector->n_value; addr += IVSIZE) { if (grab(addr) || grab(addr + 2)sys/autoconfig/read_dtab.c 640 0 12 6101 5514426535 11060 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)read_dtab.c 2.1 (2.11BSD GTE) 1/10/94 */ #include #include #include #include #include "dtab.h" #include "uprobe.h" extern UPROBE uprobe[]; int guess_ndev = 0; /* Guess as to size of nlist table */ #define STRSAVE(str) (strcpy(malloc((u_int)(strlen(str) + 1)),str)) /* * read the device table (/etc/dtab) into internal structures * format of lines in the device table are: * device_name unit_number address vector br handler[0-3] ; comment * # comment */ read_dtab() { register DTAB *dp, *cdp; UPROBE *up; HAND *sp; FILE *fp; int nhandlers, /* number of handlers per line */ line; /* line number in dtab file */ short cnt; /* general counter */ char *cp, /* traveling char pointer */ *save, /* save string position */ buf[500], /* line buffer */ name[20], /* device name */ unit[5], /* unit number */ *index(), *malloc(), *strcpy(), *fgets(); if (!(fp = fopen(dtab_name,"r"))) { perror(dtab_name); exit(AC_SETUP); } for (line = 1,devs = NULL;fgets(buf, sizeof(buf), fp);++line) { if (cp = index(buf, '\n')) *cp = EOS; else { fprintf(stderr,"%s: line %d too long.\n",myname,line); exit(AC_SINGLE); } for (cp = buf;isspace(*cp);++cp); if (!*cp || cp == ';' || *cp == '#') continue; dp = (DTAB *)malloc(sizeof(DTAB)); if (sscanf(buf," %s %s %o %o %o ",name,unit,&dp->dt_addr,&dp->dt_vector,&dp->dt_br) != 5) { fprintf(stderr,"%s: missing information on line %d.\n",myname,line); exit(AC_SINGLE); } dp->dt_name = STRSAVE(name); dp->dt_unit = *unit == '?' ? -1 : atoi(unit); for (cnt = 0;cnt < 5;++cnt) { for (;!isspace(*cp);++cp); for (;isspace(*cp);++cp); } dp->dt_probe = dp->dt_attach = (NLIST *)0; dp->dt_handlers = (HAND *)0; for (nhandlers = 0;;nhandlers) { if (!*cp || *cp == ';' || *cp == '#') break; if (++nhandlers == 4) fprintf(stderr,"%s: warning: more than three handlers for device %s on line %d.\n",myname,dp->dt_name,line); for (save = cp;!isspace(*cp);++cp); *cp = EOS; addent(&dp->dt_handlers,STRSAVE(save)); for (++cp;isspace(*cp);++cp); } guess_ndev += nhandlers; /* * In addition to the "handler" symbols for a device we need 3 more * symbols: 'xxVec', 'xxprobe', and 'xxattach'. * * N.B. If more symbols are added (to the 'DTAB' structure) the following * line may need to be modified. */ guess_ndev += 3; for (up = uprobe;up->up_name;++up) if (!strcmp(dp->dt_name,up->up_name)) { dp->dt_uprobe = up->up_func; break; } dp->dt_next = NULL; if (!devs) devs = cdp = dp; else { cdp->dt_next = dp; cdp = dp; } } } static addent(listp, cp) HAND **listp; char *cp; { HAND *el, *sp; char *malloc(); el = (HAND *)malloc(sizeof(HAND)); el->s_str = cp; el->s_next = NULL; if (!*listp) *listp = el; else { for (sp = *listp;sp->s_next; sp = sp->s_next); sp->s_next = el; } } (where there's space). * The handler at 50 is already in place. * The funny numbers are due to attempts to find vectors * that are unlikely to be used, and the need for the value * at 0 to serve as both a vector and an instruction * (br 112 is octal 444). */ if ((grab(0110) == bad_nl->n_value) && (grab(0112) == PSL_BR7) && (grab(0444) == bad_nl->n_value) && (grab(0446) == PSL_BR7)) { stuff(0444, 0); /* br 0112 */sys/autoconfig/read_nlist.c 640 0 12 7615 5516036624 11310 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)read_nlist.c 2.2 (2.11BSD GTE) 1/10/94 */ /* * Read all the symbols we'll need for the devices we want to configure * These are -- The probe, attach and handler routines for each device, * and a few symbols that we'll need later on. */ #include #include #include #include #include #include "dtab.h" extern char *strdup(); extern char *nlist_name; /* file we read the namelist from */ extern int guess_ndev; /* number of lines read from dtab */ extern int debug; extern int kmem; extern int pflag; NLIST *nl, *np, *int_nl, *good_nl, *bad_nl, *trap_nl, *sep_nl, *vers_nl, *add_nlist(), *end_vector, *next_nl; #define END_NAME "endvec" #define NEXTIV_NAME "_nextiv" /* floating vector allocator */ #define INT_NAME "_conf_int" #define GOOD_NAME "CGOOD" #define BAD_NAME "CBAD" #define TRAP_NAME "trap" #define SEPID_NAME "KERN_NONSEP" /* KERN_NONSEP */ #define VERSION "_version" read_nlist() { register NLIST **lp, *nnp; register DTAB *dp; struct exec head; struct ovlhdr ovhead; HAND *already = (HAND *)NULL, *sp; off_t offst; int unix_fd; short cnt; char tname[20], unix_vers[100], core_vers[100], *calloc(); NLIST *add_nlist(); np = nl = (NLIST *)calloc(guess_ndev + 10,sizeof(NLIST)); for (dp = devs; dp != NULL; dp = dp->dt_next) { sprintf(tname, "_%sprobe", dp->dt_name); dp->dt_probe = add_nlist(tname); sprintf(tname, "_%sattach", dp->dt_name); dp->dt_attach = add_nlist(tname); sprintf(tname, "_%sVec", dp->dt_name); dp->dt_setvec = add_nlist(tname); for (sp = dp->dt_handlers;sp;sp = sp->s_next) sp->s_nl = add_nlist(sp->s_str); } end_vector = np++; end_vector->n_un.n_name = END_NAME; int_nl = np++; int_nl->n_un.n_name = INT_NAME; good_nl = np++; good_nl->n_un.n_name = GOOD_NAME; bad_nl = np++; bad_nl->n_un.n_name = BAD_NAME; next_nl = np++; next_nl->n_un.n_name = NEXTIV_NAME; trap_nl = np++; trap_nl->n_un.n_name = TRAP_NAME; vers_nl = np++; vers_nl->n_un.n_name = VERSION; sep_nl = np++; sep_nl->n_un.n_name = SEPID_NAME; if ((unix_fd = open(nlist_name,O_RDONLY)) < 0) { perror(nlist_name); exit(AC_SETUP); } nlist(nlist_name,nl); if (debug || pflag) for (np = nl; np->n_un.n_name; np++) printf("%s = %o\n", np->n_un.n_name, np->n_value); for (np = end_vector; np <= trap_nl; np++) if (!np->n_value) { fprintf(stderr,"%s: couldn't find symbols in %s.\n",myname,nlist_name); exit(AC_SETUP); } if (!debug) { #define round(x) (ctob(stoc(ctos(btoc(x))))) lseek(unix_fd,(off_t)0,L_SET); read(unix_fd,(char *)&head,sizeof(head)); offst = (off_t)vers_nl->n_value + (off_t)head.a_text + sizeof(head); if (head.a_magic == A_MAGIC2 || head.a_magic == A_MAGIC5) offst -= (off_t)round(head.a_text); if (head.a_magic == A_MAGIC5 || head.a_magic == A_MAGIC6) { read(unix_fd,(char *)&ovhead,sizeof(ovhead)); offst += sizeof(ovhead); if (head.a_magic == A_MAGIC5) offst -= (off_t)round(ovhead.max_ovl); for (cnt = 0;cnt < NOVL;++cnt) offst += (off_t)ovhead.ov_siz[cnt]; } lseek(unix_fd,offst,L_SET); read(unix_fd,unix_vers,sizeof(unix_vers)); lseek(kmem,(off_t)vers_nl->n_value,L_SET); read(kmem,core_vers,sizeof(core_vers)); unix_vers[99] = core_vers[99] = EOS; /* Just in case! */ if (strcmp(unix_vers,core_vers)) { fprintf(stderr,"%s: %s is not the running version.\n",myname,nlist_name); exit(AC_SETUP); } } close(unix_fd); } /* * If the passed symbol is in the nlist table, return pointer to it, * otherwise add it to the table and return a pointer to new entry. */ NLIST * add_nlist(name) char *name; { register NLIST *n; for (n = nl;n < np;++n) if (!strcmp(n->n_un.n_name, name)) return(n); np->n_un.n_name = strdup(name); return(np++); } to * the good interrupt vector routine. Also save values to * later restore them. Since we init_lowcore() eversys/autoconfig/uprobe.h 640 0 12 471 4021263265 10427 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)uprobe.h 1.1 (2.10BSD Berkeley) 12/1/86 */ typedef struct uprobe { char *up_name; int (*up_func)(); } UPROBE; hkauto.cghtauto.cglpauto.cgraauto.cg rkauto.cg rlauto.cg rxauto.cg siauto.cg tmauto.cg tmsauto.ctsauto.cgxpauto.cgcnausys/autoconfig/uprobe.c 640 0 12 3633 5407761565 10464 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)uprobe.c 2.1 (2.11BSD GTE) 6/16/93 */ /* * The uprobe table contains the pointers to the user-level probe routines * that may attempt to make various devices interrupt. * * NOTES: * Reads and writes to kmem (done by grab, stuff) are currently done a * byte at a time in the kernel. Also, many of these are untested and * some of them assume that if something is at the address, it is the * correct device. Others assume that if something *isn't* at the * address, the correct device *is*. Why are you looking at me like * that? */ #include "uprobe.h" int xpprobe(), hkprobe(), rlprobe(), rkprobe(), htprobe(), siprobe(), tmprobe(), tsprobe(), cnprobe(), dzprobe(), dhprobe(), dmprobe(), drprobe(), lpprobe(), dhuprobe(), raprobe(), rxprobe(), brprobe(), dnprobe(), tmsprobe(), dhvprobe(); UPROBE uprobe[] = { "hk", hkprobe, /* hk -- rk611, rk06/07 */ "hp", xpprobe, /* hp -- rjp04/06, rwp04/06 */ "ra", raprobe, /* ra -- MSCP */ "rk", rkprobe, /* rk -- rk05 */ "rl", rlprobe, /* rl -- rl01/02 */ "si", siprobe, /* si -- SI 9500 for CDC 9766 */ "xp", xpprobe, /* xp -- rm02/03/05, rp04/05/06, Diva, Ampex, SI Eagle */ "ht", htprobe, /* ht -- tju77, twu77, tje16, twe16 */ "tm", tmprobe, /* tm -- tm11 */ "ts", tsprobe, /* ts -- ts11 */ "dh", dhprobe, /* dh -- DH11 */ "dm", dmprobe, /* dm -- DM11 */ "dr", drprobe, /* dr -- DR11W */ "du", dhuprobe, /* du -- DHU11 */ "dhv", dhvprobe, /* dhv -- DHV11 */ "dz", dzprobe, /* dz -- dz11 */ "cn", cnprobe, /* cn -- kl11, dl11 */ "lp", lpprobe, /* lp -- line printer */ "rx", rxprobe, /* rx -- RX01/02 */ "br", brprobe, /* br -- EATON 1538 BR1537/BR1711 */ "dn", dnprobe, /* dn -- dn11 autodialer */ "tms", tmsprobe, /* tms -- TMSCP tape controller */ 0, 0, }; = nl = (NLIST *)calloc(guess_ndev + 10,sizeof(NLIST)); for (dp = devs; dp != NULL; dp = dp->dt_nextsys/autoconfig/brauto.c 640 0 12 670 5320450566 10430 #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" #include "brreg.h" /* * Can't seem to force an interrupt reliably, so... we just return * the fact that we exist. autoconfig has already checked for our CSR. */ brprobe(addr, vector) struct brdevice *addr; int vector; { /* stuff(BR_IDE | BR_IDLE | BR_GO, (&(addr->brcs.w))); DELAY(10L); stuff(0, (&(addr->brcs.w))); */ return(ACP_EXISTS); } tmauto.cg tmsauto.ctsauto.cgxpauto.cgcnausys/autoconfig/dhauto.c 640 0 12 1702 5320450674 10435 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dhauto.c 1.2 (2.11BSD GTE) 12/30/92 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" #include "ioctl.h" #include "dhreg.h" #include "dmreg.h" dhprobe(addr,vector) struct dhdevice *addr; int vector; { stuff(DH_TIE, &(addr->un.dhcsr)); DELAY(5L); stuff((B9600 << 10) | (B9600 << 6) | BITS7|PENABLE, &(addr->dhlpr)); stuff(-1, &(addr->dhbcr)); stuff(0, &(addr->dhcar)); stuff(1, &(addr->dhbar)); DELAY(35000L); /* wait 1/10'th of a sec for interrupt */ DELAY(35000L); stuff(0, &(addr->un.dhcsr)); return(ACP_IFINTR); } dmprobe(addr,vector) struct dmdevice *addr; int vector; { stuff(grab(&(addr->dmcsr)) | DM_DONE | DM_IE, &(addr->dmcsr)); DELAY(20L); stuff(0, &(addr->dmcsr)); return(ACP_IFINTR); } hprobe, /* dh -- DH11 */ "dm", dmprobe, /* dm -- DM11 */ "drsys/autoconfig/dhuauto.c 640 0 12 725 5320450724 10602 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dhuauto.c 1.2 (2.11BSD GTE) 12/30/92 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" dhuprobe(addr,vector) u_int *addr; int vector; { extern int errno; errno = 0; grab(addr); return(errno ? ACP_NXDEV : ACP_EXISTS); } tsauto.cgxpauto.cgcnausys/autoconfig/dnauto.c 640 0 12 450 5320450770 10417 #include "param.h" #include "dnreg.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" dnprobe(addr,vector) struct dndevice *addr; int vector; { stuff(DN_MINAB | DN_INTENB | DN_DONE, (&(addr->dnisr[0]))); DELAY(5L); stuff(0, (&(addr->dnisr[0]))); return(ACP_IFINTR); } dzauto.cghkauto.cghtauto.cglpauto.cgraauto.cg rkauto.cg rlauto.cg rxauto.cg siauto.cg tmauto.cg tmsauto.ctsauto.cgxpauto.cgcnausys/autoconfig/drauto.c 640 0 12 1067 5320451020 10435 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)drauto.c 1.2 (2.11BSD GTE) 12/30/92 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" #include "drreg.h" drprobe(addr,vector) struct drdevice *addr; int vector; { stuff(DR_MANT, &(addr->csr)); /* toggle maintence bit */ stuff(0, &(addr->csr)); /* to reset dr11 */ return(ACP_EXISTS); /* can't make it interrupt */ } uff(-1, &(addr->dhbcr)); tuff(0, &(addr->dhcar)); stuff(1, &(addr->dhbar)); DELAY(35000L); /* wait 1/10'th of a sec for interrupt */ DELAY(35000L); stuff(0, &(addr->un.dhcsr)); return(ACP_IFINTR); } dmprobe(addr,vector) struct dmdevice *addr; int vector; { stuff(grab(&(addr->dmcsr)) | DM_DONE | DM_IE, &(addr->dmcsr)); DELAY(20L); stuff(0, &(addr->dmcsr)); return(ACP_IFINTR); } hprobe, /* dh -- DH11 */ "dm", dmprobe, /* dm -- DM11 */ "drsys/autoconfig/dzauto.c 640 0 12 1113 5320451050 10440 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dzauto.c 1.2 (2.11BSD GTE) 12/30/92 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" #include "dzreg.h" dzprobe(addr,vector) struct dzdevice *addr; int vector; { stuff(grab(&(addr->dzcsr)) | DZ_TIE | DZ_MSE, &(addr->dzcsr)); stuff(1, &(addr->dztcr)); DELAY(35000L); DELAY(35000L); stuff(DZ_CLR, &(addr->dzcsr)); return(ACP_IFINTR); } r)); tuff(0, &(addr->dhcar)); stuff(1, &(addr->dhbar)); DELAY(35000L); /* wait 1/10'th of a sec for interrupt */ DELAY(35000L); stuff(0, &(addr->un.dhcsr)); return(ACP_IFINTR); } dmprobe(addr,vector) struct dmdevice *addr; int vector; { stuff(grab(&(addr->dmcsr)) | DM_DONE | DM_IE, &(addr->dmcsr)); DELAY(20L); stuff(0, &(addr->dmcsr)); return(ACP_IFINTR); } hprobe, /* dh -- DH11 */ "dm", dmprobe, /* dm -- DM11 */ "drsys/autoconfig/hkauto.c 640 0 12 1023 5320451101 10422 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)hkauto.c 1.2 (2.11BSD GTE) 12/30/92 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" #include "hkreg.h" hkprobe(addr,vector) struct hkdevice *addr; int vector; { stuff(HK_CDT | HK_IE | HK_CRDY, (&(addr->hkcs1))); DELAY(10L); stuff(HK_CDT, (&(addr->hkcs1))); return(ACP_IFINTR); } 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)hkauto.c 1.2 (2.11BSD GTE) 12/30/92 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" #include "hkreg.h" hkprobe(addr,vector) struct hkdevice *addr; int vector; { stuff(HK_CDT | HK_IE | HK_CRDY, (&(addr->hkcs1))); DELAY(10L); stuff(HK_CDT, (&(addr->hkcs1))); retsys/autoconfig/htauto.c 640 0 12 1704 5320451150 10445 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)htauto.c 1.2 (2.11BSD GTE) 12/30/92 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" #include "htreg.h" htprobe(addr,vector) struct htdevice *addr; int vector; { /* * I can't get the hardware to interrupt when a transport is selected * without doing i/o, so I select transport 0 on driver 7 (that's tape * drive 56). If you happen to have 56 tape drives on your system and * you boot with it on line, tough. */ stuff(07, (&(addr->htcs2))); stuff(HT_SENSE | HT_IE | HT_GO, (&(addr->htcs1))); DELAY(10L); stuff(0, (&(addr->htcs1))); /* * clear error condition, or driver will report an error first * time you open it after the boot. */ stuff(HTCS2_CLR, (&(addr->htcs2))); return(ACP_IFINTR); } robe, /* dh -- DH11 */ "dm", dmprobe, /* dm -- DM11 */ "drsys/autoconfig/lpauto.c 640 0 12 1205 5320451213 10441 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)lpauto.c 1.2 (2.11BSD GTE) 12/30/92 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" /* * LP_IE and lpdevice copied from lp.c!!! */ #define LP_IE 0100 /* interrupt enable */ struct lpdevice { short lpcs; short lpdb; }; lpprobe(addr,vector) struct lpdevice *addr; int vector; { stuff(grab(&(addr->lpcs)) | LP_IE, &(addr->lpcs)); DELAY(10L); stuff(0, &(addr->lpcs)); return(ACP_IFINTR); } it on line, tough. */ stuff(07, (&(addr->htcs2))); stuff(HT_SENSE | HT_IE | HT_GO, (&(addr->htcs1))); DELAY(10L); stuff(0, (&(addr->htcs1))); /* * clear error condition, or driver will report an error first * time you open it after the boot. */ stuff(HTCS2_CLR, (&(addr->htcs2))); return(ACP_IFINTR); } robe, /* dh -- DH11 */ "dm", dmprobe, /* dm -- DM11 */ "drsys/autoconfig/raauto.c 640 0 12 1217 5320451456 10444 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)raauto.c 1.2 (2.11BSD GTE) 12/30/92 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" /* * This is one of the few devices which could use the 'vector' parameter. * Forcing an interrupt from a MSCP device is a large enough undertaking * that it hasn't been done (yet). */ raprobe(addr,vector) u_int *addr; int vector; { extern int errno; errno = 0; grab(addr); return(errno ? ACP_NXDEV : ACP_EXISTS); } e, tough. */ stuff(07, (&(addr->htcs2))); stuff(HT_SENSE | HT_IE | HT_GO, (&(addr->htcs1))); DELAY(10L); stuff(0, (&(addr->htcs1))); /* * clear error condition, or driver will report an error first * time you open it after the boot. */ stuff(HTCS2_CLR, (&(addr->htcs2))); return(ACP_IFINTR); } robe, /* dh -- DH11 */ "dm", dmprobe, /* dm -- DM11 */ "drsys/autoconfig/rkauto.c 640 0 12 1024 5320451520 10442 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)rkauto.c 1.2 (2.11BSD GTE) 12/30/92 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" #include "rkreg.h" rkprobe(addr,vector) struct rkdevice *addr; int vector; { stuff(RKCS_IDE | RKCS_DRESET | RKCS_GO, (&(addr->rkcs))); DELAY(10L); stuff(0, (&(addr->rkcs))); return(ACP_IFINTR); } ctor) u_int *addr; int vector; { extern int errno; errn= 0; grab(addr); return(errno ? ACP_NXDEV : ACP_EXISTS); } e, tough. */ stuff(07, (&(addr->htcs2))); stuff(HT_SENSE | HT_IE | HT_GO, (&(addr->htcs1))); DELAY(10L); stuff(0, (&(addr->htcs1))); /* * clear error condition, or driver will report an error first * time you open it after the boot. */ stuff(HTCS2_CLR, (&(addr->htcs2))); return(ACP_IFINTR); } robe, /* dh -- DH11 */ "dm", dmprobe, /* dm -- DM11 */ "drsys/autoconfig/rlauto.c 640 0 12 1113 5320451550 10445 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)rlauto.c 2.1 (2.11BSD GTE) 12/30/92 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" #include "rlreg.h" rlprobe(addr,vector) struct rldevice *addr; int vector; { stuff(RLDA_RESET | RLDA_GS, (&(addr->rlda))); DELAY(10L); stuff(RL_GETSTATUS | RL_IE , (&(addr->rlcs))); DELAY(10L); stuff(RL_CRDY, (&(addr->rlcs))); return(ACP_IFINTR); } errn= 0; grab(addr); return(errno ? ACP_NXDEV : ACP_EXISTS); } e, tough. */ stuff(07, (&(addr->htcs2))); stuff(HT_SENSE | HT_IE | HT_GO, (&(addr->htcs1))); DELAY(10L); stuff(0, (&(addr->htcs1))); /* * clear error condition, or driver will report an error first * time you open it after the boot. */ stuff(HTCS2_CLR, (&(addr->htcs2))); return(ACP_IFINTR); } robe, /* dh -- DH11 */ "dm", dmprobe, /* dm -- DM11 */ "drsys/autoconfig/rxauto.c 640 0 12 1046 5320451601 10463 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)rxauto.c 1.2 (2.11BSD GTE) 12/30/92 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" #include "rxreg.h" /* * rxprobe - check for rx */ rxprobe(addr,vector) struct rxdevice *addr; int vector; { stuff(RX_INIT | RX_IE, (&(addr)->rxcs)); DELAY(1000L); stuff(0, (&(addr)->rxcs)); return(ACP_IFINTR); } ddr->rlcs))); return(ACP_IFINTR); } errn= 0; grab(addr); return(errno ? ACP_NXDEV : ACP_EXISTS); } e, tough. */ stuff(07, (&(addr->htcs2))); stuff(HT_SENSE | HT_IE | HT_GO, (&(addr->htcs1))); DELAY(10L); stuff(0, (&(addr->htcs1))); /* * clear error condition, or driver will report an error first * time you open it after the boot. */ stuff(HTCS2_CLR, (&(addr->htcs2))); return(ACP_IFINTR); } robe, /* dh -- DH11 */ "dm", dmprobe, /* dm -- DM11 */ "drsys/autoconfig/siauto.c 640 0 12 1053 5320451627 10453 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)siauto.c 1.2 (2.11BSD GTE) 12/30/92 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" #include "sireg.h" siprobe(addr,vector) struct sidevice *addr; int vector; { stuff(SI_IE | SI_READ, &(addr->sicnr)); stuff(SI_IE | SI_READ | SI_DONE, &(addr->sicnr)); DELAY(10L); stuff(0, &(addr->sicnr)); return(0); } rlcs))); return(ACP_IFINTR); } errn= 0; grab(addr); return(errno ? ACP_NXDEV : ACP_EXISTS); } e, tough. */ stuff(07, (&(addr->htcs2))); stuff(HT_SENSE | HT_IE | HT_GO, (&(addr->htcs1))); DELAY(10L); stuff(0, (&(addr->htcs1))); /* * clear error condition, or driver will report an error first * time you open it after the boot. */ stuff(HTCS2_CLR, (&(addr->htcs2))); return(ACP_IFINTR); } robe, /* dh -- DH11 */ "dm", dmprobe, /* dm -- DM11 */ "drsys/autoconfig/tmauto.c 640 0 12 1117 5320451651 10456 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)tmauto.c 1.2 (2.11BSD GTE) 12/30/92 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" #include "tmreg.h" tmprobe(addr,vector) struct tmdevice *addr; { extern int errno; stuff(TM_IE, &(addr->tmcs)); errno = 0; /* check distant register, make */ grab(&(addr->tmba)); /* sure this isn't a ts-11 */ return(errno ? ACP_NXDEV : ACP_IFINTR); } n= 0; grab(addr); return(errno ? ACP_NXDEV : ACP_EXISTS); } e, tough. */ stuff(07, (&(addr->htcs2))); stuff(HT_SENSE | HT_IE | HT_GO, (&(addr->htcs1))); DELAY(10L); stuff(0, (&(addr->htcs1))); /* * clear error condition, or driver will report an error first * time you open it after the boot. */ stuff(HTCS2_CLR, (&(addr->htcs2))); return(ACP_IFINTR); } robe, /* dh -- DH11 */ "dm", dmprobe, /* dm -- DM11 */ "drsys/autoconfig/tmsauto.c 640 0 12 1430 5320452065 10637 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)tmsauto.c 1.1 (2.11BSD GTE) 12/30/92 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" /* * The TMSCP controller is another one which has programmable vectors. * The kernel and autoconfigure program have been modified to handle this, * which is why the vector is being passed to all of the probe routines. * For now just continue testing for the presence of a device until a * real probe routine can be written. */ tmsprobe(addr,vector) u_int *addr; { extern int errno; errno = 0; grab(addr); return(errno ? ACP_NXDEV : ACP_EXISTS); } ; /* * clear error condition, or driver will report an error first * time you open it after the boot. */ stuff(HTCS2_CLR, (&(addr->htcs2))); return(ACP_IFINTR); } robe, /* dh -- DH11 */ "dm", dmprobe, /* dm -- DM11 */ "drsys/autoconfig/tsauto.c 640 0 12 2065 5320452113 10461 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)tsauto.c 2.1 (2.11BSD) 12/30/92 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" #include "tsreg.h" tsprobe(addr,vector) register struct tsdevice *addr; int vector; { extern int errno; /* * Unfortunately the TS and TM CSRs overlap. So simply testing for * presence of a TS register isn't good enough. We borrow from * the "universal" tape boot block by poking the controller and * looking for the "need buffer address" bit from a TS. If that * bit fails to come on the device is not a TS. */ errno = 0; stuff(0, &addr->tssr); /* poke the controller */ if (errno) /* paranoia */ return(ACP_NXDEV); DELAY(100L); /* give TS time for diagnostics */ if (grab(&addr->tssr) & TS_NBA) /* need buffer address bit on? */ return(ACP_EXISTS); /* yes = return existence */ return(ACP_NXDEV); /* not a TS */ } -- DHU11 */ "dhv", dhvprobe, /* dhv -- DHV11 */ "dz", dzprobe, /* dz -- dz11 */ "cn", cnprobe, /* cn -- kl11, dl11 */ "lp", lpprobe, /* lp -- line printer */ "rx", rxprobe, /* rx -- RX01/02 */ "br", brprobe, /* br -- EATON 1538 BR1537/BR1711 */ "dn", dnprobe, /* dn -- dn11 autodialer */ "tms", tmsprobe, /* tms -- TMSCP tape controller */ 0, 0, }; = nl = (NLIST *)calloc(guess_ndev + 10,sizeof(NLIST)); for (dp = devs; dp != NULL; dp = dp->dt_nextsys/autoconfig/xpauto.c 640 0 12 1251 5320452136 10463 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)xpauto.c 1.2 (2.11BSD GTE) 12/30/92 */ /* * Several drives use this probe routine. * * hp -- rjp04/06, rwp04/06 * rm -- rjm02/rwm03, rm02/03/05 * xp -- rm02/03/05, rp04/05/06, Diva, Ampex, SI Eagle, Fuji 160 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" #include "hpreg.h" xpprobe(addr,vector) struct hpdevice *addr; { stuff(HP_IE | HP_RDY, &(addr->hpcs1.w)); DELAY(10L); stuff(0, &(addr->hpcs1.w)); return(ACP_IFINTR); } t from a TS. If that * bit fails to come on the device is not a TS. */ errno = 0; stuff(0, &addr->tssr); /* poke the controller */ if (errno) /* paranoia */ return(ACP_NXDEV); DELAY(100L); /* give TS time for diagnostics */ if (grab(&addr->tssr) & TS_NBA) /* need buffer address bit on? */ return(ACP_EXISTS); /* yes = retursys/autoconfig/cnauto.c 640 0 12 1110 5320450626 10430 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)cauto.c 1.2 (2.11BSD GTE) 12/30/92 */ #include "param.h" #include "../machine/autoconfig.h" #include "cons.h" cnprobe(addr, vector) struct dldevice *addr; int vector; { stuff(grab(&(addr->dlxcsr)) | DLXCSR_TIE, &(addr->dlxcsr)); DELAY(35000L); DELAY(35000L); /* * Leave TIE enabled; cons.c never turns it off * (and this could be the console). */ return(ACP_IFINTR); } IE | HP_Y, &(addr->hpcs1.w)); DELAY(10L); stuff(0, &(addr->hpcs1.w)); return(ACP_IFINTR); } t from a TS. If that * bit fails to come on the device is not a TS. */ errno = 0; stuff(0, &addr->tssr); /* poke the controller */ if (errno) /* paranoia */ return(ACP_NXDEV); DELAY(100L); /* give TS time for diagnostics */ if (grab(&addr->tssr) & TS_NBA) /* need buffer address bit on? */ return(ACP_EXISTS); /* yes = retursys/autoconfig/dhvauto.c 640 3 12 1275 5320450754 10632 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dhuauto.c 1.2 (2.11BSD GTE) 12/30/92 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" #include "../pdpuba/dhvreg.h" dhvprobe(addr,vector) struct dhvdevice *addr; int vector; { if ( grab ( &(addr->dhvcsr) ) & DHV_CS_MCLR ) DELAY(35000L); if ( grab ( &(addr->dhvcsr) ) & (DHV_CS_MCLR|DHV_CS_DFAIL) ) return ( 0 ); stuff ( DHV_CS_RI | DHV_CS_RIE, &(addr->dhvcsr) ); DELAY(3500L); stuff ( 0, &(addr->dhvcsr) ); return(ACP_IFINTR); } * * @(#)dhuauto.c 1.2 (2.11BSD GTE) 12/30/92 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" #include "../pdpuba/dhvreg.h" dhvprobe(addr,vector) struct dhvdevice *addr; int vector; { if ( grab ( &(addr->dhvcsr) ) & DHV_CS_MCLR ) DELAY(35000L); if ( grab ( &(addr->sys/netns/ 755 0 12 0 5526060267 5720 sys/netns/tags 751 0 12 0 6045325027 10520 2../sys/tagssys/netns/ns_error.c 444 12 0 14367 4235740460 10027 /* * Copyright (c) 1984, 1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)ns_error.c 7.5 (Berkeley) 2/4/88 */ #include "param.h" #ifdef NS #include "systm.h" #include "mbuf.h" #include "protosw.h" #include "socket.h" #include "time.h" #include "kernel.h" #include "../net/route.h" #include "ns.h" #include "ns_pcb.h" #include "idp.h" #include "ns_error.h" #ifdef lint #define NS_ERRPRINTFS 1 #endif #ifdef NS_ERRPRINTFS /* * NS_ERR routines: error generation, receive packet processing, and * routines to turnaround packets back to the originator. */ int ns_errprintfs = 0; #endif ns_err_x(c) { register u_short *w, *lim, *base = ns_errstat.ns_es_codes; u_short x = c; /* * zero is a legit error code, handle specially */ if (x == 0) return (0); lim = base + NS_ERR_MAX - 1; for (w = base + 1; w < lim; w++) { if (*w == 0) *w = x; if (*w == x) break; } return (w - base); } /* * Generate an error packet of type error * in response to bad packet. */ ns_error(om, type, param) struct mbuf *om; int type; { register struct ns_epidp *ep; struct mbuf *m; struct idp *nip; register struct idp *oip = mtod(om, struct idp *); extern int idpcksum; /* * If this packet was sent to the echo port, * and nobody was there, just echo it. * (Yes, this is a wart!) */ if (type==NS_ERR_NOSOCK && oip->idp_dna.x_port==htons(2) && (type = ns_echo(oip)==0)) return; #ifdef NS_ERRPRINTFS if (ns_errprintfs) printf("ns_err_error(%x, %d, %d)\n", oip, type, param); #endif /* * Don't Generate error packets in response to multicasts. */ if (oip->idp_dna.x_host.c_host[0] & 1) goto free; ns_errstat.ns_es_error++; /* * Make sure that the old IDP packet had 30 bytes of data to return; * if not, don't bother. Also don't EVER error if the old * packet protocol was NS_ERR. */ if (oip->idp_len < sizeof(struct idp)) { ns_errstat.ns_es_oldshort++; goto free; } if (oip->idp_pt == NSPROTO_ERROR) { ns_errstat.ns_es_oldns_err++; goto free; } /* * First, formulate ns_err message */ m = m_get(M_DONTWAIT, MT_HEADER); if (m == NULL) goto free; m->m_len = sizeof(*ep); m->m_off = MMAXOFF - m->m_len; ep = mtod(m, struct ns_epidp *); if ((u_int)type > NS_ERR_TOO_BIG) panic("ns_err_error"); ns_errstat.ns_es_outhist[ns_err_x(type)]++; ep->ns_ep_errp.ns_err_num = htons((u_short)type); ep->ns_ep_errp.ns_err_param = htons((u_short)param); bcopy((caddr_t)oip, (caddr_t)&ep->ns_ep_errp.ns_err_idp, 42); nip = &ep->ns_ep_idp; nip->idp_len = sizeof(*ep); nip->idp_len = htons((u_short)nip->idp_len); nip->idp_pt = NSPROTO_ERROR; nip->idp_tc = 0; nip->idp_dna = oip->idp_sna; nip->idp_sna = oip->idp_dna; if (idpcksum) { nip->idp_sum = 0; nip->idp_sum = ns_cksum(dtom(nip), sizeof(*ep)); } else nip->idp_sum = 0xffff; (void) ns_output(dtom(nip), (struct route *)0, 0); free: m_freem(dtom(oip)); } ns_printhost(p) register struct ns_addr *p; { printf("", p->x_net.s_net[0], p->x_net.s_net[1], p->x_host.s_host[0], p->x_host.s_host[1], p->x_host.s_host[2], p->x_port); } /* * Process a received NS_ERR message. */ ns_err_input(m) struct mbuf *m; { register struct ns_errp *ep; register struct ns_epidp *epidp = mtod(m, struct ns_epidp *); register int i; int type, code, param; /* * Locate ns_err structure in mbuf, and check * that not corrupted and of at least minimum length. */ #ifdef NS_ERRPRINTFS if (ns_errprintfs) { printf("ns_err_input from "); ns_printhost(&epidp->ns_ep_idp.idp_sna); printf("len %d\n", ntohs(epidp->ns_ep_idp.idp_len)); } #endif i = sizeof (struct ns_epidp); if ((m->m_off > MMAXOFF || m->m_len < i) && (m = m_pullup(m, i)) == 0) { ns_errstat.ns_es_tooshort++; return; } ep = &(mtod(m, struct ns_epidp *)->ns_ep_errp); type = ntohs(ep->ns_err_num); param = ntohs(ep->ns_err_param); ns_errstat.ns_es_inhist[ns_err_x(type)]++; #ifdef NS_ERRPRINTFS /* * Message type specific processing. */ if (ns_errprintfs) printf("ns_err_input, type %d param %d\n", type, param); #endif if (type >= NS_ERR_TOO_BIG) { goto badcode; } ns_errstat.ns_es_outhist[ns_err_x(type)]++; switch (type) { case NS_ERR_UNREACH_HOST: code = PRC_UNREACH_NET; goto deliver; case NS_ERR_TOO_OLD: code = PRC_TIMXCEED_INTRANS; goto deliver; case NS_ERR_TOO_BIG: code = PRC_MSGSIZE; goto deliver; case NS_ERR_FULLUP: code = PRC_QUENCH; goto deliver; case NS_ERR_NOSOCK: code = PRC_UNREACH_PORT; goto deliver; case NS_ERR_UNSPEC_T: case NS_ERR_BADSUM_T: case NS_ERR_BADSUM: case NS_ERR_UNSPEC: code = PRC_PARAMPROB; goto deliver; deliver: /* * Problem with datagram; advise higher level routines. */ #ifdef NS_ERRPRINTFS if (ns_errprintfs) printf("deliver to protocol %d\n", ep->ns_err_idp.idp_pt); #endif switch(ep->ns_err_idp.idp_pt) { case NSPROTO_SPP: spp_ctlinput(code, (caddr_t)ep); break; default: idp_ctlinput(code, (caddr_t)ep); } goto free; default: badcode: ns_errstat.ns_es_badcode++; goto free; } free: m_freem(m); } #ifdef notdef u_long nstime() { int s = splclock(); u_long t; t = (time.tv_sec % (24*60*60)) * 1000 + time.tv_usec / 1000; splx(s); return (htonl(t)); } #endif ns_echo(idp) register struct idp *idp; { struct mbuf *m = dtom(idp); register struct echo { struct idp ec_idp; u_short ec_op; /* Operation, 1 = request, 2 = reply */ } *ec = (struct echo *)idp; struct ns_addr temp; if (idp->idp_pt!=NSPROTO_ECHO) return(NS_ERR_NOSOCK); if (ec->ec_op!=htons(1)) return(NS_ERR_UNSPEC); ec->ec_op = htons(2); temp = idp->idp_dna; idp->idp_dna = idp->idp_sna; idp->idp_sna = temp; if (idp->idp_sum != 0xffff) { idp->idp_sum = 0; idp->idp_sum = ns_cksum(m, (int)(((ntohs(idp->idp_len) - 1)|1)+1)); } (void) ns_output(m, (struct route *)0, NS_FORWARDING); return(0); } #endif imp->il_network = 0; /* !! */ if (IN_CLASSA(addr)) { imp->il_host = ((addr>>16) & 0xFF); imp->il_imp = addr & 0xFF; } else if (IN_CLASSB(addr)) { imp->il_host = ((addr>>8) & 0xFF); imp->il_imp = addr & 0xFF; } else { imp->il_host = ((addr>>4) & 0xFsys/netns/ns.c 444 12 0 15373 4235740422 6612 /* * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)ns.c 7.2 (Berkeley) 1/20/88 */ #include "param.h" #ifdef NS #include "mbuf.h" #include "ioctl.h" #include "protosw.h" #include "socket.h" #include "socketvar.h" #include "uio.h" #include "user.h" #include "../net/if.h" #include "../net/route.h" #include "../net/af.h" #include "ns.h" #include "ns_if.h" struct ns_ifaddr *ns_ifaddr; ns_hash(sns, hp) register struct sockaddr_ns *sns; struct afhash *hp; { register long hash = 0; register u_short *s = sns->sns_addr.x_host.s_host; union { union ns_net net_e; long long_e; } net; net.net_e = sns->sns_addr.x_net; hp->afh_nethash = net.long_e; hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s; hp->afh_hosthash = hash; } ns_netmatch(sns1, sns2) struct sockaddr_ns *sns1, *sns2; { return (ns_neteq(sns1->sns_addr, sns2->sns_addr)); } /* * Generic internet control operations (ioctl's). */ /* ARGSUSED */ ns_control(so, cmd, data, ifp) struct socket *so; int cmd; caddr_t data; register struct ifnet *ifp; { register struct ifreq *ifr = (struct ifreq *)data; register struct ns_ifaddr *ia; struct ifaddr *ifa; struct mbuf *m; /* * Find address for this interface, if it exists. */ if (ifp == 0) return (EADDRNOTAVAIL); for (ia = ns_ifaddr; ia; ia = ia->ia_next) if (ia->ia_ifp == ifp) break; switch (cmd) { case SIOCGIFADDR: if (ia == (struct ns_ifaddr *)0) return (EADDRNOTAVAIL); ifr->ifr_addr = ia->ia_addr; return (0); case SIOCGIFBRDADDR: if (ia == (struct ns_ifaddr *)0) return (EADDRNOTAVAIL); if ((ifp->if_flags & IFF_BROADCAST) == 0) return (EINVAL); ifr->ifr_dstaddr = ia->ia_broadaddr; return (0); case SIOCGIFDSTADDR: if (ia == (struct ns_ifaddr *)0) return (EADDRNOTAVAIL); if ((ifp->if_flags & IFF_POINTOPOINT) == 0) return (EINVAL); ifr->ifr_dstaddr = ia->ia_dstaddr; return (0); } if (!suser()) return (u.u_error); switch (cmd) { case SIOCSIFADDR: case SIOCSIFDSTADDR: if (ia == (struct ns_ifaddr *)0) { m = m_getclr(M_WAIT, MT_IFADDR); if (m == (struct mbuf *)NULL) return (ENOBUFS); if (ia = ns_ifaddr) { for ( ; ia->ia_next; ia = ia->ia_next) ; ia->ia_next = mtod(m, struct ns_ifaddr *); } else ns_ifaddr = mtod(m, struct ns_ifaddr *); ia = mtod(m, struct ns_ifaddr *); if (ifa = ifp->if_addrlist) { for ( ; ifa->ifa_next; ifa = ifa->ifa_next) ; ifa->ifa_next = (struct ifaddr *) ia; } else ifp->if_addrlist = (struct ifaddr *) ia; ia->ia_ifp = ifp; IA_SNS(ia)->sns_family = AF_NS; } } switch (cmd) { case SIOCSIFDSTADDR: if ((ifp->if_flags & IFF_POINTOPOINT) == 0) return (EINVAL); if (ia->ia_flags & IFA_ROUTE) { rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCDELRT, RTF_HOST); ia->ia_flags &= ~IFA_ROUTE; } if (ifp->if_ioctl) { int error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia); if (error) return (error); } ia->ia_dstaddr = ifr->ifr_dstaddr; return (0); case SIOCSIFADDR: return (ns_ifinit(ifp, ia, (struct sockaddr_ns *)&ifr->ifr_addr)); default: if (ifp->if_ioctl == 0) return (EOPNOTSUPP); return ((*ifp->if_ioctl)(ifp, cmd, data)); } } /* * Initialize an interface's internet address * and routing table entry. */ ns_ifinit(ifp, ia, sns) register struct ifnet *ifp; register struct ns_ifaddr *ia; struct sockaddr_ns *sns; { struct sockaddr_ns netaddr; register union ns_host *h = &(IA_SNS(ia)->sns_addr.x_host); int s = splimp(), error; /* * The convention we shall adopt for naming is that * a supplied address of zero means that "we don't care". * if there is a single interface, use the address of that * interface as our 6 byte host address. * if there are multiple interfaces, use any address already * used. * * If we have gotten into trouble and want to reset back to * virginity, we recognize a request of the broadcast address. */ if (ns_hosteqnh(sns->sns_addr.x_host, ns_broadhost)) { ns_thishost = ns_zerohost; splx(s); return (0); } /* * Delete any previous route for an old address. */ bzero((caddr_t)&netaddr, sizeof (netaddr)); netaddr.sns_family = AF_NS; netaddr.sns_addr.x_host = ns_broadhost; netaddr.sns_addr.x_net = ia->ia_net; if (ia->ia_flags & IFA_ROUTE) { if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, (int)SIOCDELRT, 0); } else rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCDELRT, RTF_HOST); } /* * Set up new addresses. */ ia->ia_addr = *(struct sockaddr *)sns; ia->ia_net = sns->sns_addr.x_net; netaddr.sns_addr.x_net = ia->ia_net; if (ifp->if_flags & IFF_BROADCAST) { ia->ia_broadaddr = * (struct sockaddr *) &netaddr; } /* * Give the interface a chance to initialize * if this is its first address, * and to validate the address if necessary. */ if (ns_hosteqnh(ns_thishost, ns_zerohost)) { if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { splx(s); return (error); } ns_thishost = *h; } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost) || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) { *h = ns_thishost; if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { splx(s); return (error); } if (!ns_hosteqnh(ns_thishost,*h)) { splx(s); return (EINVAL); } } else { splx(s); return (EINVAL); } /* * Add route for the network. */ if (ifp->if_flags & IFF_POINTOPOINT) rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT, RTF_HOST|RTF_UP); else rtinit(&ia->ia_broadaddr, &ia->ia_addr, (int)SIOCADDRT, RTF_UP); ia->ia_flags |= IFA_ROUTE; return (0); } /* * Return address info for specified internet network. */ struct ns_ifaddr * ns_iaonnetof(dst) register struct ns_addr *dst; { register struct ns_ifaddr *ia; register struct ns_addr *compare; register struct ifnet *ifp; struct ns_ifaddr *ia_maybe = 0; union ns_net net; net = dst->x_net; for (ia = ns_ifaddr; ia; ia = ia->ia_next) { if (ifp = ia->ia_ifp) { if (ifp->if_flags & IFF_POINTOPOINT) { compare = &satons_addr(ia->ia_dstaddr); if (ns_hosteq(*dst, *compare)) return (ia); if (ns_neteqnn(net, ia->ia_net)) ia_maybe = ia; } else { if (ns_neteqnn(net, ia->ia_net)) return (ia); } } } return (ia_maybe); } #endif _op; /* Operation, 1 = request, 2 = reply */ } *ec = (struct echo *)idp; struct ns_addr temp; if (idp->idp_pt!=NSPROTO_ECHO) return(NS_ERR_NOSOCK); if (ec->ec_op!=htons(1)) return(NS_ERR_UNSPEC); ec->ec_op = htons(2); temp = idp->idp_dna; idp->idp_dnasys/netns/ns.h 444 12 0 6236 5511210237 6567 /* * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)ns.h 7.3.1 (2.11BSD GTE) 12/31/93 */ /* * Constants and Structures defined by the Xerox Network Software * per "Internet Transport Protocols", XSIS 028112, December 1981 */ /* * Protocols */ #define NSPROTO_RI 1 /* Routing Information */ #define NSPROTO_ECHO 2 /* Echo Protocol */ #define NSPROTO_ERROR 3 /* Error Protocol */ #define NSPROTO_PE 4 /* Packet Exchange */ #define NSPROTO_SPP 5 /* Sequenced Packet */ #define NSPROTO_RAW 255 /* Placemarker*/ #define NSPROTO_MAX 256 /* Placemarker*/ /* * Port/Socket numbers: network standard functions */ #define NSPORT_RI 1 /* Routing Information */ #define NSPORT_ECHO 2 /* Echo */ #define NSPORT_RE 3 /* Router Error */ /* * Ports < NSPORT_RESERVED are reserved for priveleged * processes (e.g. root). */ #define NSPORT_RESERVED 3000 /* flags passed to ns_output as last parameter */ #define NS_FORWARDING 0x1 /* most of idp header exists */ #define NS_ROUTETOIF 0x10 /* same as SO_DONTROUTE */ #define NS_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */ #define NS_MAXHOPS 15 /* flags passed to get/set socket option */ #define SO_HEADERS_ON_INPUT 1 #define SO_HEADERS_ON_OUTPUT 2 #define SO_DEFAULT_HEADERS 3 #define SO_LAST_HEADER 4 #define SO_NSIP_ROUTE 5 #define SO_SEQNO 6 #define SO_ALL_PACKETS 7 #define SO_MTU 8 /* * NS addressing */ union ns_host { u_char c_host[6]; u_short s_host[3]; }; union ns_net { u_char c_net[4]; u_short s_net[2]; }; union ns_net_u { union ns_net net_e; u_long long_e; }; struct ns_addr { union ns_net x_net; union ns_host x_host; u_short x_port; }; /* * Socket address, Xerox style */ struct sockaddr_ns { u_short sns_family; struct ns_addr sns_addr; char sns_zero[2]; }; #define sns_port sns_addr.x_port #ifdef vax #define ns_netof(a) (*(long *) & ((a).x_net)) /* XXX - not needed */ #endif #define ns_neteqnn(a,b) (((a).s_net[0]==(b).s_net[0]) && \ ((a).s_net[1]==(b).s_net[1])) #define ns_neteq(a,b) ns_neteqnn((a).x_net, (b).x_net) #define satons_addr(sa) (((struct sockaddr_ns *)&(sa))->sns_addr) #define ns_hosteqnh(s,t) ((s).s_host[0] == (t).s_host[0] && \ (s).s_host[1] == (t).s_host[1] && (s).s_host[2] == (t).s_host[2]) #define ns_hosteq(s,t) (ns_hosteqnh((s).x_host,(t).x_host)) #define ns_nullhost(x) (((x).x_host.s_host[0]==0) && \ ((x).x_host.s_host[1]==0) && ((x).x_host.s_host[2]==0)) /* * Routines for number representation conversion. */ u_short ntohs(), htons(); u_long ntohl(), htonl(); #ifdef SUPERVISOR extern struct domain nsdomain; union ns_host ns_thishost; union ns_host ns_zerohost; union ns_host ns_broadhost; union ns_net ns_zeronet; union ns_net ns_broadnet; u_short ns_cksum(); #endif tiple interfaces, use any address already * used. * * If we have gotten into trouble and want to reset back to * virginity, we recognize a request of the broadcast address. */ if (ns_hosteqnh(sns->sns_addr.x_host, ns_broadhost)) { ns_thishost = ns_zerohost; splx(s); return (0); } /* * Delete any previous route for an old address. sys/netns/idp.h 444 12 0 1713 4235470127 6726 /* * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)idp.h 7.2 (Berkeley) 1/20/88 */ /* * Definitions for NS(tm) Internet Datagram Protocol */ struct idp { u_short idp_sum; /* Checksum */ u_short idp_len; /* Length, in bytes, including header */ u_char idp_tc; /* Transport Crontrol (i.e. hop count) */ u_char idp_pt; /* Packet Type (i.e. level 2 protocol) */ struct ns_addr idp_dna; /* Destination Network Address */ struct ns_addr idp_sna; /* Source Network Address */ }; e NSPROTO_RAW 255 /* Placemarker*/ #define NSPROTO_Msys/netns/idp_var.h 444 12 0 1643 4320005361 7565 /* * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)idp_var.h 7.2 (Berkeley) 1/20/88 */ /* * IDP Kernel Structures and Variables */ struct idpstat { long idps_badsum; /* checksum bad */ long idps_tooshort; /* packet too short */ long idps_toosmall; /* not enough data */ long idps_badhlen; /* ip header length < data size */ long idps_badlen; /* ip length < ip header length */ }; #ifdef SUPERVISOR struct idpstat idpstat; #endif dp_sna; /* Source Network Address */ }; e NSPROTO_RAW 255 /* Placemarker*/ #define NSPROTO_Msys/netns/ns_error.h 444 12 0 5043 4235472331 10002 /* * Copyright (c) 1984, 1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)ns_error.h 7.3 (Berkeley) 1/28/88 */ /* * Xerox NS error messages */ struct ns_errp { u_short ns_err_num; /* Error Number */ u_short ns_err_param; /* Error Parameter */ struct idp ns_err_idp; /* Initial segment of offending packet */ u_char ns_err_lev2[12]; /* at least this much higher level protocol */ }; struct ns_epidp { struct idp ns_ep_idp; struct ns_errp ns_ep_errp; }; #define NS_ERR_UNSPEC 0 /* Unspecified Error detected at dest. */ #define NS_ERR_BADSUM 1 /* Bad Checksum detected at dest */ #define NS_ERR_NOSOCK 2 /* Specified socket does not exist at dest*/ #define NS_ERR_FULLUP 3 /* Dest. refuses packet due to resource lim.*/ #define NS_ERR_UNSPEC_T 0x200 /* Unspec. Error occured before reaching dest*/ #define NS_ERR_BADSUM_T 0x201 /* Bad Checksum detected in transit */ #define NS_ERR_UNREACH_HOST 0x202 /* Dest cannot be reached from here*/ #define NS_ERR_TOO_OLD 0x203 /* Packet x'd 15 routers without delivery*/ #define NS_ERR_TOO_BIG 0x204 /* Packet too large to be forwarded through some intermediate gateway. The error parameter field contains the max packet size that can be accommodated */ #define NS_ERR_MAX 20 /* * Variables related to this implementation * of the network systems error message protocol. */ struct ns_errstat { /* statistics related to ns_err packets generated */ long ns_es_error; /* # of calls to ns_error */ long ns_es_oldshort; /* no error 'cuz old ip too short */ long ns_es_oldns_err; /* no error 'cuz old was ns_err */ long ns_es_outhist[NS_ERR_MAX]; /* statistics related to input messages processed */ long ns_es_badcode; /* ns_err_code out of range */ long ns_es_tooshort; /* packet < IDP_MINLEN */ long ns_es_checksum; /* bad checksum */ long ns_es_badlen; /* calculated bound mismatch */ long ns_es_reflect; /* number of responses */ long ns_es_inhist[NS_ERR_MAX]; u_short ns_es_codes[NS_ERR_MAX];/* which error code for outhist since we might not know all */ }; #ifdef SUPERVISOR struct ns_errstat ns_errstat; #endif a))->sns_addr) #define ns_hosteqnh(s,t) ((s).s_host[0] == (t).s_host[0] && \ (s).s_host[1] == (t).s_host[1] && (s).s_host[2] == (t).s_host[2]) #define ns_hosteq(s,t) (ns_hosteqnh((s).x_host,(t).x_host)) #define ns_nullhost(x) (((x).x_host.s_host[0]==0) && \ ((x).x_host.s_host[1]==0) && ((x).x_host.s_host[2]==0)) /* * Routines for number representation conversion. */ u_short ntohs(), htons(); u_long ntohl(), htonl(); #ifdef SUPERVISOR extern struct domain nsdomain; unsys/netns/ns_if.h 444 12 0 3454 4235472377 7265 /* * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)ns_if.h 7.2 (Berkeley) 1/20/88 */ /* * Interface address, xerox version. One of these structures * is allocated for each interface with an internet address. * The ifaddr structure contains the protocol-independent part * of the structure and is assumed to be first. */ struct ns_ifaddr { struct ifaddr ia_ifa; /* protocol-independent info */ #define ia_addr ia_ifa.ifa_addr #define ia_broadaddr ia_ifa.ifa_broadaddr #define ia_dstaddr ia_ifa.ifa_dstaddr #define ia_ifp ia_ifa.ifa_ifp union ns_net ia_net; /* network number of interface */ int ia_flags; struct ns_ifaddr *ia_next; /* next in list of internet addresses */ }; /* * Given a pointer to an ns_ifaddr (ifaddr), * return a pointer to the addr as a sockadd_ns. */ #define IA_SNS(ia) ((struct sockaddr_ns *)(&((struct ns_ifaddr *)ia)->ia_addr)) /* * ia_flags */ #define IFA_ROUTE 0x01 /* routing entry installed */ /* This is not the right place for this but where is? */ #define ETHERTYPE_NS 0x0600 #ifdef NSIP struct nsip_req { struct sockaddr rq_ns; /* must be ns format destination */ struct sockaddr rq_ip; /* must be ip format gateway */ short rq_flags; }; #endif #ifdef SUPERVISOR struct ns_ifaddr *ns_ifaddr; struct ns_ifaddr *ns_iaonnetof(); struct ifqueue nsintrq; /* XNS input packet queue */ #endif ns_errstat { /* statistics related to ns_err packets generated */ long ns_es_error; /* # of calls to ns_error */ long ns_es_oldshort; /* no error 'cuz old ip too short */ long ns_es_oldns_err; /* no error 'csys/netns/ns_input.c 444 12 0 24767 4235740471 10044 /* * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)ns_input.c 7.2 (Berkeley) 1/20/88 */ #include "param.h" #ifdef NS #include "systm.h" #include "mbuf.h" #include "domain.h" #include "protosw.h" #include "socket.h" #include "socketvar.h" #include "errno.h" #include "time.h" #include "kernel.h" #include "../net/if.h" #include "../net/route.h" #include "../net/raw_cb.h" #include "ns.h" #include "ns_if.h" #include "ns_pcb.h" #include "idp.h" #include "idp_var.h" #include "ns_error.h" /* * NS initialization. */ union ns_host ns_thishost; union ns_host ns_zerohost; union ns_host ns_broadhost; union ns_net ns_zeronet; union ns_net ns_broadnet; static u_short allones[] = {-1, -1, -1}; struct nspcb nspcb; struct nspcb nsrawpcb; struct ifqueue nsintrq; int nsqmaxlen = IFQ_MAXLEN; int idpcksum = 1; long ns_pexseq; ns_init() { extern struct timeval time; ns_broadhost = * (union ns_host *) allones; ns_broadnet = * (union ns_net *) allones; nspcb.nsp_next = nspcb.nsp_prev = &nspcb; nsrawpcb.nsp_next = nsrawpcb.nsp_prev = &nsrawpcb; nsintrq.ifq_maxlen = nsqmaxlen; ns_pexseq = time.tv_usec; } /* * Idp input routine. Pass to next level. */ int nsintr_getpck = 0; int nsintr_swtch = 0; nsintr() { register struct idp *idp; register struct mbuf *m; register struct nspcb *nsp; struct ifnet *ifp; struct mbuf *m0; register int i; int len, s, error; char oddpacketp; next: /* * Get next datagram off input queue and get IDP header * in first mbuf. */ s = splimp(); IF_DEQUEUEIF(&nsintrq, m, ifp); splx(s); nsintr_getpck++; if (m == 0) return; if ((m->m_off > MMAXOFF || m->m_len < sizeof (struct idp)) && (m = m_pullup(m, sizeof (struct idp))) == 0) { idpstat.idps_toosmall++; goto next; } /* * Give any raw listeners a crack at the packet */ for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) { struct mbuf *m1 = m_copy(m, 0, (int)M_COPYALL); if (m1) idp_input(m1, nsp, ifp); } idp = mtod(m, struct idp *); len = ntohs(idp->idp_len); if (oddpacketp = len & 1) { len++; /* If this packet is of odd length, preserve garbage byte for checksum */ } /* * Check that the amount of data in the buffers * is as at least much as the IDP header would have us expect. * Trim mbufs if longer than we expect. * Drop packet if shorter than we expect. */ i = -len; m0 = m; for (;;) { i += m->m_len; if (m->m_next == 0) break; m = m->m_next; } if (i != 0) { if (i < 0) { idpstat.idps_tooshort++; m = m0; goto bad; } if (i <= m->m_len) m->m_len -= i; else m_adj(m0, -i); } m = m0; if (idpcksum && ((i = idp->idp_sum)!=0xffff)) { idp->idp_sum = 0; if (i != (idp->idp_sum = ns_cksum(m,len))) { idpstat.idps_badsum++; idp->idp_sum = i; if (ns_hosteqnh(ns_thishost, idp->idp_dna.x_host)) error = NS_ERR_BADSUM; else error = NS_ERR_BADSUM_T; ns_error(m, error, 0); goto next; } } /* * Is this a directed broadcast? */ if (ns_hosteqnh(ns_broadhost,idp->idp_dna.x_host)) { if ((!ns_neteq(idp->idp_dna, idp->idp_sna)) && (!ns_neteqnn(idp->idp_dna.x_net, ns_broadnet)) && (!ns_neteqnn(idp->idp_sna.x_net, ns_zeronet)) && (!ns_neteqnn(idp->idp_dna.x_net, ns_zeronet)) ) { /* * Look to see if I need to eat this packet. * Algorithm is to forward all young packets * and prematurely age any packets which will * by physically broadcasted. * Any very old packets eaten without forwarding * would die anyway. * * Suggestion of Bill Nesheim, Cornell U. */ if (idp->idp_tc < NS_MAXHOPS) { idp_forward(idp); goto next; } } /* * Is this our packet? If not, forward. */ } else if (!ns_hosteqnh(ns_thishost,idp->idp_dna.x_host)) { idp_forward(idp); goto next; } /* * Locate pcb for datagram. */ nsp = ns_pcblookup(&idp->idp_sna, idp->idp_dna.x_port, NS_WILDCARD); /* * Switch out to protocol's input routine. */ nsintr_swtch++; if (nsp) { if (oddpacketp) { m_adj(m0, -1); } if ((nsp->nsp_flags & NSP_ALL_PACKETS)==0) switch (idp->idp_pt) { case NSPROTO_SPP: spp_input(m, nsp, ifp); goto next; case NSPROTO_ERROR: ns_err_input(m); goto next; } idp_input(m, nsp, ifp); } else { ns_error(m, NS_ERR_NOSOCK, 0); } goto next; bad: m_freem(m); goto next; } u_char nsctlerrmap[PRC_NCMDS] = { ECONNABORTED, ECONNABORTED, 0, 0, 0, 0, EHOSTDOWN, EHOSTUNREACH, ENETUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, EMSGSIZE, 0, 0, 0, 0, 0, 0, 0 }; idp_donosocks = 1; idp_ctlinput(cmd, arg) int cmd; caddr_t arg; { struct ns_addr *ns; struct nspcb *nsp; struct ns_errp *errp; int idp_abort(); extern struct nspcb *idp_drop(); int type; if (cmd < 0 || cmd > PRC_NCMDS) return; if (nsctlerrmap[cmd] == 0) return; /* XXX */ type = NS_ERR_UNREACH_HOST; switch (cmd) { struct sockaddr_ns *sns; case PRC_IFDOWN: case PRC_HOSTDEAD: case PRC_HOSTUNREACH: sns = (struct sockaddr_ns *)arg; if (sns->sns_family != AF_INET) return; ns = &sns->sns_addr; break; default: errp = (struct ns_errp *)arg; ns = &errp->ns_err_idp.idp_dna; type = errp->ns_err_num; type = ntohs((u_short)type); } switch (type) { case NS_ERR_UNREACH_HOST: ns_pcbnotify(ns, (int)nsctlerrmap[cmd], idp_abort, (long)0); break; case NS_ERR_NOSOCK: nsp = ns_pcblookup(ns, errp->ns_err_idp.idp_sna.x_port, NS_WILDCARD); if(nsp && idp_donosocks && ! ns_nullhost(nsp->nsp_faddr)) (void) idp_drop(nsp, (int)nsctlerrmap[cmd]); } } int idpprintfs = 0; int idpforwarding = 1; /* * Forward a packet. If some error occurs return the sender * an error packet. Note we can't always generate a meaningful * error message because the NS errors don't have a large enough repetoire * of codes and types. */ struct route idp_droute; struct route idp_sroute; idp_forward(idp) register struct idp *idp; { register int error, type, code; struct mbuf *mcopy = NULL; int agedelta = 1; int flags = NS_FORWARDING; int ok_there = 0; int ok_back = 0; if (idpprintfs) { printf("forward: src "); ns_printhost(&idp->idp_sna); printf(", dst "); ns_printhost(&idp->idp_dna); printf("hop count %d\n", idp->idp_tc); } if (idpforwarding == 0) { /* can't tell difference between net and host */ type = NS_ERR_UNREACH_HOST, code = 0; goto senderror; } idp->idp_tc++; if (idp->idp_tc > NS_MAXHOPS) { type = NS_ERR_TOO_OLD, code = 0; goto senderror; } /* * Save at most 42 bytes of the packet in case * we need to generate an NS error message to the src. */ mcopy = m_copy(dtom(idp), 0, imin((int)ntohs(idp->idp_len), 42)); if ((ok_there = idp_do_route(&idp->idp_dna,&idp_droute))==0) { type = NS_ERR_UNREACH_HOST, code = 0; goto senderror; } /* * Here we think about forwarding broadcast packets, * so we try to insure that it doesn't go back out * on the interface it came in on. Also, if we * are going to physically broadcast this, let us * age the packet so we can eat it safely the second time around. */ if (idp->idp_dna.x_host.c_host[0] & 0x1) { struct ns_ifaddr *ia = ns_iaonnetof(&idp->idp_dna); struct ifnet *ifp; if (ia) { /* I'm gonna hafta eat this packet */ agedelta += NS_MAXHOPS - idp->idp_tc; idp->idp_tc = NS_MAXHOPS; } if ((ok_back = idp_do_route(&idp->idp_sna,&idp_sroute))==0) { /* error = ENETUNREACH; He'll never get it! */ m_freem(dtom(idp)); goto cleanup; } if (idp_droute.ro_rt && (ifp=idp_droute.ro_rt->rt_ifp) && idp_sroute.ro_rt && (ifp!=idp_sroute.ro_rt->rt_ifp)) { flags |= NS_ALLOWBROADCAST; } else { type = NS_ERR_UNREACH_HOST, code = 0; goto senderror; } } /* need to adjust checksum */ if (idp->idp_sum!=0xffff) { union bytes { u_char c[4]; u_short s[2]; long l; } x; register int shift; x.l = 0; x.c[0] = agedelta; shift = (((((int)ntohs(idp->idp_len))+1)>>1)-2) & 0xf; x.l = idp->idp_sum + (x.l << shift); x.l = x.s[0] + x.s[1]; x.l = x.s[0] + x.s[1]; if (x.l==0xffff) idp->idp_sum = 0; else idp->idp_sum = x.l; } if ((error = ns_output(dtom(idp), &idp_droute, flags)) && (mcopy!=NULL)) { idp = mtod(mcopy, struct idp *); type = NS_ERR_UNSPEC_T, code = 0; switch (error) { case ENETUNREACH: case EHOSTDOWN: case EHOSTUNREACH: case ENETDOWN: case EPERM: type = NS_ERR_UNREACH_HOST; break; case EMSGSIZE: type = NS_ERR_TOO_BIG; code = 576; /* too hard to figure out mtu here */ break; case ENOBUFS: type = NS_ERR_UNSPEC_T; break; } mcopy = NULL; senderror: ns_error(dtom(idp), type, code); } cleanup: if (ok_there) idp_undo_route(&idp_droute); if (ok_back) idp_undo_route(&idp_sroute); if (mcopy != NULL) m_freem(mcopy); } idp_do_route(src, ro) struct ns_addr *src; struct route *ro; { struct sockaddr_ns *dst; bzero((caddr_t)ro, sizeof (*ro)); dst = (struct sockaddr_ns *)&ro->ro_dst; dst->sns_family = AF_NS; dst->sns_addr = *src; dst->sns_addr.x_port = 0; rtalloc(ro); if (ro->ro_rt == 0 || ro->ro_rt->rt_ifp == 0) { return (0); } ro->ro_rt->rt_use++; return (1); } idp_undo_route(ro) register struct route *ro; { if (ro->ro_rt) {RTFREE(ro->ro_rt);} } static union ns_net ns_zeronet; ns_watch_output(m, ifp) struct mbuf *m; struct ifnet *ifp; { register struct nspcb *nsp; register struct ifaddr *ia; /* * Give any raw listeners a crack at the packet */ for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) { struct mbuf *m0 = m_copy(m, 0, (int)M_COPYALL); if (m0) { struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA); if(m1 == NULL) m_freem(m0); else { register struct idp *idp; m1->m_off = MMINOFF; m1->m_len = sizeof (*idp); m1->m_next = m0; idp = mtod(m1, struct idp *); idp->idp_sna.x_net = ns_zeronet; idp->idp_sna.x_host = ns_thishost; if (ifp && (ifp->if_flags & IFF_POINTOPOINT)) for(ia = ifp->if_addrlist; ia; ia = ia->ifa_next) { if (ia->ifa_addr.sa_family==AF_NS) { idp->idp_sna = satons_addr(ia->ifa_dstaddr); break; } } idp->idp_len = 0xffff; idp_input(m1, nsp, ifp); } } } } #endif NS truct mbusys/netns/spp_debug.c 444 12 0 6332 4235740542 10120 /* * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)spp_debug.c 7.4 (Berkeley) 3/12/88 */ #include "param.h" #ifdef NS #include "systm.h" #include "mbuf.h" #include "socket.h" #include "socketvar.h" #include "protosw.h" #include "errno.h" #include "../net/route.h" #include "../net/if.h" #include "../netinet/tcp_fsm.h" #include "ns.h" #include "ns_pcb.h" #include "idp.h" #include "idp_var.h" #include "sp.h" #include "spidp.h" #define SPPTIMERS #include "spp_timer.h" #include "spp_var.h" #define SANAMES #include "spp_debug.h" int sppconsdebug = 0; /* * spp debug routines */ spp_trace(act, ostate, sp, si, req) short act; u_char ostate; struct sppcb *sp; struct spidp *si; int req; { #ifdef INET u_short seq, ack, len, alo; u_long iptime(); int flags; struct spp_debug *sd = &spp_debug[spp_debx++]; extern char *prurequests[]; extern char *sanames[]; extern char *tcpstates[]; extern char *spptimers[]; if (spp_debx == SPP_NDEBUG) spp_debx = 0; sd->sd_time = iptime(); sd->sd_act = act; sd->sd_ostate = ostate; sd->sd_cb = (caddr_t)sp; if (sp) sd->sd_sp = *sp; else bzero((caddr_t)&sd->sd_sp, sizeof (*sp)); if (si) sd->sd_si = *si; else bzero((caddr_t)&sd->sd_si, sizeof (*si)); sd->sd_req = req; if (sppconsdebug == 0) return; if (ostate >= TCP_NSTATES) ostate = 0; if (act >= SA_DROP) act = SA_DROP; if (sp) printf("%x %s:", sp, tcpstates[ostate]); else printf("???????? "); printf("%s ", sanames[act]); switch (act) { case SA_RESPOND: case SA_INPUT: case SA_OUTPUT: case SA_DROP: if (si == 0) break; seq = si->si_seq; ack = si->si_ack; alo = si->si_alo; len = si->si_len; if (act == SA_OUTPUT) { seq = ntohs(seq); ack = ntohs(ack); alo = ntohs(alo); len = ntohs(len); } #ifndef lint #define p1(f) { printf("%s = %x, ", "f", f); } p1(seq); p1(ack); p1(alo); p1(len); #endif flags = si->si_cc; if (flags) { char *cp = "<"; #ifndef lint #define pf(f) { if (flags&SP_/**/f) { printf("%s%s", cp, "f"); cp = ","; } } pf(SP); pf(SA); pf(OB); pf(EM); #else cp = cp; #endif printf(">"); } #ifndef lint #define p2(f) { printf("%s = %x, ", "f", si->si_/**/f); } p2(sid);p2(did);p2(dt);p2(pt); #endif ns_printhost(&si->si_sna); ns_printhost(&si->si_dna); if (act==SA_RESPOND) { printf("idp_len = %x, ", ((struct idp *)si)->idp_len); } break; case SA_USER: printf("%s", prurequests[req&0xff]); if ((req & 0xff) == PRU_SLOWTIMO) printf("<%s>", spptimers[req>>8]); break; } if (sp) printf(" -> %s", tcpstates[sp->s_state]); /* print out internal state of sp !?! */ printf("\n"); if (sp == 0) return; #ifndef lint #define p3(f) { printf("%s = %x, ", "f", sp->s_/**/f); } printf("\t"); p3(rack);p3(ralo);p3(smax);p3(flags); printf("\n"); #endif #endif } #endif * Algorithm is to forward all young packets * and prematurely age any packets which will * by physically broadcasted. * Any very old packets eaten without forwarding * would die anyway. * * Suggestion of Bill Nesheim, Cornell U. */ if (idp->idp_tc < NS_MAXHOPS) sys/netns/ns_proto.c 444 12 0 3765 4235740533 10022 /* * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)ns_proto.c 7.2 (Berkeley) 1/20/88 */ #include "param.h" #ifdef NS #include "socket.h" #include "protosw.h" #include "domain.h" #include "mbuf.h" #include "ns.h" /* * NS protocol family: IDP, ERR, PE, SPP, ROUTE. */ int ns_init(); int idp_input(), idp_output(), idp_ctlinput(), idp_usrreq(); int idp_raw_usrreq(), idp_ctloutput(); int spp_input(), spp_ctlinput(); int spp_usrreq(), spp_usrreq_sp(), spp_ctloutput(); int spp_init(), spp_fasttimo(), spp_slowtimo(); extern int raw_usrreq(); extern struct domain nsdomain; struct protosw nssw[] = { { 0, &nsdomain, 0, 0, 0, idp_output, 0, 0, 0, ns_init, 0, 0, 0, }, { SOCK_DGRAM, &nsdomain, 0, PR_ATOMIC|PR_ADDR, 0, 0, idp_ctlinput, idp_ctloutput, idp_usrreq, 0, 0, 0, 0, }, { SOCK_STREAM, &nsdomain, NSPROTO_SPP, PR_CONNREQUIRED|PR_WANTRCVD, spp_input, 0, spp_ctlinput, spp_ctloutput, spp_usrreq, spp_init, spp_fasttimo, spp_slowtimo, 0, }, { SOCK_SEQPACKET,&nsdomain, NSPROTO_SPP, PR_CONNREQUIRED|PR_WANTRCVD|PR_ATOMIC, spp_input, 0, spp_ctlinput, spp_ctloutput, spp_usrreq_sp, 0, 0, 0, 0, }, { SOCK_RAW, &nsdomain, NSPROTO_RAW, PR_ATOMIC|PR_ADDR, idp_input, idp_output, 0, idp_ctloutput, idp_raw_usrreq, 0, 0, 0, 0, }, { SOCK_RAW, &nsdomain, NSPROTO_ERROR, PR_ATOMIC|PR_ADDR, idp_ctlinput, idp_output, 0, idp_ctloutput, idp_raw_usrreq, 0, 0, 0, 0, }, }; struct domain nsdomain = { AF_NS, "network systems", 0, 0, 0, nssw, &nssw[sizeof(nssw)/sizeof(nssw[0])] }; #endif (si == 0) sys/netns/sp.h 444 12 0 2203 4235473427 6575 /* * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)sp.h 7.2 (Berkeley) 1/20/88 */ /* * Definitions for Xerox NS style sequenced packet protocol */ struct sphdr { u_char sp_cc; /* connection control */ u_char sp_dt; /* datastream type */ #define SP_SP 0x80 /* system packet */ #define SP_SA 0x40 /* send acknowledgement */ #define SP_OB 0x20 /* attention (out of band data) */ #define SP_EM 0x10 /* end of message */ u_short sp_sid; /* source connection identifier */ u_short sp_did; /* destination connection identifier */ u_short sp_seq; /* sequence number */ u_short sp_ack; /* acknowledge number */ u_short sp_alo; /* allocation number */ }; 0, 0, 0, }, { SOCK_DGRAM, &nsdomain, 0, PR_ATOMIC|PR_ADDR, 0, 0, idp_ctlinput, idp_ctloutput, idp_usrreq, 0, 0, 0, 0, }, { SOCK_STREAM, &nsdomain, NSPROTO_SPP, PR_CONNREQUIRED|PR_WANTRCVD, spp_input, 0, spp_ctlinput, spp_ctloutput, spp_usrreq, spp_init, spp_fasttimo, spp_slowtimo, 0, }, { SOCK_SEQPACKET,&nsdomain, NSPROTO_SPP, PR_CONNREQUIRED|PR_WANTRCVD|PRsys/netns/spidp.h 444 12 0 2321 4235473447 7275 /* * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)spidp.h 7.2 (Berkeley) 1/20/88 */ /* * Definitions for NS(tm) Internet Datagram Protocol * containing a Sequenced Packet Protocol packet. */ struct spidp { struct idp si_i; struct sphdr si_s; }; struct spidp_q { struct spidp_q *si_next; struct spidp_q *si_prev; }; #define SI(x) ((struct spidp *)x) #define si_sum si_i.idp_sum #define si_len si_i.idp_len #define si_tc si_i.idp_tc #define si_pt si_i.idp_pt #define si_dna si_i.idp_dna #define si_sna si_i.idp_sna #define si_sport si_i.idp_sna.x_port #define si_cc si_s.sp_cc #define si_dt si_s.sp_dt #define si_sid si_s.sp_sid #define si_did si_s.sp_did #define si_seq si_s.sp_seq #define si_ack si_s.sp_ack #define si_alo si_s.sp_alo preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or impliedsys/netns/spp_debug.h 444 12 0 1742 4235473731 10130 /* * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)spp_debug.h 7.2 (Berkeley) 1/20/88 */ struct spp_debug { u_long sd_time; short sd_act; short sd_ostate; caddr_t sd_cb; short sd_req; struct spidp sd_si; struct sppcb sd_sp; }; #define SA_INPUT 0 #define SA_OUTPUT 1 #define SA_USER 2 #define SA_RESPOND 3 #define SA_DROP 4 #ifdef SANAMES char *sanames[] = { "input", "output", "user", "respond", "drop" }; #endif #define SPP_NDEBUG 2 struct spp_debug spp_debug[SPP_NDEBUG]; int spp_debx; sna si_i.idp_sna #define si_spsys/netns/spp_var.h 444 12 0 16556 5514434750 7662 /* * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)spp_var.h 7.4.1 (2.11BSD GTE) 12/31/93 */ /* * Sp control block, one per connection */ struct sppcb { struct spidp_q s_q; /* queue for out-of-order receipt */ struct nspcb *s_nspcb; /* backpointer to internet pcb */ u_char s_state; u_char s_flags; #define SF_ACKNOW 0x01 /* Ack peer immediately */ #define SF_DELACK 0x02 /* Ack, but try to delay it */ #define SF_HI 0x04 /* Show headers on input */ #define SF_HO 0x08 /* Show headers on output */ #define SF_PI 0x10 /* Packet (datagram) interface */ #define SF_WIN 0x20 /* Window info changed */ #define SF_RXT 0x40 /* Rxt info changed */ #define SF_RVD 0x80 /* Calling from read usrreq routine */ u_short s_mtu; /* Max packet size for this stream */ /* use sequence fields in headers to store sequence numbers for this connection */ struct idp *s_idp; struct sphdr s_shdr; /* prototype header to transmit */ #define s_cc s_shdr.sp_cc /* connection control (for EM bit) */ #define s_dt s_shdr.sp_dt /* datastream type */ #define s_sid s_shdr.sp_sid /* source connection identifier */ #define s_did s_shdr.sp_did /* destination connection identifier */ #define s_seq s_shdr.sp_seq /* sequence number */ #define s_ack s_shdr.sp_ack /* acknowledge number */ #define s_alo s_shdr.sp_alo /* allocation number */ #define s_dport s_idp->idp_dna.x_port /* where we are sending */ struct sphdr s_rhdr; /* last received header (in effect!)*/ u_short s_rack; /* their acknowledge number */ u_short s_ralo; /* their allocation number */ u_short s_smax; /* highest packet # we have sent */ u_short s_snxt; /* which packet to send next */ /* congestion control */ #define CUNIT 1024 /* scaling for ... */ int s_cwnd; /* Congestion-controlled window */ /* in packets * CUNIT */ short s_swnd; /* == tcp snd_wnd, in packets */ short s_smxw; /* == tcp max_sndwnd */ /* difference of two spp_seq's can be no bigger than a short */ u_short s_swl1; /* == tcp snd_wl1 */ u_short s_swl2; /* == tcp snd_wl2 */ int s_cwmx; /* max allowable cwnd */ int s_ssthresh; /* s_cwnd size threshhold for * slow start exponential-to- * linear switch */ /* transmit timing stuff * srtt and rttvar are stored as fixed point, for convenience in smoothing. * srtt has 3 bits to the right of the binary point, rttvar has 2. */ short s_idle; /* time idle */ short s_timer[SPPT_NTIMERS]; /* timers */ short s_rxtshift; /* log(2) of rexmt exp. backoff */ short s_rxtcur; /* current retransmit value */ u_short s_rtseq; /* packet being timed */ short s_rtt; /* timer for round trips */ short s_srtt; /* averaged timer */ short s_rttvar; /* variance in round trip time */ char s_force; /* which timer expired */ char s_dupacks; /* counter to intuit xmt loss */ /* out of band data */ char s_oobflags; #define SF_SOOB 0x08 /* sending out of band data */ #define SF_IOOB 0x10 /* receiving out of band data */ char s_iobc; /* input characters */ /* debug stuff */ u_short s_want; /* Last candidate for sending */ char s_outx; /* exit taken from spp_output */ char s_inx; /* exit taken from spp_input */ }; #define nstosppcb(np) ((struct sppcb *)(np)->nsp_pcb) #define sotosppcb(so) (nstosppcb(sotonspcb(so))) struct sppstat { long spps_connattempt; /* connections initiated */ long spps_accepts; /* connections accepted */ long spps_connects; /* connections established */ long spps_drops; /* connections dropped */ long spps_conndrops; /* embryonic connections dropped */ long spps_closed; /* conn. closed (includes drops) */ long spps_segstimed; /* segs where we tried to get rtt */ long spps_rttupdated; /* times we succeeded */ long spps_delack; /* delayed acks sent */ long spps_timeoutdrop; /* conn. dropped in rxmt timeout */ long spps_rexmttimeo; /* retransmit timeouts */ long spps_persisttimeo; /* persist timeouts */ long spps_keeptimeo; /* keepalive timeouts */ long spps_keepprobe; /* keepalive probes sent */ long spps_keepdrops; /* connections dropped in keepalive */ long spps_sndtotal; /* total packets sent */ long spps_sndpack; /* data packets sent */ long spps_sndbyte; /* data bytes sent */ long spps_sndrexmitpack; /* data packets retransmitted */ long spps_sndrexmitbyte; /* data bytes retransmitted */ long spps_sndacks; /* ack-only packets sent */ long spps_sndprobe; /* window probes sent */ long spps_sndurg; /* packets sent with URG only */ long spps_sndwinup; /* window update-only packets sent */ long spps_sndctrl; /* control (SYN|FIN|RST) packets sent */ long spps_sndvoid; /* couldn't find requested packet*/ long spps_rcvtotal; /* total packets received */ long spps_rcvpack; /* packets received in sequence */ long spps_rcvbyte; /* bytes received in sequence */ long spps_rcvbadsum; /* packets received with ccksum errs */ long spps_rcvbadoff; /* packets received with bad offset */ long spps_rcvshort; /* packets received too short */ long spps_rcvduppack; /* duplicate-only packets received */ long spps_rcvdupbyte; /* duplicate-only bytes received */ long spps_rcvpartduppack; /* packets with some duplicate data */ long spps_rcvpartdupbyte; /* dup. bytes in part-dup. packets */ long spps_rcvoopack; /* out-of-order packets received */ long spps_rcvoobyte; /* out-of-order bytes received */ long spps_rcvpackafterwin; /* packets with data after window */ long spps_rcvbyteafterwin; /* bytes rcvd after window */ long spps_rcvafterclose; /* packets rcvd after "close" */ long spps_rcvwinprobe; /* rcvd window probe packets */ long spps_rcvdupack; /* rcvd duplicate acks */ long spps_rcvacktoomuch; /* rcvd acks for unsent data */ long spps_rcvackpack; /* rcvd ack packets */ long spps_rcvackbyte; /* bytes acked by rcvd acks */ long spps_rcvwinupd; /* rcvd window update packets */ }; struct spp_istat { short hdrops; short badsum; short badlen; short slotim; short fastim; short nonucn; short noconn; short notme; short wrncon; short bdreas; short gonawy; short notyet; short lstdup; struct sppstat newstats; }; #ifdef SUPERVISOR struct spp_istat spp_istat; /* Following was struct sppstat sppstat; */ #ifndef sppstat #define sppstat spp_istat.newstats #endif u_short spp_iss; extern struct sppcb *spp_close(), *spp_disconnect(), *spp_usrclosed(), *spp_timers(), *spp_drop(); #endif #define SPP_ISSINCR 128 /* * SPP sequence numbers are 16 bit integers operated * on with modular arithmetic. These macros can be * used to compare such integers. */ #ifdef sun short xnsCbug; #define SSEQ_LT(a,b) ((xnsCbug = (short)((a)-(b))) < 0) #define SSEQ_LEQ(a,b) ((xnsCbug = (short)((a)-(b))) <= 0) #define SSEQ_GT(a,b) ((xnsCbug = (short)((a)-(b))) > 0) #define SSEQ_GEQ(a,b) ((xnsCbug = (short)((a)-(b))) >= 0) #else #define SSEQ_LT(a,b) (((short)((a)-(b))) < 0) #define SSEQ_LEQ(a,b) (((short)((a)-(b))) <= 0) #define SSEQ_GT(a,b) (((short)((a)-(b))) > 0) #define SSEQ_GEQ(a,b) (((short)((a)-(b))) >= 0) #endif t->rt_ifp) && idp_sroute.ro_rt && (ifp!=idp_sroute.ro_rt->rt_ifp)) { flags |= NS_ALLOWBROADCAST; } else { type = NS_ERR_UNREACsys/netns/ns_ip.c 444 12 0 21325 4235740503 7274 /* * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)ns_ip.c 7.2 (Berkeley) 1/20/88 */ /* * Software interface driver for encapsulating ns in ip. */ #include "param.h" #ifdef NSIP #include "systm.h" #include "mbuf.h" #include "socket.h" #include "socketvar.h" #include "errno.h" #include "ioctl.h" #include "protosw.h" #include "../net/if.h" #include "../net/netisr.h" #include "../net/route.h" #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netinet/in_var.h" #include "../netinet/ip.h" #include "../netinet/ip_var.h" #ifdef vax #include "../vax/mtpr.h" #endif #include "../netns/ns.h" #include "../netns/ns_if.h" #include "../netns/idp.h" struct ifnet_en { struct ifnet ifen_ifnet; struct route ifen_route; struct in_addr ifen_src; struct in_addr ifen_dst; }; int nsipoutput(), nsipioctl(); #define LOMTU (1024+512); struct ifnet nsipif; struct mbuf *nsip_list; /* list of all hosts and gateways or broadcast addrs */ struct mbuf * nsipattach() { register struct mbuf *m = m_getclr(M_DONTWAIT, MT_PCB); register struct ifnet *ifp; if (m == NULL) return (NULL); m->m_off = MMINOFF; m->m_len = sizeof(struct ifnet_en); m->m_next = nsip_list; nsip_list = m; ifp = mtod(m, struct ifnet *); ifp->if_name = "nsip"; ifp->if_mtu = LOMTU; ifp->if_ioctl = nsipioctl; ifp->if_output = nsipoutput; ifp->if_flags = IFF_POINTOPOINT; ifp->if_unit = nsipif.if_unit++; if_attach(ifp); return (dtom(ifp)); } /* * Process an ioctl request. */ /* ARGSUSED */ nsipioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { int error = 0; struct ifreq *ifr; switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; /* fall into: */ case SIOCSIFDSTADDR: /* * Everything else is done at a higher level. */ break; case SIOCSIFFLAGS: ifr = (struct ifreq *)data; if ((ifr->ifr_flags & IFF_UP) == 0) error = nsip_free(ifp); default: error = EINVAL; } return (error); } struct mbuf *nsip_badlen; struct mbuf *nsip_lastin; int nsip_hold_input; idpip_input(m, ifp) register struct mbuf *m; struct ifnet *ifp; { register struct ip *ip; register struct idp *idp; register struct ifqueue *ifq = &nsintrq; int len, s; if (nsip_hold_input) { if (nsip_lastin) { m_freem(nsip_lastin); } nsip_lastin = m_copy(m, 0, (int)M_COPYALL); } /* * Get IP and IDP header together in first mbuf. */ nsipif.if_ipackets++; s = sizeof (struct ip) + sizeof (struct idp); if ((m->m_off > MMAXOFF || m->m_len < s) && (m = m_pullup(m, s)) == 0) { nsipif.if_ierrors++; return; } ip = mtod(m, struct ip *); if (ip->ip_hl > (sizeof (struct ip) >> 2)) { ip_stripoptions(ip, (struct mbuf *)0); if (m->m_len < s) { if ((m = m_pullup(m, s)) == 0) { nsipif.if_ierrors++; return; } ip = mtod(m, struct ip *); } } /* * Make mbuf data length reflect IDP length. * If not enough data to reflect IDP length, drop. */ m->m_off += sizeof (struct ip); m->m_len -= sizeof (struct ip); idp = mtod(m, struct idp *); len = ntohs(idp->idp_len); if (len & 1) len++; /* Preserve Garbage Byte */ if (ip->ip_len != len) { if (len > ip->ip_len) { nsipif.if_ierrors++; if (nsip_badlen) m_freem(nsip_badlen); nsip_badlen = m; return; } /* Any extra will be trimmed off by the NS routines */ } /* * Place interface pointer before the data * for the receiving protocol. */ if (m->m_off >= MMINOFF + sizeof(struct ifnet *)) { m->m_off -= sizeof(struct ifnet *); m->m_len += sizeof(struct ifnet *); } else { struct mbuf *n; n = m_get(M_DONTWAIT, MT_HEADER); if (n == (struct mbuf *)0) goto bad; n->m_off = MMINOFF; n->m_len = sizeof(struct ifnet *); n->m_next = m; m = n; } *(mtod(m, struct ifnet **)) = ifp; /* * Deliver to NS */ s = splimp(); if (IF_QFULL(ifq)) { IF_DROP(ifq); bad: m_freem(m); splx(s); return; } IF_ENQUEUE(ifq, m); schednetisr(NETISR_NS); splx(s); return; } /* ARGSUSED */ nsipoutput(ifn, m0, dst) struct ifnet_en *ifn; struct mbuf *m0; struct sockaddr *dst; { register struct mbuf *m = dtom(ifn); register struct ip *ip; register struct route *ro = &(ifn->ifen_route); register int len = 0; register struct idp *idp = mtod(m0, struct idp *); int error; if (m->m_len != sizeof(struct ifnet_en)) { printf("nsipoutput: bad dst ifp %x\n", ifn); goto bad; } ifn->ifen_ifnet.if_opackets++; nsipif.if_opackets++; /* * Calculate data length and make space * for IP header. */ len = ntohs(idp->idp_len); if (len & 1) len++; /* Preserve Garbage Byte */ m = m0; if (m->m_off < MMINOFF + sizeof (struct ip)) { m = m_get(M_DONTWAIT, MT_HEADER); if (m == 0) { m_freem(m0); return (ENOBUFS); } m->m_off = MMAXOFF - sizeof (struct ip); m->m_len = sizeof (struct ip); m->m_next = m0; } else { m->m_off -= sizeof (struct ip); m->m_len += sizeof (struct ip); } /* * Fill in IP header. */ ip = mtod(m, struct ip *); *(long *)ip = 0; ip->ip_p = IPPROTO_IDP; ip->ip_src = ifn->ifen_src; ip->ip_dst = ifn->ifen_dst; ip->ip_len = (u_short)len + sizeof (struct ip); ip->ip_ttl = MAXTTL; /* * Output final datagram. */ error = (ip_output(m, (struct mbuf *)0, ro, SO_BROADCAST)); if (error) { ifn->ifen_ifnet.if_oerrors++; ifn->ifen_ifnet.if_ierrors = error; } return (error); bad: m_freem(m0); return (ENETUNREACH); } struct ifreq ifr = {"nsip0"}; nsip_route(m) register struct mbuf *m; { register struct nsip_req *rq = mtod(m, struct nsip_req *); struct sockaddr_ns *ns_dst = (struct sockaddr_ns *)&rq->rq_ns; struct sockaddr_in *ip_dst = (struct sockaddr_in *)&rq->rq_ip; struct route ro; struct ifnet_en *ifn; struct sockaddr_in *src; /* * First, make sure we already have an ns address: */ if (ns_hosteqnh(ns_thishost, ns_zerohost)) return (EADDRNOTAVAIL); /* * Now, determine if we can get to the destination */ bzero((caddr_t)&ro, sizeof (ro)); ro.ro_dst = *(struct sockaddr *)ip_dst; rtalloc(&ro); if (ro.ro_rt == 0 || ro.ro_rt->rt_ifp == 0) { return (ENETUNREACH); } /* * And see how he's going to get back to us: * i.e., what return ip address do we use? */ { register struct in_ifaddr *ia; struct ifnet *ifp = ro.ro_rt->rt_ifp; for (ia = in_ifaddr; ia; ia = ia->ia_next) if (ia->ia_ifp == ifp) break; if (ia == 0) ia = in_ifaddr; if (ia == 0) { RTFREE(ro.ro_rt); return (EADDRNOTAVAIL); } src = (struct sockaddr_in *)&ia->ia_addr; } /* * Is there a free (pseudo-)interface or space? */ for (m = nsip_list; m; m = m->m_next) { struct ifnet *ifp = mtod(m, struct ifnet *); if ((ifp->if_flags & IFF_UP) == 0) break; } if (m == (struct mbuf *) 0) m = nsipattach(); if (m == NULL) { RTFREE(ro.ro_rt); return (ENOBUFS); } ifn = mtod(m, struct ifnet_en *); ifn->ifen_route = ro; ifn->ifen_dst = ip_dst->sin_addr; ifn->ifen_src = src->sin_addr; /* * now configure this as a point to point link */ ifr.ifr_name[4] = '0' + nsipif.if_unit - 1; ifr.ifr_dstaddr = * (struct sockaddr *) ns_dst; (void)ns_control((struct socket *)0, (int)SIOCSIFDSTADDR, (caddr_t)&ifr, (struct ifnet *)ifn); satons_addr(ifr.ifr_addr).x_host = ns_thishost; return (ns_control((struct socket *)0, (int)SIOCSIFADDR, (caddr_t)&ifr, (struct ifnet *)ifn)); } nsip_free(ifp) struct ifnet *ifp; { register struct ifnet_en *ifn = (struct ifnet_en *)ifp; struct route *ro = & ifn->ifen_route; if (ro->ro_rt) { RTFREE(ro->ro_rt); ro->ro_rt = 0; } ifp->if_flags &= ~IFF_UP; return (0); } nsip_ctlinput(cmd, sa) int cmd; struct sockaddr *sa; { extern u_char inetctlerrmap[]; struct sockaddr_in *sin; int in_rtchange(); if ((unsigned)cmd >= PRC_NCMDS) return; if (sa->sa_family != AF_INET && sa->sa_family != AF_IMPLINK) return; sin = (struct sockaddr_in *)sa; if (sin->sin_addr.s_addr == INADDR_ANY) return; switch (cmd) { case PRC_ROUTEDEAD: case PRC_REDIRECT_NET: case PRC_REDIRECT_HOST: case PRC_REDIRECT_TOSNET: case PRC_REDIRECT_TOSHOST: nsip_rtchange(&sin->sin_addr); break; } } nsip_rtchange(dst) register struct in_addr *dst; { register struct mbuf *m; register struct ifnet_en *ifn; for (m = nsip_list; m; m = m->m_next) { ifn = mtod(m, struct ifnet_en *); if (ifn->ifen_dst.s_addr == dst->s_addr && ifn->ifen_route.ro_rt) { RTFREE(ifn->ifen_route.ro_rt); ifn->ifen_route.ro_rt = 0; } } } #endif dst = (struct sockaddr_ns *)&ro->ro_dst; dst->sns_family = AF_NS; dst->sns_addr = *src; dst->sns_addr.x_port = 0; rtalloc(ro); if (ro->ro_rt == 0 || ro->ro_rt->rt_ifp == 0) { return (0); } ro->ro_rt->rt_use++; return (1); } idp_undo_route(ro) register struct route *ro; { if (ro->ro_rtsys/netns/idp_usrreq.c 444 12 0 24725 4235740444 10354 /* * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)idp_usrreq.c 7.2 (Berkeley) 1/20/88 */ #include "param.h" #ifdef NS #include "user.h" #include "mbuf.h" #include "protosw.h" #include "socket.h" #include "socketvar.h" #include "errno.h" #include "stat.h" #include "../net/if.h" #include "../net/route.h" #include "ns.h" #include "ns_pcb.h" #include "ns_if.h" #include "idp.h" #include "idp_var.h" #include "ns_error.h" /* * IDP protocol implementation. */ struct sockaddr_ns idp_ns = { AF_NS }; /* * This may also be called for raw listeners. */ idp_input(m, nsp, ifp) struct mbuf *m; register struct nspcb *nsp; struct ifnet *ifp; { register struct idp *idp = mtod(m, struct idp *); if (nsp==0) panic("No nspcb"); /* * Construct sockaddr format source address. * Stuff source address and datagram in user buffer. */ idp_ns.sns_addr = idp->idp_sna; if (ns_neteqnn(idp->idp_sna.x_net, ns_zeronet) && ifp) { register struct ifaddr *ia; for (ia = ifp->if_addrlist; ia; ia = ia->ifa_next) { if (ia->ifa_addr.sa_family == AF_NS) { idp_ns.sns_addr.x_net = IA_SNS(ia)->sns_addr.x_net; break; } } } nsp->nsp_rpt = idp->idp_pt; if ( ! (nsp->nsp_flags & NSP_RAWIN) ) { m->m_len -= sizeof (struct idp); m->m_off += sizeof (struct idp); } if (sbappendaddr(&nsp->nsp_socket->so_rcv, (struct sockaddr *)&idp_ns, m, (struct mbuf *)0) == 0) goto bad; sorwakeup(nsp->nsp_socket); return; bad: m_freem(m); } idp_abort(nsp) struct nspcb *nsp; { struct socket *so = nsp->nsp_socket; ns_pcbdisconnect(nsp); soisdisconnected(so); } /* * Drop connection, reporting * the specified error. */ struct nspcb * idp_drop(nsp, errno) register struct nspcb *nsp; int errno; { struct socket *so = nsp->nsp_socket; /* * someday, in the xerox world * we will generate error protocol packets * announcing that the socket has gone away. */ /*if (TCPS_HAVERCVDSYN(tp->t_state)) { tp->t_state = TCPS_CLOSED; (void) tcp_output(tp); }*/ so->so_error = errno; ns_pcbdisconnect(nsp); soisdisconnected(so); } int noIdpRoute; idp_output(nsp, m0) struct nspcb *nsp; struct mbuf *m0; { register struct mbuf *m; register struct idp *idp; register struct socket *so; register int len = 0; register struct route *ro; struct mbuf *mprev; extern int idpcksum; /* * Calculate data length. */ for (m = m0; m; m = m->m_next) { mprev = m; len += m->m_len; } /* * Make sure packet is actually of even length. */ if (len & 1) { m = mprev; if (m->m_len + m->m_off < MMAXOFF) { m->m_len++; } else { struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA); if (m1 == 0) { m_freem(m0); return (ENOBUFS); } m1->m_len = 1; m1->m_off = MMAXOFF - 1; * mtod(m1, char *) = 0; m->m_next = m1; } } /* * Fill in mbuf with extended IDP header * and addresses and length put into network format. */ if (nsp->nsp_flags & NSP_RAWOUT) { m = m0; idp = mtod(m, struct idp *); } else { m = m_get(M_DONTWAIT, MT_HEADER); if (m == 0) { m_freem(m0); return (ENOBUFS); } m->m_off = MMAXOFF - sizeof (struct idp) - 2; /* adjust to start on longword bdry for NSIP on gould */ m->m_len = sizeof (struct idp); m->m_next = m0; idp = mtod(m, struct idp *); idp->idp_tc = 0; idp->idp_pt = nsp->nsp_dpt; idp->idp_sna = nsp->nsp_laddr; idp->idp_dna = nsp->nsp_faddr; len += sizeof (struct idp); } idp->idp_len = htons((u_short)len); if (idpcksum) { idp->idp_sum = 0; len = ((len - 1) | 1) + 1; idp->idp_sum = ns_cksum(m, len); } else idp->idp_sum = 0xffff; /* * Output datagram. */ so = nsp->nsp_socket; if (so->so_options & SO_DONTROUTE) return (ns_output(m, (struct route *)0, (so->so_options & SO_BROADCAST) | NS_ROUTETOIF)); /* * Use cached route for previous datagram if * possible. If the previous net was the same * and the interface was a broadcast medium, or * if the previous destination was identical, * then we are ok. * * NB: We don't handle broadcasts because that * would require 3 subroutine calls. */ ro = &nsp->nsp_route; #ifdef ancient_history /* * I think that this will all be handled in ns_pcbconnect! */ if (ro->ro_rt) { if(ns_neteq(nsp->nsp_lastdst, idp->idp_dna)) { /* * This assumes we have no GH type routes */ if (ro->ro_rt->rt_flags & RTF_HOST) { if (!ns_hosteq(nsp->nsp_lastdst, idp->idp_dna)) goto re_route; } if ((ro->ro_rt->rt_flags & RTF_GATEWAY) == 0) { register struct ns_addr *dst = &satons_addr(ro->ro_dst); dst->x_host = idp->idp_dna.x_host; } /* * Otherwise, we go through the same gateway * and dst is already set up. */ } else { re_route: RTFREE(ro->ro_rt); ro->ro_rt = (struct rtentry *)0; } } nsp->nsp_lastdst = idp->idp_dna; #endif ancient_history if (noIdpRoute) ro = 0; return (ns_output(m, ro, so->so_options & SO_BROADCAST)); } /* ARGSUSED */ idp_ctloutput(req, so, level, name, value) int req, level; struct socket *so; int name; struct mbuf **value; { register struct mbuf *m; struct nspcb *nsp = sotonspcb(so); int mask, error = 0; extern long ns_pexseq; if (nsp == NULL) return (EINVAL); switch (req) { case PRCO_GETOPT: if (value==NULL) return (EINVAL); m = m_get(M_DONTWAIT, MT_DATA); if (m==NULL) return (ENOBUFS); switch (name) { case SO_ALL_PACKETS: mask = NSP_ALL_PACKETS; goto get_flags; case SO_HEADERS_ON_INPUT: mask = NSP_RAWIN; goto get_flags; case SO_HEADERS_ON_OUTPUT: mask = NSP_RAWOUT; get_flags: m->m_len = sizeof(short); m->m_off = MMAXOFF - sizeof(short); *mtod(m, short *) = nsp->nsp_flags & mask; break; case SO_DEFAULT_HEADERS: m->m_len = sizeof(struct idp); m->m_off = MMAXOFF - sizeof(struct idp); { register struct idp *idp = mtod(m, struct idp *); idp->idp_len = 0; idp->idp_sum = 0; idp->idp_tc = 0; idp->idp_pt = nsp->nsp_dpt; idp->idp_dna = nsp->nsp_faddr; idp->idp_sna = nsp->nsp_laddr; } break; case SO_SEQNO: m->m_len = sizeof(long); m->m_off = MMAXOFF - sizeof(long); *mtod(m, long *) = ns_pexseq++; break; default: error = EINVAL; } *value = m; break; case PRCO_SETOPT: switch (name) { int *ok; case SO_ALL_PACKETS: mask = NSP_ALL_PACKETS; goto set_head; case SO_HEADERS_ON_INPUT: mask = NSP_RAWIN; goto set_head; case SO_HEADERS_ON_OUTPUT: mask = NSP_RAWOUT; set_head: if (value && *value) { ok = mtod(*value, int *); if (*ok) nsp->nsp_flags |= mask; else nsp->nsp_flags &= ~mask; } else error = EINVAL; break; case SO_DEFAULT_HEADERS: { register struct idp *idp = mtod(*value, struct idp *); nsp->nsp_dpt = idp->idp_pt; } break; #ifdef NSIP case SO_NSIP_ROUTE: error = nsip_route(*value); break; #endif NSIP default: error = EINVAL; } if (value && *value) m_freem(*value); break; } return (error); } /*ARGSUSED*/ idp_usrreq(so, req, m, nam, rights) struct socket *so; int req; struct mbuf *m, *nam, *rights; { struct nspcb *nsp = sotonspcb(so); int error = 0; if (req == PRU_CONTROL) return (ns_control(so, (int)m, (caddr_t)nam, (struct ifnet *)rights)); if (rights && rights->m_len) { error = EINVAL; goto release; } if (nsp == NULL && req != PRU_ATTACH) { error = EINVAL; goto release; } switch (req) { case PRU_ATTACH: if (nsp != NULL) { error = EINVAL; break; } error = ns_pcballoc(so, &nspcb); if (error) break; error = soreserve(so, 2048, 2048); if (error) break; break; case PRU_DETACH: if (nsp == NULL) { error = ENOTCONN; break; } ns_pcbdetach(nsp); break; case PRU_BIND: error = ns_pcbbind(nsp, nam); break; case PRU_LISTEN: error = EOPNOTSUPP; break; case PRU_CONNECT: if (!ns_nullhost(nsp->nsp_faddr)) { error = EISCONN; break; } error = ns_pcbconnect(nsp, nam); if (error == 0) soisconnected(so); break; case PRU_CONNECT2: error = EOPNOTSUPP; break; case PRU_ACCEPT: error = EOPNOTSUPP; break; case PRU_DISCONNECT: if (ns_nullhost(nsp->nsp_faddr)) { error = ENOTCONN; break; } ns_pcbdisconnect(nsp); soisdisconnected(so); break; case PRU_SHUTDOWN: socantsendmore(so); break; case PRU_SEND: { struct ns_addr laddr; int s; if (nam) { laddr = nsp->nsp_laddr; if (!ns_nullhost(nsp->nsp_faddr)) { error = EISCONN; break; } /* * Must block input while temporarily connected. */ s = splnet(); error = ns_pcbconnect(nsp, nam); if (error) { splx(s); break; } } else { if (ns_nullhost(nsp->nsp_faddr)) { error = ENOTCONN; break; } } error = idp_output(nsp, m); m = NULL; if (nam) { ns_pcbdisconnect(nsp); splx(s); nsp->nsp_laddr.x_host = laddr.x_host; nsp->nsp_laddr.x_port = laddr.x_port; } } break; case PRU_ABORT: ns_pcbdetach(nsp); sofree(so); soisdisconnected(so); break; case PRU_SOCKADDR: ns_setsockaddr(nsp, nam); break; case PRU_PEERADDR: ns_setpeeraddr(nsp, nam); break; case PRU_SENSE: /* * stat: don't bother with a blocksize. */ return (0); case PRU_SENDOOB: case PRU_FASTTIMO: case PRU_SLOWTIMO: case PRU_PROTORCV: case PRU_PROTOSEND: error = EOPNOTSUPP; break; case PRU_CONTROL: case PRU_RCVD: case PRU_RCVOOB: return (EOPNOTSUPP); /* do not free mbuf's */ default: panic("idp_usrreq"); } release: if (m != NULL) m_freem(m); return (error); } /*ARGSUSED*/ idp_raw_usrreq(so, req, m, nam, rights) struct socket *so; int req; struct mbuf *m, *nam, *rights; { int error = 0; struct nspcb *nsp = sotonspcb(so); extern struct nspcb nsrawpcb; switch (req) { case PRU_ATTACH: if (!suser() || (nsp != NULL)) { error = EINVAL; break; } error = ns_pcballoc(so, &nsrawpcb); if (error) break; error = soreserve(so, 2048, 2048); if (error) break; nsp = sotonspcb(so); nsp->nsp_faddr.x_host = ns_broadhost; nsp->nsp_flags = NSP_RAWIN | NSP_RAWOUT; break; default: error = idp_usrreq(so, req, m, nam, rights); } return (error); } #endif ovided ``as is'' without express or impliedsys/netns/ns_pcb.h 444 12 0 3527 4235473200 7416 /* * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)ns_pcb.h 7.2 (Berkeley) 1/20/88 */ /* * Ns protocol interface control block. */ struct nspcb { struct nspcb *nsp_next; /* doubly linked list */ struct nspcb *nsp_prev; struct nspcb *nsp_head; struct socket *nsp_socket; /* back pointer to socket */ struct ns_addr nsp_faddr; /* destination address */ struct ns_addr nsp_laddr; /* socket's address */ caddr_t nsp_pcb; /* protocol specific stuff */ struct route nsp_route; /* routing information */ struct ns_addr nsp_lastdst; /* validate cached route for dg socks*/ long nsp_notify_param; /* extra info passed via ns_pcbnotify*/ short nsp_flags; u_char nsp_dpt; /* default packet type for idp_output*/ u_char nsp_rpt; /* last received packet type by idp_input() */ }; /* possible flags */ #define NSP_IN_ABORT 0x1 /* calling abort through socket */ #define NSP_RAWIN 0x2 /* show headers on input */ #define NSP_RAWOUT 0x4 /* show header on output */ #define NSP_ALL_PACKETS 0x8 /* Turn off higher proto processing */ #define NS_WILDCARD 1 #define nsp_lport nsp_laddr.x_port #define nsp_fport nsp_faddr.x_port #define sotonspcb(so) ((struct nspcb *)((so)->so_pcb)) /* * Nominal space allocated to a ns socket. */ #define NSSNDQ 2048 #define NSRCVQ 2048 #ifdef SUPERVISOR struct nspcb nspcb; /* head of list */ struct nspcb *ns_pcblookup(); #endif 0) goto bad; sorwakeup(nsp->nsp_socket); return; bad: m_freem(m); } idp_abort(nsp) struct nspcb *nsp; { struct socket *so = nsp->nsp_socket; ns_pcbdisconnect(nsys/netns/ns_pcb.c 444 12 0 16746 4235740523 7445 /* * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)ns_pcb.c 7.3 (Berkeley) 1/20/88 */ #include "param.h" #ifdef NS #include "systm.h" #include "user.h" #include "mbuf.h" #include "socket.h" #include "socketvar.h" #include "../net/if.h" #include "../net/route.h" #include "protosw.h" #include "ns.h" #include "ns_if.h" #include "ns_pcb.h" struct ns_addr zerons_addr; ns_pcballoc(so, head) struct socket *so; struct nspcb *head; { struct mbuf *m; register struct nspcb *nsp; m = m_getclr(M_DONTWAIT, MT_PCB); if (m == NULL) return (ENOBUFS); nsp = mtod(m, struct nspcb *); nsp->nsp_socket = so; insque(nsp, head); so->so_pcb = (caddr_t)nsp; return (0); } ns_pcbbind(nsp, nam) register struct nspcb *nsp; struct mbuf *nam; { register struct sockaddr_ns *sns; u_short lport = 0; if(nsp->nsp_lport || !ns_nullhost(nsp->nsp_laddr)) return (EINVAL); if (nam == 0) goto noname; sns = mtod(nam, struct sockaddr_ns *); if (nam->m_len != sizeof (*sns)) return (EINVAL); if (!ns_nullhost(sns->sns_addr)) { int tport = sns->sns_port; sns->sns_port = 0; /* yech... */ if (ifa_ifwithaddr((struct sockaddr *)sns) == 0) return (EADDRNOTAVAIL); sns->sns_port = tport; } lport = sns->sns_port; if (lport) { u_short aport = ntohs(lport); if (aport < NSPORT_RESERVED && u.u_uid != 0) return (EACCES); if (ns_pcblookup(&zerons_addr, lport, 0)) return (EADDRINUSE); } nsp->nsp_laddr = sns->sns_addr; noname: if (lport == 0) do { if (nspcb.nsp_lport++ < NSPORT_RESERVED) nspcb.nsp_lport = NSPORT_RESERVED; lport = htons(nspcb.nsp_lport); } while (ns_pcblookup(&zerons_addr, lport, 0)); nsp->nsp_lport = lport; return (0); } /* * Connect from a socket to a specified address. * Both address and port must be specified in argument sns. * If don't have a local address for this socket yet, * then pick one. */ ns_pcbconnect(nsp, nam) struct nspcb *nsp; struct mbuf *nam; { struct ns_ifaddr *ia; register struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *); struct sockaddr_ns *ifaddr; register struct ns_addr *dst; if (nam->m_len != sizeof (*sns)) return (EINVAL); if (sns->sns_family != AF_NS) return (EAFNOSUPPORT); if (sns->sns_port==0 || ns_nullhost(sns->sns_addr)) return (EADDRNOTAVAIL); if (ns_nullhost(nsp->nsp_laddr)) { register struct route *ro; struct ifnet *ifp; /* * If route is known or can be allocated now, * our src addr is taken from the i/f, else punt. */ ro = &nsp->nsp_route; dst = &satons_addr(ro->ro_dst); ia = (struct ns_ifaddr *)0; if (ro->ro_rt) { if ((!ns_neteq(nsp->nsp_lastdst, sns->sns_addr)) || ((ifp = ro->ro_rt->rt_ifp) && (ifp->if_flags & IFF_POINTOPOINT) && (!ns_hosteq(nsp->nsp_lastdst, sns->sns_addr))) || (nsp->nsp_socket->so_options & SO_DONTROUTE)) { RTFREE(ro->ro_rt); ro->ro_rt = (struct rtentry *)0; } } if ((nsp->nsp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/ (ro->ro_rt == (struct rtentry *)0 || ro->ro_rt->rt_ifp == (struct ifnet *)0)) { /* No route yet, so try to acquire one */ ro->ro_dst.sa_family = AF_NS; *dst = sns->sns_addr; dst->x_port = 0; rtalloc(ro); } /* * If we found a route, use the address * corresponding to the outgoing interface */ if (ro->ro_rt && (ifp = ro->ro_rt->rt_ifp)) for (ia = ns_ifaddr; ia; ia = ia->ia_next) if (ia->ia_ifp == ifp) break; if (ia == 0) { u_short fport = sns->sns_addr.x_port; sns->sns_addr.x_port = 0; ia = (struct ns_ifaddr *) ifa_ifwithdstaddr((struct sockaddr *)sns); sns->sns_addr.x_port = fport; if (ia == 0) ia = ns_iaonnetof(&sns->sns_addr); if (ia == 0) ia = ns_ifaddr; if (ia == 0) return (EADDRNOTAVAIL); } nsp->nsp_laddr.x_net = satons_addr(ia->ia_addr).x_net; nsp->nsp_lastdst = sns->sns_addr; } if (ns_pcblookup(&sns->sns_addr, nsp->nsp_lport, 0)) return (EADDRINUSE); if (ns_nullhost(nsp->nsp_laddr)) { if (nsp->nsp_lport == 0) (void) ns_pcbbind(nsp, (struct mbuf *)0); nsp->nsp_laddr.x_host = ns_thishost; } nsp->nsp_faddr = sns->sns_addr; /* Includes nsp->nsp_fport = sns->sns_port; */ return (0); } ns_pcbdisconnect(nsp) struct nspcb *nsp; { nsp->nsp_faddr = zerons_addr; if (nsp->nsp_socket->so_state & SS_NOFDREF) ns_pcbdetach(nsp); } ns_pcbdetach(nsp) struct nspcb *nsp; { struct socket *so = nsp->nsp_socket; so->so_pcb = 0; sofree(so); if (nsp->nsp_route.ro_rt) rtfree(nsp->nsp_route.ro_rt); remque(nsp); (void) m_free(dtom(nsp)); } ns_setsockaddr(nsp, nam) register struct nspcb *nsp; struct mbuf *nam; { register struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *); nam->m_len = sizeof (*sns); sns = mtod(nam, struct sockaddr_ns *); bzero((caddr_t)sns, sizeof (*sns)); sns->sns_family = AF_NS; sns->sns_addr = nsp->nsp_laddr; } ns_setpeeraddr(nsp, nam) register struct nspcb *nsp; struct mbuf *nam; { register struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *); nam->m_len = sizeof (*sns); sns = mtod(nam, struct sockaddr_ns *); bzero((caddr_t)sns, sizeof (*sns)); sns->sns_family = AF_NS; sns->sns_addr = nsp->nsp_faddr; } /* * Pass some notification to all connections of a protocol * associated with address dst. Call the * protocol specific routine to handle each connection. * Also pass an extra paramter via the nspcb. (which may in fact * be a parameter list!) */ ns_pcbnotify(dst, errno, notify, param) register struct ns_addr *dst; long param; int errno, (*notify)(); { register struct nspcb *nsp, *oinp; int s = splimp(); for (nsp = (&nspcb)->nsp_next; nsp != (&nspcb);) { if (!ns_hosteq(*dst,nsp->nsp_faddr)) { next: nsp = nsp->nsp_next; continue; } if (nsp->nsp_socket == 0) goto next; if (errno) nsp->nsp_socket->so_error = errno; oinp = nsp; nsp = nsp->nsp_next; oinp->nsp_notify_param = param; (*notify)(oinp); } splx(s); } #ifdef notdef /* * After a routing change, flush old routing * and allocate a (hopefully) better one. */ ns_rtchange(nsp) struct nspcb *nsp; { if (nsp->nsp_route.ro_rt) { rtfree(nsp->nsp_route.ro_rt); nsp->nsp_route.ro_rt = 0; /* * A new route can be allocated the next time * output is attempted. */ } /* SHOULD NOTIFY HIGHER-LEVEL PROTOCOLS */ } #endif struct nspcb * ns_pcblookup(faddr, lport, wildp) struct ns_addr *faddr; u_short lport; { register struct nspcb *nsp, *match = 0; int matchwild = 3, wildcard; u_short fport; fport = faddr->x_port; for (nsp = (&nspcb)->nsp_next; nsp != (&nspcb); nsp = nsp->nsp_next) { if (nsp->nsp_lport != lport) continue; wildcard = 0; if (ns_nullhost(nsp->nsp_faddr)) { if (!ns_nullhost(*faddr)) wildcard++; } else { if (ns_nullhost(*faddr)) wildcard++; else { if (!ns_hosteq(nsp->nsp_faddr, *faddr)) continue; if( nsp->nsp_fport != fport) { if(nsp->nsp_fport != 0) continue; else wildcard++; } } } if (wildcard && wildp==0) continue; if (wildcard < matchwild) { match = nsp; matchwild = wildcard; if (wildcard == 0) break; } } return (match); } #endif _PCB); if (m == NULL) rsys/netns/ns_output.c 444 12 0 5665 4235740512 10215 /* * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)ns_output.c 7.2 (Berkeley) 1/20/88 */ #include "param.h" #ifdef NS #include "mbuf.h" #include "errno.h" #include "socket.h" #include "socketvar.h" #include "../net/if.h" #include "../net/route.h" #include "ns.h" #include "ns_if.h" #include "idp.h" #include "idp_var.h" #ifdef vax #include "../vax/mtpr.h" #endif int ns_hold_output = 0; int ns_copy_output = 0; int ns_output_cnt = 0; struct mbuf *ns_lastout; ns_output(m0, ro, flags) struct mbuf *m0; struct route *ro; int flags; { register struct idp *idp = mtod(m0, struct idp *); register struct ifnet *ifp = 0; int error = 0; struct route idproute; struct sockaddr_ns *dst; extern int idpcksum; if (ns_hold_output) { if (ns_lastout) { (void)m_free(ns_lastout); } ns_lastout = m_copy(m0, 0, (int)M_COPYALL); } /* * Route packet. */ if (ro == 0) { ro = &idproute; bzero((caddr_t)ro, sizeof (*ro)); } dst = (struct sockaddr_ns *)&ro->ro_dst; if (ro->ro_rt == 0) { dst->sns_family = AF_NS; dst->sns_addr = idp->idp_dna; dst->sns_addr.x_port = 0; /* * If routing to interface only, * short circuit routing lookup. */ if (flags & NS_ROUTETOIF) { struct ns_ifaddr *ia = ns_iaonnetof(&idp->idp_dna); if (ia == 0) { error = ENETUNREACH; goto bad; } ifp = ia->ia_ifp; goto gotif; } rtalloc(ro); } else if ((ro->ro_rt->rt_flags & RTF_UP) == 0) { /* * The old route has gone away; try for a new one. */ rtfree(ro->ro_rt); ro->ro_rt = NULL; rtalloc(ro); } if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) { error = ENETUNREACH; goto bad; } ro->ro_rt->rt_use++; if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST)) dst = (struct sockaddr_ns *)&ro->ro_rt->rt_gateway; gotif: /* * Look for multicast addresses and * and verify user is allowed to send * such a packet. */ if (dst->sns_addr.x_host.c_host[0]&1) { if ((ifp->if_flags & IFF_BROADCAST) == 0) { error = EADDRNOTAVAIL; goto bad; } if ((flags & NS_ALLOWBROADCAST) == 0) { error = EACCES; goto bad; } } if (htons(idp->idp_len) <= ifp->if_mtu) { ns_output_cnt++; if (ns_copy_output) { ns_watch_output(m0, ifp); } error = (*ifp->if_output)(ifp, m0, (struct sockaddr *)dst); goto done; } else error = EMSGSIZE; bad: if (ns_copy_output) { ns_watch_output(m0, ifp); } m_freem(m0); done: if (ro == &idproute && (flags & NS_ROUTETOIF) == 0 && ro->ro_rt) RTFREE(ro->ro_rt); return (error); } #endif &satons_addr(ro->ro_dst); ia = (struct ns_ifaddr *)0; if (ro->ro_rt) {sys/netns/spp_usrreq.c 444 12 0 116667 4235740556 10435 /* * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)spp_usrreq.c 7.6 (Berkeley) 3/12/88 */ #include "param.h" #ifdef NS #include "systm.h" #include "user.h" #include "mbuf.h" #include "protosw.h" #include "socket.h" #include "socketvar.h" #include "errno.h" #include "../net/if.h" #include "../net/route.h" #include "../netinet/tcp_fsm.h" #include "ns.h" #include "ns_pcb.h" #include "idp.h" #include "idp_var.h" #include "ns_error.h" #include "sp.h" #include "spidp.h" #include "spp_timer.h" #include "spp_var.h" #include "spp_debug.h" /* * SP protocol implementation. */ spp_init() { spp_iss = 1; /* WRONG !! should fish it out of TODR */ } struct spidp spp_savesi; int traceallspps = 0; extern int sppconsdebug; int spp_hardnosed; int spp_use_delack = 0; /*ARGSUSED*/ spp_input(m, nsp, ifp) register struct mbuf *m; register struct nspcb *nsp; struct ifnet *ifp; { register struct sppcb *cb; register struct spidp *si = mtod(m, struct spidp *); register struct socket *so; short ostate; int dropsocket = 0; sppstat.spps_rcvtotal++; if (nsp == 0) { panic("No nspcb in spp_input\n"); return; } cb = nstosppcb(nsp); if (cb == 0) goto bad; if (m->m_len < sizeof(*si)) { if ((m = m_pullup(m, sizeof(*si))) == 0) { sppstat.spps_rcvshort++; return; } si = mtod(m, struct spidp *); } si->si_seq = ntohs(si->si_seq); si->si_ack = ntohs(si->si_ack); si->si_alo = ntohs(si->si_alo); so = nsp->nsp_socket; if (so->so_options & SO_DEBUG || traceallspps) { ostate = cb->s_state; spp_savesi = *si; } if (so->so_options & SO_ACCEPTCONN) { struct sppcb *ocb = cb; struct socket *oso = so; so = sonewconn(so); if (so == 0) { goto drop; } /* * This is ugly, but .... * * Mark socket as temporary until we're * committed to keeping it. The code at * ``drop'' and ``dropwithreset'' check the * flag dropsocket to see if the temporary * socket created here should be discarded. * We mark the socket as discardable until * we're committed to it below in TCPS_LISTEN. */ dropsocket++; nsp = (struct nspcb *)so->so_pcb; nsp->nsp_laddr = si->si_dna; cb = nstosppcb(nsp); cb->s_mtu = ocb->s_mtu; /* preserve sockopts */ cb->s_flags = ocb->s_flags; /* preserve sockopts */ if (so->so_snd.sb_hiwat != oso->so_snd.sb_hiwat) /*XXX*/ sbreserve(&so->so_snd, oso->so_snd.sb_hiwat); if (so->so_rcv.sb_hiwat != oso->so_rcv.sb_hiwat) /*XXX*/ sbreserve(&so->so_rcv, oso->so_rcv.sb_hiwat); cb->s_state = TCPS_LISTEN; } /* * Packet received on connection. * reset idle time and keep-alive timer; */ cb->s_idle = 0; cb->s_timer[SPPT_KEEP] = SPPTV_KEEP; switch (cb->s_state) { case TCPS_LISTEN:{ struct mbuf *am; register struct sockaddr_ns *sns; struct ns_addr laddr; /* * If somebody here was carying on a conversation * and went away, and his pen pal thinks he can * still talk, we get the misdirected packet. */ if (spp_hardnosed && (si->si_did != 0 || si->si_seq != 0)) { spp_istat.gonawy++; goto dropwithreset; } am = m_get(M_DONTWAIT, MT_SONAME); if (am == NULL) goto drop; am->m_len = sizeof (struct sockaddr_ns); sns = mtod(am, struct sockaddr_ns *); sns->sns_family = AF_NS; sns->sns_addr = si->si_sna; laddr = nsp->nsp_laddr; if (ns_nullhost(laddr)) nsp->nsp_laddr = si->si_dna; if (ns_pcbconnect(nsp, am)) { nsp->nsp_laddr = laddr; (void) m_free(am); spp_istat.noconn++; goto drop; } (void) m_free(am); spp_template(cb); dropsocket = 0; /* committed to socket */ cb->s_did = si->si_sid; cb->s_rack = si->si_ack; cb->s_ralo = si->si_alo; #define THREEWAYSHAKE #ifdef THREEWAYSHAKE cb->s_state = TCPS_SYN_RECEIVED; cb->s_force = 1 + SPPT_KEEP; sppstat.spps_accepts++; cb->s_timer[SPPT_KEEP] = SPPTV_KEEP; } break; /* * This state means that we have heard a response * to our acceptance of their connection * It is probably logically unnecessary in this * implementation. */ case TCPS_SYN_RECEIVED: { if (si->si_did!=cb->s_sid) { spp_istat.wrncon++; goto drop; } #endif nsp->nsp_fport = si->si_sport; cb->s_timer[SPPT_REXMT] = 0; cb->s_timer[SPPT_KEEP] = SPPTV_KEEP; soisconnected(so); cb->s_state = TCPS_ESTABLISHED; sppstat.spps_accepts++; } break; /* * This state means that we have gotten a response * to our attempt to establish a connection. * We fill in the data from the other side, * telling us which port to respond to, instead of the well- * known one we might have sent to in the first place. * We also require that this is a response to our * connection id. */ case TCPS_SYN_SENT: if (si->si_did!=cb->s_sid) { spp_istat.notme++; goto drop; } sppstat.spps_connects++; cb->s_did = si->si_sid; cb->s_rack = si->si_ack; cb->s_ralo = si->si_alo; cb->s_dport = nsp->nsp_fport = si->si_sport; cb->s_timer[SPPT_REXMT] = 0; cb->s_flags |= SF_ACKNOW; soisconnected(so); cb->s_state = TCPS_ESTABLISHED; /* Use roundtrip time of connection request for initial rtt */ if (cb->s_rtt) { cb->s_srtt = cb->s_rtt << 3; cb->s_rttvar = cb->s_rtt << 1; SPPT_RANGESET(cb->s_rxtcur, ((cb->s_srtt >> 2) + cb->s_rttvar) >> 1, SPPTV_MIN, SPPTV_REXMTMAX); cb->s_rtt = 0; } } if (so->so_options & SO_DEBUG || traceallspps) spp_trace(SA_INPUT, (u_char)ostate, cb, &spp_savesi, 0); m->m_len -= sizeof (struct idp); m->m_off += sizeof (struct idp); if (spp_reass(cb, si)) { (void) m_freem(m); } if (cb->s_force || (cb->s_flags & (SF_ACKNOW|SF_WIN|SF_RXT))) (void) spp_output(cb, (struct mbuf *)0); cb->s_flags &= ~(SF_WIN|SF_RXT); return; dropwithreset: if (dropsocket) (void) soabort(so); si->si_seq = ntohs(si->si_seq); si->si_ack = ntohs(si->si_ack); si->si_alo = ntohs(si->si_alo); ns_error(dtom(si), NS_ERR_NOSOCK, 0); if (cb->s_nspcb->nsp_socket->so_options & SO_DEBUG || traceallspps) spp_trace(SA_DROP, (u_char)ostate, cb, &spp_savesi, 0); return; drop: bad: if (cb == 0 || cb->s_nspcb->nsp_socket->so_options & SO_DEBUG || traceallspps) spp_trace(SA_DROP, (u_char)ostate, cb, &spp_savesi, 0); m_freem(m); } int spprexmtthresh = 3; /* * This is structurally similar to the tcp reassembly routine * but its function is somewhat different: It merely queues * packets up, and suppresses duplicates. */ spp_reass(cb, si) register struct sppcb *cb; register struct spidp *si; { register struct spidp_q *q; register struct mbuf *m; register struct socket *so = cb->s_nspcb->nsp_socket; char packetp = cb->s_flags & SF_HI; int incr; char wakeup = 0; if (si == SI(0)) goto present; /* * Update our news from them. */ if (si->si_cc & SP_SA) cb->s_flags |= (spp_use_delack ? SF_DELACK : SF_ACKNOW); if (SSEQ_GT(si->si_alo, cb->s_ralo)) cb->s_flags |= SF_WIN; if (SSEQ_LEQ(si->si_ack, cb->s_rack)) { if ((si->si_cc & SP_SP) && cb->s_rack != (cb->s_smax + 1)) { sppstat.spps_rcvdupack++; /* * If this is a completely duplicate ack * and other conditions hold, we assume * a packet has been dropped and retransmit * it exactly as in tcp_input(). */ if (si->si_ack != cb->s_rack || si->si_alo != cb->s_ralo) cb->s_dupacks = 0; else if (++cb->s_dupacks == spprexmtthresh) { u_short onxt = cb->s_snxt; int cwnd = cb->s_cwnd; cb->s_snxt = si->si_ack; cb->s_cwnd = CUNIT; cb->s_force = 1 + SPPT_REXMT; (void) spp_output(cb, (struct mbuf *)0); cb->s_timer[SPPT_REXMT] = cb->s_rxtcur; cb->s_rtt = 0; if (cwnd >= 4 * CUNIT) cb->s_cwnd = cwnd / 2; if (SSEQ_GT(onxt, cb->s_snxt)) cb->s_snxt = onxt; return (1); } } else cb->s_dupacks = 0; goto update_window; } cb->s_dupacks = 0; /* * If our correspondent acknowledges data we haven't sent * TCP would drop the packet after acking. We'll be a little * more permissive */ if (SSEQ_GT(si->si_ack, (cb->s_smax + 1))) { sppstat.spps_rcvacktoomuch++; si->si_ack = cb->s_smax + 1; } sppstat.spps_rcvackpack++; /* * If transmit timer is running and timed sequence * number was acked, update smoothed round trip time. * See discussion of algorithm in tcp_input.c */ if (cb->s_rtt && SSEQ_GT(si->si_ack, cb->s_rtseq)) { sppstat.spps_rttupdated++; if (cb->s_srtt != 0) { register short delta; delta = cb->s_rtt - (cb->s_srtt >> 3); if ((cb->s_srtt += delta) <= 0) cb->s_srtt = 1; if (delta < 0) delta = -delta; delta -= (cb->s_rttvar >> 2); if ((cb->s_rttvar += delta) <= 0) cb->s_rttvar = 1; } else { /* * No rtt measurement yet */ cb->s_srtt = cb->s_rtt << 3; cb->s_rttvar = cb->s_rtt << 1; } cb->s_rtt = 0; cb->s_rxtshift = 0; SPPT_RANGESET(cb->s_rxtcur, ((cb->s_srtt >> 2) + cb->s_rttvar) >> 1, SPPTV_MIN, SPPTV_REXMTMAX); } /* * If all outstanding data is acked, stop retransmit * timer and remember to restart (more output or persist). * If there is more data to be acked, restart retransmit * timer, using current (possibly backed-off) value; */ if (si->si_ack == cb->s_smax + 1) { cb->s_timer[SPPT_REXMT] = 0; cb->s_flags |= SF_RXT; } else if (cb->s_timer[SPPT_PERSIST] == 0) cb->s_timer[SPPT_REXMT] = cb->s_rxtcur; /* * When new data is acked, open the congestion window. * If the window gives us less than ssthresh packets * in flight, open exponentially (maxseg at a time). * Otherwise open linearly (maxseg^2 / cwnd at a time). */ incr = CUNIT; if (cb->s_cwnd > cb->s_ssthresh) incr = MAX(incr * incr / cb->s_cwnd, 1); cb->s_cwnd = MIN(cb->s_cwnd + incr, cb->s_cwmx); /* * Trim Acked data from output queue. */ while ((m = so->so_snd.sb_mb) != NULL) { if (SSEQ_LT((mtod(m, struct spidp *))->si_seq, si->si_ack)) sbdroprecord(&so->so_snd); else break; } if ((so->so_snd.sb_flags & SB_WAIT) || so->so_snd.sb_sel) sowwakeup(so); cb->s_rack = si->si_ack; update_window: if (SSEQ_LT(cb->s_snxt, cb->s_rack)) cb->s_snxt = cb->s_rack; if (SSEQ_LT(cb->s_swl1, si->si_seq) || cb->s_swl1 == si->si_seq && (SSEQ_LT(cb->s_swl2, si->si_ack) || cb->s_swl2 == si->si_ack && SSEQ_LT(cb->s_ralo, si->si_alo))) { /* keep track of pure window updates */ if ((si->si_cc & SP_SP) && cb->s_swl2 == si->si_ack && SSEQ_LT(cb->s_ralo, si->si_alo)) { sppstat.spps_rcvwinupd++; sppstat.spps_rcvdupack--; } cb->s_ralo = si->si_alo; cb->s_swl1 = si->si_seq; cb->s_swl2 = si->si_ack; cb->s_swnd = (1 + si->si_alo - si->si_ack); if (cb->s_swnd > cb->s_smxw) cb->s_smxw = cb->s_swnd; cb->s_flags |= SF_WIN; } /* * If this packet number is higher than that which * we have allocated refuse it, unless urgent */ if (SSEQ_GT(si->si_seq, cb->s_alo)) { if (si->si_cc & SP_SP) { sppstat.spps_rcvwinprobe++; return (1); } else sppstat.spps_rcvpackafterwin++; if (si->si_cc & SP_OB) { if (SSEQ_GT(si->si_seq, cb->s_alo + 60)) { ns_error(dtom(si), NS_ERR_FULLUP, 0); return (0); } /* else queue this packet; */ } else { /*register struct socket *so = cb->s_nspcb->nsp_socket; if (so->so_state && SS_NOFDREF) { ns_error(dtom(si), NS_ERR_NOSOCK, 0); (void)spp_close(cb); } else would crash system*/ spp_istat.notyet++; ns_error(dtom(si), NS_ERR_FULLUP, 0); return (0); } } /* * If this is a system packet, we don't need to * queue it up, and won't update acknowledge # */ if (si->si_cc & SP_SP) { return (1); } /* * We have already seen this packet, so drop. */ if (SSEQ_LT(si->si_seq, cb->s_ack)) { spp_istat.bdreas++; sppstat.spps_rcvduppack++; if (si->si_seq == cb->s_ack - 1) spp_istat.lstdup++; return (1); } /* * Loop through all packets queued up to insert in * appropriate sequence. */ for (q = cb->s_q.si_next; q!=&cb->s_q; q = q->si_next) { if (si->si_seq == SI(q)->si_seq) { sppstat.spps_rcvduppack++; return (1); } if (SSEQ_LT(si->si_seq, SI(q)->si_seq)) { sppstat.spps_rcvoopack++; break; } } insque(si, q->si_prev); /* * If this packet is urgent, inform process */ if (si->si_cc & SP_OB) { cb->s_iobc = ((char *)si)[1 + sizeof(*si)]; sohasoutofband(so); cb->s_oobflags |= SF_IOOB; } present: #define SPINC sizeof(struct sphdr) /* * Loop through all packets queued up to update acknowledge * number, and present all acknowledged data to user; * If in packet interface mode, show packet headers. */ for (q = cb->s_q.si_next; q!=&cb->s_q; q = q->si_next) { if (SI(q)->si_seq == cb->s_ack) { cb->s_ack++; m = dtom(q); if (SI(q)->si_cc & SP_OB) { cb->s_oobflags &= ~SF_IOOB; if (so->so_rcv.sb_cc) so->so_oobmark = so->so_rcv.sb_cc; else so->so_state |= SS_RCVATMARK; } q = q->si_prev; remque(q->si_next); wakeup = 1; sppstat.spps_rcvpack++; if (packetp) { sbappendrecord(&so->so_rcv, m); } else { cb->s_rhdr = *mtod(m, struct sphdr *); m->m_off += SPINC; m->m_len -= SPINC; sbappend(&so->so_rcv, m); } } else break; } if (wakeup) sorwakeup(so); return (0); } spp_ctlinput(cmd, arg) int cmd; caddr_t arg; { struct ns_addr *na; extern u_char nsctlerrmap[]; extern spp_abort(), spp_quench(); extern struct nspcb *idp_drop(); struct ns_errp *errp; struct nspcb *nsp; struct sockaddr_ns *sns; int type; if (cmd < 0 || cmd > PRC_NCMDS) return; type = NS_ERR_UNREACH_HOST; switch (cmd) { case PRC_ROUTEDEAD: return; case PRC_IFDOWN: case PRC_HOSTDEAD: case PRC_HOSTUNREACH: sns = (struct sockaddr_ns *)arg; if (sns->sns_family != AF_NS) return; na = &sns->sns_addr; break; default: errp = (struct ns_errp *)arg; na = &errp->ns_err_idp.idp_dna; type = errp->ns_err_num; type = ntohs((u_short)type); } switch (type) { case NS_ERR_UNREACH_HOST: ns_pcbnotify(na, (int)nsctlerrmap[cmd], spp_abort, (long) 0); break; case NS_ERR_TOO_BIG: case NS_ERR_NOSOCK: nsp = ns_pcblookup(na, errp->ns_err_idp.idp_sna.x_port, NS_WILDCARD); if (nsp) { if(nsp->nsp_pcb) (void) spp_drop((struct sppcb *)nsp->nsp_pcb, (int)nsctlerrmap[cmd]); else (void) idp_drop(nsp, (int)nsctlerrmap[cmd]); } break; case NS_ERR_FULLUP: ns_pcbnotify(na, 0, spp_quench, (long) 0); } } /* * When a source quench is received, close congestion window * to one packet. We will gradually open it again as we proceed. */ spp_quench(nsp) struct nspcb *nsp; { struct sppcb *cb = nstosppcb(nsp); if (cb) cb->s_cwnd = CUNIT; } #ifdef notdef int spp_fixmtu(nsp) register struct nspcb *nsp; { register struct sppcb *cb = (struct sppcb *)(nsp->nsp_pcb); register struct mbuf *m; register struct spidp *si; struct ns_errp *ep; struct sockbuf *sb; int badseq, len; struct mbuf *firstbad, *m0; if (cb) { /* * The notification that we have sent * too much is bad news -- we will * have to go through queued up so far * splitting ones which are too big and * reassigning sequence numbers and checksums. * we should then retransmit all packets from * one above the offending packet to the last one * we had sent (or our allocation) * then the offending one so that the any queued * data at our destination will be discarded. */ ep = (struct ns_errp *)nsp->nsp_notify_param; sb = &nsp->nsp_socket->so_snd; cb->s_mtu = ep->ns_err_param; badseq = SI(&ep->ns_err_idp)->si_seq; for (m = sb->sb_mb; m; m = m->m_act) { si = mtod(m, struct spidp *); if (si->si_seq == badseq) break; } if (m == 0) return; firstbad = m; /*for (;;) {*/ /* calculate length */ for (m0 = m, len = 0; m ; m = m->m_next) len += m->m_len; if (len > cb->s_mtu) { } /* FINISH THIS } */ } } #endif spp_output(cb, m0) register struct sppcb *cb; struct mbuf *m0; { struct socket *so = cb->s_nspcb->nsp_socket; register struct mbuf *m; register struct spidp *si = (struct spidp *) 0; register struct sockbuf *sb = &so->so_snd; int len = 0, win, rcv_win; short span, off; u_short alo; int error = 0, idle, sendalot; struct mbuf *mprev; extern int idpcksum; if (m0) { int mtu = cb->s_mtu; int datalen; /* * Make sure that packet isn't too big. */ for (m = m0; m ; m = m->m_next) { mprev = m; len += m->m_len; } datalen = (cb->s_flags & SF_HO) ? len - sizeof (struct sphdr) : len; if (datalen > mtu) { if (cb->s_flags & SF_PI) { m_freem(m0); return (EMSGSIZE); } else { int oldEM = cb->s_cc & SP_EM; cb->s_cc &= ~SP_EM; while (len > mtu) { m = m_copy(m0, 0, mtu); if (m == NULL) { error = ENOBUFS; goto bad_copy; } error = spp_output(cb, m); if (error) { bad_copy: cb->s_cc |= oldEM; m_freem(m0); return(error); } m_adj(m0, mtu); len -= mtu; } cb->s_cc |= oldEM; } } /* * Force length even, by adding a "garbage byte" if * necessary. */ if (len & 1) { m = mprev; if (m->m_len + m->m_off < MMAXOFF) m->m_len++; else { struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA); if (m1 == 0) { m_freem(m0); return (ENOBUFS); } m1->m_len = 1; m1->m_off = MMAXOFF - 1; m->m_next = m1; } } m = m_get(M_DONTWAIT, MT_HEADER); if (m == 0) { m_freem(m0); return (ENOBUFS); } /* * Fill in mbuf with extended SP header * and addresses and length put into network format. * Long align so prepended ip headers will work on Gould. */ m->m_off = MMAXOFF - sizeof (struct spidp) - 2; m->m_len = sizeof (struct spidp); m->m_next = m0; si = mtod(m, struct spidp *); si->si_i = *cb->s_idp; si->si_s = cb->s_shdr; if ((cb->s_flags & SF_PI) && (cb->s_flags & SF_HO)) { register struct sphdr *sh; if (m0->m_len < sizeof (*sh)) { if((m0 = m_pullup(m0, sizeof(*sh))) == NULL) { (void) m_free(m); m_freem(m0); return (EINVAL); } m->m_next = m0; } sh = mtod(m0, struct sphdr *); si->si_dt = sh->sp_dt; si->si_cc |= sh->sp_cc & SP_EM; m0->m_len -= sizeof (*sh); m0->m_off += sizeof (*sh); len -= sizeof (*sh); } len += sizeof(*si); if (cb->s_oobflags & SF_SOOB) { /* * Per jqj@cornell: * make sure OB packets convey exactly 1 byte. * If the packet is 1 byte or larger, we * have already guaranted there to be at least * one garbage byte for the checksum, and * extra bytes shouldn't hurt! */ if (len > sizeof(*si)) { si->si_cc |= SP_OB; len = (1 + sizeof(*si)); } } si->si_len = htons((u_short)len); /* * queue stuff up for output */ sbappendrecord(sb, m); cb->s_seq++; } idle = (cb->s_smax == (cb->s_rack - 1)); again: sendalot = 0; off = cb->s_snxt - cb->s_rack; win = MIN(cb->s_swnd, (cb->s_cwnd/CUNIT)); /* * If in persist timeout with window of 0, send a probe. * Otherwise, if window is small but nonzero * and timer expired, send what we can and go into * transmit state. */ if (cb->s_force == 1 + SPPT_PERSIST) { if (win != 0) { cb->s_timer[SPPT_PERSIST] = 0; cb->s_rxtshift = 0; } } span = cb->s_seq - cb->s_rack; len = MIN(span, win) - off; if (len < 0) { /* * Window shrank after we went into it. * If window shrank to 0, cancel pending * restransmission and pull s_snxt back * to (closed) window. We will enter persist * state below. If the widndow didn't close completely, * just wait for an ACK. */ len = 0; if (win == 0) { cb->s_timer[SPPT_REXMT] = 0; cb->s_snxt = cb->s_rack; } } if (len > 1) sendalot = 1; rcv_win = sbspace(&so->so_rcv); /* * Send if we owe peer an ACK. */ if (cb->s_oobflags & SF_SOOB) { /* * must transmit this out of band packet */ cb->s_oobflags &= ~ SF_SOOB; sendalot = 1; sppstat.spps_sndurg++; goto found; } if (cb->s_flags & SF_ACKNOW) goto send; if (cb->s_state < TCPS_ESTABLISHED) goto send; /* * Silly window can't happen in spp. * Code from tcp deleted. */ if (len) goto send; /* * Compare available window to amount of window * known to peer (as advertised window less * next expected input.) If the difference is at least two * packets or at least 35% of the mximum possible window, * then want to send a window update to peer. */ if (rcv_win > 0) { u_short delta = 1 + cb->s_alo - cb->s_ack; int adv = rcv_win - (delta * cb->s_mtu); if ((so->so_rcv.sb_cc == 0 && adv >= (2 * cb->s_mtu)) || (100 * adv / so->so_rcv.sb_hiwat >= 35)) { sppstat.spps_sndwinup++; cb->s_flags |= SF_ACKNOW; goto send; } } /* * Many comments from tcp_output.c are appropriate here * including . . . * If send window is too small, there is data to transmit, and no * retransmit or persist is pending, then go to persist state. * If nothing happens soon, send when timer expires: * if window is nonzero, transmit what we can, * otherwise send a probe. */ if (so->so_snd.sb_cc && cb->s_timer[SPPT_REXMT] == 0 && cb->s_timer[SPPT_PERSIST] == 0) { cb->s_rxtshift = 0; spp_setpersist(cb); } /* * No reason to send a packet, just return. */ cb->s_outx = 1; return (0); send: /* * Find requested packet. */ si = 0; if (len > 0) { cb->s_want = cb->s_snxt; for (m = sb->sb_mb; m; m = m->m_act) { si = mtod(m, struct spidp *); if (SSEQ_LEQ(cb->s_snxt, si->si_seq)) break; } found: if (si) { if (si->si_seq == cb->s_snxt) cb->s_snxt++; else sppstat.spps_sndvoid++, si = 0; } } /* * update window */ if (rcv_win < 0) rcv_win = 0; alo = cb->s_ack - 1 + (rcv_win / ((short)cb->s_mtu)); if (SSEQ_LT(alo, cb->s_alo)) alo = cb->s_alo; if (si) { /* * must make a copy of this packet for * idp_output to monkey with */ m = m_copy(dtom(si), 0, (int)M_COPYALL); if (m == NULL) { return (ENOBUFS); } m0 = m; si = mtod(m, struct spidp *); if (SSEQ_LT(si->si_seq, cb->s_smax)) sppstat.spps_sndrexmitpack++; else sppstat.spps_sndpack++; } else if (cb->s_force || cb->s_flags & SF_ACKNOW) { /* * Must send an acknowledgement or a probe */ if (cb->s_force) sppstat.spps_sndprobe++; if (cb->s_flags & SF_ACKNOW) sppstat.spps_sndacks++; m = m_get(M_DONTWAIT, MT_HEADER); if (m == 0) { return (ENOBUFS); } /* * Fill in mbuf with extended SP header * and addresses and length put into network format. * Allign beginning of packet to long to prepend * ifp's on loopback, or NSIP encaspulation for fussy cpu's. */ m->m_off = MMAXOFF - sizeof (struct spidp) - 2; m->m_len = sizeof (*si); m->m_next = 0; si = mtod(m, struct spidp *); si->si_i = *cb->s_idp; si->si_s = cb->s_shdr; si->si_seq = cb->s_smax + 1; si->si_len = htons(sizeof (*si)); si->si_cc |= SP_SP; } else { cb->s_outx = 3; if (so->so_options & SO_DEBUG || traceallspps) spp_trace(SA_OUTPUT, cb->s_state, cb, si, 0); return (0); } /* * Stuff checksum and output datagram. */ if ((si->si_cc & SP_SP) == 0) { if (cb->s_force != (1 + SPPT_PERSIST) || cb->s_timer[SPPT_PERSIST] == 0) { /* * If this is a new packet and we are not currently * timing anything, time this one. */ if (SSEQ_LT(cb->s_smax, si->si_seq)) { cb->s_smax = si->si_seq; if (cb->s_rtt == 0) { sppstat.spps_segstimed++; cb->s_rtseq = si->si_seq; cb->s_rtt = 1; } } /* * Set rexmt timer if not currently set, * Initial value for retransmit timer is smoothed * round-trip time + 2 * round-trip time variance. * Initialize shift counter which is used for backoff * of retransmit time. */ if (cb->s_timer[SPPT_REXMT] == 0 && cb->s_snxt != cb->s_rack) { cb->s_timer[SPPT_REXMT] = cb->s_rxtcur; if (cb->s_timer[SPPT_PERSIST]) { cb->s_timer[SPPT_PERSIST] = 0; cb->s_rxtshift = 0; } } } else if (SSEQ_LT(cb->s_smax, si->si_seq)) { cb->s_smax = si->si_seq; } } else if (cb->s_state < TCPS_ESTABLISHED) { if (cb->s_rtt == 0) cb->s_rtt = 1; /* Time initial handshake */ if (cb->s_timer[SPPT_REXMT] == 0) cb->s_timer[SPPT_REXMT] = cb->s_rxtcur; } { /* * Do not request acks when we ack their data packets or * when we do a gratuitous window update. */ if (((si->si_cc & SP_SP) == 0) || cb->s_force) si->si_cc |= SP_SA; si->si_seq = htons(si->si_seq); si->si_alo = htons(alo); si->si_ack = htons(cb->s_ack); if (idpcksum) { si->si_sum = 0; len = ntohs(si->si_len); if (len & 1) len++; si->si_sum = ns_cksum(dtom(si), len); } else si->si_sum = 0xffff; cb->s_outx = 4; if (so->so_options & SO_DEBUG || traceallspps) spp_trace(SA_OUTPUT, cb->s_state, cb, si, 0); if (so->so_options & SO_DONTROUTE) error = ns_output(m, (struct route *)0, NS_ROUTETOIF); else error = ns_output(m, &cb->s_nspcb->nsp_route, 0); } if (error) { return (error); } sppstat.spps_sndtotal++; /* * Data sent (as far as we can tell). * If this advertises a larger window than any other segment, * then remember the size of the advertized window. * Any pending ACK has now been sent. */ cb->s_force = 0; cb->s_flags &= ~(SF_ACKNOW|SF_DELACK); if (SSEQ_GT(alo, cb->s_alo)) cb->s_alo = alo; if (sendalot) goto again; cb->s_outx = 5; return (0); } int spp_do_persist_panics = 0; spp_setpersist(cb) register struct sppcb *cb; { register t = ((cb->s_srtt >> 2) + cb->s_rttvar) >> 1; extern int spp_backoff[]; if (cb->s_timer[SPPT_REXMT] && spp_do_persist_panics) panic("spp_output REXMT"); /* * Start/restart persistance timer. */ SPPT_RANGESET(cb->s_timer[SPPT_PERSIST], t*spp_backoff[cb->s_rxtshift], SPPTV_PERSMIN, SPPTV_PERSMAX); if (cb->s_rxtshift < SPP_MAXRXTSHIFT) cb->s_rxtshift++; } /*ARGSUSED*/ spp_ctloutput(req, so, level, name, value) int req; struct socket *so; int name; struct mbuf **value; { register struct mbuf *m; struct nspcb *nsp = sotonspcb(so); register struct sppcb *cb; int mask, error = 0; if (level != NSPROTO_SPP) { /* This will have to be changed when we do more general stacking of protocols */ return (idp_ctloutput(req, so, level, name, value)); } if (nsp == NULL) { error = EINVAL; goto release; } else cb = nstosppcb(nsp); switch (req) { case PRCO_GETOPT: if (value == NULL) return (EINVAL); m = m_get(M_DONTWAIT, MT_DATA); if (m == NULL) return (ENOBUFS); switch (name) { case SO_HEADERS_ON_INPUT: mask = SF_HI; goto get_flags; case SO_HEADERS_ON_OUTPUT: mask = SF_HO; get_flags: m->m_len = sizeof(short); m->m_off = MMAXOFF - sizeof(short); *mtod(m, short *) = cb->s_flags & mask; break; case SO_MTU: m->m_len = sizeof(u_short); m->m_off = MMAXOFF - sizeof(short); *mtod(m, short *) = cb->s_mtu; break; case SO_LAST_HEADER: m->m_len = sizeof(struct sphdr); m->m_off = MMAXOFF - sizeof(struct sphdr); *mtod(m, struct sphdr *) = cb->s_rhdr; break; case SO_DEFAULT_HEADERS: m->m_len = sizeof(struct spidp); m->m_off = MMAXOFF - sizeof(struct sphdr); *mtod(m, struct sphdr *) = cb->s_shdr; break; default: error = EINVAL; } *value = m; break; case PRCO_SETOPT: if (value == 0 || *value == 0) { error = EINVAL; break; } switch (name) { int *ok; case SO_HEADERS_ON_INPUT: mask = SF_HI; goto set_head; case SO_HEADERS_ON_OUTPUT: mask = SF_HO; set_head: if (cb->s_flags & SF_PI) { ok = mtod(*value, int *); if (*ok) cb->s_flags |= mask; else cb->s_flags &= ~mask; } else error = EINVAL; break; case SO_MTU: cb->s_mtu = *(mtod(*value, u_short *)); break; case SO_DEFAULT_HEADERS: { register struct sphdr *sp = mtod(*value, struct sphdr *); cb->s_dt = sp->sp_dt; cb->s_cc = sp->sp_cc & SP_EM; } break; default: error = EINVAL; } m_freem(*value); break; } release: return (error); } /*ARGSUSED*/ spp_usrreq(so, req, m, nam, rights) struct socket *so; int req; struct mbuf *m, *nam, *rights; { struct nspcb *nsp = sotonspcb(so); register struct sppcb *cb; int s = splnet(); int error = 0, ostate; struct mbuf *mm; register struct sockbuf *sb; if (req == PRU_CONTROL) return (ns_control(so, (int)m, (caddr_t)nam, (struct ifnet *)rights)); if (rights && rights->m_len) { error = EINVAL; goto release; } if (nsp == NULL) { if (req != PRU_ATTACH) { error = EINVAL; goto release; } } else cb = nstosppcb(nsp); ostate = cb ? cb->s_state : 0; switch (req) { case PRU_ATTACH: if (nsp != NULL) { error = EISCONN; break; } error = ns_pcballoc(so, &nspcb); if (error) break; error = soreserve(so, 3072, 3072); if (error) break; nsp = sotonspcb(so); mm = m_getclr(M_DONTWAIT, MT_PCB); sb = &so->so_snd; if (mm == NULL) { error = ENOBUFS; break; } cb = mtod(mm, struct sppcb *); mm = m_getclr(M_DONTWAIT, MT_HEADER); if (mm == NULL) { m_free(dtom(m)); error = ENOBUFS; break; } cb->s_idp = mtod(mm, struct idp *); cb->s_state = TCPS_LISTEN; cb->s_smax = -1; cb->s_swl1 = -1; cb->s_q.si_next = cb->s_q.si_prev = &cb->s_q; cb->s_nspcb = nsp; cb->s_mtu = 576 - sizeof (struct spidp); cb->s_cwnd = sbspace(sb) * CUNIT / cb->s_mtu; cb->s_ssthresh = cb->s_cwnd; cb->s_cwmx = sb->sb_mbmax * CUNIT / (2 * sizeof (struct spidp)); /* Above is recomputed when connecting to account for changed buffering or mtu's */ cb->s_rtt = SPPTV_SRTTBASE; cb->s_rttvar = SPPTV_SRTTDFLT << 2; SPPT_RANGESET(cb->s_rxtcur, ((SPPTV_SRTTBASE >> 2) + (SPPTV_SRTTDFLT << 2)) >> 1, SPPTV_MIN, SPPTV_REXMTMAX); nsp->nsp_pcb = (caddr_t) cb; break; case PRU_DETACH: if (nsp == NULL) { error = ENOTCONN; break; } if (cb->s_state > TCPS_LISTEN) cb = spp_disconnect(cb); else cb = spp_close(cb); break; case PRU_BIND: error = ns_pcbbind(nsp, nam); break; case PRU_LISTEN: if (nsp->nsp_lport == 0) error = ns_pcbbind(nsp, (struct mbuf *)0); if (error == 0) cb->s_state = TCPS_LISTEN; break; /* * Initiate connection to peer. * Enter SYN_SENT state, and mark socket as connecting. * Start keep-alive timer, setup prototype header, * Send initial system packet requesting connection. */ case PRU_CONNECT: if (nsp->nsp_lport == 0) { error = ns_pcbbind(nsp, (struct mbuf *)0); if (error) break; } error = ns_pcbconnect(nsp, nam); if (error) break; soisconnecting(so); sppstat.spps_connattempt++; cb->s_state = TCPS_SYN_SENT; cb->s_did = 0; spp_template(cb); cb->s_timer[SPPT_KEEP] = SPPTV_KEEP; cb->s_force = 1 + SPPTV_KEEP; /* * Other party is required to respond to * the port I send from, but he is not * required to answer from where I am sending to, * so allow wildcarding. * original port I am sending to is still saved in * cb->s_dport. */ nsp->nsp_fport = 0; error = spp_output(cb, (struct mbuf *) 0); break; case PRU_CONNECT2: error = EOPNOTSUPP; break; /* * We may decide later to implement connection closing * handshaking at the spp level optionally. * here is the hook to do it: */ case PRU_DISCONNECT: cb = spp_disconnect(cb); break; /* * Accept a connection. Essentially all the work is * done at higher levels; just return the address * of the peer, storing through addr. */ case PRU_ACCEPT: { struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *); nam->m_len = sizeof (struct sockaddr_ns); sns->sns_family = AF_NS; sns->sns_addr = nsp->nsp_faddr; break; } case PRU_SHUTDOWN: socantsendmore(so); cb = spp_usrclosed(cb); if (cb) error = spp_output(cb, (struct mbuf *) 0); break; /* * After a receive, possibly send acknowledgment * updating allocation. */ case PRU_RCVD: cb->s_flags |= SF_RVD; (void) spp_output(cb, (struct mbuf *) 0); cb->s_flags &= ~SF_RVD; break; case PRU_ABORT: (void) spp_drop(cb, ECONNABORTED); break; case PRU_SENSE: case PRU_CONTROL: m = NULL; error = EOPNOTSUPP; break; case PRU_RCVOOB: if ((cb->s_oobflags & SF_IOOB) || so->so_oobmark || (so->so_state & SS_RCVATMARK)) { m->m_len = 1; *mtod(m, caddr_t) = cb->s_iobc; break; } error = EINVAL; break; case PRU_SENDOOB: if (sbspace(&so->so_snd) < -512) { error = ENOBUFS; break; } cb->s_oobflags |= SF_SOOB; /* fall into */ case PRU_SEND: error = spp_output(cb, m); m = NULL; break; case PRU_SOCKADDR: ns_setsockaddr(nsp, nam); break; case PRU_PEERADDR: ns_setpeeraddr(nsp, nam); break; case PRU_SLOWTIMO: cb = spp_timers(cb, (int)nam); req |= ((int)nam) << 8; break; case PRU_FASTTIMO: case PRU_PROTORCV: case PRU_PROTOSEND: error = EOPNOTSUPP; break; default: panic("sp_usrreq"); } if (cb && (so->so_options & SO_DEBUG || traceallspps)) spp_trace(SA_USER, (u_char)ostate, cb, (struct spidp *)0, req); release: if (m != NULL) m_freem(m); splx(s); return (error); } spp_usrreq_sp(so, req, m, nam, rights) struct socket *so; int req; struct mbuf *m, *nam, *rights; { int error = spp_usrreq(so, req, m, nam, rights); if (req == PRU_ATTACH && error == 0) { struct nspcb *nsp = sotonspcb(so); ((struct sppcb *)nsp->nsp_pcb)->s_flags |= (SF_HI | SF_HO | SF_PI); } return (error); } /* * Create template to be used to send spp packets on a connection. * Called after host entry created, fills * in a skeletal spp header (choosing connection id), * minimizing the amount of work necessary when the connection is used. */ spp_template(cb) register struct sppcb *cb; { register struct nspcb *nsp = cb->s_nspcb; register struct idp *idp = cb->s_idp; register struct sockbuf *sb = &(nsp->nsp_socket->so_snd); idp->idp_pt = NSPROTO_SPP; idp->idp_sna = nsp->nsp_laddr; idp->idp_dna = nsp->nsp_faddr; cb->s_sid = htons(spp_iss); spp_iss += SPP_ISSINCR/2; cb->s_alo = 1; cb->s_cwnd = (sbspace(sb) * CUNIT) / cb->s_mtu; cb->s_ssthresh = cb->s_cwnd; /* Try to expand fast to full complement of large packets */ cb->s_cwmx = (sb->sb_mbmax * CUNIT) / (2 * sizeof(struct spidp)); cb->s_cwmx = MAX(cb->s_cwmx, cb->s_cwnd); /* But allow for lots of little packets as well */ } /* * Close a SPIP control block: * discard spp control block itself * discard ns protocol control block * wake up any sleepers */ struct sppcb * spp_close(cb) register struct sppcb *cb; { register struct spidp_q *s; struct nspcb *nsp = cb->s_nspcb; struct socket *so = nsp->nsp_socket; register struct mbuf *m; s = cb->s_q.si_next; while (s != &(cb->s_q)) { s = s->si_next; m = dtom(s->si_prev); remque(s->si_prev); m_freem(m); } (void) m_free(dtom(cb->s_idp)); (void) m_free(dtom(cb)); nsp->nsp_pcb = 0; soisdisconnected(so); ns_pcbdetach(nsp); sppstat.spps_closed++; return ((struct sppcb *)0); } /* * Someday we may do level 3 handshaking * to close a connection or send a xerox style error. * For now, just close. */ struct sppcb * spp_usrclosed(cb) register struct sppcb *cb; { return (spp_close(cb)); } struct sppcb * spp_disconnect(cb) register struct sppcb *cb; { return (spp_close(cb)); } /* * Drop connection, reporting * the specified error. */ struct sppcb * spp_drop(cb, errno) register struct sppcb *cb; int errno; { struct socket *so = cb->s_nspcb->nsp_socket; /* * someday, in the xerox world * we will generate error protocol packets * announcing that the socket has gone away. */ if (TCPS_HAVERCVDSYN(cb->s_state)) { sppstat.spps_drops++; cb->s_state = TCPS_CLOSED; /*(void) tcp_output(cb);*/ } else sppstat.spps_conndrops++; so->so_error = errno; return (spp_close(cb)); } spp_abort(nsp) struct nspcb *nsp; { (void) spp_close((struct sppcb *)nsp->nsp_pcb); } int spp_backoff[SPP_MAXRXTSHIFT+1] = { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 }; /* * Fast timeout routine for processing delayed acks */ spp_fasttimo() { register struct nspcb *nsp; register struct sppcb *cb; int s = splnet(); nsp = nspcb.nsp_next; if (nsp) for (; nsp != &nspcb; nsp = nsp->nsp_next) if ((cb = (struct sppcb *)nsp->nsp_pcb) && (cb->s_flags & SF_DELACK)) { cb->s_flags &= ~SF_DELACK; cb->s_flags |= SF_ACKNOW; sppstat.spps_delack++; (void) spp_output(cb, (struct mbuf *) 0); } splx(s); } /* * spp protocol timeout routine called every 500 ms. * Updates the timers in all active pcb's and * causes finite state machine actions if timers expire. */ spp_slowtimo() { register struct nspcb *ip, *ipnxt; register struct sppcb *cb; int s = splnet(); register int i; /* * Search through tcb's and update active timers. */ ip = nspcb.nsp_next; if (ip == 0) { splx(s); return; } while (ip != &nspcb) { cb = nstosppcb(ip); ipnxt = ip->nsp_next; if (cb == 0) goto tpgone; for (i = 0; i < SPPT_NTIMERS; i++) { if (cb->s_timer[i] && --cb->s_timer[i] == 0) { (void) spp_usrreq(cb->s_nspcb->nsp_socket, PRU_SLOWTIMO, (struct mbuf *)0, (struct mbuf *)i, (struct mbuf *)0); if (ipnxt->nsp_prev != ip) goto tpgone; } } cb->s_idle++; if (cb->s_rtt) cb->s_rtt++; tpgone: ip = ipnxt; } spp_iss += SPP_ISSINCR/PR_SLOWHZ; /* increment iss */ splx(s); } /* * SPP timer processing. */ struct sppcb * spp_timers(cb, timer) register struct sppcb *cb; int timer; { long rexmt; int win; cb->s_force = 1 + timer; switch (timer) { /* * 2 MSL timeout in shutdown went off. TCP deletes connection * control block. */ case SPPT_2MSL: printf("spp: SPPT_2MSL went off for no reason\n"); cb->s_timer[timer] = 0; break; /* * Retransmission timer went off. Message has not * been acked within retransmit interval. Back off * to a longer retransmit interval and retransmit one packet. */ case SPPT_REXMT: if (++cb->s_rxtshift > SPP_MAXRXTSHIFT) { cb->s_rxtshift = SPP_MAXRXTSHIFT; sppstat.spps_timeoutdrop++; cb = spp_drop(cb, ETIMEDOUT); break; } sppstat.spps_rexmttimeo++; rexmt = ((cb->s_srtt >> 2) + cb->s_rttvar) >> 1; rexmt *= spp_backoff[cb->s_rxtshift]; SPPT_RANGESET(cb->s_rxtcur, rexmt, SPPTV_MIN, SPPTV_REXMTMAX); cb->s_timer[SPPT_REXMT] = cb->s_rxtcur; /* * If we have backed off fairly far, our srtt * estimate is probably bogus. Clobber it * so we'll take the next rtt measurement as our srtt; * move the current srtt into rttvar to keep the current * retransmit times until then. */ if (cb->s_rxtshift > SPP_MAXRXTSHIFT / 4 ) { cb->s_rttvar += (cb->s_srtt >> 2); cb->s_srtt = 0; } cb->s_snxt = cb->s_rack; /* * If timing a packet, stop the timer. */ cb->s_rtt = 0; /* * See very long discussion in tcp_timer.c about congestion * window and sstrhesh */ win = MIN(cb->s_swnd, (cb->s_cwnd/CUNIT)) / 2; if (win < 2) win = 2; cb->s_cwnd = CUNIT; cb->s_ssthresh = win * CUNIT; (void) spp_output(cb, (struct mbuf *) 0); break; /* * Persistance timer into zero window. * Force a probe to be sent. */ case SPPT_PERSIST: sppstat.spps_persisttimeo++; spp_setpersist(cb); (void) spp_output(cb, (struct mbuf *) 0); break; /* * Keep-alive timer went off; send something * or drop connection if idle for too long. */ case SPPT_KEEP: sppstat.spps_keeptimeo++; if (cb->s_state < TCPS_ESTABLISHED) goto dropit; if (cb->s_nspcb->nsp_socket->so_options & SO_KEEPALIVE) { if (cb->s_idle >= SPPTV_MAXIDLE) goto dropit; sppstat.spps_keepprobe++; (void) spp_output(cb, (struct mbuf *) 0); } else cb->s_idle = 0; cb->s_timer[SPPT_KEEP] = SPPTV_KEEP; break; dropit: sppstat.spps_keepdrops++; cb = spp_drop(cb, ETIMEDOUT); break; } return (cb); } #ifndef lint int SppcbSize = sizeof (struct sppcb); int NspcbSize = sizeof (struct nspcb); #endif lint #endif V_SRTTDFLT << 2)) >> 1, SPPTV_MIN, SPPTV_REXMTMAX); nsp->nsp_pcb sys/netns/spp_timer.h 640 12 0 7572 4235474015 10163 /* * Copyright (c) 1982, 1986, 1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)spp_timer.h 7.1 (Berkeley) 3/12/88 */ /* * Definitions of the SPP timers. These timers are counted * down PR_SLOWHZ times a second. */ #define SPPT_NTIMERS 4 #define SPPT_REXMT 0 /* retransmit */ #define SPPT_PERSIST 1 /* retransmit persistance */ #define SPPT_KEEP 2 /* keep alive */ #define SPPT_2MSL 3 /* 2*msl quiet time timer */ /* * The SPPT_REXMT timer is used to force retransmissions. * The SPP has the SPPT_REXMT timer set whenever segments * have been sent for which ACKs are expected but not yet * received. If an ACK is received which advances tp->snd_una, * then the retransmit timer is cleared (if there are no more * outstanding segments) or reset to the base value (if there * are more ACKs expected). Whenever the retransmit timer goes off, * we retransmit one unacknowledged segment, and do a backoff * on the retransmit timer. * * The SPPT_PERSIST timer is used to keep window size information * flowing even if the window goes shut. If all previous transmissions * have been acknowledged (so that there are no retransmissions in progress), * and the window is too small to bother sending anything, then we start * the SPPT_PERSIST timer. When it expires, if the window is nonzero, * we go to transmit state. Otherwise, at intervals send a single byte * into the peer's window to force him to update our window information. * We do this at most as often as SPPT_PERSMIN time intervals, * but no more frequently than the current estimate of round-trip * packet time. The SPPT_PERSIST timer is cleared whenever we receive * a window update from the peer. * * The SPPT_KEEP timer is used to keep connections alive. If an * connection is idle (no segments received) for SPPTV_KEEP amount of time, * but not yet established, then we drop the connection. If the connection * is established, then we force the peer to send us a segment by sending: * * This segment is (deliberately) outside the window, and should elicit * an ack segment in response from the peer. If, despite the SPPT_KEEP * initiated segments we cannot elicit a response from a peer in SPPT_MAXIDLE * amount of time, then we drop the connection. */ #define SPP_TTL 30 /* default time to live for SPP segs */ /* * Time constants. */ #define SPPTV_MSL ( 15*PR_SLOWHZ) /* max seg lifetime */ #define SPPTV_SRTTBASE 0 /* base roundtrip time; if 0, no idea yet */ #define SPPTV_SRTTDFLT ( 3*PR_SLOWHZ) /* assumed RTT if no info */ #define SPPTV_PERSMIN ( 5*PR_SLOWHZ) /* retransmit persistance */ #define SPPTV_PERSMAX ( 60*PR_SLOWHZ) /* maximum persist interval */ #define SPPTV_KEEP ( 75*PR_SLOWHZ) /* keep alive - 75 secs */ #define SPPTV_MAXIDLE ( 8*SPPTV_KEEP) /* maximum allowable idle time before drop conn */ #define SPPTV_MIN ( 1*PR_SLOWHZ) /* minimum allowable value */ #define SPPTV_REXMTMAX ( 64*PR_SLOWHZ) /* max allowable REXMT value */ #define SPP_LINGERTIME 120 /* linger at most 2 minutes */ #define SPP_MAXRXTSHIFT 12 /* maximum retransmits */ #ifdef SPPTIMERS char *spptimers[] = { "REXMT", "PERSIST", "KEEP", "2MSL" }; #endif /* * Force a time value to be in a certain range. */ #define SPPT_RANGESET(tv, value, tvmin, tvmax) { \ (tv) = (value); \ if ((tv) < (tvmin)) \ (tv) = (tvmin); \ else if ((tv) > (tvmax)) \ (tv) = (tvmax); \ } #ifdef SUPERVISOR extern int spp_backoff[]; #endif case SPPT_KEEP: sppstat.spps_keeptimeo++; if (cb->s_state < TCPS_ESTABLISHED) goto dropit; if (cb->s_nspcb->nsp_socket->so_osys/pdp/ 755 0 12 0 6016521566 5353 sys/pdp/conf.c 440 0 12 26577 6005073467 6564 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)conf.c 2.8 (2.11BSD GTE) 1995/07/24 */ #include "param.h" #include "conf.h" #include "buf.h" #include "time.h" #include "ioctl.h" #include "resource.h" #include "inode.h" #include "proc.h" #include "clist.h" #include "tty.h" int nulldev(); int nodev(); int rawrw(); #include "rk.h" #if NRK > 0 int rkopen(), rkstrategy(); daddr_t rksize(); #define rkclose nulldev #else #define rkopen nodev #define rkclose nodev #define rkstrategy nodev #define rksize NULL #endif #include "tm.h" #if NTM > 0 int tmopen(), tmclose(), tmioctl(), tmstrategy(); #else #define tmopen nodev #define tmclose nodev #define tmioctl nodev #define tmstrategy nodev #endif #include "hk.h" #if NHK > 0 int hkopen(), hkstrategy(), hkroot(); daddr_t hksize(); #define hkclose nulldev #else #define hkopen nodev #define hkclose nodev #define hkroot nulldev #define hkstrategy nodev #define hksize NULL #endif #include "xp.h" #if NXPD > 0 int xpopen(), xpstrategy(), xproot(), xpclose(), xpioctl(); daddr_t xpsize(); #else #define xpopen nodev #define xpclose nodev #define xpioctl nodev #define xproot nulldev #define xpstrategy nodev #define xpsize NULL #endif #include "br.h" #if NBR > 0 int bropen(), brstrategy(), brroot(); daddr_t brsize(); #define brclose nulldev #else #define bropen nodev #define brclose nodev #define brroot nulldev #define brstrategy nodev #define brsize NULL #endif #include "ht.h" #if NHT > 0 int htopen(), htclose(), htstrategy(), htioctl(); #else #define htopen nodev #define htclose nodev #define htioctl nodev #define htstrategy nodev #endif #include "rl.h" #if NRL > 0 int rlopen(), rlstrategy(), rlroot(), rlclose(), rlioctl(); daddr_t rlsize(); #else #define rlroot nulldev #define rlopen nodev #define rlclose nodev #define rlioctl nodev #define rlstrategy nodev #define rlsize NULL #endif #include "ts.h" #if NTS > 0 int tsopen(), tsclose(), tsstrategy(), tsioctl(); #else #define tsopen nodev #define tsclose nodev #define tsioctl nodev #define tsstrategy nodev #endif #include "tms.h" #if NTMS > 0 int tmscpopen(), tmscpclose(), tmscpstrategy(), tmscpioctl(); #else #define tmscpopen nodev #define tmscpclose nodev #define tmscpioctl nodev #define tmscpstrategy nodev #endif #include "si.h" #if NSI > 0 int siopen(), sistrategy(), siroot(); daddr_t sisize(); #define siclose nulldev #else #define siopen nodev #define siclose nodev #define siroot nulldev #define sistrategy nodev #define sisize NULL #endif #include "ra.h" #if NRAC > 0 int rastrategy(), raroot(), raopen(), raclose(), raioctl(); daddr_t rasize(); #else #define raopen nodev #define raclose nodev #define raioctl nodev #define raroot nulldev #define rastrategy nodev #define rasize nodev #endif #include "rx.h" #if NRX > 0 int rxopen(), rxstrategy(), rxioctl(); #define rxclose nulldev #else #define rxopen nodev #define rxclose nodev #define rxstrategy nodev #define rxioctl nodev #endif #include "ram.h" #if NRAM > 0 int ramopen(), ramstrategy(); #define ramclose nulldev #else #define ramopen nodev #define ramclose nodev #define ramstrategy nodev #endif struct bdevsw bdevsw[] = { /* ht = 0 */ htopen, htclose, htstrategy, nulldev, NULL, B_TAPE, /* tm = 1 */ tmopen, tmclose, tmstrategy, nulldev, NULL, B_TAPE, /* ts = 2 */ tsopen, tsclose, tsstrategy, nulldev, NULL, B_TAPE, /* ram = 3 */ ramopen, ramclose, ramstrategy, nulldev, NULL, 0, /* hk = 4 */ hkopen, hkclose, hkstrategy, hkroot, hksize, 0, /* ra = 5 */ raopen, raclose, rastrategy, raroot, rasize, 0, /* rk = 6 */ rkopen, rkclose, rkstrategy, nulldev, rksize, 0, /* rl = 7 */ rlopen, rlclose, rlstrategy, rlroot, rlsize, 0, /* rx = 8 */ rxopen, rxclose, rxstrategy, nulldev, NULL, 0, /* si = 9 */ siopen, siclose, sistrategy, siroot, sisize, 0, /* xp = 10 */ xpopen, xpclose, xpstrategy, xproot, xpsize, 0, /* br = 11 */ bropen, brclose, brstrategy, brroot, brsize, 0, /* tmscp = 12 (tu81/tk50) */ tmscpopen, tmscpclose, tmscpstrategy, nulldev, NULL, B_TAPE, }; int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]); int cnopen(), cnclose(), cnread(), cnwrite(), cnioctl(); extern struct tty cons[]; #include "lp.h" #if NLP > 0 int lpopen(), lpclose(), lpwrite(); #else #define lpopen nodev #define lpclose nodev #define lpwrite nodev #endif #include "dh.h" #if NDH > 0 int dhopen(), dhclose(), dhread(), dhwrite(), dhioctl(), dhstop(); extern struct tty dh11[]; #else #define dhopen nodev #define dhclose nodev #define dhread nodev #define dhwrite nodev #define dhioctl nodev #define dhstop nodev #define dh11 ((struct tty *) NULL) #endif #include "dz.h" #if NDZ > 0 int dzopen(), dzclose(), dzread(), dzwrite(), dzioctl(); int dzstop(); extern struct tty dz_tty[]; #else #define dzopen nodev #define dzclose nodev #define dzread nodev #define dzwrite nodev #define dzioctl nodev #define dzstop nodev #define dz_tty ((struct tty *) NULL) #endif #include "pty.h" #if NPTY > 0 int ptsopen(), ptsclose(), ptsread(), ptswrite(), ptsstop(); int ptcopen(), ptcclose(), ptcread(), ptcwrite(), ptyioctl(); int ptcselect(); extern struct tty pt_tty[]; #else #define ptsopen nodev #define ptsclose nodev #define ptsread nodev #define ptswrite nodev #define ptsstop nodev #define ptcopen nodev #define ptcclose nodev #define ptcread nodev #define ptcwrite nodev #define ptyioctl nodev #define ptcselect nodev #define pt_tty ((struct tty *)NULL) #endif #include "dr.h" #if NDR > 0 int dropen(), drclose(), drioctl(), drstrategy(); #else #define dropen nodev #define drclose nodev #define drioctl nodev #define drstrategy nodev #endif #include "dhu.h" #if NDHU > 0 int dhuopen(), dhuclose(), dhuread(), dhuwrite(), dhuioctl(), dhustop(); extern struct tty dhu_tty[]; #else #define dhuopen nodev #define dhuclose nodev #define dhuread nodev #define dhuwrite nodev #define dhuioctl nodev #define dhustop nodev #define dhu_tty ((struct tty *) NULL) #endif #include "dhv.h" #if NDHV > 0 int dhvopen(), dhvclose(), dhvread(), dhvwrite(), dhvioctl(), dhvstop(); int dhvselect(); extern struct tty dhv_tty[]; #else #define dhvopen nodev #define dhvclose nodev #define dhvread nodev #define dhvwrite nodev #define dhvioctl nodev #define dhvstop nodev #define dhvselect nodev #define dhv_tty ((struct tty *) NULL) #endif #include "dn.h" #if NDN > 0 int dnopen(), dnclose(), dnwrite(); #define dnread nodev #define dnioctl nodev #else #define dnopen nodev #define dnclose nodev #define dnread nodev #define dnwrite nodev #define dnioctl nodev #endif int logopen(), logclose(), logread(), logioctl(), logselect(); int syopen(), syread(), sywrite(), syioctl(), syselect(); int mmrw(); #define mmselect seltrue #include "ingres.h" #if NINGRES > 0 int ingres_open(), ingres_write(); #define ingres_read nodev #define ingres_ioctl nodev #define ingres_close nulldev #else #define ingres_open nodev #define ingres_close nodev #define ingres_read nodev #define ingres_write nodev #define ingres_ioctl nodev #endif int ttselect(), seltrue(); struct cdevsw cdevsw[] = { /* cn = 0 */ cnopen, cnclose, cnread, cnwrite, cnioctl, nulldev, cons, ttselect, nulldev, /* mem = 1 */ nulldev, nulldev, mmrw, mmrw, nodev, nulldev, 0, mmselect, nulldev, /* dz = 2 */ dzopen, dzclose, dzread, dzwrite, dzioctl, dzstop, dz_tty, ttselect, nulldev, /* dh = 3 */ dhopen, dhclose, dhread, dhwrite, dhioctl, dhstop, dh11, ttselect, nulldev, /* dhu = 4 */ dhuopen, dhuclose, dhuread, dhuwrite, dhuioctl, dhustop, dhu_tty, ttselect, nulldev, /* lp = 5 */ lpopen, lpclose, nodev, lpwrite, nodev, nulldev, 0, nodev, nulldev, /* ht = 6 */ htopen, htclose, rawrw, rawrw, htioctl, nulldev, 0, seltrue, htstrategy, /* tm = 7 */ tmopen, tmclose, rawrw, rawrw, tmioctl, nulldev, 0, seltrue, tmstrategy, /* ts = 8 */ tsopen, tsclose, rawrw, rawrw, tsioctl, nulldev, 0, seltrue, tsstrategy, /* tty = 9 */ syopen, nulldev, syread, sywrite, syioctl, nulldev, 0, syselect, nulldev, /* ptc = 10 */ ptcopen, ptcclose, ptcread, ptcwrite, ptyioctl, nulldev, pt_tty, ptcselect, nulldev, /* pts = 11 */ ptsopen, ptsclose, ptsread, ptswrite, ptyioctl, ptsstop, pt_tty, ttselect, nulldev, /* dr = 12 */ dropen, drclose, rawrw, rawrw, drioctl, nulldev, 0, seltrue, drstrategy, /* hk = 13 */ hkopen, hkclose, rawrw, rawrw, nodev, nulldev, 0, seltrue, hkstrategy, /* ra = 14 */ raopen, raclose, rawrw, rawrw, raioctl, nulldev, 0, seltrue, rastrategy, /* rk = 15 */ rkopen, rkclose, rawrw, rawrw, nodev, nulldev, 0, seltrue, rkstrategy, /* rl = 16 */ rlopen, rlclose, rawrw, rawrw, rlioctl, nulldev, 0, seltrue, rlstrategy, /* rx = 17 */ rxopen, rxclose, rawrw, rawrw, rxioctl, nulldev, 0, seltrue, rxstrategy, /* si = 18 */ siopen, siclose, rawrw, rawrw, nodev, nulldev, 0, seltrue, sistrategy, /* xp = 19 */ xpopen, xpclose, rawrw, rawrw, xpioctl, nulldev, 0, seltrue, xpstrategy, /* br = 20 */ bropen, brclose, rawrw, rawrw, nodev, nulldev, 0, seltrue, brstrategy, /* dn = 21 */ dnopen, dnclose, dnread, dnwrite, dnioctl, nulldev, 0, seltrue, nulldev, /* log = 22 */ logopen, logclose, logread, nodev, logioctl, nulldev, 0, logselect, nulldev, /* tmscp = 23 (tu81/tk50) */ tmscpopen, tmscpclose, rawrw, rawrw, tmscpioctl, nulldev, 0, seltrue, tmscpstrategy, /* dhv = 24 */ dhvopen, dhvclose, dhvread, dhvwrite, dhvioctl, dhvstop, dhv_tty, dhvselect, nulldev, /* ingres = 25 */ ingres_open, ingres_close, ingres_read, ingres_write, ingres_ioctl, nulldev, 0, seltrue, nulldev, }; int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]); /* * Routine that identifies /dev/mem and /dev/kmem. * * A minimal stub routine can always return 0. */ iskmemdev(dev) register dev_t dev; { if (major(dev) == 1 && (minor(dev) == 0 || minor(dev) == 1)) return (1); return (0); } /* * Routine to determine if a device is a disk. * * A minimal stub routine can always return 0. */ isdisk(dev, type) dev_t dev; register int type; { switch (major(dev)) { case 3: /* ram */ case 4: /* hk */ case 5: /* ra */ case 6: /* rk */ case 7: /* rl */ case 8: /* rx */ case 9: /* si */ case 10: /* xp */ case 11: /* br */ if (type == IFBLK) return (1); return (0); case 13: /* rhk */ case 14: /* rra */ case 15: /* rrk */ case 16: /* rrl */ case 17: /* rrx */ case 18: /* rsi */ case 19: /* rxp */ case 20: /* rbr */ if (type == IFCHR) return (1); /* fall through */ default: return (0); } /* NOTREACHED */ } #define MAXDEV 26 static char chrtoblktbl[MAXDEV] = { /* CHR */ /* BLK */ /* 0 */ NODEV, /* 1 */ NODEV, /* 2 */ NODEV, /* 3 */ NODEV, /* 4 */ NODEV, /* 5 */ NODEV, /* 6 */ 0, /* ht */ /* 7 */ 1, /* tm */ /* 8 */ 2, /* ts */ /* 9 */ NODEV, /* 10 */ NODEV, /* 11 */ NODEV, /* 12 */ NODEV, /* 13 */ 4, /* hk */ /* 14 */ 5, /* ra */ /* 15 */ 6, /* rk */ /* 16 */ 7, /* rl */ /* 17 */ 8, /* rx */ /* 18 */ 9, /* si */ /* 19 */ 10, /* xp */ /* 20 */ 11, /* br */ /* 21 */ NODEV, /* 22 */ NODEV, /* 23 */ 12, /* tmscp */ /* 24 */ NODEV, /* 25 */ NODEV }; /* * Routine to convert from character to block device number. * * A minimal stub routine can always return NODEV. */ chrtoblk(dev) register dev_t dev; { register int blkmaj; if (major(dev) >= MAXDEV || (blkmaj = chrtoblktbl[major(dev)]) == NODEV) return (NODEV); return (makedev(blkmaj, minor(dev))); } (), brroot(); daddr_t brsize(); #define brclose nulldev #else #define bropen nodev #define brclose nodev #define brroot nulldsys/pdp/psl.h 444 0 12 2522 4177375370 6414 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)psl.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * PDP program status longword */ #define PSL_C 0x00000001 /* carry bit */ #define PSL_V 0x00000002 /* overflow bit */ #define PSL_Z 0x00000004 /* zero bit */ #define PSL_N 0x00000008 /* negative bit */ #define PSL_ALLCC 0x0000000f /* all cc bits - unlikely */ #define PSL_T 0x00000010 /* trace enable bit */ #define PSL_IPL 0x000000e0 /* interrupt priority level */ #define PSL_PRVMOD 0x00003000 /* previous mode (all on is user) */ #define PSL_CURMOD 0x0000c000 /* current mode (all on is user) */ #define PSL_CURSUP 0x00004000 /* current supervisor previous kernel */ #define PSL_BR0 0x00000000 /* bus request level 0 */ #define PSL_BR1 0x00000020 /* bus request level 1 */ #define PSL_BR2 0x00000040 /* bus request level 2 */ #define PSL_BR3 0x00000060 /* bus request level 3 */ #define PSL_BR4 0x00000080 /* bus request level 4 */ #define PSL_BR5 0x000000a0 /* bus request level 5 */ #define PSL_BR6 0x000000c0 /* bus request level 6 */ #define PSL_BR7 0x000000e0 /* bus request level 7 */ #define PSL_USERSET (PSL_PRVMOD|PSL_CURMOD) #define PSL_USERCLR PSL_IPL /* must be clear in user mode */ V); return (makedev(blkmaj, minor(dev))); } (), brroot(); daddr_t brsize(); #define brclose nulldev #else #define bropen nodev #define brclose nodev #define brroot nulldsys/pdp/reg.h 444 0 12 756 4001143262 6335 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)reg.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * Location of the users' stored * registers relative to R0. * Usage is u.u_ar0[XX]. */ #define R0 (0) #define R1 (-3) #define R2 (-11) #define R3 (-10) #define R4 (-9) #define R5 (-7) #define R6 (-4) #define R7 (1) #define PC (1) #define RPS (2) cons.hs.ssys/pdp/trap.h 444 0 12 2362 4236511554 6556 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)trap.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * Trap type values */ #define T_BUSFLT 000 /* bus error */ #define T_INSTRAP 001 /* illegal instruction */ #define T_BPTTRAP 002 /* bpt/trace trap */ #define T_IOTTRAP 003 /* iot trap */ #define T_POWRFAIL 004 /* power failure */ #define T_EMTTRAP 005 /* emt trap */ #define T_SYSCALL 006 /* system call */ #define T_PIRQ 007 /* program interrupt request */ #define T_ARITHTRAP 010 /* floating point trap */ #define T_SEGFLT 011 /* segmentation fault */ #define T_PARITYFLT 012 /* parity fault */ #define T_SWITCHTRAP 014 /* process switch */ /* * T_RANDOMTRAP is used by autoconfig/do_config.c when it substitutes * the trap routine for the standard device interrupt routines when * probing a device in case the device probe routine causes an interrupt. * Ignored in trap.c */ #define T_RANDOMTRAP 016 /* random trap */ #define T_ZEROTRAP 017 /* trap to zero */ /* * User mode flag added to trap code passed to trap routines * if trap is from user space. */ #define USER 020 #define SUPV 040 L_USERSET (PSL_PRVMOD|PSL_CURMOD) #define PSL_USERCLR PSL_IPL /* must be clear in user mode */ V); return (makedev(blkmaj, minor(dev))); } (), brroot(); daddr_t brsize(); #define brclose nulldev #else #define bropen nodev #define brclose nodev #define brroot nulldsys/pdp/fperr.h 444 0 12 550 4001143205 6663 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)fperr.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * Structure of the floating point error register save/return */ struct fperr { short f_fec; caddr_t f_fea; }; up.s mch_click.sclock.ck. genassym.c mem.c mch_copy.s libc_ffs.scons.cs.scons.hs.ssys/pdp/koverlay.h 444 0 12 4437 4001143226 7434 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)koverlay.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * Definitions relating to kernel text overlays. The kernel and * stand/bootstrap/boot.c must be recompiled if these are changed. * In practice, it is very difficult to change these numbers since * many changes will be necessary in mch.s. This file is provided * mainly to specify how kernel overlays are laid out, not for tuning. * * * Primary variables: * # ovly regs the maximum size of a kernel * overlay segment will be * 8k bytes * # ovly regs. * Currently, must be 1. * * OVLY_TABLE_BASE the address in l.s where the * kernel stores the prototype * PARs and PDRs. The only one * of the constants in this file * which may readily be changed. * * NUM_TEXT_REGS the maximum size of the kernel * base text segment will be * 8k bytes * NUM_TEXT_REGS. */ #define OVLY_TABLE_BASE 01000 #define I_NUM_TEXT_REGS 7 /* 8 - # ovly regs */ #define N_NUM_TEXT_REGS 2 #ifdef KERN_NONSEP #define NUM_TEXT_REGS N_NUM_TEXT_REGS #else !KERN_NONSEP #define NUM_TEXT_REGS I_NUM_TEXT_REGS #endif KERN_NONSEP #define I_MAX_DATA_REGS 6 #define N_MAX_DATA_REGS 3 /* 6 - NUM_TEXT_REGS - # ovly regs */ #ifdef KERN_NONSEP #define MAX_DATA_REGS N_MAX_DATA_REGS #else !KERN_NONSEP #define MAX_DATA_REGS I_MAX_DATA_REGS #endif KERN_NONSEP #define I_DATA_PAR_BASE KDSA0 #define N_DATA_PAR_BASE KISA3 /* &KISA[NUM_TEXT_REGS + # ovly regs] */ #ifdef KERN_NONSEP #define DATA_PAR_BASE N_DATA_PAR_BASE #else !KERN_NONSEP #define DATA_PAR_BASE I_DATA_PAR_BASE #endif KERN_NONSEP #define I_DATA_PDR_BASE KDSD0 #define N_DATA_PDR_BASE KISD3 /* &KISD[NUM_TEXT_REGS + # ovly regs] */ #ifdef KERN_NONSEP #define DATA_PDR_BASE N_DATA_PDR_BASE #else !KERN_NONSEP #define DATA_PDR_BASE I_DATA_PDR_BASE #endif KERN_NONSEP #define TEXT_PAR_BASE KISA0 #define TEXT_PDR_BASE KISD0 #ifdef KERN_NONSEP #define OVLY_PAR KISA2 /* &KISA[NUM_TEXT_REGS] */ #define OVLY_PDR KISD2 /* &KISD[NUM_TEXT_REGS] */ #else !KERN_NONSEP #define OVLY_PAR KISA7 /* &KISA[NUM_TEXT_REGS] */ #define OVLY_PDR KISD7 /* &KISD[NUM_TEXT_REGS] */ #endif KERN_NONSEP overlays. The kernel and * stand/bootstrap/boot.c must be recompiled if these are changed. * In practice, it is very difficult to change these numbers since * many changes will be necessary in mch.s. This file is providsys/pdp/autoconfig.h 444 0 12 1674 4020452331 7737 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)autoconfig.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * Possible error codes of the auto configuration program */ #define AC_OK 0 /* Everything A-OK for system go */ #define AC_SETUP 1 /* Error in initializing autoconf program */ #define AC_SINGLE 2 /* Non serious error, come to single user */ #define ACI_BADINTR -1 /* device interrupted through wrong vector */ #define ACP_EXISTS 1 /* device exists */ #define ACI_GOODINTR 1 /* interrupt OK */ #define ACP_IFINTR 0 /* device exists if interrupts OK */ #define ACI_NOINTR 0 /* device didn't interrupt */ #define ACP_NXDEV -1 /* no such device */ #define YES 1 /* general yes */ #define NO 0 /* general no */ /* * Magic number to verify that autoconfig runs only once. */ #define CONF_MAGIC 0x1960 REGS the maximum size of the kernel * base text segment will be sys/pdp/mscp.h 444 0 12 20450 4026720553 6566 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)mscp.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * Definitions for the Mass Storage Control Protocol * * Unused mscp definitions are commented out because of the * limited symbol table size in the V7 C compiler, * `too many defines'. * Lots of strangeness in mscp packet definitions, i.e., * dealing with longs as hi & lo words. This is due to the * way the PDP-11 stores a long, i.e., high order word * in low memory word and low order word in high memory word. * The UDA does not like that at all ! * * Fred Canter 10/22/83 */ /* * Control message opcodes */ #define M_O_ABORT 0001 /* Abort command */ #define M_O_GTCMD 0002 /* Get command status command */ #define M_O_GTUNT 0003 /* Get unit status command */ #define M_O_STCON 0004 /* Set controller characteristics command */ #define M_O_SEREX 0007 /* Serious exception end message */ #define M_O_AVAIL 0010 /* Available command */ #define M_O_ONLIN 0011 /* Online command */ #define M_O_STUNT 0012 /* Set unit characteristics command */ #define M_O_DTACP 0013 /* Determine access paths command */ #define M_O_ACCES 0020 /* Access command */ #define M_O_CMPCD 0021 /* Compare controller data command */ #define M_O_ERASE 0022 /* Erase command */ #define M_O_FLUSH 0023 /* Flush command */ #define M_O_REPLC 0024 /* Replace command */ #define M_O_COMP 0040 /* Compare host data command */ #define M_O_READ 0041 /* Read command */ #define M_O_WRITE 0042 /* Write command */ #define M_O_AVATN 0100 /* Available attention message */ #define M_O_DUPUN 0101 /* Duplicate unit number attention message */ #define M_O_ACPTH 0102 /* Access path attention message */ #define M_O_END 0200 /* End message flag */ /* * End message flags */ #define M_E_BBLR 0200 /* Bad block reported */ #define M_E_BBLU 0100 /* Bad block unreported */ #define M_E_ERLOG 0040 /* Error log generated */ #define M_E_SEREX 0020 /* Serious exception */ /* * Controller flags */ #define M_C_ATTN 0200 /* Enable attention messages */ #define M_C_MISC 0100 /* Enable miscellaneous error log messages */ #define M_C_OTHER 0040 /* Enable other host's error log messages */ #define M_C_THIS 0020 /* Enable this host's error log messages */ #define M_C_MLTHS 0004 /* Multi-host */ #define M_C_SHADW 0002 /* Shadowing */ #define M_C_576 0001 /* 576 byte sectors */ /* * Status codes */ #define M_S_MASK 037 /* Status code mask */ #define M_S_SUCC 000 /* Success */ #define M_S_ICMD 001 /* Invalid command */ #define M_S_ABRTD 002 /* Command aborted */ #define M_S_OFFLN 003 /* Unit offline */ #define M_S_AVLBL 004 /* Unit available */ #define M_S_MFMTE 005 /* Media format error */ #define M_S_WRTPR 006 /* Write protected */ #define M_S_COMP 007 /* Compare error */ #define M_S_DATA 010 /* Data error */ #define M_S_HSTBF 011 /* Host buffer access error */ #define M_S_CNTLR 012 /* Controller error */ #define M_S_DRIVE 013 /* Drive error */ #define M_S_DIAG 037 /* Message from a internal diagnostic */ /* * MSCP packet info */ struct mscp_header { u_short ra_msglen; /* length of MSCP packet */ char ra_credits; /* low 4 bits: credits, high 4 bits: msgtype */ char ra_vcid; /* virtual circuit id */ }; /* * An MSCP packet */ struct mscp { struct mscp_header m_header; /* device specific header */ u_short m_cmdref; /* command reference number */ u_short m_elref; /* plus error log reference number */ u_short m_unit; /* unit number */ u_short m_xxx1; /* unused */ u_char m_opcode; /* opcode */ u_char m_flags; /* end message flags */ u_short m_modifier; /* modifiers */ union { struct { u_short Ms_bytecnt; /* byte count */ u_short Ms_zzz2; /* 64kb max on V7 */ u_short Ms_buf_l; /* buffer descriptor low word */ u_short Ms_buf_h; /* buffer descriptor hi word */ long Ms_xx2[2]; /* unused */ u_short Ms_lbn_l; /* logical block number low word */ u_short Ms_lbn_h; /* logical bhock number hi word */ long Ms_xx4; /* unused */ long *Ms_dscptr; /* pointer to descriptor (software) */ long Ms_sftwds[4]; /* software words, padding */ } m_generic; struct { u_short Ms_version; /* MSCP version */ u_short Ms_cntflgs; /* controller flags */ u_short Ms_hsttmo; /* host timeout */ u_short Ms_usefrac; /* use fraction */ long Ms_time; /* time and date */ } m_setcntchar; struct { u_short Ms_multunt; /* multi-unit code */ u_short Ms_unitflgs; /* unit flags */ long Ms_hostid; /* host identifier */ quad Ms_unitid; /* unit identifier */ long Ms_mediaid; /* media type identifier */ u_short Ms_shdwunt; /* shadow unit */ u_short Ms_shdwsts; /* shadow status */ u_short Ms_track; /* track size */ u_short Ms_group; /* group size */ u_short Ms_cylinder; /* cylinder size */ u_short Ms_xx3; /* reserved */ u_short Ms_rctsize; /* RCT table size */ char Ms_rbns; /* RBNs / track */ char Ms_rctcpys; /* RCT copies */ } m_getunitsts; } m_un; int m_msgpad[3]; /* pad msg length to 64 bytes */ /* required by UQ bus port spec */ }; /* * generic packet */ #define m_zzz2 m_un.m_generic.Ms_zzz2 #define m_bytecnt m_un.m_generic.Ms_bytecnt #define m_buf_l m_un.m_generic.Ms_buf_l #define m_buf_h m_un.m_generic.Ms_buf_h #define m_lbn_l m_un.m_generic.Ms_lbn_l #define m_lbn_h m_un.m_generic.Ms_lbn_h #define m_dscptr m_un.m_generic.Ms_dscptr #define m_sftwds m_un.m_generic.Ms_sftwds #define m_status m_modifier /* * Abort / Get Command Status packet */ #define m_outref m_bytecnt /* * Online / Set Unit Characteristics packet */ #define m_elgfll m_lbn_l #define m_elgflh m_lbn_h #define m_copyspd m_shdwsts /* * Replace packet */ #define m_rbn m_bytecnt /* * Set Controller Characteristics packet */ #define m_version m_un.m_setcntchar.Ms_version #define m_cntflgs m_un.m_setcntchar.Ms_cntflgs #define m_hsttmo m_un.m_setcntchar.Ms_hsttmo #define m_usefrac m_un.m_setcntchar.Ms_usefrac #define m_time m_un.m_setcntchar.Ms_time /* * Get Unit Status end packet */ #define m_multunt m_un.m_getunitsts.Ms_multunt #define m_unitflgs m_un.m_getunitsts.Ms_unitflgs #define m_hostid m_un.m_getunitsts.Ms_hostid #define m_unitid m_un.m_getunitsts.Ms_unitid #define m_mediaid m_un.m_getunitsts.Ms_mediaid #define m_shdwunt m_un.m_getunitsts.Ms_shdwunt #define m_shdwsts m_un.m_getunitsts.Ms_shdwsts #define m_track m_un.m_getunitsts.Ms_track #define m_group m_un.m_getunitsts.Ms_group #define m_cylinder m_un.m_getunitsts.Ms_cylinder #define m_rctsize m_un.m_getunitsts.Ms_rctsize #define m_rbns m_un.m_getunitsts.Ms_rbns #define m_rctcpys m_un.m_getunitsts.Ms_rctcpys /* * Online / Set Unit Characteristics end packet */ #define m_uslow m_un.m_getunitsts.Ms_track #define m_ushigh m_un.m_getunitsts.Ms_group #define m_volser m_sftwds[0] /* * Set Controller Characteristics end packet */ #define m_cnttmo m_hsttmo #define m_cntcmdl m_usefrac #define m_cntid m_unitid /* * Error Log message format codes */ #define M_F_CNTERR 0 /* Controller error */ #define M_F_BUSADDR 1 /* Host memory access error */ #define M_F_DISKTRN 2 /* Disk transfer error */ #define M_F_SDI 3 /* SDI error */ #define M_F_SMLDSK 4 /* Small disk error */ /* * Error Log message flags */ #define M_LF_SUCC 0200 /* Operation successful */ #define M_LF_CONT 0100 /* Operation continuing */ #define M_LF_SQNRS 0001 /* Sequence number reset */ /* * MSCP Error Log packet * * NOTE: MSCP packet must be padded to this size. */ struct mslg { struct mscp_header me_header; /* device specific header */ int me_cmdref; /* command reference number */ int me_elref; /* error log reference number */ short me_unit; /* unit number */ short me_seqnum; /* sequence number */ u_char me_format; /* format */ u_char me_flags; /* error log message flags */ short me_event; /* event code */ quad me_cntid; /* controller id */ u_char me_cntsvr; /* controller software version */ u_char me_cnthvr; /* controller hardware version */ short me_multunt; /* multi-unit code */ quad me_unitid; /* unit id */ u_char me_unitsvr; /* unit software version */ u_char me_unithvr; /* unit hardware version */ short me_group; /* group; retry + level */ int me_volser[2]; /* volume serial number */ int me_hdr[2]; /* header */ char me_sdistat[12]; /* SDI status information */ }; #define me_busaddr me_unitid #define me_sdecyl me_group and */ #define M_O_GTCMD 0002 /* Get command status command */ #define M_O_GTUNT 0003 /* Get unit status command */ #define M_O_STCON 0004 /* Set controller characteristics command */ #define M_O_SEREX 0007 /* Seriousys/pdp/seg.h 444 0 12 11543 5321157750 6407 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)seg.h 1.2 (2.11BSD GTE) 1/1/93 */ #ifndef _SEG_ #define _SEG_ /* * Access abilities */ #define RO 02 /* Read only */ #define RW 06 /* Read and write */ #define NOACC 0 /* Abort all accesses */ #define ACCESS 07 /* Mask for access field */ #define ED 010 /* Extension direction */ #define TX 020 /* Software: text segment */ #define ABS 040 /* Software: absolute address */ #ifndef SUPERVISOR u_short *ka6; /* nonseparate: KISA6; separate: KDSA6 */ u_int kdsa6; /* saved KDSA6, if any */ #endif /* * Addresses and bits for DEC's KT-11 * and macros for remapping kernel data space. */ #define UISD ((u_short *) 0177600) /* first user I-space descriptor */ #define UDSD ((u_short *) 0177620) /* first user D-space descriptor */ #ifdef ENABLE34 # define DEC_UISA7 ((u_short *) 0177656) extern u_short *UISA, *UDSA, *KISA0, *KDSA1, *KDSA2, *KDSA5, *KDSA6; #else # define UISA ((u_short *) 0177640) /* first user I-space address */ # define UDSA ((u_short *) 0177660) /* first user D-space address */ #endif #ifndef ENABLE34 # define KISA0 ((u_short *) 0172340) # define KISA1 ((u_short *) 0172342) # define KISA5 ((u_short *) 0172352) # define KISA6 ((u_short *) 0172354) # define SSR3 ((u_short *) 0172516) #endif #define SISD0 ((u_short *) 0172200) #define SDSD0 ((u_short *) 0172220) #define SISA0 ((u_short *) 0172240) #define SDSA0 ((u_short *) 0172260) #define KISD1 ((u_short *) 0172302) #define KISD5 ((u_short *) 0172312) #define KISD6 ((u_short *) 0172314) #ifdef KERN_NONSEP # ifndef ENABLE34 # define KDSA5 KISA5 # define KDSA6 KISA6 # endif !ENABLE34 # define KDSD5 KISD5 # define KDSD6 KISD6 #else # ifndef ENABLE34 # define SDSA5 ((u_short *) 0172272) # define SDSA6 ((u_short *) 0172274) # define KDSA5 ((u_short *) 0172372) # define KDSA6 ((u_short *) 0172374) # endif !ENABLE34 # define SDSD5 ((u_short *) 0172232) # define SDSD6 ((u_short *) 0172234) # define KDSD5 ((u_short *) 0172332) # define KDSD6 ((u_short *) 0172334) #endif /* start of possibly mapped area; see machdep.c */ #ifndef SUPERVISOR #define REMAP_AREA ((caddr_t)&proc[0]) #endif #define SEG5 ((caddr_t) 0120000) #define SEG6 ((caddr_t) 0140000) #define SEG7 ((caddr_t) 0160000) #ifdef COMMENT * Macros for resetting the kernel segmentation registers to map in * out-of-address space data. If KDSA5 is used for kernel data space * only proc, file and text tables are allowed in that range. Routines * can repoint KDSA5 to map in data such as buffers or clists without * raising processor priority by calling these macros. Copy (in mch.s) uses * two registers, KDSA5 and 6. If KDSA6 is in use, the prototype register * kdsa6 will be non-zero, and the kernel will be running on a temporary stack * in bss. Interrupt routines that access any of the structures in this range * or the u. must call savemap (in machdep.c) to save the current mapping * information in a local structure and restore it before returning. * * USAGE: * To repoint KDSA5 from the top level, * mapseg5(addr, desc); /* KDSA5 now points at addr */ * ... * normalseg5(); /* normal mapping */ * * To repoint KDSA5 from interrupt or top level, * segm saveregs; * saveseg5(saveregs); /* save previous mapping of segment 5 */ * mapseg5(addr, desc); /* KDSA5 now points at addr */ * ... * restorseg5(saveregs); /* restore previous mapping */ * * To access proc, text, file or user structures from interrupt level, * mapinfo map; /* save ALL mapping information, */ * savemap(map); /* restore normal mapping of KA5 */ * ... /* and 6 */ * restormap(map); /* restore previous mapping */ #endif /* COMMENT */ /* * Structure to hold a saved PAR/PDR pair. */ struct segm_reg { u_int se_desc; u_int se_addr; }; typedef struct segm_reg segm; typedef struct segm_reg mapinfo[2]; /* KA5, KA6 */ #ifndef DIAGNOSTIC # define mapout(bp) normalseg5() #endif /* use segment 5 to access the given address. */ #ifdef SUPERVISOR #define mapseg5(addr,desc) { \ *SDSD5 = desc; \ *SDSA5 = addr; \ } #else #define mapseg5(addr,desc) { \ *KDSD5 = desc; \ *KDSA5 = addr; \ } #endif /* save the previous contents of KDSA5/KDSD5. */ #ifdef SUPERVISOR #define saveseg5(save) { \ save.se_addr = *SDSA5; \ save.se_desc = *SDSD5; \ } #else #define saveseg5(save) { \ save.se_addr = *KDSA5; \ save.se_desc = *KDSD5; \ } #endif /* restore normal kernel map for seg5. */ extern segm seg5; /* prototype KDSA5, KDSD5 */ #define normalseg5() restorseg5(seg5) /* restore the previous contents of KDSA5/KDSD5. */ #ifdef SUPERVISOR #define restorseg5(save) { \ *SDSD5 = save.se_desc; \ *SDSA5 = save.se_addr; \ } #else #define restorseg5(save) { \ *KDSD5 = save.se_desc; \ *KDSA5 = save.se_addr; \ } caddr_t mapin(); #endif #endif /* _SEG_ */ le size */ char Ms_rbns; /* RBNs / track */ char Ms_rctcpys; /* RCT copies */ } m_getunitsts; } m_un; int m_msgpad[3]; /* pad msg length to 64 bytes sys/pdp/iopage.h 444 0 12 1511 5317203371 7043 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)iopage.h 1.2 (2.11BSD GTE) 12/26/92 */ /* * I/O page addresses */ #define PS ((u_short *) 0177776) #define SL ((u_short *) 0177774) #define PIR ((u_short *) 0177772) #define CPUERR ((u_short *) 0177766) #define SYSSIZEHI ((u_short *) 0177762) #define SYSSIZELO ((u_short *) 0177760) #define MEMSYSCTRL ((u_short *) 0177746) #define MEMSYSERR ((u_short *) 0177744) #define MEMERRHI ((u_short *) 0177742) #define MEMERRLO ((u_short *) 0177740) /* Memory control registers (one per memory board) */ #define MEMSYSMCR ((u_short *) 0172100) #define MEMMCR_EIE 0000001 /* Error Indication Enable */ #define CSW ((u_short *) 0177570) * first user I-space descriptor */ #define UDSD ((u_short *) 0177620) /* first user D-space descriptor */ #ifdef ENABLE34 # define DEC_UISA7 ((u_short *) 0177656) extern u_short *UIsys/pdp/DEFS.h 644 3 12 4101 5317203510 6316 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)DEFS.h 1.2 (2.11BSD GTE) 12/24/92 */ #ifndef _DEFS_ #define _DEFS_ /* * Machine language assist. Uses the C preprocessor to produce suitable code * for various 11's. */ #include "localopts.h" #include "assym.h" #define INTSTK 500. /* bytes for interrupt stack */ #ifdef PROF # define HIGH 06 /* See also the :splfix files */ # define HIPRI 0300 /* Many spl's are done in-line */ #else # define HIGH 07 # define HIPRI 0340 #endif # define NET 02 # define NETPRI 0100 /* * adapt to any 11 at boot */ #ifdef GENERIC # undef NONSEPARATE /* Enable support for separate I&D if found */ #endif #ifdef NONSEPARATE /* 11/40, 34, 23, 24 */ # define mfpd mfpi # define mtpd mtpi #endif #if defined(GENERIC) || defined(SUPERVISOR) || defined(NONSEPARATE) /* * GENERIC: movb instruction are available on all PDP-11s. * * SUPERVISOR: can't use spl instructions even if the machine * supports them since spl is a privileged instruction. */ # define SPLHIGH movb $HIPRI,PS # define SPL7 movb $0340,PS # define SPLLOW clrb PS # define SPLNET movb $NETPRI,PS #else # define SPLHIGH spl HIGH # define SPL7 spl 7 # define SPLLOW spl 0 # define SPLNET spl NET #endif #define CONST(s, x, v) DEC_/**/s(x); x=v; #define INT(s, x, v) .data; .even; DEC_/**/s(x); x:; v; .text; #define CHAR(s, x, v) .data; DEC_/**/s(x); x:; .byte v; .text; #define STRING(s, x, v) .data; DEC_/**/s(x); x:; v; .text; #define SPACE(s, x, n) .bss; .even; DEC_/**/s(x); x:; .=.+[n]; .text; #define DEC_GLOBAL(x) .globl x; #define DEC_LOCAL(x) /* * Macros for compatibility with standard library routines that we have * copies of ... */ #define ENTRY(x) .globl _/**/x; _/**/x:; #define ASENTRY(x) .globl x; x:; #define P_ENTRY(x) .globl _/**/x; _/**/x:; PROFCODE; #define P_ASENTRY(x) .globl x; x:; PROFCODE; /* * PROFCODE: * - kernel profiling not currently implemented. */ #define PROFCODE ; #endif _DEFS_ ne in-line */ #else # define HIGH 07 # define HIPRI 0340 #endif # define NET 02 # define NETPRI 0100 /* * adapt to any 11 at boot */ #ifdef GENERIC # undef NONSEPARATE /* Enable support for separate I&D if found */ #endif #ifdef NONSEPARATE /* 11/40, 34, 23, 24 */ # define mfpd mfpi # define mtpd mtpi #endif #if defined(GENERIC) || defined(SUPERVISOR) || defined(NONSEPARATE) /* * GENERIC: movb instruction are available on all PDP-1sys/pdp/cpu.h 444 0 12 1423 5705712070 6372 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)cpu.h 1.3 (2.11BSD GTE) 1/14/95 */ /* * Define others as needed. The old practice of defining _everything_ * for _all_ models and then attempting to 'ifdef' the mess on a particular * cputype was simply too cumbersome (and didn't work when moving kernels * between cpu types). */ #define PDP1170_LEAR ((physadr) 0177740) /* * CTL_MACHDEP definitions. */ #define CPU_CONSDEV 1 /* dev_t: console terminal device */ #define CPU_MAXID 2 /* number of valid machdep ids */ #ifndef KERNEL #define CTL_MACHDEP_NAMES { \ { 0, 0 }, \ { "console_device", CTLTYPE_STRUCT }, \ } #endif found */ #endif #ifdef NONSEPARATE /* 11/40, 34, 23, 24 */ # define mfpd mfpi # define mtpd mtpi #endif #if defined(GENERIC) || defined(SUPERVISOR) || defined(NONSEPARATE) /* * GENERIC: movb instruction are available on all PDP-1sys/pdp/scb.s 440 0 12 21634 5321157654 6414 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)scb.s 1.3 (2.11BSD GTE) 1/1/93 */ #include "DEFS.h" #include "../machine/trap.h" #include "../machine/mch_iopage.h" #include "../machine/koverlay.h" /* for OVLY_TABLE_BASE */ #include "acc.h" #include "css.h" #include "de.h" #include "dh.h" #include "dhu.h" #include "dhv.h" #include "dn.h" #include "dr.h" #include "dz.h" #include "ec.h" #include "hk.h" #include "ht.h" #include "il.h" #include "lp.h" #include "ra.h" #include "rk.h" #include "rl.h" #include "br.h" #include "rx.h" #include "si.h" #include "sri.h" #include "tm.h" #include "ts.h" #include "tms.h" #include "xp.h" #include "vv.h" /* * Reference the global symbol "_end" so that ld(1) will define it for us. */ .globl _end sup = 40000 /* current supervisor previous kernel */ br4 = 200 /* PS interrupt priority masks */ br5 = 240 br6 = 300 br7 = 340 #ifdef KERN_NONSEP .text /* vectors at text zero */ #else .data /* vectors at data zero */ #endif ZERO: #define SETDOT(n) . = ZERO+n #define TRAP(handler, pri) .globl handler; handler; pri; #define DEVTRAP(vec, handler, pri) SETDOT(vec); handler; pri; SETDOT(0) #ifdef KERN_NONSEP /* * If vectors at 110 and 444 are unused, autoconfig will set these * to something more reasonable. On jump, this will branch to 112, * which branches to 50. On trap, will vector to 444, where a * T_ZEROTRAP will be simulated. */ 42 /* illegal instruction if jump */ 777 /* trace trap at high priority if trap */ #else TRAP(trap, br7+T_ZEROTRAP) /* trap-to-zero trap */ #endif SETDOT(4) /* trap vectors */ TRAP(trap, br7+T_BUSFLT) /* bus error */ TRAP(trap, br7+T_INSTRAP) /* illegal instruction */ TRAP(trap, br7+T_BPTTRAP) /* bpt-trace trap */ #ifdef INET TRAP(iothndlr, br7+T_IOTTRAP) /* network uses iot */ #else TRAP(trap, br7+T_IOTTRAP) /* iot trap */ #endif TRAP(powrdown, br7+T_POWRFAIL) /* power fail */ TRAP(emt, br7+T_EMTTRAP) /* emulator trap */ TRAP(start, br7+T_SYSCALL) /* system (overlaid by 'syscall') */ #ifdef KERN_NONSEP SETDOT(40) /* manual reboot entry */ jmp do_panic #endif SETDOT(44) /* manual dump entry */ jmp dump #ifdef KERN_NONSEP SETDOT(50) /* handler for jump-to-zero panic. */ mov $zjmp, -(sp) jsr pc, _panic #endif DEVTRAP(60, cnrint, br4) /* KL11 console */ DEVTRAP(64, cnxint, br4) DEVTRAP(100, hardclock, br6) /* KW11-L clock */ #ifdef PROFILE DEVTRAP(104, _sprof, br7) /* KW11-P clock */ #else DEVTRAP(104, hardclock, br6) #endif SETDOT(114) TRAP(trap, br7+T_PARITYFLT) /* 11/70 parity fault */ #if NDE > 0 /* DEUNA */ DEVTRAP(120, deintr, sup|br5) #endif #if NCSS > 0 /* IMP-11A */ DEVTRAP(124, cssrint,sup|br5) /* note that the transmit interrupt vector is up at 274 ... */ #endif #if NDR > 0 /* DR-11W */ DEVTRAP(124, drintr, br5) #endif #if NRAC > 0 /* RQDX? (RX50,RD51/52/53) */ /* UDA50 (RA60/80/81), KLESI (RA25) */ DEVTRAP(154, raintr, br5) #endif #if NRL > 0 /* RL01/02 */ DEVTRAP(160, rlintr, br5) #endif #if NSI > 0 /* SI 9500 -- CDC 9766 disks */ DEVTRAP(170, siintr, br5) #endif #if NHK > 0 /* RK611, RK06/07 */ DEVTRAP(210, hkintr, br5) #endif #if NRK > 0 /* RK05 */ DEVTRAP(220, rkintr, br5) #endif SETDOT(240) TRAP(trap, br7+T_PIRQ) /* program interrupt request */ TRAP(trap, br7+T_ARITHTRAP) /* floating point */ TRAP(trap, br7+T_SEGFLT) /* segmentation violation */ #if NBR > 0 DEVTRAP(254, brintr, br5) /* EATON BR1537 or EATON BR1711 */ #endif #if NXPD > 0 /* RM02/03/05, RP04/05/06 */ /* DIVA, SI Eagle */ DEVTRAP(254, xpintr, br5) #endif #if NRX > 0 /* RX01 */ DEVTRAP(264, rxintr, br5) #endif #if NACC > 0 /* ACC LH/DH-11 */ DEVTRAP(270, accrint, sup|br5) DEVTRAP(274, accxint, sup|br5) #endif #if NCSS > 0 /* IMP-11A */ /* note that the receive interrupt vector is down at 124 ... */ DEVTRAP(274, cssxint,sup|br5) #endif #if NIL > 0 /* Interlan Ethernet */ DEVTRAP(340, ilrint, sup|br5) DEVTRAP(344, ilcint, sup|br5) #endif #if NVV > 0 /* V2LNI */ DEVTRAP(350, vvrint, sup|br5) DEVTRAP(354, vvxint, sup|br5) #endif #if NEC > 0 /* 3Com ethernet */ /* * These are almost certainly wrong for any given site since the * 3Com seems to be somewhat randomly configured. Pay particular * attention to the interrupt priority levels: if they're too low * you'll get recursive interrupts; if they're too high you'll lock * out important interrupts (like the clock). */ DEVTRAP(400, ecrint, sup|br6) DEVTRAP(404, eccollide,sup|br4) DEVTRAP(410, ecxint, sup|br6) #endif #if NSRI > 0 /* SRI DR11-C ARPAnet IMP */ DEVTRAP(500, srixint, sup|br5) DEVTRAP(504, srirint, sup|br5) #endif /* * End of floating vectors. Endvec should be past vector space if NONSEP, * should be at least 450. * */ SETDOT(1000) CONST(GLOBAL, endvec, .) /* * The overlay tables are initialized by boot. Ovhndlr, cret and call use * them to perform kernel overlay switches. The tables contain an arrays of * segment addresses and descriptors. Note: don't use SPACE macro as it * allocates it's space in bss, not data space ... */ . = ZERO+OVLY_TABLE_BASE .globl ova, ovd ova: .=.+40 /* overlay addresses */ ovd: .=.+40 /* overlay descriptors */ /* * FLASH! for overlaid programs /boot kindly lets us know where our * load image stops by depositing a value at the end of the overlay tables. * Needless to say this had been clobbering something all along, but the * effect was rather nasty (crash) when the 'last interrupt vector' location * was overwritten! Not sure whether to fix /boot or leave room here, so * for now just add a "pad" word. */ INT(LOCAL, physend, 0) /* * _lastiv is used for assigning vectors to devices which have programmable * vectors. Usage is to decrement _lastiv by 4 before use. The routine * _nextiv (in mch_xxx.s) will do this, returning the assigned vector in r0. */ INT(GLOBAL, _lastiv, endvec) .text TEXTZERO: / base of system program text #ifndef KERN_NONSEP /* * this is text location 0 for separate I/D kernels. */ mov $zjmp,-(sp) jsr pc,_panic /*NOTREACHED*/ #endif STRING(LOCAL, zjmp, ) #ifndef KERN_NONSEP /* * Unmap is called from _doboot to turn off memory management. The "return" * is arranged by putting a jmp at unmap+2 (data space). */ ASENTRY(unmap) reset /* * The next instruction executed is from unmap+2 in physical memory, * which is unmap+2 in data space. */ #endif /* * Halt cpu in its tracks ... */ ENTRY(halt) halt /* NOTREACHED */ /* * CGOOD and CBAD are used by autoconfig. All unused vectors are set to CBAD * before probing the devices. */ ASENTRY(CGOOD) mov $1,_conf_int rtt ASENTRY(CBAD) mov $-1,_conf_int rtt /* * Routine to call panic, take dump and reboot; entered by manually loading * the PC with 040 and continuing. Note that putting this here is calculated * to waste as little text space as possible for separate I&D kernels. * Currently the zero jmp, unmap, halt, CGOOD, and CBAD routines leave the * separate I&D assembly counter at 034, so the ". = 40" below only wastes * 4 bytes. This is safe since any attempt to set the assembly counter back * will cause an error indicating that the assembly counter is higher than * 040 meaning things need to be rearranged ... */ #ifndef KERN_NONSEP . = TEXTZERO+040 #endif do_panic: mov $1f,-(sp) STRING(LOCAL, 1, ) jsr pc, _panic /* NOTREACHED */ /* * Start of locore interrupt entry thunks. */ #define HANDLER(handler) .globl _/**/handler; \ handler: jsr r0,call; jmp _/**/handler HANDLER(cnrint) /* KL-11, DL-11 */ HANDLER(cnxint) HANDLER(hardclock) #if NDR > 0 /* DR-11W */ HANDLER(drintr) #endif #if NRAC > 0 /* RQDX? (RX50,RD51/52/53) */ HANDLER(raintr) /* UDA50 (RA60/80/81), KLESI (RA25) */ #endif #if NRL > 0 /* RL01/02 */ HANDLER(rlintr) #endif #if NSI > 0 /* SI 9500 -- CDC 9766 disks */ HANDLER(siintr) #endif #if NLP > 0 /* Line Printer */ HANDLER(lpintr) #endif #if NHK > 0 /* RK611, RK06/07 */ HANDLER(hkintr) #endif #if NRK > 0 /* RK05 */ HANDLER(rkintr) #endif #if NBR > 0 HANDLER(brintr) /* EATON BR1537/BR1711 */ #endif #if NXPD > 0 /* RM02/03/05, RP04/05/06 */ HANDLER(xpintr) /* DIVA, SI Eagle */ #endif #if NRX > 0 /* RX01/02 */ HANDLER(rxintr) #endif #if NHT > 0 /* TJU77, TWU77, TJE16, TWE16 */ HANDLER(htintr) #endif #if NTM > 0 /* TM-11 */ HANDLER(tmintr) #endif #if NTS > 0 /* TS-11 */ HANDLER(tsintr) #endif #if NTMSCP > 0 HANDLER(tmsintr) /* TMSCP (TU81/TK50) */ #endif #if NDH > 0 /* DH-11 */ HANDLER(dhrint) HANDLER(dhxint) #endif #if NDM > 0 /* DM-11 */ HANDLER(dmintr) #endif #if NDHU > 0 /* DHU */ HANDLER(dhurint) HANDLER(dhuxint) #endif #if NDHV > 0 /* DHV */ HANDLER(dhvrint) HANDLER(dhvxint) #endif #if NDN > 0 /* DN11 */ HANDLER(dnint) #endif #if NDZ > 0 /* DZ */ HANDLER(dzrint) #endif work uses iot */ #else TRAP(trap, br7+T_IOTTRAP) /* iot trap */ #endif TRAP(powrdown, br7+T_POWRFAsys/pdp/enable34.h 444 0 12 1450 4001143205 7162 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)enable34.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * Addresses and bits for Able's ENABLE/34. * * All information relevant to the ENABLE/34 is supplied with * the permission of ABLE Computer and may not be disclosed in * any manner to sites not licensed by the University of California * for the Second Berkeley Software Distribution. * */ #define ENABLE_SSR3 ((u_short *) 0163676) /* bits in the ENABLE's SSR3 */ #define ENABLE_SSR3_PARS_ON 0000010 #define ENABLE_SSR3_UBMAP_ON 0000020 #define ENABLE_SSR4 ((u_short *) 0163674) /* bits in the ENABLE's SSR4 */ #define ENABLE_SSR4_MAP_ON 0000001 81), KLESI (RA25) */ #endif #if NRL > 0 /* RL01/02 */ HANDLER(rlintr) #endif #if NSI > 0 /* SI 9500 -- CDC 9766 disks */ HANDLER(siintr) #endif #if NLP > 0 /* Line Printer */ HANDLER(lpintr) #endif #isys/pdp/machparam.h 444 0 12 10470 5404441375 7561 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)machparam.h 1.2 (2.11BSD GTE) 12/24/92 */ /* * Machine dependent constants for PDP. */ #define MACHINE "pdp" #ifndef ENDIAN /* * Definitions for byte order, * according to byte significance from low address to high. */ #define LITTLE 1234 /* least-significant byte first (vax) */ #define BIG 4321 /* most-significant byte first */ #define PDP 3412 /* LSB first in word, MSW first in long (pdp) */ #define ENDIAN PDP /* byte order on pdp */ /* * Macros for network/external number representation conversion. */ #if ENDIAN == BIG && !defined(lint) #define ntohl(x) (x) #define ntohs(x) (x) #define htonl(x) (x) #define htons(x) (x) #else #include u_short ntohs(), htons(); u_long ntohl(), htonl(); #endif #define CHAR_BIT NBBY #define CHAR_MAX 0x7f #define CHAR_MIN 0x80 #define CLK_TCK 60 /* for times() */ #define INT_MAX 0x7fff #define INT_MIN 0x8000 #define LONG_MAX 0x7fffffff #define LONG_MIN 0x80000000 #define SCHAR_MAX 0x7f #define SCHAR_MIN 0x80 #define SHRT_MAX 0x7fff #define SHRT_MIN 0x8000 #define UCHAR_MAX 0xff #define UINT_MAX ((unsigned int)0xffff) #define ULONG_MAX 0x7fffffff #define USHRT_MAX ((unsigned short)0xffff) #define NBPG 512 /* bytes/page */ #define PGOFSET (NBPG-1) /* byte offset into page */ #define PGSHIFT 9 /* LOG2(NBPG) */ #define DEV_BSIZE 1024 #define DEV_BSHIFT 10 /* log2(DEV_BSIZE) */ #define DEV_BMASK 0x3ffL /* DEV_BSIZE - 1 */ #define CLSIZE 2 #define CLSIZELOG2 1 #define SSIZE 20 /* initial stack size (*64 bytes) */ #define SINCR 20 /* increment of stack (*64 bytes) */ /* machine dependent stuff for core files */ #define TXTRNDSIZ 8192L #define stacktop(siz) (0x10000L) #define stackbas(siz) (0x10000L-(siz)) /* * User area: a user structure, followed by a stack for the networking code * (running in supervisor space on the PDP-11), followed by the kernel * stack. The numbers for NET_SSIZE and KERN_SSIZE are determined * empirically. * * Note that the SBASE and STOP constants are only used by the assembly code, * but are defined here to localize information about the user area's * layout (see pdp/genassym.c). Note also that a networking stack is always * allocated even for non-networking systems. This prevents problems with * applications having to be recompiled for networking versus non-networking * systems. */ #define NET_SSIZE 16 /* size of the network stack (*64) */ #define KERN_SSIZE 32 /* size of the kernel stack (*64) */ #define USIZE (btoc(sizeof(struct user)) + NET_SSIZE + KERN_SSIZE) #define NET_SBASE ctob(btoc(sizeof(struct user))) #define NET_STOP (NET_SBASE + ctob(NET_SSIZE)) #define KERN_SBASE NET_STOP #define KERN_STOP (KERN_SBASE + ctob(KERN_SSIZE)) /* * Some macros for units conversion */ /* Core clicks (64 bytes) to segments and vice versa */ #define ctos(x) (((x)+127)/128) #define stoc(x) ((x)*128) /* Core clicks (64 bytes) to disk blocks */ #define ctod(x) (((x)+7)>>3) /* clicks to bytes */ #define ctob(x) ((x)<<6) /* bytes to clicks */ #define btoc(x) ((((unsigned)(x)+63)>>6)) /* these should be fixed to use unsigned longs, if we ever get them. */ #define btodb(bytes) /* calculates (bytes / DEV_BSIZE) */ \ ((long)(bytes) >> DEV_BSHIFT) #define dbtob(db) /* calculates (db * DEV_BSIZE) */ \ ((long)(db) << DEV_BSHIFT) /* clicks to KB */ #define ctok(x) (((x)>>4)&07777) /* * Macros to decode processor status word. */ #define SUPVMODE(ps) (((ps) & PSL_CURMOD) == PSL_CURSUP) #define USERMODE(ps) (((ps) & PSL_USERSET) == PSL_USERSET) #define BASEPRI(ps) (((ps) & PSL_IPL) == 0) #define DELAY(n) { long N = ((long)(n))<<1; while (--N > 0); } /* * Treat ps as byte, to allow restoring value from mfps/movb * (see :splfix.*) */ #define PS_LOBYTE ((char *)0177776) #define splx(ops) (*PS_LOBYTE = ((char)(ops))) /* * high int of a long * low int of a long */ #define hiint(long) (((int *)&(long))[0]) #define loint(long) (((int *)&(long))[1]) /* * SUPERADD is used to distinguish a supervisor-mode address from a * kernel mode address to insure uniqueness over both address spaces. */ #define SUPERADD(add) ((int)(add)|01) #define KERNELADD(add) ((int)(add)&~01) #define ISSUPERADD(add) ((int)(add)&01) #endif ENDIAN ured. Pay particular * attention to the interrupt priority levels: if they're too low * you'll get recursive interrupts; if they're too high you'll lock * out important interrupts (like the closys/pdp/clock.h 444 0 12 1474 4001143105 6665 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)clock.h 1.1 (2.10BSD Berkeley) 12/1/86 */ #define SECDAY ((unsigned)(24*60*60)) /* seconds per day */ #define SECYR ((unsigned)(365*SECDAY)) /* per common year */ #define LKS ((u_short *)0177546) /* line clock */ #define KW11P_CCSR ((u_short *)0172540) /* programmable clock */ #define KW11P_CCSB ((u_short *)0172542) /* count set buffer */ #define KW11P_CCNT ((u_short *)0172544) /* counter */ #define K_RUN 0x01 /* start counter */ #define K_10KRATE 0x02 /* 10kHz frequency */ #define K_LFRATE 0x04 /* line frequency */ #define K_MODE 0x08 /* repeat interrupt */ #define K_IENB 0x40 /* interrupt enable */ ine htons(x) (x) #else #include u_short ntohs(), htons(); u_long ntohl(), htonl(); #endif #define CHAR_BIT NBBY #define CHAR_MAX 0x7f #define CHAR_MIN 0x80 #define CLK_TCK 60 /* sys/pdp/tags 751 0 12 0 6045325047 10156 2../sys/tagssys/pdp/trap.c 440 0 12 24531 5665737475 6612 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)trap.c 1.4 (2.11BSD GTE) 11/24/94 */ #include "param.h" #include "../machine/psl.h" #include "../machine/reg.h" #include "../machine/seg.h" #include "../machine/trap.h" #include "../machine/iopage.h" #include "systm.h" #include "user.h" #include "proc.h" #include "vm.h" extern int fpp, kdj11; #ifdef INET extern int netoff; #endif #ifdef DIAGNOSTIC extern int hasmap; static int savhasmap; #endif /* * Offsets of the user's registers relative to * the saved r0. See sys/reg.h. */ char regloc[] = { R0, R1, R2, R3, R4, R5, R6, R7, RPS }; /* * Translation table to convert the FP-11 FECs (Floating Exception Codes) to * the various FPE_... codes defined in . On the VAX these come * free because those *are* the codes the VAX FP hardware generates. */ static u_char pdpfec[16] = { FPE_CRAZY, /* 0: not a legal FEC code */ FPE_CRAZY, /* 1: not a legal FEC code */ FPE_OPCODE_TRAP, /* 2: bad floating point op code */ FPE_CRAZY, /* 3: not a legal FEC code */ FPE_FLTDIV_TRAP, /* 4: floating devide by zero */ FPE_CRAZY, /* 5: not a legal FEC code */ FPE_DECOVF_TRAP, /* 6: floating to integer conversion error */ FPE_CRAZY, /* 7: not a legal FEC code */ FPE_FLTOVF_TRAP, /* 8: floating overflow */ FPE_CRAZY, /* 9: not a legal FEC code */ FPE_CRAZY, /* 10: not a legal FEC code */ FPE_FLTUND_TRAP, /* 11: floating underflow */ FPE_OPERAND_TRAP, /* 12: bad floating point operand */ FPE_CRAZY, /* 13: not a legal FEC code */ FPE_MAINT_TRAP, /* 14: maintenance trap */ FPE_CRAZY, /* 15: not a legal FEC code */ }; /* * Called from mch.s when a processor trap occurs. * The arguments are the words saved on the system stack * by the hardware and software during the trap processing. * Their order is dictated by the hardware and the details * of C's calling sequence. They are peculiar in that * this call is not 'by value' and changed user registers * get copied back on return. * Dev is the kind of trap that occurred. */ /*ARGSUSED*/ trap(dev, sp, r1, ov, nps, r0, pc, ps) dev_t dev; caddr_t sp, pc; int r1, ov, nps, r0, ps; { extern int _ovno; static int once_thru = 0; register int i; register struct proc *p; time_t syst; mapinfo kernelmap; #ifdef UCB_METER cnt.v_trap++; #endif /* * In order to stop the system from destroying * kernel data space any further, allow only one * fatal trap. After once_thru is set, any * futher traps will be handled by looping in place. */ if (once_thru) { (void) _splhigh(); for(;;); } if (USERMODE(ps)) dev |= USER; else #ifdef INET if (SUPVMODE(ps)) dev |= SUPV; else #endif savemap(kernelmap); /* guarantee normal kernel mapping */ syst = u.u_ru.ru_stime; p = u.u_procp; u.u_fpsaved = 0; u.u_ar0 = &r0; switch(minor(dev)) { /* * Trap not expected. Usually a kernel mode bus error. The numbers * printed are used to find the hardware PS/PC as follows. (all * numbers in octal 18 bits) * address_of_saved_ps = * (ka6*0100) + aps - 0140000; * address_of_saved_pc = * address_of_saved_ps - 2; */ default: once_thru = 1; #ifdef DIAGNOSTIC /* * Clear hasmap if we attempt to sync the fs. * Else it might fail if we faulted with a mapped * buffer. */ savhasmap = hasmap; hasmap = 0; #endif i = splhigh(); printf("ka6 = %o\n", *ka6); printf("aps = %o\n", &ps); printf("pc = %o, ps = %o\n", pc, ps); printf("__ovno = %d\n", ov); if ((cputype == 70) || (cputype == 44)) printf("cpuerr = %o\n", *CPUERR); printf("trap type %o\n", dev); splx(i); panic("trap"); /*NOTREACHED*/ case T_BUSFLT + USER: i = SIGBUS; break; case T_INSTRAP + USER: #if defined(FPSIM) || defined(GENERIC) /* * If no floating point hardware is present, see if the * offending instruction was a floating point instruction ... */ if (fpp == 0) { i = fptrap(); #ifdef UCB_METER if (i != SIGILL) { cnt.v_fpsim++; } #endif if (i == 0) goto out; if (i == SIGTRAP) ps &= ~PSL_T; u.u_code = pdpfec[(unsigned)u.u_fperr.f_fec & 0xf]; break; } #endif /* * If illegal instructions are not being caught and the * offending instruction is a SETD, the trap is ignored. * This is because C produces a SETD at the beginning of * every program which will trap on CPUs without an FP-11. */ #define SETD 0170011 /* SETD instruction */ if(fuiword((caddr_t)(pc-2)) == SETD && u.u_signal[SIGILL] == 0) goto out; i = SIGILL; u.u_code = ILL_RESAD_FAULT; /* it's simplest to lie */ break; case T_BPTTRAP + USER: i = SIGTRAP; ps &= ~PSL_T; break; case T_IOTTRAP + USER: i = SIGIOT; break; case T_EMTTRAP + USER: i = SIGEMT; break; /* * Since the floating exception is an imprecise trap, a user * generated trap may actually come from kernel mode. In this * case, a signal is sent to the current process to be picked * up later. */ #ifdef INET case T_ARITHTRAP+SUPV: #endif case T_ARITHTRAP: case T_ARITHTRAP + USER: i = SIGFPE; stst(&u.u_fperr); /* save error code and address */ u.u_code = pdpfec[(unsigned)u.u_fperr.f_fec & 0xf]; break; /* * If the user SP is below the stack segment, grow the stack * automatically. This relies on the ability of the hardware * to restart a half executed instruction. On the 11/40 this * is not the case and the routine backup/mch.s may fail. * The classic example is on the instruction * cmp -(sp),-(sp) * * The KDJ-11 (11/53,73,83,84,93,94) handles the trap when doing * a double word store differently than the other pdp-11s. When * doing: * setl * movfi fr0,-(sp) * and the stack segment becomes invalid part way thru then the * trap is generated (as expected) BUT 'sp' IS NOT LEFT DECREMENTED! * The 'grow' routine sees that SP is still within the (valid) stack * segment and does not extend the stack, resulting in a 'segmentation * violation' rather than a successfull floating to long store. * The "fix" is to pretend that SP is 4 bytes lower than it really * is (for KDJ-11 systems only) when calling 'grow'. */ case T_SEGFLT + USER: { caddr_t osp; osp = sp; if (kdj11) osp -= 4; if (backup(u.u_ar0) == 0) if (!u.u_onstack && grow((u_int)osp)) goto out; i = SIGSEGV; break; } /* * The code here is a half-hearted attempt to do something with * all of the PDP11 parity registers. In fact, there is little * that can be done. */ case T_PARITYFLT: case T_PARITYFLT + USER: #ifdef INET case T_PARITYFLT + SUPV: #endif printf("parity\n"); if ((cputype == 70) || (cputype == 44)) { for(i = 0; i < 4; i++) printf("%o ", MEMERRLO[i]); printf("\n"); MEMERRLO[2] = MEMERRLO[2]; if (dev & USER) { i = SIGBUS; break; } } panic("parity"); /*NOTREACHED*/ /* * Allow process switch */ case T_SWITCHTRAP + USER: goto out; #ifdef INET case T_BUSFLT+SUPV: case T_INSTRAP+SUPV: case T_BPTTRAP+SUPV: case T_IOTTRAP+SUPV: case T_EMTTRAP+SUPV: case T_PIRQ+SUPV: case T_SEGFLT+SUPV: case T_SYSCALL+SUPV: case T_SWITCHTRAP+SUPV: case T_ZEROTRAP+SUPV: case T_RANDOMTRAP+SUPV: i = splhigh(); if (!netoff) { netoff = 1; savestate(); } printf("Unexpected net code trap (%o)\n", dev-SUPV); printf("ka6 = %o\n", *ka6); printf("aps = %o\n", &ps); printf("pc = %o ps = %o\n", pc, ps); splx(i); panic("net crashed"); /*NOTREACHED*/ #endif /* * Whenever possible, locations 0-2 specify this style trap, since * DEC hardware often generates spurious traps through location 0. * This is a symptom of hardware problems and may represent a real * interrupt that got sent to the wrong place. Watch out for hangs * on disk completion if this message appears. Uninitialized * interrupt vectors may be set to trap here also. */ case T_ZEROTRAP: case T_ZEROTRAP + USER: printf("Trap to 0: "); /*FALL THROUGH*/ case T_RANDOMTRAP: /* generated by autoconfig */ case T_RANDOMTRAP + USER: printf("Random interrupt ignored\n"); if (!(dev & USER)) restormap(kernelmap); return; } psignal(p, i); out: if (p->p_cursig || ISSIG(p)) psig(); curpri = setpri(p); if (runrun) { setrq(u.u_procp); u.u_ru.ru_nivcsw++; swtch(); } if (u.u_prof.pr_scale) addupc(pc, &u.u_prof, (int) (u.u_ru.ru_stime - syst)); if (u.u_fpsaved) restfp(&u.u_fps); } /* * Called from mch.s when a system call occurs. dev, ov and nps are * unused, but are necessitated by the values of the R[0-7] ... constants * in sys/reg.h (which, in turn, are defined by trap's stack frame). */ /*ARGSUSED*/ syscall(dev, sp, r1, ov, nps, r0, pc, ps) dev_t dev; caddr_t sp, pc; int r1, ov, nps, r0, ps; { extern int nsysent; register int code; register struct sysent *callp; time_t syst; register caddr_t opc; /* original pc for restarting syscalls */ #ifdef UCB_METER cnt.v_syscall++; #endif syst = u.u_ru.ru_stime; u.u_fpsaved = 0; u.u_ar0 = &r0; u.u_error = 0; opc = pc - 2; /* opc now points at syscall */ code = fuiword((caddr_t)opc) & 0377; /* bottom 8 bits are index */ if (code >= nsysent) callp = &sysent[0]; /* indir (illegal) */ else callp = &sysent[code]; if (callp->sy_narg) copyin(sp+2, (caddr_t)u.u_arg, callp->sy_narg*NBPW); u.u_r.r_val1 = 0; u.u_r.r_val2 = r1; if (setjmp(&u.u_qsave)) { if (u.u_error == 0 && u.u_eosys != RESTARTSYS) u.u_error = EINTR; } else { u.u_eosys = NORMALRETURN; (*callp->sy_call)(); #ifdef DIAGNOSTIC if (hasmap) panic("hasmap"); #endif } if (u.u_eosys == NORMALRETURN) { if (u.u_error) { ps |= PSL_C; r0 = u.u_error; } else { ps &= ~PSL_C; r0 = u.u_r.r_val1; r1 = u.u_r.r_val2; } } else if (u.u_eosys == RESTARTSYS) pc = opc; /* back up pc to restart syscall */ /* else if (u.u_eosys == JUSTRETURN) */ /* nothing to do */ if (u.u_procp->p_cursig || ISSIG(u.u_procp)) psig(); curpri = setpri(u.u_procp); if (runrun) { setrq(u.u_procp); u.u_ru.ru_nivcsw++; swtch(); } if (u.u_prof.pr_scale) addupc(pc, &u.u_prof, (int)(u.u_ru.ru_stime - syst)); if (u.u_fpsaved) restfp(&u.u_fps); } /* * nonexistent system call-- signal process (may want to handle it) * flag error if process won't see signal immediately * Q: should we do that all the time ?? */ nosys() { if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD) u.u_error = EINVAL; psignal(u.u_procp, SIGSYS); } * 7: not a legal FEC code */ FPE_FLTOVF_TRAP, /* 8: floating overflow */ FPE_CRAZY, /* 9: not a legal FEC code */ FPE_CRAZY, /* 10: not a legal FEC code */ FPsys/pdp/enable34.c 440 0 12 7340 4174163231 7171 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)enable34.c 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * All information relevant to the ENABLE/34 is supplied with * the permission of ABLE Computer and may not be disclosed in * any manner to sites not licensed by the University of California * for the Second Berkeley Software Distribution. * * ENABLE/34 support routines. * Warning: if part of an overlaid kernel, this module must be * loaded in the base segment. */ #include "param.h" #ifdef ENABLE34 #include "systm.h" #include "dir.h" #include "user.h" #include "inode.h" #include "proc.h" #include "seg.h" #include "iopage.h" #include "enable34.h" /* * Turn on an ENABLE/34 and fudge the PARs to achieve the ``nominal map,'' * i.e. 0163700 - 0163716: KISA0 - KISA7 * 0163720 - 0163736: UISA0 - UISA7 * 0163740 - 0163756: UDSA0 - UDSA7 * 0163760 - 0163776: KDSA0 - KDSA7 * * Assumes that DEC memory management is already on. This routine * cannot be interruptible since we might be changing PARs which * point to overlay pages. */ /* * Shorthand: */ #define A ((u_short *) 0163700) /* ENABLE/34 PARs */ #define KI ((u_short *) 0172340) /* DEC Kernel I PARs */ #ifndef KERN_NONSEP #define KD ((u_short *) 0172360) /* DEC Kernel D PARs */ #else #define KD KI /* DEC Kernel D PARs */ #endif #define UI ((u_short *) 0177640) /* DEC User I PARs */ #ifdef NONSEPARATE #define UD ((u_short *) 0177660) /* DEC User D PARs */ #else #define UD UI /* DEC User D PARs */ #endif void enableon() { register i, s; extern bool_t enable34; if (!enable34) panic ("enableon"); else if (*ENABLE_SSR4) return; else s = splhigh(); for (i = 0; i < 31; i++) A[i] = (u_short) 0200 * (u_short) i; A[31] = (u_short) 0200 * (u_short) 0511; /* * Ok so far because the ENABLE mapping is not turned on. * Since the above map is the identity map, turning on * ENABLE mapping will cause no harm. */ *ENABLE_SSR3 = ENABLE_SSR3_PARS_ON | ENABLE_SSR3_UBMAP_ON; *ENABLE_SSR4 |= ENABLE_SSR4_MAP_ON; for (i = 0; i < 7; i++) A[i + 24] = sep_id ? KD[i] : KI[i]; for (i = 0; i < 8; i++) A[i + 16] = KI[i]; /* * Wiggle around changing DEC PARs to the nominal map. This is * possible because we have extra A[] entries to use. Even though * the values of A[] and K?[] change, A[K?[]] is unchanged. */ for (i = 0; i < 8; i++) { #ifndef KERN_NONSEP KD[i] = (u_short) 0200 * (u_short) (i + 24); #endif KI[i] = (u_short) 0200 * (u_short) (i + 16); A[i] = A[i + 16]; KI[i] = (u_short) 0200 * (u_short) i; } /* * The kernel mode part of the nominal map has been established. * Now do the user mode part. This is much easier. */ for (i = 0; i < 8; i++) { A[i + 8] = UI[i]; A[i + 16] = sep_id ? UD[i] : UI[i]; #ifndef NONSEPARATE UI[i] = (u_short) 0200 * (u_short) (i + 8); if (sep_id) #endif UD[i] = (u_short) 0200 * (u_short) (i + 16); } for (i = 0; i < 32; i++) if (A[i] == 07600) A[i] = (u_short) 0200 * (u_short) 511; splx(s); } /* * Routines for probing the I/O page. We must repoint the DEC * segmentation registers because of the second level of indirection * introduced by the ENABLE/34 segmentation registers. These routines * cannot be interruptible. */ #define MapUI7 \ register saveuisa7 = *DEC_UISA7; \ register s = splhigh(); \ *DEC_UISA7 = 0177600; #define UnmapUI7 \ *DEC_UISA7 = saveuisa7; \ splx (s); fiobyte (addr) { register val; MapUI7; val = fuibyte (addr); UnmapUI7; return (val); } fioword (addr) { register val; MapUI7; val = fuiword (addr); UnmapUI7; return (val); } #endif ENABLE34 i = SIGBUS; break; case T_INSTRAP + USER: #if defined(FPSIM) || defined(GENERIC) /* * If no floating point hardware is present, see if the * offending instruction was a floating point instruction ... */ if (fpp == 0) { i = fptrap(); #ifdef UCB_METER if (i != SIGsys/pdp/machdep.c 640 0 12 14125 5321523337 7220 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)machdep.c 2.1 (2.11BSD) 1/3/93 */ #include "param.h" #include "../machine/psl.h" #include "../machine/reg.h" #include "user.h" #include "proc.h" #include "buf.h" #include "map.h" #include "uba.h" #ifdef CURRENTLY_EXPANDED_INLINE /* * Clear registers on exec */ setregs(entry) u_int entry; { u.u_ar0[PC] = entry & ~01; u.u_fps.u_fpsr = 0; } #endif /* * Send an interrupt to process. * * Stack is set up to allow trampoline code stored at u.u_pcb.pcb_sigc (as * specified by the user process) to call the user's real signal catch * routine, followed by sys sigreturn to the sigreturn routine below (see * /usr/src/lib/libc/pdp/sys/sigvec.s). After sigreturn resets the signal * mask, the stack, and the frame pointer, it returns to the user specified * pc, ps. */ sendsig(p, sig, mask) int (*p)(), sig; long mask; { struct sigframe { int sf_signum; int sf_code; struct sigcontext *sf_scp; struct sigcontext sf_sc; }; struct sigframe sf; register struct sigframe *sfp = &sf; register struct sigcontext *scp = &sf.sf_sc; register int *regs; int oonstack; caddr_t n; regs = u.u_ar0; oonstack = u.u_onstack; /* * Allocate and validate space for the signal frame. */ if (!u.u_onstack && (u.u_sigonstack & sigmask(sig))) { n = (caddr_t)((struct sigframe *)u.u_sigsp - 1); u.u_onstack = 1; } else n = (caddr_t)((struct sigframe *)regs[R6] - 1); if (!u.u_onstack && n < (caddr_t)-ctob(u.u_ssize) && !grow(n)) { /* * Process has trashed its stack; give it an segment * violation to halt it in its tracks. */ u.u_signal[SIGILL] = SIG_DFL; mask = sigmask(SIGILL); u.u_procp->p_sigignore &= ~mask; u.u_procp->p_sigcatch &= ~mask; u.u_procp->p_sigmask &= ~mask; psignal(u.u_procp, SIGILL); return; } /* * Build the argument list for the signal handler. */ sfp->sf_signum = sig; if (sig == SIGILL || sig == SIGFPE) { sfp->sf_code = u.u_code; u.u_code = 0; } else sfp->sf_code = 0; sfp->sf_scp = (struct sigcontext *) (n + (u_int)&((struct sigframe *)0)->sf_sc); /* * Build the signal context to be used by sigreturn. */ scp->sc_onstack = oonstack; scp->sc_mask = mask; scp->sc_sp = regs[R6]; scp->sc_fp = regs[R5]; scp->sc_r1 = regs[R1]; scp->sc_r0 = regs[R0]; scp->sc_pc = regs[R7]; scp->sc_ps = regs[RPS]; scp->sc_ovno = u.u_ovdata.uo_ovbase ? u.u_ovdata.uo_curov : 0; copyout((caddr_t)sfp, n, sizeof(*sfp)); regs[R0] = (int)p; regs[R6] = (int)n; regs[R7] = (int)u.u_pcb.pcb_sigc; regs[RPS] &= ~PSL_T; } /* * System call to cleanup state after a signal * has been taken. Reset signal mask and * stack state from context left by sendsig (above). * Return to previous pc and ps as specified by * context left by sendsig. Check carefully to * make sure that the user has not modified the * ps to gain improper priviledges or to cause * a machine fault. */ sigreturn() { struct a { struct sigcontext *scp; }; struct sigcontext sc; register struct sigcontext *scp = ≻ register int *regs = u.u_ar0; u.u_error = copyin((caddr_t)((struct a *)u.u_ap)->scp, (caddr_t *)scp, sizeof(*scp)); if (u.u_error) return; if ((scp->sc_ps & PSL_USERCLR) != 0 || !USERMODE(scp->sc_ps)) { u.u_error = EINVAL; return; } u.u_eosys = JUSTRETURN; u.u_onstack = scp->sc_onstack & 01; u.u_procp->p_sigmask = scp->sc_mask &~ (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP)); regs[R6] = scp->sc_sp; regs[R5] = scp->sc_fp; regs[R1] = scp->sc_r1; regs[R0] = scp->sc_r0; regs[R7] = scp->sc_pc; regs[RPS] = scp->sc_ps; } #define UMAPSIZ 10 struct mapent _ubmap[UMAPSIZ]; struct map ub_map[1] = { &_ubmap[0], &_ubmap[UMAPSIZ], "ub_map" }; int ub_wantmr; #ifdef UCB_METER struct ubmeter ub_meter; #endif /* * Routine to allocate the UNIBUS map and initialize for a UNIBUS device. * For buffers already mapped by the UNIBUS map, perform the physical to * UNIBUS-virtual address translation. */ mapalloc(bp) register struct buf *bp; { register struct ubmap *ubp; register int ub_nregs; ubadr_t ubaddr; long paddr; int s, ub_first; if (!ubmap) return; #ifdef UCB_METER ++ub_meter.ub_calls; #endif paddr = ((long)((u_int)bp->b_xmem)) << 16 | ((long)((u_int)bp->b_un.b_addr)); if (!(bp->b_flags & B_PHYS)) { /* * Transfer in the buffer cache. * Change the buffer's physical address * into a UNIBUS address for the driver. */ #ifdef UCB_METER ++ub_meter.ub_remaps; #endif ubaddr = paddr - (((ubadr_t)bpaddr) << 6) + BUF_UBADDR; bp->b_un.b_addr = (caddr_t)loint(ubaddr); bp->b_xmem = hiint(ubaddr); bp->b_flags |= B_UBAREMAP; } else { /* * Physical I/O. * Allocate a section of the UNIBUS map. */ ub_nregs = (int)btoub(bp->b_bcount); #ifdef UCB_METER ub_meter.ub_pages += ub_nregs; #endif s = splclock(); while (!(ub_first = malloc(ub_map,ub_nregs))) { #ifdef UCB_METER ++ub_meter.ub_fails; #endif ub_wantmr = 1; sleep(ub_map, PSWP + 1); } splx(s); ubp = &UBMAP[ub_first]; bp->b_xmem = ub_first >> 3; bp->b_un.b_addr = (caddr_t)((ub_first & 07) << 13); bp->b_flags |= B_MAP; while (ub_nregs--) { ubp->ub_lo = loint(paddr); ubp->ub_hi = hiint(paddr); ubp++; paddr += (ubadr_t)UBPAGE; } } } mapfree(bp) register struct buf *bp; { register int s; ubadr_t ubaddr; long paddr; if (bp->b_flags & B_MAP) { /* * Free the UNIBUS map registers * allocated to this buffer. */ s = splclock(); mfree(ub_map, (size_t)btoub(bp->b_bcount), (bp->b_xmem << 3) | (((u_int)bp->b_un.b_addr >> 13) & 07)); splx(s); bp->b_flags &= ~B_MAP; if (ub_wantmr) wakeup((caddr_t) ub_map); ub_wantmr = 0; } else if (bp->b_flags & B_UBAREMAP) { /* * Translate the UNIBUS virtual address of this buffer * back to a physical memory address. */ ubaddr = ((long)((u_int) bp->b_xmem)) << 16 | ((long)((u_int)bp->b_un.b_addr)); paddr = ubaddr - (long)BUF_UBADDR + (((long)bpaddr) << 6); bp->b_un.b_addr = (caddr_t)loint(paddr); bp->b_xmem = hiint(paddr); bp->b_flags &= ~B_UBAREMAP; } } )n; regs[R7] = (int)u.u_pcb.pcb_sigc; regs[RPS] &= ~PSL_T; } /* * System call to cleanup state after a signal * has been taken. Reset signal mask and * stack state from context left by sendsig (above). * Return to previous pc and ps as specified by * context left by sendsig. Check carefully to * make sure that the user has not modified the * ps to gain improper priviledges or to cause * a machine fault. */ sigrsys/pdp/mch_backup.s 440 0 12 13772 5317201566 7742 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)mch_backup.s 1.2 (2.11BSD GTE) 12/26/92 */ #include "DEFS.h" SPACE(GLOBAL, ssr, 3*2) / contents of MM registers SSR0-2 / after trap /* * unwind(ar0::r0, mod::r1) * caddr_t ar0; * u_char mod; * * Unwind a register modification from a partially completed aborted * instruction. Ar0 is the address of the user's register r0 as saved in * the stack (_regloc contains the relative indexes of the the user's * registers from ar0). Mod contains a register modification recorded as: * * 7 3 2 0 * +------------------------+ * | displacement | reg | * +------------------------+ * * where "reg" is the index of the modified register and displacement is * the 2's complement displacement of the modification. */ unwind: mov r1,-(sp) / grab displacement asr (sp) / tmp = mod >> 3 { signed shift } asr (sp) asr (sp) bic $!7,r1 / mod = _regloc[mod&7] * sizeof(int) movb _regloc(r1),r1 asl r1 add r0,r1 / ar0[mod] -= tmp sub (sp)+,(r1) rts pc /* * backup(ar0) * caddr_t ar0; * * Back up user CPU state after aborted instruction. Called from trap when * attempting an automatic stack grow to restore the user's state prior to * a stack fault. Returns zero if successful. */ #ifndef KERN_NONSEP /* * Backup routine for use with machines with SSR1 and SSR2 (saved in ssr+2 * and ssr+4 by trap). SSR1 records any auto-increments and/or decrements * that were already performed for the aborted instruction. SSR2 holds * the adddress of the instruction which faulted. */ ENTRY(backup) mov 2(sp),r0 / r0 = ar0 movb ssr+2,r1 / undo first register modification from jsr pc,unwind / saved SSR1 movb ssr+3,r1 / and second ... jsr pc,unwind movb _regloc+7,r1 / ar0[_regloc[PC] * sizeof(int)] asl r1 / = saved SSR2 add r0,r1 mov ssr+4,(r1) clr r0 / and return success rts pc #else KERN_NONSEP /* * 11/40 version of backup, for use with no SSR1 and SSR2. Actually SSR1 * usually exists for all processors except the '34 and '40 but always * reads as zero on those without separate I&D ... */ .bss bflg: .=.+1 jflg: .=.+1 fflg: .=.+1 .text ENTRY(backup) mov 2(sp),ssr+2 / pass ar0 to the real backup routine mov r2,-(sp) / backup needs an extra register jsr pc,backup mov r2,ssr+2 / save computed register modification mov (sp)+,r2 / mask and restore r2 movb jflg,r0 / if backup failed, return failure bne 1f mov 2(sp),r0 / r0 = ar0 movb ssr+2,r1 / undo register modifications jsr pc,unwind movb ssr+3,r1 jsr pc,unwind movb _regloc+7,r1 / ar0[_regloc[PC] * sizeof(int)] = asl r1 / computed fault pc add r0,r1 mov ssr+4,(r1) clr r0 / and indicate success 2: rts pc /* * Hard part: simulate the ssr2 register missing on 11/40 and similar * processors. */ backup: clr r2 / backup register ssr1 mov $1,bflg / clrs jflg clrb fflg mov ssr+4,r0 jsr pc,fetch mov r0,r1 ash $-11.,r0 bic $!36,r0 jmp *0f(r0) 0: t00; t01; t02; t03; t04; t05; t06; t07 t10; t11; t12; t13; t14; t15; t16; t17 t00: clrb bflg t10: mov r1,r0 swab r0 bic $!16,r0 jmp *0f(r0) 0: u0; u1; u2; u3; u4; u5; u6; u7 u6: / single op, m[tf]pi, sxt, illegal bit $400,r1 beq u5 / all but m[tf], sxt bit $200,r1 beq 1f / mfpi bit $100,r1 bne u5 / sxt / Simulate mtpi with double (sp)+,dd. bic $4000,r1 / turn instr into (sp)+ br t01 / Simulate mfpi with double ss,-(sp). 1: ash $6,r1 bis $46,r1 / -(sp) br t01 u4: / jsr mov r1,r0 jsr pc,setreg / assume no fault bis $173000,r2 / -2 from sp rts pc t07: / EIS clrb bflg u0: / jmp, swab u5: / single op f5: / movei, movfi ff1: / ldfps ff2: / stfps ff3: / stst mov r1,r0 br setreg t01: / mov t02: / cmp t03: / bit t04: / bic t05: / bis t06: / add t16: / sub clrb bflg t11: / movb t12: / cmpb t13: / bitb t14: / bicb t15: / bisb mov r1,r0 ash $-6,r0 jsr pc,setreg swab r2 mov r1,r0 jsr pc,setreg / If delta(dest) is zero, no need to fetch source. bit $370,r2 beq 1f / If mode(source) is R, no fault is possible. bit $7000,r1 beq 1f / If reg(source) is reg(dest), too bad. mov r2,-(sp) bic $174370,(sp) cmpb 1(sp),(sp)+ beq u7 / Start source cycle. Pick up value of reg. mov r1,r0 ash $-6,r0 bic $!7,r0 movb _regloc(r0),r0 asl r0 add ssr+2,r0 mov (r0),r0 / If reg has been incremented, must decrement it before fetch. bit $174000,r2 ble 2f dec r0 bit $10000,r2 beq 2f dec r0 2: / If mode is 6,7 fetch and add X(R) to R. bit $4000,r1 beq 2f bit $2000,r1 beq 2f mov r0,-(sp) mov ssr+4,r0 add $2,r0 jsr pc,fetch add (sp)+,r0 2: / Fetch operand. If mode is 3, 5, or 7, fetch *. jsr pc,fetch bit $1000,r1 beq 1f bit $6000,r1 bne fetch 1: rts pc t17: / floating point instructions clrb bflg mov r1,r0 swab r0 bic $!16,r0 jmp *0f(r0) 0: f0; f1; f2; f3; f4; f5; f6; f7 f0: mov r1,r0 ash $-5,r0 bic $!16,r0 jmp *0f(r0) 0: ff0; ff1; ff2; ff3; ff4; ff5; ff6; ff7 f1: / mulf, modf f2: / addf, movf f3: / subf, cmpf f4: / movf, divf ff4: / clrf ff5: / tstf ff6: / absf ff7: / negf inc fflg mov r1,r0 br setreg f6: bit $400,r1 beq f1 / movfo br f5 / movie f7: bit $400,r1 beq f5 / movif br f1 / movof ff0: / cfcc, setf, setd, seti, setl u1: / br u2: / br u3: / br u7: / illegal incb jflg rts pc setreg: mov r0,-(sp) bic $!7,r0 bis r0,r2 mov (sp)+,r0 ash $-3,r0 bic $!7,r0 movb 0f(r0),r0 tstb bflg beq 1f bit $2,r2 beq 2f bit $4,r2 beq 2f 1: cmp r0,$20 beq 2f cmp r0,$-20 beq 2f asl r0 2: tstb fflg beq 3f asl r0 stfps r1 bit $200,r1 beq 3f asl r0 3: bisb r0,r2 rts pc 0: .byte 0,0,10,20,-10,-20,0,0 fetch: bic $1,r0 mov nofault,-(sp) mov $1f,nofault mfpi (r0) mov (sp)+,r0 mov (sp)+,nofault rts pc 1: mov (sp)+,nofault clrb r2 / clear out dest on fault mov $-1,r0 rts pc #endif KERN_NONSEP ating sys/pdp/mch_click.s 440 0 12 16113 5351510055 7544 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)mch_click.s 1.3 (2.11BSD GTE) 3/16/93 */ #include "DEFS.h" #include "../machine/mch_iopage.h" /* * copy(src, dst, count) * memaddr src, dst; * int count; * * Copy count clicks from src to dst. Uses KDSA5 and 6 to copy with mov * instructions. Interrupt routines must restore segmentation registers * if needed; see seg.h. */ ENTRY(copy) jsr r5, csv #ifdef INET mov PS,-(sp) / have to lock out interrupts... bit $0340,(sp) / Are we currently at spl0? bne 1f SPLNET / No, lock out network interrupts. 1: #endif mov KDSA5,-(sp) / saveseg5(sp) mov KDSD5,-(sp) mov 10(r5),r3 / r3 = count beq 3f / (exit early if zero) mov 4(r5),KDSA5 / seg5 = (src, 1 click read only) mov $RO,KDSD5 mov sp,r4 / save current sp mov $eintstk,sp / and switch to intstk mov KDSA6,_kdsa6 / save u area address, mark as mapped mov 6(r5),KDSA6 / out and seg6 = (dst, 1 click read/ mov $RW,KDSD6 / write) 1: mov $5*8192.,r0 / r0 = SEG5 { src } mov $6*8192.,r1 / r1 = SEG6 { dst } mov $8.,r2 / copy one click (8*8) 2: mov (r0)+,(r1)+ mov (r0)+,(r1)+ mov (r0)+,(r1)+ mov (r0)+,(r1)+ sob r2,2b inc KDSA5 / next click inc KDSA6 sob r3,1b mov _kdsa6,KDSA6 / restore u area mapping mov $USIZE-1\<8|RW, KDSD6 clr _kdsa6 mov r4,sp / back to normal stack 3: mov (sp)+,KDSD5 / restorseg5(sp) mov (sp)+,KDSA5 #ifdef INET mov (sp)+,PS / back to normal priority #endif jmp cret /* * Clear count clicks at dst. Uses KDSA5. Interrupt routines must restore * segmentation registers if needed; see seg.h. * * clear(dst, count) * memaddr dst; * u_int count; */ ENTRY(clear) jsr r5, csv mov KDSA5,-(sp) / saveseg5(sp) mov KDSD5,-(sp) mov 4(r5),KDSA5 / point KDSA5 at source mov $RW,KDSD5 / 64 bytes, read-write mov 6(r5),r3 / count beq 3f 1: mov $5*8192.,r0 / point r0 at KDSA5 map mov $8.,r2 / clear one click (8*8) 2: clr (r0)+ clr (r0)+ clr (r0)+ clr (r0)+ sob r2,2b inc KDSA5 / next click sob r3,1b 3: mov (sp)+,KDSD5 / restore seg5 mov (sp)+,KDSA5 / restore seg5 jmp cret #ifdef INET /* * copyv(fromaddr, toaddr, count) * virtual_addr fromaddr, * toaddr; * u_int count; * * typedef struct { * memaddr click; * u_int offset; * } virtual_addr; * * Copy two arbitrary pieces of PDP11 virtual memory from one location * to another. Up to 8K bytes can be copied at one time. * * A PDP11 virtual address is a two word value; a 16 bit "click" that * defines the start in physical memory of an 8KB segment and an offset. */ ENTRY(copyv) mov 10.(sp),r0 / exit early if count == 0 or >= 8K beq 4f cmp r0,$8192. bhis 4f mov r2,-(sp) / need a register for the stack switch /* * Note: the switched stack is only for use of a fatal kernel trap * occurring during the copy; otherwise we might conflict with the * other copy routines. */ mov sp,r2 / switch stacks cmp sp,$eintstk / are we already in the intstk? blo 1f mov $eintstk,sp / No, point sp to intstk 1: mov PS,-(sp) / save current PS bit $0340,(sp) / are we currently at SPL? bne 2f SPLNET / nope, lock out the network 2: mov KDSA5,-(sp) / save seg5 mov KDSD5,-(sp) mov _kdsa6,-(sp) / save the current saved kdsa6 bne 3f / was it set to anything? mov KDSA6,_kdsa6 / nope, set it to the current kdsa6 3: mov KDSA6,-(sp) / save user area mov KDSD6,-(sp) mov r2,r0 / set up bcopy arguments on new stack add $14.,r0 / and grab click addresses ... mov -(r0),-(sp) / copy count mov -(r0),-(sp) / copy and translate toaddr.offset add $6*8192.,(sp) mov -(r0),r1 / pick up and save toaddr.click mov -(r0),-(sp) / copy and translate fromaddr.offset add $5*8192.,(sp) mov -(r0),KDSA5 / use fromaddr.click to remap seg5 mov $128.-1\<8.|RO,KDSD5 / for 8K read-only mov r1,KDSA6 / use toaddr.click to remap seg6 mov $128.-1\<8.|RW,KDSD6 / for 8K read/write jsr pc,_bcopy / finally, do the copy add $6.,sp / toss the arguments to bcopy mov (sp)+,KDSD6 / restore user area mov (sp)+,KDSA6 mov (sp)+,_kdsa6 / restore old _kdsa6 value mov (sp)+,KDSD5 / restore seg5 mov (sp)+,KDSA5 mov (sp)+,PS / unlock interrupts mov r2,sp / restore stack pointer and retrieve mov (sp)+,r2 / old register value 4: clr r0 / clear r0 and r1 (why?) rts pc / and return #endif /* * fmove(par, pdr, from, to, length) * u_short par, pdr; * caddr_t from, to; * u_short length; * * Map the par/pdr into segment 6 and perform a bcopy(from, to, length). * Returns zero on success, EFAULT on failure. See uiofmove for more * information. * * As written, fmove may only be called from the high kernel and is *not* * re-entrant: it doesn't save the previous fault trap, uses the intstk and * kdsa6 without checking to see if they're already in use (see the fault * handler at 2f below) and assumes that a user structure is currently mapped * in (see the restore of KDSD6 below). */ ENTRY(fmove) mov r2,-(sp) / need a few registers for the mov r3,-(sp) / copy and stack switch mov r4,-(sp) mov sp,r4 / switch stacks (SEG6 is out) mov $eintstk,sp mov r4,r0 / grab parameters add $8.,r0 mov (r0)+,-(sp) / push par and pdr onto new stack mov (r0)+,-(sp) mov (r0)+,r1 / r1 = from mov (r0)+,r2 / r2 = to mov (r0),r0 / r0 = length mov KDSA6,_kdsa6 / save current segment 6 mapping mov (sp)+,KDSD6 / passed par/pdr mov (sp)+,KDSA6 / and map segment 6 with the mov $8f,nofault / catch any faults during the copy, /* * The following code has been lifted almost intact from "bcopy". * The biggest reason is for error recovery in the case of a user * memory fault. */ tst r0 / if (length == 0) beq 7f / return cmp r0,$10. / if (length > 10) bhi 2f / try words 1: movb (r1)+,(r2)+ / do *dst++ = *src++ sob r0,1b / while (--length) br 7f 2: bit $1,r1 / if (src&1 != dst&1) beq 3f / do bytes bit $1,r2 beq 1b / (src odd, dst even - do bytes) movb (r1)+,(r2)+ / copy leading odd byte dec r0 br 4f 3: bit $1,r2 bne 1b / (src even, dst odd - do bytes) 4: mov r0,r3 / save trailing byte indicator clc ror r0 / length >>= 1 (unsigned) asr r0 / if (length >>= 1, wasodd(length)) bcc 5f / handle leading non multiple of four mov (r1)+,(r2)+ 5: asr r0 / if (length >>= 1, wasodd(length)) bcc 6f / handle leading non multiple of eight mov (r1)+,(r2)+ mov (r1)+,(r2)+ 6: mov (r1)+,(r2)+ / do mov (r1)+,(r2)+ / move eight bytes mov (r1)+,(r2)+ mov (r1)+,(r2)+ sob r0,6b / while (--length) asr r3 / if (odd trailing byte) bcc 7f movb (r1)+,(r2)+ / copy it /* * End of stolen bcopy code. */ 7: clr nofault / clear the fault trap and return / status (zero from successful copy) mov _kdsa6,KDSA6 / restore the previous segment 6 mov $USIZE-1\<8|RW, KDSD6 / mapping (user structure) clr _kdsa6 / (segment 6 not mapped out any more) mov r4,sp / restore previous stack pointer mov (sp)+,r4 / and saved registers mov (sp)+,r3 mov (sp)+,r2 rts pc / and return 8: mov $EFAULT,r0 / copy failed, return EFAULT br 7b L+SUPV: case T_SWITCHTRAP+SUPV: case T_ZEROTRAP+SUPV: case T_RANDOMTRAP+SUPV: i = splhigh(); if (!netoff) { netoff = 1; savestate(); } printf("Unexpected net code trap (%o)\n", dev-SUPV); printf("ka6 = %o\n", *ka6); printf("aps = %o\n", &ps); printf("pc = %o ps = %o\n", pc, ps); splx(i); panic("net crashed"); /*NOTREACHED*/ #endif /* * Whenever possible, locations 0-2 specify this style trap, since sys/pdp/clock.c 440 0 12 1632 4020776713 6672 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)clock.c 1.1 (2.10BSD Berkeley) 12/1/86 */ #include "param.h" #include "clock.h" clkstart() { register u_short *lks; lks = LKS; if (fioword((caddr_t)lks) == -1) { lks = KW11P_CCSR; if (fioword((caddr_t)lks) == -1) { printf("no clock!!"); return; } *KW11P_CCNT = 0; *KW11P_CCSB = 1; *lks = K_IENB | K_LFRATE | K_MODE | K_RUN; } else *lks = K_IENB; } #if defined(PROFILE) && !defined(ENABLE34) /* * Profiling expects to have a KW11-P in addition to the * line-frequency clock, and it should enter at BR7. */ isprof() { if (fioword((caddr_t)KW11P_CCSR) == -1) panic("no profile clock"); *KW11P_CCSB = 100; /* count set = 100 */ *KW11P_CCSR = K_IENB | K_10KRATE | K_MODE | K_RUN; } #endif / save current sp mov $eintstk,sp / and switch to intstk mov KDSA6,_kdsa6 / save u area addressys/pdp/genassym.c 440 0 12 5443 5317241635 7431 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)genassym.c 1.1 (2.10BSD Berkeley) 6/12/88 */ #include "param.h" #include "../machine/seg.h" #include "user.h" #include "inode.h" #include "mbuf.h" #include "buf.h" #include "proc.h" #include "errno.h" #include "reboot.h" #include "syscall.h" #include "vm.h" #include "dz.h" #include "../net/netisr.h" #include struct proc proc[1]; /* satisfy proc.h and inode.h */ struct inode inode[1]; struct buf buf[1]; main() { { struct buf *bp = 0; printf("#define B_ADDR %o\n",&bp->b_un.b_addr); printf("#define B_XMEM %o\n",&bp->b_xmem); } { segm *se = 0; printf("#define SE_ADDR %o\n",&se->se_addr); printf("#define SE_DESC %o\n",&se->se_desc); } { struct user *u = 0; printf("#define U_AR0 %o\n",&u->u_ar0); printf("#define U_CUROV %o\n",&u->u_ovdata.uo_curov); printf("#define U_FPERR %o\n",&u->u_fperr); printf("#define U_FPREGS %o\n",&u->u_fps.u_fpregs[0]); printf("#define U_FPSR %o\n",&u->u_fps.u_fpsr); printf("#define U_OVBASE %o\n",&u->u_ovdata.uo_ovbase); printf("#define U_RU %o\n",&u->u_ru); printf("#define U_PROCP %o\n",&u->u_procp); printf("#define U_SSIZE %o\n",&u->u_ssize); printf("#define U_STACK %o\n",u->u_stack); } { struct fperr *f = 0; printf("#define F_FEC %o\n",&f->f_fec); printf("#define F_FEA %o\n",&f->f_fea); } { struct k_rusage *ru = 0; printf("#define RU_OVLY %o\n",&ru->ru_ovly); } { struct vmrate *vm = 0; printf("#define V_INTR %o\n",&vm->v_intr); printf("#define V_SOFT %o\n",&vm->v_soft); printf("#define V_PDMA %o\n",&vm->v_pdma); printf("#define V_OVLY %o\n",&vm->v_ovly); } printf("#define NET_SBASE [_u+%d.]\n",NET_SBASE); printf("#define NET_STOP [_u+%d.]\n",NET_STOP); printf("#define KERN_SBASE [_u+%d.]\n",KERN_SBASE); printf("#define KERN_STOP [_u+%d.]\n",KERN_STOP); printf("#define DEV_BSIZE %d.\n",DEV_BSIZE); printf("#define EFAULT %d.\n",EFAULT); printf("#define ENOENT %d.\n",ENOENT); printf("#define MAXBSIZE %d.\n",MAXBSIZE); printf("#define NETISR_IMP %d.\n",NETISR_IMP); printf("#define NETISR_IP %d.\n",NETISR_IP); printf("#define NETISR_NS %d.\n",NETISR_NS); printf("#define NETISR_RAW %d.\n",NETISR_RAW); printf("#define NETISR_CLOCK %d.\n",NETISR_CLOCK); printf("#define NOVL %d.\n",NOVL); printf("#define RB_POWRFAIL %d.\n",RB_POWRFAIL); printf("#define RB_SINGLE %d.\n",RB_SINGLE); printf("#define SIGFPE %d.\n",SIGFPE); printf("#define SIGILL %d.\n",SIGILL); printf("#define SIGSEGV %d.\n",SIGSEGV); printf("#define SIGTRAP %d.\n",SIGTRAP); printf("#define SYS_execv %d.\n",SYS_execv); printf("#define SYS_exit %d.\n",SYS_exit); printf("#define USIZE %d.\n",USIZE); exit(0); } dr; * u_int count; * * typedef struct { * memaddr click; * u_int offset; * } virtual_addr; * * Copy two arbitrary pieces of PDP11 virtual memory from one location * to another. Up to 8K bytes can be copied at osys/pdp/mem.c 440 0 12 4231 5667011655 6360 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)mem.c 1.2 (2.11BSD GTE) 11/29/94 */ #include "param.h" #include "../machine/seg.h" #include "user.h" #include "conf.h" #include "uio.h" #include "hk.h" #include "xp.h" /* * This routine is callable only from the high * kernel as it assumes normal mapping and doesn't * bother to save 'seg5'. */ mmrw(dev, uio, flag) dev_t dev; register struct uio *uio; int flag; { register struct iovec *iov; int error = 0; register u_int c; u_int on; while (uio->uio_resid && error == 0) { iov = uio->uio_iov; if (iov->iov_len == 0) { uio->uio_iov++; uio->uio_iovcnt--; if (uio->uio_iovcnt < 0) panic("mmrw"); continue; } switch (minor(dev)) { /* minor device 0 is physical memory */ case 0: mapseg5((memaddr)(uio->uio_offset>>6), ((btoc(8192)-1)<<8)|RW); on = uio->uio_offset & 077L; c = MIN(iov->iov_len, 8192 - on); error = uiomove(SEG5+on, c, uio); normalseg5(); continue; /* minor device 1 is kernel memory */ case 1: error = uiomove((caddr_t)uio->uio_offset, iov->iov_len, uio); continue; /* minor device 2 is EOF/RATHOLE */ case 2: if (uio->uio_rw == UIO_READ) return(0); c = iov->iov_len; break; } if (error) break; iov->iov_base += c; iov->iov_len -= c; uio->uio_offset += c; uio->uio_resid -= c; } return(error); } #if NHK > 0 || NXPD > 0 /* * Internal versions of mmread(), mmwrite() * used by disk driver ecc routines. */ getmemc(addr) long addr; { register int a, c, d; /* * bn = addr >> 6 * on = addr & 077 */ a = UISA[0]; d = UISD[0]; UISA[0] = addr >> 6; UISD[0] = RO; /* one click, read only */ c = fuibyte((caddr_t)(addr & 077)); UISA[0] = a; UISD[0] = d; return(c); } putmemc(addr,contents) long addr; int contents; { register int a, d; /* * bn = addr >> 6 * on = addr & 077 */ a = UISA[0]; d = UISD[0]; UISA[0] = addr >> 6; UISD[0] = RW; /* one click, read/write */ suibyte((caddr_t)(addr & 077), contents); UISA[0] = a; UISD[0] = d; } #endif intf("#define SYS_execv %d.\n",SYS_execv); printf("#define SYS_exit %d.\n",SYS_exit); printf("#define USIZE %d.\n",USIZE); exit(0); } dr; * u_int count; * * typedef struct { * memaddr click; * u_int offset; * } virtual_addr; * * Copy two arbitrary pieces of PDP11 virtual memory from one location * to another. Up to 8K bytes can be copied at osys/pdp/mch_copy.s 440 0 12 36412 5514077303 7442 /* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)mch_copy.s 1.3 (2.11BSD GTE) 1/9/94 */ #include "DEFS.h" #include "../machine/mch_iopage.h" /* * Fetch and set user byte routines: * fubyte(addr): fetch user data space byte * fuibyte(addr): fetch user instruction space byte * subyte(addr, byte): set user data space byte * suibyte(addr, byte): set user instruction space byte * caddr_t addr; * u_char byte; * * The fetch routines return the requested byte or -1 on fault. The set * routines return 0 on success, -1 on failure. The data space routines are * really the corresponding instruction space routines if NONSEPARATE is * defined. */ ENTRY(fubyte) #ifndef NONSEPARATE mov nofault,-(sp) / set fault trap mov $fsfault,nofault mov 4(sp),r1 bic $1,r1 / r1 = addr&~1 mfpd (r1) / tmp = user data word at (addr&~1) mov (sp)+,r0 cmp r1,4(sp) / if (addr&1) beq 1f / tmp >>= 8 swab r0 1: bic $!377,r0 / return((u_char)tmp) mov (sp)+,nofault / restore fault trap, and return rts pc #endif !NONSEPARATE ENTRY(fuibyte) mov nofault,-(sp) / set fault trap mov $fsfault,nofault mov 4(sp),r1 bic $1,r1 / r1 = addr&~1 mfpi (r1) / tmp = user instruction word at mov (sp)+,r0 / (addr&~1) cmp r1,4(sp) / if (addr&1) beq 1f / tmp >>= 8 swab r0 1: bic $!377,r0 / return((u_char)tmp) mov (sp)+,nofault / restore fault trap, and return rts pc ENTRY(subyte) #ifndef NONSEPARATE mov nofault,-(sp) / set fault trap mov $fsfault,nofault mov 4(sp),r1 bic $1,r1 / r1 = addr&~1 mfpd (r1) / tmp = user data word at (addr&~1) cmp r1,6(sp) / if (addr&1) beq 1f movb 10(sp),1(sp) / *((char *)tmp + 1) = byte br 2f 1: / else movb 10(sp),(sp) / *((char *)tmp) = byte 2: mtpd (r1) / user data word (addr&~1) = tmp clr r0 / return success mov (sp)+,nofault / restore fault trap, and return rts pc #endif !NONSEPARATE ENTRY(suibyte) mov nofault,-(sp) / set fault trap mov $fsfault,nofault mov 4(sp),r1 bic $1,r1 / r1 = addr&~1 mfpi (r1) / tmp = user instruction word at cmp r1,6(sp) / (addr&~1) beq 1f / if (addr&1) movb 10(sp),1(sp) / *((char *)tmp + 1) = byte br 2f 1: / else movb 10(sp),(sp) / *((char *)tmp) = byte 2: mtpi (r1) / user instruction word (addr&~1) = tmp clr r0 / return success mov (sp)+,nofault / restore fault trap, and return rts pc /* * Fetch and set user word routines: * fuiword(addr): fetch user instruction space word * fuword(addr): fetch user data space word * suiword(addr, word): set user instruction space word * suword(addr, word): set user data space word * caddr_t addr; * u_short word; * * The fetch routines return the requested word or -1 on fault. The set * routines return 0 on success, -1 on failure. Addr must be even. The data * space routines are really the corresponding instruction space routines if * NONSEPARATE is defined. */ ENTRY(fuword) #ifndef NONSEPARATE mov nofault,-(sp) / set fault trap mov $fsfault,nofault mov 4(sp),r1 / r1 = addr mfpd (r1) / r0 = user data word at addr mov (sp)+,r0 mov (sp)+,nofault / restore fault trap, and return rts pc #endif !NONSEPARATE ENTRY(fuiword) mov nofault,-(sp) / set fault trap mov $fsfault,nofault mov 4(sp),r1 / r1 = addr mfpi (r1) / r0 = user instruction word at addr mov (sp)+,r0 mov (sp)+,nofault / restore fault trap, and return rts pc ENTRY(suword) #ifndef NONSEPARATE mov nofault,-(sp) / set fault trap mov $fsfault,nofault mov 4(sp),r1 / r1 = addr mov 6(sp),-(sp) / user data word at addr = word mtpd (r1) clr r0 / resturn success mov (sp)+,nofault / restore fault trap, and return rts pc #endif !NONSEPARATE ENTRY(suiword) mov nofault,-(sp) / set fault trap mov $fsfault,nofault mov 4(sp),r1 / r1 = adddr mov 6(sp),-(sp) / user instruction word at addr = word mtpi (r1) clr r0 / return success mov (sp)+,nofault / restore fault trap, and return rts pc /* * Common fault trap for fetch/set user byte/word routines. Returns -1 to * indicate fault. Stack contains saved fault trap followed by return * address. */ fsfault: mov (sp)+,nofault / restore fault trap, mov $-1,r0 / return failure (-1) rts pc /* * copyin(fromaddr, toaddr, length) * caddr_t fromaddr, toaddr; * u_int length; * * copyiin(fromaddr, toaddr, length) * caddr_t fromaddr, toaddr; * u_int length; * * Copy length/2 words from user space fromaddr to kernel space address * toaddr. Fromaddr and toaddr must be even. Returns zero on success, * EFAULT on failure. Copyin copies from data space, copyiin from * instruction space. */ ENTRY(copyin) #ifndef NONSEPARATE jsr pc,copysetup / r1 = fromaddr, r2 = toaddr, 1: / r0 = length/2 mfpd (r1)+ / do mov (sp)+,(r2)+ / *toaddr++ = *fromaddr++ sob r0,1b / while (--length) br copycleanup #endif !NONSEPARATE ENTRY(copyiin) jsr pc,copysetup / r1 = fromaddr, r2 = toaddr, 1: / r0 = length/2 mfpi (r1)+ / do mov (sp)+,(r2)+ / *toaddr++ = *fromaddr++ sob r0,1b / while (--length) br copycleanup /* * copyout(fromaddr, toaddr, length) * caddr_t fromaddr, toaddr; * u_int length; * * copyiout(fromaddr, toaddr, length) * caddr_t fromaddr, toaddr; * u_int length; * * Copy length/2 words from kernel space fromaddr to user space address * toaddr. Fromaddr and toaddr must be even. Returns zero on success, * EFAULT on failure. Copyout copies to data space, copyiout to * instruction space. */ ENTRY(copyout) #ifndef NONSEPARATE jsr pc,copysetup / r1 = fromaddr, r2 = toaddr, 1: / r0 = length/2 mov (r1)+,-(sp) / do mtpd (r2)+ / *toaddr++ = *fromaddr++ sob r0,1b / while (--length) br copycleanup #endif !NONSEPARATE ENTRY(copyiout) jsr pc,copysetup / r1 = fromaddr, r2 = toaddr, 1: / r0 = length/2 mov (r1)+,-(sp) / do mtpi (r2)+ / *toaddr++ = *fromaddr++ sob r0,1b / while (--length) br copycleanup /* * Common set up code for the copy(in|out) routines. Performs zero length * check, set up fault trap, and loads fromaddr, toaddr and length into the * registers r1, r2 and r0 respectively. Leaves old values of r2 and * nofault on stack. */ copysetup: mov (sp)+,r0 / snag return address mov r2,-(sp) / reserve r2 for our use, mov nofault,-(sp) / save nofault so we can set our own mov r0,-(sp) / trap and push return address back mov $copyfault,nofault mov 14(sp),r0 / r0 = (unsigned)length/2 beq 1f / (exit early if length equals zero) asr r0 bic $100000,r0 mov 10(sp),r1 / r1 = fromaddr mov 12(sp),r2 / r2 = toaddr rts pc 1: tst (sp)+ / short circuit the copy for zero br copycleanup / length returning "success" ... copyfault: mov $EFAULT,r0 / we faulted out, return EFAULT /*FALLTHROUGH*/ /* * Common clean up code for the copy(in|out) routines. When copy routines * finish successfully r0 has already been decremented to zero which is * exactly what we want to return for success ... Tricky, hhmmm? */ copycleanup: mov (sp)+,nofault / restore fault trap, mov (sp)+,r2 / and reserved registers rts pc #ifdef INET /* * Kernel/Network copying routines. * * NOTE: * The m[ft]sd functions operate at high ipl. This is done mostly * because it's simpler to do a ``mov $10340,PS'' than ``bic $30000,PS; * bis $10000,PS''. But these functions will never take up enough time * to cause anyone any problems. * * WARNING: * All functions assume that the segments in supervisor space * containing the source or target variables are never remapped. * * void * mtsd(addr, word) * caddr_t addr; destination address in supervisor space * int word word to store * * Move To Supervisor Data, simplified interface for the kernel to store * single words in the supervisor data space. */ ENTRY(mtsd) mov 2(sp),r0 / get the destination address mov PS,-(sp) / save psw mov $10340,PS / previous supervisor mov 6(sp),-(sp) / grab word mtpd (r0) / and store it in supervisor space mov (sp)+,PS / restore psw rts pc / return /* * int * mfsd(addr) * caddr_t addr; source address in supervisor space * * Move From Supervisor Data, simplified interface for the kernel to get * single words from the supervisor data space. */ ENTRY(mfsd) mov 2(sp),r0 / get the address of the data mov PS,-(sp) / save psw mov $10340,PS / previous supervisor mfpd (r0) / get the word mov (sp)+,r0 / return value mov (sp)+,PS / restore psw rts pc / return #endif /* * error = vcopyin(fromaddr, toaddr, length) * int error; * caddr_t fromaddr, toaddr; * u_int length; * * Copy length bytes from user address space fromaddr to kernel space toaddr. * Returns zero on success, EFAULT on failure. Vcopyin is only called when * fromaddr, toaddr or length is odd and the length doesn't justify an * fmove. */ ENTRY(vcopyin) mov r2,-(sp) / allocate a couple registers mov r3,-(sp) mov nofault,-(sp) mov $5f,nofault / set up error trap mov 10(sp),r1 / r1 = fromaddr (user address) mov 12(sp),r2 / r2 = toaddr (kernel address) mov 14(sp),r0 / r0 = length beq 4f / (exit early if 0) bit $1,r1 / fromaddr odd? beq 1f dec r1 / yes, grab the even word and snarf mfpd (r1)+ / the high byte to start us off swab (sp) movb (sp)+,(r2)+ dec r0 1: mov r0,r3 / save trailing byte indicator and asr r0 / convert length remaining to units of beq 3f / words 2: mfpd (r1)+ / grab next word from user space movb (sp),(r2)+ / move the first byte swab (sp) / and the second ... movb (sp)+,(r2)+ sob r0,2b 3: / r0 = 0 asr r3 / need to copy in trailing byte? bcc 4f / nope, all done mfpd (r1) / grab last word and take the low movb (sp)+,(r2) / byte 4: mov (sp)+,nofault / restore error trap mov (sp)+,r3 / restore registers mov (sp)+,r2 rts pc / and return 5: mov $EFAULT,r0 / we got a memory fault give them the br 4b / error /* * error = vcopyout(fromaddr, toaddr, length) * int error; * caddr_t fromaddr, toaddr; * u_int length; * * Copy length bytes from kernel address space fromaddr to user space toaddr. * Returns zero on success, EFAULT on failure. Vcopyout is only called when * fromaddr, toaddr or length is odd and the length doesn't justify an fmove. */ ENTRY(vcopyout) mov r2,-(sp) / allocate a couple extra registers mov r3,-(sp) mov nofault,-(sp) mov $5f,nofault / set up error trap mov 10(sp),r1 / r1 = fromaddr (kernel space) mov 12(sp),r2 / r2 = toaddr (user address) mov 14(sp),r0 / r0 = length beq 4f / (exit early if 0) bit $1,r2 / toaddr odd? beq 1f dec r2 / yes, grab even word so we can stuff mfpd (r2) / our first byte into the high byte movb (r1)+,1(sp) / of that word mtpd (r2)+ dec r0 1: mov r0,r3 / save trailing byte indicator and asr r0 / convert length remaining to units of beq 3f / words 2: movb (r1)+,-(sp) / form word to copy out on the stack movb (r1)+,1(sp) mtpd (r2)+ / and send it on its way sob r0,2b 3: / r0 = 0 asr r3 / need to copy out trailing byte? bcc 4f / nope, all done mfpd (r2) / have to stuff our last byte out so movb (r1),(sp) / stick it into the lower byte and mtpd (r2) / rewrite it 4: mov (sp)+,nofault / restore previous error trap mov (sp)+,r3 / restore registers mov (sp)+,r2 rts pc / and return 5: mov $EFAULT,r0 / user memory fault ... return br 4b / EFAULT /* * error = copyinstr(fromaddr, toaddr, maxlength, &lencopied) * int error; * caddr_t fromaddr, toaddr; * u_int maxlength, *lencopied; * * Copy a null terminated string from the user address space into the kernel * address space. Returns zero on success, EFAULT on user memory management * trap, ENOENT if maxlength exceeded. If lencopied is non-zero, *lencopied * gets the length of the copy (including the null terminating byte). */ ENTRY(copyinstr) mov r2,-(sp) / allocate a couple extra registers mov r3,-(sp) mov nofault,-(sp) mov $7f,nofault / set up error trap mov 10(sp),r1 / r1 = fromaddr (user address) mov 12(sp),r2 / r2 = toaddr (kernel address) mov 14(sp),r0 / r0 = maxlength (remaining space) beq 3f / (exit early with ENOENT if 0) bit $1,r1 / fromaddr odd? beq 1f dec r1 / yes, grab the even word to start mfpd (r1)+ / us off mov (sp)+,r3 br 2f / and enter the loop halfway in ... 1: mfpd (r1)+ / grab next word from user space mov (sp)+,r3 movb r3,(r2)+ / move the first byte beq 4f dec r0 beq 3f 2: swab r3 / and the second ... movb r3,(r2)+ beq 4f sob r0,1b 3: mov $ENOENT,r0 / ran out of room - indicate failure br 5f / and exit ... 4: clr r0 / success! 5: tst 16(sp) / does the caller want the copy length? beq 6f sub 12(sp),r2 / yes, figure out how much we copied: mov r2,*16(sp) / *lencopied = r2 {toaddr'} - toaddr 6: mov (sp)+,nofault / restore error trap mov (sp)+,r3 / restore registers mov (sp)+,r2 / and return rts pc 7: mov $EFAULT,r0 / we got a memory fault give them the br 5b / error /* * error = copyoutstr(fromaddr, toaddr, maxlength, lencopied) * int error; * caddr_t fromaddr, toaddr; * u_int maxlength, *lencopied; * * Copy a null terminated string from the kernel address space to the user * address space. Returns zero on success, EFAULT on user memory management * trap, ENOENT if maxlength exceeded. If lencopied is non-zero, *lencopied * gets the length of the copy (including the null terminating byte). Note * that *lencopied will not by valid on EFAULT. */ ENTRY(copyoutstr) mov r2,-(sp) / allocate a couple extra registers mov r3,-(sp) mov nofault,-(sp) mov $7f,nofault / set up error trap /* * First find out how much we're going to be copying: * min(strlen(fromaddr), maxlength). */ mov 10(sp),r0 / r0 = fromaddr (kernel address) mov 14(sp),r1 / r1 = maxlength (remaining space) beq 6f / (exit early with ENOENT if 0) 1: tstb (r0)+ / found null? beq 2f sob r1,1b / run out of room? mov 14(sp),r0 / ran out of room: r0 = maxlength br 3f 2: sub 10(sp),r0 / found null: r0 = strlen(fromaddr) 3: tst 16(sp) / does the caller want the copy length? beq 4f / yes, mov r0,*16(sp) / lencopied = r0 (invalid on EFAULT) 4: mov 10(sp),r1 / r1 = fromaddr (kernel space) mov 12(sp),r2 / r2 = toaddr (user address) bit $1,r2 / toaddr odd? beq 5f dec r2 / yes, grab even word so we can stuff mfpd (r2) / our first byte into the high byte movb (r1)+,1(sp) / of that word mtpd (r2)+ dec r0 5: mov r0,r3 / save trailing byte indicator and asr r0 / convert space remaining to units of beq 2f / words 1: movb (r1)+,-(sp) / form word to copy out on the stack movb (r1)+,1(sp) mtpd (r2)+ / and send it on its way sob r0,1b 2: asr r3 / need to copy out trailing byte? bcc 3f / nope, all done mfpd (r2) / have to stuff our last byte out so movb (r1)+,(sp) / stick it into the lower byte and mtpd (r2) / rewrite it 3: movb -(r1),r0 / did we copy the null out? beq 5f 4: mov $ENOENT,r0 / no, so indicate ENOENT 5: mov (sp)+,nofault / restore previous error trap mov (sp)+,r3 / restore registers mov (sp)+,r2 rts pc / and return /* * Rapacious silliness here - someone has passed us maxlength == 0 ... */ 6: tst 16(sp) / do they want to know about it? beq 4b / (guess not ...) clr *16(sp) / *lencopied = 0 br 4b / return ENOENT 7: mov $EFAULT,r0 / user memory fault ... return br 5b / EFAULT ; * * Copy length/2 words from kernel space fromaddr to user space address * toaddr. Fromaddr and toaddr must be even. Returns zero on success, * EFAULT on failure. Copyout copies to data space, copyiout to * instruction space. */ ENTRY(sys/pdp/libc_ffs.s 440 0 12 1434 4020412615 7352 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifdef LIBC_SCCS <@(#)ffs.s 1.2 (Berkeley) 1/8/87\0> .even #endif LIBC_SCCS #include "DEFS.h" /* * ffs(mask) * long mask; * * Return index of lowest order bit set in mask (counting from the right * starting at 1), or zero if mask is zero. Ffs(m) is essentiallty * log2(m)+1 with a 0 error return. */ ENTRY(ffs) clr r0 / cnt:r0 = 0 mov 4(sp),r1 / if ((imask = loint(mask)) != 0) bne 1f mov 2(sp),r1 / if ((imask = hiint(mask)) == 0) beq 2f mov $16.,r0 / else cnt = 16 1: inc r0 / do { cnt++ asr r1 / imask >>= 1 bcc 1b / } while (!wasodd(imask)) 2: rts pc / return(cnt:r0) did we copy the null out? beq 5f 4: mov $ENOENT,r0 / no, so indicate ENOENT 5: mov (sp)+,nofault / restore previous error trap mov (sp)+,r3 / restore registers mov (sp)+,r2 rts pc / and return /* * Rapacious silsys/pdp/cons.c 440 0 12 10054 5667263273 6571 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)cons.c 1.2 (2.11BSD GTE) 11/29/94 */ /* * KL/DL-11 driver */ #include "param.h" #include "conf.h" #include "user.h" #include "proc.h" #include "ioctl.h" #include "tty.h" #include "systm.h" #include "cons.h" #include "cn.h" /* * Normal addressing: * minor 0 addresses KLADDR * minor 1 thru n-1 address from KLBASE (0176600), * where n is the number of additional KL11's * minor n on address from DLBASE (0176500) */ struct dldevice *cnaddr = (struct dldevice *)0177560; int nkl11 = NKL; /* for pstat */ struct tty cons[NKL]; int cnstart(); int ttrstrt(); char partab[]; cnattach(addr, unit) struct dldevice *addr; { if ((u_int)unit <= NKL) { cons[unit].t_addr = (caddr_t)addr; return (1); } return (0); } /*ARGSUSED*/ cnopen(dev, flag) dev_t dev; { register struct dldevice *addr; register struct tty *tp; register int d; d = minor(dev); tp = &cons[d]; if (!d && !tp->t_addr) tp->t_addr = (caddr_t)cnaddr; if (d >= NKL || !(addr = (struct dldevice *)tp->t_addr)) return (ENXIO); tp->t_oproc = cnstart; if ((tp->t_state&TS_ISOPEN) == 0) { ttychars(tp); tp->t_state = TS_ISOPEN|TS_CARR_ON; tp->t_flags = EVENP|ECHO|XTABS|CRMOD; } if (tp->t_state&TS_XCLUDE && u.u_uid != 0) return (EBUSY); addr->dlrcsr |= DL_RIE|DL_DTR|DL_RE; addr->dlxcsr |= DLXCSR_TIE; return ((*linesw[tp->t_line].l_open)(dev, tp)); } /*ARGSUSED*/ cnclose(dev, flag) dev_t dev; { register struct tty *tp = &cons[minor(dev)]; (*linesw[tp->t_line].l_close)(tp, flag); ttyclose(tp); } /*ARGSUSED*/ cnread(dev, uio, flag) dev_t dev; struct uio *uio; int flag; { register struct tty *tp = &cons[minor(dev)]; return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); } /*ARGSUSED*/ cnwrite(dev, uio, flag) dev_t dev; struct uio *uio; int flag; { register struct tty *tp = &cons[minor(dev)]; return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); } /*ARGSUSED*/ cnrint(dev) dev_t dev; { register int c; register struct dldevice *addr; register struct tty *tp = &cons[minor(dev)]; addr = (struct dldevice *)tp->t_addr; c = addr->dlrbuf; addr->dlrcsr |= DL_RE; (*linesw[tp->t_line].l_rint)(c, tp); } /*ARGSUSED*/ cnioctl(dev, cmd, addr, flag) dev_t dev; register u_int cmd; caddr_t addr; { register struct tty *tp = &cons[minor(dev)]; register int error; error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr, flag); if (error >= 0) return (error); error = ttioctl(tp, cmd, addr, flag); if (error < 0) error = ENOTTY; return (error); } cnxint(dev) dev_t dev; { register struct tty *tp = &cons[minor(dev)]; tp->t_state &= ~TS_BUSY; (*linesw[tp->t_line].l_start)(tp); } cnstart(tp) register struct tty *tp; { register struct dldevice *addr; register int c, s; s = spltty(); if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) goto out; if (tp->t_outq.c_cc <= TTLOWAT(tp)) { if (tp->t_state&TS_ASLEEP) { tp->t_state &= ~TS_ASLEEP; wakeup((caddr_t)&tp->t_outq); } if (tp->t_wsel) { selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); tp->t_wsel = 0; tp->t_state &= ~TS_WCOLL; } } if (tp->t_outq.c_cc == 0) goto out; addr = (struct dldevice *)tp->t_addr; if ((addr->dlxcsr & DLXCSR_TRDY) == 0) goto out; c = getc(&tp->t_outq); if (tp->t_flags & (RAW|LITOUT)) addr->dlxbuf = c&0xff; else if (c <= 0177) addr->dlxbuf = (c | ((partab[c]&0200))&0xff); else { timeout(ttrstrt, (caddr_t)tp, c&0177); tp->t_state |= TS_TIMEOUT; goto out; } tp->t_state |= TS_BUSY; out: splx(s); } /* copied, for supervisory networking, to sys_sup.c */ cnputc(c) register int c; { register int s, timo; timo = 30000; /* * Try waiting for the console tty to come ready, * otherwise give up after a reasonable time. */ while ((cnaddr->dlxcsr & DLXCSR_TRDY) == 0) if (--timo == 0) break; if (c == 0) return; s = cnaddr->dlxcsr; cnaddr->dlxcsr = 0; cnaddr->dlxbuf = c&0xff; if (c == '\n') cnputc('\r'); cnputc(0); cnaddr->dlxcsr = s; } in supervisor space * * Move From Supervisor Data, simplified interface for the kernel to get * single words from the supervisor data space. */ ENTRY(mfsd) mov 2(sp),r0 / get the address of the data mov PS,-(sp) / save psw mov $10340,PS / previous supervisor mfpd (r0) / get the word mov (sp)+,r0 / return value mov (sp)+,PS / restore psw rts pc / return #endif /* * error = vcopyin(fromaddr, toaddr, length) * int error; * caddr_t fromaddr, tsys/pdp/cons.h 444 0 12 3507 4001143122 6532 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)cons.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * KL11/DL11 registers and bits */ struct dldevice { short dlrcsr; short dlrbuf; short dlxcsr; short dlxbuf; }; /* bits in dlrcsr */ #define DL_DSC 0100000 /* data status change (RO) */ #define DL_RNG 0040000 /* ring indicator (RO) */ #define DL_CTS 0020000 /* clear to send (RO) */ #define DL_CD 0010000 /* carrier detector (RO) */ #define DL_RA 0004000 /* receiver active (RO) */ #define DL_SRD 0002000 /* secondary received data (RO) */ /* bits 9-8 are unused */ #define DL_RDONE 0000200 /* receiver done (RO) */ #define DL_RIE 0000100 /* receiver interrupt enable */ #define DL_DIE 0000040 /* dataset interrupt enable */ /* bit 4 is unused */ #define DL_STD 0000010 /* secondary transmitted data */ #define DL_RTS 0000004 /* request to send */ #define DL_DTR 0000002 /* data terminal ready */ #define DL_RE 0000001 /* reader enable (write only) */ #define DL_BITS \ "\10\20DSC\17RNG\16CTS\15CD\14RA\13SRD\10RDONE\7RIE\6DIE\4STD\3RTS\2DTR\1RE" /* bits in dlrbuf */ #define DLRBUF_ERR 0100000 /* error (RO) */ #define DLRBUF_OVR 0040000 /* overrun (RO) */ #define DLRBUF_FRE 0020000 /* framing error (RO) */ #define DLRBUF_RDPE 0010000 /* receive data parity error (RO) */ #define DLRBUF_BITS \ "\10\20ERR\17OVR\16FRE\15RDPE" /* bits in dlxcsr */ /* bits 15-8 are unused */ #define DLXCSR_TRDY 0000200 /* transmitter ready (RO) */ #define DLXCSR_TIE 0000100 /* transmitter interrupt enable */ /* bits 5-3 are unused */ #define DLXCSR_MM 0000004 /* maintenance */ /* bit 1 is unused */ #define DLXCSR_BRK 0000001 /* break */ #define DLXCSR_BITS \ "\10\10TRDY\7TIE\3MM\1BRK" f; short dlxcsr; short dlxbuf; }; /* bits in dlrcsr */ #define DL_DSC 0100000 /* data status change (RO) */ #define DL_RNG 0040000 /* ring indicator (RO) */ #define DL_CTS 00200sys/pdp/frame.h 444 0 12 1044 4016525546 6700 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)frame.h 7.1 (Berkeley) 6/5/86 */ /* * Definition of the pdp call frame. */ struct frame { int fr_savr2; /* saved register 2 */ int fr_savr3; /* saved register 3 */ int fr_savr4; /* saved register 4 */ int fr_savov; /* saved overlay number */ int fr_savfp; /* saved frame pointer */ int fr_savpc; /* saved program counter */ }; DL_CD 0010000 /* carrier detector (RO) */define DL_RA 0004000 /* receiver active (RO) */ #define DL_SRD 0002000 /* secondary received data (RO) */ /* bits 9-8 are unused */ #define DL_RDONE 0000200 /* receiver done (RO) */ #define DL_RIE 0000100 /* receiver interrupt enable */ #define DL_DIE 0000040 /* dataset interrupt enable */ /* bit 4 is unused */ #define DL_STD 0000010 /* secondary transmitted data */ #define DL_RTS 0000004 /* request to send */ #desys/pdp/in_cksum.c 440 0 12 3307 4236504251 7403 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)in_cksum.c 1.1 (2.10BSD Berkeley) 12/1/86 */ #include "param.h" #include "../machine/seg.h" #include "mbuf.h" #include "domain.h" #include "protosw.h" #include #include /* * Checksum routine for Internet Protocol family headers. This routine is * very heavily used in the network code and should be rewritten for each * CPU to be as fast as possible. */ #ifdef DIAGNOSTIC int in_ckprint = 0; /* print sums */ #endif in_cksum(m, len) struct mbuf *m; int len; { register u_char *w; /* known to be r4 */ register u_int mlen = 0; /* known to be r3 */ register u_int sum = 0; /* known to be r2 */ u_int plen = 0; #ifdef DIAGNOSTIC if (in_ckprint) printf("ck m%o l%o", m, len); #endif for (;;) { /* * Each trip around loop adds in * words from one mbuf segment. */ w = mtod(m, u_char *); if (plen & 01) { /* * The last segment was an odd length, add the high * order byte into the checksum. */ sum = in_ckadd(sum,(*w++ << 8)); mlen = m->m_len - 1; len--; } else mlen = m->m_len; m = m->m_next; if (len < mlen) mlen = len; len -= mlen; plen = mlen; if (mlen > 0) in_ckbuf(); /* arguments already in registers */ if (len == 0) break; /* * Locate the next block with some data. */ for (;;) { if (m == 0) { printf("cksum: out of data\n"); goto done; } if (m->m_len) break; m = m->m_next; } } done: #ifdef DIAGNOSTIC if (in_ckprint) printf(" s%o\n", ~sum); #endif return(~sum); } uio, flag) dev_t dev; struct uio *uio; int flag; { register struct tty *tp = &cons[minor(dev)]; return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); } /*ARGSUSED*/ cnwrite(dev, uio, flag) dev_t dev; struct uio *uio; int flag; { register struct tty *tp = &cons[minor(dev)]; return ((*linesw[tp->t_linsys/pdp/vmparam.h 444 0 12 1306 4052740527 7250 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)vmparam.h 1.1 (2.10BSD Berkeley) 6/5/86 */ /* * The time for a process to be blocked before being very swappable. * This is a number of seconds which the system takes as being a non-trivial * amount of real time. You probably shouldn't change this; * it is used in subtle ways (fractions and multiples of it are, that is, like * half of a ``long time'', almost a long time, etc.) * It is related to human patience and other factors which don't really * change over time. */ #define MAXSLP 20 register u_char *w; /* known to be r4 */ register u_int mlen = 0; /* known to be r3 */ register u_int sum = 0; /* known to be r2 */ u_int plen = 0; #ifdef DIAGNOSTIC if (in_ckprint) printf("ck m%o l%o", m, len); #endif for (;;) { /* * Each trip around loop adds in * words from one mbuf segment. sys/pdp/machdep2.c 644 0 0 25022 5752045365 7271 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)machdep2.c 2.4 (2.11BSD GTE) 1995/05/01 */ #include "param.h" #include "../machine/seg.h" #include "../machine/iopage.h" #include "dir.h" #include "inode.h" #include "user.h" #include "proc.h" #include "fs.h" #include "map.h" #include "buf.h" #include "text.h" #include "file.h" #include "clist.h" #include "uba.h" #include "callout.h" #include "reboot.h" #include "systm.h" #include "ram.h" #include "msgbuf.h" #include "namei.h" #include "ra.h" #include "tms.h" #include "ingres.h" #include "disklabel.h" #if NINGRES > 0 #include #endif #ifdef QUOTA #include "quota.h" #endif size_t physmem; /* total amount of physical memory (for savecore) */ #if NRAC > 0 || NTMSCP > 0 memaddr _iostart, _iobase; ubadr_t _ioumr; u_short _iosize = 2 * (1928 + 1096 + 128); /* enough for 2 TMSCP and 2 MSCP */ #endif segm seg5; /* filled in by initialization */ /* * Machine dependent startup code */ startup() { #ifdef UCB_CLIST extern memaddr clststrt; #endif extern ubadr_t clstaddr; extern int end; register memaddr i, freebase, maxclick; #if NRAM > 0 size_t ramsize; #endif printf("\n%s\n", version); saveseg5(seg5); /* must be done before clear() is called */ /* * REMAP_AREA is the start of possibly-mapped area, for consistency * check. Only proc, text and file tables are after it, and it must * lie at <= 0120000, or other kernel data will be mapped out. */ if (REMAP_AREA > SEG5) panic("remapped area > SEG5"); /* * Zero and free all of core: * * MAXCLICK is the maximum accessible physical memory, assuming an 8K * I/O page. On systems without a Unibus map the end of memory is * heralded by the beginning of the I/O page (some people have dz's * at 0160000). On systems with a Unibus map, the last 256K of the * 4M address space is off limits since 017000000 to 017777777 is the * actual 18 bit Unibus address space. 61440 is btoc(4M - 256K), * and 65408 is btoc(4M - 8K). * * Previous cautions about 18bit devices on a 22bit Qbus were misguided. * Since the GENERIC kernel was built with Q22 defined the limiting * effect on memory size was not achieved, thus an 18bit controller * could not be used to load the distribution. ALSO, the kernel * plus associated data structures do not leave enough room in 248kb * to run the programs necessary to do _anything_. */ #define MAXCLICK_22U 61440 /* 22 bit UNIBUS (UNIBUS mapping) */ #define MAXCLICK_22 65408 /* 22 bit QBUS */ maxclick = ubmap ? MAXCLICK_22U : MAXCLICK_22; i = freebase = *ka6 + USIZE; UISD[0] = ((stoc(1) - 1) << 8) | RW; for (;;) { UISA[0] = i; if (fuibyte((caddr_t)0) < 0) break; ++maxmem; /* avoid testing locations past "real" memory. */ if (++i >= maxclick) break; } clear(freebase,i - freebase); mem_parity(); /* enable parity checking */ clear(freebase,i - freebase); /* quick check for parities */ mfree(coremap,i - freebase,freebase); physmem = i; procNPROC = proc + nproc; textNTEXT = text + ntext; inodeNINODE = inode + ninode; fileNFILE = file + nfile; /* * IMPORTANT! Mapped out clists should always be allocated first! * This prevents needlessly having to restrict all memory use * (maxclick) to 248K just because an 18-bit DH is present on a * 22-bit Q-BUS machine. The maximum possible location for mapped * out clists this way is 232K (56K base + 15 * 8K overlays + 48K * data space + 8K (maximum) user structure, which puts the maximum * top of mapped out clists at 240K ... */ #ifdef UCB_CLIST #define C (nclist * sizeof(struct cblock)) if ((clststrt = malloc(coremap, btoc(C))) == 0) panic("clists"); clstaddr = ((ubadr_t)clststrt) << 6; #undef C #else clstaddr = (ubadr_t)cfree; #endif #ifdef EXTERNALITIMES #define C (btoc(ninode * sizeof (struct icommon2))) if ((xitimes = malloc(coremap, C)) == 0) panic("xitimes"); xitdesc = ((C - 1) << 8) | RW; #undef C #endif #ifdef QUOTA #define C (btoc(8192)) if ((quotreg = malloc(coremap, C)) == 0) panic("quotamem"); quotdesc = ((C - 1) << 8) | RW; QUOini(); #undef C #endif { register int B; nchsize = 8192 / sizeof(struct namecache); if (nchsize > (ninode * 11 / 10)) nchsize = ninode * 11 / 10; B = (btoc(nchsize * sizeof(struct namecache))); if ((nmidesc.se_addr = malloc(coremap, B)) == 0) panic("nmidesc"); nmidesc.se_desc = ((B - 1) << 8) | RW; namecache = (struct namecache *)SEG5; } #if NRAC > 0 || NTMSCP > 0 if ((_iobase = malloc(coremap, btoc(_iosize))) == 0) panic("_iobase"); #endif NRAC #define B (size_t)(((long)nbuf * (MAXBSIZE)) / ctob(1)) if ((bpaddr = malloc(coremap, B)) == 0) panic("buffers"); #undef B #define C (btoc(MSG_BSIZE)) if ((msgbuf.msg_click = malloc(coremap, C)) == 0) panic("msgbuf"); msgbuf.msg_magic = MSG_MAGIC; msgbuf.msg_bufc = SEG5; msgbuf.msg_bufx = msgbuf.msg_bufr = 0; #undef C #if NINGRES > 0 #define C (btoc(LOCKTABSIZE)) if (Locktabseg.se_addr = malloc(coremap, C)) Locktabseg.se_desc = ((C - 1) << 8) | RW; #undef C #endif /* * Allocate the initial disklabels. */ (void) initdisklabels(); #if NRAM > 0 ramsize = raminit(); #endif /* * Initialize callouts */ callfree = callout; for (i = 1; i < ncallout; i++) callout[i-1].c_next = &callout[i]; UISA[7] = ka6[1]; /* io segment */ UISD[7] = ((stoc(1) - 1) << 8) | RW; } mem_parity() { register int cnt; for (cnt = 0;cnt < 16;++cnt) { if (fioword((caddr_t)(MEMSYSMCR+cnt)) == -1) return; *(MEMSYSMCR+cnt) = MEMMCR_EIE; /* enable parity interrupts */ } } #if defined(PROFILE) && !defined(ENABLE34) /* * Allocate memory for system profiling. Called once at boot time. * Returns number of clicks used by profiling. * * The system profiler uses supervisor I space registers 2 and 3 * (virtual addresses 040000 through 0100000) to hold the profile. */ msprof() { memaddr proloc; int nproclicks; nproclicks = btoc(8192*2); proloc = malloc(coremap, nproclicks); if (proloc == 0) panic("msprof"); *SISA2 = proloc; *SISA3 = proloc + btoc(8192); *SISD2 = 077400|RW; *SISD3 = 077400|RW; *SISD0 = RW; *SISD1 = RW; /* * Enable system profiling. Zero out the profile buffer * and then turn the clock (KW11-P) on. */ clear(proloc, nproclicks); isprof(); printf("profiling on\n"); return (nproclicks); } #endif /* * Re-initialize the Unibus map registers to statically map * the clists and buffers. Free the remaining registers for * physical I/O. At this time the [T]MSCP arena is also mapped. */ ubinit() { register int i, ub_nreg; long paddr; register struct ubmap *ubp; if (!ubmap) return; /* * Clists start at UNIBUS virtual address 0. The size of * the clist segment can be no larger than UBPAGE bytes. * Clstaddt was the physical address of clists. */ if (nclist * sizeof(struct cblock) > ctob(stoc(1))) panic("clist > 8k"); setubregno(0, clstaddr); clstaddr = (ubadr_t)0; /* * Buffers start at UNIBUS virtual address BUF_UBADDR. */ paddr = ((long)bpaddr) << 6; ub_nreg = nubreg(nbuf, MAXBSIZE); for (i = BUF_UBADDR/UBPAGE; i < ub_nreg + (BUF_UBADDR/UBPAGE); i++) { setubregno(i, paddr); paddr += (long)UBPAGE; } /* * The 3Com ethernet board is hardwired to use UNIBUS registers 28, 29 * and 30 (counting from 0) and UNIBUS register 31 isn't usable. */ #include "ec.h" #if NEC > 0 mfree(ub_map, 28 - ub_nreg - 1, 1 + ub_nreg); /* 3Com board */ #else mfree(ub_map, 31 - ub_nreg - 1, 1 + ub_nreg); #endif /* * this early in the system's life there had better be a UMR or two * available!! N.B. This was moved from where the [T]MSCP memory was * allocated because at that point the UMR map was not initialized. */ #if NRAC > 0 || NTMSCP > 0 _iostart = _iobase; i = (int)btoub(_iosize); ub_nreg = malloc(ub_map, i); _ioumr = (ubadr_t)ub_nreg << 13; ubp = &UBMAP[ub_nreg]; paddr = ctob((ubadr_t)_iostart); while (i--) { ubp->ub_lo = loint(paddr); ubp->ub_hi = hiint(paddr); ubp++; paddr += (ubadr_t)UBPAGE; } #endif NRAC } int waittime = -1; boot(dev, howto) register dev_t dev; register int howto; { register struct fs *fp; /* * Force the root filesystem's superblock to be updated, * so the date will be as current as possible after * rebooting. */ if (fp = getfs(rootdev)) fp->fs_fmod = 1; if ((howto&RB_NOSYNC)==0 && waittime < 0 && bfreelist[0].b_forw) { waittime = 0; printf("syncing disks... "); (void) _splnet(); /* * Release inodes held by texts before update. */ xumount(NODEV); update(); { register struct buf *bp; int iter, nbusy; for (iter = 0; iter < 20; iter++) { nbusy = 0; for (bp = &buf[nbuf]; --bp >= buf; ) if (bp->b_flags & B_BUSY) nbusy++; if (nbusy == 0) break; printf("%d ", nbusy); delay(40000L * iter); } } printf("done\n"); } (void) _splhigh(); if (howto & RB_HALT) { printf("halting\n"); halt(); /*NOTREACHED*/ } else { if (howto & RB_DUMP) { /* * save the registers in low core. */ saveregs(); dumpsys(); } doboot(dev, howto); /*NOTREACHED*/ } } /* * Dumpsys takes a dump of memory by calling (*dump)(), which must * correspond to dumpdev. *(dump)() should dump from dumplo blocks * to the end of memory or to the end of the logical device. */ dumpsys() { extern int (*dump)(); register int error; if (dumpdev != NODEV) { printf("\ndumping to dev %o, offset %D\ndump ",dumpdev,dumplo); error = (*dump)(dumpdev); switch(error) { case EFAULT: printf("device not ready (EFAULT)\n"); break; case EINVAL: printf("arguments invalid (EINVAL)\n"); break; case EIO: printf("I/O error (EIO)\n"); break; default: printf("unknown error (%d)\n",error); break; case 0: printf("succeeded\n"); break; } } } #if NRAC > 0 || NTMSCP > 0 memaddr _ioget(size) u_int size; { register memaddr base; register u_int csize; csize = btoc(size); size = ctob(csize); if (size > _iosize) return(0); _iosize -= size; base = _iobase; _iobase += csize; return(base); } ubadr_t _iomap(addr) register memaddr addr; { return(((ubadr_t)(addr - _iostart) << 6) + _ioumr); } #endif NRAC #define NLABELS 6 memaddr _dlabelbase; int _dlabelnum = NLABELS; void initdisklabels() { #define C (NLABELS * (btoc(sizeof (struct disklabel)))) _dlabelbase = malloc(coremap, C); } memaddr disklabelalloc() { register memaddr base; if (--_dlabelnum) { base = _dlabelbase; _dlabelbase += btoc(sizeof (struct disklabel)); return(base); } base = malloc(coremap, btoc (sizeof (struct disklabel))); return(base); } 1),(sp) / stick it into the lower byte and mtpd (r2) / rewrite it 4: mov (sp)+,nofault / restore previous error trap mov (sp)+,r3 / restore registers mov (sp)+,r2 rts pc / and return 5: mov $EFAULT,r0 / user memory fault ... return br 4b / EFAULT /* * error = copyinstr(fromaddr, toaddr, maxlength, &lencopied) * int error; * caddr_t fromaddr, toaddr; * u_int maxlength, *lencopied; * * Copy a null terminated string from the user address space into the kernelsys/pdp/kern_pdp.c 440 0 12 7025 4263757453 7414 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)kern_pdp.c 1.1 (2.10BSD Berkeley) 12/1/86 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/seg.h" #include "user.h" #include "proc.h" #include "kernel.h" #include "systm.h" /* * used to pass result from int service to probe(); * do not declare static!! */ int conf_int = CONF_MAGIC; /* * ucall allows user level code to call various kernel functions. * Autoconfig uses it to call the probe and attach routines of the * various device drivers. */ ucall() { register struct a { int priority; int (*routine)(); int arg1; int arg2; } *uap = (struct a *)u.u_ap; int s; if (!suser()) return; switch(uap->priority) { case 0: s = spl0(); break; case 1: s = spl1(); break; case 2: case 3: case 4: s = spl4(); break; case 5: s = spl5(); break; case 6: s = spl6(); break; case 7: default: s = spl7(); break; } u.u_r.r_val1 = (*uap->routine)(uap->arg1,uap->arg2); splx(s); } /* * Lock user into core as much as possible. Swapping may still * occur if core grows. */ lock() { struct a { int flag; }; if (!suser()) return; if (((struct a *)u.u_ap)->flag) u.u_procp->p_flag |= SULOCK; else u.u_procp->p_flag &= ~SULOCK; } gldav() { struct a { short *ptr; }; u.u_error = copyout((caddr_t)avenrun, (caddr_t)(((struct a *)u.u_ap)->ptr),3 * sizeof(short)); } /* * fetch the word at iaddr from user I-space. This system call is * required on machines with separate I/D space because the mfpi * instruction reads from D-space if the current and previous modes * in the program status word are both user. */ fetchi() { struct a { caddr_t iaddr; }; #ifdef NONSEPARATE u.u_error = EINVAL; #else !NONSEPARATE u.u_error = copyiin((struct a *)u.u_ap, u.u_r.r_val1, NBPW); #endif NONSEPARATE } /* * return the floating point error registers as they were following * the last floating point exception generated by the calling process. * Required because the error registers may have been changed so the * system saves them at the time of the exception. */ fperr() { u.u_r.r_val1 = (int)u.u_fperr.f_fec; u.u_r.r_val2 = (int)u.u_fperr.f_fea; } /* * set up the process to have no stack segment. The process is * responsible for the management of its own stack, and can thus * use the full 64K byte address space. */ nostk() { if (estabur(u.u_tsize, u.u_dsize, 0, u.u_sep, RO)) return; expand(0,S_STACK); u.u_ssize = 0; } /* * set up a physical address * into users virtual address space. */ phys() { register struct a { int segno; int size; int phys; } *uap = (struct a *)u.u_ap; register int i, s; int d; if (!suser()) return; i = uap->segno; if (i < 0 || i >= 8) goto bad; s = uap->size; if (s < 0 || s > 128) goto bad; #ifdef NONSEPARATE d = u.u_uisd[i]; #else d = u.u_uisd[i + 8]; #endif if (d != 0 && (d & ABS) == 0) goto bad; #ifdef NONSEPARATE u.u_uisd[i] = 0; u.u_uisa[i] = 0; #else u.u_uisd[i + 8] = 0; u.u_uisa[i + 8] = 0; if (!u.u_sep) { u.u_uisd[i] = 0; u.u_uisa[i] = 0; } #endif if (s) { #ifdef NONSEPARATE u.u_uisd[i] = ((s - 1) << 8) | RW | ABS; u.u_uisa[i] = uap->phys; #else u.u_uisd[i + 8] = ((s - 1) << 8) | RW | ABS; u.u_uisa[i + 8] = uap->phys; if (!u.u_sep) { u.u_uisa[i] = u.u_uisa[i + 8]; u.u_uisd[i] = u.u_uisd[i + 8]; } #endif } sureg(); return; bad: u.u_error = EINVAL; } ),3 * sizeof(short)); } /* * fetch the word at iaddr from user I-space. This system call is * required on machines with separate I/D space because the mfpi * instruction reads from D-space if the current and previous modes * in the program status word are both user. */ fetchi() { struct a { caddr_t iaddr; }; #ifdef NONSEPARATE u.u_error = EINVAL; #else !NONSEPARATE u.u_error = copyiin((struct a *)u.u_ap, u.u_r.r_val1, NBPW); #endif NONSEPARATE } /* * return the floating psys/pdp/cksum-fix 440 0 12 2475 3436275137 7276 /in_ckad/ .,.+1c / 1's comp add. sum = in_ckadd(a,b); mov (sp)+,r0 add (sp),r0 adc r0 . /in_ckbu/ .c / 1's complement checksum routine. assumes sum on entry is on logical even / byte boundary, even though entry address may be odd. / / r2 - 1's complement sum / r3 - number of bytes / r4 - byte address clr -(sp) /assume even start address bit $1,r4 beq 1f /if even starting address inc (sp) clr r0 bisb (r4)+,r0 /get byte at odd address add r0,r2 adc r2 swab r2 dec r3 /and adjust byte count 1: clr r1 /assume even byte count asr r3 /convert byte to word count adc r1 /set r1 if extra trailing odd byte tst r3 beq 4f /if no words left 2: add (r4)+,r2 /add into checksum adc r2 sob r3,2b /and process all of them 4: tst r1 /extra trailing byte? beq 3f /if not, exit clr r0 bisb (r4)+,r0 /get that extra byte add r0,r2 /and include in the checksum adc r2 3: tst (sp)+ beq 5f /if starting address not odd swab r2 5: . w q d[i + 8] = ((s - 1) << 8) | RW | ABS; u.u_uisa[i + 8] = uap->phys; if (!u.u_sep) { u.u_uisa[i] = u.u_uisa[i + 8]; u.u_uisd[i] = u.u_uisd[i + 8]; } #endif } sureg(); return; bad: usys/pdp/mch_cpu.h 444 0 12 457 5317205704 7207 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)mch_cpu.h 1.2 (2.11BSD GTE) 12/26/92 */ #define PDP1170_LEAR 0177740 /* See comments in pdp/cpu.h */ s libc_bcmp.ss libc_bcopy.s libc_bzero.s libc_insque.s libc_remque.s ram.c libc_strlen.s~ libc_ldiv.ss} libc_lmul.ss| libc_lrem.ss{ libc_htosys/pdp/mch_dump.s 444 0 12 23534 5316460210 7433 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)mch_dump.s 1.3 (2.11BSD GTE) 12/24/92 */ #include "DEFS.h" #include "../machine/mch_iopage.h" /* * Save regs r0, r1, r2, r3, r4, r5, r6, K[DI]SA6 * starting at data location 0300, in preparation for dumping core. */ ENTRY(saveregs) #ifdef KERN_NONSEP movb $RW, KISD0 / write enable #endif KERN_NONSEP mov r0,300 mov $302,r0 mov r1,(r0)+ mov r2,(r0)+ mov r3,(r0)+ mov r4,(r0)+ mov r5,(r0)+ mov sp,(r0)+ mov KDSA6,(r0)+ mov KDSA5,(r0)+ rts pc #ifdef INET SPACE(GLOBAL, suprsav, 32) /* * Save ALL registers, KDSA[5,6], SDSA[5,6], SSR3. Expressly for * network crashes where the state at the time of initial trap is * desired rather than after thrashing about on the way to a 'panic'. * Also, this is extensible so that as much volatile information as * required may be saved. Currently 14 of the 16 words allocated are used. * Multiple entries into this routine should be blocked by making the * call to this routine conditional on 'netoff' being set and * setting 'netoff' on the first call. Must be at splhigh upon entry. */ ENTRY(savestate) mov r0,suprsav mov $suprsav+2,r0 mov r1,(r0)+ mov r2,(r0)+ mov r3,(r0)+ mov r4,(r0)+ mov r5,(r0)+ mov sp,(r0)+ mov PS,-(sp) mov $010340,PS /previous super, spl7 mfpd sp /fetch supervisor stack pointer mov (sp)+,(r0)+ mov $030340,PS /previous user, spl7 mfpd sp /fetch user stack pointer mov (sp)+,(r0)+ mov (sp)+,PS mov KDSA5,(r0)+ mov KDSA6,(r0)+ mov SDSA5,(r0)+ mov SDSA6,(r0)+ mov SSR3,(r0)+ rts pc #endif #include "ht.h" #include "tm.h" #include "ts.h" /* * Mag tape dump -- save registers in low core and write core (up to 248K) * onto mag tape. Entry is through 044 (physical) with memory management off. */ #ifndef KERN_NONSEP .data #endif !KERN_NONSEP ASENTRY(dump) #if NHT > 0 || NTM > 0 || NTS > 0 /* * save regs r0, r1, r2, r3, r4, r5, r6, KIA6 * starting at location 4 (physical) */ inc $-1 / check for first time bne 1f / if not, don't save registers again mov r0,300 mov $302,r0 mov r1,(r0)+ mov r2,(r0)+ mov r3,(r0)+ mov r4,(r0)+ mov r5,(r0)+ mov sp,(r0)+ mov KDSA6,(r0)+ 1: /* * dump all of core (i.e. to first mt error) * onto mag tape. (9 track or 7 track 'binary') */ #if NHT > 0 HT = 0172440 HTCS1 = HT+0 HTWC = HT+2 HTBA = HT+4 HTFC = HT+6 HTCS2 = HT+10 HTTC = HT+32 mov $HTCS1,r0 mov $40,*$HTCS2 mov $2300,*$HTTC clr *$HTBA mov $1,(r0) 1: mov $-512.,*$HTFC mov $-256.,*$HTWC movb $61,(r0) 2: tstb (r0) bge 2b bit $1,(r0) bne 2b bit $40000,(r0) beq 1b mov $27,(r0) #else !NHT > 0 #if NTM > 0 MTC = 172522 IO = 0177600 UBMR0 = 0170200 /* * register usage is as follows: * * reg 0 -- holds the tm11 CSR address * reg 1 -- points to UBMAP register 0 low * reg 2 -- is used to contain and calculate memory pointer * for UBMAP register 0 low * reg 3 -- is used to contain and calculate memory pointer * for UBMAP register 0 high * reg 4 -- r4 = 1 for map used, r4 = 0 for map not used * reg 5 -- is used as an interation counter when mapping is enabled */ movb _ubmap,r4 / UB map used indicator beq 2f / no UBMAP - br 1: /* * This section of code initializes the Unibus map registers and * and the memory management registers. * UBMAP reg 0 gets updated to point to the current memory area. * Kernal I space 0 points to low memory * Kernal I space 7 points to the I/O page. */ mov $UBMR0,r1 / point to map register 0 clr r2 / init for low map reg clr r3 / init for high map reg mov $77406,*$KISD0 / set KISDR0 mov $77406,*$KISD7 / set KISDR7 clr *$KISA0 / point KISAR0 to low memory mov $IO,*$KISA7 / point KISAR7 to IO page inc *$SSR0 / turn on memory mngt mov $60,*$SSR3 / enable 22 bit mapping mov r2,(r1) / load map reg 1 low mov r3,2(r1) / load map reg 1 high 2: / this section of code initializes the TM11 mov $MTC,r0 mov $60004,(r0) clr 4(r0) mov $20,r5 / set up SOB counter for UBMAP /* * This section does the write; if mapping is needed the sob loop * comes in play here. When the sob falls through the UBMAP reg * will be updated by 20000 to point to next loop section. * If mapping not needed then just let bus address register increment. */ 3: mov $-512.,2(r0) / set byte count inc (r0) / start xfer 1: tstb (r0) / wait for tm11 ready bge 1b */ tst (r0) / any error bge 2f / no, continue xfer bit $200,-2(r0) / yes, must be NXM error beq . / hang if not reset / error was NXM mov $60007,(r0) / write EOF halt / halt on good dump 2: tst r4 / mapping beq 3b / branch if not sob r5,3b / yes, continue loop mov $20,r5 / reset loop count add $20000,r2 / bump low map adc r3 / carry to high map mov r2,(r1) / load map reg 0 low mov r3,2(r1) / load map reg 0 high clr 4(r0) / set bus address to 0 br 3b / do some more #else !NTM > 0 #if NTS > 0 TSDB = 0172520 TSSR = 0172522 IO = 0177600 UBMR0 = 0170200 /* * register usage is as follows: * * reg 0 -- points to UBMAP register 1 low * reg 1 -- is used to calculate the current memory address * for each 512 byte transfer. * reg 2 -- is used to contain and calculate memory pointer * for UBMAP register 1 low * reg 3 -- is used to contain and calculate memory pointer * for UBMAP register 1 high * reg 4 -- points to the command packet * reg 5 -- is used as an interation counter when mapping is enabled */ movb _ubmap,setmap / unibus map present? beq 2f / no, skip map init /* * This section of code initializes the Unibus map registers and * and the memory management registers. * UBMAP reg 0 points to low memory for the TS11 command, * characteristics, and message buffers. * UBMAP reg 1 gets updated to point to the current memory area. * Kernal I space 0 points to low memory * Kernal I space 7 points to the I/O page. */ mov $UBMR0,r0 / point to map register 0 clr r2 / init for low map reg clr r3 / init for high map reg clr (r0)+ / load map reg 0 low clr (r0)+ / load map reg 0 high mov $77406,*$KISD0 / set KISDR0 mov $77406,*$KISD7 / set KISDR7 clr *$KISA0 / point KISAR0 to low memory mov $IO,*$KISA7 / point KISAR7 to IO page inc *$SSR0 / turn on memory mngt mov $60,*$SSR3 / enable 22 bit mapping mov r2,(r0) / load map reg 1 low mov r3,2(r0) / load map reg 1 high 2: / this section of code initializes the TS11 tstb *$TSSR / make sure bpl 2b / drive is ready mov $comts,r4 / point to command packet add $2,r4 / set up mod 4 bic $3,r4 / alignment mov $140004,(r4) / write characteristics command mov $chrts,2(r4) / characteristics buffer clr 4(r4) / clear ext mem addr (packet) clr tsxma / clear extended memory save loc mov $10,6(r4) / set byte count for command mov $mests,*$chrts / show where message buffer is clr *$chrts+2 / clear extended memory bits here too mov $16,*$chrts+4 / set message buffer length mov r4,*$TSDB / start command mov $20,r5 / set up SOB counter for UBMAP clr r1 / init r1 beginning memory address 1: tstb *$TSSR / wait for ready bpl 1b / not yet mov *$TSSR,tstcc / error condition (SC)? bpl 2f / no error bic $!16,tstcc / yes error, get TCC cmp tstcc,$10 / recoverable error? bne 8f / no mov $101005,(r4) / yes, load write data retry command clr 4(r4) / clear packet ext mem addr mov r4,*$TSDB / start retry br 1b 8: bit $4000,*$TSSR / is error NXM? beq . / no, hang (not sure of good dump) mov $140013,(r4) / load a TS init command mov r4,*$TSDB / to clear NXM error 6: tstb *$TSSR / wait for ready bpl 6b mov $1,6(r4) / set word count = 1 mov $100011,(r4) / load write EOF command mov r4,*$TSDB / do write EOF 7: tstb *$TSSR / wait for ready bpl 7b halt / halt after good dump 9: br 1b 2: /* * If mapping is needed this section calculates the base address to * be loaded into map reg 1; the algorithm is (!(r5 - 21))*1000) | * 20000. The complement is required because an SOB loop is being * used for the counter. This loop causes 20000 bytes to be written * before the UBMAP is updated. */ tst setmap / UBMAP? beq 3f / no map mov r2,(r0) / load map reg 1 low mov r3,2(r0) / load map reg 1 high mov r5,r1 / calculate sub $21,r1 / address for this pass com r1 / based on current mul $1000,r1 / interation bis $20000,r1 / select map register 1 clr 4(r4) / clear extended memory bits 3: /* * This section does the write. If mapping is needed the sob loop * comes in play here. When the sob falls through the UBAMP reg will * be updated by 20000 to point to next loop section. If mapping not * needed then just calculate the next 512 byte address pointer. */ mov r1,2(r4) / load mem address mov tsxma,4(r4) / load ext mem address mov $512.,6(r4) / set byte count mov $100005,(r4) / set write command mov r4,*$TSDB / initiate xfer tst setmap / mapping? beq 4f / branch if not sob r5,9b / yes continue loop mov $20,r5 / reset loop count add $20000,r2 / bump low map adc r3 / carry to high map br 1b / do some more 4: add $512.,r1 / bump address for no mapping adc tsxma / carry to extended memory bits br 1b / do again /* * The following TS11 command and message buffers, must be in initialized data * space instead of bss space. This allows them to be mapped by the first * M/M mapping register, which is the only one used durring a core dump. */ tsxma: 0 / ts11 extended memory address bits setmap: 0 / UB map usage indicator tstcc: 0 / ts11 temp location for TCC comts: / ts11 command packet 0 ; 0 ; 0 ; 0 ; 0 chrts: / ts11 characteristics 0 ; 0 ; 0 ; 0 mests: / ts11 message buffer 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 0 #endif NTS #endif NTM #endif NHT #endif NHT || NTM || NTS br . / If no tape drive, fall through to here ng\n"); halt(); /*NOTREACHED*/ } else { if (howto & RB_DUMP) { /* * save the registers in low core. */ saveregs(); dumpsys(); } doboot(sys/pdp/mch_dzpdma.s 440 0 12 5034 4236507311 7720 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)mch_dzpdma.s 1.1 (2.10BSD Berkeley) 2/10/87 */ #include "DEFS.h" #include "../machine/mch_iopage.h" #include "../machine/koverlay.h" #include "dz.h" #if NDZ > 0 /* * DZ-11 pseudo-DMA interrupt routine. Called directly from the * interrupt vector; the device number is in the low bits of the PS. * Calls dzxint when the end of the buffer is reached. The pdma * structure is known to be: * * struct pdma { * struct dzdevice *pd_addr; / address of controlling device * char *p_mem; / start of buffer * char *p_end; / end of buffer * struct tty *p_arg; / tty structure for this line * }; */ ASENTRY(dzdma) mov PS,-(sp) / save new PS, r0-r3 and __ovno (r0 mov r0,-(sp) / saved before __ovno so we can mov __ovno,-(sp) / use it to restore overlay mov r1,-(sp) / mapping if necessary) mov r2,-(sp) mov r3,-(sp) #ifdef UCB_METER /* * 4.3BSD doesn't count this as an interrupt (cnt.v_intr) so we don't * either. */ inc _cnt+V_PDMA / cnt.v_pdma++ #endif mov 12(sp),r3 / new PS bic $!37,r3 / extract device number ash $3+3,r3 / r3 = &_dzpdma[dev*8] - 8 lines per DZ add $_dzpdma,r3 mov (r3)+,r2 / pd_addr in r2; r3 points to p_mem #ifdef UCB_CLIST mov KDSA5,-(sp) / save previous mapping mov KDSD5,-(sp) mov _clststrt,KDSA5 / map in clists mov _clstdesc,KDSD5 #endif 1: / loop until no line is ready movb 1(r2),r1 / dzcsr high byte bge 3f / test TRDY; branch if none bic $!7,r1 / extract line number ash $3,r1 / convert to pdma offset add r3,r1 / r1 is pointer to pdma.p_mem for line mov (r1)+,r0 / pdma->p_mem cmp r0,(r1)+ / cmp p_mem to p_end bhis 2f / if p_mem >= p_end movb (r0)+,6(r2) / dztbuf = *p_mem++ mov r0,-4(r1) / update p_mem br 1b 2: / buffer is empty; call dzxint mov (r1),-(sp) / p_arg jsr pc,_dzxint / r0, r1 are modified! tst (sp)+ br 1b / no more lines ready; return 3: #ifdef UCB_CLIST mov (sp)+,KDSD5 mov (sp)+,KDSA5 / restore previous mapping #endif mov (sp)+,r3 / restore saved registers mov (sp)+,r2 mov (sp)+,r1 SPL7 mov (sp)+,r0 / overlays get switched while we were cmp r0,__ovno / doing our thing? beq 4f mov r0,__ovno / yes, have to restore the earlier asl r0 / overlay mapping mov ova(r0),OVLY_PAR mov ovd(r0),OVLY_PDR 4: mov (sp)+,r0 / restore r0, toss new PS value tst (sp)+ / and return from the interrupt rtt #endif NDZ > 0 / set up SOB counter for UBMAP clr r1 / init r1 beginning memory address 1: tstb *$TSSR / wait for ready bpl 1b / not yet mov *$TSSR,tstcc / error condition (SC)? bpl 2f / no error bic $!16,tstcc / yes error, get TCC cmp tstcc,$10 / recoverable error? bne 8f / no mov $101005,(r4) / yes, load write data retry command clr 4(r4) / clear packet ext mem addr mov r4,*$TSDB / start retry br 1b 8: bit $4000,*$TSSR / is error NXM? beq . / no, hang (notsys/pdp/mch_iopage.h 440 0 12 11553 4263762454 7730 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)mch_iopage.h 1.1 (2.10BSD Berkeley) 6/12/88 */ /* * Access abilities (from seg.h) */ #define RO 02 /* Read only */ #define RW 06 /* Read and write */ #define SSR3 0172516 /* Memory Management register 3 */ #define CCSR 0172540 /* KW11-P Control/Status Register */ #define CCSB 0172542 /* KW11-P Counter Set Buffer */ #define SSR0 0177572 /* Memory Management register 0 */ #define SSR1 0177574 /* Memory Management register 1 */ #define SSR2 0177576 /* Memory Management register 2 */ #define STACKLIM 0177774 /* Stack Limit register */ #define PS 0177776 /* Processor Status register */ #define PIR 0177772 /* Program Interrupt Request register */ /* * ENABLE/34 registers * * All information relevant to the ENABLE/34 is supplied with * the permission of ABLE Computer and may not be disclosed in * any manner to sites not licensed by the University of California * for the Second Berkeley Software Distribution. * */ #ifdef ENABLE34 # define ENABLE_UISA 0163720 # define DEC_UISA 0177640 # ifdef NONSEPARATE # define ENABLE_UDSA ENABLE_UISA # define DEC_UDSA DEC_UISA # else # define ENABLE_UDSA 0163740 # define DEC_UDSA 0177660 # endif NONSEPARATE # define ENABLE_KISA0 0163700 # define ENABLE_KISA6 0163714 # define DEC_KISA0 0172340 # define DEC_KISA6 0172354 # ifdef KERN_NONSEP # define ENABLE_KDSA1 0163702 # define ENABLE_KDSA2 0163704 # define ENABLE_KDSA5 0163712 # define ENABLE_KDSA6 0163714 # define DEC_KDSA1 0172342 # define DEC_KDSA2 0172344 # define DEC_KDSA5 0172352 # define DEC_KDSA6 0172354 # else # define ENABLE_KDSA1 0163762 # define ENABLE_KDSA2 0163764 # define ENABLE_KDSA5 0163772 # define ENABLE_KDSA6 0163774 # define DEC_KDSA1 0172362 # define DEC_KDSA2 0172364 # define DEC_KDSA5 0172372 # define DEC_KDSA6 0172374 # endif KERN_NONSEP # define ENABLE_SSR4 0163674 # define ENABLE_SSR3 0163676 #endif ENABLE34 /* * Supervisor segmentation registers: * SISD: Supervisor Instruction Space Descriptors registers * SDSD: Supervisor Data Space Descriptors registers * SISA: Supervisor Instruction Space Address registers * SDSA: Supervisor Data Space Address registers */ #define SISD0 0172200 #define SISD1 0172202 #define SISD2 0172204 #define SISD3 0172206 #define SISD4 0172210 #define SISD5 0172212 #define SISD6 0172214 #define SISD7 0172216 #define SDSD0 0172220 #define SDSD1 0172222 #define SDSD2 0172224 #define SDSD3 0172226 #define SDSD4 0172230 #define SDSD5 0172232 #define SDSD6 0172234 #define SDSD7 0172236 #define SISA0 0172240 #define SISA1 0172242 #define SISA2 0172244 #define SISA3 0172246 #define SISA4 0172250 #define SISA5 0172252 #define SISA6 0172254 #define SISA7 0172256 #define SDSA0 0172260 #define SDSA1 0172262 #define SDSA2 0172264 #define SDSA3 0172266 #define SDSA4 0172270 #define SDSA5 0172272 #define SDSA6 0172274 #define SDSA7 0172276 /* * Kernel segmentation registers: * KISD: Kernel Instruction Space Descriptors registers * KDSD: Kernel Data Space Descriptors registers * KISA: Kernel Instruction Space Address registers * KDSA: Kernel Data Space Address registers */ #define KISD0 0172300 #define KISD1 0172302 #define KISD2 0172304 #define KISD4 0172310 #define KISD5 0172312 #define KISD6 0172314 #define KISD7 0172316 #ifdef KERN_NONSEP # define KDSD0 KISD0 # define KDSD5 KISD5 # define KDSD6 KISD6 # define KDSD7 KISD7 #else # define KDSD0 0172320 # define KDSD5 0172332 # define KDSD6 0172334 # define KDSD7 0172336 #endif #ifdef ENABLE34 # define KISA0 *_KISA0 #else # define KISA0 0172340 #endif #define KISA1 0172342 #define KISA2 0172344 #define KISA4 0172350 #define KISA5 0172352 #ifdef ENABLE34 # define KISA6 *_KISA6 #else # define KISA6 0172354 #endif #define KISA7 0172356 #ifdef KERN_NONSEP # define KDSA0 KISA0 # ifdef ENABLE34 # define KDSA1 *_KDSA1 # define KDSA2 *_KDSA2 # define KDSA5 *_KDSA5 # define KDSA6 *_KDSA6 # else # define KDSA1 KISA1 # define KDSA2 KISA2 # define KDSA5 KISA5 # define KDSA6 KISA6 # endif # define KDSA7 KISA7 #else KERN_NONSEP # define KDSA0 0172360 # ifdef ENABLE34 # define KDSA1 *_KDSA1 # define KDSA2 *_KDSA2 # define KDSA5 *_KDSA5 # define KDSA6 *_KDSA6 # else # define KDSA1 0172362 # define KDSA2 0172364 # define KDSA5 0172372 # define KDSA6 0172374 # endif # define KDSA7 0172376 #endif KERN_NONSEP /* * User segmentation registers: * UISD: User Instruction Space Descriptors registers * UDSD: User Data Space Descriptors registers * UISA: User Instruction Space Address registers * UDSA: User Data Space Address registers */ #ifdef ENABLE34 # define UISA *_UISA # define UDSA *_UDSA #else # define UISA 0177640 # define UDSA 0177660 #endif 05,(r4) / set write command mov r4,*$TSDB / initiate xfer tst setmap / mapping? beq 4f / branch if not sob r5,9b / yes continue loop movsys/pdp/toy.s 640 0 12 12416 5233350020 6440 / the notes say that the TOY clock uses 24 hour time, but then later on / mention flags dealing with AM/PM... So, code is present but disabled / to handle 12 hour time. If this code is needed change the 0 below to / a 1. toy24=0 / extraneous flag bit possible in the day field. this "should never / happen", but if it does change the 0 to a 1 below. dayflags=0 .globl TOYCSR TOYCSR = 177526 .globl _toyclk .text _toyclk: jsr r5,csv / callable from C, save regs sub $8.,sp / need 8 byte scratch area tdata = -20 cmp _cputype,$93. / are we a 11/93? beq 1f / yes - br cmp _cputype,$94. / are we a 11/94? bne err / no, go return "error" 1: jsr pc,initoy / initialize the clock for reading mov r5,(sp) add $tdata,(sp) / pointer to scratch area jsr pc,_gettoy / read the toy clock mov (sp),r2 / pointer to scratch area mov $8.,r3 / number of bytes of clock data 2: clr r1 bisb (r2),r1 / fetch byte of clock data (!sign ext) .if toy24 cmp r3,$5 / are we on the hours field? bne 3f / no - br bic $240,r1 / clear am/pm flags 3: .endif jsr pc,bcd / convert 2 nybbles bcd to binary .if toy24 cmp r3,$5 / hours field? bne 4f / no - skip am/pm stuff tstb (r2) / $200 = am/pm in use bpl 4f / not am/pm, skip it cmp r1,$12. / exactly 12? bne 5f / no - br clr r1 / make midnight 5: bitb $40,(r2) / PM? beq 4f / no - br add $12.,r1 / convert to 24 hour time .endif 4: movb r1,(r2)+ / store converted/correct binary value sob r3,2b / continue on for rest of the bytes sub $7,r2 / back up to seconds field .if dayflags bicb $177770,4(r2) / clear possible excess bits in day .endif mov $bounds,r3 / do bounds checking now, not 100ths 1: movb (r2)+,r1 / get byte of clock data cmpb r1,(r3)+ / below lo bound? blo err / yes - br cmpb r1,(r3)+ / above hi bound bhi err / yes - br cmp r3,$bounds+14. / at end (7 limits * 2 bytes per = 14)? blo 1b / no - br sub $8.,r2 / back to seconds field movb 7(r2),r0 / fetch the year of century cmp r0,$90. / are we a "90s" system? bhis 1f / yep - br add $100.,r0 / next century for years 00 - 89 1: movb r0,7(r2) / store fixed up year decb 6(r2) / convert 1-12 month to 0-11 mov r2,(sp) / pointer to the toy clock data jsr pc,_tm2t / convert to a 32bit # of seconds time br ret err: clr r0 / a double precision value clr r1 / of 0 signals an error ret: jmp cret / return .data bounds: .byte 0,59. / seconds lo,hi .byte 0,59. / minutes lo,hi .byte 0,23. / hours lo,hi .byte 0,7 / day of week lo,hi .byte 1,31. / day of month lo,hi .byte 1,12. / month of year lo,hi .byte 0,99. / year of century lo,hi .text initoy: tst *$TOYCSR / strobe the clock register clr -(sp) / save previous high byte of register movb *$TOYCSR+1,(sp) / only bit 8 belongs to TOY! bic $1,(sp) / make sure bit 8 (TOY bit) is clear mov $2,r2 / number of double words to send clock 1: mov $35305,r0 / first word of recognition code jsr pc,toyload / send it to clock mov $56243,r0 / second word jsr pc,toyload / send it sob r2,1b / do the whole thing twice tst (sp)+ / clean stack rts pc / send contents of r0 to the TOY. 2(sp) has the old bits 9-15, bit 8 / has been cleared. toyload: mov $16.,r1 / number of bits to send 1: mov r0,r3 / scratch copy bic $177776,r3 / clear all but bit being sent bis 2(sp),r3 / merge in old_csr_bits movb r3,*$TOYCSR+1 / send bit to clock asr r0 / shift pattern down sob r1,1b / do all 16 bits in the word rts pc .globl _gettoy _gettoy: / (void)gettoy(&char[8]); jsr r5,csv / C callable mov 4(r5),r2 / buffer address mov $4,r3 / number of words in buffer 1: mov $16.,r4 / number of bits in word 2: movb *$TOYCSR+1,r0 / low bit of top byte is a clock bit asr r0 / put it in carry ror r1 / ripple in at top end of r1 sob r4,2b / do all 16 bits mov r1,(r2)+ / store the word in the buffer sob r3,1b / do all 4 words jmp cret / and return bcd: clr r0 div $16.,r0 mov r1,-(sp) mov r0,r1 mul $10.,r1 add (sp)+,r1 rts pc .globl _tm2t _tm2t: jsr r5,csv mov 4(r5),r4 movb 1(r4),r1 mov r1,-(sp) clr -(sp) movb 2(r4),r0 mul $74,r0 mov r1,-(sp) mov r0,-(sp) mov $7020,-(sp) sxt -(sp) movb 3(r4),r1 mov r1,-(sp) clr -(sp) jsr pc,lmul add $10,sp mov r1,-(sp) mov r0,-(sp) mov $50600,-(sp) mov $1,-(sp) mov r4,-(sp) jsr pc,_ndays / return value in r1 tst (sp)+ dec r1 mov r1,-(sp) sxt -(sp) jsr pc,lmul add $10,sp add (sp)+,r0 add (sp)+,r1 adc r0 add (sp)+,r0 add (sp)+,r1 adc r0 add (sp)+,r0 add (sp)+,r1 adc r0 jmp cret _leap: / r2 = year number, r1 clobbered mov r2,r1 add $3554,r1 sxt r0 div $620,r0 tst r1 bne 2f br 3f 1: clr r0 / return false br 4f 2: mov r2,r1 sxt r0 div $144,r0 tst r1 jeq 1b bit $3,r2 jne 1b 3: mov $1,r0 / return true 4: rts pc .data mdays: .byte 37,34,37,36,37,36,37,37,36,37,36,37,0 .even .text _ndays: jsr r5,csv mov 4(r5),r0 movb 5(r0),r4 mov $106,r2 jbr 3f 1: add $555,r4 jsr pc,*$_leap / r2 has year in it already add r0,r4 inc r2 3: mov 4(r5),r0 movb 7(r0),r0 cmp r2,r0 jlt 1b clr r3 jbr 8f 4: clr r0 cmp $1,r3 jne 5f jsr pc,*$_leap / r2 has year 5: movb mdays(r3),r1 add r1,r0 add r0,r4 inc r3 8: mov 4(r5),r0 movb 6(r0),r0 cmp r3,r0 jlt 4b mov r4,r1 / return value in r1 not r0 jmp cret day field. this "should never / happen", but if it does change the 0 to a 1 below. dayflags=0 .globl TOYCSR TOYCSR = 177526 .globl _toyclk .text _toyclk: jsr r5,csv / callable from C, save regs sub $8.,sp / need 8 byte scratch asys/pdp/mch_profile.s 440 0 12 3630 5316460316 10104 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)mch_profile.s 1.2 (2.11BSD GTE) 12/24/92 */ /* * XXX - Current system profiling code doesn't really work with the new * kernel. As soon as I've figured out how I'm going to implement * general profiling, I'll integrate it into the kernel. * * Casey */ #ifdef PROF /* * System profiler * * Expects to have a KW11-P in addition to the line-frequency clock, and it * should be set to BR7. Uses supervisor I space register 2 and 3 (040000 - * 0100000) to maintain the profile. */ CONST(GLOBAL, _probsiz, 040000) / max prof pc/4 (040000 is everything) SPACE(GLOBAL, _outside, 2) / times outside profiling range SPACE(GLOBAL, _mode, 4*4) / what mode we're spending our time in /* * Process profiling clock interrupts */ ENTRY(sprof) mov r0,-(sp) / snag a register for our use mov PS,r0 / r0 = previous mode * 4 ash $-10.,r0 bic $!14,r0 add $1,_mode+2(r0) / mode[previous mode]++ adc _mode(r0) cmp r0,$14 / if previous made was user, beq 2f / we're done ... mov 2(sp),r0 / r0 = (interrupted pc / 4) &~ 0140001 asr r0 asr r0 bic $0140001,r0 cmp r0,$_probsiz / if r0 >= probsiz, blo 1f inc _outside / outside++ br 2f / and we're done 1: mov $010340,PS / set previous mode to supervisor #ifdef INET mov SISA2, -(sp) / save supervisor mapping mov SISD2, -(sp) mov SISA3, -(sp) mov SISD3, -(sp) mov _proloc, SISA2 mov 77406, SISD2 mov _proloc+2, SISA3 mov 77406, SISD3 #endif mfpi 40000(r0) / and increment 040000[r0] inc (sp) / (the rtt will reset the PS mtpi 40000(r0) / properly) #ifdef INET mov (sp)+, SISD3 mov (sp)+, SISA3 mov (sp)+, SISD2 mov (sp)+, SISA2 #endif 2: mov (sp)+,r0 / restore the used register rtt / and return from the interrupt #endif PROF br sub $8.,r2 / back to seconds field movb 7(r2),r0 / fetch the year of century cmp r0,$90. / asys/pdp/mch_start.s 440 0 12 12147 5436274745 7640 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)mch_start.s 1.4 (2.11BSD GTE) 8/23/93 */ #include "DEFS.h" #include "../machine/mch_iopage.h" #include "../machine/mch_cpu.h" #include "../machine/trap.h" ASENTRY(start) bit $1,SSR0 / is memory management enabled? beq . / better be !!! mov r0,_cputype / save cpu type passed by boot /* * The following two instructions change the contents of the "sys" * instruction vector (034-037) to read: * syscall; br0+T_SYSCALL */ mov $syscall,34 mov $0+T_SYSCALL,36 #ifdef KERN_NONSEP movb $RO,KISD0 / Turn off write permission on kernel / low text #endif mov $USIZE-1\<8|RW,KDSD6 / Get a stack pointer (_u + 64*USIZE) mov $_u+[USIZE*64.],sp #ifdef INET /* * Initial set up for SUPERVISOR space networking: set SUPERVISOR * space as split I&D, set stack pointer and map user area and I/O * page. */ bis $2,SSR3 / split i/d for supervisor network mov PS,-(sp) / set SUPERVISOR sp to NET_STOP mov $010340,PS mov $NET_STOP,-(sp) mtpd sp mov (sp)+,PS mov KDSA6,SDSA6 / map user area and I/O page mov KDSD6,SDSD6 mov KDSD7,SDSD7 mov KDSA7,SDSA7 #endif mov $_u,r0 / Clear user block 1: clr (r0)+ cmp r0,sp blo 1b /* * Get bootflags and leave them in _initflags; the bootstrap leaves * them in r4. R2 should be the complement of bootflags. */ com r2 / if r4 != ~r2 cmp r4,r2 beq 1f mov $RB_SINGLE,r4 / r4 = RB_SINGLE 1: mov r1,_bootcsr / save boot controller csr mov r3,_bootdev / save boot device major,unit mov r4,_boothowto / save boot flags mov $_initflags+6,r2 / get a pointer to the \0 in _initflags mov r4,r1 / r1 = boot options 1: clr r0 / r0:r1 = (long)r1 div $10.,r0 / r0 = r0:r1 / 10; r1 = r0:r1 % 10 add $'0,r1 / bias by ASCII '0' movb r1,-(r2) / and stuff into _initflags mov r0,r1 / shift quotient and continue bne 1b / if non-zero /* Check out (and if necessary, set up) the hardware. */ jsr pc,hardprobe /* * Set up previous mode and call main. On return, set user stack * pointer and enter user mode at location zero to execute the * init thunk _icode copied out in main. */ mov $30340,PS / set current kernel mode, previous / mode to user, spl7, make adb clr r5 / find end of kernel stack frames jsr pc,_main / call main mov $177776,-(sp) / set init thunk stack pointer to top mtpd sp / of memory ... mov $170000,-(sp) / set up pseudo trap frame: user/user clr -(sp) / mode, location zero, rtt / and book ... .data /* * Icode is copied out to process 1 to exec /etc/init. * If the exec fails, process 1 exits. */ .globl _initflags, _szicode, _boothowto, _bootcsr, _bootdev ENTRY(icode) mov $argv-_icode,-(sp) mov $init-_icode,-(sp) tst -(sp) / simulate return address stack spacing sys SYS_execv sys SYS_exit init: _initflags: <-00000\0> / decimal ASCII initflags .even argv: init+5-_icode / address of "init\0" _initflags-_icode 0 _szicode: _szicode-_icode _boothowto: 0 / boot flags passed by boot _bootdev: 0 / boot major#,unit _bootcsr: 0 / csr of booting controller .text /* * Determine a couple of facts about the hardware and finishing setting * up what 'boot' hasn't done already. * We use the cpu type passed thru from /boot. No sense in duplicating * that code here in the kernel. We do have to repeat the KDJ-11 test * (for use in trap.c) though. /boot also stuffed the right bits into * the MSCR register to disable cache and unibus traps. */ hardprobe: mov $1f,nofault setd inc _fpp 1: /* * Test for SSR3 and UNIBUS map capability. If there is no SSR3, the * first test of SSR3 will trap and we skip past the separate I/D test. * 2.11BSD will be _seriously_ upset if I/D is not available! */ mov $2f,nofault bit $40,SSR3 beq 1f incb _ubmap 1: bit $1,SSR3 / Test for separate I/D capability beq 2f incb _sep_id 2: / Test for stack limit register; set it if present. mov $1f,nofault mov $intstk-256.,STACKLIM 1: clr _kdj11 mov $1f,nofault mfpt cmp r0,$5 / KDJ-11 returns 5 (11/44 returns 1) bne 1f mov r0,_kdj11 1: #ifdef ENABLE34 /* * Test for an ENABLE/34. We are very cautious since the ENABLE's * PARs are in the range of the floating addresses. */ tstb _ubmap bne 2f mov $2f,nofault mov $32.,r0 mov $ENABLE_KISA0,r1 1: tst (r1)+ sob r0,1b tst *$PDP1170_LEAR tst *$ENABLE_SSR3 tst *$ENABLE_SSR4 incb _enable34 incb _ubmap /* * Turn on an ENABLE/34. Enableon() is a C routine which does a PAR * shuffle and turns mapping on. */ .data _UISA: DEC_UISA _UDSA: DEC_UDSA _KISA0: DEC_KISA0 _KISA6: DEC_KISA6 _KDSA1: DEC_KDSA1 _KDSA2: DEC_KDSA2 _KDSA5: DEC_KDSA5 _KDSA6: DEC_KDSA6 .text mov $ENABLE_UISA, _UISA mov $ENABLE_UDSA, _UDSA mov $ENABLE_KISA0, _KISA0 mov $ENABLE_KISA6, _KISA6 mov $ENABLE_KDSA1, _KDSA1 mov $ENABLE_KDSA2, _KDSA2 mov $ENABLE_KDSA5, _KDSA5 mov $ENABLE_KDSA6, _KDSA6 mov $ENABLE_KDSA6, _ka6 jsr pc, _enableon 2: #endif ENABLE34 clr nofault / clear fault trap and return rts pc packet 0 ; 0 ; 0 ; 0 ; 0 chrts: / ts11 characteristics 0 ; 0 ; 0 ; 0 mests: / ts11 message buffer 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 0 #endif NTS #endif NTM #endif NHT #endif NHT || NTM || NTS br . / If no tape drive, fall through to here ng\n"); halt(); /*NOTREACHED*/ } else { if (howto & RB_DUMP) { /* * save the registers in low core. */ saveregs(); dumpsys(); } doboot(sys/pdp/mch_trap.s 640 0 12 21752 5514077332 7443 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)mch_trap.s 2.2 (2.11BSD GTE) 1/9/94 */ #include "DEFS.h" #include "../machine/mch_iopage.h" #include "../machine/koverlay.h" #include "../machine/trap.h" SPACE(LOCAL, saveps, 2) /* * jsr r0,call * jmp trap_handler * * mov PS,saveps * jsr r0,call1 * jmp trap_handler * * Interrupt interface code to C. Creates an interrupt stack frame, calls * the indicated trap_handler. Call forces the previous mode to be user so * that copy in/out and friends use user space if called from interrupt * level. Call1 is simply an alternate entry to call that assumes that the * PS has already been changed and the original PS can be found in saveps. * Call1 also doesn't increment cnt.v_intr since it's only called from * synchronous software traps. * * The interrupt stack frame - note that values in must agree: * * reg.h * | ps | 2 / ps and pc saved by interrupt * | pc | 1 * u.u_ar0 | r0 | 0 * | nps | / from interrupt vector * | ovno | * | r1 | -3 * | sp | -4 * | code | / nps & 037 * --------------------------------/ above belongs to call, below to csv * | ret | / return address to call * r5 | old r5 | -7 * | ovno | * | r4 | -9 * | r3 | -10 * | r2 | -11 * sp | *empty* | */ call1: mov saveps,-(sp) / stuff saved nps into interrupt frame SPLLOW / ensure low priority (why?) br 1f / branch around count of interrupts ASENTRY(call) /* * Interrupt entry code. Save various registers, etc., and call * interrupt service routine. */ mov PS,-(sp) / stuff nps into interrupt frame #ifdef UCB_METER inc _cnt+V_INTR / cnt.v_intr++ #endif 1: mov __ovno,-(sp) / save overlay number, mov r1,-(sp) / r1, mfpd sp / sp mov 6(sp),-(sp) / grab nps and calculate bic $!37,(sp) / code = nps & 037 bis $30000,PS / force previous mode = user jsr pc,(r0) / call trap_handler #ifdef INET /* * Check for scheduled network service requests. The network sets * _knetisr to schedule network activity at a later time when the * system IPL is low and things are ``less hectic'' ... */ mov PS,-(sp) / set SPL7 so _knetisr doesn't get SPL7 / changed while we're looking at it tst _knetisr / if (_knetisr != 0 beq 2f bit $340,20(sp) / && interrupted IPL == 0 bne 2f / [shouldn't we check against SPLNET?] cmp sp,$_u / && sp > _u (not on interrupt stack)) blos 2f #ifdef UCB_METER inc _cnt+V_SOFT / increment soft interrupt counter, #endif clr _knetisr / reset the flag, SPLNET / set network IPL, clr -(sp) / and KScall(netintr, 0) mov $_netintr,-(sp) jsr pc,_KScall cmp (sp)+,(sp)+ 2: mov (sp)+,PS / restore PS #endif /* * Clean up from interrupt. If previous mode was user and _runrun * is set, generate an artificial SWITCHTRAP so we can schedule in a * new process. */ bit $20000,10(sp) / previous mode = user?? beq 4f tstb _runrun / yep, is the user's time up? beq 3f mov $T_SWITCHTRAP,(sp) / yep, set code to T_SWITCHTRAP jsr pc,_trap / and give up cpu 3: /* * Trap from user space: toss code and reset user's stack pointer. */ tst (sp)+ / toss code, reset user's sp mtpd sp / and enter common cleanup code br 5f 4: /* * Trap from kernel or supervisor space: toss code and stack pointer * (only user stack pointers need to be set or reset). */ cmp (sp)+,(sp)+ / trap from kernel or supervisor: 5: / toss code and sp /* * Finish final clean up, restore registers, etc. make sure we * leave the same overlay mapped that we came in on, and return * from the interrupt. */ mov (sp)+,r1 / restore r1 mov (sp)+,r0 / current overlay different from cmp r0,__ovno / interrupted overlay? beq 6f SPL7 / yes, go non-interruptable (rtt / below restores PS) mov r0,__ovno / reset ovno and mapping for asl r0 / interrupted overlay mov ova(r0),OVLY_PAR mov ovd(r0),OVLY_PDR 6: tst (sp)+ / toss nps mov (sp)+,r0 / restore r0 rtt / and return from the trap ... #ifdef INET /* * iothndlr is used to allow the network in supervisor mode to make calls * to the kernel. * * the network pushes a pair on the kernel stack before doing the * 'iot'. when we process the iot here we throw the saved pair * resulting from the 'iot' away and use instead the pair pushed by the * network as the target for our 'rtt'. * * there was a warning that this hasn't been tested with overlays in the * kernel. can't see why it wouldn't work. */ ASENTRY(iothndlr) mov PS,saveps / save PS in case we have to trap bit $20000,PS / previous mode = supervisor? bne trap1 / (no, let trap handle it) bit $10000,PS beq trap1 / (no, let trap handle it) cmp (sp)+,(sp)+ / yes, toss iot frame and execute rtt rtt / on behalf of networking kernel #endif /* * System call interface to C code. Creates a fake interrupt stack frame and * then vectors on to the real syscall handler. It's not necessary to * create a real interrupt stack frame with everything in the world saved * since this is a synchronous trap. */ ASENTRY(syscall) mov PS,saveps / save PS just in case we need to trap bit $20000,PS / trap from user space? beq trap2 / no, die mov r0,-(sp) cmp -(sp),-(sp) / fake __ovno and nps - not needed mov r1,-(sp) mfpd sp / grab user's sp for argument addresses tst -(sp) / fake code - not needed jsr pc,_syscall / call syscall and start cleaning up tst (sp)+ mtpd sp / reload user sp, r1 and r0 mov (sp)+,r1 / (cret already reloaded the other cmp (sp)+,(sp)+ / registers) mov (sp)+,r0 rtt / and return from the trap /* * Emt takes emulator traps, which are requests to change the overlay for the * current process. If an invalid emt is received, _trap is called. Note * that choverlay is not called with a trap frame - only r0 and r1 are saved; * it's not necessary to save __ovno as this is a synchronous trap. */ ASENTRY(emt) mov PS,saveps / save PS just in case we need to trap bit $20000,PS / if the emt isn't from user mode, beq trap2 / or, the process isn't overlaid, tst _u+U_OVBASE / or the requested overlay number beq trap2 / isn't valid, enter _trap cmp r0,$NOVL bhi trap2 mov r0,-(sp) / everything's cool, save r0 and r1 mov r1,-(sp) / so they don't get trashed mov r0,_u+U_CUROV / u.u_curov = r0 mov $RO,-(sp) / map the overlay in read only #ifdef UCB_METER inc _cnt+V_OVLY / cnt.v_ovly++ #endif add $1,_u+U_RU+RU_OVLY+2 / u.u_ru.ru_ovly++ adc _u+U_RU+RU_OVLY jsr pc,_choverlay / and get choverlay to bring the overlay in tst (sp)+ / toss choverlay's paramter, mov (sp)+,r1 / restore r0 and r1, mov (sp)+,r0 rtt / and return from the trap /* * Traps without specialized catchers get vectored here. We re-enable memory * management because the fault that caused this trap may have been a memory * management fault which sometimes causes the contents of the memory managment * registers to be frozen so error recovery can be attempted. */ ASENTRY(trap) mov PS,saveps / save PS for call1 trap1: tst nofault / if someone's already got this trap bne catchfault / scoped out, give it to them /* * save current values of memory management registers in case we * want to back up the instruction that failed */ mov SSR0,ssr #ifndef KERN_NONSEP mov SSR1,ssr+2 #endif mov SSR2,ssr+4 mov $1,SSR0 / re-enable relocation trap2: jsr r0,call1; jmp _trap / and let call take us in to _trap ... /*NOTREACHED*/ /* * We branch here when we take a trap and find that the variable nofault is * set indicating that someone else is interested in taking the trap. */ catchfault: mov $1,SSR0 / re-enable memory management mov nofault,(sp) / relocation, fiddle with the rtt / machine trap frame and boogie /* * Power fail handling. On power down, we just set up for the next trap. * On power up we attempt an autoboot ... */ #define PVECT 24 / power fail vector ASENTRY(powrdown) mov $powrup,PVECT / on power up, trap to powrup, SPL7 / and loop at high priority br . #ifndef KERN_NONSEP .data #endif /* * Power back on... wait a bit, then attempt a reboot. Can't do much * since memory management is off (hence we are in "data" space). */ powrup: /* * Not sure why these are necessary except that on a 44 it appears * that the first instruction or two of a power up trap do not * execute properly. */ nop;nop;nop /* * The nested loop below gives 38 seconds of delay on a 11/44 (30 sec * on a 11/93) for controllers to complete selftest after power comes * back up. */ mov $400.,r0 2: clr r1 3: nop sob r1,3b sob r0,2b mov $RB_POWRFAIL,r4 / and try to reboot ... mov _bootdev,r3 /* * 'jsr' can not be used because there is no stack at the moment (battery * backup preserves memory but not registers). 'hardboot' sets up a stack * if it needs one, so it is not necessary to do that here. */ jmp *$hardboot /*NOTREACHED*/ .text : clr r0 / success!sys/pdp/mch_vars.s 440 0 12 2156 5436274026 7425 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)mch_vars.s 1.2 (2.11BSD GTE) 8/23/93 */ #include "DEFS.h" #include "../machine/mch_iopage.h" CONST(GLOBAL, _u, 0140000) INT(GLOBAL, _fpp, 0) / we have a floating point processor INT(GLOBAL, _ubmap, 0) / we have a unibus map INT(GLOBAL, _cputype, 0) / cpu type INT(GLOBAL, _kdj11, 0) / cpu is a KDJ-11 CHAR(GLOBAL, _sep_id, 0) / we have a separate I&D CPU #ifdef ENABLE34 CHAR(GLOBAL, _enable34, 0) / we have an ABLE Enable/34 network board #endif .even /* * Define _ka6 and give it a reasonable initial value */ #ifdef KERN_NONSEP # ifdef ENABLE34 INT(GLOBAL, _ka6, DEC_KISA6) # else INT(GLOBAL, _ka6, KISA6) # endif #else # ifdef ENABLE34 INT(GLOBAL, _ka6, DEC_KDSA6) # else INT(GLOBAL, _ka6, KDSA6) # endif #endif SPACE(GLOBAL, intstk, INTSTK) / temp stack while KDSA6 is unmapped CONST(GLOBAL, eintstk, intstk+INTSTK) / top of interuupt stack INT(GLOBAL, nofault, 0) / address of temp fault trap handler re License Agreement * specifies the terms and conditions for redistribution. * * @(#)mch_vars.s 1.2 (2.11BSD GTE) 8/23/93 */ #include "DEFS.h" #include "../machine/mch_iopage.h" CONST(GLOBAL, _u, 0140000) INT(GLOBAL, _fpp, 0) / we have a floating point processor INT(GLOBAL, _ubmap, 0) / we have a unibus map INT(GLOBAL, _cputype, 0) / cpu type INT(GLOBAL, _kdj11, 0) / cpu is a KDJ-11 CHsys/pdp/mch_xxx.s 640 0 12 40115 5674212626 7322 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)mch_xxx.s 1.5 (2.11BSD GTE) 12/15/94 */ #include "DEFS.h" #include "../machine/mch_iopage.h" #include "../machine/koverlay.h" /* * noop() * * Do nothing. Typically used to provide enough time for interrupts to * happen between a pair of spl's in C. We use noop rather than inserting * meaningless instructions between the spl's to prevent any future C * optimizer `improvements' from causing problems. * * delay(usec) * long usec; * * Delay (approximately) usec micro-seconds. It really isn't very acurrate * since we can be interrupted and take much longer than we intended, but * that's alright - we just don't want to come home early ... */ ENTRY(delay) mov 2(sp),r0 / r0 = hiint(usec) mov 4(sp),r1 / r1 = loint(usec) ashc $1,r0 / sob's ~= 1/2 micro second, beq 2f / oops, got passed a delay of 0L-leave tst r1 /* * If the low int of the loop counter is zero, the double sob loop * below will perform correctly, otherwise the high byte must be * increment. */ beq 1f inc r0 / correct for looping 1: sob r1,1b / sit on our hands for a while ... sob r0,1b 2: ENTRY(noop) rts pc /* * idle() * * Sit and wait for something to happen ... */ /* * If you have a console display it's amusing to see a slowly rotating * sequence of lights in the display. If the system is very active the display * will appear blurred. */ INT(LOCAL, rdisply, 0377) / idle pattern INT(LOCAL, wcount, 2) / rotate rdisply every wcount calls ENTRY(idle) mov PS,-(sp) / save current SPL, indicate that no mov $1,_noproc / process is running dec wcount / if (--wcount <= 0) { bgt 1f mov $2,wcount / wcount = 2 clc / rdisply <<= 1 rol rdisply bpl 1f / if (``one shifted out'') bis $1,rdisply / rdisply |= 1 1: / } mov rdisply,r0 / wait displays contents of r0 SPLLOW / set SPL low so we can be interrupted wait / wait for something to happen mov (sp)+,PS / restore previous SPL rts pc / and return #ifdef PROF /* * These words are to insure that times reported for any following routine do * not include those spent while in idle mode when statistics are gathered * for system profiling. */ rts pc rts pc rts pc #endif /* * setjmp(env) * label_t *env; * * longjmp(u, env) * resume(u, env) * memaddr u; * label_t *env; * * Setjmp(env) will save the process' current register variable, stack, * overlay and program counter context and return a zero. * * Longjmp(u, env) (and resume) will will generate a "return(1)" from the last * call to setjmp(env) by mapping in the user structure pointed to by u, * restoring the context saved by setjmp in env and returning a one. Note that * registers are recovered statically from the env buffer rather than * dynamically from the stack ... * * This longjmp differs from the longjmp found in the standard library and the * VAX 4.3 kernel - it's actually closer to the resume routine of the 4.3 * kernel and, indeed, even used to be called resume in the 2.9 kernel. * We've given it both names to promote some degree of compatibility between * the 4.3 and 2.10 C kernel source ... */ ENTRY(setjmp) mov (sp)+,r1 / save return address mov (sp),r0 / r0 = env mov r2,(r0)+ / save register variables r2 - r4 mov r3,(r0)+ / in env ... mov r4,(r0)+ mov r5,(r0)+ / frame pointer, mov sp,(r0)+ / stack pointer, #ifdef INET mov PS,-(sp) / network stack pointer, mov $010340,PS mfpd sp #ifdef CHECKSTACK cmp (sp),$NET_STOP / (check network stack pointer to bhi 1f / make sure it's in the network cmp (sp),$NET_SBASE / stack ...) bhi 2f 1: halt 2: #endif mov (sp)+,(r0)+ mov (sp)+,PS #endif mov __ovno,(r0)+ / overlay number, mov r1,(r0)+ / and return address clr r0 / return a zero for the setjmp call jmp (r1) ENTRY(longjmp) ENTRY(resume) mov 2(sp),r0 / r0 = u mov 4(sp),r1 / r1 = env SPL7 / can't let anything in till we / (at least) get a valid stack ... mov r0,KDSA6 / map new process' u structure in #ifdef INET mov r0,SDSA6 / map supervisor stack area to same #endif mov (r1)+,r2 / restore register variables mov (r1)+,r3 / from env ... mov (r1)+,r4 mov (r1)+,r5 / frame pointer, mov (r1)+,sp / stack pointer, #ifdef INET mov PS,-(sp) / network stack pointer, mov $010340,PS mov (r1)+,-(sp) mtpd sp mov (sp)+,PS #endif mov (r1)+,r0 / grab return overlay number ... cmp r0,__ovno / old overlay currently mapped in? beq 1f mov r0,__ovno / nope, set new overlay number asl r0 / compute descriptor index and map mov ova(r0),OVLY_PAR / the old overlay back in ... mov ovd(r0),OVLY_PDR 1: mov $1001,SSR0 / J-11 bug, force MMU registers to start / tracking again between processes SPLLOW / release interrupts and transfer back mov $1,r0 / to setjmp return with a return jmp *(r1)+ / value of 1 /* * struct uprof { / profile arguments * short *pr_base; / buffer base * unsigned pr_size; / buffer size * unsigned pr_off; / pc offset * unsigned pr_scale; / pc scaling * } u_prof; * * addupc(pc, pbuf, ticks) * caddr_t pc; * struct uprof *pbuf; * int ticks; * * Addupc implements the profil(2) facility: * * b = (pc - pbuf->pr_off)>>1; * b *= pbuf->pr_scale>>1; * b >>= 14; { 2^14 = 2^16/2/2 - because of the two `>>'s above } * if (b < pbuf->pr_size) { * b += pbuf->pr_base; * if (fuword(b, &w) < 0 || suword(b, w) < 0) * pbuf->pr_scale = 0; { turn off profiling } * } */ ENTRY(addupc) mov r2,-(sp) / save register so we can use it mov 6(sp),r2 / r2 = pbuf mov 4(sp),r0 / r0 = pc sub 4(r2),r0 / r0 -= pbuf->pr_off clc / r0 >>= 1 { ensure high bit 0 } ror r0 mov 6(r2),r1 / r1 = pbuf->pr_scale clc / r1 >>= 1 { ensure high bit 0 } ror r1 mul r1,r0 / r0:r1 = r0 * (pbuf->pr_scale>>1) ashc $-14.,r0 / r0:r1 >>= 14 inc r1 / *round* r1 to a word offset bic $1,r1 cmp r1,2(r2) / if r1 > pbuf->pr_size bhis 3f / bug out ... add (r2),r1 / r1 += pbuf->pr_base mov nofault,-(sp) / set up for possible memory fault when mov $1f,nofault / access pbuf->pr_base[r1] : branch / to 1f on fault mfpd (r1) / pbuf->pr_base[r1] += ticks add 12.(sp),(sp) mtpd (r1) br 2f / (branch around fault code) 1: / on fault: disable profiling clr 6(r2) / (pbuf->pr_scale = 0) 2: mov (sp)+,nofault / reset fault branch 3: mov (sp)+,r2 / restore saved registers rts pc / and return #ifndef ENABLE34 /* * fioword(addr) * caddr_t addr; * * Fetch a word from an address on the I/O page, * returning -1 if address does not exist. */ ENTRY(fioword) mov nofault,-(sp) mov $2f,nofault mov *4(sp),r0 1: mov (sp)+,nofault rts pc 2: mov $-1,r0 br 1b #endif /* * error = copystr(fromaddr, toaddr, maxlength, lencopied) * int error; * caddr_t fromaddr, toaddr; * u_int maxlength, *lencopied; * * Copy a null terminated string from one point to another in the kernel * address space. Returns zero on success, ENOENT if maxlength exceeded. If * lencopied is non-zero, *lencopied gets the length of the copy (including * the null terminating byte). */ ENTRY(copystr) mov r2,-(sp) / need an extra register mov 4.(sp),r0 / r0 = fromaddr mov 6.(sp),r1 / r1 = toaddr mov 8.(sp),r2 / r2 = maxlength (remaining space) beq 2f / (exit early with ENOENT if 0) 1: movb (r0)+,(r1)+ / move a byte beq 3f / (done when we cross the null) sob r2,1b / and loop as long as there's room 2: mov $ENOENT,r0 / ran out of room - indicate failure br 4f / and exit ... 3: clr r0 / success! 4: tst 10.(sp) / does the caller want the copy length? beq 5f sub 6.(sp),r1 / yes, figure out how much we copied: mov r1,*10.(sp) / *lencopied = r1 {toaddr'} - toaddr 5: mov (sp)+,r2 / restore registers rts pc / and return /* * Zero the core associated with a buffer. Since this routine calls mapin * without saving the current map, it cannot be called from interrupt routines. */ ENTRY(clrbuf) mov 2(sp),-(sp) / pass bp to mapin jsr pc,_mapin / r0 = buffer pointer tst (sp)+ tst _fpp / do we have floating point hardware? beq 2f / nope, use regular clr instructions stfps -(sp) / save old floating point status setd / use double precision mov $MAXBSIZE\/32.,r1 / clear 32 bytes per loop 1: clrf (r0)+ clrf (r0)+ clrf (r0)+ clrf (r0)+ sob r1,1b ldfps (sp)+ / restore floating point status br 4f 2: mov $MAXBSIZE\/8.,r1 / clear 8 bytes per loop 3: clr (r0)+ clr (r0)+ clr (r0)+ clr (r0)+ sob r1,1b 4: #ifdef DIAGNOSTIC jmp _mapout / map out buffer #else mov _seg5+SE_DESC,KDSD5 / normalseg5(); mov _seg5+SE_ADDR,KDSA5 rts pc #endif #ifdef DIAGNOSTIC SPACE(GLOBAL, _hasmap, 2) / (struct bp *): SEG5 mapped #endif /* * caddr_t * mapin(bp) * struct buf *bp; * * Map in an out-of-address space buffer. If this is done * from interrupt level, the previous map must be saved before * mapin, and restored after mapout; e.g. * segm save; * saveseg5(save); * mapin(bp); * ... * mapout(bp); * restorseg5(save); * * caddr_t * mapin(bp) * register struct buf *bp; * { * register u_int paddr; * register u_int offset; * * #ifdef DIAGNOSTIC * if (hasmap) { * printf("mapping %o over %o\n", bp, hasmap); * panic("mapin"); * } * hasmap = bp; * #endif * offset = (u_int)bp->b_un.b_addr & 077; * paddr = bftopaddr(bp); * mapseg5((u_short)paddr, * (u_short)(((u_int)DEV_BSIZE << 2) | (u_int)RW)); * return(SEG5 + offset); * } */ ENTRY(mapin) mov 2(sp),r0 / r0 = bp #ifdef DIAGNOSTIC tst _hasmap / is buffer already mapped in?? beq 9f mov _hasmap,-(sp) / oops ... print out a message and die mov r0,-(sp) / with a panic mov $1f,-(sp) STRING(LOCAL, 1, ) jsr pc,_printf cmp (sp)+,(sp)+ mov $1f,(sp) STRING(LOCAL, 1, ) jsr pc,_panic /*NOTREACHED*/ 9: mov r0,_hasmap / save mapin buffer address #endif mov B_ADDR(r0),r1 / r1 = bp->b_addr movb B_XMEM(r0),r0 / r0 = bp->b_xmem mov r1,-(sp) / for later... ashc $-6,r0 / r0:r1 = bftopaddr(bp) mov r1,KDSA5 / mapseg5((u_short)r0:r1, mov $DEV_BSIZE\<2|RW,KDSD5 / (DEV_BSIZE << 2) | RW) mov (sp)+,r0 bic $!077,r0 / return(SEG5 + (bp->b_un.b_addr&077)) add $0120000,r0 rts pc #ifdef DIAGNOSTIC /* * Map out buffer pointed to by bp and restore previous mapping. * Mapout is handled by a macro in seg.h if DIAGNOSTIC isn't defined. * * #ifdef DIAGNOSTIC * void * mapout(bp) * struct buf *bp; * { * if (bp != hasmap) { * printf("unmapping %o, not %o\n", bp, hasmap); * panic("mapout"); * } * hasmap = NULL; * * normalseg5(); * } * #endif */ ENTRY(mapout) cmp 2(sp),_hasmap / mapping out same buffer that was beq 9f / mapped in? mov _hasmap,-(sp) / not good ... print out a message mov 4(sp),-(sp) / and die mov $1f,-(sp) STRING(LOCAL, 1, ) jsr pc,_printf cmp (sp)+,(sp)+ mov $1f,(sp) STRING(LOCAL, 1, ) jsr pc,_panic /*NOTREACHED*/ 9: clr _hasmap / indicate mapping clear mov _seg5+SE_DESC,KDSD5 / normalseg5(); mov _seg5+SE_ADDR,KDSA5 rts pc #endif /* * Save current SEG5 and SEG6 mapping in map and setup normal mapping. * * #define KD6 (((USIZE-1)<<8) | RW) / proto descriptor for u. * savemap(map) * register mapinfo map; * { * map[0].se_desc = *KDSD5; * map[0].se_addr = *KDSA5; * map[1].se_desc = *KDSD6; * map[1].se_addr = *KDSA6; * if (kdsa6) { * *KDSD6 = KD6; * *KDSA6 = kdsa6; * } * normalseg5(seg5); * } */ ENTRY(savemap) mov 2(sp),r0 / r0 = map mov KDSD5,(r0)+ / map[0].se_desc = *KDSD5 mov KDSA5,(r0)+ / map[0].se_addr = *KDSA5 mov KDSD6,(r0)+ / map[1].se_desc = *KDSD6 mov KDSA6,(r0) / map[1].se_addr = *KDSA6 tst _kdsa6 / SEG mapped out?? beq 9f mov $USIZE-1\<8|RW,KDSD6 / yep, map it in, *KDSD6 = (USIZE, RW) mov _kdsa6,KDSA6 / *KDSA6 = kdsa6 9: mov _seg5+SE_DESC,KDSD5 / normalseg5(); mov _seg5+SE_ADDR,KDSA5 rts pc /* * Restore SEG5 and SEG6 mapping from map. * * restormap(map) * register mapinfo map; * { * *KDSD5 = map[0].se_desc; * *KDSA5 = map[0].se_addr; * *KDSD6 = map[1].se_desc; * *KDSA6 = map[1].se_addr; * } */ ENTRY(restormap) mov 2(sp),r0 / r0 = map mov (r0)+,KDSD5 / *KDSD5 = map[0].se_desc mov (r0)+,KDSA5 / *KDSA5 = map[0].se_addr mov (r0)+,KDSD6 / *KDSD6 = map[1].se_desc mov (r0),KDSA6 / *KDSA6 = map[1].se_addr rts pc /* * savfp(fps) * struct fps *fps; * * Save current floating point processor state: floating point status register, * and all six floating point registers. */ ENTRY(savfp) tst _fpp / do we really have floating point beq 1f / hardware?? mov 2(sp),r1 / r1 = fps stfps (r1)+ / save floating point status register setd / (always save registers as double) movf fr0,(r1)+ / and save floating point registers movf fr1,(r1)+ movf fr2,(r1)+ movf fr3,(r1)+ movf fr4,fr0 movf fr0,(r1)+ movf fr5,fr0 movf fr0,(r1)+ 1: rts pc /* * restfp(fps) * struct fps *fps; * * Restore floating point processor state. */ ENTRY(restfp) tst _fpp / do we really have floating point beq 1f / hardware?? mov 2(sp),r1 / r0 = r1 = fps mov r1,r0 setd / (we saved the registers as double) add $8.+2.,r1 / skip fpsr and fr0 for now movf (r1)+,fr1 / restore fr1 thru fr3 movf (r1)+,fr2 movf (r1)+,fr3 movf (r1)+,fr0 / grab and restore saved fr4 and fr5 movf fr0,fr4 movf (r1)+,fr0 movf fr0,fr5 movf 2(r0),fr0 / restore fr0 ldfps (r0) / and floating point status register 1: rts pc /* * stst(fperr) * struct fperr *fperr; * * Save floating point error registers. The argument is a pointer to a two * word structure as defined in . */ ENTRY(stst) tst _fpp / do we really have floating point beq 1f / hardware?? stst *2(sp) / simple, no? 1: rts pc /* * scanc(size, str, table, mask) * u_int size; * u_char *str, table[]; * u_char mask; * * Scan through str up to (but not including str[size]) stopping when a * character who's entry in table has mask bits set. Return number of * characters left in str. */ ENTRY(scanc) mov 2(sp),r0 / r0 = size beq 3f / exit early if zero mov 4(sp),r1 / r1 = str mov r2,-(sp) / r2 = table mov 6+2(sp),r2 mov r3,-(sp) / r3 = mask mov 10+4(sp),r3 mov r4,-(sp) / r4 is temporary 1: / do clr r4 / if (table[*str++] & mask) bisb (r1)+,r4 add r2,r4 bitb r3,(r4) bne 2f / break; sob r0,1b / while (--size != 0) 2: mov (sp)+,r4 / restore registers mov (sp)+,r3 mov (sp)+,r2 3: rts pc / and return size /* * locc(mask, size, str) * u_char mask; * u_int size; * u_char *str; * * Scan through str up to (but not including str[size]) stopping when a * character equals mask. Return number of characters left in str. */ ENTRY(locc) mov 4(sp),r0 / r0 = size beq 3f / exit early if zero mov 6(sp),r1 / r1 = str mov r2,-(sp) / r2 = mask mov 2+2(sp),r2 1: / do cmpb (r1)+,r2 / if (*str++ == mask) beq 2f sob r0,1b / while (--size != 0) 2: mov (sp)+,r2 / restore registers 3: rts pc / and return size /* * nextiv() * * Decrement _lastiv by size of a vector (4) and return the new value. * Placed here for centralized access and easy calling from the networking * (via SKcall) and 'autoconfig' (via ucall). */ ENTRY(nextiv) sub $4,_lastiv / adjust last interrupt vector mov _lastiv,r0 / put in right place for return value rts pc / return assigned vector /* * vattr_null() * * Initialize a inode attribute structure. See the comments in h/inode.h * for more details. If the vnode/inode attribute structure (which is a * subset of 4.4's) changes then this routine must change also. The 'sxt' * sequences below are shorter/faster than "mov $VNOVAL,..." since VNOVAL * is -1. */ ENTRY(vattr_null) mov 2(sp),r0 / get address of vattr structure mov $-1,(r0)+ / va_mode = VNOVAL sxt (r0)+ / va_uid = VNOVAL sxt (r0)+ / va_gid = VNOVAL sxt (r0)+ / va_size - hi = VNOVAL sxt (r0)+ / va_size - lo = VNOVAL sxt (r0)+ / va_atime - hi = VNOVAL sxt (r0)+ / va_atime - lo = VNOVAL sxt (r0)+ / va_mtime - hi = VNOVAL sxt (r0)+ / va_mtime - lo = VNOVAL sxt (r0)+ / va_flags = VNOVAL clr (r0)+ / va_vaflags = 0 rts pc *lencopied gets the length of the copy (including * the null terminating byte). */ ENTRY(copystr) mov r2,-(sp) / need an extra register mov 4.(sp),r0 / r0 = fromaddr mov 6.(sp),r1 / r1 = toaddr mov 8.(sp),r2 / r2 = maxlength (remaining space) beq 2f / (exit early with ENOENT if 0) 1: movb (r0)+,(r1)+ / move a byte beq 3f / (done when we cross the null) sob r2,1b / and loop as long as there's room 2: mov $ENOENsys/pdp/libc_udiv.s 444 0 12 2243 4007421230 7544 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifdef LIBC_SCCS <@(#)udiv.s 2.3 (Berkeley) 1/28/87\0> .even #endif LIBC_SCCS /* * udiv(lhs::r0, rhs::r1) * unsigned lhs, rhs; * * urem(lhs::r0, rhs::r1) * unsigned lhs, rhs; * * Return unsigned div/rem and condition codes of result. */ #include "DEFS.h" ASENTRY(udiv) cmp r1,$1 / if rhs > 1 && rhs < (2^16)/2 /*tricky*/ ble 9f / return ((unsigned long)lhs)/rhs mov r1,-(sp) mov r0,r1 clr r0 div (sp)+,r0 rts pc 9: bne 9f / else if rhs == 1 tst r0 / return lhs rts pc 9: cmp r1,r0 / else if lhs < rhs blos 9f / return 0 clr r0 rts pc 9: mov $1,r0 / else return 1 rts pc ASENTRY(urem) cmp r1,$1 / if rhs > 1 && rhs < (2^16)/2 /*tricky*/ ble 9f / return ((unsigned long)lhs)%rhs mov r1,-(sp) mov r0,r1 clr r0 div (sp)+,r0 mov r1,r0 / (div leaves "%" in r1) rts pc 9: bne 9f / else if rhs == 1 clr r0 / return 0 rts pc 9: cmp r0,r1 / else if lhs >= rhs blo 9f / return lhs - rhs sub r1,r0 9: tst r0 / else return lhs rts pc to by bp and restore previous mapping. * Mapout is handled by a macro in seg.h if DIAGNOSTIC isn't defined. * * #ifdef DIAGNOSTIC * void * mapout(bp) * struct buf *bp; * { * if (bp != hasmap) { * printf("unmapping %o, not %o\n", bp, hasmap); * panic("mapout"); * } * hasmap = NULL; * * normalseg5(); * } * #endif */ ENTRY(sys/pdp/libc_bcmp.s 440 0 12 4314 4020412615 7515 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifdef LIBC_SCCS <@(#)bcmp.s 1.2 (Berkeley) 1/8/87\0> .even #endif LIBC_SCCS #include "DEFS.h" /* * bcmp(b1, b2, length) * * Compare length bytes starting at b1 and b2 - return 0 if equal, non zero * otherwise. Bcmp uses a cost analysis heuristic to determine if it's worth * while to try for a word comparison. If length > N, then try for a word * comparison. Bcmp will fail if N < 3. 8 is a good value for N: * * Algorithm Cost (in instructions) * byte loop 3 * length * word loop overhead [worst case] 12 * word loop 1.5 * length * * N * 3 > 12 + N * 1.5 * N > 8 */ #define N 8. ENTRY(bcmp) mov 6(sp),r0 / if ((r0 = length) == 0) beq 3f / return(length:r0) mov r2,-(sp) / reserve a register for our use mov 6(sp),r2 / r2 = b2 mov 4(sp),r1 / r1 = b1 cmp r0,$N / if (length > N) bhi 4f / try words 1: cmpb (r1)+,(r2)+ / do if (*b1++ != *b2++) bne 2f / return(length:r0) {length != 0} sob r0,1b / while (--length) 2: mov (sp)+,r2 / return(length:r0) 3: rts pc /* * The length of the comparison justifies trying a word by word comparison. * If b1 and b2 are of the same parity, we can do a word comparison by * handling any leading and trailing odd bytes separately. */ 4: bit $1,r1 / if (b1&1 != b2&1) beq 5f / do bytes bit $1,r2 beq 1b / (b1 odd, b2 even - do bytes) cmpb (r1)+,(r2)+ / if (leading odd bytes equal) bne 2b / return(non_zero::r0) dec r0 / else onto word loop br 6f 5: bit $1,r2 bne 1b / (b1 even, b2 odd - do bytes) 6: mov r0,-(sp) / save trailing byte indicator asr r0 / length >>= 1 (unsigned) bic $0100000,r0 / (length is now in remaining words to compare) 7: cmp (r1)+,(r2)+ / do if (*(short *)b1++ != *(short *)b2++) bne 9f / return(length:r0) {length != 0} sob r0,7b / while (--length) 8: mov (sp)+,r0 / if (no odd trailing byte) bic $!1,r0 beq 2b / return(0) cmpb (r1)+,(r2)+ / if (trailing odd bytes different) bne 2b / return(non-zero) clr r0 / else return(0) br 2b 9: mov (sp)+,r0 / bad compare in word loop, br 2b / return(non-zero) map[1].se_desc = *KDSD6; * map[1].se_addr = *KDSA6; * if (kdsa6) { * *KDSD6 = KD6; * *KDSA6 = kdsa6; * } * normalseg5(seg5); * } */ ENTRY(savemap) mov 2(sp),r0 / r0 = map mov KDSD5,(r0)+ / map[0].se_desc = *KDSD5 mov KDSA5,(r0)+ / map[0].se_addr = *KDSA5 mov KDSD6,(r0)+ / map[1].sesys/pdp/libc_bcopy.s 440 0 12 7305 4113206506 7716 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifdef LIBC_SCCS <@(#)bcopy.s 1.2 (Berkeley) 8/21/87\0> .even #endif LIBC_SCCS #include "DEFS.h" /* * bcopy(src, dst, length) * caddr_t src, dst; * u_int length; * * Copy length bytes from src to dst - handles overlapping moves. Bcopy uses * a cost analysis heuristic to determine if it's worth while to see if a word * copy should be tried. The test is if length > N, then try for a word * copy. This routine will fail if N < 8. 10 is a good value for N: * * Algorithm Cost (in instructions) * byte loop cost 2 * length * word loop setup [worst case] 14 (instructions) * word loop cost 0.625 * length, for length > 10 * * N * 2 > 14 N * 0.625 * N > 10 */ #undef N #define N 10. ENTRY(bcopy) mov 6(sp),r0 / if ((r0 = length) == 0) beq 3f / return mov r2,-(sp) / reserve a register for our use mov 6(sp),r2 / r2 = dst mov 4(sp),r1 / r1 = src cmp r2,r1 / if (dst == src) beq 2f / return bhi 9f / if (dst > src) / do backwards copy /* * copy memory from src:r1 to dst:r2 for length:r0 bytes, FORWARDS ... */ cmp r0,$N / if (length >= N) bhi 4f / try words 1: movb (r1)+,(r2)+ / do *dst++ = *src++ sob r0,1b / while (--length) 2: mov (sp)+,r2 / and return 3: rts pc /* * The length of the copy justifies trying a word by word copy. If src and * dst are of the same parity, we can do a word copy by handling any leading * and trailing odd bytes separately. */ 4: bit $1,r1 / if (src&1 != dst&1) beq 5f / do bytes bit $1,r2 beq 1b / (src odd, dst even - do bytes) movb (r1)+,(r2)+ / copy leading odd byte dec r0 br 6f 5: bit $1,r2 bne 1b / (src even, dst odd - do bytes) 6: mov r0,-(sp) / save trailing byte indicator asr r0 / length >>= 1 (unsigned) bic $0100000,r0 / (length is now in remaining words to copy) asr r0 / if (length >>= 1, wasodd(length)) bcc 7f / handle leading non multiple of four mov (r1)+,(r2)+ 7: asr r0 / if (length >>= 1, wasodd(length)) bcc 8f / handle leading non multiple of eight mov (r1)+,(r2)+ mov (r1)+,(r2)+ 8: mov (r1)+,(r2)+ / do mov (r1)+,(r2)+ / move eight bytes mov (r1)+,(r2)+ mov (r1)+,(r2)+ sob r0,8b / while (--length) bit $1,(sp)+ / if (odd trailing byte) beq 2b movb (r1)+,(r2)+ / copy it br 2b / and return /* * copy memory from src:r1 to dst:r2 for length:r0 bytes, BACKWARDS ... */ 9: add r0,r1 / src += length add r0,r2 / dst += length cmp r0,$N / if (length >= N) bhi 4f / try words 1: movb -(r1),-(r2) / do *--dst = *--src sob r0,1b / while (--length) 2: mov (sp)+,r2 / and return 3: rts pc /* * The length of the copy justifies trying a word by word copy. If src and * dst are of the same parity, we can do a word copy by handling any leading * and trailing odd bytes separately. */ 4: bit $1,r1 / if (src&1 != dst&1) beq 5f / do bytes bit $1,r2 beq 1b / (src odd, dst even - do bytes) movb -(r1),-(r2) / copy leading odd byte dec r0 br 6f 5: bit $1,r2 bne 1b / (src even, dst odd - do bytes) 6: mov r0,-(sp) / save trailing byte indicator asr r0 / length >>= 1 (unsigned) bic $0100000,r0 / (length is now in remaining words to copy) asr r0 / if (length >>= 1, wasodd(length)) bcc 7f / handle leading non multiple of four mov -(r1),-(r2) 7: asr r0 / if (length >>= 1, wasodd(length)) bcc 8f / handle leading non multiple of eight mov -(r1),-(r2) mov -(r1),-(r2) 8: mov -(r1),-(r2) / do mov -(r1),-(r2) / move eight bytes mov -(r1),-(r2) mov -(r1),-(r2) sob r0,8b / while (--length) bit $1,(sp)+ / if (odd trailing byte) beq 2b movb -(r1),-(r2) / copy it br 2b / and return movf fr0,(r1)+ movf fr5,fr0 movf fr0,(r1)+ 1: rts pc /* * restfp(fps) * struct fps *fps; * * Restore floating point processor state. */ ENTRY(restfp) tst _fpp / do we really have floating point beq 1f / hardware?? mov 2(sp),r1 / r0 = r1 = fps mov r1,r0 setd / (we saved the registers as dousys/pdp/libc_bzero.s 440 0 12 3431 4113207040 7711 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifdef LIBC_SCCS <@(#)bzero.s 1.2 (Berkeley) 8/21/87\0> .even #endif LIBC_SCCS #include "DEFS.h" /* * bzero(b, length) * caddr_t b; * u_int length; * * Zero length bytes starting at b. Bzero uses a cost analysis heuristic to * determine if it's worth while to try zeroing memory by words. If length > * N, then try for a word zero. This routine will fail if N < 8. * 8 is a good value for N: * * Algorithm Cost (in instructions) * byte loop 2 * length * word loop overhead [worst case] 11 * word loop 0.625 * length * * N * 2 > 11 + N * 0.625 * N > 8 */ #undef N #define N 8. ENTRY(bzero) mov 4(sp),r0 / if ((r0 = length) == 0) beq 2f / return mov 2(sp),r1 / r1 = b cmp r0,$N / if (length > N) bhi 3f / do words 1: clrb (r1)+ / do *b++ = 0 sob r0,1b / while (--length) 2: rts pc / and return /* * The length of the zero justifies using a word loop, handling any leading * and trailing odd bytes separately. */ 3: bit $1,r1 / if (odd leading byte) beq 4f / { zero it clrb (r1)+ / length-- dec r0 / } 4: mov r0,-(sp) / save trailing byte indicator asr r0 / length >>= 1 (unsigned) bic $0100000,r0 / (length is now in remaining words to zero) asr r0 / if (length >>= 1, wasodd(length)) bcc 5f / handle leading non multiple of four clr (r1)+ 5: asr r0 / if (length >>= 1, wasodd(length)) bcc 6f / handle leading non multiple of eight clr (r1)+ clr (r1)+ 6: clr (r1)+ / do clr (r1)+ / clear eight bytes clr (r1)+ clr (r1)+ sob r0,6b / while (--length) bit $1,(sp)+ / if (odd trailing byte) beq 7f clrb (r1)+ / zero it 7: rts pc / and return n, dst odd - do bytes) 6: mov r0,-(sp) / save trailing byte indicator asr r0 / length >>= 1 (unsigned) bic $0100000,r0 / (length is now in remaining words to copy) asr r0 / if (length >>= 1, wasodd(length)) bcc 7f / handle sys/pdp/libc_insque.s 440 0 12 1442 4020412616 10100 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifdef LIBC_SCCS <@(#)insque.s 1.2 (Berkeley) 1/20/87\0> .even #endif LIBC_SCCS /* * struct qelem * { * struct qelem *q_forw; * struct qelem *q_back; * char q_data[]; * } * * insque (elem, pred) * struct qelem *elem, *pred * * Insert elem into queue with predecessor pred. */ #include "DEFS.h" ENTRY(insque) mov 2(sp),r0 / r0 = elem mov 4(sp),r1 / r1 = pred mov r1, 2(r0) / elem->q_back = pred mov (r1),(r0) / elem->q_forw = pred->q_forw mov r0,(r1) / pred->q_forw = elem mov (r0),r1 / r1 = elem->q_forw /* was pred->q_forw */ mov r0,2(r1) / elem->q_forw->q_back = elem rts pc NTRY(bzero) mov 4(sp),r0 / if ((r0 = length) == 0) beq 2f / return mov 2(sp),r1 / r1 = b cmp r0,$N / if (length > N) bhi 3f / do words 1: clrb (r1)+ / do *b++ = 0 sob r0,1b / while (--length) 2: rts pc / andsys/pdp/libc_remque.s 440 0 12 1261 4020412616 10071 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifdef LIBC_SCCS <@(#)remque.s 1.2 (Berkeley) 1/20/87\0> .even #endif LIBC_SCCS /* * struct qelem * { * struct qelem *q_forw; * struct qelem *q_back; * char q_data[]; * } * * remque (elem) * struct qelem *elem * * Remove elem from queue. */ #include "DEFS.h" ENTRY(remque) mov 2(sp),r0 / r0 = elem mov (r0),r1 / r1 = elem->q_forw mov 2(r0),r0 / r0 = elem->q_back mov r1,(r0) / elem->q_back->q_forw = elem->forw mov r0,2(r1) / elem->q_forw->q_back = elem->back rts pc em mov (r0),r1 / r1 = elem->q_forw /* was pred->q_forw */ mov r0,2(r1) / elem->q_forw->q_back = elem rts pc NTRY(bzero) mov 4(sp),r0 / if ((r0 = length) == 0) beq 2f / return mov 2(sp),r1 / r1 = b cmp r0,$N / if (length > N) bhi 3f / do words 1: clrb (r1)+ / do *b++ = 0 sob r0,1b / while (--length) 2: rts pc / andsys/pdp/ram.c 440 0 12 6420 4113140262 6341 /* * ISR 'ramdisk' driver. * This driver implements a 'ram disk' in main memory. * * For the block device, the driver works by remapping buffer header * addresses and simply returning. This way the buffer copy is done only * once. It is faster than any mass storage device in access time and * transfer time (both are immediate) and consumes less cpu time in the * driver than most. * * Gregory Travis, Institute for Social Research, September 1984 * Mucked about, KB, March 1987. * Remucked and stomped, Casey Leedom, August 1987. */ #include "ram.h" #if NRAM > 0 #include "param.h" #include "../machine/seg.h" #include "buf.h" #include "user.h" #include "conf.h" #include "map.h" #include "systm.h" #include "dk.h" #ifdef UCB_METER static int ram_dkn = -1; /* number for iostat */ #endif u_int ram_size = NRAM; /* (patchable) ram disk size */ memaddr ram_base; /* base of ram disk area */ /* * Allocate core for ramdisk(s) */ size_t raminit() { if (ram_size) { if (ram_base = malloc(coremap, ram_size*btoc(NBPG))) { #ifdef UCB_METER dk_alloc(&ram_dkn, 1, "ram", 0L); #endif return(ram_size*btoc(NBPG)); } printf("ram: nospace\n"); } return(0); } ramopen(dev) dev_t dev; { if (minor(dev) || !ram_base) return (ENXIO); return (0); } ramstrategy(bp) register struct buf *bp; { register memaddr ramaddr; if (!ram_base) { printf("ram: not allocated\n"); bp->b_error = ENXIO; bp->b_flags |= B_ERROR; goto done; } if(bp->b_blkno < 0 || ((bp->b_blkno + ((bp->b_bcount+(NBPG-1)) >> PGSHIFT)) > ram_size)) { bp->b_error = EINVAL; bp->b_flags |= B_ERROR; goto done; } #ifdef UCB_METER if (ram_dkn >= 0) { dk_xfer[ram_dkn]++; dk_wds[ram_dkn] += bp->b_bcount>>6; } #endif ramaddr = ram_base + bp->b_blkno * btoc(NBPG); if (bp->b_flags & B_PHYS) ramstart(ramaddr, bp); else if (bp->b_flags & B_READ) { #ifdef DIAGNOSTIC if(bp->b_flags & B_RAMREMAP) panic("ram: remap!"); #endif bp->b_flags |= B_RAMREMAP; /* block read (sic) */ bp->b_un.b_addr = (caddr_t)(ramaddr << 6); bp->b_xmem = (ramaddr >> 10) & 077; } else if ((bp->b_flags & B_RAMREMAP) == 0) ramstart(ramaddr, bp); /* virgin write */ done: iodone(bp); } /* * Start transfer between ram disk (ramaddr) and buffer. Actually completes * synchronously of course, but what the heck. */ ramstart(ramaddr, bp) memaddr ramaddr; register struct buf *bp; { register u_int n, c; memaddr bufaddr; caddr_t seg6addr; int error; if (!(n = bp->b_bcount)) return; #ifdef UCB_METER if (ram_dkn >= 0) dk_busy |= 1 << ram_dkn; #endif bufaddr = bftopaddr(bp); /* click address of buffer */ seg6addr = SEG6 + ((u_int)bp->b_un.b_addr & 077); c = MIN(n, (SEG6+8192)-seg6addr); for (;;) { if (bp->b_flags & B_READ) { mapseg5(ramaddr, ((btoc(8192)-1)<<8)|RO); if (error = fmove(bufaddr, ((btoc(8192)-1)<<8)|RW, SEG5, seg6addr, c)) break; } else { mapseg5(ramaddr, ((btoc(8192)-1)<<8)|RW); if (error = fmove(bufaddr, ((btoc(8192)-1)<<8)|RO, seg6addr, SEG5, c)) break; } if (!(n -= c)) break; ramaddr += btoc(8192); bufaddr += btoc(8192); seg6addr = SEG6; c = MIN(n, 8192); } normalseg5(); #ifdef UCB_METER if (ram_dkn >= 0) dk_busy &= ~(1 << ram_dkn); #endif if (error) { bp->b_error = error; bp->b_flags |= B_ERROR; } } #endif NRAM = 1, wasodd(length)) bcc 7f / handle leading non multiple of four mov -(r1),-(r2) 7: asr r0 / if (length >>= 1, wasodd(length)) bcc 8f / handle leading non multiple of eight mov -(r1),-(r2) mov -(r1),-(r2) 8: mov -(r1),-(r2) / do sys/pdp/libc_strlen.s 440 0 12 1023 4020412616 10076 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifdef LIBC_SCCS <@(#)strlen.s 1.1 (Berkeley) 1/20/87\0> .even #endif LIBC_SCCS /* * Return the length of cp (not counting '\0'). * * strlen(cp) * char *cp; */ #include "DEFS.h" ENTRY(strlen) mov 2(sp),r0 / r0 = cp 1: tstb (r0)+ / find end os string bne 1b sub 2(sp),r0 / length = location('\0')+1 - cp - 1 dec r0 rts pc , August 1987. */ #include "ram.h" #if NRAM > 0 #include "pam.h" #include "../machine/seg.h" #include "buf.h" #include "user.h" #include "conf.h" #include "map.h" #include "systm.h" #include "dk.h" #ifdef UCB_METER static int ram_dkn = -1; /* number for iostat */ #endif u_int ram_size = NRAM; /* (patchable) ram disk size */ memaddr ram_base; /* base of ram disk area */ /* * Allocate core for ramdisk(s) */ size_t raminit() { if (ram_size) { if (ram_base = malloc(coremap, sys/pdp/libc_ldiv.s 444 0 12 13475 5317201737 7601 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifdef LIBC_SCCS <@(#)ldiv.s 2.4 (GTE) 12/26/92\0> .even #endif LIBC_SCCS /* * ldiv(lhs, rhs) * long lhs, rhs; * * 32-bit "/" routine. Calls to ldiv are generated automatically by the C * compiler. */ #include "DEFS.h" #if !defined(KERNEL) /* * Ldiv for floating point hardware. Check for divide by zero. Don't want * floating divide trap in integer math. */ ASENTRY(ldiv) tst 6(sp) / divide by zero check bne 1f tst 8.(sp) bne 1f mov 2(sp),r0 mov 4(sp),r1 / return lhs rts pc 1: setl movif 2(sp),fr0 / fr0 = lhs movif 6(sp),fr1 / fr1 = rhs divf fr1,fr0 / fr0 /= rhs movfi fr0,-(sp) mov (sp)+,r0 / return result mov (sp)+,r1 seti rts pc #else /* * Ldiv for fixed point hardware. */ #define negl(high, low) neg high; \ neg low; \ sbc high / high -= (low != 0) ASENTRY(ldiv) mov r2,-(sp) / faster than csv/cret ... mov r3,-(sp) mov r4,-(sp) mov 14.(sp),r3 / r3 = loint(rhs) sxt r4 / r4 = sign(rhs) bpl 1f / if (int)loint(rhs) < 0 neg r3 / r3 = asb(loint(rhs)) 1: cmp r4,12.(sp) / hiint(rhs) all sign bits? bne hardldiv / no, rhs >= 2^15 mov 10.(sp),r2 / r2 = loint(lhs) mov 8.(sp),r1 / r1 = hiint(lhs) bge 2f / if lhs < 0 negl(r1, r2) / r1:r2 = abs(lhs) com r4 / invert sign of result 2: /* * At this point we know what the sign of the result is going to be * (r4), abs(rhs) < 2^15, we have the absolute value of rhs in * r3 as a single word integer and the absolute value of lhs in * r1 (hiint) and r2 (loint). References to hiint(rhs), loint(lhs) * and hiint(lhs) in the following comments actually refer to the * absolute value of rhs and lhs. * * We perform a long division the same way you learned in school: * hiint(quo) = hiint(lhs) / loint(rhs) * tmp = (hiint(lhs) % loint(rhs))<<16 | loint(lhs) * loint(quo) = tmp / loint(rhs) */ mov r4,-(sp) / save sign of result clr r0 / r0 = hiint(lhs) / loint(rhs) div r3,r0 / r1 = hiint(lhs) % loint(rhs) mov r0,r4 / save high quotient mov r1,-(sp) / stash hiint(tmp) mov r1,r0 / tmp=(hiint(lhs)%loint(rhs))<<16 | loint(lhs) mov r2,r1 / (r0:r1 = tmp) div r3,r0 / r0 = tmp / loint(rhs) bvc 3f / done if tmp/loint(rhs) < 2^15 /* * Our second division overflowed leaving undefined values in * registers. This can only happen when: * tmp/loint(rhs) >= 2^15 * tmp >= 2^15 * loint(rhs) * tmp >= 2^16 * (loint(rhs)/2) * * If we subtract 2^16 * loint(rhs) from both sides however, we get: * tmp - (2^16 * loint(rhs)) >= -(2^16 * (loint(rhs)/2)) * * and then divide both sides by loint(rhs): * tmp/loint(rhs) - 2^16 >= -(2^15) * * which is a division that won't generate an overflow. Finally: * tmp = quo*loint(rhs) + rem * tmp - (2^16 * loint(rhs)) = (quo - 2^16) * loint(rhs) + rem * * which is fine since all we're going for is a 16 bit quotient so the * subtraction of 2^16 won't have any effect. However, since we're * now dividing a negative number and since the div instruction * always generates a remainder the same sign as the dividend, if we * get a non-zero remainder, we'll actually get: * (quo+1 - 2^16) * loint(rhs) + rem-loint(rhs) * * which means we'll have to adjust the quotient returned by * subtracting one ... */ mov (sp),r0 / reload r0:r1 with tmp (regs may be mov r2,r1 / clobbered by failed div) sub r3,r0 / r0:r1 -= 2^16 * loint(rhs) div r3,r0 tst r1 / if (negative) remainder, subtract one from sxt r1 / quotient add r1,r0 / cannot overflow! 3: tst (sp)+ / pop hiint(tmp) off stack mov r0,r1 / r1 (loint(quo)) = tmp / loint(rhs) mov r4,r0 / r0 (hiint(quo)) = hiint(lhs) / loint(rhs) tst (sp)+ bpl ret negret: / if result should be negative negl(r0, r1) / quo = -quo ret: mov (sp)+,r4 / restore registers mov (sp)+,r3 mov (sp)+,r2 rts pc /* * The divisor (rhs) is known to be >= 2^15 so we perform a bit shift * algorithm as only 16 cycles are needed: * long * hardldiv(lhs, rhs) * long lhs, rhs; * { * int flag; * long hi_sreg, lo_sreg; * unsigned int quo, cnt; * * flag = 0; * if (lhs < 0) { * lhs = -lhs; * flag = !flag; * } * if (rhs < 0) { * rhs = -rhs; * flag = !flag; * } * hi_sreg = hiint(lhs); * lo_sreg = loint(lhs)<<16; * quo = 0; * for (cnt = 16; cnt; cnt--) { * quo <<= 1; * qshiftl(&hi_sreg, &lo_sreg); * if (hi_sreg >= rhs) { * hi_sreg -= rhs; * quo |= 1; * } * } * return((long)(flag ? -quo : quo)); * } * The assembly version of the above algorithm uses r2, r0 and r1 to implement * hi_sreg, lo_sreg and quo by putting lhs into r0:r1 and zeroing r2 thereby * creating a three word register r2:r0:r1 with hi_sreg = r2:r0, lo_sreg = * r0:r1, and quo = r1 (using the unused bits in r1 as they become available * after the shift in the loop) ... */ hardldiv: mov 10.(sp),r1 / r1 = loint(lhs) mov 8.(sp),r0 / r0 = hiint(lhs) sxt -(sp) / flag = sign(lhs) bpl 1f / if lhs < 0 negl(r0, r1) / r0:r1 = abs(lhs) 1: mov 14.(sp),r3 / r3 = hiint(rhs) bge 2f / if rhs < 0 negl(r3, 16.(sp)) / rhs = -rhs (r3:loint(rhs)) com (sp) / flag = !flag 2: clr r2 / clear top of shift register mov $16.,r4 / loop 16 times 3: clc / shift combined shift register and quotient rol r1 / left one place rol r0 rol r2 cmp r3,r2 / How do r2:r0 (hi_sreg) and rhs compare? bgt 4f blt 5f cmp 16.(sp),r0 blos 5f 4: sob r4,3b / r2:r0 (hi_sreg) < rhs: br 6f / just loop 5: sub 16.(sp),r0 / r2:r0 (hi_sreg) >= rhs sbc r2 / subtract rhs from r2:r0 (hi_sreg) sub r3,r2 inc r1 / set bit in quotient sob r4,3b / and loop 6: clr r0 / clear upper word of quotient tst (sp)+ / test negative flag bge ret / and head off to the appropriate return br negret #endif to a two * word structure as defined in . */ ENTRY(stst) tst _fpp / do we really have floating point beq 1f / hardware?? stst *2(sp) / simple, no? 1: rts pc /* * scanc(sys/pdp/libc_lmul.s 444 0 12 2071 4007421230 7545 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifdef LIBC_SCCS <@(#)lmul.s 2.3 (Berkeley) 1/28/87\0> .even #endif LIBC_SCCS /* * lmul(lhs, rhs) * long lhs, rhs; * * 32-bit "*" routine for fixed point hardware. Also recommended for floating * hardware, for compatility & speed. Credit to an unknown author who slipped * it under the door. Calls to aldiv are generated automatically by the C * compiler. */ #include "DEFS.h" ASENTRY(lmul) mov r2,-(sp) / faster than csv and just 1 more word mov r3,-(sp) mov 8.(sp),r2 / r2 = loint(lhs) sxt r1 / r1 = sxt(loint(lhs)) - hiint(lhs) sub 6(sp),r1 mov 12.(sp),r0 / r0 = loint(rhs) sxt r3 / r3 = sxt(loint(rhs)) - hiint(rhs) sub 10.(sp),r3 mul r0,r1 / MAGIC = loint(rhs) * hiint(lhs)' mul r2,r3 / + loint(lhs) * hiint(rhs)' add r1,r3 mul r2,r0 / prod (r0:r1) = loint(lhs)*loint(rhs) sub r3,r0 / hiint(prod) -= MAGIC mov (sp)+,r3 mov (sp)+,r2 rts pc then divide both sides by loint(rhs): * tmp/loint(rhs) - 2^16 >= -(2^15) * * which is a division that won't generate an overflow. Finally: * tmp = quo*loint(rhs) + rem * tmp - (2^16 * loint(rhs)) = (quo - 2^16) * loint(rhs) + rem * * which is fine since all we're going for is a 16 bit quotient so the * subtraction of 2^16 won't have any effect. However, since we're * now dividing a negative number and since the div instruction *sys/pdp/libc_lrem.s 444 0 12 12353 5317201506 7566 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifdef LIBC_SCCS <@(#)lrem.s 2.4 (GTE) 12/26/92\0> .even #endif LIBC_SCCS /* * lrem(lhs, rhs) * long lhs, rhs; * * 32-bit "%" routine. Calls to lrem are generated automatically by the C * compiler. */ #include "DEFS.h" #if !defined(KERNEL) /* * Lrem for floating point hardware. Check for divide by zero. Don't want * floating point divide trap in integer math. */ #define one 040200 ASENTRY(lrem) tst 6(sp) / divide by zero check bne 1f tst 8.(sp) bne 1f mov 2(sp),r0 mov 4(sp),r1 / return lhs rts pc 1: setl movif 2(sp),fr0 / fr0 = lhs movf fr0,fr2 / fr2 = lhs movif 6(sp),fr3 / fr3 = rhs divf fr3,fr0 / fr0 = lhs/rhs modf $one,fr0 / fr0 = integer((lhs/rhs) * 1.0) mulf fr3,fr1 / fr0 = integer(lhs/rhs) * rhs subf fr1,fr2 / fr2 = lhs - (integer(*lhs/rhs) * rhs) movfi fr2,-(sp) / (result) mov (sp)+,r0 mov (sp)+,r1 seti rts pc #else /* * Lrem for fixed point hardware. */ #define negl(high, low) neg high; \ neg low; \ sbc high / high -= (low != 0) ASENTRY(lrem) mov r2,-(sp) / faster than csv/cret ... mov r3,-(sp) mov r4,-(sp) mov 14.(sp),r3 / r3 = loint(rhs) sxt r4 / r4 = sign(rhs) bpl 1f / if (int)loint(rhs) < 0 neg r3 / r3 = asb(loint(rhs)) 1: cmp r4,12.(sp) / hiint(rhs) all sign bits? bne hardlrem / no, rhs >= 2^15 mov 10.(sp),r2 / r2 = loint(lhs) mov 8.(sp),r1 / r1 = hiint(lhs) bge 2f / if lhs < 0 negl(r1, r2) / r1:r2 = abs(lhs) 2: /* * At this point we know what the sign of the result is going to be * (r4), abs(rhs) < 2^15, we have the absolute value of rhs in * r3 as a single word integer and the absolute value of lhs in * r1 (hiint) and r2 (loint). References to hiint(rhs), loint(lhs) * and hiint(lhs) in the following comments actually refer to the * absolute value of rhs and lhs. * * We perform a long remainder via: * tmp = (hiint(lhs) % loint(rhs))<<16 | loint(lhs) * loint(rem) = tmp % loint(rhs) */ clr r0 div r3,r0 / r1 = hiint(lhs) % loint(rhs) mov r1,r4 / stash hiint(tmp) mov r1,r0 / tmp=(hiint(lhs)%loint(rhs))<<16 | loint(lhs) mov r2,r1 / (r0:r1 = tmp) div r3,r0 / r1 = tmp % loint(rhs) bvc 3f / done if tmp/loint(rhs) < 2^15 /* * Our second division overflowed leaving undefined values in * registers. This can only happen when: * tmp/loint(rhs) >= 2^15 * tmp >= 2^15 * loint(rhs) * tmp >= 2^16 * (loint(rhs)/2) * * If we subtract 2^16 * loint(rhs) from both sides however, we get: * tmp - (2^16 * loint(rhs)) >= -(2^16 * (loint(rhs)/2)) * * and then divide both sides by loint(rhs): * tmp/loint(rhs) - 2^16 >= -(2^15) * * which is a division that won't generate an overflow. Finally: * tmp = quo*loint(rhs) + rem * tmp - (2^16 * loint(rhs)) = (quo - 2^16) * loint(rhs) + rem * * Since we're now dividing a negative number and since the div * instruction always generates a remainder the same sign as the * dividend, if we get a non-zero remainder, we'll actually get: * (quo+1 - 2^16) * loint(rhs) + rem-loint(rhs) * * which means we'll have to adjust the remainder returned by * adding loint(rhs) ... */ mov r4,r0 / reload r0:r1 with tmp (regs may be mov r2,r1 / clobbered by failed div) sub r3,r0 / r0:r1 -= 2^16 * loint(rhs) div r3,r0 tst r1 / if no remainder (0), bop out immediately, beq 4f / otherwise add loint(rhs) add r3,r1 3: tst 8.(sp) / if lhs < 0 (result always sign of lhs) bpl 4f / rem = -rem neg r1 4: sxt r0 / sign extend remainder ret: mov (sp)+,r4 / restore registers mov (sp)+,r3 mov (sp)+,r2 rts pc /* * The divisor (rhs) is known to be >= 2^15 so we perform a bit shift * algorithm as only 16 cycles are needed: * long * hardlrem(lhs, rhs) * long lhs, rhs; * { * long hi_sreg, lo_sreg; * unsigned int cnt; * * if (lhs < 0) * lhs = -lhs; * if (rhs < 0) * rhs = -rhs; * hi_sreg = hiint(lhs); * lo_sreg = loint(lhs)<<16; * for (cnt = 16; cnt; cnt--) { * qshiftl(&hi_sreg, &lo_sreg); * if (hi_sreg >= rhs) * hi_sreg -= rhs; * } * return((long)((lhs < 0) ? -hi_sreg : hi_sreg)); * } * The assembly version of the above algorithm uses r0, r1 and r2 to implement * hi_sreg and lo_sreg by putting lhs into r0:r1 and zeroing r2 thereby * creating a three word register r2:r0:r1 with hi_sreg = r0:r1 and lo_sreg = * r1:r2 ... */ hardlrem: mov 10.(sp),r2 / r2 = loint(lhs) mov 8.(sp),r1 / r1 = hiint(lhs) bpl 1f / if lhs < 0 negl(r1, r2) / r1:r2 = abs(lhs) 1: mov 12.(sp),r3 / r3 = hiint(rhs) bge 2f / if rhs < 0 negl(r3, 14.(sp)) / rhs = -rhs (r3:loint(rhs)) 2: clr r0 / clear top of shift register mov $16.,r4 / loop 16 times 3: clc / shift combined shift register and quotient rol r2 / left one place rol r1 rol r0 cmp r3,r0 / How do r0:r1 (hi_sreg) and rhs compare? bgt 4f blt 5f cmp 14.(sp),r1 blos 5f 4: sob r4,3b / r0:r1 (hi_sreg) < rhs: br 6f / just loop 5: sub 14.(sp),r1 / r0:r1 (hi_sreg) >= rhs sbc r0 / subtract rhs from r0:r1 (hi_sreg) sub r3,r0 sob r4,3b / and loop 6: tst 8(sp) / if lhs >= 0 bge ret / return immediately negl(r0, r1) / else negate answer before returning br ret #endif / (r0:r1 = tmp) div r3,r0 / r1 = tmp % loint(rhs) bvc 3f / done if tmp/loint(rhs) < 2^15 /* * Our second division overflowed leaving undefined values in * registers. This can only happen when: * tmp/loint(rhs) >= 2^15 * tmp >= 2^15 * loint(rhs) * tmp >= 2^16 *sys/pdp/libc_htonl.s 440 0 12 1416 4020412745 7724 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifdef LIBC_SCCS <@(#)htonl.s 1.1 (Berkeley) 1/25/87\0> .even #endif LIBC_SCCS /* * netlong = htonl(hostlong); * u_long netlong, * hostlong; * * hostlong = ntohl(netlong); * u_long hostlong, * netlong; * * Translate from host unsigned long representation to network unsigned * long representation and back. On the PDP-11 all this requires is * swapping the bytes within the high and low words of a long, so the * two routines are really one ... */ #include "DEFS.h" .globl _htonl, _ntohl _htonl: _ntohl: PROFCODE mov 2(sp),r0 mov 4(sp),r1 swab r0 swab r1 rts pc cles are needed: * long * hardlrem(lhs, rhs) * long lhs, rhs; * { * long hi_sreg, lo_sreg; * unsigned int cnt; * * if (lhs < 0) * lhs = -lhs; * if (rhs < 0) * rhs = -rhs; * hi_sreg = hiint(lhs); * lo_sreg = loint(lhssys/pdp/libc_htons.s 440 0 12 1343 4020412745 7732 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifdef LIBC_SCCS <@(#)htons.s 1.1 (Berkeley) 1/25/87\0> .even #endif LIBC_SCCS /* * netshort = htons(hostshort); * u_short netshort, * hostshort; * * hostshort = ntohs(netshort); * u_short hostshort, * netshort; * * Translate from host unsigned short representation to network unsigned * short representation and back. On the PDP-11 all this requires is * swapping the bytes of a short, so the two routines are really one ... */ #include "DEFS.h" .globl _htons, _ntohs _htons: _ntohs: PROFCODE mov 2(sp),r0 swab r0 rts pc r0 mov 4(sp),r1 swab r0 swab r1 rts pc cles are needed: * long * hardlrem(lhs, rhs) * long lhs, rhs; * { * long hi_sreg, lo_sreg; * unsigned int cnt; * * if (lhs < 0) * lhs = -lhs; * if (rhs < 0) * rhs = -rhs; * hi_sreg = hiint(lhs); * lo_sreg = loint(lhssys/pdp/net_mac.h 440 0 12 13405 5321525065 7230 /* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * %W% (Berkeley) %G% */ struct socket *asoqremque(); #define ASOQREMQUE(so, n) \ KScall(asoqremque, sizeof(struct socket *) + sizeof(int), so, n) int b_to_q(); #define B_TO_Q(cp, cc, q) \ SKcall(b_to_q, sizeof(char *) + sizeof(int) + sizeof(struct clist *), \ cp, cc, q) int connwhile(); #define CONNWHILE(so) \ KScall(connwhile, sizeof(struct socket *), so) memaddr malloc(); #define MALLOC(map, size) \ (memaddr)SKcall(malloc, sizeof(struct map *) + sizeof(u_int), \ map, size) int fpfetch(); #define FPFETCH(fp, fpp) \ SKcall(fpfetch, sizeof(struct file *) + sizeof(struct file *), \ fp, fpp) void fpflags(); #define FPFLAGS(fp, set, clear) \ SKcall(fpflags, sizeof(struct file *) + sizeof(int) + \ sizeof(int), fp, set, clear) int gsignal(); #define GSIGNAL(pgrp, sig) \ SKcall(gsignal, sizeof(int) + sizeof(int), pgrp, sig) struct mbuf *m_free(); #define M_FREE(m) \ KScall(m_free, sizeof(struct mbuf *), m) int m_freem(); #define M_FREEM(m) \ KScall(m_freem, sizeof(struct mbuf *), m) int netcopyout(); #define NETCOPYOUT(from, to, len) \ KScall(netcopyout, sizeof(struct mbuf *) + sizeof(char *) + \ sizeof(u_int), from, to, len) int netcrash(); #define NETCRASH() \ SKcall(netcrash, 0) int iput(); #define IPUT(ip) \ SKcall(iput, sizeof(struct inode *), ip) struct proc *netpfind(); #define NETPFIND(pid) \ SKcall(netpfind, sizeof(int), pid) int netpsignal(); #define NETPSIGNAL(p, sig) \ SKcall(netpsignal, sizeof(struct proc *) + sizeof(int), p, sig) int netstart(); #define NETSTART() \ KScall(netstart, 0) int putc(); #define PUTC(c, p) \ SKcall(putc, sizeof(int) + sizeof(struct clist *), c, p) int selwakeup(); #define SELWAKEUP(p, coll) \ SKcall(selwakeup, sizeof(struct proc *) + sizeof(long), p, coll) int sleep(); #define SLEEP(chan, pri) \ SKcall(sleep, sizeof(caddr_t) + sizeof(int), SUPERADD(chan), pri) int soacc1(); #define SOACC1(so) \ KScall(soacc1, sizeof(struct socket *), so) int soaccept(); #define SOACCEPT(so, nam) \ KScall(soaccept, sizeof(struct socket *) + sizeof(struct mbuf *), \ so, nam) int sobind(); #define SOBIND(so, nam) \ KScall(sobind, sizeof(struct socket *) + sizeof(struct mbuf *), \ so, nam) int soclose(); #define SOCLOSE(so) \ KScall(soclose, sizeof(struct socket *), so) int soconnect(); #define SOCON1(so, nam) \ KScall(soconnect, sizeof(struct socket *) + \ sizeof(struct mbuf *), so, nam) int soconnect2(); #define SOCON2(so1, so2) \ KScall(soconnect2, sizeof(struct socket *) + \ sizeof(struct socket *), so1, so2) int socreate(); #define SOCREATE(dom, aso, type, proto) \ KScall(socreate, sizeof(int) + sizeof(struct socket **) + \ sizeof(int) + sizeof(int), dom, aso, type, proto) int sogetnam(); #define SOGETNAM(so, m) \ KScall(sogetnam, sizeof(struct socket *) + sizeof(struct mbuf *), \ so, m) int sogetopt(); #define SOGETOPT(so, level, optname, mp) \ KScall(sogetopt, sizeof(struct socket *) + sizeof(int) + \ sizeof(int) + sizeof(struct mbuf **), so, level, optname, mp) int sogetpeer(); #define SOGETPEER(so, m) \ KScall(sogetpeer, sizeof(struct socket *) + sizeof(struct mbuf *), \ so, m) int solisten(); #define SOLISTEN(so, backlog) \ KScall(solisten, sizeof(struct socket *) + sizeof(int), so, backlog) /* note; pass pointer to a socket, not pointer to file structure */ int soo_ioctl(); #define SOO_IOCTL(fp, cmd, data) \ KScall(soo_ioctl, sizeof(struct socket *) + sizeof(int) + \ sizeof(caddr_t), fp->f_socket, cmd, data) /* note; pass pointer to a socket, not pointer to file structure */ int soo_select(); #define SOO_SELECT(fp, which) \ KScall(soo_select, sizeof(struct socket *) + sizeof(int), \ fp->f_socket, which) int soo_stat(); #define SOO_STAT(so, ub) \ KScall(soo_stat, sizeof(struct socket *) + sizeof(struct stat *), \ so, ub) int soreceive(); #define SORECEIVE(so, aname, uiop, flags, rightsp) \ KScall(soreceive, sizeof(struct socket *) + sizeof(struct mbuf **) + \ sizeof(struct uio *) + sizeof(int) + sizeof(struct mbuf **), \ so, aname, uiop, flags, rightsp) int sosend(); #define SOSEND(so, nam, uiop, flags, rights) \ KScall(sosend, sizeof(struct socket *) + sizeof(struct mbuf *) + \ sizeof(struct uio *) + sizeof(int) + sizeof(struct mbuf *), \ so, nam, uiop, flags, rights) int sosetopt(); #define SOSETOPT(so, level, optname, m0) \ KScall(sosetopt, sizeof(struct socket *) + sizeof(int) + \ sizeof(int) + sizeof(struct mbuf *), so, level, optname, m0) int soshutdown(); #define SOSHUTDOWN(so, how) \ KScall(soshutdown, sizeof(struct socket *) + sizeof(int), so, how) int timeout(); #define TIMEOUT(fun, arg, t) \ SKcall(timeout, sizeof(memaddr) + sizeof(caddr_t) + sizeof(int), \ SUPERADD(fun), (caddr_t)arg, t) int ttstart(); #define TTSTART(tp) \ SKcall(ttstart, sizeof(struct tty *), tp) int ttyflush(); #define TTYFLUSH(tp, rw) \ SKcall(ttyflush, sizeof(struct tty *) + sizeof(int), tp, rw) int ttywflush(); #define TTYWFLUSH(tp) \ SKcall(ttywflush, sizeof(struct tty *), tp) int unpbind(); #define UNPBIND(path, len, ipp, unpsock) \ SKcall(unpbind, sizeof(char *) + sizeof(int) + \ sizeof(struct inode **) + sizeof(struct socket *), \ path, len, ipp, unpsock) int unpconn(); #define UNPCONN(path, len, so2, ipp) \ SKcall(unpconn, sizeof(char *) + sizeof(int) + \ sizeof(struct socket **) + sizeof(struct inode **), \ path, len, so2, ipp) int unputc(); #define UNPUTC(p) \ SKcall(unputc, sizeof(struct clist *), p) void unpdet(); #define UNPDET(ip) \ SKcall(unpdet, sizeof(struct inode *), ip) int wakeup(); #define WAKEUP(chan) \ SKcall(wakeup, sizeof(caddr_t), SUPERADD(chan)) ) \ SKcall(putc, sizeof(int) + sizeof(struct clist *), c, p) int selwakeup(); #define SELWAKEUP(p, coll) \ SKcall(selwakeup, sizeof(struct proc *) + sizeof(long), p, coll) int sleep(); #define SLEEP(chan, pri) \ SKcall(sleep, sizeof(caddr_t) + sisys/pdp/mch_KScall.s 440 0 12 10210 4263760613 7630 /* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)mch_KScall.s 1.1 (2.10BSD Berkeley) 4/3/88 */ #include "DEFS.h" #include "../machine/mch_iopage.h" /* * Inter-address-space procedure call subroutines. * KScall -- kernel to supervisor */ /* * KScall(func, nbytes, a1, ..., aN) * * C-call from kernel to supervisor. * Calls func(a1, ..., aN) in supervisor mode. */ ENTRY(KScall) mov r5,-(sp) mov PS,-(sp) / Save current PS mov 010(sp),r0 / r0: # bytes of arguments to copy /* * Allocate enough space on the supervisor stack to hold * the call frame. We must allocate space to hold all the * arguments, plus: * a null R5 entry as a marker * a return address (Sretu) * * We assume here that the supervisor stack pointer is always * in seg6 and further that both supervisor and kernel addresses * in this region are mapped to the same physical memory. * * This means that it is NOT ok for the network code to move the * supervisor SP outside of seg6, or for it to remap SDSA6 to * point to something other than the stack, unless it can guarantee * that KScall will not be called for the duration of the stack * fiddling. */ mov $010340,PS / Current KERN, prev SUPV, spl7 (paranoia) mfpd sp / Supervisor stack pointer mov (sp),r1 / Pointer to base of call frame #ifdef CHECKSTACK /* * The following is just to make sure that the supervisor stack * pointer looks reasonable and a check that *SDSA6 == *KDSA6 */ cmp r1,$_u blos 8f cmp r1,$USIZE\<6.+_u bhis 8f cmp SDSA6,KDSA6 beq 9f 8: spl 7 / lock out interrupts halt / drop dead so people can see where we are br . / go no further 9: #endif /* CHECKSTACK */ sub r0,(sp) sub $4.,(sp) / New SP. mtpd sp / Set up alternate stack ptr mov (sp),PS / Restore current PS mov r5,-(r1) / Old frame ptr mov r1,r5 / New frame ptr for other mode /* * Copy arguments. * Note that the stack offsets here are one word deeper than * after we saved the PS. */ mov r2,-(sp) / Save mov r0,r2 / r2: number of bytes of arguments to copy beq 2f / None to copy? if so, skip loop asr r2 / r2: number of words of arguments to copy add sp,r0 add $12.,r0 / r0: ptr to argN+1 1: mov -(r0),-(r1) sob r2,1b 2: mov (sp)+,r2 / Restore /* * Build the remainder of the frame on the * supervisor stack. */ mov $Sretu,-(r1) / Return address in supervisor space /* * Push the iothndlr pair, and the * pair for calling the supervisor function * on the kernel stack. */ mov PS,r0 / To get current priority bic $170000,r0 / Clear out current/previous modes bis $050000,r0 / Current SUPV, previous SUPV mov $ret,-(sp) / Stack kernel PC to go with saved kernel PS mov r0,-(sp) / Stack the new PS mov 10.(sp),-(sp) / Stack the address of function being called /* * At this point, the stacks look like the following: * * KERNEL SUPERVISOR * ------ ---------- *KSP-> <-SSP * * ... * * <0> * * * <# bytes of args> * * ... * * * "" is the address in supervisor address * space of the function being called. */ rtt / Call the function /* * Return to caller of KScall. * We arrive here with the same PS as that with which we were * called, via the rtt in iothndlr. */ ret: mov (sp)+,r5 rts pc /* * Kretu is the exit point in kernel code that cleans up * the kernel stack for return to supervisor mode from a * net-to-kernel procedure call. */ ASENTRY(Kretu) mov r5,sp / Throw away arguments from stack tst (sp)+ / Discard old frame pointer /* * At this point, the stacks look like the following: * * SUPERVISOR KERNEL * ---------- ------ *SSP-> * <_Kretu> * * <# bytes of args> ... * * ... <0> * <-KSP * */ rtt / Back to previous address space n . */ ENTRY(stst) tst _fpp / do we really have floating point beq 1f / hardware?? stst *2(sp) / simple, no? 1: rts pc /* * scanc(size, str, table, mask) * u_int size; * u_char *str, table[]; * u_char mask; * * Scan through str up to (but not including str[size]) stopping when a * character who's entry in table has mask bits set. Return nsys/pdp/net_SKcall.s 440 0 12 13324 4240430250 7642 /* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)net_SKcall.s 1.1 (2.10BSD Berkeley) 4/3/88 */ #include "DEFS.h" #include "../machine/mch_iopage.h" /* * Inter-address-space procedure call subroutines. * SKcall -- supervisor to kernel */ /* * SKcall(func, nbytes, a1, ..., aN) * * C-call from supervisor to kernel. * Calls func(a1, ..., aN) in kernel mode. */ ENTRY(SKcall) mov r5,-(sp) mov PS,-(sp) / Save current PS mov 010(sp),r0 / r0: # bytes of arguments to copy /* * Allocate enough space on the kernel stack to hold * the call frame. We must allocate space to hold all the * arguments, plus: * a PS, PC pair to take us to the function being called * in kernel space. * a return address (Kretu) * a null R5 entry as a marker * a PS, PC pair to take us back to supervisor mode. * * We assume that if the kernel stack pointer is pointing to * an address before the start of seg6, the kernel stack has * been remapped and we must use mtpd instructions instead * of simple mov's. * * WARNING: * ======= * * The reason we use mtpd is to guarantee that we write into * the kernel stack. However, when the kernel stack is remapped * to point outside of seg 6, there may not be enough room for * storing the arguments in the new stack. There is currently no * check made here to prevent overflowing this remapped stack. */ mov $040340,PS / Current SUPV, prev KERN, spl7 (paranoia) mfpd sp / Kernel stack pointer mov (sp),r1 / Pointer to base of new call frame sub r0,(sp) sub $12.,(sp) / New SP. mtpd sp / Set up alternate stack ptr cmp r1,$_u / Is kernel SP pointing in seg6? bhi skmov / Yes: OK to use normal mov instructions jmp skmtpd / No: must use mtpd instead skmov: mov (sp),PS / Restore original PS mov (sp)+,-(r1) / Transfer saved PS to alternate stack mov $ret,-(r1) / Will return to ret below mov r5,-(r1) / Old frame ptr mov r1,r5 / New frame ptr for other mode /* * Copy arguments. * Note that the stack offsets here are the same as they * were right after we saved the PS. */ mov r2,-(sp) / Save mov r0,r2 / r2: number of bytes of arguments to copy beq 2f / None to copy? if so, skip loop asr r2 / r2: number of words of arguments to copy add sp,r0 add $10.,r0 / r0: ptr to argN+1 1: mov -(r0),-(r1) sob r2,1b 2: mov (sp)+,r2 / Restore /* * Build the rest of the kernel stack frame. * This consists of a normal return address (Kretu) to which * the kernel function will return, and a pair used * by Kretu to get back here to supervisor mode. */ mov $Kretu,-(r1) / Address of RTT-er in kernel mode mov $30000,-(r1) / New PS mode: (current KERN, prev USER) bisb PS,(r1) / New PS priority mov 04(sp),-(r1) / Stack address of function to be called skcall: /* * At this point, the stacks look like the following: * * SUPERVISOR KERNEL * ---------- ------ *SSP-> <-KSP * * * <# bytes of args> * ... * ... * <0> * * * * "" is the address in kernel address * space of the function being called. */ iot /* * Return to caller of SKcall. * We arrive here with the PS being the same as it was on * calling SKcall, via a "rtt" from Kretu in kernel mode. */ ret: mov (sp)+,r5 rts pc /* * The kernel stack has been repointed. * Use mtpd to set up the kernel stack for the call. * * We expect that r1 contains the address in kernel space * of the base of the call frame we are about to build. * The word on the top of the stack is the original PS. */ skmtpd: mov (sp),PS / Restore original PS (mainly for priority) bic $30000,PS / Previous mode is kernel mtpd -(r1) / Transfer saved PS to alternate stack mov $ret,-(sp) / Will return to ret below mtpd -(r1) mov r5,-(sp) / Old frame ptr mtpd -(r1) mov r1,r5 / New frame ptr for other mode /* * Copy arguments. * Note that the stack offsets here are the same as they * were right after we saved the PS. */ mov r2,-(sp) / Save mov r0,r2 / r2: number of bytes of arguments to copy beq 2f / None to copy? if so, skip loop asr r2 / r2: number of words of arguments to copy add sp,r0 add $10.,r0 / r0: ptr to argN+1 1: mov -(r0),-(sp) mtpd -(r1) sob r2,1b 2: mov (sp)+,r2 / Restore /* * Build the rest of the kernel stack frame. * This consists of a normal return address (Kretu) to which * the kernel function will return, and a pair used * by Kretu to get back here to supervisor mode. */ mov $Kretu,-(sp) / Address of RTT-er in kernel mode mtpd -(r1) mov $010000,-(sp) / New PS mode: (current KERN, prev SUPV) bisb PS,(sp) / New PS priority mtpd -(r1) mov 04(sp),-(sp) / Stack address of function to be called mtpd -(r1) jmp skcall / Back to complete the call /* * Sretu is the exit point in supervisor code that cleans up * the supervisor stack for return to kernel mode from a * kernel-to-net procedure call. * * We can't use rtt here, so instead we use the a "iot" * in just the same way as we would use to "call" something * in the kernel. */ ASENTRY(Sretu) mov r5,sp / Base of frame area tst (sp)+ / Throw away old frame pointer /* * At this point, the stacks look like the following: * * KERNEL SUPERVISOR * ------ ---------- * <_Sretu> * *KSP-> ... * * <0> * <-SSP * <# bytes of args> * * ... * */ iot g0> * ... * * * "" is the address in supervisor address * space of the function being called. */ rtt / Call the function /* * Return to caller of KScall. * We arrive here with the same PS as that with which we were * called, via the rtt in iothndlr. sys/pdp/net_trap.s 440 0 12 5426 4555230303 7431 /* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)net_trap.s 1.1 (2.10BSD Berkeley) 4/3/88 */ #include "DEFS.h" #include "../machine/mch_iopage.h" /* * All interrupts to the network kernel are vectored through this routine. * No attempt is made to force rescheduling of the cpu. * * Since the network kernel does not use overlays, we don't have to * worry about them here. If a network interrupt service routine makes * a call to the kernel, then Kretu over on the kernel side will take * care of saving and restoring the overlay number. */ ASENTRY(call) mov PS, -(sp) / save new PS mov r1,-(sp) / save r1 mfpd sp / save old sp mov 4(sp), -(sp) / copy of new PS bic $!37,(sp) / extract dev or unit jsr pc,(r0)+ / and execute trap handler cmp (sp)+,(sp)+ / discard dev and sp /* * An 'rtt' here might not work since supervisor can't rtt to the * kernel, instead, we use the "iot" mechanism to schedule a rtt * from kernel mode to the PS, PC pair we push on the kernel stack. * * Transfer our saved pair to the kernel stack. The spl7 * below is pure paranoia, BUT while we're at it let's bump the * interrupt count - it's a mere two instructions of overhead (the * increment would have been done anyhow)! */ mov PS,-(sp) mov $40340,PS / current mode SUPV, prev KERN, BR7 #ifdef UCB_METER mfpd *$_cnt+V_INTR / fetch interrupt count inc (sp) / bump it mtpd *$_cnt+V_INTR / put it back #endif mfpd sp / old kernel stack pointer mov (sp),r1 sub $4,(sp) / grow the kernel stack mtpd sp /* * Can't assume kernel stack in seg6, this is slower but safe. */ mov 12(sp),-(sp) / push PS for iothndlr mtpd -(r1) mov 10(sp),-(sp) / push PC for iothndlr mtpd -(r1) mov (sp)+,PS mov (sp)+,r1 / restore r1, tst (sp)+ / discard new PS, mov (sp)+,r0 / restore r0, cmp (sp)+,(sp)+ / discard PS and PC iot / have the kernel do our rtt for us /* * Scan net interrupt status register (netisr) for service requests. */ ENTRY(netintr) mov r2,-(sp) / use r2 for scan of netisr 1: SPL7 mov _netisr,r2 / get copy of netisr clr _netisr / and clear it, atomically SPLNET #ifdef INET bit $1\>= 8 swab r0 1: bic $!377,r0 / return((u_char)tmp) br fscleanup / restore fault trap and PS, and return ENTRY(subyte) jsr pc,fssetup / r1 = addr, previous mode = user bic $1,r1 / r1 = addr&~1 mfpd (r1) / tmp = user data word at (addr&~1) cmp r1,10(sp) / if (addr&1) beq 1f movb 12(sp),1(sp) / *((char *)tmp + 1) = byte br 2f 1: / else movb 12(sp),(sp) / *((char *)tmp) = byte 2: mtpd (r1) / user data word (addr&~1) = tmp clr r0 / return success br fscleanup / restore fault trap and PS, and return /* * Fetch and set user word routines: * fuword(addr): fetch user data space word * suword(addr, word): set user data space word * caddr_t addr; * u_short word; * * The fetch routines return the requested word or -1 on fault. The set * routines return 0 on success, -1 on failure. Addr must be even. The data * space routines are really the corresponding instruction space routines if * NONSEPARATE is defined. */ ENTRY(fuword) jsr pc,fssetup / r1 = addr, previous mode = user mfpd (r1) / r0 = user data word at addr mov (sp)+,r0 br fscleanup / restore fault trap and PS, and return ENTRY(suword) jsr pc,fssetup / r1 = addr, previous mode = user mov 10(sp),-(sp) / user data word at addr = word mtpd (r1) clr r0 / resturn success br fscleanup / restore fault trap and PS, and return /* * Common set up code for the [fs]u(byte|word) routines. Sets up fault * trap, sets previous mode to user, and loads addr into r1. Leaves old * values of PS and nofault on stack. */ fssetup: mov (sp)+,r0 / snag return address mov PS,-(sp) / save current PS, bic $30000,PS / set previous mode kernel mfpd *$nofault / grab current value of nofault mov $fsfault,-(sp) / and set new fault trap mtpd *$nofault bis $30000,PS / leave previous mode set to user mov 6(sp),r1 / r1 = addr jmp (r0) / return to f/s routine /* * Common fault trap for fetch/set user byte/word routines. Returns -1 to * indicate fault. Stack contains saved fault trap followed by return * address. */ fsfault: mov $-1,r0 / return failure (-1) /*FALLTHROUGH*/ /* * Common clean up code for the [fs]u(byte|word) routines. */ fscleanup: bic $30000,PS / set previous more to kernel mtpd *$nofault / restore fault trap, mov (sp)+,PS / PS, rts pc / and return /* * copyin(fromaddr, toaddr, length) * caddr_t fromaddr, toaddr; * u_int length; * * Copy length/2 words from user space fromaddr to kernel space address * toaddr. Fromaddr and toaddr must be even. Returns zero on success, * EFAULT on failure. */ ENTRY(copyin) jsr pc,copysetup / r1 = fromaddr, r2 = toaddr, 1: / r0 = length/2 mfpd (r1)+ / do mov (sp)+,(r2)+ / *toaddr++ = *fromaddr++ sob r0,1b / while (--length) br copycleanup /* * copyout(fromaddr, toaddr, length) * caddr_t fromaddr, toaddr; * u_int length; * * Copy length/2 words from kernel space fromaddr to user space address * toaddr. Fromaddr and toaddr must be even. Returns zero on success, * EFAULT on failure. */ ENTRY(copyout) jsr pc,copysetup / r1 = fromaddr, r2 = toaddr, 1: / r0 = length/2 mov (r1)+,-(sp) / do mtpd (r2)+ / *toaddr++ = *fromaddr++ sob r0,1b / while (--length) br copycleanup /* * Common set up code for the copy(in|out) routines. Performs zero length * check, sets up fault trap, sets previous mode to user, and loads * fromaddr, toaddr and length into the registers r1, r2 and r0 * respectively. Leaves old values of r2, PS, and nofault on stack. */ copysetup: mov (sp)+,r0 / snag return address mov r2,-(sp) / reserve r2 for our use, mov PS,-(sp) / save current PS, bic $30000,PS / set previous mode kernel mfpd *$nofault / grab current value of nofault mov r0,-(sp) / push return address back mov $copyfault,-(sp) / and set new fault trap mtpd *$nofault bis $30000,PS / leave previous mode set to user mov 16(sp),r0 / r0 = (unsigned)length/2 beq 1f / (exit early if length equals zero) asr r0 bic $100000,r0 mov 12(sp),r1 / r1 = fromaddr mov 14(sp),r2 / r2 = toaddr rts pc 1: tst (sp)+ / short circuit the copy for zero br copycleanup / length returning "success" ... copyfault: mov $EFAULT,r0 / we faulted out, return EFAULT /*FALLTHROUGH*/ /* * Common clean up code for the copy(in|out) routines. When copy routines * finish successfully r0 has already been decremented to zero which is * exactly what we want to return for success ... Tricky, hhmmm? */ copycleanup: bic $30000,PS / set previous mode to kernel mtpd *$nofault / restore fault trap, mov (sp)+,PS / PS, mov (sp)+,r2 / and reserved registers rts pc /* * Kernel/Network copying routines. * * NOTE: * The cp(to|from)kern functions operate atomically, at high ipl. * This is done mostly out of paranoia. If the cp(to|from)kern * routines start taking up too much time at high IPL, then this * parnoia should probably be reconsidered. * * * WARNING: * All functions assume that the segments in supervisor space * containing the source or target variables are never remapped. */ #ifdef notdef /* not currently used */ /* * void * cptokern(nfrom, kto, len) * caddr_t nfrom; source address in network space * caddr_t kto; destination address in kernel space * int len; number of bytes to copy * * Copy words from the network to the kernel. Len must be even and both * nfrom and kto must begin on an even word boundary. */ ENTRY(cptokern) mov r2,-(sp) mov PS,-(sp) mov $40340,PS / set previous mode to kernel mov 6(sp),r0 / nfrom mov 10(sp),r1 / kto mov 12(sp),r2 / len asr r2 / len/2 1: mov (r0)+,-(sp) mtpd (r1)+ sob r2,1b mov (sp)+,PS mov (sp)+,r2 rts pc #endif /* notdef */ /* * void * cpfromkern(kfrom, nto, len) * caddr_t kfrom; source address in kernel space * caddr_t nto; destination address in network space * int len; number of bytes to copy * * Copy words from the kernel to the network. Len must be even and both * kfrom and nto must begin on an even word boundary. */ ENTRY(cpfromkern) mov r2,-(sp) mov PS,-(sp) mov $40340,PS / set previous mode to kernel mov 6(sp),r0 / kfrom mov 10(sp),r1 / nto mov 12(sp),r2 / len asr r2 / len/2 1: mfpd (r0)+ mov (sp)+,(r1)+ sob r2,1b mov (sp)+,PS mov (sp)+,r2 rts pc /* * void * mtkd(addr, word) * caddr addr; destination address in kernel space * int word; word to store * * Move To Kernel Data, simplified interface for the network to store * single words in the kernel data space. */ ENTRY(mtkd) mov 2(sp),r0 / get the destination address mov PS,-(sp) / save psw bic $30000,PS / previous kernel mov 6(sp),-(sp) / grab word mtpd (r0) / and store it in kernel space mov (sp)+,PS / restore psw rts pc / return /* * int * mfkd(addr) * caddr_t addr; source address in kernel space * * Move From Kernel Data, simplified interface for the network to get * single words from the kernel data space. */ ENTRY(mfkd) mov 2(sp),r0 / get the address of the data mov PS,-(sp) / save psw bic $30000,PS / previous kernel mfpd (r0) / get the word mov (sp)+,r0 / return value mov (sp)+,PS / restore psw rts pc / return mov $MAXBSIZE\/32.,r1 / clear 32 bytes per loop 1: clrf (r0)+ clrf (r0)+ clrf (r0)+ clrf (r0)+ sob r1,1b ldfps (sp)+ / restore floating point status br 4f 2: mov $MAXsys/pdp/net_mbuf.s 644 0 12 6371 5351502234 7422 /* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)net_mbuf.s 2.0 (2.11BSD GTE) 3/13/93 */ #include "DEFS.h" #include "../machine/mch_iopage.h" /* * mbcopyin(click, off, ptr, len) * u_short click; / address of external DMA buffer * u_short off; / offset into click of start of buffer * caddr_t ptr; / address of internal buffer * short len; / bytes to copy from click/off to ptr * * mbcopyout(ptr, click, off, len) * caddr_t ptr; / address of internal buffer * u_short click; / address of external DMA buffer * u_short off; / offset into click of start of buffer * short len; / bytes to copy from ptr to click/off * * Used for copying data from/to the UNIBUS DMA pages to/from the * in-address-space mbufs. Cannot copy data to or from the stack. Len * cannot exceed 8Kbytes. * * We remap SDSA6 to do the copy and run at SPL7. */ ENTRY(mbcopyin) jsr r5,csv mov 012(r5),r0 / grab byte count ble 3f / nothing to do if len <= 0 ... mov 06(r5),r1 / grab offset and computer pointer add $140000,r1 / to mapped in source data mov 010(r5),r2 / grab ptr (destination address) mov PS,-(sp) / save PS since we lock out interrupts SPL7 mov SDSA6,r3 / save mapping for stack / u. area mov 04(r5),SDSA6 / map in source data br 0f ENTRY(mbcopyout) jsr r5,csv mov 012(r5),r0 / grab byte count ble 3f / nothing to do if len <= 0 ... mov 04(r5),r1 / grab ptr (source address) mov 010(r5),r2 / grab offset and compute pointer add $140000,r2 / to mapped destination address mov PS,-(sp) / save PS since we lock out interrupts SPL7 mov SDSA6,r3 / save mapping for stack / u. area mov 06(r5),SDSA6 / map in destination address data /* * Common loop and return for mbcopyin and mbcopyout. Copy from (r1) to * (r2) for r0 bytes. r3 contains old seg6 address descriptor. */ 0: cmp r0,$8192. / too big? bge 2f / yes, ignore it cmp r0,$10. / if (length >= 10) bhi 4f / try words 1: movb (r1)+,(r2)+ / do *dst++ = *src++ sob r0,1b / while (--length) 2: mov r3,SDSA6 / map back in stack / u. area mov (sp)+,PS / restore original priority 3: jmp cret /* * The length of the copy justifies trying a word by word copy. If src and * dst are of the same parity, we can do a word copy by handling any leading * and trailing odd bytes separately. NOTE: r4 is used to hold the odd byte * indicator because the stack is invalid (mapped out). */ 4: bit $1,r1 / if (src&1 != dst&1) beq 5f / do bytes bit $1,r2 beq 1b / (src odd, dst even - do bytes) movb (r1)+,(r2)+ / copy leading odd byte dec r0 br 6f 5: bit $1,r2 bne 1b / (src even, dst odd - do bytes) 6: mov r0,r4 / save trailing byte indicator asr r0 / length >>= 1 (unsigned) asr r0 / if (length >>= 1, wasodd(length)) bcc 7f / handle leading non multiple of four mov (r1)+,(r2)+ 7: asr r0 / if (length >>= 1, wasodd(length)) bcc 8f / handle leading non multiple of eight mov (r1)+,(r2)+ mov (r1)+,(r2)+ 8: mov (r1)+,(r2)+ / do mov (r1)+,(r2)+ / move eight bytes mov (r1)+,(r2)+ mov (r1)+,(r2)+ sob r0,8b / while (--length) asr r4 / if (odd trailing byte) bcc 2b movb (r1)+,(r2)+ / copy it br 2b / and return ains saved fault trap followed by return * address. */ fsfault: mov $-1,r0 / return failure (-1) /*FALLTHROUGH*/ /* * Common clean up code for the [fs]u(byte|word) routines. */ fscleanup: bic $30000,PS / set previous more to kernel mtpd *$nofault / rsys/pdp/net_scb.s 440 0 12 1774 5266716016 7246 /* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)net_scb.s 1.2 (2.11BSD GTE) 10/13/92 */ #include "acc.h" #include "css.h" #include "de.h" #include "ec.h" #include "il.h" #include "qe.h" #include "qt.h" #include "sri.h" #include "vv.h" /* * Entry points for interrupt vectors from kernel low-core */ #define HANDLER(handler) .globl handler, _/**/handler; \ handler: jsr r0,call; jmp _/**/handler #if NACC > 0 HANDLER(accrint) HANDLER(accxint) #endif #if NCSS > 0 HANDLER(cssrint) HANDLER(cssxint) #endif #if NDE > 0 HANDLER(deintr) #endif #if NEC > 0 HANDLER(ecrint) HANDLER(eccollide) HANDLER(ecxint) #endif #if NIL > 0 HANDLER(ilrint) HANDLER(ilcint) #endif #if NQE > 0 HANDLER(qeintr) #endif #if NQT > 0 HANDLER(qtintr) #endif #if NSRI > 0 HANDLER(srixint) HANDLER(srirint) #endif #if NVV > 0 HANDLER(vvrint) HANDLER(vvxint) #endif (r5)sys/pdp/mch_csv.s 444 0 12 23176 5316460073 7272 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if defined(LIBC_SCCS) && !defined(KERNEL) && !defined(SUPERVISOR) <@(#)csv.s 2.4 (2.11BSD GTE) 12/24/92\0> .even #endif /* * C register save and restore routines. When a C routine is called its stack * frame (after csv or ovhandlr have set things up) looks like this: * * _________________________________ * | return address to caller | * |-------------------------------| * r5-> | old r5 ("frame pointer") | * |-------------------------------| * | previous __ovno | * |-------------------------------| * | old r4 | * |-------------------------------| * | old r3 | * |-------------------------------| * | old r2 | * |-------------------------------| * sp-> | empty parameter slot | * |_______________________________| * * The "empty parameter slot" is a simple optimization the compiler uses to * avoid overhead in its generated parameter cleanup code after a function * has been called. Rather than (for example) generating: * * mov foo,-(sp) / push parameter * jsr pc,bar / call function * tst (sp)+ / throw away parameter * * The compiler always keeps one empty slot on the stack and generates: * * mov foo,(sp) / pass parameter * jsr pc,bar / call function * * The savings are not quite so dramatic when more than one parameter is * passed, but still worth the effort. If the function has any local stack * variables, space for them will have be be allocated by the function thereby * "moving" the empty parameter slot down. */ /* * KERNEP and SUPERVISOR (network code) notes: * * Stack checking can be enabled for the KERNEL (and SUPERVISOR network) * by defining CHECKSTACK in the config file. Looks to see if the * kernel and supervisor (network) stacks have collided, etc. * * Networking kernel doesn't currently need overlays (and probably never * will). If it's ever necessary to overlay the networking code, it would * be done in exactly the same manner as that used by the kernel. This would * actually end up simplifying things ... * * It's debatable whether or not the standard library, KERNEL, and * SUPERVISOR copies of csv/cret should be integrated this way, because * the ifdef's sometimes make it hard to keep track of things. But the * code and comments here are complicated enough that it's worth the effort * to keep all three versions in general sync. */ #include "DEFS.h" #ifndef SUPERVISOR /* networking kernel doesn't use overlays */ #ifdef KERNEL #include "../machine/mch_iopage.h" #include "../machine/koverlay.h" #endif .data #ifdef KERNEL .globl ova, ovd / overlay descriptor tables #endif .globl __ovno / currently mapped overlay __ovno: 0 .text .globl _etext / used by cret to determine returns to overlay / area (any return address higher than _etext) / the loader defines only if referenced /* * The loader (/bin/ld) generates `thunks' for functions loaded in overlays. * A thunk resides in the base segment and takes the name _foo which is the * function's interface to the outside world (this allows pointers to functions * to work even if functions are located in overlays). The function itself is * renamed to ~foo. * * ovhndlr(1-9,a-f) are called from the thunks via a jsr r5 after r1 is set to * the location of the first instruction in the subroutine after the call to * csv (~foo+4). * * _foo: mov $~foo+4,r1 * jsr r5,ovhndlr`n' * * The ovhndlr`n' in turn move the requested overlay number into r0 and * branch to ovhndlr which sets the overlay, simulates a csv and transfers to * (r1) (~foo+4). Thus, the function's call to csv is bypassed. */ #define ovh(x, n) .globl ovhndlr/**/x; \ ovhndlr/**/x: \ mov $n,r0; \ br ovhndlr; ovh(1,001); ovh(2,002); ovh(3,003); ovh(4,004) ovh(5,005); ovh(6,006); ovh(7,007); ovh(8,010) ovh(9,011); ovh(a,012); ovh(b,013); ovh(c,014) ovh(d,015); ovh(e,016); ovh(f,017) #ifndef KERNEL emt = 0104000 / overlays switched by emulator trap / overlay number is placed in r0 #endif KERNEL /* * ovhndlr(ov::r0, ~foo+4::r1, _foo+8::r5) * * Ovhandler builds the new stack frame as fast as possible to avoid problems * with getting interrupted halfway through. if we get interrupted between the * "jsr r5,ovhndlr`x'" and the "mov sp,r5" below and a longjmp is attempted, * rollback will fail utterly. If we get interrupted before we finish saving * registers reserved for register variables and an attempt is made to longjmp * to the caller of our service routine rollback will incorrectly pull `saved' * register values from the incomplete stack frame leading to * non-deterministic behavior. * * There's very little that can be done about this asside from changing the * entire stack frame sequence which involves changes to the compiler, loader, * this file and any other routine (like rollback) which `knows' how the C * stack frame is put together ... */ ovhndlr: #if defined(KERNEL) && defined(CHECKSTACK) cmp sp, $_u / before the u. area? blo 9f / yes, assume it's remapped, so OK cmp sp, $KERN_SBASE / falling off the bottom? bhi 9f / no, also OK spl 7 / lock out interrupts halt / can't 'panic', that uses the stack! br . / in case continue is done 9: #endif mov sp,r5 / simulate a csv ... mov __ovno,-(sp) cmp r0,(sp) / is the requested overlay already mapped? beq 1f #ifdef KERNEL mov PS,-(sp) / save PS SPL7 mov r0,__ovno / set new overlay number asl r0 / compute descriptor index and map mov ova(r0), OVLY_PAR / the new overlay in mov ovd(r0), OVLY_PDR mov (sp)+,PS / restore PS, unmask interrupts #else emt / no, ask the kernel for it ... mov r0,__ovno / and indicate the new overlay /* * SPECIAL NOTE: the pair of instructions "emt" and "mov r0,__ovno" * form a race condition. A signal can interrupt the sequence * causing all sorts of nastiness if the signal routine calls a * routine in the old overlay or is itself in the old overlay ... * There is no solution that doesn't involve changing the way * an overlay switch from the kernal. Most [potential] solutions * significantly increase the overhead of an overlay switch. * A tenable solution has yet to be found ... */ #endif 1: mov r4,-(sp) mov r3,-(sp) mov r2,-(sp) jsr pc,(r1) / jsr leaves empty parameter slot on stack #endif /* !SUPERVISOR */ /* * Csv for routines called directly (in base or intra-overlay calls). * no overlays have been changed, so we just save the previous overlay * number on the stack. Note that r0 isn't set to the current overlay * because we weren't called through a thunk. */ .globl csv csv: #if (defined(KERNEL) || defined(SUPERVISOR)) && defined(CHECKSTACK) #ifdef SUPERVISOR cmp sp,$NET_STOP / out of the top of the stack? bhi 8f / yes, die cmp sp,$NET_SBASE / falling off the bottom? bhi 9f / no, so OK 8: spl 7 / lock out interrupts halt / can't 'panic', that uses the stack! br . / in case continue is done 9: #else cmp sp,$_u / before the u. area? blo 9f / assume it was remapped, so OK cmp sp,$KERN_SBASE / falling off the bottom? bhi 9f / no, so OK spl 7 / lock out interrupts halt / can't 'panic', that uses the stack! br . / in case continue is done 9: #endif #endif mov r5,r1 / save transfer address, mov sp,r5 #ifdef SUPERVISOR clr -(sp) #else mov __ovno,-(sp) #endif mov r4,-(sp) mov r3,-(sp) mov r2,-(sp) jsr pc,(r1) /* * Cret is used by everyone so it has to check if we're returning to an * overlay different from the one that may be currently mapped. */ .globl cret cret: #if (defined(KERNEL) || defined(SUPERVISOR)) && defined(CHECKSTACK) #ifdef SUPERVISOR cmp sp,$NET_STOP / out of the top of the stack? bhi 8f / yes, die cmp sp,$NET_SBASE / falling off the bottom? bhi 9f / no, so OK 8: spl 7 / lock out interrupts halt / can't 'panic', that uses the stack! br . / in case continue is done 9: #else cmp sp,$_u / before the u. area? blo 9f / assume it was remapped, so OK cmp sp,$KERN_SBASE / falling off the bottom? bhi 9f / no, so OK spl 7 / lock out interrupts halt / can't 'panic', that uses the stack! br . / in case continue is done 9: #endif #endif mov r5,r2 #ifdef SUPERVISOR tst -(r2) / skip over overlay slot #else mov -(r2),r4 / r4 = old __ovno - if non-zero we've started bne 2f / using overlays so we'll have to make / sure the old overlay is mapped if we're / returning to the overlay area 1: #endif mov -(r2),r4 / restore registers, reset stack, pop frame mov -(r2),r3 / pointer and return mov -(r2),r2 mov r5,sp / (more interrupt problems here *sigh* ...) mov (sp)+,r5 rts pc #ifndef SUPERVISOR 2: /* * Not returning to base segment, so check that the right * overlay is mapped in, and if not change the mapping. */ cmp r4,__ovno / current overlay same as old overlay? beq 1b / lucked out! #if defined(KERNEL) && defined(INET) cmp 2(r5),$Kretu / must always restore overlays if returning beq 3f / from SKcall #endif cmp 2(r5),$_etext / returning to base segment? blos 1b / sometimes things *do* work out ... #ifdef KERNEL 3: mov PS,-(sp) / (sigh) returning to a different overlay SPL7 mov r4,__ovno / set new overlay number asl r4 / and map the new overlay in mov ova(r4), OVLY_PAR mov ovd(r4), OVLY_PDR mov (sp)+,PS / restore PS, unmask interrupts br 1b #else mov r0,r3 / (sigh) returning to a different overlay - mov r4,r0 / have to save r0 because we can't trash emt / a function result and ask UNIX to switch mov r4,__ovno / the old overlay in mov r3,r0 / note that as with ovhndlr the pair "emt" br 1b / "mov r4,__ovno" can be interrupted #endif #endif /* !SUPERVISOR */ complete stack frame leading to * non-deterministic behavior. * * There's very little that can be done about this asside from changing the * entire stack frame sequence which involves changes to the compiler, loader, * this file and any other routine (like rollback) which `knows' how the C * stack frame is put together ... */ ovhndlr: #if defined(KERNEL) && defined(CHECKSTACK)sys/pdp/net_csv.s 444 0 12 23176 5316460073 12577 1sys/pdp/mch_csv.ssys/pdp/mch_fpsim.s 644 3 12 52303 5317256553 7623 /* * LICENSED FROM DIGITAL EQUIPMENT CORPORATION * COPYRIGHT (c) * DIGITAL EQUIPMENT CORPORATION * MAYNARD, MASSACHUSETTS * 1985, 1986, 1987 * ALL RIGHTS RESERVED * * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT * NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL * EQUIPMENT CORPORATION. DIGITAL MAKES NO REPRESENTATIONS ABOUT * THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. IT IS * SUPPLIED "AS IS" WITHOUT EXPRESSED OR IMPLIED WARRANTY. * * IF THE REGENTS OF THE UNIVERSITY OF CALIFORNIA OR ITS LICENSEES * MODIFY THE SOFTWARE IN A MANNER CREATING DERIVATIVE COPYRIGHT * RIGHTS, APPROPRIATE COPYRIGHT LEGENDS MAY BE PLACED ON THE * DERIVATIVE WORK IN ADDITION TO THAT SET FORTH ABOVE. * * @(#)mch_fpsim.s 1.2 (2.11BSD GTE) 12/26/92 */ #include "DEFS.h" /* * Kernel floating point simulator */ #if defined(FPSIM) || defined(GENERIC) m.ext = 200 / long mode bit m.lngi = 100 / long integer mode _u = 140000 / XXX uar0 = _u + U_AR0 / u.u_ar0 fec = _u + U_FPERR + F_FEC / u.u_fperr.f_fec fea = _u + U_FPERR + F_FEA / u.u_fperr.f_fea fpsr = _u + U_FPSR / u.u_fps.u.fpsr ac0 = _u + U_FPREGS + [0.*8.] / u.u_fsp.u_fpregs[0] ac1 = _u + U_FPREGS + [1.*8.] / u.u_fsp.u_fpregs[1] ac2 = _u + U_FPREGS + [2.*8.] / u.u_fsp.u_fpregs[2] ac3 = _u + U_FPREGS + [3.*8.] / u.u_fsp.u_fpregs[3] /* * fptrap() * * Return Status: * 0 successful simulation * otherwise the signal number. */ ENTRY(fptrap) jsr r5,csv sub $74,sp instr = -12 / int instr; trapins = -14 / int trapins; pctmp = -24 / double pctmp; modctl2 = -26 / int (*modctl2)(); modctl = -30 / int (*modctl)(); local = -32 / int local; bexp = -34 / int bexp; breg = -44 / double breg; bsign = -46 / int bsign; aexp = -50 / int aexp; areg = -60 / double areg; asign = -62 / int asign; sps = -64 / int sps; spc = -66 / int spc; ssp = -70 / int ssp; / sr5 = -72 / int sr5; / sr4 = -74 / int sr5; / sr3 = -76 / int sr5; / sr2 = -100 / int sr5; sr1 = -102 / int sr1; sr0 = -104 / int sr0; / make copies of all the registers - see trap.c (regloc) for the offsets mov $sr0,r1 add r5,r1 mov $_regloc,r3 / see trap.c mov $9.,r4 / r0,1,2,3,4,5,sp,pc,psw 1: movb (r3)+,r2 / fetch next register offset from u_ar0 asl r2 / make word index add uar0,r2 / add in u_ar0 mov (r2),(r1)+ / save register sob r4,1b / get the offending instruction mov spc(r5),r1 dec r1 dec r1 jsr pc,ffuiword mov r0,instr(r5) again: sub $8,sp / room for double push /hmm.... clr local(r5) mov instr(r5),r4 bic $7777,r4 cmp r4,$170000 beq 1f jmp badins 1: / clear fp error bic $100000,fpsr bic $170000,instr(r5) mov instr(r5),r4 bit $7000,r4 bne class3 bit $700,r4 bne class2 cmp r4,$12 blos 1f jmp badins 1: asl r4 jmp *agndat(r4) class2: cmp instr(r5),$400 bge 1f mov $mod0rx,modctl(r5) mov $mod242,modctl2(r5) br 2f 1: mov $mod0f,modctl(r5) mov $mod24f,modctl2(r5) 2: jsr pc,fsrc /## jsr r1,fsrc mov r3,instr(r5) asl r4 / r4 = (r4&0700)>>7; asl r4 clrb r4 swab r4 asl r4 jsr pc,*cls2dat(r4) jmp sret class3: cmp instr(r5),$5000 blt 1f mov instr(r5),r2 clrb r2 cmp r2,$6400 blt 2f sub $1400,r2 2: cmp r2,$5000 bne 2f mov $mod0rx,modctl(r5) mov $mod242,modctl2(r5) br 3f 2: cmp r2,$5400 bne 2f mov $mod0ra,modctl(r5) mov $mod24i,modctl2(r5) br 3f 2: mov $mod0f,modctl(r5) mov $mod24d,modctl2(r5) br 3f 1: mov $mod0f,modctl(r5) mov $mod24f,modctl2(r5) 3: jsr pc,fsrc /### jsr r1,fsrc jsr pc,freg mov r2,instr(r5) bis $2,local(r5) / mark as local, since (r2) is always local clrb r4 / r4 = r4 & ~0377 >> 8; swab r4 asl r4 jsr pc,*cls3dat(r4) br sret i.cfcc: mov fpsr,r1 / get the FPP reg bic $!17,r1 / clear everything except the NZVC bits bic $17,sps(r5) / clear the old NZVC bits bis r1,sps(r5) / set the new NZVC bits br ret i.setf: bic $m.ext,fpsr br ret i.setd: bis $m.ext,fpsr br ret i.seti: bic $m.lngi,fpsr br ret i.setl: bis $m.lngi,fpsr br ret sret: mov $fpsr,r2 bic $17,(r2) bit $2,local(r5) bne 1f mov instr(r5),r1 jsr pc,ffuword br 2f 1: mov *instr(r5),r0 2: swab r0 tstb r0 bpl 1f bis $10,(r2) br ret 1: bne ret bis $4,(r2) ret: / restore all the new register values mov $sr0,r1; add r5,r1 mov $_regloc,r3 mov $9.,r4 1: movb (r3)+,r2 asl r2 add uar0,r0 mov (r1)+,(r0) sob r4,1b bit $020,sps(r5) / Check to see if T bit was set. bne 1f mov spc(r5),r1 / Check the next instruction jsr pc,ffuiword / to see if it is another cmp r0,$170000 / floating point instruction. blo 3f mov r0,instr(r5) add $2,spc(r5) / Update our copy of pc, mov uar0,r0 / update add $2,2.(r0) / the real pc, jbr again / and save the trap. 3: clr r0 / Normal Return 2: jmp cret 1: mov $SIGTRAP.,r0 br 2b badins: / Illegal Instruction mov $SIGILL.,r0 br 2b segfault: / Segmentation Violation mov uar0,r0 / Don't update any registers, but sub $2,2.(r0) / back up the pc to point to the instruction. mov $SIGSEGV.,r0 br 2b fpexcept: / Floating Point Exception / restore all the new register values, and then / return an error. mov $sr0,r1; add r5,r1 mov uar0,r0 mov (r1)+,(r0) / r0 mov (r1)+,-4.(r0) / r1 mov (r1)+,-20.(r0) / r2 mov (r1)+,-18.(r0) / r3 mov (r1)+,-16.(r0) / r4 mov (r1)+,-12.(r0) / r5 mov (r1)+,-6.(r0) / sp (r6) mov (r1)+,2.(r0) / pc (r7) mov (r1)+,4.(r0) / psw mov $SIGFPE.,r0 jmp cret freg: mov instr(r5),r2 bic $!300,r2 asr r2 asr r2 asr r2 add $ac0,r2 rts pc fsrc: mov instr(r5),r3 bic $!7,r3 / register asl r3 add $sr0,r3; add r5,r3 mov instr(r5),r0 bic $!70,r0 / mode asr r0 asr r0 jmp *moddat(r0) mod24f: mov $4,r0 bit $m.ext,fpsr beq 1f add $4,r0 1: rts pc mod24d: mov $8,r0 bit $m.ext,fpsr beq 1f sub $4,r0 1: rts pc mod242: mov $2,r0 rts pc mod24i: mov $2,r0 bit $m.lngi,fpsr beq 1f add $2,r0 1: rts pc mod0: jmp *modctl(r5) mod0f: sub $sr0,r3 sub r5,r3 cmp r3,$6*2 bhis badi1 asl r3 asl r3 add $ac0,r3 br mod0rx mod0ra: bit $m.lngi,fpsr bne badi1 mod0r: mov $ssp,-(sp); add r5,(sp) cmp r3,(sp)+ bhis badi1 mod0rx: bis $3,local(r5) / mark it as a local addr, not a user addr rts pc /### rts r1 mod1: / register deferred *rn or (rn) mov $spc,-(sp); add r5,(sp) cmp r3,(sp)+ beq badi1 mov (r3),r3 br check mod2: mov (r3),-(sp) jsr pc,*modctl2(r5) mov $spc,-(sp); add r5,(sp) cmp r3,(sp)+ bne 1f mov (r3),r1 / PC relative - immediate $n jsr pc,ffuiword mov r0,pctmp(r5) mov $pctmp,(sp); add r5,(sp) / need to clean garbage out of rest of pctmp(r5) mov (sp),r0 tst (r0)+ clr (r0)+ clr (r0)+ clr (r0)+ mov $2,r0 bis $3,local(r5) / signify address is not in user space 1: / Auto increment (rn)+ add r0,(r3) mov (sp)+,r3 br check mod3: mov (r3),r1 mov $spc,-(sp); add r5,(sp) cmp r3,(sp)+ bne 1f jsr pc,ffuiword / PC Absolute *$A br 2f 1: jsr pc,ffuword /autoincrement deferred *(rn)+ 2: add $2,(r3) mov r0,r3 br check mod4: / Autodecrement -(rn) mov $spc,-(sp); add r5,(sp) cmp r3,(sp)+ / test pc beq badi1 jsr pc,*modctl2(r5) sub r0,(r3) mov (r3),r3 br check mod5: / Autodecrement Deferred *-(rn) mov $spc,-(sp); add r5,(sp) cmp r3,(sp)+ beq badi1 sub $2,(r3) mov (r3),r1 jsr pc,ffuword mov r0,r3 br check mod6: / Index or PC relative mov spc(r5),r1 jsr pc,ffuiword add $2,spc(r5) add (r3),r0 mov r0,r3 br check mod7: / Index Deferred or PC Relative Deferred jsr pc,mod6 /### jsr r1,mod6 mov r3,r1 jsr pc,ffuword mov r0,r3 br check badi1: jmp badins check: bit $1,r3 bne 1f rts pc /### rts r1 1: jmp segfault setab: bis $4,local(r5) mov $asign,r0; add r5,r0 jsr pc,seta mov r3,r2 bit $1,local(r5) bne 1f bic $4,local(r5) 1: mov $bsign,r0; add r5,r0 seta: clr (r0) bit $4,local(r5) bne 4f mov r0,-(sp) mov r2,r1; jsr pc,ffuword; mov r0,r1 add $2,r2 mov (sp)+,r0 br 5f 4: mov (r2)+,r1 5: mov r1,-(sp) beq 1f blt 2f inc (r0)+ br 3f 2: dec (r0)+ 3: bic $!177,r1 bis $200,r1 br 2f 1: clr (r0)+ 2: mov r1,(r0)+ bit $4,local(r5) bne 4f mov r1,-(sp) mov r3,-(sp) mov r0,r3 mov r2,r1 jsr pc,ffuword; add $2,r1; mov r0,(r3)+ bit $m.ext,fpsr beq 5f jsr pc,ffuword; add $2,r1; mov r0,(r3)+ jsr pc,ffuword; add $2,r1; mov r0,(r3)+ br 6f 5: clr (r3)+ clr (r3)+ 6: mov r1,r2 mov r3,r0 mov (sp)+,r3 mov (sp)+,r1 br 3f 4: mov (r2)+,(r0)+ bit $m.ext,fpsr beq 2f mov (r2)+,(r0)+ mov (r2)+,(r0)+ br 3f 2: clr (r0)+ clr (r0)+ 3: mov (sp)+,r1 asl r1 clrb r1 swab r1 sub $200,r1 mov r1,(r0)+ / exp rts pc norm: mov $areg,r0; add r5,r0 mov (r0)+,r1 mov r1,-(sp) mov (r0)+,r2 bis r2,(sp) mov (r0)+,r3 bis r3,(sp) mov (r0)+,r4 bis r4,(sp)+ bne 1f clr asign(r5) rts pc 1: bit $!377,r1 beq 1f clc ror r1 ror r2 ror r3 ror r4 inc (r0) br 1b 1: bit $200,r1 bne 1f asl r4 rol r3 rol r2 rol r1 dec (r0) br 1b 1: mov r4,-(r0) mov r3,-(r0) mov r2,-(r0) mov r1,-(r0) rts pc .globl _grow, nofault PS = 177776 ffuword: mov $1f,trapins(r5) mov PS,-(sp) SPLHIGH mov nofault,-(sp) mov $ferr1,nofault 1: mfpd (r1) mov (sp)+,r0 br 2f ffuiword: mov PS,-(sp) SPLHIGH mov nofault,-(sp) mov $ferr2,nofault /stack isn't in I space, so just bomb out. mfpi (r1) mov (sp)+,r0 br 2f fsuword: mov $1f,trapins(r5) mov PS,-(sp) SPLHIGH mov nofault,-(sp) mov $ferr1,nofault 1: mov r0,-(sp) mtpd (r1) 2: mov (sp)+,nofault mov (sp)+,PS rts pc ferr1: /first fault could be because we need to grow the stack. mov (sp)+,nofault mov (sp)+,PS mov r0,-(sp) /save r0 and r1 because mov r1,-(sp) /grow() will muck them up mov ssp(r5),-(sp) jsr pc,_grow tst (sp)+ tst r0 bne 1f jmp segfault 1: mov (sp)+,r1 /restore r1 mov (sp)+,r0 /and r0 mov PS,-(sp) SPLHIGH mov nofault,-(sp) mov $ferr2,nofault jmp *trapins(r5) ferr2: /second fault, we have a valid memory fault now, /so make the users program bomb out! mov (sp)+,nofault mov (sp)+,PS jmp segfault / class 2 instructions fiuv = 04000 i.ldfps: bit $1,local(r5) beq 1f mov (r3),fpsr br 2f 1: mov r3,r1 jsr pc,ffuword mov r0,fpsr 2: jmp ret i.stfps: bit $1,local(r5) beq 1f mov fpsr,(r3) br 2f 1: mov fpsr,r0 mov r3,r1 jsr pc,fsuword 2: jmp ret i.stst: bit $1,local(r5) beq 1f / must be either a register or immediate mode, only save fec mov fec,(r3)+ br 2f 1: mov fec,r0 mov r3,r1 jsr pc,fsuword mov fea,r0 add $2,r1 jsr pc,fsuword 2: jmp ret i.clrx: bit $1,local(r5) bne 1f clr r0 mov r3,r1 jsr pc,fsuword add $2,r1 jsr pc,fsuword bit $m.ext,fpsr beq 2f add $2,r1 jsr pc,fsuword add $2,r1 jsr pc,fsuword 2: rts pc 1: clr (r3)+ clr (r3)+ bit $m.ext,fpsr beq 2f clr (r3)+ clr (r3)+ 2: rts pc i.tstx: bit $fiuv,fpsr bne 2f 1: rts pc /this could be real easy, except that the lousy tstx instruction / does the fiuv trap AFTER execution, not before. So, since / normally this instruction doesn't get done until after the rts pc, / we explicitly do it here. 2: bit $2,local(r5) bne 1b mov $fpsr,r2 bic $17,(r2) mov instr(r5),r1 jsr pc,ffuword swab r0 tstb r0 bpl 1f bis $10,(r2) /set negative flag br 2f 1: bne 2f bis $4,(r2) /set zero flag 2: jsr pc,chkuv /finally, check for sign bit and a biased 0 exp jmp ret i.absx: bit $1,local(r5) beq 1f bic $!77777,(r3) rts pc 1: mov r3,r1 jsr pc,ffuword bit $fiuv,fpsr beq 2f jsr pc,chkuv 2: bic $!77777,r0 mov r3,r1 jsr pc,fsuword rts pc chkuv: mov r0,-(sp) bic $77,(sp) /clear the fraction part bit $140000,(sp)+ /check for sign bit and biased exponent of 0 bne 1f jmp undefvar 1: rts pc undefvar: mov $12., fec jmp fpexcept i.negx: bit $1,local(r5) bne 1f mov r3,r1 jsr pc,ffuword bit $fiuv,fpsr beq 2f jsr pc,chkuv 2: tst r0 beq 2f add $100000,r0 mov r3,r1 jsr pc,fsuword 2: rts pc 1: tst (r3) beq 2f add $100000,(r3) 2: rts pc / class 3 i.ldx: bit $1,local(r5) bne 1f /user to kernel mov r3,r1; jsr pc,ffuword bit $fiuv,fpsr beq 2f jsr pc,chkuv 2: mov r0,(r2)+ add $2,r1; jsr pc,ffuword; mov r0,(r2)+ bit $m.ext,fpsr beq 2f add $2,r1; jsr pc,ffuword; mov r0,(r2)+ add $2,r1; jsr pc,ffuword; mov r0,(r2)+ rts pc 1: /kernel to kernel mov (r3)+,(r2)+ mov (r3)+,(r2)+ bit $m.ext,fpsr beq 2f mov (r3)+,(r2)+ mov (r3)+,(r2)+ rts pc 2: clr (r2)+ clr (r2)+ rts pc i.stx: bit $1,local(r5) bne 1f /kernel to user mov (r2)+,r0; mov r3,r1; jsr pc,fsuword; mov (r2)+,r0; add $2,r1; jsr pc,fsuword bit $m.ext,fpsr beq 2f mov (r2)+,r0; add $2,r1; jsr pc,fsuword mov (r2)+,r0; add $2,r1; jsr pc,fsuword br 2f 1: /kernel to kernel mov (r2)+,(r3)+ mov (r2)+,(r3)+ bit $m.ext,fpsr beq 2f mov (r2)+,(r3)+ mov (r2)+,(r3)+ 2: jmp ret / does not set cc's i.cmpx: mov $areg,r4; add r5,r4 mov r4,instr(r5) / bit 2 of local(r5) is already set. bit $1,local(r5) bne 9f mov r3,r1; jsr pc,ffuword bit $fiuv,fpsr beq 1f jsr pc,chkuv 1: tst (r2) bge 1f tst r0 bge 1f cmp (r2),r0 bgt 4f blt 3f 1: cmp (r2)+,r0 bgt 3f blt 4f add $2,r1; jsr pc,ffuword; cmp (r2)+,r0 bne 5f bit $m.ext,fpsr beq 2f add $2,r1; jsr pc,ffuword; cmp (r2)+,r0 bne 5f add $2,r1; jsr pc,ffuword; cmp (r2)+,r0 beq 2f br 5f 9: tst (r2) bge 1f tst (r3) bge 1f cmp (r2),(r3) bgt 4f blt 3f 1: cmp (r2)+,(r3)+ bgt 3f blt 4f cmp (r2)+,(r3)+ bne 5f bit $m.ext,fpsr beq 2f cmp (r2)+,(r3)+ bne 5f cmp (r2)+,(r3)+ beq 2f 5: bhi 3f 4: movb $1,1(r4) rts pc 3: mov $-1,(r4) rts pc 2: clr (r4) rts pc i.ldcyx: /ldcdf or ldcfd bit $1,local(r5) bne 1f mov r3,r1; jsr pc,ffuword bit $fiuv,fpsr beq 2f jsr pc,chkuv 2: mov r0,(r2)+ add $2,r1; jsr pc,ffuword; mov r0,(r2)+ bit $m.ext,fpsr bne 2f add $2,r1; jsr pc,ffuword; mov r0,(r2)+ add $2,r1; jsr pc,ffuword; mov r0,(r2)+ rts pc 1: mov (r3)+,(r2)+ mov (r3)+,(r2)+ bit $m.ext,fpsr bne 2f mov (r3)+,(r2)+ mov (r3)+,(r2)+ rts pc 2: clr (r2)+ clr (r2)+ rts pc i.stcxy: bit $1,local(r5) bne 1f mov (r2)+,r0; mov r3,r1; jsr pc,fsuword mov (r2)+,r0; add $2,r1; jsr pc,fsuword bit $m.ext,fpsr bne 2f clr r0 add $2,r1; jsr pc,fsuword add $2,r1; jsr pc,fsuword br 2f 1: mov (r2)+,(r3)+ mov (r2)+,(r3)+ bit $m.ext,fpsr bne 2f clr (r3)+ clr (r3)+ 2: rts pc i.ldcjx: mov $asign,r2; add r5,r2 mov $1,(r2)+ bit $1,local(r5) bne 1f mov r3,r1; jsr pc,ffuword bit $fiuv,fpsr beq 2f jsr pc,chkuv 2: mov r0,(r2)+ bit $m.lngi,fpsr beq 3f add $2,r1; jsr pc,ffuword; mov r0,(r2)+ br 2f 1: mov (r3)+,(r2)+ bit $m.lngi,fpsr beq 3f mov (r3)+,(r2)+ 2: clr (r2)+ clr (r2)+ mov $32.-8,(r2)+ jmp saret 3: clr (r2)+ clr (r2)+ clr (r2)+ mov $16.-8,(r2) jmp saret i.stcxj: mov r3,instr(r5) bit $1,local(r5) bne 1f /bit 2 of local(r5) is already set bic $2,local(r5) 1: mov $asign,r0; add r5,r0 bis $4,local(r5) /tell seta that r2 is a local addr jsr pc,seta clr r4 mov $areg,r0; add r5,r0 mov (r0)+,r1 mov (r0)+,r2 mov (r0)+,r3 mov aexp(r5),r0 1: cmp r0,$48.-8 bge 1f clc ror r1 ror r2 ror r3 inc r0 br 1b 1: bgt 7f tst r1 beq 1f 7: bis $1,r4 / C-bit 1: bit $m.lngi,fpsr beq 1f tst asign(r5) bge 2f neg r3 adc r2 bcs 2f neg r2 bis $10,r4 / N-bit 2: bit $2,local(r5) bne 9f mov r4,-(sp) / save r4 mov r1,-(sp) / save r1 mov r0,-(sp) / save r0 mov r2,r0; mov instr(r5),r1; jsr pc,fsuword mov r3,r0; add $2,r1; jsr pc,fsuword mov (sp)+,r0 / restore r0 mov (sp)+,r1 / restore r1 br t1 9: mov r4,-(sp) / save r4 mov instr(r5),r4 mov r2,(r4) mov r3,2(r4) t1: mov (sp)+,r4 / restore r4 bis r2,r3 br 8f 1: tst r2 beq 1f bis $1,r4 / C-bit 1: tst asign(r5) bge 2f neg r3 bis $10,r4 / N-bit 2: bit $1,local(r5) bne 9f mov r3,r0 mov instr(r5),r1 jsr pc,fsuword tst r3 br 8f 9: mov r3,*instr(r5) 8: bne 1f bis $4,r4 / Z-bit 1: bic $17,sps(r5) bic $17,fpsr bis r4,sps(r5) bis r4,fpsr jmp ret xoflo: bis $1,fpsr / set fixed overflow (carry) jmp ret i.ldexp: mov $asign,r0; add r5,r0 bis $4,local(r5) /tell seta that r2 is a local addr jsr pc,seta bit $1,local(r5) bne 1f mov r3,r1; jsr pc,ffuword; mov r0,aexp(r5) br 2f 1: mov (r3),aexp(r5) 2: jsr pc,reta jmp sret i.stexp: mov $asign,r0; add r5,r0 bis $4,local(r5) /tell seta that r2 is a local addr jsr pc,seta bit $1,local(r5) bne 1f mov aexp(r5),r0; mov r3,r1; jsr pc,fsuword mov r3,instr(r5) bic $17,sps(r5) tst aexp(r5) br 3f 1: mov aexp(r5),(r3) mov r3,instr(r5) bic $17,sps(r5) tst (r3) 3: bmi 1f bne 2f bis $4,sps(r5) / Z-bit br 2f 1: bis $10,sps(r5) / N-bit 2: / next 4 lines because of previous mov r3,instr(r5) bit $1,local(r5) / bit 2 of local(r5) is currently set. bne 1f bic $2,local(r5) 1: jmp sret i.addx: jsr pc,setab br 1f i.subx: jsr pc,setab neg bsign(r5) 1: tst bsign(r5) beq reta tst asign(r5) beq retb mov aexp(r5),r1 sub bexp(r5),r1 blt 1f beq 2f cmp r1,$56. bge reta mov $breg,r0; add r5,r0 br 4f 1: neg r1 cmp r1,$56. bge retb mov $areg,r0; add r5,r0 4: mov r1,-(sp) mov (r0)+,r1 mov (r0)+,r2 mov (r0)+,r3 mov (r0)+,r4 add (sp),(r0) 1: clc ror r1 ror r2 ror r3 ror r4 dec (sp) bgt 1b mov r4,-(r0) mov r3,-(r0) mov r2,-(r0) mov r1,-(r0) tst (sp)+ 2: mov $aexp,r1; add r5,r1 mov $bexp,r2; add r5,r2 mov $4,r0 cmp asign(r5),bsign(r5) bne 4f clc 1: adc -(r1) bcs 3f add -(r2),(r1) 2: dec r0 bne 1b br 5f 3: add -(r2),(r1) sec br 2b br 5f 4: clc 1: sbc -(r1) bcs 3f sub -(r2),(r1) 2: dec r0 bne 1b br 5f 3: sub -(r2),(r1) sec br 2b saret: mov $areg,r1; add r5,r1 5: tst (r1) bge 3f mov $areg+8,r1; add r5,r1 mov $4,r0 clc 1: adc -(r1) bcs 2f neg (r1) 2: dec r0 bne 1b neg -(r1) 3: jsr pc,norm br reta retb: mov $bsign,r1; add r5,r1 mov $asign,r2; add r5,r2 mov $6,r0 1: mov (r1)+,(r2)+ dec r0 bne 1b reta: mov instr(r5),r2 mov $asign,r0; add r5,r0 tst (r0) beq unflo mov aexp(r5),r1 cmp r1,$177 bgt ovflo cmp r1,$-177 blt unflo add $200,r1 swab r1 clc ror r1 tst (r0)+ bge 1f bis $100000,r1 1: bic $!177,(r0) bis (r0)+,r1 bit $2,local(r5) bne 3f mov r3,-(sp) /save r3 mov r0,r3 /and move r0 to r3 mov r1,r0; mov r2,r1; jsr pc,fsuword mov (r3)+,r0; add $2,r1; jsr pc,fsuword bit $m.ext,fpsr beq 2f mov (r3)+,r0; add $2,r1; jsr pc,fsuword mov (r3)+,r0; add $2,r1; jsr pc,fsuword 2: mov r3,r0 /move r3 back to r0 mov (sp)+,r3 /and restor r3 rts pc 3: mov r1,(r2)+ mov (r0)+,(r2)+ bit $m.ext,fpsr beq 1f mov (r0)+,(r2)+ mov (r0)+,(r2)+ 1: rts pc unflo: bit $2,local(r5) bne 1f clr r0 mov r2,r1; jsr pc,fsuword add $2,r1; jsr pc,fsuword bit $m.ext,fpsr beq 2f add $2,r1; jsr pc,fsuword add $2,r1; jsr pc,fsuword br 2f 1: clr (r2)+ clr (r2)+ bit $m.ext,fpsr beq 2f clr (r2)+ clr (r2)+ 2: rts pc ovflo: bis $2,fpsr / set v-bit (overflow) jmp ret i.mulx: jsr pc,i.mul jbr saret i.modx: jsr pc,i.mul jsr pc,norm mov $asign,r0; add r5,r0 mov $bsign,r1; add r5,r1 mov $6,r2 1: mov (r0)+,(r1)+ dec r2 bne 1b clr r0 / count mov $200,r1 / bit clr r2 / reg offset 1: add r5,r2 cmp r0,aexp(r5) bge 2f / in fraction bic r1,areg(r2) br 3f 2: bic r1,breg(r2) 3: sub r5,r2 inc r0 clc ror r1 bne 1b mov $100000,r1 add $2,r2 cmp r2,$8 blt 1b jsr pc,norm jsr pc,reta cmp instr(r5),$ac1 beq 1f cmp instr(r5),$ac3 beq 1f bit $200,breg(r5) bne 2f clr bsign(r5) 2: add $8,instr(r5) jsr pc,retb sub $8,instr(r5) 1: rts pc i.divx: jsr pc,setab tst bsign(r5) beq zerodiv sub bexp(r5),aexp(r5) jsr pc,xorsign mov instr(r5),-(sp) mov $areg,r0; add r5,r0 mov (r0),r1 clr (r0)+ mov (r0),r2 clr (r0)+ mov (r0),r3 clr (r0)+ mov (r0),r4 clr (r0)+ mov $areg,instr(r5); add r5,instr(r5) mov $400,-(sp) 1: mov $breg,r0; add r5,r0 cmp (r0)+,r1 blt 2f bgt 3f cmp (r0)+,r2 blo 2f bhi 3f cmp (r0)+,r3 blo 2f bhi 3f cmp (r0)+,r4 bhi 3f 2: mov $breg,r0; add r5,r0 sub (r0)+,r1 clr -(sp) sub (r0)+,r2 adc (sp) clr -(sp) sub (r0)+,r3 adc (sp) sub (r0)+,r4 sbc r3 adc (sp) sub (sp)+,r2 adc (sp) sub (sp)+,r1 bis (sp),*instr(r5) 3: asl r4 rol r3 rol r2 rol r1 clc ror (sp) bne 1b mov $100000,(sp) add $2,instr(r5) mov $aexp,-(sp); add r5,(sp) cmp instr(r5),(sp)+ blo 1b tst (sp)+ mov (sp)+,instr(r5) jmp saret zerodiv: mov $4,fec jmp fpexcept i.mul: jsr pc,setab add bexp(r5),aexp(r5) dec aexp(r5) jsr pc,xorsign mov instr(r5),-(sp) mov $breg+4,instr(r5); add r5,instr(r5) bit $m.ext,fpsr beq 1f add $4,instr(r5) 1: clr r0 clr r1 clr r2 clr r3 clr r4 1: asl r0 bne 2f inc r0 sub $2,instr(r5) 2: cmp r0,$400 bne 2f mov $breg,-(sp); add r5,(sp) cmp instr(r5),(sp)+ bhi 2f mov $areg,r0; add r5,r0 mov r1,(r0)+ mov r2,(r0)+ mov r3,(r0)+ mov r4,(r0)+ mov (sp)+,instr(r5) rts pc 2: clc ror r1 ror r2 ror r3 ror r4 bit r0,*instr(r5) beq 1b mov r0,-(sp) mov $areg,r0; add r5,r0 add (r0)+,r1 clr -(sp) add (r0)+,r2 adc (sp) clr -(sp) add (r0)+,r3 adc (sp) add (r0)+,r4 adc r3 adc (sp) add (sp)+,r2 adc (sp) add (sp)+,r1 mov (sp)+,r0 br 1b xorsign: cmp asign(r5),bsign(r5) beq 1f mov $-1,asign(r5) rts pc 1: mov $1,asign(r5) rts pc .data agndat: i.cfcc / 170000 i.setf / 170001 i.seti / 170002 badins badins badins badins badins badins i.setd / 170011 i.setl / 170012 cls2dat: badins / 1700xx i.ldfps / 1701xx i.stfps / 1702xx i.stst / 1703xx i.clrx / 1704xx i.tstx / 1705xx i.absx / 1706xx i.negx / 1707xx cls3dat: badins / 1700xx badins / 1704xx i.mulx / 1710xx i.modx / 1714xx i.addx / 1720xx i.ldx / 1724xx i.subx / 1730xx i.cmpx / 1734xx i.stx / 1740xx i.divx / 1744xx i.stexp / 1750xx i.stcxj / 1754xx i.stcxy / 1760xx i.ldexp / 1764xx i.ldcjx / 1770xx i.ldcyx / 1774xx moddat: mod0 mod1 mod2 mod3 mod4 mod5 mod6 mod7 #endif /* FPSIM || GENERIC */ the fraction part bit $140000,(sp)+ /check for sign bit and biased exponent of 0 bne 1f jmp undefvar 1: rts pc undefvar: mov $12., fec jmp fpexcept i.negx: bit $1,local(r5) bne 1f mov r3,r1 jsr pc,ffuword bit $fiuv,fpsr beq 2f jsr pc,chkuv 2: tst r0 beq 2f add $100000,r0 mov r3,r1 jsr pc,fsuwordsys/pdp/tmscp.h 444 0 12 26223 4637261533 6764 /* @(#)tmscp.h 7.1 (Berkeley) 6/5/86 */ /* * @(#)tmscp.h 1.3 10/21/85 * Definitions for the Tape Mass Storage Control Protocol */ /**************************************************************** * * * Licensed from Digital Equipment Corporation * * Copyright (c) * * Digital Equipment Corporation * * Maynard, Massachusetts * * 1985, 1986 * * All rights reserved. * * * * The Information in this software is subject to change * * without notice and should not be construed as a commitment * * by Digital Equipment Corporation. Digital makes no * * representations about the suitability of this software for * * any purpose. It is supplied "As Is" without expressed or * * implied warranty. * * * * If the Regents of the University of California or its * * licensees modify the software in a manner creating * * diriviative copyright rights, appropriate copyright * * legends may be placed on the drivative work in addition * * to that set forth above. * * * **************************************************************** * * Modification history: /sys/pdp/tmscp.h * * 18-Oct-85 - afd * Added: defines for tape format (density) flag values. * * 18-Jul-85 - afd * Added: #define M_UF_WBKNV 0000100 * for write back (which enables cache). ************************************************************************/ /* * Control message opcodes */ #define M_OP_ABORT 0001 /* Abort command */ #define M_OP_GTCMD 0002 /* Get command status command */ #define M_OP_GTUNT 0003 /* Get unit status command */ #define M_OP_STCON 0004 /* Set controller characteristics command */ #define M_OP_AVAIL 0010 /* Available command */ #define M_OP_ONLIN 0011 /* Online command */ #define M_OP_STUNT 0012 /* Set unit characteristics command */ #define M_OP_DTACP 0013 /* Determine access paths command */ #define M_OP_ACCES 0020 /* Access command */ #define M_OP_CMPCD 0021 /* Compare controller data command */ #define M_OP_ERASE 0022 /* Erase command */ #define M_OP_FLUSH 0023 /* Flush command */ #define M_OP_ERGAP 0026 /* Erase gap command */ #define M_OP_COMP 0040 /* Compare host data command */ #define M_OP_READ 0041 /* Read command */ #define M_OP_WRITE 0042 /* Write command */ #define M_OP_WRITM 0044 /* Write tape mark command */ #define M_OP_REPOS 0045 /* Reposition command */ #define M_OP_AVATN 0100 /* Available attention message */ #define M_OP_DUPUN 0101 /* Duplicate unit number attention message */ #define M_OP_ACPTH 0102 /* Access path attention message */ #define M_OP_END 0200 /* End message flag */ /* * Generic command modifiers */ #define M_MD_COMP 0040000 /* Compare */ #define M_MD_CLSEX 0020000 /* Clear serious exception */ #define M_MD_SECOR 0001000 /* Suppress error correction */ #define M_MD_SEREC 0000400 /* Suppress error recovery */ #define M_MD_STWRP 0000004 /* Set write protect */ #define M_MD_ALLCD 0000002 /* All class drivers */ #define M_MD_NXUNT 0000001 /* Next unit */ /* * TMSCP command modifiers */ #define M_MD_DLEOT 0000200 /* Delete LEOT */ #define M_MD_IMMED 0000100 /* Immediate completion */ #define M_MD_EXCAC 0000040 /* Exclusive access */ #define M_MD_UNLOD 0000020 /* Unload */ #define M_MD_REVRS 0000010 /* reverse */ #define M_MD_OBJCT 0000004 /* object count */ #define M_MD_REWND 0000002 /* rewind */ /* * End message flags */ #define M_EF_ERLOG 0040 /* Error log generated */ #define M_EF_SEREX 0020 /* Serious exception */ #define M_EF_EOT 0010 /* End of tape encountered */ #define M_EF_PLS 0004 /* Position lost */ /* * Controller flags */ #define M_CF_ATTN 0200 /* Enable attention messages */ #define M_CF_MISC 0100 /* Enable miscellaneous error log messages */ #define M_CF_OTHER 0040 /* Enable other host's error log messages */ #define M_CF_THIS 0020 /* Enable this host's error log messages */ /* * Unit flags */ #define M_UF_WRTPH 0020000 /* Write protect (hardware) */ #define M_UF_WRTPS 0010000 /* Write protect (software or volume) */ #define M_UF_WBKNV 0000100 /* Write back (enables cache) */ #define M_UF_VSMSU 0000040 /* Variable speed mode suppression */ #define M_UF_VARSP 0000020 /* Variable speed unit */ #define M_UF_CMPWR 0000002 /* Compare writes */ #define M_UF_CMPRD 0000001 /* Compare reads */ /* * Status codes */ #define M_ST_MASK 037 /* Status code mask */ #define M_ST_SUCC 000 /* Success */ #define M_ST_ICMD 001 /* Invalid command */ #define M_ST_ABRTD 002 /* Command aborted */ #define M_ST_OFFLN 003 /* Unit offline */ #define M_ST_AVLBL 004 /* Unit available */ #define M_ST_WRTPR 006 /* Write protected */ #define M_ST_COMP 007 /* Compare error */ #define M_ST_DATA 010 /* Data error */ #define M_ST_HSTBF 011 /* Host buffer access error */ #define M_ST_CNTLR 012 /* Controller error */ #define M_ST_DRIVE 013 /* Drive error */ #define M_ST_FMTER 014 /* Formatter error */ #define M_ST_BOT 015 /* BOT encountered */ #define M_ST_TAPEM 016 /* Tape mark encountered */ #define M_ST_RDTRN 020 /* Record data truncated */ #define M_ST_PLOST 021 /* Position lost */ #define M_ST_SEX 022 /* Serious exception */ #define M_ST_LED 023 /* LEOT detected */ #define M_ST_DIAG 037 /* Message from an internal diagnostic */ /* * An MSCP packet */ struct mscp { struct mscp_header mscp_header;/* device specific header */ u_short mscp_cmdref; /* command reference number */ u_short m_xxx0; /* filler */ short mscp_unit; /* unit number */ short m_xxx1; /* unused */ u_char mscp_opcode; /* opcode */ u_char mscp_flags; /* end message flags */ short mscp_modifier; /* modifiers */ union { struct { u_short Ms_bytecnt; /* byte count */ u_short Ms_zzz2; /* 64kb max for pdp-11 */ u_short Ms_buf_l; /* buffer descriptor low word */ u_short Ms_buf_h; /* buffer descriptor high word */ long Ms_xxx2[2]; /* unused */ u_short Ms_lbn_l; /* logical block number low word */ u_short Ms_lbn_h; /* logical block number high word */ long Ms_xxx4; /* unused */ long *Ms_dscptr; /* pointer to descriptor (software) */ long Ms_sftwds[17];/* software words, padding */ } mscp_generic; struct { short Ms_version; /* MSCP version */ short Ms_cntflgs; /* controller flags */ short Ms_hsttmo; /* host timeout */ short Ms_usefrac; /* use fraction */ quad Ms_time; /* time and date */ long Ms_cntdep; /* controller dependent parameters */ } mscp_setcntchar; struct { short Ms_multunt; /* multi-unit code */ short Ms_unitflgs; /* unit flags */ long Ms_hostid; /* host identifier */ quad Ms_unitid; /* unit identifier */ long Ms_mediaid; /* media type identifier */ short Ms_format; /* format (tape density) */ short Ms_speed; /* tape speed = (ips * bpi) /1000 */ short Ms_fmtmenu; /* format menu */ short Ms_group; /* group size */ short Ms_cylinder; /* cylinder size */ short Ms_xxx3; /* reserved */ short Ms_rctsize; /* RCT table size */ char Ms_rbns; /* RBNs / track */ char Ms_rctcpys; /* RCT copies */ } mscp_getunitsts; } mscp_un; short m_filler[3]; }; #define mscp_msglen (sizeof (struct mscp) - sizeof(struct mscp_header)) /* * generic packet */ #define mscp_zzz2 mscp_un.mscp_generic.Ms_zzz2 #define mscp_bytecnt mscp_un.mscp_generic.Ms_bytecnt #define mscp_buffer_h mscp_un.mscp_generic.Ms_buf_h #define mscp_buffer_l mscp_un.mscp_generic.Ms_buf_l #define mscp_lbn_h mscp_un.mscp_generic.Ms_lbn_h #define mscp_lbn_l mscp_un.mscp_generic.Ms_lbn_l #define mscp_dscptr mscp_un.mscp_generic.Ms_dscptr #define mscp_sftwds mscp_un.mscp_generic.Ms_sftwds #define mscp_status mscp_modifier /* * Abort / Get Command Status packet */ #define mscp_outref mscp_bytecnt /* * Set Controller Characteristics packet */ #define mscp_version mscp_un.mscp_setcntchar.Ms_version #define mscp_cntflgs mscp_un.mscp_setcntchar.Ms_cntflgs #define mscp_hsttmo mscp_un.mscp_setcntchar.Ms_hsttmo #define mscp_usefrac mscp_un.mscp_setcntchar.Ms_usefrac #define mscp_time mscp_un.mscp_setcntchar.Ms_time #define mscp_cntdep mscp_un.mscp_setcntchar.Ms_cntdep /* * Reposition command packet fields */ #define mscp_reccnt mscp_bytecnt /* record/object count */ #define mscp_tmkcnt mscp_buffer_l /* tape mark count */ /* * Get Unit Status end packet */ #define mscp_multunt mscp_un.mscp_getunitsts.Ms_multunt #define mscp_unitflgs mscp_un.mscp_getunitsts.Ms_unitflgs #define mscp_hostid mscp_un.mscp_getunitsts.Ms_hostid #define mscp_unitid mscp_un.mscp_getunitsts.Ms_unitid #define mscp_mediaid mscp_un.mscp_getunitsts.Ms_mediaid #define mscp_format mscp_un.mscp_getunitsts.Ms_format /* density:0=high */ #define mscp_speed mscp_un.mscp_getunitsts.Ms_speed /* (ips*bpi)/1000 */ #define mscp_fmtmenu mscp_un.mscp_getunitsts.Ms_fmtmenu /* * Online / Set Unit Characteristics end packet */ #define mscp_maxwrt mscp_dscptr /* max write byte count */ #define mscp_noiserec mscp_cylinder /* noise record */ /* * Set Controller Characteristics end packet */ #define mscp_cnttmo mscp_hsttmo /* controller timeout */ #define mscp_cntcmdl mscp_usefrac /* controller soft & hardware version */ #define mscp_cntid mscp_unitid /* controller id */ /* * Error Log message format codes */ #define M_FM_CNTERR 0 /* Controller error */ #define M_FM_BUSADDR 1 /* Host memory access error */ #define M_FM_TAPETRN 5 /* Tape transfer error */ #define M_FM_STIERR 6 /* STI communication or command failure */ #define M_FM_STIDEL 7 /* STI drive error log */ #define M_FM_STIFEL 010 /* STI formatter error log */ /* * Error Log message flags */ #define M_LF_SUCC 0200 /* Operation successful */ #define M_LF_CONT 0100 /* Operation continuing */ #define M_LF_SQNRS 0001 /* Sequence number reset */ /* * Tape Format Flag Values */ #define M_TF_800 001 /* NRZI 800 bpi */ #define M_TF_PE 002 /* Phase Encoded 1600 bpi */ #define M_TF_GCR 004 /* Group Code Recording 6250 bpi */ #define M_TF_BLK 010 /* Cartridge Block Mode */ /* * MSCP Error Log packet * * NOTE: MSCP packet must be padded to this size. */ struct mslg { struct mscp_header mslg_header;/* device specific header */ long mslg_cmdref; /* command reference number */ short mslg_unit; /* unit number */ short mslg_seqnum; /* sequence number */ u_char mslg_format; /* format */ u_char mslg_flags; /* error log message flags */ short mslg_event; /* event code */ quad me_cntid; /* controller id */ u_char me_cntsvr; /* controller software version */ u_char me_cnthvr; /* controller hardware version */ short mslg_multunt; /* multi-unit code */ quad me_unitid; /* unit id */ u_char me_unitsvr; /* unit software version */ u_char me_unithvr; /* unit hardware version */ short mslg_group; /* group; retry + level */ long mslg_position; /* position (object count) */ u_char me_fmtsvr; /* formatter software version */ u_char me_fmthvr; /* formatter hardware version */ short mslg_xxx2; /* unused */ char mslg_stiunsucc[62]; /* STI status information */ }; #define mslg_busaddr me_unitid.val[0] #define mslg_sdecyl mslg_group ldcfd bit $1,local(r5) bne 1f mov r3,r1; jsr pc,ffuword bit $fiuv,fpsr beq 2f jsr pc,chkuv 2: mov r0,(r2)+ add $2,r1; jsr pc,ffuword; mov r0,(r2)+ bit $m.ext,fpsr bne 2f add $2,r1; jsr pc,ffuword; mov r0,(r2)+ add $2,r1; jsr pc,ffuword; mov r0,(r2)+ rts pc 1: mov (r3)+,(r2)+ mov (r3)+,(r2)+ bit $m.ext,fpsr bne 2f mov (r3)+,(r2)+ mov (r3)+,(r2)+sys/pdp/libc_ulsh.s 444 0 12 3047 5404535065 7571 /* * Program: ulsh.s * Copyright 1993, GTE Government Systems * Author: Steven M. Schultz * * Version Date Modification * 0.0 02Feb91 1. Initial inspiration struck. * 1.0 05Jun93 2. Released into the Public Domain. */ #include "DEFS.h" /* * All routines have both a C interface and an assembly interface. Normally * the two are the same. In the case of 'ulsh' the compiler has placed one * of the operands in r0 and r1 so the assembly interface differs from the * C interface. */ /* * u_long ulsh(lhs, count) * u_long lhs; * short count; * * 32-bit "<<" and ">>" routines. Calls to ulsh are generated * automatically by the C compiler. */ ASENTRY(ulsh) tst 2(sp) / shift count is on stack, long is in r0+r1 bpl 1f ror r0 ror r1 inc 2(sp) 1: ashc 2(sp),r0 rts pc ENTRY(ulsh) mov 2(sp),r0 mov 4(sp),r1 tst 6(sp) / positive count? bpl 1f / yes - br ror r0 / do the first shift ror r1 / the hard way inc 6(sp) / bump count towards zero 1: ashc 6(sp),r0 / do the rest of the shifting rts pc /* * u_long ualsh(lhs, count) * u_long *lhs; * short count; * * 32-bit "<<=" and ">>=" routines. Calls to ualsh are generated * automatically by the C compiler. */ .globl ualsh ualsh: ENTRY(ualsh) mov r2,-(sp) / save a register mov 4(sp),r2 / *lhs mov (r2)+,r0 mov (r2)+,r1 tst 6(sp) / positive count? bpl 1f / yes - br ror r0 / do the first shift ror r1 / the hard way inc 6(sp) / bump count towards zero 1: ashc 6(sp),r0 / do the rest of the shifting mov r1,-(r2) mov r0,-(r2) mov (sp)+,r2 rts pc /* * End message flags */ #define M_EF_ERLOG 0040 /* Error log generated */ #define M_EF_SEREX 0020 /* Serious exception */ #define M_EF_EOT 0010 /* End of tape encountered */ #define M_EF_PLS 0004 /* Position lost */ /* * Controller flags */ #define M_CF_ATTN 0200 /* Enable attention messages */ #define M_CF_MISC 0100 /* Enable miscellaneous error log messages */ #define M_CF_OTHER 0040 /* Enable other host's error log messages */ #define M_CF_THIS 0020 /* Esys/pdp/libc_uldiv.s 444 0 12 10541 5404535064 7755 /* * Program: uldiv.s * Copyright 1993, GTE Government Systems * Author: Steven M. Schultz * * Version Date Modification * 0.0 02Feb91 1. Initial inspiration struck. * 1.0 05Jun93 2. Released into the Public Domain. */ #include "DEFS.h" /* * All routines have both a C interface and an assembly interface. Normally * the two are the same. In the case of 'ulsh' the compiler has placed one * of the operands in r0 and r1 so the assembly interface differs from the * C interface. */ /* * u_long uldiv(lhs, rhs) * u_long lhs, rhs; * * unsigned 32-bit "/" routine. Calls to uldiv are generated automatically * by the C compiler. */ #if !defined(KERNEL) /* * uldiv for applications (uses floating point) */ .globl l2f, l6f .globl uldiv uldiv: ENTRY(uldiv) jsr pc,l2f / 2(sp) -> fr0 jsr pc,l6f / 6(sp) -> fr3 tstf fr3 / check for zero divisor cfcc / don't want to have an FP fault beq 1f / in integer arithmetic divf fr3,fr0 / fr0 /= rhs 1: movfi fr0,-(sp) mov (sp)+,r0 / return result mov (sp)+,r1 seti rts pc #else /* * uldiv for the kernel (fixed point only - no FP) */ .globl uldiv uldiv: ENTRY(uldiv) mov r2,-(sp) / faster than csv/cret ... mov r3,-(sp) mov r4,-(sp) mov 14.(sp),r3 / r3 = lo(rhs) bmi slowuldiv / rhs >= 2^15 tst 12.(sp) / hi(rhs) empty? bne slowuldiv / no, rhs >= 2^16 mov 10.(sp),r2 / r2 = lo(lhs) mov 8.(sp),r1 / r1 = hi(lhs) clr r0 / r0 = hi(lhs) / lo(rhs) div r3,r0 / r1 = hi(lhs) % lo(rhs) mov r0,r4 / save high quotient mov r1,-(sp) / stash hi(tmp) mov r1,r0 / tmp=(hi(lhs)%lo(rhs))<<16 | lo(lhs) mov r2,r1 / (r0:r1 = tmp) div r3,r0 / r0 = tmp / lo(rhs) bvc 3f / done if tmp/lo(rhs) < 2^15 mov (sp),r0 / reload r0:r1 with tmp (regs may be mov r2,r1 / clobbered by failed div) sub r3,r0 / r0:r1 -= 2^16 * lo(rhs) div r3,r0 tst r1 / if (negative) remainder, subtract one from sxt r1 / quotient add r1,r0 / cannot overflow! 3: tst (sp)+ / pop hi(tmp) off stack mov r0,r1 / r1 (lo(quo)) = tmp / lo(rhs) mov r4,r0 / r0 (hi(quo)) = hi(lhs) / lo(rhs) 9: mov (sp)+,r4 / restore registers mov (sp)+,r3 mov (sp)+,r2 rts pc /* * The divisor (rhs) is known to be >= 2^15 so we perform a shift and * subtract algorithm. It's slow - feel free to improve it. * * The algorithm for signed divide broke down for unsigned operands, a slower * larger, more painful algorithm was implmented using scaling and * repetitive subraction/shifting. Works best for large numbers (fewer * shifts that way). */ slowuldiv: mov 8.(sp),r0 / r0 = hi(lhs) mov 10.(sp),r1 / r1 = lo(lhs) mov 12.(sp),r2 / r2 = hi(rhs) / r3 = lo(rhs) - already done clr r4 / init scale of lhs 2: ashc $1,r0 blos 1f / check for zero at same time inc r4 br 2b 1: mov r4,-(sp) / save scale of lhs clr r4 2: asl r3 rol r2 bcs 1f inc r4 / bump rhs scale br 2b 1: clr r0 mov $1,r1 sub (sp)+,r4 / difference in scale (rhs - lhs) ashc r4,r0 / initial quotient adder mov r1,-(sp) / quoadder lo mov r0,-(sp) / quoadder hi mov 12.(sp),r0 / r0 = hi(lhs) mov 14.(sp),r1 / r1 = lo(lhs) mov 16.(sp),r2 / r2 = hi(rhs) mov 18.(sp),r3 / r3 = lo(rhs) ashc r4,r2 / scale rhs up for repetitive subtraction clr r4 / quo lo clr -(sp) / quo hi docmp: cmp r2,r0 bhi noadd blo dosub cmp r3,r1 bhi noadd dosub: sub r3,r1 sbc r0 sub r2,r0 add 4(sp),r4 / quo lo += quoadder lo adc (sp) / quo hi add 2(sp),(sp) / quo hi += quoadder hi br docmp noadd: clc / right shift rhs ror r2 ror r3 clc / right shift quotient adder ror 2(sp) ror 4(sp) bne docmp / quo adder not 0 means more to do tst 2(sp) bne docmp mov (sp)+,r0 / quo hi mov r4,r1 / quo lo cmp (sp)+,(sp)+ / remove quot adder br 9b #endif KERNEL /* * u_long ualdiv(lhs, rhs) * u_long *lhs, rhs; * * 32-bit "/=" routine. Calls to ualdiv are generated automatically by the C * compiler. */ .globl ualdiv ualdiv: ENTRY(ualdiv) mov r2,-(sp) / need a register to point at the lhs mov 8.(sp),-(sp) / The divide algorithm is long mov 8.(sp),-(sp) / enough that it just doesn't make sense mov 8.(sp),r2 / to bother repeating it. We just translate mov 2(r2),-(sp) / the call for uldiv and let it do the work mov (r2),-(sp) / and return its results (also stuffing it jsr pc,uldiv / into *lhs) add $8.,sp / clean up stack mov r0,(r2)+ / store high word, mov r1,(r2) / and low mov (sp)+,r2 / restore r2 rts pc / and return */ long Ms_cntdep; /* controller dependent parameters */ } mscp_setcntchar; struct { short Ms_multunt; /* multi-unit code */ short Ms_unitflgs; /* unisys/pdp/symbols.raw 644 0 12 3270 5520341367 7643 #symbols.raw 1.0 January 22, 1994 _version #checksys _end _nbuf _buf _nproc _proc _ntext _text _nfile _file _ninode _inode _ncallout _callout _ucb_clist _nclist _ram_size _xitdesc _quotdesc _namecache __iosize #ps _proc _nproc _hz #snake _avenrun #trace _tracebuf #welcome _avenrun #jove _avenrun #ntpd _tickadj _hz _tick #gcore _proc _nproc #netstat _netdata _nfile _file _mbstat _ipstat _tcb _tcpstat _udb _udpstat _rawcb _ifnet _hosts _rthost _rtnet _icmpstat _rtstat _unixsw _rthashsize _nspcb _idpstat # _spp_istat # _ns_errstat #w _proc _swapdev _avenrun _boottime _nproc #vmstat _cp_time _rate _total # _deficit _forkstat _sum _firstfree _maxfree _boottime _dk_xfer # _rectime # _pgintime _hz _phz _nchstats # _intrnames # _eintrnames # _intrcnt # _eintrcnt _dk_ndrive _xstats _dk_name _dk_unit _freemem # _mbdinit # _ubdinit #acucntrl _cdevsw _dzopen _dzinfo _dz_cnt _dzsoftCAR _dhopen _dhinfo _ndh11 _dhsoftCAR _dmfopen _dmfinfo _ndmf _dmfsoftCAR #iostat _dk_busy _dk_time _dk_xfer _dk_wds _tk_nin _tk_nout _dk_seek _cp_time _dk_wps _hz _dk_ndrive _dk_name _dk_unit #sendmail _avenrun #fstat _proc _nproc _netdata #trsp # _spp_debug # _spp_debx #savecore _dumpdev _dumplo _time _panicstr _physmem _boottime _version #route.c _rthost _rtnet _rthashsize _netdata #trpt.c # _tcp_debug # _tcp_debx #dmesg _msgbuf #arp _arptab _arptab_size _netdata #rwhod _avenrun _boottime #pstat _inode _text _proc _dz_tty _dz_cnt _cons _file _nswap _nkl11 _swapmap _dh11 _ndh11 _nproc _ntext _nfile _ninode _pt_tty _dmf_tty _ndmf _npty _dhu_tty _ndhu _dmz_tty _ndmz _dhv_tty _ndhv eload r0:r1 with tmp (regs may be mov r2,r1 / clobbered by failed div) sub r3,r0 / r0:r1 -= 2^16 * lo(rhs) div r3,r0 tst r1 / if (negative) remainder, subtract one from sxt r1 / quotient add r1,r0 / cannot overflow! 3: tst (sp)+ / pop hi(tmp) off stack mov r0,r1 / r1 (lo(quo)) = tmp / lo(rhs) mov r4,r0 / rsys/pdp/symbols.sort 644 0 12 1520 5520342132 10024 __iosize _arptab _arptab_size _avenrun _boottime _buf _callout _cdevsw _cons _cp_time _dh11 _dhinfo _dhopen _dhsoftCAR _dhu_tty _dhv_tty _dk_busy _dk_name _dk_ndrive _dk_seek _dk_time _dk_unit _dk_wds _dk_wps _dk_xfer _dmf_tty _dmfinfo _dmfopen _dmfsoftCAR _dmz_tty _dumpdev _dumplo _dz_cnt _dz_tty _dzinfo _dzopen _dzsoftCAR _end _file _firstfree _forkstat _freemem _hosts _hz _icmpstat _idpstat _ifnet _inode _ipstat _maxfree _mbstat _msgbuf _namecache _nbuf _ncallout _nchstats _nclist _ndh11 _ndhu _ndhv _ndmf _ndmz _netdata _nfile _ninode _nkl11 _nproc _npty _nspcb _nswap _ntext _panicstr _physmem _phz _proc _pt_tty _quotdesc _ram_size _rate _rawcb _rthashsize _rthost _rtnet _rtstat _sum _swapdev _swapmap _tcb _tcpstat _text _tick _tickadj _time _tk_nin _tk_nout _total _tracebuf _ucb_clist _udb _udpstat _unixsw _version _xitdesc _xstats _xstats _dk_name _dk_unit _freemem # _mbdinit # _ubdinit #acucntrl _cdevsw _dzopen _dzinfo _dz_cnt _dzsoftCAR _dhopen _dhinfo _ndh11 _dhsoftCAR _dmfopen _dmfinfo sys/mdec/ 755 0 0 0 6001105343 5436 sys/mdec/rm05uboot.s 644 0 0 11753 5763226016 7611 MAJOR = 10. / major # from bdevsw[] / RM02/03/05 bootstrap / / 1995/05/31 - The unit number needs to go in bits 3-5 of bootdev / because the partition number now goes into bits 0-2. / / disk boot program to load and transfer / to a unix entry. / for use with 1 KB byte blocks, CLSIZE is 2. / NDIRIN is the number of direct inode addresses (currently 4) / assembled size must be <= 512; if > 494, the 16-byte a.out header / must be removed RM05 = 1 / 0-> RM02/03, 1-> RM05 / options: none. all options of reading an alternate name or echoing to / the keyboard had to be removed to make room for the / code which understands the new directory structure on disc / constants: CLSIZE = 2. / physical disk blocks per logical block CLSHFT = 1. / shift to multiply by CLSIZE BSIZE = 512.*CLSIZE / logical block size INOSIZ = 64. / size of inode in bytes NDIRIN = 4. / number of direct inode addresses ADDROFF = 12. / offset of first address in inode INOPB = BSIZE\/INOSIZ / inodes per logical block INOFF = 31. / inode offset = (INOPB * (SUPERB+1)) - 1 PBSHFT = -4 / shift to divide by inodes per block WC = -256.*CLSIZE / word count / The boot options and device are placed in the last SZFLAGS bytes / at the end of core by the kernel for autobooting. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 CHECKWORD= 6 .. = ENDCORE-512.-SZFLAGS / save room for boot flags / entry is made by jsr pc,*$0 / so return can be rts pc / establish sp, copy / program up to end of core. nop / These two lines must be present or DEC br start / boot ROMs will refuse to run boot block! start: mov r0,unit mov r1,csr mov $..,sp mov sp,r1 clr r0 1: mov (r0)+,(r1)+ cmp r1,$end blo 1b jmp *$2f / On error, restart from here. restart: clr r0 / clear core to make things clean 2: clr (r0)+ cmp r0,sp blo 2b / initialize disk mov csr,r1 mov unit,rmcs2(r1) mov $preset+go,rmcs1(r1) mov $fmt22,rmof(r1) mov $bootnm, r1 mov $2,r0 / ROOTINO jsr pc,iget clr r2 / offset again: jsr pc,readdir beq restart / error - restart mov 4(r0),r4 / dp->d_namlen cmp r4,$bootlen / if (bootlen == dp->d_namlen) bne again / nope, go try next entry mov r0,r3 add $6,r3 / r3 = dp->d_name mov r1,r5 / r5 = filename 9: cmpb (r3)+,(r5)+ bne again / no match - go read next entry sob r4,9b mov (r0),r0 / r0 = dp->d_ino jsr pc,iget / fetch boot's inode br loadfile / 'boot'- go read it / get the inode specified in r0 iget: add $INOFF,r0 mov r0,r5 ash $PBSHFT,r0 bic $!7777,r0 mov r0,dno clr r0 jsr pc,rblk bic $!17,r5 mov $INOSIZ,r0 mul r0,r5 add $buf,r5 mov $inod,r4 1: movb (r5)+,(r4)+ sob r0,1b rts pc readdir: bit $BSIZE-1,r2 bne 1f jsr pc,rmblk / read mapped block (bno) br err / end of file branch clr r2 / start at beginning of buf 1: mov $buf,r0 add r2,r0 / dp = buf+offset add buf+2(r2),r2 / dp += dp->d_reclen tst (r0) / dp->d_ino == 0? beq readdir / yes - go look at next rts pc / return with r0 = &dp->d_ino err: clr r0 / return with rts pc / dp = NULL loadfile: clr bno / start at block 0 of inode in 'inod' / read file into core until / a mapping error, (no disk address) clr r1 1: jsr pc,rmblk br 1f mov $buf,r2 2: mov (r2)+,(r1)+ cmp r2,$buf+BSIZE blo 2b br 1b / relocate core around / assembler header 1: clr r0 cmp (r0),$407 bne 2f 1: mov 20(r0),(r0)+ cmp r0,sp blo 1b / enter program and / restart if return 2: mov ENDCORE-BOOTOPTS, r4 mov unit,r3 ash $3,r3 / unit # in bits 3-5, partition # is 0 bis $MAJOR\<8.,r3 mov ENDCORE-CHECKWORD, r2 mov csr,r1 jsr pc,*$0 br restart / read a mapped block / offset in file is in bno. / skip if success, no skip if fail / the algorithm only handles a single / indirect block. that means that / files longer than NDIRIN+256 blocks (260kb) cannot / be loaded. rmblk: add $2,(sp) mov bno,r0 cmp r0,$NDIRIN blt 1f mov $NDIRIN,r0 1: ash $2,r0 mov addr+2(r0),dno mov addr(r0),r0 bne 1f tst dno beq 2f 1: jsr pc,rblk mov bno,r0 inc bno sub $NDIRIN,r0 blt 1f ash $2,r0 mov buf+2(r0),dno mov buf(r0),r0 bne rblk tst dno bne rblk 2: sub $2,(sp) 1: rts pc read = 70 preset = 20 go = 1 fmt22 = 10000 NSECT = 32. .if RM05 NTRAK = 19. / RM05 .endif .if RM05-1 NTRAK = 5. / RM02/03 .endif rmcs1 = 0 rmda = rmcs1+6 rmcs2 = rmcs1+10 rmds = rmcs1+12 rmof = rmcs1+32 rmca = rmcs1+34 / rm02/3/5 disk driver. / low order address in dno, / high order in r0. rblk: mov r1,-(sp) mov dno,r1 .if CLSIZE-1 ashc $CLSHFT,r0 / multiply by CLSIZE .endif div $NSECT*NTRAK,r0 mov csr,r3 mov r0,rmca(r3) clr r0 div $NSECT,r0 swab r0 bis r1,r0 add $rmcs2,r3 mov unit,(r3) mov r0,-(r3) mov $buf,-(r3) mov $WC,-(r3) mov $read+go,-(r3) 1: tstb (r3) bge 1b mov (sp)+,r1 rts pc bootnm: bootlen = 4 / strlen(bootnm) unit: 0 csr: 0 end: inod = ..-512.-BSIZE / room for inod, buf, stack addr = inod+ADDROFF / first address in inod buf = inod+INOSIZ bno = buf+BSIZE dno = bno+2 ies */ } mscp_getunisys/mdec/hpuboot.s 644 0 0 11730 5763225763 7440 MAJOR = 10. / major # from bdevsw[] / RP04/05/06 bootstrap. / / 1995/05/31 - The unit number needs to go in bits 3-5 of bootdev / because the partition number now goes into bits 0-2. / / disk boot program to load and transfer / to a unix entry. / for use with 1 KB byte blocks, CLSIZE is 2. / NDIRIN is the number of direct inode addresses (currently 4) / assembled size must be <= 512; if > 494, the 16-byte a.out header / must be removed / options: none. all options of reading an alternate name or echoing to / the keyboard had to be removed to make room for the / code which understands the new directory structure on disc / 930124 Fixed major bug that made booting impossible. / Lasse Ylitalo & Johnny Billquist / constants: CLSIZE = 2. / physical disk blocks per logical block CLSHFT = 1. / shift to multiply by CLSIZE BSIZE = 512.*CLSIZE / logical block size INOSIZ = 64. / size of inode in bytes NDIRIN = 4. / number of direct inode addresses ADDROFF = 12. / offset of first address in inode INOPB = BSIZE\/INOSIZ / inodes per logical block INOFF = 31. / inode offset = (INOPB * (SUPERB+1)) - 1 PBSHFT = -4 / shift to divide by inodes per block WC = -256.*CLSIZE / word count / The boot options and device are placed in the last SZFLAGS bytes / at the end of core by the kernel for autobooting. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 CHECKWORD= 6 .. = ENDCORE-512.-SZFLAGS / save room for boot flags / entry is made by jsr pc,*$0 / so return can be rts pc / establish sp, copy / program up to end of core. nop / These two lines must be present or DEC br start / boot ROMs will refuse to run boot block! start: mov r0,unit mov r1,csr mov $..,sp mov sp,r1 clr r0 1: mov (r0)+,(r1)+ cmp r1,$end blo 1b jmp *$2f / On error, restart from here. restart: clr r0 / clear core to make things clean 2: clr (r0)+ cmp r0,sp blo 2b / initialize hp mov csr,r1 mov unit,hpcs2(r1) mov $preset+go,hpcs1(r1) mov $fmt22,hpof(r1) mov $bootnm, r1 mov $2,r0 / ROOTINO jsr pc,iget clr r2 / offset again: jsr pc,readdir beq restart / error - restart mov 4(r0),r4 / dp->d_namlen cmp r4,$bootlen / if (bootlen == dp->d_namlen) bne again / nope, go try next entry mov r0,r3 add $6,r3 / r3 = dp->d_name mov r1,r5 / r5 = filename 9: cmpb (r3)+,(r5)+ bne again / no match - go read next entry sob r4,9b mov (r0),r0 / r0 = dp->d_ino jsr pc,iget / fetch boot's inode br loadfile / 'boot'- go read it / get the inode specified in r0 iget: add $INOFF,r0 mov r0,r5 ash $PBSHFT,r0 bic $!7777,r0 mov r0,dno clr r0 jsr pc,rblk bic $!17,r5 mov $INOSIZ,r0 mul r0,r5 add $buf,r5 mov $inod,r4 1: movb (r5)+,(r4)+ sob r0,1b rts pc readdir: bit $BSIZE-1,r2 bne 1f jsr pc,rmblk / read mapped block (bno) br err / end of file branch clr r2 / start at beginning of buf 1: mov $buf,r0 add r2,r0 / dp = buf+offset add buf+2(r2),r2 / dp += dp->d_reclen tst (r0) / dp->d_ino == 0? beq readdir / yes - go look at next rts pc / return with r0 = &dp->d_ino err: clr r0 / return with rts pc / dp = NULL loadfile: clr bno / start at block 0 of inode in 'inod' / read file into core until / a mapping error, (no disk address) clr r1 1: jsr pc,rmblk br 1f mov $buf,r2 2: mov (r2)+,(r1)+ cmp r2,$buf+BSIZE blo 2b br 1b / relocate core around / assembler header 1: clr r0 cmp (r0),$407 bne 2f 1: mov 20(r0),(r0)+ cmp r0,sp blo 1b / enter program and / restart if return 2: mov ENDCORE-BOOTOPTS, r4 mov unit,r3 ash $3,r3 / unit # in bits 3-5, partition # is 0 bis $MAJOR\<8.,r3 mov ENDCORE-CHECKWORD, r2 mov csr,r1 jsr pc,*$0 br restart / read a mapped block / offset in file is in bno. / skip if success, no skip if fail / the algorithm only handles a single / indirect block. that means that / files longer than NDIRIN+256 blocks (260kb) cannot / be loaded. rmblk: add $2,(sp) mov bno,r0 cmp r0,$NDIRIN blt 1f mov $NDIRIN,r0 1: ash $2,r0 mov addr+2(r0),dno mov addr(r0),r0 bne 1f tst dno beq 2f 1: jsr pc,rblk mov bno,r0 inc bno sub $NDIRIN,r0 blt 1f ash $2,r0 mov buf+2(r0),dno mov buf(r0),r0 bne rblk tst dno bne rblk 2: sub $2,(sp) 1: rts pc read = 70 preset = 20 go = 1 fmt22 = 10000 hpcs1 = 0 hpda = hpcs1+6 hpcs2 = hpcs1+10 hpds = hpcs1+12 hpof = hpcs1+32 hpca = hpcs1+34 / rp0456 disk driver. / low order address in dno, / high order in r0. rblk: mov r1,-(sp) mov dno,r1 .if CLSIZE-1 ashc $CLSHFT,r0 / multiply by CLSIZE .endif div $22.*19.,r0 mov csr,r3 mov r0,hpca(r3) clr r0 div $22.,r0 swab r0 bis r1,r0 add $hpcs2,r3 / 930124 LY&JB mov unit,(r3) mov r0,-(r3) mov $buf,-(r3) mov $WC,-(r3) mov $read+go,-(r3) 1: tstb (r3) bge 1b mov (sp)+,r1 rts pc bootnm: bootlen = 4 / strlen(bootnm) unit: 0 csr: 0 end: inod = ..-512.-BSIZE / room for inod, buf, stack addr = inod+ADDROFF / first address in inod buf = inod+INOSIZ bno = buf+BSIZE dno = bno+2 / r0 = dp->d_ino jsr pc,iget / fetch sys/mdec/rkuboot.s 644 0 0 11552 5763225776 7453 MAJOR = 6 / major # from bdevsw[] / RK05 bootstrap. / / 1995/05/31 - The unit number needs to go in bits 3-5 of bootdev / because the partition number now goes into bits 0-2. / / disk boot program to load and transfer / to a unix entry. / for use with 1 KB byte blocks, CLSIZE is 2. / NDIRIN is the number of direct inode addresses (currently 4) / assembled size must be <= 512; if > 494, the 16-byte a.out header / must be removed / options: none. all options of reading an alternate name or echoing to / the keyboard had to be removed to make room for the / code which understands the new directory structure on disc / constants: CLSIZE = 2. / physical disk blocks per logical block CLSHFT = 1. / shift to multiply by CLSIZE BSIZE = 512.*CLSIZE / logical block size INOSIZ = 64. / size of inode in bytes NDIRIN = 4. / number of direct inode addresses ADDROFF = 12. / offset of first address in inode INOPB = BSIZE\/INOSIZ / inodes per logical block INOFF = 31. / inode offset = (INOPB * (SUPERB+1)) - 1 PBSHFT = -4 / shift to divide by inodes per block WC = -256.*CLSIZE / word count / The boot options and device are placed in the last SZFLAGS bytes / at the end of core by the kernel for autobooting. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 CHECKWORD= 6 .. = ENDCORE-512.-SZFLAGS / save room for boot flags / entry is made by jsr pc,*$0 / so return can be rts pc / establish sp, copy / program up to end of core. nop / These two lines must be present or DEC br start / boot ROMs will refuse to run boot block! start: mov r0,unit mov r1,csr mov $..,sp mov sp,r1 clr r0 1: mov (r0)+,(r1)+ cmp r1,$end blo 1b jmp *$2f / On error, restart from here. restart: clr r0 / clear core to make things clean 2: clr (r0)+ cmp r0,sp blo 2b / initialize rk mov csr,r1 mov $reset+go,rkcs(r1) / reset controller mov $bootnm, r1 mov $2,r0 / ROOTINO jsr pc,iget clr r2 / offset again: jsr pc,readdir beq restart / error - restart mov 4(r0),r4 / dp->d_namlen cmp r4,$bootlen / if (bootlen == dp->d_namlen) bne again / nope, go try next entry mov r0,r3 add $6,r3 / r3 = dp->d_name mov r1,r5 / r5 = filename 9: cmpb (r3)+,(r5)+ bne again / no match - go read next entry sob r4,9b mov (r0),r0 / r0 = dp->d_ino jsr pc,iget / fetch boot's inode br loadfile / 'boot'- go read it / get the inode specified in r0 iget: add $INOFF,r0 mov r0,r5 ash $PBSHFT,r0 bic $!7777,r0 mov r0,dno clr r0 jsr pc,rblk bic $!17,r5 mov $INOSIZ,r0 mul r0,r5 add $buf,r5 mov $inod,r4 1: movb (r5)+,(r4)+ sob r0,1b rts pc readdir: bit $BSIZE-1,r2 bne 1f jsr pc,rmblk / read mapped block (bno) br err / end of file branch clr r2 / start at beginning of buf 1: mov $buf,r0 add r2,r0 / dp = buf+offset add buf+2(r2),r2 / dp += dp->d_reclen tst (r0) / dp->d_ino == 0? beq readdir / yes - go look at next rts pc / return with r0 = &dp->d_ino err: clr r0 / return with rts pc / dp = NULL loadfile: clr bno / start at block 0 of inode in 'inod' / read file into core until / a mapping error, (no disk address) clr r1 1: jsr pc,rmblk br 1f mov $buf,r2 2: mov (r2)+,(r1)+ cmp r2,$buf+BSIZE blo 2b br 1b / relocate core around / assembler header 1: clr r0 cmp (r0),$407 bne 2f 1: mov 20(r0),(r0)+ cmp r0,sp blo 1b / enter program and / restart if return 2: mov ENDCORE-BOOTOPTS, r4 mov unit,r3 ash $3,r3 / unit # in bits 3-5, partition # is 0 bis $MAJOR\<8.,r3 mov ENDCORE-CHECKWORD, r2 mov csr,r1 jsr pc,*$0 br restart / read a mapped block / offset in file is in bno. / skip if success, no skip if fail / the algorithm only handles a single / indirect block. that means that / files longer than NDIRIN+256 blocks (260kb) cannot / be loaded. rmblk: add $2,(sp) mov bno,r0 cmp r0,$NDIRIN blt 1f mov $NDIRIN,r0 1: ash $2,r0 mov addr+2(r0),dno mov addr(r0),r0 bne 1f tst dno beq 2f 1: jsr pc,rblk mov bno,r0 inc bno sub $NDIRIN,r0 blt 1f ash $2,r0 mov buf+2(r0),dno mov buf(r0),r0 bne rblk tst dno bne rblk 2: sub $2,(sp) 1: rts pc read = 4 reset = 0 go = 1 rkcs = 0 / offset from base csr rkwc = 2 rkba = 4 rkda = 6 / rk05 disk driver. / low order address in dno, / high order in r0. rblk: mov r1,-(sp) mov dno,r1 .if CLSIZE-1 ashc $CLSHFT,r0 / multiply by CLSIZE .endif div $12.,r0 ash $4,r0 bis r1,r0 mov unit,r3 ash $13.,r3 bis r3,r0 mov csr,r3 mov r0,rkda(r3) / stuff disc address mov $buf,rkba(r3) / where to put it. mov $WC,rkwc(r3) / yes sir, yes sir, three bags full mov $read+go,(r3) / rkcs - press the button 1: tstb (r3) / rkcs bge 1b mov (sp)+,r1 rts pc bootnm: bootlen = 4 / strlen(bootnm) unit: 0 csr: 0 end: inod = ..-512.-BSIZE / room for inod, buf, stack addr = inod+ADDROFF / first address in inod buf = inod+INOSIZ bno = buf+BSIZE dno = bno+2 2.-BSIZE / room for inod, buf, stack addr = inod+ADDROFF / first address in inod buf = inod+INOSIZ bno = buf+BSIZE dno = bno+2 ies */ } mscp_getunisys/mdec/rluboot.s 644 0 0 14206 5763226004 7434 MAJOR = 7 / major # from bdevsw[] / RL01/02 bootstrap. / / 1995/05/31 - The unit number needs to go in bits 3-5 of bootdev / because the partition number now goes into bits 0-2. / / disk boot program to load and transfer / to a unix entry. / for use with 1 KB byte blocks, CLSIZE is 2. / NDIRIN is the number of direct inode addresses (currently 4) / assembled size must be <= 512; if > 494, the 16-byte a.out header / must be removed / options: none. all options of reading an alternate name or echoing to / the keyboard had to be removed to make room for the / code which understands the new directory structure on disc / constants: CLSIZE = 2. / physical disk blocks per logical block CLSHFT = 1. / shift to multiply by CLSIZE BSIZE = 512.*CLSIZE / logical block size INOSIZ = 64. / size of inode in bytes NDIRIN = 4. / number of direct inode addresses ADDROFF = 12. / offset of first address in inode INOPB = BSIZE\/INOSIZ / inodes per logical block INOFF = 31. / inode offset = (INOPB * (SUPERB+1)) - 1 PBSHFT = -4 / shift to divide by inodes per block WC = -256.*CLSIZE / word count / The boot options and device are placed in the last SZFLAGS bytes / at the end of core by the kernel for autobooting. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 CHECKWORD= 6 .. = ENDCORE-512.-SZFLAGS / save room for boot flags / entry is made by jsr pc,*$0 / so return can be rts pc nop / These two lines must be present or DEC MXV-11 br start / boot ROMs will refuse to run boot block! / establish sp, copy / program up to end of core. start: movb r0,unit+1 / unit # in high byte mov r1,csr mov $..,sp mov sp,r1 clr r0 1: mov (r0)+,(r1)+ cmp r1,$end blo 1b jmp *$2f / On error, restart from here. restart: clr r0 / clear core to make things clean 2: clr (r0)+ cmp r0,sp blo 2b / initialize rl / mov $13,*$rlda /get status / mov $4,*$rlcs / / jsr pc,rdy / mov *$rlda,r5 /superstision / mov $bootnm, r1 mov $2,r0 / ROOTINO jsr pc,iget clr r2 / offset again: jsr pc,readdir beq restart / error - restart mov 4(r0),r4 / dp->d_namlen cmp r4,$bootlen / if (bootlen == dp->d_namlen) bne again / nope, go try next entry mov r0,r3 add $6,r3 / r3 = dp->d_name mov r1,r5 / r5 = filename 9: cmpb (r3)+,(r5)+ bne again / no match - go read next entry sob r4,9b mov (r0),r0 / r0 = dp->d_ino jsr pc,iget / fetch boot's inode br loadfile / 'boot'- go read it / get the inode specified in r0 iget: add $INOFF,r0 mov r0,r5 ash $PBSHFT,r0 bic $!7777,r0 mov r0,dno clr r0 jsr pc,rblk bic $!17,r5 mov $INOSIZ,r0 mul r0,r5 add $buf,r5 mov $inod,r4 1: movb (r5)+,(r4)+ sob r0,1b rts pc readdir: bit $BSIZE-1,r2 bne 1f jsr pc,rmblk / read mapped block (bno) br err / end of file branch clr r2 / start at beginning of buf 1: mov $buf,r0 add r2,r0 / dp = buf+offset add buf+2(r2),r2 / dp += dp->d_reclen tst (r0) / dp->d_ino == 0? beq readdir / yes - go look at next rts pc / return with r0 = &dp->d_ino err: clr r0 / return with rts pc / dp = NULL loadfile: clr bno / start at block 0 of inode in 'inod' / read file into core until / a mapping error, (no disk address) clr r1 1: jsr pc,rmblk br 1f mov $buf,r2 2: mov (r2)+,(r1)+ cmp r2,$buf+BSIZE blo 2b br 1b / relocate core around / assembler header 1: clr r0 cmp (r0),$407 bne 2f 1: mov 20(r0),(r0)+ cmp r0,sp blo 1b / enter program and / restart if return 2: mov ENDCORE-BOOTOPTS, r4 movb unit+1,r3 ash $3,r3 / unit # in bits 3-5, partition # is 0 bis $MAJOR\<8.,r3 mov ENDCORE-CHECKWORD, r2 mov csr,r1 jsr pc,*$0 br restart / read a mapped block / offset in file is in bno. / skip if success, no skip if fail / the algorithm only handles a single / indirect block. that means that / files longer than NDIRIN+256 blocks (260kb) cannot / be loaded. rmblk: add $2,(sp) mov bno,r0 cmp r0,$NDIRIN blt 1f mov $NDIRIN,r0 1: ash $2,r0 mov addr+2(r0),dno mov addr(r0),r0 bne 1f tst dno beq 2f 1: jsr pc,rblk mov bno,r0 inc bno sub $NDIRIN,r0 blt 1f ash $2,r0 mov buf+2(r0),dno mov buf(r0),r0 bne rblk tst dno bne rblk 2: sub $2,(sp) 1: rts pc / / RL02 read only non-interrupt driven driver / Dave Clemans, TEK, 4/8/82 / / NOTE: / errors are NOT checked / spiral reads are NOT implemented / it MUST run in the lower 64K address space / / Parameters: / r0: high part of disk block number / dno: low part of disk block number / WC: amount of data to read / buf: buffer to read data into / / Register usage: / r1,r2: used, but saved / r0,r3,r4 used and clobbered rlcs = 0 / offset from base csr rlba = 2 rlda = 4 rlmp = 6 READ = 14 SEEK = 6 RDHDR = 10 SEEKHI = 5 SEEKLO = 1 CRDY = 200 RLSECT = 20. rblk: mov r1,-(sp) mov r2,-(sp) mov csr,r4 mov dno,r1 .if CLSIZE-1 ashc $CLSHFT,r0 / multiply by CLSIZE .endif div $RLSECT,r0 / cylinder number - surface asl r1 / sector number mov unit,-(sp) bis $RDHDR,(sp) mov (sp)+,(r4) / find where the heads are now 7: tstb (r4) / wait for the STUPID!!! controller (CRDY=200) bpl 7b mov rlmp(r4),r2 ash $-7,r2 bic $!777,r2 / we are at this cylinder now mov r0,r3 asr r3 / desired cylinder number sub r3,r2 / compute relative seek distance bge 1f / up or down? neg r2 ash $7,r2 bis $SEEKHI,r2 / up br 2f 1: ash $7,r2 inc r2 / down (SEEKLO = 1, so just do 'inc') 2: mov r0,r3 / compute desired disk surface bic $!1,r3 ash $4,r3 bis r3,r2 mov r2,rlda(r4) / disk address for seek mov unit,-(sp) bis $SEEK,(sp) mov (sp)+,(r4) / do the seek 7: tstb (r4) / wait for the STUPID!!! controller bpl 7b ash $6,r0 / compute disk address for read bis r1,r0 add $rlmp,r4 / point to rlmp mov $WC,(r4) / word count for read mov r0,-(r4) / disk address for read mov $buf,-(r4) / buffer address for read mov unit,-(sp) bis $READ,(sp) mov (sp)+,-(r4) / do the read 7: tstb (r4) / wait for the STUPID!!! controller bpl 7b mov (sp)+,r2 mov (sp)+,r1 rts pc bootnm: bootlen = 4 / strlen(bootnm) unit: 0 csr: 0 end: inod = ..-512.-BSIZE / room for inod, buf, stack addr = inod+ADDROFF / first address in inod buf = inod+INOSIZ bno = buf+BSIZE dno = bno+2 p)+,r1 rts pc bootnm: bootlen = 4 / strlen(bootnm) unit: 0 csr: 0 end: inod = ..-512.-BSIZE / room for inod, buf, stack addr = inod+ADDROFF / first address in inod buf = inod+INOSIZ bno = buf+BSIZE dno = bno+2 2.-BSIZE / room for inod, buf, stack addr = inod+ADDROFF / first address in inod buf = inod+INOSIZ bno = buf+BSIZE dno = bno+2 ies */ } mscp_getunisys/mdec/si51uboot.s 644 0 0 12010 5763226025 7572 MAJOR = 10. / major # from bdevsw[] / Fujitsu Eagle (2351A) on SI 6100 Controller bootstrap / Actually just a small modification of the RM02/03/05 bootstrap / / 1995/05/31 - The unit number needs to go in bits 3-5 of bootdev / because the partition number now goes into bits 0-2. / / disk boot program to load and transfer / to a unix entry. / for use with 1 KB byte blocks, CLSIZE is 2. / NDIRIN is the number of direct inode addresses (currently 4) / assembled size must be <= 512; if > 494, the 16-byte a.out header / must be removed / options: none. all options of reading an alternate name or echoing to / the keyboard had to be removed to make room for the / code which understands the new directory structure on disc / constants: CLSIZE = 2. / physical disk blocks per logical block CLSHFT = 1. / shift to multiply by CLSIZE BSIZE = 512.*CLSIZE / logical block size INOSIZ = 64. / size of inode in bytes NDIRIN = 4. / number of direct inode addresses ADDROFF = 12. / offset of first address in inode INOPB = BSIZE\/INOSIZ / inodes per logical block INOFF = 31. / inode offset = (INOPB * (SUPERB+1)) - 1 PBSHFT = -4 / shift to divide by inodes per block WC = -256.*CLSIZE / word count / The boot options and device are placed in the last SZFLAGS bytes / at the end of core by the kernel for autobooting. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 CHECKWORD= 6 .. = ENDCORE-512.-SZFLAGS / save room for boot flags / entry is made by jsr pc,*$0 / so return can be rts pc / establish sp, copy / program up to end of core. nop / These two lines must be present or DEC br start / boot ROMs will refuse to run boot block! start: mov r0,unit mov r1,csr mov $..,sp mov sp,r1 clr r0 1: mov (r0)+,(r1)+ cmp r1,$end blo 1b jmp *$2f / On error, restart from here. restart: clr r0 / clear core to make things clean 2: clr (r0)+ cmp r0,sp blo 2b / initialize disk mov csr,r1 mov unit,rmcs2(r1) mov $preset+go,rmcs1(r1) mov $fmt22,rmof(r1) mov $bootnm, r1 mov $2,r0 / ROOTINO jsr pc,iget clr r2 / offset again: jsr pc,readdir beq restart / error - restart mov 4(r0),r4 / dp->d_namlen cmp r4,$bootlen / if (bootlen == dp->d_namlen) bne again / nope, go try next entry mov r0,r3 add $6,r3 / r3 = dp->d_name mov r1,r5 / r5 = filename 9: cmpb (r3)+,(r5)+ bne again / no match - go read next entry sob r4,9b mov (r0),r0 / r0 = dp->d_ino jsr pc,iget / fetch boot's inode br loadfile / 'boot'- go read it / get the inode specified in r0 iget: add $INOFF,r0 mov r0,r5 ash $PBSHFT,r0 bic $!7777,r0 mov r0,dno clr r0 jsr pc,rblk bic $!17,r5 mov $INOSIZ,r0 mul r0,r5 add $buf,r5 mov $inod,r4 1: movb (r5)+,(r4)+ sob r0,1b rts pc readdir: bit $BSIZE-1,r2 bne 1f jsr pc,rmblk / read mapped block (bno) br err / end of file branch clr r2 / start at beginning of buf 1: mov $buf,r0 add r2,r0 / dp = buf+offset add buf+2(r2),r2 / dp += dp->d_reclen tst (r0) / dp->d_ino == 0? beq readdir / yes - go look at next rts pc / return with r0 = &dp->d_ino err: clr r0 / return with rts pc / dp = NULL loadfile: clr bno / start at block 0 of inode in 'inod' / read file into core until / a mapping error, (no disk address) clr r1 1: jsr pc,rmblk br 1f mov $buf,r2 2: mov (r2)+,(r1)+ cmp r2,$buf+BSIZE blo 2b br 1b / relocate core around / assembler header 1: clr r0 cmp (r0),$407 bne 2f 1: mov 20(r0),(r0)+ cmp r0,sp blo 1b / enter program and / restart if return 2: mov ENDCORE-BOOTOPTS, r4 mov unit,r3 ash $3,r3 / unit # in bits 3-5, partition # is 0 bis $MAJOR\<8.,r3 mov ENDCORE-CHECKWORD, r2 mov csr,r1 jsr pc,*$0 br restart / read a mapped block / offset in file is in bno. / skip if success, no skip if fail / the algorithm only handles a single / indirect block. that means that / files longer than NDIRIN+256 blocks (260kb) cannot / be loaded. rmblk: add $2,(sp) mov bno,r0 cmp r0,$NDIRIN blt 1f mov $NDIRIN,r0 1: ash $2,r0 mov addr+2(r0),dno mov addr(r0),r0 bne 1f tst dno beq 2f 1: jsr pc,rblk mov bno,r0 inc bno sub $NDIRIN,r0 blt 1f ash $2,r0 mov buf+2(r0),dno mov buf(r0),r0 bne rblk tst dno bne rblk 2: sub $2,(sp) 1: rts pc read = 70 preset = 20 go = 1 fmt22 = 10000 NSECT = 48. NTRAK = 20. / SI 6100 with Fujitsu 2351A rmcs1 = 0 rmda = rmcs1+6 rmcs2 = rmcs1+10 rmds = rmcs1+12 rmof = rmcs1+32 rmca = rmcs1+34 / rm02/3/5 disk driver. / low order address in dno, / high order in r0. rblk: mov r1,-(sp) mov dno,r1 .if CLSIZE-1 ashc $CLSHFT,r0 / multiply by CLSIZE .endif div $NSECT*NTRAK,r0 mov csr,r3 mov r0,rmca(r3) clr r0 div $NSECT,r0 swab r0 bis r1,r0 add $rmcs2,r3 mov unit,(r3) mov r0,-(r3) mov $buf,-(r3) mov $WC,-(r3) mov $read+go,-(r3) 1: tstb (r3) bge 1b mov (sp)+,r1 rts pc bootnm: bootlen = 4 / strlen(bootnm) unit: 0 csr: 0 end: inod = ..-512.-BSIZE / room for inod, buf, stack addr = inod+ADDROFF / first address in inod buf = inod+INOSIZ bno = buf+BSIZE dno = bno+2 t header / must be removed / options: none. all options of reading an alternate name or echoing to / the keyboard had to be removed to make room for the / code which understands the new directory structure on disc / constants: CLSIZE = 2. / physical disk blocks per logical block CLSHFT = 1. / shift to multiply by CLSIZE BSIZE = 512.*CLSIZE / logical block size INOSIZ = 64. / size of inode in bytes NDIRIN = 4. / number of direct inode addresses ADDROFF = 12. / offset of first addsys/mdec/hkuboot.s 644 0 12 12536 5763225755 7464 MAJOR = 4 / major # from bdevsw[] / RK06/RK07 bootstrap / / 1995/05/31 - The unit number needs to go in bits 3-5 of bootdev / because the partition number now goes into bits 0-2. / / disk boot program to load and transfer / to a unix entry. / for use with 1 KB byte blocks, CLSIZE is 2. / NDIRIN is the number of direct inode addresses (currently 4) / assembled size must be <= 512; if > 494, the 16-byte a.out header / must be removed RK07 = 1 / 1-> RK07, 0-> RK06 / options: none. all options of reading an alternate name or echoing to / the keyboard had to be removed to make room for the / code which understands the new directory structure on disc / constants: CLSIZE = 2. / physical disk blocks per logical block CLSHFT = 1. / shift to multiply by CLSIZE BSIZE = 512.*CLSIZE / logical block size INOSIZ = 64. / size of inode in bytes NDIRIN = 4. / number of direct inode addresses ADDROFF = 12. / offset of first address in inode INOPB = BSIZE\/INOSIZ / inodes per logical block INOFF = 31. / inode offset = (INOPB * (SUPERB+1)) - 1 PBSHFT = -4 / shift to divide by inodes per block WC = -256.*CLSIZE / word count / The boot options and device are placed in the last SZFLAGS bytes / at the end of core by the kernel for autobooting. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 CHECKWORD= 6 .. = ENDCORE-512.-SZFLAGS / save room for boot flags / entry is made by jsr pc,*$0 / so return can be rts pc / establish sp, copy / program up to end of core. nop / These two lines must be present or DEC br start / boot ROMs will refuse to run boot block! start: mov r0,unit mov r1,csr mov $..,sp mov sp,r1 clr r0 1: mov (r0)+,(r1)+ cmp r1,$end blo 1b jmp *$2f / On error, restart from here. restart: clr r0 / clear core to make things clean 2: clr (r0)+ cmp r0,sp blo 2b / initialize hk mov csr,r1 mov unit,r0 bis $clear,r0 mov r0,hkcs2(r1) mov $ack,hkcs1(r1) 0: tstb hkcs1(r1) bpl 0b / wait for acknowledge to complete mov $bootnm, r1 mov $2,r0 / ROOTINO jsr pc,iget clr r2 / offset again: jsr pc,readdir beq restart / error - restart mov 4(r0),r4 / dp->d_namlen cmp r4,$bootlen / if (bootlen == dp->d_namlen) bne again / nope, go try next entry mov r0,r3 add $6,r3 / r3 = dp->d_name mov r1,r5 / r5 = filename 9: cmpb (r3)+,(r5)+ bne again / no match - go read next entry sob r4,9b mov (r0),r0 / r0 = dp->d_ino jsr pc,iget / fetch boot's inode br loadfile / 'boot'- go read it / get the inode specified in r0 iget: add $INOFF,r0 mov r0,r5 ash $PBSHFT,r0 bic $!7777,r0 mov r0,dno clr r0 jsr pc,rblk bic $!17,r5 mov $INOSIZ,r0 mul r0,r5 add $buf,r5 mov $inod,r4 1: movb (r5)+,(r4)+ sob r0,1b rts pc readdir: bit $BSIZE-1,r2 bne 1f jsr pc,rmblk / read mapped block (bno) br err / end of file branch clr r2 / start at beginning of buf 1: mov $buf,r0 add r2,r0 / dp = buf+offset add buf+2(r2),r2 / dp += dp->d_reclen tst (r0) / dp->d_ino == 0? beq readdir / yes - go look at next rts pc / return with r0 = &dp->d_ino err: clr r0 / return with rts pc / dp = NULL loadfile: clr bno / start at block 0 of inode in 'inod' / read file into core until / a mapping error, (no disk address) clr r1 1: jsr pc,rmblk br 1f mov $buf,r2 2: mov (r2)+,(r1)+ cmp r2,$buf+BSIZE blo 2b br 1b / relocate core around / assembler header 1: clr r0 cmp (r0),$407 bne 2f 1: mov 20(r0),(r0)+ cmp r0,sp blo 1b / enter program and / restart if return 2: mov ENDCORE-BOOTOPTS, r4 mov unit,r3 ash $3,r3 / unit # in bits 3-5, partition # is 0 bis $MAJOR\<8.,r3 mov ENDCORE-CHECKWORD, r2 mov csr,r1 jsr pc,*$0 br restart / read a mapped block / offset in file is in bno. / skip if success, no skip if fail / the algorithm only handles a single / indirect block. that means that / files longer than NDIRIN+256 blocks (260kb) cannot / be loaded. rmblk: add $2,(sp) mov bno,r0 cmp r0,$NDIRIN blt 1f mov $NDIRIN,r0 1: ash $2,r0 mov addr+2(r0),dno mov addr(r0),r0 bne 1f tst dno beq 2f 1: jsr pc,rblk mov bno,r0 inc bno sub $NDIRIN,r0 blt 1f ash $2,r0 mov buf+2(r0),dno mov buf(r0),r0 bne rblk tst dno bne rblk 2: sub $2,(sp) 1: rts pc hkcs1 = 0 / control & status 1 hkda = 6 / desired track/sector address hkcs2 = 10 / control & status 2 hkca = 20 / desired cylinder .if RK07 / RK07 constants ack = 02003 / pack acknowledge clear = 040 / subsystem clear iocom = 2021 / read + go .endif .if RK07-1 / RK06 constants. ack = 03 / pack acknowledge clear = 040 / subsystem clear iocom = 021 / read + go .endif / rk06/07 disk driver / low order address in dno, / high order in r0. rblk: mov r1,-(sp) mov dno,r1 .if CLSIZE-1 ashc $CLSHFT,r0 / multiply by CLSIZE .endif div $22.,r0 / r0 = sectors r1 = blocks mov r1,-(sp) mov r0,r1 clr r0 div $3.,r0 / r0 = cylinder r1 = track bisb r1,1(sp) mov csr,r3 mov r0,hkca(r3) / cylinder wanted mov unit,hkcs2(r3) add $hkda,r3 mov (sp)+,(r3) / track & sector wanted mov $buf,-(r3) / bus address mov $WC,-(r3) / word count mov $iocom,-(r3) 1: tstb (r3) bge 1b / wait for iocom to complete mov (sp)+,r1 rts pc bootnm: bootlen = 4 / strlen(bootnm) unit: 0 csr: 0 end: inod = ..-512.-BSIZE / room for inod, buf, stack addr = inod+ADDROFF / first address in inod buf = inod+INOSIZ bno = buf+BSIZE dno = bno+2 efine mscp_lbn_h mscp_un.mscp_generic.Ms_lbn_h #define mscp_lbn_l mscp_un.mscp_generic.Ms_lbn_l #define mscp_dscptr mscp_un.mscp_generic.Ms_dscptr #define mscp_sfsys/mdec/Makefile 644 0 0 1525 5551450716 7206 # # Copyright (c) 1980, 1986 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)Makefile 1.1 (2.11BSD GTE) 4/8/94 # ALL= bruboot dvhpuboot hkuboot hpuboot rauboot rkuboot rluboot \ rm03uboot rm05uboot si51uboot si94uboot si95uboot all: ${ALL} ${ALL}: /lib/cpp -E $*.s | sed -e 's;^#;/;' | as -o a.out nm -u a.out size a.out strip a.out dd if=a.out of=b.out bs=16 skip=1 dd if=b.out of=$@ conv=sync bruboot: bruboot.s dvhpuboot: dvhpuboot.s hkuboot: hkuboot.s hpuboot: hpuboot.s rauboot: rauboot.s rkuboot: rkuboot.s rluboot: rluboot.s rm03uboot: rm03uboot.s rm05uboot: rm05uboot.s si51uboot: si51uboot.s si94uboot: si94uboot.s si95uboot: si95uboot.s clean: rm -f x.s a.out b.out ${ALL} install: cp *boot ${DESTDIR}/mdec inode in bytes NDIRIN = 4. / number of direct inode addresses ADDROFF = 12. / offset of first address in inode INOPB = BSIZE\/INOSIZ / inodes per logical block INOFFsys/mdec/dvhpuboot.s 644 0 0 11640 5763225745 7772 MAJOR = 10. / major # from bdevsw[] / Bootstrap for Diva Comp. IV controller (33 sectors) / / 1995/05/31 - The unit number needs to go in bits 3-5 of bootdev / because the partition number now goes into bits 0-2. / / disk boot program to load and transfer / to a unix entry. / for use with 1 KB byte blocks, CLSIZE is 2. / NDIRIN is the number of direct inode addresses (currently 4) / assembled size must be <= 512; if > 494, the 16-byte a.out header / must be removed / options: none. all options of reading an alternate name or echoing to / the keyboard had to be removed to make room for the / code which understands the new directory structure on disc / constants: CLSIZE = 2. / physical disk blocks per logical block CLSHFT = 1. / shift to multiply by CLSIZE BSIZE = 512.*CLSIZE / logical block size INOSIZ = 64. / size of inode in bytes NDIRIN = 4. / number of direct inode addresses ADDROFF = 12. / offset of first address in inode INOPB = BSIZE\/INOSIZ / inodes per logical block INOFF = 31. / inode offset = (INOPB * (SUPERB+1)) - 1 PBSHFT = -4 / shift to divide by inodes per block WC = -256.*CLSIZE / word count / The boot options and device are placed in the last SZFLAGS bytes / at the end of core by the kernel for autobooting. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 CHECKWORD= 6 .. = ENDCORE-512.-SZFLAGS / save room for boot flags / entry is made by jsr pc,*$0 / so return can be rts pc / establish sp, copy / program up to end of core. nop / These two lines must be present or DEC br start / boot ROMs will refuse to run boot block! start: mov r0,unit mov r1,csr mov $..,sp mov sp,r1 clr r0 1: mov (r0)+,(r1)+ cmp r1,$end blo 1b jmp *$2f / On error, restart from here. restart: / clear core to make things clean clr r0 2: clr (r0)+ cmp r0,sp blo 2b / initialize disk mov csr,r1 mov unit,hpcs2(r1) mov $preset+go,hpcs1(r1) mov $fmt22,hpof(r1) mov $bootnm, r1 mov $2,r0 / ROOTINO jsr pc,iget clr r2 / offset again: jsr pc,readdir beq restart / error - restart mov 4(r0),r4 / dp->d_namlen cmp r4,$bootlen / if (bootlen == dp->d_namlen) bne again / nope, go try next entry mov r0,r3 add $6,r3 / r3 = dp->d_name mov r1,r5 / r5 = filename 9: cmpb (r3)+,(r5)+ bne again / no match - go read next entry sob r4,9b mov (r0),r0 / r0 = dp->d_ino jsr pc,iget / fetch boot's inode br loadfile / 'boot'- go read it / get the inode specified in r0 iget: add $INOFF,r0 mov r0,r5 ash $PBSHFT,r0 bic $!7777,r0 mov r0,dno clr r0 jsr pc,rblk bic $!17,r5 mov $INOSIZ,r0 mul r0,r5 add $buf,r5 mov $inod,r4 1: movb (r5)+,(r4)+ sob r0,1b rts pc readdir: bit $BSIZE-1,r2 bne 1f jsr pc,rmblk / read mapped block (bno) br err / end of file branch clr r2 / start at beginning of buf 1: mov $buf,r0 add r2,r0 / dp = buf+offset add buf+2(r2),r2 / dp += dp->d_reclen tst (r0) / dp->d_ino == 0? beq readdir / yes - go look at next rts pc / return with r0 = &dp->d_ino err: clr r0 / return with rts pc / dp = NULL loadfile: clr bno / start at block 0 of inode in 'inod' / read file into core until / a mapping error, (no disk address) clr r1 1: jsr pc,rmblk br 1f mov $buf,r2 2: mov (r2)+,(r1)+ cmp r2,$buf+BSIZE blo 2b br 1b / relocate core around / assembler header 1: clr r0 cmp (r0),$407 bne 2f 1: mov 20(r0),(r0)+ cmp r0,sp blo 1b / enter program and / restart if return 2: mov ENDCORE-BOOTOPTS, r4 mov unit,r3 ash $3,r3 / unit # in bits 3-5, partition # is 0 bis $MAJOR\<8.,r3 mov ENDCORE-CHECKWORD, r2 mov csr,r1 jsr pc,*$0 br restart / read a mapped block / offset in file is in bno. / skip if success, no skip if fail / the algorithm only handles a single / indirect block. that means that / files longer than NDIRIN+256 blocks (260kb) cannot / be loaded. rmblk: add $2,(sp) mov bno,r0 cmp r0,$NDIRIN blt 1f mov $NDIRIN,r0 1: ash $2,r0 mov addr+2(r0),dno mov addr(r0),r0 bne 1f tst dno beq 2f 1: jsr pc,rblk mov bno,r0 inc bno sub $NDIRIN,r0 blt 1f ash $2,r0 mov buf+2(r0),dno mov buf(r0),r0 bne rblk tst dno bne rblk 2: sub $2,(sp) 1: rts pc read = 70 preset = 20 go = 1 fmt22 = 10000 hpcs1 = 0 / offset from base csr hpda = hpcs1+6 hpcs2 = hpcs1+10 hpds = hpcs1+12 hpof = hpcs1+32 hpca = hpcs1+34 / rp0456 disk driver. / low order address in dno, / high order in r0. rblk: mov r1,-(sp) mov dno,r1 .if CLSIZE-1 ashc $CLSHFT,r0 / multiply by CLSIZE .endif div $33.*19.,r0 mov csr,r3 mov r0,hpca(r3) clr r0 div $33.,r0 swab r0 bis r1,r0 add $hpcs2,r3 mov unit,(r3) mov r0,-(r3) mov $buf,-(r3) mov $WC,-(r3) mov $read+go,-(r3) 1: tstb (r3) bge 1b mov (sp)+,r1 rts pc bootnm: bootlen = 4 / strlen(bootnm) unit: 0 csr: 0 end: inod = ..-512.-BSIZE / room for inod, buf, stack addr = inod+ADDROFF / first address in inod buf = inod+INOSIZ bno = buf+BSIZE dno = bno+2 e loaded. rmblk: add $2,(sp) mov bno,r0 cmp r0,$NDIRIN blt 1f mov $NDIRIN,r0 1: ash $2,r0 sys/mdec/si94uboot.s 644 0 0 12014 5763226032 7603 MAJOR = 10. / major # from bdevsw[] / Fujitsu 160 on SI 9400 or Emulex SC01B Controller bootstrap / Actually just a small modification of the RM02/03/05 bootstrap / / 1995/05/31 - The unit number needs to go in bits 3-5 of bootdev / because the partition number now goes into bits 0-2. / / disk boot program to load and transfer / to a unix entry. / for use with 1 KB byte blocks, CLSIZE is 2. / NDIRIN is the number of direct inode addresses (currently 4) / assembled size must be <= 512; if > 494, the 16-byte a.out header / must be removed / options: none. all options of reading an alternate name or echoing to / the keyboard had to be removed to make room for the / code which understands the new directory structure on disc / constants: CLSIZE = 2. / physical disk blocks per logical block CLSHFT = 1. / shift to multiply by CLSIZE BSIZE = 512.*CLSIZE / logical block size INOSIZ = 64. / size of inode in bytes NDIRIN = 4. / number of direct inode addresses ADDROFF = 12. / offset of first address in inode INOPB = BSIZE\/INOSIZ / inodes per logical block INOFF = 31. / inode offset = (INOPB * (SUPERB+1)) - 1 PBSHFT = -4 / shift to divide by inodes per block WC = -256.*CLSIZE / word count / The boot options and device are placed in the last SZFLAGS bytes / at the end of core by the kernel for autobooting. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 CHECKWORD= 6 .. = ENDCORE-512.-SZFLAGS / save room for boot flags / entry is made by jsr pc,*$0 / so return can be rts pc / establish sp, copy / program up to end of core. nop / These two lines must be present or DEC br start / boot ROMs will refuse to run boot block! start: mov r0,unit mov r1,csr mov $..,sp mov sp,r1 clr r0 1: mov (r0)+,(r1)+ cmp r1,$end blo 1b jmp *$2f / On error, restart from here. restart: clr r0 / clear core to make things clean 2: clr (r0)+ cmp r0,sp blo 2b / initialize disk mov csr,r1 mov unit,rmcs2(r1) mov $preset+go,rmcs1(r1) mov $fmt22,rmof(r1) mov $bootnm, r1 mov $2,r0 / ROOTINO jsr pc,iget clr r2 / offset again: jsr pc,readdir beq restart / error - restart mov 4(r0),r4 / dp->d_namlen cmp r4,$bootlen / if (bootlen == dp->d_namlen) bne again / nope, go try next entry mov r0,r3 add $6,r3 / r3 = dp->d_name mov r1,r5 / r5 = filename 9: cmpb (r3)+,(r5)+ bne again / no match - go read next entry sob r4,9b mov (r0),r0 / r0 = dp->d_ino jsr pc,iget / fetch boot's inode br loadfile / 'boot'- go read it / get the inode specified in r0 iget: add $INOFF,r0 mov r0,r5 ash $PBSHFT,r0 bic $!7777,r0 mov r0,dno clr r0 jsr pc,rblk bic $!17,r5 mov $INOSIZ,r0 mul r0,r5 add $buf,r5 mov $inod,r4 1: movb (r5)+,(r4)+ sob r0,1b rts pc readdir: bit $BSIZE-1,r2 bne 1f jsr pc,rmblk / read mapped block (bno) br err / end of file branch clr r2 / start at beginning of buf 1: mov $buf,r0 add r2,r0 / dp = buf+offset add buf+2(r2),r2 / dp += dp->d_reclen tst (r0) / dp->d_ino == 0? beq readdir / yes - go look at next rts pc / return with r0 = &dp->d_ino err: clr r0 / return with rts pc / dp = NULL loadfile: clr bno / start at block 0 of inode in 'inod' / read file into core until / a mapping error, (no disk address) clr r1 1: jsr pc,rmblk br 1f mov $buf,r2 2: mov (r2)+,(r1)+ cmp r2,$buf+BSIZE blo 2b br 1b / relocate core around / assembler header 1: clr r0 cmp (r0),$407 bne 2f 1: mov 20(r0),(r0)+ cmp r0,sp blo 1b / enter program and / restart if return 2: mov ENDCORE-BOOTOPTS, r4 mov unit,r3 ash $3,r3 / unit # in bits 3-5, partition # is 0 bis $MAJOR\<8.,r3 mov ENDCORE-CHECKWORD, r2 mov csr,r1 jsr pc,*$0 br restart / read a mapped block / offset in file is in bno. / skip if success, no skip if fail / the algorithm only handles a single / indirect block. that means that / files longer than NDIRIN+256 blocks (260kb) cannot / be loaded. rmblk: add $2,(sp) mov bno,r0 cmp r0,$NDIRIN blt 1f mov $NDIRIN,r0 1: ash $2,r0 mov addr+2(r0),dno mov addr(r0),r0 bne 1f tst dno beq 2f 1: jsr pc,rblk mov bno,r0 inc bno sub $NDIRIN,r0 blt 1f ash $2,r0 mov buf+2(r0),dno mov buf(r0),r0 bne rblk tst dno bne rblk 2: sub $2,(sp) 1: rts pc read = 70 preset = 20 go = 1 fmt22 = 10000 NSECT = 32. NTRAK = 10. / SI 9400 with Fujitsu 160 rmcs1 = 0 rmda = rmcs1+6 rmcs2 = rmcs1+10 rmds = rmcs1+12 rmof = rmcs1+32 rmca = rmcs1+34 / rm02/3/5 disk driver. / low order address in dno, / high order in r0. rblk: mov r1,-(sp) mov dno,r1 .if CLSIZE-1 ashc $CLSHFT,r0 / multiply by CLSIZE .endif div $NSECT*NTRAK,r0 mov csr,r3 mov r0,rmca(r3) clr r0 div $NSECT,r0 swab r0 bis r1,r0 add $rmcs2,r3 mov unit,(r3) mov r0,-(r3) mov $buf,-(r3) mov $WC,-(r3) mov $read+go,-(r3) 1: tstb (r3) bge 1b mov (sp)+,r1 rts pc bootnm: bootlen = 4 / strlen(bootnm) unit: 0 csr: 0 end: inod = ..-512.-BSIZE / room for inod, buf, stack addr = inod+ADDROFF / first address in inod buf = inod+INOSIZ bno = buf+BSIZE dno = bno+2 ress mov $WC,-(r3) / word count mov $iocom,-(r3) 1: tstb (r3) bge 1b / wait for iocom to complete mov (sp)+,r1 rts pc bootnm: bootlen = 4 / strlen(bootnm) unit: 0 csr: 0 end: inod = ..-512.-BSIZE / room for inod, buf, stack addr = inod+ADDROFF / first address in inod buf = inod+INOSIZ bno = buf+BSIZE dno = bno+2 efine mscp_lbn_h mscp_un.mscp_generic.Ms_lbn_h #define mscp_lbn_l mscp_un.mscp_generic.Ms_lbn_l #define mscp_dscptr mscp_un.mscp_generic.Ms_dscptr #define mscp_sfsys/mdec/rauboot.s 644 0 12 16256 5763225771 7465 MAJOR = 5 / major # from bdevsw[] / RA bootstrap. / / 1995/05/31 - The unit number needs to go in bits 3-5 of bootdev / because the partition number now goes into bits 0-2. / / disk boot program to load and transfer to a unix entry. / for use with 1 KB byte blocks, CLSIZE is 2. / NDIRIN is the number of direct inode addresses (currently 4) / / Note: this is a complex boot, but then MSCP is complex!!!! / / assembled size must be <= 512 / a.out header must be removed from boot block! MSCPSIZE = 64. / One MSCP command packet is 64bytes long (need 2) RASEMAP = 140000 / RA controller owner semaphore RAERR = 100000 / error bit RASTEP1 = 04000 / step1 has started RAGO = 01 / start operation, after init RASTCON = 4 / Setup controller info RAONLIN = 11 / Put unit on line RAREAD = 41 / Read command code RAWRITE = 42 / Write command code RAEND = 200 / End command code RACMDI = 4. / Command Interrupt RARSPI = 6. / Response Interrupt RARING = 8. / Ring base RARSPL = 8. / Response Command low RARSPH = 10. / Response Command high RACMDL = 12. / Command to controller low RACMDH = 14. / Command to controller high RARSPS = 16. / Response packet length (location) RARSPREF = 20. / Response reference number RACMDS = 80. / Command packet length (location) RACMDREF = 84. / Command reference number RAUNIT = 88. / Command packet unit RAOPCODE = 92. / Command opcode offset RABYTECT = 96. / Transfer byte count RABUFL = 100. / Buffer location (16 bit addressing only) RABUFH = 102. / Buffer location high 6 bits RALBNL = 112. / Logical block number low RALBNH = 114. / Logical block number high / options: none. all options of reading an alternate name or echoing to / the keyboard had to be removed to make room for the / code which understands the new directory structure on disc / also, this is the single largest boot around to begin with. / constants: / CLSIZE = 2. / physical disk blocks per logical block CLSHFT = 1. / shift to multiply by CLSIZE BSIZE = 512.*CLSIZE / logical block size INOSIZ = 64. / size of inode in bytes NDIRIN = 4. / number of direct inode addresses ADDROFF = 12. / offset of first address in inode INOPB = BSIZE\/INOSIZ / inodes per logical block INOFF = 31. / inode offset = (INOPB * (SUPERB+1)) - 1 PBSHFT = -4 / shift to divide by inodes per block / / The boot options and device are placed in the last SZFLAGS bytes / at the end of core by the kernel for autobooting. / ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 CHECKWORD= 6 .. = ENDCORE-512.-SZFLAGS / save room for boot flags / entry is made by jsr pc,*$0 / so return can be rts pc / establish sp, copy / program up to end of core. nop / These two lines must be present or DEC br start / boot ROMs will refuse to run boot block! start: mov r0,unit / Save unit number passed by ROMs(and kernel) mov r1,raip / save csr passed by ROMs (and kernel) mov $..,sp mov sp,r1 clr r0 1: mov (r0)+,(r1)+ cmp r1,$end blo 1b jmp *$2f / On error, restart from here. restart: clr r0 / clear core to make things clean 2: clr (r0)+ cmp r0,sp blo 2b / / RA initialize controller / mov $RASTEP1,r0 mov raip,r1 clr (r1)+ / go through controller init seq. mov $icons,r2 1: bit r0,(r1) beq 1b mov (r2)+,(r1) asl r0 bpl 1b mov $ra+RARSPREF,*$ra+RARSPL / set controller characteristics mov $ra+RACMDREF,*$ra+RACMDL mov $RASTCON,r0 jsr pc,racmd mov unit,*$ra+RAUNIT / bring boot unit online mov $RAONLIN,r0 jsr pc,racmd mov $bootnm, r1 mov $2,r0 / ROOTINO jsr pc,iget clr r2 / offset again: jsr pc,readdir beq restart / error - restart mov 4(r0),r4 / dp->d_namlen cmp r4,$bootlen / if (bootlen == dp->d_namlen) bne again / nope, go try next entry mov r0,r3 add $6,r3 / r3 = dp->d_name mov r1,r5 / r5 = filename 9: cmpb (r3)+,(r5)+ bne again / no match - go read next entry sob r4,9b mov (r0),r0 / r0 = dp->d_ino jsr pc,iget / fetch boot's inode br loadfile / 'boot'- go read it / get the inode specified in r0 iget: add $INOFF,r0 mov r0,r5 ash $PBSHFT,r0 bic $!7777,r0 mov r0,dno clr r0 jsr pc,rblk bic $!17,r5 mov $INOSIZ,r0 mul r0,r5 add $buf,r5 mov $inod,r4 1: movb (r5)+,(r4)+ sob r0,1b rts pc readdir: bit $BSIZE-1,r2 bne 1f jsr pc,rmblk / read mapped block (bno) br err / end of file branch clr r2 / start at beginning of buf 1: mov $buf,r0 add r2,r0 / dp = buf+offset add buf+2(r2),r2 / dp += dp->d_reclen tst (r0) / dp->d_ino == 0? beq readdir / yes - go look at next rts pc / return with r0 = &dp->d_ino err: clr r0 / return with rts pc / dp = NULL loadfile: clr bno / start at block 0 of inode in 'inod' / read file into core until / a mapping error, (no disk address) clr r1 1: jsr pc,rmblk br 1f mov $buf,r2 2: mov (r2)+,(r1)+ cmp r2,$buf+BSIZE blo 2b br 1b / relocate core around / assembler header 1: clr r0 cmp (r0),$407 bne 2f 1: mov 20(r0),(r0)+ cmp r0,sp blo 1b / enter program and / restart if return 2: mov ENDCORE-BOOTOPTS, r4 mov unit, r3 ash $3,r3 / unit # in bits 3-5, partition # is 0 bis $MAJOR\<8.,r3 mov ENDCORE-CHECKWORD, r2 mov raip,r1 jsr pc,*$0 jmp restart / read a mapped block / offset in file is in bno. / skip if success, no skip if fail / the algorithm only handles a single / indirect block. that means that / files longer than NDIRIN+256 blocks (260kb) cannot / be loaded. rmblk: add $2,(sp) mov bno,r0 cmp r0,$NDIRIN blt 1f mov $NDIRIN,r0 1: ash $2,r0 mov addr+2(r0),dno mov addr(r0),r0 bne 1f tst dno beq 2f 1: jsr pc,rblk mov bno,r0 inc bno sub $NDIRIN,r0 blt 1f ash $2,r0 mov buf+2(r0),dno mov buf(r0),r0 bne rblk tst dno bne rblk 2: sub $2,(sp) 1: rts pc read = 4 go = 1 / / RA MSCP read block routine. This is very primative, so don't expect / too much from it. Note that MSCP requires large data communications / space at end of ADDROFF for command area. / N.B. This MUST preceed racmd - a "jsr/rts" sequence is saved by / falling thru! / / dno -> 1k block # to load (low half) / buf -> address of buffer to put block into / BSIZE -> size of block to read / / Tim Tucker, Gould Electronics, August 23rd 1985 / rblk: mov dno,r0 asl r0 mov r0,*$ra+RALBNL / Put in disk block number mov $BSIZE,*$ra+RABYTECT / Put in byte to transfer mov $buf,*$ra+RABUFL / Put in disk buffer location mov $RAREAD,r0 / / perform MSCP command -> response poll version / racmd: movb r0,*$ra+RAOPCODE / fill in command type mov $MSCPSIZE,*$ra+RARSPS / give controller struct sizes mov $MSCPSIZE,*$ra+RACMDS mov $RASEMAP,*$ra+RARSPH / set mscp semaphores mov $RASEMAP,*$ra+RACMDH mov *raip,r0 / tap controllers shoulder mov $ra+RACMDI,r0 1: tst (r0) beq 1b / Wait till command read clr (r0)+ / Tell controller we saw it, ok. 2: tst (r0) beq 2b / Wait till response written clr (r0) / Tell controller we go it rts pc icons: RAERR ra+RARING 0 RAGO bootnm: bootlen = 4 / strlen(bootnm) unit: 0 / unit number from ROMs raip: 0 / csr address from ROMs end: inod = ..-512.-BSIZE / room for inod, buf, stack addr = inod+ADDROFF / first address in inod buf = inod+INOSIZ bno = buf+BSIZE dno = bno+2 ra = dno + 2 / ra mscp communications area (BIG!) ror */ #define M_FM_BUSADDR 1 /* Host memory access error */ #define M_FM_TAPETRN 5 /* Tape transfer error */ #define M_FM_STIERR 6 /* STI communication or command failure */ #define M_FM_STIDEL 7 /* STI drive error log */ #define M_FM_STIFEL 010 /* STI formatter error log */ /* * Error Log message flags */ #define M_LF_SUCC 0200 sys/mdec/rm03uboot.s 644 0 0 11753 5763226011 7602 MAJOR = 10. / major # from bdevsw[] / RM02/03/05 bootstrap / / 1995/05/31 - The unit number needs to go in bits 3-5 of bootdev / because the partition number now goes into bits 0-2. / / disk boot program to load and transfer / to a unix entry. / for use with 1 KB byte blocks, CLSIZE is 2. / NDIRIN is the number of direct inode addresses (currently 4) / assembled size must be <= 512; if > 494, the 16-byte a.out header / must be removed RM05 = 0 / 0-> RM02/03, 1-> RM05 / options: none. all options of reading an alternate name or echoing to / the keyboard had to be removed to make room for the / code which understands the new directory structure on disc / constants: CLSIZE = 2. / physical disk blocks per logical block CLSHFT = 1. / shift to multiply by CLSIZE BSIZE = 512.*CLSIZE / logical block size INOSIZ = 64. / size of inode in bytes NDIRIN = 4. / number of direct inode addresses ADDROFF = 12. / offset of first address in inode INOPB = BSIZE\/INOSIZ / inodes per logical block INOFF = 31. / inode offset = (INOPB * (SUPERB+1)) - 1 PBSHFT = -4 / shift to divide by inodes per block WC = -256.*CLSIZE / word count / The boot options and device are placed in the last SZFLAGS bytes / at the end of core by the kernel for autobooting. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 CHECKWORD= 6 .. = ENDCORE-512.-SZFLAGS / save room for boot flags / entry is made by jsr pc,*$0 / so return can be rts pc / establish sp, copy / program up to end of core. nop / These two lines must be present or DEC br start / boot ROMs will refuse to run boot block! start: mov r0,unit mov r1,csr mov $..,sp mov sp,r1 clr r0 1: mov (r0)+,(r1)+ cmp r1,$end blo 1b jmp *$2f / On error, restart from here. restart: clr r0 / clear core to make things clean 2: clr (r0)+ cmp r0,sp blo 2b / initialize disk mov csr,r1 mov unit,rmcs2(r1) mov $preset+go,rmcs1(r1) mov $fmt22,rmof(r1) mov $bootnm, r1 mov $2,r0 / ROOTINO jsr pc,iget clr r2 / offset again: jsr pc,readdir beq restart / error - restart mov 4(r0),r4 / dp->d_namlen cmp r4,$bootlen / if (bootlen == dp->d_namlen) bne again / nope, go try next entry mov r0,r3 add $6,r3 / r3 = dp->d_name mov r1,r5 / r5 = filename 9: cmpb (r3)+,(r5)+ bne again / no match - go read next entry sob r4,9b mov (r0),r0 / r0 = dp->d_ino jsr pc,iget / fetch boot's inode br loadfile / 'boot'- go read it / get the inode specified in r0 iget: add $INOFF,r0 mov r0,r5 ash $PBSHFT,r0 bic $!7777,r0 mov r0,dno clr r0 jsr pc,rblk bic $!17,r5 mov $INOSIZ,r0 mul r0,r5 add $buf,r5 mov $inod,r4 1: movb (r5)+,(r4)+ sob r0,1b rts pc readdir: bit $BSIZE-1,r2 bne 1f jsr pc,rmblk / read mapped block (bno) br err / end of file branch clr r2 / start at beginning of buf 1: mov $buf,r0 add r2,r0 / dp = buf+offset add buf+2(r2),r2 / dp += dp->d_reclen tst (r0) / dp->d_ino == 0? beq readdir / yes - go look at next rts pc / return with r0 = &dp->d_ino err: clr r0 / return with rts pc / dp = NULL loadfile: clr bno / start at block 0 of inode in 'inod' / read file into core until / a mapping error, (no disk address) clr r1 1: jsr pc,rmblk br 1f mov $buf,r2 2: mov (r2)+,(r1)+ cmp r2,$buf+BSIZE blo 2b br 1b / relocate core around / assembler header 1: clr r0 cmp (r0),$407 bne 2f 1: mov 20(r0),(r0)+ cmp r0,sp blo 1b / enter program and / restart if return 2: mov ENDCORE-BOOTOPTS, r4 mov unit,r3 ash $3,r3 / unit # in bits 3-5, partition # is 0 bis $MAJOR\<8.,r3 mov ENDCORE-CHECKWORD, r2 mov csr,r1 jsr pc,*$0 br restart / read a mapped block / offset in file is in bno. / skip if success, no skip if fail / the algorithm only handles a single / indirect block. that means that / files longer than NDIRIN+256 blocks (260kb) cannot / be loaded. rmblk: add $2,(sp) mov bno,r0 cmp r0,$NDIRIN blt 1f mov $NDIRIN,r0 1: ash $2,r0 mov addr+2(r0),dno mov addr(r0),r0 bne 1f tst dno beq 2f 1: jsr pc,rblk mov bno,r0 inc bno sub $NDIRIN,r0 blt 1f ash $2,r0 mov buf+2(r0),dno mov buf(r0),r0 bne rblk tst dno bne rblk 2: sub $2,(sp) 1: rts pc read = 70 preset = 20 go = 1 fmt22 = 10000 NSECT = 32. .if RM05 NTRAK = 19. / RM05 .endif .if RM05-1 NTRAK = 5. / RM02/03 .endif rmcs1 = 0 rmda = rmcs1+6 rmcs2 = rmcs1+10 rmds = rmcs1+12 rmof = rmcs1+32 rmca = rmcs1+34 / rm02/3/5 disk driver. / low order address in dno, / high order in r0. rblk: mov r1,-(sp) mov dno,r1 .if CLSIZE-1 ashc $CLSHFT,r0 / multiply by CLSIZE .endif div $NSECT*NTRAK,r0 mov csr,r3 mov r0,rmca(r3) clr r0 div $NSECT,r0 swab r0 bis r1,r0 add $rmcs2,r3 mov unit,(r3) mov r0,-(r3) mov $buf,-(r3) mov $WC,-(r3) mov $read+go,-(r3) 1: tstb (r3) bge 1b mov (sp)+,r1 rts pc bootnm: bootlen = 4 / strlen(bootnm) unit: 0 csr: 0 end: inod = ..-512.-BSIZE / room for inod, buf, stack addr = inod+ADDROFF / first address in inod buf = inod+INOSIZ bno = buf+BSIZE dno = bno+2 AONLIN,r0 jsr pc,racsys/mdec/si95uboot.s 644 0 0 13163 5763226040 7611 MAJOR = 9. / major # from bdevsw[] / CDC 9766 disk on SI 9500 Controller bootstrap / / 1995/05/31 - The unit number needs to go in bits 3-5 of bootdev / because the partition number now goes into bits 0-2. / / disk boot program to load and transfer / to a unix entry. / for use with 1 KB byte blocks, CLSIZE is 2. / NDIRIN is the number of direct inode addresses (currently 4) / assembled size must be <= 512; if > 494, the 16-byte a.out header / must be removed / options: none. all options of reading an alternate name or echoing to / the keyboard had to be removed to make room for the / code which understands the new directory structure on disc shared = 1 / 9500 shared computer option support / constants: CLSIZE = 2. / physical disk blocks per logical block CLSHFT = 1. / shift to multiply by CLSIZE BSIZE = 512.*CLSIZE / logical block size INOSIZ = 64. / size of inode in bytes NDIRIN = 4. / number of direct inode addresses ADDROFF = 12. / offset of first address in inode INOPB = BSIZE\/INOSIZ / inodes per logical block INOFF = 31. / inode offset = (INOPB * (SUPERB+1)) - 1 PBSHFT = -4 / shift to divide by inodes per block WC = 256.*CLSIZE / word count / The boot options and device are placed in the last SZFLAGS bytes / at the end of core by the kernel for autobooting. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 CHECKWORD= 6 .. = ENDCORE-512.-SZFLAGS / save room for boot flags / entry is made by jsr pc,*$0 / so return can be rts pc / establish sp, copy / program up to end of core. nop / These two lines must be present or DEC br start / boot ROMs will refuse to run boot block! start: mov r0,unit mov r1,csr mov $..,sp mov sp,r1 clr r0 1: mov (r0)+,(r1)+ cmp r1,$end blo 1b jmp *$2f / On error, restart from here. restart: clr r0 / clear core to make things clean 2: clr (r0)+ cmp r0,sp blo 2b / initialize disk mov csr,r1 mov $reset,sicnr(r1) mov $bootnm, r1 mov $2,r0 / ROOTINO jsr pc,iget clr r2 / offset again: jsr pc,readdir beq restart / error - restart mov 4(r0),r4 / dp->d_namlen cmp r4,$bootlen / if (bootlen == dp->d_namlen) bne again / nope, go try next entry mov r0,r3 add $6,r3 / r3 = dp->d_name mov r1,r5 / r5 = filename 9: cmpb (r3)+,(r5)+ bne again / no match - go read next entry sob r4,9b mov (r0),r0 / r0 = dp->d_ino jsr pc,iget / fetch boot's inode br loadfile / 'boot'- go read it / get the inode specified in r0 iget: add $INOFF,r0 mov r0,r5 ash $PBSHFT,r0 bic $!7777,r0 mov r0,dno clr r0 jsr pc,rblk bic $!17,r5 mov $INOSIZ,r0 mul r0,r5 add $buf,r5 mov $inod,r4 1: movb (r5)+,(r4)+ sob r0,1b rts pc readdir: bit $BSIZE-1,r2 bne 1f jsr pc,rmblk / read mapped block (bno) br err / end of file branch clr r2 / start at beginning of buf 1: mov $buf,r0 add r2,r0 / dp = buf+offset add buf+2(r2),r2 / dp += dp->d_reclen tst (r0) / dp->d_ino == 0? beq readdir / yes - go look at next rts pc / return with r0 = &dp->d_ino err: clr r0 / return with rts pc / dp = NULL loadfile: clr bno / start at block 0 of inode in 'inod' / read file into core until / a mapping error, (no disk address) clr r1 1: jsr pc,rmblk br 1f mov $buf,r2 2: mov (r2)+,(r1)+ cmp r2,$buf+BSIZE blo 2b br 1b / relocate core around / assembler header 1: clr r0 cmp (r0),$407 bne 2f 1: mov 20(r0),(r0)+ cmp r0,sp blo 1b / enter program and / restart if return 2: mov ENDCORE-BOOTOPTS, r4 mov unit,r3 ash $3,r3 / unit # in bits 3-5, partition # is 0 bis $MAJOR\<8.,r3 mov ENDCORE-CHECKWORD, r2 mov csr,r1 jsr pc,*$0 br restart / read a mapped block / offset in file is in bno. / skip if success, no skip if fail / the algorithm only handles a single / indirect block. that means that / files longer than NDIRIN+256 blocks (260kb) cannot / be loaded. rmblk: add $2,(sp) mov bno,r0 cmp r0,$NDIRIN blt 1f mov $NDIRIN,r0 1: ash $2,r0 mov addr+2(r0),dno mov addr(r0),r0 bne 1f tst dno beq 2f 1: jsr pc,rblk mov bno,r0 inc bno sub $NDIRIN,r0 blt 1f ash $2,r0 mov buf+2(r0),dno mov buf(r0),r0 bne rblk tst dno bne rblk 2: sub $2,(sp) 1: rts pc read = 4 reset = 0 go = 1 NSECT = 32. NTRAK = 19. / 9766 sicnr = 0 siwcr = sicnr+2 sipcr = sicnr+4 sihsr = sicnr+6 simar = sicnr+10 sierr = sicnr+12 siscr = sicnr+24 / si 9500/9766 disk driver. / low order address in dno, / high order in r0. rblk: mov r1,-(sp) mov dno,r1 .if CLSIZE-1 ashc $CLSHFT,r0 / multiply by CLSIZE .endif div $NSECT*NTRAK,r0 mov csr,r3 .if shared mov r0,-(sp) / push onto stack mov siscr(r3),r0 / load shared computer register bit $200,r0 / see if grant bit set bne 1f / if so, is dual ported mov sierr(r3),r0 / move error register to r0 bic $037777,r0 / clear all but top two bits cmp $140000,r0 / see if contention error bne 2f / if not, not dual ported 1: bit $200,siscr(r3) / test for grant bne 2f / if set, go do command clr sicnr(r3) / issue logic master clear mov $1,siscr(r3) / request grant br 1b / loop until grant 2: mov (sp)+,r0 / pop off stack .endif mov r0,sipcr(r3) / port and cylinder mov unit,r0 ash $10.,r0 add r0,sipcr(r3) / add in unit number clr r0 div $NSECT,r0 ash $5.,r0 bis r0,r1 mov r1,sihsr(r3) / head and sector mov $buf,simar(r3) / buffer address mov $WC,siwcr(r3) / word count mov $read+go,sicnr(r3) / read it 1: tstb sicnr(r3) bge 1b mov (sp)+,r1 rts pc bootnm: bootlen = 4 / strlen(bootnm) unit: 0 csr: 0 end: inod = ..-512.-BSIZE / room for inod, buf, stack addr = inod+ADDROFF / first address in inod buf = inod+INOSIZ bno = buf+BSIZE dno = bno+2 f(r0),r0 bne rblk tst dno bne rblk 2: sub $2,(sp) 1: rts pc read = 4 go = 1 / / RA MSCP read block routine. This is very primative, so don't expect / too much from it. Note that MSCP requires large data communications / space at end of ADDROFF for command area. / N.B. This MUST preceed racmd - a "jsr/rts" sequence is saved by / falling thru! / / dno -> 1k block # to load (low half) / sys/mdec/bruboot.s 640 0 0 12723 5763225740 7426 MAJOR = 11. / major # from bdevsw[] / BR bootstrap. supports the 32 sec/trk, 19 trk/cyl EATON 1537/1711 / Controller and 1538A/B/C/D drive. / / 1995/05/31 - The unit number needs to go in bits 3-5 of bootdev / because the partition number now goes into bits 0-2. / / disk boot program to load and transfer / to a unix entry. / for use with 1 KB byte blocks, CLSIZE is 2. / NDIRIN is the number of direct inode addresses (currently 4) / assembled size must be <= 512; if > 494, the 16-byte a.out header / must be removed / options: none. all options of reading an alternate name or echoing to / the keyboard had to be removed to make room for the / code which understands the new directory structure on disc / constants: CLSIZE = 2. / physical disk blocks per logical block CLSHFT = 1. / shift to multiply by CLSIZE BSIZE = 512.*CLSIZE / logical block size INOSIZ = 64. / size of inode in bytes NDIRIN = 4. / number of direct inode addresses ADDROFF = 12. / offset of first address in inode INOPB = BSIZE\/INOSIZ / inodes per logical block INOFF = 31. / inode offset = (INOPB * (SUPERB+1)) - 1 PBSHFT = -4 / shift to divide by inodes per block WC = -256.*CLSIZE / word count / The boot options and device are placed in the last SZFLAGS bytes / at the end of core by the kernel for autobooting. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 CHECKWORD= 6 .. = ENDCORE-512.-SZFLAGS / save room for boot flags / entry is made by jsr pc,*$0 / so return can be rts pc / establish sp, copy / program up to end of core. nop / These two lines must be present or DEC br start / boot ROMs will refuse to run boot block! start: clr r0 / XXX - for Rome 11/70, boot card doesn't work mov $176714,r1 / XXX - for Rome 11/70, boot card doesn't work movb r0,unit+1 / save the unit in high byte (for brcs) mov r1,csr / and csr from the ROMs (not base addr!) mov $..,sp mov sp,r1 clr r0 1: mov (r0)+,(r1)+ cmp r1,$end blo 1b jmp *$2f / On error, restart from here. restart: clr r0 / clear core to make things clean 2: clr (r0)+ cmp r0,sp blo 2b / initialize controller mov csr,r1 mov unit,brcs(r1) / clr addr extension bits, select unit mov $32.,r0 / default # of sec/track bit $2400,brae(r1) / is this a 22 sec/track drive beq 9f mov $22.,r0 9: mov $19.,r5 / default # of tracks/cyl bit $1400,brae(r1) / is this a 5 tr/cy drive? beq 9f / no - br mov $5,r5 9: mov r0,sectors mul r0,r5 / sectors/cyl mov r5,seccyl mov $bootnm, r1 mov $2,r0 / ROOTINO jsr pc,iget clr r2 / offset again: jsr pc,readdir beq restart / error - restart mov 4(r0),r4 / dp->d_namlen cmp r4,$bootlen / if (bootlen == dp->d_namlen) bne again / nope, go try next entry mov r0,r3 add $6,r3 / r3 = dp->d_name mov r1,r5 / r5 = filename 9: cmpb (r3)+,(r5)+ bne again / no match - go read next entry sob r4,9b mov (r0),r0 / r0 = dp->d_ino jsr pc,iget / fetch boot's inode br loadfile / 'boot'- go read it / get the inode specified in r0 iget: add $INOFF,r0 mov r0,r5 ash $PBSHFT,r0 bic $!7777,r0 mov r0,dno clr r0 jsr pc,rblk bic $!17,r5 mov $INOSIZ,r0 mul r0,r5 add $buf,r5 mov $inod,r4 1: movb (r5)+,(r4)+ sob r0,1b rts pc readdir: bit $BSIZE-1,r2 bne 1f jsr pc,rmblk / read mapped block (bno) br err / end of file branch clr r2 / start at beginning of buf 1: mov $buf,r0 add r2,r0 / dp = buf+offset add buf+2(r2),r2 / dp += dp->d_reclen tst (r0) / dp->d_ino == 0? beq readdir / yes - go look at next rts pc / return with r0 = &dp->d_ino err: clr r0 / return with rts pc / dp = NULL loadfile: clr bno / start at block 0 of inode in 'inod' / read file into core until / a mapping error, (no disk address) clr r1 1: jsr pc,rmblk br 1f mov $buf,r2 2: mov (r2)+,(r1)+ cmp r2,$buf+BSIZE blo 2b br 1b / relocate core around / assembler header 1: clr r0 cmp (r0),$407 bne 2f 1: mov 20(r0),(r0)+ cmp r0,sp blo 1b / enter program and / restart if return 2: mov ENDCORE-BOOTOPTS, r4 movb unit+1,r3 ash $3,r3 / unit # in bits 3-5, partition # is 0 bis $MAJOR\<8.,r3 mov ENDCORE-CHECKWORD, r2 mov csr,r1 jsr pc,*$0 jmp restart / read a mapped block / offset in file is in bno. / skip if success, no skip if fail / the algorithm only handles a single / indirect block. that means that / files longer than NDIRIN+256 blocks (260kb) cannot / be loaded. rmblk: add $2,(sp) mov bno,r0 cmp r0,$NDIRIN blt 1f mov $NDIRIN,r0 1: ash $2,r0 mov addr+2(r0),dno mov addr(r0),r0 bne 1f tst dno beq 2f 1: jsr pc,rblk mov bno,r0 inc bno sub $NDIRIN,r0 blt 1f ash $2,r0 mov buf+2(r0),dno mov buf(r0),r0 bne rblk tst dno bne rblk 2: sub $2,(sp) 1: rts pc read = 4 go = 1 brds = -4 brer = -2 brcs = 0 / offset from base csr passed by ROMs brwc = 2 brba = 4 brca = 6 brda = 10 brae = 12 / br disk driver. / low order address in dno, / high order in r0. rblk: mov r1,-(sp) mov dno,r1 .if CLSIZE-1 ashc $CLSHFT,r0 / multiply by CLSIZE .endif div seccyl,r0 mov csr,r3 mov r0,brca(r3) clr r0 div sectors,r0 swab r0 bis r1,r0 mov r0,brda(r3) mov $buf,brba(r3) mov $WC,brwc(r3) mov unit,r0 bis $read+go,r0 mov r0,(r3) / brcs 1: tstb (r3) / brcs bge 1b mov (sp)+,r1 rts pc bootnm: bootlen = 4 / strlen(bootnm) unit: 0 csr: 0 seccyl: 0 sectors: 0 end: inod = ..-512.-BSIZE / room for inod, buf, stack addr = inod+ADDROFF / first address in inod buf = inod+INOSIZ bno = buf+BSIZE dno = bno+2 it: 0 csr: 0 end: inod = ..-512.-BSIZE / rosys/mdec/boilerplate 644 0 0 2241 5157241254 7764 mov $bootnm, r1 mov $2,r0 / ROOTINO jsr pc,iget clr r2 / offset again: jsr pc,readdir beq restart / error - restart mov 4(r0),r4 / dp->d_namlen cmp r4,$bootlen / if (len == dp->d_namlen) bne again / nope, go try next entry mov r0,r3 add $6,r3 / r3 = dp->d_name mov r1,r5 / r5 = filename 9: cmpb (r3)+,(r5)+ bne again / no match - go read next entry sob r4,9b mov (r0),r0 / r0 = dp->d_ino jsr pc,iget / fetch boot's inode br loadfile / 'boot'- go read it / get the inode specified in r0 iget: add $INOFF,r0 mov r0,r5 ash $PBSHFT,r0 bic $!7777,r0 mov r0,dno clr r0 jsr pc,rblk bic $!17,r5 mov $INOSIZ,r0 mul r0,r5 add $buf,r5 mov $inod,r4 1: movb (r5)+,(r4)+ sob r0,1b rts pc readdir: bit $BSIZE-1,r2 bne 1f jsr pc,rmblk / read mapped block (bno) br err / end of file branch clr r2 / start at beginning of buf 1: mov $buf,r0 add r2,r0 / dp = buf+offset add buf+2(r2),r2 / dp += dp->d_reclen tst (r0) / dp->d_ino == 0? beq readdir / yes - go look at next rts pc / return with r0 = &dp->d_ino err: clr r0 / return with rts pc / dp = NULL loadfile: clr bno / start at block 0 of inode in 'inod' -256.*CLSIZE / word count / The boot options and device are placed in the last SZFLAGS bytes / at the end of core by the kernel for autobooting. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 CHECKWORD= 6 .. = ENDCORE-512.-SZFLAGS / save rosys/netinet/ 755 0 12 0 6044573440 6235 sys/netinet/if_ether.h 444 0 0 5057 4235412354 10236 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)if_ether.h 7.2 (Berkeley) 12/7/87 */ /* * Structure of a 10Mb/s Ethernet header. */ struct ether_header { u_char ether_dhost[6]; u_char ether_shost[6]; u_short ether_type; }; #define ETHERTYPE_PUP 0x0200 /* PUP protocol */ #define ETHERTYPE_IP 0x0800 /* IP protocol */ #define ETHERTYPE_ARP 0x0806 /* Addr. resolution protocol */ /* * The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have * (type-ETHERTYPE_TRAIL)*512 bytes of data followed * by an ETHER type (as given above) and then the (variable-length) header. */ #define ETHERTYPE_TRAIL 0x1000 /* Trailer packet */ #define ETHERTYPE_NTRAILER 16 #define ETHERMTU 1500 #define ETHERMIN (60-14) /* * Ethernet Address Resolution Protocol. * * See RFC 826 for protocol description. Structure below is adapted * to resolving internet addresses. Field names used correspond to * RFC 826. */ struct ether_arp { struct arphdr ea_hdr; /* fixed-size header */ u_char arp_sha[6]; /* sender hardware address */ u_char arp_spa[4]; /* sender protocol address */ u_char arp_tha[6]; /* target hardware address */ u_char arp_tpa[4]; /* target protocol address */ }; #define arp_hrd ea_hdr.ar_hrd #define arp_pro ea_hdr.ar_pro #define arp_hln ea_hdr.ar_hln #define arp_pln ea_hdr.ar_pln #define arp_op ea_hdr.ar_op /* * Structure shared between the ethernet driver modules and * the address resolution code. For example, each ec_softc or il_softc * begins with this structure. */ struct arpcom { struct ifnet ac_if; /* network-visible interface */ u_char ac_enaddr[6]; /* ethernet hardware address */ struct in_addr ac_ipaddr; /* copy of ip address- XXX */ }; /* * Internet to ethernet address resolution table. */ struct arptab { struct in_addr at_iaddr; /* internet address */ u_char at_enaddr[6]; /* ethernet address */ u_char at_timer; /* minutes since last reference */ u_char at_flags; /* flags */ struct mbuf *at_hold; /* last packet until resolved/timeout */ }; #ifdef SUPERVISOR u_char etherbroadcastaddr[6]; struct arptab *arptnew(); char *ether_sprintf(); #endif 0 / so return can be rts pc / establish sp, copy / program up to end of core. nop / These two lines must be present or DEC br start / boot ROMs will refuse to run boot block! start: clr r0 / XXX - for Rome 11/70, boot card doesn't work mov $176714,r1 / XXX - for Rome 11/70, boot card doesn't work movb r0,unit+1 / save the unit in high byte (for brcs) mov r1,csr / and csr from the ROMs (not base addr!) mov $..,sp mov sp,r1 clr r0 1: mov (r0)+,(sys/netinet/in.h 444 0 0 10661 6036400634 7073 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)in.h 7.5.3 (2.11BSD GTE) 1995/10/09 */ /* * Constants and structures defined by the internet system, * Per RFC 790, September 1981. */ /* * Protocols */ #define IPPROTO_IP 0 /* dummy for IP */ #define IPPROTO_ICMP 1 /* control message protocol */ #define IPPROTO_GGP 3 /* gateway^2 (deprecated) */ #define IPPROTO_TCP 6 /* tcp */ #define IPPROTO_EGP 8 /* exterior gateway protocol */ #define IPPROTO_PUP 12 /* pup */ #define IPPROTO_UDP 17 /* user datagram protocol */ #define IPPROTO_IDP 22 /* xns idp */ #define IPPROTO_RAW 255 /* raw IP packet */ #define IPPROTO_MAX 256 /* * Ports < IPPORT_RESERVED are reserved for * privileged processes (e.g. root). * Ports > IPPORT_USERRESERVED are reserved * for servers, not necessarily privileged. */ #define IPPORT_RESERVED 1024 #define IPPORT_USERRESERVED 5000 /* * Link numbers */ #define IMPLINK_IP 155 #define IMPLINK_LOWEXPER 156 #define IMPLINK_HIGHEXPER 158 /* * Internet address (a structure for historical reasons) */ struct in_addr { u_long s_addr; }; /* * Definitions of bits in internet address integers. * On subnets, the decomposition of addresses to host and net parts * is done according to subnet mask, not the masks here. */ #define IN_CLASSA(i) (((long)(i) & 0x80000000L) == 0) #define IN_CLASSA_NET 0xff000000L #define IN_CLASSA_NSHIFT 24 #define IN_CLASSA_HOST 0x00ffffffL #define IN_CLASSA_MAX 128 #define IN_CLASSB(i) (((long)(i) & 0xc0000000L) == 0x80000000L) #define IN_CLASSB_NET 0xffff0000L #define IN_CLASSB_NSHIFT 16 #define IN_CLASSB_HOST 0x0000ffffL #define IN_CLASSB_MAX 65536 #define IN_CLASSC(i) (((long)(i) & 0xe0000000L) == 0xc0000000L) #define IN_CLASSC_NET 0xffffff00L #define IN_CLASSC_NSHIFT 8 #define IN_CLASSC_HOST 0x000000ffL #define IN_CLASSD(i) (((long)(i) & 0xf0000000L) == 0xe0000000L) #define IN_MULTICAST(i) IN_CLASSD(i) #define IN_EXPERIMENTAL(i) (((long)(i) & 0xe0000000L) == 0xe0000000L) #define IN_BADCLASS(i) (((long)(i) & 0xf0000000L) == 0xf0000000L) #define INADDR_ANY 0x00000000L #define INADDR_BROADCAST 0xffffffffL /* must be masked */ #ifndef KERNEL #define INADDR_NONE 0xffffffffL /* -1 return */ #endif #define IN_LOOPBACKNET 127 /* official! */ /* * Socket address, internet style. */ struct sockaddr_in { short sin_family; u_short sin_port; struct in_addr sin_addr; char sin_zero[8]; }; /* * Options for use with [gs]etsockopt at the IP level. */ #define IP_OPTIONS 1 /* set/get IP per-packet options */ /* * Definitions for inet sysctl operations. * * Third level is protocol number. * Fourth level is desired variable within that protocol. */ #define IPPROTO_MAXID (IPPROTO_IDP + 1) /* don't list to IPPROTO_MAX */ #ifndef KERNEL #define CTL_IPPROTO_NAMES { \ { "ip", CTLTYPE_NODE }, \ { "icmp", CTLTYPE_NODE }, \ { "igmp", CTLTYPE_NODE }, \ { 0, 0 }, \ { 0, 0 }, \ { 0, 0 }, \ { "tcp", CTLTYPE_NODE }, \ { 0, 0 }, \ { 0, 0 }, \ { 0, 0 }, \ { 0, 0 }, \ { 0, 0 }, \ { 0, 0 }, \ { 0, 0 }, \ { 0, 0 }, \ { 0, 0 }, \ { 0, 0 }, \ { "udp", CTLTYPE_NODE }, \ { 0, 0 }, \ { 0, 0 }, \ { 0, 0 }, \ { 0, 0 }, \ { "idp", CTLTYPE_NODE }, \ } #endif /* KERNEL */ /* * Names for IP sysctl objects */ #define IPCTL_FORWARDING 1 /* act as router */ #define IPCTL_SENDREDIRECTS 2 /* may send redirects when forwarding */ #define IPCTL_DEFTTL 3 /* default TTL */ #ifdef notyet #define IPCTL_DEFMTU 4 /* default MTU */ #endif #define IPCTL_FORWSRCRT 5 /* forward source-routed dgrams */ #define IPCTL_MAXID 6 #ifndef KERNEL #define IPCTL_NAMES { \ { 0, 0 }, \ { "forwarding", CTLTYPE_INT }, \ { "redirect", CTLTYPE_INT }, \ { "ttl", CTLTYPE_INT }, \ { "mtu", CTLTYPE_INT }, \ { "forwsrcrt", CTLTYPE_INT }, \ } #endif /* KERNEL */ /* * Macros for number representation conversion. */ u_short ntohs(), htons(); u_long ntohl(), htonl(); #ifdef SUPERVISOR extern struct domain inetdomain; extern struct protosw inetsw[]; struct in_addr in_makeaddr(); u_long in_netof(), in_lnaof(); #endif mov bno,r0 cmp r0,$NDIRIN blt 1f mov $NDIRIN,r0 1: ash $2,r0 mov addr+2(r0sys/netinet/in_pcb.h 444 0 0 3057 4235415063 7701 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)in_pcb.h 7.2 (Berkeley) 12/7/87 */ /* * Common structure pcb for internet protocol implementation. * Here are stored pointers to local and foreign host table * entries, local and foreign socket numbers, and pointers * up (to a socket structure) and down (to a protocol-specific) * control block. */ struct inpcb { struct inpcb *inp_next,*inp_prev; /* pointers to other pcb's */ struct inpcb *inp_head; /* pointer back to chain of inpcb's for this protocol */ struct in_addr inp_faddr; /* foreign host table entry */ u_short inp_fport; /* foreign port */ struct in_addr inp_laddr; /* local host table entry */ u_short inp_lport; /* local port */ struct socket *inp_socket; /* back pointer to socket */ caddr_t inp_ppcb; /* pointer to per-protocol pcb */ struct route inp_route; /* placeholder for routing entry */ struct mbuf *inp_options; /* IP options */ }; #define INPLOOKUP_WILDCARD 1 #define INPLOOKUP_SETLOCAL 2 #define sotoinpcb(so) ((struct inpcb *)(so)->so_pcb) #ifdef SUPERVISOR struct inpcb *in_pcblookup(); #endif nitions of bits in internet address integers. * On subnets, the decomposition of addresses to host and net parts * is done according to subnet mask, not the masks here. */ #define IN_CLASSA(i) (((long)(i) & 0x80000000L) == 0) #define IN_CLASSA_NET 0xff000000L #define IN_CLASSA_NSHIFT 24 #define IN_CLASSA_HOST 0x00ffffffL #define IN_CLASSA_MAX 128 #define IN_CLASSB(i) (((long)(i) & 0xc0000000L) == 0x80000000L) #define IN_CLASSB_NET 0xffff0000L #define sys/netinet/in_systm.h 444 0 0 2301 5514435051 10303 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)in_systm.h 7.2.1 (2.11BSD GTE) 12/31/93 */ /* * Miscellaneous internetwork * definitions for kernel. */ /* * Network types. * * Internally the system keeps counters in the headers with the bytes * swapped so that VAX instructions will work on them. It reverses * the bytes before transmission at each protocol level. The n_ types * represent the types with the bytes in ``high-ender'' order. */ typedef u_short n_short; /* short as received from the net */ typedef u_long n_long; /* long as received from the net */ typedef u_long n_time; /* ms since 00:00 GMT, byte rev */ #ifdef pdp11 #define UCHAR(a) ((u_int)((a)&0xff)) #endif #ifdef SUPERVISOR n_time iptime(); #endif cket; /* back pointer to socket */ caddr_t inp_ppcb; /* pointer to per-protocol pcb */ struct route inp_route; /* placeholder for routing entry */ struct mbuf *inp_options; /* IP options */ }; #define INPLOOKUP_WILDCARD 1 #define INPLOOKUP_SETLOCAL 2 #define sotoinpcb(so) ((struct inpcb *)(so)->so_pcb) #ifdef Ssys/netinet/ip.h 444 0 0 11026 6036404736 7100 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)ip.h 7.6.1.2 (2.11BSD) 1995/10/09 */ #ifndef BYTE_ORDER /* * Definitions for byte order, * according to byte significance from low address to high. */ #define LITTLE_ENDIAN 1234 /* least-significant byte first (vax) */ #define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */ #define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long (pdp) */ #ifdef vax #define BYTE_ORDER LITTLE_ENDIAN #else #ifdef pdp11 #define BYTE_ORDER PDP_ENDIAN #else #define BYTE_ORDER BIG_ENDIAN /* mc68000, tahoe, most others */ #endif #endif #endif BYTE_ORDER /* * Definitions for internet protocol version 4. * Per RFC 791, September 1981. */ #define IPVERSION 4 /* * Structure of an internet header, naked of options. * * We declare ip_len and ip_off to be short, rather than u_short * pragmatically since otherwise unsigned comparisons can result * against negative integers quite easily, and fail in subtle ways. */ struct ip { #if BYTE_ORDER == LITTLE_ENDIAN u_char ip_hl:4, /* header length */ ip_v:4; /* version */ #endif #if BYTE_ORDER == BIG_ENDIAN u_char ip_v:4, /* version */ ip_hl:4; /* header length */ #endif #if BYTE_ORDER == PDP_ENDIAN u_int ip_hl:4, /* header length */ ip_v:4; /* version */ #endif u_char ip_tos; /* type of service */ short ip_len; /* total length */ u_short ip_id; /* identification */ short ip_off; /* fragment offset field */ #define IP_DF 0x4000 /* dont fragment flag */ #define IP_MF 0x2000 /* more fragments flag */ u_char ip_ttl; /* time to live */ u_char ip_p; /* protocol */ u_short ip_sum; /* checksum */ struct in_addr ip_src,ip_dst; /* source and dest address */ }; #define IP_MAXPACKET 65535L /* maximum packet size */ /* * Definitions for options. */ #define IPOPT_COPIED(o) ((o)&0x80) #define IPOPT_CLASS(o) ((o)&0x60) #define IPOPT_NUMBER(o) ((o)&0x1f) #define IPOPT_CONTROL 0x00 #define IPOPT_RESERVED1 0x20 #define IPOPT_DEBMEAS 0x40 #define IPOPT_RESERVED2 0x60 #define IPOPT_EOL 0 /* end of option list */ #define IPOPT_NOP 1 /* no operation */ #define IPOPT_RR 7 /* record packet route */ #define IPOPT_TS 68 /* timestamp */ #define IPOPT_SECURITY 130 /* provide s,c,h,tcc */ #define IPOPT_LSRR 131 /* loose source route */ #define IPOPT_SATID 136 /* satnet id */ #define IPOPT_SSRR 137 /* strict source route */ /* * Offsets to fields in options other than EOL and NOP. */ #define IPOPT_OPTVAL 0 /* option ID */ #define IPOPT_OLEN 1 /* option length */ #define IPOPT_OFFSET 2 /* offset within option */ #define IPOPT_MINOFF 4 /* min value of above */ /* * Time stamp option structure. */ struct ip_timestamp { u_char ipt_code; /* IPOPT_TS */ u_char ipt_len; /* size of structure (variable) */ u_char ipt_ptr; /* index of current entry */ #if BYTE_ORDER == LITTLE_ENDIAN u_char ipt_flg:4, /* flags, see below */ ipt_oflw:4; /* overflow counter */ #endif #if BYTE_ORDER == BIG_ENDIAN u_char ipt_oflw:4, /* overflow counter */ ipt_flg:4; /* flags, see below */ #endif #if BYTE_ORDER == PDP_ENDIAN u_char ipt_flg:4, /* flags, see below */ ipt_oflw:4; /* overflow counter */ #endif union ipt_timestamp { n_long ipt_time[1]; struct ipt_ta { struct in_addr ipt_addr; n_long ipt_time; } ipt_ta[1]; } ipt_timestamp; }; /* flag bits for ipt_flg */ #define IPOPT_TS_TSONLY 0 /* timestamps only */ #define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */ #define IPOPT_TS_PRESPEC 2 /* specified modules only */ /* bits for security (not byte swapped) */ #define IPOPT_SECUR_UNCLASS 0x0000 #define IPOPT_SECUR_CONFID 0xf135 #define IPOPT_SECUR_EFTO 0x789a #define IPOPT_SECUR_MMMM 0xbc4d #define IPOPT_SECUR_RESTR 0xaf13 #define IPOPT_SECUR_SECRET 0xd788 #define IPOPT_SECUR_TOPSECRET 0x6bc5 /* * Internet implementation parameters. */ #define MAXTTL 255 /* maximum time to live (seconds) */ #define IPDEFTTL 64 /* default ttl, from RFC 1340 */ #define IPFRAGTTL 60 /* time to live for frags, slowhz */ #define IPTTLDEC 1 /* subtracted when forwarding */ #define IP_MSS 576 /* default maximum segment size */ bne 1f tst dno beq 2f 1: jsr pc,rblk mov bno,r0 inc bno sub $NDIRIN,r0 blt 1f ash $2,r0 mov buf+2(r0),dno mov buf(r0),r0 bne rblk tst dno bne rblk 2: sub $2,(sp) 1: rts pc read = 4 go = 1 brds = -4 brer = -2 brcs = 0 / offset from base csr passed by ROMs brwc = 2 brba = 4 brca = 6 brda = 10 brae = 12 / br disk driver. / low order address in dno, / high order in r0. rblk: mov r1,-(sp) mov dno,r1 .if CLSIZE-1 ashc $CLSHFT,r0 / multiply by CLSIZE .endif div seccylsys/netinet/ip_icmp.h 444 0 0 7634 4235421713 10073 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)ip_icmp.h 7.3 (Berkeley) 12/7/87 */ /* * Interface Control Message Protocol Definitions. * Per RFC 792, September 1981. */ /* * Structure of an icmp header. */ struct icmp { u_char icmp_type; /* type of message, see below */ u_char icmp_code; /* type sub code */ u_short icmp_cksum; /* ones complement cksum of struct */ union { u_char ih_pptr; /* ICMP_PARAMPROB */ struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ struct ih_idseq { n_short icd_id; n_short icd_seq; } ih_idseq; long ih_void; } icmp_hun; #define icmp_pptr icmp_hun.ih_pptr #define icmp_gwaddr icmp_hun.ih_gwaddr #define icmp_id icmp_hun.ih_idseq.icd_id #define icmp_seq icmp_hun.ih_idseq.icd_seq #define icmp_void icmp_hun.ih_void union { struct id_ts { n_time its_otime; n_time its_rtime; n_time its_ttime; } id_ts; struct id_ip { struct ip idi_ip; /* options and then 64 bits of data */ } id_ip; u_long id_mask; char id_data[1]; } icmp_dun; #define icmp_otime icmp_dun.id_ts.its_otime #define icmp_rtime icmp_dun.id_ts.its_rtime #define icmp_ttime icmp_dun.id_ts.its_ttime #define icmp_ip icmp_dun.id_ip.idi_ip #define icmp_mask icmp_dun.id_mask #define icmp_data icmp_dun.id_data }; /* * Lower bounds on packet lengths for various types. * For the error advice packets must first insure that the * packet is large enought to contain the returned ip header. * Only then can we do the check to see if 64 bits of packet * data have been returned, since we need to check the returned * ip header length. */ #define ICMP_MINLEN 8 /* abs minimum */ #define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */ #define ICMP_MASKLEN 12 /* address mask */ #define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */ #define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8) /* N.B.: must separately check that ip_hl >= 5 */ /* * Definition of type and code field values. */ #define ICMP_ECHOREPLY 0 /* echo reply */ #define ICMP_UNREACH 3 /* dest unreachable, codes: */ #define ICMP_UNREACH_NET 0 /* bad net */ #define ICMP_UNREACH_HOST 1 /* bad host */ #define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */ #define ICMP_UNREACH_PORT 3 /* bad port */ #define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */ #define ICMP_UNREACH_SRCFAIL 5 /* src route failed */ #define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */ #define ICMP_REDIRECT 5 /* shorter route, codes: */ #define ICMP_REDIRECT_NET 0 /* for network */ #define ICMP_REDIRECT_HOST 1 /* for host */ #define ICMP_REDIRECT_TOSNET 2 /* for tos and net */ #define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */ #define ICMP_ECHO 8 /* echo service */ #define ICMP_TIMXCEED 11 /* time exceeded, code: */ #define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */ #define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */ #define ICMP_PARAMPROB 12 /* ip header bad */ #define ICMP_TSTAMP 13 /* timestamp request */ #define ICMP_TSTAMPREPLY 14 /* timestamp reply */ #define ICMP_IREQ 15 /* information request */ #define ICMP_IREQREPLY 16 /* information reply */ #define ICMP_MASKREQ 17 /* address mask request */ #define ICMP_MASKREPLY 18 /* address mask reply */ #define ICMP_MAXTYPE 18 #define ICMP_INFOTYPE(type) \ ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \ (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \ (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) d_ip; u_long id_mask; char id_data[1]; } icmp_dun; #define icmp_otime icmp_dun.id_ts.its_otime sys/netinet/ip_var.h 444 0 0 6767 6036653171 7747 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)ip_var.h 7.4.1 (2.11BSD GTE) 12/31/93 */ /* * Overlay for ip header used by other protocols (tcp, udp). */ struct ipovly { caddr_t ih_next, ih_prev; /* for protocol sequence q's */ #ifdef pdp11 u_long ih_pad; #endif u_char ih_x1; /* (unused) */ u_char ih_pr; /* protocol */ short ih_len; /* protocol length */ struct in_addr ih_src; /* source internet address */ struct in_addr ih_dst; /* destination internet address */ }; /* * Ip reassembly queue structure. Each fragment * being reassembled is attached to one of these structures. * They are timed out after ipq_ttl drops to 0, and may also * be reclaimed if memory becomes tight. */ struct ipq { struct ipq *next,*prev; /* to other reass headers */ #ifdef pdp11 u_long ipq_pad; #endif u_char ipq_ttl; /* time for reass q to live */ u_char ipq_p; /* protocol of this fragment */ u_short ipq_id; /* sequence id for reassembly */ struct ipasfrag *ipq_next,*ipq_prev; /* to ip headers of fragments */ struct in_addr ipq_src,ipq_dst; }; /* * Ip header, when holding a fragment. * * Note: ipf_next must be at same offset as ipq_next above */ struct ipasfrag { #if BYTE_ORDER == LITTLE_ENDIAN u_char ip_hl:4, ip_v:4; #endif #if BYTE_ORDER == BIG_ENDIAN u_char ip_v:4, ip_hl:4; #endif #if BYTE_ORDER == PDP_ENDIAN u_int ip_hl:4, ip_v:4; #endif u_char ipf_mff; /* copied from (ip_off&IP_MF) */ short ip_len; u_short ip_id; short ip_off; u_char ip_ttl; u_char ip_p; u_short ip_sum; struct ipasfrag *ipf_next; /* next fragment */ struct ipasfrag *ipf_prev; /* previous fragment */ #ifdef pdp11 u_long ipf_pad; #endif }; /* * Structure stored in mbuf in inpcb.ip_options * and passed to ip_output when ip options are in use. * The actual length of the options (including ipopt_dst) * is in m_len. */ #define MAX_IPOPTLEN 40 struct ipoption { struct in_addr ipopt_dst; /* first-hop dst if source routed */ char ipopt_list[MAX_IPOPTLEN]; /* options proper */ }; struct ipstat { long ips_total; /* total packets received */ long ips_badsum; /* checksum bad */ long ips_tooshort; /* packet too short */ long ips_toosmall; /* not enough data */ long ips_badhlen; /* ip header length < data size */ long ips_badlen; /* ip length < ip header length */ long ips_fragments; /* fragments received */ long ips_fragdropped; /* frags dropped (dups, out of space) */ long ips_fragtimeout; /* fragments timed out */ long ips_forward; /* packets forwarded */ long ips_cantforward; /* packets rcvd for unreachable dest */ long ips_redirectsent; /* packets forwarded on same net */ }; #ifdef SUPERVISOR /* flags passed to ip_output as last parameter */ #define IP_FORWARDING 0x1 /* most of ip header exists */ #define IP_ROUTETOIF SO_DONTROUTE /* bypass routing tables */ #define IP_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */ struct ipstat ipstat; struct ipq ipq; /* ip reass. queue */ u_short ip_id; /* ip packet ctr, for ids */ int ip_defttl; /* default IP ttl */ struct mbuf *ip_srcroute(); #endif == PDP_ENsys/netinet/tcp.h 444 0 0 4561 4235735117 7243 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)tcp.h 7.4.1.1 (Berkeley) 2/7/88 */ #ifndef BYTE_ORDER /* * Definitions for byte order, * according to byte significance from low address to high. */ #define LITTLE_ENDIAN 1234 /* least-significant byte first (vax) */ #define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */ #define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long (pdp) */ #ifdef vax #define BYTE_ORDER LITTLE_ENDIAN #else #ifdef pdp11 #define BYTE_ORDER PDP_ENDIAN #else #define BYTE_ORDER BIG_ENDIAN /* mc68000, tahoe, most others */ #endif #endif #endif BYTE_ORDER typedef u_long tcp_seq; /* * TCP header. * Per RFC 793, September, 1981. */ struct tcphdr { u_short th_sport; /* source port */ u_short th_dport; /* destination port */ tcp_seq th_seq; /* sequence number */ tcp_seq th_ack; /* acknowledgement number */ #if BYTE_ORDER == LITTLE_ENDIAN u_char th_x2:4, /* (unused) */ th_off:4; /* data offset */ #endif #if BYTE_ORDER == BIG_ENDIAN u_char th_off:4, /* data offset */ th_x2:4; /* (unused) */ #endif #if BYTE_ORDER == PDP_ENDIAN u_int th_x2:4, /* (unused) */ th_off:4; /* data offset */ #endif u_char th_flags; #define TH_FIN 0x01 #define TH_SYN 0x02 #define TH_RST 0x04 #define TH_PUSH 0x08 #define TH_ACK 0x10 #define TH_URG 0x20 u_short th_win; /* window */ u_short th_sum; /* checksum */ u_short th_urp; /* urgent pointer */ }; #define TCPOPT_EOL 0 #define TCPOPT_NOP 1 #define TCPOPT_MAXSEG 2 /* * Default maximum segment size for TCP. * With an IP MSS of 576, this is 536, * but 512 is probably more convenient. */ #ifdef lint #define TCP_MSS 536 #else #ifndef IP_MSS #define IP_MSS 576 #endif #define TCP_MSS MIN(512, IP_MSS - sizeof (struct tcpiphdr)) #endif /* * User-settable options (used with setsockopt). */ #define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ #define TCP_MAXSEG 0x02 /* set maximum segment size */ op dst if source routed */ char ipopt_list[MAX_IPOPTLEN]; /* options proper */ }; struct ipstat { long ips_total; /* total packets receivedsys/netinet/tcp_debug.h 444 0 0 1725 4235454027 10406 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)tcp_debug.h 7.2 (Berkeley) 12/7/87 */ struct tcp_debug { n_time td_time; short td_act; short td_ostate; caddr_t td_tcb; struct tcpiphdr td_ti; short td_req; struct tcpcb td_cb; }; #define TA_INPUT 0 #define TA_OUTPUT 1 #define TA_USER 2 #define TA_RESPOND 3 #define TA_DROP 4 #ifdef TANAMES char *tanames[] = { "input", "output", "user", "respond", "drop" }; #endif #define TCP_NDEBUG 2 struct tcp_debug tcp_debug[TCP_NDEBUG]; int tcp_debx; se #define BYTE_ORDER BIG_ENDIAN /* mc68000sys/netinet/tcp_fsm.h 444 0 0 4341 4235454105 10077 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)tcp_fsm.h 7.2 (Berkeley) 12/7/87 */ /* * TCP FSM state definitions. * Per RFC793, September, 1981. */ #define TCP_NSTATES 11 #define TCPS_CLOSED 0 /* closed */ #define TCPS_LISTEN 1 /* listening for connection */ #define TCPS_SYN_SENT 2 /* active, have sent syn */ #define TCPS_SYN_RECEIVED 3 /* have send and received syn */ /* states < TCPS_ESTABLISHED are those where connections not established */ #define TCPS_ESTABLISHED 4 /* established */ #define TCPS_CLOSE_WAIT 5 /* rcvd fin, waiting for close */ /* states > TCPS_CLOSE_WAIT are those where user has closed */ #define TCPS_FIN_WAIT_1 6 /* have closed, sent fin */ #define TCPS_CLOSING 7 /* closed xchd FIN; await FIN ACK */ #define TCPS_LAST_ACK 8 /* had fin and close; await FIN ACK */ /* states > TCPS_CLOSE_WAIT && < TCPS_FIN_WAIT_2 await ACK of FIN */ #define TCPS_FIN_WAIT_2 9 /* have closed, fin is acked */ #define TCPS_TIME_WAIT 10 /* in 2*msl quiet wait after close */ #define TCPS_HAVERCVDSYN(s) ((s) >= TCPS_SYN_RECEIVED) #define TCPS_HAVERCVDFIN(s) ((s) >= TCPS_TIME_WAIT) #ifdef TCPOUTFLAGS /* * Flags used when sending segments in tcp_output. * Basic flags (TH_RST,TH_ACK,TH_SYN,TH_FIN) are totally * determined by state, with the proviso that TH_FIN is sent only * if all data queued for output is included in the segment. */ u_char tcp_outflags[TCP_NSTATES] = { TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK, TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK, TH_ACK, TH_ACK, }; #endif #ifdef KPROF int tcp_acounts[TCP_NSTATES][PRU_NREQ]; #endif #ifdef TCPSTATES char *tcpstates[] = { "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING", "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT", }; #endif ith setsockopt). */ #define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ #define TCP_MAXSEG 0x02 /* set maximum segment size */ op dst if source routed */ char ipopt_list[MAX_IPOPTLEN]; /* options proper */ }; struct ipstat { long ips_total; /* total packets receivedsys/netinet/tcp_seq.h 444 0 0 2502 4235461123 10075 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)tcp_seq.h 7.2 (Berkeley) 12/7/87 */ /* * TCP sequence numbers are 32 bit integers operated * on with modular arithmetic. These macros can be * used to compare such integers. */ #define SEQ_LT(a,b) ((long)((a)-(b)) < 0) #define SEQ_LEQ(a,b) ((long)((a)-(b)) <= 0) #define SEQ_GT(a,b) ((long)((a)-(b)) > 0) #define SEQ_GEQ(a,b) ((long)((a)-(b)) >= 0) /* * Macros to initialize tcp sequence numbers for * send and receive from initial send and receive * sequence numbers. */ #define tcp_rcvseqinit(tp) \ (tp)->rcv_adv = (tp)->rcv_nxt = (tp)->irs + 1 #define tcp_sendseqinit(tp) \ (tp)->snd_una = (tp)->snd_nxt = (tp)->snd_max = (tp)->snd_up = \ (tp)->iss #define TCP_ISSINCR 128 /* increment for tcp_iss each second */ #ifdef SUPERVISOR tcp_seq tcp_iss; /* tcp initial send seq # */ #endif N */ #define TCPS_FIN_WAIT_2 9 /* have closed, fin is acked */ #define TCPS_TIME_WAIT 10 /* in 2*msl quiet wait after close */ #define TCPS_HAVERCVDSYN(s) ((s) >= TCPS_SYN_RECEIVED) #defisys/netinet/tcp_timer.h 444 0 0 10513 6037100504 10441 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)tcp_timer.h 7.5.1 (2.11BSD) 1995/10/10 */ /* * Definitions of the TCP timers. These timers are counted * down PR_SLOWHZ times a second. */ #define TCPT_NTIMERS 4 #define TCPT_REXMT 0 /* retransmit */ #define TCPT_PERSIST 1 /* retransmit persistance */ #define TCPT_KEEP 2 /* keep alive */ #define TCPT_2MSL 3 /* 2*msl quiet time timer */ /* * The TCPT_REXMT timer is used to force retransmissions. * The TCP has the TCPT_REXMT timer set whenever segments * have been sent for which ACKs are expected but not yet * received. If an ACK is received which advances tp->snd_una, * then the retransmit timer is cleared (if there are no more * outstanding segments) or reset to the base value (if there * are more ACKs expected). Whenever the retransmit timer goes off, * we retransmit one unacknowledged segment, and do a backoff * on the retransmit timer. * * The TCPT_PERSIST timer is used to keep window size information * flowing even if the window goes shut. If all previous transmissions * have been acknowledged (so that there are no retransmissions in progress), * and the window is too small to bother sending anything, then we start * the TCPT_PERSIST timer. When it expires, if the window is nonzero, * we go to transmit state. Otherwise, at intervals send a single byte * into the peer's window to force him to update our window information. * We do this at most as often as TCPT_PERSMIN time intervals, * but no more frequently than the current estimate of round-trip * packet time. The TCPT_PERSIST timer is cleared whenever we receive * a window update from the peer. * * The TCPT_KEEP timer is used to keep connections alive. If an * connection is idle (no segments received) for TCPTV_KEEP_INIT amount of time, * but not yet established, then we drop the connection. Once the connection * is established, if the connection is idle for TCPTV_KEEP_IDLE time * (and keepalives have been enabled on the socket), we begin to probe * the connection. We force the peer to send us a segment by sending: * * This segment is (deliberately) outside the window, and should elicit * an ack segment in response from the peer. If, despite the TCPT_KEEP * initiated segments we cannot elicit a response from a peer in TCPT_MAXIDLE * amount of time probing, then we drop the connection. */ /* * Time constants. */ #define TCPTV_MSL ( 30*PR_SLOWHZ) /* max seg lifetime (hah!) */ #define TCPTV_SRTTBASE 0 /* base roundtrip time; if 0, no idea yet */ #define TCPTV_SRTTDFLT ( 3*PR_SLOWHZ) /* assumed RTT if no info */ #define TCPTV_PERSMIN ( 5*PR_SLOWHZ) /* retransmit persistance */ #define TCPTV_PERSMAX ( 60*PR_SLOWHZ) /* maximum persist interval */ #define TCPTV_KEEP_INIT ( 75*PR_SLOWHZ) /* initial connect keep alive */ #define TCPTV_KEEP_IDLE (120*60*PR_SLOWHZ) /* dflt time before probing */ #define TCPTV_KEEPINTVL ( 75*PR_SLOWHZ) /* default probe interval */ #define TCPTV_KEEPCNT 8 /* max probes before drop */ #define TCPTV_MIN ( 1*PR_SLOWHZ) /* minimum allowable value */ #define TCPTV_REXMTMAX ( 64*PR_SLOWHZ) /* max allowable REXMT value */ #define TCP_LINGERTIME 120 /* linger at most 2 minutes */ #define TCP_MAXRXTSHIFT 12 /* maximum retransmits */ #ifdef TCPTIMERS char *tcptimers[] = { "REXMT", "PERSIST", "KEEP", "2MSL" }; #endif /* * Force a time value to be in a certain range. */ #define TCPT_RANGESET(tv, value, tvmin, tvmax) { \ (tv) = (value); \ if ((tv) < (tvmin)) \ (tv) = (tvmin); \ else if ((tv) > (tvmax)) \ (tv) = (tvmax); \ } #ifdef SUPERVISOR #define tcp_keepidle tcp_kdle #define tcp_keepintvl tcp_kntv extern int tcp_keepidle; /* time before keepalive probes begin */ extern int tcp_keepintvl; /* time between keepalive probes */ extern int tcp_maxidle; /* time to drop after starting probes */ extern int tcp_backoff[]; #endif /* default ttl, from RFC 1340 */ #define IPFRAGTTL 60 /* time to live for frags, slowhz */ #define IPTTLDEC 1 /* subtracted when forwarding */ #define IP_MSS 576 /* default masys/netinet/tcp_var.h 444 0 0 21655 5316413552 10133 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)tcp_var.h 7.7 (Berkeley) 2/27/88 */ /* * TCP configuration: This is a half-assed attempt to make TCP * self-configure for a few varieties of 4.2 and 4.3-based unixes. * If you don't have a) a 4.3bsd vax or b) a 3.x Sun (x<6), check * this carefully (it's probably not right). Please send me mail * if you run into configuration problems. * - Van Jacobson (van@lbl-csam.arpa) */ #define TCP_COMPAT_42 /* _always_ set for 2.11BSD - not worth the trouble * of making it conditional */ #ifndef SB_MAX #ifdef SB_MAXCOUNT #define SB_MAX SB_MAXCOUNT /* Sun has to be a little bit different... */ #else #define SB_MAX 8192 /* XXX */ #endif SB_MAXCOUNT #endif SB_MAX #ifndef IP_MAXPACKET #define IP_MAXPACKET 65535L /* maximum packet size */ #endif /* * Bill Nowicki pointed out that the page size (CLBYTES) has * nothing to do with the mbuf cluster size. So, we followed * Sun's lead and made the new define MCLBYTES stand for the mbuf * cluster size. The following define makes up backwards compatible * with 4.3 and 4.2. If CLBYTES is >1024 on your machine, check * this against the mbuf cluster definitions in /usr/include/sys/mbuf.h. */ #ifndef MCLBYTES #define MCLBYTES CLBYTES /* XXX */ #endif /* * The routine in_localaddr is broken in Sun's 3.4. We redefine ours * (in tcp_input.c) so we use can it but won't have a name conflict. */ #ifdef sun #define in_localaddr tcp_in_localaddr #endif /* --------------- end of TCP config ---------------- */ /* * Kernel variables for tcp. */ /* * Tcp control block, one per tcp; fields: */ struct tcpcb { struct tcpiphdr *seg_next; /* sequencing queue */ struct tcpiphdr *seg_prev; short t_state; /* state of this connection */ short t_timer[TCPT_NTIMERS]; /* tcp timers */ short t_rxtshift; /* log(2) of rexmt exp. backoff */ short t_rxtcur; /* current retransmit value */ short t_dupacks; /* consecutive dup acks recd */ u_short t_maxseg; /* maximum segment size */ char t_force; /* 1 if forcing out a byte */ u_char t_flags; #define TF_ACKNOW 0x01 /* ack peer immediately */ #define TF_DELACK 0x02 /* ack, but try to delay it */ #define TF_NODELAY 0x04 /* don't delay packets to coalesce */ #define TF_NOOPT 0x08 /* don't use tcp options */ #define TF_SENTFIN 0x10 /* have sent FIN */ struct tcpiphdr *t_template; /* skeletal packet for transmit */ struct inpcb *t_inpcb; /* back pointer to internet pcb */ /* * The following fields are used as in the protocol specification. * See RFC783, Dec. 1981, page 21. */ /* send sequence variables */ tcp_seq snd_una; /* send unacknowledged */ tcp_seq snd_nxt; /* send next */ tcp_seq snd_up; /* send urgent pointer */ tcp_seq snd_wl1; /* window update seg seq number */ tcp_seq snd_wl2; /* window update seg ack number */ tcp_seq iss; /* initial send sequence number */ u_short snd_wnd; /* send window */ /* receive sequence variables */ u_short rcv_wnd; /* receive window */ tcp_seq rcv_nxt; /* receive next */ tcp_seq rcv_up; /* receive urgent pointer */ tcp_seq irs; /* initial receive sequence number */ /* * Additional variables for this implementation. */ /* receive variables */ tcp_seq rcv_adv; /* advertised window */ /* retransmit variables */ tcp_seq snd_max; /* highest sequence number sent * used to recognize retransmits */ /* congestion control (for slow start, source quench, retransmit after loss) */ u_short snd_cwnd; /* congestion-controlled window */ u_short snd_ssthresh; /* snd_cwnd size threshhold for * for slow start exponential to * linear switch */ /* * transmit timing stuff. * srtt and rttvar are stored as fixed point; for convenience in smoothing, * srtt has 3 bits to the right of the binary point, rttvar has 2. * "Variance" is actually smoothed difference. */ short t_idle; /* inactivity time */ short t_rtt; /* round trip time */ tcp_seq t_rtseq; /* sequence number being timed */ short t_srtt; /* smoothed round-trip time */ short t_rttvar; /* variance in round-trip time */ u_short max_rcvd; /* most peer has sent into window */ u_short max_sndwnd; /* largest window peer has offered */ /* out-of-band data */ char t_oobflags; /* have some */ char t_iobc; /* input character */ #define TCPOOB_HAVEDATA 0x01 #define TCPOOB_HADDATA 0x02 }; #define intotcpcb(ip) ((struct tcpcb *)(ip)->inp_ppcb) #define sototcpcb(so) (intotcpcb(sotoinpcb(so))) /* * TCP statistics. * Many of these should be kept per connection, * but that's inconvenient at the moment. */ #define tcps_connattempt tcps_ca #define tcps_connects tcps_co #define tcps_conndrops tcps_cd #define tcps_keeptimeo tcps_kt #define tcps_keepprobe tcps_kp #define tcps_keepdrops tcps_kd #define tcps_sndtotal tcps_st #define tcps_sndpack tcps_sp #define tcps_sndbyte tcps_sb #define tcps_sndrexmitpack tcps_xp #define tcps_sndrexmitbyte tcps_xb #define tcps_sndacks tcps_sa #define tcps_sndprobe tcps_SP #define tcps_sndurg tcps_su #define tcps_sndwinup tcps_sw #define tcps_sndctrl tcps_sc #define tcps_rcvtotal tcps_RT #define tcps_rcvpack tcps_rp #define tcps_rcvbyte tcps_rb #define tcps_rcvbadsum tcps_bs #define tcps_rcvbadoff tcps_bo #define tcps_rcvshort tcps_rs #define tcps_rcvduppack tcps_dp #define tcps_rcvdupbyte tcps_db #define tcps_rcvpartduppack tcps_DP #define tcps_rcvpartdupbyte tcps_DB #define tcps_rcvoopack tcps_op #define tcps_rcvoobyte tcps_ob #define tcps_rcvpackafterwin tcps_pw #define tcps_rcvbyteafterwin tcps_bw #define tcps_rcvafterclose tcps_ra #define tcps_rcvwinprobe tcps_wp #define tcps_rcvdupack tcps_da #define tcps_rcvacktoomuch tcps_tm #define tcps_rcvackpack tcps_ap #define tcps_rcvackbyte tcps_ab #define tcps_rcvwinupd tcps_wu struct tcpstat { u_long tcps_connattempt; /* connections initiated */ u_long tcps_accepts; /* connections accepted */ u_long tcps_connects; /* connections established */ u_long tcps_drops; /* connections dropped */ u_long tcps_conndrops; /* embryonic connections dropped */ u_long tcps_closed; /* conn. closed (includes drops) */ u_long tcps_segstimed; /* segs where we tried to get rtt */ u_long tcps_rttupdated; /* times we succeeded */ u_long tcps_delack; /* delayed acks sent */ u_long tcps_timeoutdrop; /* conn. dropped in rxmt timeout */ u_long tcps_rexmttimeo; /* retransmit timeouts */ u_long tcps_persisttimeo; /* persist timeouts */ u_long tcps_keeptimeo; /* keepalive timeouts */ u_long tcps_keepprobe; /* keepalive probes sent */ u_long tcps_keepdrops; /* connections dropped in keepalive */ u_long tcps_sndtotal; /* total packets sent */ u_long tcps_sndpack; /* data packets sent */ u_long tcps_sndbyte; /* data bytes sent */ u_long tcps_sndrexmitpack; /* data packets retransmitted */ u_long tcps_sndrexmitbyte; /* data bytes retransmitted */ u_long tcps_sndacks; /* ack-only packets sent */ u_long tcps_sndprobe; /* window probes sent */ u_long tcps_sndurg; /* packets sent with URG only */ u_long tcps_sndwinup; /* window update-only packets sent */ u_long tcps_sndctrl; /* control (SYN|FIN|RST) packets sent */ u_long tcps_rcvtotal; /* total packets received */ u_long tcps_rcvpack; /* packets received in sequence */ u_long tcps_rcvbyte; /* bytes received in sequence */ u_long tcps_rcvbadsum; /* packets received with ccksum errs */ u_long tcps_rcvbadoff; /* packets received with bad offset */ u_long tcps_rcvshort; /* packets received too short */ u_long tcps_rcvduppack; /* duplicate-only packets received */ u_long tcps_rcvdupbyte; /* duplicate-only bytes received */ u_long tcps_rcvpartduppack; /* packets with some duplicate data */ u_long tcps_rcvpartdupbyte; /* dup. bytes in part-dup. packets */ u_long tcps_rcvoopack; /* out-of-order packets received */ u_long tcps_rcvoobyte; /* out-of-order bytes received */ u_long tcps_rcvpackafterwin; /* packets with data after window */ u_long tcps_rcvbyteafterwin; /* bytes rcvd after window */ u_long tcps_rcvafterclose; /* packets rcvd after "close" */ u_long tcps_rcvwinprobe; /* rcvd window probe packets */ u_long tcps_rcvdupack; /* rcvd duplicate acks */ u_long tcps_rcvacktoomuch; /* rcvd acks for unsent data */ u_long tcps_rcvackpack; /* rcvd ack packets */ u_long tcps_rcvackbyte; /* bytes acked by rcvd acks */ u_long tcps_rcvwinupd; /* rcvd window update packets */ }; #ifdef SUPERVISOR struct inpcb tcb; /* head of queue of active tcpcb's */ struct tcpstat tcpstat; /* tcp statistics */ struct tcpiphdr *tcp_template(); struct tcpcb *tcp_close(), *tcp_drop(); struct tcpcb *tcp_timers(), *tcp_disconnect(), *tcp_usrclosed(); #endif slg_group ldcfd bit $1,local(r5) bne 1f mov r3,r1; jsr pc,ffuword bit $fiuv,fpssys/netinet/tcpip.h 444 0 0 2316 4235466462 7574 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)tcpip.h 7.2 (Berkeley) 12/7/87 */ /* * Tcp+ip header, after ip options removed. */ struct tcpiphdr { struct ipovly ti_i; /* overlaid ip structure */ struct tcphdr ti_t; /* tcp header */ }; #define ti_next ti_i.ih_next #define ti_prev ti_i.ih_prev #define ti_pad ti_i.ih_pad #define ti_x1 ti_i.ih_x1 #define ti_pr ti_i.ih_pr #define ti_len ti_i.ih_len #define ti_src ti_i.ih_src #define ti_dst ti_i.ih_dst #define ti_sport ti_t.th_sport #define ti_dport ti_t.th_dport #define ti_seq ti_t.th_seq #define ti_ack ti_t.th_ack #define ti_x2 ti_t.th_x2 #define ti_off ti_t.th_off #define ti_flags ti_t.th_flags #define ti_win ti_t.th_win #define ti_sum ti_t.th_sum #define ti_urp ti_t.th_urp IP_MAXPACKET 65535L /* maximum packet size */ #endif /* * Bill Nowicki pointed out that the page size (CLBYTES) has * nothing to do with the mbuf cluster size. So, we followed * Sun's lead and made the new define MCLBYTES stand for the mbuf * cluster size. The following define makes up backwards sys/netinet/udp.h 444 0 0 1427 4235466515 7246 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)udp.h 7.2 (Berkeley) 12/7/87 */ /* * Udp protocol header. * Per RFC 768, September, 1981. */ struct udphdr { u_short uh_sport; /* source port */ u_short uh_dport; /* destination port */ short uh_ulen; /* udp length */ u_short uh_sum; /* udp checksum */ }; ad ti_i.ih_pad #define ti_x1 ti_i.ih_x1 #define ti_pr ti_i.ih_pr #define ti_len ti_i.ih_len #define ti_src ti_i.ih_src #define ti_dst ti_i.ih_dst #define ti_sport ti_t.th_sport #define ti_dport ti_t.th_dport #define ti_seq ti_sys/netinet/udp_var.h 444 0 0 3562 6036653370 10116 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)udp_var.h 7.3.2 (2.11BSD GTE) 1995/10/09 */ /* * UDP kernel structures and variables. */ struct udpiphdr { struct ipovly ui_i; /* overlaid ip structure */ struct udphdr ui_u; /* udp header */ }; #define ui_next ui_i.ih_next #define ui_prev ui_i.ih_prev #define ui_pad ui_i.ih_pad #define ui_x1 ui_i.ih_x1 #define ui_pr ui_i.ih_pr #define ui_len ui_i.ih_len #define ui_src ui_i.ih_src #define ui_dst ui_i.ih_dst #define ui_sport ui_u.uh_sport #define ui_dport ui_u.uh_dport #define ui_ulen ui_u.uh_ulen #define ui_sum ui_u.uh_sum struct udpstat { /* input statistics: */ long udps_ipackets; /* total input packets */ long udps_hdrops; /* packet shorter than header */ long udps_badsum; /* checksum error */ long udps_badlen; /* data length larger than packet */ long udps_noport; /* no socket on port */ long udps_noportbcast; /* of above, arrived as broadcast */ long udps_fullsock; /* not delivered, input socket full */ long udpps_pcbcachemiss; /* input packets missing pcb cache */ /* output statistics: */ long udps_opackets; /* total output packets */ }; /* * Names for UDP sysctl objects */ #define UDPCTL_CHECKSUM 1 /* checksum UDP packets */ #define UDPCTL_MAXID 2 #ifndef KERNEL #define UDPCTL_NAMES { \ { 0, 0 }, \ { "checksum", CTLTYPE_INT }, \ } #endif #ifdef SUPERVISOR struct inpcb udb; struct udpstat udpstat; #endif #define in_localaddr tcp_in_localaddr #endif /* --------------- end of TCP config ---------------- */ /* * Kernel variables for tcp. */ /sys/netinet/if_ether.c 644 3 12 35370 4361051030 10270 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)if_ether.c 7.6 (Berkeley) 12/7/87 */ /* * Ethernet address resolution protocol. * TODO: * run at splnet (add ARP protocol intr.) * link entries onto hash chains, keep free list * add "inuse/lock" bit (or ref. count) along with valid bit */ #include "ether.h" #if NETHER > 0 #include "param.h" #include "systm.h" #include "mbuf.h" #include "socket.h" #include "time.h" #include "kernel.h" #include "errno.h" #include "ioctl.h" #include "syslog.h" #include "domain.h" #include "protosw.h" #include "../net/if.h" #include "in.h" #include "in_systm.h" #include "ip.h" #include "if_ether.h" #define ARPTAB_BSIZ 5 /* bucket size */ #define ARPTAB_NB 13 /* number of buckets */ #define ARPTAB_SIZE (ARPTAB_BSIZ * ARPTAB_NB) struct arptab arptab[ARPTAB_SIZE]; int arptab_size = ARPTAB_SIZE; /* for arp command */ /* * ARP trailer negotiation. Trailer protocol is not IP specific, * but ARP request/response use IP addresses. */ #define ETHERTYPE_IPTRAILERS ETHERTYPE_TRAIL #define ARPTAB_HASH(a) \ ((short)((((a) >> 16) ^ (a)) & 0x7fff) % ARPTAB_NB) #define ARPTAB_LOOK(at,addr) { \ register n; \ at = &arptab[ARPTAB_HASH(addr) * ARPTAB_BSIZ]; \ for (n = 0 ; n < ARPTAB_BSIZ ; n++,at++) \ if (at->at_iaddr.s_addr == addr) \ break; \ if (n >= ARPTAB_BSIZ) \ at = 0; \ } /* timer values */ #define ARPT_AGE (60*1) /* aging timer, 1 min. */ #define ARPT_KILLC 20 /* kill completed entry in 20 mins. */ #define ARPT_KILLI 3 /* kill incomplete entry in 3 minutes */ u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; extern struct ifnet loif; extern int hz; /* * Timeout routine. Age arp_tab entries once a minute. */ arptimer() { register struct arptab *at; register i; TIMEOUT(arptimer, (caddr_t)0, ARPT_AGE * hz); at = &arptab[0]; for (i = 0; i < ARPTAB_SIZE; i++, at++) { if (at->at_flags == 0 || (at->at_flags & ATF_PERM)) continue; if (++at->at_timer < ((at->at_flags&ATF_COM) ? ARPT_KILLC : ARPT_KILLI)) continue; /* timer has expired, clear entry */ arptfree(at); } } /* * Broadcast an ARP packet, asking who has addr on interface ac. */ arpwhohas(ac, addr) register struct arpcom *ac; struct in_addr *addr; { register struct mbuf *m; register struct ether_header *eh; register struct ether_arp *ea; struct sockaddr sa; if ((m = m_get(M_DONTWAIT, MT_DATA)) == NULL) return; m->m_len = sizeof *ea; m->m_off = MMAXOFF - m->m_len; ea = mtod(m, struct ether_arp *); eh = (struct ether_header *)sa.sa_data; bzero((caddr_t)ea, sizeof (*ea)); bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, sizeof(eh->ether_dhost)); eh->ether_type = ETHERTYPE_ARP; /* if_output will swap */ ea->arp_hrd = htons(ARPHRD_ETHER); ea->arp_pro = htons(ETHERTYPE_IP); ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */ ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */ ea->arp_op = htons(ARPOP_REQUEST); bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha, sizeof(ea->arp_sha)); bcopy((caddr_t)&ac->ac_ipaddr, (caddr_t)ea->arp_spa, sizeof(ea->arp_spa)); bcopy((caddr_t)addr, (caddr_t)ea->arp_tpa, sizeof(ea->arp_tpa)); sa.sa_family = AF_UNSPEC; (*ac->ac_if.if_output)(&ac->ac_if, m, &sa); } int useloopback = 1; /* use loopback interface for local traffic */ /* * Resolve an IP address into an ethernet address. If success, * desten is filled in. If there is no entry in arptab, * set one up and broadcast a request for the IP address. * Hold onto this mbuf and resend it once the address * is finally resolved. A return value of 1 indicates * that desten has been filled in and the packet should be sent * normally; a 0 return indicates that the packet has been * taken over here, either now or for later transmission. * * We do some (conservative) locking here at splimp, since * arptab is also altered from input interrupt service (ecintr/ilintr * calls arpinput when ETHERTYPE_ARP packets come in). */ arpresolve(ac, m, destip, desten, usetrailers) register struct arpcom *ac; struct mbuf *m; register struct in_addr *destip; register u_char *desten; int *usetrailers; { register struct arptab *at; struct sockaddr_in sin; u_long lna; int s; *usetrailers = 0; if (in_broadcast(*destip)) { /* broadcast address */ bcopy((caddr_t)etherbroadcastaddr, (caddr_t)desten, sizeof(etherbroadcastaddr)); return (1); } lna = in_lnaof(*destip); /* if for us, use software loopback driver if up */ if (destip->s_addr == ac->ac_ipaddr.s_addr) { /* * This test used to be * if (loif.if_flags & IFF_UP) * It allowed local traffic to be forced * through the hardware by configuring the loopback down. * However, it causes problems during network configuration * for boards that can't receive packets they send. * It is now necessary to clear "useloopback" * to force traffic out to the hardware. */ if (useloopback) { sin.sin_family = AF_INET; sin.sin_addr = *destip; (void) looutput(&loif, m, (struct sockaddr *)&sin); /* * The packet has already been sent and freed. */ return (0); } else { bcopy((caddr_t)ac->ac_enaddr, (caddr_t)desten, sizeof(ac->ac_enaddr)); return (1); } } s = splimp(); ARPTAB_LOOK(at, destip->s_addr); if (at == 0) { /* not found */ if (ac->ac_if.if_flags & IFF_NOARP) { bcopy((caddr_t)ac->ac_enaddr, (caddr_t)desten, 3); desten[3] = (lna >> 16) & 0x7f; desten[4] = (lna >> 8) & 0xff; desten[5] = lna & 0xff; splx(s); return (1); } else { at = arptnew(destip); if (at == 0) panic("arpresolve: no free entry"); at->at_hold = m; arpwhohas(ac, destip); splx(s); return (0); } } at->at_timer = 0; /* restart the timer */ if (at->at_flags & ATF_COM) { /* entry IS complete */ bcopy((caddr_t)at->at_enaddr, (caddr_t)desten, sizeof(at->at_enaddr)); #ifdef I_WANT_MY_MACHINE_TO_CRASH if (at->at_flags & ATF_USETRAILERS) *usetrailers = 1; #endif splx(s); return (1); } /* * There is an arptab entry, but no ethernet address * response yet. Replace the held mbuf with this * latest one. */ if (at->at_hold) m_freem(at->at_hold); at->at_hold = m; arpwhohas(ac, destip); /* ask again */ splx(s); return (0); } /* * Called from 10 Mb/s Ethernet interrupt handlers * when ether packet type ETHERTYPE_ARP * is received. Common length and type checks are done here, * then the protocol-specific routine is called. */ arpinput(ac, m) struct arpcom *ac; struct mbuf *m; { register struct arphdr *ar; if (ac->ac_if.if_flags & IFF_NOARP) goto out; IF_ADJ(m); if (m->m_len < sizeof(struct arphdr)) goto out; ar = mtod(m, struct arphdr *); if (ntohs(ar->ar_hrd) != ARPHRD_ETHER) goto out; if (m->m_len < sizeof(struct arphdr) + 2 * ar->ar_hln + 2 * ar->ar_pln) goto out; switch (ntohs(ar->ar_pro)) { case ETHERTYPE_IP: case ETHERTYPE_IPTRAILERS: in_arpinput(ac, m); return; default: break; } out: m_freem(m); } /* * ARP for Internet protocols on 10 Mb/s Ethernet. * Algorithm is that given in RFC 826. * In addition, a sanity check is performed on the sender * protocol address, to catch impersonators. * We also handle negotiations for use of trailer protocol: * ARP replies for protocol type ETHERTYPE_TRAIL are sent * along with IP replies if we want trailers sent to us, * and also send them in response to IP replies. * This allows either end to announce the desire to receive * trailer packets. * We reply to requests for ETHERTYPE_TRAIL protocol as well, * but don't normally send requests. */ in_arpinput(ac, m) register struct arpcom *ac; struct mbuf *m; { register struct ether_arp *ea; struct ether_header *eh; register struct arptab *at; /* same as "merge" flag */ struct mbuf *mcopy = 0; struct sockaddr_in sin; struct sockaddr sa; struct in_addr isaddr, itaddr, myaddr; int proto, op, s, completed = 0; myaddr = ac->ac_ipaddr; ea = mtod(m, struct ether_arp *); proto = ntohs(ea->arp_pro); op = ntohs(ea->arp_op); bcopy((caddr_t)ea->arp_spa, (caddr_t)&isaddr, sizeof (isaddr)); bcopy((caddr_t)ea->arp_tpa, (caddr_t)&itaddr, sizeof (itaddr)); if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr, sizeof (ea->arp_sha))) goto out; /* it's from me, ignore it. */ if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)etherbroadcastaddr, sizeof (ea->arp_sha))) { printf("arp: ether address is broadcast for IP address %x!\n", ntohl(isaddr.s_addr)); goto out; } if (isaddr.s_addr == myaddr.s_addr) { printf("%s: %s\n", "duplicate IP address!! sent from ethernet address", ether_sprintf(ea->arp_sha)); itaddr = myaddr; if (op == ARPOP_REQUEST) goto reply; goto out; } s = splimp(); ARPTAB_LOOK(at, isaddr.s_addr); if (at) { bcopy((caddr_t)ea->arp_sha, (caddr_t)at->at_enaddr, sizeof(ea->arp_sha)); if ((at->at_flags & ATF_COM) == 0) completed = 1; at->at_flags |= ATF_COM; if (at->at_hold) { sin.sin_family = AF_INET; sin.sin_addr = isaddr; (*ac->ac_if.if_output)(&ac->ac_if, at->at_hold, (struct sockaddr *)&sin); at->at_hold = 0; } } if (at == 0 && itaddr.s_addr == myaddr.s_addr) { /* ensure we have a table entry */ if (at = arptnew(&isaddr)) { bcopy((caddr_t)ea->arp_sha, (caddr_t)at->at_enaddr, sizeof(ea->arp_sha)); completed = 1; at->at_flags |= ATF_COM; } } splx(s); reply: switch (proto) { case ETHERTYPE_IPTRAILERS: /* partner says trailers are OK */ if (at) at->at_flags |= ATF_USETRAILERS; /* * Reply to request iff we want trailers. */ if (op != ARPOP_REQUEST || ac->ac_if.if_flags & IFF_NOTRAILERS) goto out; break; case ETHERTYPE_IP: /* * Reply if this is an IP request, * or if we want to send a trailer response. * Send the latter only to the IP response * that completes the current ARP entry. */ if (op != ARPOP_REQUEST && (completed == 0 || ac->ac_if.if_flags & IFF_NOTRAILERS)) goto out; } if (itaddr.s_addr == myaddr.s_addr) { /* I am the target */ bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha, sizeof(ea->arp_sha)); bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha, sizeof(ea->arp_sha)); } else { ARPTAB_LOOK(at, itaddr.s_addr); if (at == NULL || (at->at_flags & ATF_PUBL) == 0) goto out; bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha, sizeof(ea->arp_sha)); bcopy((caddr_t)at->at_enaddr, (caddr_t)ea->arp_sha, sizeof(ea->arp_sha)); } bcopy((caddr_t)ea->arp_spa, (caddr_t)ea->arp_tpa, sizeof(ea->arp_spa)); bcopy((caddr_t)&itaddr, (caddr_t)ea->arp_spa, sizeof(ea->arp_spa)); ea->arp_op = htons(ARPOP_REPLY); /* * If incoming packet was an IP reply, * we are sending a reply for type IPTRAILERS. * If we are sending a reply for type IP * and we want to receive trailers, * send a trailer reply as well. */ if (op == ARPOP_REPLY) ea->arp_pro = htons(ETHERTYPE_IPTRAILERS); else if (proto == ETHERTYPE_IP && (ac->ac_if.if_flags & IFF_NOTRAILERS) == 0) mcopy = m_copy(m, 0, (int)M_COPYALL); eh = (struct ether_header *)sa.sa_data; bcopy((caddr_t)ea->arp_tha, (caddr_t)eh->ether_dhost, sizeof(eh->ether_dhost)); eh->ether_type = ETHERTYPE_ARP; sa.sa_family = AF_UNSPEC; (*ac->ac_if.if_output)(&ac->ac_if, m, &sa); if (mcopy) { ea = mtod(mcopy, struct ether_arp *); ea->arp_pro = htons(ETHERTYPE_IPTRAILERS); (*ac->ac_if.if_output)(&ac->ac_if, mcopy, &sa); } return; out: m_freem(m); return; } /* * Free an arptab entry. */ arptfree(at) register struct arptab *at; { int s = splimp(); if (at->at_hold) m_freem(at->at_hold); at->at_hold = 0; at->at_timer = at->at_flags = 0; at->at_iaddr.s_addr = 0; splx(s); } /* * Enter a new address in arptab, pushing out the oldest entry * from the bucket if there is no room. * This always succeeds since no bucket can be completely filled * with permanent entries (except from arpioctl when testing whether * another permanent entry will fit). * MUST BE CALLED AT SPLIMP. */ struct arptab * arptnew(addr) struct in_addr *addr; { register n; int oldest = -1; register struct arptab *at, *ato = NULL; static int first = 1; if (first) { first = 0; TIMEOUT(arptimer, (caddr_t)0, hz); } at = &arptab[ARPTAB_HASH(addr->s_addr) * ARPTAB_BSIZ]; for (n = 0; n < ARPTAB_BSIZ; n++,at++) { if (at->at_flags == 0) goto out; /* found an empty entry */ if (at->at_flags & ATF_PERM) continue; if ((int) at->at_timer > oldest) { oldest = at->at_timer; ato = at; } } if (ato == NULL) return (NULL); at = ato; arptfree(at); out: at->at_iaddr = *addr; at->at_flags = ATF_INUSE; return (at); } arpioctl(cmd, data) int cmd; caddr_t data; { register struct arpreq *ar = (struct arpreq *)data; register struct arptab *at; register struct sockaddr_in *sin; int s; if (ar->arp_pa.sa_family != AF_INET || ar->arp_ha.sa_family != AF_UNSPEC) return (EAFNOSUPPORT); sin = (struct sockaddr_in *)&ar->arp_pa; s = splimp(); ARPTAB_LOOK(at, sin->sin_addr.s_addr); if (at == NULL) { /* not found */ if (cmd != SIOCSARP) { splx(s); return (ENXIO); } if (ifa_ifwithnet(&ar->arp_pa) == NULL) { splx(s); return (ENETUNREACH); } } switch (cmd) { case SIOCSARP: /* set entry */ if (at == NULL) { at = arptnew(&sin->sin_addr); if (at == NULL) { splx(s); return (EADDRNOTAVAIL); } if (ar->arp_flags & ATF_PERM) { /* never make all entries in a bucket permanent */ register struct arptab *tat; /* try to re-allocate */ tat = arptnew(&sin->sin_addr); if (tat == NULL) { arptfree(at); splx(s); return (EADDRNOTAVAIL); } arptfree(tat); } } bcopy((caddr_t)ar->arp_ha.sa_data, (caddr_t)at->at_enaddr, sizeof(at->at_enaddr)); at->at_flags = ATF_COM | ATF_INUSE | (ar->arp_flags & (ATF_PERM|ATF_PUBL|ATF_USETRAILERS)); at->at_timer = 0; break; case SIOCDARP: /* delete entry */ arptfree(at); break; case SIOCGARP: /* get entry */ bcopy((caddr_t)at->at_enaddr, (caddr_t)ar->arp_ha.sa_data, sizeof(at->at_enaddr)); ar->arp_flags = at->at_flags; break; } splx(s); return (0); } /* * Convert Ethernet address to printable (loggable) representation. */ char * ether_sprintf(ap) register u_char *ap; { register i; static char etherbuf[18]; register char *cp = etherbuf; static char digits[] = "0123456789abcdef"; for (i = 0; i < 6; i++) { *cp++ = digits[*ap >> 4]; *cp++ = digits[*ap++ & 0xf]; *cp++ = ':'; } *--cp = 0; return (etherbuf); } #endif n, sizeof(etherbroadcastaddr)); return (1); } lna = in_lnaof(*destip); /* if for us, use software loopback driver if up */ if (destip->s_addr == ac->ac_ipaddr.s_addr) { /* * This test used to be * if (loif.if_flags & IFF_UP) * It allowed locsys/netinet/in.c 440 0 12 24400 6036657073 7114 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)in.c 7.7.1 (2.11BSD) 1995/10/10 */ #include "param.h" #include "ioctl.h" #include "mbuf.h" #include "domain.h" #include "protosw.h" #include "socket.h" #include "socketvar.h" #include "user.h" #include "in_systm.h" #include "../net/if.h" #include "../net/route.h" #include "../net/af.h" #include "in.h" #include "in_var.h" #ifdef INET inet_hash(sin, hp) register struct sockaddr_in *sin; struct afhash *hp; { register u_long n; n = in_netof(sin->sin_addr); if (n) while ((n & 0xffL) == 0L) n >>= 8; hp->afh_nethash = n; hp->afh_hosthash = ntohl(sin->sin_addr.s_addr); } inet_netmatch(sin1, sin2) struct sockaddr_in *sin1, *sin2; { return (in_netof(sin1->sin_addr) == in_netof(sin2->sin_addr)); } /* * Formulate an Internet address from network + host. */ struct in_addr in_makeaddr(net, host) u_long net, host; { register struct in_ifaddr *ia; register u_long mask; u_long addr; if (IN_CLASSA(net)) mask = IN_CLASSA_HOST; else if (IN_CLASSB(net)) mask = IN_CLASSB_HOST; else mask = IN_CLASSC_HOST; for (ia = in_ifaddr; ia; ia = ia->ia_next) if ((ia->ia_netmask & net) == ia->ia_net) { mask = ~ia->ia_subnetmask; break; } addr = htonl(net | (host & mask)); return (*(struct in_addr *)&addr); } /* * Return the network number from an internet address. */ u_long in_netof(in) struct in_addr in; { register u_long i = ntohl(in.s_addr); register u_long net; register struct in_ifaddr *ia; if (IN_CLASSA(i)) net = i & IN_CLASSA_NET; else if (IN_CLASSB(i)) net = i & IN_CLASSB_NET; else if (IN_CLASSC(i)) net = i & IN_CLASSC_NET; else return (0); /* * Check whether network is a subnet; * if so, return subnet number. */ for (ia = in_ifaddr; ia; ia = ia->ia_next) if (net == ia->ia_net) return (i & ia->ia_subnetmask); return (net); } /* * Return the host portion of an internet address. */ u_long in_lnaof(in) struct in_addr in; { register u_long i = ntohl(in.s_addr); register u_long net, host; register struct in_ifaddr *ia; if (IN_CLASSA(i)) { net = i & IN_CLASSA_NET; host = i & IN_CLASSA_HOST; } else if (IN_CLASSB(i)) { net = i & IN_CLASSB_NET; host = i & IN_CLASSB_HOST; } else if (IN_CLASSC(i)) { net = i & IN_CLASSC_NET; host = i & IN_CLASSC_HOST; } else return (i); /* * Check whether network is a subnet; * if so, use the modified interpretation of `host'. */ for (ia = in_ifaddr; ia; ia = ia->ia_next) if (net == ia->ia_net) return (host &~ ia->ia_subnetmask); return (host); } #ifndef SUBNETSARELOCAL #define SUBNETSARELOCAL 1 #endif int subnetsarelocal = SUBNETSARELOCAL; /* * Return 1 if an internet address is for a ``local'' host * (one to which we have a connection). If subnetsarelocal * is true, this includes other subnets of the local net. * Otherwise, it includes only the directly-connected (sub)nets. */ in_localaddr(in) struct in_addr in; { register u_long i = ntohl(in.s_addr); register struct in_ifaddr *ia; if (subnetsarelocal) { for (ia = in_ifaddr; ia; ia = ia->ia_next) if ((i & ia->ia_netmask) == ia->ia_net) return (1); } else { for (ia = in_ifaddr; ia; ia = ia->ia_next) if ((i & ia->ia_subnetmask) == ia->ia_subnet) return (1); } return (0); } /* * Determine whether an IP address is in a reserved set of addresses * that may not be forwarded, or whether datagrams to that destination * may be forwarded. */ in_canforward(in) struct in_addr in; { register u_long i = ntohl(in.s_addr); register u_long net; if (IN_EXPERIMENTAL(i)) return (0); if (IN_CLASSA(i)) { net = i & IN_CLASSA_NET; if (net == 0 || net == IN_LOOPBACKNET) return (0); } return (1); } extern struct ifnet loif; /* * Generic internet control operations (ioctl's). * Ifp is 0 if not an interface-specific ioctl. */ /* ARGSUSED */ in_control(so, cmd, data, ifp) struct socket *so; int cmd; caddr_t data; register struct ifnet *ifp; { register struct ifreq *ifr = (struct ifreq *)data; register struct in_ifaddr *ia = 0; struct ifaddr *ifa; struct mbuf *m; int error; /* * Find address for this interface, if it exists. */ if (ifp) for (ia = in_ifaddr; ia; ia = ia->ia_next) if (ia->ia_ifp == ifp) break; switch (cmd) { case SIOCSIFADDR: case SIOCSIFNETMASK: case SIOCSIFDSTADDR: if (!suser()) return (u.u_error); if (ifp == 0) panic("in_control"); if (ia == (struct in_ifaddr *)0) { m = m_getclr(M_WAIT, MT_IFADDR); if (m == (struct mbuf *)NULL) return (ENOBUFS); if (ia = in_ifaddr) { for ( ; ia->ia_next; ia = ia->ia_next) ; ia->ia_next = mtod(m, struct in_ifaddr *); } else in_ifaddr = mtod(m, struct in_ifaddr *); ia = mtod(m, struct in_ifaddr *); if (ifa = ifp->if_addrlist) { for ( ; ifa->ifa_next; ifa = ifa->ifa_next) ; ifa->ifa_next = (struct ifaddr *) ia; } else ifp->if_addrlist = (struct ifaddr *) ia; ia->ia_ifp = ifp; IA_SIN(ia)->sin_family = AF_INET; } break; case SIOCSIFBRDADDR: if (!suser()) return (u.u_error); /* FALLTHROUGH */ default: if (ia == (struct in_ifaddr *)0) return (EADDRNOTAVAIL); break; } switch (cmd) { case SIOCGIFADDR: ifr->ifr_addr = ia->ia_addr; break; case SIOCGIFBRDADDR: if ((ifp->if_flags & IFF_BROADCAST) == 0) return (EINVAL); ifr->ifr_dstaddr = ia->ia_broadaddr; break; case SIOCGIFDSTADDR: if ((ifp->if_flags & IFF_POINTOPOINT) == 0) return (EINVAL); ifr->ifr_dstaddr = ia->ia_dstaddr; break; case SIOCGIFNETMASK: #define satosin(sa) ((struct sockaddr_in *)(sa)) satosin(&ifr->ifr_addr)->sin_family = AF_INET; satosin(&ifr->ifr_addr)->sin_addr.s_addr = htonl(ia->ia_subnetmask); break; case SIOCSIFDSTADDR: { struct sockaddr oldaddr; if ((ifp->if_flags & IFF_POINTOPOINT) == 0) return (EINVAL); oldaddr = ia->ia_dstaddr; ia->ia_dstaddr = ifr->ifr_dstaddr; if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) { ia->ia_dstaddr = oldaddr; return (error); } if (ia->ia_flags & IFA_ROUTE) { rtinit(&oldaddr, &ia->ia_addr, (int)SIOCDELRT, RTF_HOST); rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT, RTF_HOST|RTF_UP); } } break; case SIOCSIFBRDADDR: if ((ifp->if_flags & IFF_BROADCAST) == 0) return (EINVAL); ia->ia_broadaddr = ifr->ifr_broadaddr; break; case SIOCSIFADDR: return (in_ifinit(ifp, ia, &ifr->ifr_addr)); case SIOCSIFNETMASK: ia->ia_subnetmask = ntohl(satosin(&ifr->ifr_addr)->sin_addr.s_addr); break; default: if (ifp == 0 || ifp->if_ioctl == 0) return (EOPNOTSUPP); return ((*ifp->if_ioctl)(ifp, cmd, data)); } return (0); } /* * Initialize an interface's internet address * and routing table entry. */ in_ifinit(ifp, ia, sin) register struct ifnet *ifp; register struct in_ifaddr *ia; struct sockaddr_in *sin; { register u_long i = ntohl(sin->sin_addr.s_addr); struct sockaddr oldaddr; struct sockaddr_in netaddr; int s = splimp(), error; oldaddr = ia->ia_addr; ia->ia_addr = *(struct sockaddr *)sin; /* * Give the interface a chance to initialize * if this is its first address, * and to validate the address if necessary. */ if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { splx(s); ia->ia_addr = oldaddr; return (error); } /* * Delete any previous route for an old address. */ bzero((caddr_t)&netaddr, sizeof (netaddr)); netaddr.sin_family = AF_INET; if (ia->ia_flags & IFA_ROUTE) { if (ifp->if_flags & IFF_LOOPBACK) rtinit(&oldaddr, &oldaddr, (int)SIOCDELRT, RTF_HOST); else if (ifp->if_flags & IFF_POINTOPOINT) rtinit(&ia->ia_dstaddr, &oldaddr, (int)SIOCDELRT, RTF_HOST); else { netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY); rtinit((struct sockaddr *)&netaddr, &oldaddr, (int)SIOCDELRT, 0); } ia->ia_flags &= ~IFA_ROUTE; } if (IN_CLASSA(i)) ia->ia_netmask = IN_CLASSA_NET; else if (IN_CLASSB(i)) ia->ia_netmask = IN_CLASSB_NET; else ia->ia_netmask = IN_CLASSC_NET; ia->ia_net = i & ia->ia_netmask; /* * The subnet mask includes at least the standard network part, * but may already have been set to a larger value. */ ia->ia_subnetmask |= ia->ia_netmask; ia->ia_subnet = i & ia->ia_subnetmask; if (ifp->if_flags & IFF_BROADCAST) { ia->ia_broadaddr.sa_family = AF_INET; ((struct sockaddr_in *)(&ia->ia_broadaddr))->sin_addr = in_makeaddr(ia->ia_subnet, INADDR_BROADCAST); ia->ia_netbroadcast.s_addr = htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask)); } /* * Add route for the network. */ if (ifp->if_flags & IFF_LOOPBACK) rtinit(&ia->ia_addr, &ia->ia_addr, (int)SIOCADDRT, RTF_HOST|RTF_UP); else if (ifp->if_flags & IFF_POINTOPOINT) rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT, RTF_HOST|RTF_UP); else { netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY); rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, (int)SIOCADDRT, RTF_UP); } ia->ia_flags |= IFA_ROUTE; splx(s); return (0); } /* * Return address info for specified internet network. */ struct in_ifaddr * in_iaonnetof(net) u_long net; { register struct in_ifaddr *ia; for (ia = in_ifaddr; ia; ia = ia->ia_next) if (ia->ia_subnet == net) return (ia); return ((struct in_ifaddr *)0); } /* * Return 1 if the address might be a local broadcast address. */ in_broadcast(in) struct in_addr in; { register struct in_ifaddr *ia; u_long t; /* * Look through the list of addresses for a match * with a broadcast address. */ for (ia = in_ifaddr; ia; ia = ia->ia_next) if (ia->ia_ifp->if_flags & IFF_BROADCAST) { if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr == in.s_addr) return (1); /* * Check for old-style (host 0) broadcast. */ if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net) return (1); } if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY) return (1); return (0); } #endif number from an internet address. */ u_long in_netof(in) struct in_addr in; { register u_long i = ntohl(in.s_addr); register u_long net; register struct in_ifaddr *ia; if (IN_CLASSA(i)) net = i & IN_CLASSA_NET; else if (IN_CLASSB(i)) net = i & Isys/netinet/in_pcb.c 444 0 0 24573 5531762045 7727 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)in_pcb.c 7.6.1 (2.11BSD GTE) 2/20/94 */ #include "param.h" #include "systm.h" #include "user.h" #include "mbuf.h" #include "socket.h" #include "socketvar.h" #include "ioctl.h" #include "domain.h" #include "protosw.h" #include "in.h" #include "in_systm.h" #include "../net/if.h" #include "../net/route.h" #include "in_pcb.h" #include "in_var.h" #include "kernel.h" struct in_addr zeroin_addr; in_pcballoc(so, head) struct socket *so; struct inpcb *head; { struct mbuf *m; register struct inpcb *inp; m = m_getclr(M_DONTWAIT, MT_PCB); if (m == NULL) return (ENOBUFS); inp = mtod(m, struct inpcb *); inp->inp_head = head; inp->inp_socket = so; insque(inp, head); so->so_pcb = (caddr_t)inp; return (0); } in_pcbbind(inp, nam) register struct inpcb *inp; struct mbuf *nam; { register struct socket *so = inp->inp_socket; register struct inpcb *head = inp->inp_head; register struct sockaddr_in *sin; u_short lport = 0; int wild = 0; if (in_ifaddr == 0) return (EADDRNOTAVAIL); if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY) return (EINVAL); if ((so->so_options & SO_REUSEADDR) == 0 && ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 || (so->so_options & SO_ACCEPTCONN) == 0)) wild = INPLOOKUP_WILDCARD; if (nam == 0) goto noname; sin = mtod(nam, struct sockaddr_in *); if (nam->m_len != sizeof (*sin)) return (EINVAL); if (sin->sin_addr.s_addr != INADDR_ANY) { int tport = sin->sin_port; sin->sin_port = 0; /* yech... */ if (ifa_ifwithaddr((struct sockaddr *)sin) == 0) return (EADDRNOTAVAIL); sin->sin_port = tport; } lport = sin->sin_port; if (lport) { u_short aport = ntohs(lport); /* GROSS */ if (aport < IPPORT_RESERVED && u.u_uid != 0) return (EACCES); if (in_pcblookup(head, zeroin_addr, 0, sin->sin_addr, lport, wild)) return (EADDRINUSE); } inp->inp_laddr = sin->sin_addr; noname: if (lport == 0) do { if (head->inp_lport++ < IPPORT_RESERVED || head->inp_lport > IPPORT_USERRESERVED) head->inp_lport = IPPORT_RESERVED; lport = htons(head->inp_lport); } while (in_pcblookup(head, zeroin_addr, 0, inp->inp_laddr, lport, 0)); inp->inp_lport = lport; return (0); } /* * Connect from a socket to a specified address. * Both address and port must be specified in argument sin. * If don't have a local address for this socket yet, * then pick one. */ in_pcbconnect(inp, nam) register struct inpcb *inp; struct mbuf *nam; { struct in_ifaddr *ia; struct sockaddr_in *ifaddr; register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); if (nam->m_len != sizeof (*sin)) return (EINVAL); if (sin->sin_family != AF_INET) return (EAFNOSUPPORT); if (sin->sin_port == 0) return (EADDRNOTAVAIL); if (in_ifaddr) { /* * If the destination address is INADDR_ANY, * use the primary local address. * If the supplied address is INADDR_BROADCAST, * and the primary interface supports broadcast, * choose the broadcast address for that interface. */ #define satosin(sa) ((struct sockaddr_in *)(sa)) if (sin->sin_addr.s_addr == INADDR_ANY) sin->sin_addr = IA_SIN(in_ifaddr)->sin_addr; else if (sin->sin_addr.s_addr == (u_long)INADDR_BROADCAST && (in_ifaddr->ia_ifp->if_flags & IFF_BROADCAST)) sin->sin_addr = satosin(&in_ifaddr->ia_broadaddr)->sin_addr; } if (inp->inp_laddr.s_addr == INADDR_ANY) { register struct route *ro; struct ifnet *ifp; ia = (struct in_ifaddr *)0; /* * If route is known or can be allocated now, * our src addr is taken from the i/f, else punt. */ ro = &inp->inp_route; if (ro->ro_rt && (satosin(&ro->ro_dst)->sin_addr.s_addr != sin->sin_addr.s_addr || inp->inp_socket->so_options & SO_DONTROUTE)) { RTFREE(ro->ro_rt); ro->ro_rt = (struct rtentry *)0; } if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/ (ro->ro_rt == (struct rtentry *)0 || ro->ro_rt->rt_ifp == (struct ifnet *)0)) { /* No route yet, so try to acquire one */ ro->ro_dst.sa_family = AF_INET; ((struct sockaddr_in *) &ro->ro_dst)->sin_addr = sin->sin_addr; rtalloc(ro); } /* * If we found a route, use the address * corresponding to the outgoing interface * unless it is the loopback (in case a route * to our address on another net goes to loopback). */ if (ro->ro_rt && (ifp = ro->ro_rt->rt_ifp) && (ifp->if_flags & IFF_LOOPBACK) == 0) for (ia = in_ifaddr; ia; ia = ia->ia_next) if (ia->ia_ifp == ifp) break; if (ia == 0) { int fport = sin->sin_port; sin->sin_port = 0; ia = (struct in_ifaddr *) ifa_ifwithdstaddr((struct sockaddr *)sin); sin->sin_port = fport; if (ia == 0) ia = in_iaonnetof(in_netof(sin->sin_addr)); if (ia == 0) ia = in_ifaddr; if (ia == 0) return (EADDRNOTAVAIL); } ifaddr = (struct sockaddr_in *)&ia->ia_addr; } if (in_pcblookup(inp->inp_head, sin->sin_addr, sin->sin_port, inp->inp_laddr.s_addr ? inp->inp_laddr.s_addr : ifaddr->sin_addr.s_addr, inp->inp_lport, 0)) return (EADDRINUSE); if (inp->inp_laddr.s_addr == INADDR_ANY) { if (inp->inp_lport == 0) (void)in_pcbbind(inp, (struct mbuf *)0); inp->inp_laddr = ifaddr->sin_addr; } inp->inp_faddr = sin->sin_addr; inp->inp_fport = sin->sin_port; return (0); } in_pcbdisconnect(inp) struct inpcb *inp; { inp->inp_faddr.s_addr = INADDR_ANY; inp->inp_fport = 0; if (inp->inp_socket->so_state & SS_NOFDREF) in_pcbdetach(inp); } in_pcbdetach(inp) struct inpcb *inp; { struct socket *so = inp->inp_socket; so->so_pcb = 0; sofree(so); if (inp->inp_options) (void)m_free(inp->inp_options); if (inp->inp_route.ro_rt) rtfree(inp->inp_route.ro_rt); remque(inp); (void) m_free(dtom(inp)); } in_setsockaddr(inp, nam) register struct inpcb *inp; struct mbuf *nam; { register struct sockaddr_in *sin; nam->m_len = sizeof (*sin); sin = mtod(nam, struct sockaddr_in *); bzero((caddr_t)sin, sizeof (*sin)); sin->sin_family = AF_INET; sin->sin_port = inp->inp_lport; sin->sin_addr = inp->inp_laddr; } in_setpeeraddr(inp, nam) struct inpcb *inp; struct mbuf *nam; { register struct sockaddr_in *sin; nam->m_len = sizeof (*sin); sin = mtod(nam, struct sockaddr_in *); bzero((caddr_t)sin, sizeof (*sin)); sin->sin_family = AF_INET; sin->sin_port = inp->inp_fport; sin->sin_addr = inp->inp_faddr; } /* * Pass some notification to all connections of a protocol * associated with address dst. The local address and/or port numbers * may be specified to limit the search. The "usual action" will be * taken, depending on the ctlinput cmd. The caller must filter any * cmds that are uninteresting (e.g., no error in the map). * Call the protocol specific routine (if any) to report * any errors for each matching socket. * * Must be called at splnet. */ in_pcbnotify(head, dst, fport, laddr, lport, cmd, notify) struct inpcb *head; struct sockaddr *dst; u_short fport, lport; struct in_addr laddr; int cmd, (*notify)(); { register struct inpcb *inp, *oinp; struct in_addr faddr; int errno; int in_rtchange(); extern u_char inetctlerrmap[]; if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET) return; faddr = ((struct sockaddr_in *)dst)->sin_addr; if (faddr.s_addr == INADDR_ANY) return; /* * Redirects go to all references to the destination, * and use in_rtchange to invalidate the route cache. * Dead host indications: notify all references to the destination. * Otherwise, if we have knowledge of the local port and address, * deliver only to that socket. */ if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) { fport = 0; lport = 0; laddr.s_addr = 0; if (cmd != PRC_HOSTDEAD) notify = in_rtchange; } errno = inetctlerrmap[cmd]; for (inp = head->inp_next; inp != head;) { if (inp->inp_faddr.s_addr != faddr.s_addr || inp->inp_socket == 0 || (lport && inp->inp_lport != lport) || (laddr.s_addr && inp->inp_laddr.s_addr != laddr.s_addr) || (fport && inp->inp_fport != fport)) { inp = inp->inp_next; continue; } oinp = inp; inp = inp->inp_next; if (notify) (*notify)(oinp, errno); } } /* * Check for alternatives when higher level complains * about service problems. For now, invalidate cached * routing information. If the route was created dynamically * (by a redirect), time to try a default gateway again. */ in_losing(inp) struct inpcb *inp; { register struct rtentry *rt; if ((rt = inp->inp_route.ro_rt)) { if (rt->rt_flags & RTF_DYNAMIC) (void) rtrequest((int)SIOCDELRT, rt); rtfree(rt); inp->inp_route.ro_rt = 0; /* * A new route can be allocated * the next time output is attempted. */ } } /* * After a routing change, flush old routing * and allocate a (hopefully) better one. */ in_rtchange(inp) register struct inpcb *inp; { if (inp->inp_route.ro_rt) { rtfree(inp->inp_route.ro_rt); inp->inp_route.ro_rt = 0; /* * A new route can be allocated the next time * output is attempted. */ } } struct inpcb * in_pcblookup(head, faddr, fport, laddr, lport, flags) struct inpcb *head; struct in_addr faddr, laddr; u_short fport, lport; int flags; { register struct inpcb *inp, *match = 0; int matchwild = 3, wildcard; for (inp = head->inp_next; inp != head; inp = inp->inp_next) { if (inp->inp_lport != lport) continue; wildcard = 0; if (inp->inp_laddr.s_addr != INADDR_ANY) { if (laddr.s_addr == INADDR_ANY) wildcard++; else if (inp->inp_laddr.s_addr != laddr.s_addr) continue; } else { if (laddr.s_addr != INADDR_ANY) wildcard++; } if (inp->inp_faddr.s_addr != INADDR_ANY) { if (faddr.s_addr == INADDR_ANY) wildcard++; else if (inp->inp_faddr.s_addr != faddr.s_addr || inp->inp_fport != fport) continue; } else { if (faddr.s_addr != INADDR_ANY) wildcard++; } if (wildcard && (flags & INPLOOKUP_WILDCARD) == 0) continue; if (wildcard < matchwild) { match = inp; matchwild = wildcard; if (matchwild == 0) break; } } return (match); } register struct inpcb *inp; struct mbuf *nam; { struct in_ifaddr *ia; struct sockaddr_in *ifaddr; register struct sockaddr_in *sys/netinet/ip_icmp.c 444 0 0 26616 6036654771 10124 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)ip_icmp.c 7.7.2 (2.11BSD GTE) 1995/10/10 */ #include "param.h" #include "systm.h" #include "mbuf.h" #include "protosw.h" #include "socket.h" #include "time.h" #include "kernel.h" #include "errno.h" #include "../net/route.h" #include "../net/if.h" #include "domain.h" #include "in.h" #include "in_systm.h" #include "in_var.h" #include "ip.h" #include "ip_icmp.h" #include "icmp_var.h" extern int icmpmaskrepl; #ifdef ICMPPRINTFS /* * ICMP routines: error generation, receive packet processing, and * routines to turnaround packets back to the originator, and * host table maintenance routines. */ int icmpprintfs = 0; #endif /* * Generate an error packet of type error * in response to bad packet ip. */ /*VARARGS4*/ icmp_error(oip, type, code, ifp, dest) struct ip *oip; int type, code; struct ifnet *ifp; struct in_addr dest; { register unsigned oiplen = oip->ip_hl << 2; register struct icmp *icp; struct mbuf *m; struct ip *nip; unsigned icmplen; #ifdef ICMPPRINTFS if (icmpprintfs) printf("icmp_error(%x, %d, %d)\n", oip, type, code); #endif if (type != ICMP_REDIRECT) icmpstat.icps_error++; /* * Don't send error if not the first fragment of message. * Don't error if the old packet protocol was ICMP * error message, only known informational types. */ if (oip->ip_off &~ (IP_MF|IP_DF)) goto free; if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT && !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiplen))->icmp_type)) { icmpstat.icps_oldicmp++; goto free; } /* * First, formulate icmp message */ m = m_get(M_DONTWAIT, MT_HEADER); if (m == NULL) goto free; icmplen = oiplen + MIN(8, oip->ip_len); m->m_len = icmplen + ICMP_MINLEN; m->m_off = MMAXOFF - m->m_len; icp = mtod(m, struct icmp *); if ((u_int)type > ICMP_MAXTYPE) panic("icmp_error"); icmpstat.icps_outhist[type]++; icp->icmp_type = type; if (type == ICMP_REDIRECT) icp->icmp_gwaddr = dest; else icp->icmp_void = 0; if (type == ICMP_PARAMPROB) { icp->icmp_pptr = code; code = 0; } icp->icmp_code = code; bcopy((caddr_t)oip, (caddr_t)&icp->icmp_ip, icmplen); nip = &icp->icmp_ip; nip->ip_len += oiplen; nip->ip_len = htons((u_short)nip->ip_len); /* * Now, copy old ip header in front of icmp message. */ if (m->m_len + oiplen > MLEN) oiplen = sizeof(struct ip); if (m->m_len + oiplen > MLEN) panic("icmp len"); m->m_off -= oiplen; m->m_len += oiplen; nip = mtod(m, struct ip *); bcopy((caddr_t)oip, (caddr_t)nip, oiplen); nip->ip_len = m->m_len; nip->ip_p = IPPROTO_ICMP; icmp_reflect(nip, ifp); free: m_freem(dtom(oip)); } static struct sockproto icmproto = { AF_INET, IPPROTO_ICMP }; static struct sockaddr_in icmpsrc = { AF_INET }; static struct sockaddr_in icmpdst = { AF_INET }; static struct sockaddr_in icmpgw = { AF_INET }; struct in_ifaddr *ifptoia(); /* * Process a received ICMP message. */ icmp_input(m, ifp) register struct mbuf *m; struct ifnet *ifp; { register struct icmp *icp; register struct ip *ip = mtod(m, struct ip *); int icmplen = ip->ip_len, hlen = ip->ip_hl << 2; register int i; struct in_ifaddr *ia; int (*ctlfunc)(), code; extern u_char ip_protox[]; extern struct in_addr in_makeaddr(); /* * Locate icmp structure in mbuf, and check * that not corrupted and of at least minimum length. */ #ifdef ICMPPRINTFS if (icmpprintfs) printf("icmp_input src %X len %d", ntohl(ip->ip_src), icmplen); #endif if (icmplen < ICMP_MINLEN) { icmpstat.icps_tooshort++; goto free; } i = hlen + MIN(icmplen, ICMP_ADVLENMIN); if ((m->m_off > MMAXOFF || m->m_len < i) && (m = m_pullup(m, i)) == 0) { icmpstat.icps_tooshort++; return; } ip = mtod(m, struct ip *); m->m_len -= hlen; m->m_off += hlen; icp = mtod(m, struct icmp *); if (in_cksum(m, icmplen)) { icmpstat.icps_checksum++; goto free; } m->m_len += hlen; m->m_off -= hlen; #ifdef ICMPPRINTFS /* * Message type specific processing. */ if (icmpprintfs) printf("icmp_input, type %d code %d\n", icp->icmp_type, icp->icmp_code); #endif if (icp->icmp_type > ICMP_MAXTYPE) goto raw; icmpstat.icps_inhist[icp->icmp_type]++; code = icp->icmp_code; switch (icp->icmp_type) { case ICMP_UNREACH: if (code > 5) goto badcode; code += PRC_UNREACH_NET; goto deliver; case ICMP_TIMXCEED: if (code > 1) goto badcode; code += PRC_TIMXCEED_INTRANS; goto deliver; case ICMP_PARAMPROB: if (code) goto badcode; code = PRC_PARAMPROB; goto deliver; case ICMP_SOURCEQUENCH: if (code) goto badcode; code = PRC_QUENCH; deliver: /* * Problem with datagram; advise higher level routines. */ icp->icmp_ip.ip_len = ntohs((u_short)icp->icmp_ip.ip_len); if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp)) { icmpstat.icps_badlen++; goto free; } #ifdef ICMPPRINTFS if (icmpprintfs) printf("deliver to protocol %d\n", icp->icmp_ip.ip_p); #endif icmpsrc.sin_addr = icp->icmp_ip.ip_dst; if (ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput) (*ctlfunc)(code, (struct sockaddr *)&icmpsrc, (caddr_t)&icp->icmp_ip); break; badcode: icmpstat.icps_badcode++; break; case ICMP_ECHO: icp->icmp_type = ICMP_ECHOREPLY; goto reflect; case ICMP_TSTAMP: if (icmplen < ICMP_TSLEN) { icmpstat.icps_badlen++; break; } icp->icmp_type = ICMP_TSTAMPREPLY; icp->icmp_rtime = iptime(); icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */ goto reflect; case ICMP_IREQ: #define satosin(sa) ((struct sockaddr_in *)(sa)) if (in_netof(ip->ip_src) == 0 && (ia = ifptoia(ifp))) ip->ip_src = in_makeaddr(in_netof(IA_SIN(ia)->sin_addr), in_lnaof(ip->ip_src)); icp->icmp_type = ICMP_IREQREPLY; goto reflect; case ICMP_MASKREQ: if (icmpmaskrepl == 0) break; /* * We are not able to respond with all ones broadcast * unless we receive it over a point-to-point interface. * This check is a 'switch' in 4.4BSD but 2.11's C compiler * does not allow "long"s in a switch statement. */ if (icmplen < ICMP_MASKLEN || (ia = ifptoia(ifp)) == 0) break; if ((ip->ip_dst.s_addr == INADDR_BROADCAST || ip->ip_dst.s_addr == INADDR_ANY)) icmpdst.sin_addr = ip->ip_src; else icmpdst.sin_addr = ip->ip_dst; icp->icmp_type = ICMP_MASKREPLY; icp->icmp_mask = htonl(ia->ia_subnetmask); if (ip->ip_src.s_addr == 0) { if (ia->ia_ifp->if_flags & IFF_BROADCAST) ip->ip_src = satosin(&ia->ia_broadaddr)->sin_addr; else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT) ip->ip_src = satosin(&ia->ia_dstaddr)->sin_addr; } reflect: ip->ip_len += hlen; /* since ip_input deducts this */ icmpstat.icps_reflect++; icmpstat.icps_outhist[icp->icmp_type]++; icmp_reflect(ip, ifp); return; case ICMP_REDIRECT: if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp)) { icmpstat.icps_badlen++; break; } /* * Short circuit routing redirects to force * immediate change in the kernel's routing * tables. The message is also handed to anyone * listening on a raw socket (e.g. the routing * daemon for use in updating its tables). */ icmpgw.sin_addr = ip->ip_src; icmpdst.sin_addr = icp->icmp_gwaddr; #ifdef ICMPPRINTFS if (icmpprintfs) printf("redirect dst %X to %X\n", ntohl(icp->icmp_ip.ip_dst), ntohl(icp->icmp_gwaddr)); #endif if (code == ICMP_REDIRECT_NET || code == ICMP_REDIRECT_TOSNET) { icmpsrc.sin_addr = in_makeaddr(in_netof(icp->icmp_ip.ip_dst), INADDR_ANY); rtredirect((struct sockaddr *)&icmpsrc, (struct sockaddr *)&icmpdst, RTF_GATEWAY, (struct sockaddr *)&icmpgw); icmpsrc.sin_addr = icp->icmp_ip.ip_dst; pfctlinput(PRC_REDIRECT_NET, (struct sockaddr *)&icmpsrc); } else { icmpsrc.sin_addr = icp->icmp_ip.ip_dst; rtredirect((struct sockaddr *)&icmpsrc, (struct sockaddr *)&icmpdst, RTF_GATEWAY | RTF_HOST, (struct sockaddr *)&icmpgw); pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&icmpsrc); } break; /* * No kernel processing for the following; * just fall through to send to raw listener. */ case ICMP_ECHOREPLY: case ICMP_TSTAMPREPLY: case ICMP_IREQREPLY: case ICMP_MASKREPLY: default: break; } raw: icmpsrc.sin_addr = ip->ip_src; icmpdst.sin_addr = ip->ip_dst; raw_input(m, &icmproto, (struct sockaddr *)&icmpsrc, (struct sockaddr *)&icmpdst); return; free: m_freem(m); } /* * Reflect the ip packet back to the source */ icmp_reflect(ip, ifp) register struct ip *ip; struct ifnet *ifp; { register struct in_ifaddr *ia; struct in_addr t; struct mbuf *opts = 0, *ip_srcroute(); int optlen = (ip->ip_hl << 2) - sizeof(struct ip); t = ip->ip_dst; ip->ip_dst = ip->ip_src; /* * If the incoming packet was addressed directly to us, * use dst as the src for the reply. Otherwise (broadcast * or anonymous), use the address which corresponds * to the incoming interface. */ for (ia = in_ifaddr; ia; ia = ia->ia_next) { if (t.s_addr == IA_SIN(ia)->sin_addr.s_addr) break; if ((ia->ia_ifp->if_flags & IFF_BROADCAST) && t.s_addr == satosin(&ia->ia_broadaddr)->sin_addr.s_addr) break; } if (ia == (struct in_ifaddr *)0) ia = ifptoia(ifp); if (ia == (struct in_ifaddr *)0) ia = in_ifaddr; t = IA_SIN(ia)->sin_addr; ip->ip_src = t; ip->ip_ttl = MAXTTL; if (optlen > 0) { /* * Retrieve any source routing from the incoming packet * and strip out other options. Adjust the IP length. */ opts = ip_srcroute(); ip->ip_len -= optlen; ip_stripoptions(ip, (struct mbuf *)0); } icmp_send(ip, opts); if (opts) (void)m_free(opts); } struct in_ifaddr * ifptoia(ifp) struct ifnet *ifp; { register struct in_ifaddr *ia; for (ia = in_ifaddr; ia; ia = ia->ia_next) if (ia->ia_ifp == ifp) return (ia); return ((struct in_ifaddr *)0); } /* * Send an icmp packet back to the ip level, * after supplying a checksum. */ icmp_send(ip, opts) register struct ip *ip; struct mbuf *opts; { register int hlen; register struct icmp *icp; register struct mbuf *m; m = dtom(ip); hlen = ip->ip_hl << 2; m->m_off += hlen; m->m_len -= hlen; icp = mtod(m, struct icmp *); icp->icmp_cksum = 0; icp->icmp_cksum = in_cksum(m, ip->ip_len - hlen); m->m_off -= hlen; m->m_len += hlen; #ifdef ICMPPRINTFS if (icmpprintfs) printf("icmp_send dst %X src %X\n", ntohl(ip->ip_dst.s_addr), ntohl(ip->ip_src.s_addr)); #endif (void) ip_output(m, opts, (struct route *)0, 0); } n_time iptime() { struct timeval atv; int s = splhigh(); u_long t; extern struct timeval time; extern int lbolt, hz; cpfromkern(&time, &atv, sizeof(struct timeval)); t = (atv.tv_sec % (24L*60L*60L)) * 1000L + (long)mfkd(&lbolt) * 1000L / (long)hz; splx(s); return (htonl(t)); } int icmp_sysctl(name, namelen, oldp, oldlenp, newp, newlen) int *name; u_int namelen; void *oldp; size_t *oldlenp; void *newp; size_t newlen; { /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); switch (name[0]) { case ICMPCTL_MASKREPL: return (sysctl_int(oldp, oldlenp, newp, newlen, &icmpmaskrepl)); default: return (ENOPROTOOPT); } /* NOTREACHED */ } CMP_SOURCEQUENCH: if (code) goto badcode; code = PRC_QUENCH; deliver: /* * Problem with datagram; advsys/netinet/ip_input.c 444 0 0 60606 6037101311 10302 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)ip_input.c 7.9.2 (2.11BSD GTE) 1995/10/09 */ #include "param.h" #include "systm.h" #include "mbuf.h" #include "domain.h" #include "protosw.h" #include "socket.h" #include "errno.h" #include "time.h" #include "kernel.h" #include "../net/if.h" #include "../net/route.h" #include "in.h" #include "in_pcb.h" #include "in_systm.h" #include "in_var.h" #include "ip.h" #include "ip_var.h" #include "ip_icmp.h" #include "tcp.h" extern int ipforwarding, ipsendredirects, ipforward_srcrt, ip_defttl; u_char ip_protox[IPPROTO_MAX]; int ipqmaxlen = IFQ_MAXLEN; int ipprintfs = 0; struct in_ifaddr *in_ifaddr; /* first inet address */ /* * We need to save the IP options in case a protocol wants to respond * to an incoming packet over the same route if the packet got here * using IP source routing. This allows connection establishment and * maintenance when the remote end is on a network that is not known * to us. */ int ip_nhops = 0; static struct ip_srcrt { char nop; /* one NOP to align */ char srcopt[IPOPT_OFFSET + 1]; /* OPTVAL, OLEN and OFFSET */ struct in_addr route[MAX_IPOPTLEN]; } ip_srcrt; /* * IP initialization: fill in IP protocol switch table. * All protocols not implemented in kernel go to raw IP protocol handler. */ ip_init() { register struct protosw *pr; register int i; extern struct timeval time; struct timeval nettime; pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW); if (pr == 0) panic("ip_init"); for (i = 0; i < IPPROTO_MAX; i++) ip_protox[i] = pr - inetsw; for (pr = inetdomain.dom_protosw; pr < inetdomain.dom_protoswNPROTOSW; pr++) if (pr->pr_domain->dom_family == PF_INET && pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) ip_protox[pr->pr_protocol] = pr - inetsw; ipq.next = ipq.prev = &ipq; cpfromkern(&time, &nettime, sizeof (struct timeval)); ip_id = nettime.tv_sec & 0xffffL; ipintrq.ifq_maxlen = ipqmaxlen; } u_char ipcksum = 1; struct ip *ip_reass(); struct sockaddr_in ipaddr = { AF_INET }; struct route ipforward_rt; /* * Ip input routine. Checksum and byte swap header. If fragmented * try to reassamble. If complete and fragment queue exists, discard. * Process options. Pass to next level. */ ipintr() { register struct ip *ip; register struct mbuf *m; struct mbuf *m0; register int i; register struct ipq *fp; register struct in_ifaddr *ia; struct ifnet *ifp; int hlen, s; next: /* * Get next datagram off input queue and get IP header * in first mbuf. */ s = splimp(); IF_DEQUEUEIF(&ipintrq, m, ifp); splx(s); if (m == 0) return; /* * If no IP addresses have been set yet but the interfaces * are receiving, can't do anything with incoming packets yet. */ if (in_ifaddr == NULL) goto bad; ipstat.ips_total++; if ((m->m_off > MMAXOFF || m->m_len < sizeof (struct ip)) && (m = m_pullup(m, sizeof (struct ip))) == 0) { ipstat.ips_toosmall++; goto next; } ip = mtod(m, struct ip *); hlen = ip->ip_hl << 2; if (hlen < sizeof(struct ip)) { /* minimum header length */ ipstat.ips_badhlen++; goto bad; } if (hlen > m->m_len) { if ((m = m_pullup(m, hlen)) == 0) { ipstat.ips_badhlen++; goto next; } ip = mtod(m, struct ip *); } if (ipcksum) if (ip->ip_sum = in_cksum(m, hlen)) { ipstat.ips_badsum++; goto bad; } /* * Convert fields to host representation. */ ip->ip_len = ntohs((u_short)ip->ip_len); if (ip->ip_len < hlen) { ipstat.ips_badlen++; goto bad; } ip->ip_id = ntohs(ip->ip_id); ip->ip_off = ntohs((u_short)ip->ip_off); /* * Check that the amount of data in the buffers * is as at least much as the IP header would have us expect. * Trim mbufs if longer than we expect. * Drop packet if shorter than we expect. */ i = -(u_short)ip->ip_len; m0 = m; for (;;) { i += m->m_len; if (m->m_next == 0) break; m = m->m_next; } if (i != 0) { if (i < 0) { ipstat.ips_tooshort++; m = m0; goto bad; } if (i <= m->m_len) m->m_len -= i; else m_adj(m0, -i); } m = m0; /* * Process options and, if not destined for us, * ship it on. ip_dooptions returns 1 when an * error was detected (causing an icmp message * to be sent and the original packet to be freed). */ ip_nhops = 0; /* for source routed packets */ if (hlen > sizeof (struct ip) && ip_dooptions(ip, ifp)) goto next; /* * Check our list of addresses, to see if the packet is for us. */ for (ia = in_ifaddr; ia; ia = ia->ia_next) { #define satosin(sa) ((struct sockaddr_in *)(sa)) if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr) goto ours; if ( #ifdef DIRECTED_BROADCAST ia->ia_ifp == ifp && #endif (ia->ia_ifp->if_flags & IFF_BROADCAST)) { u_long t; if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr == ip->ip_dst.s_addr) goto ours; if (ip->ip_dst.s_addr == ia->ia_netbroadcast.s_addr) goto ours; /* * Look for all-0's host part (old broadcast addr), * either for subnet or net. */ t = ntohl(ip->ip_dst.s_addr); if (t == ia->ia_subnet) goto ours; if (t == ia->ia_net) goto ours; } } if (ip->ip_dst.s_addr == (u_long)INADDR_BROADCAST) goto ours; if (ip->ip_dst.s_addr == INADDR_ANY) goto ours; /* * Not for us; forward if possible and desirable. */ if (ipforwarding == 0) { ipstat.ips_cantforward++; m_freem(m); } else ip_forward(ip, ifp, 0); goto next; ours: /* * If offset or IP_MF are set, must reassemble. * Otherwise, nothing need be done. * (We could look in the reassembly queue to see * if the packet was previously fragmented, * but it's not worth the time; just let them time out.) */ if (ip->ip_off &~ IP_DF) { /* * Look for queue of fragments * of this datagram. */ for (fp = ipq.next; fp != &ipq; fp = fp->next) if (ip->ip_id == fp->ipq_id && ip->ip_src.s_addr == fp->ipq_src.s_addr && ip->ip_dst.s_addr == fp->ipq_dst.s_addr && ip->ip_p == fp->ipq_p) goto found; fp = 0; found: /* * Adjust ip_len to not reflect header, * set ip_mff if more fragments are expected, * convert offset of this to bytes. */ ip->ip_len -= hlen; ((struct ipasfrag *)ip)->ipf_mff = 0; if (ip->ip_off & IP_MF) ((struct ipasfrag *)ip)->ipf_mff = 1; ip->ip_off <<= 3; /* * If datagram marked as having more fragments * or if this is not the first fragment, * attempt reassembly; if it succeeds, proceed. */ if (((struct ipasfrag *)ip)->ipf_mff || ip->ip_off) { ipstat.ips_fragments++; ip = ip_reass((struct ipasfrag *)ip, fp); if (ip == 0) goto next; m = dtom(ip); } else if (fp) ip_freef(fp); } else ip->ip_len -= hlen; /* * Switch out to protocol's input routine. */ (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, ifp); goto next; bad: m_freem(m); goto next; } /* * Take incoming datagram fragment and try to * reassemble it into whole datagram. If a chain for * reassembly of this datagram already exists, then it * is given as fp; otherwise have to make a chain. */ struct ip * ip_reass(ip, fp) register struct ipasfrag *ip; register struct ipq *fp; { register struct mbuf *m = dtom(ip); register struct ipasfrag *q; struct mbuf *t; int hlen = ip->ip_hl << 2; int i, next; /* * Presence of header sizes in mbufs * would confuse code below. */ m->m_off += hlen; m->m_len -= hlen; /* * If first fragment to arrive, create a reassembly queue. */ if (fp == 0) { if ((t = m_get(M_DONTWAIT, MT_FTABLE)) == NULL) goto dropfrag; fp = mtod(t, struct ipq *); insque(fp, &ipq); fp->ipq_ttl = IPFRAGTTL; fp->ipq_p = ip->ip_p; fp->ipq_id = ip->ip_id; fp->ipq_next = fp->ipq_prev = (struct ipasfrag *)fp; fp->ipq_src = ((struct ip *)ip)->ip_src; fp->ipq_dst = ((struct ip *)ip)->ip_dst; q = (struct ipasfrag *)fp; goto insert; } /* * Find a segment which begins after this one does. */ for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) if (q->ip_off > ip->ip_off) break; /* * If there is a preceding segment, it may provide some of * our data already. If so, drop the data from the incoming * segment. If it provides all of our data, drop us. */ if (q->ipf_prev != (struct ipasfrag *)fp) { i = q->ipf_prev->ip_off + q->ipf_prev->ip_len - ip->ip_off; if (i > 0) { if (i >= ip->ip_len) goto dropfrag; m_adj(dtom(ip), i); ip->ip_off += i; ip->ip_len -= i; } } /* * While we overlap succeeding segments trim them or, * if they are completely covered, dequeue them. */ while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) { i = (ip->ip_off + ip->ip_len) - q->ip_off; if (i < q->ip_len) { q->ip_len -= i; q->ip_off += i; m_adj(dtom(q), i); break; } q = q->ipf_next; m_freem(dtom(q->ipf_prev)); ip_deq(q->ipf_prev); } insert: /* * Stick new segment in its place; * check for complete reassembly. */ ip_enq(ip, q->ipf_prev); next = 0; for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) { if (q->ip_off != next) return (0); next += q->ip_len; } if (q->ipf_prev->ipf_mff) return (0); /* * Reassembly is complete; concatenate fragments. */ q = fp->ipq_next; m = dtom(q); t = m->m_next; m->m_next = 0; m_cat(m, t); q = q->ipf_next; while (q != (struct ipasfrag *)fp) { t = dtom(q); q = q->ipf_next; m_cat(m, t); } /* * Create header for new ip packet by * modifying header of first packet; * dequeue and discard fragment reassembly header. * Make header visible. */ ip = fp->ipq_next; ip->ip_len = next; ((struct ip *)ip)->ip_src = fp->ipq_src; ((struct ip *)ip)->ip_dst = fp->ipq_dst; remque(fp); (void) m_free(dtom(fp)); m = dtom(ip); m->m_len += (ip->ip_hl << 2); m->m_off -= (ip->ip_hl << 2); return ((struct ip *)ip); dropfrag: ipstat.ips_fragdropped++; m_freem(m); return (0); } /* * Free a fragment reassembly header and all * associated datagrams. */ ip_freef(fp) struct ipq *fp; { register struct ipasfrag *q, *p; for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = p) { p = q->ipf_next; ip_deq(q); m_freem(dtom(q)); } remque(fp); (void) m_free(dtom(fp)); } /* * Put an ip fragment on a reassembly chain. * Like insque, but pointers in middle of structure. */ ip_enq(p, prev) register struct ipasfrag *p, *prev; { p->ipf_prev = prev; p->ipf_next = prev->ipf_next; prev->ipf_next->ipf_prev = p; prev->ipf_next = p; } /* * To ip_enq as remque is to insque. */ ip_deq(p) register struct ipasfrag *p; { p->ipf_prev->ipf_next = p->ipf_next; p->ipf_next->ipf_prev = p->ipf_prev; } /* * IP timer processing; * if a timer expires on a reassembly * queue, discard it. */ ip_slowtimo() { register struct ipq *fp; int s = splnet(); fp = ipq.next; if (fp == 0) { splx(s); return; } while (fp != &ipq) { --fp->ipq_ttl; fp = fp->next; if (fp->prev->ipq_ttl == 0) { ipstat.ips_fragtimeout++; ip_freef(fp->prev); } } splx(s); } /* * Drain off all datagram fragments. */ ip_drain() { while (ipq.next != &ipq) { ipstat.ips_fragdropped++; ip_freef(ipq.next); } } extern struct in_ifaddr *ifptoia(); struct in_ifaddr *ip_rtaddr(); /* * Do option processing on a datagram, * possibly discarding it if bad options * are encountered. */ ip_dooptions(ip, ifp) register struct ip *ip; struct ifnet *ifp; { register u_char *cp; int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; register struct ip_timestamp *ipt; register struct in_ifaddr *ia; struct in_addr *sin; n_time ntime, iptime(); cp = (u_char *)(ip + 1); cnt = (ip->ip_hl << 2) - sizeof (struct ip); for (; cnt > 0; cnt -= optlen, cp += optlen) { opt = UCHAR(cp[IPOPT_OPTVAL]); if (opt == IPOPT_EOL) break; if (opt == IPOPT_NOP) optlen = 1; else { optlen = UCHAR(cp[IPOPT_OLEN]); if (optlen <= 0 || optlen > cnt) { code = &cp[IPOPT_OLEN] - (u_char *)ip; goto bad; } } switch (opt) { default: break; /* * Source routing with record. * Find interface with current destination address. * If none on this machine then drop if strictly routed, * or do nothing if loosely routed. * Record interface address and bring up next address * component. If strictly routed make sure next * address on directly accessible net. */ case IPOPT_LSRR: case IPOPT_SSRR: if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { code = &cp[IPOPT_OFFSET] - (u_char *)ip; goto bad; } ipaddr.sin_addr = ip->ip_dst; ia = (struct in_ifaddr *) ifa_ifwithaddr((struct sockaddr *)&ipaddr); if (ia == 0) { if (opt == IPOPT_SSRR) { type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; goto bad; } /* * Loose routing, and not at next destination * yet; nothing to do except forward. */ break; } off--; /* 0 origin */ if (off > optlen - sizeof(struct in_addr)) { /* * End of source route. Should be for us. */ save_rte(cp, ip->ip_src); break; } /* * locate outgoing interface */ bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr, sizeof(ipaddr.sin_addr)); if ((opt == IPOPT_SSRR && in_iaonnetof(in_netof(ipaddr.sin_addr)) == 0) || (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) { type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; goto bad; } ip->ip_dst = ipaddr.sin_addr; bcopy((caddr_t)&(IA_SIN(ia)->sin_addr), (caddr_t)(cp + off), sizeof(struct in_addr)); cp[IPOPT_OFFSET] += sizeof(struct in_addr); /* * Since 2.11 will never have multicasting so the following line from 4.4 * is effectively always 1. */ forward = !IN_MULTICAST(ip->ip_dst.s_addr); break; case IPOPT_RR: if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { code = &cp[IPOPT_OFFSET] - (u_char *)ip; goto bad; } /* * If no space remains, ignore. */ off--; /* 0 origin */ if (off > optlen - sizeof(struct in_addr)) break; bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr, sizeof(ipaddr.sin_addr)); /* * locate outgoing interface */ if ((ia = ip_rtaddr(ipaddr.sin_addr)) == 0) { type = ICMP_UNREACH; code = ICMP_UNREACH_HOST; goto bad; } bcopy((caddr_t)&(IA_SIN(ia)->sin_addr), (caddr_t)(cp + off), sizeof(struct in_addr)); cp[IPOPT_OFFSET] += sizeof(struct in_addr); break; case IPOPT_TS: code = cp - (u_char *)ip; ipt = (struct ip_timestamp *)cp; if (ipt->ipt_len < 5) goto bad; if (ipt->ipt_ptr > ipt->ipt_len - sizeof (long)) { if (++ipt->ipt_oflw == 0) goto bad; break; } sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1); switch (ipt->ipt_flg) { case IPOPT_TS_TSONLY: break; case IPOPT_TS_TSANDADDR: if (ipt->ipt_ptr + sizeof(n_time) + sizeof(struct in_addr) > ipt->ipt_len) goto bad; ia = ifptoia(ifp); bcopy((caddr_t)&IA_SIN(ia)->sin_addr, (caddr_t)sin, sizeof(struct in_addr)); ipt->ipt_ptr += sizeof(struct in_addr); break; case IPOPT_TS_PRESPEC: if (ipt->ipt_ptr + sizeof(n_time) + sizeof(struct in_addr) > ipt->ipt_len) goto bad; bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr, sizeof(struct in_addr)); if (ifa_ifwithaddr((struct sockaddr *)&ipaddr) == 0) continue; ipt->ipt_ptr += sizeof(struct in_addr); break; default: goto bad; } ntime = iptime(); bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1, sizeof(n_time)); ipt->ipt_ptr += sizeof(n_time); } } if (forward) { if (ipforward_srcrt == 0) { type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; goto bad; } ip_forward(ip, ifp, 1); return(1); } return (0); bad: ip->ip_len -= ip->ip_hl << 2; /* XXX icmp_error adds in hdr length */ icmp_error(ip, type, code, ifp); return (1); } /* * Given address of next destination (final or next hop), * return internet address info of interface to be used to get there. */ struct in_ifaddr * ip_rtaddr(dst) struct in_addr dst; { register struct sockaddr_in *sin; register struct in_ifaddr *ia; sin = (struct sockaddr_in *) &ipforward_rt.ro_dst; if (ipforward_rt.ro_rt == 0 || dst.s_addr != sin->sin_addr.s_addr) { if (ipforward_rt.ro_rt) { RTFREE(ipforward_rt.ro_rt); ipforward_rt.ro_rt = 0; } sin->sin_family = AF_INET; sin->sin_addr = dst; rtalloc(&ipforward_rt); } if (ipforward_rt.ro_rt == 0) return ((struct in_ifaddr *)0); /* * Find address associated with outgoing interface. */ for (ia = in_ifaddr; ia; ia = ia->ia_next) if (ia->ia_ifp == ipforward_rt.ro_rt->rt_ifp) break; return (ia); } /* * Save incoming source route for use in replies, * to be picked up later by ip_srcroute if the receiver is interested. */ save_rte(option, dst) u_char *option; struct in_addr dst; { unsigned olen; olen = option[IPOPT_OLEN]; if (olen > sizeof(ip_srcrt) - 1) { if (ipprintfs) printf("save_rte: olen %d\n", olen); return; } bcopy((caddr_t)option, (caddr_t)ip_srcrt.srcopt, olen); ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr); ip_srcrt.route[ip_nhops++] = dst; } /* * Retrieve incoming source route for use in replies, * in the same form used by setsockopt. * The first hop is placed before the options, will be removed later. */ struct mbuf * ip_srcroute() { register struct in_addr *p, *q; register struct mbuf *m; if (ip_nhops == 0) return ((struct mbuf *)0); m = m_get(M_DONTWAIT, MT_SOOPTS); if (m == 0) return ((struct mbuf *)0); m->m_len = ip_nhops * sizeof(struct in_addr) + IPOPT_OFFSET + 1 + 1; /* * First save first hop for return route */ p = &ip_srcrt.route[ip_nhops - 1]; *(mtod(m, struct in_addr *)) = *p--; /* * Copy option fields and padding (nop) to mbuf. */ ip_srcrt.nop = IPOPT_NOP; bcopy((caddr_t)&ip_srcrt, mtod(m, caddr_t) + sizeof(struct in_addr), IPOPT_OFFSET + 1 + 1); q = (struct in_addr *)(mtod(m, caddr_t) + sizeof(struct in_addr) + IPOPT_OFFSET + 1 + 1); /* * Record return path as an IP source route, * reversing the path (pointers are now aligned). */ while (p >= ip_srcrt.route) *q++ = *p--; return (m); } /* * Strip out IP options, at higher * level protocol in the kernel. * Second argument is buffer to which options * will be moved, and return value is their length. */ ip_stripoptions(ip, mopt) struct ip *ip; struct mbuf *mopt; { register int i; register struct mbuf *m; register caddr_t opts; int olen; olen = (ip->ip_hl<<2) - sizeof (struct ip); m = dtom(ip); opts = (caddr_t)(ip + 1); if (mopt) { mopt->m_len = olen; mopt->m_off = MMINOFF; bcopy(opts, mtod(mopt, caddr_t), (unsigned)olen); } i = m->m_len - (sizeof (struct ip) + olen); bcopy(opts + olen, opts, (unsigned)i); m->m_len -= olen; ip->ip_hl = sizeof(struct ip) >> 2; } u_char inetctlerrmap[PRC_NCMDS] = { 0, 0, 0, 0, 0, 0, EHOSTDOWN, EHOSTUNREACH, ENETUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, EMSGSIZE, EHOSTUNREACH, 0, 0, 0, 0, 0, 0, ENOPROTOOPT }; extern int in_interfaces; /* * Forward a packet. If some error occurs return the sender * an icmp packet. Note we can't always generate a meaningful * icmp message because icmp doesn't have a large enough repertoire * of codes and types. * * If not forwarding (possibly because we have only a single external * network), just drop the packet. This could be confusing if ipforwarding * was zero but some routing protocol was advancing us as a gateway * to somewhere. However, we must let the routing protocol deal with that. * * The srcrt parameter indicates whether the packet is being forwarded * via a source route. */ ip_forward(ip, ifp, srcrt) register struct ip *ip; struct ifnet *ifp; int srcrt; { register int error, type = 0, code; register struct sockaddr_in *sin; struct mbuf *mcopy; struct in_addr dest; dest.s_addr = 0; if (ipprintfs) printf("forward: src %X dst %X ttl %x\n", ntohl(ip->ip_src), ntohl(ip->ip_dst), ip->ip_ttl); ip->ip_id = htons(ip->ip_id); if (in_canforward(ip->ip_dst) == 0) { ipstat.ips_cantforward++; m_freem(dtom(ip)); return; } if (ip->ip_ttl < IPTTLDEC) { type = ICMP_TIMXCEED, code = ICMP_TIMXCEED_INTRANS; goto sendicmp; } ip->ip_ttl -= IPTTLDEC; sin = (struct sockaddr_in *)&ipforward_rt.ro_dst; if (ipforward_rt.ro_rt == 0 || ip->ip_dst.s_addr != sin->sin_addr.s_addr) { if (ipforward_rt.ro_rt) { RTFREE(ipforward_rt.ro_rt); ipforward_rt.ro_rt = 0; } sin->sin_family = AF_INET; sin->sin_addr = ip->ip_dst; rtalloc(&ipforward_rt); if (ipforward_rt.ro_rt == 0) { ip->ip_len -= ip->ip_hl << 2; /* icmp_error assumes this */ icmp_error(ip,ICMP_UNREACH,ICMP_UNREACH_HOST,ifp,dest); return; } } /* * Save at most 64 bytes of the packet in case * we need to generate an ICMP message to the src. */ mcopy = m_copy(dtom(ip), 0, MIN((int)ip->ip_len, 64)); /* * If forwarding packet using same interface that it came in on, * perhaps should send a redirect to sender to shortcut a hop. * Only send redirect if source is sending directly to us, * and if packet was not source routed (or has any options). * Also, don't send redirect if forwarding using a default route * or a route modfied by a redirect. */ #define satosin(sa) ((struct sockaddr_in *)(sa)) if (ipforward_rt.ro_rt && ipforward_rt.ro_rt->rt_ifp == ifp && (ipforward_rt.ro_rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 && satosin(&ipforward_rt.ro_rt->rt_dst)->sin_addr.s_addr != 0 && ipsendredirects && !srcrt && ip->ip_hl == (sizeof(struct ip) >> 2)){ struct in_ifaddr *ia; u_long src = ntohl(ip->ip_src.s_addr); u_long dst = ntohl(ip->ip_dst.s_addr); if ((ia = ifptoia(ifp)) && (src & ia->ia_subnetmask) == ia->ia_subnet) { if (ipforward_rt.ro_rt->rt_flags & RTF_GATEWAY) dest = satosin(&ipforward_rt.ro_rt->rt_gateway)->sin_addr; else dest = ip->ip_dst; /* * If the destination is reached by a route to host, * is on a subnet of a local net, or is directly * on the attached net (!), use host redirect. * (We may be the correct first hop for other subnets.) */ type = ICMP_REDIRECT; code = ICMP_REDIRECT_NET; if ((ipforward_rt.ro_rt->rt_flags & RTF_HOST) || (ipforward_rt.ro_rt->rt_flags & RTF_GATEWAY) == 0) code = ICMP_REDIRECT_HOST; else for (ia = in_ifaddr; ia = ia->ia_next; ) if ((dst & ia->ia_netmask) == ia->ia_net) { if (ia->ia_subnetmask != ia->ia_netmask) code = ICMP_REDIRECT_HOST; break; } if (ipprintfs) printf("redirect (%d) to %x\n", code, dest); } } error = ip_output(dtom(ip), (struct mbuf *)0, &ipforward_rt, IP_FORWARDING); if (error) ipstat.ips_cantforward++; else if (type) ipstat.ips_redirectsent++; else { if (mcopy) m_freem(mcopy); ipstat.ips_forward++; return; } if (mcopy == NULL) return; ip = mtod(mcopy, struct ip *); type = ICMP_UNREACH; switch (error) { case 0: /* forwarded, but need redirect */ type = ICMP_REDIRECT; /* code set above */ break; case ENETUNREACH: case ENETDOWN: if (in_localaddr(ip->ip_dst)) code = ICMP_UNREACH_HOST; else code = ICMP_UNREACH_NET; break; case EMSGSIZE: code = ICMP_UNREACH_NEEDFRAG; break; case EPERM: code = ICMP_UNREACH_PORT; break; case ENOBUFS: type = ICMP_SOURCEQUENCH; break; case EHOSTDOWN: case EHOSTUNREACH: code = ICMP_UNREACH_HOST; break; } sendicmp: ip->ip_len -= ip->ip_hl << 2; /* icmp_error assumes this */ icmp_error(ip, type, code, ifp, dest); } int ip_sysctl(name, namelen, oldp, oldlenp, newp, newlen) int *name; u_int namelen; void *oldp; size_t *oldlenp; void *newp; size_t newlen; { /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); switch (name[0]) { case IPCTL_FORWARDING: return (sysctl_int(oldp, oldlenp, newp, newlen, &ipforwarding)); case IPCTL_SENDREDIRECTS: return (sysctl_int(oldp, oldlenp, newp, newlen, &ipsendredirects)); case IPCTL_DEFTTL: return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_defttl)); #ifdef notyet case IPCTL_DEFMTU: return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtu)); #endif case IPCTL_FORWSRCRT: return (sysctl_int(oldp, oldlenp, newp, newlen, &ipforward_srcrt)); default: return (EOPNOTSUPP); } /* NOTREACHED */ } UNREACH_HOST; goto bad; } bcopy((caddr_t)&(IA_SIN(ia)->sin_addr), (caddr_t)(cp + off), sizeof(struct in_asys/netinet/ip_output.c 444 0 0 26264 4235735524 10526 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)ip_output.c 7.9 (Berkeley) 3/15/88 */ #include "param.h" #include "mbuf.h" #include "errno.h" #include "protosw.h" #include "socket.h" #include "socketvar.h" #include "../net/if.h" #include "../net/route.h" #include "domain.h" #include "in.h" #include "in_pcb.h" #include "in_systm.h" #include "in_var.h" #include "ip.h" #include "ip_var.h" #ifdef vax #include "../machine/mtpr.h" #endif #define ovbcopy(a,b,c) bcopy(a,b,c) struct mbuf *ip_insertoptions(); /* * IP output. The packet in mbuf chain m contains a skeletal IP * header (with len, off, ttl, proto, tos, src, dst). * The mbuf chain containing the packet will be freed. * The mbuf opt, if present, will not be freed. */ ip_output(m0, opt, ro, flags) struct mbuf *m0; struct mbuf *opt; struct route *ro; int flags; { register struct ip *ip, *mhip; register struct ifnet *ifp; register struct mbuf *m = m0; register int hlen = sizeof (struct ip); int len, off, error = 0; struct route iproute; struct sockaddr_in *dst; if (opt) { m = ip_insertoptions(m, opt, &len); hlen = len; } ip = mtod(m, struct ip *); /* * Fill in IP header. */ if ((flags & IP_FORWARDING) == 0) { ip->ip_v = IPVERSION; ip->ip_off &= IP_DF; ip->ip_id = htons(ip_id++); ip->ip_hl = hlen >> 2; } else hlen = ip->ip_hl << 2; /* * Route packet. */ if (ro == 0) { ro = &iproute; bzero((caddr_t)ro, sizeof (*ro)); } dst = (struct sockaddr_in *)&ro->ro_dst; /* * If there is a cached route, * check that it is to the same destination * and is still up. If not, free it and try again. */ if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 || dst->sin_addr.s_addr != ip->ip_dst.s_addr)) { RTFREE(ro->ro_rt); ro->ro_rt = (struct rtentry *)0; } if (ro->ro_rt == 0) { dst->sin_family = AF_INET; dst->sin_addr = ip->ip_dst; } /* * If routing to interface only, * short circuit routing lookup. */ if (flags & IP_ROUTETOIF) { struct in_ifaddr *ia; ia = (struct in_ifaddr *)ifa_ifwithdstaddr(dst); if (ia == 0) ia = in_iaonnetof(in_netof(ip->ip_dst)); if (ia == 0) { error = ENETUNREACH; goto bad; } ifp = ia->ia_ifp; } else { if (ro->ro_rt == 0) rtalloc(ro); if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) { if (in_localaddr(ip->ip_dst)) error = EHOSTUNREACH; else error = ENETUNREACH; goto bad; } ro->ro_rt->rt_use++; if (ro->ro_rt->rt_flags & RTF_GATEWAY) dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway; } #ifndef notdef /* * If source address not specified yet, use address * of outgoing interface. */ if (ip->ip_src.s_addr == INADDR_ANY) { register struct in_ifaddr *ia; for (ia = in_ifaddr; ia; ia = ia->ia_next) if (ia->ia_ifp == ifp) { ip->ip_src = IA_SIN(ia)->sin_addr; break; } } #endif /* * Look for broadcast address and * and verify user is allowed to send * such a packet. */ if (in_broadcast(dst->sin_addr)) { if ((ifp->if_flags & IFF_BROADCAST) == 0) { error = EADDRNOTAVAIL; goto bad; } if ((flags & IP_ALLOWBROADCAST) == 0) { error = EACCES; goto bad; } /* don't allow broadcast messages to be fragmented */ if (ip->ip_len > ifp->if_mtu) { error = EMSGSIZE; goto bad; } } /* * If small enough for interface, can just send directly. */ if (ip->ip_len <= ifp->if_mtu) { ip->ip_len = htons((u_short)ip->ip_len); ip->ip_off = htons((u_short)ip->ip_off); ip->ip_sum = 0; ip->ip_sum = in_cksum(m, hlen); error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst); goto done; } /* * Too large for interface; fragment if possible. * Must be able to put at least 8 bytes per fragment. */ if (ip->ip_off & IP_DF) { error = EMSGSIZE; goto bad; } len = (ifp->if_mtu - hlen) &~ 7; if (len < 8) { error = EMSGSIZE; goto bad; } { int mhlen, firstlen = len; struct mbuf **mnext = &m->m_act; /* * Loop through length of segment after first fragment, * make new header and copy data of each part and link onto chain. */ m0 = m; mhlen = sizeof (struct ip); for (off = hlen + len; off < ip->ip_len; off += len) { MGET(m, M_DONTWAIT, MT_HEADER); if (m == 0) { error = ENOBUFS; goto bad; } m->m_off = MMAXOFF - hlen; mhip = mtod(m, struct ip *); *mhip = *ip; if (hlen > sizeof (struct ip)) { mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); mhip->ip_hl = mhlen >> 2; } m->m_len = mhlen; mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF); if (ip->ip_off & IP_MF) mhip->ip_off |= IP_MF; if (off + len >= ip->ip_len) len = ip->ip_len - off; else mhip->ip_off |= IP_MF; mhip->ip_len = htons((u_short)(len + mhlen)); m->m_next = m_copy(m0, off, len); if (m->m_next == 0) { error = ENOBUFS; /* ??? */ goto sendorfree; } mhip->ip_off = htons((u_short)mhip->ip_off); mhip->ip_sum = 0; mhip->ip_sum = in_cksum(m, mhlen); *mnext = m; mnext = &m->m_act; } /* * Update first fragment by trimming what's been copied out * and updating header, then send each fragment (in order). */ m_adj(m0, hlen + firstlen - ip->ip_len); ip->ip_len = htons((u_short)(hlen + firstlen)); ip->ip_off = htons((u_short)(ip->ip_off | IP_MF)); ip->ip_sum = 0; ip->ip_sum = in_cksum(m0, hlen); sendorfree: for (m = m0; m; m = m0) { m0 = m->m_act; m->m_act = 0; if (error == 0) error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst); else m_freem(m); } } done: if (ro == &iproute && (flags & IP_ROUTETOIF) == 0 && ro->ro_rt) RTFREE(ro->ro_rt); return (error); bad: m_freem(m0); goto done; } /* * Insert IP options into preformed packet. * Adjust IP destination as required for IP source routing, * as indicated by a non-zero in_addr at the start of the options. */ struct mbuf * ip_insertoptions(m, opt, phlen) register struct mbuf *m; struct mbuf *opt; int *phlen; { register struct ipoption *p = mtod(opt, struct ipoption *); struct mbuf *n; register struct ip *ip = mtod(m, struct ip *); unsigned optlen; optlen = opt->m_len - sizeof(p->ipopt_dst); if (p->ipopt_dst.s_addr) ip->ip_dst = p->ipopt_dst; if (m->m_off >= MMAXOFF || MMINOFF + optlen > m->m_off) { MGET(n, M_DONTWAIT, MT_HEADER); if (n == 0) return (m); m->m_len -= sizeof(struct ip); m->m_off += sizeof(struct ip); n->m_next = m; m = n; m->m_off = MMAXOFF - sizeof(struct ip) - optlen; m->m_len = optlen + sizeof(struct ip); bcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip)); } else { m->m_off -= optlen; m->m_len += optlen; ovbcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip)); } ip = mtod(m, struct ip *); bcopy((caddr_t)p->ipopt_list, (caddr_t)(ip + 1), (unsigned)optlen); *phlen = sizeof(struct ip) + optlen; ip->ip_len += optlen; return (m); } /* * Copy options from ip to jp, * omitting those not copied during fragmentation. */ ip_optcopy(ip, jp) struct ip *ip, *jp; { register u_char *cp, *dp; int opt, optlen, cnt; cp = (u_char *)(ip + 1); dp = (u_char *)(jp + 1); cnt = (ip->ip_hl << 2) - sizeof (struct ip); for (; cnt > 0; cnt -= optlen, cp += optlen) { opt = UCHAR(cp[0]); if (opt == IPOPT_EOL) break; if (opt == IPOPT_NOP) optlen = 1; else optlen = UCHAR(cp[IPOPT_OLEN]); /* bogus lengths should have been caught by ip_dooptions */ if (optlen > cnt) optlen = cnt; if (IPOPT_COPIED(opt)) { bcopy((caddr_t)cp, (caddr_t)dp, (unsigned)optlen); dp += optlen; } } for (optlen = dp - (u_char *)(jp+1); optlen & 0x3; optlen++) *dp++ = IPOPT_EOL; return (optlen); } /* * IP socket option processing. */ ip_ctloutput(op, so, level, optname, m) int op; struct socket *so; int level, optname; struct mbuf **m; { int error = 0; struct inpcb *inp = sotoinpcb(so); if (level != IPPROTO_IP) error = EINVAL; else switch (op) { case PRCO_SETOPT: switch (optname) { case IP_OPTIONS: return (ip_pcbopts(&inp->inp_options, *m)); default: error = EINVAL; break; } break; case PRCO_GETOPT: switch (optname) { case IP_OPTIONS: *m = m_get(M_WAIT, MT_SOOPTS); if (inp->inp_options) { (*m)->m_off = inp->inp_options->m_off; (*m)->m_len = inp->inp_options->m_len; bcopy(mtod(inp->inp_options, caddr_t), mtod(*m, caddr_t), (unsigned)(*m)->m_len); } else (*m)->m_len = 0; break; default: error = EINVAL; break; } break; } if (op == PRCO_SETOPT && *m) (void)m_free(*m); return (error); } /* * Set up IP options in pcb for insertion in output packets. * Store in mbuf with pointer in pcbopt, adding pseudo-option * with destination address if source routed. */ ip_pcbopts(pcbopt, m) struct mbuf **pcbopt; register struct mbuf *m; { register cnt, optlen; register u_char *cp; u_char opt; /* turn off any old options */ if (*pcbopt) (void)m_free(*pcbopt); *pcbopt = 0; if (m == (struct mbuf *)0 || m->m_len == 0) { /* * Only turning off any previous options. */ if (m) (void)m_free(m); return (0); } #ifndef vax if (m->m_len % sizeof(long)) goto bad; #endif /* * IP first-hop destination address will be stored before * actual options; move other options back * and clear it when none present. */ #if MAX_IPOPTLEN >= MMAXOFF - MMINOFF if (m->m_off + m->m_len + sizeof(struct in_addr) > MAX_IPOPTLEN) goto bad; #else if (m->m_off + m->m_len + sizeof(struct in_addr) > MMAXOFF) goto bad; #endif cnt = m->m_len; m->m_len += sizeof(struct in_addr); cp = mtod(m, u_char *) + sizeof(struct in_addr); ovbcopy(mtod(m, caddr_t), (caddr_t)cp, (unsigned)cnt); bzero(mtod(m, caddr_t), sizeof(struct in_addr)); for (; cnt > 0; cnt -= optlen, cp += optlen) { opt = cp[IPOPT_OPTVAL]; if (opt == IPOPT_EOL) break; if (opt == IPOPT_NOP) optlen = 1; else { optlen = cp[IPOPT_OLEN]; if (optlen <= IPOPT_OLEN || optlen > cnt) goto bad; } switch (opt) { default: break; case IPOPT_LSRR: case IPOPT_SSRR: /* * user process specifies route as: * ->A->B->C->D * D must be our final destination (but we can't * check that since we may not have connected yet). * A is first hop destination, which doesn't appear in * actual IP option, but is stored before the options. */ if (optlen < IPOPT_MINOFF - 1 + sizeof(struct in_addr)) goto bad; m->m_len -= sizeof(struct in_addr); cnt -= sizeof(struct in_addr); optlen -= sizeof(struct in_addr); cp[IPOPT_OLEN] = optlen; /* * Move first hop before start of options. */ bcopy((caddr_t)&cp[IPOPT_OFFSET+1], mtod(m, caddr_t), sizeof(struct in_addr)); /* * Then copy rest of options back * to close up the deleted entry. */ ovbcopy((caddr_t)(&cp[IPOPT_OFFSET+1] + sizeof(struct in_addr)), (caddr_t)&cp[IPOPT_OFFSET+1], (unsigned)cnt + sizeof(struct in_addr)); break; } } *pcbopt = m; return (0); bad: (void)m_free(m); return (EINVAL); } >ip_off &= IP_DF; ip->ip_id = htons(ip_id++); ip->ip_hl = hlen >> 2; } else hlen = ip->ip_hl << 2; /* * Route packet. */ if (ro == 0) { ro = &iproute; bzero((caddr_t)ro, sizeof (*ro)); } dst = (struct sockaddr_in *)&ro->ro_dst; /* * If there is a cached route, * check that it is to the same destination *sys/netinet/raw_ip.c 640 0 12 7503 4455211331 7740 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)raw_ip.c 7.3 (Berkeley) 12/7/87 */ #include "param.h" #include "mbuf.h" #include "socket.h" #include "protosw.h" #include "socketvar.h" #include "errno.h" #include "../net/if.h" #include "../net/route.h" #include "../net/raw_cb.h" #include "domain.h" #include "in.h" #include "in_systm.h" #include "ip.h" #include "ip_var.h" /* * Raw interface to IP protocol. */ struct sockaddr_in ripdst = { AF_INET }; struct sockaddr_in ripsrc = { AF_INET }; struct sockproto ripproto = { PF_INET }; /* * Setup generic address and protocol structures * for raw_input routine, then pass them along with * mbuf chain. */ rip_input(m) struct mbuf *m; { register struct ip *ip = mtod(m, struct ip *); ripproto.sp_protocol = ip->ip_p; ripdst.sin_addr = ip->ip_dst; ripsrc.sin_addr = ip->ip_src; raw_input(m, &ripproto, (struct sockaddr *)&ripsrc, (struct sockaddr *)&ripdst); } rip_output(m, so) register struct mbuf *m; struct socket *so; { register struct ip *ip; int error; struct rawcb *rp = sotorawcb(so); struct sockaddr_in *sin; #if BSD>=43 short proto = rp->rcb_proto.sp_protocol; #else short proto = so->so_proto->pr_protocol; #endif /* * if the protocol is IPPROTO_RAW, the user handed us a * complete IP packet. Otherwise, allocate an mbuf for a * header and fill it in as needed. */ if (proto != IPPROTO_RAW) { /* * Calculate data length and get an mbuf * for IP header. */ int len = 0; struct mbuf *m0; for (m0 = m; m; m = m->m_next) len += m->m_len; m = m_get(M_DONTWAIT, MT_HEADER); if (m == 0) { m = m0; error = ENOBUFS; goto bad; } m->m_off = MMAXOFF - sizeof(struct ip); m->m_len = sizeof(struct ip); m->m_next = m0; ip = mtod(m, struct ip *); ip->ip_tos = 0; ip->ip_off = 0; ip->ip_p = proto; ip->ip_len = sizeof(struct ip) + len; ip->ip_ttl = MAXTTL; } else ip = mtod(m, struct ip *); if (rp->rcb_flags & RAW_LADDR) { sin = (struct sockaddr_in *)&rp->rcb_laddr; if (sin->sin_family != AF_INET) { error = EAFNOSUPPORT; goto bad; } ip->ip_src.s_addr = sin->sin_addr.s_addr; } else ip->ip_src.s_addr = 0; ip->ip_dst = ((struct sockaddr_in *)&rp->rcb_faddr)->sin_addr; #if BSD>=43 return (ip_output(m, rp->rcb_options, &rp->rcb_route, (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST)); #else return (ip_output(m, (struct mbuf *)0, &rp->rcb_route, (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST)); #endif bad: m_freem(m); return (error); } /* * Raw IP socket option processing. */ rip_ctloutput(op, so, level, optname, m) int op; struct socket *so; int level, optname; struct mbuf **m; { int error = 0; register struct rawcb *rp = sotorawcb(so); if (level != IPPROTO_IP) error = EINVAL; else switch (op) { case PRCO_SETOPT: switch (optname) { case IP_OPTIONS: return (ip_pcbopts(&rp->rcb_options, *m)); default: error = EINVAL; break; } break; case PRCO_GETOPT: switch (optname) { case IP_OPTIONS: *m = m_get(M_WAIT, MT_SOOPTS); if (rp->rcb_options) { (*m)->m_off = rp->rcb_options->m_off; (*m)->m_len = rp->rcb_options->m_len; bcopy(mtod(rp->rcb_options, caddr_t), mtod(*m, caddr_t), (unsigned)(*m)->m_len); } else (*m)->m_len = 0; break; default: error = EINVAL; break; } break; } if (op == PRCO_SETOPT && *m) (void)m_free(*m); return (error); } ; ip->ip_off = htons((u_short)ip->ip_off); ip->ip_sum = 0; ip->ip_sum = in_cksum(m, hlen); error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst); goto done; } /* * Too lasys/netinet/tcp_debug.c 644 0 0 6013 6037100676 10376 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)tcp_debug.c 7.2.1 (2.11BSD) 1995/10/11 */ #ifdef TCPDEBUG #define TCPTIMERS #define TANAMES #define PRUREQUESTS #define TCPSTATES #endif #include "param.h" #include "systm.h" #include "mbuf.h" #include "socket.h" #include "socketvar.h" #include "protosw.h" #include "errno.h" #include "../net/route.h" #include "../net/if.h" #include "domain.h" #include "in.h" #include "in_pcb.h" #include "in_systm.h" #include "ip.h" #include "ip_var.h" #include "tcp.h" #include "tcp_fsm.h" #include "tcp_seq.h" #include "tcp_timer.h" #include "tcp_var.h" #include "tcpip.h" #include "tcp_debug.h" #ifdef TCPDEBUG int tcpconsdebug = 0; #endif /* * Tcp debug routines */ tcp_trace(act, ostate, tp, ti, req) short act, ostate; struct tcpcb *tp; struct tcpiphdr *ti; int req; { tcp_seq seq, ack; int len, flags; struct tcp_debug *td = &tcp_debug[tcp_debx++]; if (tcp_debx == TCP_NDEBUG) tcp_debx = 0; td->td_time = iptime(); td->td_act = act; td->td_ostate = ostate; td->td_tcb = (caddr_t)tp; if (tp) td->td_cb = *tp; else bzero((caddr_t)&td->td_cb, sizeof (*tp)); if (ti) td->td_ti = *ti; else bzero((caddr_t)&td->td_ti, sizeof (*ti)); td->td_req = req; #ifdef TCPDEBUG if (tcpconsdebug == 0) return; if (tp) printf("%x %s:", tp, tcpstates[ostate]); else printf("???????? "); printf("%s ", tanames[act]); switch (act) { case TA_INPUT: case TA_OUTPUT: case TA_DROP: if (ti == 0) break; seq = ti->ti_seq; ack = ti->ti_ack; len = ti->ti_len; if (act == TA_OUTPUT) { seq = ntohl(seq); ack = ntohl(ack); len = ntohs((u_short)len); } if (act == TA_OUTPUT) len -= sizeof (struct tcphdr); if (len) printf("[%X..%X)", seq, seq+len); else printf("%X", seq); printf("@%X, urp=%X", ack, ti->ti_urp); flags = ti->ti_flags; if (flags) { #ifndef lint char *cp = "<"; #define pf(f) { if (ti->ti_flags&TH_/**/f) { printf("%s%s", cp, "f"); cp = ","; } } pf(SYN); pf(ACK); pf(FIN); pf(RST); pf(PUSH); pf(URG); #endif printf(">"); } break; case TA_USER: printf("%s", prurequests[req&0xff]); if ((req & 0xff) == PRU_SLOWTIMO) printf("<%s>", tcptimers[req>>8]); break; } if (tp) printf(" -> %s", tcpstates[tp->t_state]); /* print out internal state of tp !?! */ printf("\n"); if (tp == 0) return; printf("\trcv_(nxt,wnd,up) (%X,%x,%x) snd_(una,nxt,max) (%X,%X,%X)\n", tp->rcv_nxt, tp->rcv_wnd, tp->rcv_up, tp->snd_una, tp->snd_nxt, tp->snd_max); printf("\tsnd_(wl1,wl2,wnd) (%X,%X,%x)\n", tp->snd_wl1, tp->snd_wl2, tp->snd_wnd); #endif /* TCPDEBUG */ } ight (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. sys/netinet/tcp_input.c 444 0 0 104267 4240702423 10507 /* * Copyright (c) 1982, 1986, 1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)tcp_input.c 7.15.1.2 (Berkeley) 3/16/88 */ #include "param.h" #include "systm.h" #include "mbuf.h" #include "protosw.h" #include "socket.h" #include "socketvar.h" #include "errno.h" #include "../net/if.h" #include "../net/route.h" #include "domain.h" #include "in.h" #include "in_pcb.h" #include "in_systm.h" #include "ip.h" #include "ip_var.h" #include "tcp.h" #include "tcp_fsm.h" #include "tcp_seq.h" #include "tcp_timer.h" #include "tcp_var.h" #include "tcpip.h" #include "tcp_debug.h" int tcpprintfs = 0; int tcpcksum = 1; int tcprexmtthresh = 3; struct tcpiphdr tcp_saveti; extern tcpnodelack; struct tcpcb *tcp_newtcpcb(); /* * Insert segment ti into reassembly queue of tcp with * control block tp. Return TH_FIN if reassembly now includes * a segment with FIN. The macro form does the common case inline * (segment is the next to be received on an established connection, * and the queue is empty), avoiding linkage into and removal * from the queue and repetition of various conversions. */ #define TCP_REASS(tp, ti, m, so, flags) { \ if ((ti)->ti_seq == (tp)->rcv_nxt && \ (tp)->seg_next == (struct tcpiphdr *)(tp) && \ (tp)->t_state == TCPS_ESTABLISHED) { \ (tp)->rcv_nxt += (ti)->ti_len; \ flags = (ti)->ti_flags & TH_FIN; \ tcpstat.tcps_rcvpack++;\ tcpstat.tcps_rcvbyte += (ti)->ti_len;\ sbappend(&(so)->so_rcv, (m)); \ sorwakeup(so); \ } else \ (flags) = tcp_reass((tp), (ti)); \ } tcp_reass(tp, ti) register struct tcpcb *tp; register struct tcpiphdr *ti; { register struct tcpiphdr *q; struct socket *so = tp->t_inpcb->inp_socket; struct mbuf *m; int flags; /* * Call with ti==0 after become established to * force pre-ESTABLISHED data up to user socket. */ if (ti == 0) goto present; /* * Find a segment which begins after this one does. */ for (q = tp->seg_next; q != (struct tcpiphdr *)tp; q = (struct tcpiphdr *)q->ti_next) if (SEQ_GT(q->ti_seq, ti->ti_seq)) break; /* * If there is a preceding segment, it may provide some of * our data already. If so, drop the data from the incoming * segment. If it provides all of our data, drop us. */ if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) { register int i; q = (struct tcpiphdr *)q->ti_prev; /* conversion to int (in i) handles seq wraparound */ i = q->ti_seq + q->ti_len - ti->ti_seq; if (i > 0) { if (i >= ti->ti_len) { tcpstat.tcps_rcvduppack++; tcpstat.tcps_rcvdupbyte += ti->ti_len; goto drop; } m_adj(dtom(ti), i); ti->ti_len -= i; ti->ti_seq += i; } q = (struct tcpiphdr *)(q->ti_next); } tcpstat.tcps_rcvoopack++; tcpstat.tcps_rcvoobyte += ti->ti_len; /* * While we overlap succeeding segments trim them or, * if they are completely covered, dequeue them. */ while (q != (struct tcpiphdr *)tp) { register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq; if (i <= 0) break; if (i < q->ti_len) { q->ti_seq += i; q->ti_len -= i; m_adj(dtom(q), i); break; } q = (struct tcpiphdr *)q->ti_next; m = dtom(q->ti_prev); remque(q->ti_prev); m_freem(m); } /* * Stick new segment in its place. */ insque(ti, q->ti_prev); present: /* * Present data to user, advancing rcv_nxt through * completed sequence space. */ if (TCPS_HAVERCVDSYN(tp->t_state) == 0) return (0); ti = tp->seg_next; if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt) return (0); if (tp->t_state == TCPS_SYN_RECEIVED && ti->ti_len) return (0); do { tp->rcv_nxt += ti->ti_len; flags = ti->ti_flags & TH_FIN; remque(ti); m = dtom(ti); ti = (struct tcpiphdr *)ti->ti_next; if (so->so_state & SS_CANTRCVMORE) m_freem(m); else sbappend(&so->so_rcv, m); } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt); sorwakeup(so); return (flags); drop: m_freem(dtom(ti)); return (0); } /* * TCP input routine, follows pages 65-76 of the * protocol specification dated September, 1981 very closely. */ tcp_input(m0) struct mbuf *m0; { register struct tcpiphdr *ti; struct inpcb *inp; register struct mbuf *m; struct mbuf *om = 0; int len, tlen, off; register struct tcpcb *tp = 0; register int tiflags; struct socket *so; int todrop, acked, ourfinisacked, needoutput = 0; short ostate; struct in_addr laddr; int dropsocket = 0; long iss = 0; tcpstat.tcps_rcvtotal++; /* * Get IP and TCP header together in first mbuf. * Note: IP leaves IP header in first mbuf. */ m = m0; ti = mtod(m, struct tcpiphdr *); if (((struct ip *)ti)->ip_hl > (sizeof (struct ip) >> 2)) ip_stripoptions((struct ip *)ti, (struct mbuf *)0); if (m->m_off > MMAXOFF || m->m_len < sizeof (struct tcpiphdr)) { if ((m = m_pullup(m, sizeof (struct tcpiphdr))) == 0) { tcpstat.tcps_rcvshort++; return; } ti = mtod(m, struct tcpiphdr *); } /* * Checksum extended TCP header and data. */ tlen = ((struct ip *)ti)->ip_len; len = sizeof (struct ip) + tlen; if (tcpcksum) { ti->ti_next = ti->ti_prev = 0; ti->ti_x1 = 0; ti->ti_pad = 0; ti->ti_len = (u_short)tlen; ti->ti_len = htons((u_short)ti->ti_len); if (ti->ti_sum = in_cksum(m, len)) { if (tcpprintfs) printf("tcp sum: src %x\n", ti->ti_src); tcpstat.tcps_rcvbadsum++; goto drop; } } /* * Check that TCP offset makes sense, * pull out TCP options and adjust length. */ off = ti->ti_off << 2; if (off < sizeof (struct tcphdr) || off > tlen) { if (tcpprintfs) printf("tcp off: src %x off %d\n", ti->ti_src, off); tcpstat.tcps_rcvbadoff++; goto drop; } tlen -= off; ti->ti_len = tlen; if (off > sizeof (struct tcphdr)) { if (m->m_len < sizeof(struct ip) + off) { if ((m = m_pullup(m, sizeof (struct ip) + off)) == 0) { tcpstat.tcps_rcvshort++; return; } ti = mtod(m, struct tcpiphdr *); } om = m_get(M_DONTWAIT, MT_DATA); if (om == 0) goto drop; om->m_len = off - sizeof (struct tcphdr); { caddr_t op = mtod(m, caddr_t) + sizeof (struct tcpiphdr); bcopy(op, mtod(om, caddr_t), (unsigned)om->m_len); m->m_len -= om->m_len; bcopy(op+om->m_len, op, (unsigned)(m->m_len-sizeof (struct tcpiphdr))); } } tiflags = ti->ti_flags; /* * Drop TCP and IP headers; TCP options were dropped above. */ m->m_off += sizeof(struct tcpiphdr); m->m_len -= sizeof(struct tcpiphdr); /* * Convert TCP protocol specific fields to host format. */ ti->ti_seq = ntohl(ti->ti_seq); ti->ti_ack = ntohl(ti->ti_ack); ti->ti_win = ntohs(ti->ti_win); ti->ti_urp = ntohs(ti->ti_urp); /* * Locate pcb for segment. */ findpcb: inp = in_pcblookup (&tcb, ti->ti_src, ti->ti_sport, ti->ti_dst, ti->ti_dport, INPLOOKUP_WILDCARD); /* * If the state is CLOSED (i.e., TCB does not exist) then * all data in the incoming segment is discarded. * If the TCB exists but is in CLOSED state, it is embryonic, * but should either do a listen or a connect soon. */ if (inp == 0) goto dropwithreset; tp = intotcpcb(inp); if (tp == 0) goto dropwithreset; if (tp->t_state == TCPS_CLOSED) goto drop; so = inp->inp_socket; if (so->so_options & SO_DEBUG) { ostate = tp->t_state; tcp_saveti = *ti; } if (so->so_options & SO_ACCEPTCONN) { so = sonewconn(so); if (so == 0) goto drop; /* * This is ugly, but .... * * Mark socket as temporary until we're * committed to keeping it. The code at * ``drop'' and ``dropwithreset'' check the * flag dropsocket to see if the temporary * socket created here should be discarded. * We mark the socket as discardable until * we're committed to it below in TCPS_LISTEN. */ dropsocket++; inp = (struct inpcb *)so->so_pcb; inp->inp_laddr = ti->ti_dst; inp->inp_lport = ti->ti_dport; #if BSD>=43 inp->inp_options = ip_srcroute(); #endif tp = intotcpcb(inp); tp->t_state = TCPS_LISTEN; } /* * Segment received on connection. * Reset idle time and keep-alive timer. */ tp->t_idle = 0; tp->t_timer[TCPT_KEEP] = tcp_keepidle; /* * Process options if not in LISTEN state, * else do it below (after getting remote address). */ if (om && tp->t_state != TCPS_LISTEN) { tcp_dooptions(tp, om, ti); om = 0; } /* * Calculate amount of space in receive window, * and then do TCP input processing. * Receive window is amount of space in rcv queue, * but not less than advertised window. */ { int win; win = sbspace(&so->so_rcv); if (win < 0) win = 0; tp->rcv_wnd = MAX(win, (int)(tp->rcv_adv - tp->rcv_nxt)); } switch (tp->t_state) { /* * If the state is LISTEN then ignore segment if it contains an RST. * If the segment contains an ACK then it is bad and send a RST. * If it does not contain a SYN then it is not interesting; drop it. * Don't bother responding if the destination was a broadcast. * Otherwise initialize tp->rcv_nxt, and tp->irs, select an initial * tp->iss, and send a segment: * * Also initialize tp->snd_nxt to tp->iss+1 and tp->snd_una to tp->iss. * Fill in remote peer address fields if not previously specified. * Enter SYN_RECEIVED state, and process any other fields of this * segment in this state. */ case TCPS_LISTEN: { struct mbuf *am; register struct sockaddr_in *sin; if (tiflags & TH_RST) goto drop; if (tiflags & TH_ACK) goto dropwithreset; if ((tiflags & TH_SYN) == 0) goto drop; if (in_broadcast(ti->ti_dst)) goto drop; am = m_get(M_DONTWAIT, MT_SONAME); if (am == NULL) goto drop; am->m_len = sizeof (struct sockaddr_in); sin = mtod(am, struct sockaddr_in *); sin->sin_family = AF_INET; sin->sin_addr = ti->ti_src; sin->sin_port = ti->ti_sport; laddr = inp->inp_laddr; if (inp->inp_laddr.s_addr == INADDR_ANY) inp->inp_laddr = ti->ti_dst; if (in_pcbconnect(inp, am)) { inp->inp_laddr = laddr; (void) m_free(am); goto drop; } (void) m_free(am); tp->t_template = tcp_template(tp); if (tp->t_template == 0) { tp = tcp_drop(tp, ENOBUFS); dropsocket = 0; /* socket is already gone */ goto drop; } if (om) { tcp_dooptions(tp, om, ti); om = 0; } if (iss) tp->iss = iss; else tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; tp->irs = ti->ti_seq; tcp_sendseqinit(tp); tcp_rcvseqinit(tp); tp->t_flags |= TF_ACKNOW; tp->t_state = TCPS_SYN_RECEIVED; tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; dropsocket = 0; /* committed to socket */ tcpstat.tcps_accepts++; goto trimthenstep6; } /* * If the state is SYN_SENT: * if seg contains an ACK, but not for our SYN, drop the input. * if seg contains a RST, then drop the connection. * if seg does not contain SYN, then drop it. * Otherwise this is an acceptable SYN segment * initialize tp->rcv_nxt and tp->irs * if seg contains ack then advance tp->snd_una * if SYN has been acked change to ESTABLISHED else SYN_RCVD state * arrange for segment to be acked (eventually) * continue processing rest of data/controls, beginning with URG */ case TCPS_SYN_SENT: if ((tiflags & TH_ACK) && (SEQ_LEQ(ti->ti_ack, tp->iss) || SEQ_GT(ti->ti_ack, tp->snd_max))) goto dropwithreset; if (tiflags & TH_RST) { if (tiflags & TH_ACK) tp = tcp_drop(tp, ECONNREFUSED); goto drop; } if ((tiflags & TH_SYN) == 0) goto drop; if (tiflags & TH_ACK) { tp->snd_una = ti->ti_ack; if (SEQ_LT(tp->snd_nxt, tp->snd_una)) tp->snd_nxt = tp->snd_una; } tp->t_timer[TCPT_REXMT] = 0; tp->irs = ti->ti_seq; tcp_rcvseqinit(tp); tp->t_flags |= TF_ACKNOW; if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) { tcpstat.tcps_connects++; soisconnected(so); tp->t_state = TCPS_ESTABLISHED; tp->t_maxseg = MIN(tp->t_maxseg, tcp_mss(tp)); (void) tcp_reass(tp, (struct tcpiphdr *)0); /* * if we didn't have to retransmit the SYN, * use its rtt as our initial srtt & rtt var. */ if (tp->t_rtt) { tp->t_srtt = tp->t_rtt << 3; tp->t_rttvar = tp->t_rtt << 1; TCPT_RANGESET(tp->t_rxtcur, ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1, TCPTV_MIN, TCPTV_REXMTMAX); tp->t_rtt = 0; } } else tp->t_state = TCPS_SYN_RECEIVED; trimthenstep6: /* * Advance ti->ti_seq to correspond to first data byte. * If data, trim to stay within window, * dropping FIN if necessary. */ ti->ti_seq++; if (ti->ti_len > tp->rcv_wnd) { todrop = ti->ti_len - tp->rcv_wnd; #if BSD>=43 m_adj(m, -todrop); #else /* XXX work around 4.2 m_adj bug */ if (m->m_len) { m_adj(m, -todrop); } else { /* skip tcp/ip header in first mbuf */ m_adj(m->m_next, -todrop); } #endif ti->ti_len = tp->rcv_wnd; tiflags &= ~TH_FIN; tcpstat.tcps_rcvpackafterwin++; tcpstat.tcps_rcvbyteafterwin += todrop; } tp->snd_wl1 = ti->ti_seq - 1; tp->rcv_up = ti->ti_seq; goto step6; } /* * States other than LISTEN or SYN_SENT. * First check that at least some bytes of segment are within * receive window. If segment begins before rcv_nxt, * drop leading data (and SYN); if nothing left, just ack. */ todrop = tp->rcv_nxt - ti->ti_seq; if (todrop > 0) { if (tiflags & TH_SYN) { tiflags &= ~TH_SYN; ti->ti_seq++; if (ti->ti_urp > 1) ti->ti_urp--; else tiflags &= ~TH_URG; todrop--; } if (todrop > ti->ti_len || todrop == ti->ti_len && (tiflags&TH_FIN) == 0) { tcpstat.tcps_rcvduppack++; tcpstat.tcps_rcvdupbyte += ti->ti_len; /* * If segment is just one to the left of the window, * check two special cases: * 1. Don't toss RST in response to 4.2-style keepalive. * 2. If the only thing to drop is a FIN, we can drop * it, but check the ACK or we will get into FIN * wars if our FINs crossed (both CLOSING). * In either case, send ACK to resynchronize, * but keep on processing for RST or ACK. */ if ((tiflags & TH_FIN && todrop == ti->ti_len + 1) #ifdef TCP_COMPAT_42 || (tiflags & TH_RST && ti->ti_seq == tp->rcv_nxt - 1) #endif ) { todrop = ti->ti_len; tiflags &= ~TH_FIN; tp->t_flags |= TF_ACKNOW; } else goto dropafterack; } else { tcpstat.tcps_rcvpartduppack++; tcpstat.tcps_rcvpartdupbyte += todrop; } m_adj(m, todrop); ti->ti_seq += todrop; ti->ti_len -= todrop; if (ti->ti_urp > todrop) ti->ti_urp -= todrop; else { tiflags &= ~TH_URG; ti->ti_urp = 0; } } /* * If new data are received on a connection after the * user processes are gone, then RST the other end. */ if ((so->so_state & SS_NOFDREF) && tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) { tp = tcp_close(tp); tcpstat.tcps_rcvafterclose++; goto dropwithreset; } /* * If segment ends after window, drop trailing data * (and PUSH and FIN); if nothing left, just ACK. */ todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd); if (todrop > 0) { tcpstat.tcps_rcvpackafterwin++; if (todrop >= ti->ti_len) { tcpstat.tcps_rcvbyteafterwin += ti->ti_len; /* * If a new connection request is received * while in TIME_WAIT, drop the old connection * and start over if the sequence numbers * are above the previous ones. */ if (tiflags & TH_SYN && tp->t_state == TCPS_TIME_WAIT && SEQ_GT(ti->ti_seq, tp->rcv_nxt)) { iss = tp->rcv_nxt + TCP_ISSINCR; (void) tcp_close(tp); goto findpcb; } /* * If window is closed can only take segments at * window edge, and have to drop data and PUSH from * incoming segments. Continue processing, but * remember to ack. Otherwise, drop segment * and ack. */ if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) { tp->t_flags |= TF_ACKNOW; tcpstat.tcps_rcvwinprobe++; } else goto dropafterack; } else tcpstat.tcps_rcvbyteafterwin += todrop; #if BSD>=43 m_adj(m, -todrop); #else /* XXX work around m_adj bug */ if (m->m_len) { m_adj(m, -todrop); } else { /* skip tcp/ip header in first mbuf */ m_adj(m->m_next, -todrop); } #endif ti->ti_len -= todrop; tiflags &= ~(TH_PUSH|TH_FIN); } /* * If the RST bit is set examine the state: * SYN_RECEIVED STATE: * If passive open, return to LISTEN state. * If active open, inform user that connection was refused. * ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES: * Inform user that connection was reset, and close tcb. * CLOSING, LAST_ACK, TIME_WAIT STATES * Close the tcb. */ if (tiflags&TH_RST) switch (tp->t_state) { case TCPS_SYN_RECEIVED: so->so_error = ECONNREFUSED; goto close; case TCPS_ESTABLISHED: case TCPS_FIN_WAIT_1: case TCPS_FIN_WAIT_2: case TCPS_CLOSE_WAIT: so->so_error = ECONNRESET; close: tp->t_state = TCPS_CLOSED; tcpstat.tcps_drops++; tp = tcp_close(tp); goto drop; case TCPS_CLOSING: case TCPS_LAST_ACK: case TCPS_TIME_WAIT: tp = tcp_close(tp); goto drop; } /* * If a SYN is in the window, then this is an * error and we send an RST and drop the connection. */ if (tiflags & TH_SYN) { tp = tcp_drop(tp, ECONNRESET); goto dropwithreset; } /* * If the ACK bit is off we drop the segment and return. */ if ((tiflags & TH_ACK) == 0) goto drop; /* * Ack processing. */ switch (tp->t_state) { /* * In SYN_RECEIVED state if the ack ACKs our SYN then enter * ESTABLISHED state and continue processing, otherwise * send an RST. */ case TCPS_SYN_RECEIVED: if (SEQ_GT(tp->snd_una, ti->ti_ack) || SEQ_GT(ti->ti_ack, tp->snd_max)) goto dropwithreset; tcpstat.tcps_connects++; soisconnected(so); tp->t_state = TCPS_ESTABLISHED; tp->t_maxseg = MIN(tp->t_maxseg, tcp_mss(tp)); (void) tcp_reass(tp, (struct tcpiphdr *)0); tp->snd_wl1 = ti->ti_seq - 1; /* fall into ... */ /* * In ESTABLISHED state: drop duplicate ACKs; ACK out of range * ACKs. If the ack is in the range * tp->snd_una < ti->ti_ack <= tp->snd_max * then advance tp->snd_una to ti->ti_ack and drop * data from the retransmission queue. If this ACK reflects * more up to date window information we update our window information. */ case TCPS_ESTABLISHED: case TCPS_FIN_WAIT_1: case TCPS_FIN_WAIT_2: case TCPS_CLOSE_WAIT: case TCPS_CLOSING: case TCPS_LAST_ACK: case TCPS_TIME_WAIT: if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) { if (ti->ti_len == 0 && ti->ti_win == tp->snd_wnd) { tcpstat.tcps_rcvdupack++; /* * If we have outstanding data (not a * window probe), this is a completely * duplicate ack (ie, window info didn't * change), the ack is the biggest we've * seen and we've seen exactly our rexmt * threshhold of them, assume a packet * has been dropped and retransmit it. * Kludge snd_nxt & the congestion * window so we send only this one * packet. If this packet fills the * only hole in the receiver's seq. * space, the next real ack will fully * open our window. This means we * have to do the usual slow-start to * not overwhelm an intermediate gateway * with a burst of packets. Leave * here with the congestion window set * to allow 2 packets on the next real * ack and the exp-to-linear thresh * set for half the current window * size (since we know we're losing at * the current window size). */ if (tp->t_timer[TCPT_REXMT] == 0 || ti->ti_ack != tp->snd_una) tp->t_dupacks = 0; else if (++tp->t_dupacks == tcprexmtthresh) { tcp_seq onxt = tp->snd_nxt; u_int win = MIN(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg; if (win < 2) win = 2; tp->snd_ssthresh = win * tp->t_maxseg; tp->t_timer[TCPT_REXMT] = 0; tp->t_rtt = 0; tp->snd_nxt = ti->ti_ack; tp->snd_cwnd = tp->t_maxseg; (void) tcp_output(tp); if (SEQ_GT(onxt, tp->snd_nxt)) tp->snd_nxt = onxt; goto drop; } } else tp->t_dupacks = 0; break; } tp->t_dupacks = 0; if (SEQ_GT(ti->ti_ack, tp->snd_max)) { tcpstat.tcps_rcvacktoomuch++; goto dropafterack; } acked = ti->ti_ack - tp->snd_una; tcpstat.tcps_rcvackpack++; tcpstat.tcps_rcvackbyte += acked; /* * If transmit timer is running and timed sequence * number was acked, update smoothed round trip time. * Since we now have an rtt measurement, cancel the * timer backoff (cf., Phil Karn's retransmit alg.). * Recompute the initial retransmit timer. */ if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq)) { tcpstat.tcps_rttupdated++; if (tp->t_srtt != 0) { register short delta; /* * srtt is stored as fixed point with 3 bits * after the binary point (i.e., scaled by 8). * The following magic is equivalent * to the smoothing algorithm in rfc793 * with an alpha of .875 * (srtt = rtt/8 + srtt*7/8 in fixed point). * Adjust t_rtt to origin 0. */ delta = tp->t_rtt - 1 - (tp->t_srtt >> 3); if ((tp->t_srtt += delta) <= 0) tp->t_srtt = 1; /* * We accumulate a smoothed rtt variance * (actually, a smoothed mean difference), * then set the retransmit timer to smoothed * rtt + 2 times the smoothed variance. * rttvar is stored as fixed point * with 2 bits after the binary point * (scaled by 4). The following is equivalent * to rfc793 smoothing with an alpha of .75 * (rttvar = rttvar*3/4 + |delta| / 4). * This replaces rfc793's wired-in beta. */ if (delta < 0) delta = -delta; delta -= (tp->t_rttvar >> 2); if ((tp->t_rttvar += delta) <= 0) tp->t_rttvar = 1; } else { /* * No rtt measurement yet - use the * unsmoothed rtt. Set the variance * to half the rtt (so our first * retransmit happens at 2*rtt) */ tp->t_srtt = tp->t_rtt << 3; tp->t_rttvar = tp->t_rtt << 1; } tp->t_rtt = 0; tp->t_rxtshift = 0; TCPT_RANGESET(tp->t_rxtcur, ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1, TCPTV_MIN, TCPTV_REXMTMAX); } /* * If all outstanding data is acked, stop retransmit * timer and remember to restart (more output or persist). * If there is more data to be acked, restart retransmit * timer, using current (possibly backed-off) value. */ if (ti->ti_ack == tp->snd_max) { tp->t_timer[TCPT_REXMT] = 0; needoutput = 1; } else if (tp->t_timer[TCPT_PERSIST] == 0) tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; /* * When new data is acked, open the congestion window. * If the window gives us less than ssthresh packets * in flight, open exponentially (maxseg per packet). * Otherwise open linearly (maxseg per window, * or maxseg^2 / cwnd per packet). */ { u_long incr = tp->t_maxseg; if (tp->snd_cwnd > tp->snd_ssthresh) incr = MAX((long)(incr * incr / tp->snd_cwnd), 1L); tp->snd_cwnd = MIN((long)(tp->snd_cwnd + incr), IP_MAXPACKET); /* XXX */ } if (acked > so->so_snd.sb_cc) { tp->snd_wnd -= so->so_snd.sb_cc; sbdrop(&so->so_snd, (int)so->so_snd.sb_cc); ourfinisacked = 1; } else { sbdrop(&so->so_snd, acked); tp->snd_wnd -= acked; ourfinisacked = 0; } if ((so->so_snd.sb_flags & SB_WAIT) || so->so_snd.sb_sel) sowwakeup(so); tp->snd_una = ti->ti_ack; if (SEQ_LT(tp->snd_nxt, tp->snd_una)) tp->snd_nxt = tp->snd_una; switch (tp->t_state) { /* * In FIN_WAIT_1 STATE in addition to the processing * for the ESTABLISHED state if our FIN is now acknowledged * then enter FIN_WAIT_2. */ case TCPS_FIN_WAIT_1: if (ourfinisacked) { /* * If we can't receive any more * data, then closing user can proceed. * Starting the timer is contrary to the * specification, but if we don't get a FIN * we'll hang forever. */ if (so->so_state & SS_CANTRCVMORE) { soisdisconnected(so); tp->t_timer[TCPT_2MSL] = tcp_maxidle; } tp->t_state = TCPS_FIN_WAIT_2; } break; /* * In CLOSING STATE in addition to the processing for * the ESTABLISHED state if the ACK acknowledges our FIN * then enter the TIME-WAIT state, otherwise ignore * the segment. */ case TCPS_CLOSING: if (ourfinisacked) { tp->t_state = TCPS_TIME_WAIT; tcp_canceltimers(tp); tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; soisdisconnected(so); } break; /* * In LAST_ACK, we may still be waiting for data to drain * and/or to be acked, as well as for the ack of our FIN. * If our FIN is now acknowledged, delete the TCB, * enter the closed state and return. */ case TCPS_LAST_ACK: if (ourfinisacked) { tp = tcp_close(tp); goto drop; } break; /* * In TIME_WAIT state the only thing that should arrive * is a retransmission of the remote FIN. Acknowledge * it and restart the finack timer. */ case TCPS_TIME_WAIT: tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; goto dropafterack; } } step6: /* * Update window information. * Don't look at window if no ACK: TAC's send garbage on first SYN. */ if ((tiflags & TH_ACK) && (SEQ_LT(tp->snd_wl1, ti->ti_seq) || tp->snd_wl1 == ti->ti_seq && (SEQ_LT(tp->snd_wl2, ti->ti_ack) || tp->snd_wl2 == ti->ti_ack && ti->ti_win > tp->snd_wnd))) { /* keep track of pure window updates */ if (ti->ti_len == 0 && tp->snd_wl2 == ti->ti_ack && ti->ti_win > tp->snd_wnd) tcpstat.tcps_rcvwinupd++; tp->snd_wnd = ti->ti_win; tp->snd_wl1 = ti->ti_seq; tp->snd_wl2 = ti->ti_ack; if (tp->snd_wnd > tp->max_sndwnd) tp->max_sndwnd = tp->snd_wnd; needoutput = 1; } /* * Process segments with URG. */ if ((tiflags & TH_URG) && ti->ti_urp && TCPS_HAVERCVDFIN(tp->t_state) == 0) { /* * This is a kludge, but if we receive and accept * random urgent pointers, we'll crash in * soreceive. It's hard to imagine someone * actually wanting to send this much urgent data. */ if (ti->ti_urp + so->so_rcv.sb_cc > SB_MAX) { ti->ti_urp = 0; /* XXX */ tiflags &= ~TH_URG; /* XXX */ goto dodata; /* XXX */ } /* * If this segment advances the known urgent pointer, * then mark the data stream. This should not happen * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since * a FIN has been received from the remote side. * In these states we ignore the URG. * * According to RFC961 (Assigned Protocols), * the urgent pointer points to the last octet * of urgent data. We continue, however, * to consider it to indicate the first octet * of data past the urgent section * as the original spec states. */ if (SEQ_GT(ti->ti_seq+ti->ti_urp, tp->rcv_up)) { tp->rcv_up = ti->ti_seq + ti->ti_urp; so->so_oobmark = so->so_rcv.sb_cc + (tp->rcv_up - tp->rcv_nxt) - 1; if (so->so_oobmark == 0) so->so_state |= SS_RCVATMARK; sohasoutofband(so); tp->t_oobflags &= ~(TCPOOB_HAVEDATA | TCPOOB_HADDATA); } /* * Remove out of band data so doesn't get presented to user. * This can happen independent of advancing the URG pointer, * but if two URG's are pending at once, some out-of-band * data may creep in... ick. */ if (ti->ti_urp <= ti->ti_len #ifdef SO_OOBINLINE && (so->so_options & SO_OOBINLINE) == 0 #endif ) tcp_pulloutofband(so, ti); } else /* * If no out of band data is expected, * pull receive urgent pointer along * with the receive window. */ if (SEQ_GT(tp->rcv_nxt, tp->rcv_up)) tp->rcv_up = tp->rcv_nxt; dodata: /* XXX */ /* * Process the segment text, merging it into the TCP sequencing queue, * and arranging for acknowledgment of receipt if necessary. * This process logically involves adjusting tp->rcv_wnd as data * is presented to the user (this happens in tcp_usrreq.c, * case PRU_RCVD). If a FIN has already been received on this * connection then we just ignore the text. */ if ((ti->ti_len || (tiflags&TH_FIN)) && TCPS_HAVERCVDFIN(tp->t_state) == 0) { TCP_REASS(tp, ti, m, so, tiflags); if (tcpnodelack == 0) tp->t_flags |= TF_DELACK; else tp->t_flags |= TF_ACKNOW; /* * Note the amount of data that peer has sent into * our window, in order to estimate the sender's * buffer size. */ len = so->so_rcv.sb_hiwat - (tp->rcv_adv - tp->rcv_nxt); if (len > tp->max_rcvd) tp->max_rcvd = len; } else { m_freem(m); tiflags &= ~TH_FIN; } /* * If FIN is received ACK the FIN and let the user know * that the connection is closing. */ if (tiflags & TH_FIN) { if (TCPS_HAVERCVDFIN(tp->t_state) == 0) { socantrcvmore(so); tp->t_flags |= TF_ACKNOW; tp->rcv_nxt++; } switch (tp->t_state) { /* * In SYN_RECEIVED and ESTABLISHED STATES * enter the CLOSE_WAIT state. */ case TCPS_SYN_RECEIVED: case TCPS_ESTABLISHED: tp->t_state = TCPS_CLOSE_WAIT; break; /* * If still in FIN_WAIT_1 STATE FIN has not been acked so * enter the CLOSING state. */ case TCPS_FIN_WAIT_1: tp->t_state = TCPS_CLOSING; break; /* * In FIN_WAIT_2 state enter the TIME_WAIT state, * starting the time-wait timer, turning off the other * standard timers. */ case TCPS_FIN_WAIT_2: tp->t_state = TCPS_TIME_WAIT; tcp_canceltimers(tp); tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; soisdisconnected(so); break; /* * In TIME_WAIT state restart the 2 MSL time_wait timer. */ case TCPS_TIME_WAIT: tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; break; } } if (so->so_options & SO_DEBUG) tcp_trace(TA_INPUT, ostate, tp, &tcp_saveti, 0); /* * Return any desired output. */ if (needoutput || (tp->t_flags & TF_ACKNOW)) (void) tcp_output(tp); return; dropafterack: /* * Generate an ACK dropping incoming segment if it occupies * sequence space, where the ACK reflects our state. */ if (tiflags & TH_RST) goto drop; m_freem(m); tp->t_flags |= TF_ACKNOW; (void) tcp_output(tp); return; dropwithreset: if (om) { (void) m_free(om); om = 0; } /* * Generate a RST, dropping incoming segment. * Make ACK acceptable to originator of segment. * Don't bother to respond if destination was broadcast. */ if ((tiflags & TH_RST) || in_broadcast(ti->ti_dst)) goto drop; if (tiflags & TH_ACK) tcp_respond(tp, ti, (tcp_seq)0, ti->ti_ack, TH_RST); else { if (tiflags & TH_SYN) ti->ti_len++; tcp_respond(tp, ti, ti->ti_seq+ti->ti_len, (tcp_seq)0, TH_RST|TH_ACK); } /* destroy temporarily created socket */ if (dropsocket) (void) soabort(so); return; drop: if (om) (void) m_free(om); /* * Drop space held by incoming segment and return. */ if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) tcp_trace(TA_DROP, ostate, tp, &tcp_saveti, 0); m_freem(m); /* destroy temporarily created socket */ if (dropsocket) (void) soabort(so); return; } tcp_dooptions(tp, om, ti) struct tcpcb *tp; struct mbuf *om; struct tcpiphdr *ti; { register u_char *cp; int opt, optlen, cnt; cp = mtod(om, u_char *); cnt = om->m_len; for (; cnt > 0; cnt -= optlen, cp += optlen) { opt = UCHAR(cp[0]); if (opt == TCPOPT_EOL) break; if (opt == TCPOPT_NOP) optlen = 1; else { optlen = UCHAR(cp[1]); if (optlen <= 0) break; } switch (opt) { default: break; case TCPOPT_MAXSEG: if (optlen != 4) continue; if (!(ti->ti_flags & TH_SYN)) continue; tp->t_maxseg = *(u_short *)(cp + 2); tp->t_maxseg = ntohs((u_short)tp->t_maxseg); tp->t_maxseg = MIN(tp->t_maxseg, tcp_mss(tp)); break; } } (void) m_free(om); } /* * Pull out of band byte out of a segment so * it doesn't appear in the user's data queue. * It is still reflected in the segment length for * sequencing purposes. */ tcp_pulloutofband(so, ti) struct socket *so; struct tcpiphdr *ti; { register struct mbuf *m; int cnt = ti->ti_urp - 1; m = dtom(ti); while (cnt >= 0) { if (m->m_len > cnt) { char *cp = mtod(m, caddr_t) + cnt; struct tcpcb *tp = sototcpcb(so); tp->t_iobc = *cp; tp->t_oobflags |= TCPOOB_HAVEDATA; bcopy(cp+1, cp, (unsigned)(m->m_len - cnt - 1)); m->m_len--; return; } cnt -= m->m_len; m = m->m_next; if (m == 0) break; } panic("tcp_pulloutofband"); } /* * Determine a reasonable value for maxseg size. * If the route is known, use one that can be handled * on the given interface without forcing IP to fragment. * If bigger than an mbuf cluster (MCLBYTES), round down to nearest size * to utilize large mbufs. * If interface pointer is unavailable, or the destination isn't local, * use a conservative size (512 or the default IP max size, but no more * than the mtu of the interface through which we route), * as we can't discover anything about intervening gateways or networks. * We also initialize the congestion/slow start window to be a single * segment if the destination isn't local; this information should * probably all be saved with the routing entry at the transport level. * * This is ugly, and doesn't belong at this level, but has to happen somehow. */ tcp_mss(tp) register struct tcpcb *tp; { struct route *ro; struct ifnet *ifp; int mss; struct inpcb *inp; inp = tp->t_inpcb; ro = &inp->inp_route; if ((ro->ro_rt == (struct rtentry *)0) || (ifp = ro->ro_rt->rt_ifp) == (struct ifnet *)0) { /* No route yet, so try to acquire one */ if (inp->inp_faddr.s_addr != INADDR_ANY) { ro->ro_dst.sa_family = AF_INET; ((struct sockaddr_in *) &ro->ro_dst)->sin_addr = inp->inp_faddr; rtalloc(ro); } if ((ro->ro_rt == 0) || (ifp = ro->ro_rt->rt_ifp) == 0) return (TCP_MSS); } mss = ifp->if_mtu - sizeof(struct tcpiphdr); #if (MCLBYTES & (MCLBYTES - 1)) == 0 if (mss > MCLBYTES) mss &= ~(MCLBYTES-1); #else if (mss > MCLBYTES) mss = mss / MCLBYTES * MCLBYTES; #endif if (in_localaddr(inp->inp_faddr)) return (mss); mss = MIN(mss, TCP_MSS); tp->snd_cwnd = mss; return (mss); } #if BSD<43 /* XXX this belongs in netinet/in.c */ in_localaddr(in) struct in_addr in; { register u_long i = ntohl(in.s_addr); register struct ifnet *ifp; register struct sockaddr_in *sin; register u_long mask; if (IN_CLASSA(i)) mask = IN_CLASSA_NET; else if (IN_CLASSB(i)) mask = IN_CLASSB_NET; else if (IN_CLASSC(i)) mask = IN_CLASSC_NET; else return (0); i &= mask; for (ifp = ifnet; ifp; ifp = ifp->if_next) { if (ifp->if_addr.sa_family != AF_INET) continue; sin = (struct sockaddr_in *)&ifp->if_addr; if ((sin->sin_addr.s_addr & mask) == i) return (1); } return (0); } #endif L; soisdisconnected(so); } break; /* * In LAST_ACK, we may still be waiting for data to drain * and/or to be acked, as well as for the ack of our FIN. * If our FIN is now acknowledged, delete the TCB, * enter the closed state and return. */ case TCPS_LAST_ACK: if (ourfinisacked) { tp = tcp_csys/netinet/tcp_output.c 444 0 0 27175 6036654252 10705 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)tcp_output.c 7.13.1.4 (Berkeley) 1995/10/10 */ #include "param.h" #include "systm.h" #include "mbuf.h" #include "protosw.h" #include "socket.h" #include "socketvar.h" #include "errno.h" #include "../net/route.h" #include "domain.h" #include "in.h" #include "in_pcb.h" #include "in_systm.h" #include "ip.h" #include "ip_var.h" #include "tcp.h" #define TCPOUTFLAGS #include "tcp_fsm.h" #include "tcp_seq.h" #include "tcp_timer.h" #include "tcp_var.h" #include "tcpip.h" #include "tcp_debug.h" /* * Initial options. */ u_char tcp_initopt[4] = { TCPOPT_MAXSEG, 4, 0x0, 0x0, }; /* * Tcp output routine: figure out what should be sent and send it. */ tcp_output(tp) register struct tcpcb *tp; { register struct socket *so = tp->t_inpcb->inp_socket; register int len, win; struct mbuf *m0; int off, flags, error; register struct mbuf *m; register struct tcpiphdr *ti; u_char *opt; unsigned optlen = 0; int idle, sendalot; /* * Determine length of data that should be transmitted, * and flags that will be used. * If there is some data or critical controls (SYN, RST) * to send, then transmit; otherwise, investigate further. */ idle = (tp->snd_max == tp->snd_una); again: sendalot = 0; off = tp->snd_nxt - tp->snd_una; win = MIN(tp->snd_wnd, tp->snd_cwnd); /* * If in persist timeout with window of 0, send 1 byte. * Otherwise, if window is small but nonzero * and timer expired, we will send what we can * and go to transmit state. */ if (tp->t_force) { if (win == 0) win = 1; else { tp->t_timer[TCPT_PERSIST] = 0; tp->t_rxtshift = 0; } } len = MIN(so->so_snd.sb_cc, win) - off; flags = tcp_outflags[tp->t_state]; if (len < 0) { /* * If FIN has been sent but not acked, * but we haven't been called to retransmit, * len will be -1. Otherwise, window shrank * after we sent into it. If window shrank to 0, * cancel pending retransmit and pull snd_nxt * back to (closed) window. We will enter persist * state below. If the window didn't close completely, * just wait for an ACK. */ len = 0; if (win == 0) { tp->t_timer[TCPT_REXMT] = 0; tp->snd_nxt = tp->snd_una; } } if (len > tp->t_maxseg) { len = tp->t_maxseg; sendalot = 1; } if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc)) flags &= ~TH_FIN; win = sbspace(&so->so_rcv); /* * If our state indicates that FIN should be sent * and we have not yet done so, or we're retransmitting the FIN, * then we need to send. */ if (flags & TH_FIN && ((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una)) goto send; /* * Send if we owe peer an ACK. */ if (tp->t_flags & TF_ACKNOW) goto send; if (flags & (TH_SYN|TH_RST)) goto send; if (SEQ_GT(tp->snd_up, tp->snd_una)) goto send; /* * Sender silly window avoidance. If connection is idle * and can send all data, a maximum segment, * at least a maximum default-size segment do it, * or are forced, do it; otherwise don't bother. * If peer's buffer is tiny, then send * when window is at least half open. * If retransmitting (possibly after persist timer forced us * to send into a small window), then must resend. */ if (len) { if (len == tp->t_maxseg) goto send; if ((idle || tp->t_flags & TF_NODELAY) && len + off >= so->so_snd.sb_cc) goto send; if (tp->t_force) goto send; if (len >= tp->max_sndwnd / 2) goto send; if (SEQ_LT(tp->snd_nxt, tp->snd_max)) goto send; } /* * Compare available window to amount of window * known to peer (as advertised window less * next expected input). If the difference is at least two * max size segments or at least 35% of the maximum possible * window, then want to send a window update to peer. */ if (win > 0) { int adv = win - (tp->rcv_adv - tp->rcv_nxt); if (so->so_rcv.sb_cc == 0 && adv >= 2 * tp->t_maxseg) goto send; if (100 * adv / so->so_rcv.sb_hiwat >= 35) goto send; } /* * TCP window updates are not reliable, rather a polling protocol * using ``persist'' packets is used to insure receipt of window * updates. The three ``states'' for the output side are: * idle not doing retransmits or persists * persisting to move a small or zero window * (re)transmitting and thereby not persisting * * tp->t_timer[TCPT_PERSIST] * is set when we are in persist state. * tp->t_force * is set when we are called to send a persist packet. * tp->t_timer[TCPT_REXMT] * is set when we are retransmitting * The output side is idle when both timers are zero. * * If send window is too small, there is data to transmit, and no * retransmit or persist is pending, then go to persist state. * If nothing happens soon, send when timer expires: * if window is nonzero, transmit what we can, * otherwise force out a byte. */ if (so->so_snd.sb_cc && tp->t_timer[TCPT_REXMT] == 0 && tp->t_timer[TCPT_PERSIST] == 0) { tp->t_rxtshift = 0; tcp_setpersist(tp); } /* * No reason to send a segment, just return. */ return (0); send: /* * Grab a header mbuf, attaching a copy of data to * be transmitted, and initialize the header from * the template for sends on this connection. */ MGET(m, M_DONTWAIT, MT_HEADER); if (m == NULL) return (ENOBUFS); m->m_off = MMAXOFF - sizeof (struct tcpiphdr); m->m_len = sizeof (struct tcpiphdr); if (len) { if (tp->t_force && len == 1) tcpstat.tcps_sndprobe++; else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) { tcpstat.tcps_sndrexmitpack++; tcpstat.tcps_sndrexmitbyte += len; } else { tcpstat.tcps_sndpack++; tcpstat.tcps_sndbyte += len; } m->m_next = m_copy(so->so_snd.sb_mb, off, len); if (m->m_next == 0) len = 0; } else if (tp->t_flags & TF_ACKNOW) tcpstat.tcps_sndacks++; else if (flags & (TH_SYN|TH_FIN|TH_RST)) tcpstat.tcps_sndctrl++; else if (SEQ_GT(tp->snd_up, tp->snd_una)) tcpstat.tcps_sndurg++; else tcpstat.tcps_sndwinup++; ti = mtod(m, struct tcpiphdr *); if (tp->t_template == 0) panic("tcp_output"); bcopy((caddr_t)tp->t_template, (caddr_t)ti, sizeof (struct tcpiphdr)); /* * Fill in fields, remembering maximum advertised * window for use in delaying messages about window sizes. * If resending a FIN, be sure not to use a new sequence number. */ if (flags & TH_FIN && tp->t_flags & TF_SENTFIN && tp->snd_nxt == tp->snd_max) tp->snd_nxt--; ti->ti_seq = htonl(tp->snd_nxt); ti->ti_ack = htonl(tp->rcv_nxt); /* * Before ESTABLISHED, force sending of initial options * unless TCP set to not do any options. */ opt = NULL; if (flags & TH_SYN && (tp->t_flags & TF_NOOPT) == 0) { u_short mss; mss = MIN(so->so_rcv.sb_hiwat / 2, tcp_mss(tp)); if (mss > IP_MSS - sizeof(struct tcpiphdr)) { opt = tcp_initopt; optlen = sizeof (tcp_initopt); *(u_short *)(opt + 2) = htons(mss); } } if (opt) { m0 = m->m_next; m->m_next = m_get(M_DONTWAIT, MT_DATA); if (m->m_next == 0) { (void) m_free(m); m_freem(m0); return (ENOBUFS); } m->m_next->m_next = m0; m0 = m->m_next; m0->m_len = optlen; bcopy((caddr_t)opt, mtod(m0, caddr_t), optlen); opt = (u_char *)(mtod(m0, caddr_t) + optlen); while (m0->m_len & 0x3) { *opt++ = TCPOPT_EOL; m0->m_len++; } optlen = m0->m_len; ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2; } ti->ti_flags = flags; /* * Calculate receive window. Don't shrink window, * but avoid silly window syndrome. */ if (win < (so->so_rcv.sb_hiwat / 4) && win < tp->t_maxseg) win = 0; if (win < (int)(tp->rcv_adv - tp->rcv_nxt)) win = (int)(tp->rcv_adv - tp->rcv_nxt); if (win > IP_MAXPACKET) win = IP_MAXPACKET; ti->ti_win = htons((u_short)win); if (SEQ_GT(tp->snd_up, tp->snd_nxt)) { ti->ti_urp = htons((u_short)(tp->snd_up - tp->snd_nxt)); ti->ti_flags |= TH_URG; } else /* * If no urgent pointer to send, then we pull * the urgent pointer to the left edge of the send window * so that it doesn't drift into the send window on sequence * number wraparound. */ tp->snd_up = tp->snd_una; /* drag it along */ /* * If anything to send and we can send it all, set PUSH. * (This will keep happy those implementations which only * give data to the user when a buffer fills or a PUSH comes in.) */ if (len && off+len == so->so_snd.sb_cc) ti->ti_flags |= TH_PUSH; /* * Put TCP length in extended header, and then * checksum extended header and data. */ if (len + optlen) ti->ti_len = htons((u_short)(sizeof(struct tcphdr) + optlen + len)); ti->ti_sum = in_cksum(m, sizeof (struct tcpiphdr) + (int)optlen + len); /* * In transmit state, time the transmission and arrange for * the retransmit. In persist state, just set snd_max. */ if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) { tcp_seq startseq = tp->snd_nxt; /* * Advance snd_nxt over sequence space of this segment. */ if (flags & TH_SYN) tp->snd_nxt++; if (flags & TH_FIN) { tp->snd_nxt++; tp->t_flags |= TF_SENTFIN; } tp->snd_nxt += len; if (SEQ_GT(tp->snd_nxt, tp->snd_max)) { tp->snd_max = tp->snd_nxt; /* * Time this transmission if not a retransmission and * not currently timing anything. */ if (tp->t_rtt == 0) { tp->t_rtt = 1; tp->t_rtseq = startseq; tcpstat.tcps_segstimed++; } } /* * Set retransmit timer if not currently set, * and not doing an ack or a keep-alive probe. * Initial value for retransmit timer is smoothed * round-trip time + 2 * round-trip time variance. * Initialize shift counter which is used for backoff * of retransmit time. */ if (tp->t_timer[TCPT_REXMT] == 0 && tp->snd_nxt != tp->snd_una) { tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; if (tp->t_timer[TCPT_PERSIST]) { tp->t_timer[TCPT_PERSIST] = 0; tp->t_rxtshift = 0; } } } else if (SEQ_GT(tp->snd_nxt + len, tp->snd_max)) tp->snd_max = tp->snd_nxt + len; /* * Trace. */ if (so->so_options & SO_DEBUG) tcp_trace(TA_OUTPUT, tp->t_state, tp, ti, 0); /* * Fill in IP length and desired time to live and * send to IP level. */ ((struct ip *)ti)->ip_len = sizeof (struct tcpiphdr) + optlen + len; ((struct ip *)ti)->ip_ttl = ip_defttl; /* XXX */ #if BSD>=43 error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route, so->so_options & SO_DONTROUTE); #else error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route, so->so_options & SO_DONTROUTE); #endif if (error) { if (error == ENOBUFS) { tcp_quench(tp->t_inpcb); return (0); } return (error); } tcpstat.tcps_sndtotal++; /* * Data sent (as far as we can tell). * If this advertises a larger window than any other segment, * then remember the size of the advertised window. * Any pending ACK has now been sent. */ if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv)) tp->rcv_adv = tp->rcv_nxt + win; tp->t_flags &= ~(TF_ACKNOW|TF_DELACK); if (sendalot) goto again; return (0); } tcp_setpersist(tp) register struct tcpcb *tp; { register t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1; if (tp->t_timer[TCPT_REXMT]) panic("tcp_output REXMT"); /* * Start/restart persistance timer. */ TCPT_RANGESET(tp->t_timer[TCPT_PERSIST], t * tcp_backoff[tp->t_rxtshift], TCPTV_PERSMIN, TCPTV_PERSMAX); if (tp->t_rxtshift < TCP_MAXRXTSHIFT) tp->t_rxtshift++; } o->so_state |= SS_RCVATMARK; sohasoutofband(so); tp->t_oobflags &= ~(TCPOOB_HAVEDATA | TCPOOB_HADDATA); } /* * Remove out of band data so doesn't get presented to user. * This can happen independent of advancing the URG pointer, * but if two URG's are pending at once, some out-of-band * data may creep in... ick. */ if (ti->ti_urp <= ti->ti_len #ifdef SO_OOBIsys/netinet/tcp_timer.c 444 0 0 16441 4235737516 10463 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)tcp_timer.c 7.11.1.2 (Berkeley) 3/16/88 */ #include "param.h" #include "systm.h" #include "mbuf.h" #include "socket.h" #include "socketvar.h" #include "protosw.h" #include "errno.h" #include "../net/if.h" #include "../net/route.h" #include "domain.h" #include "in.h" #include "in_pcb.h" #include "in_systm.h" #include "ip.h" #include "ip_var.h" #include "tcp.h" #include "tcp_fsm.h" #include "tcp_seq.h" #include "tcp_timer.h" #include "tcp_var.h" #include "tcpip.h" int tcpnodelack = 0; int tcp_keepidle = TCPTV_KEEP_IDLE; int tcp_keepintvl = TCPTV_KEEPINTVL; int tcp_maxidle; /* * Fast timeout routine for processing delayed acks */ tcp_fasttimo() { register struct inpcb *inp; register struct tcpcb *tp; int s = splnet(); inp = tcb.inp_next; if (inp) for (; inp != &tcb; inp = inp->inp_next) if ((tp = (struct tcpcb *)inp->inp_ppcb) && (tp->t_flags & TF_DELACK)) { tp->t_flags &= ~TF_DELACK; tp->t_flags |= TF_ACKNOW; tcpstat.tcps_delack++; (void) tcp_output(tp); } splx(s); } /* * Tcp protocol timeout routine called every 500 ms. * Updates the timers in all active tcb's and * causes finite state machine actions if timers expire. */ tcp_slowtimo() { register struct inpcb *ip, *ipnxt; register struct tcpcb *tp; int s = splnet(); register int i; tcp_maxidle = TCPTV_KEEPCNT * tcp_keepintvl; /* * Search through tcb's and update active timers. */ ip = tcb.inp_next; if (ip == 0) { splx(s); return; } for (; ip != &tcb; ip = ipnxt) { ipnxt = ip->inp_next; tp = intotcpcb(ip); if (tp == 0) continue; for (i = 0; i < TCPT_NTIMERS; i++) { if (tp->t_timer[i] && --tp->t_timer[i] == 0) { (void) tcp_usrreq(tp->t_inpcb->inp_socket, PRU_SLOWTIMO, (struct mbuf *)0, (struct mbuf *)i, (struct mbuf *)0); if (ipnxt->inp_prev != ip) goto tpgone; } } tp->t_idle++; if (tp->t_rtt) tp->t_rtt++; tpgone: ; } tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ #ifdef TCP_COMPAT_42 if ((long)tcp_iss < 0) tcp_iss = 0; /* XXX */ #endif splx(s); } /* * Cancel all timers for TCP tp. */ tcp_canceltimers(tp) struct tcpcb *tp; { register int i; for (i = 0; i < TCPT_NTIMERS; i++) tp->t_timer[i] = 0; } int tcp_backoff[TCP_MAXRXTSHIFT + 1] = { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 }; /* * TCP timer processing. */ struct tcpcb * tcp_timers(tp, timer) register struct tcpcb *tp; int timer; { register int rexmt; switch (timer) { /* * 2 MSL timeout in shutdown went off. If we're closed but * still waiting for peer to close and connection has been idle * too long, or if 2MSL time is up from TIME_WAIT, delete connection * control block. Otherwise, check again in a bit. */ case TCPT_2MSL: if (tp->t_state != TCPS_TIME_WAIT && tp->t_idle <= tcp_maxidle) tp->t_timer[TCPT_2MSL] = tcp_keepintvl; else tp = tcp_close(tp); break; /* * Retransmission timer went off. Message has not * been acked within retransmit interval. Back off * to a longer retransmit interval and retransmit one segment. */ case TCPT_REXMT: if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) { tp->t_rxtshift = TCP_MAXRXTSHIFT; tcpstat.tcps_timeoutdrop++; tp = tcp_drop(tp, ETIMEDOUT); break; } tcpstat.tcps_rexmttimeo++; rexmt = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1; rexmt *= tcp_backoff[tp->t_rxtshift]; TCPT_RANGESET(tp->t_rxtcur, rexmt, TCPTV_MIN, TCPTV_REXMTMAX); tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; /* * If losing, let the lower level know and try for * a better route. Also, if we backed off this far, * our srtt estimate is probably bogus. Clobber it * so we'll take the next rtt measurement as our srtt; * move the current srtt into rttvar to keep the current * retransmit times until then. */ if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) { #if BSD>=43 in_losing(tp->t_inpcb); #endif tp->t_rttvar += (tp->t_srtt >> 2); tp->t_srtt = 0; } tp->snd_nxt = tp->snd_una; /* * If timing a segment in this window, stop the timer. */ tp->t_rtt = 0; /* * Close the congestion window down to one segment * (we'll open it by one segment for each ack we get). * Since we probably have a window's worth of unacked * data accumulated, this "slow start" keeps us from * dumping all that data as back-to-back packets (which * might overwhelm an intermediate gateway). * * There are two phases to the opening: Initially we * open by one mss on each ack. This makes the window * size increase exponentially with time. If the * window is larger than the path can handle, this * exponential growth results in dropped packet(s) * almost immediately. To get more time between * drops but still "push" the network to take advantage * of improving conditions, we switch from exponential * to linear window opening at some threshhold size. * For a threshhold, we use half the current window * size, truncated to a multiple of the mss. * * (the minimum cwnd that will give us exponential * growth is 2 mss. We don't allow the threshhold * to go below this.) */ { u_int win = MIN(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg; if (win < 2) win = 2; tp->snd_cwnd = tp->t_maxseg; tp->snd_ssthresh = win * tp->t_maxseg; } (void) tcp_output(tp); break; /* * Persistance timer into zero window. * Force a byte to be output, if possible. */ case TCPT_PERSIST: tcpstat.tcps_persisttimeo++; tcp_setpersist(tp); tp->t_force = 1; (void) tcp_output(tp); tp->t_force = 0; break; /* * Keep-alive timer went off; send something * or drop connection if idle for too long. */ case TCPT_KEEP: tcpstat.tcps_keeptimeo++; if (tp->t_state < TCPS_ESTABLISHED) goto dropit; if (tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE && tp->t_state <= TCPS_CLOSE_WAIT) { if (tp->t_idle >= tcp_keepidle + tcp_maxidle) goto dropit; /* * Send a packet designed to force a response * if the peer is up and reachable: * either an ACK if the connection is still alive, * or an RST if the peer has closed the connection * due to timeout or reboot. * Using sequence number tp->snd_una-1 * causes the transmitted zero-length segment * to lie outside the receive window; * by the protocol spec, this requires the * correspondent TCP to respond. */ tcpstat.tcps_keepprobe++; #ifdef TCP_COMPAT_42 /* * The keepalive packet must have nonzero length * to get a 4.2 host to respond. */ tcp_respond(tp, tp->t_template, tp->rcv_nxt - 1, tp->snd_una - 1, 0); #else tcp_respond(tp, tp->t_template, tp->rcv_nxt, tp->snd_una - 1, 0); #endif tp->t_timer[TCPT_KEEP] = tcp_keepintvl; } else tp->t_timer[TCPT_KEEP] = tcp_keepidle; break; dropit: tcpstat.tcps_keepdrops++; tp = tcp_drop(tp, ETIMEDOUT); break; } return (tp); } nd-trip time + 2 * round-trip time variance. * Initialize shift counter which is used for backoff * of retransmit time. */ if (tp->t_timer[TCPT_REXMT] == 0 && tp->snd_nxt != tp->snd_una) { tp->t_timer[TCsys/netinet/tcp_usrreq.c 444 0 0 25201 4235737701 10652 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)tcp_usrreq.c 7.7.1.2 (Berkeley) 3/16/88 */ #include "param.h" #include "systm.h" #include "mbuf.h" #include "socket.h" #include "socketvar.h" #include "protosw.h" #include "errno.h" #include "stat.h" #include "../net/if.h" #include "../net/route.h" #include "domain.h" #include "in.h" #include "in_pcb.h" #include "in_systm.h" #include "ip.h" #include "ip_var.h" #include "tcp.h" #include "tcp_fsm.h" #include "tcp_seq.h" #include "tcp_timer.h" #include "tcp_var.h" #include "tcpip.h" #include "tcp_debug.h" /* * TCP protocol interface to socket abstraction. */ extern char *tcpstates[]; struct tcpcb *tcp_newtcpcb(); /* * Process a TCP user request for TCP tb. If this is a send request * then m is the mbuf chain of send data. If this is a timer expiration * (called from the software clock routine), then timertype tells which timer. */ /*ARGSUSED*/ tcp_usrreq(so, req, m, nam, rights) struct socket *so; int req; struct mbuf *m, *nam, *rights; { register struct inpcb *inp; register struct tcpcb *tp; int s; int error = 0; int ostate; #if BSD>=43 if (req == PRU_CONTROL) return (in_control(so, (int)m, (caddr_t)nam, (struct ifnet *)rights)); #else if (req == PRU_CONTROL) return(EOPNOTSUPP); #endif if (rights && rights->m_len) return (EINVAL); s = splnet(); inp = sotoinpcb(so); /* * When a TCP is attached to a socket, then there will be * a (struct inpcb) pointed at by the socket, and this * structure will point at a subsidary (struct tcpcb). */ if (inp == 0 && req != PRU_ATTACH) { splx(s); return (EINVAL); /* XXX */ } if (inp) { tp = intotcpcb(inp); /* WHAT IF TP IS 0? */ #ifdef KPROF tcp_acounts[tp->t_state][req]++; #endif ostate = tp->t_state; } else ostate = 0; switch (req) { /* * TCP attaches to socket via PRU_ATTACH, reserving space, * and an internet control block. */ case PRU_ATTACH: if (inp) { error = EISCONN; break; } error = tcp_attach(so); if (error) break; if ((so->so_options & SO_LINGER) && so->so_linger == 0) so->so_linger = TCP_LINGERTIME; tp = sototcpcb(so); break; /* * PRU_DETACH detaches the TCP protocol from the socket. * If the protocol state is non-embryonic, then can't * do this directly: have to initiate a PRU_DISCONNECT, * which may finish later; embryonic TCB's can just * be discarded here. */ case PRU_DETACH: if (tp->t_state > TCPS_LISTEN) tp = tcp_disconnect(tp); else tp = tcp_close(tp); break; /* * Give the socket an address. */ case PRU_BIND: error = in_pcbbind(inp, nam); if (error) break; break; /* * Prepare to accept connections. */ case PRU_LISTEN: if (inp->inp_lport == 0) error = in_pcbbind(inp, (struct mbuf *)0); if (error == 0) tp->t_state = TCPS_LISTEN; break; /* * Initiate connection to peer. * Create a template for use in transmissions on this connection. * Enter SYN_SENT state, and mark socket as connecting. * Start keep-alive timer, and seed output sequence space. * Send initial segment on connection. */ case PRU_CONNECT: if (inp->inp_lport == 0) { error = in_pcbbind(inp, (struct mbuf *)0); if (error) break; } error = in_pcbconnect(inp, nam); if (error) break; tp->t_template = tcp_template(tp); if (tp->t_template == 0) { in_pcbdisconnect(inp); error = ENOBUFS; break; } soisconnecting(so); tcpstat.tcps_connattempt++; tp->t_state = TCPS_SYN_SENT; tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; tcp_sendseqinit(tp); error = tcp_output(tp); break; /* * Create a TCP connection between two sockets. */ case PRU_CONNECT2: error = EOPNOTSUPP; break; /* * Initiate disconnect from peer. * If connection never passed embryonic stage, just drop; * else if don't need to let data drain, then can just drop anyways, * else have to begin TCP shutdown process: mark socket disconnecting, * drain unread data, state switch to reflect user close, and * send segment (e.g. FIN) to peer. Socket will be really disconnected * when peer sends FIN and acks ours. * * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB. */ case PRU_DISCONNECT: tp = tcp_disconnect(tp); break; /* * Accept a connection. Essentially all the work is * done at higher levels; just return the address * of the peer, storing through addr. */ case PRU_ACCEPT: { struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); nam->m_len = sizeof (struct sockaddr_in); sin->sin_family = AF_INET; sin->sin_port = inp->inp_fport; sin->sin_addr = inp->inp_faddr; break; } /* * Mark the connection as being incapable of further output. */ case PRU_SHUTDOWN: socantsendmore(so); tp = tcp_usrclosed(tp); if (tp) error = tcp_output(tp); break; /* * After a receive, possibly send window update to peer. */ case PRU_RCVD: (void) tcp_output(tp); break; /* * Do a send by putting data in output queue and updating urgent * marker if URG set. Possibly send more data. */ case PRU_SEND: sbappend(&so->so_snd, m); error = tcp_output(tp); break; /* * Abort the TCP. */ case PRU_ABORT: tp = tcp_drop(tp, ECONNABORTED); break; case PRU_SENSE: ((struct stat *) m)->st_blksize = so->so_snd.sb_hiwat; (void) splx(s); return (0); case PRU_RCVOOB: if ((so->so_oobmark == 0 && (so->so_state & SS_RCVATMARK) == 0) || #ifdef SO_OOBINLINE so->so_options & SO_OOBINLINE || #endif tp->t_oobflags & TCPOOB_HADDATA) { error = EINVAL; break; } if ((tp->t_oobflags & TCPOOB_HAVEDATA) == 0) { error = EWOULDBLOCK; break; } m->m_len = 1; *mtod(m, caddr_t) = tp->t_iobc; if (((int)nam & MSG_PEEK) == 0) tp->t_oobflags ^= (TCPOOB_HAVEDATA | TCPOOB_HADDATA); break; case PRU_SENDOOB: if (sbspace(&so->so_snd) < -512) { m_freem(m); error = ENOBUFS; break; } /* * According to RFC961 (Assigned Protocols), * the urgent pointer points to the last octet * of urgent data. We continue, however, * to consider it to indicate the first octet * of data past the urgent section. * Otherwise, snd_up should be one lower. */ sbappend(&so->so_snd, m); tp->snd_up = tp->snd_una + so->so_snd.sb_cc; tp->t_force = 1; error = tcp_output(tp); tp->t_force = 0; break; case PRU_SOCKADDR: in_setsockaddr(inp, nam); break; case PRU_PEERADDR: in_setpeeraddr(inp, nam); break; /* * TCP slow timer went off; going through this * routine for tracing's sake. */ case PRU_SLOWTIMO: tp = tcp_timers(tp, (int)nam); req |= (int)nam << 8; /* for debug's sake */ break; default: panic("tcp_usrreq"); } if (tp && (so->so_options & SO_DEBUG)) tcp_trace(TA_USER, ostate, tp, (struct tcpiphdr *)0, req); splx(s); return (error); } #if BSD>=43 tcp_ctloutput(op, so, level, optname, mp) int op; struct socket *so; int level, optname; struct mbuf **mp; { int error = 0; struct inpcb *inp = sotoinpcb(so); register struct tcpcb *tp = intotcpcb(inp); register struct mbuf *m; if (level != IPPROTO_TCP) return (ip_ctloutput(op, so, level, optname, mp)); switch (op) { case PRCO_SETOPT: m = *mp; switch (optname) { case TCP_NODELAY: if (m == NULL || m->m_len < sizeof (int)) error = EINVAL; else if (*mtod(m, int *)) tp->t_flags |= TF_NODELAY; else tp->t_flags &= ~TF_NODELAY; break; case TCP_MAXSEG: /* not yet */ default: error = EINVAL; break; } if (m) (void) m_free(m); break; case PRCO_GETOPT: *mp = m = m_get(M_WAIT, MT_SOOPTS); m->m_len = sizeof(int); switch (optname) { case TCP_NODELAY: *mtod(m, int *) = tp->t_flags & TF_NODELAY; break; case TCP_MAXSEG: *mtod(m, int *) = tp->t_maxseg; break; default: error = EINVAL; break; } break; } return (error); } #endif int tcp_sendspace = 1024*4; int tcp_recvspace = 1024*4; /* * Attach TCP protocol to socket, allocating * internet protocol control block, tcp control block, * bufer space, and entering LISTEN state if to accept connections. */ tcp_attach(so) struct socket *so; { register struct tcpcb *tp; struct inpcb *inp; int error; error = soreserve(so, tcp_sendspace, tcp_recvspace); if (error) return (error); error = in_pcballoc(so, &tcb); if (error) return (error); inp = sotoinpcb(so); tp = tcp_newtcpcb(inp); if (tp == 0) { int nofd = so->so_state & SS_NOFDREF; /* XXX */ so->so_state &= ~SS_NOFDREF; /* don't free the socket yet */ in_pcbdetach(inp); so->so_state |= nofd; return (ENOBUFS); } tp->t_state = TCPS_CLOSED; return (0); } /* * Initiate (or continue) disconnect. * If embryonic state, just send reset (once). * If in ``let data drain'' option and linger null, just drop. * Otherwise (hard), mark socket disconnecting and drop * current input data; switch states based on user close, and * send segment to peer (with FIN). */ struct tcpcb * tcp_disconnect(tp) register struct tcpcb *tp; { struct socket *so = tp->t_inpcb->inp_socket; if (tp->t_state < TCPS_ESTABLISHED) tp = tcp_close(tp); else if ((so->so_options & SO_LINGER) && so->so_linger == 0) tp = tcp_drop(tp, 0); else { soisdisconnecting(so); sbflush(&so->so_rcv); tp = tcp_usrclosed(tp); if (tp) (void) tcp_output(tp); } return (tp); } /* * User issued close, and wish to trail through shutdown states: * if never received SYN, just forget it. If got a SYN from peer, * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN. * If already got a FIN from peer, then almost done; go to LAST_ACK * state. In all other cases, have already sent FIN to peer (e.g. * after PRU_SHUTDOWN), and just have to play tedious game waiting * for peer to send FIN or not respond to keep-alives, etc. * We can let the user exit from the close as soon as the FIN is acked. */ struct tcpcb * tcp_usrclosed(tp) register struct tcpcb *tp; { switch (tp->t_state) { case TCPS_CLOSED: case TCPS_LISTEN: case TCPS_SYN_SENT: tp->t_state = TCPS_CLOSED; tp = tcp_close(tp); break; case TCPS_SYN_RECEIVED: case TCPS_ESTABLISHED: tp->t_state = TCPS_FIN_WAIT_1; break; case TCPS_CLOSE_WAIT: tp->t_state = TCPS_LAST_ACK; break; } if (tp && tp->t_state >= TCPS_FIN_WAIT_2) soisdisconnected(tp->t_inpcb->inp_socket); return (tp); } tp->rcv_adv = tp->rcv_nxt + win; tp->t_flags &= ~(TF_ACKNOW|TF_DELACK); if (sendalot) goto again; return (0); } tcp_setpersist(tp) register struct tcpcb *tp; { register t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1; if (tp->t_timer[TCPT_REXMT]) panic("tcp_output REXMT"); /* * Start/restart persistance timer. */ TCPT_RANGESET(tp->t_timer[TCPT_PERSIST], t * tsys/netinet/tags 751 0 12 0 6045325132 11034 2../sys/tagssys/netinet/tcp_subr.c 444 0 12 17321 6036654475 10342 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)tcp_subr.c 7.13.3 (2.11BSD GTE) 1995/10/10 */ #include "param.h" #include "systm.h" #include "mbuf.h" #include "socket.h" #include "socketvar.h" #include "protosw.h" #include "errno.h" #include "../net/route.h" #include "../net/if.h" #include "domain.h" #include "in.h" #include "in_pcb.h" #include "in_systm.h" #include "ip.h" #include "ip_var.h" #include "ip_icmp.h" #include "tcp.h" #include "tcp_fsm.h" #include "tcp_seq.h" #include "tcp_timer.h" #include "tcp_var.h" #include "tcpip.h" /* * Tcp initialization */ tcp_init() { tcp_iss = 1; /* wrong */ tcb.inp_next = tcb.inp_prev = &tcb; } /* * Create template to be used to send tcp packets on a connection. * Call after host entry created, allocates an mbuf and fills * in a skeletal tcp/ip header, minimizing the amount of work * necessary when the connection is used. */ struct tcpiphdr * tcp_template(tp) struct tcpcb *tp; { register struct inpcb *inp = tp->t_inpcb; register struct mbuf *m; register struct tcpiphdr *n; if ((n = tp->t_template) == 0) { m = m_get(M_DONTWAIT, MT_HEADER); if (m == NULL) return (0); m->m_off = MMAXOFF - sizeof (struct tcpiphdr); m->m_len = sizeof (struct tcpiphdr); n = mtod(m, struct tcpiphdr *); } n->ti_next = n->ti_prev = 0; n->ti_x1 = 0; n->ti_pad = 0; n->ti_pr = IPPROTO_TCP; n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip)); n->ti_src = inp->inp_laddr; n->ti_dst = inp->inp_faddr; n->ti_sport = inp->inp_lport; n->ti_dport = inp->inp_fport; n->ti_seq = 0; n->ti_ack = 0; n->ti_x2 = 0; n->ti_off = 5; n->ti_flags = 0; n->ti_win = 0; n->ti_sum = 0; n->ti_urp = 0; return (n); } /* * Send a single message to the TCP at address specified by * the given TCP/IP header. If flags==0, then we make a copy * of the tcpiphdr at ti and send directly to the addressed host. * This is used to force keep alive messages out using the TCP * template for a connection tp->t_template. If flags are given * then we send a message back to the TCP which originated the * segment ti, and discard the mbuf containing it and any other * attached mbufs. * * In any case the ack and sequence number of the transmitted * segment are as specified by the parameters. */ tcp_respond(tp, ti, ack, seq, flags) struct tcpcb *tp; register struct tcpiphdr *ti; tcp_seq ack, seq; int flags; { register struct mbuf *m; int win = 0, tlen; struct route *ro = 0; if (tp) { win = sbspace(&tp->t_inpcb->inp_socket->so_rcv); ro = &tp->t_inpcb->inp_route; } if (flags == 0) { m = m_get(M_DONTWAIT, MT_HEADER); if (m == NULL) return; #ifdef TCP_COMPAT_42 tlen = 1; #else tlen = 0; #endif m->m_len = sizeof (struct tcpiphdr) + tlen; *mtod(m, struct tcpiphdr *) = *ti; ti = mtod(m, struct tcpiphdr *); flags = TH_ACK; } else { m = dtom(ti); m_freem(m->m_next); m->m_next = 0; m->m_off = (int)ti - (int)m; tlen = 0; m->m_len = sizeof (struct tcpiphdr); #define xchg(a,b,type) { type t; t=a; a=b; b=t; } xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_long); xchg(ti->ti_dport, ti->ti_sport, u_short); #undef xchg } ti->ti_next = ti->ti_prev = 0; ti->ti_x1 = 0; ti->ti_pad = 0; ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen)); ti->ti_seq = htonl(seq); ti->ti_ack = htonl(ack); ti->ti_x2 = 0; ti->ti_off = sizeof (struct tcphdr) >> 2; ti->ti_flags = flags; ti->ti_win = htons((u_short)win); ti->ti_urp = 0; ti->ti_sum = in_cksum(m, sizeof (struct tcpiphdr) + tlen); ((struct ip *)ti)->ip_len = sizeof (struct tcpiphdr) + tlen; ((struct ip *)ti)->ip_ttl = ip_defttl; (void) ip_output(m, (struct mbuf *)0, ro, 0); } /* * Create a new TCP control block, making an * empty reassembly queue and hooking it to the argument * protocol control block. */ struct tcpcb * tcp_newtcpcb(inp) struct inpcb *inp; { struct mbuf *m = m_getclr(M_DONTWAIT, MT_PCB); register struct tcpcb *tp; if (m == NULL) return ((struct tcpcb *)0); tp = mtod(m, struct tcpcb *); tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp; tp->t_maxseg = TCP_MSS; tp->t_flags = 0; /* sends options! */ tp->t_inpcb = inp; /* * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no * rtt estimate. Set rttvar so that srtt + 2 * rttvar gives * reasonable initial retransmit time. */ tp->t_srtt = TCPTV_SRTTBASE; tp->t_rttvar = TCPTV_SRTTDFLT << 2; TCPT_RANGESET(tp->t_rxtcur, ((TCPTV_SRTTBASE >> 2) + (TCPTV_SRTTDFLT << 2)) >> 1, TCPTV_MIN, TCPTV_REXMTMAX); tp->snd_cwnd = sbspace(&inp->inp_socket->so_snd); tp->snd_ssthresh = 65535; /* XXX */ inp->inp_ppcb = (caddr_t)tp; return (tp); } /* * Drop a TCP connection, reporting * the specified error. If connection is synchronized, * then send a RST to peer. */ struct tcpcb * tcp_drop(tp, errno) register struct tcpcb *tp; int errno; { struct socket *so = tp->t_inpcb->inp_socket; if (TCPS_HAVERCVDSYN(tp->t_state)) { tp->t_state = TCPS_CLOSED; (void) tcp_output(tp); tcpstat.tcps_drops++; } else tcpstat.tcps_conndrops++; so->so_error = errno; return (tcp_close(tp)); } /* * Close a TCP control block: * discard all space held by the tcp * discard internet protocol block * wake up any sleepers */ struct tcpcb * tcp_close(tp) register struct tcpcb *tp; { register struct tcpiphdr *t; struct inpcb *inp = tp->t_inpcb; struct socket *so = inp->inp_socket; register struct mbuf *m; t = tp->seg_next; while (t != (struct tcpiphdr *)tp) { t = (struct tcpiphdr *)t->ti_next; m = dtom(t->ti_prev); remque(t->ti_prev); m_freem(m); } if (tp->t_template) (void) m_free(dtom(tp->t_template)); (void) m_free(dtom(tp)); inp->inp_ppcb = 0; soisdisconnected(so); in_pcbdetach(inp); tcpstat.tcps_closed++; return ((struct tcpcb *)0); } tcp_drain() { register struct inpcb *ip, *ipnxt; register struct tcpcb *tp; /* * Search through tcb's and look for TIME_WAIT states to liberate, * these are due to go away soon anyhow and we're short of space or * we wouldn't be here... */ ip = tcb.inp_next; if (ip == 0) return; for (; ip != &tcb; ip = ipnxt) { ipnxt = ip->inp_next; tp = intotcpcb(ip); if (tp == 0) continue; if (tp->t_state == TCPS_TIME_WAIT) tcp_close(tp); } } /* * Notify a tcp user of an asynchronous error; * just wake up so that he can collect error status. */ tcp_notify(inp, error) register struct inpcb *inp; int error; { inp->inp_socket->so_error = error; WAKEUP((caddr_t) &inp->inp_socket->so_timeo); sorwakeup(inp->inp_socket); sowwakeup(inp->inp_socket); } tcp_ctlinput(cmd, sa, ip) register int cmd; struct sockaddr *sa; register struct ip *ip; { register struct tcphdr *th; extern struct in_addr zeroin_addr; extern u_char inetctlerrmap[]; int (*notify)() = tcp_notify, tcp_quench(); if (cmd == PRC_QUENCH) notify = tcp_quench; else if ((unsigned)cmd > PRC_NCMDS || inetctlerrmap[cmd] == 0) return; if (ip) { th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2)); in_pcbnotify(&tcb, sa, th->th_dport, ip->ip_src, th->th_sport, cmd, notify); } else in_pcbnotify(&tcb, sa, 0, zeroin_addr, 0, cmd, notify); } /* * When a source quench is received, close congestion window * to one segment. We will gradually open it again as we proceed. */ tcp_quench(inp) struct inpcb *inp; { struct tcpcb *tp = intotcpcb(inp); if (tp) tp->snd_cwnd = tp->t_maxseg; } never received SYN, just forget it. If got a SYN from peer, * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN. * If already got a FIN from peer, then almost done; go to LAST_ACK * state. In all other cases, have already sent FIN to peer (e.g. * after PRU_SHUTDOWN), and just sys/netinet/udp_usrreq.c 444 0 0 22046 6036653464 10664 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)udp_usrreq.c 7.5.2 (2.11BSD GTE) 1995/10/09 */ #include "param.h" #include "user.h" #include "mbuf.h" #include "protosw.h" #include "socket.h" #include "socketvar.h" #include "errno.h" #include "../net/if.h" #include "../net/route.h" #include "domain.h" #include "in.h" #include "in_pcb.h" #include "in_systm.h" #include "ip.h" #include "ip_var.h" #include "ip_icmp.h" #include "udp.h" #include "udp_var.h" struct inpcb *udp_last_inpcb = &udb; /* * UDP protocol implementation. * Per RFC 768, August, 1980. */ udp_init() { udb.inp_next = udb.inp_prev = &udb; } #ifndef COMPAT_42 int udpcksum = 1; #else int udpcksum = 0; /* XXX */ #endif struct sockaddr_in udp_in = { AF_INET }; udp_input(m0, ifp) struct mbuf *m0; struct ifnet *ifp; { register struct udpiphdr *ui; register struct inpcb *inp; register struct mbuf *m; int len; struct ip ip; udpstat.udps_ipackets++; /* * Get IP and UDP header together in first mbuf. */ m = m0; if ((m->m_off > MMAXOFF || m->m_len < sizeof (struct udpiphdr)) && (m = m_pullup(m, sizeof (struct udpiphdr))) == 0) { udpstat.udps_hdrops++; return; } ui = mtod(m, struct udpiphdr *); if (((struct ip *)ui)->ip_hl > (sizeof (struct ip) >> 2)) ip_stripoptions((struct ip *)ui, (struct mbuf *)0); /* * Make mbuf data length reflect UDP length. * If not enough data to reflect UDP length, drop. */ len = ntohs((u_short)ui->ui_ulen); if (((struct ip *)ui)->ip_len != len) { if (len > ((struct ip *)ui)->ip_len) { udpstat.udps_badlen++; goto bad; } m_adj(m, len - ((struct ip *)ui)->ip_len); /* ((struct ip *)ui)->ip_len = len; */ } /* * Save a copy of the IP header in case we want restore it for ICMP. */ ip = *(struct ip*)ui; /* * Checksum extended UDP header and data. */ if (udpcksum && ui->ui_sum) { ui->ui_next = ui->ui_prev = 0; ui->ui_pad = 0; ui->ui_x1 = 0; ui->ui_len = ui->ui_ulen; if (ui->ui_sum = in_cksum(m, len + sizeof (struct ip))) { udpstat.udps_badsum++; m_freem(m); return; } } /* * Locate pcb for datagram. */ inp = udp_last_inpcb; if (inp->inp_lport != ui->ui_dport || inp->inp_fport != ui->ui_sport || inp->inp_faddr.s_addr != ui->ui_src.s_addr || inp->inp_laddr.s_addr != ui->ui_dst.s_addr) { inp = in_pcblookup(&udb, ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport, INPLOOKUP_WILDCARD); if (inp) udp_last_inpcb = inp; udpstat.udpps_pcbcachemiss++; } if (inp == 0) { udpstat.udps_noport++; /* don't send ICMP response for broadcast packet */ if (in_broadcast(ui->ui_dst)) { udpstat.udps_noportbcast++; goto bad; } *(struct ip *)ui = ip; icmp_error((struct ip *)ui, ICMP_UNREACH, ICMP_UNREACH_PORT, ifp); return; } /* * Construct sockaddr format source address. * Stuff source address and datagram in user buffer. */ udp_in.sin_port = ui->ui_sport; udp_in.sin_addr = ui->ui_src; m->m_len -= sizeof (struct udpiphdr); m->m_off += sizeof (struct udpiphdr); if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in, m, (struct mbuf *)0) == 0) { udpstat.udps_fullsock++; goto bad; } sorwakeup(inp->inp_socket); return; bad: m_freem(m); } /* * Notify a udp user of an asynchronous error; * just wake up so that he can collect error status. */ udp_notify(inp, errno) register struct inpcb *inp; int errno; { inp->inp_socket->so_error = errno; sorwakeup(inp->inp_socket); sowwakeup(inp->inp_socket); } udp_ctlinput(cmd, sa, ip) register int cmd; struct sockaddr *sa; register struct ip *ip; { register struct udphdr *uh; extern struct in_addr zeroin_addr; extern u_char inetctlerrmap[]; if ((unsigned)cmd > PRC_NCMDS || inetctlerrmap[cmd] == 0) return; if (ip) { uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2)); in_pcbnotify(&udb, sa, uh->uh_dport, ip->ip_src, uh->uh_sport, cmd, udp_notify); } else in_pcbnotify(&udb, sa, 0, zeroin_addr, 0, cmd, udp_notify); } udp_output(inp, m0, addr, control) register struct inpcb *inp; struct mbuf *m0; struct mbuf *addr, *control; { register struct mbuf *m = m0; register struct udpiphdr *ui; register int len = 0; struct in_addr laddr; int s, error = 0; if (addr) { laddr = inp->inp_laddr; if (inp->inp_faddr.s_addr != INADDR_ANY) { error = EISCONN; goto release; } /* * Must block input while temporarily connected. */ s = splnet(); error = in_pcbconnect(inp, addr); if (error) { splx(s); goto release; } } else { if (inp->inp_faddr.s_addr == INADDR_ANY) { error = ENOTCONN; goto release; } } /* * Calculate data length and get a mbuf * for UDP and IP headers. */ for (m = m0; m; m = m->m_next) len += m->m_len; MGET(m, M_WAIT, MT_HEADER); /* * Fill in mbuf with extended UDP header * and addresses and length put into network format. */ m->m_off = MMAXOFF - sizeof (struct udpiphdr); m->m_len = sizeof (struct udpiphdr); m->m_next = m0; ui = mtod(m, struct udpiphdr *); ui->ui_next = ui->ui_prev = 0; ui->ui_pad = 0; ui->ui_x1 = 0; ui->ui_pr = IPPROTO_UDP; ui->ui_len = htons((u_short)len + sizeof (struct udphdr)); ui->ui_src = inp->inp_laddr; ui->ui_dst = inp->inp_faddr; ui->ui_sport = inp->inp_lport; ui->ui_dport = inp->inp_fport; ui->ui_ulen = ui->ui_len; /* * Stuff checksum and output datagram. */ ui->ui_sum = 0; if (udpcksum) { if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0) ui->ui_sum = 0xffff; } ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; ((struct ip *)ui)->ip_ttl = ip_defttl; udpstat.udps_opackets++; error = ip_output(m, inp->inp_options, &inp->inp_route, inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST)); if (addr) { in_pcbdisconnect(inp); inp->inp_laddr = laddr; splx(s); } return(error); release: m_freem(m); return(error); } int udp_sendspace = 2048; /* really max datagram size */ int udp_recvspace = 4 * (1024+sizeof(struct sockaddr_in)); /* 4 1K dgrams */ /*ARGSUSED*/ udp_usrreq(so, req, m, nam, rights) struct socket *so; int req; struct mbuf *m, *nam, *rights; { register struct inpcb *inp = sotoinpcb(so); int error = 0; register int s; if (req == PRU_CONTROL) return (in_control(so, (int)m, (caddr_t)nam, (struct ifnet *)rights)); if (rights && rights->m_len) { error = EINVAL; goto release; } if (inp == NULL && req != PRU_ATTACH) { error = EINVAL; goto release; } switch (req) { case PRU_ATTACH: if (inp != NULL) { error = EINVAL; break; } s = splnet(); error = in_pcballoc(so, &udb); splx(s); if (error) break; error = soreserve(so, udp_sendspace, udp_recvspace); if (error) break; break; case PRU_DETACH: udp_detach(inp); break; case PRU_BIND: s = splnet(); error = in_pcbbind(inp, nam); splx(s); break; case PRU_LISTEN: error = EOPNOTSUPP; break; case PRU_CONNECT: if (inp->inp_faddr.s_addr != INADDR_ANY) { error = EISCONN; break; } s = splnet(); error = in_pcbconnect(inp, nam); splx(s); if (error == 0) soisconnected(so); break; case PRU_CONNECT2: error = EOPNOTSUPP; break; case PRU_ACCEPT: error = EOPNOTSUPP; break; case PRU_DISCONNECT: if (inp->inp_faddr.s_addr == INADDR_ANY) { error = ENOTCONN; break; } s = splnet(); in_pcbdisconnect(inp); inp->inp_laddr.s_addr = INADDR_ANY; splx(s); so->so_state &= ~SS_ISCONNECTED; /* XXX */ break; case PRU_SHUTDOWN: socantsendmore(so); break; case PRU_SEND: return(udp_output(inp, m, nam, rights)); case PRU_ABORT: soisdisconnected(so); udp_detach(inp); break; case PRU_SOCKADDR: in_setsockaddr(inp, nam); break; case PRU_PEERADDR: in_setpeeraddr(inp, nam); break; case PRU_SENSE: /* * stat: don't bother with a blocksize. */ return (0); case PRU_SENDOOB: case PRU_FASTTIMO: case PRU_SLOWTIMO: case PRU_PROTORCV: case PRU_PROTOSEND: error = EOPNOTSUPP; break; case PRU_RCVD: case PRU_RCVOOB: return (EOPNOTSUPP); /* do not free mbuf's */ default: panic("udp_usrreq"); } release: if (m != NULL) m_freem(m); return (error); } udp_detach(inp) register struct inpcb *inp; { register int s = splnet(); if (inp == udp_last_inpcb) udp_last_inpcb = &udb; in_pcbdetach(inp); splx(s); } /* * Sysctl for udp variables. */ udp_sysctl(name, namelen, oldp, oldlenp, newp, newlen) int *name; u_int namelen; void *oldp; size_t *oldlenp; void *newp; size_t newlen; { /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); switch (name[0]) { case UDPCTL_CHECKSUM: return (sysctl_int(oldp, oldlenp, newp, newlen, &udpcksum)); default: return (ENOPROTOOPT); } /* NOTREACHED */ } . We will gradually open it again as we proceed. */ tcp_quench(inp) struct inpcb *inp; { struct tcpcb *tp = intotcpcb(inp); if (tp) tp->snd_cwnd = tp->t_maxseg; } never received SYN, just forget it. If got a SYN from peer, * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN. * If already got a FIN from peer, then almost done; go to LAST_ACK * state. In all other cases, have already sent FIN to peer (e.g. * after PRU_SHUTDOWN), and just sys/netinet/icmp_var.h 444 0 0 3015 6036401263 10237 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)icmp_var.h 7.3.2 (2.11BSD GTE) 1995/10/09 */ /* * Variables related to this implementation * of the internet control message protocol. */ struct icmpstat { /* statistics related to icmp packets generated */ long icps_error; /* # of calls to icmp_error */ long icps_oldshort; /* no error 'cuz old ip too short */ long icps_oldicmp; /* no error 'cuz old was icmp */ long icps_outhist[ICMP_MAXTYPE + 1]; /* statistics related to input messages processed */ long icps_badcode; /* icmp_code out of range */ long icps_tooshort; /* packet < ICMP_MINLEN */ long icps_checksum; /* bad checksum */ long icps_badlen; /* calculated bound mismatch */ long icps_reflect; /* number of responses */ long icps_inhist[ICMP_MAXTYPE + 1]; }; /* * Names for ICMP sysctl objects */ #define ICMPCTL_MASKREPL 1 /* allow replies to netmask requests */ #define ICMPCTL_MAXID 2 #ifndef KERNEL #define ICMPCTL_NAMES { \ { 0, 0 }, \ { "maskrepl", CTLTYPE_INT }, \ } #endif #ifdef SUPERVISOR struct icmpstat icmpstat; #endif 0; register struct udpiphdr *ui; register int len = 0; struct in_addr laddr; int s, error = 0; if (addr) { laddr = inp->inp_laddr; if (inp->inp_faddr.s_addr != INADDR_ANY) { error = EISCONN; goto release; } /* * Must block input while temporarily connected. */ s = splnet(); error = in_pcbconnect(inp, addr); if (error) { splx(s); goto release; } } else { if (inp->inp_faddr.s_addr == INADDR_ANY) { error = ENOTCONN; goto release; } } /* * Calsys/netinet/in_proto.c 444 0 0 7300 6036406700 10265 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)in_proto.c 7.2.1 (2.11BSD) 1995/10/09 */ #include "param.h" #include "socket.h" #include "protosw.h" #include "domain.h" #include "mbuf.h" #include "in.h" #include "in_systm.h" #include "ip.h" /* * TCP/IP protocol family: IP, ICMP, UDP, TCP. */ int ip_output(),ip_ctloutput(); int ip_init(),ip_slowtimo(),ip_drain(), ip_sysctl(); int icmp_input(), icmp_sysctl(); int udp_input(),udp_ctlinput(), udp_sysctl(); int udp_usrreq(); int udp_init(); int tcp_input(),tcp_ctlinput(); int tcp_usrreq(),tcp_ctloutput(); int tcp_init(),tcp_fasttimo(),tcp_slowtimo(),tcp_drain(); int rip_input(),rip_output(),rip_ctloutput(); extern int raw_usrreq(); /* * IMP protocol family: raw interface. * Using the raw interface entry to get the timer routine * in is a kludge. */ #include "imp.h" #if NIMP > 0 int rimp_output(), hostslowtimo(); #endif #ifdef NSIP int idpip_input(), nsip_ctlinput(); #endif extern struct domain inetdomain; struct protosw inetsw[] = { { 0, &inetdomain, 0, 0, 0, ip_output, 0, 0, 0, ip_init, 0, ip_slowtimo, ip_drain, ip_sysctl }, { SOCK_DGRAM, &inetdomain, IPPROTO_UDP, PR_ATOMIC|PR_ADDR, udp_input, 0, udp_ctlinput, ip_ctloutput, udp_usrreq, udp_init, 0, 0, 0, udp_sysctl }, { SOCK_STREAM, &inetdomain, IPPROTO_TCP, PR_CONNREQUIRED|PR_WANTRCVD, tcp_input, 0, tcp_ctlinput, tcp_ctloutput, tcp_usrreq, tcp_init, tcp_fasttimo, tcp_slowtimo, tcp_drain, }, { SOCK_RAW, &inetdomain, IPPROTO_RAW, PR_ATOMIC|PR_ADDR, rip_input, rip_output, 0, rip_ctloutput, raw_usrreq, 0, 0, 0, 0, }, { SOCK_RAW, &inetdomain, IPPROTO_ICMP, PR_ATOMIC|PR_ADDR, icmp_input, rip_output, 0, rip_ctloutput, raw_usrreq, 0, 0, 0, 0, icmp_sysctl }, #ifdef NSIP { SOCK_RAW, &inetdomain, IPPROTO_IDP, PR_ATOMIC|PR_ADDR, idpip_input, rip_output, nsip_ctlinput, 0, raw_usrreq, 0, 0, 0, 0, }, #endif /* raw wildcard */ { SOCK_RAW, &inetdomain, 0, PR_ATOMIC|PR_ADDR, rip_input, rip_output, 0, rip_ctloutput, raw_usrreq, 0, 0, 0, 0, }, }; struct domain inetdomain = { AF_INET, "internet", 0, 0, 0, inetsw, &inetsw[sizeof(inetsw)/sizeof(inetsw[0])] }; #if NIMP > 0 extern struct domain impdomain; struct protosw impsw[] = { { SOCK_RAW, &impdomain, 0, PR_ATOMIC|PR_ADDR, 0, rimp_output, 0, 0, raw_usrreq, 0, 0, hostslowtimo, 0, }, }; struct domain impdomain = { AF_IMPLINK, "imp", 0, 0, 0, impsw, &impsw[sizeof (impsw)/sizeof(impsw[0])] }; #endif #include "hy.h" #if NHY > 0 /* * HYPERchannel protocol family: raw interface. */ int rhy_output(); extern struct domain hydomain; struct protosw hysw[] = { { SOCK_RAW, &hydomain, 0, PR_ATOMIC|PR_ADDR, 0, rhy_output, 0, 0, raw_usrreq, 0, 0, 0, 0, }, }; struct domain hydomain = { AF_HYLINK, "hy", 0, 0, 0, hysw, &hysw[sizeof (hysw)/sizeof(hysw[0])] }; #endif #ifndef IPFORWARDING #define IPFORWARDING 1 #endif #ifndef IPSENDREDIRECTS #define IPSENDREDIRECTS 1 #endif #ifndef IPFORWARDSRCRT #if !defined(IPFORWARDING) #define IPFORWARDSRCRT 0 #else #define IPFORWARDSRCRT 1 #endif #endif int ipforwarding = IPFORWARDING; int ipsendredirects = IPSENDREDIRECTS; int ipforward_srcrt = IPFORWARDSRCRT; int ip_defttl = IPDEFTTL; #ifdef GATEWAY int icmpmaskrepl = 1; #else int icmpmaskrepl = 0; #endif ror); release: m_freem(m); return(error); } int udp_sendspace = 2048; /* really max datagram size */ int udp_recvspace = 4 * (1024+sizeof(struct sockaddr_in)); /* 4 1K dgrams */ /*ARGSUSED*/ udp_usrreq(so, req, m, nam, rights) struct socket *so; int req; struct mbuf *m, *nam, *rights; { register struct inpcb sys/netinet/in_var.h 444 0 0 3361 4235415654 7731 /* * Copyright (c) 1985, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)in_var.h 7.2 (Berkeley) 12/7/87 */ /* * Interface address, Internet version. One of these structures * is allocated for each interface with an Internet address. * The ifaddr structure contains the protocol-independent part * of the structure and is assumed to be first. */ struct in_ifaddr { struct ifaddr ia_ifa; /* protocol-independent info */ #define ia_addr ia_ifa.ifa_addr #define ia_broadaddr ia_ifa.ifa_broadaddr #define ia_dstaddr ia_ifa.ifa_dstaddr #define ia_ifp ia_ifa.ifa_ifp u_long ia_net; /* network number of interface */ u_long ia_netmask; /* mask of net part */ u_long ia_subnet; /* subnet number, including net */ u_long ia_subnetmask; /* mask of net + subnet */ struct in_addr ia_netbroadcast; /* broadcast addr for (logical) net */ int ia_flags; struct in_ifaddr *ia_next; /* next in list of internet addresses */ }; /* * Given a pointer to an in_ifaddr (ifaddr), * return a pointer to the addr as a sockadd_in. */ #define IA_SIN(ia) ((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_addr)) /* * ia_flags */ #define IFA_ROUTE 0x01 /* routing entry installed */ #ifdef SUPERVISOR struct in_ifaddr *in_ifaddr; struct in_ifaddr *in_iaonnetof(); struct ifqueue ipintrq; /* ip packet input queue */ #endif put, rip_output, nsip_ctlinput, 0, raw_usrreq, 0, 0, 0, 0, }, #endif /* raw wildcard */ { SOCK_RAW, &inetdomain, 0, PR_ATOMIC|PR_ADDR, rip_input, rip_output, 0, rip_ctloutput, raw_usrreq, 0, 0, 0, 0, }, }; struct domain inetdomain = { AF_INET, "insys/machine 751 0 0 0 6045325134 6607 2pdpsys/pdpstand/ 755 0 0 0 6046604377 6367 sys/pdpstand/ra.c 644 0 0 15724 6007611070 7234 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ra.c 2.6 (2.11BSD GTE) 1995/08/01 */ /* * MSCP disk device driver (rx23, rx33, rx50, rd??, ra??, rz??) */ #include "../h/param.h" #include "../machine/mscp.h" #include "../pdpuba/rareg.h" #include "saio.h" #define NRA 2 #define RA_SMASK (RA_STEP4|RA_STEP3|RA_STEP2|RA_STEP1) struct radevice *RAcsr[NRA + 1] = { (struct radevice *)0172150, (struct radevice *)0, (struct radevice *)-1 }; /* * RA Communications Area */ struct rdca { short ca_xxx1; /* unused */ char ca_xxx2; /* unused */ char ca_bdp; /* BDP to purge */ short ca_cmdint; /* command queue transition interrupt flag */ short ca_rspint; /* response queue transition interrupt flag */ short ca_rspl; /* response descriptors */ short ca_rsph; short ca_cmdl; /* command descriptors */ short ca_cmdh; }; #define ca_ringbase ca_rspl #define RA_OWN 0x8000 /* RQ owns this descriptor */ #define RA_INT 0x4000 /* allow interrupt on ring transition */ static struct ra { struct rdca ra_ca; struct mscp ra_rsp; struct mscp ra_cmd; } rd[NRA]; static u_char rainit[NRA]; static int mx(); extern char *itoa(); /* * This contains the volume size in sectors of units which have been * brought online. This value is used at default label generation time * along with the results of a 'get unit status' command to compute the * "geometry" of the drive. */ static long raonline[NRA][8]; raopen(io) register struct iob *io; { register struct radevice *raaddr; register struct ra *racom; struct disklabel *lp = &io->i_label; int i, ctlr, unit, bae, lo16; ctlr = io->i_ctlr; unit = io->i_unit; if (genopen(NRA, io) < 0) return(-1); raaddr = RAcsr[ctlr]; racom = &rd[ctlr]; if (rainit[ctlr] == 0) { again: raaddr->raip = 0; if (ra_step(raaddr, RA_STEP1, 1)) goto again; raaddr->rasa = RA_ERR | (0154/4); if (ra_step(raaddr, RA_STEP2, 2)) goto again; iomapadr(&racom->ra_ca.ca_ringbase, &bae, &lo16); raaddr->rasa = lo16; if (ra_step(raaddr, RA_STEP3, 3)) goto again; raaddr->rasa = bae; if (ra_step(raaddr, RA_STEP4, 4)) goto again; raaddr->rasa = RA_GO; if (racmd(M_O_STCON, io) < 0) { printf("ra%d STCON err\n", ctlr); return(-1); } rainit[ctlr] = 1; } if (raonline[ctlr][unit] == 0) if (ramount(io) == -1) return(-1); if (devlabel(io, READLABEL) == -1) return(-1); io->i_boff = lp->d_partitions[io->i_part].p_offset; return(0); } raclose(io) register struct iob *io; { raonline[io->i_ctlr][io->i_unit] = 0; return(0); } ramount(io) register struct iob *io; { register int ctlr = io->i_ctlr; register int unit = io->i_unit; if (racmd(M_O_ONLIN, io) < 0) { printf("ra%d,%d: !online\n", ctlr, unit); return(-1); } raonline[ctlr][unit] = rd[ctlr].ra_rsp.m_uslow + ((long)(rd[ctlr].ra_rsp.m_ushigh) << 16); return(0); } racmd(op, io) int op; struct iob *io; { register struct mscp *mp; int ctlr = io->i_ctlr; int unit = io->i_unit; register struct ra *racom = &rd[ctlr]; struct radevice *csr = RAcsr[ctlr]; int i, bae, lo16; racom->ra_cmd.m_opcode = op; racom->ra_cmd.m_unit = unit; racom->ra_cmd.m_cntflgs = 0; racom->ra_rsp.m_header.ra_msglen = sizeof(struct mscp); racom->ra_cmd.m_header.ra_msglen = sizeof(struct mscp); iomapadr(&racom->ra_rsp.m_cmdref, &bae, &lo16); racom->ra_ca.ca_rspl = lo16; racom->ra_ca.ca_rsph = RA_OWN | bae; iomapadr(&racom->ra_cmd.m_cmdref, &bae, &lo16); racom->ra_ca.ca_cmdl = lo16; racom->ra_ca.ca_cmdh = RA_OWN | bae; i = csr->raip; mp = &racom->ra_rsp; while (1) { while (racom->ra_ca.ca_cmdh & RA_OWN) { delay(200); /* SA access delay */ if (csr->rasa & (RA_ERR|RA_SMASK)) goto fail; } while (racom->ra_ca.ca_rsph & RA_OWN) { delay(200); /* SA access delay */ if (csr->rasa & (RA_ERR|RA_SMASK)) goto fail; } racom->ra_ca.ca_cmdint = 0; racom->ra_ca.ca_rspint = 0; if (mp->m_opcode == (op | M_O_END)) break; printf("ra%d: rsp %x op %x ignored\n", ctlr,mp->m_header.ra_credits & 0xf0, mp->m_opcode); racom->ra_ca.ca_rsph |= RA_OWN; } if ((mp->m_status & M_S_MASK) != M_S_SUCC) { printf("ra%d,%d: err op=%x sts=%x\n", ctlr, unit, mp->m_opcode, mp->m_status); return(-1); } return(0); fail: printf("ra%d: rasa=%o\n", ctlr, csr->rasa); } rastrategy(io, func) register struct iob *io; int func; { register struct mscp *mp; struct ra *racom; int bae, lo16; racom = &rd[io->i_ctlr]; mp = &racom->ra_cmd; iomapadr(io->i_ma, &bae, &lo16); mp->m_lbn_l = loint(io->i_bn); mp->m_lbn_h = hiint(io->i_bn); mp->m_bytecnt = io->i_cc; mp->m_buf_l = lo16; mp->m_buf_h = bae; if (racmd(func == READ ? M_O_READ : M_O_WRITE, io) < 0) return(-1); return(io->i_cc); } ra_step(csr, mask, step) register struct radevice *csr; int mask, step; { register int cnt; for (cnt = 0; (csr->rasa & mask) == 0; ) { delay(2000); cnt++; if (cnt < 5000) continue; printf("RA(%o) failed step %d. retrying\n",csr,step); return(1); } return(0); } /* * This routine is called by the general 'devlabel' routine out of conf.c * and is used by the standalone disklabel program to initialize the * default disklabel. The MSCP driver does not need geometry info but * it is almost trivial (because the drive has already been brought online by * 'raopen') to fetch the required information with a 'get unit status' * command. */ ralabel(io) struct iob *io; { register struct disklabel *lp = &io->i_label; register char *cp, *dp; daddr_t nblks = raonline[io->i_ctlr][io->i_unit]; struct mscp *mp = &rd[io->i_ctlr].ra_rsp; int nameid, numid; lp->d_type = DTYPE_MSCP; lp->d_partitions[0].p_size = nblks; /* span the drive with 'a' */ /* lp->d_secperunit = nblks; /* size of entire volume */ if (racmd(M_O_GTUNT, io) != 0) { printf("ra%d,%d M_OP_GTUNT failed\n", io->i_ctlr, io->i_unit); return(-1); } /* * Yes it's a lot of code but since the standalone utilities (at least 'restor') * are likely going to end up split I/D anyhow why not get the information. * * sectors/track * tracks/group * group/cyl = tracks/cyl * sectors/track * tracks/cyl = sectors/cyl * sectors / sectors/cyl = cyl */ lp->d_nsectors = mp->m_track; lp->d_ntracks = mp->m_group * mp->m_cylinder; lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; lp->d_ncylinders = nblks / lp->d_secpercyl; nameid = (((loint(mp->m_mediaid) & 0x3f) << 9) | ((hiint(mp->m_mediaid) >> 7) & 0x1ff)); numid = hiint(mp->m_mediaid) & 0x7f; /* * Next put 'RA81' or 'RD54', etc into the typename field. */ cp = lp->d_typename; *cp++ = mx(nameid, 2); *cp++ = mx(nameid, 1); dp = itoa(numid); while (*cp++ = *dp++) ; *cp = mx(nameid, 0); if (*cp != ' ') cp++; *cp = '\0'; return(0); } /* * this is a routine rather than a macro to save space - shifting, etc * generates a lot of code. */ static mx(l, i) int l, i; { register int c; c = (l >> (5 * i)) & 0x1f; if (c == 0) c = ' ' - '@'; return(c + '@'); } ror = EOPNOTSUPP; break; case PRU_ACCEPTsys/pdpstand/Makefile 644 0 12 10557 5765474215 10172 # Standalone Makefile # # The limitations on program size have been removed. The addition # of disklabel support pushed 'restor' over the limit. Even with # additional space saving measures it was impossible to fit restor # into 48kb. 'icheck' and 'restor' are now built with split I/D. # # This is not as bad as it sounds - the kernel has not been able to # run on a non split machine for many years. It made little sense # to restrict the standalone utilities to non-split mode when the # operating system itself required split I/D. # # It is still possible to hand craft a version of the utilities by leaving # out all but the necessary drivers. # # If a GENERIC kernel distribution is being created be sure # to install /sys/pdpdist/dtab (or /etc/dtab.save) as ${ROOT}/etc/dtab # so that the GENERIC kernel can find the tape device. # # 1995/06/05 - add disklabel program to Makefile. # 1995/06/01 - use split I/D for icheck and restor. # 1995/05/30 - Begin adding disklabel support. # DISK which disk to take a root dump of for the distribution tape # TAPE which tape to write the distribution on # DUMP where to store a root system dump if you do a ``make dump'' # DISK= xp0a TAPE= mt8 DUMP= /usr/root.dump ROOT= ETCSRC= ${ROOT}/usr/src/etc MKFS= ${ETCSRC}/mkfs.c RESTOR= ${ETCSRC}/restor/restor.c ICHECK= ${ETCSRC}/icheck.c DEFS= -DSTANDALONE -I${ROOT}/usr/include -I${ROOT}. CFLAGS= -O ${DEFS} BOOT= M.o boot.o ubmapset.o DRIVERS=prf.o sys.o label.o \ ht.o tm.o ts.o tmscp.o \ xp.o rk.o rl.o br.o hk.o si.o ra.o ALL= mtboot boot disklabel mkfs restor icheck maketape toyset all: ${ALL} .c.o: cc ${CFLAGS} -c $*.c .s.o: /lib/cpp -P ${DEFS} $< | as -u -V -o $@ srt0-i.o: srt0.s /lib/cpp -P -DSPLIT_ID ${DEFS} srt0.s | as -u -V -o $@ distribution: tape1 switch_tapes tape2 tmscptape: ${ALL} ${DUMP} ./maketape /dev/nr${TAPE} maketape.data dd if=${DUMP} of=/dev/nr${TAPE} bs=20b cd ${ROOT}/usr; tar cfb /dev/nr${TAPE} 20 \ adm bin dict doc games guest hosts include ingres lib \ local man msgs new old preserve pub skel spool tmp ucb cd ${ROOT}/usr/src; tar cfb /dev/nr${TAPE} 20 \ sys include cd ${ROOT}/usr/src; tar cfb /dev/r${TAPE} 20 \ Makefile asm.sed asm.sed.pdp asm.sed.vax bin etc games \ lib local man new old ucb usr.bin usr.lib tape1: ${ALL} ${DUMP} ./maketape /dev/nr${TAPE} maketape.data dd if=${DUMP} of=/dev/nr${TAPE} bs=20b cd ${ROOT}/usr; tar cfb /dev/nr${TAPE} 20 \ adm bin dict doc games guest hosts include ingres lib \ local man msgs new old preserve pub skel spool tmp ucb cd ${ROOT}/usr/src; tar cfb /dev/r${TAPE} 20 \ sys include switch_tapes: FRC @echo "Switch tapes. Hit CR when second tape is mounted." @head -1 FRC: tape2: cd ${ROOT}/usr/src; tar cfb /dev/r${TAPE} 20 \ Makefile asm.sed asm.sed.pdp asm.sed.vax bin etc games \ lib local man new old ucb usr.bin usr.lib ${DUMP}: @echo "You must make a dump of the root file system first." exit 1 dump: dump 0f ${DUMP} /dev/r${DISK} install: boot install -s boot ${ROOT}/ libsa.a: ${DRIVERS} ar rv $@ $? ranlib $@ mkfs.o: ${MKFS} cc ${CFLAGS} -c ${MKFS} restor.o: ${RESTOR} cc ${CFLAGS} -c ${RESTOR} icheck.o: ${ICHECK} cc ${CFLAGS} -c ${ICHECK} mtboot: mtboot.o strip $@.o dd if=$@.o of=mtboot bs=16 skip=1 rm -f $@.o boot: M.o conf.o boot.o ubmapset.o libsa.a ld -X -o $@ M.o conf.o boot.o ubmapset.o libsa.a -lc mkfs: srt0.o conf.o libsa.a mkfs.o ld -X -o $@ srt0.o conf.o $@.o libsa.a -lc restor: srt0-i.o conf.o libsa.a restor.o ld -X -i -o $@ srt0-i.o conf.o $@.o libsa.a -lc icheck: srt0-i.o conf.o libsa.a icheck.o ld -X -i -o $@ srt0-i.o conf.o $@.o libsa.a -lc disklabel: srt0.o conf.o libsa.a disklabel.o displaylab.o ld -X -o $@ srt0.o conf.o $@.o displaylab.o libsa.a -lc maketape: maketape.c cc -o $@ maketape.c toyset: toyset.o srt0.o conf.o libsa.a ld -X -o $@ srt0.o conf.o $@.o libsa.a -lc tags: FRC rm -f tags ctags *.[ch] for i in M.s; do \ ${EGREP} '^[_a-zA-Z][_a-zA-Z0-9]*:' $$i \ | ${SED} "s;\([^:]*\):\(.*\)$$;\1 $$i /^\1:\2$$/;" \ >> tags; \ done sort -o tags tags FRC: clean: rm -f ${ALL} ${AUX} libsa.a *.o tags boot.o: boot.c conf.o: conf.c cat.o: cat.c displaylab.o: displaylab.c disklabel.o: disklabel.c hk.o: hk.c ht.o: ht.c label.o: label.c mtboot.o: mtboot.s prf.o: prf.c rk.o: rk.c rl.o: rl.c br.o: br.c srt0.o: srt0.s srt0-i.o: srt0.s sys.o: sys.c tm.o: tm.c tmscp.o: tmscp.c ts.o: ts.c ubmapset.o: ubmapset.c xp.o: xp.c { register int c; c = (l >> (5 * i)) & 0x1f; if (c == 0) c = ' ' - '@'; return(c + '@'); } ror = EOPNOTSUPP; break; case PRU_ACCEPTsys/pdpstand/ht.c 444 0 12 5744 5765731572 7273 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ht.c 2.2 (2.11BSD) 1995/06/08 */ /* * TM02/3 - TU16/TE16/TU77 standalone tape driver */ #include "../h/param.h" #include "../pdpuba/htreg.h" #include "saio.h" #define NHT 2 #define H_NOREWIND 004 /* not used in stand alone driver */ #define H_1600BPI 010 struct htdevice *HTcsr[NHT + 1] = { (struct htdevice *)0172440, (struct htdevice *)0, (struct htdevice *)-1 }; extern int tapemark; /* flag to indicate tapemark encountered (see sys.c as to how it's used) */ htopen(io) register struct iob *io; { register skip; register int ctlr = io->i_ctlr; if (genopen(NHT, io) < 0) return(-1); io->i_flgs |= F_TAPE; htstrategy(io, HT_REW); skip = io->i_part; while (skip--) { io->i_cc = -1; while (htstrategy(io, HT_SFORW)) continue; delay(30000); htstrategy(io, HT_SENSE); } return(0); } htclose(io) struct iob *io; { htstrategy(io, HT_REW); } /* * Copy the space logic from the open routine but add the check for spacing * backwards. */ htseek(io, space) struct iob *io; register int space; { register int fnc; if (space < 0) { space = -space; fnc = HT_SREV; } else fnc = HT_SFORW; while (space--) { io->i_cc = -1; htstrategy(io, fnc); delay(30000); htstrategy(io, HT_SENSE); } } /* * Returns 0 if no tape mark was seen. Returns 1 if a tape mark (or error) * has been encountered. */ htstrategy(io, func) register struct iob *io; { register unit, com; int errcnt, ctlr, bae, lo16; register struct htdevice *htaddr; unit = io->i_unit; ctlr = io->i_ctlr; htaddr = HTcsr[ctlr]; errcnt = 0; retry: while ((htaddr->htcs1 & HT_RDY) == 0) continue; while (htaddr->htfs & HTFS_PIP) continue; iomapadr(io->i_ma, &bae, &lo16); htaddr->httc = ((io->i_unit&H_1600BPI) ? HTTC_1600BPI : HTTC_800BPI) | HTTC_PDP11 | unit; htaddr->htba = (caddr_t) lo16; htaddr->htfc = -io->i_cc; htaddr->htwc = -(io->i_cc >> 1); com = (bae << 8) | HT_GO; if (func == READ) com |= HT_RCOM; else if (func == WRITE) com |= HT_WCOM; else if (func == HT_SREV) { htaddr->htfc = -1; htaddr->htcs1 = com | HT_SREV; return(0); } else com |= func; htaddr->htcs1 = com; while ((htaddr->htcs1 & HT_RDY) == 0) continue; if (htaddr->htfs & HTFS_TM) { tapemark = 1; htinit(htaddr); return(0); } if (htaddr->htcs1 & HT_TRE) { if (errcnt == 0) printf("\nht%d,%d err: cs2=%o, er=%o", ctlr, unit, htaddr->htcs2, htaddr->hter); htinit(htaddr); if (errcnt++ == 10) { printf("\n(FATAL ERROR)\n"); return(-1); } htstrategy(io, HT_SREV); goto retry; } return(io->i_cc+htaddr->htfc); } htinit(htaddr) register struct htdevice *htaddr; { register int omt, ocs2; omt = htaddr->httc & 03777; ocs2 = htaddr->htcs2 & 07; htaddr->htcs2 = HTCS2_CLR; htaddr->htcs2 = ocs2; htaddr->httc = omt; htaddr->htcs1 = HT_DCLR|HT_GO; } ar rv $@ $? ranlib $@ mkfssys/pdpstand/srt0.s 444 0 12 6470 5764745614 7566 / 1995/06/04 - devsw[] entries are 14. bytes, need a tape seek routine entry. / 1995/06/02 - Modifications for split I/D to work. The vectors need to be / in 'data' space. / 1995/06/01 - Make copy of SSR3 so we can tell if split I/D is enabled. / 1995/05/30 - devsw[] entries are 12. bytes now. / / Startup code for standalone utilities / sms - mods to pass boot device and csr on to program / / Note that the bootstrap passes the cputype through in r0. PS = 177776 SSR3 = 172516 .globl _main, __rtt, _devsw, _ADJcsr #ifdef SPLIT_ID .data #else .text #endif ZERO: jmp start / / trap vectors / trap;340 / 004 - bus error trap;341 / 010 - illegal instruction trap;342 / 014 - BPT trap;343 / 020 - IOT trap;344 / 024 - POWER FAIL trap;345 / 030 - EMT start;346 / 034 - TRAP .= ZERO + 400 .text start: mov $340,*$PS mov $trap,*$034 / Save information which Boot has passed thru to us mov r0,_cputype / assume that the boot left this in r0 mov r1,_bootcsr / assume that boot left csr in r1 mov r3,_bootdev / and boot device major,minor in r3 / Make a copy of SSR3. If this register does not exist it is probably better / to trap now rather than later - the absence of this register means no split / I/D space and the kernel won't run. mov *$SSR3,_ssr3copy mov $157772,sp / return address,psw at 157774&6 / controller number is in bits 6&7 of r3 (_bootdev). major device number / is in bits 8-15. what we need to do now is place the csr into / the appropriate driver's csrlist which is indexed by controller number. ash $-5,r3 / r3 = controller# * 2 mov r3,r0 / controller number in bits 1,2 bic $!6,r0 / make a word index ash $-3,r3 / major device # to bits 0-7 mov r3,r2 / save major for later mul $14.,r3 / devsw[] members are 14. bytes each mov _devsw+10(r3),r3 / get csrlist for driver add r0,r3 / point to controller's entry asr r0 / controller number in bits 0,1 mov r0,_bootctlr / set default controller number / the CSR passed from the ROMs is not necessarily the first address / of a device! We therefore have to adjust the CSR so that the structure / pointers in the drivers are origined at the base address rather than / the ROM supplied address. The adjustment was not stored in devsw[] to / save space (can get by with an array of bytes instead of words). movb _ADJcsr(r2),r2 / adjust (possibly) the CSR mov _bootcsr,r1 sub r2,r1 mov r1,(r3) / store controller's csr in table jsr pc,_main / fix up stack to point at trap ps-pc pair located at top of memory / so we can return to the bootstrap. / / the return protocol originally changed from 140000 because icheck was / too large. icheck was reduced in size but the 157774 return protocol / was retained to allow for slightly oversized programs. __rtt: mov $157774,sp rtt / we hope! br . .globl _trap trap: mov *$PS,-(sp) tst nofault bne 3f mov r0,-(sp) mov r1,-(sp) 2: jsr pc,_trap mov (sp)+,r1 mov (sp)+,r0 tst (sp)+ rtt 3: tst (sp)+ mov nofault,(sp) rtt .data .globl _cputype, _bootcsr, _bootdev, _ssr3copy, _bootctlr nofault: .=.+2 / where to go on predicted trap _cputype: .=.+2 / cpu type (currently 44, 70, 73) _bootdev: .=.+2 / makedev(major,unit) for boot device _bootcsr: .=.+2 / csr of boot controller _bootctlr: .=.+2 / number of boot controller (bits 6 and 7 of minor) _ssr3copy: .=.+2 / copy of SSR3 s: srt0.o conf.o libsa.a mkfs.o ld -X -o $@ srt0.o conf.o $@.o libsa.a -lc restor: srt0-i.o conf.o libsa.a restor.o ld -X -i -o $@ srt0-i.o conf.o $@.o libsa.a -lc icheck: srt0-i.o conf.o libsa.a sys/pdpstand/mtboot.s 644 0 0 22315 5763225722 10165 /* * Primary tape boot program to load and execute secondary boot. * * 1995/05/31 - unit number changed to be in bits 3-5 of 'bootdev' * * This is a universal tape boot which can handle HT, TM, TS and TMSCP * tapes. This boot is FULL. Some of the more extended error * checking had to be left out to get all the drivers to fit. * * Two copies of the primary boot are stored in the first and second records * of the first tape file (some boot proms execute the second one when * booting a tape). The secondary boot is also stored in the first tape * file, starting at record #3. * * Also note that the struct exec header must be removed from this bootstrap. * This needs to be done so taking the address of the tape read and rewind * functions will work. * * Due to size constraints and the rather destructive way in which * all the registers are used, this boot does not support the * "jsr pc,0; br restart" convention. */ NEWLOC = [48.*1024.] / we relocate ourselves to this address OURSIZE = 512. / assume we are up to this size HT_MAJOR = 0 / major device number from bdevsw[] TM_MAJOR = 1 TS_MAJOR = 2 TMS_MAJOR = 12. a_text = 02 / a_text (struct exec) field offset a_data = 04 / a_data (struct exec) field offset csr = r5 / saved csr of boot device tread = r4 / pointer at tread routine blkcnt = r3 / number of blocks to read memaddr = r2 / memory location to read into / r1 & r0 are junk registers .. = NEWLOC / so absolute address work ... start: nop / DEC boot block standard br 1f / " " " " 1: mov $NEWLOC,sp / give ourselves a stack to work with clr r4 mov sp,r5 mov $OURSIZE\/2,r3 / primary boot size in words 2: clr OURSIZE(r5) / clear work area (major & TS/MSCP area) mov (r4)+,(r5)+ / move primary boot to just above sob r3,2b / the stack jmp *$3f / bypass the relocation code 3: mov r0,unit / save unit number mov r1,csr / save the csr cmp r1,$172440 / HT is always at this address beq common / r3 is table index inc r3 / index for TMSCP cmp r1,$172522 / is this a TS? blo common / no - br, likely TMSCP cmp r1,$172522+[7*4] / is CSR in the TS range? bhi common / no, is a TMSCP - br inc r3 / adjust index to TS mov (r1),r4 / save contents of csr in case of a TM clr (r1) / poke the controller / clr r2 / now we delay /1: / sob r2,1b / time for TS to run diagnostics 2: tstb (r1) / is controller ready? bpl 2b / no - br bit $2000,(r1) / TS "address required" bit bne common / if a TS - br mov r4,(r1) / is a TM, restore unit/density select inc r3 / make TM index common: movb table1(r3),major+1 / save major device number to high byte asl r3 / make a word index mov table2(r3),tread / fetch read routine address jsr pc,*table3(r3) / call rewind routine (must preserve r4) readit: clr memaddr / load starting at 0 jsr pc,*tread / skip the two copies of this jsr pc,*tread / program on the tape clr memaddr / reset memory address jsr pc,*tread / read first block of boot mov *$a_text,blkcnt / compute remaining amount to read: add *$a_data,blkcnt / (a_text + a_data add $15.,blkcnt / + sizeof(struct exec) + 511 ash $-9.,blkcnt / - 512) [already read one block] bic $177600,blkcnt / / 512 [[unsigned]] beq done / already done if == 0 [not likely] 2: jsr pc,*tread sob blkcnt,2b done: 1: / down by sizeof(struct exec) mov 20(blkcnt),(blkcnt)+ / r3 cleared by loop above cmp blkcnt,sp blo 1b mov csr,r1 / put things where 'boot' mov unit,r3 / expects them ash $3,r3 / unit # in bits 3-5 bis major,r3 / the major device to high byte clr pc / go to location 0 ... no return /* * HT tape driver */ htcs1 = 0 / offset from base csr htwc = 2 htba = 4 htfc = 6 htcs2 = 10 htds = 12 hter = 14 httc = 32 RESET = 040 READ = 071 REW = 07 hrrec: mov memaddr,htba(csr) mov $-256.,htwc(csr) mov $READ,(csr) / htcs1 htcmd: tstb (csr) / controller ready? bpl htcmd tst htds(csr) / drive ready? bpl htcmd tstb htcs2+1(csr) / any controller errors? bne ctlerr bit $!1000,hter(csr) / any drive errors except HTER_FCE? beq bumpaddr / no, go bump address ctlerr: halt /* * Rewind tape. This routine is only done once and must preceed any reads. */ htrew: tstb (csr) / controller ready? bpl htrew / no - go try again mov htcs2(csr),r1 / boot unit(formatter) number bic $!7,r1 / only the low bits mov httc(csr),r0 / save format,slave,density bic $!3767,r0 / only the bits we're interested in mov $RESET,htcs2(csr) / reset controller movb r1,htcs2(csr) / reselect boot unit(formatter) mov r0,httc(csr) / reselect density/format/slave(drive) mov $REW,(csr) br htcmd / join common code /* * TM tape driver */ tmer = -2 / offset from base csr tmcs = 0 tmbc = 2 tmba = 4 tmdb = 6 tmrd = 10 tmmr = 12 tmrrec: mov $-512.,tmbc(csr) / bytecount mov memaddr,tmba(csr) / bus address mov $3,r1 / 'read' tmcmd: mov (csr),r0 bic $!63400,r0 / save the density and unit bis r1,r0 / merge in the function code mov r0,(csr) / tmcs - give command /1: / bit $100,tmer(csr) / unit still selected? (TMER_SELR) / beq ctlerr / nope, go halt / bit $1,tmer(csr) / unit ready? (TMER_TUR) / beq 1b / no, keep waiting tmtscom: bit $100200,(csr) / error or ready? beq tmtscom / neither, keep looking bmi ctlerr / error - go halt bumpaddr: add $512.,memaddr rts pc /* * Rewind tape. * Side effects: * just what the first line says ... */ tmrew: mov $17,r1 / 'rewind' br tmcmd / join common code /* * TS tape driver */ tsdb = -2 / offset from ROM supplied address tssr = 0 TSCHAR = 140004 TSREW = 102010 TSREAD = 100001 tsrrec: mov $tsdbuf+6,r0 mov $512.,(r0) clr -(r0) mov memaddr,-(r0) mov $TSREAD,-(r0) mov r0,tsdb(csr) br tmtscom /* * Rewind and initialize tape - only done once. * Side effects: * just what the first line says ... */ tsrew: mov $tsdbuf,tsdb(csr) br tmtscom / go join common code .if [.-start]&2 .blkb 2 / tsdbuf must be on a mod 4 boundary .endif tsdbuf: TSCHAR / command tsdbuf+10 / buffer address (lo) 0 / buffer address (hi - always 0) 10 / length of command buffer / from here on is used only at initialization/rewind time. The Set / Charactistics command only looks at the word following the buffer length, / part of the TMSCP code is used as the remainder of the characteristics packet. tsdbuf+10 / buffer address (lo) 0 / buffer address (hi - always 0) 16 / minimum length packet 0 / characteristics to set (lo byte) /* * Copyright (c) Digital Equipment Corporation 1984, 1985, 1986. * All Rights Reserved. * Reference "/usr/src/COPYRIGHT" for applicable restrictions. * * ULTRIX-11 Block Zero Bootstrap for TMSCP Magtape * * SCCSID: @(#)tkboot.s 3.0 4/21/86 * * Chung_wu Lee 2/8/85 * * sms 4/27/91 - merged into universal tape boot * sms 4/12/91 - saved some more space. the major device number and unit * number are now passed to the secondary boot along with the csr of * the booting controller. * * Steven M. Schultz (sms@wlv.imsd.contel.com) Aug 20 1990. Port to 2.11BSD */ s1 = 4000 go = 1 / TK initialization (and rewind) - only done once tkrew: clr (csr)+ / start tk init sequence / move pointer to tksa register mov $s1,r0 / set tk state test bit to step 1 mov $cmdtbl,r1 / address of init seq table 2: tst (csr) / error ? bmi . / yes, hang - can't restart !!! bit r0,(csr) / current step done ? beq 2b / no mov (r1)+,(csr) / yes, load next step info from table asl r0 / change state test bit to next step bpl 2b / if all steps not done, go back / r0 now = 100000, TK_OWN bit mov $400,cmdhdr+2 / tape VCID = 1 mov $36.,cmdhdr / command packet length / don't set response packet length, / little shakey but it works. / unit is already loaded at tkcmd+4 mov $11,tkcmd+8. / on-line command opcode mov $20000,tkcmd+10. / set clear serious exception mov $ring,r2 / initialize cmd/rsp ring mov $tkrsp,(r2)+ / address of response packet mov r0,(r2)+ / set TK owner mov $tkcmd,(r2)+ / address of command packet mov r0,(r2)+ / set TK owner mov -(csr),r0 / start TK polling 3: jsr pc,tkready mov $tkcmd+8.,r0 mov $45,(r0)+ / reposition opcode mov $20002,(r0)+ / set rewind & clear serious exception clr (r0)+ / clear record/object count clr (r0)+ / zzz2 clr (r0)+ / clear tape mark count tkpoll: mov $100000,ring+2 / set TK owner of response mov $100000,ring+6 / set TK owner of command mov (csr),r0 / start TK polling tkready: tst ring+2 / wait for response bmi tkready tstb tkrsp+10. / does returned status = SUCCESS ? bne . / no, hang rts pc tkread: mov $tkcmd+8.,r0 mov $41,(r0)+ / read opcode mov $20000,(r0)+ / set clear serious exception mov $512.,(r0)+ / byte count clr (r0)+ / zzz2 mov memaddr,(r0)+ / buffer address jsr pc,bumpaddr / bump address br tkpoll / wait for response cmdtbl: 100000 / TK_ERR, init step 1 ring / address of ringbase 0 / hi ringbase address go / TK go bit table1: .byte HT_MAJOR .byte TMS_MAJOR .byte TS_MAJOR .byte TM_MAJOR table2: hrrec tkread tsrrec tmrrec table3: htrew tkrew tsrew tmrew end: major = NEWLOC+OURSIZE cmdint = major+2 / TMSCP stuff rspint = cmdint+2. ring = rspint+2. rsphdr = ring+8. tkrsp = rsphdr+4. cmdhdr = tkrsp+48. tkcmd = cmdhdr+4. unit = tkcmd+4 egister struct tcpcb *tp; { switch (tp->t_state) { case TCPS_CLOSED: case TCPS_LISTEN: case TCPS_SYN_SENT: tp->t_state = TCPS_CLOSED; tp = tcp_close(tp); break; case TCPS_SYN_RECEIVED: case TCPS_ESTABLISHED: tp->t_state = TCPS_FIN_WAIT_1; break; case TCPS_CLOSE_WAIT: tp->t_state = TCsys/pdpstand/si.c 444 0 12 3517 5765731703 7263 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)si.c 2.1 (2.11BSD) 1995/06/08 * * SI 9500 CDC 9766 Stand Alone disk driver */ #include "../h/param.h" #include "../pdpuba/sireg.h" #include "saio.h" #define NSI 2 struct sidevice *SIcsr[NSI + 1] = { (struct sidevice *)0176700, (struct sidevice *)0, (struct sidevice *)-1 }; /* defines for 9766 */ #define NHEADS 19 #define NSECT 32 #define NSPC NSECT*NHEADS static u_char dualsi[NSI]; sistrategy(io, func) register struct iob *io; { int unit = io->i_unit; register int ctlr = io->i_ctlr; register struct sidevice *siaddr = SIcsr[ctlr]; int ii; daddr_t bn; int sn, cn, tn, bae, lo16; /* * weirdness with bit 2 (04) removed - see xp.c for comments * about this */ bn = io->i_bn; cn = bn / (NSPC); sn = bn % (NSPC); tn = sn / (NSECT); sn = sn % (NSECT); if (!dualsi[ctlr]) { if (siaddr->siscr != 0) dualsi[ctlr]++; else if ((siaddr->sierr & (SIERR_ERR | SIERR_CNT)) == (SIERR_ERR | SIERR_CNT)) dualsi[ctlr]++; } if (dualsi[ctlr]) while (!(siaddr->siscr & 0200)) { siaddr->sicnr = SI_RESET; siaddr->siscr = 1; } iomapadr(io->i_ma, &bae, &lo16); siaddr->sipcr = cn + (unit <<10); siaddr->sihsr = (tn << 5) + sn; siaddr->simar = (caddr_t)lo16; siaddr->siwcr = io->i_cc >> 1; ii = (bae << 4) | SI_GO; if (func == READ) ii |= SI_READ; else if (func == WRITE) ii |= SI_WRITE; siaddr->sicnr = ii; while ((siaddr->sicnr & SI_DONE) == 0) continue; if (siaddr->sierr & SIERR_ERR) { printf("si%d,%d err cy=%d hd=%d sc=%d cnr=%o, err=%o\n", ctlr, unit, cn, tn, sn, siaddr->sicnr, siaddr->sierr); return(-1); } return(io->i_cc); } siopen(io) struct iob *io; { return(genopen(NSI, io)); } y the low bits mov httc(csr),r0 / save format,slave,density bic $!3767,r0 / only the bits we're interested in mov $RESET,htcs2(csr) / reset controller movb r1,htcs2(csr) sys/pdpstand/M.s 444 0 12 20105 5764745375 7105 / / SCCS id @(#)M.s 1.7 (Berkeley) 7/11/83 / @(#)M.s 3.1 (2.11BSD) 1995/06/01 (sms@wlv.iipo.gtegsc.com) / / Startup code for two-stage bootstrap with support for autoboot. / Supports 11/45, 11/70, 11/53, 11/73, 11/83, 11/84, 11/93, 11/94 / The boot options and device are placed in the last SZFLAGS bytes / at the end of core by the kernel if this is an autoboot. / The first-stage boot will leave them in registers for us; / we clobber possible old flags so that they don't get re-used. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 / makedev(major,unit) CHECKWORD= 6 / ~BOOTOPTS .globl _end .globl _main,_ubmapset jmp start / / trap vectors / trap;340 / bus error -- grok! trap;341 / illegal instruction trap;342 / BPT trap;343 / IOT trap;344 / POWER FAIL trap;345 / EMT tvec: start;346 / TRAP / NOTE NOTE NOTE NOTE NOTE NOTE / / Here is a totally tacky ``fix'' if your kernel is larger than / 192K and therefore overwrites boot here. Just change the .=400^. / below to something like .=10240^. This will move the critical / sections of boot up far enough so that the load can finish. / We can't actually load boot too much higher because it can't use memory / above 256-8K (to avoid UNIBUS mapping problems). / .=400^. start: reset mov $340,PS mov $_end+512.,sp /save boot options, if present mov r4,_bootopts mov r3,_bootdev mov r2,_checkword mov r1,_bootcsr / 'boot' will apply ADJcsr[] correction /clobber any boot flags left in memory clr ENDCORE-BOOTOPTS clr ENDCORE-BOOTDEV clr ENDCORE-CHECKWORD / / determine what kind of cpu we are running on. this was totally rewritten / when support for the 93 and 94 was added. clrb _sep_id clrb _ubmap jsr pc,cpuprobe / fill in _cputype, _ubmap and _sep_id / also sets MSCR bits clr nofault / / Set kernel I space registers to physical 0 and I/O page / clr r1 mov $77406, r2 mov $KISA0, r3 mov $KISD0, r4 jsr pc, setseg mov $IO, -(r3) / Set user I space registers to physical N*64kb and I/O page. This is / where boot will copy itself to. Boot is less simple minded about its / I/O addressing than it used to be. Physical memory addresses are now / calculated (because support was needed for running split I/D utilities) / rather than assuming that boot is loaded on a 64kb boundary. / / The constraint forcing us to keep boot in the bottom 248Kb of / memory is UNIBUS mapping. There would be little difficulty in relocating / Boot much higher on a Qbus system. / / Unless boot's method of managing its I/O addressing and physical addressing / is reworked some more, 3*64Kb +/- a couple Kb is probably the highest / we'll ever relocate boot. This means that the maximum size / of any program boot can load is ~192Kb. That size includes text, data / and bss. N = 3 / 3*64Kb = 192Kb mov $N*64.*16., r1 / N*64 * btoc(1024) mov $UISA0, r3 mov $UISD0, r4 jsr pc, setseg mov $IO, -(r3) / / If 11/40 class processor, only need set the I space registers / movb _sep_id, _ksep jeq 1f / / Set kernel D space registers to physical 0 and I/O page / clr r1 mov $KDSA0, r3 mov $KDSD0, r4 jsr pc, setseg mov $IO, -(r3) / / Set user D space registers to physical N*64kb and I/O page / mov $N*64.*16., r1 / N*64 * btoc(1024) mov $UDSA0, r3 mov $UDSD0, r4 jsr pc, setseg mov $IO, -(r3) 1: / enable map tstb _ubmap beq 2f jsr pc,_ubmapset / 24, 44, 70 -> ubmap tstb _sep_id bne 3f mov $60,SSR3 / 24 -> !I/D br 1f 3: mov $65,SSR3 / 44, 70 -> ubmap, I/D br 1f 2: tstb _sep_id / 23, 34, 40, 45, 60, 73 -> no ubmap beq 1f mov $25,SSR3 / 45, 73 -> no ubmap, I/D; maybe 22-bit 1: mov $30340,PS inc SSR0 / turn on memory management / copy program to user I space mov $_end,r0 clc ror r0 clr r1 1: mov (r1),-(sp) mtpi (r1)+ sob r0,1b / continue execution in user space copy. No sense in loading sp with / anything special since the call to _main below overwrites low core. mov $140340,-(sp) mov $user,-(sp) rtt user: / clear bss mov $_edata,r0 mov $_end,r1 sub r0,r1 inc r1 clc ror r1 1: clr (r0)+ sob r1,1b mov $_end+512.,sp mov sp,r5 jsr pc,_main mov _cputype,r0 mov _bootcsr,r1 / csr of boot controller (from ROMs) mov _bootdev,r3 / makedev(major,unit) (from ROMs & bootblock) mov _bootopts,r4 mov r4,r2 com r2 / checkword mov $160000,-(sp) / set ksp to very top so that the trap mtpi sp / puts the return address and psw at 157774,6 sys 0 / can't use "trap" because that's a label br user cpuprobe: mov $1f,nofault / catch possible trap tst *$UBMAP / look for unibus map incb _ubmap / we've got one, note that and continue on 1: mov $1f,nofault tst *$KDSA6 / look for split I/D incb _sep_id 1: mov $nomfpt,nofault / catch possible fault from instruction mfpt / 23/24, 44, and KDJ-11 have this instruction cmp r0,$1 / 44? bne 1f / no - br mov $1,*$MSCR / disable cache parity traps mov $44.,_cputype rts pc 1: cmp r0,$5 / KDJ-11? bne 2f / no - br mov *$MAINT,r0 / get system maint register ash $-4,r0 / move down and bic $177760,r0 / isolate the module id mov $1,*$MSCR / disable cache parity traps movb j11typ(r0),r0 / lookup cpu type movb _ubmap,r1 / unibus? beq 1f / nope - br bis $2,*$MSCR / disable unibus traps 1: add r1,r0 / bump the cpu type (93 -> 94, 83 ->84) br out 2: cmp r0,$3 / 23 or 24? bne nomfpt / mfpt returned other than 1,3,5 - HELP! mov $23.,r0 / assume 23 movb _ubmap,r1 / add in... add r1,r0 / the unibus flag (23 -> 24) br out nomfpt: tstb _sep_id / split I/D present? beq 2f / no - br mov $45.,r0 / assume 45 tstb _ubmap / is that correct? beq out / yes - br mov $3,*$MSCR / disable unibus and cache traps mov $70.,r0 br out 2: mov $40.,r0 / assume 40 mov $out,nofault tst *$MSCR / 60 has MSCR, 40 doesn't mov $60.,r0 mov $1,*$MSCR out: mov r0,_cputype rts pc setseg: mov $8,r0 1: mov r1,(r3)+ add $200,r1 mov r2,(r4)+ sob r0,1b rts pc .globl _setseg _setseg: mov 2(sp),r1 mov r2,-(sp) mov r3,-(sp) mov r4,-(sp) mov $77406,r2 mov $KISA0,r3 mov $KISD0,r4 jsr pc,setseg tstb _ksep bne 1f mov $IO,-(r3) 1: mov (sp)+,r4 mov (sp)+,r3 mov (sp)+,r2 rts pc .globl _setnosep _setnosep: bic $4,SSR3 / turn off kernel i/d sep clrb _ksep rts pc .globl _setsep _setsep: bis $4,SSR3 / turn on kernel i/d sep (if not already) movb $1,_ksep rts pc / clrseg(addr,count) .globl _clrseg _clrseg: mov 4(sp),r0 asr r0 bic $!77777,r0 beq 2f mov 2(sp),r1 1: clr -(sp) mtpi (r1)+ sob r0,1b 2: rts pc / mtpd(word,addr) .globl _mtpd _mtpd: mov 4(sp),r0 mov 2(sp),-(sp) mtpd (r0)+ rts pc / mtpi(word,addr) .globl _mtpi _mtpi: mov 4(sp),r0 mov 2(sp),-(sp) mtpi (r0)+ rts pc .globl __rtt __rtt: br . / Can't do halt because that is an illegal / instruction in 'user mode' (which Boot / runs in). .globl _trap trap: mov *$PS,-(sp) tst nofault bne 3f mov r0,-(sp) mov r1,-(sp) jsr pc,_trap mov (sp)+,r1 mov (sp)+,r0 tst (sp)+ rtt 3: tst (sp)+ mov nofault,(sp) rtt PS = 177776 SSR0 = 177572 SSR1 = 177574 SSR2 = 177576 SSR3 = 172516 KISA0 = 172340 KISA6 = 172354 KISD0 = 172300 KISD7 = 172316 KDSA0 = 172360 KDSA6 = 172374 KDSD0 = 172320 UISA0 = 177640 UISD0 = 177600 UDSA0 = 177660 UDSD0 = 177620 MSCR = 177746 / 11/44/60/70 memory system cache control register MAINT = 177750 / KDJ-11 system maintenance register IO = 177600 UBMAP = 170200 .data .globl _cputype .globl _ksep, _sep_id, _ubmap, _ssr3copy .globl _bootopts, _bootdev, _checkword, _bootcsr, _bootctlr _ssr3copy: .=.+2 / copy of SSR3. Always 0 in Boot because that runs / in user mode. The standalone utilities which run / in kernel mode have their copy of SSR3 in srt0.s nofault: .=.+2 / where to go on predicted trap _cputype: .=.+2 / cpu type _sep_id: .=.+1 / 1 if we have separate I and D _ksep: .=.+1 / 1 if kernel mode has sep I/D enabled _ubmap: .=.+2 / 1 if we have a unibus map _bootopts: .=.+2 / flags if an autoboot _bootdev: .=.+2 / device booted from _bootcsr: .=.+2 / csr of device booted from _bootctlr: .=.+2 / number of controller booted from _checkword: .=.+2 / saved r2, complement of bootopts if an autoboot j11typ: .byte 0, 73., 83., 0, 53., 93. ) tcp_pulloutofband(so, ti); } else /* * If no out of band data is expected, * pull receive urgent pointer along * with the receive window. */ if (SEQ_GT(tp->rcv_nxt, tp->rcv_up)) tp->rcv_up = tp->rcv_nxt; dodata: /* XXX */ /* * Process the segment text, merging it into the TCP sequencing queue, * and arranging for acknowledgment of receipt if necessary. * This process logically involves adjusting tp->sys/pdpstand/NEW/ 755 0 12 0 5321426215 7027 sys/pdpstand/NEW/dskinit.c 644 3 12 60365 5316263450 10766 /* * SCCSID: @(#)dskinit.c 3.0 4/21/86 */ /* * LICENSED FROM DIGITAL EQUIPMENT CORPORATION * COPYRIGHT (c) * DIGITAL EQUIPMENT CORPORATION * MAYNARD, MASSACHUSETTS * 1985, 1986, 1987 * ALL RIGHTS RESERVED * * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT * NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL * EQUIPMENT CORPORATION. DIGITAL MAKES NO REPRESENTATIONS ABOUT * THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. IT IS * SUPPLIED "AS IS" WITHOUT EXPRESSED OR IMPLIED WARRANTY. * * IF THE REGENTS OF THE UNIVERSITY OF CALIFORNIA OR ITS LICENSEES * MODIFY THE SOFTWARE IN A MANNER CREATING DERIVATIVE COPYRIGHT * RIGHTS, APPROPRIATE COPYRIGHT LEGENDS MAY BE PLACED ON THE * DERIVATIVE WORK IN ADDITION TO THAT SET FORTH ABOVE. */ /* * ULTRIX-11 standalone disk surface verifer and formater * * Fred Canter 11/1/82 * Jerry Brenner 12/16/82 * Fred Canter 9/28/85 * Changes to allow format of unformatted packs. * * Functionality: * * Add: * This routine adds an entry to the bad sector file and * marks that sector as bad on the disk. * * Verify: * This routine formats (optional), and surface verifies a disk. * Up to 8 data patterns are utilized, including the worst * case pattern for the disk type. The current bad sector file, * if valid, is used unless otherwise specified. * * BUGS: * This code arbitrarily limits the maximum number of * bad sectors to the sectors per track count of that disk. * e.g. RK06/07 maximum of 22 bad sectors. * */ #include #include #include "sa_defs.h" /* * This programs accesses physical devices only. * Must use 512 instead of BSIZE (1024 for new file system). * Fred Canter 6/12/85 */ #undef BSIZE #define BSIZE 512 #define READ 1 #define WRITE 0 /* * BAD144 info for disk bad blocking. A zero entry in * di_size indicates that disk type has no bad blocking. */ #define NP -1 #define HP 1 #define HM 2 #define HJ 3 struct dkinfo { char *di_type; /* type name of disk */ int di_flag; /* prtdsk() flags */ char *di_name; /* ULTRIX-11 disk name */ long di_size; /* size of entire volume in blocks */ int di_nsect; /* sectors per track */ int di_ntrak; /* tracks per cylinder */ int di_wcpat[2]; /* worst case pattern */ } dkinfo[] = { "rk06", 0, "hk", 22L*3L*411L, 22, 3, 0135143, 072307, "rk07", 0, "hk", 22L*3L*815L, 22, 3, 0135143, 072307, "rm02", NP, "hp", 32L*5L*823L, 32, 5, 0165555, 0133333, "rm02_0", HP, "hp", 32L*5L*823L, 32, 5, 0165555, 0133333, "rm02_1", HM, "hm", 32L*5L*823L, 32, 5, 0165555, 0133333, "rm02_2", HJ, "hj", 32L*5L*823L, 32, 5, 0165555, 0133333, "rm03", NP, "hp", 32L*5L*823L, 32, 5, 0165555, 0133333, "rm03_0", HP, "hp", 32L*5L*823L, 32, 5, 0165555, 0133333, "rm03_1", HM, "hm", 32L*5L*823L, 32, 5, 0165555, 0133333, "rm03_2", HJ, "hj", 32L*5L*823L, 32, 5, 0165555, 0133333, "rm05", NP, "hp", 32L*19L*823L, 32, 19, 0165555, 0133333, "rm05_0", HP, "hp", 32L*19L*823L, 32, 19, 0165555, 0133333, "rm05_1", HM, "hm", 32L*19L*823L, 32, 19, 0165555, 0133333, "rm05_2", HJ, "hj", 32L*19L*823L, 32, 19, 0165555, 0133333, "rp04", NP, "hp", 22L*19L*411L, 22, 19, 0165555, 0133333, "rp04_0", HP, "hp", 22L*19L*411L, 22, 19, 0165555, 0133333, "rp04_1", HM, "hm", 22L*19L*411L, 22, 19, 0165555, 0133333, "rm04_2", HJ, "hj", 22L*19L*411L, 22, 19, 0165555, 0133333, "rp05", NP, "hp", 22L*19L*411L, 22, 19, 0165555, 0133333, "rp05_0", HP, "hp", 22L*19L*411L, 22, 19, 0165555, 0133333, "rp05_1", HM, "hm", 22L*19L*411L, 22, 19, 0165555, 0133333, "rp05_2", HJ, "hj", 22L*19L*411L, 22, 19, 0165555, 0133333, "rp06", NP, "hp", 22L*19L*815L, 22, 19, 0165555, 0133333, "rp06_0", HP, "hp", 22L*19L*815L, 22, 19, 0165555, 0133333, "rp06_1", HM, "hm", 22L*19L*815L, 22, 19, 0165555, 0133333, "rp06_2", HJ, "hj", 22L*19L*815L, 22, 19, 0165555, 0133333, 0, }; /* * Pointer into the argument buffer, * used to flush the cartridge serial number * if it is not used by DSKINIT. * (see prf.c - getchar()) */ extern char *argp; struct dkbad dkbad; struct dkinfo *dip; struct bt_bad *bt; struct bt_bad tbt; int i, badcnt, csn_used; long bn, atob(); long nblk, nbo; int fd, rcnt; long atol(); char line[20]; char fn[30]; /* file spec i.e., hp(0,0) */ char dt[20]; /* disk type rm03, etc */ char dn[2]; /* drive number */ int dskpat[8][2] = { 0, 0, 0125252, 0125252, 0252525, 0252525, 0177777, 0177777, 0, 0, 0, 0177777, 0177777, 0, 1, 1, }; struct hk_fmt { int hkcyl; int hktrk; int hkxor; }; struct hp_fmt { int hpcyl; int hptrk; long hpkey; int hpdat[256]; }; struct hm_fmt { int hmcyl; int hmtrk; int hmdat[256]; }; union { long serl; /* pack serial number as a long */ int seri[2]; /* serial number as two int's */ }dsk; long badbn[64]; /* array to hold bad block numbers */ int newbad; struct { int t_cn; int t_tn; int t_sn; }da; char buf[(BSIZE+4)*32]; int patbuf[BSIZE/sizeof(int)]; char *bblock = "Block Cyl Trk Sec\n"; int argflag; /* 0=interactive, 1=called by SDLOAD */ main() { printf("\n\nDisk Surface Verify and Format Program\n"); retry: printf("\nDisk type : "); gets(dt); if(dt[0] == '?'){ prtdsk(); goto retry; } if(strlen(dt) < 1) exit(NORMAL); for(dip=dkinfo; dip->di_type; dip++) if(strcmp(dip->di_type, dt) == 0) break; if(dip->di_type == 0) { printf("\n`%s' not a vaild disk type!\n", dt); rt_xit: if(argflag) exit(FATAL); else goto retry; } if(dip->di_size == 0){ printf("\n`%s' not supported in standalone mode!\n", dt); goto rt_xit; } if(dip->di_nsect == 0 || dip->di_ntrak == 0){ printf("\n`%s' : No bad block support!\n", dt); goto rt_xit; } printf("\nUnit number: "); gets(dn); if((strlen(dn) != 1) || (dn[0] < '0') || (dn[0] > '3')) { printf("\nUnits 0 -> 3 only!\n"); goto rt_xit; } sprintf(fn, "%s(%s,0)", dip->di_name, dn); /* force open, even if driver can't read the bad sector file */ BAD_CMD->r[0] = BAD_CHK; dskopen(0); bn = dip->di_size - dip->di_nsect; /* first sector of last track */ /* * MUST always show bad sector file, because * that is where we check if the pack is an * alignment cartridge and exit if so. printf("\nPrint bad sector file <[y] or n> ? "); gets(line); if(line[0] == 'y' || line[0] == '\0') */ if(showbad()) { printf("\nPack has invalid or no bad sector file\n"); if(argflag) /* discard sdload's answer (no question) */ while(*argp++ != '\r') ; } else { /* ask only if pack has valid bad sector file */ printf("\n\nEnter additional bad blocks into bad sector "); printf("file ? "); gets(line); if(line[0] == 'y') addbad(); } printf("\n\nInitialize Pack ? "); gets(line); if(line[0] == 'y') initdsk(); goto retry; } showbad(){ if(readbad()){ printf("Not a valid bad sector file\n"); return(1); } dsk.seri[0] = dkbad.bt_csnh; dsk.seri[1] = dkbad.bt_csnl; printf("Cartridge serial number: %D\n", dsk.serl); switch(dkbad.bt_flag) { case -1: printf("\nAlignment cartridge!\n"); exit(FATAL); case 0: break; default: printf("\nBad sector file flag word = %o\n" , dkbad.bt_flag); return(1); } printf("Block\t Cyl\t Trk\t Sec\n"); for(i=0; i<(BSIZE/sizeof(long)); i++, bt++) { if(bt->bt_cyl == 0177777) break; if(bt->bt_cyl == 0 && bt->bt_trksec == 0){ dkbad.bt_mbz = -1; return(-1); } bn = atob(bt); printf("%D\t %d\t %d\t %d\n", bn, bt->bt_cyl, bt->bt_trksec>>8, bt->bt_trksec&0377); } return(0); } addbad(){ int chngd, cn, tn, sn, cnt; for(cnt = 0; cnt < dip->di_nsect; cnt++) badbn[cnt] = -1L; BAD_CMD->r[0] = BAD_CHK; /* force open */ dskopen(2); if(readbad()){ /* Have to initialize bads */ printf("Not a valid bad sector file\n"); printf("Please initialize pack first\n"); return(0); } if(dkbad.bt_flag == -1 && dkbad.bt_mbz == 0){ printf("Alignment Cartridge\n"); return(1); } printf("Adding to bad sector information\n"); printf("Format is (cylinder track sector)enter values in decimal \n"); bt = dkbad.bt_badb; for(i = 0; i < 126; i++, bt++){ tomany(i); if(bt->bt_cyl == 0177777 || (bt->bt_cyl == 0 && bt->bt_trksec == 0)) break; } for(chngd = cnt = 0; ;){ tomany(i); gets(line); if(line[0] == '\0') { if(chngd){ sortbn(0); setbads(); sortbn(1); writbad(); dskopen(2); if(strcmp(dip->di_name, "hk") == 0){ for(cnt = 0; (bn = badbn[cnt]) > 0L;cnt++){ bn = (bn/dip->di_nsect)*dip->di_nsect; lseek(fd, bn*512, 0); write(fd, buf, dip->di_nsect*512); } } showbad(); } else printf("\nBad sector file not changed\n"); return(0); } sscanf(line, "%d %d %d", &cn, &tn, &sn); if(cn >= dip->di_size/(dip->di_ntrak*dip->di_nsect) || tn >= dip->di_ntrak || sn >= dip->di_nsect){ printf("ERROR in specification. Max of "); printf("%o cyls %o tracks %o sectors\n" , dip->di_size/(dip->di_ntrak*dip->di_nsect) , dip->di_ntrak, dip->di_nsect); continue; } if(chkdup(cn, tn, sn)){ printf("\nThat sector is already marked bad\n"); continue; } chngd++; tbt.bt_cyl = cn; tbt.bt_trksec = (tn<<8)|sn; bn = atob(&tbt); badbn[cnt++] = bn; i++; } } chkdup(cyl, trk, sec) int cyl, trk, sec; { register struct bt_bad *bpnt; int cnt; bpnt = dkbad.bt_badb; for(cnt = 0; cnt < 126; cnt++, bpnt++){ if(bpnt->bt_cyl == 0177777) break; if(bpnt->bt_cyl == cyl && bpnt->bt_trksec == ((trk << 8)|sec)) return(1); } return(0); } initdsk(){ int patcnt, baddat, cnt, cnt1, fmt, chk, chk1; int *tbuf; unsigned rsize; long bbn, tbn, maxbn; for(cnt = 0; cnt <= dip->di_nsect; cnt++) badbn[cnt] = -1; printf("Format Disk ? "); gets(line); if(line[0] == 'y') fmt = 1; else fmt = 0; if(fmt == 1) /* force open only if formatting */ BAD_CMD->r[0] = BAD_CHK; else BAD_CMD->r[0] = 0; dskopen(2); printf("Use current bad sector file ? <[y] or n> "); gets(line); csn_used = 0; if(line[0] == 'n') initbads(); else if(readbad()){ printf("Bad Sector file Invalid - Initializing\n"); csn_used++; initbads(); } if(argflag && (csn_used == 0)) /* throw away cartridge SN */ while(*argp++ != '\r') ; /* * Load all entries in the current bad sector * file into badbn[] (flag them as bad blocks) so * they will not get lost when the disk is formatted. */ if(fmt) { cnt1 = 0; for(cnt=0; cnt<126; cnt++) { if(dkbad.bt_badb[cnt].bt_cyl == -1) break; tbt.bt_cyl = dkbad.bt_badb[cnt].bt_cyl; tbt.bt_trksec = dkbad.bt_badb[cnt].bt_trksec; badbn[cnt1++] = atob(&tbt); } } while(1){ printf("\nnumber of patterns <1 to 8> ?"); gets(line); patcnt = atoi(line); if((strcmp(dip->di_name, "hk")) == 0 && (patcnt <= 0 || patcnt > 8) && fmt) continue; else if(patcnt < 0 || patcnt > 8) continue; break; } patcnt--; if(fmt != 0){ if(formatdsk()) exit(FATAL); printf("Format complete\n"); setbads(); for(cnt=0; badbn[cnt] != -1; cnt++) badbn[cnt] = -1; } dskpat[0][0] = dip->di_wcpat[0]; dskpat[0][1] = dip->di_wcpat[1]; if(fmt) maxbn = dip->di_size; else maxbn = dip->di_size - (dip->di_nsect * 2); for(i = patcnt, badcnt = 0; i >= 0 ; i--){ if(strcmp(dip->di_name, "hk") || i != 0){ ldbuf(dskpat[i][0],dskpat[i][1], i, 0); } if(i == 7) printf("\nPattern %d = %s", i+1, "Random"); else{ printf("\nPattern %d = ", i+1); fulprt(dskpat[i][1]); fulprt(dskpat[i][0]); } rsize = BSIZE*dip->di_nsect; printf("\nWRITING\n"); for(bn = 0; bn < maxbn ;){ if((strcmp(dip->di_name, "hk")) == 0 && i == 0){ if((bn/(dip->di_ntrak*dip->di_nsect))&01) /* odd cylinder */ ldbuf(dskpat[i][1],dskpat[i][1],i, 0); else /* even cylinder */ ldbuf(dskpat[i][0],dskpat[i][0],i, 0); } lseek(fd, bn * BSIZE, 0); BAD_CMD->r[0] = BAD_CHK; if(rsize <= 0 || rsize > (BSIZE*dip->di_nsect)) rsize = BSIZE * dip->di_nsect; rcnt = write(fd, buf, rsize); if(rcnt < 0){ btoa(bn); printf("\n\nFATAL Error at "); printf("Block %D\t cyl %d\t trk %d\t sec %d\n" , bn, da.t_cn, da.t_tn, da.t_sn); exit(FATAL); } else if(rcnt != rsize){ bbn = bn + (rcnt/BSIZE); if(badblk(bbn)){ badcnt++; btoa(bbn); btoa(bbn); printf("%s%D\t%d\t%d\t%d\t%s" , bblock , bbn, da.t_cn, da.t_tn, da.t_sn ,"BAD SECTOR - WRITE ERROR\n\n"); } rsize = (dip->di_nsect-((rcnt/BSIZE)))* BSIZE; bn = ++bbn; } else{ rsize = BSIZE*dip->di_nsect; bn += dip->di_nsect; bn -= bn%dip->di_nsect; } } rsize = BSIZE*dip->di_nsect; printf("\nREADING (with ECC disabled)\n"); for(bn = 0; bn < maxbn;){ if((strcmp(dip->di_name, "hk")) == 0 && i == 0){ if((bn/(dip->di_ntrak*dip->di_nsect))&01) /* odd cylinder */ ldbuf(dskpat[i][1],dskpat[i][1],i, 1); else /* even cylinder */ ldbuf(dskpat[i][0],dskpat[i][0],i, 1); } lseek(fd, bn * BSIZE, 0); BAD_CMD->r[0] = BAD_CHK; /* * Fred Canter -- 8/20/85 * We want blocks with ECC errors to be revectored, * whether or not we formatted the disk. if(fmt) */ BAD_CMD->r[0] |= BAD_NEC; rcnt = read(fd, buf, rsize); if(rcnt < 0){ btoa(bn); printf("\n\nFATAL Error at "); printf("Block %D\t cyl %d\t trk %d\t sec %d\n" , bn, da.t_cn, da.t_tn, da.t_sn); exit(FATAL); } else if(rcnt != rsize){ bbn = bn + (rcnt/BSIZE); if(badblk(bbn)){ badcnt++; btoa(bbn); printf("%s%D\t%d\t%d\t%d\t%s" , bblock , bbn, da.t_cn, da.t_tn, da.t_sn ,"BAD SECTOR\n\n"); } rsize = (dip->di_nsect-((rcnt/BSIZE)+1))* BSIZE; tbn = ++bbn; } else{ rsize = BSIZE*dip->di_nsect; tbn = bn + dip->di_nsect; tbn -= tbn%dip->di_nsect; } for(chk = 0; chk < (rcnt/BSIZE); chk++){ baddat = 0; tbuf = buf + (chk*BSIZE); for(chk1=0; chk1<(BSIZE/sizeof(int)); chk1++){ if(*tbuf != patbuf[chk1]){ bbn = bn + chk; btoa(bbn); printf("%s%D\t%d\t%d\t%d\t%s" , bblock , bbn, da.t_cn, da.t_tn, da.t_sn ,"DATA COMPARE ERROR "); printf("sb "); fulprt(patbuf[chk1]); printf(" is "); fulprt(*tbuf); printf("\n"); if(++baddat > 4) break; } tbuf++; } if(baddat){ bbn = bn + chk; if(badblk(bbn)){ badcnt++; btoa(bbn); printf("%s%D\t%d\t%d\t%d\t%s" , bblock , bbn, da.t_cn, da.t_tn, da.t_sn ,"BAD SECTOR\n\n"); } } } clrbuf(); bn = tbn; } } printf("\n\nVerify Complete\n"); if(badcnt > 0 || newbad || fmt){ sortbn(0); setbads(); sortbn(1); writbad(); } dskopen(2); if((strcmp(dip->di_name, "hk")) == 0){ for(cnt = 0; (bn = badbn[cnt]) > 0L;cnt++){ bn = (bn/dip->di_nsect)*dip->di_nsect; lseek(fd, bn*512, 0); write(fd, buf, dip->di_nsect*512); } } if(badcnt > 0) printf("%d%sbad blocks found\n" , badcnt, newbad?" ":" additional "); else printf("No%sbad blocks found\n",newbad?" ":" additional "); showbad(); } initbads() { register struct bt_bad *pnt; int cnt; newbad++; while(1) { printf("Cartridge serial number ? "); gets(line); for(cnt=0; line[cnt]; cnt++) if((line[cnt] < '0') || (line[cnt] > '9')) break; if(line[cnt] != '\0') { printf("\nSerial number - numbers only!\n"); continue; } dsk.serl = atol(line); if(dsk.serl <= 0L) { printf("\nSerial number - must be greater than zero!\n"); continue; } break; } dkbad.bt_csnl = dsk.seri[1]; dkbad.bt_csnh = dsk.seri[0]; dkbad.bt_mbz = 0; dkbad.bt_flag = 0; for(cnt = 0, pnt = dkbad.bt_badb; cnt < 126; cnt++, pnt++) pnt->bt_cyl = pnt->bt_trksec = 0177777; } formatdsk() { struct hk_fmt *whk; struct hp_fmt *whp; struct hm_fmt *whm; int tcnt, scnt, tsize, wsize, rsec; long seekpnt; printf("Begin Format ? "); gets(line); if(line[0] != 'y'){ if(newbad) return(1); return(0); } printf("\nFormating %s %s\n", dip->di_type, dn); tcnt = 0; if(strcmp(dip->di_name, "hk") == 0){ tsize = dip->di_nsect; wsize = tsize * sizeof(struct hk_fmt); for(; tcnt < (dip->di_size/tsize); tcnt++){ whk = buf; for(scnt = 0; scnt < tsize; scnt++, whk++){ whk->hkcyl = tcnt/dip->di_ntrak; whk->hktrk = (tcnt%dip->di_ntrak)<<5; whk->hktrk |= (scnt&037); whk->hktrk |= 0140000; whk->hkxor = (whk->hkcyl ^ whk->hktrk); } seekpnt = (long)tcnt*dip->di_nsect*BSIZE; fmtfunc(WRITE, seekpnt, wsize); } } else if(strncmp(dip->di_type, "rm", 2) == 0){ tsize = dip->di_nsect*sizeof(struct hm_fmt); for(; tcnt < (dip->di_size/dip->di_nsect); tcnt++){ whm = buf; for(scnt = 0; scnt < dip->di_nsect; scnt++, whm++){ whm->hmcyl = tcnt/dip->di_ntrak; whm->hmtrk = (tcnt%dip->di_ntrak)<<8; whm->hmtrk |= (scnt&037); whm->hmcyl |= 0150000; } seekpnt = (long)tcnt*dip->di_nsect*BSIZE; fmtfunc(WRITE, seekpnt, tsize); } } else if(strcmp(dip->di_name, "hp") == 0 || strcmp(dip->di_name, "hm") == 0){ tsize = dip->di_nsect*sizeof(struct hp_fmt); for(; tcnt < (dip->di_size/dip->di_nsect); tcnt++){ whp = buf; for(scnt = 0; scnt < dip->di_nsect; scnt++,whp++){ whp->hpcyl = (tcnt/dip->di_ntrak); whp->hptrk = (tcnt%dip->di_ntrak)<<8; whp->hptrk |= (scnt&037); whp->hpcyl |= 010000; } seekpnt = (long)tcnt*dip->di_nsect*BSIZE; fmtfunc(WRITE, seekpnt, tsize); } } else{ printf("Cannot format %s's\n", dip->di_type); return(1); } return(0); } badblk(bbn) long bbn; { register struct bt_bad *pnt; int cnt, cnt1, trksec; if(bbn >= (dip->di_size - (dip->di_nsect *2))){ printf("Bad Block %D in Disk Bad Sector Area\n", bbn); printf("Pack Unacceptable for ULTRIX-11\n"); exit(BADPACK); } btoa(bbn); trksec = da.t_tn << 8; trksec |= da.t_sn&0377; pnt = dkbad.bt_badb; for(cnt = 0; cnt < dip->di_nsect; cnt++, pnt++){ if(pnt->bt_cyl == 0177777) break; if(pnt->bt_cyl == da.t_cn && pnt->bt_trksec == trksec) return(0); } for(cnt = 0; cnt < dip->di_nsect; cnt++){ if(badbn[cnt] == bbn) return(0); if(badbn[cnt] == -1) break; } tomany(cnt); badbn[cnt] = bbn; return(1); } clrbuf() { int cnt, *tbuf, pat; if(patbuf[0] == 0 && patbuf[1] == 0) pat = -1; else pat = 0; for(cnt = 0,tbuf = buf;cnt < (sizeof(buf)/sizeof(int));cnt++,tbuf++) *tbuf = pat; } ldbuf(lpat, hpat, flg, patflg) int lpat, hpat, flg, patflg; { int *rbuf, *tpat; int cnt, cnt1; if(flg == 7) srand(1); rbuf = patbuf; for(cnt = 0; cnt < ((BSIZE/sizeof(int))/2); cnt++) { if(flg == 7) { *(rbuf++) = rand(); *(rbuf++) = rand(); } else { *(rbuf++) = lpat; *(rbuf++) = hpat; } } if(patflg) return; for(cnt = 0, rbuf = buf; cnt < dip->di_nsect; cnt++){ for(cnt1=0, tpat=patbuf; cnt1<(BSIZE/sizeof(int)); cnt1++) *(rbuf++) = *(tpat++); } } btoa(bn) long bn; { da.t_cn = bn/(dip->di_ntrak*dip->di_nsect); da.t_sn = bn%(dip->di_ntrak*dip->di_nsect); da.t_tn = da.t_sn/dip->di_nsect; da.t_sn = da.t_sn%dip->di_nsect; } readbad() { int cnt; dkbad.bt_mbz = -1; bn = dip->di_size - dip->di_nsect; /* first sector of last track */ for(cnt = 0; cnt < 5; cnt++){ lseek(fd, BSIZE * bn, 0); printf("\nBad sector file at block %D of %s\n", bn, fn); if(read(fd, &dkbad, sizeof(struct dkbad)) != sizeof(struct dkbad)) { bn += 2; continue; } break; } if(cnt >= 5){ printf("\nCan't read bad sector file for %s unit %s!\n", dip->di_type, dn); printf("\nCAUTION: disk pack probably needs formatting!\n\n"); dkbad.bt_mbz = -1; /* force next to fail */ } bt = dkbad.bt_badb; if(dkbad.bt_mbz || (dkbad.bt_csnl == 0 && dkbad.bt_csnh == 0)){ dkbad.bt_mbz = -1; return(1); } return(0); } writbad() { int cnt; bn = dip->di_size - dip->di_nsect; printf("\nWriting bad sector file"); printf(" starting at block %D of %s\n", bn, fn); for(cnt = 0; cnt < 5; cnt++){ lseek(fd, BSIZE * bn, 0); BAD_CMD->r[0] = BAD_CHK; write(fd, &dkbad, 512); bn += 2; } } fmtfunc(flag, pnt, size) int flag; long pnt; int size; { int rcnt; lseek(fd, pnt, 0); BAD_CMD->r[0] = BAD_FMT; if(flag == WRITE){ if((rcnt = write(fd, buf, size)) != size){ printf("FATAL: write format returned "); printf("%d should be %d\n", rcnt , size); exit(FATAL); } } else if((rcnt = read(fd, buf, size)) != size){ printf("FATAL: read format returned "); printf("%d should be %d\n", rcnt , size); exit(FATAL); } } dskopen(mode) int mode; { if(fd > 0) close(fd); if((fd = open(fn, mode)) <= 0) { printf("\nCan't open %s!\n", fn); exit(FATAL); } } tomany(num) int num; { if(num > dip->di_nsect){ printf("\nToo many bad blocks. Do not use this Pack\n"); exit(BADPACK); } } fulprt(val) int val; { int cnt, cnv; char c; for(cnt = 5; cnt >= 0; cnt--){ cnv = val&(07<<(cnt*3)); if(cnt == 5) c = ((cnv>>1)&~0100000)>>14; else c = cnv>>(cnt*3); printf("%c",c+060); } } long atob(bt) struct bt_bad *bt; { long blkn; blkn = (long)bt->bt_cyl * (long)(dip->di_ntrak * dip->di_nsect); blkn += (long)((bt->bt_trksec >> 8) * dip->di_nsect); blkn += ((long)bt->bt_trksec & 0377); return(blkn); } sortbn(merge) { long lbn, tbn[64]; int max, cnt, cnt1, li; struct bt_bad *pt; for(cnt = 0; cnt < 64; cnt++) tbn[cnt] = -1L; if(merge) for(cnt = 0, pt = dkbad.bt_badb; ;cnt++, pt++){ if(pt->bt_cyl == 0177777) break; tbn[cnt] = atob(pt); } else cnt = 0; for(cnt1 = 0; badbn[cnt1] != -1L; cnt1++){ tbn[cnt] = badbn[cnt1]; cnt++; } max = cnt; cnt = cnt1 = 0; for(lbn = tbn[0], li = 0; cnt < max; ){ if(lbn == 0 && tbn[cnt1] > 0){ lbn = tbn[cnt1]; li = cnt1; } if(tbn[cnt1] == 0L){ cnt1++; continue; } if(tbn[cnt1] == -1L && lbn > 0){ badbn[cnt] = tbn[li]; cnt++; tbn[li] = 0L; cnt1 = 0; lbn = 0; continue; } if(tbn[cnt1] == -1L) break; if(tbn[cnt1] < lbn){ li = cnt1; lbn = tbn[cnt1]; } cnt1++; } badbn[cnt] = -1L; if(merge){ for(cnt = 0, pt = dkbad.bt_badb; ;cnt++, pt++){ if(badbn[cnt] == -1L) break; btoa(badbn[cnt]); pt->bt_cyl = da.t_cn; pt->bt_trksec = da.t_tn << 8; pt->bt_trksec |= da.t_sn&0377; } for(;cnt < 126; cnt++, pt++) pt->bt_cyl = pt->bt_trksec = 0177777; } } setbads() { struct hk_fmt *whk; struct hp_fmt *whp; struct hm_fmt *whm; int cnt, tcnt, scnt, tsize, wsize, csec; int found; long seekpnt, bbn; struct { int cylnum; int trksecnum; }dskadr; if(strcmp(dip->di_name, "hk") == 0){ tsize = dip->di_nsect; wsize = tsize * sizeof(struct hk_fmt); for(cnt = 0; badbn[cnt] != -1; ){ tcnt = badbn[cnt]/tsize; seekpnt = (long)tcnt*dip->di_nsect*BSIZE; fmtfunc(READ, seekpnt, wsize); whk = buf; found = 0; for(scnt = 0; scnt < dip->di_nsect; scnt++, whk++){ dskadr.cylnum = whk->hkcyl; dskadr.trksecnum = (whk->hktrk&0340)<<3; dskadr.trksecnum |= whk->hktrk&037; if((bbn = atob(&dskadr)) == badbn[cnt]){ found++; whk->hktrk &= ~040000; whk->hkxor = (whk->hkcyl ^ whk->hktrk); btoa(bbn); prtvec(bbn); if(badbn[++cnt] == -1) break; } } if(found == 0) { printf("\nBad block not found in sector headers!\n"); exit(BADPACK); } fmtfunc(WRITE, seekpnt, wsize); } } else if(strncmp(dip->di_type, "rm", 2) == 0){ tsize = sizeof(struct hm_fmt); for(cnt = 0; badbn[cnt] != -1; cnt++){ seekpnt = (long)(badbn[cnt]*BSIZE); fmtfunc(READ, seekpnt, tsize); whm = buf; if((whm->hmcyl & 0140000) != 0140000) continue; whm->hmcyl &= ~040000; btoa(badbn[cnt]); prtvec(badbn[cnt]); fmtfunc(WRITE, seekpnt, tsize); } } else if(strcmp(dip->di_name, "hp") == 0 || strcmp(dip->di_name, "hm") == 0){ tsize = sizeof(struct hp_fmt); for(cnt = 0; badbn[cnt] != -1; cnt++){ seekpnt = (long)(badbn[cnt]*BSIZE); fmtfunc(READ, seekpnt, tsize); whp = buf; if((whp->hpcyl & 010000) == 0) continue; whp->hpcyl &= ~010000; btoa(badbn[cnt]); prtvec(badbn[cnt]); fmtfunc(WRITE, seekpnt, tsize); } } } prtvec(bbn) long bbn; { printf("Revectoring block #%D", bbn); printf(" cyl = %d trk = %d sec = %d\n" ,da.t_cn, da.t_tn, da.t_sn); } prtdsk() { struct dkinfo *dp; printf("\nDisk\tULTRIX\tSize in"); printf("\nName\tName\tBlocks\tComments"); printf("\n----\t----\t------\t--------"); for(dp=dkinfo; dp->di_type; dp++){ if(dp->di_flag == NP) continue; printf("\n%s\t", dp->di_type); printf("%s\t", dp->di_name); printf("%D\t", dp->di_size); if(dp->di_flag == HP) printf("(first ) RH11/RH70 Controller"); if(dp->di_flag == HM) printf("(second ) RH11/RH70 Controller"); if(dp->di_flag == HJ) printf("(third ) RH11/RH70 Controller"); } printf("\n"); } } clrbuf(); bn = tbn; } } printf("\n\nVerify Complete\n"); if(badcnt > 0 || newbad || fmt){ sortbn(0); setbads(); sortbn(1); writbad(); } dskopen(2); if((strcmp(dip->di_name, "hk")) == 0){ for(cnt = 0; (bn = badbn[cnt]) > 0L;cnt++){ bn = sys/pdpstand/NEW/dkbad.c 644 3 12 10076 4361051753 10360 /* * SCCSID: @(#)dkbad.c 3.0 4/21/86 */ /* * LICENSED FROM DIGITAL EQUIPMENT CORPORATION * COPYRIGHT (c) * DIGITAL EQUIPMENT CORPORATION * MAYNARD, MASSACHUSETTS * 1985, 1986, 1987 * ALL RIGHTS RESERVED * * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT * NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL * EQUIPMENT CORPORATION. DIGITAL MAKES NO REPRESENTATIONS ABOUT * THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. IT IS * SUPPLIED "AS IS" WITHOUT EXPRESSED OR IMPLIED WARRANTY. * * IF THE REGENTS OF THE UNIVERSITY OF CALIFORNIA OR ITS LICENSEES * MODIFY THE SOFTWARE IN A MANNER CREATING DERIVATIVE COPYRIGHT * RIGHTS, APPROPRIATE COPYRIGHT LEGENDS MAY BE PLACED ON THE * DERIVATIVE WORK IN ADDITION TO THAT SET FORTH ABOVE. */ /* * ULTRIX-11 Standalone Common Bad Sector Code * * Jerry Brenner 12/20/82 * Fred Canter 7/4/84 (modified for multiple dk_bad structures) */ #include #include #include #include "saio.h" struct dkres dkr[2]; /* * Search the bad sector table looking for * the specified sector. Return index if found. * Return -1 if not found. */ isbad(bt, cyl, trk, sec) register struct dkbad *bt; { register int i; register long blk, bblk; blk = ((long)cyl << 16) + (trk << 8) + sec; for (i = 0; i < 126; i++) { bblk=((long)bt->bt_badb[i].bt_cyl<<16)+bt->bt_badb[i].bt_trksec; if (blk == bblk) return (i); if (blk < bblk || bblk < 0) break; } return (-1); } fixbad(io, wcnt, flag, dkn) struct iob *io; unsigned wcnt; int flag, dkn; { int scnt, rcnt, tcnt; long tadr; tcnt = -(io->i_cc>>1); scnt = (wcnt - tcnt)<<1; scnt = (scnt/512)*512; rcnt = io->i_cc - scnt; tadr = (((long)segflag)<<16) + io->i_ma; tadr += scnt; if(flag){ dkr[dkn].r_vma = tadr&0177777; dkr[dkn].r_vxm = tadr >> 16; if(rcnt > 512){ dkr[dkn].r_cc = rcnt - 512; dkr[dkn].r_vcc = 512; tadr += 512; dkr[dkn].r_ma = tadr&0177777; dkr[dkn].r_xm = tadr >> 16; dkr[dkn].r_bn = io->i_bn +(scnt/512)+1; } else { dkr[dkn].r_vcc = rcnt<=0?512:rcnt; dkr[dkn].r_cc = 0; dkr[dkn].r_ma = 0; } }else{ dkr[dkn].r_ma = tadr&0177777; dkr[dkn].r_xm = tadr >> 16; dkr[dkn].r_cc = rcnt; dkr[dkn].r_vcc = scnt; dkr[dkn].r_bn = io->i_bn + (scnt/512); } } /* * Allocate a bads structure for the disk, * or return index into dk_badf[] if one * allready allocated. */ extern int dk_badf[]; dkn_set(io) struct iob *io; { register int i; /* form sort of a major/minor device number */ i = (io->i_ino.i_dev << 8) | io->i_unit; if(dk_badf[0] == i) return(0); else if(dk_badf[1] == i) return(1); else if(dk_badf[0] == 0) { dk_badf[0] = i; return(0); } else if(dk_badf[1] == 0) { dk_badf[1] = i; return(1); } else return(-1); } /* * This routine is called by the HP and HK drivers * to do ECC error correction on data in the user's buffer. * The problem is that the buffer is not mapped into the same * 64KB segment is the driver (most of the time). * Snarf KISA5 to map to the buffer. Everything is single threded, * so that should be safe. * * segflag, defines the 64KB segment where I/O buffer located. * addr - address within the 64KB segment * xor - data to exclusive or with the data in the buffer */ #define KISA5 ((physadr)0172352) fixecc(addr, xor) unsigned addr; unsigned xor; { register int okisa5; register int i; register char *p; okisa5 = KISA5->r[0]; i = segflag << 10; i |= ((addr >> 6) & 01600); KISA5->r[0] = i; p = (addr & 017777) | 0120000; *((int *)p) ^= xor; KISA5->r[0] = okisa5; } /* * This routine performs the same function as fixecc(), but is * only used by the HK driver. Instead of fixing the ECC in the user's * buffer, it fixes the sector headers read into the user's buffer * when revectoring bad blocks. */ fixhdr(addr, data) unsigned addr; unsigned data; { register int okisa5; register int i; register char *p; okisa5 = KISA5->r[0]; i = segflag << 10; i |= ((addr >> 6) & 01600); KISA5->r[0] = i; p = (addr & 017777) | 0120000; *((int *)p) = data; KISA5->r[0] = okisa5; } write(fd, buf, dip->di_nsect*512); } } if(badcnt > 0) printf("%d%sbad blocks found\n" , badcnt, newbad?" ":" additional "); else printf("No%sbad blocks found\n",newbad?" ":" additional "); showbad(); } initbads() { register struct bt_bad *pnt; int cnt; newbad++; while(1) { printf("Cartridge serial number ? "); gets(line); for(cnt=0; line[cnt]; cnt++) if((line[cnt] < '0') || (line[cnt] > '9')) break; if(line[cnt] sys/pdpstand/NEW/bads.c 644 3 12 25704 5316263462 10233 /* * SCCSID: @(#)bads.c 3.1 3/26/87 */ /* * LICENSED FROM DIGITAL EQUIPMENT CORPORATION * COPYRIGHT (c) * DIGITAL EQUIPMENT CORPORATION * MAYNARD, MASSACHUSETTS * 1985, 1986, 1987 * ALL RIGHTS RESERVED * * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT * NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL * EQUIPMENT CORPORATION. DIGITAL MAKES NO REPRESENTATIONS ABOUT * THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. IT IS * SUPPLIED "AS IS" WITHOUT EXPRESSED OR IMPLIED WARRANTY. * * IF THE REGENTS OF THE UNIVERSITY OF CALIFORNIA OR ITS LICENSEES * MODIFY THE SOFTWARE IN A MANNER CREATING DERIVATIVE COPYRIGHT * RIGHTS, APPROPRIATE COPYRIGHT LEGENDS MAY BE PLACED ON THE * DERIVATIVE WORK IN ADDITION TO THAT SET FORTH ABOVE. */ /* * ULTRIX-11 standalone quick disk surface verifer * * Fred Canter 2/26/83 * Jerry Brenner 12/16/82 * * Functionality: * * Scan: * This routine prints the contents of the bad sector file * on a disk pack, per DEC standard 144. * It also scans a selected area for the disk for bad blocks * by reading the data, this is a very gross check at best. * * This code arbitrarily limits the maximum number of * bad sectors to the sectors per track count of that disk. * e.g. RK06/07 maximum of 22 bad sectors. * */ #include "sa_defs.h" #include #include /* * This programs accesses physical devices only. * Must use 512 instead of BSIZE (1024 for new file system). * Fred Canter 6/12/85 */ #undef BSIZE #define BSIZE 512 /* * BAD144 info for disk bad blocking. A zero entry in * di_size indicates that disk type has no bad blocking. */ #define NP -1 #define HP 1 #define HM 2 #define HJ 3 struct dkinfo { char *di_type; /* type name of disk */ int di_flag; /* prtdsk() flags */ char *di_name; /* ULTRIX-11 disk name */ long di_size; /* size of entire volume in blocks */ int di_nsect; /* sectors per track */ int di_ntrak; /* tracks per cylinder */ int di_wcpat[2]; /* worst case pattern */ } dkinfo[] = { "rk05", 0, "rk", 4872L, 12, 0, 0, 0, "rl01", 0, "rl", 10240L, 20, 0, 0, 0, "rl02", 0, "rl", 20480L, 20, 0, 0, 0, "ml11", NP, "hp", 8192L, 16, 0, 0, 0, "ml11_0", HP, "hp", 8192L, 16, 0, 0, 0, "ml11_1", HM, "hm", 8192L, 16, 0, 0, 0, "ml11_2", HJ, "hj", 8192L, 16, 0, 0, 0, "rk06", 0, "hk", 22L*3L*411L, 22, 3, 0135143, 072307, "rk07", 0, "hk", 22L*3L*815L, 22, 3, 0135143, 072307, "rm02", NP, "hp", 32L*5L*823L, 32, 5, 0165555, 0133333, "rm02_0", HP, "hp", 32L*5L*823L, 32, 5, 0165555, 0133333, "rm02_1", HM, "hm", 32L*5L*823L, 32, 5, 0165555, 0133333, "rm02_2", HJ, "hj", 32L*5L*823L, 32, 5, 0165555, 0133333, "rm03", NP, "hp", 32L*5L*823L, 32, 5, 0165555, 0133333, "rm03_0", HP, "hp", 32L*5L*823L, 32, 5, 0165555, 0133333, "rm03_1", HM, "hm", 32L*5L*823L, 32, 5, 0165555, 0133333, "rm03_2", HJ, "hj", 32L*5L*823L, 32, 5, 0165555, 0133333, "rm05", NP, "hp", 32L*19L*823L, 32, 19, 0165555, 0133333, "rm05_0", HP, "hp", 32L*19L*823L, 32, 19, 0165555, 0133333, "rm05_1", HM, "hm", 32L*19L*823L, 32, 19, 0165555, 0133333, "rm05_2", HJ, "hj", 32L*19L*823L, 32, 19, 0165555, 0133333, "rp02", 0, "rp", 10L*20L*200L, 10, 0, 0, 0, "rp03", 0, "rp", 10L*20L*400L, 10, 0, 0, 0, "rp04", NP, "hp", 22L*19L*411L, 22, 19, 0165555, 0133333, "rp04_0", HP, "hp", 22L*19L*411L, 22, 19, 0165555, 0133333, "rp04_1", HM, "hm", 22L*19L*411L, 22, 19, 0165555, 0133333, "rm04_2", HJ, "hj", 22L*19L*411L, 22, 19, 0165555, 0133333, "rp05", NP, "hp", 22L*19L*411L, 22, 19, 0165555, 0133333, "rp05_0", HP, "hp", 22L*19L*411L, 22, 19, 0165555, 0133333, "rp05_1", HM, "hm", 22L*19L*411L, 22, 19, 0165555, 0133333, "rp05_2", HJ, "hj", 22L*19L*411L, 22, 19, 0165555, 0133333, "rp06", NP, "hp", 22L*19L*815L, 22, 19, 0165555, 0133333, "rp06_0", HP, "hp", 22L*19L*815L, 22, 19, 0165555, 0133333, "rp06_1", HM, "hm", 22L*19L*815L, 22, 19, 0165555, 0133333, "rp06_2", HJ, "hj", 22L*19L*815L, 22, 19, 0165555, 0133333, /* * RA disks can't do full track reads because of buffer size. * UDA50 buffering makes < full track reads plenty big enough. * # sectors must divide evenly into total disk size */ "ra60", 0, "ra", 400176L, 28, 0, 0, 0, "ra80", 0, "ra", 236964L, 28, 0, 0, 0, "ra81", 0, "ra", 891072L, 32, 0, 0, 0, "rx50", 0, "rx", 800L, 10, 0, 0, 0, "rx33", 0, "rx", 2400L, 10, 0, 0, 0, "rd31", 0, "rd", 41560L, 20, 0, 0, 0, "rd32", 0, "rd", 83204L, 22, 0, 0, 0, "rd51", 0, "rd", 21600L, 18, 0, 0, 0, "rd52", 0, "rd", 60480L, 18, 0, 0, 0, "rd53", 0, "rd", 138672L, 18, 0, 0, 0, "rd54", 0, "rd", 311200L, 20, 0, 0, 0, "rc25", 0, "rc", 50902L, 31, 0, 0, 0, 0, }; struct dkbad dkbad; struct dkinfo *dip; struct bt_bad *bt; int i; daddr_t bn; long nblk, nbo; int fd, rcnt; long atol(); char line[20]; char fn[30]; /* file spec i.e., hp(0,0) */ char dt[20]; /* disk type rm03, etc */ char dn[2]; /* drive number */ struct { int t_cn; int t_tn; int t_sn; }da; char buf[(BSIZE+4)*32]; union { long serl; int seri[2]; }dsk; char *bblock = "Block Cyl Trk Sec\n"; extern int argflag; /* 0=interactive, 1=called by sdload */ main() { printf("\n\nQuick Bad Block Scan Program\n"); retry: printf("\nDisk type : "); gets(dt); if(dt[0] == '?'){ prtdsk(); goto retry; } if(strlen(dt) < 1) exit(NORMAL); for(dip=dkinfo; dip->di_type; dip++) if(strcmp(dip->di_type, dt) == 0) break; if(dip->di_type == 0) { printf("\n`%s' not a vaild disk type !\n", dt); rt_xit: if(argflag) exit(FATAL); else goto retry; } if(dip->di_size == 0L){ printf("\n`%s' not supported by standalone code !\n", dt); goto rt_xit; } if(dip->di_nsect == 0){ printf("\n`%s' not supported by Bads !\n", dt); goto rt_xit; } printf("\nUnit number: "); gets(dn); if((strlen(dn) != 1) || (dn[0] < '0') || (dn[0] > '3')) { printf("\nUnits 0 -> 3 only !\n"); goto rt_xit; } sprintf(fn, "%s(%s,0)", dip->di_name, dn); dskopen(0); if(dip->di_ntrak){ bn = dip->di_size - dip->di_nsect; printf("\nPrint bad sector file <[y] or n> ? "); gets(line); if(line[0] == 'y' || line[0] == '\0') if(showbad()) { printf("\n\7\7\7Invalid or No bad sector file.\n"); printf("Disk pack must be initialized with\n"); printf("DSKINIT before use with ULTRIX-11.\n\n"); if(argflag) exit(NO_BBF); } } printf("\nScan disk pack for bad blocks <[y] or n> ? "); gets(line); if(line[0] == 'y' || line[0] == '\0') scanbad(); close(fd); goto retry; } showbad(){ if(readbad()){ return(1); } dsk.seri[0] = dkbad.bt_csnh; dsk.seri[1] = dkbad.bt_csnl; printf("Cartridge serial number: %D\n", dsk.serl); switch(dkbad.bt_flag) { case -1: printf("\nAlignment cartridge !\n"); return(1); break; case 0: break; default: printf("\nBad sector file flag word = %o\n" , dkbad.bt_flag); return(1); } printf("Block\t Cyl\t Trk\t Sec\n"); for(i=0; i<(BSIZE/sizeof(long)); i++, bt++) { if(bt->bt_cyl == 0177777) break; if(bt->bt_cyl == 0 && bt->bt_trksec == 0){ dkbad.bt_mbz = -1; printf("Pack has Invalid Bad Sector file\n"); return(-1); } bn=((long)bt->bt_cyl * (long)dip->di_ntrak+(long)(bt->bt_trksec>>8)) * (long)dip->di_nsect + (long)(bt->bt_trksec&0377); printf("%D\t %u\t %d\t %d\n", bn, bt->bt_cyl, bt->bt_trksec>>8, bt->bt_trksec&0377); } return(0); } scanbad(){ int badcnt, rsize, j; long rbn, rrbn; printf("\nBlock offset: "); gets(line); if(strlen(line) > 6 || (nbo = atol(line)) < 0 || nbo > dip->di_size){ printf("\nBad offset !\n"); return(1); } printf("\n# of blocks : "); gets(line); if(line[0] == '\0') nblk = dip->di_size; else nblk = atol(line); if(nblk <= 0) { printf("\nBad # of blocks !\n"); return(1); } if((nbo + nblk) > dip->di_size){ nblk = dip->di_size - nbo; printf("Offset + # of blocks too large\n"); printf("Truncating # of blocks to %D\n", nblk); } rsize = dip->di_nsect * BSIZE; printf("READING\n"); for(badcnt = bn = 0; bnr[0] = BAD_CHK; if(rsize <= 0 || rsize > (BSIZE*dip->di_nsect)) rsize = BSIZE*dip->di_nsect; rcnt = read(fd, buf, rsize); if(rcnt < 0){ rbn = bn+nbo; if(dip->di_ntrak){ btoa(rbn); printf("\n\nFATAL Error at "); printf("Block %D\t cyl %d\t trk %d\t sec %d\n" , rbn, da.t_cn, da.t_tn, da.t_sn); } else { printf("\n\nBAD BLOCK IN CLUSTER: "); printf("finding actual block number\n"); rrbn = bn+nbo; for(j=0; ((j*BSIZE)di_ntrak){ btoa(rbn); printf("%s%D\t%d\t%d\t%d\t%s" , bblock , rbn, da.t_cn, da.t_tn, da.t_sn ,"BAD BLOCK\n\n"); } else printf("%s%D\t\t\t\t\t%s",bblock, rbn, "BAD BLOCK\n"); bn = ++rbn - nbo; rsize = (dip->di_nsect - ((rcnt/BSIZE)+1))* BSIZE; } else{ cont: bn += dip->di_nsect; bn -= bn%dip->di_nsect; rsize = dip->di_nsect * BSIZE; } if(badcnt >= dip->di_nsect && dip->di_ntrak){ printf("\n\nTOO MANY BAD BLOCKS ON THIS PACK.\n"); printf("ONLY %d BAD BLOCKS ALLOWED ON AN %s DISK\n" , dip->di_nsect, dip->di_type); printf("DO NOT USE THIS PACK\n"); exit(FATAL); } } printf("\n%D blocks checked\n", bn); printf("%d bad blocks found\n", badcnt); if(argflag && badcnt) exit(HASBADS); else return(0); } btoa(bn) long bn; { da.t_cn = bn/(dip->di_ntrak*dip->di_nsect); da.t_sn = bn%(dip->di_ntrak*dip->di_nsect); da.t_tn = da.t_sn/dip->di_nsect; da.t_sn = da.t_sn%dip->di_nsect; } readbad() { int cnt; dkbad.bt_mbz = -1; bn = dip->di_size - dip->di_nsect; /* first sector of last track */ for(cnt = 0; cnt < 5; cnt++){ lseek(fd, BSIZE * bn, 0); printf("\nBad sector file at block %D of %s\n", bn, fn); if(read(fd, &dkbad, sizeof(struct dkbad)) != sizeof(struct dkbad)) { bn += 2; continue; } break; } if(cnt >= 5){ printf("\nCan't read bad sector file for %s unit %s !\n" , dip->di_type, dn); exit(FATAL); } bt = dkbad.bt_badb; if(dkbad.bt_mbz || (dkbad.bt_csnl == 0 && dkbad.bt_csnh == 0)){ dkbad.bt_mbz = -1; return(1); } return(0); } dskopen(mode) int mode; { if((fd = open(fn, mode)) <= 0) { printf("\nCan't open %s !\n", fn); exit(FATAL); } } prtdsk() { struct dkinfo *dp; printf("\nDisk\tULTRIX\tSize in"); printf("\nName\tName\tBlocks\tComments"); printf("\n----\t----\t------\t--------"); for(dp=dkinfo; dp->di_type; dp++){ if(dp->di_flag == NP) continue; printf("\n%s\t", dp->di_type); printf("%s\t", dp->di_name); printf("%D\t", dp->di_size); if(dp->di_flag == HP) printf("(first ) RH11/RH70 Controller"); if(dp->di_flag == HM) printf("(second ) RH11/RH70 Controller"); if(dp->di_flag == HJ) printf("(third ) RH11/RH70 Controller"); } printf("\n"); } This routine prints the contents of the bad sector file * osys/pdpstand/NEW/rabads.c 644 3 12 146043 4361052134 10565 /* * SCCSID: @(#)rabads.c 3.3 12/30/87 */ /* * LICENSED FROM DIGITAL EQUIPMENT CORPORATION * COPYRIGHT (c) * DIGITAL EQUIPMENT CORPORATION * MAYNARD, MASSACHUSETTS * 1985, 1986, 1987 * ALL RIGHTS RESERVED * * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT * NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL * EQUIPMENT CORPORATION. DIGITAL MAKES NO REPRESENTATIONS ABOUT * THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. IT IS * SUPPLIED "AS IS" WITHOUT EXPRESSED OR IMPLIED WARRANTY. * * IF THE REGENTS OF THE UNIVERSITY OF CALIFORNIA OR ITS LICENSEES * MODIFY THE SOFTWARE IN A MANNER CREATING DERIVATIVE COPYRIGHT * RIGHTS, APPROPRIATE COPYRIGHT LEGENDS MAY BE PLACED ON THE * DERIVATIVE WORK IN ADDITION TO THAT SET FORTH ABOVE. */ /* * ULTRIX-11 stand-alone MSCP Disk Initialization * * Fred Canter * For RX33/RX50, reads all blocks and flags any bad ones. * For RD31/RD32/RD51/RD52/RD53/RD54 reads all blocks and rewrites any bad * blocks to force controller initiated replacement. * For RA60/RA80/RA81, reads all blocks and uses host initiated * replacement to revector any bad blocks. * * SECRET STUFF: * * This program has the following undocumented commands/features, * used mainly for debugging: * * 1. The "u" command is commented out. This was an unsuccessful * attempt to unreplace a block. I soon discovered that could * not be done. * * 2. The "t all" feature of the table command causes all entries * in the RCT to be printed, not just the ones that represent * replaced blocks. Also allows RCT copy # selection. * * 3. The "f" command (requires a simple password) causes the * specified block to be written with the "force error" * modifier. This is used for debugging. * * NOTE: * This program consists, for the most part, of straight-line * unoptimized code! Its only saving grace is that it works, at * least as far as I can tell so far! -- Fred Canter 8/5/84 * */ #include "sa_defs.h" #include #include #include "saio.h" #include "ra_saio.h" /*#define DEBUG 1 /* Include conditional code for debugging */ #define RD 0 #define WRT 1 #define RW 2 #define ERR 0 #define NOERR 1 #define YES 1 #define NO 0 #define HELP 2 /* * Bad block replacement strategy flags */ #define BB_COOP 0 /* Use MSCP cooperative replacement */ #define BB_RWRT 1 /* (rd51/rd52) - rewriting a block replaces it */ #define BB_NONE 2 /* RX33/RX50 - no bad block replacement */ struct dkinfo { char *di_type; /* type name of disk */ char *di_name; /* ULTRIX-11 disk name */ daddr_t di_size; /* size of entire volume in blocks */ int di_chunk; /* number of sectors per read */ int di_flag; /* replacement strategy to use */ /* if set, just rewrite block to replace it. */ } dkinfo[] = { "ra60", "ra", 400176L, 32, BB_COOP, "ra80", "ra", 236964L, 31, BB_COOP, "ra81", "ra", 891072L, 32, BB_COOP, "rx33", "rx", 2400L, 10, BB_NONE, "rx50", "rx", 800L, 10, BB_NONE, "rd31", "rd", 41560L, 20, BB_RWRT, "rd32", "rd", 83204L, 20, BB_RWRT, "rd51", "rd", 21600L, 18, BB_RWRT, "rd52", "rd", 60480L, 18, BB_RWRT, "rd53", "rd", 138672L, 18, BB_RWRT, /* RQDX3 NOT OPTIMUM */ "rd54", "rd", 311200L, 20, BB_RWRT, /* RQDX3 NOT OPTIMUM */ "rc25", "rc", 50902L, 31, BB_COOP, 0, }; char buf[512*32]; /* disk read and replacement process buffer */ /* * Bad block replacement process definitions. */ /* Command Modifiers */ #define MD_CMP 040000 /* Compare */ #define MD_ERR 010000 /* Force Error */ #define MD_SEC 01000 /* Suppress Error Correction */ #define MD_SREC 0400 /* Suppress Error Recovery */ #define MD_PRI 01 /* Primary replacement block */ /* End Message Flags */ #define EF_BBR 0200 /* Bad block Reported */ #define EF_BBU 0100 /* Bad Block Unreported */ /* Status or Event Codes */ #define ST_MSK 037 /* Status/event code mask */ #define ST_SUC 0 /* Success (includes subcode "normal") */ #define ST_DAT 010 /* Data Error */ #define MD_HCE 0110 /* Header Compare Error */ /* Revector Control Info flags */ #define RCI_VP 02 /* Volume write protect flag */ #define RCI_FE 0200 /* Forced error flag */ #define RCI_BR 020000 /* Bad RBN flag */ #define RCI_P2 040000 /* Phase 2 flag */ #define RCI_P1 0100000 /* Phase 1 flag */ /* Block read check return values */ #define BR_NBBR 0 /* no bad block reported */ #define BR_BBR 1 /* bad block reported */ #define BR_CECC 2 /* correctable ECC error */ #define BR_UECC 3 /* uncorrectable ECC error */ #define BR_NDE 4 /* non data error */ #define BR_FEM 5 /* block written with "force error" modifier */ #define BR_DEB 6 /* data error with bad block reported */ /* * Variables used by the replacement process. */ #ifdef DEBUG int rp_bps; /* interrupt replacement process at step ? */ #endif DEBUG daddr_t rp_lbn; /* LBN of logical block being replaced */ daddr_t rp_rbn; /* RBN (Replacement Block Number) */ int rp_didit; /* Says block actually replaced */ int rp_hblk; /* RCT block of primary RBN descriptor */ int rp_hoff; /* RCT block offset of primary RBN descriptor */ int rp_blk; /* Current RCT block being searched */ int rp_off; /* Current RCT block offset */ int rp_oblk; /* RCT block number of OLD RBN */ int rp_ooff; /* RCT block offset of OLD RBN */ int rp_delta; /* RCT block search offset delta (ping-pong) */ int rp_irs; /* Initial read of bad LBN successful */ int rp_wcs7; /* Step 7, write-compare sucessful */ int rp_wcs8; /* Step 8, write-compare sucessful */ int rp_prev; /* LBN was previously replaced */ daddr_t rp_orbn; /* If previously replaced, OLD RBN */ daddr_t rp_orbd; /* old RBN descriptor, in case replace fsils */ int rp_pri; /* RBN is primary replacement block */ int rp_sec; /* RBN is non-primary replacement block */ int rp_l; /* Number of LBNs per track */ int rp_r; /* Number of RBNs per track */ int rp_dirty; /* Phase (P1 | P2) of interrupted replacement */ /* * Replacement process buffer pointers, * segment the read/write buffer for use * by the replacement process. */ struct rct_rci *bp_rci = &buf[0]; /* RCT blk 0 - replacement cntrl info */ char *bp_ir = &buf[512]; /* RCT blk 1 - image of bad LBN */ union rctb *bp_rct1 = &buf[1024]; /* RCT blk F - first block being searched */ union rctb *bp_rct2 = &buf[1536]; /* RCT blk S - second block (if needed) */ int *bp_tp = &buf[2048]; /* test data pattern ( 0165555 0133333 ) */ char *bp_tmp = &buf[2560]; /* scratch buffer */ /* * Structure of RCT (Revector Control Table) block 0. * Used during bad block replacement. */ struct rct_rci { short rt_vsn[4]; /* volume serial number */ short rt_stat; /* replacement process status word */ short rt_rsvd; /* reserved ??? */ union { /* LBN being replaced */ short ri_lbnw[2]; daddr_t ri_lbnl; } rt_lbn; union { /* RBN - replacement block number */ short ri_rbnw[2]; daddr_t ri_rbnl; } rt_rbn; union { /* bad RBN - RBN being replaced */ short ri_brbw[2]; daddr_t ri_brbl; } rt_brb; short rt_pad[244]; /* bad to 512 byte block */ }; /* * Structure used to access an RCT block * containing 128 RBN descriptors. The * order (swap hi & lo words) must be reversed * because of the way the V7 C compiler stores longs. */ union rctb { daddr_t rbnd_l; /* Access descriptor as a long */ short rbnd_w[2]; /* Access descriptor as two shorts */ }; /* * External variables found in the MSCP disk driver (ra.c). * Used to modifier driver operation for bad block * replacement and get error status info from the driver. */ #define RP_WRT 1 #define RP_RD 2 #define RP_REP 3 #define RP_AC 4 extern union { /* RABADS RBN for ra.c */ daddr_t ra_rbnl; short ra_rbnw[2]; } ra_rbn; extern int ra_badc; /* RABADS command flag in ra.c */ extern int ra_badm; /* RABADS command modifier in ra.c */ extern int ra_ctid[]; /* MSCP controller type ID */ extern char *ra_dct[]; /* Controller type name string */ extern int ra_stat[]; /* MSCP status/event code */ extern int ra_ecode[]; /* MSCP end code */ extern int ra_eflags[]; /* MSCP end message flags */ extern struct ra_drv ra_drv[3][4]; /* Drive type info */ struct dkinfo *dip; daddr_t sbn, us, nblk, nbc, rbn, nb; daddr_t bn; int repcnt, badcnt, rsize; int fd, rcnt; int ask; /* flag so table doesn't ask for a return */ int allflag; int rwfem; int force; long atol(); int cn; int unit; char line[50]; char fn[30]; /* file spec i.e., hp(0,0) */ char cmd[20]; /* command name */ char dt[20]; /* disk type rm03, etc */ char dn[2]; /* drive number */ int firstblk; /* flag for linear rct searching */ int off_bottom; /* descriptor in RCT greater that 127 */ int off_top; /* descriptor in RCT less than zero */ int first_level; /* have completed first level search of the RCT block */ int nondataerr; /* got a non-data error reading the block in step 7 */ int bbr_recur; /* BBR recursion counter */ char *help[] = { "", "To correct typing mistakes, press to erase one character", "or to erase the entire line.", "", "To execute a command, type the first letter of the command then", "press . The program may prompt for additional information.", "", "The valid RABADS commands are:", "", "help - Print this help message.", "", "exit - Exit from the RABADS program.", "", "drives - List the disks that can be initialized with RABADS.", "", "status - Print the status and geometry of the specified disk.", "", "table - Print the RCT (Revector Control Table) for a disk.", "", "init - Do a read scan of the disk and replace any bad blocks.", "", "replace - Force replacement of a disk block.", "", 0 }; char *fewarn[] = { "", "The block was written with the \"force error\" modifier, that is,", "when the block is read report an error even if the read succeeds.", "This indicates that the block has already been replaced but that", "valid data could not be recovered from the bad block before it", "was replaced. This may also indicate that a previous attempt to", "replace the block failed for some reason. In either case, the", "recommended procedure is to rewrite the block then reread it and", "only replace the block if the reread fails.", "", " ****** CAUTION ******", "", "Rewriting the block will clear the \"forced error\", however, the", "data in the block must be considered to have been corrupted. This", "is because valid data could not be read from the block before it", "was replaced.", "", 0 }; char *bdwarn = "\n\n\7\7\7DISK SHOULD NOT BE USED: \ \n (has unreplaced bad blocks or uncleared \"forced error\" blocks!)\n"; char *pwstr = "qwerty"; char *feb_nc1 = "was written with \"forced error\" - NOT CLEARED!\n"; char *feb_nc2 = "(Data in this block must considered invalid!)\n"; char *ndemsg = "(NON DATA ERROR: suspect faulty disk hardware or bad media!)\n"; char *rb_uecc = "(Uncorrectable ECC error in replacement block!)\n"; char *rb_bad = "(Hardware says replacement block bad, retry disk initialization!)\n"; extern int argflag; /* 0=interactive, 1=called by sdload */ int rctcopy; main() { struct rct_rci *rtp; register int i, j; register char *p; int s, cnt, k; int found, rctend, rctrw; long *lp; printf("\n\nULTRIX-11 MSCP Disk Initialization Program\n"); if(argflag) { /* called by SDLOAD, can only do init command */ cmd[0] = 'i'; cmd[1] = '\0'; goto do_i; } retry: ask = 1; force = 0; allflag = 0; rctcopy = 0; printf("\nrabads : "); gets(cmd); switch(cmd[0]) { case 'f': goto do_f; case 'h': for(i=0; help[i]; i++) printf("\n%s", help[i]); goto retry; case 'e': exit(NORMAL); case 'd': prtdsk(); goto retry; case 's': goto do_s; case 't': if(strcmp("t all", cmd) == 0) allflag++; /* print entire RCT */ if(strcmp("t go", cmd) == 0){ ask = 0; /* don't stop to ask */ allflag++; /* print entire RCT */ } goto do_t; case 'r': goto do_r; case 'i': goto do_i; case 0: goto retry; default: printf("\n(%s) - not a valid command!\n", cmd); goto retry; } do_s: if(dipset() < 0) goto retry; dskopen(NOERR, RD); if(fd >= 0) close(fd); printf("\nMSCP controller: %s at micro-code revision %d", ra_dct[cn], ra_ctid[cn] & 017); printf("\nUnit %d: ", unit); switch(ra_drv[cn][unit].ra_dt) { case RC25: printf("RC25"); break; case RX33: printf("RX33"); break; case RX50: printf("RX50"); break; case RD31: printf("RD31"); break; case RD32: printf("RD32"); break; case RD51: printf("RD51"); break; case RD52: printf("RD52"); break; case RD53: printf("RD53"); break; case RD54: printf("RD54"); break; case RA60: printf("RA60"); break; case RA80: printf("RA80"); break; case RA81: printf("RA81"); break; default: printf("UKNOWN or NONEXISTENT"); break; } printf(" status ="); if(ra_drv[cn][unit].ra_online) printf(" ONLINE"); else printf(" OFFLINE"); printf("\nLogical blocks per track\t= %d", ra_drv[cn][unit].ra_trksz); printf("\nReplacement blocks per track\t= %d", ra_drv[cn][unit].ra_rbns); printf("\nNumber of RCT copies\t\t= %d", ra_drv[cn][unit].ra_ncopy); printf("\nSize of each RCT copy in blocks\t= %d", ra_drv[cn][unit].ra_rctsz); printf("\nHost area size in blocks\t= %D\n", ra_drv[cn][unit].d_un.ra_dsize); goto retry; do_u: /* semi-secret stuff (unreplace block(s)) */ /* ******************************************************************************* printf("\nPassword: "); gets(line); if(strcmp("farkle", line) != 0) { printf("\nReserved for Digital!\n"); goto retry; } if(dipset() < 0) goto retry; dskopen(NOERR, RW); if(fd < 0) { printf("\nCan't open %s!\n", fn); goto retry; } if(rp_dirty) { printf("\nUnreplace aborted!\n"); goto do_u_x; } s = ra_drv[cn][unit].ra_rctsz; if(s == 0) { printf("\nDisk does not have a Revector Control Table!"); goto do_u_x; } do_u_bn: if(allflag == 0) { printf("\nBlock number: "); gets(line); if(line[0] == '\0') goto do_u_bn; bn = atol(line); if((bn < 0) || (bn >= ra_drv[cn][unit].d_un.ra_dsize)) goto do_u_bn; } rctend = 0; rctrw = 0; for(i=2; i> 12) & 017; switch(k) { case 02: case 03: if(allflag) { found++; bp_rct1[j].rbnd_l = 0L; break; } if(bn == (bp_rct1[j].rbnd_l & ~036000000000)) { found++; bp_rct1[j].rbnd_l = 0L; } break; case 07: if(((ra_ctid[cn] >> 4) & 017) == RQDX1) { rctend++; break; } else continue; case 010: rctend++; break; default: continue; } } if(found) { if(rctmcw(i, bp_rct1) < 0) { printf("\nPANIC: RCT multicopy write failed!\n"); exit(FATAL); } rctrw++; } if(rctend) { if(rctrw == 0) printf("\nBlock %D was not revectored!\n", bn); break; } } ******************************************************************************* */ do_u_x: close(fd); printf("\n"); goto retry; do_r: if(dipset() < 0) goto retry; if(dip->di_flag == BB_NONE) { printf("\nCannot replace blocks on an %s disk!\n", dip->di_type); goto retry; } dskopen(NOERR, RW); if(fd < 0) { printf("\nCan't open %s!\n", fn); goto retry; } if(rp_dirty) goto rp_s1; /* finish up interrupted replacement */ if(ra_drv[cn][unit].ra_rctsz == 0) { printf("\nDisk does not have a Revector Control Table!"); goto do_u_x; } do_r_bn: printf("\nBlock number: "); gets(line); if(line[0] == '\0') goto do_r_bn; bn = atol(line); if((bn < 0) || (bn >= ra_drv[cn][unit].d_un.ra_dsize)) goto do_r_bn; if(dip->di_flag == BB_RWRT) { /* cntlr will replace block if bad */ lseek(fd, (long)(bn*512), 0); ra_badc = RP_RD; read(fd, (char *)&buf, 512); } printf("\nBlock %D read check: ", bn); s = brchk(bn); /* read check block - see if really bad */ if((s == BR_BBR) || (s == BR_NBBR)) printf("SUCCEEDED - "); else printf("FAILED - "); switch(s) { case BR_BBR: case BR_DEB: printf("bad block reported\n"); break; case BR_NBBR: printf("no bad block reported\n"); if(dip->di_flag == BB_RWRT) { printf("\n\7\7\7Disk controller replaces bad blocks,"); printf(" no way to force replacement!\n"); goto do_u_x; } printf("\nReally replace this block ? "); if(yes(0) == YES) break; else goto do_u_x; case BR_CECC: case BR_UECC: printf("data error\n"); break; case BR_NDE: printf("non data error\n"); printf("\n** - block connot be replaced!\n"); goto do_u_x; case BR_FEM: printf("block written with \"force error\" modifier\n"); for(i=0; fewarn[i]; i++) printf("\n%s", fewarn[i]); printf("\nRewrite the block ? "); if(yes(0) == NO) goto do_u_x; lseek(fd, (long)(bn*512), 0); ra_badc = RP_WRT; if(write(fd, (char *)bp_tmp, 512) != 512) { printf("\n\7\7\7BLOCK REWRITE FAILED!\n"); goto do_u_x; } lseek(fd, (long)(bn*512), 0); ra_badc = RP_RD; if(dip->di_flag == BB_RWRT) goto do_r_rq; if(read(fd, (char *)bp_tmp, 512) == 512) printf("\nREREAD SUCCEEDED: block not replaced!\n"); else printf("\nREREAD FAILED: retry the replace command!\n"); goto do_u_x; do_r_rq: if(read(fd, (char *)bp_tmp, 512) != 512) { printf("\n\7\7\7Disk controller failed "); printf("to replace bad block!\n"); } else printf("\nDisk controller replaced block!\n"); goto do_u_x; } if(dip->di_flag == BB_COOP) { printf("\nBLOCK: %D - replacement ", bn); force++; /* force replacement (see rp_s8:) */ rp_lbn = bn; goto rp_s1; } goto do_u_x; do_f: printf("\nPassword: "); gets(line); if(strcmp(line, pwstr) != 0) { printf("\nSorry - reserved for Digital!\n"); goto retry; } if(dipset() < 0) goto retry; if(dip->di_flag == BB_NONE) { printf("\nCannot replace blocks on an %s disk!\n", dip->di_type); goto retry; } dskopen(NOERR, RW); if(fd < 0) { printf("\nCan't open %s!\n", fn); goto retry; } if(rp_dirty) { printf("\nForce aborted!\n"); goto do_u_x; } if(ra_drv[cn][unit].ra_rctsz == 0) { printf("\nDisk does not have a Revector Control Table!"); goto do_u_x; } do_f_bn: printf("\nBlock number: "); gets(line); if(line[0] == '\0') goto do_f_bn; bn = atol(line); if((bn < 0) || (bn >= ra_drv[cn][unit].d_un.ra_dsize)) goto do_f_bn; lseek(fd, (long)(bn*512), 0); read(fd, buf, 512); lseek(fd, (long)(bn*512), 0); ra_badc = RP_WRT; ra_badm = 010000; /* MD_ERR (force error) */ write(fd, buf, 512); goto do_u_x; do_t: if(dipset() < 0) goto retry; dskopen(NOERR, RD); if(fd < 0) { printf("\nCan't open %s!\n", fn); goto retry; } s = ra_drv[cn][unit].ra_rctsz; if(s == 0) { printf("\nDisk does not have a Revector Control Table!"); goto do_t_x; } if(allflag == 0) /* if "t all" ask which copy */ goto do_t_n; printf("\nRCT copy < "); k = ra_drv[cn][unit].ra_ncopy; for(i=0; i: "); gets(line); rctcopy = atoi(line); if((rctcopy < 0) || (rctcopy > k)) rctcopy = 0; if(rctmcr(0, bp_rci) < 0) goto do_t_err; rtp = bp_rci; i = rtp->rt_lbn.ri_lbnw[0]; /* reverse order */ rtp->rt_lbn.ri_lbnw[0] = rtp->rt_lbn.ri_lbnw[1]; rtp->rt_lbn.ri_lbnw[1] = i; i = rtp->rt_rbn.ri_rbnw[0]; /* reverse order */ rtp->rt_rbn.ri_rbnw[0] = rtp->rt_rbn.ri_rbnw[1]; rtp->rt_rbn.ri_rbnw[1] = i; i = rtp->rt_brb.ri_brbw[0]; /* reverse order */ rtp->rt_brb.ri_brbw[0] = rtp->rt_brb.ri_brbw[1]; rtp->rt_brb.ri_brbw[1] = i; printf("\nRCT block 0: revector control information.\n"); printf("\nStatus bits: P1=%d ", rtp->rt_stat&RCI_P1 ? 1 : 0); printf("P2=%d ", rtp->rt_stat&RCI_P2 ? 1 : 0); printf("BR=%d ", rtp->rt_stat&RCI_BR ? 1 : 0); printf("FE=%d ", rtp->rt_stat&RCI_FE ? 1 : 0); printf("VP=%d ", rtp->rt_stat&RCI_VP ? 1 : 0); printf("\nBad LBN\t= %D", rtp->rt_lbn.ri_lbnl); printf("\nRBN\t= %D", rtp->rt_rbn.ri_rbnl); printf("\nOld RBN\t= %D\n", rtp->rt_brb.ri_brbl); printf("\nOctal dump RCT block 1 ? "); gets(line); if(line[0] != 'y') goto do_t_n; if(rctmcr(1, bp_ir) < 0) goto do_t_err; printf("\nRCT block 1 contents:\n"); for(i=0; i<256; i++) { if((i%8) == 0) printf("\n "); printf("%o\t", bp_ir[i]); if(i == 127) if (ask) if(prfm()) goto do_t_x; } if (ask) if(prfm()) goto do_t_x; do_t_n: cnt = -1; for(i=2; i> 12) & 017; switch(k) { case 02: case 03: case 04: case 05: break; case 07: if(((ra_ctid[cn] >> 4) & 017) == RQDX1) { if(allflag) break; else goto do_t_x; } else continue; case 010: goto do_t_x; default: if(allflag) break; else continue; } cnt++; printf("\n%d\t%d\t%D\t", i, j, bp_rct1[j].rbnd_l & ~036000000000); switch(k) { case 00: printf("Unallocated replacement block"); break; case 02: printf("Allocated - primary RBN"); break; case 03: printf("Allocated - non-primary RBN"); break; case 04: case 05: printf("Unusable replacement block"); break; default: printf("Unknown code (%o)", k); break; } } } do_t_x: close(fd); printf("\n"); goto retry; do_i: if(dipset() < 0) goto retry; dskopen(ERR, RW); if(rp_dirty) { printf("\nInitialization aborted!\n"); goto do_u_x; } us = ra_drv[cn][unit].d_un.ra_dsize; printf("\nStarting block number < 0 >: "); gets(line); if(line[0] == '\0') sbn = 0L; else { sbn = atol(line); if((sbn < 0) || (sbn >= us)) { printf("\nBad starting block!\n"); do_i_ex: if(argflag) exit(FATAL); else goto retry; } } printf("\nNumber of blocks to check < %D >: ", us - sbn); gets(line); if(line[0] == '\0') nblk = us - sbn; else nblk = atol(line); if(nblk <= 0) { printf("\nBad # of blocks!\n"); goto do_i_ex; } if(nblk > (us - sbn)) { nblk = (us - sbn); printf("\nToo many blocks, truncating to %D blocks!\n", nblk); } do_i_rw: if(dip->di_flag != BB_NONE) { if(argflag == 0) { printf("\nRewrite blocks written with \"forced error\" "); printf("(? for help) ? "); rwfem = yes(HELP); if(rwfem == HELP) { for(i=0; fewarn[i]; i++) printf("\n%s", fewarn[i]); goto do_i_rw; } } else rwfem = YES; } printf("\nREADING...\n"); badcnt = 0; repcnt = 0; bn = sbn; nbc = 0; do_i_lp: nb = dip->di_chunk; if((bn + nb) > us) nb = (us - bn); if((nb + nbc) > nblk) nb = nblk - nbc; rsize = nb * 512; lseek(fd, (long)(bn*512), 0); ra_badc = RP_AC; rcnt = read(fd, (char *)&buf, rsize); if(rcnt == rsize) { do_i_lp1: bn += nb; nbc += nb; if(nbc >= nblk) { bg_loop: close(fd); printf("\n\n%D blocks checked", nbc); printf("\n%d bad blocks found", badcnt); printf("\n%d bad blocks replaced\n", repcnt); if(argflag == 0) { if(repcnt != badcnt) printf("%s", bdwarn); else printf("\n"); goto retry; } if(repcnt != badcnt) exit(HASBADS); while(getchar() != '\n') ; /* wait for */ exit(NORMAL); } goto do_i_lp; } for(rbn=bn; rbn<(bn+nb); rbn++) { lseek(fd, (long)(rbn*512), 0); ra_badc = RP_RD; rcnt = read(fd, (char *)&buf, 512); if(rcnt == 512) continue; badcnt++; printf("\nBLOCK: %D - ", rbn); switch(dip->di_flag) { /* replacement strategy to use */ case BB_COOP: if(ra_eflags[cn] & EF_BBR) { printf("replacement "); rp_lbn = rbn; goto rp_s1; /* go replace block */ } else if(ra_stat[cn] == ST_DAT) { /* FEM */ /* data error with force error modifier */ do_i_rs: if(!rwfem) { /* NOT REWRITING FORCED ERRORS */ printf("%s", feb_nc1); /* warn bad data */ printf("%s", feb_nc2); } else { if(fembrw(0, rbn) == YES) badcnt--; } break; } else { printf("(no bad block reported flag) "); printf("cannot be replaced!\n"); deprnt(); break; } do_i_rg: /* return here if replacement succeeded */ repcnt++; printf("SUCCEEDED!\n"); s = brchk(rbn); /* read check replacement block */ if(s == BR_NBBR) break; /* every thing is cool! */ if(s == BR_FEM) { /* replacement block - forced error */ if(!rwfem) { printf("BLOCK: %D - ", rbn); printf("%s", feb_nc1); printf("%s", feb_nc2); repcnt--; break; } if(fembrw(1, rbn) == NO) repcnt--; break; } repcnt--; printf("BLOCK: %D - ", rbn); printf("replacement block read check FAILED!\n"); switch(s) { case BR_UECC: printf("%s", rb_uecc); deprnt(); break; case BR_BBR: printf("%s", rb_bad); /* BAD REPLACEMENT BLOCK ?????? */ /* should go back and rescan */ break; case BR_NDE: default: printf("%s", ndemsg); deprnt(); break; } break; do_i_rb: /* return here if replacement failed */ printf("\nBLOCK: %D - replacement FAILED!\n", rbn); break; do_i_ra: /* return here if replacement aborted */ /* i.e., block was not really bad */ printf("ABORTED (block not really bad)!\n"); lseek(fd, (long)(rbn*512), 0); ra_badc = RP_RD; read(fd, (char *)&buf, 512); if(ra_stat[cn] != ST_DAT) { badcnt--; break; /* NOT FORCED ERROR */ } if(!rwfem) { printf("BLOCK: %D - ", rbn); printf("%s", feb_nc1); printf("%s", feb_nc2); break; } if(fembrw(1, rbn) == YES) badcnt--; break; case BB_NONE: printf("%s: bad blocks cannot be replaced!\n", dip->di_type); deprnt(); break; case BB_RWRT: if(ra_eflags[cn] & EF_BBR) { printf("replacement "); switch(brchk(rbn)) { /* read check */ case BR_NBBR: repcnt++; printf("SUCCEEDED!\n"); break; case BR_FEM: printf("SUCCEEDED!\n"); repcnt++; if(!rwfem) { printf("BLOCK: %D - ", rbn); printf("%s", feb_nc1); printf("%s", feb_nc2); repcnt--; break; } if(fembrw(1, rbn) == NO) repcnt--; break; case BR_UECC: printf("FAILED!\n"); printf("%s", rb_uecc); deprnt(); break; case BR_BBR: printf("FAILED!\n"); printf("%s", rb_bad); /* BAD REPLACEMENT BLOCK ?????? */ /* should go back and rescan */ break; case BR_NDE: default: printf("FAILED!\n"); printf("%s", ndemsg); deprnt(); break; } } else if(ra_stat[cn] == ST_DAT) { /* FEM */ if(!rwfem) { /* NOT REWRITING FORCED ERRORS */ printf("%s", feb_nc1); /* warn bad data */ printf("%s", feb_nc2); } else { if(fembrw(0, rbn) == YES) badcnt--; } } else { printf("cannot be replaced!\n"); printf("%s", ndemsg); deprnt(); } break; } } goto do_i_lp1; /* * MSCP: host initiated bad block replacement algorithm * * I allow myself one editorial comment before proceeding: * * Fred Canter "Good GOD Gertrude, you must be kidding!" * * Each step of the bad block replacement procedure is labeled * so as to correspond to the steps in section 7.5 of the "DSA * DISK FORMAT SPECIFICATION" Version 1.4.0. */ rp_s1: #ifdef DEBUG if(rp_bps == 1) goto do_u_x; #endif DEBUG /* * Step 1 is performed elsewhere in the program. Either the replacement * process is initilated by an error with the BAD BLOCK REPORTED flag set, * or the process is restarted because it was interrupted by a failure of * some type. The latter case is detected when the unit is prought online. */ rp_didit = 0; /* clear block actually replaced indicator */ /* in case of interrupted replacement */ rp_prev = rp_pri = rp_sec = 0; rp_s2: #ifdef DEBUG if(rp_bps == 2) goto do_u_x; #endif DEBUG /* * The DSA spec calls for a soft lock of the unit, but because replacement * is only done by this stand-alone program a lock is not necessary. */ bbr_recur = 0; /* initialize the BBR recursion counter to 0 */ rp_s3: #ifdef DEBUG if(rp_bps == 3) goto do_u_x; #endif DEBUG /* * The first two steps were easy, but I don't expect this trend to continue. */ if(rp_dirty == 0) goto rp_s4; /* NOT an interrupted replacement! */ /* * Interrupted replacement, * Re-establish software context for Phase 1 * and Phase 2, if necessary. * Yes, I know that RCT block 0 was read in * during the dskopen()! */ printf("\n\7\7\7COMPLETING INTERRUPTED BAD BLOCK REPLACEMENT"); printf(" (Phase %d)...\n", rp_dirty); if(rctmcr(0, bp_rci) < 0) { /* revector control info */ rp_rcte(3, RD, 0); goto rp_s18; } if(rctmcr(1, bp_ir) < 0) { /* bad LBN image */ rp_rcte(3, RD, 1); goto rp_s18; } rtp = (struct rct_rci *)bp_rci; if(rtp->rt_stat & RCI_FE) /* initial read sucessful or not */ rp_irs = NO; else rp_irs = YES; /* * The DSA spec says that the LBN is only valid * if the P1 bit is set, but I don't buy it! * I never clear the LBN until after phase 2 is * complete or a fatal error. */ i = rtp->rt_lbn.ri_lbnw[0]; /* reverse order */ rtp->rt_lbn.ri_lbnw[0] = rtp->rt_lbn.ri_lbnw[1]; rtp->rt_lbn.ri_lbnw[1] = i; rp_lbn = rtp->rt_lbn.ri_lbnl; /* bad block's LBN */ printf("\nBLOCK: %D - replacement ", rp_lbn); if(rp_dirty == 1) goto rp_s7; /* Interrupted during phase one */ i = rtp->rt_rbn.ri_rbnw[0]; /* new RBN - reverse order */ rtp->rt_rbn.ri_rbnw[0] = rtp->rt_rbn.ri_rbnw[1]; rtp->rt_rbn.ri_rbnw[1] = i; rp_rbn = rtp->rt_rbn.ri_rbnl; i = rtp->rt_brb.ri_brbw[0]; /* old RBN - reverse order */ rtp->rt_brb.ri_brbw[0] = rtp->rt_brb.ri_brbw[1]; rtp->rt_brb.ri_brbw[1] = i; if(rtp->rt_stat & RCI_BR) { /* previously replaced */ rp_prev = 1; rp_orbn = rtp->rt_brb.ri_brbl; } rp_l = ra_drv[cn][unit].ra_trksz; /* LBNs per track */ rp_r = ra_drv[cn][unit].ra_rbns; /* RBNs per track */ /* Primary RBN descriptor */ rp_hblk = (((rp_lbn / rp_l) * rp_r) / 128) + 2; rp_hoff = ((rp_lbn / rp_l) * rp_r) % 128; rp_blk = (rp_rbn / 128) + 2; /* Actual RBN descriptor */ rp_off = rp_rbn % 128; if((rp_blk == rp_hblk) && (rp_off == rp_hoff)) /* Primary RBN ? */ rp_pri = 1; else rp_sec = 1; /* YES, I know rp_sec not really used */ if(rp_prev) { /* set saved old RBN desc, as best we can */ rp_orbd = rp_lbn; /* LBN being replaced */ rp_oblk = (rp_orbn / 128) + 2; rp_ooff = rp_orbn % 128; if((rp_oblk == rp_hblk) && (rp_ooff == rp_hoff)) rp_orbd |= 04000000000; /* primary RBN */ else rp_orbd |= 06000000000; /* non-primary RBN */ } if(rctmcr(rp_blk, bp_rct1) < 0) { /* First RCT block */ rp_rcte(3, RD, rp_blk); goto rp_s18; } goto rp_s11; /* finish up phase 2 */ rp_s4: #ifdef DEBUG if(rp_bps == 4) goto do_u_x; #endif DEBUG printf("4 "); /* * Read the suspected bad block, remember whether or not the read succeeded. * Also, remember if the forced error indicator was set. */ rp_irs = NO; p = bp_ir; for(i=0; i<512; i++) *p++ = 0; lseek(fd, (long)(rp_lbn*512), 0); ra_badc = RP_RD; for (i=0; i < 4; i++) if(read(fd, bp_ir, 512) == 512) { rp_irs = YES; break; } else { if(ra_stat[cn] & ST_DAT) break; rp_irs = NO; } rp_s5: #ifdef DEBUG if(rp_bps == 5) goto do_u_x; #endif DEBUG printf("5 "); /* * Save data read in step 4 in RCT block 1. */ if(rctmcw(1, bp_ir) < 0) { rp_rcte(4, WRT, 1); goto rp_s18; } rp_s6: #ifdef DEBUG if(rp_bps == 6) goto do_u_x; #endif DEBUG printf("6 "); /* * Begin phase 1, save info in RCT block 0. */ if(rctmcr(0, bp_rci) < 0) { rp_rcte(6, RD, 0); goto rp_s18; } rtp = (struct rct_rci *)bp_rci; rtp->rt_lbn.ri_lbnl = rp_lbn; i = rtp->rt_lbn.ri_lbnw[0]; /* reverse order */ rtp->rt_lbn.ri_lbnw[0] = rtp->rt_lbn.ri_lbnw[1]; rtp->rt_lbn.ri_lbnw[1] = i; rtp->rt_stat &= ~RCI_FE; if(rp_irs == NO) rtp->rt_stat |= RCI_FE; rtp->rt_stat |= RCI_P1; if(rctmcw(0, bp_rci) < 0) { rp_rcte(6, WRT, 0); goto rp_s17; } rp_s7: #ifdef DEBUG if(rp_bps == 7) goto do_u_x; #endif DEBUG printf("7 "); /* * Check to see if the block is really bad. * * Read the block, then write customer data, then write inverted * customer data. */ nondataerr = NO; rp_wcs7 = YES; if(rctmcr(1, bp_tmp) < 0) { /* Get best guess data from RCT blk 1 */ rp_rcte(7, RD, 1); goto rp_s18; } for (i = 0; i < 4; i++) { /* check for any data error */ lseek(fd, (long)(rp_lbn*512), 0); ra_badc = RP_AC; ra_badm = MD_SEC|MD_SREC; if ((read(fd, buf, 512) != 512) && ((ra_eflags[cn] & EF_BBR) || (ra_eflags[cn] & EF_BBU)) || (ra_stat[cn] & 0xe8)) { rp_wcs7 = NO; break; } } if (rp_wcs7 == NO && ((ra_stat[cn] & 0xe8) != 0xe8)) { /* printf(" nondata read failure status = 0x%x - aborting\n", ra_stat); GMM */ rp_wcs7 = YES; nondataerr = YES; } if (rp_wcs7 == YES && ~nondataerr) { bp_tp = &buf[2048]; bp_tmp = &buf[512]; for (j= 0; j < 512; j++) *bp_tp++ = ~*bp_ir++; bp_tp = &buf[2048]; bp_ir = &buf[512]; for (i = 0; i < 8; i++) { if ((rp_wcs7 = blocktest(fd, !rp_irs, bp_ir)) == YES) rp_wcs7 = blocktest(fd, 0, bp_tp); if (rp_wcs7 == NO) break; } } rp_s8: #ifdef DEBUG if(rp_bps == 8) goto do_u_x; #endif DEBUG printf("8 "); /* * Bad block may be good, write saved bad block contents back * out to bad block. May be a transient bad block error???? * * NOTE: the "force" variable causes replacement regardless! */ rp_wcs8 = YES; lseek(fd, (long)(rp_lbn*512), 0); ra_badc = RP_WRT; ra_badm = MD_CMP; if(rp_irs == NO) ra_badm |= MD_ERR; if(write(fd, (char *)bp_ir, 512) == 512) { if(((ra_eflags[cn] & EF_BBR) == 0) && (rp_irs == YES)) { if(force || (rp_wcs7 == NO)) goto rp_s9; else goto rp_s13; } } if((ra_stat[cn] & 0xe8) && /* DATA ERROR with FORCED ERROR */ (rp_irs == NO) && ((ra_eflags[cn] & EF_BBR) == 0)) if(force) goto rp_s9; else goto rp_s13; rp_s9: #ifdef DEBUG if(rp_bps == 9) goto do_u_x; #endif DEBUG printf("9 "); /* * Seach the RCT for the replacement block number (RBN) and * whether or not the bad LBN was previously replaced, if so * also get the old RBN. */ /* Set initial (hash) RCT block # and offset, init variables */ if (bbr_recur >= 2) { printf("Replacement Command Failure at LBN %d\n", rp_lbn); goto rp_s16; } else bbr_recur++; firstblk = 0; rp_prev = rp_pri = rp_sec = 0; rp_l = ra_drv[cn][unit].ra_trksz; /* LBNs per track */ rp_r = ra_drv[cn][unit].ra_rbns; /* RBNs per track */ rp_hblk = (((rp_lbn / rp_l) * rp_r) / 128) + 2; rp_hoff = ((rp_lbn / rp_l) * rp_r) % 128; rp_blk = rp_hblk; rp_off = rp_hoff; /* Check for primary RBN descriptor empty or matches this LBN */ if(rctmcr(rp_blk, bp_rct1) < 0) { rp_rcte(9, RD, rp_blk); goto rp_s16; } if(rbempty()) { rp_pri++; goto rp_s9_f; /* found RBN */ } if(rbmatch()) { rp_prev++; rp_orbn = ((rp_blk - 2) * 128) + rp_off; /* OLDCODE rp_orbn = bp_rct1[rp_off].rbnd_l & ~036000000000; */ rp_orbd = bp_rct1[rp_off].rbnd_l; } /* Start ping-pong search */ first_level = YES; off_bottom = off_top = NO; rp_delta = 1; do { rp_off = rp_hoff + rp_delta; if((rp_off >= 0) && (rp_off <= 127) && !rbnull()) { if(rbempty()) { rp_sec++; goto rp_s9_f; /* found RBN */ } if(rbmatch()) { rp_prev++; rp_orbn = ((rp_blk - 2) * 128) + rp_off; rp_orbd = bp_rct1[rp_off].rbnd_l; } } else { if(rp_off > 127) off_bottom = YES; if(rp_off < 0) off_top = YES; if((off_top = YES) && (off_top == off_bottom)) first_level == NO; } rp_delta = -rp_delta; if(rp_delta >= 0) rp_delta++; } while ((first_level) && (!rbnull())); if(!rbnull()) rp_blk++; else rp_blk = 2; firstblk++; rp_off = rp_hoff = 0; /* Start of linear search */ rp_s9_l: if(rblast()) { /* If primary in last RCT block, go to first block */ rp_blk = 2; rp_off = 0; } rp_s9_l1: if(rctmcr(rp_blk, bp_rct1) < 0) { rp_rcte(9, RD, rp_blk); goto rp_s16; } rp_off = 0; rp_s9_l2: if((rp_blk == rp_hblk) && (!firstblk )) { /* search failed */ rp_rcte(9, -1, 0); /* RP step 9 FAILED! - message */ printf("\nRCT search failed: no replacement block available!\n"); goto rp_s16; } if(rbempty()) { rp_sec++; goto rp_s9_f; /* found RBN */ } if(rbmatch()) { rp_prev++; rp_orbn = ((rp_blk - 2) * 128) + rp_off; /* OLDCODE rp_orbn = bp_rct1[rp_off].rbnd_l & ~036000000000; */ rp_orbd = bp_rct1[rp_off].rbnd_l; } if(rbnull()) { rp_blk = 2; goto rp_s9_l1; } rp_off++; if(rp_off > 127) { rp_blk++; firstblk = 0; goto rp_s9_l1; } goto rp_s9_l2; rp_s9_f: rp_rbn = ((rp_blk - 2) * 128) + rp_off; rp_s10: #ifdef DEBUG if(rp_bps == 10) goto do_u_x; #endif DEBUG /* * Update RCT block 0 with RBN, BR flag, and say in phase 2. */ printf("10 "); rtp->rt_rbn.ri_rbnl = rp_rbn; i = rtp->rt_rbn.ri_rbnw[0]; /* reverse order */ rtp->rt_rbn.ri_rbnw[0] = rtp->rt_rbn.ri_rbnw[1]; rtp->rt_rbn.ri_rbnw[1] = i; if(rp_prev) { rtp->rt_brb.ri_brbl = rp_orbn; i = rtp->rt_brb.ri_brbw[0]; /* reverse order */ rtp->rt_brb.ri_brbw[0] = rtp->rt_brb.ri_brbw[1]; rtp->rt_brb.ri_brbw[1] = i; rtp->rt_stat |= RCI_BR; } rtp->rt_stat &= ~RCI_P1; rtp->rt_stat |= RCI_P2; if(rctmcw(0, bp_rci) < 0) { rp_rcte(10, WRT, 0); goto rp_s16; } rp_s11: #ifdef DEBUG if(rp_bps == 11) goto do_u_x; #endif DEBUG /* * Update RCT to say block has been replaced. */ printf("11 "); bp_rct1[rp_off].rbnd_l = rp_lbn; if(rp_pri) bp_rct1[rp_off].rbnd_w[0] |= 020000; else bp_rct1[rp_off].rbnd_w[0] |= 030000; rp_oblk = (rp_orbn / 128) + 2; rp_ooff = rp_orbn % 128; if(rp_prev) { if(rp_blk != rp_oblk) { /* rbn & old rbn in diff blks */ if(rctmcr(rp_oblk, bp_rct2) < 0) { rp_rcte(11, RD, rp_oblk); goto rp_s16; } bp_rct2[rp_ooff].rbnd_l = 010000000000L; } else bp_rct1[rp_ooff].rbnd_l = 010000000000L; } if(rctmcw(rp_blk, bp_rct1) < 0) { rp_rcte(11, WRT, rp_blk); goto rp_s15; } if(rp_prev && (rp_oblk != rp_blk)) { if(rctmcw(rp_blk, bp_rct2) < 0) { rp_rcte(11, WRT, rp_blk); goto rp_s15; } } rp_s12: #ifdef DEBUG if(rp_bps == 12) goto do_u_x; #endif DEBUG /* * Use the REPLACE command to cause the controller * to replace the bad block. */ printf("12 "); lseek(fd, (long)(rp_lbn*512), 0); ra_badc = RP_REP; if(rp_pri) ra_badm = MD_PRI; ra_rbn.ra_rbnl = rp_rbn; /* tell driver replacement block # */ write(fd, (char *)bp_ir, 512); /* really a REPLACE command */ if((ra_stat[cn] & ST_MSK) != ST_SUC) { rp_rcte(12, -1, 0); /* RP step 12 FAILED! - message */ printf("\nMSCP replace command failed!\n"); goto rp_s17; } if(rp_dirty == 2) goto rp_s120; /* * First, read the block and check for the Forced Error flag. * All unused RBNs are written with the forced error flag, so * it should be set if the replace command worked. */ lseek(fd, (long)(rp_lbn*512), 0); ra_badc = RP_RD; read(fd, buf, 512); if ((ra_stat[cn] & ST_DAT) != ST_DAT) { rp_rcte(12, -1, 0); /* RP step 12 FAILED! - message */ printf("\nMSCP replace command failed!\n"); printf("RBN used for LBN %d did not contain Forced Error indicator.\n", rp_lbn); /*printd2("ra_stat = 0x%x, ra_ecode = 0x%x, ra_eflags = 0x%x\n", ra_stat, ra_ecode, ra_eflags); */ goto rp_s17; } /* * Read the date to be written to the replacement block * from RCT block 1 -- just to be safe. */ /* if (rctmcr(1, bp_ir) < 0) { rp_rcte(12, RD, 0); goto rp_s18; } */ rp_s120: lseek(fd, (long)(rp_lbn*512), 0); ra_badc = RP_WRT; ra_badm = MD_CMP; if(rp_irs == NO) ra_badm |= MD_ERR; write(fd, (char *)bp_ir, 512); /* write saved -> replacement block */ if((ra_stat[cn] & ST_MSK) == ST_SUC) goto rp_s121; if((ra_eflags[cn] & EF_BBR) != EF_BBR) if((ra_stat[cn] == ST_DAT) && (rp_irs == NO)) goto rp_s121; /* write - compare failed */ rp_rcte(12, -1, 0); printf("\nWRITE-COMPARE operation on replacement block failed!\n"); /* * If a header compare error or a bad block reported, go back * to step 9 and try to find another RBN. */ if((ra_stat[cn] != MD_HCE) || (ra_eflags[cn] & EF_BBR)) goto rp_s9; else { printf("Check the RCT, it MAY be corrupt!!\n"); if(cmd[0] = 'i') goto bg_loop; else { goto do_u_x; } } rp_s121: /* replacement succeeded */ rp_didit++; rp_s13: #ifdef DEBUG if(rp_bps == 13) goto do_u_x; #endif DEBUG /* * Update RCT block 0 to indicate replacement * no longer in progress. */ printf("13 "); rtp->rt_stat &= RCI_VP; /* clean out all but VP */ rtp->rt_lbn.ri_lbnl = 0L; rtp->rt_rbn.ri_rbnl = 0L; rtp->rt_brb.ri_brbl = 0L; if(rctmcw(0, bp_rci) < 0) { rp_rcte(13, WRT, 0); goto rp_s17; } rp_s14: #ifdef DEBUG if(rp_bps == 14) goto do_u_x; #endif DEBUG /* * Soft lock not used. * Replacement completed, return! */ if(cmd[0] == 'i') { if(rp_didit) goto do_i_rg; else goto do_i_ra; } else { if(fd > 0) close(fd); if(rp_dirty) rp_dirty = 0; if(rp_didit) printf("SUCCEEDED!\n"); else if (nondataerr) { printf("ABORTED (nondata error encontered)!\n"); nondataerr = NO; } else printf("ABORTED (block not really bad)!\n"); goto retry; } rp_s15: #ifdef DEBUG if(rp_bps == 15) goto do_u_x; #endif DEBUG /* * Restore RCT to say new RBN unusable and * set bad LBN back to its original state. * ECO: not sure what to do yet! * For now, say RBN unusable regardless! */ printf("15 "); bp_rct1[rp_off].rbnd_l = 010000000000L; if(rp_prev) { if(rp_blk != rp_oblk) bp_rct2[rp_ooff].rbnd_l = rp_orbd; else bp_rct1[rp_ooff].rbnd_l = rp_orbd; } if(rctmcw(rp_blk, bp_rct1) < 0) rp_rcte(15, WRT, rp_blk); if(rp_prev && (rp_blk != rp_oblk)) if(rctmcw(rp_oblk, bp_rct2) < 0) rp_rcte(15, WRT, rp_oblk); rp_s16: #ifdef DEBUG if(rp_bps == 16) goto do_u_x; #endif DEBUG /* * Write saved date back to the bad LBN * with forced error modifier. */ printf("16 "); lseek(fd, (long)(rp_lbn*512), 0); ra_badc = RP_WRT; if(rp_irs == NO) ra_badm = MD_ERR; if(write(fd, (char *)bp_ir, 512) != 512) { rp_rcte(16, -1, 0); /* RP step 16 FAILED! - message */ printf("\nRewrite of original data back to bad block failed!\n"); } rp_s17: #ifdef DEBUG if(rp_bps == 17) goto do_u_x; #endif DEBUG /* * Update RCT block 0 to say replacement * no longer inprogress. */ printf("17 "); rtp->rt_stat &= RCI_VP; /* clean out all but VP */ rtp->rt_lbn.ri_lbnl = 0L; rtp->rt_rbn.ri_rbnl = 0L; rtp->rt_brb.ri_brbl = 0L; if(rctmcw(0, bp_rci) < 0) rp_rcte(17, WRT, 0); rp_s18: #ifdef DEBUG if(rp_bps == 18) goto do_u_x; #endif DEBUG /* * Soft lock not used. * Replacement failed, return! */ if(cmd[0] == 'i') goto do_i_rb; else { if(rp_dirty) rp_dirty = 0; printf("\n\7\7\7Block %D replacement FAILED!\n", rp_lbn); if(fd > 0) close(fd); goto retry; } } /* * Write data to a block, and then read it -- thus testing the block */ blocktest(fd, ucerr, bp) int fd; /* file descriptor */ char *bp; int ucerr; /* uncorrectable ECC error when reading * the block the block to be replaced */ { int i, count; int block_good; /* true if block is thought to be good */ block_good = YES; lseek(fd, (long)(rp_lbn*512), 0); ra_badc = RP_WRT; ra_badm = (MD_CMP|MD_SEC|MD_SREC | (!ucerr ? 0 : MD_ERR)); if((((count = write(fd, bp, 512)) != 512) && (ra_eflags[cn] & EF_BBR)) || (ra_stat[cn] & 0xe8)) { block_good = NO; } if (block_good == YES) { for (i = 0; i < 4; i++) { lseek(fd, (long)(rp_lbn*512), 0); ra_badc = RP_AC; ra_badm = MD_SEC|MD_SREC; if(((read(fd, buf, 512) != 512) && (ra_eflags[cn] & EF_BBR)) || (ra_stat[cn] & 0xe8)) { block_good = NO; break; } } } return (block_good); } /* * RCT read/write fatal error message * * s = step in replacement process * rw = failure was on read or write * = -1, print first line then return * lbn = block number */ rp_rcte(s, rw, lbn) int s; int rw; int lbn; { printf("\n\7\7\7Bad block replacement process step %d FAILED!", s); if(rw == -1) return; printf("\nMulticopy %s", (rw == WRT) ? "write" : "read"); printf(" of RCT block %d FAILED!\n", lbn); deprnt(); /* print disk error info */ } /* * Open the disk and set file descriptor in fd. * mode = how to open, read, write, read/write. * err = ignore errors (see if drive is there). * * If the disk has an RCT, read RCT block zero * and set rp_dirty to the phase that was in * progress if the replacement was interrupted. * Otherwise, set rp_dirty to zero. */ dskopen(err, mode) int err; int mode; { register struct rct_rci *rtp; if((fd = open(fn, mode)) <= 0) { if(err == 0) { printf("\nCan't open %s!\n", fn); exit(FATAL); } return; } rp_dirty = 0; if((ra_drv[cn][unit].ra_rctsz == 0) || (dip->di_flag != BB_COOP)) return; if(rctmcr(0, bp_rci) < 0) { printf("\n\7\7\7WARNING: cannot read RCT block zero for "); printf("%s unit %d!\n", ra_dct[cn], unit); return; } rtp = (struct rct_rci *)bp_rci; if(rtp->rt_stat & RCI_P1) rp_dirty = 1; if(rtp->rt_stat & RCI_P2) rp_dirty = 2; if(rp_dirty == 0) return; printf("\n\7\7\7\t\t****** WARNING ******\n"); printf("\nA bad block replacement was interrupted during phase %d.\n", rp_dirty); if(cmd[0] == 'r') return; printf("\nAfter the current command completes, execute a replace"); printf("\ncommand by responding to the rabads < ..... >: prompt"); printf("\nwith the letter r followed by . This will"); printf("\ncause the interrupted replacement of be completed.\n"); } prtdsk() { struct dkinfo *dp; printf("\nDisk\tULTRIX\tSize in"); printf("\nName\tName\tBlocks"); printf("\n----\t----\t------"); for(dp=dkinfo; dp->di_type; dp++){ printf("\n%s\t", dp->di_type); printf("%s\t", dp->di_name); printf("%D", dp->di_size); } printf("\n"); } /* * Drive information pointer set, * pointer into dkinfo table, * unit number, * MSCP controller number, * file name - ??(#,0). */ dipset() { register int i; printf("\nDisk type < "); for(i=0; dkinfo[i].di_type; i++) { printf("%s ", dkinfo[i].di_type); } printf(">: "); gets(dt); for(dip=dkinfo; dip->di_type; dip++) if(strcmp(dip->di_type, dt) == 0) break; if(dip->di_type == 0) { printf("\n(%s) - not supported by RABADS!\n", dt); dip_x: if(argflag) exit(FATAL); else return(-1); } printf("\nUnit number < 0-3 >: "); gets(dn); if((strlen(dn) != 1) || (dn[0] < '0') || (dn[0] > '3')) { printf("\nUnits 0 -> 3 only!\n"); goto dip_x; } unit = dn[0] - '0'; sprintf(fn, "%s(%s,0)", dip->di_name, dn); for(i=0; devsw[i].dv_name; i++) if(strcmp(dip->di_name, devsw[i].dv_name) == 0) break; cn = devsw[i].dv_cn; #ifdef DEBUG printf("\nDEBUG: Break Point at replacement step ? "); gets(line); if(line[0] == '\0') rp_bps = 0; else rp_bps = atoi(line); #endif DEBUG return(0); } /* * RCT multicopy read, * lbn = sector of RCT to read. * bp = pointer to buffer. * Host area size is added to lbn. * cn is MSCP cntlr number, unit is drive number, * fd is the previously opened file descriptor, * all are external to main(). */ rctmcr(lbn, bp) unsigned lbn; union rctb *bp; { register int i, n, s; daddr_t bn, boff; n = ra_drv[cn][unit].ra_ncopy; s = ra_drv[cn][unit].ra_rctsz; bn = ra_drv[cn][unit].d_un.ra_dsize + lbn; for(i=0; i 1) rctrev(bp); return(0); } bn += s; } return(-1); } /* * RCT multicopy write, * lbn = sector of RCT to write. * bp = pointer to buffer. * Host area size is added to lbn. * cn is the MSCP cntlr number, unit is drive number, * fd is the previously opened file descriptor, * all are external to main(). */ rctmcw(lbn, bp) unsigned lbn; union rctb *bp; { register int i, n, s; int ec, sc, fatal; daddr_t bn, boff; n = ra_drv[cn][unit].ra_ncopy; s = ra_drv[cn][unit].ra_rctsz; bn = ra_drv[cn][unit].d_un.ra_dsize + lbn; ec = fatal = 0; if(lbn > 1) /* only reverse blocks containing RBNs */ rctrev(bp); for(i=0; i> 5) & 03777; if((ra_stat[cn] & ST_MSK) == ST_DAT) { if((sc != 2) && (sc != 3) && (sc != 7)) continue; /* NOT - HCE, DATA SYNC, UNC ECC */ ec++; lseek(fd, (long)boff, 0); ra_badc = RP_WRT; ra_badm = MD_ERR; write(fd, (char *)bp, 512); if((ra_stat[cn] & ST_MSK) == ST_SUC) continue; sc = (ra_stat[cn] >> 5) & 03777; if((ra_stat[cn] & ST_MSK) == ST_DAT) { if((sc != 2) && (sc != 3) && (sc != 7)) continue; } } fatal = -1; break; } if(ec >= n) fatal = -1; return(fatal); } /* * Reverse the order of the RBN descriptors in bp_rct1[]. * ULTRIX-11 C still need hi order word first! */ rctrev(bp) union rctb *bp; { register union rctb *rbp; register int i, j; rbp = bp; for(i=0; i<128; i++) { j = rbp[i].rbnd_w[0]; rbp[i].rbnd_w[0] = rbp[i].rbnd_w[1]; rbp[i].rbnd_w[1] = j; } } /* * Print the disk error information that would * have been printed by the driver if the ra_badc * flag was not set. */ deprnt() { printf("%s unit %d disk error: ", ra_dct[cn], unit); printf("endcode=%o flags=%o status=%o\n", ra_ecode[cn], ra_eflags[cn], ra_stat[cn]); printf("(FATAL ERROR)\n"); } rbempty() { if((bp_rct1[rp_off].rbnd_l & 036000000000) == 0) return(1); else return(0); } rbmatch() { if((bp_rct1[rp_off].rbnd_l & 04000000000) == 0) return(0); if(rp_lbn == (bp_rct1[rp_off].rbnd_l & ~036000000000)) return(1); return(0); } rbnull() { if((bp_rct1[rp_off].rbnd_l & 036000000000) == 020000000000) return(1); else return(0); } rblast() { register int i; for(i=0; i<128; i++) if((bp_rct1[i].rbnd_l & 036000000000) == 020000000000) return(1); return(0); } prfm() { register char c; printf("\n\nPress for more"); printf(" ( to abort): "); while((c=getchar()) != '\n') { if(c == 03) /* */ return(1); } return(0); } char ynline[40]; yes(hlp) { yorn: gets(ynline); if((strcmp(ynline, "y") == 0) || (strcmp(ynline, "yes") == 0)) return(YES); if((strcmp(ynline, "n") == 0) || (strcmp(ynline, "no") == 0)) return(NO); if(hlp) if((strcmp(ynline, "?") == 0) || (strcmp(ynline, "help") == 0)) return(HELP); printf("\nPlease answer yes or no!\n"); goto yorn; } /* * Read a suspected bad block and * return its status. */ brchk(lbn) daddr_t lbn; { register int i, s; for(i=0; i<100; i++) { lseek(fd, (long)(lbn*512), 0); ra_badc = RP_AC; if(read(fd, (char *)&buf, 512) != 512) break; } s = ra_stat[cn] & ST_MSK; if(s == ST_SUC) { if(ra_eflags[cn] & EF_BBR) return(BR_BBR); else return(BR_NBBR); } else if(s == ST_DAT) { if((dip->di_flag != BB_RWRT) && (ra_eflags[cn] & EF_BBR)) return(BR_DEB); switch((ra_stat[cn] >> 5) & 03777) { case 0: return(BR_FEM); case 4: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: /* can't happen - not allowing datagrams */ return(BR_CECC); case 7: return(BR_UECC); default: return(BR_NDE); } } else return(BR_NDE); } /* * Conditionally print BLOCK # header message. * Rewite a block that was written with "forced error". * Return status of rewrite operation. */ fembrw(hm, lbn) int hm; daddr_t lbn; { if(hm) printf("BLOCK: %D - ", lbn); printf("rewrite to clear \"forced error\" "); lseek(fd, (long)(lbn*512), 0); ra_badc = RP_WRT; write(fd, (char *)&buf, 512); lseek(fd, (long)(lbn*512), 0); if(read(fd, (char *)&buf, 512) == 512) { printf("SUCCEEDED!\n"); return(YES); } else { printf("FAILED!\n"); deprnt(); /* print disk error info */ return(NO); } } : #ifdef DEBUG if(rp_bps == 16) goto do_u_x; #endif DEBUG /* * Write saved date back to the bad LBN * with forced error modifier. */ printf("16 "); lseek(fd, (long)(rp_lbn*512), 0); ra_badc = RP_WRT; if(rp_irs == NO) ra_badm = MD_ERR; if(write(fd, (char *)bp_ir, 512) != 512) { rp_rcte(16, -1, 0); /* RP step 16 FAILED! - message */ printf("\nRewrite of original data back to bad block failed!\n"); } rp_s17: #ifdef DEBUG if(rp_bps == 17) goto do_u_x; #endsys/pdpstand/boot.c 444 0 12 32610 5765731213 7623 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)boot.c 2.3 (2.11BSD) 1995/06/08 */ #include "../h/param.h" #include "../machine/seg.h" #include "../machine/koverlay.h" #include "../h/reboot.h" #include "saio.h" #include #undef btoc /* to save space */ #define KB * 1024L #define KISD0 ((u_short *) 0172300) #define KISD3 ((u_short *) 0172306) #define KDSD0 ((u_short *) 0172320) #undef KISA0 #define KISA0 ((u_short *) 0172340) #define KISA3 ((u_short *) 0172346) #define KDSA0 ((u_short *) 0172360) #define SEG_DATA 01 #define SEG_TEXT 02 #define SEG_OVLY 04 extern caddr_t *bootcsr; /* csr of boot controller */ extern int bootctlr; /* boot controller number */ extern int bootopts; /* boot options from previous incarnation */ extern int bootdev; /* makedev(major,unit) booted from */ extern int checkword; /* one's complements of bootopts */ extern int cputype; /* 24, 40, 44, 45, 70, or 73 */ extern bool_t ksep; /* is kernel mode currently separated */ extern bool_t sep_id; /* does the cpu support separate I/D? */ extern int ndevsw; /* number of devices in devsw[] */ extern char ADJcsr[]; /* adjustments for ROM csr addresses */ extern char *itoa(); extern char *index(); extern struct devsw devsw[]; /* device table */ extern struct iob iob[]; /* I/O descriptor table */ char module[] = "Boot"; /* this program's name (used by trap) */ bool_t overlaid = 0; u_short pdrproto[16 + NOVL] = {0}; struct exec exec; struct ovlhdr ovlhdr; unsigned btoc(); struct loadmap { int seg_type; long seg_len; }; struct loadtable { short lt_magic; struct loadmap *lt_map; }; struct loadmap load407[] = { SEG_DATA, 56 KB, 0, 0 KB }; struct loadmap load410[] = { SEG_TEXT, 48 KB, SEG_DATA, 56 KB, 0, 0 KB }; struct loadmap load411[] = { SEG_DATA, 56 KB, SEG_TEXT, 64 KB, 0, 0 KB }; struct loadmap load430[] = { SEG_TEXT, 16 KB, /* minumum, 8 KB + 1 */ SEG_OVLY, 8 KB, /* 1 */ SEG_DATA, 24 KB, SEG_OVLY, 8 KB, /* 2 */ SEG_OVLY, 8 KB, /* 3 */ SEG_OVLY, 8 KB, /* 4 */ SEG_OVLY, 8 KB, /* 5 */ SEG_OVLY, 8 KB, /* 6 */ SEG_OVLY, 8 KB, /* 7 */ SEG_OVLY, 8 KB, /* 8 */ SEG_OVLY, 8 KB, /* 9 */ SEG_OVLY, 8 KB, /* 10 */ SEG_OVLY, 8 KB, /* 11 */ SEG_OVLY, 8 KB, /* 12 */ SEG_OVLY, 8 KB, /* 13 */ SEG_OVLY, 8 KB, /* 14 */ SEG_OVLY, 8 KB, /* 15 */ 0, 0 KB }; struct loadmap load431[] = { SEG_DATA, 56 KB, /* minumum, 48 KB + 1 */ SEG_TEXT, 56 KB, SEG_OVLY, 8 KB, /* 1 */ SEG_OVLY, 8 KB, /* 2 */ SEG_OVLY, 8 KB, /* 3 */ SEG_OVLY, 8 KB, /* 4 */ SEG_OVLY, 8 KB, /* 5 */ SEG_OVLY, 8 KB, /* 6 */ SEG_OVLY, 8 KB, /* 7 */ SEG_OVLY, 8 KB, /* 8 */ SEG_OVLY, 8 KB, /* 9 */ SEG_OVLY, 8 KB, /* 10 */ SEG_OVLY, 8 KB, /* 11 */ SEG_OVLY, 8 KB, /* 12 */ SEG_OVLY, 8 KB, /* 13 */ SEG_OVLY, 8 KB, /* 14 */ SEG_OVLY, 8 KB, /* 15 */ 0, 0 KB }; struct loadtable loadtable[] = { A_MAGIC1, load407, A_MAGIC2, load410, A_MAGIC3, load411, A_MAGIC5, load430, A_MAGIC6, load431 }; main() { register int i, j, maj; int retry = 0, unit, part; caddr_t *adjcsr; struct loadtable *setup(); struct iob *file; char *cp, *defname = "unix", line[64], defdev[64]; maj = major(bootdev); if (maj >= ndevsw) _stop("bad major"); /* can't happen */ adjcsr = (caddr_t *)((short)bootcsr - ADJcsr[maj]); for (i = 0; devsw[maj].dv_csr != (caddr_t) -1; i++) { if (adjcsr == devsw[maj].dv_csr[i]) break; if (devsw[maj].dv_csr[i] == 0) { devsw[maj].dv_csr[i] = adjcsr; break; } } if (devsw[maj].dv_csr[i] == (caddr_t *) -1) _stop("no free csr slots"); bootdev &= ~(3 << 6); bootdev |= (i << 6); /* controller # to bits 6&7 */ bootctlr = i; unit = (minor(bootdev) >> 3) & 7; part = minor(bootdev) & 7; printf("\n%d%s from %s(%d,%d,%d) at 0%o\n", cputype, module, devsw[major(bootdev)].dv_name, bootctlr, unit, part, bootcsr); strcpy(defdev, devsw[major(bootdev)].dv_name); strcat(defdev, "("); strcat(defdev, itoa(bootctlr)); strcat(defdev, ","); strcat(defdev, itoa(unit)); strcat(defdev, ","); strcat(defdev, itoa(part)); strcat(defdev, ")"); /* * The machine language will have gotten the bootopts * if we're an autoboot and will pass them along. * If r2 (checkword) was the complement of bootopts, * this is an automatic reboot, otherwise do it the hard way. */ if (checkword != ~bootopts) bootopts = RB_SINGLE | RB_ASKNAME; do { if (bootopts & RB_ASKNAME) { printf(": "); gets(line); } else { strcpy(line, defdev); strcat(line, defname); printf(": %s\n", line); } if (line[0] == '\0') { strcpy(line, defdev); strcat(line, defname); printf(": %s\n", line); } /* * If a plain filename (/unix) is entered then prepend the default * device, e.g. ra(0,1,0) to the filename. */ cp = index(line, ')'); if (!cp) { bcopy(line, line + strlen(defdev), strlen(line) + 1); bcopy(defdev, line, strlen(defdev)); } i = open(line, 0); j = -1; if (i >= 0) { file = &iob[i - 3]; /* -3 for pseudo stdin/o/e */ j = checkunix(i, setup(i)); (void) close(i); } if (++retry > 2) bootopts = RB_SINGLE | RB_ASKNAME; } while (j < 0); i = file->i_ino.i_dev; bootdev = makedev(i, ((file->i_ctlr << 6) | (file->i_unit << 3) | file->i_part)); bootcsr = devsw[i].dv_csr[file->i_ctlr]; bootcsr = (caddr_t *)((short)bootcsr + ADJcsr[i]); printf("%s: bootdev=0%o bootcsr=0%o\n", module, bootdev, bootcsr); } struct loadtable * setup(io) register io; { register i; exec.a_magic = getw(io); exec.a_text = (unsigned) getw(io); exec.a_data = (unsigned) getw(io); exec.a_bss = (unsigned) getw(io); /* * Space over the remainder of the exec header. We do this * instead of seeking because the input might be a tape which * doesn't know how to seek. */ getw(io); getw(io); getw(io); getw(io); /* * If overlaid, get overlay header. */ if (exec.a_magic == A_MAGIC5 || exec.a_magic == A_MAGIC6) { overlaid++; ovlhdr.max_ovl = getw(io); for (i = 0; i < NOVL; i++) ovlhdr.ov_siz[i] = (unsigned) getw(io); } for (i = 0; i < sizeof(loadtable) / sizeof(struct loadtable); i++) if (loadtable[i].lt_magic == exec.a_magic) return(&loadtable[i]); printf("Bad magic # 0%o\n", exec.a_magic); return((struct loadtable *) NULL); } checkunix(io, lt) struct loadtable *lt; { char *segname, *toosmall = "Base too small, %dK min\n"; register int ovseg, segtype; register unsigned seglen; struct loadmap *lm = lt->lt_map; if (lt == (struct loadtable *) NULL) return(-1); /* * Check and set I & D space requirements. */ if (exec.a_magic == A_MAGIC3 || exec.a_magic == A_MAGIC6) if (!sep_id) { printf("Can't load split I&D files\n"); return(-1); } else setsep(); else if (sep_id) setnosep(); /* * Check the sizes of each segment. */ ovseg = 0; while (segtype = lm->seg_type) { switch (segtype) { case SEG_TEXT: /* * Round text size to nearest page. */ if (exec.a_magic == A_MAGIC2) seglen = ctob(stoc(ctos(btoc(exec.a_text)))); else seglen = exec.a_text; segname = "Text"; break; case SEG_DATA: seglen = exec.a_data + exec.a_bss; segname = "Data"; if (exec.a_magic == A_MAGIC1) seglen += exec.a_text; else /* * Force a complaint if the file * won't fit. It's here instead * of in the SEG_TEXT case above * because it's more likely to be * a data overflow problem. */ if (exec.a_magic == A_MAGIC2) seglen += ctob(stoc(ctos(btoc(exec.a_text)))); break; case SEG_OVLY: seglen = ovlhdr.ov_siz[ovseg]; segname = "Overlay"; ovseg++; break; default: /* * This ``cannot happen.'' */ printf("seg type botch: %d\n", segtype); return(-1); /*NOTREACHED*/ } seglen = ctob(btoc(seglen)); if (((long) seglen) > lm->seg_len) { if (segtype == SEG_OVLY) printf("%s %d over by %D bytes", segname, ovseg, lm->seg_len -((long) seglen)); else printf("%s over by %D bytes", segname, lm->seg_len -((long) seglen)); return(-1); } if (segtype == SEG_TEXT) switch (exec.a_magic) { case A_MAGIC5: if (seglen <= 8 KB) { printf(toosmall, 8); return(-1); } break; case A_MAGIC6: if (seglen <= 48 KB) { printf(toosmall, 48); return(-1); } break; default: break; } lm++; } copyunix(io, lt); setregs(lt); return(0); } copyunix(io, lt) register io; struct loadtable *lt; { int i; bool_t donedata = 0; register int addr; register unsigned seglen; off_t segoff; int segtype; int nseg, phys, ovseg; struct loadmap *lm = lt->lt_map; /* * Load the segments and set up prototype PDRs. */ nseg = 0; phys = 0; ovseg = 0; lm = lt->lt_map; while (segtype = lm++->seg_type) { segoff = (off_t) N_TXTOFF(exec); switch (segtype) { case SEG_TEXT: seglen = exec.a_text; break; case SEG_DATA: seglen = exec.a_data; /* * If this is a 0407 style object, the text * and data are loaded together. */ if (exec.a_magic != A_MAGIC1) { segoff += (off_t) exec.a_text; if (overlaid) for (i = 0; i < NOVL; i++) segoff += (off_t) ovlhdr.ov_siz[i]; } else seglen += exec.a_text; donedata++; break; case SEG_OVLY: seglen = ovlhdr.ov_siz[ovseg]; segoff += (off_t) exec.a_text; for (i = 0; i < ovseg; i++) segoff += (off_t) ovlhdr.ov_siz[i]; ovseg++; break; default: printf("copyunix: bad seg type %d\n", segtype); seglen=0; break; } if (!seglen) continue; setseg(phys); /* * ARGH! Despite (or in spite of) the earlier cautions against seeking and * tape devices here is an 'lseek' that caused problems loading split I/D * images from tape! */ if (exec.a_magic != A_MAGIC1) (void) lseek(io, segoff, 0); for (addr = 0; addr < seglen; addr += 2) mtpi(getw(io), addr); if (segtype == SEG_DATA) { clrseg(addr, exec.a_bss); seglen += exec.a_bss; } pdrproto[nseg++] = btoc(seglen); if (!donedata) seglen = ctob(stoc(ctos(btoc(seglen)))); phys += btoc(seglen); } } /* * Set the real segmentation registers. */ setregs(lt) struct loadtable *lt; { register i; register u_short *par_base, *pdr_base; bool_t donedata = 0; int phys, segtype; int nseg, ntextpgs, novlypgs, npages, pagelen; struct loadmap *lm = lt->lt_map; nseg = 0; phys = 0; ntextpgs = 0; novlypgs = 0; setseg(0); if (exec.a_magic == A_MAGIC1) return; /* * First deny access to all except I/O page. */ par_base = KISA0; pdr_base = KISD0; for (i = 0; i <(ksep ? 8 : 7); i++) { *par_base++ = 0; *pdr_base++ = NOACC; } if (ksep) { par_base = KDSA0; pdr_base = KDSD0; for (i = 0; i < 7; i++) { *par_base++ = 0; *pdr_base++ = NOACC; } } if (overlaid) { /* * We must write the prototype overlay register table. * N.B.: we assume that the table lies in the first 8k * of kernel virtual space, and the appropriate page lies * at physical 0. */ if (ksep) *KDSD0 = ((128 -1) << 8) | RW; else *KISD0 = ((128 -1) << 8) | RW; par_base = &(((u_short *) OVLY_TABLE_BASE)[0]); pdr_base = &(((u_short *) OVLY_TABLE_BASE)[1 + NOVL]); for (i = 0; i < NOVL; i++) { mtpd(0, par_base++); mtpd(NOACC, pdr_base++); } } /* * Now set all registers which should be nonzero. */ lm = lt->lt_map; while (segtype = lm++->seg_type) { if (!(npages = ctos(pdrproto[nseg]))) continue; switch (segtype) { case SEG_TEXT: /* * Text always starts at KI0; */ par_base = KISA0; pdr_base = KISD0; ntextpgs += npages; break; case SEG_DATA: if (overlaid) if (ksep) { par_base = I_DATA_PAR_BASE; pdr_base = I_DATA_PDR_BASE; } else { par_base = N_DATA_PAR_BASE; pdr_base = N_DATA_PDR_BASE; } else if (ksep) { par_base = KDSA0; pdr_base = KDSD0; } else { par_base = &KISA0[ntextpgs + novlypgs]; pdr_base = &KISD0[ntextpgs + novlypgs]; } donedata++; break; case SEG_OVLY: par_base = &(((u_short *) OVLY_TABLE_BASE)[1 + novlypgs]); pdr_base = &(((u_short *) OVLY_TABLE_BASE)[1 + NOVL + 1 + novlypgs]); novlypgs += npages; break; } for (i = 0; i < npages; i++) { pagelen = MIN(btoc((int)(8 KB)), pdrproto[nseg]); if (segtype == SEG_OVLY) { mtpd(phys, par_base); mtpd(((pagelen - 1) << 8) | RO, pdr_base); } else { *par_base = phys; if (segtype == SEG_TEXT) if (ksep) *pdr_base = ((pagelen - 1) << 8) | RO; else /* * Nonseparate kernels will * write into text page 0 * when first booted. */ if (i == 0) *pdr_base = ((pagelen - 1) << 8) | RW; else *pdr_base = ((pagelen - 1) << 8) | RO; else *pdr_base = ((pagelen - 1) << 8) | RW; } par_base++, pdr_base++; if (donedata) phys += pagelen; else phys += stoc(ctos(pagelen)); pdrproto[nseg] -= pagelen; } nseg++; } /* * Phys now contains the address of the start of * free memory. We set K[ID]6 now or systrap to * kernel mode will clobber text at 0140000. */ if (ksep) { KDSA0[6] = phys; KDSD0[6] = (stoc(1) - 1) << 8 | RW; } else { KISA0[6] = phys; KISD0[6] = (stoc(1) - 1) << 8 | RW; } if (overlaid) mtpd(phys, &(((u_short *) OVLY_TABLE_BASE)[1 + NOVL + 1 + NOVL])); } unsigned btoc(nclicks) register unsigned nclicks; { return((unsigned)(((((long) nclicks) + ((long) 63)) >> 6))); } er unsigned seglen; struct loadmap *lm = lt->lt_map; if (lt == (struct loadtable *) NULL) return(-1); /* * Checsys/pdpstand/ubmapset.c 444 0 12 724 4303075322 10426 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ubmapset.c 1.1 (2.10BSD Berkeley) 12/1/86 */ #include "../h/types.h" #define UBMAP ((physadr)0170200) extern char ubmap; ubmapset() { register unsigned int i; if (ubmap) for (i = 0; i < 62; i += 2) { UBMAP->r[i] = i << 12; UBMAP->r[i+1] = i >> 4; } } ubmapset.ox prf.olabel.cosys/pdpstand/hk.c 444 0 12 4156 5765731557 7261 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)hk.c 2.1 (2.11BSD) 1995/06/08 */ /* * RK06/07 disk driver for standalone */ #include "../h/param.h" #include "../pdpuba/hkreg.h" #include "saio.h" #define NHK 2 #define NSECT 22 #define NTRAC 3 struct hkdevice *HKcsr[NHK + 1] = { (struct hkdevice *)0177440, (struct hkdevice *)0, (struct hkdevice *)-1 }; int hk_drvtyp[NHK][8]; char hk_mntflg[NHK][8]; hkstrategy(io, func) register struct iob *io; { register unit, com; register struct hkdevice *hkaddr; daddr_t bn; int sn, cn, tn, ctlr, bae, lo16; unit = io->i_unit; ctlr = io->i_ctlr; hkaddr = HKcsr[ctlr]; if (hk_mntflg[ctlr][unit] != '1') { hk_drvtyp[ctlr][unit] = 0; hkaddr->hkcs2 = unit; hkaddr->hkcs1 = HK_SELECT|HK_GO; while ((hkaddr->hkcs1 & HK_CRDY) == 0) continue; if (hkaddr->hkcs1 & HK_CERR && hkaddr->hker & HKER_DTYE) { hk_drvtyp[ctlr][unit] = 02000; } hk_mntflg[ctlr][unit] = '1'; } bn = io->i_bn; hkaddr->hkcs2 = HKCS2_SCLR; while ((hkaddr->hkcs1 & HK_CRDY) == 0) continue; hkaddr->hkcs2 = unit; hkaddr->hkcs1 = hk_drvtyp[ctlr][unit]|HK_SELECT|HK_GO; while ((hkaddr->hkcs1 & HK_CRDY) == 0) continue; if ((hkaddr->hkds & HKDS_VV) == 0) { hkaddr->hkcs1 = hk_drvtyp[ctlr][unit]|HK_PACK|HK_GO; while ((hkaddr->hkcs1 & HK_CRDY) == 0) continue; } cn = bn/(NSECT*NTRAC); sn = bn%(NSECT*NTRAC); tn = sn/NSECT; sn = sn%NSECT; iomapadr(io->i_ma, &bae, &lo16); hkaddr->hkcyl = cn; hkaddr->hkda = (tn<<8) | sn; hkaddr->hkba = (caddr_t)lo16; hkaddr->hkwc = -(io->i_cc>>1); com = hk_drvtyp[ctlr][unit]|(bae << 8) | HK_GO; if (func == READ) com |= HK_READ; else if (func == WRITE) com |= HK_WRITE; hkaddr->hkcs1 = com; while ((hkaddr->hkcs1 & HK_CRDY) == 0) continue; if (hkaddr->hkcs1 & HK_CERR) { printf("hk%d,%d err: cy=%d tr=%d sc=%d cs2=%d er=%o\n", ctlr, unit, cn, tn, sn, hkaddr->hkcs2, hkaddr->hker); return(-1); } return(io->i_cc); } hkopen(io) struct iob *io; { return(genopen(NHK, io)); } re License Agreement * specifies the terms and conditions for redistribution. * * @(#)hk.c 2.1 (2.11BSD) 1995/06/08 */ /* * RK06/07 disk driver for standalone */ #include "../h/param.h" #include "../pdpuba/hkreg.h" #include "saio.h" #define NHK 2 #define NSECT 22 #define NTRAC 3 struct hkdevice *HKcsr[NHK + 1] = { (struct hkdevice *)0177440, (struct hkdevice *)0, (struct hkdevice sys/pdpstand/prf.c 444 0 12 5746 5764401522 7435 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)prf.c 1.3 (2.11BSD) 1995/06/04 */ #include "../machine/cons.h" #define KLADDR ((struct dldevice *)0177560) #define CTRL(x) ('x' & 037) /* * Scaled down version of C Library printf. Only %s %u %d (==%u) %o %x %D * are recognized. Used to print diagnostic information directly on * console tty. Since it is not interrupt driven, all system activities * are pretty much suspended. Printf should not be used for chit-chat. */ printf(fmt, x1) register char *fmt; unsigned x1; { register c; register unsigned int *adx; unsigned char *s; adx = &x1; loop: while ((c = *fmt++) != '%') { if (c == '\0') return; putchar(c); } c = *fmt++; if (c == 'd' || c == 'u' || c == 'o' || c == 'x') printn((long)*adx, c=='o'? 8: (c=='x'? 16:10)); else if (c == 's') { s = (unsigned char *)*adx; while (c = *s++) putchar(c); } else if (c == 'D' || c == 'O') { printn(*(long *)adx, c == 'D' ? 10 : 8); adx += (sizeof(long) / sizeof(int)) - 1; } else if (c == 'c') putchar((char *)*adx); adx++; goto loop; } /* * Print an unsigned integer in base b. */ printn(n, b) long n; register int b; { long a; if (n < 0) { /* shouldn't happen */ putchar('-'); n = -n; } if (a = n/b) printn(a, b); putchar("0123456789ABCDEF"[(int)(n%b)]); } putchar(c) register c; { register s; register unsigned timo; #ifdef notdef /* * If last char was a break or null, don't print */ if ((KLADDR->dlrbuf & 0177) == 0) return; #endif timo = 60000; /* * Try waiting for the console tty to come ready, * otherwise give up after a reasonable time. */ while ((KLADDR->dlxcsr & DLXCSR_TRDY) == 0) if (--timo == 0) break; if (c == 0) return(c); s = KLADDR->dlxcsr; KLADDR->dlxcsr = 0; KLADDR->dlxbuf = c; if (c == '\n') { putchar('\r'); putchar(0177); } putchar(0); KLADDR->dlxcsr = s; return(c); } getchar() { register c; KLADDR->dlrcsr = DL_RE; while ((KLADDR->dlrcsr & DL_RDONE) == 0) continue; c = KLADDR->dlrbuf & 0177; if (c=='\r') c = '\n'; return(c); } gets(buf) char *buf; { register char *lp, *cp; register int c; lp = buf; for (;;) { c = getchar() & 0177; switch (c) { default: if (c < ' ' || c >= 127) putchar(CTRL(G)); else { *lp++ = c; putchar(c); } break; case '\n': case '\r': putchar('\n'); c = '\n'; *lp++ = '\0'; return; case '\177': case '\b': case '#': if (lp <= buf) putchar(CTRL(G)); else { lp--; putchar('\b'); putchar(' '); putchar('\b'); } break; case CTRL(U): case '@': while (lp > buf) { lp--; putchar('\b'); putchar(' '); putchar('\b'); } break; case CTRL(R): putchar('^'); putchar('R'); putchar('\n'); for (cp = buf; cp < lp; cp++) putchar(*cp); break; } } } data) seglen = ctob(stosys/pdpstand/rk.c 444 0 12 2351 5765731657 7267 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)rk.c 2.1 (2.11BSD) 1995/06/08 */ /* * RK disk driver */ #include "../h/param.h" #include "../pdpuba/rkreg.h" #include "saio.h" #define NRK 2 struct rkdevice *RKcsr[NRK + 1] = { (struct rkdevice *)0177400, (struct rkdevice *)0, (struct rkdevice *)-1 }; rkstrategy(io, func) register struct iob *io; { register com; register struct rkdevice *rkaddr; daddr_t bn; int dn, cn, sn, bae, lo16; bn = io->i_bn; dn = io->i_unit; cn = bn/12; sn = bn%12; iomapadr(io->i_ma, &bae, &lo16); rkaddr = RKcsr[io->i_ctlr]; rkaddr->rkda = (dn<<13) | (cn<<4) | sn; rkaddr->rkba = (caddr_t)lo16; rkaddr->rkwc = -(io->i_cc>>1); com = (bae<<4)|RKCS_GO; if (func == READ) com |= RKCS_RCOM; else com |= RKCS_WCOM; rkaddr->rkcs = com; while ((rkaddr->rkcs & RKCS_RDY) == 0) continue; if (rkaddr->rkcs<0) { /* error bit */ printf("RK%d,%d err cy=%d sc=%d, er=%o, ds=%o\n", io->i_ctlr, io->i_unit, cn, sn, rkaddr->rker, rkaddr->rkds); return(-1); } return(io->i_cc); } rkopen(io) struct iob *io; { return(genopen(NRK, io)); } ed integer in base b. */ printn(n, b) long n; register int b; { long a; if (n < 0) { /* shouldn't happen */ putchar('-'); n = -n; } if (a = n/b) printn(a, b); putchar("0123456789ABCDEF"[(int)(n%b)]); } putchar(c) register c; { register s; register unsigned timsys/pdpstand/rl.c 444 0 12 14133 6007611040 7256 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)rl.c 2.4 (2.11BSD) 1995/08/01 */ /* * RL disk driver * * Modified to handle disklabels - 1995/06/15 * RL driver modified for the standalone shell. * Armando P. Stettner Digital Equipment Corp. July, 1980 */ #include "../h/param.h" #include "../pdpuba/rlreg.h" #include "saio.h" #define NRL 2 struct rldevice *RLcsr[NRL + 1] = { (struct rldevice *)0174400, (struct rldevice *)0, (struct rldevice *)-1 }; #define BLKRL1 10240 /* Number of UNIX blocks for an RL01 drive */ #define BLKRL2 20480 /* Number of UNIX blocks for an RL02 drive */ #define RLCYLSZ 10240 /* bytes per cylinder */ #define RLSECSZ 256 /* bytes per sector */ struct Rldrives { int cn[4]; /* location of heads for each drive */ int type[4]; /* # blocks on drive (RL01/02) */ int com; /* read or write command word */ int chn; /* cylinder and head number */ unsigned int bleft; /* bytes left to be transferred */ unsigned int bpart; /* number of bytes transferred */ int sn; /* sector number */ union { int w[2]; long l; } addr; /* address of memory for transfer */ } rl[NRL] = {{-1,-1,-1,-1,-1,-1,-1,-1}, {-1,-1,-1,-1,-1,-1,-1,-1}}; /* initialize cn[] and type[] */ rlstrategy(io, func) register struct iob *io; int func; { int drive = io->i_unit; int dif; int head; int bae, lo16; int ctlr = io->i_ctlr; register struct rldevice *rladdr; register struct Rldrives *rlp; rladdr = RLcsr[ctlr]; rlp = &rl[ctlr]; iomapadr(io->i_ma, &bae, &lo16); rlp->chn = io->i_bn/20; rlp->sn = (io->i_bn%20) << 1; rlp->bleft = io->i_cc; rlp->addr.w[0] = bae; rlp->addr.w[1] = lo16; rlp->com = (drive << 8); if (func == READ) rlp->com |= RL_RCOM; else rlp->com |= RL_WCOM; reading: /* * One has to seek an RL head, relativily. */ dif =(rlp->cn[drive] >> 1) - (rlp->chn >>1); head = (rlp->chn & 1) << 4; if (dif < 0) rladdr->rlda = (-dif <<7) | RLDA_SEEKHI | head; else rladdr->rlda = (dif << 7) | RLDA_SEEKLO | head; rladdr->rlcs = (drive << 8) | RL_SEEK; rlp->cn[drive] = rlp->chn; /* keep current, our notion of where the heads are */ if (rlp->bleft < (rlp->bpart = RLCYLSZ - (rl->sn * RLSECSZ))) rlp->bpart = rlp->bleft; while ((rladdr->rlcs&RL_CRDY) == 0) continue; rladdr->rlda = (rlp->chn << 6) | rlp->sn; rladdr->rlba = (caddr_t) rlp->addr.w[1]; rladdr->rlmp = -(rlp->bpart >> 1); rladdr->rlcs = rlp->com | rlp->addr.w[0] << 4; while ((rladdr->rlcs & RL_CRDY) == 0) /* wait for completion */ continue; if (rladdr->rlcs < 0) { /* check error bit */ if (rladdr->rlcs & 040000) { /* Drive error */ /* * get status from drive */ rladdr->rlda = RLDA_GS; rladdr->rlcs = (drive << 8) | RL_GETSTATUS; while ((rladdr->rlcs & RL_CRDY) == 0) /* wait for controller */ continue; } printf("rl%d,%d err cy=%d, hd=%d, sc=%d, rlcs=%o, rlmp=%o\n", ctlr, drive, rlp->chn>>01, rlp->chn&01, rlp->sn, rladdr->rlcs, rladdr->rlmp); return(-1); } /* * Determine if there is more to read to satisfy this request. * This is to compensate for the lack of spiraling reads. */ if ((rlp->bleft -= rlp->bpart) > 0) { rlp->addr.l += rlp->bpart; rlp->sn = 0; rlp->chn++; goto reading; /* read some more */ } return(io->i_cc); } rlopen(io) register struct iob *io; { register struct disklabel *lp = &io->i_label; register int part = io->i_part; if (io->i_unit > 3) return(-1); if (genopen(NRL, io) < 0) return(-1); rlgsts(io); /* get status and head position */ if (devlabel(io, READLABEL) < 0) return(-1); io->i_boff = lp->d_partitions[part].p_offset; return(0); } /* * We must determine what type of drive we are talking to in order * to determine how many blocks are on the device. The rl.type[] * array has been initialized with -1's so that we may test first * contact with a particular drive and do this determination only once. * * RL02 GET STATUS BAND-AID - Fred Canter 10/14/80 * * For some unknown reason the RL02 (seems to be * only drive 1) does not return a valid drive status * the first time that a GET STATUS request is issued * for the drive, in fact it can take up to three or more * GET STATUS requests to obtain the correct status. * In order to overcome this "HACK" the driver has been * modified to issue a GET STATUS request, validate the * drive status returned, and then use it to determine the * drive type. If a valid status is not returned after eight * attempts, then an error message is printed. */ rlgsts(io) struct iob *io; { int ctr; int drive = io->i_unit; int ctlr = io->i_ctlr; register struct Rldrives *rlp = &rl[ctlr]; register struct rldevice *rladdr = RLcsr[ctlr]; if (rlp->type[drive] < 0) { ctr = 0; do { /* load this register; what a dumb controller */ rladdr->rlda = RLDA_RESET|RLDA_GS; /* set up csr */ rladdr->rlcs = (drive << 8) | RL_GETSTATUS; while ((rladdr->rlcs & RL_CRDY) == 0) /* wait for it */ continue; } while (((rladdr->rlmp & 0177477) != 035) && (++ctr < 8)); if (ctr >= 8) printf("\nCan't get rl%d,%d sts\n", ctlr, drive); if (rladdr->rlmp & RLMP_DTYP) rlp->type[drive] = BLKRL2; /* drive is RL02 */ else rlp->type[drive] = BLKRL1; /* drive RL01 */ /* * When device is first touched, find out where the heads are. */ rladdr->rlcs = (drive << 8) | RL_RHDR; while ((rladdr->rlcs&RL_CRDY) == 0) continue; rlp->cn[drive] = ((rladdr->rlmp) >> 6) & 01777; } return; } /* * This generates a default label. 'rlopen' has already been called so * we can use the 'types' field as the number of sectors on the device. */ rllabel(io) register struct iob *io; { register struct disklabel *lp = &io->i_label; daddr_t nblks = rl[io->i_ctlr].type[io->i_unit]; lp->d_type = DTYPE_DEC; lp->d_partitions[0].p_size = nblks; lp->d_nsectors = 20; /* sectors per track */ lp->d_ntracks = 2; /* tracks per cylinder */ lp->d_secpercyl = 40; /* sectors per cylinder */ lp->d_ncylinders = nblks / (lp->d_nsectors * lp->d_ntracks); lp->d_secperunit = nblks; return(0); } ion */ continue; if (rladdr->rlcs < 0) { /* check error bit */ if (rladdr->rlcs & 040000) { /* Drive error */ /* * get status from drive */ rladdr->rlda = RLDA_GS; rladdr->rlcs = (drive << 8) | RL_GETSTATUS; while ((rladdr->rlcs & RL_CRDY) == 0) /* wait for controller */ continue; } printf("rl%d,%d err cy=%d, hd=%d, sc=%d, rlcs=%o, rlmp=%o\n", ctlr, drive, rlp->chn>>01, rlp->chsys/pdpstand/OLD/ 755 0 12 0 4304043676 7022 sys/pdpstand/OLD/copy.c 640 206 12 1212 4102233653 10255 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)bcopy.c 1.1 (2.10BSD Berkeley) 7/25/87 */ #define BLKSIZE 1024 char module[] = "copy"; /* module name -- used by trap */ char buffer[BLKSIZE]; main() { int c, o, i; char buf[50]; printf("%s\n",module); do { printf("Infile: "); gets(buf); i = open(buf, 0); } while (i <= 0); do { printf("Outfile: "); gets(buf); o = open(buf, 1); } while (o <= 0); while ((c = read(i, buffer, BLKSIZE)) > 0) write(o, buffer, c); exit(0); } ime that a GET STATUS request is issued * for the drive, in fact it can take up to three or more * GET STATUS requests to obtain the correct status. * In order to overcome this "HACK" the driver has been * modified to issue a GET STATUS request, validate the * drive status returned, and then use it to determine the * drive type. If a valid status is not returned aftsys/pdpstand/OLD/bcopy.c 640 206 12 1227 4102233653 10425 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)bcopy.c 1.1 (2.10BSD Berkeley) 7/25/87 */ #define BLKSIZE 1024 char module[] = "bcopy"; /* module name -- used by trap */ char buffer[BLKSIZE]; main() { int c, o, i; char buf[50]; printf("%s\n",module); do { printf("Infile: "); gets(buf); i = open(buf, 0); } while (i <= 0); do { printf("Outfile: "); gets(buf); o = open(buf, 1); } while (o <= 0); if ((c = read(i, buffer, BLKSIZE)) > 0) write(o, buffer, c > 512 ? 512 : c); exit(0); } T STATUS request is issued * for the drive, in fact it can take up to three or more * GET STATUS requests to obtain the correct status. * In order to overcome this "HACK" the driver has been * modified to issue a GET STATUS request, validate the * drive status returned, and then use it to determine the * drive type. If a valid status is not returned aftsys/pdpstand/OLD/cat.c 640 206 12 753 4001144244 10036 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)cat.c 1.1 (2.10BSD Berkeley) 12/1/86 */ char module[] = "cat"; /* module name -- used by trap */ main() { int c, i; char buf[50]; printf("%s\n",module); do { printf("File: "); gets(buf); i = open(buf, 0); } while (i <= 0); while ((c = getc(i)) > 0) putchar(c); exit(0); } sys/pdpstand/sys.c 644 0 12 35376 6016776777 7532 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)sys.c 2.3 (2.11BSD) 1995/08/23 */ #include "../h/param.h" #include "../h/dir.h" #include "../machine/seg.h" #include "../machine/iopage.h" #include "../machine/psl.h" #include "../machine/machparam.h" #include "saio.h" #undef KISA0 #define KISA0 ((u_short *) 0172340) #define KDSA0 ((u_short *) 0172360) extern struct devsw devsw[]; extern int ssr3copy, bootctlr; extern long atol(); /* * These buffers are only used in mapping inode blocks to disk sectors, * no good reason to make them global. * * The strange initialization is due to the fact that the 0'th case is * not legal since it would be used for quadruple indirect files. The * use of the array 'b' is: * * b[0] - not allocated, saving 1kb of space * b[1] - triple indirect block * b[2] - double indirect block * b[3] - single indirect block * * In the 1kb filesystem double indirect files can be up to ~65 megabytes * (the old 512 byte filesystem double indirect files were up to ~8mb). */ static char tplind[DEV_BSIZE], dblind[DEV_BSIZE], sngind[DEV_BSIZE]; static char *b[4] = { NULL, /* j = 0 */ tplind, /* j = 1 */ dblind, /* j = 2 */ sngind /* j = 3 */ }; static daddr_t blknos[4]; #define NFILES 4 struct iob iob[NFILES]; ino_t dlook(); struct direct *readdir(); struct dirstuff { long loc; struct iob *io; }; /* * wfj - mods to trap to explicitly detail why we stopped */ static openi(n, io) register ino_t n; register struct iob *io; { register struct dinode *dp; daddr_t tdp; io->i_offset = 0; tdp = itod(n); io->i_bn = fsbtodb(tdp) + io->i_boff; io->i_cc = DEV_BSIZE; io->i_ma = io->i_buf; devread(io); dp = (struct dinode *)io->i_buf; dp = &dp[itoo(n)]; io->i_ino.i_number = n; io->i_ino.i_mode = dp->di_mode; io->i_ino.i_size = dp->di_size; bcopy(dp->di_addr, io->i_ino.i_addr, NADDR * sizeof (daddr_t)); } static find(path, file) register char *path; struct iob *file; { register char *q; register char c; ino_t n; if (path==NULL || *path=='\0') { printf("null path\n"); return(0); } openi((ino_t) ROOTINO, file); while (*path) { while (*path == '/') path++; q = path; while (*q != '/' && *q != '\0') q++; c = *q; *q = '\0'; if (q == path) path = "." ; /* "/" means "/." */ if ((n=dlook(path, file))!=0) { if (c=='\0') break; openi(n, file); *q = c; path = q; continue; } else { printf("%s not found\n", path); return(0); } /*NOTREACHED*/ } return(n); } static daddr_t sbmap(io, bn) register struct iob *io; daddr_t bn; { register i; register struct inode *ip; int j, sh; daddr_t nb, *bap; ip = &io->i_ino; if (bn < 0) { printf("bn < 0\n"); return((daddr_t)0); } /* * blocks 0..NADDR-4 are direct blocks */ if (bn < NADDR-3) { i = bn; nb = ip->i_addr[i]; return(nb); } /* * addresses NADDR-3, NADDR-2, and NADDR-1 * have single, double, triple indirect blocks. * the first step is to determine * how many levels of indirection. */ sh = 0; nb = 1; bn -= NADDR-3; for (j=3; j>0; j--) { sh += NSHIFT; nb <<= NSHIFT; if (bn < nb) break; bn -= nb; } if (j == 0) { printf("bn ovf %D\n", bn); return((daddr_t)0); } /* * At this point: * * j NADDR-j meaning * --- ------- ------- * 0 7 illegal - tossed out in the 'if' above * 1 6 triple indirect block number * 2 5 double indirect block number * 3 4 single indirect block number */ /* * fetch the address from the inode */ nb = ip->i_addr[NADDR-j]; if (nb == 0) goto bnvoid; /* * fetch through the indirect blocks */ for (; j<=3; j++) { if (blknos[j] != nb) { io->i_bn = fsbtodb(nb) + io->i_boff; io->i_ma = b[j]; io->i_cc = DEV_BSIZE; devread(io); blknos[j] = nb; } bap = (daddr_t *)b[j]; sh -= NSHIFT; i = (bn>>sh) & NMASK; nb = bap[i]; if (nb == 0) { bnvoid: printf("bn void %D\n", bn); return((daddr_t)0); } } return(nb); } static ino_t dlook(s, io) char *s; register struct iob *io; { register struct direct *dp; register struct inode *ip; struct dirstuff dirp; int len; if (s==NULL || *s=='\0') return(0); ip = &io->i_ino; if ((ip->i_mode&IFMT) != IFDIR || !ip->i_size) { printf("%s: !directory,mode %o size: %D ip %o\n", s, ip->i_mode, ip->i_size, ip); return(0); } len = strlen(s); dirp.loc = 0; dirp.io = io; for (dp = readdir(&dirp); dp; dp = readdir(&dirp)) { if (dp->d_ino == 0) continue; if (dp->d_namlen == len && !strcmp(s,dp->d_name)) return(dp->d_ino); } return(0); } struct direct * readdir(dirp) register struct dirstuff *dirp; { register struct direct *dp; register struct iob *io; daddr_t lbn, d, off; io = dirp->io; for (;;) { if (dirp->loc >= io->i_ino.i_size) return(NULL); off = blkoff(dirp->loc); if (off == 0) { lbn = lblkno(dirp->loc); d = sbmap(io, lbn); if (d == 0) return(NULL); io->i_bn = fsbtodb(d) + io->i_boff; io->i_ma = io->i_buf; io->i_cc = DEV_BSIZE; devread(io); } dp = (struct direct *)(io->i_buf + off); dirp->loc += dp->d_reclen; if (dp->d_ino == 0) continue; return(dp); } } /* * Modified to call the tape driver's seek routine. This only works when * the record size is DEV_BSIZE (1kb). */ lseek(fdesc, addr, ptr) register int fdesc; off_t addr; int ptr; { off_t new; register struct iob *io; if (ptr != 0) { printf("lseek\n"); return(-1); } fdesc -= 3; if (fdesc < 0 || fdesc >= NFILES || ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) return(-1); new = addr / DEV_BSIZE; if (io->i_flgs & F_TAPE) { #ifdef debug printf("seek: new=%D i_bn=%D\n", new, io->i_bn); #endif /* * Subtract 1 to acccount for the block currently in the buffer - the * tape is currently positioned at the next record. Need to convert the * block number from 512 byte to 1024 byte records (undo the fsbtodb). */ devseek(io, (int)(new - dbtofsb(io->i_bn) - 1)); } io->i_offset = addr; io->i_bn = fsbtodb(new) + io->i_boff; io->i_cc = 0; return(0); } /* if tape mark encountered, set flag (in driver) */ int tapemark; getc(fdesc) int fdesc; { register struct iob *io; register unsigned char *p; register int c; int off; daddr_t tbn; if (fdesc >= 0 && fdesc <= 2) return(getchar()); fdesc -= 3; if (fdesc < 0 || fdesc >= NFILES || ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) return(-1); if (io->i_cc <= 0) { io->i_bn = fsbtodb(io->i_offset/(off_t)DEV_BSIZE); if (io->i_flgs&F_FILE) { tbn = sbmap(io, dbtofsb(io->i_bn)); io->i_bn = fsbtodb(tbn) + io->i_boff; } io->i_ma = io->i_buf; io->i_cc = DEV_BSIZE; #ifdef DEBUG printf("getc: fetch block %D, dev = %d\n", io->i_bn, io->i_ino.i_dev); #endif tapemark = 0; devread(io); off = io->i_offset % (off_t)DEV_BSIZE; if (io->i_flgs&F_FILE) { if (io->i_offset+(DEV_BSIZE-off) >= io->i_ino.i_size) io->i_cc = io->i_ino.i_size - io->i_offset + off; } if (tapemark) return(-1); io->i_cc -= off; if (io->i_cc <= 0) return(-1); io->i_ma = &io->i_buf[off]; } io->i_cc--; io->i_offset++; c = (int)(*(unsigned char *)io->i_ma++); return(c); } getw(fdesc) int fdesc; { register w, i; register unsigned char *cp; int val; for (i = 0, val = 0, cp = (unsigned char *)&val; i < sizeof(val); i++) { w = getc(fdesc); if (w < 0) { if (i == 0) return(-1); else return(val); } *cp++ = w; } return(val); } read(fdesc, buf, count) register int fdesc; char *buf; int count; { register i; register struct iob *file; if (fdesc >= 0 & fdesc <= 2) { i = count; do { *buf = getchar(); } while (--i && *buf++ != '\n'); return(count - i); } fdesc -= 3; if (fdesc < 0 || fdesc >= NFILES || ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) return(-1); if ((file->i_flgs&F_READ) == 0) return(-1); if ((file->i_flgs&F_FILE) == 0) { file->i_cc = count; file->i_ma = buf; i = devread(file); file->i_bn += (count / NBPG); return(i); } else { if (file->i_offset+count > file->i_ino.i_size) count = file->i_ino.i_size - file->i_offset; if ((i = count) <= 0) return(0); do { *buf++ = getc(fdesc+3); } while (--i); return(count); } } write(fdesc, buf, count) register int fdesc; char *buf; int count; { register i; register struct iob *file; if (fdesc >= 0 && fdesc <= 2) { i = count; while (i--) putchar(*buf++); return(count); } fdesc -= 3; if (fdesc < 0 || fdesc >= NFILES || ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) return(-1); if ((file->i_flgs&F_WRITE) == 0) return(-1); file->i_cc = count; file->i_ma = buf; i = devwrite(file); file->i_bn += (count / NBPG); return(i); } open(str, how) char *str; int how; { register char *cp; int i, i2, i3; register struct iob *file; register struct devsw *dp; int fdesc; for (fdesc = 0; fdesc < NFILES; fdesc++) if (iob[fdesc].i_flgs == 0) goto gotfile; _stop("No file slots"); gotfile: (file = &iob[fdesc])->i_flgs |= F_ALLOC; for (cp = str; *cp && *cp != '('; cp++) ; if (*cp != '(') { printf("Bad device\n"); file->i_flgs = 0; return(-1); } *cp = '\0'; for (dp = devsw; dp->dv_name; dp++) { if (strcmp(str, dp->dv_name) == 0) goto gotdev; } printf("Unknown device\n"); file->i_flgs = 0; return(-1); gotdev: /* * The parse is a bit lengthier and complex now. The syntax is now: * * xx(ctlr, unit, partition)filename * or * xx(unit, partition)filename * * * The controller number must be less than 4. NOTE: many drivers * limit the number of controllers to 1 or 2. If the controller is not * specified it defaults to 0. * * The unit number must be less than 8. * * The partition number is also used to specify the tapefile to be loaded. * When loading a tapefile the 'filename' must not be specified. The partition * number must be less than 8. This means that the number of standalone * programs is limited to 7. */ *cp++ = '('; file->i_ino.i_dev = dp-devsw; for (i = 0; *cp >= '0' && *cp <= '9'; cp++) { i *= 10; i += (*cp - '0'); } if (*cp++ != ',') { badoff: printf("Bad offset or ctlr, unit, part out of bounds\n"); file->i_flgs = 0; return(-1); } for (i2 = 0; *cp >= '0' && *cp <= '9'; cp++) { i2 *= 10; i2 += (*cp - '0'); } /* * If we encounter a ')' now it means we have the two arg form 'ra(x,y)'. If * a ',' is seen then we have the three arg form 'xp(x,y,z)'. If neither a * ',' or ')' it is an error. */ if (*cp == ')') { file->i_ctlr = bootctlr; file->i_unit = i; file->i_part = i2; cp++; /* skip ) */ } else if (*cp == ',') { for (i3 = 0, cp++; *cp >= '0' && *cp <= '9'; cp++) { i3 *= 10; i3 += (*cp - '0'); } file->i_ctlr = i; file->i_unit = i2; file->i_part = i3; if (*cp++ != ')') goto badoff; } else goto badoff; if (file->i_ctlr > 3 || file->i_unit > 7 || file->i_part > 7) goto badoff; if (devopen(file) < 0) { file->i_flgs = 0; return(-1); } if (*cp == '\0') { file->i_flgs |= how+1; goto comret; } if ((i = find(cp, file)) == 0) { file->i_flgs = 0; return(-1); } if (how != 0) { printf("Can't write files\n"); file->i_flgs = 0; return(-1); } openi(i, file); file->i_flgs |= F_FILE | (how+1); comret: file->i_offset = 0; file->i_cc = 0; file->i_bn = 0; return(fdesc+3); } close(fdesc) register int fdesc; { register struct iob *file; fdesc -= 3; if (fdesc < 0 || fdesc >= NFILES || ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) return(-1); if ((file->i_flgs&F_FILE) == 0) devclose(file); file->i_flgs = 0; return(0); } exit() { _stop("Exit called"); } _stop(s) char *s; { printf("%s\n", s); _rtt(); } extern char module[]; trap(r1, r0, nps, pc, ps) int nps, r1, r0, pc, ps; { printf("Trap in %s,", module); switch (nps&7) { case 0: printf("bus error"); break; case 1: printf("illegal instruction"); break; case 2: printf("bpt/trace"); break; case 3: printf("iot"); break; case 4: printf("power fail"); break; case 5: printf("emt"); break; case 6: printf("sys/trap"); break; default: printf("weird"); } printf(" at loc %o\n", pc); printf("registers: r0=%o, r1=%o, ps=%o, nps=%o\n", r0, r1, ps, nps); for (;;) ; } genopen(maxctlr, io) int maxctlr; struct iob *io; { register struct devsw *dp = &devsw[io->i_ino.i_dev]; register char *cp; register int ctlr = io->i_ctlr; int csr; char line[64]; if (ctlr >= maxctlr) return(-1); if (dp->dv_csr[ctlr]) return(0); printf("%s%d csr[0%o]: ", dp->dv_name, ctlr, dp->dv_csr[ctlr]); gets(line); for (csr = 0, cp = line; *cp >= '0' && *cp <= '7'; cp++) csr = csr * 8 + (*cp - '0'); if (csr == 0) return(-1); dp->dv_csr[ctlr] = (caddr_t *)csr; /* * Tapes don't need this. Disk drivers which support labels do not need * this either but disk drivers which do not support labels _do_ need this. * Doing it here is safe for everyone because label capable drivers will * load i_boff from the label _after_ calling this routine. */ io->i_boff = 0; return(0); } delay(i) int i; { while (i) i--; } char * ltoa(l) u_long l; { static char x[12]; register char *cp = x + sizeof (x); do { *--cp = (l % 10) + '0'; l /= 10; } while (l); return(cp); } char * itoa(i) register int i; { static char x[8]; register char *cp = x + sizeof (x); do { *--cp = (i % 10) + '0'; i /= 10; } while (i); return(cp); } /* * Convert a 16 bit (virtual) address into a 18 bit (UNIBUS) address. * The address extension bits (bits 16, 17) are placed into 'bae' while * the lower order bits (bits 0 - 15) are placed in 'lo16'. * * This routine was primarily created to handle split I/D kernel mode * utilities. Boot itself must run non split I/D and runs in user mode. * A side effect of this routine is that Boot no longer must be loaded at * a 64Kb boundary. * * Everything (Boot and standalone utilities) must still run in the low * 248kb of memory which is mapped by the UNIBUS mapping registers. */ iomapadr(buf, bae, lo16) memaddr buf; u_short *bae, *lo16; { u_long uadr; int curmode = *PS & PSL_CURMOD, segno; u_int nb, ts; extern char module[]; if (curmode == 0) { /* Kernel mode - we're in a utility */ /* * For split I/D we need to emulate the kernel's method of looking at * the segment registers and calculating the physical address. Whew, forgot * that ;-) */ nb = ((int)buf >> 6) & 01777; segno = nb >> 7; if (ssr3copy & 4) ts = KDSA0[segno]; /* kernel I/D is on */ else ts = KISA0[segno]; /* kernel I/D is off */ ts += (nb & 0177); uadr = ((u_long)ts << 6) + (buf & 077); } else if (curmode == PSL_CURMOD) { /* User mode - we're in Boot */ uadr = UISA[0]; /* No I/D for Boot! */ uadr <<= 6; /* clicks to bytes */ uadr += buf; } else _stop("Bad PSL mode"); *bae = (uadr >> 16) & 3; /* 18 bit mode */ *lo16 = uadr & 0xffff; } *dp; register struct iob *io; daddr_t lbn, d, off; io = dirp->io; for (;;) { if (dirp->loc >= io->i_ino.i_size) return(NULL); off = blkoff(dirp->loc); if (off == 0) { lbn = lblkno(dirp->loc); d = sbmap(io, lbn); if (d == 0) returnsys/pdpstand/tm.c 444 0 12 4657 5765731755 7305 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)tm.c 2.1 (2.11BSD) 1995/06/08 */ /* * TM11 - TU10/TE10/TS03 standalone tape driver */ #include "../h/param.h" #include "../pdpuba/tmreg.h" #include "saio.h" #define NTM 2 struct tmdevice *TMcsr[NTM + 1] = { (struct tmdevice *)0172520, (struct tmdevice *)0, (struct tmdevice *)-1 }; extern int tapemark; /* flag to indicate tapemark has been encountered (see sys.c) */ /* * Bits in device code. */ #define T_NOREWIND 04 /* not used in stand alone driver */ #define TMDENS(dev) (((dev) & 030) >> 3) tmclose(io) struct iob *io; { tmstrategy(io, TM_REW); } tmopen(io) register struct iob *io; { register skip; if (genopen(NTM, io) < 0) return(-1); io->i_flgs |= F_TAPE; tmstrategy(io, TM_REW); skip = io->i_part; while (skip--) { io->i_cc = 0; while (tmstrategy(io, TM_SFORW)) continue; } return(0); } u_short tmdens[4] = { TM_D800, TM_D1600, TM_D6250, TM_D800 }; tmstrategy(io, func) register struct iob *io; { register int com, unit = io->i_unit; register struct tmdevice *tmaddr; int errcnt = 0, ctlr = io->i_ctlr, bae, lo16; tmaddr = TMcsr[ctlr]; retry: while ((tmaddr->tmcs&TM_CUR) == 0) continue; while ((tmaddr->tmer&TMER_TUR) == 0) continue; while ((tmaddr->tmer&TMER_SDWN) != 0) continue; iomapadr(io->i_ma, &bae, &lo16); com = (unit<<8)|(bae<<4) | tmdens[TMDENS(unit)]; tmaddr->tmbc = -io->i_cc; tmaddr->tmba = (caddr_t)lo16; if (func == READ) tmaddr->tmcs = com | TM_RCOM | TM_GO; else if (func == WRITE) tmaddr->tmcs = com | TM_WCOM | TM_GO; else if (func == TM_SREV) { tmaddr->tmbc = -1; tmaddr->tmcs = com | TM_SREV | TM_GO; return(0); } else tmaddr->tmcs = com | func | TM_GO; while ((tmaddr->tmcs&TM_CUR) == 0) continue; if (tmaddr->tmer&TMER_EOF) { tapemark=1; return(0); } if (tmaddr->tmer & TM_ERR) { if (errcnt == 0) printf("\ntm%d,%d err: er=%o cs=%o", ctlr, unit, tmaddr->tmer, tmaddr->tmcs); if (errcnt++ == 10) { printf("\n(FATAL ERROR)\n"); return(-1); } tmstrategy(io, TM_SREV); goto retry; } return(io->i_cc+tmaddr->tmbc); } tmseek(io, space) register struct iob *io; int space; { int fnc; if (space < 0) { fnc = TM_SREV; space = -space; } else fnc = TM_SFORW; while (space--) tmstrategy(io, fnc); return(0); } (nb & 0177); uadr = ((u_long)ts << 6) + (buf & 077); } else if (curmode == sys/pdpstand/ts.c 444 0 12 7320 5765732014 7266 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ts.c 2.2 (2.11BSD) 1995/06/08 */ /* * Stand-alone TS11/TU80/TS05/TK25 magtape driver. */ #include "../h/param.h" #include "../pdpuba/tsreg.h" #include "saio.h" extern int tapemark; /* flag to indicate tapemark encountered (see sys.c as to how its used) */ #define NTS 2 struct tsdevice *TScsr[NTS + 1] = { (struct tsdevice *)0172520, (struct tsdevice *)0, (struct tsdevice *)-1 }; caddr_t tsptr[NTS]; struct ts_char chrbuf[NTS]; /* characteristics buffer */ struct ts_sts mesbuf[NTS]; /* message buffer */ struct ts_cmd *combuf[NTS]; /* command packet buffer */ char softspace[(NTS * sizeof(struct ts_cmd)) + 3]; /* bit definitions for Command mode field during read command */ #define TS_RPREV 0400 /* read previous (reverse) */ tsopen(io) register struct iob *io; { int skip, bae, lo16; register struct tsdevice *tsaddr; register struct ts_char *chrb; struct ts_cmd *cmb; int ctlr = io->i_ctlr; char *cp; if (genopen(NTS, io) < 0) return(-1); io->i_flgs |= F_TAPE; tsaddr = TScsr[ctlr]; /* combuf must be aligned on a mod 4 byte boundary */ cp = (char *)((u_short)softspace + 3 & ~3); cp += (ctlr * sizeof (struct ts_cmd)); cmb = combuf[ctlr] = (struct ts_cmd *)cp; iomapadr(cmb, &bae, &lo16); tsptr[ctlr] = (caddr_t)(lo16 | bae); cmb->c_cmd = (TS_ACK|TS_CVC|TS_INIT); tsaddr->tsdb = (u_short) tsptr[ctlr]; while ((tsaddr->tssr & TS_SSR) == 0) continue; chrb = &chrbuf[ctlr]; iomapadr(&mesbuf, &bae, &lo16); chrb->char_bptr = lo16; chrb->char_bae = bae; chrb->char_size = 016; chrb->char_mode = 0; cmb->c_cmd = (TS_ACK|TS_CVC|TS_SETCHR); iomapadr(&chrbuf, &bae, &lo16); cmb->c_loba = lo16; cmb->c_hiba = bae; cmb->c_size = 010; tsaddr->tsdb = (u_short) tsptr[ctlr]; while ((tsaddr->tssr & TS_SSR) == 0) continue; tsstrategy(io, TS_REW); skip = io->i_part; while (skip--) { io->i_cc = 0; while (tsstrategy(io, TS_SFORWF)) continue; } return(0); } tsclose(io) struct iob *io; { tsstrategy(io, TS_REW); } tsstrategy(io, func) register struct iob *io; { register int ctlr = io->i_ctlr; int errcnt, unit = io->i_unit, bae, lo16; register struct tsdevice *tsaddr = TScsr[ctlr]; errcnt = 0; iomapadr(io->i_ma, &bae, &lo16); combuf[ctlr]->c_loba = lo16; combuf[ctlr]->c_hiba = bae; combuf[ctlr]->c_size = io->i_cc; if (func == TS_SFORW || func == TS_SFORWF || func == TS_SREV || func == TS_SREVF) combuf[ctlr]->c_repcnt = 1; if (func == READ) combuf[ctlr]->c_cmd = TS_ACK|TS_RCOM; else if (func == WRITE) combuf[ctlr]->c_cmd = TS_ACK|TS_WCOM; else combuf[ctlr]->c_cmd = TS_ACK|func; tsaddr->tsdb = (u_short) tsptr[ctlr]; retry: while ((tsaddr->tssr & TS_SSR) == 0) continue; if (mesbuf[ctlr].s_xs0 & TS_TMK) { tapemark = 1; return(0); } if (tsaddr->tssr & TS_SC) { if (errcnt == 0) printf("\nts%d,%d err sr=%o xs0=%o xs1=%o xs2=%o xs3=%o", ctlr, unit, tsaddr->tssr, mesbuf[ctlr].s_xs0, mesbuf[ctlr].s_xs1, mesbuf[ctlr].s_xs2, mesbuf[ctlr].s_xs3); if (errcnt++ == 10) { printf("\n(FATAL ERROR)\n"); return(-1); } if (func == READ) combuf[ctlr]->c_cmd = (TS_ACK|TS_RPREV|TS_RCOM); else if (func == WRITE) combuf[ctlr]->c_cmd = (TS_ACK|TS_RETRY|TS_WCOM); else { putchar('\n'); return(-1); } tsaddr->tsdb = (u_short) tsptr[ctlr]; goto retry; } return (io->i_cc+mesbuf[ctlr].s_rbpcr); } tsseek(io, space) register struct iob *io; int space; { int fnc; if (space < 0) { fnc = TS_SREV; space = -space; } else fnc = TS_SFORW; while (space--) { io->i_cc = 0; tsstrategy(io, fnc); } return(0); } (2.11BSD) 1995/06/08 */ /* * Stand-alone TS11/TU80/TS05/TK25 magtape driver. */ #include "../h/param.h" #include "../pdpuba/tsreg.h" #include "saio.h" extern int tapemark; /* flag to indicate tapemark encountered (see sys.c as to how its used) */ #define NTS 2 struct tsdevice *TScsr[NTS +sys/pdpstand/xp.c 644 0 0 15721 6007611160 7256 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)xp.c 2.2 (2.11BSD) 1995/08/01 */ /* * SMD disk driver */ #include "../h/param.h" #include "../pdpuba/hpreg.h" #include "../machine/iopage.h" #include "saio.h" #define NXP 2 struct hpdevice *XPcsr[NXP + 1] = { (struct hpdevice *)0176700, (struct hpdevice *)0, (struct hpdevice *)-1 }; static char xpinit[NXP][8]; /* XXX */ xpopen(io) register struct iob *io; { register struct disklabel *lp = &io->i_label; register struct hpdevice *xpaddr; int dummy; if (genopen(NXP, io) < 0) return(-1); /* * If this is the first access for the drive check to see if it is * present. If the drive is present then read the label. */ if (xpinit[io->i_ctlr][io->i_unit] == 0) { xpaddr = XPcsr[io->i_ctlr]; xpaddr->hpcs1.w = HP_NOP; xpaddr->hpcs2.w = io->i_unit; xpaddr->hpcs1.w = HP_GO; delay(6000); dummy = xpaddr->hpds; if (xpaddr->hpcs2.w & HPCS2_NED) { xpaddr->hpcs2.w = HPCS2_CLR; return(-1); } if (devlabel(io, READLABEL) == -1) return(-1); xpinit[io->i_ctlr][io->i_unit] = 1; } io->i_boff = lp->d_partitions[io->i_part].p_offset; return(0); } xpclose(io) struct iob *io; { xpinit[io->i_ctlr][io->i_unit] = 0; return(0); } xpstrategy(io, func) register struct iob *io; { int i; daddr_t bn; int sn, cn, tn, bae, lo16; register struct hpdevice *xpaddr = XPcsr[io->i_ctlr]; register struct disklabel *lp = &io->i_label; bn = io->i_bn; xpaddr->hpcs2.w = io->i_unit; if ((xpaddr->hpds & HPDS_VV) == 0) { xpaddr->hpcs1.c[0] = HP_PRESET|HP_GO; xpaddr->hpof = HPOF_FMT22; } cn = bn / lp->d_secpercyl; sn = bn % lp->d_secpercyl; tn = sn / lp->d_nsectors; sn = sn % lp->d_nsectors; iomapadr(io->i_ma, &bae, &lo16); xpaddr->hpdc = cn; xpaddr->hpda = (tn << 8) + sn; xpaddr->hpba = (caddr_t)lo16; xpaddr->hpwc = -(io->i_cc>>1); i = (bae << 8) | HP_GO; if (func == READ) i |= HP_RCOM; else if (func == WRITE) i |= HP_WCOM; xpaddr->hpcs1.w = i; while ((xpaddr->hpcs1.w & HP_RDY) == 0) continue; if (xpaddr->hpcs1.w & HP_TRE) { printf("xp%d,%d err cy=%d tr=%d sc=%d cs2=%o er1=%o\n", io->i_ctlr, io->i_unit, cn, tn, sn, xpaddr->hpcs2, xpaddr->hper1); return(-1); } return(io->i_cc); } /* * ALL drive type identification has been removed from the kernel's XP * driver and placed here. * * These tables are used to provide "the best guess" of the geometry * of the drive. DEC RP0{4,5,6,7} and RM0{3,5} drives will match exactly. * Non DEC controllers (performing an emulation) often use the DEC drive * type to mean completely different geometry/capacity drives. */ struct xpst { int flags; /* flags: XP_CC, XP_NOSEARCH */ int ncyl; /* number of cylinders */ int nspc; /* number of sectors per cylinder */ int ntpc; /* number of tracks per cylinder */ int nspt; /* number of sectors per track */ daddr_t nspd; /* number of sectors per drive */ }; static struct xpst rp04_st = { XP_CC, 411, 22 * 19, 19, 22, 411L * 22 * 19 }; /* rp05 uses same table as rp04 */ static struct xpst rp06_st = { XP_CC, 815, 22 * 19, 19, 22, 815L * 22 * 19 }; static struct xpst rp07_st = { XP_CC, 630, 50 * 32, 32, 50, 630L * 50 * 32 }; static struct xpst rm02_st; /* filled in dynamically */ static struct xpst rm03_st = { 0, 823, 32 * 5, 5, 32, 823L * 32 * 5 }; static struct xpst rm05_st = { 0, 823, 32 * 19, 19, 32, 823L * 32 * 19 }; static struct xpst rm80_st = { 0, 559, 31 * 14, 14, 31, 559L * 31 * 14 }; /* * SI controller stuff - likely not used any longer and will probably go away * eventually (when the D space is needed for something more important). */ static struct xpst cdc9775_st = { 0, 843, 32 * 40, 40, 32, 843L * 32 * 40 }; static struct xpst cdc9730_st = { 0, 823, 32 * 10, 10, 32, 823L * 32 * 10 }; static struct xpst cdc9766_st = { 0, 823, 32 * 19, 19, 32, 823L * 32 * 19 }; static struct xpst cdc9762_st = { 0, 823, 32 * 5, 5, 32, 823L * 32 * 5 }; static struct xpst capric_st = { 0, 1024, 32 * 16, 16, 32, 1024L * 32 * 16 }; static struct xpst eagle_st = { 0, 842, 48 * 20, 20, 48, 842L * 48 * 20 }; /* * A "default". If none of the above are useable then a default geometry * suitable for writing a label (sector 1) is used. */ static struct xpst default_st = { 0, 1, 2 * 1, 1, 2, 2 }; /* * This routine does not return an error (-1). If the drive is totally * unrecognizeable then the default above is used. */ xplabel(io) struct iob *io; { register struct xpst *st = NULL; int type, xpsn; register struct hpdevice *xpaddr = XPcsr[io->i_ctlr]; register struct disklabel *lp; type = xpaddr->hpdt & 077; switch (type) { case HPDT_RP04: /* 020 */ case HPDT_RP05: /* 021 */ st = &rp04_st; break; case HPDT_RP06: /* 022 */ st = &rp06_st; break; case HPDT_RP07: /* 042 */ st = &rp07_st; break; case HPDT_RM80: /* 026 */ st = &rm80_st; break; case HPDT_RM05: /* 027 */ st = &rm05_st; break; case HPDT_RM03: /* 024 */ st = &rm03_st; break; case HPDT_RM02: /* 025 */ /* * Borrowing a quote from 4BSD: * "We know this isn't a dec controller, so we can assume sanity." */ st = &rm02_st; xpaddr->hpcs1.w = HP_NOP; xpaddr->hpcs2.w = io->i_unit; xpaddr->rmhr = HPHR_MAXTRAK; st->ntpc = xpaddr->rmhr + 1; xpaddr->rmhr = HPHR_MAXSECT; st->nspt = xpaddr->rmhr + 1; xpaddr->rmhr = HPHR_MAXCYL; st->ncyl = xpaddr->rmhr + 1; xpaddr->hpcs1.w = HP_DCLR | HP_GO; st->nspc = st->nspt * st->ntpc; st->nspd = (long)st->nspc * st->ncyl; printf("type: RM02 c=%d t/c=%d s/t=%d\n", st->ncyl, st->ntpc, st->nspt); break; default: printf("xp%d,%d unknown drive type: %d -- ", io->i_ctlr, io->i_unit, type); printf("using 1 cyl, 1 trk, 2 sec/trk\n"); st = &default_st; break; } /* * Handle SI model byte stuff when we think it's an RM05 or RM03. Is any * one still using one of these? Is it worth all this code? */ if (type == HPDT_RM05 || type == HPDT_RM03) { xpsn = xpaddr->hpsn; if ((xpsn & SIMB_LU) != io->i_unit) goto notsi; switch ((xpsn & SIMB_MB) &~ (SIMB_S6|SIRM03|SIRM05)) { case SI9775D: st = &cdc9775_st; break; case SI9730D: st = &cdc9730_st; break; case SI9766: st = &cdc9766_st; break; case SI9762: st = &cdc9762_st; break; case SICAPD: st = &capric_st; break; case SI9751D: st = &eagle_st; break; default: printf("xp%d,%d unknown SI drive model %d -- ", io->i_ctlr, io->i_unit, xpsn); printf("using 1 cyl, 1 trk, 2 sec/trk\n"); st = &default_st; break; } } notsi: lp = &io->i_label; lp->d_type = DTYPE_SMD; lp->d_secsize = 512; /* XXX */ lp->d_secperunit = st->nspd; lp->d_partitions[0].p_size = st->nspd; lp->d_nsectors = st->nspt; lp->d_ntracks = st->ntpc; lp->d_secpercyl = st->nspc; lp->d_ncylinders = st->ncyl; lp->d_drivedata[0] = st->flags; strcpy(lp->d_typename, "SMD"); return(0); } flgs |= F_ALLOC; for (cp = str; *cp && *cp !=sys/pdpstand/maketape.c 644 0 0 4174 5006732566 10412 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)maketape.c 1.1 (2.10BSD Berkeley) 12/1/86 * (2.11BSD Contel) 4/20/91 * TU81s didn't like open/close/write at 1600bpi, use * ioctl to write tape marks instead. */ #include #include #include #include #define MAXB 30 extern int errno; char buf[MAXB * 512]; char name[50]; struct mtop mtio; int blksz, recsz; int mt; int fd; int cnt; main(argc, argv) int argc; char *argv[]; { register int i, j = 0, k = 0; FILE *mf; if (argc != 3) { fprintf(stderr, "usage: maketape tapedrive makefile\n"); exit(1); } if ((mt = creat(argv[1], 0666)) < 0) { perror(argv[1]); exit(1); } if ((mf = fopen(argv[2], "r")) == NULL) { perror(argv[2]); exit(1); } for (;;) { if ((i = fscanf(mf, "%s %d", name, &blksz))== EOF) exit(0); if (i != 2) { fprintf(stderr, "Help! Scanf didn't read 2 things (%d)\n", i); exit(1); } if (blksz <= 0 || blksz > MAXB) { fprintf(stderr, "Block size %d is invalid\n", blksz); exit(1); } recsz = blksz * 512; /* convert to bytes */ if (strcmp(name, "*") == 0) { mtio.mt_op = MTWEOF; mtio.mt_count = 1; if (ioctl(mt, MTIOCTOP, &mtio) < 0) fprintf(stderr, "MTIOCTOP err: %d\n", errno); k++; continue; } fd = open(name, 0); if (fd < 0) { perror(name); exit(1); } printf("%s: block %d, file %d\n", name, j, k); /* * wfj fix to final block output. * we pad the last record with nulls * (instead of the bell std. of padding with trash). * this allows you to access text files on the * tape without garbage at the end of the file. * (note that there is no record length associated * with tape files) */ while ((cnt=read(fd, buf, recsz)) == recsz) { j++; if (write(mt, buf, cnt) < 0) { perror(argv[1]); exit(1); } } if (cnt>0) { j++; bzero(buf + cnt, recsz - cnt); if (write(mt, buf, recsz) < 0) { perror(argv[1]); exit(1); } } close(fd); } } []; { register int i, j = 0, k = 0; FILE *mf; if (argc != 3) { fprintf(stderr, "usage: maketape tapedrive makefile\n"); exit(1); } if ((mt = creat(argv[1], 0666)) < 0) { perror(argv[1]); exit(1); } if ((mf = fopen(argv[2], "r")) == NULL) { perror(argv[2]); exit(1); } for (;;) { if ((i = fscanf(mf, "%s %d", name, &blksz))== EOF) exit(0); if (i != 2) { fpsys/pdpstand/saio.h 444 0 12 2666 5765731167 7620 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)saio.h 2.1 (2.11BSD GTE) 1995/06/08 */ /* * This must be done so that the standalone I/O system uses the same * size for the inode structure as the utilities (restor, mkfs, etc). * See the comments in mkfs.c for more information. */ #undef EXTERNALITIMES #include #include #include /* * io block: includes an * inode, cells for the use of seek, etc, a buffer * and a disklabel. */ struct iob { char i_flgs; char i_ctlr; struct inode i_ino; short i_unit; short i_part; daddr_t i_boff; off_t i_offset; daddr_t i_bn; char *i_ma; int i_cc; char i_buf[DEV_BSIZE]; struct disklabel i_label; }; #define F_READ 01 #define F_WRITE 02 #define F_ALLOC 04 #define F_FILE 010 #define F_TAPE 020 #define READ F_READ #define WRITE F_WRITE #define READLABEL 0x1 #define WRITELABEL 0x2 #define DEFAULTLABEL 0x3 /* * device switch */ struct devsw { char *dv_name; int (*dv_strategy)(); int (*dv_open)(); int (*dv_close)(); caddr_t **dv_csr; int (*dv_label)(); int (*dv_seek)(); }; /* * Set to inhibit 'disklabel missing or corrupt' error messages. This * is normally left off and only set by the standalone disklabeling utility * when it expects to be reading an unlabeled disk. */ int Nolabelerr; me, 0); if (fd < 0) { perror(name); exit(1); } printf("%s: blosys/pdpstand/maketape.data 644 0 12 116 5767173627 11107 mtboot 1 mtboot 1 boot 1 * 1 disklabel 2 * 1 mkfs 2 * 1 restor 2 * 1 icheck 2 t0.sdcmtboot.sc si.ca M.sta NEWtaboot.cd ubmapset.cc hk.ca prf.c rk.ca rl.ca OLDta sys.c tm.ca ts.ca xp.ca maketape.ccsaio.hdc maketape.data br.caconf.cddtmscp.cdp Makefile.vaxM.otamtbootdv conf.odvboot.odv ubmapset.ox prf.olabel.cosys/pdpstand/br.c 444 0 12 4271 5765731321 7245 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)br.c 2.2 (2.11BSD) 1995/06/08 */ /* * rp03-like disk driver * modified to handle BR 1537 and 1711 controllers with * T300, T200, T80 and T50 drives. */ #include "../h/param.h" #include "../pdpuba/brreg.h" #include "saio.h" #define NBR 2 #define SEC22 02400 /* T200 or T50 */ #define CYL5 01400 /* T80 or T50 */ struct brdevice *BRcsr[NBR + 1] = { (struct brdevice *)0176710, (struct brdevice *)0, (struct brdevice *)-1 }; int brsctrk[NBR][8], brtrkcyl[NBR][8]; brstrategy(io, func) register struct iob *io; { register struct brdevice *braddr; register int ctlr; int com, cn, tn, sn, unit, sectrk, trkcyl, ctr, bae, lo16; unit = io->i_unit; ctlr = io->i_ctlr; braddr = BRcsr[ctlr]; /* if we haven't gotten the characteristics yet, do so now. */ trkcyl = brtrkcyl[ctlr][unit]; if (!(sectrk = brsctrk[ctlr][unit])) { /* give a home seek command, then wait for complete */ braddr->brcs.w = (unit << 8) | BR_HSEEK | BR_GO; ctr = 0; while ((braddr->brcs.w & BR_RDY) == 0 && --ctr) continue; if (braddr->brcs.w & BR_HE) { printf("br%d,%d !ready\n", ctlr,unit); return(-1); } com = braddr->brae; if (com & SEC22) sectrk = 22; else sectrk = 32; if (com & CYL5) trkcyl = 5; else trkcyl = 19; brsctrk[ctlr][unit] = sectrk; brtrkcyl[ctlr][unit] = trkcyl; } cn = io->i_bn/(sectrk * trkcyl); sn = io->i_bn%(sectrk * trkcyl); tn = sn/sectrk; sn = sn%sectrk; iomapadr(io->i_ma, &bae, &lo16); braddr->brcs.w = (unit<<8); braddr->brda = (tn<<8) | sn; braddr->brca = cn; braddr->brba = (caddr_t)lo16; braddr->brwc = -(io->i_cc>>1); braddr->brae = bae; com = (bae<<4)|BR_GO; if (func == READ) com |= BR_RCOM; else com |= BR_WCOM; braddr->brcs.w |= com; while ((braddr->brcs.w& BR_RDY)==0) continue; if (braddr->brcs.w < 0) { /* error bit */ printf("br%d err: cy=%d tr=%d sc=%d er=%o ds=%o\n", unit, cn, tn, sn, braddr->brer, braddr->brds); return(-1); } return(io->i_cc); } bropen(io) struct iob *io; { return(genopen(NBR, io)); } %d,%d err cy=%d tr=%d sc=%d cs2=%o er1=%o\n", io->i_ctlr, io->i_unit, cn, tn, sn, xpaddr->hpcs2, xpaddr->hper1); return(-1); } return(io->i_cc); } /* * ALL drive type identification has been removed from the kernel's XP * driver and placed here. * * These tables are used to provide "the best guess" of thsys/pdpstand/conf.c 444 0 12 11215 6002635756 7603 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)conf.c 2.4 (2.11BSD) 1995/07/17 */ #include "../h/param.h" #include "saio.h" int nullsys(); extern int xpstrategy(), xpopen(), xpclose(), xplabel(); extern int brstrategy(), bropen(); extern int rkstrategy(), rkopen(); extern int hkstrategy(), hkopen(); extern int rlstrategy(), rlopen(), rllabel(); extern int sistrategy(), siopen(); extern int rastrategy(), raopen(), raclose(), ralabel(); extern int tmstrategy(), tmopen(), tmclose(), tmseek(); extern int htstrategy(), htopen(), htclose(), htseek(); extern int tsstrategy(), tsopen(), tsclose(), tsseek(); extern int tmscpstrategy(), tmscpopen(), tmscpclose(), tmscpseek(); extern caddr_t *XPcsr[], *BRcsr[], *RKcsr[], *HKcsr[], *RLcsr[]; extern caddr_t *SIcsr[], *RAcsr[], *TMcsr[], *HTcsr[], *TScsr[], *TMScsr[]; /* * NOTE! This table must be in major device number order. See /sys/pdp/conf.c * for the major device numbers. */ struct devsw devsw[] = { "ht", htstrategy, htopen, htclose, HTcsr, /* 0 */ nullsys, htseek, "tm", tmstrategy, tmopen, tmclose, TMcsr, /* 1 */ nullsys, tmseek, "ts", tsstrategy, tsopen, tsclose, TScsr, /* 2 */ nullsys, tsseek, "ram", nullsys, nullsys, nullsys, 0, /* 3 */ nullsys, nullsys, "hk", hkstrategy, hkopen, nullsys, HKcsr, /* 4 */ nullsys, nullsys, "ra", rastrategy, raopen, raclose, RAcsr, /* 5 */ ralabel, nullsys, "rk", rkstrategy, rkopen, nullsys, RKcsr, /* 6 */ nullsys, nullsys, "rl", rlstrategy, rlopen, nullsys, RLcsr, /* 7 */ rllabel, nullsys, "rx", nullsys, nullsys, nullsys, 0, /* 8 */ nullsys, nullsys, "si", sistrategy, siopen, nullsys, SIcsr, /* 9 */ nullsys, nullsys, "xp", xpstrategy, xpopen, xpclose, XPcsr, /* 10 */ xplabel, nullsys, "br", brstrategy, bropen, nullsys, BRcsr, /* 11 */ nullsys, nullsys, "tms", tmscpstrategy, tmscpopen, tmscpclose, TMScsr,/* 12 */ nullsys, tmscpseek, 0, 0, 0, 0, 0, nullsys, nullsys, }; int ndevsw = (sizeof (devsw) / sizeof (devsw[0])) - 1; char ADJcsr[] = { 0, /* HT = 0 */ 2, /* TM = 1 */ 2, /* TS = 2 */ 0, /* RAM = 3 */ 0, /* HK = 4 */ 0, /* RA = 5 */ 4, /* RK = 6 */ 0, /* RL = 7 */ 0, /* RX = 8 */ 0, /* XP/SI = 9 */ 0, /* XP = 10 */ 4, /* BR =11 */ 0, /* TMS = 12 */ }; devread(io) register struct iob *io; { return((*devsw[io->i_ino.i_dev].dv_strategy)(io, READ)); } devwrite(io) register struct iob *io; { return((*devsw[io->i_ino.i_dev].dv_strategy)(io, WRITE)); } devopen(io) register struct iob *io; { return((*devsw[io->i_ino.i_dev].dv_open)(io)); } devclose(io) register struct iob *io; { (*devsw[io->i_ino.i_dev].dv_close)(io); } /* * Call the 'seek' entry for a tape device. Seeking only works for 1kb * records - which is how the executables are stored - not for the dump * or tar files on a boot tape. */ devseek(io, space) register struct iob *io; int space; { return((*devsw[io->i_ino.i_dev].dv_seek)(io, space)); } devlabel(io, fnc) register struct iob *io; int fnc; { int (*dvlab)() = devsw[io->i_ino.i_dev].dv_label; int (*strat)() = devsw[io->i_ino.i_dev].dv_strategy; register struct disklabel *lp; register struct partition *pi; char *name = devsw[io->i_ino.i_dev].dv_name; switch (fnc) { case WRITELABEL: return(writelabel(io, strat, name)); case READLABEL: return(readlabel(io, strat, name)); case DEFAULTLABEL: /* * Zero out the label buffer and then assign defaults common to all drivers. * Many of these are rarely (if ever) changed. The 'a' partition is set up * to be one sector past the label sector - the driver is expected to change * this to span the volume once the size is known. */ lp = &io->i_label; pi = &lp->d_partitions[0]; bzero(lp, sizeof (struct disklabel)); lp->d_npartitions = 1; pi->p_offset = 0; pi->p_size = LABELSECTOR + 1; pi->p_fsize = DEV_BSIZE; pi->p_frag = 1; pi->p_fstype = FS_V71K; strcpy(lp->d_packname, "DEFAULT"); lp->d_secsize = 512; lp->d_interleave = 1; lp->d_rpm = 3600; /* * param.h declares BBSIZE to be DEV_BSIZE which is 1kb. This is _wrong_, * the boot block size (what the bootroms read) is 512. The disklabel(8) * program explicitly sets d_bbsize to 512 so we do the same thing here. * * What a mess - when the 1k filesystem was created there should have been * a (clearer) distinction made between '(hardware) sectors' and * '(filesystem) blocks'. Sigh. */ lp->d_bbsize = 512; lp->d_sbsize = SBSIZE; return((*dvlab)(io)); default: printf("devlabel: bad fnc %d\n"); return(-1); } } nullsys() { return(-1); } 2, /* TM = 1 */ 2, /* TS = 2 */ 0, /* RAM = 3 */ 0, /* HK = 4 */ 0, /* RA = 5 */ 4, /* RK = 6 */ 0, /* RL = 7 */ 0, /* RX = 8 */ 0, /* XP/SI = 9 */ 0, /* XP = 10 */ 4, /* BR =11 */ 0, /* TMS = 12 */ }; devread(io) register struct iob *io; { return((*devsw[io->i_ino.i_dev].dv_strategy)(io, READ)); } devwrite(io) register struct iob *io; sys/pdpstand/tmscp.c 644 0 12 22144 5765732000 10004 /* @(#)tmscp.c 7.1.2 (2.11BSD GTE) 1995/06/08 */ /**************************************************************** * Licensed from Digital Equipment Corporation * * Copyright (c) * * Digital Equipment Corporation * * Maynard, Massachusetts * * 1985, 1986 * * All rights reserved. * * * * The Information in this software is subject to change * * without notice and should not be construed as a commitment * * by Digital Equipment Corporation. Digital makes no * * representations about the suitability of this software for * * any purpose. It is supplied "As Is" without expressed or * * implied warranty. * * * * If the Regents of the University of California or its * * licensees modify the software in a manner creating * * deriviative copyright rights, appropriate copyright * * legends may be placed on the drivative work in addition * * to that set forth above. * ***************************************************************/ /* * tmscp.c - TMSCP (TK50/TU81) standalone driver */ /* static char *sccsid = "@(#)tmscp.c 1.5 (ULTRIX) 4/18/86"; */ /* ------------------------------------------------------------------------ * Modification History: /sys/pdpstand/tmscp.c * * 5-30-95 sms - new iob structure. * 4-20-91 sms - add multi controller and unit support (sms) * 8-20-90 steven m. schultz (sms@wlv.iipo.gtegsc.com) * Port from 4.3BSD to 2.11BSD * 3-15-85 afd * Don't ask for an interrupt when commands are issued and * check ownership bit in the response descriptor to detect when a * command is complete. Necessary due to the TU81's failure to set * the response interrupt field in the communications area. * * ------------------------------------------------------------------------ */ #include "../h/param.h" #include "saio.h" /* * Parameters for the communications area * (Only 1 cmd & 1 rsp packet) */ #define NRSPL2 0 #define NCMDL2 0 #define NRSP (1<> 3) & 3) /* unused for now */ struct tmscpdevice *TMScsr[NTMS + 1] = { (struct tmscpdevice *)0174500, (struct tmscpdevice *)0, (struct tmscpdevice *)-1 }; struct tmscp { struct tmscpca tmscp_ca; struct mscp tmscp_rsp; struct mscp tmscp_cmd; } tmscp[NTMS]; u_char tmsoffline[NTMS] = {1, 1}; /* Flag to prevent multiple STCON */ u_char tms_offline[NTMS][4] = {{1,1,1,1}, {1,1,1,1}}; /* Flag to prevent multiple ONLIN */ static char opnmsg[] = "tms%d: step %d failed sa=0%o\n"; extern int tapemark; /* flag to indicate tapemark encountered (see sys.c as to how it's used) */ /* * Open a tmscp device. Initialize the controller and set the unit online. */ tmscpopen(io) register struct iob *io; { register struct tmscpdevice *tmscpaddr; int ctlr = io->i_ctlr; int unit = io->i_unit, bae, lo16; register struct tmscp *tms = &tmscp[ctlr]; if (genopen(NTMS, io) < 0) return(-1); io->i_flgs |= F_TAPE; tmscpaddr = TMScsr[ctlr]; /* * Have the tmscp controller characteristics already been set up * (STCON)? */ if (tmsoffline[ctlr]) { /* * Initialize the tmscp device and wait for the 4 steps * to complete. */ tmscpaddr->tmscpip = 0; while ((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0) ; tmscpaddr->tmscpsa =TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8); while ((tmscpaddr->tmscpsa & TMSCP_STEP2) == 0) ; #define STEP1MASK 0174377 #define STEP1GOOD (TMSCP_STEP2|TMSCP_IE|(NCMDL2<<3)|NRSPL2) iomapadr(&tms->tmscp_ca.ca_ringbase, &bae, &lo16); if ((tmscpaddr->tmscpsa&STEP1MASK) != STEP1GOOD) printf(opnmsg, ctlr, 1, tmscpaddr->tmscpsa); tmscpaddr->tmscpsa = lo16; while ((tmscpaddr->tmscpsa & TMSCP_STEP3) == 0) ; #define STEP2MASK 0174377 #define STEP2GOOD (TMSCP_STEP3) if ((tmscpaddr->tmscpsa&STEP2MASK) != STEP2GOOD) printf(opnmsg, ctlr, 2, tmscpaddr->tmscpsa); tmscpaddr->tmscpsa = bae; while ((tmscpaddr->tmscpsa & TMSCP_STEP4) == 0) ; #define STEP3MASK 0174000 #define STEP3GOOD TMSCP_STEP4 if ((tmscpaddr->tmscpsa&STEP3MASK) != STEP3GOOD) printf(opnmsg, ctlr, 3, tmscpaddr->tmscpsa); tmscpaddr->tmscpsa = TMSCP_GO; if (tmscpcmd(ctlr, M_OP_STCON, 0) == 0) { printf("tms%d STCON", ctlr); return(-1); } tmsoffline[ctlr] = 0; } tms->tmscp_cmd.mscp_unit = unit; /* * Has this unit been issued an ONLIN? */ if (tms_offline[ctlr][unit]) { if (tmscpcmd(ctlr, M_OP_ONLIN, 0) == 0) { printf("tms%d,%d ONLIN", ctlr, unit); return(-1); } tms_offline[ctlr][unit] = 0; } tmscpclose(io); /* close just does a rewind */ if (io->i_part > 0) /* * Skip forward the appropriate number of files on the tape. */ { tms->tmscp_cmd.mscp_tmkcnt = io->i_part; tms->tmscp_cmd.mscp_buffer_h = 0; tms->tmscp_cmd.mscp_bytecnt = 0; tmscpcmd(ctlr, M_OP_REPOS, 0); tms->tmscp_cmd.mscp_tmkcnt = 0; } return(0); } /* * Close the device (rewind it to BOT) */ tmscpclose(io) register struct iob *io; { register struct tmscp *tms = &tmscp[io->i_ctlr]; tms->tmscp_cmd.mscp_buffer_l = 0; /* tmkcnt */ tms->tmscp_cmd.mscp_buffer_h = 0; tms->tmscp_cmd.mscp_bytecnt = 0; tms->tmscp_cmd.mscp_unit = io->i_unit; tmscpcmd(io->i_ctlr, M_OP_REPOS, M_MD_REWND | M_MD_CLSEX); } /* * Set up tmscp command packet. Cause the controller to poll to pick up * the command. */ tmscpcmd(ctlr, op,mod) register int ctlr; int op, mod; /* opcode and modifier (usu 0) */ { register struct tmscp *tms = &tmscp[ctlr]; register struct mscp *mp; /* ptr to cmd packet */ int i; /* read into to init polling */ int bae, lo16; /* * Init cmd & rsp area */ iomapadr(&tms->tmscp_cmd.mscp_cmdref, &bae, &lo16); tms->tmscp_ca.ca_cmddsc[0].lsh = lo16; tms->tmscp_ca.ca_cmddsc[0].hsh = bae; tms->tmscp_cmd.mscp_dscptr = (long *)tms->tmscp_ca.ca_cmddsc; tms->tmscp_cmd.mscp_header.tmscp_vcid = 1; /* for tape */ iomapadr(&tms->tmscp_rsp.mscp_cmdref, &bae, &lo16); tms->tmscp_ca.ca_rspdsc[0].lsh = lo16; tms->tmscp_ca.ca_rspdsc[0].hsh = bae; tms->tmscp_rsp.mscp_dscptr = (long *)tms->tmscp_ca.ca_rspdsc; tms->tmscp_cmd.mscp_cntflgs = 0; tms->tmscp_cmd.mscp_opcode = op; tms->tmscp_cmd.mscp_modifier = mod; tms->tmscp_cmd.mscp_header.tmscp_msglen = mscp_msglen; tms->tmscp_ca.ca_cmddsc[0].hsh |= TMSCP_OWN; /* | TMSCP_INT */ tms->tmscp_rsp.mscp_header.tmscp_msglen = mscp_msglen; tms->tmscp_ca.ca_rspdsc[0].hsh |= TMSCP_OWN; /* | TMSCP_INT */ tms->tmscp_cmd.mscp_zzz2 = 0; i = TMScsr[ctlr]->tmscpip; for (;;) { if (TMScsr[ctlr]->tmscpsa & TMSCP_ERR) { printf("tms%d: Fatal error sa=%o\n", ctlr, TMScsr[ctlr]->tmscpsa); return(0); } if (tms->tmscp_ca.ca_cmdint) tms->tmscp_ca.ca_cmdint = 0; /* * This is to handle the case of devices not setting the * interrupt field in the communications area. Some * devices (early TU81's) only clear the ownership field * in the Response Descriptor. */ /* if (tms->tmscp_ca.ca_rspint) break; */ if (!(tms->tmscp_ca.ca_rspdsc[0].hsh & TMSCP_OWN)) break; } tms->tmscp_ca.ca_rspint = 0; mp = &tms->tmscp_rsp; if (mp->mscp_opcode != (op|M_OP_END) || (mp->mscp_status&M_ST_MASK) != M_ST_SUCC) { /* Detect hitting tape mark. This signifies the end of the * tape mini-root file. We don't want to return an error * condition to the strategy routine. Set tapemark flag * for sys.c */ if ((mp->mscp_status & M_ST_MASK) == M_ST_TAPEM) { tapemark = 1; return(1); } printf("tms%d,%d: I/O err 0%o op=0%o mod=0%o\n", ctlr, mp->mscp_unit, mp->mscp_status, op, mod); return(0); } return(1); } /* * Set up to do reads and writes; call tmscpcmd to issue the cmd. */ tmscpstrategy(io, func) register struct iob *io; int func; { int ctlr = io->i_ctlr, unit = io->i_unit; int bae, lo16; register struct tmscp *tms = &tmscp[ctlr]; register struct mscp *mp; mp = &tms->tmscp_cmd; mp->mscp_lbn_l = loint(io->i_bn); mp->mscp_lbn_h = hiint(io->i_bn); mp->mscp_unit = unit; mp->mscp_bytecnt = io->i_cc; iomapadr(io->i_ma, &bae, &lo16); mp->mscp_buffer_l = lo16; mp->mscp_buffer_h = bae; if (tmscpcmd(ctlr, func == READ ? M_OP_READ : M_OP_WRITE, 0) ==0) return(-1); /* * Detect hitting tape mark so we do it gracefully and return a * character count of 0 to signify end of copy. */ if (tapemark) return(0); return(io->i_cc); } tmscpseek(io, space) register struct iob *io; int space; { register struct tmscp *tms = &tmscp[io->i_ctlr]; int mod; if (space == 0) return(0); if (space < 0) { mod = M_MD_REVRS; space = -space; } else mod = 0; tms->tmscp_cmd.mscp_buffer_l = 0; tms->tmscp_cmd.mscp_buffer_h = 0; tms->tmscp_cmd.mscp_unit = io->i_unit; tms->tmscp_cmd.mscp_reccnt = space; tmscpcmd(io->i_ctlr, M_OP_REPOS, mod | M_MD_OBJCT); return(0); } -------------------------------------------------------------------- */ #include "../h/param.h" #include "saio.h" /* * Parameters for the communications area * (Only 1 cmd & 1 rsp packet) */ #define NRSPL2 0 #define NCMDL2 0 #define NRSP (1<> 3) & 3) /* unused sys/pdpstand/Makefile.vax 644 0 12 3215 5006473034 10722 # This is a special case for creating 1600bpi distributions on a TU81 # (the various binary images must obviously be the pdp-11 ones). # TU81s do not handle the open/write/close/open/write/etc cycle, # apparently a lingering serious exception is left (possibly because # of density switching) when a close at low density is done. 'maketape' # (the dd and tar commands as well) would receive hard errors after the # first record/file. # The solution was three fold: # 1) 'maketape' was modified to write tapemarks rather than # doing close/open. # 2) temporary files are constructed by tar (a large empty partition # is necessary for all this to work) # 3) a version of maketape.data is constructed on the fly with # the extra files appended to it - this allows 'maketape' # to write the entire tape without closing. # TAPE which tape to write the distribution on # DUMP where to store a root system dump if you do a ``make dump'' # TAPE= mt0 DUMP= /xusr/root.dump TMP1= /xusr/1st.tar TMP2= /xusr/2nd.tar ROOT= /xusr/root distribution: tape1 switch_tapes tape2 tape1: ${TMP2} ${TMP1} ./maketape /dev/r${TAPE} maketape.data switch_tapes: FRC @echo "Switch tapes. Hit CR when second tape is mounted." @echo "DON'T FORGET TO CLEAN UP THE TAR TEMP FILES WHEN DONE!" @head -1 FRC: tape2: cd ${ROOT}/usr/src; tar cfb /dev/r${TAPE} 20 \ Makefile asm.sed asm.sed.pdp asm.sed.vax bin etc games \ lib local man new old ucb usr.bin usr.lib ${TMP1}: cd ${ROOT}/usr; tar cf ${TMP1} \ adm bin dict doc games guest hosts include ingres lib \ local man msgs new old preserve pub skel spool tmp ucb ${TMP2}: cd ${ROOT}/usr/src; tar cf ${TMP2} sys include ; return(io->i_cc); } tmscpseek(io, space) register struct iob *io; int space; { register struct tmscp *tms = &tmscp[io->i_ctlr]; int mod; if (space == 0) return(0); if (space < 0) { mod = M_MD_REVRS; space = -space; } else mod = 0; tms->tmscp_cmd.mscp_buffer_l = 0; tms->tmscp_cmd.mscp_buffer_h = 0; tms->tmscp_cmd.mscp_unit = io->i_unit; tms-sys/pdpstand/label.c 644 0 0 10232 6007611347 7705 /*- * Public domain, May 1995 * * @(#)label.c 1.1 (2.11BSD GTE) 1995/08/01 * * Date: 1995/08/01 * Move the check for a partition number being out of bounds to the * readlabel routine. This is necessary in order to permit unlabeled disks * (or disks whose label is corrupt) to be open'd. This check can't be done * in the open routine because a corrupt or missing label could have garbage * for the number of partitions. */ #include "../h/param.h" #include "saio.h" /* * Called from the general device label routine in conf.c. A label with * a fake geometry suitable for reading the label sector is created and * the driver's strategy routine is called. If the label is corrupted * or absent an error is possibly printed. * * NOTES: We reuse the iob structure's buffer (i_buf). * All disks must have at least LABELSECTOR+1 sectors in a track. * (this is not expected to be a problem since LABELSECTOR is 1). */ readlabel(io, strat, name) struct iob *io; int (*strat)(); char *name; { struct disklabel *lp = &io->i_label; io->i_bn = LABELSECTOR; io->i_ma = io->i_buf; io->i_cc = 512; /* XXX */ lp->d_nsectors = LABELSECTOR + 1; /* # sectors per track */ lp->d_ntracks = 1; /* # tracks per cylinder */ lp->d_secpercyl = LABELSECTOR + 1; /* # sectors per cylinder */ if ((*strat)(io, READ) != 512) { printf("%s%d,%d: error reading labelsector\n", name, io->i_ctlr, io->i_unit); return(-1); } bcopy(io->i_buf, lp, sizeof (struct disklabel)); if (Nolabelerr) return(0); if (lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || dkcksum(lp) != 0) { printf("%s%d,%d disklabel missing or corrupt\n", name, io->i_ctlr, io->i_unit); return(-1); } if (io->i_part >= lp->d_npartitions || lp->d_partitions[io->i_part].p_size == 0) { printf("%s%d,%d%c bad partition # or size = 0\n", name, io->i_ctlr, io->i_unit, 'a' + io->i_part); return(-1); } return(0); } writelabel(io, strat, name) register struct iob *io; int (*strat)(); char *name; { register struct disklabel *lp = &io->i_label; if ((io->i_flgs & F_WRITE) == 0) return(-1); io->i_bn = LABELSECTOR; io->i_ma = (char *)&io->i_label; io->i_cc = 512; /* XXX */ /* * The geometry had better be set up and correct at this point - we can not * fake the geometry because that would overwrite the contents of the label * itself. */ lp->d_secsize = 512; /* XXX */ lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_checksum = 0; lp->d_checksum = dkcksum(lp); if ((*strat)(io, WRITE) != 512) { printf("%s: error writing labelsector\n", name); return(-1); } return(0); } /* * Compute checksum for disk label. */ dkcksum(lp) register struct disklabel *lp; { register u_short *start, *end; register u_short sum = 0; start = (u_short *)lp; end = (u_short *)&lp->d_partitions[lp->d_npartitions]; while (start < end) sum ^= *start++; return (sum); } /* * Check for partitions which overlap each other. While it is legal * to have partitions which overlap (as long as they are not used at the * same time) it is often a mistake or oversite. */ overlapchk(lp) register struct disklabel *lp; { register struct partition *pp; int i, part, openmask; daddr_t start, end; #define RAWPART 2 /* * 'c' is normally (but not always) the partition which spans the whole * drive, thus it is not normally an error for it to overlap all other * partitions. */ openmask = ~0 & ~(1 << RAWPART); for (part = 0; part < lp->d_npartitions; part++) { pp = &lp->d_partitions[part]; if (part == RAWPART || pp->p_size == 0) continue; start = pp->p_offset; end = start + pp->p_size; for (pp = lp->d_partitions, i = 0; i < lp->d_npartitions; pp++, i++) { /* * We make sure to not report zero length partitions or that a * partition overlaps itself. We've already checked lower partitions * so avoid giving something like "a overlaps b" and then "b overlaps a". */ if (i <= part || pp->p_size == 0) continue; if (pp->p_offset + pp->p_size <= start || pp->p_offset >= end) continue; if ((openmask & (1 << i)) == 0) continue; printf("warning: partition '%c' overlaps '%c'\n", 'a' + part, 'a' + i); } } } EP2MASK 0174377 #define STEP2GOOD (TMSCP_STEP3) if ((tmscpaddr->tmscpsa&STEP2MASK) != STEP2GOOD) printf(opnmsg, ctlr, 2, tmscpaddr->tmscpsa); tmscpaddr->tmscpsa = bae; while ((tmscpaddr->tmscpsa & TMSCP_STEP4) == 0) ; #define STEP3MASK 0174000 #define STEP3GOOD TMSCP_STEP4 if ((tmscpaddr->tmscpsa&STEP3MASK) != STEP3GOOD) printf(opnmsg, csys/pdpstand/toyset.s 644 0 0 23306 5435567160 10212 TOYCSR = 177526 / August 21, 1993 - Steven M. Schultz (sms@wlv.iipo.gtegsc.com) / This is a standalone program which is used to set the TOY (Time Of Year) / clock on a PDP-11/93 or 11/94. If this program is run on other than a / 93 or 94 an error is printed and the program 'exits' back to the boot / runtime. / / The current date is printed (in the same format used to enter the new date) / and the prompt "Toyset> " is displayed. At that time a string of the form: / YYMMDDHHMM[.SS]\n is entered. The seconds "SS" are optional, if not entered / the seconds will be set to 0. Any invalid input string simply loops back / to the top of the program. / / To not change the date and time simply hit a return and the program will / exit, returning control to 'boot'. .globl _main, csv, cret, _printf, _gets, _exit, _cputype, _module _main: main: jsr r5,csv / srt0.o sets up a C frame... jsr pc,init / check cpu type and display current TOY clrb line / init buffer mov $line,-(sp) jsr pc,_gets / get input from user tst r0 bgt 1f leave: jsr pc,_exit / exit on error 1: tstb line / did we get anything? beq leave / nope - go exit clr r3 / clear '.' seen flag mov $line,r4 / point to input data 2: movb (r4)+,r0 beq 1f / end of string - go validate it cmpb r0,$'. / are there seconds present? bne 2b / not yet - go try another byte clrb -1(r4) / zap '.' - separating two parts of date mov r4,r3 / set seconds present flag tstb (r3)+ / must have two... beq main / and only two... tstb (r3)+ / characters after... beq main / the '.'... tstb (r3) / followed by a ... bne main / null character. 1: clrb seconds / assume no seconds (start of minute) tst r3 / do we have seconds? beq nosec / no - br cmpb -(r3),-(r3) / back up to beginning of seconds string mov r3,-(sp) jsr pc,atoi2 / convert two digits to binary tst (sp)+ cmp r0,$59. / range check bhi main / error - go back to top movb r0,seconds / save for later nosec: sub $line+1,r4 / number of characters in date string cmp r4,$10. / _must_ have *exactly* "YYMMDDhhmm" bne main / back to the top on error mov $line,r4 / point to start of date string mov r4,-(sp) jsr pc,atoi2 / convert 2 digits to binary (year) tst (sp)+ cmp r4,$-1 / error? beq main / yes - go back to top cmp r0,$69. / before [19]69? bgt 1f / no - it's a 1970-1999 year - br add $100.,r0 / 21st century and 11s are still around! 1: movb r0,year / save year for later cmpb (r4)+,(r4)+ / skip two digits, move to month mov r4,-(sp) jsr pc,atoi2 / convert month to binary tst (sp)+ cmp r0,$12. / range check bhi main / back to top on too high cmpb (r4)+,(r4)+ / move on to day of month movb r0,month / save month for later beq main / can't have a month 0 mov r4,-(sp) jsr pc,atoi2 / convert day of month to binary tst (sp)+ movb month,r1 cmpb r0,Mtab-1(r1) / crude check (no leap year case) bhi main / on day of month movb r0,day / save the day for later cmpb (r4)+,(r4)+ / move along to hours of day mov r4,-(sp) jsr pc,atoi2 / convert hours of day to binary tst (sp)+ cmp r0,$23. / can't have more than 23 hours bhi main / but 00 is ok (midnight) movb r0,hours / save hours for later cmpb (r4)+,(r4)+ / move over to minutes mov r4,-(sp) jsr pc,atoi2 / convert minutes to binary tst (sp)+ cmp r0,$59. / can't have more than 59 minutes bhi main / back to top on out of range error movb r0,minutes / save for later / need to compute the "day of week". why the TOY clock couldn't figure / this out (or do without) itself i don't know. jsr pc,t2dow / find out "day of week" movb r0,dow / save for later / now we have to convert the binary data to BCD. We needed (or preferred) / the binary form for ease of range checking but the TOY wants BCD. Besides / i like to improve my typing skills ;-) movb seconds,r1 jsr pc,tobcd movb r0,bcd+1 / seconds movb minutes,r1 jsr pc,tobcd movb r0,bcd+2 / minutes movb hours,r1 jsr pc,tobcd movb r0,bcd+3 / hours movb dow,r1 jsr pc,tobcd movb r0,bcd+4 / day of week movb day,r1 jsr pc,tobcd movb r0,bcd+5 / day of month movb month,r1 jsr pc,tobcd movb r0,bcd+6 / month of year movb year,r1 jsr pc,tobcd movb r0,bcd+7 / Now initialize the TOY by sending the 'recognition' sequence. We have / to inline this because immediately after the recognition sequence must / come the 'write' of data - a 'read' to save the contents of the CSR / would tell the TOY we're reading data. *sigh* tst *$TOYCSR / strobe the clock register clr -(sp) / save previous high byte of register movb *$TOYCSR+1,(sp) / only bit 8 belongs to TOY! bic $1,(sp) / make sure bit 8 (TOY bit) is clear mov $2,r2 / number of double words to send clock 1: mov $35305,r0 / first word of recognition code jsr pc,toyload / send it to clock mov $56243,r0 / second word jsr pc,toyload / send it sob r2,1b / do the whole thing twice / Now write the data to the TOY without an intervening 'tst' or 'movb' / to the CSR. mov bcd,r0 / first two bytes jsr pc,toyload mov bcd+2,r0 / bytes 3 and 4 jsr pc,toyload mov bcd+4,r0 jsr pc,toyload / bytes 5 and 6 mov bcd+6,r0 jsr pc,toyload / bytes 7 and 8 tst (sp)+ / clean stack now, we're done clr r0 / "exit" status. ha! ;-) jsr pc,_exit / Check the cpu type - only the 93 and 94 have a TOY. Then initialize / the TOY and read the current date. Convert the date into printable / form and print it out along with the prompt. init: cmp _cputype,$93. beq 1f cmp _cputype,$94. beq 1f mov $errmsg1,-(sp) jsr pc,_printf mov $1,r0 jsr pc,_exit 1: jsr pc,initoy / init the TOY clock mov $bcd,-(sp) / buffer for the date jsr pc,_gettoy / read the TOY tst (sp)+ mov $timbuf,r3 / where to put printable form of date clr r1 bisb bcd+7,r1 / year in bcd jsr pc,bcd2msg movb bcd+6,r1 / month in bcd jsr pc,bcd2msg movb bcd+5,r1 / day of month in bcd jsr pc,bcd2msg movb bcd+3,r1 / hour of day in bcd jsr pc,bcd2msg movb bcd+2,r1 / minute of hour in bcd jsr pc,bcd2msg movb $'.,(r3)+ movb bcd+1,r1 / seconds of minute in bcd jsr pc,bcd2msg mov $timmsg,-(sp) jsr pc,_printf tst (sp)+ rts pc / convert two bytes of ascii pointed to by 2(sp) into a binary number. / the return value is in r0. atoi2: movb *2(sp),r1 inc 2(sp) movb *2(sp),r0 sub $'0,r1 sub $'0,r0 mul $10.,r1 add r1,r0 rts pc / convert a byte of BCD (in r1) two to ascii digits and place those / at (r3)+ and (r3)+ respectively. bcd2msg: clr r0 div $16.,r0 add $'0,r0 add $'0,r1 movb r0,(r3)+ movb r1,(r3)+ rts pc / convert a binary number (in r1) to a byte containing two bcd digits. / return result in r0. tobcd: clr r0 div $100.,r0 / truncate to max of 99 clr r0 div $10.,r0 ash $4,r0 bis r1,r0 rts pc / To calculate the day of the week (Sunday = 1) an algorithm found in / "The Ready Reference (r) Weekly Planner 1986 ((c) 1986 Ready Reference)" / is used. t2dow: jsr r5,csv / save registers movb year,r4 / low two digits (93) of year mov r4,r0 asr r0 / divide by 4 asr r0 / ignoring any remainder add r0,r4 / add to year movb day,r0 add r0,r4 / add day of month movb month,r0 movb m_magic-1(r0),r3 cmp r0,$2 / February Or January? bgt 1f / no - br movb year,r0 add $1900.,r0 mov r0,-(sp) jsr pc,isleap / are we in a leap year? mov r0,(sp)+ beq 1f / no - br dec r3 / adjust number from magic month table 1: add r3,r4 / add magic number to total cmpb year,$69. / before 1969? bgt 2f / no - br, we're in the 20th century add $6,r4 / adjustment for 21st century 2: mov r4,r1 clr r0 div $7,r0 / divide total by 7 dec r1 / Sunday? bne 3f / no - br mov $7,r1 / yes - set it to day 7 3: mov r1,r0 / put return value in right place jmp cret / (((y) % 4) == 0 && ((y) % 100) != 0 || ((y) % 400) == 0) isleap: clr r0 mov 2(sp),r1 / get year bit $3,r1 / easy check for "mod 4" bne 1f / can't be a leap - br div $100.,r0 / % 100 tst r1 / check remainder bne 2f bit $3,r0 / % 400 beq 2f 1: clr r0 rts pc 2: mov $1,r0 rts pc initoy: tst *$TOYCSR / strobe the clock register clr -(sp) / save previous high byte of register movb *$TOYCSR+1,(sp) / only bit 8 belongs to TOY! bic $1,(sp) / make sure bit 8 (TOY bit) is clear mov $2,r2 / number of double words to send clock 1: mov $35305,r0 / first word of recognition code jsr pc,toyload / send it to clock mov $56243,r0 / second word jsr pc,toyload / send it sob r2,1b / do the whole thing twice tst (sp)+ / clean stack rts pc / send contents of r0 to the TOY. 2(sp) has the old bits 9-15, bit 8 / has been cleared. toyload: mov $16.,r1 / number of bits to send 1: mov r0,r3 / scratch copy bic $177776,r3 / clear all but bit being sent bis 2(sp),r3 / merge in old_csr_bits movb r3,*$TOYCSR+1 / send bit to clock asr r0 / shift pattern down sob r1,1b / do all 16 bits in the word rts pc .globl _gettoy _gettoy: / (void)gettoy(&char[8]); jsr r5,csv / C callable mov 4(r5),r2 / buffer address mov $4,r3 / number of words in buffer 1: mov $16.,r4 / number of bits in word 2: movb *$TOYCSR+1,r0 / low bit of top byte is a clock bit asr r0 / put it in carry ror r1 / ripple in at top end of r1 sob r4,2b / do all 16 bits mov r1,(r2)+ / store the word in the buffer sob r3,1b / do all 4 words jmp cret / and return .data Mtab: .byte 31.,29.,31.,30.,30.,30. .byte 31.,31.,30.,31.,30.,31. m_magic: .byte 1,4,4,0,2,5,0,3,6,1,4,6 errmsg1: timmsg: timbuf: .=.+13. / room for YYMMDDhhmm.ss <\n> \0> _module: .even .bss seconds: .=.+1 minutes: .=.+1 hours: .=.+1 day: .=.+1 month: .=.+1 year: .=.+1 dow: .=.+1 .even bcd: .=.+8. line: .=.+64. program is run on other than a / 93 or 94 an error is printed and the program 'exits' back to the boot / runtime. / / The current date is printed (in the same format used to enter the new date) / and the prompt "Toyset> " is displayed. At that time a string of the form: / YYMMDDHHMM[.SS]\n is entered. The seconsys/pdpstand/disklabel.c 640 0 0 36216 6000412731 10553 /* * Public domain, June 1995 * * @(#)disklabel.c 1.2 (2.11BSD GTE) 1995/07/10 */ #define DKTYPENAMES #include "../h/param.h" #include "saio.h" int Nolabelerr = 1; /* Inhibit spurious label error msgs */ char module[] = "disklabel"; /* This program's name */ char line[80], device[80]; extern long atol(); extern struct iob iob[]; extern struct devsw devsw[]; main() { register int f; register struct disklabel *lp; struct iob *io; printf("%s\n", module); while (1) { printf("Disk? "); gets(line); if (!line[0]) continue; strcpy(device, line); f = open(device, F_WRITE); if (f < 0) { printf("Error opening '%s' for writing\n", device); continue; } io = &iob[f - 3]; if (io->i_flgs & F_TAPE) { printf("Can not label tapes.\n"); continue; } break; } /* * The open() will have retrieved the label sector. This explicit read * is for debugging and testing because the driver's open routine may be * under development and the automatic retrieval of the label is commented * out. */ if (devlabel(io, READLABEL) < 0) { printf("Can not read label sector from '%s'\n", device); return; /* back to Boot */ } lp = &io->i_label; if (lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || dkcksum(lp)) { printf("'%s' is unlabeled or the label is corrupt.\n", device); printf("Proceed? [y/n] "); if (gyon() == 'n') return; /* back to Boot */ /* * We next call the driver's entry which attempts to identify the drive * and set up a default (1 partition) label with the best guess as to * geometry, etc. If this call fails then the driver does not support * labels ('nullsys' is being used in the device table). */ if (devlabel(io, DEFAULTLABEL) < 0) { printf("The '%s' driver does not support labels.\n", devsw[io->i_ino.i_dev].dv_name); return; /* back to Boot */ } } doit(io); return; } doit(io) register struct iob *io; { int c, dirty = 0; struct disklabel *lp = &io->i_label; while (1) { printf("d(isplay) D(efault) m(odify) w(rite) q(uit)? "); c = egetchar("dDmwq"); switch (c) { case 'm': modifylabel(lp); overlapchk(lp); (void)checklabel(lp); /* * We make the assumption that the label was modified - the dirty * flag is set so we can ask if the changes should be discarded on a 'q'. */ dirty = 1; break; case 'w': overlapchk(lp); (void)checklabel(lp); devlabel(io, WRITELABEL); /* * Changed label was committed to disk so we can clear the dirty flag now * and not ask the user if the changes should be kept when a 'q'uit is done. */ dirty = 0; break; case 'd': displaylabel(lp); break; case 'D': devlabel(io, DEFAULTLABEL); dirty = 1; break; case 'q': if (!dirty) return; printf("Label changed. Discard changes [y/n]? "); if (gyon() == 'n') break; return; default: break; } } /* NOTREACHED */ } modifylabel(lp) register struct disklabel *lp; { register int c; while (1) { printf("modify\n"); printf("d(isplay) g(eometry) m(isc) p(artitions) q(uit)? "); c = egetchar("dgmpq"); switch (c) { case 'd': displaylabel(lp); break; case 'g': dogeometry(lp); break; case 'm': domisc(lp); break; case 'p': dopartitions(lp); break; case 'q': return; default: break; } } /* NOTREACHED */ } dogeometry(lp) struct disklabel *lp; { register int c; while (1) { printf("modify geometry\n"); printf("d(isplay) s(ector/trk) t(rk/cyl) c(yl) S(ector/cyl) q(uit)? "); c = egetchar("dstcSq"); switch (c) { case 'd': displaylabel(lp); break; case 's': fillin_int(&lp->d_nsectors, "sectors/track [%d]: ", 512); break; case 't': fillin_int(&lp->d_ntracks, "tracks/cylinder [%d]: ", 127); break; case 'c': fillin_int(&lp->d_ncylinders, "cylinders [%d]: ", 4096); break; case 'S': lp->d_secpercyl= lp->d_nsectors * lp->d_ntracks; fillin_int(&lp->d_secpercyl, "sectors/cylinder [%d]: ", 65535); break; case 'q': if (lp->d_secpercyl == 0) lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; lp->d_secperunit = (long)lp->d_ncylinders * lp->d_secpercyl; return; default: break; } } /* NOTREACHED */ } domisc(lp) register struct disklabel *lp; { register int c; char junk[32]; while (1) { printf("modify misc\n"); printf("d(isplay) t(ype) n(ame) l(abel) f(lags) r(pm) D(rivedata) q(uit)? "); c = egetchar("dtnlfrDq"); switch (c) { case 'd': displaylabel(lp); break; case 't': if (lp->d_type >= DKMAXTYPES) lp->d_type = 0; printf("type [%s]: ", dktypenames[lp->d_type]); gets(line); if (line[0]) lp->d_type = findtype(dktypenames, line, lp->d_type); break; case 'n': strncpy(junk, lp->d_typename, sizeof (lp->d_typename)); junk[sizeof (lp->d_typename)] = '\0'; printf("disk [%s]: ", junk); gets(line); if (line[0]) strncpy(lp->d_typename, line, sizeof (lp->d_typename)); break; case 'l': strncpy(junk, lp->d_packname, sizeof (lp->d_packname)); junk[sizeof (lp->d_packname)] = '\0'; printf("label [%s]: ", junk); gets(line); if (line[0]) strncpy(lp->d_packname, line, sizeof (lp->d_packname)); break; case 'f': doflags(lp); break; case 'r': fillin_int(&lp->d_rpm, "rpm [%d]: ", 32767); break; case 'D': dodrivedata(lp); break; case 'q': return; default: break; } } /* NOTREACHED */ } dodrivedata(lp) struct disklabel *lp; { register u_long *ulp; register int i; for (i = 0, ulp = lp->d_drivedata; i < NDDATA; i++, ulp++) { printf("modify misc drivedata\n"); printf("drivedata #%d [%D]: ", i, *ulp); gets(line); if (line[0]) *ulp = atol(line); } return; } doflags(lp) register struct disklabel *lp; { register int c; while (1) { printf("modify misc flags\n"); printf("d(isplay) c(lear) e(cc) b(adsect) r(emovable) q(uit)? "); c = egetchar("dcerbq"); switch (c) { case 'c': lp->d_flags = 0; break; case 'd': displaylabel(lp); break; case 'r': lp->d_flags |= D_REMOVABLE; break; case 'e': lp->d_flags |= D_ECC; break; case 'b': lp->d_flags |= D_BADSECT; break; case 'q': return; default: break; } } /* NOTREACHED */ } dopartitions(lp) struct disklabel *lp; { register int c; int i; while (1) { printf("modify partitions\n"); printf("d(isplay) n(umber) s(elect) q(uit)? "); c = egetchar("dsnq"); switch (c) { case 'd': displaylabel(lp); break; case 'n': printf("Number of partitions (%d max) [%d]? ", MAXPARTITIONS, lp->d_npartitions); gets(line); if (line[0] == '\0') i = lp->d_npartitions; else i = atoi(line); if (i > 0 && i <= MAXPARTITIONS) lp->d_npartitions = i; break; case 's': printf("a b c d e f g h q(uit)? "); i = getpartnum(); if (i < 0) break; if (i > lp->d_npartitions) lp->d_npartitions = i + 1; dopartmods(lp, i); break; case 'q': return; default: break; } } /* NOTREACHED */ } dopartmods(lp, part) struct disklabel *lp; int part; { char pname = 'a' + part; int i, c; register struct partition *pp = &lp->d_partitions[part]; u_int cyl; daddr_t off, sec, size; printf("sizes and offsets may be given as sectors, cylinders\n"); printf("or cylinders plus sectors: 6200, 32c, 19c10s respectively\n"); while (1) { printf("modify partition '%c'\n", pname); printf("d(isplay) z(ero) t(ype) o(ffset) s(ize) f(rag) F(size) q(uit)? "); c = egetchar("dztosfFq"); switch (c) { case 'z': pp->p_size = 0; pp->p_offset = 0; pp->p_fstype = FS_UNUSED; break; case 'd': displaylabel(lp); break; case 't': if (pp->p_fstype >= FSMAXTYPES) pp->p_fstype = FS_UNUSED; printf("'%c' fstype [%s]: ", pname, fstypenames[pp->p_fstype]); gets(line); if (line[0]) pp->p_fstype = findtype(fstypenames, line, pp->p_fstype); break; case 'o': printf("'%c' offset [%D]: ",pname,pp->p_offset); gets(line); if (line[0] == '\0') break; i = parse_sec_cyl(lp, line, &sec, &cyl); if (i < 0) break; if (cyl) off = lp->d_secpercyl * cyl; else off = 0; off += sec; pp->p_offset = off; break; case 's': printf("'%c' size [%D]: ", pname, pp->p_size); gets(line); if (line[0] == '\0') break; i = parse_sec_cyl(lp, line, &sec, &cyl); if (i < 0) break; if (cyl) size = lp->d_secpercyl * cyl; else size = 0; size += sec; pp->p_size = size; break; case 'f': printf("'%c' frags/fs-block [1]: ", pname); gets(line); if (line[0] == '\0') break; i = atoi(line); if (i <= 0 || i > 255) { printf("frags/block <= 0 || > 255\n"); pp->p_frag = 1; } else pp->p_frag = i; break; case 'F': /* Not really used at the present */ printf("'%c' frag size [1024]: ", pname); gets(line); if (line[0] == '\0') break; i = atoi(line); if (i <= 0 || (i % NBPG)) { printf("fragsize <= 0 || ! % NBPG\n"); pp->p_fsize = 0; } else pp->p_fsize = i; break; case 'q': if (pp->p_fsize == 0) pp->p_fsize = 1024; if (pp->p_frag == 0) pp->p_frag = 1; return; default: break; } } /* NOTREACHED */ } getpartnum() { register int c; c = egetchar("abcdefghq"); if (c == 'q') return(-1); return(c - 'a'); } findtype(list, name, deflt) char **list; char *name; int deflt; { register char **cpp; int i; for (i = 0, cpp = list; *cpp; cpp++, i++) { if (strcmp(*cpp, name) == 0) return(i); } printf("%s not found in list. The possible choices are:\n\n", name); for (cpp = list; *cpp; cpp++) printf(" %s\n", *cpp); putchar('\n'); return(deflt); } /* * Sizes and offsets can be specified in four ways: * * Number of sectors: 32678 * Number of cylinders: 110c * Number of cylinders and sectors: 29c14s * Number of sectors and cylinders: 22s134c * * The trailing 's' or 'c' can be left off in the last two cases. * * The geometry section of the label must have been filled in previously. * A warning is issued if the cylinder or cylinder+sector forms are used * and the necessary geometry information is not present. */ parse_sec_cyl(lp, line, sec, cyl) struct disklabel *lp; char line[]; daddr_t *sec; u_int *cyl; { register char *cp; int error = 0; long tmp, tmpcyl = 0, tmpsec = 0; for (tmp = 0, cp = line; *cp; cp++) { if (*cp >= '0' && *cp <= '9') { tmp *= 10; tmp += (*cp - '0'); } else if (*cp == 'c') { if (tmpcyl) { printf("duplicate 'c'ylinder specified\n"); error = 1; break; } tmpcyl = tmp; tmp = 0; } else if (*cp == 's') { if (tmpsec) { printf("duplicate 's'ector specified\n"); error = 1; break; } tmpsec = tmp; tmp = 0; } else { printf("illegal character '%c'\n", *cp); error = 1; break; } } if (error) return(-1); /* * At this point if either a 's' or 'c' was encountered in the string then * one or both of 'tmpsec' and 'tmpcyl' will be non-zero. If the trailing * character was omitted we need to figure out which variable gets the * contents left in 'tmp' when the terminating null character was seen. This * is because "15c8" and "18s3" are both valid and indicate "15 cylinders + * 8 sectors" and "18 sectors + 3 cylinders" respectively. * * If neither 'tmpsec' or 'tmpcyl' are nonzero then we have a simple sector * number in 'tmp'. */ if (tmpsec || tmpcyl) { if (tmpsec) tmpcyl = tmp; else tmpsec = tmp; } else { tmpsec = tmp; tmpcyl = 0; } /* * It is an error condition to specify a number of cylinders and not * have previously defined the geometry - it is impossible to calculate * the number of sectors in the partition without geometry. */ if (tmpcyl && lp->d_secpercyl == 0) { printf("# cylinders specified but no geometry info present!\n"); return(-1); } /* * Sanity check to make sure erroneous number of cylinders is not believed * due to truncation (number of cylinders is really a 'u_int') */ if (tmpcyl > 65535L) { printf("Number of cylinders specified (%D) is ridiculous!\n", tmpcyl); return(-1); } *cyl = (u_int)tmpcyl; *sec = tmpsec; return(0); } fillin_int(where, fmt, limit) u_int *where; char *fmt; u_int limit; { u_int i; printf(fmt, *where); gets(line); if (line[0]) { i = (u_int)atoi(line); if (i > limit) { printf("%d is out of bounds (> %d)\n", i, limit); return; } *where = i; } } fillin_long(where, fmt, limit) u_long *where; char *fmt; u_long limit; { u_long l; printf(fmt, *where); gets(line); if (line[0]) { l = (u_int)atol(line); if (l > limit) { printf("%D is out of bounds (> %D)\n", l, limit); return; } *where = l; } } gyon() { register int c; c = egetchar("yYnN"); if (c >= 'A' && c <= 'Z') c += ('a' - 'A'); return(c); } egetchar(str) char *str; { register int c; while (1) { c = getchar(); if (index(str, c)) break; putchar('\007'); } putchar(c); putchar('\n'); return(c); } /* * Check disklabel for errors and fill in * derived fields according to supplied values. * * Adapted from the disklabel utility. */ checklabel(lp) register struct disklabel *lp; { register struct partition *pp; int i, errors = 0; char part; if (lp->d_nsectors == 0) { printf("sectors/track %d\n", lp->d_nsectors); return(1); } if (lp->d_ntracks == 0) { printf("tracks/cylinder %d\n", lp->d_ntracks); return(1); } if (lp->d_ncylinders == 0) { printf("cylinders/unit %d\n", lp->d_ncylinders); errors++; } if (lp->d_rpm == 0) Warning("revolutions/minute %d", lp->d_rpm); if (lp->d_secpercyl == 0) lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; if (lp->d_secperunit == 0) lp->d_secperunit = (long) lp->d_secpercyl * lp->d_ncylinders; for (i = 0; i < lp->d_npartitions; i++) { part = 'a' + i; pp = &lp->d_partitions[i]; if (pp->p_size == 0 && pp->p_offset != 0) Warning("partition %c: size 0, but offset %d", part, pp->p_offset); #ifdef notdef if (pp->p_size % lp->d_secpercyl) Warning("partition %c: size %% cylinder-size != 0", part); if (pp->p_offset % lp->d_secpercyl) Warning("partition %c: offset %% cylinder-size != 0", part); #endif if (pp->p_offset > lp->d_secperunit) { printf("partition %c: offset past end of unit %D %D\n", part, pp->p_offset, lp->d_secperunit); errors++; } if (pp->p_offset + pp->p_size > lp->d_secperunit) { printf("partition %c: extends past end of unit %D %D %D\n", part, pp->p_offset, pp->p_size, lp->d_secperunit); errors++; } } for (; i < MAXPARTITIONS; i++) { part = 'a' + i; pp = &lp->d_partitions[i]; if (pp->p_size || pp->p_offset) Warning("unused partition %c: size %D offset %D", 'a' + i, pp->p_size, pp->p_offset); } return(errors); } /*VARARGS1*/ Warning(fmt, a1, a2, a3, a4, a5) char *fmt; { printf("Warning, "); printf(fmt, a1, a2, a3, a4, a5); printf("\n"); } lp->d_flags |= D_REMOVABLE; break; case 'e': lp->d_flags |= D_ECC; break; case 'b': lp->d_flags |= D_BADSECT; break; case 'q': return; default: break; } } /* NOTREACHED */ } dopartitions(lp) struct disklabel *lp; { register int c; int i; while (1) { printf("modify partitions\n"); printf("d(isplay) n(umber) s(esys/pdpstand/displaylab.c 644 0 0 4632 5765736574 10765 /* * 1995/06/08 - Borrowed from disklabel.c * * Many of the unused or invariant fields are omitted from the display. This * has the benefit of having everything fit on one screen - important since * the standalone console driver does not do xon/xoff. * * The partition display is jagged because the minimal printf() function * does not do field padding or justification. */ #define DKTYPENAMES #include #include "saio.h" displaylabel(lp) register struct disklabel *lp; { register int i; register struct partition *pp; char junk[32]; putchar('\n'); if (lp->d_type < DKMAXTYPES) printf("type: %s\n", dktypenames[lp->d_type]); else printf("type: %d\n", lp->d_type); strncpy(junk, lp->d_typename, sizeof (lp->d_typename)); junk[sizeof(lp->d_typename)] = '\0'; printf("disk: %s\n", junk); strncpy(junk, lp->d_packname, sizeof (lp->d_packname)); junk[sizeof(lp->d_packname)] = '\0'; printf("label: %s\n", junk); printf("flags:"); if (lp->d_flags & D_REMOVABLE) printf(" removeable"); if (lp->d_flags & D_ECC) printf(" ecc"); if (lp->d_flags & D_BADSECT) printf(" badsect"); printf("\n"); printf("bytes/sector: %d\n", lp->d_secsize); printf("sectors/track: %d\n", lp->d_nsectors); printf("tracks/cylinder: %d\n", lp->d_ntracks); printf("sectors/cylinder: %d\n", lp->d_secpercyl); printf("cylinders: %d\n", lp->d_ncylinders); printf("rpm: %d\n", lp->d_rpm); printf("drivedata: "); for (i = 0; i < NDDATA; i++) printf("%D ", lp->d_drivedata[i]); printf("\n\n%d partitions:\n", lp->d_npartitions); printf("# size offset fstype [fsize bsize]\n"); pp = lp->d_partitions; for (i = 0; i < lp->d_npartitions; i++, pp++) { if (pp->p_size == 0) continue; printf(" %c: %D %D ", 'a' + i, pp->p_size, pp->p_offset); if ((unsigned) pp->p_fstype < FSMAXTYPES) printf("%s", fstypenames[pp->p_fstype]); else printf("%d", pp->p_fstype); switch (pp->p_fstype) { case FS_V71K: case FS_UNUSED: printf(" %d %d ", pp->p_fsize, pp->p_fsize * pp->p_frag); break; default: printf(" "); break; } printf("\t# (Cyl. %D", pp->p_offset / lp->d_secpercyl); if (pp->p_offset % lp->d_secpercyl) putchar('*'); else putchar(' '); printf("- %D", (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) / lp->d_secpercyl - 1); if (pp->p_size % lp->d_secpercyl) putchar('*'); printf(")\n"); } putchar('\n'); } se "15c8" and "18s3" are both valid and indicate "15 cylinders + * 8 sectors" and "18 sectors + 3 cylsys/OTHERS/ 755 0 12 0 5316467713 5601 sys/OTHERS/dm11/ 755 0 12 0 3771400653 6334 sys/OTHERS/dm11/dhdm.c 444 3 12 4703 3616477112 7510 /* * SCCS id @(#)dhdm.c 2.1 (Berkeley) 8/5/83 */ /* * DM11-BB driver */ #include "dmbb.h" #if NDMBB > 0 #include "param.h" #include "tty.h" #include "file.h" #include "conf.h" #define DMADDR ((struct device *)0170500) struct tty dh11[]; int dhlowdm; /* minor device of first line with DM11-BB */ int dhndm; /* number of lines with DM11-BB (both set in dh.c) */ #define DONE 0200 #define SCENABL 040 #define CLSCAN 01000 #define TURNON 03 /* CD lead, line enable */ #define SECX 010 /* secondary xmit */ #define RQS 04 /* request to send */ #define TURNOFF 1 /* line enable only */ #define CARRIER 0100 #define CLS 040 /* clear to send */ #define SECR 020 /* secondary receive */ struct device { int dmcsr; int dmlstat; int junk[2]; }; #define B1200 9 #define B300 7 /* * Turn on the line associated with the (DH) device dev. */ dmopen(dev) { register struct tty *tp; register struct device *addr; register d; d = minor(dev); tp = &dh11[d]; if(d < dhlowdm || d >= dhlowdm+dhndm) { tp->t_state |= CARR_ON; return; } addr = DMADDR; addr += (d - dhlowdm) >> 4; (void) _spl5(); addr->dmcsr = d&017; addr->dmlstat = TURNON; if (addr->dmlstat&CARRIER) { tp->t_state |= CARR_ON; } addr->dmcsr = IENABLE|SCENABL; while ((tp->t_state&CARR_ON)==0) sleep((caddr_t)&tp->t_rawq, TTIPRI); addr->dmcsr = d&017; if (addr->dmlstat&SECR) { tp->t_ispeed = B1200; tp->t_ospeed = B1200; dhparam(dev); } addr->dmcsr = IENABLE|SCENABL; (void) _spl0(); } /* * Dump control bits into the DM registers. */ dmctl(dev, bits) { register struct device *addr; register d, s; d = minor(dev); if(d < dhlowdm || d >= dhlowdm+dhndm) return; addr = DMADDR; addr += (d - dhlowdm) >> 4; s = spl5(); addr->dmcsr = d&017; addr->dmlstat = bits; addr->dmcsr = IENABLE|SCENABL; splx(s); } /* * DM11 interrupt. * Mainly, deal with carrier transitions. */ dmint(dev) { register struct tty *tp; register struct device *addr; register d; d = minor(dev); addr = DMADDR; addr += d; if (addr->dmcsr&DONE) { tp = &dh11[(d<<4)+(addr->dmcsr&017)]; tp += dhlowdm; if (tp < &dh11[dhlowdm+dhndm]) { wakeup((caddr_t)&tp->t_rawq); if ((addr->dmlstat&CARRIER)==0) { if ((tp->t_state&WOPEN)==0 && (tp->t_local&LNOHANG)==0) { gsignal(tp->t_pgrp, SIGHUP); addr->dmlstat = 0; flushtty(tp, FREAD|FWRITE); } tp->t_state &= ~CARR_ON; } else { tp->t_state |= CARR_ON; } } addr->dmcsr = IENABLE|SCENABL; } } #endif NDMBB ndicate "15 cylinders + * 8 sectors" and "18 sectors + 3 cylsys/OTHERS/dm11/dhfdm.c 444 3 12 420 3563000300 7604 /* * DM-BB fake driver */ /* * SCCS id @(#)dhfdm.c 2.1 (Berkeley) 8/5/83 */ #include "param.h" #include "tty.h" #include "conf.h" struct tty dh11[]; dmopen(dev) { register struct tty *tp; tp = &dh11[minor(dev)]; tp->t_state |= CARR_ON; } dmctl(dev, bits) { } sys/OTHERS/cat/ 755 0 12 0 3771452453 6346 sys/OTHERS/cat/cat.c 444 3 12 2073 3771375123 7347 /* * GP DR11C driver used for C/A/T */ #include "cat.h" #if NCAT > 0 #include "param.h" #include "user.h" #include "tty.h" #ifdef UCB_SCCSID static char sccs_id[] = "@(#)cat.c 3.1"; #endif #define CATADDR ((struct catdev *)0167770) #define PCAT (PZERO+9) #define CATHIWAT 100 #define CATLOWAT 30 struct { int catlock; struct clist oq; } cat; struct catdev { int catcsr; int catbuf; }; ctopen(dev) { if (cat.catlock == 0) { cat.catlock++; CATADDR->catcsr |= IENABLE; return(0); } return(ENXIO); } ctclose() { cat.catlock = 0; catintr(); } ctwrite(dev) { register c; extern lbolt; while ((c=cpass()) >= 0) { spl5(); while (cat.oq.c_cc > CATHIWAT) sleep((caddr_t)&cat.oq, PCAT); while (putc(c, &cat.oq) < 0) sleep((caddr_t)&lbolt, PCAT); catintr(); spl0(); } } catintr() { register int c; if (CATADDR->catcsr&DONE) { if ((c = getc(&cat.oq)) >= 0) { CATADDR->catbuf = c; if (cat.oq.c_cc==0 || cat.oq.c_cc==CATLOWAT) wakeup((caddr_t)&cat.oq); } else { if (cat.catlock==0) CATADDR->catcsr = 0; } } } #endif NCAT > 0 >> 4; (void) _spl5(); addr->dmcsr = d&017; addr->dmlstat = TURNON; if (addr->dmlstat&CARRIER) { tp->t_state |= CARR_ON; } addr->dmcsr = IENABLE|SCENABL; while ((tp->t_state&CARR_ON)==0) sleep((caddr_t)&tp->t_rawq, TTIPRI); addr->dmcsr = d&017; if (addr->dmlstat&SECR) { tp->t_ispeed = B1200; tp->t_ospeed = B1200; dhparam(dev); } addr->dmcsr = IENABLE|SCENABL; (void) _spl0(); } /* * Dump control bits into the DM registers. */sys/OTHERS/rs03.04/ 755 0 12 0 5325716403 6603 sys/OTHERS/rs03.04/hs.c 444 3 12 5527 5321516355 7460 /* * SCCS id @(#)hs.c 2.2 1/3/93 */ /* * RS03/04 disk driver */ #ifdef AUTOCONFIG #include "param.h" #include "hsreg.h" #include "autoconfig.h" hsprobe(addr) struct hsdevice *addr; { stuff(HS_IE | HS_DCLR | HS_GO, (&(addr->hscs1))); WAIT(10); stuff(0, (&(addr->hscs1))); return(ACP_IFINTR); } #else !AUTOCONFIG #include "hs.h" #if NHS > 0 #include "param.h" #include "systm.h" #include "buf.h" #include "conf.h" #include "user.h" #include "seg.h" #include "hsreg.h" #define HS_NRS03BLKS 1024 #define HS_NRS04BLKS 2048 struct hsdevice *HSADDR = (struct hsdevice *)0172040; struct buf hstab; hsroot() { hsattach(HSADDR, 0); } hsattach(addr, unit) register struct hsdevice *addr; { if (unit != 0) return(0); if (fioword(addr) != -1) { HSADDR = addr; if (fioword(&(addr->hsbae)) != -1) hstab.b_flags |= B_RH70; return(1); } HSADDR = (struct hsdevice *) NULL; return(0); } hsstrategy(bp) register struct buf *bp; { register s, mblks; if (minor(bp->b_dev) < 8) mblks = HS_NRS03BLKS; else mblks = HS_NRS04BLKS; if (HSADDR == (struct hsdevice *) NULL) { bp->b_error = ENXIO; goto errexit; } if (bp->b_blkno < 0 || bp->b_blkno >= mblks) { bp->b_error = EINVAL; errexit: bp->b_flags |= B_ERROR; iodone(bp); return; } if ((hstab.b_flags & B_RH70) == 0) mapalloc(bp); bp->av_forw = 0; s = spl5(); if (hstab.b_actf == 0) hstab.b_actf = bp; else hstab.b_actl->av_forw = bp; hstab.b_actl = bp; if (hstab.b_active == 0) hsstart(); splx(s); } hsstart() { register struct hsdevice *hsaddr = HSADDR; register struct buf *bp; register com_addr; if ((bp = hstab.b_actf) == 0) return; hstab.b_active++; com_addr = bp->b_blkno; if(minor(bp->b_dev) < 8) com_addr <<= 1; /* RJS03 */ hsaddr->hscs2 = minor(bp->b_dev) & 07; hsaddr->hsda = com_addr << 1; if (hstab.b_flags & B_RH70) hsaddr->hsbae = bp->b_xmem; hsaddr->hsba = bp->b_un.b_addr; hsaddr->hswc = -(bp->b_bcount >> 1); com_addr = HS_IE | HS_GO | ((bp->b_xmem & 03) << 8); if(bp->b_flags & B_READ) hsaddr->hscs1 = com_addr | HS_RCOM; else hsaddr->hscs1 = com_addr | HS_WCOM; #ifdef HS_DKN dk_busy |= 1 << HS_DKN; dk_numb[HS_DKN]++; dk_wds[HS_DKN] += (bp->b_bcount >> 6) & 01777; #endif HS_DKN } hsintr() { register struct hsdevice *hsaddr = HSADDR; register struct buf *bp; register i; if (hstab.b_active == 0) return; #ifdef HS_DKN dk_busy &= ~(1 << HS_DKN); #endif HS_DKN bp = hstab.b_actf; hstab.b_active = 0; if(hsaddr->hscs1 & HS_TRE) { #ifdef UCB_DEVERR harderr(bp, "hs"); printf("cs1=%b cs2=%b\n", hsaddr->hscs1, HS_BITS, hsaddr->hscs2, HSCS2_BITS); #else deverror(bp, hsaddr->hscs1, hsaddr->hscs2); #endif hsaddr->hscs1 = HS_DCLR | HS_GO; if (++hstab.b_errcnt <= 10) { hsstart(); return; } bp->b_flags |= B_ERROR; } hstab.b_errcnt = 0; hstab.b_actf = bp->av_forw; iodone(bp); hsstart(); } #endif NHS #endif AUTOCONFIG DDR = (struct hsdevice *) NULL; return(0); } hsstrategy(bp) register struct buf *bp; { register s, mblks; if (minor(bp->b_dev) < 8) mblks = HS_NRS03BLKS; else sys/OTHERS/rs03.04/hsreg.h 444 3 12 7106 3562773611 10163 struct hsdevice { short hscs1; /* Control and Status register 1 */ short hswc; /* Word count register */ caddr_t hsba; /* UNIBUS address register */ short hsda; /* Desired address register */ short hscs2; /* Control and Status register 2 */ short hsds; /* Drive Status */ short hser; /* Error register */ short hsas; /* Attention summary */ short hsla; /* Look ahead register used */ short hsdb; /* Data buffer register */ short hsmr; /* Maintenance register */ short hsdt; /* Drive type register */ short hsbae; /* Bus extension (11/70) */ }; /* bits in hscs1 */ #define HS_SC 0100000 /* special condition */ #define HS_TRE 0040000 /* transfer error */ #define HS_MCPE 0020000 /* MASSBUS control bus parity error */ /* bit 12 is unused */ #define HS_DVA 0004000 /* drive available */ #define HS_PSEL 0002000 /* port select */ /* bits 9-8 are the UNIBUS extension bits */ #define HS_RDY 0000200 /* ready */ #define HS_IE 0000100 /* interrupt enable */ /* bits 5-1 are the function */ #define HS_GO 0000001 /* go */ #define HS_BITS \ "\10\20SC\17TRE\16MCPE\14DVA\13PSEL\10RDY\7IE\1GO" /* commands */ #define HS_NOOP 0000000 /* no operation */ #define HS_DCLR 0000010 /* drive clear */ #define HS_SEARCH 0000030 /* search */ #define HS_WCHK 0000050 /* write check */ #define HS_WCOM 0000060 /* write */ #define HS_RCOM 0000070 /* read */ /* bits in hscs2 */ #define HSCS2_DLT 0100000 /* data late */ #define HSCS2_WCE 0040000 /* write check error */ #define HSCS2_PE 0020000 /* parity error */ #define HSCS2_NED 0010000 /* nonexistent drive */ #define HSCS2_NEM 0004000 /* nonexistent memory */ #define HSCS2_PGE 0002000 /* program error */ #define HSCS2_MXF 0001000 /* missed transfer */ #define HSCS2_MDPE 0000400 /* MASSBUS data bus parity error */ #define HSCS2_OR 0000200 /* output ready */ #define HSCS2_IR 0000100 /* input ready */ #define HSCS2_CLR 0000040 /* controller clear */ #define HSCS2_PAT 0000020 /* parity test */ #define HSCS2_BAI 0000010 /* UNIBUS address increment inhibit */ /* bits 2-0 are unit select */ #define HSCS2_BITS \ "\10\20DLT\17WCE\16PE\15NED\14NEM\13PGE\12MXF\11MDPE\10OR\7IR\6CLR\5PAT\4BAI" /* bits in hsds */ #define HSDS_ATA 0100000 /* attention active */ #define HSDS_ERR 0040000 /* error summary */ #define HSDS_PIP 0020000 /* positioning in progress */ #define HSDS_MOL 0010000 /* medium on line */ #define HSDS_WRL 0004000 /* write locked */ #define HSDS_LBT 0002000 /* last block transferred */ /* bit 9 is unused */ #define HSDS_DPR 0000400 /* drive present */ #define HSDS_DRY 0000200 /* drive ready */ /* bits 6-0 are unused */ #define HSDS_BITS \ "\10\20ATA\17ERR\16PIP\15MOL\14WRL\13LBT\11DPR\10DRY" /* bits in hser */ #define HSER_DCK 0100000 /* data check */ #define HSER_UNS 0040000 /* unsafe */ #define HSER_OPI 0020000 /* operation incomplete */ #define HSER_DTE 0010000 /* drive timing error */ #define HSER_WLE 0004000 /* write lock error */ #define HSER_IAE 0002000 /* invalid address error */ #define HSER_AO 0001000 /* address overflow */ /* bits 8-4 are unused */ #define HSER_PAR 0000010 /* bus parity error */ #define HSER_RMR 0000004 /* register modify refused */ #define HSER_ILR 0000002 /* illegal register */ #define HSER_ILF 0000001 /* illegal function */ #define HSER_BITS \ "\10\20DCK\17UNS\16OPI\15DTE\14WLE\13IAE\12AO\4PAR\3RMR\2ILR\1ILF" /* bits in hsdt */ /* bits 15-9 always read as 0 */ #define HSDT_HS03 0000000 /* RS03 */ #define HSDT_HS03SI 0000001 /* RS03 with sector interleave */ #define HSDT_HS04 0000002 /* RS04 */ #define HSDT_HS04SI 0000003 /* RS04 with sector interleave */ printf("%d is out of bounds (> %d)\n", i, limit); return; } *where = i; } } fillin_long(where, fmt, limit) u_long *where; char *fmt; u_long limit; { u_long l; printf(fmt, *where); gets(line); if (line[0]) { l = (u_int)atol(line); if (l > limit) { printf("%D is out of bounds (> %D)\n", l, limit); return; } *where = l; } } gyon() { register int c; c = egetchar("yYnN"); if (c >= 'A' && c <=sys/OTHERS/dvhp/ 755 0 12 0 5325716401 6531 sys/OTHERS/dvhp/dvhp.c 444 3 12 24624 5321516303 7747 /* * SCCS id @(#)dvhp.c 2.2 (2.11BSD GTE) 1/2/93 */ /* * Disk driver for Diva Comp V controller. */ #include "dvhp.h" #if NDVHP > 0 #include "param.h" #include "systm.h" #include "buf.h" #include "conf.h" #include "user.h" #include "hpreg.h" #ifndef INTRLVE #include "inline.h" #endif !INTRLVE #include "uba.h" #define DVHP_NSECT 33 #define DVHP_NTRAC 19 #define DVHP_SDIST 2 #define DVHP_RDIST 6 extern struct size dv_sizes[]; extern struct hpdevice *DVHPADDR; int dvhp_offset[] = { HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, 0, 0, 0, 0 }; struct buf dvhptab; struct buf dvhputab[NDVHP]; #ifdef INTRLVE extern daddr_t dkblock(); #endif void dvhproot() { dvhpattach(DVHPADDR, 0); } dvhpattach(addr, unit) register struct hpdevice *addr; { if (unit != 0) return(0); if ((addr != (struct hpdevice *) NULL) && (fioword(addr) != -1)) { DVHPADDR = addr; if (fioword(&(addr->hpbae)) != -1) dvhptab.b_flags |= B_RH70; return(1); } DVHPADDR = (struct hpdevice *) NULL; return(0); } dvhpstrategy(bp) register struct buf *bp; { register struct buf *dp; register unit; long bn; unit = minor(bp->b_dev) & 077; if (unit >= (NDVHP << 3) || (DVHPADDR == (struct hpdevice *) NULL)) { bp->b_error = ENXIO; goto errexit; } if (bp->b_blkno < 0 || (bn = dkblock(bp)) + (long) ((bp->b_bcount + 511) >> 9) > dv_sizes[unit & 07].nblocks) { bp->b_error = EINVAL; errexit: bp->b_flags |= B_ERROR; iodone(bp); return; } if ((dvhptab.b_flags & B_RH70) == 0) mapalloc(bp); bp->b_cylin = bn / (DVHP_NSECT * DVHP_NTRAC) + dv_sizes[unit & 07].cyloff; unit = dkunit(bp); dp = &dvhputab[unit]; (void) _spl5(); disksort(dp, bp); if (dp->b_active == 0) { dvhpustart(unit); if (dvhptab.b_active == 0) dvhpstart(); } (void) _spl0(); } /* * Unit start routine. * Seek the drive to where the data are * and then generate another interrupt * to actually start the transfer. * If there is only one drive on the controller * or we are very close to the data, don't * bother with the search. If called after * searching once, don't bother to look * where we are, just queue for transfer (to avoid * positioning forever without transferring). */ dvhpustart(unit) register unit; { register struct hpdevice *dvhpaddr = DVHPADDR; register struct buf *dp; struct buf *bp; daddr_t bn; int sn, cn, csn; dvhpaddr->hpcs2.w = unit; dvhpaddr->hpcs1.c[0] = HP_IE; dvhpaddr->hpas = 1 << unit; if (unit >= NDVHP) return; #ifdef DVHP_DKN dk_busy &= ~(1 << (unit + DVHP_DKN)); #endif dp = &dvhputab[unit]; if ((bp=dp->b_actf) == NULL) return; /* * If we have already positioned this drive, * then just put it on the ready queue. */ if (dp->b_active) goto done; dp->b_active++; /* * If drive has just come up, * set up the pack. */ if ((dvhpaddr->hpds & HPDS_VV) == 0) { /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ dvhpaddr->hpcs1.c[0] = HP_IE | HP_PRESET | HP_GO; dvhpaddr->hpof = HPOF_FMT22; } #if NDVHP > 1 /* * If drive is offline, forget about positioning. */ if ((dvhpaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL)) goto done; /* * Not on cylinder at correct position: seek */ bn = dkblock(bp); cn = bp->b_cylin; sn = bn % (DVHP_NSECT * DVHP_NTRAC); sn = (sn + DVHP_NSECT - DVHP_SDIST) % DVHP_NSECT; if (dvhpaddr->hpcc != cn) { dvhpaddr->hpdc = cn; dvhpaddr->hpcs1.c[0] = HP_IE | HP_SEEK | HP_GO; #ifdef DVHP_DKN /* * Mark unit busy for iostat. */ unit += DVHP_DKN; dk_busy |= 1 << unit; dk_numb[unit]++; #endif return; } #endif NDVHP > 1 done: /* * Device is ready to go. * Put it on the ready queue for the controller. */ dp->b_forw = NULL; if (dvhptab.b_actf == NULL) dvhptab.b_actf = dp; else dvhptab.b_actl->b_forw = dp; dvhptab.b_actl = dp; } /* * Start up a transfer on a drive. */ dvhpstart() { register struct hpdevice *dvhpaddr = DVHPADDR; register struct buf *bp; struct buf *dp; register unit; daddr_t bn; int dn, sn, tn, cn; loop: /* * Pull a request off the controller queue. */ if ((dp = dvhptab.b_actf) == NULL) return; if ((bp = dp->b_actf) == NULL) { dvhptab.b_actf = dp->b_forw; goto loop; } /* * Mark controller busy and * determine destination of this request. */ dvhptab.b_active++; unit = minor(bp->b_dev) & 077; dn = dkunit(bp); bn = dkblock(bp); cn = bn / (DVHP_NSECT * DVHP_NTRAC) + dv_sizes[unit & 07].cyloff; sn = bn % (DVHP_NSECT * DVHP_NTRAC); tn = sn / DVHP_NSECT; sn = sn % DVHP_NSECT; /* * Select drive. */ dvhpaddr->hpcs2.w = dn; /* * Check that it is ready and online. */ if ((dvhpaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL)) { dvhptab.b_active = 0; dvhptab.b_errcnt = 0; dp->b_actf = bp->av_forw; bp->b_flags |= B_ERROR; iodone(bp); goto loop; } if (dvhptab.b_errcnt >= 16 && (bp->b_flags & B_READ)) { dvhpaddr->hpof = dvhp_offset[dvhptab.b_errcnt & 017] | HPOF_FMT22; dvhpaddr->hpcs1.w = HP_OFFSET | HP_GO; while ((dvhpaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY) ; } dvhpaddr->hpdc = cn; dvhpaddr->hpda = (tn << 8) + sn; dvhpaddr->hpba = bp->b_un.b_addr; if (dvhptab.b_flags & B_RH70) dvhpaddr->hpbae = bp->b_xmem; dvhpaddr->hpwc = -(bp->b_bcount >> 1); /* * Warning: unit is being used as a temporary. */ unit = ((bp->b_xmem & 3) << 8) | HP_IE | HP_GO; if (bp->b_flags & B_READ) unit |= HP_RCOM; else unit |= HP_WCOM; dvhpaddr->hpcs1.w = unit; #ifdef DVHP_DKN dk_busy |= 1 << (DVHP_DKN + NDVHP); dk_numb[DVHP_DKN + NDVHP]++; dk_wds[DVHP_DKN + NDVHP] += bp->b_bcount >> 6; #endif DVHP_DKN } /* * Handle a disk interrupt. */ dvhpintr() { register struct hpdevice *dvhpaddr = DVHPADDR; register struct buf *dp; struct buf *bp; register unit; int as, i, j; as = dvhpaddr->hpas & 0377; if (dvhptab.b_active) { #ifdef DVHP_DKN dk_busy &= ~(1 << (DVHP_DKN + NDVHP)); #endif DVHP_DKN /* * Get device and block structures. Select the drive. */ dp = dvhptab.b_actf; bp = dp->b_actf; unit = dkunit(bp); dvhpaddr->hpcs2.c[0] = unit; /* * Check for and process errors. */ if (dvhpaddr->hpcs1.w & HP_TRE) { /* error bit */ while ((dvhpaddr->hpds & HPDS_DRY) == 0) ; if (dvhpaddr->hper1 & HPER1_WLE) { /* * Give up on write locked devices * immediately. */ printf("dvhp%d: write locked\n", unit); bp->b_flags |= B_ERROR; } else { /* * After 28 retries (16 without offset and * 12 with offset positioning), give up. */ if (++dvhptab.b_errcnt > 28) { bp->b_flags |= B_ERROR; #ifdef UCB_DEVERR harderr(bp, "dvhp"); printf("cs2=%b er1=%b\n", dvhpaddr->hpcs2.w, HPCS2_BITS, dvhpaddr->hper1, HPER1_BITS); #else deverror(bp, dvhpaddr->hpcs2.w, dvhpaddr->hper1); #endif } else dvhptab.b_active = 0; } #ifdef UCB_ECC /* * If soft ecc, correct it (continuing * by returning if necessary). * Otherwise, fall through and retry the transfer. */ if ((dvhpaddr->hper1 & (HPER1_DCK | HPER1_ECH)) == HPER1_DCK) if (dvhpecc(bp)) return; #endif dvhpaddr->hpcs1.w = HP_TRE | HP_IE | HP_DCLR | HP_GO; if ((dvhptab.b_errcnt & 07) == 4) { dvhpaddr->hpcs1.w = HP_RECAL | HP_IE | HP_GO; while ((dvhpaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY) ; } } if (dvhptab.b_active) { if (dvhptab.b_errcnt) { dvhpaddr->hpcs1.w = HP_RTC | HP_GO; while ((dvhpaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY) ; } dvhptab.b_active = 0; dvhptab.b_errcnt = 0; dvhptab.b_actf = dp->b_forw; dp->b_active = 0; dp->b_actf = bp->av_forw; bp->b_resid = -(dvhpaddr->hpwc << 1); iodone(bp); dvhpaddr->hpcs1.w = HP_IE; if (dp->b_actf) dvhpustart(unit); } as &= ~(1 << unit); } else { if (as == 0) dvhpaddr->hpcs1.w = HP_IE; dvhpaddr->hpcs1.c[1] = HP_TRE >> 8; } for (unit = 0; unit < NDVHP; unit++) if (as & (1 << unit)) dvhpustart(unit); dvhpstart(); } #ifdef UCB_ECC #define exadr(x,y) (((long)(x) << 16) | (unsigned)(y)) /* * Correct an ECC error and restart the i/o to complete * the transfer if necessary. This is quite complicated because * the transfer may be going to an odd memory address base * and/or across a page boundary. */ dvhpecc(bp) register struct buf *bp; { register struct hpdevice *dvhpaddr = DVHPADDR; register unsigned byte; ubadr_t bb, addr; long wrong; int bit, wc; unsigned ndone, npx; int ocmd; int cn, tn, sn; daddr_t bn; struct ubmap *ubp; /* * ndone is #bytes including the error * which is assumed to be in the last disk page transferred. */ wc = dvhpaddr->hpwc; ndone = (wc * NBPW) + bp->b_bcount; npx = ndone / PGSIZE; printf("dvhp%d%c: soft ecc bn %D\n", dkunit(bp), 'a' + (minor(bp->b_dev) & 07), bp->b_blkno + (npx - 1)); wrong = dvhpaddr->hpec2; if(wrong == 0) { dvhpaddr->hpof = HPOF_FMT22; dvhpaddr->hpcs1.w |= HP_IE; return (0); } /* * Compute the byte/bit position of the err * within the last disk page transferred. * Hpec1 is origin-1. */ byte = dvhpaddr->hpec1 - 1; bit = byte & 07; byte >>= 3; byte += ndone - PGSIZE; bb = exadr(bp->b_xmem, bp->b_un.b_addr); wrong <<= bit; /* * Correct until mask is zero or until end of transfer, * whichever comes first. */ while (byte < bp->b_bcount && wrong != 0) { addr = bb + byte; if (bp->b_flags & (B_MAP | B_UBAREMAP)) { /* * Simulate UNIBUS map if UNIBUS transfer. */ ubp = UBMAP + ((addr >> 13) & 037); addr = exadr(ubp->ub_hi, ubp->ub_lo) + (addr & 017777); } putmemc(addr, getmemc(addr) ^ (int) wrong); byte++; wrong >>= 8; } dvhptab.b_active++; if (wc == 0) return (0); /* * Have to continue the transfer. Clear the drive * and compute the position where the transfer is to continue. * We have completed npx sectors of the transfer already. */ ocmd = (dvhpaddr->hpcs1.w & ~HP_RDY) | HP_IE | HP_GO; dvhpaddr->hpcs2.w = dkunit(bp); dvhpaddr->hpcs1.w = HP_TRE | HP_DCLR | HP_GO; bn = dkblock(bp); cn = bp->b_cylin - bn / (DVHP_NSECT * DVHP_NTRAC); bn += npx; addr = bb + ndone; cn += bn / (DVHP_NSECT * DVHP_NTRAC); sn = bn % (DVHP_NSECT * DVHP_NTRAC); tn = sn / DVHP_NSECT; sn %= DVHP_NSECT; dvhpaddr->hpdc = cn; dvhpaddr->hpda = (tn << 8) + sn; dvhpaddr->hpwc = ((int)(ndone - bp->b_bcount)) / NBPW; dvhpaddr->hpba = (int) addr; if (dvhptab.b_flags & B_RH70) dvhpaddr->hpbae = (int) (addr >> 16); dvhpaddr->hpcs1.w = ocmd; return (1); } #endif UCB_ECC #endif NDVHP intf("a b c d e f g h q(uit)? "); i = getpartnum(); if (i < 0) break; if (i > lp->d_npartitsys/OTHERS/dvhp/dvhp_stand.c 444 3 12 5727 4001144246 11120 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dvhp.c 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * RP04/RP06 disk driver * Modified for Diva Comp V Controller - 33 SEC/TRACK */ #include #include #include "saio.h" struct device { union { int w; char c[2]; } dvhpcs1; /* Control and Status register 1 */ int dvhpwc; /* Word count register */ caddr_t dvhpba; /* UNIBUS address register */ int dvhpda; /* Desired address register */ union { int w; char c[2]; } dvhpcs2; /* Control and Status register 2*/ int dvhpds; /* Drive Status */ int dvhper1; /* Error register 1 */ int dvhpas; /* Attention Summary */ int dvhpla; /* Look ahead */ int dvhpdb; /* Data buffer */ int dvhpmr; /* Maintenance register */ int dvhpdt; /* Drive type */ int dvhpsn; /* Serial number */ int dvhpof; /* Offset register */ int dvhpdc; /* Desired Cylinder address register*/ int dvhpcc; /* Current Cylinder */ int dvhper2; /* Error register 2 */ int dvhper3; /* Error register 3 */ int dvhpec1; /* Burst error bit position */ int dvhpec2; /* Burst error bit pattern */ int dvhpbae; /* 11/70 bus extension */ int dvhpcs3; }; int cyloff[] = /* Cylinder offsets of logical drives */ { 0, 15, 215, 415, 615, 15, 415, 15, }; #define DVHPADDR ((struct device *)0176700) #define NSECT 33 #define NTRAC 19 #define SDIST 2 #define RDIST 6 #define P400 020 #define M400 0220 #define P800 040 #define M800 0240 #define P1200 060 #define M1200 0260 #define GO 01 #define PRESET 020 #define RTC 016 #define OFFSET 014 #define SEARCH 030 #define RECAL 06 #define DCLR 010 #define WCOM 060 #define RCOM 070 #define IE 0100 #define PIP 020000 #define DRY 0200 #define ERR 040000 #define TRE 040000 #define DCK 0100000 #define WLE 04000 #define ECH 0100 #define VV 0100 #define FMT22 010000 dvhpstrategy(io, func) register struct iob *io; { register unit; register i; daddr_t bn; int sn, cn, tn; if (((unit = io->i_unit) & 0100) == 0) bn = io->i_bn; else { unit &= 03; bn = io->i_bn; bn -= io->i_boff; i = unit + 1; unit = bn%i; bn /= i; bn += io->i_boff; } DVHPADDR->dvhpcs2.w = (unit&070)>>3; if((DVHPADDR->dvhpds & VV) == 0) { DVHPADDR->dvhpcs1.c[0] = PRESET|GO; DVHPADDR->dvhpof = FMT22; } cn = bn/(NSECT*NTRAC) + cyloff[unit&07]; sn = bn%(NSECT*NTRAC); tn = sn/NSECT; sn = sn%NSECT; DVHPADDR->dvhpdc = cn; DVHPADDR->dvhpda = (tn << 8) + sn; DVHPADDR->dvhpba = io->i_ma; DVHPADDR->dvhpwc = -(io->i_cc>>1); unit = (segflag << 8) | GO; if (func == READ) unit |= RCOM; else if (func == WRITE) unit |= WCOM; DVHPADDR->dvhpcs1.w = unit; while ((DVHPADDR->dvhpcs1.w&DRY) == 0) ; if (DVHPADDR->dvhpcs1.w & TRE) { printf("disk error: cyl=%d track=%d sect=%d cs2=%o, er1=%o\n", cn, tn, sn, DVHPADDR->dvhpcs2, DVHPADDR->dvhper1); return(-1); } return(io->i_cc); } atus register 1 */ int dvhpwc; /* Word sys/OTHERS/rp03/ 755 0 12 0 5325716403 6356 sys/OTHERS/rp03/rp.c 444 3 12 7773 5321516025 7241 /* * SCCS id @(#)rp.c 2.2 (2.11BSD GTE) 1/2/93 */ /* * RP03 disk driver */ #ifdef AUTOCONFIG #include "param.h" #include "rpreg.h" #include "autoconfig.h" rpprobe(addr) struct rpdevice *addr; { stuff(RP_IDE | RP_IDLE | RP_GO, (&(addr->rpcs.w))); WAIT(10); stuff(0, (&(addr->rpcs.w))); return(ACP_IFINTR); } #else !AUTOCONFIG #include "rp.h" #if NRP > 0 #include "param.h" #include "systm.h" #include "buf.h" #include "conf.h" #include "user.h" #include "rpreg.h" struct rpdevice *RPADDR = (struct rpdevice *)0176710; #ifdef SHOULD_WORK_BUT_DOESN'T /* * Apparently, some controllers have problems getting to the "spare* * 6 tracks on the RP03's. The second set of tables ignores those tracks. */ struct size rp_sizes[] = { 10400, 0, /* cyl 0 - 51 */ 5200, 52, /* cyl 52 - 77 */ 65600, 78, /* cyl 78 - 405 */ 0, 0, /* not defined */ 0, 0, /* not defined */ 0, 0, /* not defined */ 0, 0, /* not defined */ 81200, 0, /* cyl 0 - 405 */ }; #endif SHOULD_WORK_BUT_DOESN'T struct size rp_sizes[] = { 10400, 0, /* cyl 0 - 51 */ 5200, 52, /* cyl 52 - 77 */ 64400, 78, /* cyl 78 - 399 */ 0, 0, /* not defined */ 0, 0, /* not defined */ 0, 0, /* not defined */ 0, 0, /* not defined */ 80000, 0, /* cyl 0 - 399 */ }; struct buf rptab; #define RP_NSECT 10 #define RP_NTRAC 20 rpattach(addr, unit) struct rpdevice *addr; { if (unit != 0) return(0); RPADDR = addr; return(1); } rpstrategy(bp) register struct buf *bp; { register struct buf *dp; register int unit; long sz; unit = minor(bp->b_dev); sz = bp->b_bcount; sz = (sz + 511) >> 9; if (RPADDR == (struct rpdevice *) NULL) { bp->b_error = ENXIO; goto errexit; } if (unit >= (NRP << 3) || bp->b_blkno + sz > rp_sizes[unit & 07].nblocks) { bp->b_error = EINVAL; errexit: bp->b_flags |= B_ERROR; iodone(bp); return; } mapalloc(bp); bp->av_forw = NULL; unit >>= 3; (void) _spl5(); dp = &rptab; if (dp->b_actf == NULL) dp->b_actf = bp; else dp->b_actl->av_forw = bp; dp->b_actl = bp; if (dp->b_active == NULL) rpstart(); (void) _spl0(); } rpstart() { register struct rpdevice *rpaddr = RPADDR; register struct buf *bp; register int unit; int com, cn, tn, sn, dn; daddr_t bn; if ((bp = rptab.b_actf) == NULL) return; rptab.b_active++; unit = minor(bp->b_dev); dn = unit >> 3; bn = bp->b_blkno; cn = bn / (RP_NTRAC * RP_NSECT) + rp_sizes[unit & 07].cyloff; sn = bn % (RP_NTRAC * RP_NSECT); tn = sn / RP_NSECT; sn = sn % RP_NSECT; rpaddr->rpcs.w = (dn << 8); rpaddr->rpda = (tn << 8) | sn; rpaddr->rpca = cn; rpaddr->rpba = bp->b_un.b_addr; rpaddr->rpwc = -(bp->b_bcount >> 1); com = ((bp->b_xmem & 3) << 4) | RP_IDE | RP_GO; if (bp->b_flags & B_READ) com |= RP_RCOM; else com |= RP_WCOM; rpaddr->rpcs.w |= com; #ifdef RP_DKN dk_busy |= 1 << RP_DKN; dk_numb[RP_DKN]++; dk_wds[RP_DKN] += bp->b_bcount >> 6; #endif RP_DKN } rpintr() { register struct rpdevice *rpaddr = RPADDR; register struct buf *bp; register int ctr; if (rptab.b_active == NULL) return; #ifdef RP_DKN dk_busy &= ~(1 << RP_DKN); #endif RP_DKN bp = rptab.b_actf; rptab.b_active = NULL; if (rpaddr->rpcs.w & RP_ERR) { while ((rpaddr->rpcs.w & RP_RDY) == 0) ; if (rpaddr->rper & RPER_WPV) /* * Give up on write locked devices * immediately. */ printf("rp%d: write locked\n", minor(bp->b_dev)); else { #ifdef UCB_DEVERR harderr(bp, "rp"); printf("er=%b ds=%b\n", rpaddr->rper, RPER_BITS, rpaddr->rpds, RPDS_BITS); #else deverror(bp, rpaddr->rper, rpaddr->rpds); #endif if(rpaddr->rpds & (RPDS_SUFU | RPDS_SUSI | RPDS_HNF)) { rpaddr->rpcs.c[0] = RP_HSEEK | RP_GO; ctr = 0; while ((rpaddr->rpds & RPDS_SUSU) && --ctr) ; } rpaddr->rpcs.w = RP_IDLE | RP_GO; ctr = 0; while ((rpaddr->rpcs.w & RP_RDY) == 0 && --ctr) ; if (++rptab.b_errcnt <= 10) { rpstart(); return; } } bp->b_flags |= B_ERROR; } rptab.b_errcnt = 0; rptab.b_actf = bp->av_forw; bp->b_resid = -(rpaddr->rpwc << 1); iodone(bp); rpstart(); } #endif NRP #endif AUTOCONFIG vhptasys/OTHERS/rp03/rpreg.h 444 3 12 7074 3562773625 7756 struct rpdevice { short rpds; short rper; union { short w; char c[2]; } rpcs; short rpwc; caddr_t rpba; short rpca; short rpda; short rpm1; short rpm2; short rpm3; short suca; short silo; }; /* bits in rpds */ #define RPDS_SURDY 0100000 /* selected unit ready */ #define RPDS_SUOL 0040000 /* selected unit on line */ #define RPDS_RP03 0020000 /* selected unit RP03 */ #define RPDS_HNF 0010000 /* header not found */ #define RPDS_SUSI 0004000 /* selected unit seek incomplete */ #define RPDS_SUSU 0002000 /* selected unit seek underway */ #define RPDS_SUFU 0001000 /* selected unit file unsafe */ #define RPDS_SUWP 0000400 /* selected unit write protected */ /* bits 7-0 are attention bits */ #define RPDS_BITS \ "\10\20SURDY\17SUOL\16RP03\15HNF\14SUSI\13SUSU\12SUFU\11SUWP" /* bits in rper */ #define RPER_WPV 0100000 /* write protect violation */ #define RPER_FUV 0040000 /* file unsafe violation */ #define RPER_NXC 0020000 /* nonexistent cylinder */ #define RPER_NXT 0010000 /* nonexistent track */ #define RPER_NXS 0004000 /* nonexistent sector */ #define RPER_PROG 0002000 /* program error */ #define RPER_FMTE 0001000 /* format error */ #define RPER_MODE 0000400 /* mode error */ #define RPER_LPE 0000200 /* longitudinal parity error */ #define RPER_WPE 0000100 /* word parity error */ #define RPER_CSME 0000040 /* checksum error */ #define RPER_TIMEE 0000020 /* timing error */ #define RPER_WCE 0000010 /* write check error */ #define RPER_NXME 0000004 /* nonexistent memory */ #define RPER_EOP 0000002 /* end of pack */ #define RPER_DSKERR 0000001 /* disk error */ #define RPER_BITS \ "\10\20WPV\17FUV\16NXC\15NXT\14NXS\13PROG\12FMTE\11MODE\10LPE\ \7WPE\6CSME\5TIMEE\4WCE\3NXME\2EOP\1DSKERR" /* bits in rpcs */ #define RP_ERR 0100000 /* error */ #define RP_HE 0040000 /* hard error */ #define RP_ATE 0020000 /* attention interrupt enable */ #define RP_MODE 0010000 /* mode */ #define RP_HDR 0004000 /* header */ /* bits 10-8 are drive select */ #define RP_RDY 0000200 /* ready */ #define RP_IDE 0000100 /* interrupt on done (error) enable */ /* bits 5-4 are the UNIBUS extension bits */ /* bits 3-1 are the function */ #define RP_GO 0000001 /* go */ #define RP_BITS \ "\10\20ERR\17HE\16ATE\15MODE\14HDR\10RDY\7IDE\1GO" /* commands */ #define RP_IDLE 0000000 /* idle */ #define RP_WCOM 0000002 /* write */ #define RP_RCOM 0000004 /* read */ #define RP_WCHK 0000006 /* write check */ #define RP_SEEK 0000010 /* seek */ #define RP_WNS 0000012 /* write (no seek) */ #define RP_HSEEK 0000014 /* home seek */ #define RP_RNS 0000016 /* read (no seek) */ /* bits in rpm1 */ /* bits 15-13 are unused */ #define RPM1_SORDY 0010000 /* silo out ready */ #define RPM1_SIRDY 0004000 /* silo in ready */ #define RPM1_CONTROL 0002000 /* control */ #define RPM1_SETHEAD 0001000 /* set head */ #define RPM1_SETCYL 0000400 /* set cylinder */ /* bits 7-0 are the bus out signals */ #define RPM1_BITS \ "\10\15SORDY\14SIRDY\13CONTROL\12SETHEAD\11SETCYL" /* bits in rpm3 */ #define RPM3_MRO 0100000 /* maintenance read only */ #define RPM3_MRDY 0040000 /* maintenance ready */ #define RPM3_MOL 0020000 /* maintenance on line */ #define RPM3_MIDX 0010000 /* maintenance index */ #define RPM3_MFU 0004000 /* maintenance file unsafe */ #define RPM3_MSI 0002000 /* maintenance seek incomplete */ #define RPM3_MECYL 0001000 /* maintenance end of cylinder */ #define RPM3_MSECT 0000400 /* maintenance sector */ /* bits 7-1 are unused */ #define RPM3_CLK 0000001 /* maintenance clock */ #define RPM3_BITS \ "\10\20MRO\17MRDY\16MOL\15MIDX\14MFU\13MSI\12MECYL\11MSECT\1CLK" s.c[0] = RP_HSEEK | RP_GO; ctr = 0; while ((rpaddr->rpds & RPDS_SUSU) && --ctr) ; } rpaddr->rpcs.w = RP_IDLE | RP_GO; ctr = 0; while ((rpaddr->rpcs.w & RP_RDY) == 0 && --ctr) ; if (++rptab.b_errcnt <= 10) { rpstart(); return; } } bp->b_flags |= B_ERROR; } rptab.b_errcnt = 0; rptab.b_actf = bp->av_forw; bp->b_resid = -(rpaddr->rpwc << 1); iodone(bp); rpstart(); } #endif NRP #endif AUTOCONFIG vhptasys/OTHERS/rp03/rp03.b 444 3 12 1610 3746613127 7375 =============================================================================== Subject: bsd 2.9 boot problems with rp03 disk I am running an 11/73 with rp03-emulating disks under 2.9. My problem was that the l.s file doesn't know about rp03's as root devices, and the kernel doesn't know what to do with the first interrupt from the root device, or something similar. This was despite the fact that the installation document claims that 2.9 supports rp's as the root device. It was easy to fix -- I just added another #if - #endif case for rp at vector 254 in the l.s code. After this, our compiled systems booted without problem. Also: I found that the bootstrap code (marked UNTESTED) in boot.s won't work, so we couldn't do AUTOBOOTS until I replaced that section with the code listed in the manual page boot(8). =============================================================================== file unsafe violation */ #define RPER_NXC 0020000 /* nonexistent cylinder */ #define RPER_NXT 0010000 /* nonexistent sys/OTHERS/rp03/rpuboot.s 640 3 12 11352 4016524736 10344 / RP03 bootstrap. / / disk boot program to load and transfer / to a unix entry. / for use with 1 KB byte blocks, CLSIZE is 2. / NDIRIN is the number of direct inode addresses (currently 4) / assembled size must be <= 512; if > 494, the 16-byte a.out header / must be removed cyl = 0. / cylinder offset of filesys to read from / options: readname= 1 / 1->normal, if default not found, read name / from console. 0->loop on failure, saves 36 bytes prompt = 1 / 1->prompt ('>') before reading from console / 0-> no prompt, saves 8 bytes / constants: CLSIZE = 2. / physical disk blocks per logical block CLSHFT = 1. / shift to multiply by CLSIZE BSIZE = 512.*CLSIZE / logical block size INOSIZ = 64. / size of inode in bytes NDIRIN = 4. / number of direct inode addresses ADDROFF = 12. / offset of first address in inode INOPB = BSIZE\/INOSIZ / inodes per logical block INOFF = 31. / inode offset = (INOPB * (SUPERB+1)) - 1 PBSHFT = -4 / shift to divide by inodes per block WC = -256.*CLSIZE / word count / The boot options and device are placed in the last SZFLAGS bytes / at the end of core by the kernel for autobooting. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 CHECKWORD= 6 .. = ENDCORE-512.-SZFLAGS / save room for boot flags / entry is made by jsr pc,*$0 / so return can be rts pc / establish sp, copy / program up to end of core. start: mov $..,sp mov sp,r1 clr r0 1: mov (r0)+,(r1)+ cmp r1,$end blo 1b jmp *$2f / On error, restart from here. restart: / clear core to make things clean clr r0 2: clr (r0)+ cmp r0,sp blo 2b / initialize rp clr *$rpcs / selects drive zero / at origin, read pathname .if prompt mov $'>, r0 jsr pc, putc .endif / spread out in array 'names', one / component every 14 bytes. mov $names,r1 1: mov r1,r2 2: jsr pc,getc cmp r0,$'\n beq 1f cmp r0,$'/ beq 3f movb r0,(r2)+ br 2b 3: cmp r1,r2 beq 2b add $14.,r1 br 1b / now start reading the inodes / starting at the root and / going through directories 1: mov $names,r1 mov $2,r0 1: clr bno jsr pc,iget tst (r1) beq 1f 2: jsr pc,rmblk br restart mov $buf,r2 3: mov r1,r3 mov r2,r4 add $16.,r2 tst (r4)+ beq 5f 4: cmpb (r3)+,(r4)+ bne 5f cmp r4,r2 blo 4b mov -16.(r2),r0 add $14.,r1 br 1b 5: cmp r2,$buf+BSIZE blo 3b br 2b / read file into core until / a mapping error, (no disk address) 1: clr r1 1: jsr pc,rmblk br 1f mov $buf,r2 2: mov (r2)+,(r1)+ cmp r2,$buf+BSIZE blo 2b br 1b / relocate core around / assembler header 1: clr r0 cmp (r0),$407 bne 2f 1: mov 20(r0),(r0)+ cmp r0,sp blo 1b / enter program and / restart if return 2: mov ENDCORE-BOOTOPTS, r4 mov ENDCORE-BOOTDEV, r3 mov ENDCORE-CHECKWORD, r2 jsr pc,*$0 br restart / get the inode specified in r0 iget: add $INOFF,r0 mov r0,r5 ash $PBSHFT,r0 bic $!7777,r0 mov r0,dno clr r0 jsr pc,rblk bic $!17,r5 mul $INOSIZ,r5 add $buf,r5 mov $inod,r4 1: mov (r5)+,(r4)+ cmp r4,$inod+INOSIZ blo 1b rts pc / read a mapped block / offset in file is in bno. / skip if success, no skip if fail / the algorithm only handles a single / indirect block. that means that / files longer than NDIRIN+128 blocks cannot / be loaded. rmblk: add $2,(sp) mov bno,r0 cmp r0,$NDIRIN blt 1f mov $NDIRIN,r0 1: mov r0,-(sp) asl r0 add (sp)+,r0 add $addr+1,r0 movb (r0)+,dno movb (r0)+,dno+1 movb -3(r0),r0 bne 1f tst dno beq 2f 1: jsr pc,rblk mov bno,r0 inc bno sub $NDIRIN,r0 blt 1f ash $2,r0 mov buf+2(r0),dno mov buf(r0),r0 bne rblk tst dno bne rblk 2: sub $2,(sp) 1: rts pc read = 4 go = 1 rpcs = 176710 rpda = 176724 rpca = 176722 rpba = 176720 / rp03 disk driver. / low order address in dno, / high order in r0. rblk: mov r1,-(sp) mov dno,r1 .if CLSIZE-1 ashc $CLSHFT,r0 / multiply by CLSIZE .endif div $20.*10.,r0 .if cyl add $cyl,r0 .endif mov r0,*$rpca clr r0 div $10.,r0 swab r0 bis r1,r0 mov r0,*$rpda mov $rpba,r1 mov $buf,(r1) mov $WC,-(r1) mov $read+go,-(r1) 1: tstb (r1) bge 1b mov (sp)+,r1 rts pc tks = 177560 tkb = 177562 / read and echo a teletype character / if *cp is nonzero, it is the next char to simulate typing / after the defnm is tried once, read a name from the console getc: movb *cp, r0 beq 2f inc cp .if readname br putc 2: mov $tks,r0 inc (r0) 1: tstb (r0) bge 1b mov tkb,r0 bic $!177,r0 cmp r0,$'A blo 2f cmp r0,$'Z bhi 2f add $'a-'A,r0 .endif 2: tps = 177564 tpb = 177566 / print a teletype character putc: tstb *$tps bge putc mov r0,*$tpb cmp r0,$'\r bne 1f mov $'\n,r0 br putc 1: rts pc cp: defnm defnm: end: inod = ..-512.-BSIZE / room for inod, buf, stack addr = inod+ADDROFF / first address in inod buf = inod+INOSIZ bno = buf+BSIZE dno = bno+2 names = dno+2 f *bp; { register struct hpdevice *dvhpaddr = DVHPADDR; register unsigned byte; ubadr_t bb, addr; long wrong; int bit, wc; unsigned ndone, npx; int ocmd; int cn, tn, sn; daddr_t bn; struct ubmap *ubp; /* * ndone is #bytes including the error * which is assumed tsys/OTHERS/rp03/rp.pdpstand.c 640 3 12 2041 4302057162 11032 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)rp.c 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * rp03 disk driver */ #include "../h/param.h" #include "../h/inode.h" #include "../pdpuba/rpreg.h" #include "saio.h" #define RPADDR ((struct rpdevice *) 0176710) rpstrategy(io, func) register struct iob *io; { int com, cn, tn, sn; cn = io->i_bn/(20*10); sn = io->i_bn%(20*10); tn = sn/10; sn = sn%10; RPADDR->rpcs.w = (io->i_unit<<8); RPADDR->rpda = (tn<<8) | sn; RPADDR->rpca = cn; RPADDR->rpba = io->i_ma; RPADDR->rpwc = -(io->i_cc>>1); com = (segflag<<4)|RP_GO; if (func == READ) com |= RP_RCOM; else com |= RP_WCOM; RPADDR->rpcs.w |= com; while ((RPADDR->rpcs.w & RP_RDY) == 0) continue; if (RPADDR->rpcs.w < 0) { /* error bit */ printf("disk error: cyl=%d track=%d sect=%d er=%o ds=%o\n", cn, tn, sn, RPADDR->rper, RPADDR->rpds); return(-1); } return(io->i_cc); } device are placed in the last SZFLAGS bytes / at the end of core by the kernel for autobooting. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 CHECKWORD= 6 .. = ENDCORE-512.-SZFLAGS / save room for boot flags / entry is made by jsr pc,*$0 / so return can be rts pc / establish sp, copy / program up to end of core. start: mov $..,sp mov sp,r1 clr r0 1: mov (r0)+,(rsys/OTHERS/cr11/ 755 0 12 0 3771402307 6336 sys/OTHERS/cr11/cr.c 444 3 12 10353 3552650412 7215 /* * SCCS id @(#)cr.c 2.1 (Berkeley) 8/5/83 */ /* Module Name: cr.c -- card reader driver for Unix Installation: Function: Provide the interface necessary to handle the CR-11 card reader. Globals contained: cr11 control info and wait channel address Routines contained: cropen process-level open request crclose process-level close request crread process-level read request crint interrupt handler Modules referenced: param.h miscellaneous parameters conf.h configuration options user.h definition of the user table Modules referencing: c.c and l.s Compile time parameters and effects: CRPRI Waiting priority for the card reader. Should be positive. Since the card reader is a delayable device, this needn't be particularly high (i.e., a low number). CRLOWAT The low water mark. If the card reader has been stopped because the process code has not been taking the data, this is the point at which to restart it. CRHIWAT The high water mark. If the queued data exceeds this limit at a card boundry, the reader will be temporarily stopped. Module History: Created 30Jan78 by Greg Noel, based upon the version from the Children's Museum, which didn't work on our system (the original was Copyright 1974; reproduced by permission). */ /*! Rehacked for v7 by Bill Jolitz 8/79 */ #include "param.h" #include "cr.h" #if NCR > 0 #include #include #include #define CRPRI (PZERO+10) #define CRLOWAT 50 #define CRHIWAT 160 #define NLCHAR 0140 /* internal value used for end-of-line */ #define EOFCHAR 07417 /* end-of-file character (not currently used) */ /* card reader status */ struct { int crstate; /* see below */ struct { int cc; int cf; int cl; } crin; } cr11; /* bits in crstate */ #define CLOSED 0 #define WAITING 1 #define READING 2 #define EOF 3 int nospl = { 0 }; extern struct crdevice *CRADDR; char asctab[] { ' ', '1', '2', '3', '4', '5', '6', '7', '8', ' ', ':', '#', '@', '`', '=', '"', '9', '0', '/', 's', 't', 'u', 'v', 'w', 'x', 'y', ' ', ']', ',', '%', '_', '>', '?', 'z', '-', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', ' ', '!', '$', '*', ')', ';', '\\', 'r', '&', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', ' ', '[', '.', '<', '(', '+', '^', 'i', ' ', ' ', ' ', ' ' }; #define BADCHAR '~' /* was blank */ /*ARGSUSED*/ cropen(dev, flag) dev_t dev; { extern lbolt; if (flag!=0 || cr11.crstate!=CLOSED) { err: u.u_error = ENXIO; return; } while(CRADDR->crcs & (CR_HARDERR|CR_RRS|CR_BUSY)) { CRADDR->crcs = 0; sleep(&lbolt, CRPRI); if(cr11.crstate != CLOSED) goto err; /* somebody else got it */ } CRADDR->crcs = CR_IE|CR_READ; cr11.crstate = WAITING; } /*ARGSUSED*/ crclose(dev, flag) dev_t dev; { if(!nospl) (void) _spl6(); CRADDR->crcs = 0; while (getc(&cr11.crin) >= 0) ; cr11.crstate = CLOSED; (void) _spl0(); } crread() { register int c; do { if(!nospl) (void) _spl6(); while((c = getc(&cr11.crin))<0) { if(cr11.crstate == EOF) goto out; if((CRADDR->crcs & CR_CARDDONE) && (cr11.crin.cccrcs |= CR_IE|CR_READ; sleep(&cr11.crin,CRPRI); } (void) _spl0(); } while (passc(asciicon(c)) >= 0); out: (void) _spl0(); } crint() { if (cr11.crstate == WAITING) { if(CRADDR->crcs & CR_ERR) { CRADDR->crcs = CR_IE|CR_READ; return; } cr11.crstate = READING; } if(cr11.crstate == READING) { if (CRADDR->crcs & CR_ERR) /* This code is not really smart enough. The actual EOF condition is indicated by a simultaneous CR_HCHK and CR_CARDDONE; anything else is a real error. In the event of a real error we should discard the current card image, wait for the operator to fix it, and continue. This is very hard to do..... */ cr11.crstate = EOF; else { if ((CRADDR->crcs&CR_CARDDONE) == 0) { putc(CRADDR->crb2,&cr11.crin); return; } else { cr11.crstate = WAITING; if (cr11.crin.cc < CRHIWAT) CRADDR->crcs = CR_IE|CR_READ; } } putc(NLCHAR,&cr11.crin); /* card end or EOF -- insert CR */ wakeup(&cr11.crin); } } asciicon(c) { register c1, c2; c1 = c&0377; if (c1 == NLCHAR) return('\n'); if (c1>=0200) c1 -= 040; c2 = c1; while ((c2 -= 040) >= 0) c1 -= 017; if(c1 > 0107) c1 = BADCHAR; else c1 = asctab[c1]; return(c1); } #endif NCR inc cp .if readname br putc 2: mov $tks,r0 inc (r0) 1: tstb (r0) bge 1b mov tkb,r0 bic $!177,r0 cmp r0,$'A blo 2f cmp r0,$'Z bhi 2f add $'a-'A,r0 .endif 2: tps = 177564 tpb = 177566 / print a teletype character putc: tstb *$tps bge putc mov r0,*$tpb cmp r0,$'sys/OTHERS/cr11/crreg.h 444 3 12 1404 2762130453 7675 struct crdevice { short crcs; short crb1; short crb2; }; /* bits in crcs */ #define CR_ERR 0100000 /* error */ #define CR_CARDDONE 0040000 /* card done */ #define CR_HCHK 0020000 /* hopper check */ #define CR_MCHK 0010000 /* motion check */ #define CR_TERR 0004000 /* timing error */ #define CR_ONLINE 0002000 /* reader to on line */ #define CR_BUSY 0001000 /* busy */ #define CR_RRS 0000400 /* reader ready status */ #define CR_COLDONE 0000200 /* column done */ #define CR_IE 0000100 /* interrupt enable */ #define CR_EJECT 0000002 /* eject */ #define CR_READ 0000001 /* read */ #define CR_HARDERR (CR_ERR|CR_HCHK|CR_MCHK|CR_TERR) #define CR_BITS \ "\10\20ERR\17CARDDONE\16HCHK\15MCHK\14TERR\13ONLINE\12BUSY\11RRS\10COLDONE\ \7IE\2EJECT\1READ" ber). CRLOWAT The low water mark. If the card reader has been stopped because the process code has not been taking the data, this is the point at which to restart it. CRHIWAT The high water mark. If the queued data exceeds this limit at a carsys/OTHERS/dc11/ 755 0 12 0 3771402456 6325 sys/OTHERS/dc11/dc.c 444 3 12 12000 3552650417 7155 /* * SCCS id @(#)dc.c 2.1 (Berkeley) 8/5/83 */ #include "dc.h" #if NDC > 0 #include "param.h" #include #include #include #include #include struct tty dc11[NDC]; extern struct dcdevice *DCADDR; /* * Input-side speed and control bit table. * Each DC11 has 4 speeds which correspond to the 4 non-zero entries. * The table index is the same as the speed-selector * number for the DH11. * Attempts to set the speed to a zero entry are ignored. */ short dcrstab[] = { 0, /* 0 baud */ 0, /* 50 baud */ 0, /* 75 baud */ 0, /* 110 baud */ DC_7BITS | DC_IE | DC_SPEED0 | DC_DTR, /* 134.5 baud */ DC_8BITS | DC_IE | DC_SPEED1 | DC_DTR, /* 150 baud */ 0, /* 200 baud */ DC_8BITS | DC_IE | DC_SPEED2 | DC_DTR, /* 300 baud */ 0, /* 600 baud */ DC_8BITS | DC_IE | DC_SPEED3 | DC_DTR, /* 1200 baud */ 0, /* 1800 baud */ 0, /* 2400 baud */ 0, /* 4800 baud */ 0, /* 9600 baud */ 0, /* X0 */ 0 /* X1 */ }; /* * Transmitter speed and control bit table */ short dctstab[] = { 0, /* 0 baud */ 0, /* 50 baud */ 0, /* 75 baud */ 0, /* 110 baud */ DCTCSR_STOP1 | DCTCSR_TIE | DC_SPEED0 | DCTCSR_RTS, /* 134.5 baud */ DCTCSR_STOP1 | DCTCSR_TIE | DC_SPEED1 | DCTCSR_RTS, /* 150 baud */ 0, /* 200 baud */ DCTCSR_STOP1 | DCTCSR_TIE | DC_SPEED2 | DCTCSR_RTS, /* 300 baud */ 0, /* 600 baud */ DCTCSR_STOP1 | DCTCSR_TIE | DC_SPEED3 | DCTCSR_RTS, /* 1200 baud */ 0, /* 1800 baud */ 0, /* 2400 baud */ 0, /* 4800 baud */ 0, /* 9600 baud */ 0, /* X0 */ 0 /* X1 */ }; /* * Open a DC11, waiting until carrier is established. * Default initial conditions are set up on the first open. * T_state's CARR_ON bit is a pure copy of the hardware * DC_CAR bit, and is only used to regularize * carrier tests in general tty routines. */ /*ARGSUSED*/ dcopen(dev, flag) register dev_t dev; { register struct tty *tp; register struct dcdevice *dcaddr; extern klstart(); int s; if (minor(dev) >= NDC) { u.u_error = ENXIO; return; } tp = &dc11[minor(dev)]; dcaddr = DCADDR + minor(dev); tp->t_addr = (caddr_t)dcaddr; tp->t_state |= WOPEN; s = spl5(); dcaddr->dcrcsr |= DC_IE | DC_DTR; if ((tp->t_state & ISOPEN) == 0) { tp->t_iproc = NULL; tp->t_oproc = klstart; /* Yes, I know, but it works. */ ttychars(tp); tp->t_ispeed = B300; tp->t_ospeed = B300; tp->t_flags = ODDP | EVENP | ECHO; dcaddr->dcrcsr = dcrstab[B300]; dcaddr->dctcsr = dctstab[B300]; } if (dcaddr->dcrcsr & DC_CAR) tp->t_state |= CARR_ON; splx(s); while ((tp->t_state & CARR_ON) == 0) sleep((caddr_t)&tp->t_rawq, TTIPRI); ttyopen(dev, tp); } /* * Close a DC11 */ dcclose(dev) dev_t dev; { register struct tty *tp; tp = &dc11[minor(dev)]; if (tp->t_state & HUPCLS) ((struct dcdevice *) (tp->t_addr))->dcrcsr & = ~DC_DTR; ttyclose(tp); } /* * Read a DC11 */ dcread(dev) dev_t dev; { register struct tty *tp; tp = &dc11[minor(dev)]; (*linesw[tp->t_line].l_read)(tp); } /* * Write a DC11 */ dcwrite(dev) dev_t dev; { register struct tty *tp; tp = &dc11[minor(dev)]; (*linesw[tp->t_line].l_write)(tp); } /* * DC11 transmitter interrupt. */ dcxint(dev) dev_t dev; { register struct tty *tp; register struct clist *cp; tp = &dc11[minor(dev)]; cp = &(tp->t_outq); ttstart(tp); if ((cp->c_cc == 0) || (cp->c_cc == TTLOWAT(tp))) wakeup((caddr_t) cp); } /* * DC11 receiver interrupt. */ dcrint(dev) dev_t dev; { register struct tty *tp; register int c, csr; tp = &dc11[minor(dev)]; c = ((struct dcdevice *) (tp->t_addr))->dcrbuf; /* * If carrier is off, and an open is not in progress, * knock down the CD lead to hang up the local dataset * and signal a hangup. */ if (((csr = ((struct dcdevice *)(tp->t_addr))->dcrcsr) & DC_CAR) == 0) { if ((tp->t_state & WOPEN) == 0) { ((struct dcdevice *) (tp->t_addr))->dcrcsr &= ~DC_DTR; if (tp->t_state & CARR_ON) signal(tp->t_pgrp, SIGHUP); flushtty(tp, FREAD|FWRITE); } tp->t_state &= ~CARR_ON; return; } if ((tp->t_state & ISOPEN) == 0) { if ((tp->t_state & WOPEN) && (csr & DC_CAR)) tp->t_state |= CARR_ON; wakeup((caddr_t) tp); return; } if (csr & DC_BRK) if (tp->t_flags & RAW) c = 0; else c = 0177; csr &= DC_PCHK; if ((csr && ((tp->t_flags & (EVENP | ODDP)) == ODDP)) || (!csr && ((tp->t_flags & (EVENP | ODDP)) == EVENP))) (*linesw[tp->t_line].l_input)(c, tp); } /* * DC11 stty/gtty. * Perform general functions and set speeds. */ dcioctl(dev, cmd, addr, flag) dev_t dev; caddr_t addr; { register struct tty *tp; register r; tp = &dc11[minor(dev)]; if (ttioctl(cmd, tp, addr, dev, flag) == 0) { u.u_error = ENOTTY; return; } if (cmd == TIOCSETP) { r = dcrstab[tp->t_ispeed]; if (r) ((struct dcdevice *) (tp->t_addr))->dcrcsr = r; else ((struct dcdevice *) (tp->t_addr))->dcrcsr &= ~DC_DTR; r = dctstab[tp->t_ospeed]; ((struct dcdevice *) (tp->t_addr))->dctcsr = r; } else u.u_error = ENOTTY; } #endif NDC sys/OTHERS/dc11/dcreg.h 444 3 12 3435 3000710731 7634 struct dcdevice { short dcrcsr; /* receiver status register */ short dcrbuf; short dctcsr; short dctbuf; }; /* bits in dcrcsr */ #define DC_ERR 0100000 /* error */ #define DC_CTR 0040000 /* carrier transition */ #define DC_RING 0020000 /* ring indicator */ #define DC_OVERRUN 0010000 /* data overrun */ /* bit 11 is unused */ /* bits 10-9 are the character length */ #define DC_SXDATA 0000400 /* superv. transmit data */ #define DC_DONE 0000200 /* done */ #define DC_IE 0000100 /* interrupt enable */ #define DC_PCHK 0000040 /* parity check */ /* bits 4-3 are the receiver speed */ #define DC_CAR 0000004 /* carrier detect */ #define DC_BRK 0000002 /* break */ #define DC_DTR 0000001 /* data terminal ready */ #define DC_BITS \ "\10\20ERR\17CTR\16RING\15OVERRUN\11SXDATA\10DONE\7IE\6PCHK\3CAR\2BRK\1DTR" /* character lengths */ #define DC_8BITS 0000000 /* 8 bits per character */ #define DC_7BITS 0001000 /* 7 bits per character */ #define DC_6BITS 0002000 /* 6 bits per character */ #define DC_5BITS 0003000 /* 5 bits per character */ /* receiver (and transmitter) speeds */ #define DC_SPEED0 0000000 /* lowest */ #define DC_SPEED1 0000010 #define DC_SPEED2 0000020 #define DC_SPEED3 0000030 /* highest */ /* bits in dctcsr */ #define DCTCSR_SRDATA 0100000 /* supervisory receive data */ /* bits 14-9 are unused */ #define DCTCSR_STOP1 0000400 /* stop code: 0= 2 stop bits */ #define DCTCSR_RDY 0000200 /* ready */ #define DCTCSR_TIE 0000100 /* transmit interrupt enable */ /* bit 5 is unused */ /* bits 4-3 are the transmitter speed select */ #define DCTCSR_MM 0000004 /* maintenance */ #define DCTCSR_CTS 0000002 /* clear to send */ #define DCTCSR_RTS 0000001 /* request to send */ #define DCTCSR_BITS "\10\20SRDATA\11STOP\10RDY\7TIE\3MM\2CTS\1RTS" dcdevice *) (tp->t_addr))->dcrcsr = r; else ((struct dcdevice *) (tp->t_addr))->dcrcsr &= ~DC_DTR; r = dctstab[tp->t_ospeed]; ((struct dcdevice *) (tp->t_addr))->dctcsr = r; } else u.u_error = ENOTTY; } #endif NDC sys/OTHERS/rx11/ 755 0 12 0 3771402121 6355 sys/OTHERS/rx11/rx.c 444 3 12 31133 3700021570 7256 /* * RX11 floppy disk driver * Modified 2/1/78, Brad Blasing, to emulate DMA operations * * Modified 15 DEC 77 by SSB,DWD,BEB, University of Minnesota * for RX11 floppy drive. * Modified 6/16/78, Brad Blasing, to provide better error recovery * (we don't loop at spl5 waiting for INIT to finish any more). * Modified 10/19/79, Scott Bertilson, to run with slow floppy interfaces. * Modified 4/5/80, Scott Bertilson, added CP/M interleaving to table. * Modified 2/1/81, Scott Bertilson, to run on Version 7. * Modified at Tek to "sort of" run under 2.9bsd; 5/83; dgc */ #include "rx.h" #if NRX > 0 #include "param.h" #include #include #include #include extern struct rxdevice *RXADDR; /* #define DEBUG 1 */ #define DMA 1 /* #define RXADDR ((struct rxdevice *)0177170) /* MAE - 3/29/83 */ #define NRXTYP 4 #define MAXRETRY 5 #define TTIME 60 /* Timeout time in HZ */ #define RRATE 6 /* Recall rate for rxreset */ #define RESETMAX 10 /* Max. num. of reset recalls before timeout */ /* RESETMAX*RRATE/60 = time in second */ #define RXWAIT while((rxaddr->rxcs & (TR | DONE)) == 0) ; #define KISA 0172340 #define KISD 0172300 struct rxtype { int secsize; /* size (bytes) one sector */ int secpertrk; /* sectors/track */ int secperblk; /* sectors/unix block */ int numsec; /* total sectors on device */ int numblks; /* number of blocks on device */ int secincr; /* increment to get next sector of block */ int intrlv; /* interleaving factor */ int skew; /* sector skew across tracks */ int trkoffset; /* offset num of 1st sec */ } rxtypes[NRXTYP] { 128, 26, 4, 77*26, 500, 2, 13, 6, 0, /* our "standard" format */ 128, 26, 4, 77*26, 500, 1, 26, 0, 0, /* IBM format */ 128, 26, 4, 76*26, 494, 2, 13, 6, 1, /* Terak or RT11 format */ 128, 26, 4, 76*26, 494, 6, 13, 0, 2 /* CP/M format */ }; struct rxstat { int fminor; /* present request device number */ struct rxtype *ftype; /* present request floppy type */ int bytect; /* remaining bytes (neg) */ int sector; /* absolute sector (0..numsec-1) */ int toutact; /* timeout active */ int reqnum; /* floppy request number for timeout */ caddr_t coreaddr; /* current core address for transfer */ #ifdef DMA char *coreblk; /* block no. to put in seg. register */ #endif } rxstat; struct buf rxtab; rxstrategy(abp) struct buf *abp; { register struct buf *bp; extern int rxtimeout(); #ifdef DEBUG if(minor(abp->b_dev) == 127) { rxdebug(); iodone(abp); spl0(); return; } #endif bp = abp; /* * test for valid request */ if(rxok(bp) == 0) { bp->b_flags |= B_ERROR; iodone(bp); return; } /* * link buffer into device queue */ bp->av_forw = NULL; spl5(); if(rxtab.b_actf == NULL) rxtab.b_actf = bp; else rxtab.b_actl->av_forw = bp; rxtab.b_actl = bp; /* * start rxtimeout if inactive */ if(rxstat.toutact == 0) { rxstat.toutact++; timeout(rxtimeout, (caddr_t)0, TTIME); } /* * start device if there is no current request */ if(rxtab.b_active == NULL) rxstart(); spl0(); } rxstart() { register struct buf *bp; register struct rxdevice *rxaddr; register int dminor; rxaddr = RXADDR; /* * if there is no request in queue...return */ loop: if((bp = rxtab.b_actf) == NULL) return; /* * check if drive ready */ dminor = (minor(bp->b_dev) & 1) << 4; rxaddr->rxcs = dminor | RDSTAT | GO; RXWAIT if((rxaddr->rxdb & DR) == 0) { printf("rx%d: Floppy not ready\n", minor(bp->b_dev)); rxabtbuf(); goto loop; } /* * set active request flag */ rxtab.b_active++; rxsetup(bp); rxregs(bp); } rxintr() { register struct buf *bp; register struct rxtype *rxt; register struct rxdevice *rxaddr; rxaddr = RXADDR; /* * if there is no active request, false alarm. */ if(rxtab.b_active == NULL) return; rxtab.b_active = NULL; /* * pointer to the buffer */ bp = rxtab.b_actf; /* * pointer to a data structure describing * the type of device (i.e. interleaving) */ rxt = rxstat.ftype; /* * check error bit */ if(rxaddr->rxcs & ERROR) { /* * send read error register command */ rxaddr->rxcs = RDERR | GO; RXWAIT #ifndef UCB_DEVERR deverror(bp, rxaddr->rxcs, rxaddr->rxdb); #else harderr(bp, "rx"); printf("cs=%b, es=%b\n", rxaddr->rxcs, RXCS_BITS, rxaddr->rxdb, RXES_BITS); #endif /* * make MAXRETRY retries on an error */ if(++rxtab.b_errcnt <= MAXRETRY) { rxreset(0); return; } /* * return an i/o error */ bp->b_flags |= B_ERROR; } else { /* * if we just read a sector, we need to * empty the device buffer */ if(bp->b_flags & B_READ) rxempty(bp); /* * see if there is more data to read for * this request. */ rxstat.bytect += rxt->secsize; rxstat.sector++; if(rxstat.bytect < 0 && rxstat.sector < rxt->numsec) { rxtab.b_active++; rxregs(bp); return; } } rxtab.b_errcnt = 0; /* * unlink block from queue */ rxtab.b_actf = bp->av_forw; iodone(bp); /* * start i/o on next buffer in queue */ rxstart(); } rxreset(flag) { register struct rxdevice *rxaddr; rxaddr = RXADDR; /* * Check to see if this is a call from rxintr or * a recall from timeout. */ if(flag) { if(rxaddr->rxcs & DONE) { rxtab.b_active = 0; rxstart(); } else if(flag > RESETMAX) { printf("rx%d: Reset timeout\n", minor(rxtab.b_actf->b_dev)); rxabtbuf(); rxstart(); } else { timeout(rxreset, (caddr_t)flag+1, RRATE); /* * Keep rxtimeout from timing out. */ rxstat.reqnum++; } } else { rxaddr->rxcs = INIT; rxtab.b_active++; rxstat.reqnum++; timeout(rxreset, (caddr_t)1, 1); } } rxregs(abp) struct buf *abp; { register struct buf *bp; register struct rxtype *rxt; register struct rxdevice *rxaddr; int dminor, cursec, curtrk; rxaddr = RXADDR; /* * set device bit into proper position for command */ dminor = rxstat.fminor << 4; bp = abp; rxt = rxstat.ftype; /* * increment interrupt request number */ rxstat.reqnum++; /* * if command is read, initiate the command */ if(bp->b_flags & B_READ){ RXWAIT rxaddr->rxcs = dminor | IENABLE | GO | READ; } else { /* * if command is write, fill the device buffer, * then initiate the write */ rxfill(bp); RXWAIT rxaddr->rxcs = dminor | IENABLE | GO | WRITE; } /* * set track number */ curtrk = rxstat.sector / rxt->secpertrk; /* * set sector number */ dminor = rxstat.sector % rxt->secpertrk; cursec = (dminor % rxt->intrlv) * rxt->secincr + (dminor / rxt->intrlv); /* * add skew to sector */ cursec = (cursec + curtrk * rxt->skew) % rxt->secpertrk; /* * massage registers */ RXWAIT rxaddr->rxdb = cursec + 1; RXWAIT rxaddr->rxdb = curtrk + rxt->trkoffset; } rxok(abp) struct buf *abp; { register struct buf *bp; register int type; register int dminor; /* * get sub-device number and type from dminor device number */ dminor = minor((bp = abp)->b_dev); type = dminor >> 3; /* * check for valid type * * check for block number within range of device */ if(type >= NRXTYP || bp->b_blkno >= (daddr_t)rxtypes[type].numblks) return(0); #ifndef DMA if(bp->b_xmem != 0) { /* No buffers outside kernel space */ prdev("Buffer outside kernel space", bp->b_dev); return(0); } #endif return(1); } rxsetup(abp) struct buf *abp; { register struct buf *bp; register int dminor; register struct rxtype *rxt; /* * get dminor device number from buffer */ dminor = minor((bp = abp)->b_dev); /* * get sub-device number from dminor device number */ rxt = rxstat.ftype = &rxtypes[dminor >> 3]; /* * make sure device number is only 0 or 1 */ rxstat.fminor = dminor & 1; /* * get byte count to read from buffer (negative number) */ rxstat.bytect = -bp->b_bcount; /* * transform block number into the first * sector to read on the floppy */ rxstat.sector = (int)bp->b_blkno * rxt->secperblk; /* * set the core address to get or put bytes. */ #ifndef DMA rxstat.coreaddr = bp->b_un.b_addr; #endif #ifdef DMA rxstat.coreaddr = (bp->b_un.b_addr & 077) + 0120000; rxstat.coreblk = ((bp->b_un.b_addr >> 6) & 01777) | ((bp->b_xmem & 03) << 10); #endif } #ifndef DMA rxempty(abp) struct buf *abp; { register struct rxdevice *rxaddr; register int i; register char *cp; int wc; rxaddr = RXADDR; /* * start empty buffer command */ RXWAIT rxaddr->rxcs = EMPTY | GO; spl1(); /* * get core address and byte count */ cp = rxstat.coreaddr; rxstat.coreaddr += 128; wc = ((rxstat.bytect <= -128)? 128 : -rxstat.bytect); /* * move wc bytes from the device buffer * into the in core buffer */ for(i=wc; i>0; --i) { RXWAIT *cp++ = rxaddr->rxdb; } /* * sluff excess bytes */ for(i=128-wc; i>0; --i) { RXWAIT cp = rxaddr->rxdb; } spl5(); } rxfill(abp) struct buf *abp; { register struct rxdevice *rxaddr; register int i; register char *cp; int wc; rxaddr = RXADDR; /* * initiate the fill buffer command */ RXWAIT rxaddr->rxcs = FILL | GO; spl1(); /* * get core address and byte count */ cp = rxstat.coreaddr; rxstat.coreaddr += 128; wc = ((rxstat.bytect <= -128)? 128 : -rxstat.bytect); /* * move wc bytes from the in-core buffer to * the device buffer */ for(i=wc; i>0; --i) { RXWAIT rxaddr->rxdb = *cp++; } /* * sluff excess bytes */ for(i=128-wc; i>0; --i) { RXWAIT rxaddr->rxdb = 0; } spl5(); } #endif #ifdef DMA /* * This copy of the fill and empty routines emulate a dma * floppy controller. It adds the feature of being able * to write anywhere in physical memory, just like an rk * disk. To do this, we borrow a segmentation register * to do the transfer. While the segmentation register * is pointing to the proper place, we need to run at spl7. * This is harder on the system, so the non-dma driver should * be used if you only intend to do buffer requests (i.e. * no swapping or raw i/o). */ struct { int r[]; }; rxempty(abp) struct buf *abp; { register int i; register char *cp; register int wc; int a,d; struct rxdevice *rxaddr; rxaddr = RXADDR; /* * start empty buffer command */ rxaddr->rxcs = EMPTY | GO; /* * get core address and byte count */ cp = rxstat.coreaddr; wc = ((rxstat.bytect <= -128)? 128 : -rxstat.bytect); /* * save and set segmentation register. */ a = KISA->r[5]; d = KISD->r[5]; spl7(); KISA->r[5] = rxstat.coreblk; KISD->r[5] = 01006; /* * move wc bytes from the device buffer * into the in core buffer */ for(i=wc; i>0; --i) { RXWAIT *cp++ = rxaddr->rxdb; } /* * sluff excess bytes */ for(i=128-wc; i>0; --i) { RXWAIT cp = rxaddr->rxdb; } KISA->r[5] = a; KISD->r[5] = d; spl5(); rxstat.coreblk += 2; } rxfill(abp) struct buf *abp; { register int i; register char *cp; register int wc; int a,d; struct rxdevice *rxaddr; rxaddr = RXADDR; /* * initiate the fill buffer command */ rxaddr->rxcs = FILL | GO; /* * get core address and byte count */ cp = rxstat.coreaddr; wc = ((rxstat.bytect <= -128)? 128 : -rxstat.bytect); /* * save and set segmentation register. */ a = KISA->r[5]; d = KISD->r[5]; spl7(); KISA->r[5] = rxstat.coreblk; KISD->r[5] = 01006; /* * move wc bytes from the in-core buffer to * the device buffer */ for(i=wc; i>0; --i) { RXWAIT rxaddr->rxdb = *cp++; } /* * sluff excess bytes */ for(i=128-wc; i>0; --i) { RXWAIT rxaddr->rxdb = 0; } KISA->r[5] = a; KISD->r[5] = d; spl5(); rxstat.coreblk += 2; } #endif rxtimeout(dummy) { static int prevreq; register struct buf *bp; bp = rxtab.b_actf; /* * if the queue isn't empty and the current request number is the * same as last time, abort the buffer and restart i/o. */ if(bp) { if(prevreq == rxstat.reqnum) { printf("rx%d: Floppy timeout\n", minor(bp->b_dev)); rxabtbuf(); rxstart(); } prevreq = rxstat.reqnum; timeout(rxtimeout, (caddr_t)0, TTIME); } else { /* * if queue is empty, just quit and rxstrategy will * restart us. */ rxstat.toutact = 0; } } rxabtbuf() { register struct buf *bp; /* * abort the current buffer with an error and unlink it. */ bp = rxtab.b_actf; bp->b_flags |= B_ERROR; rxtab.b_actf = bp->av_forw; rxtab.b_errcnt = 0; rxtab.b_active = NULL; iodone(bp); } #ifdef DEBUG rxdebug() { register struct buf *bp; spl5(); printf("Debug: &rxtab=%o, &rxstat=%o\n", &rxtab, &rxstat); printf(" rxstat: fminor=%l, bytect=%l, sec=%l\n", rxstat.fminor, -rxstat.bytect, rxstat.sector); printf(" reqnum=%l\n", rxstat.reqnum); printf(" rxtab: d_active=%l, buffers:\n", rxtab.b_active); for(bp=rxtab.b_actf; bp; bp=bp->av_forw) printf(" dev=%l/%l, blkno=%l, bcnt=%l, flags=%o.\n", major(bp->b_dev), minor(bp->b_dev), bp->b_blkno, -bp->b_bcount, bp->b_flags); putchar('\n'); } #endif set [%D]: ",pname,pp->p_offset); gets(line); if (line[0] == '\0') break; i = parse_sec_cyl(lp, line, &sec, &cyl); if (i < 0) break; if (cyl) off = lp->d_secpercyl * cyl; else off = 0; off += sec; pp->p_offset = off; break; case 's': printf("'%c' size [%D]: ", pname, pp->p_size); gets(line); if (line[0] == '\0') break; i = parse_sec_cyl(lp,sys/OTHERS/rx02/ 755 0 12 0 5123225243 6356 sys/OTHERS/rx02/#2/ 755 3 12 0 5325716404 6575 sys/OTHERS/rx02/#2/rx.c 640 3 12 20761 5321515731 7475 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)rx.c 1.2 (2.11BSD GTE) 1/2/93 */ /* * RX02 floppy disk device driver * * This driver was written by Bill Shannon and distributed on the * DEC v7m UNIX tape. It has been modified for 2BSD and has been * included with the permission of the DEC UNIX Engineering Group. * * Modified to actually work with 2.9BSD by Gregory Travis, Indiana Univ. * * Layout of logical devices: * * name min dev unit density * ---- ------- ---- ------- * rx0a 0 0 single * rx1a 1 1 single * rx0b 2 0 double * rx1b 3 1 double * * ioctl function call may be used to format a disk. */ #include "rx.h" #if NRX > 0 #include "param.h" #include "buf.h" #include "conf.h" #include "ioctl.h" #include "tty.h" #include "rxreg.h" #include "errno.h" struct rxdevice *RXADDR; /* * the following defines use some fundamental * constants of the RX02. */ #define NSPB ((minor(bp->b_dev)&2) ? 2 : 4) /* sectors per block */ #define NRXBLKS ((minor(bp->b_dev)&2) ? 1001 : 500) /* blocks on device */ #define NBPS ((minor(bp->b_dev)&2) ? 256 : 128) /* bytes per sector */ #define DENSITY (minor(bp->b_dev)&2) /* Density: 0 = single, 2 = double */ #define UNIT (minor(bp->b_dev)&1) /* Unit Number: 0 = left, 1 = right */ #define rxwait() while (((RXADDR->rxcs) & RX_XREQ) == 0) #define seccnt(bp) ((int)((bp)->b_seccnt)) struct buf rxtab; struct buf crxbuf; /* buffer header for control functions */ /* * states of driver, kept in b_state */ #define SREAD 1 /* read started */ #define SEMPTY 2 /* empty started */ #define SFILL 3 /* fill started */ #define SWRITE 4 /* write started */ #define SINIT 5 /* init started */ #define SFORMAT 6 /* format started */ rxattach(addr, unit) struct rxdevice *addr; u_int unit; { if (unit != 0) return (0); RXADDR = addr; return (1); } /*ARGSUSED*/ rxopen(dev, flag) dev_t dev; { if (minor(dev) >= 4 || !RXADDR) return (ENXIO); return (0); } rxstrategy(bp) register struct buf *bp; { register int s; if (minor(bp->b_dev) >= 4 || !RXADDR) goto bad; mapalloc(bp); if (bp->b_blkno >= NRXBLKS) { if (bp->b_flags&B_READ) bp->b_resid = bp->b_bcount; else { bad: bp->b_flags |= B_ERROR; bp->b_error = ENXIO; } iodone(bp); return; } bp->av_forw = (struct buf *) NULL; /* * seccnt is actually the number of floppy sectors transferred, * incremented by one after each successful transfer of a sector. */ seccnt(bp) = 0; /* * We'll modify b_resid as each piece of the transfer * successfully completes. It will also tell us when * the transfer is complete. */ bp->b_resid = bp->b_bcount; s = splbio(); if (rxtab.b_actf == NULL) rxtab.b_actf = bp; else rxtab.b_actl->av_forw = bp; rxtab.b_actl = bp; if (rxtab.b_state == NULL) rxstart(); splx(s); } rxstart() { register struct buf *bp; int addr, xmem; int n, sector, track; if ((bp = rxtab.b_actf) == NULL) { rxtab.b_state = NULL; return; } if (bp == &crxbuf) { /* is it a control request ? */ rxtab.b_state = SFORMAT; RXADDR->rxcs = RX_SMD | RX_GO | RX_IE | (UNIT << 4) | (DENSITY << 7); rxwait(); RXADDR->rxdb = 0222; } else if (bp->b_flags & B_READ) { rxtab.b_state = SREAD; rxfactr((int)bp->b_blkno * NSPB + seccnt(bp), §or, &track); RXADDR->rxcs = RX_RSECT | RX_GO | RX_IE | (UNIT << 4) | (DENSITY << 7); rxwait(); RXADDR->rxsa = sector; rxwait(); RXADDR->rxta = track; } else { rxtab.b_state = SFILL; n = bp->b_resid >= NBPS ? NBPS : bp->b_resid; rxaddr ( bp, &addr, &xmem ); RXADDR->rxcs = RX_FILL | RX_Q22 | RX_GO | RX_IE | (DENSITY << 7); rxwait(); RXADDR->rxwc = n >> 1; rxwait(); RXADDR->rxba = addr; rxwait(); RXADDR->rxba = xmem; } } rxintr() { register struct buf *bp; int n, sector, track; static rxerr[4]; char *decode; int addr, xmem; if (rxtab.b_state == SINIT) { rxstart(); return; } if ((bp = rxtab.b_actf) == NULL) return; if (RXADDR->rxcs & RX_ERR) { if (rxtab.b_errcnt++ > 10 || rxtab.b_state == SFORMAT) { bp->b_flags |= B_ERROR; harderr(bp, "rx"); printf("cs=%b er=%b\n", RXADDR->rxcs, RX_BITS, RXADDR->rxes, RXES_BITS); RXADDR->rxcs = RX_RDEC | RX_GO; rxwait(); RXADDR->rxba = (short) rxerr; while ( ! (RXADDR->rxcs & RX_DONE) ); switch ( rxerr[0] ) { case 0040: decode = "bad track"; break; case 0050: decode = "found home"; break; case 0070: decode = "no sch sctr"; break; case 0120: decode = "no preamble"; break; case 0150: decode = "ozone headers"; break; case 0160: decode = "too many IDAM"; break; case 0170: decode = "data AM missing"; break; case 0200: decode = "CRC error"; break; case 0240: decode = "density error"; break; case 0250: decode = "bad fmt key"; break; case 0260: decode = "bad data AM"; break; case 0270: decode = "POK while write"; break; case 0300: decode = "drv not ready"; break; case 0310: decode = "write protected"; break; default: decode = "unknown error"; break; } printf ( "rx: errcode %o = %s\n", rxerr[0], decode ); rxtab.b_errcnt = 0; rxtab.b_actf = bp->av_forw; iodone(bp); } RXADDR->rxcs = RX_INIT; RXADDR->rxcs = RX_IE; rxtab.b_state = SINIT; return; } switch (rxtab.b_state) { case SREAD: /* read done, start empty */ rxtab.b_state = SEMPTY; n = bp->b_resid >= NBPS? NBPS : bp->b_resid; rxaddr ( bp, &addr, &xmem ); RXADDR->rxcs = RX_EMPTY | RX_Q22 | RX_GO | RX_IE | (DENSITY << 7); rxwait(); RXADDR->rxwc = n >> 1; rxwait(); RXADDR->rxba = addr; rxwait(); RXADDR->rxba = xmem; return; case SFILL: /* fill done, start write */ rxtab.b_state = SWRITE; rxfactr((int)bp->b_blkno * NSPB + seccnt(bp), §or, &track); RXADDR->rxcs = RX_WSECT | RX_GO | RX_IE | (UNIT << 4) | (DENSITY << 7); rxwait(); RXADDR->rxsa = sector; rxwait(); RXADDR->rxta = track; return; case SEMPTY: /* empty done, start next read */ case SWRITE: /* write done, start next fill */ /* * increment amount remaining to be transferred. * if it becomes positive, last transfer was a * partial sector and we're done, so set remaining * to zero. */ if (bp->b_resid <= NBPS) { done: bp->b_resid = 0; rxtab.b_errcnt = 0; rxtab.b_actf = bp->av_forw; iodone(bp); break; } bp->b_resid -= NBPS; seccnt(bp)++; break; case SFORMAT: /* format done (whew!!!) */ goto done; /* driver's getting too big... */ } /* end up here from states SWRITE and SEMPTY */ rxstart(); } /* * rxfactr -- calculates the physical sector and physical * track on the disk for a given logical sector. * call: * rxfactr(logical_sector,&p_sector,&p_track); * the logical sector number (0 - 2001) is converted * to a physical sector number (1 - 26) and a physical * track number (0 - 76). * the logical sectors specify physical sectors that * are interleaved with a factor of 2. thus the sectors * are read in the following order for increasing * logical sector numbers (1,3, ... 23,25,2,4, ... 24,26) * There is also a 6 sector slew between tracks. * Logical sectors start at track 1, sector 1; go to * track 76 and then to track 0. Thus, for example, unix block number * 498 starts at track 0, sector 25 and runs thru track 0, sector 2 * (or 6 depending on density). */ static rxfactr(sectr, psectr, ptrck) register int sectr; int *psectr, *ptrck; { register int p1, p2; p1 = sectr / 26; p2 = sectr % 26; /* 2 to 1 interleave */ p2 = (2 * p2 + (p2 >= 13 ? 1 : 0)) % 26; /* 6 sector per track slew */ *psectr = 1 + (p2 + 6 * p1) % 26; if (++p1 >= 77) p1 = 0; *ptrck = p1; } /* * rxaddr -- compute core address where next sector * goes to / comes from based on bp->b_un.b_addr, bp->b_xmem, * and seccnt(bp). */ static rxaddr(bp, addr, xmem) register struct buf *bp; register char **addr, *xmem; { *addr = bp->b_un.b_addr + seccnt(bp) * NBPS; *xmem = bp->b_xmem; if (*addr < bp->b_un.b_addr) /* overflow, bump xmem */ (*xmem)++; } /* * rxioctl -- format RX02 disk, single or double density. * density determined by device opened. */ /*ARGSUSED*/ rxioctl(dev, cmd, addr, flag) dev_t dev; u_int cmd; { register int s; register struct buf *bp; if (cmd != RXIOC_FORMAT) return (ENXIO); bp = &crxbuf; while (bp->b_flags & B_BUSY) { s = splbio(); bp->b_flags |= B_WANTED; sleep(bp, PRIBIO); } splx(s); bp->b_flags = B_BUSY; bp->b_dev = dev; bp->b_error = 0; rxstrategy(bp); iowait(bp); bp->b_flags = 0; return (0); } #endif rse_sec_cyl(lp,sys/OTHERS/rx02/#2/rxauto.c 640 3 12 1137 4307336637 10353 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)rxauto.c 1.1 (2.10BSD Berkeley) 12/1/86 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" #include "rxreg.h" /* * rxprobe - check for rx */ rxprobe(addr) struct rxdevice *addr; { stuff(RX_INIT, (&(addr)->rxcs)); stuff(RX_IE, (&(addr)->rxcs)); DELAY(200000L); stuff(RX_IE, (&(addr)->rxcs)); DELAY(1000L); stuff(0, (&(addr)->rxcs)); return(ACP_IFINTR); } density * ---- ------- ---- ------- * rx0a 0 0 single * rx1a 1 1 single * rx0b 2 0 double * rx1b 3 1 double * * ioctl function call may be used to format a disk. */ #include "rx.h" #if NRX > 0 #include "param.h" #include "buf.h" #include "conf.h" #include "ioctl.h" #include "tty.h" #include "rxreg.h" #include "errno.h" struct rxdevice *RXADDR; /* * the following defines use sosys/OTHERS/rx02/#2/rxreg.h 640 3 12 10326 4307336640 10177 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)rxreg.h 1.1 (2.10BSD Berkeley) 12/1/86 */ struct rxdevice { short rxcs; /* command and status register */ short rxdb; /* multipurpose register: */ #define rxba rxdb /* bus address register */ #define rxqa rxdb /* Q22 high-bits */ #define rxta rxdb /* track address register */ #define rxsa rxdb /* sector address register */ #define rxwc rxdb /* word count register */ #define rxes rxdb /* error and status register */ }; /* bits in rxcs */ #define RX_ERR 0100000 /* error */ #define RX_INIT 0040000 /* initialize */ /* bits 13-12 are the extension bits */ #define RX_RX02 0004000 /* rx02 (read only) */ #define RX_Q22 0002000 /* enable 22-bit mode */ #define RX_HD 0001000 /* DSD 480 head select */ #define RX_DD 0000400 /* double density */ #define RX_XREQ 0000200 /* transfer request */ #define RX_IE 0000100 /* interrupt enable */ #define RX_DONE 0000040 /* done */ #define RX_UNIT 0000020 /* unit select */ /* bits 3-1 are the function code */ #define RX_GO 0000001 /* go */ /* function codes */ #define RX_FILL 0000000 /* fill buffer */ #define RX_EMPTY 0000002 /* empty */ #define RX_WSECT 0000004 /* write sector */ #define RX_RSECT 0000006 /* read sector */ #define RX_SMD 0000010 /* set media density */ #define RX_RDSTAT 0000012 /* read status */ #define RX_WDDSECT 0000014 /* write deleted data sector */ #define RX_RDEC 0000016 /* read error code */ /* ioctls */ #define RXIOC_FORMAT _IO(r, 1) /* format media */ #define RX_BITS \ "\10\20ERR\17INIT\14RX02\13QBUS\12HD\11DD\10XREQ\7IE\6DONE\5UNIT1\1GO" /* bits in rxes */ /* bits 15-12 are unused in the standard rx11 */ #define RXES_IBMDD 0010000 /* DSD 480 IBM double density select */ #define RXES_NXM 0004000 /* nonexistent memory */ #define RXES_WCOVFL 0002000 /* word count overflow */ /* bit 9 is unused in the standard rx11 */ #define RXES_HD 0001000 /* DSD 480 head select */ #define RXES_UNIT 0000400 /* unit select */ #define RXES_RDY 0000200 /* ready */ #define RXES_DDATA 0000100 /* deleted data */ #define RXES_DD 0000040 /* double density */ #define RXES_DENSERR 0000020 /* density error */ #define RXES_ACLO 0000010 /* ac low */ #define RXES_INITDONE 0000004 /* initialization done */ /* bit 1 is unused in the standard rx11 */ #define RXES_S1RDY 0000002 /* DSD 480 side 1 ready */ #define RXES_CRC 0000001 /* crc error */ #define RXES_BITS \ "\10\15IBMDD\14NXM\13WCOVFL\12HD\11UNIT1\10RDY\7DDATA\ \6DDENS\5DENSERR\4ACLO\3INIT\2S1RDY\1CRC" /* bits in rxes1 */ /* bits 15-8 contain the word count */ /* bits 7-0 contain the error code */ #define RXES1_D0NOHOME 0000010 /* drive 0 failed to see home on init */ #define RXES1_D1NOHOME 0000020 /* drive 1 failed to see home on init */ #define RXES1_XTRK 0000040 /* track number > 076 */ #define RXES1_WRAP 0000050 /* found home before desired track */ #define RXES1_HNF 0000070 /* header not found after 2 revs */ #define RXES1_NSEP 0000110 /* up controller found not SEP clock */ #define RXES1_NOPREAMB 0000120 /* preamble not found */ #define RXES1_NOID 0000130 /* preamble found;ID burst timeout */ #define RXES1_HNEQTRK 0000150 /* track reached doesn't match header */ #define RXES1_XIDAM 0000160 /* up made to many attempts for IDAM */ #define RXES1_NOAM 0000170 /* data AM timeout */ #define RXES1_CRC 0000200 /* crc error reading disk sector */ #define RXES1_OOPS 0000220 /* read/write electronics failed test */ #define RXES1_WCOVFL 0000230 /* word count overflow */ #define RXES1_DENSERR 0000240 /* density error */ #define RXES1_BADKEY 0000250 /* bad key word for Set Media Density */ /* bits in rxes4 */ /* bits 15-8 contain the track address for header track address errors */ #define RXES4_UNIT 0000200 /* unit select */ #define RXES4_D1DENS 0000100 /* drive 1 density */ #define RXES4_HEAD 0000040 /* head loaded */ #define RXES4_D0DENS 0000020 /* drive 0 density */ /* bits 3-1 are unused */ #define RXES4_DD 0000001 /* diskette is double density */ #define RXES4_BITS "\10\10DRIVE1\7D1HIDENS\6HEAD\5D0HIDENS\1DDENS" #define b_seccnt av_back #define b_state b_active XADDR->rxes, RXES_BITS); RXADDR->rxcs = RX_RDEC | RX_GO; rxwait(); RXADDR->rxba = (short) rxerr; while ( ! (RXADDR->rxcs & RX_DONE) ); switch ( rxerr[0] ) { case 0040: decode = "bad track"; break; case 0050: decode = "found home"; break; case 0070: decode = "no sch sctr"sys/OTHERS/rx02/#2/README 640 3 12 1044 4307337054 7534 From uunet!nuchat!steve@rutgers.edu Sun May 8 20:06:15 1988 To: bostic@ucbvax.Berkeley.EDU Date: Sun, 8 May 88 18:42:38 CDT Subject: 2.10 drivers Message-Id: <8805081842.AA05397@nuchat.UUCP> From: uunet!nuchat!steve@rutgers.edu (Steve Nuchia) The rx02 driver as distributed didn't even come close to working on a Q22 machine - probe was wrong and it got worse from there. None of the changes are major; the big thing I didn't do was to ifdef my changes - I really don't have enough experience with the multi-architecture code to do that - sorry. rxwc rxdb /* word count register */ #defi rxes rxdb /* error and status register */ }; /* bits in rxcs */ #define RX_ERR 0100000 /* error */ #define RX_INIT 0040000 /* initialize */ /* bits 13-12 are the extension bits */ #define RX_RX02 0004000 /* rx02 (read only) */ #define RX_Q22 0002000 /* enable 22-bit mode */ #define RX_HD 0001000 /* DSD 480 head select */ #define RX_DD 0000400 /* double density */ #define RX_XREQ 0000200 /* transfer request sys/OTHERS/rx02/#1/ 755 3 12 0 5325716404 6574 sys/OTHERS/rx02/#1/rx2.c 440 3 12 17256 5321515645 7565 /* * RX02 floppy disk device driver * * This driver was written by Bill Shannon and distributed on the * DEC v7m UNIX tape. It has been modified for 2BSD and has been * included with the permission of the DEC UNIX Engineering Group. * * * Layout of logical devices: * * name min dev unit density * ---- ------- ---- ------- * rx0 0 0 single * rx1 1 1 single * rx2 2 0 double * rx3 3 1 double * * * Stty function call may be used to format a disk. * To enable this feature, define RX2_IOCTL. */ /* * SCCS id @(#)rx2.c 2.1 (Berkeley) 8/5/83 */ #include "rx2.h" #if NRX2 > 0 #include "param.h" #include #include #include #include #include extern struct rx2device *RX2ADDR; /* * the following defines use some fundamental * constants of the RX02. */ #define NSPB ((minor(bp->b_dev)&2) ? 4 : 8) /* sectors per block */ #define NRXBLKS ((minor(bp->b_dev)&2) ? 500 : 250) /* blocks on device */ #define NBPS ((minor(bp->b_dev)&2) ? 256 : 128) /* bytes per sector */ #define DENSITY (minor(bp->b_dev)&2) /* Density: 0 = single, 2 = double */ #define UNIT (minor(bp->b_dev)&1) /* Unit Number: 0 = left, 1 = right */ #define rx2wait() while (((RX2ADDR->(rx2cs)) & RX2_XREQ) == 0) #define b_seccnt av_back #define seccnt(bp) ((int) ((bp)->b_seccnt)) struct buf rx2tab; #ifdef RX2_IOCTL struct buf crx2buf; /* buffer header for control functions */ #endif /* * states of driver, kept in b_state */ #define SREAD 1 /* read started */ #define SEMPTY 2 /* empty started */ #define SFILL 3 /* fill started */ #define SWRITE 4 /* write started */ #define SINIT 5 /* init started */ #define SFORMAT 6 /* format started */ /*ARGSUSED*/ rx2open(dev, flag) dev_t dev; { if(minor(dev) >= 4) u.u_error = ENXIO; } rx2strategy(bp) register struct buf *bp; { if(bp->b_flags & B_PHYS) mapalloc(bp); if(bp->b_blkno >= NRXBLKS) { if(bp->b_flags&B_READ) bp->b_resid = bp->b_bcount; else { bp->b_flags |= B_ERROR; bp->b_error = ENXIO; } iodone(bp); return; } bp->av_forw = (struct buf *) NULL; /* * seccnt is actually the number of floppy sectors transferred, * incremented by one after each successful transfer of a sector. */ seccnt(bp) = 0; /* * We'll modify b_resid as each piece of the transfer * successfully completes. It will also tell us when * the transfer is complete. */ bp->b_resid = bp->b_bcount; (void) _spl5(); if(rx2tab.b_actf == NULL) rx2tab.b_actf = bp; else rx2tab.b_actl->av_forw = bp; rx2tab.b_actl = bp; if(rx2tab.b_state == NULL) rx2start(); (void) _spl0(); } rx2start() { register struct buf *bp; int sector, track; char *addr, *xmem; if((bp = rx2tab.b_actf) == NULL) { rx2tab.b_state = NULL; return; } #ifdef RX2_IOCTL if (bp == &crx2buf) { /* is it a control request ? */ rx2tab.b_state = SFORMAT; RX2ADDR->rx2cs = RX2_SMD | RX2_GO | RX2_IE | (UNIT << 4) | (DENSITY << 7); rx2wait(); RX2ADDR->rx2db = 'I'; } else #endif if(bp->b_flags & B_READ) { rx2tab.b_state = SREAD; rx2factr((int)bp->b_blkno * NSPB + seccnt(bp), §or, &track); RX2ADDR->rx2cs = RX2_RSECT | RX2_GO | RX2_IE | (UNIT << 4) | (DENSITY << 7); rx2wait(); RX2ADDR->rx2sa = sector; rx2wait(); RX2ADDR->rx2ta = track; } else { rx2tab.b_state = SFILL; rx2addr(bp, &addr, &xmem); RX2ADDR->rx2cs = RX2_FILL | RX2_GO | RX2_IE | (xmem << 12) | (DENSITY << 7); rx2wait(); RX2ADDR->rx2wc = (bp->b_resid >= NBPS ? NBPS : bp->b_resid) >> 1; rx2wait(); RX2ADDR->rx2ba = addr; } } rx2intr() { register struct buf *bp; int sector, track; char *addr, *xmem; if (rx2tab.b_state == SINIT) { rx2start(); return; } if((bp = rx2tab.b_actf) == NULL) return; if(RX2ADDR->rx2cs < 0) { if(rx2tab.b_errcnt++ > 10 || rx2tab.b_state == SFORMAT) { bp->b_flags |= B_ERROR; #ifdef UCB_DEVERR harderr(bp, "rx2"); printf("cs=%b er=%b\n", RX2ADDR->rx2cs, RX2_BITS, RX2ADDR->rx2es, RX2ES_BITS); #else deverror(bp, RX2ADDR->rx2cs, RX2ADDR->rx2db); #endif UCB_DEVERR rx2tab.b_errcnt = 0; rx2tab.b_actf = bp->av_forw; iodone(bp); } RX2ADDR->rx2cs = RX2_INIT; RX2ADDR->rx2cs = RX2_IE; rx2tab.b_state = SINIT; return; } switch (rx2tab.b_state) { case SREAD: /* read done, start empty */ rx2tab.b_state = SEMPTY; rx2addr(bp, &addr, &xmem); RX2ADDR->rx2cs = RX2_EMPTY | RX2_GO | RX2_IE | (xmem << 12) | (DENSITY << 7); rx2wait(); RX2ADDR->rx2wc = (bp->b_resid >= NBPS? NBPS : bp->b_resid) >> 1; rx2wait(); RX2ADDR->rx2ba = addr; return; case SFILL: /* fill done, start write */ rx2tab.b_state = SWRITE; rx2factr((int)bp->b_blkno * NSPB + seccnt(bp), §or, &track); RX2ADDR->rx2cs = RX2_WSECT | RX2_GO | RX2_IE | (UNIT << 4) | (DENSITY << 7); rx2wait(); RX2ADDR->rx2sa = sector; rx2wait(); RX2ADDR->rx2ta = track; return; case SWRITE: /* write done, start next fill */ case SEMPTY: /* empty done, start next read */ /* * increment amount remaining to be transferred. * if it becomes positive, last transfer was a * partial sector and we're done, so set remaining * to zero. */ if (bp->b_resid <= NBPS) { done: bp->b_resid = 0; rx2tab.b_errcnt = 0; rx2tab.b_actf = bp->av_forw; iodone(bp); break; } bp->b_resid -= NBPS; seccnt(bp)++; break; #ifdef RX2_IOCTL case SFORMAT: /* format done (whew!!!) */ goto done; /* driver's getting too big... */ #endif } /* end up here from states SWRITE and SEMPTY */ rx2start(); } /* * rx2factr -- calculates the physical sector and physical * track on the disk for a given logical sector. * call: * rx2factr(logical_sector,&p_sector,&p_track); * the logical sector number (0 - 2001) is converted * to a physical sector number (1 - 26) and a physical * track number (0 - 76). * the logical sectors specify physical sectors that * are interleaved with a factor of 2. thus the sectors * are read in the following order for increasing * logical sector numbers (1,3, ... 23,25,2,4, ... 24,26) * There is also a 6 sector slew between tracks. * Logical sectors start at track 1, sector 1; go to * track 76 and then to track 0. Thus, for example, unix block number * 498 starts at track 0, sector 25 and runs thru track 0, sector 2 * (or 6 depending on density). */ rx2factr(sectr, psectr, ptrck) register int sectr; int *psectr, *ptrck; { register int p1, p2; p1 = sectr / 26; p2 = sectr % 26; /* 2 to 1 interleave */ p2 = (2 * p2 + (p2 >= 13 ? 1 : 0)) % 26; /* 6 sector per track slew */ *psectr = 1 + (p2 + 6 * p1) % 26; if (++p1 >= 77) p1 = 0; *ptrck = p1; } /* * rx2addr -- compute core address where next sector * goes to / comes from based on bp->b_un.b_addr, bp->b_xmem, * and seccnt(bp). */ rx2addr(bp, addr, xmem) register struct buf *bp; register char **addr, **xmem; { *addr = bp->b_un.b_addr + seccnt(bp) * NBPS; *xmem = bp->b_xmem; if (*addr < bp->b_un.b_addr) /* overflow, bump xmem */ (*xmem)++; } #ifdef RX2_IOCTL /* * rx2sgtty -- format RX02 disk, single or double density. * stty with word 0 == 010 does format. density determined * by device opened. */ /*ARGSUSED*/ rx2ioctl(dev, cmd, addr, flag) dev_t dev; { register s; register struct buf *bp; struct rx2iocb { int ioc_cmd; /* command */ int ioc_res1; /* reserved */ int ioc_res2; /* reserved */ } iocb; if (cmd != TIOCSETP) { err: u.u_error = ENXIO; return(0); } if (copyin(addr, (caddr_t)&iocb, sizeof (iocb))) { u.u_error = EFAULT; return(1); } if (iocb.ioc_cmd != RX2_SMD) goto err; bp = &crx2buf; while (bp->b_flags & B_BUSY) { s = spl6(); bp->b_flags |= B_WANTED; sleep(bp, PRIBIO); } splx(s); bp->b_flags = B_BUSY; bp->b_dev = dev; bp->b_error = 0; rx2strategy(bp); iowait(bp); bp->b_flags = 0; } #endif RX2_IOCTL #endif NRX2 iodone(bp); } RXADDR->rxcs = RX_INIT; RXADDR->rxcs = RX_IE; rxtab.b_state = SINIT; return; } switch (rxtab.b_state) { case SREAD: /* read done, start empty */ rxtab.b_state = SEMPTY; n = bp->b_resid >= NBPS? NBPS : bp->b_resid; rxaddr ( bp, &addr, &xmem ); RXADDR->rxcs = RX_EMPTY | RX_Q22 | RX_GO | RX_IE | (sys/OTHERS/rx02/#1/rx2reg.h 440 3 12 7702 2777306541 10250 struct rx2device { short rx2cs; /* command and status register */ short rx2db; /* multipurpose register: */ #define rx2ba rx2db /* bus address register */ #define rx2ta rx2db /* track address register */ #define rx2sa rx2db /* sector address register */ #define rx2wc rx2db /* word count register */ #define rx2es rx2db /* error and status register */ }; /* bits in rx2cs */ #define RX2_ERR 0100000 /* error */ #define RX2_INIT 0040000 /* initialize */ /* bits 13-12 are the extension bits */ #define RX2_RX02 0004000 /* rx02 (read only) */ /* bit 10 is unused (bit 9 is also unused in the standard rx211) */ #define RX2_HD 0001000 /* DSD 480 head select */ #define RX2_DD 0000400 /* double density */ #define RX2_XREQ 0000200 /* transfer request */ #define RX2_IE 0000100 /* interrupt enable */ #define RX2_DONE 0000040 /* done */ #define RX2_UNIT 0000020 /* unit select */ /* bits 3-1 are the function code */ #define RX2_GO 0000001 /* go */ /* function codes */ #define RX2_FILL 0000000 /* fill buffer */ #define RX2_EMPTY 0000002 /* empty */ #define RX2_WSECT 0000004 /* write sector */ #define RX2_RSECT 0000006 /* read sector */ #define RX2_SMD 0000010 /* set media density */ #define RX2_RDSTAT 0000012 /* read status */ #define RX2_WDDSECT 0000014 /* write deleted data sector */ #define RX2_RDEC 0000016 /* read error code */ #define RX2_BITS \ "\10\20ERR\17INIT\14RX02\12HD\11DD\10XREQ\7IE\6DONE\5UNIT1\1GO" /* bits in rx2es */ /* bits 15-12 are unused in the standard rx211 */ #define RX2ES_IBMDD 0010000 /* DSD 480 IBM double density select */ #define RX2ES_NXM 0004000 /* nonexistent memory */ #define RX2ES_WCOVFL 0002000 /* word count overflow */ /* bit 9 is unused in the standard rx211 */ #define RX2ES_HD 0001000 /* DSD 480 head select */ #define RX2ES_UNIT 0000400 /* unit select */ #define RX2ES_RDY 0000200 /* ready */ #define RX2ES_DDATA 0000100 /* deleted data */ #define RX2ES_DD 0000040 /* double density */ #define RX2ES_DENSERR 0000020 /* density error */ #define RX2ES_ACLO 0000010 /* ac low */ #define RX2ES_INITDONE 0000004 /* initialization done */ /* bit 1 is unused in the standard rx211 */ #define RX2ES_S1RDY 0000002 /* DSD 480 side 1 ready */ #define RX2ES_CRC 0000001 /* crc error */ #define RX2ES_BITS \ "\10\15IBMDD\14NXM\13WCOVFL\12HD\11UNIT1\10RDY\7DDATA\ \6DDENS\5DENSERR\4ACLO\3INIT\2S1RDY\1CRC" /* bits in rx2es1 */ /* bits 15-8 contain the word count */ /* bits 7-0 contain the error code */ #define RX2ES1_D0NOHOME 0000010 /* drive 0 failed to see home on init */ #define RX2ES1_D1NOHOME 0000020 /* drive 1 failed to see home on init */ #define RX2ES1_XTRK 0000040 /* track number > 076 */ #define RX2ES1_WRAP 0000050 /* found home before desired track */ #define RX2ES1_HNF 0000070 /* header not found after 2 revs */ #define RX2ES1_NSEP 0000110 /* up controller found not SEP clock */ #define RX2ES1_NOPREAMB 0000120 /* preamble not found */ #define RX2ES1_NOID 0000130 /* preamble found;ID burst timeout */ #define RX2ES1_HNEQTRK 0000150 /* track reached doesn't match header */ #define RX2ES1_XIDAM 0000160 /* up made to many attempts for IDAM */ #define RX2ES1_NOAM 0000170 /* data AM timeout */ #define RX2ES1_CRC 0000200 /* crc error reading disk sector */ #define RX2ES1_OOPS 0000220 /* read/write electronics failed test */ #define RX2ES1_WCOVFL 0000230 /* word count overflow */ #define RX2ES1_DENSERR 0000240 /* density error */ #define RX2ES1_BADKEY 0000250 /* bad key word for Set Media Density */ /* bits in rx2es4 */ /* bits 15-8 contain the track address for header track address errors */ #define RX2ES4_UNIT 0000200 /* unit select */ #define RX2ES4_D1DENS 0000100 /* drive 1 density */ #define RX2ES4_HEAD 0000040 /* head loaded */ #define RX2ES4_D0DENS 0000020 /* drive 0 density */ /* bits 3-1 are unused */ #define RX2ES4_DD 0000001 /* diskette is double density */ #define RX2ES4_BITS "\10\10DRIVE1\7D1HIDENS\6HEAD\5D0HIDENS\1DDENS" #define b_seccnt av_back #define b_state b_active 6 * p1) % 26; if (++p1 >= 77) p1 = 0; *ptrck = p1; } /* sys/OTHERS/PRO/ 755 0 12 0 4120070044 6214 sys/OTHERS/PRO/PRO 444 3 12 11433 4120067644 6723 From US.CCK@CU20B.COLUMBIA.EDU Tue Nov 19 10:28:52 1985 Received: from CU20B.COLUMBIA.EDU by seismo.CSS.GOV with SMTP; Tue, 19 Nov 85 10:28:42 EST Date: Tue 19 Nov 85 10:27:03-EST From: Charlie C Kim Subject: Re: 2.9BSD for PRO350/380's To: keith Cc: US.CCK@CU20B.COLUMBIA.EDU, RICK@UOGVAX2.ARPA In-Reply-To: <8511190108.AA06319@seismo.CSS.GOV> Message-Id: <12160504635.53.US.CCK@CU20B.COLUMBIA.EDU> Status: RO >> Hi, I noticed you were on the list of people that Paul Milazzo send the >> information on the 350's out to. I'm willing to sending out one more set >> of diskette and/or tapes if you'd like a set (I assume it would eventually >> go onto the harvard/seismo distribution, thus relieving many people of >> problems). >> >> Our code is essentially what Guelph has, but with support for >> PRO380's as well. > >Hi, Charlie, thanks for writing, I was going to write you about the same >thing. I would very much like to add support for the PRO to our 2.9 >distribution, especially since we now support the 11/73. First off, >what 2.9 did you port to the PRO? And where are the changes required? > >Keith Bostic > keith@seismo.CSS.GOV > seismo!keith > 703-276-7900 Actually, to be honest, it was Rick Macklem at the University of Guelph who did all the work for PRO350s. We've just added support for PRO380 which was essentially trivial after his work (and after remembering that the 380 and 350s had a device in different places). The baseline used looks like the standard 2.9 distribution - it wasn't the harvard distribution. I've been meaning to try this out, but since our only 11s are PROs with 10MB hard disks... The modifications were minimial. Mostly changes to deal with the PRO's specialized clock and interrupt chip. The big thing that was added at Guelph was all the device drivers: cn.c (console - bitmap display/keyboard), r5.c (rx50 controller), rd.c (rd5x controller), pc.c (comm port & lp port driver), and recently if_dc.c (the decna controller). All the above drivers are for CTI bus devices. (He also included an RDQX1 controller for QBUS machines which he said might work on UDA conrollers as well - probably should too since both are MSCP). The PRO350 essentially maps to an 11/23 while the PRO380 essentially maps to an 11/73 w/o cache or unibus map (not sure if the Micro-11/73 has a unibus map). The PRO380 pretends to have a cache. CTI modules with drivers: RX50 controller RD50/RD51 controller DECNA ethernet adapter Screen/keyboard controller (n.b. part of the system unit on a 380) Memory boards (configured in by PRO diagnostics) Devices with no drivers: 1 Phone system controller (TCMS board?) * 4-line SLU adapter (probably easy, but neither of us have one) 2 RD52/RD51/RD50 controller 3 CPM card * Real Time Interface card * - no documentation and no card to test it with 1 - no card to test with and insufficent documentation 2 - I'm pretty sure that the RD52 (or 53) require a different controller than the ones which most people have for their RD51/RD50's. However, with minor modifications to the current driver, should work 3 - we have a card to test it with and some documenation, but it isn't high priority Problems with currently running software: console driver isn't as robust as it could be. Someone here is working on it. comm port driver isn't as effective as it might be. We're looking at that as well. decna driver is in beta test. No problems to date, though there might be problems with breaking out of a controller hung condition clock interrupts get lost sometimes... system isn't autoconfigured (well a couple of devices are), assumptions are made about where the major cards are in the CTI bus (relates to interrupt structure and device addresses). Unfortunately, DEC started out making it easy to do this and then dropped support for it (they had device ids in some of the earlier cards). This is something people will have to live with... Modules modified: conf/l.s, conf/ioconf.c, conf/c.c for the device drivers. The changes to the sys directory I'm sending in the next message so you can get a feel for what needed to happen. (All changes in the sys directory which apply to the PRO350 also apply to the PRO380). Rick mapped the 350 as machine type "21" (it does require slightly different handling) and I mapped the 380 as type "71" (to follow suit - was going to pick 83, but that would have been a horrible idea). Modifications for the 380 also included going through and making sure that conditions for the 70 got mapped for the 380. I guess I could give you a temporary account on our machine so you can get the stuff. However, I've got to clean up some first, you can poke around if you want. Rick, do you have any problems with giving the code to Harvard/Seismo so they can distribute it? They check licensing. Charlie ------- n(0); } if (copyin(addr, (caddr_t)&iocb, sizeof (iocb))) { u.u_error = EFAULT; return(1); } if (iocb.ioc_cmd != RX2_SMD) goto err; bp = &crx2buf; while (bp->b_flags & B_BUSY) { s = spl6(); bp->b_flags |= B_WANTED;sys/OTHERS/PRO/PRO.diff 444 3 12 31723 4120067645 7637 From columbia!cucca!cck Thu Nov 21 03:38:49 1985 Received: from columbia.UUCP by seismo.CSS.GOV with UUCP; Thu, 21 Nov 85 03:03:19 EST Message-Id: <8511210803.AA21614@seismo.CSS.GOV> Received: by columbia.edu (5.31/5.10) id AA17205; Thu, 21 Nov 85 02:04:42 EST Received: by cucca.columbia.edu; Thu, 21 Nov 85 02:07:20 est Date: Thu, 21 Nov 85 02:07:20 est From: Charlie C. Kim To: keith Subject: Rick's diffs for 2.9 on the PROs Status: R *** clock.c Fri Feb 22 11:57:08 1985 --- /usr/src/sys/sys/clock.c Tue Feb 26 19:10:10 1985 *************** *** 70,93 caddr_t pc; { register a; mapinfo map; extern caddr_t waitloc; extern char *panicstr; /* * restart clock */ - #if PDP11 == 21 - while (*((int *)0173024) & 0200) ; - a = *((int *)0173030); - #else if(lks) *lks = 0115; #endif /* * ensure normal mapping of kernel data */ savemap(map); #ifdef DISPLAY /* --- 70,89 ----- caddr_t pc; { register a; mapinfo map; extern caddr_t waitloc; extern char *panicstr; /* * restart clock */ if(lks) *lks = 0115; /* * ensure normal mapping of kernel data */ savemap(map); #ifdef DISPLAY /* * display register *************** *** 76,96 /* * restart clock */ #if PDP11 == 21 while (*((int *)0173024) & 0200) ; a = *((int *)0173030); #else if(lks) *lks = 0115; - #endif /* * ensure normal mapping of kernel data */ savemap(map); #ifdef DISPLAY /* * display register */ display(); --- 72,91 ----- register a; mapinfo map; extern caddr_t waitloc; extern char *panicstr; /* * restart clock */ if(lks) *lks = 0115; /* * ensure normal mapping of kernel data */ savemap(map); #ifdef DISPLAY /* * display register */ display(); *** machdep.c Wed Jan 23 17:13:15 1985 --- /usr/src/sys/sys/machdep.c Tue Feb 26 19:12:08 1985 *************** *** 84,106 /* * Machine dependent startup code */ startup() { register memaddr i, freebase; extern end; - #if PDP11 == 21 - ivinit(); - #endif #ifndef NOKA5 saveseg5(seg5); /* must be done before clear() is called */ if (&remap_area > SEG5) panic("&remap_area > 0120000"); #else if (&end > SEG5) panic("_end > 0120000"); #endif #if PDP11 <= 22 --- 84,103 ----- /* * Machine dependent startup code */ startup() { register memaddr i, freebase; extern end; #ifndef NOKA5 saveseg5(seg5); /* must be done before clear() is called */ if (&remap_area > SEG5) panic("&remap_area > 0120000"); #else if (&end > SEG5) panic("_end > 0120000"); #endif /* *************** *** 96,118 #endif #ifndef NOKA5 saveseg5(seg5); /* must be done before clear() is called */ if (&remap_area > SEG5) panic("&remap_area > 0120000"); #else if (&end > SEG5) panic("_end > 0120000"); #endif - #if PDP11 <= 22 - *SSR3 = 020; /* Enable 22 bit memory mgmnt */ - #endif /* * zero and free all of core */ i = freebase = *ka6 + USIZE; UISD[0] = ((stoc(1) - 1) << 8) | RW; for (;;) { UISA[0] = i; if (fuibyte((caddr_t)0) < 0) break; maxmem++; --- 93,112 ----- #ifndef NOKA5 saveseg5(seg5); /* must be done before clear() is called */ if (&remap_area > SEG5) panic("&remap_area > 0120000"); #else if (&end > SEG5) panic("_end > 0120000"); #endif /* * zero and free all of core */ i = freebase = *ka6 + USIZE; UISD[0] = ((stoc(1) - 1) << 8) | RW; for (;;) { UISA[0] = i; if (fuibyte((caddr_t)0) < 0) break; maxmem++; *************** *** 116,138 if (fuibyte((caddr_t)0) < 0) break; maxmem++; i++; /* * avoid testing locations on the IO page if possible, * since some people have dz's at 0160000 (0760000). * (3968 is btoc(248K); the macro doesn't do longs.) * (65408 is btoc(4088K)) */ - #if PDP11 <= 22 - if (!ubmap && i >= 0xff80) - #else if (!ubmap && i >= 3968) #endif break; } clear(freebase, i - freebase); mfree(coremap, i - freebase, freebase); physmem = i; #define B (size_t)(((long)nbuf * (bsize)) / ctob(1)) if ((bpaddr = malloc(coremap, B)) == 0) panic("buffers"); --- 110,129 ----- if (fuibyte((caddr_t)0) < 0) break; maxmem++; i++; /* * avoid testing locations on the IO page if possible, * since some people have dz's at 0160000 (0760000). * (3968 is btoc(248K); the macro doesn't do longs.) * (65408 is btoc(4088K)) */ if (!ubmap && i >= 3968) break; } clear(freebase, i - freebase); mfree(coremap, i - freebase, freebase); physmem = i; #define B (size_t)(((long)nbuf * (bsize)) / ctob(1)) if ((bpaddr = malloc(coremap, B)) == 0) panic("buffers"); maxmem -= B; *************** *** 120,140 /* * avoid testing locations on the IO page if possible, * since some people have dz's at 0160000 (0760000). * (3968 is btoc(248K); the macro doesn't do longs.) * (65408 is btoc(4088K)) */ #if PDP11 <= 22 if (!ubmap && i >= 0xff80) #else if (!ubmap && i >= 3968) - #endif break; } clear(freebase, i - freebase); mfree(coremap, i - freebase, freebase); physmem = i; #define B (size_t)(((long)nbuf * (bsize)) / ctob(1)) if ((bpaddr = malloc(coremap, B)) == 0) panic("buffers"); maxmem -= B; #undef B --- 111,130 ----- break; maxmem++; i++; /* * avoid testing locations on the IO page if possible, * since some people have dz's at 0160000 (0760000). * (3968 is btoc(248K); the macro doesn't do longs.) * (65408 is btoc(4088K)) */ if (!ubmap && i >= 3968) break; } clear(freebase, i - freebase); mfree(coremap, i - freebase, freebase); physmem = i; #define B (size_t)(((long)nbuf * (bsize)) / ctob(1)) if ((bpaddr = malloc(coremap, B)) == 0) panic("buffers"); maxmem -= B; #undef B *************** *** 338,361 bad: u.u_error = EINVAL; } /* * Determine whether clock is attached. If so, start it. */ clkstart() { - #if PDP11 == 21 - proclock(); - lks = 0; - #else lks = LKS; if (fioword((caddr_t)lks) == -1) { lks = KW11P_CSR; if (fioword((caddr_t)lks) == -1) { #ifndef SHORTPRT printf("no clock??\n"); #else printf("nocl\n"); #endif SHORTPRT lks = 0; --- 328,347 ----- bad: u.u_error = EINVAL; } /* * Determine whether clock is attached. If so, start it. */ clkstart() { lks = LKS; if (fioword((caddr_t)lks) == -1) { lks = KW11P_CSR; if (fioword((caddr_t)lks) == -1) { #ifndef SHORTPRT printf("no clock??\n"); #else printf("nocl\n"); #endif SHORTPRT lks = 0; *************** *** 356,376 #ifndef SHORTPRT printf("no clock??\n"); #else printf("nocl\n"); #endif SHORTPRT lks = 0; } } if (lks) *lks = 0115; - #endif } #ifndef ENABLE34 /* * Fetch a word from an address on the I/O page, * returning -1 if address does not exist. */ fioword(addr) { register val, saveUI7, saveUD7; --- 342,361 ----- #ifndef SHORTPRT printf("no clock??\n"); #else printf("nocl\n"); #endif SHORTPRT lks = 0; } } if (lks) *lks = 0115; } #ifndef ENABLE34 /* * Fetch a word from an address on the I/O page, * returning -1 if address does not exist. */ fioword(addr) { register val, saveUI7, saveUD7; *** main.c Wed Jan 23 17:12:39 1985 --- /usr/src/sys/sys/main.c Tue Feb 26 19:12:59 1985 *************** *** 36,56 * turn on clock * hand craft 0th process * call all initialization routines * fork - process 0 to schedule * - process 1 execute bootstrap */ main() { extern char version[]; - #if PDP11 > 21 printf("\n%s", version); #endif startup(); #if PDP11 == 21 printf("\n%s", version); #endif /* * set up system process */ --- 36,55 ----- * turn on clock * hand craft 0th process * call all initialization routines * fork - process 0 to schedule * - process 1 execute bootstrap */ main() { extern char version[]; printf("\n%s", version); startup(); /* * set up system process */ proc[0].p_addr = *ka6; #ifndef VIRUS_VFORK proc[0].p_size = USIZE; #endif *************** *** 38,58 * call all initialization routines * fork - process 0 to schedule * - process 1 execute bootstrap */ main() { extern char version[]; #if PDP11 > 21 printf("\n%s", version); - #endif startup(); #if PDP11 == 21 printf("\n%s", version); #endif /* * set up system process */ proc[0].p_addr = *ka6; #ifndef VIRUS_VFORK --- 37,56 ----- * hand craft 0th process * call all initialization routines * fork - process 0 to schedule * - process 1 execute bootstrap */ main() { extern char version[]; printf("\n%s", version); startup(); /* * set up system process */ proc[0].p_addr = *ka6; #ifndef VIRUS_VFORK proc[0].p_size = USIZE; #endif proc[0].p_stat = SRUN; *************** *** 40,62 * - process 1 execute bootstrap */ main() { extern char version[]; #if PDP11 > 21 printf("\n%s", version); #endif startup(); - #if PDP11 == 21 - printf("\n%s", version); - #endif /* * set up system process */ proc[0].p_addr = *ka6; #ifndef VIRUS_VFORK proc[0].p_size = USIZE; #endif proc[0].p_stat = SRUN; proc[0].p_flag |= SLOAD|SSYS; --- 38,57 ----- * call all initialization routines * fork - process 0 to schedule * - process 1 execute bootstrap */ main() { extern char version[]; printf("\n%s", version); startup(); /* * set up system process */ proc[0].p_addr = *ka6; #ifndef VIRUS_VFORK proc[0].p_size = USIZE; #endif proc[0].p_stat = SRUN; proc[0].p_flag |= SLOAD|SSYS; *************** *** 145,167 fp->s_flock = 0; fp->s_ilock = 0; fp->s_ronly = 0; #ifdef UCB_IHASH fp->s_lasti = 1; fp->s_nbehind = 0; #endif fp->s_fsmnt[0] = '/'; for (i = 1; i < sizeof(fp->s_fsmnt); i++) fp->s_fsmnt[i] = 0; - #if PDP11 == 21 - if (time == 0) - #endif time = fp->s_time; bootime = time; } memaddr bpaddr; /* physical click-address of buffers */ /* * Initialize the buffer I/O system by freeing * all buffers and setting all device buffer lists to empty. */ --- 140,159 ----- fp->s_flock = 0; fp->s_ilock = 0; fp->s_ronly = 0; #ifdef UCB_IHASH fp->s_lasti = 1; fp->s_nbehind = 0; #endif fp->s_fsmnt[0] = '/'; for (i = 1; i < sizeof(fp->s_fsmnt); i++) fp->s_fsmnt[i] = 0; time = fp->s_time; bootime = time; } memaddr bpaddr; /* physical click-address of buffers */ /* * Initialize the buffer I/O system by freeing * all buffers and setting all device buffer lists to empty. */ *** sys3.c Wed Jan 23 17:12:57 1985 --- /usr/src/sys/sys/sys3.c Tue Feb 26 19:13:27 1985 *************** *** 263,285 register struct inode *ip; register struct mount *mp; register struct buf *bp; struct buf *dp; dev = getmdev(); if (u.u_error || !suser()) return; xumount(dev); /* remove unused sticky files from text table */ update(); - #if PDP11 <= 22 - delay(2); - #endif for (mp = mount; mp < mountNMOUNT; mp++) if (mp->m_inodp != NULL && dev == mp->m_dev) { for(ip = inode; ip < inodeNINODE; ip++) if (ip->i_number != 0 && dev == ip->i_dev) { u.u_error = EBUSY; return; } (*bdevsw[major(dev)].d_close)(dev, 0); dp = bdevsw[major(dev)].d_tab; for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) { --- 263,282 ----- register struct inode *ip; register struct mount *mp; register struct buf *bp; struct buf *dp; dev = getmdev(); if (u.u_error || !suser()) return; xumount(dev); /* remove unused sticky files from text table */ update(); for (mp = mount; mp < mountNMOUNT; mp++) if (mp->m_inodp != NULL && dev == mp->m_dev) { for(ip = inode; ip < inodeNINODE; ip++) if (ip->i_number != 0 && dev == ip->i_dev) { u.u_error = EBUSY; return; } (*bdevsw[major(dev)].d_close)(dev, 0); dp = bdevsw[major(dev)].d_tab; for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) { *** sys4.c Thu Jan 31 17:16:12 1985 --- /usr/src/sys/sys/sys4.c Tue Feb 26 19:13:57 1985 *************** *** 61,83 stime() { register struct a { time_t time; } *uap; if (suser()) { uap = (struct a *)u.u_ap; bootime += uap->time - time; time = uap->time; - #if PDP11 == 21 - sdtime(); - #endif } } setuid() { register uid; struct a { int uid; }; --- 61,80 ----- stime() { register struct a { time_t time; } *uap; if (suser()) { uap = (struct a *)u.u_ap; bootime += uap->time - time; time = uap->time; } } setuid() { register uid; struct a { int uid; }; ent TOY: > timbuf: .=.+13. / room for YYMsys/OTHERS/rc/ 755 0 12 0 3771403334 6175 sys/OTHERS/rc/rc.c 444 3 12 3332 4610657700 7035 /* * SCCS id @(#)rc.c 2.1 (Berkeley) 8/5/83 */ #include "rc.h" #if NRC > 0 #include "param.h" #include #include #include #include #include extern struct rcdevice *RCADDR; rcread(dev, uio) dev_t dev; struct uio *uio; { struct tm t; if(uio->uio_resid != sizeof(t)) { u.u_error = EINVAL; return; } t.tm_year = (((RCADDR->rcymd) >> 9) & 0177); t.tm_mon = (((RCADDR->rcymd) >> 5) & 017); t.tm_mday = ((RCADDR->rcymd) & 037); t.tm_hour = (((RCADDR->rchm) >> 8) & 037); t.tm_min = ((RCADDR->rchm) & 077); t.tm_sec = ((RCADDR->rcsec) & 077); t.tm_wday = -1; t.tm_yday = -1; t.tm_isdst = -1; if (copyout((caddr_t)&t, (caddr_t)uio->uio_iov->iov_base, sizeof t) < 0) u.u_error = EFAULT; uio->uio_resid -= sizeof t; } rcwrite(dev, uio) dev_t dev; struct uio *uio; { register ymd; register hm; struct tm t; if(uio->uio_resid != sizeof(t)) { u.u_error = EINVAL; return; } if (copyin((caddr_t)uio->uio_iov->iov_base,(caddr_t)&t,sizeof(t)) < 0) { u.u_error = EINVAL; return; } if (suser()) { if((t.tm_year < 0) || (t.tm_year > 99) || (t.tm_mon < 1) || (t.tm_mon > 12) || (t.tm_mday < 1) || (t.tm_mday > 31) || (t.tm_hour < 0) || (t.tm_hour > 23) || (t.tm_min < 0) || (t.tm_min > 59)) { u.u_error = EINVAL; return; } ymd = ((((t.tm_year) << 4) | t.tm_mon) << 5) | t.tm_mday; hm = (t.tm_hour << 8) | t.tm_min; do { /*set rcymd field*/ RCADDR->rcymd = ymd; while (RCADDR->rcymd != ymd) ; RCADDR->rcsec = ymd; } while (RCADDR->rcymd != ymd); do { /*set rthm field*/ RCADDR->rchm = hm; while (RCADDR->rchm != hm) ; RCADDR->rcsec = hm; } while (RCADDR->rchm != hm); } } #endif NRC ; mfree(coremap, i - freebase, freebase); physmem = i; #define B (size_t)(((long)nbuf * (bsize)) / ctob(1)) if ((bpaddr = malloc(coremap, B)) == 0) panic("buffers"); maxmem -= B; #undef B --- 111,130 ----- break; maxmem++; i++; /* * avoid testing locsys/OTHERS/rc/rcreg.h 444 3 12 114 3006126300 7474 struct rcdevice { short rcymd; short rchm; short rcsec; short rccsr; }; sys/OTHERS/tags 751 0 12 0 6045325230 10371 2../sys/tagssys/OTHERS/rf11/ 755 0 12 0 5325716403 6343 sys/OTHERS/rf11/rf.c 444 3 12 4616 5321515607 7212 /* * SCCS id @(#)rf.c 2.2 (2.11BSD GTE) 1/2/93 */ #include "rf.h" #if NRF > 0 #include "param.h" #include "systm.h" #include "buf.h" #include "conf.h" #include "user.h" #include "rfreg.h" #define NRFBLK 1024 struct rfdevice *RFADDR = (struct rfdevice *)0177460; struct buf rftab; rfattach(addr, unit) struct rfdevice *addr; { if (unit != 0) return(0); RFADDR = addr; return(1); } rfstrategy(bp) register struct buf *bp; { if (RFADDR == (struct rfdevice *) NULL) { bp->b_error = ENXIO; goto errexit; } if (bp->b_blkno >= NRFBLK * (minor(bp->b_dev) + 1)) { bp->b_error = EINVAL; errexit: bp->b_flags |= B_ERROR; iodone(bp); return; } mapalloc(bp); bp->av_forw = (struct buf *) NULL; (void) _spl5(); if (rftab.b_actf == NULL) rftab.b_actf = bp; else rftab.b_actl->av_forw = bp; rftab.b_actl = bp; if (rftab.b_active == NULL) rfstart(); (void) _spl0(); } rfstart() { register struct rfdevice *rfaddr = RFADDR; register struct buf *bp; register com; if ((bp = rftab.b_actf) == (struct buf *) NULL) return; rftab.b_active++; rfaddr->rfdar = (short) (bp->b_blkno << 8) & 0177777; rfaddr->rfdae = (short) (bp->b_blkno >> 8) & 037; rfaddr->rfcma = bp->b_un.b_addr; rfaddr->rfwc = - (bp->b_bcount >> 1); com = (bp->b_xmem & 3) << 4; if (bp->b_flags & B_READ) com |= RF_RCOM | RF_IENABLE | RF_GO; else com |= RF_WCOM | RF_IENABLE | RF_GO; rfaddr->rfdcs = com; #ifdef RF_DKN dk_busy |= 1 << RF_DKN; dk_numb[RF_DKN]++; dk_wds[RF_DKN] += (bp->b_bcount) >> 6; #endif } rfintr() { register struct rfdevice *rfaddr = RFADDR; register struct buf *bp; if (rftab.b_active == (struct buf *) NULL) return; #ifdef RF_DKN dk_busy &= ~ (1 << RF_DKN); #endif bp = rftab.b_actf; rftab.b_active = (struct buf *) NULL; if (rfaddr->rfdcs & RF_ERR) { while ((rfaddr->rfdcs & RF_RDY) == 0) ; if (rfaddr->rfdcs & RF_WLO) /* * Give up on write locked devices * immediately. */ printf("rf%d: write locked\n", minor(bp->b_dev)); else { #ifdef UCB_DEVERR harderr(bp, "rf"); printf("cs=%b dae=%b\n", rfaddr->rfdcs, RF_BITS, rfaddr->rfdae, RFDAE_BITS); #else deverror(bp, rfaddr->rfdcs, rfaddr->rfdae); #endif rfaddr->rfdcs = RF_CTLCLR; if (++rftab.b_errcnt <= 10) { rfstart(); return; } } bp->b_flags |= B_ERROR; } rftab.b_errcnt = 0; rftab.b_actf = bp->av_forw; bp->b_resid = -(rfaddr->rfwc << 1); iodone(bp); rfstart(); } #endif NRF malloc(coremap, B)) == 0) panic("buffers"); maxmem -= B; #undef B *************** *** 338,361 bad: sys/OTHERS/rf11/rfreg.h 444 3 12 4666 3562773624 7734 struct rfdevice { short rfdcs; /* disk control status register */ short rfwc; /* word count register */ char *rfcma; /* current memory address register */ short rfdar; /* disk address register */ short rfdae; /* disk address ext. and error register */ short rfdbr; /* disk data buffer register */ short rfmar; /* maintenance register */ short rfads; /* address of disk segment register */ }; /* bits in rfcs */ #define RF_ERR 0100000 /* error */ #define RF_FRZ 0040000 /* freeze */ #define RF_WCE 0020000 /* write check error */ #define RF_DPE 0010000 /* data parity error */ #define RF_NED 0004000 /* nonexistent drive */ #define RF_WLO 0002000 /* write lockout */ #define RF_MXF 0001000 /* missed transfer */ #define RF_CTLCLR 0000400 /* disk control init */ #define RF_RDY 0000200 /* controller ready */ #define RF_IENABLE 0000100 /* bits 5 and 4 are the memory extension bits */ #define RF_MA 0000010 /* maintenance mode */ /* bits 2 and 1 are the function */ #define RF_GO 0000001 /* go */ /* function codes */ #define RF_WCHK 0000006 /* write check */ #define RF_RCOM 0000004 /* read */ #define RF_WCOM 0000002 /* write */ #define RF_NOP 0000000 /* no op */ #define RF_BITS \ "\10\20ERR\17FRZ\16WCE\15DPE\14NED\13WLO\12MXF\11CTLCLR\10RDY\7IENABLE\4MA\1GO" /* bits in rfdae */ #define RFDAE_APE 0100000 /* address parity error */ #define RFDAE_ATER 0040000 /* A timing track error */ #define RFDAE_BTER 0020000 /* B timing track error */ #define RFDAE_CTER 0010000 /* C timing track error */ /* bit 11 is unused */ #define RFDAE_NEM 0002000 /* nonexistent memory */ /* bit 9 is unused */ #define RFDAE_CMA_INH 0000400 /* memory address inhibit */ #define RFDAE_DRL 0000200 /* data request late */ /* bit 6 is unused */ #define RFDAE_DA14 0000040 /* disk address -010 */ /* bits 4-2 are the disk address */ /* bits 1-0 are the track address */ #define RFDAE_BITS \ "\10\20APE\17ATER\16BTER\15CTER\13NEM\11CMA_INH\10DRL\6DA14" /* bits in rmar */ /* bits 15-13 are unused */ #define RFMAR_MDT 0010000 /* maintenance data */ #define RFMAR_MCT 0004000 /* maintenance C timing */ #define RFMAR_MBT 0002000 /* maintenance B timing */ #define RFMAR_MAT 0001000 /* maintenance A timing */ /* bits 7-6 are data track maintenance */ /* bits 5-4 are C timing maintenance */ /* bits 3-2 are B timing maintenance */ /* bits 1-0 are A timing maintenance */ #define RFMAR_BITS "\10\15MDT\14MCT\13MBT\12MAT" _ERR 0100000 /* error */ #define RF_FRZ 0040000 /* freeze */ #definesys/OTHERS/dj11/ 755 0 12 0 3771403037 6330 sys/OTHERS/dj11/dj.c 444 3 12 6031 3552650424 7160 /* * SCCS id @(#)dj.c 2.1 (Berkeley) 8/5/83 */ #include "dj.h" #if NDJ > 0 #include "param.h" #include #include #include #include struct tty dj11[NDJ]; extern struct djdevice *dj_addr[]; /*ARGSUSED*/ djopen(dev, flag) dev_t dev; { register d; register struct tty *tp; register struct djdevice *djaddr; extern djstart(); d = minor(dev); if (d >= NDJ) { u.u_error = ENXIO; return; } tp = &dj11[d]; if ((tp->t_state & XCLUDE) && (u.u_uid != 0)) { u.u_error = EBUSY; return; } tp->t_oproc = djstart; tp->t_iproc = NULL; tp->t_state |= WOPEN | CARR_ON; djaddr = dj_addr[d >> 4]; djaddr->djcsr |= DJ_TIE | DJ_MTSE | DJ_RIE | DJ_RE; if ((tp->t_state & ISOPEN) == 0) { ttychars(tp); tp->t_ispeed = B300; tp->t_ospeed = B300; tp->t_flags = ODDP | EVENP | ECHO; } (*linesw[tp->t_line].l_open)(dev, tp); } djclose(dev) dev_t dev; { register struct tty *tp; tp = &dj11[minor(dev)]; ttyclose(tp); } djread(dev) dev_t dev; { register struct tty *tp; tp = &dj11[minor(dev)]; (*linesw[tp->t_line].l_read)(tp); } djwrite(dev) dev_t dev; { register struct tty *tp; tp = &dj11[minor(dev)]; (*linesw[tp->t_line].l_write)(tp); } djioctl(dev, cmd, addr, flag) dev_t dev; caddr_t addr; { register struct tty *tp; tp = &dj11[minor(dev)]; if (ttioctl(cmd, tp, addr, dev, flag) == 0) u.u_error = ENOTTY; } djrint(unit) { register struct tty *tp; register struct djdevice *djaddr; register c; struct tty *tp0; djaddr = dj_addr[unit]; tp0 = &dj11[unit << 4]; while ((c = djaddr->djrbuf) < 0) { tp = tp0 + ((c >> 8) & 017); if (tp >= &dj11[NDJ]) continue; if ((tp->t_state & ISOPEN) == 0) { wakeup((caddr_t) tp); continue; } if (c & DJRBUF_RDPE) if ((tp->t_flags & (EVENP | ODDP)) == EVENP || (tp->t_flags & (EVENP | ODDP)) == ODDP) continue; if (c & DJRBUF_FE) if (tp->t_flags & RAW) c = 0; else c = 0177; (*linesw[tp->t_line].l_input)(c, tp); } } djxint(unit) { register struct tty *tp, *tp0; register struct djdevice *djaddr; djaddr = dj_addr[unit]; tp0 = &dj11[unit << 4]; while (djaddr->djcsr < 0) { tp = &tp0[djaddr->dj_un.djtbufh]; djaddr->dj_un.djtbufl = tp->t_char; tp->t_state &= ~BUSY; djstart(tp); } } djstart(tp) register struct tty *tp; { register struct djdevice *djaddr; register unit; int c, s; extern ttrstrt(); unit = tp - dj11; djaddr = dj_addr[unit >> 4]; unit = 1 << (unit & 017); s = spl5(); if (tp->t_state & (TIMEOUT | BUSY)) { splx(s); return; } if (tp->t_state & TTSTOP) { djaddr->djtcr &= ~unit; splx(s); return; } if ((c = getc(&tp->t_outq)) >= 0) { if (c >= 0200 && ((tp->t_flags & RAW) == 0)) { djaddr->djtcr &= ~unit; tp->t_state |= TIMEOUT; timeout(ttrstrt, (caddr_t) tp, (c & 0177) + 6); } else { tp->t_char = c; tp->t_state |= BUSY; djaddr->djtcr |= unit; } if ((tp->t_outq.c_cc <= TTLOWAT(tp)) && (tp->t_state & ASLEEP)) { tp->t_state &= ~ASLEEP; wakeup((caddr_t) &tp->t_outq); } } else djaddr->djtcr &= ~unit; splx(s); } #endif NDJ { lks = LKS; if (fioword((caddr_t)lks) == -1) { lks = KW11P_CSR; if (fioword((caddr_t)lks) == -1) { #ifndef SHORTPRT printf("no clock??\n"); #else printf("nocl\n"); #endif SHORTPRT lks = 0; *************** *** 356,376 #ifndef SHORTPRT printf("no clock??\n"); #else printf("nocl\n"); #endif SHORTPRT lks = 0; } } if (lks) *lks = 0115; - #endif } #ifndef ENABLE34 /* * Fetch a word from an address on the I/sys/OTHERS/dj11/djreg.h 444 3 12 2477 3001024747 7665 struct djdevice { short djcsr; short djrbuf; short djtcr; #define djbcr djtcr struct { char djtbufl; char djtbufh; } dj_un; }; /* bits in djcsr */ #define DJ_TRDY 0100000 /* transmitter ready */ #define DJ_TIE 0040000 /* transmitter interrupt enable */ #define DJ_FIFO 0020000 /* FIFO full */ #define DJ_BSIE 0010000 /* FIFO buffer status interrupt enable*/ /* bit 11 is unused */ #define DJ_BRS 0002000 /* break register select */ /* bit 9 is unused */ #define DJ_MTSE 0000400 /* master transmit scan enable */ #define DJ_RDONE 0000200 /* receiver done */ #define DJ_RIE 0000100 /* receiver interrupt enable */ /* bit 5 is unused */ #define DJ_BCLR 0000020 /* busy clear */ #define DJ_MCLR 0000010 /* MOS clear */ #define DJ_MM 0000004 /* maintenance mode */ #define DJ_HDX 0000002 /* half duplex select */ #define DJ_RE 0000001 /* receiver enable */ #define DJ_BITS \ "\10\20TRDY\17TIE\16FIFO\15BSIE\13BRS\11MTSE\10RDONE\ \7RIE\5BCLR\4MCLR\3MM\2HDX\1RE" /* bits in djrbuf */ #define DJRBUF_DPR 0100000 /* data present */ #define DJRBUF_OVERRUN 0040000 /* overrun */ #define DJRBUF_FE 0020000 /* framing error */ #define DJRBUF_RDPE 0010000 /* received data parity error */ /* bits 11-8 are the line number */ /* bits 7-0 are the received data */ #define DJRBUF_BITS "\10\20DPR\17OVERRUN\16FE\15RDPE" tp, addr, dev, flag) == 0) u.u_error = ENOTTY; } djrint(unit) { register struct tty *tp; register struct djdevice *djaddr; register c; struct tty *tp0; djaddr = dj_addr[unit]; tp0 = &sys/OTHERS/ml11/ 755 0 12 0 5325716402 6343 sys/OTHERS/ml11/ml.c 444 3 12 10702 5321515535 7225 /* * ML11 solid state disk driver. * * This driver was written by Fred Canter and distributed on the * DEC v7m UNIX tape. It has been modified for 2BSD and has been * included with the permission of the DEC UNIX Engineering Group. * * This driver does not support mixed drive types, * it requires that the ML11 be on a separate * RH11 or RH70 controller and that there be only * ML11 drives on that controller. */ /* * SCCS id @(#)ml.c 2.2 (2.11BSD GTE) 1/2/93 */ #include "ml.h" #if NML > 0 #include "param.h" #include #include #include #include #include #include bool_t ml_alive; extern struct mldevice *MLADDR; /* * Ml_sizes[] contains the size of each ML11 * unit in blocks. The size is set dynamicaly * by reading the number of arrays from the ML maintenance * register. The array type bit the the ML maintenacne * register is used to adjust the number of blocks per array * from 512 (16k chips) to 2048 (64k chips). */ short ml_sizes[NML]; struct buf mltab; void mlprobe() { register unit; if (fioword (MLADDR) != -1) { ml_alive++; for (unit = 0; unit < NML; unit++) { MLADDR->mlcs2.c[0] = unit; /* * Find the size of the ML11 unit by reading * the number of array modules from the ML * maintenance register. There are 512 * blocks per array unless the array type * bit is set, in which case there are 2048 * blocks per array. */ ml_sizes[unit] = (MLADDR->mlmr >> 2) & 037000; if (MLADDR->mlmr & 02000) ml_sizes[unit] <<= 2; } if (fioword (&(MLADDR->mlbae)) != -1) mltab.b_flags |= B_RH70; } } mlstrategy(bp) register struct buf *bp; { register struct buf *dp; register unit; int tr; long sz, bn; unit = minor(bp->b_dev) & 07; if (!ml_alive || unit >= NML) goto bad; if ((bp->b_flags & B_PHYS) && ((mltab.b_flags & B_RH70) == 0)) mapalloc(bp); (void) _spl5(); if ((MLADDR->mldt & 0377) != ML11) goto bad; MLADDR->mlcs2.c[0] = unit; /* * Check the ML11 transfer rate. * 2mb is too fast for any pdp11. * 1mb allowed on pdp11/70 only. * .5mb & .25mb ok on any processor. */ tr = MLADDR->mlmr & 01400; if ((tr == MLMR_2MB) || ((tr == MLMR_1MB) && ((mltab.b_flags & B_RH70) == 0))) { printf("\nML11 xfer rate error\n"); goto bad; } sz = bp->b_bcount; sz = (sz + 511) >> 9; if (bp->b_blkno < 0 || (bp->b_blkno + sz) > ml_sizes[unit]) { goto bad; } bp->av_forw = NULL; dp = &mltab; if (dp->b_actf == NULL) dp->b_actf = bp; else dp->b_actl->av_forw = bp; dp->b_actl = bp; if (dp->b_active == NULL) mlstart(); return; bad: u.u_error = ENXIO; bp->b_flags |= B_ERROR; iodone(bp); } mlstart() { register struct buf *bp; register unit, com; if ((bp = mltab.b_actf) == NULL) return; mltab.b_active++; unit = minor(bp->b_dev) & 07; (void) _spl5(); MLADDR->mlcs2.w = unit; if ((MLADDR->mlds & MLDS_VV) == 0) MLADDR->mlcs1.w = ML_PRESET | ML_GO; if ((MLADDR->mlds & (MLDS_DPR | MLDS_MOL)) != (MLDS_DPR | MLDS_MOL)) { mltab.b_active = 0; mltab.b_errcnt = 0; bp->b_actf = bp->av_forw; bp->b_flags |= B_ERROR; iodone(bp); (void) _spl0(); return; } MLADDR->mlda = bp->b_blkno; MLADDR->mlba = bp->b_un.b_addr; if (mltab.b_flags & B_RH70) MLADDR->mlbae = bp->b_xmem; MLADDR->mlwc = -(bp->b_bcount >> 1); com = ((bp->b_xmem & 3) << 8) | ML_IE | ML_GO; if (bp->b_flags & B_READ) com |= ML_RCOM; else com |= ML_WCOM; MLADDR->mlcs1.w = com; #ifdef ML_DKN dk_busy |= 1 << (ML_DKN + NML); dk_numb[ML_DKN + NML] += 1; dk_wds[ML_DKN + NML] += bp->b_bcount >> 6; #endif ML_DKN (void) _spl0(); } mlintr() { register struct buf *bp; register unit; int as; int ctr; if (mltab.b_active == NULL) return; as = MLADDR->mlas & 0377; bp = mltab.b_actf; unit = minor(bp->b_dev) & 7; #ifdef ML_DKN dk_busy &= ~(1 << (ML_DKN + NML)); #endif as &= ~(1<mlas = as; MLADDR->mlcs2.c[0] = unit; if (MLADDR->mlcs1.w & ML_TRE) { /* error bit */ ctr = 0; while (((MLADDR->mlds & MLDS_DRY) == 0) && --ctr) ; if (mltab.b_errcnt == 0) #ifdef UCB_DEVERR harderr (bp, "ml"); printf ("cs2=%b er=%b\n", MLADDR->mlcs2.w, MLCS2_BITS, MLADDR->mler, MLER_BITS); #else deverror(bp, MLADDR->mlcs2.w, MLADDR->mler); #endif UCB_DEVERR MLADDR->mlcs1.w = ML_DCLR | ML_GO; if (++mltab.b_errcnt <= 10) { mlstart(); return; } bp->b_flags |= B_ERROR; } mltab.b_errcnt = 0; mltab.b_actf = bp->av_forw; bp->b_resid = 0; iodone(bp); mlstart(); } #endif NML tate & (TIMEOUT | BUSY)) { splx(s); return; } if (tp->t_sys/OTHERS/ml11/mlreg.h 444 3 12 3263 3000016325 7675 struct mldevice { union { short w; char c[2]; } mlcs1; /* Control and Status register 1 */ short mlwc; /* Word count register */ caddr_t mlba; /* UNIBUS address register */ short mlda; /* Desired address register */ union { short w; char c[2]; } mlcs2; /* Control and Status register 2 */ short mlds; /* Drive Status */ short mler; /* Error register */ short mlas; /* Attention Summary */ short mlpa; /* Prom address register */ short mldb; /* Data buffer */ short mlmr; /* Maintenance register */ short mldt; /* Drive type */ short mlsn; /* Serial number */ short mle1; /* ECC CRC word 1 */ short mle2; /* ECC CRC word 2 */ short mld1; /* Data diagnostic 1 register */ short mld2; /* Data diagnostic 2 register */ short mlee; /* ECC error register */ short mlel; /* ECC error location register */ short mlpd; /* Prom data register */ short mlbae; /* RH70 bus address extension */ short mlcs3; /* RH70 control & status register 3 */ }; /* bits in mlcs */ #define ML_TRE 0040000 #define ML_IE 0000100 #define ML_GO 0000001 /* function codes */ #define ML_DCLR 0000010 #define ML_PRESET 0000020 #define ML_WCOM 0000060 #define ML_RCOM 0000070 #define ML_BITS "\10\17TRE\7IE\1G0" /* bits in MLDS */ #define MLDS_MOL 0010000 #define MLDS_DPR 0000400 #define MLDS_DRY 0000200 #define MLDS_VV 0000100 #define MLDS_BITS "\10\15MOL\11DPR\10DRY\7VV" /* transfer rates */ #define MLMR_2MB 0000000 /* 2Mb transfer rate */ #define MLMR_1MB 0000400 /* 1Mb transfer rate */ #define MLMR_500KB 0001000 /* 500 Kb transfer rate */ #define MLMR_250KB 0001400 /* 250 Kb transfer rate */ #define MLDT_ML11 0000110 /* ML11 drive type */ n; as = MLADDR->mlas & 0377; bp = mltab.b_actf; unit = minor(bp->b_dev) & 7; #ifdef ML_DKN dk_busy &= ~(1 << (ML_DKN + NML)); #endif as &= ~(1<mlas = as; MLADDR->mlcs2.c[0] = unit; if (MLADDR->mlcs1.w & ML_TRE) { /* error bit */ ctr = 0; while (((MLADDR->mlds & MLDS_DRY) == 0) && --ctr) ; if (mltabsys/OTHERS/packet_driver/ 755 0 12 0 4011020272 10373 sys/OTHERS/packet_driver/pk0.c 444 3 12 24132 3144315446 11361 #define KERNEL 1 #include #ifdef UCB_SCCSID static char sccs_id[] = "@(#)pk0.c 3.1"; #endif /* * packet driver */ char next[8] ={ 1,2,3,4,5,6,7,0}; /* packet sequence numbers */ char mask[8] ={ 1,2,4,010,020,040,0100,0200 }; struct pack *pklines[NPLINES]; /* * receive control messages */ pkcntl(cntl, pk) register cntl; register struct pack *pk; { register val; register m; val = cntl & MOD8; if ( NOTCNTL(cntl) ) { pkbadframe(pk); return; } cntl >>= 3; pk->p_state &= ~BADFRAME; m = pk->p_msg; switch(cntl) { case INITB: val++; pk->p_xsize = pksizes[val]; pk->p_lpsize = val; pk->p_bits = DTOM(pk->p_xsize); if (pk->p_state & LIVE) { pk->p_msg |= M_INITC; break; } pk->p_state |= INITb; if ((pk->p_state & INITa)==0) { break; } pk->p_rmsg &= ~M_INITA; pk->p_msg |= M_INITC; break; case INITC: if ((pk->p_state&INITab)==INITab) { pk->p_state = LIVE; WAKEUP(&pk->p_state); pk->p_rmsg &= ~(M_INITA|M_INITB); } else if ((pk->p_state&LIVE)==0) pk->p_msg |= M_INITB; if (val) pk->p_swindow = val; break; case INITA: if (val==0 && pk->p_state&LIVE) { printf("alloc change\n"); break; } if (val) { pk->p_state |= INITa; pk->p_msg |= M_INITB; pk->p_rmsg |= M_INITB; pk->p_swindow = val; } break; case RJ: pk->p_state |= RXMIT; pk->p_msg |= M_RR; case RR: pk->p_rpr = val; if (pksack(pk)==0) { WAKEUP(&pk->p_ps); } break; case CLOSE: pk->p_state = DOWN+RCLOSE; pk->p_rmsg = 0; WAKEUP(&pk->p_pr); WAKEUP(&pk->p_ps); WAKEUP(&pk->p_state); return; } if (pk->p_msg==0) pk->p_msg |= pk->p_rmsg; if (m==0 && pk->p_msg) pkoutput(pk); } /* * Send RJ message on first framing error. * Cleared by receiving a good frame * (pkcntl or pkdata). */ pkbadframe(pk) register struct pack *pk; { WAKEUP(&pk->p_pr); if (pk->p_state & BADFRAME) return; pk->p_state |= BADFRAME; pk->p_timer = 2; } /* * Look at sequence numbers (mostly). */ pkaccept(pk) register struct pack *pk; { register x, seq; char m, cntl, *p, imask, **bp; int bad, accept, skip, s, t, cc; unsigned short sum; bad = accept = skip = 0; /* * wait for input */ LOCK; x = next[pk->p_pr]; if((imask=pk->p_imap)==0 && pk->p_rcount==0) { UNLOCK; goto out; } pk->p_imap = 0; UNLOCK; /* * determine input window in m. */ t = (~(-1<p_rwindow)) <>8; /* * mark newly accepted input buffers */ for(x=0; x<8; x++) { if ((imask & mask[x]) == 0) continue; if (((cntl=pk->p_is[x])&0200)==0) { bad++; free: bp = (char **)pk->p_ib[x]; LOCK; *bp = (char *)pk->p_ipool; pk->p_ipool = bp; pk->p_is[x] = 0; UNLOCK; continue; } pk->p_is[x] = ~(B_COPY+B_MARK); sum = (unsigned)chksum(pk->p_ib[x], pk->p_rsize) ^ (unsigned)cntl; sum += pk->p_isum[x]; if (sum == CHECK) { seq = (cntl>>3) & MOD8; if (m & mask[seq]) { if (pk->p_is[seq] & (B_COPY | B_MARK)) { dup: skip++; goto free; } if (x != seq) { LOCK; p = pk->p_ib[x]; pk->p_ib[x] = pk->p_ib[seq]; pk->p_is[x] = pk->p_is[seq]; pk->p_ib[seq] = p; UNLOCK; } pk->p_is[seq] = B_MARK; accept++; cc = 0; if (cntl&B_SHORT) { pk->p_is[seq] = B_MARK+B_SHORT; p = pk->p_ib[seq]; cc = (unsigned)*p++; if (cc & 0200) { cc &= 0177; cc |= *p << 7; } } pk->p_isum[seq] = pk->p_rsize - cc; } else { goto dup; } } else { bad++; goto free; } } /* * scan window again turning marked buffers into * COPY buffers and looking for missing sequence * numbers. */ accept = 0; for(x=next[pk->p_pr],t= -1; m & mask[x]; x = next[x]) { if (pk->p_is[x] & B_MARK) pk->p_is[x] |= B_COPY; if (pk->p_is[x] & B_COPY) { if (t >= 0) { bp = (char **)pk->p_ib[x]; LOCK; *bp = (char *)pk->p_ipool; pk->p_ipool = bp; pk->p_is[x] = 0; UNLOCK; skip++; } else accept++; } else { if (t<0) t = x; } } if (bad) { pk->p_msg |= M_RJ; } else if (skip) { pk->p_msg |= M_RR; } pk->p_rcount = accept; out: if (pk->p_msg) pkoutput(pk); return(accept); } pkread(S) SDEF; { register struct pack *pk; register x,s; int is,cc,xfr,count; char *cp, **bp; pk = PADDR; xfr = 0; count = -1; while (pkaccept(pk) == 0) { PKGETPKT(pk); if (pk->p_state&DOWN) { SETERROR; goto out; } if (SLEEPNO) { count++; goto out; } SLEEP(&pk->p_pr, PKIPRI); } count = 0; while (UCOUNT) { x = next[pk->p_pr]; is = pk->p_is[x]; if (is & B_COPY) { cc = MIN(pk->p_isum[x], UCOUNT); if (cc==0 && xfr) { break; } if (is & B_RESID) cp = pk->p_rptr; else { cp = pk->p_ib[x]; if (is & B_SHORT) { if (*cp++ & 0200) *cp++; } } IOMOVE(cp,cc,B_READ); count += cc; xfr++; pk->p_isum[x] -= cc; if (pk->p_isum[x] == 0) { LOCK; pk->p_pr = x; bp = (char **)pk->p_ib[x]; *bp = (char *)pk->p_ipool; pk->p_ipool = bp; pk->p_is[x] = 0; pk->p_rcount--; UNLOCK; pk->p_msg |= M_RR; } else { pk->p_rptr = cp+cc; pk->p_is[x] |= B_RESID; } if (cc==0) break; } else break; } pkoutput(pk); if (SLEEPNO) count = pk->p_rcount; out: return(count); } pkwrite(S) SDEF; { register struct pack *pk; register x; int partial; caddr_t cp; int cc, s, fc, count; int pktimeout(); pk = PADDR; if ((pk->p_state&LIVE)==0) { down: SIGNAL; SETERROR; return(-1); } count = UCOUNT; do { LOCK; while (pk->p_xcount>=pk->p_swindow) { pkoutput(pk); PKGETPKT(pk); SLEEP(&pk->p_ps,PKOPRI); if (pk->p_state&DOWN) goto down; } x = next[pk->p_pscopy]; while (pk->p_os[x]!=B_NULL) { goto down; } pk->p_os[x] = B_MARK; pk->p_pscopy = x; pk->p_xcount++; UNLOCK; cp = pk->p_ob[x] = (char *)GETEPACK; partial = 0; if ((int)UCOUNT < pk->p_xsize) { cc = UCOUNT; fc = pk->p_xsize - cc; *cp = fc&0177; if (fc > 127) { *cp++ |= 0200; *cp++ = fc>>7; } else cp++; partial = B_SHORT; } else cc = pk->p_xsize; IOMOVE(cp,cc,B_WRITE); pk->p_osum[x] = chksum(pk->p_ob[x], pk->p_xsize); pk->p_os[x] = B_READY+partial; pkoutput(pk); } while (UCOUNT); return(count-UCOUNT); } pksack(pk) register struct pack *pk; { register x, i; int s; i = 0; LOCK; for(x=pk->p_ps; x!=pk->p_rpr; ) { x = next[x]; if (pk->p_os[x]&B_SENT) { i++; FREEPACK(pk->p_ob[x], pk->p_bits); pk->p_os[x] = B_NULL; pk->p_state &= ~WAITO; pk->p_xcount--; pk->p_ps = x; WAKEUP(&pk->p_ps); } } UNLOCK; return(i); } pkoutput(pk) register struct pack *pk; { register x; int s; char bstate; int i; SDEF; extern pkzot; ISYSTEM; LOCK; if (OBUSY) { UNLOCK; return; } /* * find seq number and buffer state * of next output packet */ if (pk->p_state&RXMIT) { pk->p_nxtps = next[pk->p_rpr]; pk->p_state &= ~RXMIT; } x = pk->p_nxtps; bstate = pk->p_os[x]; /* * Send control packet if indicated */ if (pk->p_msg) { if (pk->p_msg & ~M_RR || !(bstate&B_READY) ) { x = pk->p_msg; for(i=0; i<8; i++) if (x&1) break; else x >>= 1; x = i; x <<= 3; switch(i) { case CLOSE: break; case RJ: case RR: x += pk->p_pr; break; case SRJ: break; case INITB: x += pksize(pk->p_rsize); break; case INITC: x += pk->p_rwindow; break; case INITA: x += pk->p_rwindow; break; } pk->p_msg &= ~mask[i]; pkxstart(pk, x, -1); goto out; } } /* * Don't send data packets if line is marked dead. */ if (pk->p_state&DOWN || (pk->p_state&LIVE)==0) { WAKEUP(&pk->p_ps); goto out; } /* * Start transmission (or retransmission) of data packets. */ if (bstate & (B_READY|B_SENT)) { char seq; bstate |= B_SENT; seq = x; pk->p_nxtps = next[x]; x = 0200+pk->p_pr+(seq<<3); if (bstate & B_SHORT) x |= 0100; pkxstart(pk, x, seq); if (pk->p_os[seq]) pk->p_os[seq] = bstate; pk->p_nout++; goto out; } /* * enable timeout if there's nothing to send * and transmission buffers are languishing */ if (pk->p_xcount) { pk->p_timer = 10+pkzot; pk->p_state |= WAITO; } else pk->p_state &= ~WAITO; WAKEUP(&pk->p_ps); out: pk->p_obusy = 0; UNLOCK; } /* * shut down line by * ignoring new input * letting output drain * releasing space and turning off line discipline */ pkclose(S) SDEF; { register struct pack *pk; register i,s,rbits; char **bp; #define NTRIES 1 pk = PADDR; pk->p_state |= DRAINO; /* * try to flush output */ i = 0; LOCK; if (pklive(pk)==0) { pk->p_state = DOWN; UNLOCK; goto final; } pk->p_timer = 2; while (pk->p_xcount && pk->p_state&LIVE) { if (pk->p_state&(RCLOSE+DOWN) || ++i > NTRIES) break; pkoutput(pk); SLEEP(&pk->p_ps,PKOPRI); } pk->p_timer = 0; pk->p_state |= DOWN; UNLOCK; /* * try to exchange CLOSE messages */ i = 0; while ((pk->p_state&RCLOSE)==0 && ip_msg = M_CLOSE; pk->p_timer = 2; pkoutput(pk); SLEEP(&pk->p_ps, PKOPRI); i++; } final: TURNOFF; /* * free space */ rbits = DTOM(pk->p_rsize); for (i=0;i<8;i++) { if (pk->p_os[i]!=B_NULL) { FREEPACK(pk->p_ob[i],pk->p_bits); pk->p_xcount--; } if (pk->p_is[i]!=B_NULL) { FREEPACK(pk->p_ib[i],rbits); } } LOCK; while (pk->p_ipool != NULL) { bp = pk->p_ipool; pk->p_ipool = (char **)*bp; FREEPACK((caddr_t)bp, rbits); } UNLOCK; for(i=0;ip_ps = pk->p_pr = pk->p_rpr = 0; pk->p_nxtps = 1; } chksum(s,n) register char *s; register n; { register short sum; register unsigned t; register x; sum = -1; x = 0; do { if (sum<0) { sum <<= 1; sum++; } else sum <<= 1; t = sum; sum += (unsigned)*s++; x += sum^n; if ((unsigned)sum <= t) { sum ^= x; } } while (--n > 0); return(sum); } pkline(pk) register struct pack *pk; { register i; for(i=0;i>= 5; for(k=0; n >>= 1; k++); return(k); } ocess 0 to schedule * - process 1 execute bootstrap */ main() { extern char version[]; printf("\n%s", version); startup(); /* * set up system process */ proc[0].p_addr = *ka6; #ifndef VIRUS_VFORK proc[0].p_size = USIZE; #endif proc[0].p_stat = SRUN; proc[0].p_flag |= SLOAD|SSYS; *************** *** 145,167 fp->s_flock = 0; fp->s_ilock = 0; fp->s_ronly = sys/OTHERS/packet_driver/pk1.c 444 3 12 10422 3144315447 11360 #define KERNEL 1 #include #ifdef UCB_SCCSID static char sccs_id[] = "@(#)pk1.c 3.1"; #endif /* * kernel support routines. */ struct pack *pklines[NPLINES]; int maxwindow =2; /* * start initial synchronization. * allocate space. */ pkopen(dev, tp, addr) register struct tty *tp; caddr_t addr; { register struct pack *pk; register i; int pktimeout(); char **bp; static timer_on; int s; struct piocb piocb; if (tp->t_line) return; /* * copy user parameters */ if (copyin(addr, (caddr_t)&piocb, sizeof (piocb))) { u.u_error = EFAULT; return; } npbits = dtom(sizeof(struct pack)); pk = (struct pack *)getepack(npbits); if (pk==NULL) goto notsobad; pkzero((caddr_t)pk,sizeof (struct pack)); pk->p_rwindow = piocb.window; if (pk->p_rwindow > maxwindow) pk->p_rwindow = maxwindow; pk->p_rsize = piocb.psize; if (pk->p_rsize > 512 || pk->p_rsize & 037) goto notsobad; pk->p_mode = piocb.mode; if (pk->p_mode & 01) pkdebug++; /* * try to allocate input window */ pk->p_bits = dtom(pk->p_rsize); for(i=0; ip_rwindow; i++) { bp = (char **)getepack(pk->p_bits); if (bp==NULL) break; *bp = (char *)pk->p_ipool; pk->p_ipool = bp; } if (i==0 && bp==NULL) goto notsobad; pk->p_rwindow = i; /* * start timer process, * wait for synchronization. */ flushtty(tp); s = spl6(); pkdisc = tp->t_line = piocb.t; pk->p_ttyp = tp; tp->t_linep = (caddr_t)pk; q2.c_cf = q2.c_cl = NULL; q1.c_cf = q1.c_cl = (caddr_t)&pk->p_ihbuf; q1.c_cc = -HDRSIZ; if (tp->t_iproc != NULL) (*tp->t_iproc)(tp); pk->p_rmsg = M_INITA; for(i=0; ip_timer++; if (timer_on==0) { timer_on++; pktimeout(); } splx(s); SLEEP(&pk->p_state, PKOPRI); pkreset(pk); if ((pk->p_state&LIVE)==0) { pk->p_state = DOWN; pk->p_rmsg = 0; notsobad: u.u_error = ENXIO; return; } pksetgrp(tp); pkioctl(DIOCGETP, tp, addr); } /* * unix ioctl interface */ pkioctl(com,tp,addr) register struct tty *tp; caddr_t addr; { struct piocb piocb; register struct pack *pk; pk = (struct pack *)tp->t_linep; if (com == DIOCGETP) { piocb.window = pk->p_swindow; piocb.psize = pk->p_xsize; piocb.state = pk->p_state; if (copyout((caddr_t)&piocb, addr, sizeof(piocb))) { u.u_error = EFAULT; } if (u.u_error==0) u.u_r.r_val1 = piocb.psize; } } /* * Arrange for the device (i.e. tp) * to be able to generate signals if need be. */ pksetgrp(tp) register struct tty *tp; { register struct proc *pp; pp = u.u_procp; if (pp->p_pgrp == 0) pp->p_pgrp = pp->p_pid; if (tp->t_pgrp == 0) tp->t_pgrp = pp->p_pgrp; } /* * Shut down io. * The problem is mainly input since the * device driver may have a buffer. */ pkturnoff(tp) register struct tty *tp; { register char **bp; register struct pack *pk; register s; pk = PADDR; LOCK; bp = pk->p_io; tp->t_line = 0; q1.c_cf = NULL; flushtty(tp); if (bp!=NULL) { *bp = (char *)pk->p_ipool; pk->p_ipool = bp; } UNLOCK; } /* * link dead? */ pklive(pk) register struct pack *pk; { register struct tty *tp; tp = pk->p_ttyp; if (tp->t_line!=pkdisc || tp->t_linep!=(caddr_t)pk) { return(0); } return(tp->t_state&CARR_ON); } /* * timeout process: * wakes up periodically to check status * of active lines. */ pktimeout() { register struct pack *pk; extern time_t time; register i; for(i=0;ip_nout == pk->p_tout) { if (pk->p_xcount && pk->p_timer==0) { pk->p_timer = 3; pk->p_state |= WAITO; } } else pk->p_tout = pk->p_nout; if (pk->p_timer==0) { if (pk->p_state & BADFRAME) { pk->p_msg |= M_RJ; pk->p_state &= ~BADFRAME; goto startup; } if (pk->p_rmsg) goto startup; WAKEUP(&pk->p_ps); continue; } if (--pk->p_timer == 0) { if ((pk->p_state&LIVE)==0) { startup: pk->p_timer = 1; } else if (pk->p_state & WAITO) { if (pk->p_state&DRAINO) { pk->p_state |= DOWN; } else { pk->p_state |= RXMIT; } pkoutput(pk); pk->p_timer = 5+2*pkzot; } WAKEUP(&pk->p_ps); pk->p_msg |= pk->p_rmsg; if (pk->p_msg) pkoutput(pk); } } timeout(pktimeout, (caddr_t)pk, 60); /* * randomize timeouts. */ pkzot = 2 + time&07; } for synchronization. */ flushtty(tp); s = spl6(); pkdisc = tp->t_line = piocb.t; pk->p_ttyp = tp; tp->t_linep = (caddr_t)pk; q2.c_cf = q2.c_cl = NULL; q1.c_cf = q1.c_cl = (caddr_t)&pk->p_ihbuf; q1.c_cc = -HDRSIZ; if (tp->t_iprosys/OTHERS/packet_driver/pk2.c 444 3 12 10773 3530157701 11366 #define KERNEL 1 #include #ifdef UCB_SCCSID static char sccs_id[] = "@(#)pk2.c 3.1"; #endif /* * input framing and block checking. * frame layout for most devices is: * * S|K|X|Y|C|Z| ... data ... | * * where S == initial synch byte * K == encoded frame size (indexes pksizes[]) * X, Y == block check bytes * C == control byte * Z == XOR of header (K^X^Y^C) * data == 0 or more data bytes * * device driver interfaces on input are: * pkrint - byte level * pkrend - dma or pseudo-dma transfer level * pkdata - packet level */ int pksizes[] ={ 1, 32, 64, 128, 256, 512, 1024, 2048, 4096, 1 }; /* * Pseudo-dma byte collection. * This code can be put in the device driver * interrupt routine to eliminate the per byte * subroutine call. */ pkrint(c, tp) register c; register struct tty *tp; { if (q1.c_cc<0) { if (q1.c_cf != NULL) { tp->t_erase = 0; *q1.c_cf++ = c; } if (++q1.c_cc) return; pkrend(tp); return; } } /* * End of input transfer. */ pkrend(tp) register struct tty *tp; { register char *p; struct pack *pk; struct header *h; register x; char cntl, hdcheck; unsigned short sum; int i,j,k; char **bp; p = q1.c_cl; x = (int)q1.c_cf - (int)p; pk = (struct pack *)tp->t_linep; h = (struct header * )&pk->p_ihbuf; if (x == HDRSIZ) { if (*p++ == SYN ) { hdcheck = k = *p++; sum = (unsigned)*p; hdcheck ^= *p++; sum |= (unsigned)*p << 8; hdcheck ^= *p++; hdcheck ^= cntl = *p++; if (hdcheck != *p) { goto bad; } if (k == 9) { pkcntl(cntl, pk); q1.c_cf = q1.c_cl; q1.c_cc = -HDRSIZ; goto istart1; } if (k && pksizes[k]==pk->p_rsize) { pk->p_rpr = cntl&MOD8; pksack(pk); bp = pk->p_ipool; if (bp) { pk->p_ipool = (char **)*bp; pk->p_io = bp; } else { } q1.c_cf = (char *)bp; q1.c_cc = -pk->p_rsize; h->sum = sum; h->cntl = cntl; goto istart1; } bad: pkbadframe(pk); } scan: x = HDRSIZ; j = 0; p = (caddr_t)h; for (i = 1; i < HDRSIZ; i++) if (p[i] == SYN) for(x=i; ip_rsize) { pkdata(h->cntl, h->sum, pk, q1.c_cl); pk->p_io = NULL; q1.c_cf = (char *)h; q1.c_cc = -HDRSIZ; goto istart1; } if (x == 0) { q1.c_cf = (char *)h; q1.c_cc = -HDRSIZ; pkbadframe(pk); } else { pkbadframe(pk); goto scan; } istart1: q1.c_cl = q1.c_cf; istart2: if (tp->t_iproc != NULL) (*tp->t_iproc)(tp); } /* * Put packet located at address bp * in an input slot for further processing. */ pkdata(c, sum, pk, cp) char c; unsigned short sum; register struct pack *pk; char *cp; { register struct tty *tp; register x; char **bp; int t; pk->p_state &= ~BADFRAME; bp = (char **)cp; tp = pk->p_ttyp; if (pk->p_state&DRAINO || !(pk->p_state&LIVE)) { pk->p_msg |= pk->p_rmsg; pkoutput(pk); goto drop; } t = next[pk->p_pr]; for(x=pk->p_pr; x!=t; x = (x-1)&7) { if (pk->p_is[x] == 0) goto slot; } /* * this can't happen */ printf("no slot\n"); drop: *bp = (char *)pk->p_ipool; pk->p_ipool = bp; return; slot: pk->p_imap |= mask[x]; pk->p_is[x] = c; pk->p_isum[x] = sum; pk->p_ib[x] = cp; if (tp->t_chan) sdata(tp->t_chan); else wakeup(&pk->p_pr); } /* * Start transmission on output device associated with pk. * For asynch devices (t_line==1) framing is * imposed. For devices with framing and crc * in the driver (t_line==2) the transfer is * passed on to the driver. */ pkxstart(pk, cntl, x) struct pack *pk; char cntl; register x; { struct tty *tp; register char *p; short checkword; char hdcheck; p = (caddr_t)&pk->p_ohbuf; tp = pk->p_ttyp; if (tp->t_line==1) { *p++ = SYN; if (x < 0) { *p = 9; checkword = cntl; q3.c_cl = NULL; } else { *p = pk->p_lpsize; checkword = pk->p_osum[x] ^ (unsigned)cntl; q3.c_cl = pk->p_ob[x]; } checkword = CHECK - checkword; hdcheck = *p++; hdcheck ^= *p++ = checkword; hdcheck ^= *p++ = checkword>>8; q3.c_cc = -HDRSIZ; } else { q3.c_cc = -1; } hdcheck ^= *p++ = cntl; *p = hdcheck; q3.c_cf = (caddr_t)&pk->p_ohbuf; /* pk->p_srxmit++; */ (*tp->t_oproc)(tp); } /* * transmitter interrupt. */ int pkdelay = 2; pkxint(tp) register struct tty *tp; { register struct pack *pk; register s; extern int pkoutput(); pk = (struct pack *)tp->t_linep; s = spl6(); tp->t_state &= ~BUSY; if (q3.c_cl == NULL) { pkoutput(pk); } else { q3.c_cf = q3.c_cl; q3.c_cl = NULL; q3.c_cc = -pk->p_xsize; (*tp->t_oproc)(tp); } splx(s); } inal;sys/OTHERS/packet_driver/pk3.c 444 3 12 4734 3144315453 11350 #include #include #include #include #ifdef UCB_SCCSID static char sccs_id[] = "@(#)pk3.c 3.1"; #endif #define XPRI 30 #define NBLOCKS 10 int bwaiting, wcount; struct buf *bufps[NBLOCKS]; char *nbase[NBLOCKS]; /* normal allocations */ short nmap[NBLOCKS]; /* 1 bit == 32 bytes */ char log[] ={0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4}; #define FULL -1 #define LOCK s = spl6() #define UNLOCK splx(s) /* * getepack: get empty packet * with size specified by bitmask. */ char * getepack(bits) { register i; int s, savbits; char **base; short *map; base = nbase; map = nmap; savbits = bits; /* * search for space */ LOCK; for(;;) { if (bits == FULL) goto force; for(i=0; i 16; n >>= 4) offset += 4; offset += log[n]; } else { bits = savbits; for(n=17; --n; bits <<= 1) if ((m&bits)==0) goto found; continue; found: offset = 16-n; m |= bits; } map[i] = m; UNLOCK; return(base[i] + 32*offset); } /* * grab another block from the system */ force: for(i=0;ib_flags |= B_PACK; bp->b_flags |= B_PBUSY; map[i] = bits; base[i] = bp->b_un.b_addr; UNLOCK; return(bp->b_un.b_addr); } /* * sleep until something is released */ bwaiting++; wcount++; sleep((caddr_t)&bwaiting, XPRI); bwaiting--; } } /* * freepack: release space beginning * at address p with length specified * by bits. */ freepack(p, bits) char *p; { register i, d, s; char **base; short *map; if (p==NULL) return; LOCK; base = nbase; map = nmap; for(i=0;i=0 && d<=512) goto found; } goto out; found: d >>= 5; d = (bits<b_flags &= ~B_PBUSY; base[i] = NULL; bufps[i] = NULL; #ifdef UCB_BUFOUT abrelse(bp); #else brelse(bp); #endif } if (bwaiting) wakeup((caddr_t)&bwaiting); out: splx(s); } /* * integer to bitmap conversion */ dtom(d) register d; { register m; m = 1; while (d>32) { d -= 32; m |= m+1; } return(m); } #define NRECS 160 int reclist[NRECS]; int recbits[NRECS]; t_iproc)(tp); } /* * Put packet sys/OTHERS/packet_driver/pack.h 444 3 12 4264 3562773620 11604 struct header { char sync; char ksize; short sum; char cntl; char ccntl; }; #define HDRSIZ 6 struct pack { short p_state; /* line state */ short p_bits; /* mask for getepack */ short p_rsize; /* input packet size */ short p_xsize; /* output packet size */ struct header p_ihbuf; /* input header */ struct header p_ohbuf; /* output header */ char *p_rptr; char p_mode; char **p_ipool; char p_xcount; /* # active output buffers */ char p_rcount; char p_nout,p_tout; char p_lpsize; /* log(psize/32) */ char p_timer; char p_obusy; char p_srxmit; char p_rwindow; /* window size */ char p_swindow; char p_msg; /* control msg */ char p_rmsg; /* repeated control msg */ char p_ps,p_pr; /* last packet sent, recv'd */ char p_rpr; char p_nxtps; /* next output seq number */ char p_imap; /* bit map of input buffers */ char p_pscopy; /* newest output packet */ char *p_ob[8]; /* output buffers */ char *p_ib[8]; /* input buffers */ char p_os[8]; /* output buffer status */ char p_is[8]; /* input fine PKIPRI 30 #define NPLINES 8 /* * packet ioctl buf */ struct piocb { u_short t; short psize; short mode; short state; char window; }; short pkdebug; short pksizes[]; ); #else brelse(bp); #endif } if (bwaiting) wakeup((caddr_t)&bwaiting); out: splx(s); } /* * integer to bitmap conversion */ dtom(d) register d; { register m; m = 1; while (d>32) { d -= 32; m |= m+1; } return(m); } #define NRECS 160 int reclist[NRECS]; int recbits[NRECS]; t_iproc)(tp); } /* * Put packet sys/OTHERS/packet_driver/pk.h 444 3 12 5604 3562773621 11300 /* * six-byte packet header for asynch lines. * headers for other devices take up the same * or less space. If this changes the header * struct will have to become a union. */ struct header { char sync; /* sync byte */ char ksize; /* encoded packet size */ u_short sum; /* block check of data packet */ char cntl; /* control byte */ char ccntl; /* block check of header */ }; #define HDRSIZ 6 /* * Control structure for a packet driver connection. */ struct pack { short p_state; /* line state */ short p_bits; /* mask for getepack */ short p_rsize; /* input packet size */ short p_xsize; /* output packet size */ struct header p_ihbuf; /* input header */ struct header p_ohbuf; /* output header */ char *p_rptr; char p_mode; char **p_ipool; /* head link to input buffer pool */ char **p_io; /* input buffer given to driver */ char p_xcount; /* # active output buffers */ char p_rcount; char p_nout,p_tout; char p_lpsize; /* log(psize/32) */ char p_timer; char p_obusy; char p_srxmit; char p_rwindow; /* window size */ char p_swindow; char p_msg; /* control msg */ char p_rmsg; /* repeated control msg */ char p_ps,p_pr; /* last packet sent, recv'd */ char p_rpr; /* copy of remote pr */ char p_nxtps; /* next output seq number */ char p_imap; /* bit map of input buffers */ char p_pscopy; /* newest output packet */ char *p_ob[8]; /* output buffers */ char *p_ib[8]; /* input buffers */ char p_os[8]; /* output buffer status */ char p_is[8]; /* input buffer status */ short p_osum[8]; /* output checksums */ short p_isum[8]; /* input checksums */ DSYSTEM; }; #define CHECK 0125252 #define SYN 020 #define MOD8 7 #define NOTCNTL(a) (a & 0300) #ifndef MIN #define MIN(a,b) (((a)<(b))? (a):(b)) #endif char next[8]; char mask[8]; short npbits; short pkactive; short pkzot; short pkdisc; /* * driver state */ #define DEAD 0 #define INITa 1 #define INITb 2 #define INITab 3 #define LIVE 010 #define RXMIT 020 #define RREJ 040 #define PDEBUG 0200 #define DRAINO 0400 #define WAITO 01000 #define DOWN 02000 #define RCLOSE 04000 #define BADFRAME 020000 /* * modes */ #define SLOWMODE 0100 /* * io buffer states */ #define B_NULL 0 #define B_READY 1 #define B_SENT 2 #define B_RESID 010 #define B_COPY 020 #define B_MARK 040 #define B_SHORT 0100 /* * control messages */ #define CLOSE 1 #define RJ 2 #define SRJ 3 #define RR 4 #define INITC 5 #define INITB 6 #define INITA 7 #define M_RJ 4 #define M_SRJ 010 #define M_RR 020 #define M_INITC 040 #define M_CLOSE 2 #define M_INITA 0200 #define M_INITB 0100 #define PKOPRI 31 #define PKIPRI 30 #define NPLINES 8 /* * packet ioctl buf */ struct piocb { unsigned t; short psize; short mode; short state; char window; }; short pkdebug; short pksizes[]; #define Pwrite 1 #define Poutput 1 #define Pxint 1 #define Print 01 #define Prend 01 #define Pacc 01 #define Pread 01 short *PTRACE; #define ISCNTL(a) ((a & 0300) == 0) t = next[pk->p_pr]; for(x=pk->p_pr; x!=t; x = (x-1)&7) { if (pk->p_is[x] == 0) goto slot; } /* * this can't happesys/OTHERS/packet_driver/pack.h_#2 444 3 12 4577 3770363641 12076 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)pack.h 5.1 (Berkeley) 12/13/86 */ struct header { char sync; char ksize; u_short sum; char cntl; char ccntl; }; #define HDRSIZ 6 struct pack { short p_state; /* line state */ short p_bits; /* mask for getepack */ short p_rsize; /* input packet size */ short p_xsize; /* output packet size */ struct header p_ihbuf; /* input header */ struct header p_ohbuf; /* output header */ char *p_rptr; char p_mode; char **p_ipool; char p_xcount; /* # active output buffers */ char p_rcount; char p_nout,p_tout; char p_lpsize; /* log(psize/32) */ char p_timer; char p_obusy; char p_srxmit; char p_rwindow; /* window size */ char p_swindow; char p_msg; /* control msg */ char p_rmsg; /* repeated control msg */ char p_ps,p_pr; /* last packet sent, recv'd */ char p_rpr; char p_nxtps; /* next output seq number */ char p_imap; /* bit map of input buffers */ char p_pscopy; /* newest output packet */ char *p_ob[8]; /* output buffers */ char *p_ib[8]; /* input buffers */ char p_os[8]; /* output buffer status */ char p_is[8]; /* input buffer status */ short p_osum[8]; /* output checksums */ short p_isum[8]; /* input checksums */ DSYSTEM; }; #define CHECK 0125252 #define SYN 020 #define MOD8 7 #define ISCNTL(a) ((a & 0300)==0) #define MIN(a,b) ((a 0 #include "param.h" #include #include #include #include #define N_NAP 32 #define NAPPRI 31 int ttnap[N_NAP]; /*ARGSUSED*/ napioctl(dev, cmd, addr, flags) dev_t dev; caddr_t addr; { int wakeup(); int *ptr; for(ptr=ttnap; *ptr && (ptr <= &ttnap[N_NAP]); ptr++) ; if(ptr == &ttnap[N_NAP]) { u.u_error = ENXIO; return; } *ptr = u.u_procp->p_pid; timeout(wakeup, ptr, cmd); sleep(ptr, NAPPRI); *ptr = 0; } /*ARGSUSED*/ napclose(dev, flags) dev_t dev; { int *ptr; for(ptr=ttnap; (*ptr != u.u_procp->p_pid) && (ptr <= &ttnap[N_NAP]); ptr++) ; if(*ptr == u.u_procp->p_pid) *ptr = 0; } #endif NNAP char p_nout,p_tout; char p_lpsize; /* log(psize/32) */ char p_timer; char p_obusy; char p_srxmit; char p_rwindow; /* window size */ char p_swindow; char p_msg; /* control msg */ char p_rmsg; /* repeated control msg */ char p_ps,p_pr; /* last packet sent, recv'd */ char p_rpr; char p_nxtps; /* next output seq nsys/OTHERS/du11/ 755 0 12 0 5676504577 6364 sys/OTHERS/du11/du.c 444 3 12 25762 5666036330 7244 /* * SCCS id @(#)du.c 2.2 (2.11BSD) 11/26/94 */ /* * DU-11 and DUP-11 synchronous line interface driver */ #include "du.h" #if NDU > 0 #include "param.h" #include #include #include #include #include #include extern struct dudevice *DUADDR; /* * receiver interrupt code state definitions */ #define RIDLE 0 /* idle, waiting for a message */ #define RRUN 1 /* running, message in progress */ #define RQUIT1 2 /* quit, trashing all until carrier drop */ #define RQUIT2 3 /* same as above, but return error */ /* * transmitter interrupt code state definitions */ #define TIDLE 0 /* idle, waiting for a message */ #define TRUN 1 /* running, message in progress */ #define TLAST 2 /* sending last character */ #define TCARDRP 3 /* waiting for carrier hold-down delay */ /* * miscellaneous defintions */ #define SYN 026 /* sync character */ #define MSGN 5 /* number of message buffers each direction */ #define MSGLEN 102 /* length of each message buffer */ #define TIMEOUT 3 /* number of seconds before receive timeout */ #define TDELAY 2 /* number ticks to hold down xmit carrier */ #define DUPRI 5 /* du11 sleep priority */ /* * message buffer descriptor */ struct msgbuf { caddr_t msgbufp; /* pointer to message buffer */ char msgbc; /* message byte count */ char msgerr; /* nonzero if error in message */ }; /* * du11 control info */ struct { struct proc *duproc; /* process adr of caller, 0 if closed */ /* * Transmit info */ struct buf *dutbufp; /* pointer to transmit buffer */ struct msgbuf dutbuff[MSGN]; /* message buffer descriptors */ struct msgbuf *dutbufi; /* in pointer */ struct msgbuf *dutbufo; /* out pointer */ short dutbufn; /* number of message buffers that are full */ short dutstate; /* state of transmitter interrupt code */ caddr_t dutbufc; /* char ptr for message in progress */ short dutbc; /* byte count of message in progress */ short dutdna; /* number of times data not available */ /* * Receive info */ struct msgbuf durbuff[MSGN]; /* message buffer descriptors */ struct msgbuf *durbufi; /* in pointer */ struct msgbuf *durbufo; /* out pointer */ short durbufn; /* number of message buffers that are full */ short durstate; /* state of receiver interrupt code */ caddr_t durbufc; /* char ptr for message in progress */ short durbc; /* byte count of message in progress */ short durtimer; /* seconds left until timeout */ short durover; /* number of receiver data overruns */ short durfull; /* number of times receive buffer full */ short durlong; /* number of messages > 255 bytes */ } du11; #define MAINTDEV 1 /* minor device for maintenance mode */ int maint; /* nonzero if open for maintenance */ /*ARGSUSED*/ duopen(dev, flag) dev_t dev; { register struct dudevice *duaddr = DUADDR; register n; extern durtimeout(); if (du11.duproc == u.u_procp) return; if (du11.duproc) { u.u_error = ENXIO; return; } /* * Check whether opening for maintenance mode */ if (minor(dev) == MAINTDEV) maint = 1; else maint = 0; /* * reset device */ duaddr->dutcsr = DUTCSR_MR; /* * Allocate transmit buffer */ du11.dutbufp = geteblk(); du11.dutbufi = du11.dutbufo = du11.dutbuff; du11.dutbufn = 0; for(n = 0; n < MSGN; n++) du11.dutbuff[n].msgbufp = du11.dutbufp->b_un.b_addr + MSGLEN*n; du11.dutstate = TIDLE; /* * Allocate receive buffer */ for(n = 0; n < MSGN; n++) du11.durbuff[n].msgbufp = (du11.dutbufp->b_un.b_addr+(BSIZE/2)) + (MSGLEN * n); du11.durbufi = du11.durbufo = du11.durbuff; du11.durbufn = 0; du11.durstate = RIDLE; /* * Start 1 second receiver timeout clock */ du11.durtimer = 0; timeout(durtimeout, 0, hz); du11.duproc = u.u_procp; /* * Set parameters according to whether du11 or dup11 */ #ifdef DU11 duaddr->durdbuf = DUPARCSR_8BITS | DUPARCSR_ISYNC | SYN; #else duaddr->durdbuf = DUPARCSR_DEC | DUPARCSR_CRCINH | SYN; if (maint) duaddr->dutcsr = DUTCSR_MPSYSTST; #endif /* * Start receiver */ duaddr->durcsr = DU_STSYNC | DU_DTR | DU_SSYNC; } duclose() { register struct dudevice *duaddr = DUADDR; /* * Stop device and disable interrupts */ duaddr->durcsr = 0; duaddr->dutcsr = 0; /* * Stop timer */ du11.durtimer = -1; while (du11.durtimer) sleep(&du11.durstate, DUPRI); /* * Stop interrupt code for sure */ du11.duproc = 0; /* * Release buffers */ #ifdef UCB_BUFOUT #define brelse abrelse #endif brelse(du11.dutbufp); /* * clear maintenance mode flag */ maint = 0; } duread(dev, uio) dev_t dev; struct uio *uio; { register nbytes; /* * wait for a message to appear in the receive buffer or for TIMEOUT * seconds to elapse */ du11.durtimer = TIMEOUT; (void) _spl6(); while (du11.durbufn == 0) { if (du11.durtimer == 0) { (void) _spl0(); return; } sleep(&du11.durstate, DUPRI); } (void) _spl0(); du11.durtimer = 0; /* * if an error was detected on this message, throw it away and return * an error to the caller */ if (du11.durbufo->msgerr) { if (++du11.durbufo == du11.durbuff + MSGN) du11.durbufo = du11.durbuff; du11.durbufn--; u.u_error = EIO; return; } /* * Copy the message to the caller's buffer */ nbytes = min(uio->uio_resid, du11.durbufo->msgbc); uiomove(du11.durbufo->msgbufp, nbytes, uio); if (++du11.durbufo == du11.durbuff + MSGN) du11.durbufo = du11.durbuff; du11.durbufn--; } duwrite(dev, uio) dev_t dev; struct uio *uio; { register nbytes; /* * Wait for there to be room for the message in the buffer */ while (du11.dutbufn == MSGN) sleep(&du11.dutstate, DUPRI); /* * Transfer the message from the caller's buffer to ours */ nbytes = min(uio->uio_resid, MSGLEN); du11.dutbufi->msgbc = nbytes; uiomove(du11.dutbufi->msgbufp, nbytes, uio); if (++du11.dutbufi == du11.dutbuff + MSGN) du11.dutbufi = du11.dutbuff; du11.dutbufn++; /* * If the interrupt code is not running, start it up */ if (du11.dutstate == TIDLE) duxstart(); } durint() { register c, dustat; register struct dudevice *duaddr = DUADDR; dustat = duaddr->durcsr; if (du11.duproc == 0) { duaddr->dutcsr = DUTCSR_MR; if (maint) #ifdef DU11 duaddr->dutcsr |= DUTCSR_MSYSTST; #ifdef UCB_DEVERR printf("durint: er=%b\n", dustat, DU_BITS); #else printf("durint err %o\n", dustat); #endif #else duaddr->dutcsr |= DUTCSR_MPSYSTST; #ifdef UCB_DEVERR printf("durint: er=%b\n", dustat, DU_PBITS); #else printf("durint err %o\n", dustat); #endif #endif DU11 return; } switch(du11.durstate) { /* * Wait for the first char to be rcvd, ignoring carrier changes */ case RIDLE: if ((dustat & DU_RDONE) == 0) return; if (du11.durbufn == MSGN) goto rfull; du11.durbufc = du11.durbufi->msgbufp; /* set up char ptr */ du11.durbufi->msgerr = 0; /* set no error in msg */ du11.durbc = 0; /* set byte count */ du11.durstate = RRUN; /* set message in progress */ /* * A message is in progress */ case RRUN: if (dustat & DU_RDONE) { /* a character has arrived */ c = duaddr->durdbuf; /* * End message if lost character or message too long */ if (c & DURDBUF_OVERRUN) { du11.durover++; goto rerror; } if (du11.durbc++ == MSGLEN) { du11.durlong++; goto rerror; } *du11.durbufc++ = c; } if ((dustat & DU_CAR) == 0) /* carrier drop means */ break; /* end of message */ return; /* * We have used up all the message buffers. Throw the * message away. */ rfull: du11.durfull++; du11.durstate = RQUIT1; case RQUIT1: if ((dustat & DU_CAR) == 0) { du11.durstate = RIDLE; duaddr->durcsr &= ~DU_SSYNC; /* desync receiver */ duaddr->durcsr |= DU_SSYNC; } c = duaddr->durdbuf; return; /* * Flag the message no good and junk the rest of it */ rerror: du11.durbufi->msgerr++; du11.durstate = RQUIT2; case RQUIT2: c = duaddr->durdbuf; if (dustat & DU_CAR) return; } /* * The message is finished. Set up the byte count and advance * the in pointer to pass the message to the upper-level code. */ du11.durbufi->msgbc = du11.durbc; if (++du11.durbufi == du11.durbuff + MSGN) du11.durbufi = du11.durbuff; du11.durbufn++; du11.durstate = RIDLE; duaddr->durcsr &= ~DU_SSYNC; /* desync receiver */ duaddr->durcsr |= DU_SSYNC; c = duaddr->durdbuf; wakeup(&du11.durstate); } duxint() { register dustat; register struct dudevice *duaddr = DUADDR; extern duxfin(); dustat = duaddr->dutcsr; if (du11.duproc == 0) { duaddr->dutcsr = DUTCSR_MR; if (maint) #ifdef DU11 duaddr->dutcsr |= DUTCSR_MSYSTST; #ifdef UCB_DEVERR printf("duxint: er=%b\n", dustat, DUTCSR_BITS); #else printf("duxint err %o\n", dustat); #endif #else duaddr->dutcsr |= DUTCSR_MPSYSTST; #ifdef UCB_DEVERR printf("duxint: er=%b\n", dustat, DUTCSR_PBITS); #else printf("duxint err %o\n", dustat); #endif #endif return; } switch(du11.dutstate) { /* * A message is in progress */ case TRUN: /* * Count number of times data not available */ if (dustat & DUTCSR_NODATA) du11.dutdna++; if (dustat & DUTCSR_TDONE) { if (--du11.dutbc) { /* if there are more chars */ duaddr->dutdbuf = *du11.dutbufc++ & 0377; #ifndef DU11 if (du11.dutbc == 1) { duaddr->dutdbuf = DURDBUF_REOM; duaddr->dutcsr &= ~DUTCSR_SEND; du11.dutstate = TLAST; } #endif } #ifdef DU11 else /* wait for the last one */ { duaddr->dutcsr = DUTCSR_SEND | DUTCSR_DNAIE; if (maint) duaddr->dutcsr |= DUTCSR_MSYSTST; du11.dutstate = TLAST; } #endif } return; /* * Wait for the data not available flag, signifying that the * last char has been completely sent */ case TLAST: #ifdef DU11 if (dustat & DUTCSR_NODATA) #endif { du11.dutstate = TCARDRP; duaddr->dutcsr = 0; /* drop carrier */ if (maint) #ifdef DU11 duaddr->dutcsr |= DUTCSR_MSYSTST; #else duaddr->dutcsr |= DUTCSR_MPSYSTST; #endif duaddr->durcsr &= ~DU_RTS; timeout(duxfin, 0, TDELAY); } } } /* * Carrier hold-down delay completed */ duxfin() { if (++du11.dutbufo == du11.dutbuff + MSGN) du11.dutbufo = du11.dutbuff; du11.dutbufn--; du11.dutstate = TIDLE; /* * If there is another message in the buffer, start sending it */ if (du11.dutbufi != du11.dutbufo) duxstart(); wakeup(&du11.dutstate); } /* * Start transmitting a new message */ duxstart() { register struct dudevice *duaddr = DUADDR; du11.dutbc = du11.dutbufo->msgbc; du11.dutbufc = du11.dutbufo->msgbufp; du11.dutstate = TRUN; duaddr->durcsr |= DU_RTS; duaddr->dutcsr = DUTCSR_SEND; if (maint) #ifdef DU11 duaddr->dutcsr |= DUTCSR_MSYSTST; #else duaddr->dutcsr |= DUTCSR_MPSYSTST; #endif duaddr->dutdbuf = DURDBUF_RSOM | (*du11.dutbufc++ & 0377); /* * Turn on interrupts */ duaddr->durcsr |= DU_RIE; duaddr->dutcsr |= DUTCSR_TIE; } /* * Exit if being closed */ durtimeout() { if (du11.durtimer < 0) { du11.durtimer = 0; wakeup(&du11.durstate); return; } /* * If duread is sleeping, decrement timer and wakeup if time's up */ if (du11.durtimer > 0) if (--du11.durtimer == 0) wakeup(&du11.durstate); timeout(durtimeout, 0, hz); } #endif NDU de */ if (msys/OTHERS/du11/dureg.h 444 3 12 12111 3000735030 7706 struct dudevice { short durcsr; /* receiver status register */ short durdbuf; /* receiver data buffer register */ #define duparcsr durdbuf /* (parameter control register on write) */ short dutcsr; /* transmitter status register */ short dutdbuf; /* transmitter data buffer register */ }; /* bits in durcsr */ #define DU_DSCHG 0100000 /* data set change in du11 */ #define DU_DSCHGA DU_DSCHG /* data set change A in dup11 */ #define DU_RING 0040000 /* ring indicator */ #define DU_CTS 0020000 /* clear to send */ #define DU_CAR 0010000 /* carrier */ #define DU_RACT 0004000 /* receiver active */ #define DU_SRDATA 0002000 /* secondary received data */ #define DU_DSRDY 0001000 /* data set ready */ #define DU_STSYNC 0000400 /* strip sync */ #define DU_RDONE 0000200 /* receiver done */ #define DU_RIE 0000100 /* receiver interrupt enable */ #define DU_DSIE 0000040 /* data set interrupt enable */ #define DU_SSYNC 0000020 /* search sync in du11 */ #define DU_RCVEN DU_SSYNC /* receiver interrupt enable in dup11 */ #define DU_STD 0000010 /* secondary transmit data */ #define DU_RTS 0000004 /* request to send */ #define DU_DTR 0000002 /* data terminal ready */ /* bit 0 is unused in du11 */ #define DU_DSCHGB 0000001 /* data set change B in dup11 */ #define DU_BITS \ "\10\20DSCHG\17RING\16CTS\15CAR\14RACT\13SRDATA\12DSRDY\11STSYNC\10RDONE\ \7RIE\6DSIE\5SSYNC\4STD\3RTS\2DTR" #define DU_PBITS \ "\10\20DSCHGA\17RING\16CTS\15CAR\14RACT\13SRDATA\12DSRDY\11STSYNC\10RDONE\ \7RIE\6DSIE\5RCVEN\4STD\3RTS\2DTR\1DSCHGB" /* bits in durdbuf */ #define DURDBUF_ERR 0100000 /* error */ #define DURDBUF_OVERRUN 0040000 /* overrun */ /* bit 13 is unused in dup11 */ #define DURDBUF_FE 0020000 /* framing error in du11 */ #define DURDBUF_PE 0010000 /* parity error in du11 */ #define DURDBUF_RCRC DURDBUF_PE /* RCRC error + Zero in dup11 */ /* bit 11 is unused */ /* bits 10-8 are unused in dup11 */ #define DURDBUF_RABORT 0002000 /* received ABORT in dup11 */ #define DURDBUF_REOM 0001000 /* end of received message in dup11 */ #define DURDBUF_RSOM 0000400 /* start of received message in dup11 */ /* bits 7-0 are the receiver data buffer */ #define DURDBUF_BITS "\10\20ERR\17OVERRUN\16\FE\15PE" #define DURDBUF_PBITS "\10\20ERR\17OVERRUN\15RCRC\13RABORT\12REOM\11RSOM" /* bits in duparcsr */ /* bit 15 is unused in du11 */ #define DUPARCSR_DEC 0100000 /* DEC mode in dup11 */ /* bit 14 is unused */ /* bit 13 is unused in dup11 */ /* bits 13-12 are mode select in du11 */ #define DUPARCSR_SMSEL 0010000 /* secondary mode select in dup11 */ /* bits 11-10 are word length select in du11 and unused in dup11 */ #define DUPARCSR_PE 0001000 /* parity error in du11 */ #define DUPARCSR_CRCINH DUPARCSR_PE /* CRC inhibit in dup11 */ /* bit 8 is unused in dup11 */ #define DUPARCSR_EVEN 0000400 /* select even parity in du11 */ /* bits 7-0 are the sync register */ #define DUPARCSR_BITS "\10\12PE\11EVEN" #define DUPARCSR_PBITS "\10\20DEC\15SMSEL\12CRCINH" /* duparcsr mode select bits in du11 */ #define DUPARCSR_XSYNC 0020000 /* synchronous external */ #define DUPARCSR_ISYNC 0030000 /* synchronous internal */ /* duparcsr word length select bits in du11 */ #define DUPARCSR_8BITS 0006000 /* eight bits per character */ #define DUPARCSR_7BITS 0004000 /* seven bits per character */ #define DUPARCSR_6BITS 0002000 /* six bits per character */ #define DUPARCSR_5BITS 0000000 /* five bits per character */ /* bits in dutcsr */ #define DUTCSR_NODATA 0100000 /* data not available in du 11 */ #define DUTCSR_DATALATE DUTCSR_NODATA /* data late error in dup11 */ #define DUTCSR_MD 0040000 /* maintenance data */ #define DUTCSR_MC 0020000 /* maintenance clock */ /* bits 12-11 are maintenance mode select in du11*/ /* bits 12-11 are maintenance mode select A and B in dup11*/ /* bit 10 is called ``maintenance bit window'' in earlier du11 manuals */ #define DUTCSR_RI 0002000 /* receiver input in du11 */ #define DUTCSR_MMSELECT DUTCSR_RI /* maintenance mode select A and B in dup11 */ /* bit 9 is unused in du11 */ #define DUTCSR_TACT 0001000 /* transmitter active in dup11 */ #define DUTCSR_MR 0000400 /* master reset */ #define DUTCSR_TDONE 0000200 /* transmitter done */ #define DUTCSR_TIE 0000100 /* transmitter interrupt enable */ /* bit 5 is unused in dup11 */ #define DUTCSR_DNAIE 0000040 /* data not available interrupt enable in du11 */ #define DUTCSR_SEND 0000020 /* send */ #define DUTCSR_HDX 0000010 /* half/full duplex */ /* bits 2-1 are unused */ /* bit 0 is unused in dup11 */ #define DUTCSR_BRK 0000001 /* break in du11 */ #define DUTCSR_BITS \ "\10\20NODATA\17MD\16MC\13RI\11MR\10TDONE\7TIE\6DNAIE\5SEND\4HDX\1BRK" #define DUTCSR_PBITS \ "\10\20DATALATE\17MD\16MC\13MMSELECT\12TACT\11MR\10TDONE\7TIE\5SEND\4HDX" /* dutcsr maintenance mode select bits in du11 */ #define DUTCSR_MSYSTST 0014000 /* internal mode for systems testing */ #define DUTCSR_MEXTERN 0010000 /* external */ #define DUTCSR_MINTERN 0004000 /* internal */ #define DUTCSR_MNORMAL 0000000 /* normal */ /* dutcsr maintenance mode select A and B bits in dup11 (some are the same) */ #define DUTCSR_MPSYSTST DUTCSR_MINTERN #define DUTCSR_MPINTERN DUTCSR_MSYSTST durbufn--; u.u_error = EIO; return; } /* * Copy the message to the caller's buffer */ nbytes = min(uio->uio_resid, du11.durbufo->msgbc); uiomove(du11.durbufo->msgbufp, nbytes, uio); if (++du11.durbufo == du11.durbuff + MSGN) du11.durbufo = du11.durbuff; du11.durbufn--; } duwrite(dev, uio) dev_t dev; struct uio *uio; { register nbytes; /* * Wait for there to be room for the message in the buffer */ while (du1sys/OTHERS/multiplexor/ 755 0 12 0 3771403565 10163 sys/OTHERS/multiplexor/mx1.c 444 3 12 7736 3552650470 11133 #include "param.h" #include #include #include #include #include #include #include #include #include /* * SCCS id @(#)mx1.c 2.1 (Berkeley) 8/5/83 */ /* * Multiplexor: clist version * * installation: * requires a line in cdevsw - * mxopen, mxclose, mxread, mxwrite, mxioctl, 0, * * also requires a line in linesw - * mxopen, mxclose, mcread, mcwrite, mxioctl, nulldev, nulldev, * * The linesw entry for mpx should be the last one in the table. * 'nldisp' (number of line disciplines) should not include the * mpx line. This is to prevent mpx from being enabled by an ioctl. * mxtty.c must be loaded instead of tty.c so that certain * sleeps will not be done if a typewriter is connected to * a channel and so that sdata will be called from ttyinput. * */ struct chan chans[NCHANS]; struct schan schans[NPORTS]; struct group *groups[NGROUPS]; int mpxline; struct chan *xcp(); dev_t mpxdev = -1; char mcdebugs[NDEBUGS]; /* * Allocate a channel, set c_index to index. */ struct chan * challoc(index, isport) { register s,i; register struct chan *cp; s = spl6(); for(i=0;i<((isport)?NPORTS:NCHANS);i++) { cp = (isport)? (struct chan *)(schans+i): chans+i; if(cp->c_group == NULL) { cp->c_index = index; cp->c_pgrp = 0; cp->c_flags = 0; splx(s); return(cp); } } splx(s); return(NULL); } /* * Allocate a group table cell. */ gpalloc() { register i; for (i=NGROUPS-1; i>=0; i--) if (groups[i]==NULL) { groups[i]++; return(i); } u.u_error = ENXIO; return(i); } /* * Add a channel to the group in * inode ip. */ struct chan * addch(ip, isport) struct inode *ip; { register struct chan *cp; register struct group *gp; register i; plock(ip); gp = &ip->i_un.i_group; for(i=0;ig_chans[i]; if (cp == NULL) { if ((cp=challoc(i, isport)) != NULL) { gp->g_chans[i] = cp; cp->c_group = gp; } break; } cp = NULL; } prele(ip); return(cp); } /* * Mpxchan system call. */ mpxchan() { extern mxopen(), mcread(), sdata(), scontrol(); struct inode *ip, *gip; struct tty *tp; struct file *fp, *chfp, *gfp; struct chan *cp; struct group *gp, *ngp; struct mx_args vec; struct a { int cmd; int *argvec; } *uap; dev_t dev; register int i; /* * Common setup code. */ uap = (struct a *)u.u_ap; (void) copyin((caddr_t)uap->argvec, (caddr_t)&vec, sizeof vec); gp = NULL; gfp = NULL; cp = NULL; switch(uap->cmd) { case NPGRP: if (vec.m_arg[1] < 0) break; case CHAN: case JOIN: case EXTR: case ATTACH: case DETACH: case CSIG: gfp = getf(vec.m_arg[1]); if (gfp==NULL) return; gip = gfp->f_inode; gp = &gip->i_un.i_group; if (gp->g_inode != gip) { u.u_error = ENXIO; return; } } switch(uap->cmd) { /* * Create an MPX file. */ case MPX: case MPXN: if (mpxdev < 0) { for (i=0; linesw[i].l_open; i++) { if (linesw[i].l_read==mcread) { mpxline = i; for (i=0; cdevsw[i].d_open; i++) { if (cdevsw[i].d_open==mxopen) { mpxdev = (dev_t)(i<<8); } } } } if (mpxdev < 0) { u.u_error = ENXIO; return; } } if (uap->cmd==MPXN) { if ((ip=ialloc(pipedev))==NULL) return; ip->i_mode = ((vec.m_arg[1]&0777)+IFMPC) & ~u.u_cmask; ip->i_flag = IACC|IUPD|ICHG; } else { u.u_dirp = vec.m_name; ip = namei(uchar,1); if (ip != NULL) { i = ip->i_mode&IFMT; u.u_error = EEXIST; if (i==IFMPC || i==IFMPB) { i = minor(ip->i_un.i_rdev); gp = groups[i]; if (gp && gp->g_inode==ip) u.u_error = EBUSY; } iput(ip); return; } if (u.u_error) return; ip = maknode((vec.m_arg[1]&0777)+IFMPC); if (ip == NULL) return; } if ((i=gpalloc()) < 0) { iput(ip); return; } if ((fp=falloc()) == NULL) { iput(ip); groups[i] = NULL; return; } ip->i_un.i_rdev = (daddr_t)(mpxdev+i); ip->i_count++; prele(ip); CSR_TACT 0001000 /* transmitter asys/OTHERS/multiplexor/mx2.c 444 3 12 36642 4610661177 11154 /* * SCCS id @(#)mx2.c 2.1 (Berkeley) 8/5/83 */ #include "param.h" #include #include #include #include #include #include #include #include #include /* * multiplexor driver */ struct chan chans[NCHANS]; struct group *groups[NGROUPS]; int mpxline; short cmask[16] ={ 01, 02, 04, 010, 020, 040, 0100, 0200, 0400, 01000, 02000, 04000, 010000, 020000, 040000, 0100000 }; #define IOMOVE iomove struct chan *xcp(),*addch(),*nextcp(); #define HIQ 100 #define LOQ 20 #define FP ((struct file *)cp) char mcdebugs[NDEBUGS]; struct group * getmpx(dev) dev_t dev; { register d; d = minor(dev); if (d >= NGROUPS) { u.u_error = ENXIO; return(NULL); } return(groups[d]); } /*ARGSUSED*/ mxopen(dev, flag) { register struct group *gp; register struct file *fp; register struct chan *cp; int msg; if ((gp=getmpx(dev)) == NULL) { return; } if (!(gp->g_state&INUSE)) { u.u_error = ENXIO; return; } fp = u.u_ofile[u.u_r.r_val1]; if (fp->f_inode != gp->g_inode) { u.u_error = ENXIO; return; } if ((cp=addch(gp->g_inode,0)) == NULL) { u.u_error = ENXIO; return; } cp->c_flags = XGRP; cp->c_ottyp = cp->c_ttyp = (struct tty *)cp; cp->c_line = cp->c_oline = mpxline; fp->f_flag |= FMPY; fp->f_flag |= FREAD+FWRITE; fp->f_un.f_chan = cp; if (gp->g_inode == mpxip) { plock(mpxip); mpxname(cp); msg = M_OPEN; } else msg = M_WATCH; scontrol(cp, msg+(cp->c_index<<8), u.u_uid); sleep((caddr_t)cp,TTIPRI); if (cp->c_flags&NMBUF) prele(mpxip); if (cp->c_flags & WCLOSE) { chdrain(cp); chfree(cp); u.u_error = ENXIO; return; } cp->c_fy = fp; cp->c_pgrp = u.u_procp->p_pgrp; } char mxnmbuf[NMSIZE]; int nmsize; mpxname(cp) register struct chan *cp; { register char *np; register c; np = mxnmbuf; u.u_dirp = (caddr_t)u.u_arg[0]; while (np < &mxnmbuf[NMSIZE]) { c = uchar(); if (c <= 0) break; *np++ = c; } *np++ = '\0'; nmsize = np - mxnmbuf; cp->c_flags |= NMBUF; } mxclose(dev, flag, fp) dev_t dev; register struct file *fp; { register struct group *gp; register struct inode *ip; register struct chan *cp = { fp->f_un.f_chan }; int i, fmp; fmp = flag&FMP; if ((gp=getmpx(dev)) == NULL) return; ip = gp->g_inode; if (ip==NULL || (ip->i_mode&IFMT)!=IFMPC) { return; } /* * close a channel */ if (cp!=NULL && fmp && fmp!=FMP) { for(fp=file; fp< fileNFILE; fp++) if(fp->f_count && fp->f_flag&FMP && fp->f_un.f_chan==cp){ return; } chdrain(cp); if ((cp->c_flags&WCLOSE)==0) { scontrol(cp, M_CLOSE, 0); cp->c_flags |= WCLOSE; } else { chfree(cp); } goto out; } for(fp=file; fp < fileNFILE; fp++) { if (fp->f_count && (fp->f_flag&FMP)==FMP && fp->f_inode==ip) return; } if (ip == mpxip) { mpxip = NULL; prele(ip); } for(i=0;ig_chans[i]); out: if (ip->i_count == 1) { groups[minor(dev)] = NULL; plock(ip); zero((caddr_t)gp, sizeof (struct group)); ip->i_mode = IFREG + 0666; ip->i_un.i_rdev = 0; ip->i_flag |= IUPD|ICHG; iput(ip); } } zero(s, cc) register char *s; register cc; { while (cc--) *s++ = 0; } char m_eot[] ={ M_EOT, 0, 0, 0}; /* * Mxread + mxwrite are entered from cdevsw * for all read/write calls. Operations on * an mpx file are handled here. * Calls are made through linesw to handle actual * data movement. */ mxread(dev, uio) dev_t dev; struct uio *uio; { register struct group *gp; register struct chan *cp; register esc; struct rh h; caddr_t base; unsigned count; int s, xfr, more, fmp; if ((gp=getmpx(dev))==NULL || (FP=getf(u.u_arg[0]))==NULL) { u.u_error = ENXIO; return; } fmp = FP->f_flag & FMP; if (fmp != FMP) { if (uio->uio_resid == 0) return; msread(fmp, FP->f_un.f_chan); return; } if ((int)uio->uio_iov->iov_base & 1) { u.u_error = ENXIO; return; } s = spl6(); if (uio->uio_resid == 0) { if (gp->g_datq == 0) u.u_error = ENXIO; splx(s); return; } while (gp->g_datq == 0) { sleep((caddr_t)&gp->g_datq, TTIPRI); } splx(s); while (gp->g_datq && uio->uio_resid >= CNTLSIZ + 2) { esc = 0; cp = nextcp(gp); if (cp==NULL) { continue; } h.index = cpx(cp); if (count = cp->c_ctlx.c_cc) { count += CNTLSIZ; if (cp->c_flags&NMBUF) count += nmsize; if (count > uio->uio_resid) { (void) sdata(cp); return; } esc++; } base = uio->uio_iov->iov_base; count = uio->uio_iov->iov_len; uio->uio_iov->iov_base += sizeof h; uio->uio_iov->iov_len -= sizeof h; uio->uio_resid -= sizeof h; xfr = uio->uio_resid; if (esc) { more = mcread(cp); } else { more = (*linesw[cp->c_line].l_read)(cp->c_ttyp); } if (more > 0) (void) sdata(cp); if (more < 0) scontrol(cp, M_CLOSE, 0); (void) _spl0(); if (xfr == uio->uio_resid) { esc++; IOMOVE((caddr_t)m_eot, sizeof m_eot, B_READ); } xfr -= uio->uio_resid; if (esc) { h.count = 0; h.ccount = xfr; } else { h.count = xfr; h.ccount = 0; mxrstrt(cp, &cp->cx.datq, BLOCK|ALT); } if (uio->uio_resid && (xfr&1)) { uio->uio_iov->iov_base++; uio->uio_iov->iov_len--; uio->uio_resid--; } (void) copyout((caddr_t)&h, base, sizeof h); } } mxwrite(dev, uio) dev_t dev; struct uio *uio; { register struct chan *cp; struct wh h; struct group *gp; int ucount, esc, fmp, burpcount; caddr_t ubase, hbase; if ((gp=getmpx(dev))==NULL || (FP=getf(u.u_arg[0]))==NULL) { return; } fmp = FP->f_flag & FMP; if (fmp != FMP) { mswrite(fmp, FP->f_un.f_chan); return; } burpcount = 0; while (uio->uio_resid >= sizeof h) { hbase = uio->uio_iov->iov_base; IOMOVE((caddr_t)&h, sizeof h, B_WRITE); if (u.u_error) return; esc = 0; if (h.count==0) { esc++; h.count = h.ccount; } cp = xcp(gp, h.index); if (cp==NULL || cp->c_flags&ISGRP) { u.u_error = ENXIO; return; } ucount = uio->uio_resid; ubase = uio->uio_iov->iov_base; uio->uio_resid = uio->uio_iov->iov_len = h.count; uio->uio_iov->iov_base = h.data; if (esc==0) { struct tty *tp; caddr_t waddr; int line; if (cp->c_flags&PORT) { line = cp->c_line; tp = cp->c_ttyp; } else { line = cp->c_oline; tp = cp->c_ottyp; } loop: waddr = (caddr_t)(*linesw[line].l_write)(tp); if (uio->uio_resid) { if (gp->g_state&ENAMSG) { burpcount++; cp->c_flags |= BLKMSG; /* scontrol(cp, M_BLK, uio->uio_resid); */ h.ccount = -1; h.count = uio->uio_resid; h.data = uio->uio_iov->iov_base; (void) copyout((caddr_t)&h, hbase, sizeof h); } else { if(waddr == 0) { u.u_error = ENXIO; return; } sleep(waddr, TTOPRI); goto loop; } } } else { mxwcontrol(cp); } uio->uio_resid = uio->uio_iov->iov_len = ucount; uio->uio_iov->iov_base = ubase; } uio->uio_resid = uio->uio_iov->iov_len = burpcount; } /* * Mcread and mcwrite move data on an mpx file. * Transfer addr and length is controlled by mxread/mxwrite. * Kernel-to-Kernel and other special transfers are not * yet in. */ mcread(cp, uio) register struct chan *cp; struct uio *uio; { register struct clist *q; register char *np; q = (cp->c_ctlx.c_cc) ? &cp->c_ctlx : &cp->cx.datq; (void) mxmove(q, B_READ); if (cp->c_flags&NMBUF && q == &cp->c_ctlx) { np = mxnmbuf; while (nmsize--) (void) passc(*np++); cp->c_flags &= ~NMBUF; prele(mpxip); } if (cp->c_flags&PORT) return(cp->c_ctlx.c_cc + cp->c_ttyp->t_rawq.c_cc); else return(cp->c_ctlx.c_cc + cp->cx.datq.c_cc); } caddr_t mcwrite(cp, uio) register struct chan *cp; struct uio *uio; { register struct clist *q; int s; q = &cp->cy.datq; while (uio->uio_resid) { s = spl6(); if (q->c_cc > HIQ || (cp->c_flags&EOTMARK)) { cp->c_flags |= SIGBLK; splx(s); break; } splx(s); (void) mxmove(q, B_WRITE); } wakeup((caddr_t)q); return((caddr_t)q); } /* * Msread and mswrite move bytes * between user and non-multiplexed channel. */ msread(fmp, cp, uio) register struct chan *cp; struct uio *uio; { register struct clist *q; int s; q = (fmp&FMPX) ? &cp->cx.datq : &cp->cy.datq; s = spl6(); while (q->c_cc == 0) { if (cp->c_flags&WCLOSE) { u.u_error = ENXIO; goto out; } if (cp->c_flags & EOTMARK) { cp->c_flags &= ~EOTMARK; if(msgenab(cp)) scontrol(cp, M_UBLK, 0); else { wakeup((caddr_t)cp); wakeup((caddr_t)q); } goto out; } sleep((caddr_t)q,TTIPRI); } if (cp->c_flags&WCLOSE) { u.u_error = ENXIO; goto out; } splx(s); while (mxmove(q, B_READ) > 0) ; mxrstrt(cp, q, SIGBLK); return; out: splx(s); } mswrite(fmp, cp, uio) register struct chan *cp; struct uio *uio; { register struct clist *q; register int cc; q = (fmp&FMPX) ? &cp->cy.datq : &cp->cx.datq; while (uio->uio_resid) { (void) _spl6(); if (cp->c_flags&WCLOSE) { gsignal(cp->c_pgrp, SIGPIPE); (void) _spl0(); return; } if (q->c_cc>= HIQ || cp->c_flags&FBLOCK) { if (cp->c_flags&WCLOSE) { gsignal(cp->c_pgrp, SIGPIPE); (void) _spl0(); return; } (void) sdata(cp); cp->c_flags |= BLOCK; sleep((caddr_t)q+1,TTOPRI); (void) _spl0(); continue; } (void) _spl0(); cc = mxmove(q, B_WRITE); if (cc < 0) break; } if (fmp&FMPX) { if (cp->c_flags&YGRP) (void) sdata(cp); else wakeup((caddr_t)q); } else { if (cp->c_flags&XGRP) (void) sdata(cp); else wakeup((caddr_t)q); } } /* * move chars between clist and user space. */ mxmove(q, dir, uio) register struct clist *q; register dir; struct uio *uio; { register cc; char cbuf[HIQ]; cc = MIN(uio->uio_resid, sizeof cbuf); if (dir == B_READ) cc = q_to_b(q, cbuf, cc); if (cc <= 0) return(cc); IOMOVE((caddr_t)cbuf, (unsigned)cc, dir); if (dir == B_WRITE) cc = b_to_q(cbuf, cc, q); return(cc); } mxrstrt(cp, q, b) register struct chan *cp; register struct clist *q; register b; { int s; s = spl6(); if (cp->c_flags&b && q->c_ccc_flags &= ~b; if (b&ALT) wakeup((caddr_t)q+1); else mcstart(cp, (caddr_t)q); } if (cp->c_flags&WFLUSH) wakeup((caddr_t)q+2); splx(s); } /* * called from driver start or xint routines * to wakeup output sleeper. */ mcstart(cp, q) register struct chan *cp; register caddr_t q; { if (cp->c_flags&(BLKMSG)) { cp->c_flags &= ~BLKMSG; scontrol(cp, M_UBLK, 0); } else wakeup((caddr_t)q); } mxwcontrol(cp) register struct chan *cp; { short cmd; struct sgttyb vec; int s; IOMOVE((caddr_t)&cmd, sizeof cmd, B_WRITE); if (u.u_error) return; switch(cmd) { /* * not ready to queue this up yet. */ case M_EOT: s = spl6(); while (cp->c_flags & EOTMARK) if(msgenab(cp)){ scontrol(cp, M_BLK, 0); goto out; } else sleep((caddr_t)cp, TTOPRI); cp->c_flags |= EOTMARK; out: wakeup((caddr_t)&cp->cy.datq); splx(s); break; case M_IOCTL: break; case M_IOANS: if (cp->c_flags&SIOCTL) { IOMOVE((caddr_t)&vec, sizeof vec, B_WRITE); (void) b_to_q((caddr_t)&vec, sizeof vec, &cp->c_ctly); cp->c_flags &= ~SIOCTL; wakeup((caddr_t)cp); } break; case M_BLK: cp->c_flags |= FBLOCK; break; case M_UBLK: cp->c_flags &= ~FBLOCK; chwake(cp); break; default: u.u_error = ENXIO; } } /*ARGSUSED*/ mxioctl(dev, cmd, addr, flag) caddr_t addr; { struct group *gp; int fmp; struct file *fp; struct { short c_ctl; short c_cmd; struct sgttyb c_vec; } ctlbuf; if ((gp=getmpx(dev))==NULL || (fp=getf(u.u_arg[0]))==NULL) { return; } fmp = fp->f_flag & FMP; if (fmp == FMP) { switch(cmd) { case MXLSTN: if (mpxip == NULL) { mpxip = gp->g_inode; } else { u.u_error = ENXIO; return; } break; case MXNBLK: gp->g_state |= ENAMSG; break; default: u.u_error = ENXIO; return; } } else { ctlbuf.c_ctl = M_IOCTL; ctlbuf.c_cmd = cmd; (void) copyin(addr, (caddr_t)&ctlbuf.c_vec, sizeof (struct sgttyb)); sioctl(fp->f_un.f_chan, (char *)&ctlbuf, sizeof ctlbuf); (void) copyout((caddr_t)&ctlbuf, addr, sizeof (struct sgttyb)); } } chdrain(cp) register struct chan *cp; { register struct tty *tp; int wflag; chwake(cp); wflag = (cp->c_flags&WCLOSE)==0; tp = cp->c_ttyp; if (tp == NULL) /* prob not required */ return; if (cp->c_flags&PORT && tp->t_chan == cp) { cp->c_ttyp = NULL; tp->t_chan = NULL; return; } if (wflag) wflush(cp,&cp->cx.datq); else flush(&cp->cx.datq); if (!(cp->c_flags&YGRP)) { flush(&cp->cy.datq); } } chwake(cp) register struct chan *cp; { register char *p; wakeup((caddr_t)cp); flush(&cp->c_ctlx); p = (char *)&cp->cx.datq; wakeup((caddr_t)p); wakeup((caddr_t)++p); wakeup((caddr_t)++p); p = (char *)&cp->cy.datq; wakeup((caddr_t)p); wakeup((caddr_t)++p); wakeup((caddr_t)++p); } chfree(cp) register struct chan *cp; { register struct group *gp; register i; gp = cp->c_group; if (gp==NULL) return; i = cp->c_index; if (cp == gp->g_chans[i]) { gp->g_chans[i] = NULL; } cp->c_group = NULL; wakeup((caddr_t)gp); } flush(q) register struct clist *q; { while(q->c_cc) (void) getc(q); } wflush(cp,q) register struct chan *cp; register struct clist *q; { register s; s = spl6(); if(q->c_cc && (cp->c_flags&WCLOSE) == 0) { cp->c_flags |= WFLUSH; (void) sdata(cp); sleep((caddr_t)q+2, TTOPRI); } flush(q); cp->c_flags &= ~WFLUSH; splx(s); } scontrol(cp,event,value) register struct chan *cp; short event,value; { register struct clist *q; int s; q = &cp->c_ctlx; s = spl6(); if (sdata(cp) == NULL) return; (void) putw(event,q); (void) putw(value,q); splx(s); } sioctl(cp, vec, cc) register struct chan *cp; char *vec; { register s; register struct clist *q; s = spl6(); q = &cp->cx.datq; while (q->c_cc) { cp->c_flags |= BLOCK; if (sdata(cp)==NULL) { u.u_error = ENXIO; return; } sleep((caddr_t)q+1, TTOPRI); } (void) b_to_q(vec, cc, &cp->c_ctlx); cp->c_flags |= SIOCTL; while (cp->c_flags&SIOCTL) { if (cp->c_ctlx.c_cc) if (sdata(cp)==NULL) { u.u_error = ENXIO; return; } sleep((caddr_t)cp, TTOPRI); } (void) q_to_b(&cp->c_ctly, vec, cp->c_ctly.c_cc); splx(s); } sdata(cp) struct chan *cp; { register struct group *gp = (struct group *)cp; register struct group *ngp; register int s; ngp = gp->g_group; if (ngp==NULL || (ngp->g_state&ISGRP)==0) return(NULL); s = spl6(); do { ngp->g_datq |= cmask[gp->g_index]; wakeup((caddr_t)&ngp->g_datq); gp = ngp; } while(ngp=ngp->g_group); splx(s); return((int)gp); } struct chan * xcp(gp, x) register struct group *gp; register short x; { register int i; while (gp->g_group) gp=gp->g_group; for (i=0;i= NINDEX) break; if (gp==NULL || (gp->g_state&ISGRP)==0) return((struct chan *)NULL); gp = (struct group *)gp->g_chans[x&017]; x >>= 4; } return((struct chan *)gp); } cpx(cp) register struct chan *cp; { register x; register struct group *gp; x = (-1<<4) + cp->c_index; gp = cp->c_group; while (gp->g_group) { x <<= 4; x |= gp->g_index; gp = gp->g_group; } return(x); } struct chan * nextcp(gp) register struct group *gp; { register struct group *lgp, *ngp; do { while ((gp->g_datq & cmask[gp->g_rot]) == 0) { gp->g_rot = (gp->g_rot+1)%NINDEX; } lgp = gp; gp = (struct group *)gp->g_chans[gp->g_rot]; } while (gp!=NULL && gp->g_state&ISGRP); lgp->g_datq &= ~cmask[lgp->g_rot]; lgp->g_rot = (lgp->g_rot+1)%NINDEX; while (ngp=lgp->g_group) { ngp->g_datq &= ~cmask[lgp->g_index]; if (ngp->g_datq) break; lgp = ngp; } return((struct chan *)gp); } msgenab(cp) register struct chan *cp; { register struct group *gp; for(gp=cp->c_group;gp;gp=gp->g_group) if(gp->g_state & ENAMSG)return(1); return(0); } ); break; case 5: printf("emt"); break; case 6: printf("sys/trap"); break; defaulsys/OTHERS/dv/ 755 0 12 0 5325716401 6201 sys/OTHERS/dv/dv.c 444 3 12 16136 5316441722 7074 # #define DK_N 2 /* * DV disk driver * * Adapted for Version 7 UNIX 8/21/79 - Bob Kridle */ #include #include #include #include #include #ifdef UCB_SCCSID static char sccs_id[] = "@(#)dv.c 3.1"; #endif struct { int dvcsr; int dvdbr; int dvmar; int dvwcr; int dvcbr; int dvssr; union { int i; char c[2]; } dvair; int dvusr; }; #define DVADDR ((struct device *) 0164000 ) #define NDV 4 struct dv_sizes { daddr_t nblocks; int cyloff; } dv_sizes[] { 10080, 0, /* cyl 0 thru 41 */ 10080, 42, /* cyl 42 thru 83 */ 77280, 84, /* cyl 84 thru 405 */ 97440, 0, /* cyl 0 thru 405 */ 54000, 180, /* cyl 180 thru 405 */ 65520, 0, /* cyl 0 thru 272 */ 31680, 273, /* cyl 273 thru 405 */ 2048, 123, /* cyl 123 thru 132 */ }; struct { int hd1; int hd2; int cksum; unsigned int chadr; } dvhdr; int dv_unit -1, dv_cyl, dv_head, dv_sctr, dv_count; union { long l; int in[2]; } dv_addr; int dv_debug 0; int dv_wcheck, dv_sw 0; int wcwcnt[4]; struct buf dvtab; char dvsecmap[] { 0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11, }; #define HTBCOM 000000 #define CTBCOM 020000 #define CNBCOM 030000 #define INCHD 01 #define RECAL 02 #define RESET 020 #define SEEK 040 #define CLRDA 0100 #define CHRCOM 070000 #define CHWCOM 0130000 #define CHCD 071000 #define LDSCOM 0140000 #define CTLRST 0170000 #define CHRDATA 060000 #define CHWHEAD 0110000 #define WENABL 0100000 #define DRVRDY 04000 #define ATTN 0400 #define DONE 0200 #define IENABLE 0100 #define GO 01 /* * Use av_back to save sector, * b_resid for cylinder+track. */ #define dvsec av_back #define cylhd b_resid dvstrategy(bp) register struct buf *bp; { register unsigned trkno; register struct dv_sizes *sptr; if(bp->b_flags&B_PHYS) mapalloc(bp); sptr = &dv_sizes[minor(bp->b_dev)&07]; if ((minor(bp->b_dev)&077) >= (NDV<<3) || bp->b_blkno >= sptr->nblocks) { bp->b_flags |= B_ERROR; iodone(bp); return; } bp->av_forw = NULL; trkno = bp->b_blkno/12; bp->cylhd = ((sptr->cyloff+trkno/20)<<5)|(trkno%20); bp->dvsec = bp->b_blkno%12; spl5(); disksort(&dvtab,bp); if (dvtab.b_active==0) dvstart(); spl0(); } dvstart() { register struct buf *bp; if ((bp = dvtab.b_actf) == 0) { /* dv_busy = 0; */ return; } dv_cyl = bp->cylhd>>5; dv_head = bp->cylhd&037; dv_sctr = bp->dvsec; dv_count = -bp->b_bcount; dv_addr.in[0] = bp->b_xmem & 03; dv_addr.in[1] = bp->b_un.b_addr; dvexec(); } dvexec() { register struct buf *bp; register sctr, minord; int i, cnt; bp = dvtab.b_actf; sctr = dv_sctr; minord = minor(bp->b_dev); if (minord&64) sctr = dvsecmap[sctr]; dvtab.b_active++; if (dv_unit!=((minord&077)>>3)) { /* select unit */ dv_unit = (minord&077)>>3; cnt = 0; for (i = 0; i < 2; i++) while((DVADDR->dvssr&DRVRDY) && --cnt) ; DVADDR->dvcbr = LDSCOM | dv_unit; } if(dvrdy()) return; DVADDR->dvcbr = CNBCOM | RESET | CLRDA; /* reset and clear */ if (dv_cyl != (~(DVADDR->dvssr|0177000))) { /* seek */ if(dvrdy()) return; DVADDR->dvcbr = CTBCOM | dv_cyl; if(dvrdy()) return; DVADDR->dvcbr = CNBCOM | SEEK | RESET; DVADDR->dvair.i = 1<dvcsr = DONE | IENABLE; return; } if(dvrdy()) return; DVADDR->dvcbr = HTBCOM | dv_head; /* select head */ if(dv_count <= -512) DVADDR->dvwcr = -512; else DVADDR->dvwcr = dv_count; dvhdr.hd1 = (dv_head<<8)+dv_cyl; /* set up header */ dvhdr.hd2 = 0170000|sctr; dvhdr.cksum = -dvhdr.hd1-dvhdr.hd2; dvhdr.chadr = dv_addr.in[1]; if(dvrdy()) return; DVADDR->dvmar = &dvhdr; if(dv_debug) printf("ST,h1=%o,h2=%o,h4=%o,mar=%o,wc=%o,x=%o,\n", dvhdr.hd1, dvhdr.hd2, dvhdr.chadr, DVADDR->dvmar, DVADDR->dvwcr, dv_addr.in[0] ); if (minord & 128) { if (bp->b_flags & B_READ) { dv_addr.in[0] = 0; DVADDR->dvmar = dv_addr.in[1]; DVADDR->dvcbr = CHRDATA | (sctr<<1); } else { DVADDR->dvcbr = CHWHEAD | (sctr<<1); DVADDR->dvair.i |= WENABL; } } else { if (bp->b_flags & B_READ) DVADDR->dvcbr = CHRCOM | (sctr<<1); else if (dv_wcheck) DVADDR->dvcbr = CHCD | (sctr<<1); else DVADDR->dvcbr = CHWCOM | (sctr<<1); } DVADDR->dvcsr = IENABLE | GO | (dv_addr.in[0]<<4); } int dv_tmp; int dv_errct; dvintr() { register struct buf *bp; register int csr,i; if (dvtab.b_active == 0) return; if(dv_debug) printf("IN,mar=%o,wc=%o,cbr=%o,\n", DVADDR->dvmar, DVADDR->dvwcr, DVADDR->dvcbr ); /***** I/O monitoring stuff *****/ /* Removed for v7 Upgrade * dk_busy =& ~(1<dvcsr; DVADDR->dvcsr = DONE; if (csr&ATTN) { /* seek complete */ dv_wcheck = 0; DVADDR->dvair.c[0] = 0; if(DVADDR->dvssr>0) { /* error */ printf("Seek error\n"); deverror(bp, DVADDR->dvssr, csr); DVADDR->dvcbr = CNBCOM | RECAL | RESET; dv_unit = -1; if(dvrdy()) return; DVADDR->dvcbr = CTLRST; if (++dvtab.b_errcnt<=10) { dvexec(); return; } dvherr(0); return; } else { dvexec(); return; } } else { /* r/w complete */ if (dv_count <= -512) i = -512; else i = dv_count ; if ((csr < 0 || dv_addr.in[1]-i != DVADDR->dvmar) && (minor(bp->b_dev)&128)==0) { if (dv_addr.in[1]-i != DVADDR->dvmar) { printf("hdr/xfer err "); printf("%o %o %o\n", dv_addr.in[1], DVADDR->dvmar, csr); deverror(bp, DVADDR->dvssr, csr); dv_wcheck = 0; } dv_tmp = csr; dv_errct++; dv_unit = -1; if (dv_wcheck) { printf("diva bad write\n"); wcwcnt[(minor(bp->b_dev)&030) >> 3]++; deverror(bp, DVADDR->dvssr, csr); } dv_wcheck = 0; if((dvtab.b_errcnt&03)==03) { deverror(bp, DVADDR->dvssr, csr); DVADDR->dvcbr = CNBCOM | RECAL | RESET; if(dvrdy()) return; } DVADDR->dvcbr = CTLRST; if(++dvtab.b_errcnt<=12) { dvexec(); return; } dvherr(0); return; } else { if (dv_sw && (bp->b_flags&B_READ)==B_WRITE && dv_wcheck==0 && dv_count==-512) { dv_wcheck = 1; dvexec(); return; } dv_wcheck = 0; if ((dv_count += 512)<0) { /* more to do */ dv_addr.l += 512; if (++dv_sctr>=12) { dv_sctr = 0; if (++dv_head>=20) { dv_head = 0; dv_cyl++; } } dvexec(); return; } } } if (csr < 0 && (minor(bp->b_dev)&128)) { DVADDR->dvcbr = CTLRST; dv_unit = -1; dvrdy(); if (DVADDR->dvcsr < 0) { DVADDR->dvcbr = CNBCOM | RECAL | RESET; dvrdy(); } } dv_wcheck = 0; dvtab.b_errcnt = 0; dvtab.b_actf = bp->av_forw; /* This is not right but a kludge for the moment */ bp->b_resid = 0; iodone(bp); dvstart(); } dvrdy() { register int cnt, i; if ((DVADDR->dvssr & DRVRDY) == 0) return(0); cnt = i = 0; /* * waste a bit of time, max .7(approx) sec on a 70 */ for (; i < 2; i++) while(--cnt && (DVADDR->dvssr&DRVRDY)); if (DVADDR->dvssr & DRVRDY) { printf("diva not ready\n"); dvherr(1); return(1); } return(0); } dvherr(n) { register struct buf *bp; bp = dvtab.b_actf; printf("Hard error on diva\n"); deverror(bp, DVADDR->dvssr, DVADDR->dvcsr); bp->b_flags |= B_ERROR; dvtab.b_errcnt = 0; dvtab.b_active = 0; dvtab.b_actf = bp->av_forw; iodone(bp); if(n==0) dvstart(); } p->c_group; if (gp==NULL) return; i = cp->c_index; if (cp == gp->g_chans[i]) { gp->g_chans[i] = NULL; } cp->c_group = NULL; wakeup((caddr_t)gp); } flush(q) register struct clist *q; { while(q->c_cc) (void) getc(q); } wflush(cp,q) register struct chan *cp; register struct clist *q; { register s; s = spl6(); if(q->c_cc && (cp->c_flags&WCLOSE) == 0) { cp->c_flags |= WFLUSH; (void) sdata(cp); sys/OTHERS/fast_timer/ 755 0 12 0 3771403654 7733 sys/OTHERS/fast_timer/ft.c 444 3 12 7110 3552650456 10576 #include "ft.h" #if NFT > 0 /* * Fast Timer -- a pseudo-device that behaves like an interval timer. * * Note: because of exclusive open it can also be used as a lock file. */ #include "param.h" #include #include #include #include #include #include /* * Per-minor-device state table * * Invariants: * - device is open iff ftt_procp != 0 * - timeout in progress iff ftt_state != AVAILABLE */ struct fttab { struct proc *ftt_procp; /* proctab entry and pid of */ short ftt_pid; /* controlling process. */ short ftt_state; /* AVAILABLE, CANCELLED, sig # */ } fttab[NFT]; #define AVAILABLE (0) #define CANCELLED (-1) #define MAXTIMEREQ (60 * hz) /* 1 minute */ /* * Open * * Exclusive use only */ /*ARGSUSED*/ ftopen(d, flag) { register u_short dminor; register struct fttab *ftp; dminor = minor(d); if (dminor >= NFT) { u.u_error = ENXIO; return; } ftp = &fttab[dminor]; if ((ftp->ftt_procp != (struct proc *) NULL) || (ftp->ftt_state != AVAILABLE)) { u.u_error = EBUSY; return; } ftp->ftt_procp = u.u_procp; ftp->ftt_pid = u.u_procp->p_pid; } /* * Close */ ftclose(d) { register u_short dminor; register struct fttab *ftp; dminor = minor(d); #ifdef PARANOIA if (dminor >= NFT) { printf("ERR: ftclose\n"); u.u_error = ENXIO; return; } #endif ftp = &fttab[dminor]; ftp->ftt_procp = (struct proc *) NULL; ftp->ftt_pid = 0; } /* * Ioctl * * All real work is done here using * * FTIOCSET request a software interrupt after specified * number of clock ticks * FTIOCCANCEL cancel an outstanding request */ /*ARGSUSED*/ ftioctl(dev, cmd, addr, flag) caddr_t addr; dev_t dev; { void fttimeout(); register u_short dminor; register struct fttab *ftp; dminor = minor(dev); if (dminor >= NFT) { printf("ERR: ftioctl!\n"); u.u_error = EINVAL; } ftp = &fttab[dminor]; /* * Make sure invoking process owns the device. * This can only fail if call is from a child * forked off after opening the ft device. */ if ((u.u_procp != ftp->ftt_procp) || (u.u_procp->p_pid != ftp->ftt_pid)) { u.u_error = EBUSY; return; } /* * Interpret command */ switch(cmd) { case FTIOCSET: { struct { u_short timereq; short sigreq; } request; /* * Get request, make sure it's reasonable */ if (copyin(addr, (caddr_t) &request, sizeof request)) { u.u_error = EFAULT; return; } if ((request.sigreq <= 0) || (request.sigreq > NSIG) || (request.timereq > MAXTIMEREQ)) { u.u_error = EINVAL; return; } /* * Schedule the interrupt */ if (ftp->ftt_state != AVAILABLE) { u.u_error = EBUSY; return; } ftp->ftt_state = request.sigreq; timeout(fttimeout, (caddr_t) ftp, request.timereq); } break; case FTIOCCANCEL: (void) spl5(); if (ftp->ftt_state != AVAILABLE) ftp->ftt_state = CANCELLED; (void) spl0(); break; default: u.u_error = ENOTTY; break; } } /* * Fttimeout * * Called by system timeout * * Verify that requesting process is still around * Verify that request hasn't been cancelled * Send the signal */ void fttimeout(ftp) register struct fttab *ftp; { register struct proc *pp; register prevstate; prevstate = ftp->ftt_state; ftp->ftt_state = AVAILABLE; if ((prevstate == CANCELLED) || ((pp = ftp->ftt_procp) == ((struct proc *) NULL)) || (pp->p_pid != ftp->ftt_pid)) return; #ifdef PARANOIA if ((prevstate < 1) || (prevstate >= NSIG)) { printf("ERR: fttimeout %d\n",prevstate); return; } #endif psignal(pp, prevstate); } #endif SET; DVADDR->dvair.i = 1<dvcsr = DONE | IENABLE; return; } if(dvrdy()) return; DVADDR->dvcbr = HTBCOM | dv_head; /* select head */ if(dv_count <= -512) DVADDR->dvwcr = -512; else DVADDR->dvwcr = dv_count; dvhdr.hd1 = (dv_head<<8)+dv_cyl; /* set up header */ dvhdr.hd2 = 0170000|sctr; dvhdr.cksum = -dvhdr.hd1-dvhdr.hd2; dvhdr.chadr = dv_addr.in[1]; if(dvrdy()) return; DVADDR->dvmar = &dvhdr; if(dv_desys/OTHERS/dmc11/ 755 0 12 0 5676504577 6517 sys/OTHERS/dmc11/dmc.c 444 3 12 34616 5666036433 7534 /* * DMC-11 device driver * * NOTE: * This driver uses the old, in-address-space abuffers. * Since those buffers no longer exist, this driver would * need to be converted to use its own, local buffers * before it could be used. */ /* * SCCS id @(#)dmc.c 2.2 (2.11BSD GTE) 11/26/94 */ #include "param.h" #include #include #include #include #define CLOSE /* include ioctl(NETCLOSE,,) */ #define DMCPRI PZERO-1 #define NDMC 1 #define BUFSIZ 256 /* size of buffers */ #define NRBUFS (int)(BSIZE/BUFSIZ-1) /* # of extra receive buffer headers */ #define NTBUFS 1 /* number of transmit buffer headers */ /* * note: dmc only allows 7 receive, 7 transmit buffers to be queued, * thus NRBUFS and NTBUFS must be <= 7. * On an 11/70 the Unibus map must be allocated; if mapalloc() is * used, only one buffer can have the map. NTBUFS might as * well be 1 so the next (only) write outstanding is the one * with the map allocated. */ #define LOOPCNT 10 /* max time waiting for ~RDYI */ #define MAXERRS 7 /* number of DCK or TIMEOUTs before fail */ struct device { char inctrl; char mstrctrl; char outctrl; char bsel3; unsigned bufad; unsigned port1; }; struct device *dmcaddr[] = { (struct device *)0160200, (struct device *)0160210 }; struct buf dmctbufs[NDMC][NTBUFS]; struct buf dmcrbufs[NDMC][NRBUFS]; struct dmcinfo { struct buf *bp; /* system receive buffer to relse */ caddr_t addr; /* saved addr for dmcitrans */ unsigned cnt; /* saved xmem + count for dmcitrans */ } dmcinfo[NDMC]; struct buf dmcutab[NDMC]; #define MCLR 0100 /* mstrctrl -- master clear */ #define RDYI 0200 /* inctrl -- port avail */ #define RQI 0040 /* inctrl -- request input transfer */ #define IEI 0100 /* inctrl -- interrupt enable, input */ #define RDYO 0200 /* outctrl -- output transfer ready */ #define IEO 0100 /* outctrl -- output interrupt enable */ #define TRBIT 0004 /* inctrl, outctrl -- mask for t/r flag */ #define TFLAG 0000 /* inctrl, outctrl -- flag indicates transmission */ #define RFLAG 0004 /* inctrl, outctrl -- flag indicates reception */ #define TTYPE 0003 /* inctrl, outctrl -- mask for transfer type */ #define BACC 0000 /* inctrl, outctrl -- buf addr, char count */ #define CTRL 0001 /* inctrl, outctrl -- control in/out */ #define INVAL 0002 /* inctrl -- invalid (to shut down gracefully) */ #define BASEI 0003 /* inctrl -- base in */ #define FDUP 00000 /* port1 (control in) -- full duplex operation */ #define HDUP 02000 /* port1 (control in) -- half duplex operation */ /* control out error states: */ #define FATAL 01630 /* fatal errors */ #define DCK 00001 /* data check */ #define TIMEOUT 00002 /* no response, 21 sec. */ #define ORUN 00004 /* overun error (waiting for recv buffer) */ #define MAINT 00010 /* maintenance mesg recd */ #define DLOST 00020 /* data lost (recv buffer too small) */ #define DISCON 00100 /* DSR transition */ #define RESTART 00200 /* DDCMP start received */ #define NXM 00400 /* non-existent memory */ #define PROCERR 01000 /* procedure error */ #define OPEN 001 #define CLOSING 002 /* closing gracefully */ #define STATE 003 #define ERROR 004 /* fatal line error */ #define TOLD 010 /* console message already printed */ #define R_WAITING 0100 /* read waiting */ #define W_WAITING 0200 /* write waiting */ #define TR_WAITING 0400 /* itrans waiting */ #define WAITING 0700 #define EXTSHFT 14 #ifndef hiint #define hiint(x) (int)(x>>16) #define loint(x) (int)(x&177777) #endif #define tbufq b_forw /* empty transmit buffer headers */ #define outbufq b_back /* filled transmit buffers */ #define rbufq av_forw /* empty receive buffers */ #define inbufq av_back /* filled receive buffers */ /* redeclarations for dmcutab: */ #define xcnt b_resid /* saved port1 (xmem+char cnt) */ #define state b_flags int dmcbase[NDMC][64]; dmcopen(dev) dev_t dev; { register int unit; register struct buf *dp, *bp, *hp; long base; if ((unit=minor(dev)) >= NDMC || unit < 0) { u.u_error = ENXIO; return; } dp = &dmcutab[unit]; if (dp->state & OPEN) return; dp->state = 0; dp->rbufq = bp = getiblk(); dmcinfo[unit].bp = bp; bp->b_dev = dev; dmcinit(unit); dp->tbufq = dmctbufs[unit]; for (hp = dp->tbufq; hp < &dmctbufs[unit][NTBUFS-1]; hp++) hp->tbufq = hp + 1; hp->tbufq = 0; dp->outbufq = 0; dp->state = OPEN; } dmcclose(dev) dev_t dev; { register int unit; register struct buf *dp; unit = minor(dev); dp = &dmcutab[unit]; dmcaddr[unit]->outctrl &= ~IEO; brelse(dmcinfo[unit].bp); dp->state = 0; } dmcread(dev, uio) dev_t dev; struct uio *uio; { register struct buf *dp; register struct buf *bp, *pbp; register int unit; unit=minor(dev); dp = &dmcutab[unit]; if ((!(dp->state & OPEN)) /* last read after NETCLOSE */ || (uio->uio_resid < bp->b_bcount)) { u.u_error = EINVAL; return; } for (;;) { (void) _spl5(); if ((bp = dp->inbufq) != 0) break; if (dp->state & ERROR) { u.u_error = EIO; dp->state &= ~(ERROR|TOLD); dmcinit(unit); (void) _spl0(); return; } dp->state |= R_WAITING; sleep((caddr_t)dp, DMCPRI); } (void) _spl0(); if (bp->b_bcount > 0) { uiomove(mapin(bp), bp->b_bcount, uio); mapout(bp); } dp->inbufq = bp->inbufq; for (pbp=dp; pbp->rbufq; pbp=pbp->rbufq) ; pbp->rbufq = bp; bp->rbufq = 0; dmcitrans(unit,BACC | RFLAG, bp->b_un.b_addr, bp->xcnt); } dmcwrite(dev, uio) dev_t dev; struct uio *uio; { register struct buf *bp, *dp, *pbp; register int unit; if (chkphys(BYTE)) return; unit = minor(dev); if (uio->uio_resid > BUFSIZ) { u.u_error = EINVAL; return; } dp = &dmcutab[unit]; for (;;) { (void) _spl5(); if (dp->state & ERROR) { u.u_error = EIO; /* * If it is not necessary to report all errors * on reads (presumably to one read process) * the error could be cleared here. However, * dmcinit should not be called until the outbufq * is empty, which is easiest to do by reading * until a read returns -1, at which point the error * is cleared. Otherwise, do: * dp->state &= ~(ERROR|TOLD); * dmcinit(unit); */ (void) _spl0(); return; } if (bp = dp->tbufq) break; dp->state |= W_WAITING; sleep((caddr_t)dp, DMCPRI); } (void) _spl0(); physbuf(bp,dev,B_WRITE); u.u_procp->p_flag |= SLOCK; mapalloc(bp); dp->tbufq = bp->tbufq; for (pbp=dp; pbp->outbufq; pbp=pbp->outbufq) ; pbp->outbufq = bp; bp->outbufq = 0; dmcitrans(unit, BACC|TFLAG, bp->b_un.b_addr, ((unsigned)bp->b_xmem<b_bcount); iowait(bp); uio->uio_resid = 0; bp->b_flags = 0; u.u_procp->p_flag &= ~SLOCK; bp->tbufq = dp->tbufq; dp->tbufq = bp; if (dp->state & W_WAITING) { dp->state &= ~W_WAITING; wakeup((caddr_t)dp); } } #ifdef CLOSE #define NETCLOSE (('n'<<8)|1) dmcioctl(dev,cmd,addr,flag) dev_t dev; caddr_t addr; { register unit; unit = minor(dev); if (cmd == NETCLOSE) { dmcutab[unit].state |= CLOSING | ERROR; dmcitrans(unit,INVAL,(caddr_t)0,0); } else u.u_error = ENOTTY; } #endif dmcoint(unit) { register struct device *dmc; register struct buf *bp, *dp, *pbp; int errflgs; dp = &dmcutab[unit]; dmc = dmcaddr[unit]; if ((dmc->outctrl & TTYPE) == BACC) { if ((dmc->outctrl & TRBIT) == RFLAG) { bp = dp->rbufq; #ifdef DIAG if (bp == 0) { printf("dmc rbufq missing\n"); goto error; } if (bp->b_un.b_addr != dmc->bufad) { printf("dmc receive out of order\n"); goto error; } #endif bp->b_bcount = dmc->port1; for (pbp=dp; pbp->inbufq; pbp=pbp->inbufq) ; pbp->inbufq = bp; bp->inbufq = 0; dp->rbufq = bp->rbufq; if (dp->state & R_WAITING) { dp->state &= ~R_WAITING; wakeup((caddr_t)dp); } } else { bp = dp->outbufq; #ifdef DIAG if (bp == 0) { printf("dmc outbufq missing\n"); goto error; } if (bp->b_un.b_addr != dmc->bufad) { printf("dmc transmit out of order\n"); goto error; } #endif dp->outbufq = bp->outbufq; iodone(bp); } dp->state &= ~(ERROR | TOLD); dp->b_errcnt = 0; } else { errflgs = dmc->port1; #ifdef CLOSE if ((errflgs & PROCERR) && (dp->state & CLOSING)){ /* shutting down gracefully */ dp->state &= ~(CLOSING|OPEN); dmc->outctrl &= ~IEO; goto error; } #endif if (((errflgs & (FATAL|TIMEOUT)) || ((errflgs&DCK) && ++dp->b_errcnt>MAXERRS)) && ((dp->state & TOLD)==0)) { printf("DMC/%d error=%o\n",unit,errflgs); goto error; } #ifdef DIAG else if (dp->state & TOLD == 0) { printf("dmc nonfatal error %o\n",errflgs); dp->state &= TOLD; } #endif } dmc->outctrl &= ~RDYO; return; error: dmc->outctrl &= ~RDYO; dp->state |= ERROR|TOLD; for (bp=dp->outbufq; bp; bp=bp->outbufq) { bp->b_flags = B_ERROR | B_DONE; wakeup((caddr_t)bp); } if (dp->state & WAITING) { dp->state &= ~WAITING; wakeup((caddr_t)dp); } } dmciint(unit) { register struct buf *dp; register struct device *dmc; register struct dmcinfo *infp; dp = &dmcutab[unit]; dmc = dmcaddr[unit]; infp = &dmcinfo[unit]; if (dp->b_active) { dmc->bufad = infp->addr; dmc->port1 = infp->cnt; dmc->inctrl &= ~RQI; dp->b_active = 0; if (dp->state & TR_WAITING) { dp->state &= ~TR_WAITING; wakeup((caddr_t)dp); } #ifdef DIAG } else { printf("bad DMC/%d input interrupt\n",unit); dp->state |= TOLD; #endif } } dmcinit(unit) { register struct buf *bp, *dp, *hp; long base; dp = &dmcutab[unit]; dmcaddr[unit]->mstrctrl |= MCLR; dmcitrans(unit,BASEI, (caddr_t)dmcbase[unit], 0); dmcitrans(unit,CTRL, (caddr_t)0, FDUP); dmcaddr[unit]->outctrl |= IEO; bp = dmcinfo[unit].bp; base = (long)bp->b_un.b_addr + (((long)bp->b_xmem)<<16); bp->xcnt = ((unsigned)hiint(base)<b_un.b_addr, bp->xcnt); for (hp = &dmcrbufs[unit][0]; hp <= &dmcrbufs[unit][NRBUFS-1]; hp++) { bp->rbufq = hp; base += BUFSIZ; hp->b_un.b_addr = (caddr_t)loint(base); hp->b_xmem = (char)hiint(base); hp->xcnt = ((unsigned)hiint(base)<b_un.b_addr, hp->xcnt); bp = hp; } bp->rbufq = 0; dp->b_errcnt = 0; dp->inbufq = 0; } dmcitrans(unit, ttype, addr, cnt) caddr_t addr; unsigned cnt; { register struct buf *dp; register struct device *dmc; register int i; register struct dmcinfo *infp; dp = &dmcutab[unit]; infp = &dmcinfo[unit]; for (;;) { if (dp->state & ERROR) return; (void) _spl5(); if (!dp->b_active) break; dp->state |= TR_WAITING; sleep((caddr_t)dp,DMCPRI); } (void) _spl0(); infp->addr = addr; infp->cnt = cnt; dp->b_active++; /* start transfer */ i = 0; dmc = dmcaddr[unit]; while (dmc->inctrl & RDYI) if (++i > LOOPCNT) { /* * This shouldn't happen; if it does, it * will cause a spurious initialization. */ #ifdef DIAG printf("dmc missed RDYI going off\n"); #endif dp->state |= ERROR; return; } dmc->inctrl |= RQI|ttype|IEI; } (gp==NULL || (gp->g_state&ISGRP)==0) return((struct chan *)NULL); gp = (struct group *)gp->g_chans[x&017]; sys/OTHERS/berknet/ 755 0 12 0 5676504577 7244 sys/OTHERS/berknet/bk.c 444 3 12 11111 4610712127 10060 #include "bk.h" #if NBK > 0 #include "param.h" #include "systm.h" #include "user.h" #include "tty.h" #include "proc.h" #include "inode.h" #include "file.h" #include "conf.h" #include "buf.h" /* * SCCS id @(#)bk.c 2.1 (Berkeley) 8/5/83 */ #ifdef UCB_NTTY /* * When running dz's using only SAE (silo alarm) on input * it is necessary to call dzrint() at clock interrupt time. * This is unsafe unless spl5()s in tty code are changed to * spl6()s to block clock interrupts. Note that the dh driver * currently in use works the same way as the dz, even though * we could try to more intelligently manage its silo. * Thus don't take this out if you have no dz's unless you * change clock.c and dhtimer(). */ #define spl5 spl6 /* * Line discipline for Berkeley network. * * This supplies single lines to a user level program * with a minimum of fuss. Lines are newline terminated. * A later version will implement full 8-bit paths by providing * an escape sequence to include a newline in a record. * * This discipline requires that tty device drivers call * the line specific l_ioctl routine from their ioctl routines, * assigning the result to cmd so that we can refuse most tty specific * ioctls which are unsafe because we have ambushed the * teletype input queues, overlaying them with other information. */ /* * Open as networked discipline. Called when discipline changed * with ioctl, this assigns a buffer to the line for input, and * changing the interpretation of the information in the tty structure. */ bkopen(tp) register struct tty *tp; { register struct buf *bp; if (u.u_error) return(u.u_error); /* paranoia */ /* * The suser check was added since once it gets set you can't turn * it off, even as root. Theoretically a setuid root program could * be run over the net which opened /dev/tty but this seems farfetched. */ if (tp->t_line == NETLDISC && !suser()) return(EBUSY); /* sometimes the network */ /* ... opens /dev/tty */ bp = geteblk(); flushtty(tp,FREAD|FWRITE); tp->t_bufp = bp; tp->t_cp = (char *)bp->b_un.b_addr; tp->t_inbuf = 0; tp->t_rec = 0; return(0); } /* * Break down... called when discipline changed or from device * close routine. */ bkclose(tp) register struct tty *tp; { register s; register struct buf *bp; s = spl5(); wakeup((caddr_t)&tp->t_rawq); if (tp->t_bufp) { brelse(tp->t_bufp); tp->t_bufp = 0; } else printf("bkclose: no buf\n"); tp->t_cp = 0; tp->t_inbuf = 0; tp->t_rec = 0; tp->t_line = DFLT_LDISC; /* paranoid: avoid races */ splx(s); } /* * Read from a network line. * Characters have been buffered in a system buffer and are * now dumped back to the user in one fell swoop, and with a * minimum of fuss. Note that no input is accepted when a record * is waiting. Our clearing tp->t_rec here allows further input * to accumulate. */ bkread(tp, uio) register struct tty *tp; struct uio *uio; { register int i; register s; if ((tp->t_state&CARR_ON)==0) return (-1); s = spl5(); while (tp->t_rec == 0 && tp->t_line == NETLDISC) sleep((caddr_t)&tp->t_rawq, TTIPRI); splx(s); if (tp->t_line != NETLDISC) return (-1); i = MIN(tp->t_inbuf, (int)uio->uio_resid); if (copyout(tp->t_bufp->b_un.b_addr, uio->uio_iov->iov_base, (unsigned)i)) { u.u_error = EFAULT; return (-1); } uio->uio_resid -= i; uio->uio_iov->iov_base += i; uio->uio_offset += i; tp->t_cp = (char *)tp->t_bufp->b_un.b_addr; tp->t_inbuf = 0; tp->t_rec = 0; return (0); } /* * Low level character input routine. * Stuff the character in the buffer, and wake up the top * half after setting t_rec if this completes the record * or if the buffer is (ick!) full. * * This is where the formatting should get done to allow * 8 character data paths through escapes. * * This routine should be expanded in-line in the receiver * interrupt routine of the dh-11 to make it run as fast as possible. */ bkinput(c, tp) register c; register struct tty *tp; { if (tp->t_rec) return; *tp->t_cp++ = c; if (++tp->t_inbuf == BSIZE || c == '\n') { tp->t_rec = 1; wakeup((caddr_t)&tp->t_rawq); } } /* * This routine is called whenever a ioctl is about to be performed * and gets a chance to reject the ioctl. We reject all teletype * oriented ioctl's except those which set the discipline, and * those which get parameters (gtty and get special characters). */ /*ARGSUSED*/ bkioctl(tp, cmd, addr) struct tty *tp; caddr_t addr; { if ((cmd>>8) != 't') return (cmd); switch (cmd) { case TIOCSETD: case TIOCGETD: case TIOCGETP: case TIOCGETC: return (cmd); } u.u_error = ENOTTY; return (0); } #endif UCB_NTTY #endif NBK > 0 printf("dmc transmit out of order\n"); goto error; } #endif dp->outbufq = bp->outbufq; iodone(bp); } dp->state &= ~(ERROR | TOLD); dp->b_errcnt = 0; } else { errflgs = dmc->port1; #ifdef CLOSE if ((errflgs & PROCERR) && (dp->state & CLOSING)){ sys/OTHERS/berknet/bkmac.h 444 3 12 1007 3011330776 10531 /* bk.h 2.5 6/6/80 */ #define BK_BUFSIZE 128 /* buffer size per line */ /* * Macro definition of bk.c/bkinput(). * This is used to replace a call to * (*linesw[tp->t_line].l_input)(c,tp); * with * * if (tp->t_line == NETLDISC) * BKINPUT(c, tp); * else * (*linesw[tp->t_line].l_input)(c,tp); */ #define BKINPUT(c, tp) { \ if ((tp)->t_rec == 0) { \ *(tp)->t_cp++ = c; \ if (++(tp)->t_inbuf == BK_BUFSIZE || (c) == '\n') { \ (tp)->t_rec = 1; \ wakeup((caddr_t)&(tp)->t_rawq); \ } \ } \ } se works the same way as the dz, even though * we could try to more ielligently manage its silo. * Thus don't take this out if you have no dz's unless you * change clock.c and dhtimer(). */ #define spl5 spl6 /* * Line discipline for Berkeley network. * * This supplies single lines to a user level program * with a minimum of fuss. Lines are newline terminated. * A later version will implement full 8-bit paths by providing * an escape sequence to include a newline in a record. * * Thsys/OTHERS/berknet/for_tty_conf.c 444 3 12 407 3771457263 12143 #include "bk.h" #if NBK > 0 int bkopen(),bkclose(),bkread(),bkinput(),bkioctl(); caddr_t ttwrite(); #endif #if NBK > 0 bkopen, bkclose, bkread, ttwrite, bkioctl, bkinput, nodev, nulldev, #else nodev, nodev, nodev, nodev, nodev, nodev, nodev, nodev, #endif sys/OTHERS/berknet/tty_bk.c 444 3 12 7652 5674213326 10767 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)tty_bk.c 1.2 (2.11BSD Berkeley) 11/27/94 */ #include "bk.h" #if NBK > 0 #include "param.h" #include "systm.h" #include "dir.h" #include "user.h" #include "ioctl.h" #include "tty.h" #include "proc.h" #include "inode.h" #include "file.h" #include "conf.h" #include "buf.h" #include "uio.h" /* * Line discipline for Berkeley network. * * This supplies single lines to a user level program * with a minimum of fuss. Lines are newline terminated. * * This discipline requires that tty device drivers call * the line specific l_ioctl routine from their ioctl routines, * assigning the result to cmd so that we can refuse most tty specific * ioctls which are unsafe because we have ambushed the * teletype input queues, overlaying them with other information. */ /* * Open as networked discipline. Called when discipline changed * with ioctl, this assigns a buffer to the line for input, and * changing the interpretation of the information in the tty structure. */ /*ARGSUSED*/ bkopen(dev, tp) dev_t dev; register struct tty *tp; { register struct buf *bp; if (tp->t_line == NETLDISC) return (EBUSY); /* sometimes the network opens /dev/tty */ ###################### This is not going to work on 2.10BSD without serious reworking. Basically, you'll have to map the buffer pointed at by bp in whenever you want to access it. ###################### bp = geteblk(); ttyflush(tp, FREAD|FWRITE); tp->t_bufp = bp; tp->t_cp = (char *)bp->b_un.b_addr; tp->t_inbuf = 0; tp->t_rec = 0; return (0); } /* * Break down... called when discipline changed or from device * close routine. */ bkclose(tp) register struct tty *tp; { register int s; s = spl5(); wakeup((caddr_t)&tp->t_rawq); if (tp->t_bufp) { brelse(tp->t_bufp); tp->t_bufp = 0; } else printf("bkclose: no buf\n"); tp->t_cp = 0; tp->t_inbuf = 0; tp->t_rec = 0; tp->t_line = 0; /* paranoid: avoid races */ splx(s); } /* * Read from a network line. * Characters have been buffered in a system buffer and are * now dumped back to the user in one fell swoop, and with a * minimum of fuss. Note that no input is accepted when a record * is waiting. Our clearing tp->t_rec here allows further input * to accumulate. */ bkread(tp, uio) register struct tty *tp; { register int s; int error; if ((tp->t_state&TS_CARR_ON)==0) return (-1); s = spl5(); while (tp->t_rec == 0 && tp->t_line == NETLDISC) sleep((caddr_t)&tp->t_rawq, TTIPRI); splx(s); if (tp->t_line != NETLDISC) return (-1); error = uiomove(tp->t_bufp->b_un.b_addr, tp->t_inbuf, uio); tp->t_cp = (char *)tp->t_bufp->b_un.b_addr; tp->t_inbuf = 0; tp->t_rec = 0; return (error); } /* * Low level character input routine. * Stuff the character in the buffer, and wake up the top * half after setting t_rec if this completes the record * or if the buffer is (ick!) full. * * Thisis where the formatting should get done to allow * 8 character data paths through escapes. * * This rutine should be expanded in-line in the receiver * interrupt routine of the dh-11 to make it run as fast as possible. */ bkinput(c, tp) register c; register struct tty *tp; { if (tp->t_rec) return; *tp->t_cp++ = c; if (++tp->t_inbuf == 1024 || c == '\n') { tp->t_rec = 1; wakeup((caddr_t)&tp->t_rawq); } } /* * This routine is called whenever a ioctl is about to be performed * and gets a chance to reject the ioctl. We reject all teletype * oriented ioctl's except those which set the discipline, and * those which get parameters (gtty and get special characters). */ /*ARGSUSED*/ bkioctl(tp, cmd, data, flag) struct tty *tp; u_int cmd; caddr_t data; { if ((cmd>>8) != 't') return (-1); switch (cmd) { case TIOCSETD: case TIOCGETD: case TIOCGETP: case TIOCGETC: return (-1); } return (ENOTTY); } #endif ufp = 0; } else printf("bkclose: no buf\n"); tp->t_cp = 0; tp->t_inbuf = 0; tp->sys/OTHERS/berknet/README 444 3 12 1160 4054233042 10157 bk.c is the old version that didn't work with 2.9. tty_bk.c is the new version stolen from 4.3 that doesn't work with 2.10. What you probably want to do is figure out how to make bk.c work, and then fold the changes into tty_bk.c. And then remember that it loses characters after every carriage return. It's clear that you don't want to use the buffer cache. Maybe throw 1K of data space per line at the problem? It's got to be fast. berknet_driver is a copy of 2.9's driver that was supposedly fixed. It may have all of the mapped out stuff you need, so you might be able to fold its fixes into the 4.3 one. Enjoy. ne != NETLDISC) return (-1); error = uiomove(tp->t_bufp->b_un.b_addr, tp->t_inbuf, uio); tp->t_cp = (char *)tp->t_bufp->b_un.b_addr; tp->t_inbuf = 0; tp->t_rec = 0; return (error); } /* * Low level character input routine. * Stuff the character in the buffer, and wake up the top * half after setting t_rec if this completes the record * or if the buffer is (ick!) full. * * Thisis whersys/OTHERS/berknet/bkmac.h.43 444 3 12 1245 4010732274 10761 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)bkmac.h 7.1 (Berkeley) 6/4/86 */ /* * Macro definition of bk.c/netinput(). * This is used to replace a call to * (*linesw[tp->t_line].l_rint)(c,tp); * with * * if (tp->t_line == NETLDISC) * BKINPUT(c, tp); * else * (*linesw[tp->t_line].l_rint)(c,tp); */ #define BKINPUT(c, tp) { \ if ((tp)->t_rec == 0) { \ *(tp)->t_cp++ = c; \ if (++(tp)->t_inbuf == 1024 || (c) == '\n') { \ (tp)->t_rec = 1; \ wakeup((caddr_t)&(tp)->t_rawq); \ } \ } \ } _bufp->b_un.b_addr, tp->t_inbuf, uio); tp->t_cp = (char *)tp->t_bufp->b_un.b_addr; tp->t_inbuf = 0; tp->t_rec = 0; return (error); } /* * Low level character input routine. * Stuff the character in the buffer, and wake up the top * half after setting t_rec if this completes the record * or if the buffer is (ick!) full. * * Thisis whersys/OTHERS/berknet/berknet_driver 444 3 12 44172 4054232743 12270 From dual!amd!megatest!cadvax.roman Sat Oct 12 18:33:10 1985 Date: Thu, 10 Oct 85 10:45:25 pdt From: dual!amd!megatest!cadvax.roman (Roman Rycerz) To: lll-crg!seismo!keith Subject: bk driver here is the bk driver that handles mapped buffers.. it works and we run berknet here to connect small test stations to a central host... -roman {lbl-csam,decvax!decwrl![sun|amd|fortune]}!megatest!roman ----------------------- CUT HERE -------------------------------------- : This is a shar archive. Extract with sh, not csh. : This archive ends with exit, so do not worry about trailing junk. echo 'Extracting bk.h' sed 's/^X//' > bk.h << '+ END-OF-FILE bk.h' X#define NBK 1 X/* BK_DEBUG /* turn on debugging */ + END-OF-FILE bk.h chmod 'u=rw,g=r,o=r' 'bk.h' echo ' -rw-r--r-- 1 root 52 Oct 9 22:27 bk.h (as sent)' echo -n ' ' /bin/ls -l bk.h echo 'Extracting dev/bk.c' sed 's/^X//' > dev/bk.c << '+ END-OF-FILE dev/bk.c' X#include "param.h" X#include "bk.h" X#if NBK > 0 X#include X#include X#include X#include X#include X#include X#ifdef MPX_FILS X#include X#endif X#include X#include X#include X#include X X/* X * SCCS id @(#)bk.c 2.1 (Berkeley) 8/5/83 X */ X X#ifdef UCB_NTTY X#ifdef BK_DEBUG Xint bkdbg = 1; X#define DBG_printf if(bkdbg) printf /* debugging printf */ X#else X#define DBG_printf bknull /* null routine */ Xbknull(s,a,b,c,d) char *s;{}; X#endif X X/* X * When running dz's using only SAE (silo alarm) on input X * it is necessary to call dzrint() at clock interrupt time. X * This is unsafe unless spl5()s in tty code are changed to X * spl6()s to block clock interrupts. Note that the dh driver X * currently in use works the same way as the dz, even though X * we could try to more intelligently manage its silo. X * Thus don't take this out if you have no dz's unless you X * change clock.c and dhtimer(). X */ X#define spl5 spl6 X X/* X * Line discipline for Berkeley network. X * X * This supplies single lines to a user level program X * with a minimum of fuss. Lines are newline terminated. X * A later version will implement full 8-bit paths by providing X * an escape sequence to include a newline in a record. X * X * This discipline requires that tty device drivers call X * the line specific l_ioctl routine from their ioctl routines, X * assigning the result to cmd so that we can refuse most tty specific X * ioctls which are unsafe because we have ambushed the X * teletype input queues, overlaying them with other information. X */ X X/* X * Open as networked discipline. Called when discipline changed X * with ioctl, this assigns a buffer to the line for input, and X * changing the interpretation of the information in the tty structure. X */ Xbkopen(tp) Xregister struct tty *tp; X{ X register struct buf *bp; X X if (u.u_error) X return; /* paranoia */ X /* X * The suser check was added since once it gets set you can't turn X * it off, even as root. Theoretically a setuid root program could X * be run over the net which opened /dev/tty but this seems farfetched. X */ X if (tp->t_line == NETLDISC && !suser()) { X u.u_error = EBUSY; /* sometimes the network */ X return; /* ... opens /dev/tty */ X } X bp = geteblk(); X flushtty(tp,FREAD|FWRITE); X tp->t_bufp = bp; X#ifndef NOKA5 X tp->t_cp = (char *)mapin(bp); X mapout(bp); X#else X tp->t_cp = (char *)tp->t_bufp->b_un.b_addr; X#endif X tp->t_inbuf = 0; X tp->t_rec = 0; X DBG_printf("bkop: bp %o cp %o\n",tp->t_bufp,tp->t_cp); X} X X/* X * Break down... called when discipline changed or from device X * close routine. X */ Xbkclose(tp) Xregister struct tty *tp; X{ X register s; X register struct buf *bp; X X DBG_printf("bkcl: bp %o cp %o\n",tp->t_bufp,tp->t_cp); X s = spl5(); X wakeup((caddr_t)&tp->t_bufp); X if (tp->t_bufp) { X brelse(tp->t_bufp); X tp->t_bufp = 0; X } X tp->t_cp = 0; X tp->t_inbuf = 0; X tp->t_rec = 0; X tp->t_line = DFLT_LDISC; /* paranoid: avoid races */ X splx(s); X} X X/* X * Read from a network line. X * Characters have been buffered in a system buffer and are X * now dumped back to the user in one fell swoop, and with a X * minimum of fuss. Note that no input is accepted when a record X * is waiting. Our clearing tp->t_rec here allows further input X * to accumulate. X */ Xbkread(tp) Xregister struct tty *tp; X{ X register int i; X register s; X X if ((tp->t_state&CARR_ON)==0) X return (-1); X DBG_printf("bkrd: bp %o cp %o\n",tp->t_bufp,tp->t_cp); X s = spl5(); X while (tp->t_rec == 0 && tp->t_line == NETLDISC) X sleep((caddr_t)&tp->t_bufp, TTIPRI); X splx(s); X if (tp->t_line != NETLDISC) X return (-1); X i = MIN(tp->t_inbuf, (int)u.u_count); X#ifndef NOKA5 X if (copyout(mapin(tp->t_bufp), u.u_base, (unsigned)i)) { X mapout(tp->t_bufp); X u.u_error = EFAULT; X return (-1); X }; X mapout(tp->t_bufp); X#else X if (copyout(tp->t_bufp->b_un.b_addr, u.u_base, (unsigned)i)) { X u.u_error = EFAULT; X return (-1); X }; X#endif X u.u_count -= i; X u.u_base += i; X u.u_offset += i; X#ifndef NOKA5 X tp->t_cp = (char *)mapin(tp->t_bufp); X mapout(tp->t_bufp); X#else X tp->t_cp = (char *)tp->t_bufp->b_un.b_addr; X#endif X tp->t_inbuf = 0; X tp->t_rec = 0; X DBG_printf("bkrd: bp %o cp %o\n",tp->t_bufp,tp->t_cp); X return (0); X} X X/* X * Low level character input routine. X * Stuff the character in the buffer, and wake up the top X * half after setting t_rec if this completes the record X * or if the buffer is (ick!) full. X * X * This is where the formatting should get done to allow X * 8 character data paths through escapes. X * X * This routine should be expanded in-line in the receiver X * interrupt routine of the dh-11 to make it run as fast as possible. X */ X Xbkinput(c, tp) Xregister c; Xregister struct tty *tp; X{ X#ifndef NOKA5 X segm save5; X extern struct buf *hasmap; X struct buf *oldmap; X X if (tp->t_rec) X return; X saveseg5(save5); X oldmap = hasmap; X if( hasmap != (struct buf *)NULL) X mapout(hasmap); X mapin(tp->t_bufp); X *tp->t_cp++ = c; X mapout(tp->t_bufp); X if(oldmap != (struct buf *)NULL) X mapin(oldmap); X restorseg5(save5); X#else X if (tp->t_rec) X return; X *tp->t_cp++ = c; X#endif X if (++tp->t_inbuf == BSIZE || c == '\n') { X DBG_printf("bkip: bp %o cp %o\n",tp->t_bufp,tp->t_cp); X tp->t_rec = 1; X wakeup((caddr_t)&tp->t_bufp); X } X} X X/* X * This routine is called whenever a ioctl is about to be performed X * and gets a chance to reject the ioctl. We reject all teletype X * oriented ioctl's except those which set the discipline, and X * those which get parameters (gtty and get special characters). X */ X/*ARGSUSED*/ Xbkioctl(tp, cmd, addr) Xstruct tty *tp; Xcaddr_t addr; X{ X X if ((cmd>>8) != 't') X return (cmd); X switch (cmd) { X X case TIOCSETD: X case TIOCGETD: X case TIOCGETP: X case TIOCGETC: X return (cmd); X } X u.u_error = ENOTTY; X return (0); X} X#endif UCB_NTTY X#endif NBK + END-OF-FILE dev/bk.c chmod 'u=rw,g=r,o=r' 'dev/bk.c' echo ' -rw-r--r-- 1 root 5815 Oct 9 22:27 dev/bk.c (as sent)' echo -n ' ' /bin/ls -l dev/bk.c echo 'Extracting c.c' sed 's/^X//' > c.c << '+ END-OF-FILE c.c' X/* X * SCCS id %W% (Berkeley) %G% X */ X X#include "param.h" X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X X Xint nulldev(); Xint nodev(); Xint nullioctl(); X X X#include "dh.h" X#if NDH > 0 Xint dhopen(), dhclose(), dhread(), dhwrite(), dhioctl(), dhstop(); Xextern struct tty dh11[]; X#else X#define dhopen nodev X#define dhclose nodev X#define dhread nodev X#define dhwrite nodev X#define dhioctl nodev X#define dhstop nodev X#define dh11 ((struct tty *) NULL) X#endif NDH X X#include "dn.h" X#if NDN > 0 Xint dnopen(), dnclose(), dnwrite(); X#else X#define dnopen nodev X#define dnclose nodev X#define dnwrite nodev X#endif NDN X X#include "dz.h" X#if NDZ > 0 Xint dzopen(), dzclose(), dzread(), dzwrite(), dzioctl(); X#ifdef DZ_PDMA Xint dzstop(); X#else X#define dzstop nulldev X#endif Xextern struct tty dz11[]; X#else X#define dzopen nodev X#define dzclose nodev X#define dzread nodev X#define dzwrite nodev X#define dzioctl nodev X#define dzstop nodev X#define dz11 ((struct tty *) NULL) X#endif NDZ X X#include "hk.h" X#if NHK > 0 Xint hkstrategy(), hkread(), hkwrite(), hkroot(); Xextern struct buf hktab; X#define hkopen nulldev X#define hkclose nulldev X#define _hktab &hktab X#else X#define hkopen nodev X#define hkclose nodev X#define hkstrategy nodev X#define hkread nodev X#define hkwrite nodev X#define hkroot nulldev X#define _hktab ((struct buf *) NULL) X#endif NHK X X#include "hp.h" X#if NHP > 0 Xint hpstrategy(), hpread(), hpwrite(), hproot(); Xextern struct buf hptab; X#define hpopen nulldev X#define hpclose nulldev X#define _hptab &hptab X#else X#define hpopen nodev X#define hpclose nodev X#define hproot nulldev X#define hpstrategy nodev X#define hpread nodev X#define hpwrite nodev X#define _hptab ((struct buf *) NULL) X#endif NHP X X#include "hs.h" X#if NHS > 0 Xint hsstrategy(), hsread(), hswrite(), hsroot(); Xextern struct buf hstab; X#define _hstab &hstab X#define hsopen nulldev X#define hsclose nulldev X#else X#define hsopen nodev X#define hsclose nodev X#define hsstrategy nodev X#define hsread nodev X#define hswrite nodev X#define hsroot nulldev X#define _hstab ((struct buf *) NULL) X#endif NHS X X#include "ht.h" X#if NHT > 0 Xint htopen(), htclose(), htread(), htwrite(), htstrategy(); X#ifdef HT_IOCTL Xint htioctl(); X#else X#define htioctl nodev X#endif Xextern struct buf httab; X#define _httab &httab X#else X#define htopen nodev X#define htclose nodev X#define htread nodev X#define htwrite nodev X#define htioctl nodev X#define htstrategy nodev X#define _httab ((struct buf *) NULL) X#endif NHT X X#include "lp.h" X#if NLP > 0 Xint lpopen(), lpclose(), lpwrite(); X#else X#define lpopen nodev X#define lpclose nodev X#define lpwrite nodev X#endif NLP X X#include "rk.h" X#if NRK > 0 Xint rkstrategy(), rkread(), rkwrite(); Xextern struct buf rktab; X#define rkopen nulldev X#define rkclose nulldev X#define _rktab &rktab X#else X#define rkopen nodev X#define rkclose nodev X#define rkstrategy nodev X#define rkread nodev X#define rkwrite nodev X#define _rktab ((struct buf *) NULL) X#endif NRK X X#include "rl.h" X#if NRL > 0 Xint rlstrategy(), rlread(), rlwrite(); Xextern struct buf rltab; X#define rlopen nulldev X#define rlclose nulldev X#define _rltab &rltab X#else X#define rlopen nodev X#define rlclose nodev X#define rlstrategy nodev X#define rlread nodev X#define rlwrite nodev X#define _rltab ((struct buf *) NULL) X#endif NRL X X#include "rm.h" X#if NRM > 0 Xint rmstrategy(), rmread(), rmwrite(), rmroot(); Xextern struct buf rmtab; X#define rmopen nulldev X#define rmclose nulldev X#define _rmtab &rmtab X#else X#define rmopen nodev X#define rmclose nodev X#define rmroot nulldev X#define rmstrategy nodev X#define rmread nodev X#define rmwrite nodev X#define _rmtab ((struct buf *) NULL) X#endif NRM X X#include "rp.h" X#if NRP > 0 Xint rpstrategy(), rpread(), rpwrite(); Xextern struct buf rptab; X#define rpopen nulldev X#define rpclose nulldev X#define _rptab &rptab X#else X#define rpopen nodev X#define rpclose nodev X#define rpstrategy nodev X#define rpread nodev X#define rpwrite nodev X#define _rptab ((struct buf *) NULL) X#endif NRP X X#include "tm.h" X#if NTM > 0 Xint tmopen(), tmclose(), tmread(), tmwrite(), tmstrategy(); X#ifdef TM_IOCTL Xint tmioctl(); X#else X#define tmioctl nodev X#endif Xextern struct buf tmtab; X#define _tmtab &tmtab X#else X#define tmopen nodev X#define tmclose nodev X#define tmread nodev X#define tmwrite nodev X#define tmioctl nodev X#define tmstrategy nodev X#define _tmtab ((struct buf *) NULL) X#endif NTM X X#include "ts.h" X#if NTS > 0 Xint tsopen(), tsclose(), tsread(), tswrite(), tsstrategy(); X#ifdef TS_IOCTL Xint tsioctl(); X#else X#define tsioctl nodev X#endif Xextern struct buf tstab; X#define _tstab &tstab X#else X#define tsopen nodev X#define tsclose nodev X#define tsread nodev X#define tswrite nodev X#define tsioctl nodev X#define tsstrategy nodev X#define _tstab ((struct buf *) NULL) X#endif NTS X X#include "vp.h" X#if NVP > 0 Xint vpopen(), vpclose(), vpwrite(), vpioctl(); X#else X#define vpopen nodev X#define vpclose nodev X#define vpwrite nodev X#define vpioctl nodev X#endif NVP X X#include "xp.h" X#if NXP > 0 Xint xpstrategy(), xpread(), xpwrite(), xproot(); Xextern struct buf xptab; X#define xpopen nulldev X#define xpclose nulldev X#define _xptab &xptab X#else X#define xpopen nodev X#define xpclose nodev X#define xproot nulldev X#define xpstrategy nodev X#define xpread nodev X#define xpwrite nodev X#define _xptab ((struct buf *) NULL) X#endif NXP X Xstruct bdevsw bdevsw[] = X{ X rkopen, rkclose, rkstrategy, X nulldev, _rktab, /* rk = 0 */ X X rpopen, rpclose, rpstrategy, X nulldev, _rptab, /* rp = 1 */ X X nodev, nodev, nodev, X nulldev, 0, /* rf = 2 */ X X tmopen, tmclose, tmstrategy, X nulldev, _tmtab, /* tm = 3 */ X X hkopen, hkclose, hkstrategy, X hkroot, _hktab, /* hk = 4 */ X X hsopen, hsclose, hsstrategy, X hsroot, _hstab, /* hs = 5 */ X X#if NXP > 0 X xpopen, xpclose, xpstrategy, X xproot, _xptab, /* xp = 6 */ X#else X X#if NHP > 0 X hpopen, hpclose, hpstrategy, X hproot, _hptab, /* hp = 6 */ X#else X X rmopen, rmclose, rmstrategy, X rmroot, _rmtab, /* rm = 6 */ X#endif X#endif X X htopen, htclose, htstrategy, X nulldev, _httab, /* ht = 7 */ X X rlopen, rlclose, rlstrategy, X nulldev, _rltab, /* rl = 8 */ X X tsopen, tsclose, tsstrategy, X nulldev, _tstab, /* ts = 9 */ X}; Xint nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]); X Xint klopen(), klclose(), klread(), klwrite(), klioctl(); Xextern struct tty kl11[]; Xint mmread(), mmwrite(); Xint syopen(), syread(), sywrite(), sysioctl(); X X#include "ft.h" X#if NFT > 0 Xint ftopen(), ftclose(), ftioctl(); X#else X#define ftopen nodev X#define ftclose nodev X#define ftioctl nodev X#endif X X#include "ib.h" X#if NIB > 0 Xint ibopen(), ibclose(), ibread(), ibwrite(), ibioctl(); X#else X#define ibopen nodev X#define ibclose nodev X#define ibread nodev X#define ibwrite nodev X#define ibioctl nodev X#endif X X#include "mq.h" X#if NMQ > 0 Xint mqopen(), mqclose(), mqread(), mqwrite(); X#else X#define mqopen nodev X#define mqclose nodev X#define mqread nodev X#define mqwrite nodev X#endif X Xstruct cdevsw cdevsw[] = X{ X klopen, klclose, klread, klwrite, X klioctl, nulldev, kl11, /* kl = 0 */ X X nodev, nodev, nodev, nodev, X nodev, nodev, 0, /* pc = 1 */ X X vpopen, vpclose, nodev, vpwrite, X vpioctl, nulldev, 0, /* vp = 2 */ X X lpopen, lpclose, nodev, lpwrite, X nodev, nulldev, 0, /* lp = 3 */ X X dhopen, dhclose, dhread, dhwrite, X dhioctl, dhstop, dh11, /* dh = 4 */ X X nodev, nodev, nodev, nodev, X nodev, nodev, 0, /* dp = 5 */ X X nodev, nodev, nodev, nodev, X nodev, nodev, 0, /* dj = 6 */ X X dnopen, dnclose, nodev, dnwrite, X nodev, nulldev, 0, /* dn = 7 */ X X nulldev, nulldev, mmread, mmwrite, X nodev, nulldev, 0, /* mem = 8 */ X X rkopen, rkclose, rkread, rkwrite, X nodev, nulldev, 0, /* rk = 9 */ X X nodev, nodev, nodev, nodev, X nodev, nodev, 0, /* rf = 10 */ X X rpopen, rpclose, rpread, rpwrite, X nodev, nulldev, 0, /* rp = 11 */ X X tmopen, tmclose, tmread, tmwrite, X tmioctl, nulldev, 0, /* tm = 12 */ X X hsopen, hsclose, hsread, hswrite, X nodev, nulldev, 0, /* hs = 13 */ X X#if NXP > 0 X xpopen, xpclose, xpread, xpwrite, X nodev, nulldev, 0, /* xp = 14 */ X#else X#if NHP > 0 X X hpopen, hpclose, hpread, hpwrite, X nodev, nulldev, 0, /* hp = 14 */ X#else X X rmopen, rmclose, rmread, rmwrite, X nodev, nulldev, 0, /* rm = 14 */ X#endif X#endif X X htopen, htclose, htread, htwrite, X htioctl, nulldev, 0, /* ht = 15 */ X X nodev, nodev, nodev, nodev, X nodev, nodev, 0, /* du = 16 */ X X syopen, nulldev, syread, sywrite, X sysioctl, nulldev, 0, /* tty = 17 */ X X rlopen, rlclose, rlread, rlwrite, X nodev, nulldev, 0, /* rl = 18 */ X X hkopen, hkclose, hkread, hkwrite, X nodev, nulldev, 0, /* hk = 19 */ X X tsopen, tsclose, tsread, tswrite, X tsioctl, nulldev, 0, /* ts = 20 */ X X dzopen, dzclose, dzread, dzwrite, X dzioctl, dzstop, dz11, /* dz = 21 */ X X ibopen, ibclose, ibread, ibwrite, X ibioctl, nulldev, 0, /* ib = 22 */ X X ftopen, ftclose, nodev, nodev, X ftioctl, nodev, 0, /* ft = 23 */ X X mqopen, mqclose, mqread, mqwrite, X nodev, nodev, 0 /* mq = 24 */ X}; X Xint nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]); X X#ifdef OLDTTY Xint ttread(), ttyinput(), ttyoutput(); Xcaddr_t ttwrite(); X#define ttopen nulldev X#define ttclose nulldev X#define ttioctl nullioctl X#define ttmodem nulldev X#else X#define ttopen nodev X#define ttclose nodev X#define ttread nodev X#define ttwrite nodev X#define ttioctl nodev X#define ttyinput nodev X#define ttyoutput nodev X#define ttmodem nodev X#endif X X X#ifdef UCB_NTTY Xint ntyopen(), ntyclose(), ntread(), ntyinput(), ntyoutput(); Xcaddr_t ntwrite(); X#define ntyioctl nullioctl X#define ntymodem nulldev X#else X#define ntyopen nodev X#define ntyclose nodev X#define ntread nodev X#define ntwrite nodev X#define ntyioctl nodev X#define ntyinput nodev X#define ntyoutput nodev X#define ntymodem nodev X X#endif X#include "bk.h" X#if NBK > 0 Xint bkopen(), bkclose(), bkread(), bkioctl(), bkinput(); X#else X#define bkopen nodev X#define bkclose nodev X#define bkread nodev X#define bkioctl nodev X#define bkinput nodev X#endif X Xstruct linesw linesw[] = X{ X ttopen, ttclose, ttread, ttwrite, X ttioctl, ttyinput, ttyoutput, ttmodem, /*0*/ X X ntyopen, ntyclose, ntread, ntwrite, X ntyioctl, ntyinput, ntyoutput, ntymodem, /*1*/ X X bkopen, bkclose, bkread, ntwrite, X bkioctl, bkinput, ntyoutput, ntymodem /*2*/ X}; X X#ifndef MPX_FILS Xint nldisp = sizeof(linesw) / sizeof(linesw[0]); X#else Xint nldisp = sizeof(linesw) / sizeof(linesw[0]) - 1; Xint mpxchan(); Xint (*ldmpx)() = mpxchan; X#endif + END-OF-FILE c.c chmod 'u=rw,g=r,o=r' 'c.c' echo ' -rw-r--r-- 1 root 10672 Oct 9 22:27 c.c (as sent)' echo -n ' ' /bin/ls -l c.c exit 0 tty dz11[]; X#else X#define dzopen nodev X#define dzclose nodev X#define dzread nodev X#define dzwrite nodev X#define dzioctl nodev X#define dzstop nodev X#define dz11 ((struct tty *) NULL) X#endif NDZ X X#include "hk.h" X#if NHK > 0 Xint hkstrategy(), hkread(), hkwrite(), hkroot(); Xextern struct buf hktab; X#define hkopen nulldev X#define hkclose nulldev X#define _hktab &hktasys/OTHERS/interleave/ 755 0 12 0 3772316253 7733 sys/OTHERS/interleave/dkleave.c 444 3 12 1017 3771376325 11604 /* * SCCS id @(#)dkleave.c 2.1 (Berkeley) 8/5/83 */ #include "param.h" #include "buf.h" #ifdef INTRLVE daddr_t dkblock(bp) register struct buf *bp; { register int dminor; if (((dminor=minor(bp->b_dev))&0100) == 0) return(bp->b_blkno); dminor >>= 3; dminor &= 07; dminor++; return(bp->b_blkno/dminor); } dkunit(bp) register struct buf *bp; { register int dminor; dminor = minor(bp->b_dev) >> 3; if ((dminor&010) == 0) return(dminor); dminor &= 07; dminor++; return(bp->b_blkno%dminor); } #endif INTRLVE = 7 */ X X nulldev, nulldev, mmread, mmwrite, X nodev, nulldev,, /* mem = 8 */ X X rkopen, rkclose, rkread, rkwrite, X nodev, nulldev, 0, /* rk = 9 */ X X nodev, nodev, nodev, nodev, X nodev, nodev, 0, /* rf = 10 */ X X rpopen, rpclose, rpread, rpwrite, X nodev, nulldev, 0, /* rp = 11 */ X X tmopen, tmclose, tmread, tmwrite, X tmioctl, nulldev, 0, /* tm = 12 */ X X hsopen, hsclose, hsread, hswrite, X nodev, nulldev, 0, /* hs = 13 */ X X#if NXP > 0 X xpopen, xpclose,sys/OTHERS/interleave/param.h 444 3 12 161 3772316253 11250 #ifndef INTRLVE #define dkblock(bp) ((bp)->b_blkno) #define dkunit(bp) (minor ((bp)->b_dev) >> 3) #endif INTRLVE sys/OTHERS/scsi/ 755 0 12 0 5123225243 6524 sys/OTHERS/scsi/scsi_locore 444 3 12 1706 4020206544 11043 #include "scsi.h" /* for NIOM and NIMI */ #if NIMI > 0 .globl _imiintr imiio: jsr r0,call; jmp _imiintr #endif #if NIOM > 0 .globl _iomintr iomio: jsr r0,call; jmp _iomintr #endif #include "scsi.h" #if NIOM > 0 int iomstrategy(), iomread(), iomwrite(); extern struct buf iomtab; #define iomopen nulldev #define iomclose nulldev #define iomprobe nulldev #define _iomtab &iomtab #else #define iomopen nodev #define iomclose nodev #define iomprobe nulldev #define iomstrategy nodev #define iomread nodev #define iomwrite nodev #define _iomtab ((struct buf *) NULL) #endif NIOM #if NIMI > 0 int imistrategy(), imiread(), imiwrite(); extern struct buf imitab; #define imiopen nulldev #define imiclose nulldev #define imiprobe nulldev #define _imitab &imitab #else #define imiopen nodev #define imiclose nodev #define imiprobe nulldev #define imistrategy nodev #define imiread nodev #define imiwrite nodev #define _imitab ((struct buf *) NULL) #endif NIMI ldev, 0, /* hs = 13 */ X X#if NXP > 0 X xpopen, xpclose,sys/OTHERS/scsi/scsi.c 444 3 12 13717 5067136444 7763 /* Driver for 5 1/4'' Disk Drive using the DTC510 Host Adaptor with Adaptec 4000 Controller */ #include "scsi.h" #if NIMI>0 || NIOM>0 #include #include #include #include #include #include #include #define imi ((struct dtc *)DTC1_ADDR) struct sc_sizes scsitab[TABSIZ][PARTSIZ] = { /* 512 byte blks */ /* table zero 0 - the imi disk 322 tracks total, 18 sectors on Adaptec with 512b blocks and intrlv 2, 6 heads */ { { 0, 9792 }, { 9792, 19584 }, { 29376, 3672 }, { 0, 33048 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, /* table one 1 - the old imi disk */ { { 0, 9580 }, { 9580, 2048 }, { 11628, 19584 }, { 0, 31212 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, /* table two 2 - Wren Disk without Swap Space 697 tracks with 18 512b sectors on Adaptec with interleave=2, 5 heads, leave 5 spare tracks */ { { 0, 9792 }, /* 9792 is half of an iom */ { 9792, 19584 }, { 29376, 19584 }, { 48960, 13960 }, { 0, 62640 }, { 0, 0}, { 0, 0}, { 0, 0} }, /* table three 3 - Wren Disk with Swap Space */ { { 0, 9792 }, /* 9792 is half of an iom */ { 9792, 2048 }, { 11840, 19584 }, { 31424, 19584 }, { 51008, 11632 }, { 0, 62640 }, { 0, 0 }, { 0, 0 } }, /* table four 4 - */ { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, /* table 5 5 - */ { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, /* table six 6 - */ { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, /* table seven 7 - Iomega disk in various flavors */ { { 0, 18584}, /* First filesys on Iomega fixit, swap at end */ { 18584, 1000}, /* Swap space on the fixit disk */ { 0, 9792}, /* First partition on Iomega split disk */ { 9792, 19584}, /* Second partition on Iomega split disk */ { 0, 9580}, /* First Partition for old imi backup */ { 9580, 19584}, /* Second partition for old imi backup */ { 0, 19584}, /* The whole iomega disk */ { 0, 0} /* Nothing */ } }; char imicmd[8]; char Initdata[8]; struct buf imitab; unsigned imixblks; /* Number of blks transferred */ static int Didinit = 0; imistrategy(bp) register struct buf *bp; { register unit; int part; int tab; part = bp->b_dev & PARTMSK; tab = (bp->b_dev >> TABPOS) & TABMSK; /* if(bp->b_flags&B_PHYS) mapalloc(bp); */ if(bp->b_blkno >= scsitab[tab][part].nblks) { bp->b_flags |= B_ERROR; iodone(bp); return; } bp->av_forw = (struct buf *)NULL; spl5(); if(imitab.b_actf == NULL) imitab.b_actf = bp; else imitab.b_actl->av_forw = bp; imitab.b_actl = bp; if(imitab.b_active == NULL) imistart(0); spl0(); } /* zzz */ imistart(cont) int cont; { register struct buf *bp; long baddr; register drive; int part; int tab; register nblks; if((bp = imitab.b_actf) == NULL) return; imitab.b_active++; #ifdef XEBEC if(Didinit == 0) { Initdata[0] = XIMI_NCYL >> 8; Initdata[1] = XIMI_NCYL & 0377; Initdata[2] = XIMI_NSURF; /* Reduce write current - drive proc does this */ Initdata[3] = Initdata[4] = 0; /* Write precomp trk 256 */ Initdata[5] = 255; Initdata[6] = 0; /* ECC Burst length */ Initdata[7] = 11; imicmd[0] = INITSZ; imi->cmdaddr = imicmd; imi->bufaddr = Initdata; imi->xcmdaddr = 0; imi->xbufaddr = 0; imi->csr = GO; while((imi->csr & DONE) == 0) ; if(imi->csr < 0) printf("imi init error %o\n", imi->csr); Didinit = 1; } #endif if(cont == 0) imixblks = 0; part = bp->b_dev & PARTMSK; tab = (bp->b_dev >> TABPOS) & TABMSK; /* Setup the command block */ baddr = (bp->b_blkno + scsitab[tab][part].boffset) + imixblks; drive = (bp->b_dev >> DRIVPOS) & DRIVMSK; imicmd[1] = (drive << 5) | ((baddr >> 16) & 037); imicmd[2] = ((baddr >> 8) & 0377); imicmd[3] = (baddr & 0377); /* Number of blks up to 256 (0) in one operation */ nblks = ((bp->b_bcount + 0777) >> 9) - imixblks; if(nblks > 255) imicmd[4] = 0; else imicmd[4] = nblks; imicmd[5] = 0; if(bp->b_flags & B_READ) imicmd[0] = READ; else imicmd[0] = WRITE; imi->cmdaddr = imicmd; imi->xcmdaddr = 0; imi->bufaddr = bp->b_un.b_addr; imi->xbufaddr = (bp->b_xmem >> 4) & 0x03; imi->csr = ((bp->b_xmem & 0x0f) << 2) | INTR | GO; } imiintr() { register struct buf *bp; register unsigned short stat; register unsigned short nstat; long bnum; if(imitab.b_active == NULL) return; bp = imitab.b_actf; stat = imi->csr; if((stat & ERROR)) { /* printf("stat = %o\n", stat); */ if(stat & NONXMEM) ; else if(imi->ccsr & CONTROL) /* Controller or drive error */ { imicmd[0] = RQSENSE; imicmd[1] = ((bp->b_dev >> DRIVPOS) & DRIVMSK) <<5; imicmd[2] = 0; imicmd[3] = 0; imicmd[4] = 0; imicmd[5] = 0; imi->cmdaddr = imi->bufaddr = imicmd; imi->xcmdaddr = imi->xbufaddr = 0; imi->csr = GO; while((imi->csr & DONE) == 0) ; nstat = imicmd[0]; bnum =(unsigned)imicmd[3] | ((unsigned)imicmd[2] << 8) | ((long)(imicmd[1] & 037) << 16); printf("err stat %x\n", nstat&0xffff); /* This error test is wrong- skip /* if((nstat & CDFE) && (nstat & TYPE1)) { printf("CE errblk,blkno %O,%O\n", bnum,bp->b_blkno); goto noerror; /* Continue if raw operation } else { */ bp->b_flags |= B_ERROR; deverror(bp, nstat, stat); printf("errblk,blkno %O,%O\n", bnum,bp->b_blkno); /* } /* Skip punctuation conditional of bad error clause */ } /* try again */ /* Should we really be trying again ? Can this lead to infinite loop of errors? */ if((bp->b_flags & B_ERROR) == 0) { imistart(1); return; } } noerror: imitab.b_errcnt = 0; if(imicmd[4] == 0) imixblks += 256; else imixblks += imicmd[4]; if(((bp->b_flags & B_ERROR) == 0) && ((imixblks << 9) < bp->b_bcount)) { imistart(1); return; } imitab.b_active = 0; imitab.b_actf = bp->av_forw; bp->b_resid = 0; iodone(bp); imistart(0); } #endif NIMI nodev X#define lpclose nodev X#define lpwrite nsys/OTHERS/scsi/scsireg.h 444 3 12 4362 4020204353 10421 #define NIOMBLKS 31212 /* Total number of blocks on device */ #define XIMI_NCYL 306 /* # of cylinders per drive, imi/xebec */ #define XIMI_NSECT 17 /* # of sectors per track, imi/xebec */ #define XIMI_NSURF 6 /* # of surfaces (heads) per drive, imi/xebec */ #define NPART 3 /* Number of Bits used to hold partition no. */ #define PARTMSK 07 /* 3 bit mask for above */ #define DRIVPOS 3 /* position of drive bits */ #define DRIVMSK 03 /* 2 bit mask for above */ #define NTAB 3 /* Number of bits for table number */ #define TABPOS 5 /* position of table bits */ #define TABMSK 07 /* 3 bit mask for above */ #define PARTSIZ PARTMSK + 1 /* Number of partitions in drive table entries */ #define TABSIZ TABMSK + 1 /* Number of tables in drive table entries */ /* Characteristics For IOM Disks */ #define IOMBLKFAC 1 /* blk adr. multiply x2 in command block for 256b blocks on iom */ #define IOMSHIFT 8 /* Divide by 2**8=256 (instead of 512) for number of blocks to xfer at once */ /* Interface Bits */ /* CCSR: Command Completion Status Register */ #define PERR 1 /* Parity error, bit 0 */ #define CONTROL 2 /* Control or drive error bit 1 */ #define LUN 0340 #define SEQ 0177400 /* Control/Status Register */ #define GO 1 #define FORRIOM 2 #define DXMEM 074 #define INTR 0100 #define DONE 0200 #define CXMEM 07400 #define PERR2 020000 #define NONXMEM 040000 #define ERROR 0100000 /* Disk Controller Commands Class 0 */ #define TEIOMRDY 0 #define REIOMORE 1 #define RQSENSE 3 #define FORMAT 4 #define CKTRK 5 #define FMTRK 6 #define FBDTRK 7 #define READ 010 #define WRITE 012 #define SEEK 013 #define INITSZ 014 /* Class 7 commands */ #define TEIOMRAM 0340 #define RETRY 0 #define DISRTRY 0100000 /* Error codes */ #define TYPE0 0 #define TYPE1 020 #define TYPE2 040 #define TYPE3 060 /* The only interesting one */ #define CDFE 010 /* Correctable data field error */ /* MISC */ #define DTC1_ADDR 0177460 #define DTC1_VECTOR 0134 #define DTCIOM_ADDR 0177420 #define DTCIOM_VECTOR 0130 #define EXTADDR 017 /* Extended address bits */ struct dtc { int ccsr; int csr; caddr_t bufaddr; caddr_t cmdaddr; int xbufaddr; int xcmdaddr; int dum3; /* unused */ int dum4; /* unused */ }; struct sc_sizes { long boffset; long nblks; }; ; spl0(); } /* zzz */ imistart(cont) int cont; { register struct buf *bp; long baddr; register drive; int part; int tab; register nblks; if((bp = imitab.b_actf) == NULL) return; imitab.b_active++; #ifdef XEBEC if(Didinit == 0) { Initdata[0] = XIMI_NCYL sys/OTHERS/README 444 3 12 42227 5115764262 6572 This directory contains a number of network, disk and other drivers. Attached at the end of this document is the original README. Believe it or not, you won't have to really understand how a driver works in order to install it. Just follow the bouncing ball ... Note that some of the old `glue' used to patch drivers in this directory can be found in the "GLUE" subdirectory. STEP #1: -------- Install the source code in the proper directory. A pdp MASSBUS driver would go in pdpmba, a pdp UNIBUS driver would go in pdpuba. In reality (the present system) all drivers are in pdpuba regardless of being MASSBUS or UNIBUS. We'll use the versatec driver as an example. Since it's a UNIBUS driver, we'll move vp.c into pdpuba. If you're installing a driver from the OTHERS directory, or you've got a local work of art that you wish to use, there are a few things you should check so that it will work correctly with 2.11BSD: Note, in the following examples, "XX" is the two or three letter designation that device drivers under UNIX get assigned, e.g. "vp" for the Versatec driver, "vv" for the Pronet driver, etc. a) The XXattach routines should return 1 on success, 0 on failure. b) If your XXread and XXwrite routines use physio(), make sure that you're passing the correct number and types of arguments. Between the initial release of 2.11BSD and the present the WORD/BYTE argument (added between 2.9 and 2.10) was removed. If it is important to enforce alignment this can be done in either the strategy routine or in XXread/XXwrite before calling physio(). c) The XXread and XXwrite routines should return 0, if successful, and the correct errno value (for later assignment to u.u_error) if they fail. All the XXread and XXwrite routines which only called physio() have been removed (the common routines rawread() and rawwrite() replacing XXread() and XXwrite() in the cdevsw[] table). Note: If XXread() and/or XXwrite() only calls physio() then the XXread and XXwrite entry points can be removed and the common routines 'rawread', 'rawwrite' used in the cdevsw[] table. See the entries for any of the disc or tape drivers for examples of this. d) The XXioctl routine has changed a *lot* between 2.9 and 2.11: + XXioctl() now takes four arguments, (dev, cmd, data, flags) a device (dev_t), the ioctl command (u_int), a buffer address (caddr_t), and some flags (int). Of real interest is the command, which is the low order 16 bits of the ioctl command. Ioctl's in user land are 32 bits. The low order word contains the ioctl command itself, the high order describes any necessary argument transfers between the kernel and user process. See sys/ioctl.h for macros IO, IOR, IOW and IORW that implement this. Sys/mtio.h is a good file to look at for how to add the correct definitions to your include file. THIS IS THE TRICKY PART!! Look at how other device drivers handle this. + XXioctl() no longer copies anything in or out of user land. The new upper word of the ioctl "cmd" allows the ioctl system call to perform all necessary transfers between the kernel and the user process. See the kernel ioctl() routine for more info. + XXioctl has to return 0 on success, or the correct errno value for later assignment to u.u_error. e) Make sure that you handle buffer allocation correctly. If you wish to be portable, there should be allocations of mapping registers using mapalloc() for UNIBUS mapped machines, ifdef'd on "UNIBUS_MAP". You should ifdef *real* 22-bit QBUS addressing with the define "Q22" (see the comments in conf/GENERIC and pdp/machdep2.c.) Buffer cache buffers have to be mapped in to be accessed in 2.9BSD and 2.11BSD. I don't really understand how it worked before then, but some of the drivers in the OTHERS directory predate that, so be paranoid. f) The device addresses and partition table sizes should be included in the device driver itself, not in ioconf.c (which is used for an entirely different purpose now.) See the drivers in pdpuba for examples. g) You should have an XXopen() routine that validates the unit number for the read, write, and ioctl system calls. See the the drivers in pdpuba for examples. Normally they will look something like: XXopen(dev) dev_t dev; { if (minor(dev) > XXRL || !XXADDR) return (ENXIO); return (0); } If you've already got the driver lying around, the XXstrategy routine probably already does this. The read/write/ioctl routines *MAY* do it, i.e. you can rip it out of them once you've got the open routine working. Note, make sure that you don't assign an absolute address to XXADDR when you declare it (a lot of old drivers do) as it negates the test of XXADDR in XXopen(). Also, a lot of old drivers use the minor numbers in strange and wonderful ways; don't assume that the above test, "minor(dev) > XXRL", is correct for your device. Anyway, this is a Very Important Thing. If you don't do this fix right, interesting things will happen when someone accesses a device for which you have a node in /dev, but which doesn't really exist. STEP #2: -------- Write some code that will attempt to "probe" the routine. See any of the other device drivers for examples. Install this code in the "sys/autoconfig" directory, only call it "XXauto.c", where XX is the prefix for the driver. In our example, we'll install it as "sys/autoconfig/vpauto.c". This is the code that is used by the auto configuration program to get to the device. By convention, this routine must be named "XXprobe()". It's also useful to check and see if any of the probe routines already written would be identical to your probe routine. For example, the "xpauto.c" file contains the probe routine for several flavors of disk drive. If you're porting a 4BSD driver, it probably already has a probe routine in it which may be close to what you want. Also, in any case, rip the XXprobe stuff out of the main file ... it is never used by the kernel and it just wastes text space. Previously the XXauto.c files were kept in the same directory as the device drivers themselves. This lead to the misleading assumption that '/etc/autoconfig' would automatically be rebuilt if the probe routine in the XXauto.c files in sys/pdpuba were modified. To clarify matters the XXauto.c files were moved into the sys/autoconfig directory. STEP #3: -------- Go to the auto configuration directory, "sys/autoconfig" and update the "DOBJS" and "SRCS" defines to reflect the existence of the new device driver. Our example would add "vpauto.c" to the "SRCS" define, and "vpauto.o" to the "DOBJS" define. Update the source file "sys/autoconfig/uprobe.c" to reflect the existence of the new device driver. Basically, you have to define the "vpprobe" routine and then add a new line to the "uprobe" table. For our example, we'd add: int vpprobe(); at the beginning of the file and: "vp", vpprobe, /* vp -- Versatec */ in the "uprobe" table. STEP #4: -------- Update the "/etc/dtab" table to reflect the new drive. You may be able to simply uncomment an existing line, otherwise, figure out the correct values for each field and write a new one. Our example needs an entry of the format: # vp ? 177500 174 4 vpintr # Versatec Where "vp" is the letter designation, "?" means that we aren't assigning a specific unit number (the normal case), 177500 is the address of the device, 174 is the interrupt vector, 4 is the interrupt priority level (Br), and "vpintr" is the handler(s) as designated in the file "scb.s". STEP #5: -------- In scb.s you'll need to add an interrupt interface: a) Add an include of "XX.h" to the top so that the presence or absence of the driver can be determined. b) If the driver is for a disk you'll need to add an interrupt vector definition so that device interrupts can be caught. In general this won't have to be done for most devices because /etc/autoconfig will assign, initialize and probe the device after the system has booted. Disks have to have their interrupt vectors already set up at boot time for obvious reasons. For convenience several of the networking drivers are also hardwired in, but that probably wasn't necessary. The Versatec, for instance, does not need an interrupt vector set up at boot time, so its vector will be set up by /etc/autoconfig. If an interrupt vector is needed, it can be added by determining the device's interrupt vector address, IADDR, and then adding lines of the form: #if NXX > 0 DEVTRAP(IADDR, XXintr, brX) #endif numerically in order with the other sets of lines like the above already present in scb.s. "IADDR", as mentioned above, would be the devices interrupt vector address, "XXintr" is the name of the interrupt handling routine in the C source of your driver, and "brX" is the priority level that the device interrupts at. Note that "XXintr" is the handler name that would be added to /etc/dtab. Also note that some devices have more than one interrupt vector that must be set up. If (and it doesn't!) the versatec needed an interrupt vector assigned at boot time, it would look like the following: #if NVP > 0 DEVTRAP(174, vpintr, br4) #endif c) Finally, add an interrupt interface thunk in the last half of scb.s to correspond with the new device's interrupt vector(s). These small thunks catch the device's interrupts and hand control off to the the real handler routine after first saving the machine's current context by (essentially) passing the address of the real handler to the routine "call" in pdp/mch_trap.s. The following would be added for the Versatec driver: #if NVP > 0 HANDLER(vpintr) #endif STEP #6: -------- Update the conf.c file (it used to be called c.c, in previous incarnations). This file needs to have an include line for the .h file that will determine if this driver gets included in the kernel, a set of defines so that the kernel can compile correctly whether you not you choose to include the driver, and entries in the block and/or character device switch tables. For our example we would add: #include "vp.h" #if NVP > 0 int vpopen(), vpclose(), vpwrite(), vpioctl(); #define vpstrategy nulldev #else #define vpopen nodev #define vpclose nodev #define vpwrite nodev #define vpioctl nodev #define vpstrategy nodev #endif NVP to the character device definition section of conf.c, and /* vp = 20 */ vpopen, vpclose, nodev, vpwrite, vpioctl, nulldev, 0, SELECT(nodev), vpstrategy, to the character device switch table (cdevsw[]). The strategy member of the cdevsw[] structure is new since 2.11BSD was released. Since VP does not have a strategy routine a dummy definition is created. Other devices (such as disc and tape drivers) do have strategy routines and their entries look like: #include "tms.h" #if NTMS > 0 int tmscpopen(), tmscpclose(), tmscpstrategy(), tmscpioctl(); #else #define tmscpopen nodev #define tmscpclose nodev #define tmscpioctl nodev #define tmscpstrategy nodev #endif /* tmscp = 23 (tu81/tk50) */ tmscpopen, tmscpclose, rawread, rawwrite, tmscpioctl, nulldev, 0, seltrue, tmscpstrategy, }; Note, in our example, we've been assuming that NVP is the define that governs whether or not the device is included, as well as how many of them we have. For example, "#define NVP 5" in the file "vp.h" means that we have 5 of the devices, and "#define NVP 0" means that we don't even include the driver. More on "vp.h" a little later. Since the versatec is a character device only, it only gets included in the character device switch table, "cdevsw[]". (for a disk driver, for instance, you would have entries in both the character and block device switch tables) The entries in the table correspond to the routines that get called when you open a versatec, close a versatec, etc. etc. See the include file "sys/conf.h" for more information on what the fields in the block and character switches mean. The easiest method to make a new entry is to find a device that looks like yours and do what it does. Note, the "major" number that you'll use later when you add the node to the "/dev" directory is the offset into this table, or, in the above example, 20. STEP #7: -------- Next, update the following files: "conf/GENERIC", "conf/config", "conf/Make.pdpuba" (or "conf/Make.pdpmba" or "conf/Make.net"), and "conf/Makefile". Basically, add lines of the form: NVP 0 # Versatec VP_TWOSCOMPL NO # interface needs two's complement bytecount in "conf/GENERIC". These are the lines that get changed when you want to configure a new system. Some drivers may only need a single line to describe the number of devices to be configured in, others, like the Versatec need auxiliary configuration information. Change "conf/config" to do the intelligent thing with those lines, i.e. something like echo "#define NVP $NVP" > ../$MACHINE/vp.h if [ $VP_TWOSCOMPL = YES ] ; then echo "#define VP_TWOSCOMPL" >> ../$MACHINE/vp.h fi which will place the appropriate defines for the Versatec into vp.h. Obviously, the source code for your driver should modify its behavior based on the defines found in its include file. Note that if you do have additional configuration options for your driver they *should* be put into conf/GENERIC with appropriate comments. Don't hide them in pdpuba/vpreg.h for instance - that's the way things used to be done in 2.9BSD and earlier, making it extremely difficult to configure a system. With all of the relevant options in one place (conf/GENERIC) it is very simple for the person configuring a new system to just `check off' the items they want. Finally, add the resulting object file names for your device driver to "conf/Makefile" and "conf/Make.pdpuba" (or "conf/Make.pdpmba" or "conf/Make.net"). The former just needs to know the name so it can load it; the latter must be able to compile the file. Be careful where you have "conf/Makefile" load your object as certain things have to be loaded in special places; in general, just put your object name in an overlay or the base segment. STEP #8: -------- You should also edit "dev/MAKEDEV.local" to make nodes with the correct major/minor numbers in the /dev directory. The major number for character devices is the offset of the device's entry in cdevsw[], and the major number for block devices is the similar offset in bdevsw[]. One final note, we've had fair success with porting 4BSD drivers. You just have to rip out all of the stuff that understands about multiple UNIBUS's and you're halfway there. Two things you have to check; it may play pretty loose and casual with buffers since it doesn't cost anything to have them. It's EXPENSIVE on the PDP-11, because you have to do a mapin() every time you want one, plus, you can only have one at a time!! Look for calls to geteblk(), it's a dead giveaway. Also, MBUF allocation is different in the two systems, if the driver goes for one of them, take a long look at it. As far as the various device drivers in this directory, note that comments like "will probably converted soon" and "should work without modification" are probably now specious. While comments like "is untested", "might work with ...", etc. should be taken to mean "it didn't work on 2.9BSD and you'd probably be better off rewriting it from scratch or buying an IBM PC" ... Several of the drivers in the OTHERS directory should eventually be removed because working versions exist in the pdpuba directory. These are the ts-11 (OTHERS/ts - pdpuba/ts.c), rp04/rp06 (OTHERS/rp04.06 - pdpuba/xp.c), TMSCP (OTHERS/tk - pdpuba/tmscp.c), RX01&RX02 (OTHERS/rx01, OTHERS/rx02 - pdpuba/rx.c), MSCP (OTHERS/ra - pdpuba/ra.c), TU-16 (OTHERS/ht - pdpuba/ht.c), rm02/rm03/rm05 (OTHERS/rm02.03.05 - pdpuba/xp.c), Fuji-160 (OTHERS/fuji_160 - pdpuba/xp.c), dm11 (OTHERS/dm11 - pdpuba/dh.c). Keith Bostic & Casey Leedom (revised by Steven Schultz) ORIGINAL README: ---------------- The device drivers in this directory are here because they are untested, or have not been completely converted to use new ioctl or buffering protocols, or because they are of limited interest or use. Some of them have comments at the beginning describing their state. If you test and/or finish any of these drivers, please let the 2BSD project know about it. The dc and dj drivers don't have the current ioctl mechanism. They are untested. The dmc and du drivers don't know how to handle system buffers, since there are no in-address-space buffers any longer. They could probably be made to work with dedicated buffers or mapped-in buffers. The bk driver (berknet line discipline) also has this problem, but will probably be converted and tested soon. It has never worked on PDP11's to my knowledge. The rx2, rx3 and ml drivers have been modified only slightly from working versions received from the authors. They will probably work without modification. The multiplexor driver has not been made to work with anything like the current system. It is unmodified (as far as I know); if you try it, check the order and types of arguments to the external entry points. The cr (card reader) driver is probably flaky, at least with this system. nt an existing line, otherwise, figure out the correct values for each field and write a new one. Our example needs an entry of the format: # vp ? 177500 174 4 vpintr # Versatec Where "vp" is the letter designation, "?" means that we aren't assigning a specific unit number (the normal case), 177500 is the address of the device, 174 is the interrupt vectosys/OTHERS/dsd480/ 755 0 12 0 5325716401 6576 sys/OTHERS/dsd480/rx3.c 444 3 12 34344 5321515445 7575 /* * SCCS id @(#)rx3.c 2.2 (2.11BSD GTE) 1/2/93 */ /* * * Data Systems Design (DSD480) floppy disk drive * * Lauri Rathmann * Tektronix * * * Notes: * The drive is being used in MODE 3 (Extended IBM) * The ioctl mechanism is being used to determine * format, density, number of sectors, bytes per * sector and number of sides. * * History: * August 1981 * Written (for 2.8BSD UNIX) * * January 1982 Modified slightly to work for standard V7 UNIX * S. McGeady * * NOTE: * This is a block rx3device: the 'c.c' file should contain * lines that look like: * * int rx3open(), rx3close(), rx3strategy(); * struct buf rx3tab; * ... * in bdevsw: * rx3open, rx3close, rx3strategy, &rx3tab, * * ... * int rx3ioctl(); * ... * in cdevsw: * nulldev, nulldev, nodev, nodev, rx3ioctl, nulldev, 0, * * The block rx3device is used for all I/O, and the character rx3device * is used only for the IOCTL to set up the rx3device format parameters */ #include "rx3.h" #if NRX3 > 0 #include "param.h" #include #include #include #include #include #include extern struct rx3device *RX3ADDR; #define RXUNIT(dev) (minor(dev)&07) #define NSEC 4 /* Number of logical sections on a disk */ #define MSEC 5 /* Maximum number of retrys */ #define TTIME (2 * hz)/* Timeout time in HZ */ #define trwait() while((rx3r->rx2cs & RX2_XREQ) == 0) /* * type of disk information. The floppy is logically divided * into four sections. 1) Track 0, side 0 * 2) Track 1-76, side 0 * 3) Track 0, side 1 * 4) Track 1-76, side 1 */ struct rx3info { long first_byte; /* first byte of section */ long no_bytes; /* number of bytes in section */ char first_track; /* track offset for section */ char no_track; /* number of tracks in section */ char sector_code; /* Information about sectors */ char interleave; /* interleave factor */ char secperrot; /* sectors per rotation for track */ u_short skew; /* skew factor */ char side_code; /* 0=side 0, 1=side 1; 2=either side */ } rx3info[NRX3][NSEC] = { 0L, 252928L, 0, 77, 0, 2, 13, 6, 0, 0L, 0L, 0, 0, 0, 1, 0, 0, 0, 0L, 0L, 0, 0, 0, 1, 0, 0, 0, 0L, 252928L, 0, 77, 0, 1, 26, 0, 0 }; struct secinfo { char no_sect; /* number of sectors per cyclinder */ short bytpersec; /* number of bytes per sector */ char density; /* 0=single, 1=double */ short bytpertrk; /* number of bytes per track */ short sect_size; /* coded sector size */ } secinfo[] = { 26, 128, 0, 26*128, 0, /* 26 128 byte sect/trk */ 26, 256, 1, 26*256, 0, 15, 256, 1, 15*256, 2, /* 15 512 byte sectors/track */ 15, 512, 1, 15*512, 2, 8, 512, 1, 8*512, 4, /* 8 512 byte sectors/trakc */ 8, 1024, 1, 8*1024, 4 }; struct rx3stat { char rx3open; /* open/closed status */ short bytect; /* remaining bytes */ char com; /* save current command */ char sec_code; /* pointer to sector data */ caddr_t addr; /* address in memory */ short xmem; /* high order bits of memory */ off_t seek; /* current byte to begin operation */ short uid; /* current user's uid */ } rx3stat[NRX3]; struct rx3errs { short retries; /* number of retries */ short errs; /* number of hard errors */ short errreg; /* Last error register */ short stat1; /* extended status location 1 */ short stat2; /* extended status location 2 */ short stat3; /* extended status location 3 */ short stat4; /* extended status location 4 */ } rx3errs[NRX3]; struct buf rx3tab; /* driver info */ /* * ioctl commands for * rx03 floppy */ #define RX3SET ((('r') << 8) | 2) /* set up parameters */ #define RX3RD ((('r') << 8) | 3) /* read parameters */ #define RX3STAT ((('r') << 8) | 4) /* read status */ #define RX3ERR ((('r') << 8) | 5) /* give error information */ /* * Commands. */ #define XINIT 01 #define XREAD 02 #define XWRITE 04 #define XFILL 010 #define XEMPTY 020 #define XERR 040 /* * States. */ #define NCRC 10 /* number of crc retries */ #define NDEN 2 /* number of density retries */ #ifdef RX3_TIMEOUT int rx3_wticks; /* used to keep track of lost interrupts */ int rx3wstart; int rx3watch(); #endif RX3_TIMEOUT /* * Open drive for use. * */ /*ARGSUSED*/ rx3open(dev, flag) register dev_t dev; { register drv, result; drv = RXUNIT(dev); /* Make sure drive is a valid one */ if (drv >= NRX3) { u.u_error = ENXIO; return; }; #ifdef RX3_TIMEOUT /* Start timing for timeouts. Set status to open */ if (rx3wstart==0) timeout(rx3watch, (caddr_t) 0, TTIME); rx3wstart++; #endif rx3stat[drv].rx3open++; rx3stat[drv].uid = u.u_uid; rx3errs[drv].retries = 0; rx3errs[drv].errs = 0; } /* * Close drive. Simply need to turn off timeouts and * set drive status to closed. */ /*ARGSUSED*/ rx3close(dev, flag) register dev_t dev; { register drv = RXUNIT(dev); #ifdef RX3_TIMEOUT rx3wstart--; #endif RX3_TIMEOUT rx3stat[drv].rx3open--; if (rx3stat[drv].rx3open < 0) rx3stat[drv].rx3open = 0; } rx3strategy(bp) register struct buf *bp; { register opl; int mdev,okay,i; off_t seek; if (bp->b_flags & B_PHYS) mapalloc(bp); /* * Make sure block number is within range. */ okay = 0; mdev = RXUNIT(bp->b_dev); seek = (dbtofsb(bp->b_blkno) << BSHIFT) + bp->b_bcount; for (i=0; i seek) okay = 1; if (!okay) { bp->b_flags |= B_ERROR; iodone(bp); return; }; /* * Link buffer into rx3device queue */ bp->av_forw = (struct buf *) NULL; opl = spl5(); if (rx3tab.b_actf == (struct buf *) NULL) rx3tab.b_actf = bp; else rx3tab.b_actl->av_forw = bp; rx3tab.b_actl = bp; if (rx3tab.b_active == 0) rx3start(); splx(opl); } /* * Start processing command. */ rx3start() { register struct buf *bp; register int mdev; if ((bp = rx3tab.b_actf) == (struct buf *) NULL) return; rx3tab.b_active++; /* * get minor rx3device number from buffer */ mdev = RXUNIT(bp->b_dev); /* * Set up status for current buffer */ rx3stat[mdev].addr = bp->b_un.b_addr; rx3stat[mdev].xmem = bp->b_xmem; rx3stat[mdev].seek = dbtofsb(bp->b_blkno) << BSHIFT; rx3stat[mdev].bytect = bp->b_bcount; /* * if command is read, initiate the command * if command is write, fill the rx3device buffer, * then initiate the write */ if (bp->b_flags & B_READ) rx3io(bp, XREAD); else rx3io(bp, XFILL); } /* * Do actual IO command. */ rx3io(bp, cmd) register struct buf *bp; register short cmd; { register struct rx3device *rx3r; int sect, code, trk, side, drv; rx3r = RX3ADDR; drv = RXUNIT(bp->b_dev); rx3stat[drv].com = cmd; rx3leave(bp,drv,&code,§,&trk,&side); rx3stat[drv].sec_code = code; switch (cmd) { case XINIT: /* Read status */ cmd = RX2_GO|RX2_RDSTAT|RX2_IE|drv<<4; rx3r->rx2cs = cmd; break; case XREAD: /* Read Sector */ cmd = RX2_GO|RX2_RSECT|RX2_IE|(drv<<4)|(secinfo[code].density<<8)| (side<<9); rx3r->rx2cs = cmd; trwait(); rx3r->rx2sa = sect|(secinfo[code].sect_size<<5); trwait(); rx3r->rx2ta = trk; break; case XEMPTY: /* Empty buffer */ /* no disk i/o; unit not needed */ cmd = RX2_GO|RX2_EMPTY|RX2_IE|(side<<9)|(secinfo[code].density<<8)| (drv<<4)|(rx3stat[drv].xmem<<12); rx3r->rx2cs = cmd; trwait(); /* NOT 2's complement */ if (rx3stat[drv].bytect <= secinfo[code].bytpersec) rx3r->rx2wc = rx3stat[drv].bytect>>1; else rx3r->rx2wc = secinfo[code].bytpersec>>1; trwait(); rx3r->rx2ba = (int) rx3stat[drv].addr; break; case XWRITE: /* Write buffer to disk */ cmd = RX2_GO|RX2_WSECT|RX2_IE|(drv<<4)|(secinfo[code].density<<8)| (side<<9); rx3r->rx2cs = cmd; trwait(); rx3r->rx2sa = sect|(secinfo[code].sect_size<<5); trwait(); rx3r->rx2ta = trk; break; case XFILL: /* Fill disk buffer */ /* no disk i/o; unit not needed */ cmd = RX2_GO|RX2_FILL|RX2_IE|(side<<9)|(secinfo[code].density<<8)| (drv<<4)|(rx3stat[drv].xmem<<12); rx3r->rx2cs = cmd; trwait(); /* NOT 2's complement */ if (rx3stat[drv].bytect <= secinfo[code].bytpersec) rx3r->rx2wc = rx3stat[drv].bytect>>1; else rx3r->rx2wc = secinfo[code].bytpersec>>1; trwait(); rx3r->rx2ba = (int) rx3stat[drv].addr; break; case XERR: /* Read extended error status */ cmd = RX2_IE|RX2_RDEC; rx3r->rx2cs = cmd; trwait(); rx3r->rx2ba = (int) &rx3errs[drv].stat1; break; default: panic("rx3io"); break; } } /* * Process interrupt. */ rx3intr() { register struct buf *bp; register struct rx3device *rx3r; int drv, code; long paddr; if (rx3tab.b_active == 0) { printf("rx3: stray interrupt\n"); return; } bp = rx3tab.b_actf; rx3r = RX3ADDR; #ifdef RX3_TIMEOUT rx3_wticks = 0; #endif RX3_TIMEOUT if (rx3r->rx2cs < 0) { rx3err(bp); return; } drv = RXUNIT(bp->b_dev); switch (rx3stat[drv].com) { case XINIT: rx3errs[drv].errreg = rx3r->rx2es; rx3tab.b_active = 0; rx3tab.b_errcnt = 0; rx3stat[drv].bytect = 0; iodone(bp); break; case XREAD: rx3io(bp, XEMPTY); break; case XFILL: rx3io(bp, XWRITE); break; case XWRITE: /* Go on to next sector if should */ case XEMPTY: code = rx3stat[drv].sec_code; if (rx3stat[drv].bytect <= secinfo[code].bytpersec) { rx3stat[drv].bytect = 0; rx3tab.b_errcnt = 0; rx3tab.b_active = 0; rx3tab.b_actf = bp->av_forw; iodone(bp); rx3start(); } else { rx3stat[drv].bytect -= secinfo[code].bytpersec; paddr = (long) rx3stat[drv].addr + (long) secinfo[code].bytpersec; rx3stat[drv].addr = (caddr_t) paddr; rx3stat[drv].xmem = rx3stat[drv].xmem + (int) (paddr>>16); rx3stat[drv].seek += secinfo[code].bytpersec; if (rx3stat[drv].com==XWRITE) rx3stat[drv].com=XFILL; else rx3stat[drv].com=XREAD; rx3io(bp,rx3stat[drv].com); } break; case XERR: break; default: printf("rx3: command %o\n", rx3stat[drv].com); break; } } /* * Handle an error condition. * Crc errors and density errors get retries, * only NDEN for density errors and NCRC for crc errors. * All other errors are considered hard errors. */ rx3err(bp) register struct buf *bp; { register struct rx3device *rx3r; register int drv; register int cmd; drv = minor(bp->b_dev); rx3tab.b_active = 0; rx3r = RX3ADDR; rx3errs[drv].errreg = rx3r->rx2es; /* * Crc error. */ if (rx3r->rx2es & RX2ES_CRC) { rx3errs[drv].retries++; if (rx3tab.b_errcnt < NCRC) { rx3tab.b_errcnt++; rx3reset(); return; } } /* * Density error. */ if (rx3r->rx2es & RX2ES_DENSERR) { rx3errs[drv].retries++; if (rx3tab.b_errcnt < NDEN) { rx3tab.b_errcnt++; rx3reset(); return; } } rx3errs[drv].errs++; bp->b_flags |= B_ERROR; #ifdef UCB_DEVERR harderr(bp, "rx3"); printf("cs=%b er=%b\n", rx3r->rx2cs, RX2_BITS, rx3r->rx2es, RX2ES_BITS); #else deverror(bp, (rx3r->rx2es&0377), (rx3r->rx2cs)); #endif UCB_DEVERR rx3tab.b_active = 0; rx3tab.b_errcnt = 0; rx3tab.b_actf = bp->av_forw; iodone(bp); rx3reset(); } /* * Calculate the physical sector and physical track on the * disk for a given logical sector. * */ rx3leave(bp,drv,code,sect,trk,side) int *code,*sect,*trk,*side; register struct buf *bp; { off_t seek, t0; int t1,t2,t3; int section; /* * Determine track by searching the rx3info table * looking at first_byte and no_bytes. * first_byte <= seek < first_byte + no_bytes */ seek = rx3stat[drv].seek; section = 0; *trk = 0; while (sectionb_flags |= B_ERROR; rx3tab.b_active = 0; iodone(bp); return(1); }; *code = rx3info[drv][section].sector_code; t1 = secinfo[*code].bytpertrk; t2 = t1 * (rx3info[drv][section].side_code==2 ? 2 : 1 ); *trk = seek/t2; /* track offset */ /* * Determine side of disk. Use section code. */ t3 = seek % t2; /* sector offset in track */ if (rx3info[drv][section].side_code==0) *side = 0; else if (rx3info[drv][section].side_code==1) *side = 1; else { if (t3 < t1) *side = 0; else { t3 -= t1; *side = 1; } }; /* * Determine physical sector. */ t1 = t3 / secinfo[*code].bytpersec; /* logical sector */ t1 = t1 % secinfo[*code].no_sect; t2 = t1 / rx3info[drv][section].secperrot; /* logical rotation */ t3 = t1 % rx3info[drv][section].secperrot; /* sector offset */ t3 = t3 * rx3info[drv][section].interleave; t3 = t3 + (rx3info[drv][section].skew * *trk); /* sector count begins with 1 */ *sect = (t3 + t2) % secinfo[*code].no_sect + 1; *trk += rx3info[drv][section].first_track; /* physical track */ return(0); } rx3ioctl(dev, cmd, addr, flag) caddr_t addr; { int drv; register struct rx3device *rx3r; drv = RXUNIT(dev); switch (cmd) { case RX3SET: /* Setup parameters for disk */ if (copyin(addr, (caddr_t)rx3info[drv], sizeof(struct rx3info)*NSEC)) { u.u_error = EFAULT; return; }; break; case RX3RD: /* return disk parameters */ if (copyout((caddr_t)rx3info[drv], addr, sizeof(struct rx3info)*NSEC)) { u.u_error = EFAULT; return; } break; case RX3STAT: break; case RX3ERR: if (copyout( (caddr_t)&rx3errs[drv], addr, sizeof(struct rx3errs))) { u.u_error = EFAULT; return; } break; default: u.u_error = ENOTTY; break; } } /* * reset drives and restart controller. */ rx3reset() { register struct rx3device *rx3r; register int i; register short cmd; rx3r = RX3ADDR; /* * If any drive is in use * then do an init. */ for (i = 0; i < NRX3; i++) { if (rx3stat[i].rx3open) { rx3r->rx2cs = RX2_INIT; while ((rx3r->rx2cs & RX2_DONE) == 0); break; } } rx3start(); } #ifdef RX3_TIMEOUT /* * Wake up every second and if an interrupt is pending * but nothing has happened increment wticks. If nothing * happens for 60 seconds, reset the controller and begin * anew. */ rx3watch() { if (rx3wstart) timeout(rx3watch, (caddr_t) 0, TTIME); if (rx3tab.b_active == 0) { rx3_wticks = 0; /* idling */ return; } rx3_wticks++; if (rx3_wticks >= 60) { rx3_wticks = 0; printf("rx3: lost interrupt\n"); rx3reset(); } } #endif RX3_TIMEOUT #endif NRX3 ult; drv = RXUNIT(dev); /* Make sure drive is a valid one */ if (drv >= NRX3) { u.u_error = ENXIO; return; }; #ifdef RX3_TIMEOUT /* Start timing for timeouts. Set status to open */ if (rx3wstart==0) timeout(rx3watch, (caddr_t) 0, TTIME); rx3wstart++; #endif rx3stasys/OTHERS/GLUE/ 755 0 12 0 4113746365 6332 sys/OTHERS/GLUE/c.c 444 3 12 3654 3771452622 7015 #include "cat.h" #if NCT > 0 int ctopen(), ctclose(), ctwrite(); #else #define ctopen nodev #define ctclose nodev #define ctwrite nodev #endif NCT #include "dn.h" #if NDN > 0 int dnopen(), dnclose(), dnwrite(); #else #define dnopen nodev #define dnclose nodev #define dnwrite nodev #endif NDN #include "rf.h" #if NRF > 0 int rfstrategy(), rfread(), rfwrite(); extern struct buf rftab; #define rfopen nulldev #define rfclose nulldev #define _rftab &rftab #else #define rfopen nodev #define rfclose nodev #define rfstrategy nodev #define rfread nodev #define rfwrite nodev #define _rftab ((struct buf *) NULL) #endif NRF #include "rp.h" #if NRP > 0 int rpstrategy(), rpread(), rpwrite(); extern struct buf rptab; #define rpopen nulldev #define rpclose nulldev #define _rptab &rptab #else #define rpopen nodev #define rpclose nodev #define rpstrategy nodev #define rpread nodev #define rpwrite nodev #define _rptab ((struct buf *) NULL) #endif NRP #include "hs.h" #if NHS > 0 int hsstrategy(), hsread(), hswrite(), hsroot(); extern struct buf hstab; #define _hstab &hstab #define hsopen nulldev #define hsclose nulldev #else #define hsopen nodev #define hsclose nodev #define hsstrategy nodev #define hsread nodev #define hswrite nodev #define hsroot nulldev #define _hstab ((struct buf *) NULL) #endif NHS /* rp = 1 */ rpopen, rpclose, rpstrategy, nulldev, _rptab, /* rf = 2 */ rfopen, rfclose, rfstrategy, nulldev, _rftab, /* hs = 5 */ hsopen, hsclose, hsstrategy, hsroot, _hstab, /* dn = 7 */ dnopen, dnclose, nodev, dnwrite, nodev, nulldev, 0, SELECT(nodev) /* rf = 10 */ rfopen, rfclose, rfread, rfwrite, nodev, nulldev, 0, SELECT(seltrue) /* rp = 11 */ rpopen, rpclose, rpread, rpwrite, nodev, nulldev, 0, SELECT(seltrue) /* hs = 13 */ hsopen, hsclose, hsread, hswrite, nodev, nulldev, 0, SELECT(seltrue) /* ct = 27 */ ctopen, ctclose, nodev, ctwrite, nodev, nodev, 0, SELECT(seltrue) rx3wstart==0) timeout(rx3watch, (caddr_t) 0, TTIME); rx3wstart++; #endif rx3stasys/OTHERS/GLUE/l.s 444 3 12 2456 3771454413 7045 #if NRF > 0 /* RF-11 */ .globl _rfintr rfio: jsr r0,call; jmp _rfintr #endif #if NRF > 0 /* RF-11 */ . = ZERO+204 rfio; br5 #endif ================================================================= #if NRP > 0 /* RP03 */ .globl _rpintr rpio: jsr r0,call; jmp _rpintr #endif #if NRP > 0 /* RP03 */ . = ZERO+254 rpio; br5 #endif ================================================================= #if NDVHP > 0 /* Diva Comp V */ .globl _dvhpintr dvhpio: jsr r0,call; jmp _dvhpintr #endif #if NDVHP > 0 /* Diva Comp V */ . = ZERO+254 dvhpio; br 5 #endif ================================================================= #if NCAT > 0 /* GP DR11C driver used for C/A/T */ .globl _ctintr ctio: jsr r0,call; jmp _ctintr #endif ================================================================= #if NDN > 0 /* DN-11 ACU */ .globl _dnint dnou: jsr r0,call; jmp _dnint #endif ================================================================= #if NHS > 0 /* RS03/04 */ .globl _hsintr hsio: jsr r0,call; jmp _hsintr #endif ================================================================= #if NDM > 0 /* DM */ .globl _dmintr dmin: jsr r0,call; jmp _dmintr #endif ================================================================= #if NRF > 0 /* RF-11 */ .globl _rfintr rfio: jsr r0,call; jmp _rfintr #endif ) #endif NHS /* rp = 1 */ rpopen, rpclose, rpstrategy, nulldev, _rptab, /* rf = 2 */ rfopen, rfclose, rfstrategy, nulldev, _rftab, /* hs = 5 */ hsopen, hsclose, hsstrategy, hsroot, _hstab, /* dn = 7 *sys/OTHERS/GLUE/uprobe.c 444 3 12 330 3772577723 10046 int dnprobe(), caryprobe(), hsprobe(), rpprobe(); "cary", caryprobe, /* cary -- Cary 118c Spectrophotometer */ "dn", dnprobe, /* dn -- DN11 ACU */ "hs", hsprobe, /* hs -- rs03/04 */ "rp", rpprobe, /* rp -- rp03 */ sys/OTHERS/ht/ 755 0 12 0 5325716402 6204 sys/OTHERS/ht/ht.c 444 3 12 24141 5321515340 7065 /* * TJU77/TWU77/TJE16/TWE16 tape driver */ /* * SCCS id @(#)ht.c 2.2 (2.11BSD GTE) 1/2/93 * Eric Haag's Driver * I received this from Eric when I first got 2.9 up * (Oct 84) and have recently sent it to Steve Malone * both Steve & I have Massbus (RH70) tapes */ #include "ht.h" #if NHT > 0 #include "param.h" #include #include #include #include #include #include #include #ifdef HT_IOCTL #include #endif struct buf httab; struct buf chtbuf; struct htdevice *HTADDR; #define INF 32760 struct softc { char sc_openf; char sc_lastiow; daddr_t sc_blkno; daddr_t sc_nxrec; u_short sc_erreg; u_short sc_fsreg; #ifdef HT_IOCTL short sc_resid; #endif } tu_softc[NHT]; #define SIO 1 #define SSFOR 2 #define SSREV 3 #define SRETRY 4 #define SCOM 5 #define SOK 6 #define TUUNIT(dev) (minor(dev) & 077) /* bits in minor device */ #define H_800BPI 0100 #define H_NOREWIND 0200 htattach(addr, unit) register struct htdevice *addr; { if (unit >= NHT) return(0); if ((addr != (struct htdevice *) NULL) && (fioword(addr) != -1)) { HTADDR = addr; if (fioword(&(addr->htbae)) != -1) httab.b_flags |= B_RH70; return(1); } HTADDR = (struct hpdevice *) NULL; return(0); } htopen(dev, flag) dev_t dev; { register ds; register htunit = TUUNIT(dev); register struct tu_softc *sc = &tu_softc[htunit]; httab.b_flags |= B_TAPE; if (HTADDR == (struct htdevice *) NULL || htunit >= NHT) { u.u_error = ENXIO; return; } else if (sc->sc_openf) { u.u_error = EBUSY; return; } sc->sc_blkno = (daddr_t) 0; sc->sc_nxrec = (daddr_t) INF; sc->sc_lastiow = 0; ds = htcommand(dev, HT_SENSE, 1); if ((ds & HTFS_MOL) == 0) { uprintf("tu%d: not online\n", htunit); u.u_error = EIO; return; } if ((flag & FWRITE) && (ds & HTFS_WRL)) { uprintf("tu%d: no write ring\n", htunit); u.u_error = EIO; return; } if (u.u_error == 0) sc->sc_openf++; } htclose(dev, flag) dev_t dev; { register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; if (flag == FWRITE || ((flag & FWRITE) && sc->sc_lastiow)) { htcommand(dev, HT_WEOF, 1); htcommand(dev, HT_WEOF, 1); htcommand(dev, HT_SREV, 1); } if ((minor(dev) & H_NOREWIND) == 0) htcommand(dev, HT_REW, 1); sc->sc_openf = 0; } /*ARGSUSED*/ htcommand(dev, com, count) unsigned count; dev_t dev; { register s; register struct buf *bp; bp = &chtbuf; s = spl5(); while(bp->b_flags & B_BUSY) { #ifndef SLU70 /* * This special check is because B_BUSY never * gets cleared in the non-waiting rewind case. */ if (bp->b_repcnt == 0 && (bp->b_flags & B_DONE)) break; #endif bp->b_flags |= B_WANTED; sleep((caddr_t) bp, PRIBIO); } bp->b_flags = B_BUSY | B_READ; splx(s); bp->b_dev = dev; #ifdef HT_IOCTL if (com == HT_SFORW || com == HT_SREV) bp->b_repcnt = count; #endif bp->b_command = com; bp->b_blkno = (daddr_t) 0; htstrategy(bp); #ifndef SLU70 /* * In case of rewind from close, don't wait. * This is the only case where count can be 0. */ if (count == 0) return(0); #endif iowait(bp); if(bp->b_flags & B_WANTED) wakeup((caddr_t)bp); bp->b_flags &= B_ERROR; return (bp->b_resid); } htstrategy(bp) register struct buf *bp; { int s; register daddr_t *p; register struct tu_softc *sc = &tu_softc[TUUNIT(bp->b_dev)]; /* This is almost certainly not in the right place and more work needs * to be done in htstart(). See /sys/pdpuba/ht.c */ if (bp->b_flags & B_PHYS) { sc->sc_blkno = sc->sc_nxrec = dbtofsb(bp->b_blkno); sc->sc_nxrec++; } if(bp != &chtbuf) { if ((httab.b_flags & B_RH70) == 0) mapalloc(bp); p = &sc->sc_nxrec; if(dbtofsb(bp->b_blkno) > *p) { bp->b_flags |= B_ERROR; bp->b_error = ENXIO; iodone(bp); return; } if(dbtofsb(bp->b_blkno) == *p && bp->b_flags & B_READ) { bp->b_resid = bp->b_bcount; iodone(bp); return; } if ((bp->b_flags & B_READ) == 0) { *p = dbtofsb(bp->b_blkno) + 1; sc->sc_lastiow = 1; } } bp->av_forw = NULL; s = spl5(); if (httab.b_actf == NULL) httab.b_actf = bp; else httab.b_actl->av_forw = bp; httab.b_actl = bp; if (httab.b_active == 0) htstart(); splx(s); } htstart() { register struct buf *bp; register den; int htunit; daddr_t blkno; register struct softc *sc; loop: if ((bp = httab.b_actf) == NULL) return; htunit = minor(bp->b_dev) & 0177; sc = &tu_softc[TUUNIT(bp->b_dev)]; sc->sc_erreg = HTADDR->hter; sc->sc_fsreg = HTADDR->htfs; #ifdef HT_IOCTL sc->sc_resid = HTADDR->htfc; #endif HTADDR->htcs2 = ((htunit >> 3) & 07); den = HTTC_1600BPI | HTTC_PDP11 | (htunit & 07); if (htunit & H_800BPI) den = HTTC_800BPI | HTTC_PDP11 | (htunit & 07); if ((HTADDR->httc & 03777) != den) HTADDR->httc = den; if (HTADDR->htcs2 & HTCS2_NEF || (HTADDR->htfs & HTFS_MOL) == 0) goto abort; htunit &= 077; blkno = sc->sc_blkno; if (bp == &chtbuf) { if (bp->b_command == HT_SENSE) { bp->b_resid = HTADDR->htfs; goto next; } httab.b_active = SCOM; #ifdef HT_IOCTL HTADDR->htfc = -bp->b_bcount; #else HTADDR->htfc = 0; #endif HTADDR->htcs1 = bp->b_command | HT_IE | HT_GO; return; } if (sc->sc_openf < 0 || dbtofsb(bp->b_blkno) > sc->sc_nxrec) goto abort; if (blkno == dbtofsb(bp->b_blkno)) { httab.b_active = SIO; HTADDR->htba = bp->b_un.b_addr; if(httab.b_flags & B_RH70) HTADDR->htbae = bp->b_xmem; HTADDR->htfc = -bp->b_bcount; HTADDR->htwc = -(bp->b_bcount >> 1); den = ((bp->b_xmem & 3) << 8) | HT_IE | HT_GO; if(bp->b_flags & B_READ) den |= HT_RCOM; else { if(HTADDR->htfs & HTFS_EOT) { bp->b_resid = bp->b_bcount; goto next; } den |= HT_WCOM; } HTADDR->htcs1 = den; } else { if (blkno < dbtofsb(bp->b_blkno)) { httab.b_active = SSFOR; HTADDR->htfc = blkno - dbtofsb(bp->b_blkno); HTADDR->htcs1 = HT_SFORW | HT_IE | HT_GO; } else { httab.b_active = SSREV; HTADDR->htfc = dbtofsb(bp->b_blkno) - blkno; HTADDR->htcs1 = HT_SREV | HT_IE | HT_GO; } } return; abort: bp->b_flags |= B_ERROR; next: httab.b_actf = bp->av_forw; iodone(bp); goto loop; } htintr() { register struct buf *bp; register state; int err, htunit; register struct softc *sc; if ((bp = httab.b_actf) == NULL) return; htunit = TUUNIT(bp->b_dev); state = httab.b_active; httab.b_active = 0; sc = &tu_softc[htunit]; sc->sc_erreg = HTADDR->hter; sc->sc_fsreg = HTADDR->htfs; #ifdef HT_IOCTL sc->sc_resid = HTADDR->htfc; #endif if (HTADDR->htcs1 & HT_TRE) { err = HTADDR->hter; if (HTADDR->htcs2 & HTCS2_ERR || (err & HTER_HARD)) state = 0; if (bp->b_flags & B_PHYS) err &= ~HTER_FCE; if ((bp->b_flags & B_READ) && (HTADDR->htfs & HTFS_PES)) err &= ~(HTER_CSITM | HTER_CORCRC); if ((HTADDR->htfs & HTFS_MOL) == 0) { if(sc->sc_openf) sc->sc_openf = -1; } else if (HTADDR->htfs & HTFS_TM) { HTADDR->htwc = -(bp->b_bcount >> 1); sc->sc_nxrec = dbtofsb(bp->b_blkno); state = SOK; } else if (state && err == 0) state = SOK; if (httab.b_errcnt > 6) #ifdef UCB_DEVERR printf("tu%d: hard error bn %D er=%b ds=%b\n", htunit, bp->b_blkno, sc->sc_erreg, HTER_BITS, sc->sc_fsreg, HTFS_BITS); #else deverror(bp, sc->sc_erreg, sc->sc_fsreg); #endif htinit(); if (state == SIO && ++httab.b_errcnt < 10) { httab.b_active = SRETRY; sc->sc_blkno++; HTADDR->htfc = -1; HTADDR->htcs1 = HT_SREV | HT_IE | HT_GO; return; } if (state != SOK) { bp->b_flags |= B_ERROR; state = SIO; } } else if (HTADDR->htcs1 & HT_SC) if(HTADDR->htfs & HTFS_ERR) htinit(); switch (state) { case SIO: case SOK: sc->sc_blkno++; case SCOM: httab.b_errcnt = 0; httab.b_actf = bp->av_forw; iodone(bp); bp->b_resid = -(HTADDR->htwc << 1); break; case SRETRY: if((bp->b_flags & B_READ) == 0) { httab.b_active = SSFOR; HTADDR->htcs1 = HT_ERASE | HT_IE | HT_GO; return; } case SSFOR: case SSREV: if(HTADDR->htfs & HTFS_TM) { if(state == SSREV) { sc->sc_nxrec = dbtofsb(bp->b_blkno) - HTADDR->htfc; sc->sc_blkno = sc->sc_nxrec; } else { sc->sc_nxrec = dbtofsb(bp->b_blkno) + HTADDR->htfc - 1; sc->sc_blkno = sc->sc_nxrec + 1; } } else sc->sc_blkno = dbtofsb(bp->b_blkno); break; default: return; } htstart(); } htinit() { register ocs2; register omttc; omttc = HTADDR->httc & 03777; /* preserve old slave select, dens, format */ ocs2 = HTADDR->htcs2 & 07; /* preserve old unit */ HTADDR->htcs2 = HTCS2_CLR; HTADDR->htcs2 = ocs2; HTADDR->httc = omttc; HTADDR->htcs1 = HT_DCLR | HT_GO; } #ifdef HT_IOCTL /*ARGSUSED*/ htioctl(dev, cmd, addr, flag) dev_t dev; caddr_t addr; { register struct buf *bp = &chtbuf; register struct softc *sc = &tu_softc[TUUNIT(dev)]; register callcount; int fcount; struct mtop mtop; struct mtget mtget; /* we depend on the values and order of the MT codes here */ static htops[] = {HT_WEOF, HT_SFORW, HT_SREV, HT_SFORW, HT_SREV, HT_REW, HT_REWOFFL, HT_SENSE}; switch (cmd) { case MTIOCTOP: if (copyin(addr, (caddr_t) &mtop, sizeof(mtop))) { u.u_error = EFAULT; return; } switch(mtop.mt_op) { case MTWEOF: callcount = mtop.mt_count; fcount = 1; break; case MTFSF: case MTBSF: callcount = mtop.mt_count; fcount = INF; break; case MTFSR: case MTBSR: callcount = 1; fcount = mtop.mt_count; break; case MTREW: case MTOFFL: case MTNOP: callcount = 1; fcount = 1; break; default: u.u_error = ENXIO; return; } if (callcount <= 0 || fcount <= 0) { u.u_error = ENXIO; return; } while (--callcount >= 0) { htcommand(dev, htops[mtop.mt_op], fcount); if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) && bp->b_resid) { u.u_error = EIO; break; } if ((bp->b_flags & B_ERROR) || sc->sc_fsreg & HTFS_BOT) break; } geterror(bp); return; case MTIOCGET: mtget.mt_erreg = sc->sc_erreg; mtget.mt_dsreg = sc->sc_fsreg; mtget.mt_resid = sc->sc_resid; mtget.mt_type = MT_ISHT; if (copyout((caddr_t) &mtget, addr, sizeof(mtget))) u.u_error = EFAULT; return; default: u.u_error = ENXIO; } } #endif HT_IOCTL #endif NHT section++; } } if (!*trk) { bp->b_flags |= B_ERROR; rx3tab.b_active = 0; iodone(bp); return(1); }; *code = rx3info[drv][section].sector_code; t1 = secinfo[*code].bytpertrk; t2 = t1 * (rx3info[drv][section].side_code==2 ? 2 : 1 ); *trk = seek/t2; /* track offset */ /* * Determine side of disk. Use section code. */ t3 = seek % t2; /* sector offset in track */ if (rx3info[drvsys/OTHERS/ht/ht_fix 444 3 12 3007 4056737520 7502 From wucs!root Sat Mar 8 07:50:44 1986 Date: Fri, 7 Mar 86 14:53:51 est From: adiron!root (AdironVax) To: wucs!seismo!keith Subject: ht.c Keith - after some studying of the driver I think we have found the problem. The minor device numbers in the /dev/MAKE script are incorrect and cause the wrong unit to be selected. The driver seems to be working fine. However it is noted in the source that ht.c only supports one controller. Therfore it looks like one should never set NHT to be > 1. The MAKE script does the following: WRONG RIGHT name major minor minor mt0 9 0 0 unit0 mt1 9 64 64 unit0 mt2 9 2 1 unit1 mt3 9 66 65 unit1 nmt0 9 128 128 unit0 nmt1 9 192 192 unit0 nmt2 9 130 129 unit1 nmt3 9 194 193 unit1 .. and similar permutations for rmt_ and nrmt_ (major = 17). The change to MAKE seems simple enough: ht*|ut*) umask 0 ; unit=`expr $i : '..\(.*\)'` case $i in ut*) blk=3; chr=12;; ht*) blk=9; chr=17;; esac case $unit in 0|1|2|3|4|5|6|7) name=`expr $unit '*' 2` ; one=`expr $name + 1` norew=`expr $unit + 128` ; hidens=`expr $unit + 64` norewhidens=`expr $unit + 192` /etc/mknod mt$name b $blk $unit /etc/mknod mt$one b $blk $hidens /etc/mknod nmt$name b $blk $norew /etc/mknod nmt$one b $blk $norewhidens /etc/mknod rmt$name c $chr $unit /etc/mknod rmt$one c $chr $hidens /etc/mknod nrmt$name c $chr $norew /etc/mknod nrmt$one c $chr $norewhidens umask 77 ;; *) echo bad unit for tape in: $1 ;; esac ;; It is nice to be sending you a fix for a change - tish cleared in the non-waiting rewind case. */ if (bp->b_repcnt == 0 && (bp->b_flags & B_DONE)) break; #endif bp->b_flags |= B_WANTED; sleep((caddr_t) bp, PRIBIO); } bp->b_flags = B_BUSY | B_READ; splx(s); bp->b_dev = dev; #ifdef HT_IOCTL if (com == HT_SFORW || com == HT_SREV) bp->b_repcnt = count; #endif bp->b_command = com; bp->b_blkno = (daddr_t) 0; htstrategy(bp); #ifndef SLU70 /* * In case of rewind from close, don't wait. * This is the only case where count can be 0. */sys/OTHERS/ung_bass_dr11w/ 755 0 12 0 3776021655 10417 sys/OTHERS/ung_bass_dr11w/if_un.c 444 3 12 30444 3775415071 11774 /* if_un.c 4.19 82/06/23 */ /* * Ungermann-Bass network/DR11-W interface driver */ #include "un.h" #if NUN > 0 #include "param.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "protosw.h" #include "socket.h" #include "pdpuba/ubavar.h" #ifdef notdef #include "unreg.h" #endif notdef #include #include #include #include #include #include #include #include #include #define UNMTU (600-sizeof (struct un_header)) #define US_NULL 0 /* not doing anything state */ #define US_IDLE 1 /* waiting to transfer state */ #define US_READ 2 /* reading state */ #define US_WRITE 3 /* writing state */ #define US_RESET 4 /* waiting for reset state */ int unprobe(), unattach(), unintr(); struct uba_device *uninfo[NUN]; u_short unstd[] = { 0 }; struct uba_driver undriver = { unprobe, 0, unattach, 0, unstd, "un", uninfo }; #define UNUNIT(dev) (minor(dev)) int uninit(), unoutput(), unreset(); int unrestart(); /* * Ungermann-Bass software status per interface. * * Each interface is referenced by a network interface structure, * us_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, * etc. We also have, for each interface, a UBA interface structure, which * contains information about the UNIBUS resources held by the interface: * map registers, buffered data paths, etc. Information is cached in this * structure for use by the if_uba.c routines in running the interface * efficiently. */ struct un_softc { struct ifnet us_if; /* network-visible interface */ struct ifuba us_ifuba; /* UNIBUS resources */ short us_state; /* device state */ short us_errcnt; /* number of errors since time set */ short us_restart; /* restart interval */ u_char us_maxtime; /* interval for error counting */ u_char us_maxerr; /* errors allowed in interval */ time_t us_errtime; /* time for error counting */ } un_softc[NUN]; /* * Cause an interrupt to determine interface presence and * interrupt vector. */ unprobe(reg) caddr_t reg; { register int br, cvec; /* r11, r10 value-result */ register struct undevice *addr = (struct undevice *)reg; #ifdef lint br = 0; cvec = br; br = cvec; unintr(0); #endif addr->csr = IE|UNRESET; addr->csr = IE|UNRESET|GO; DELAY(100000); addr->csr = 0; #ifdef ECHACK br = 0x16; #endif return (1); } /* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */ unattach(ui) struct uba_device *ui; { register struct un_softc *us = &un_softc[ui->ui_unit]; struct sockaddr_in *sin; us->us_if.if_unit = ui->ui_unit; us->us_if.if_name = "un"; us->us_if.if_mtu = UNMTU; us->us_if.if_net = ui->ui_flags; sin = (struct sockaddr_in *)&us->us_if.if_addr; sin->sin_family = AF_INET; /* host number will be filled in later. */ sin->sin_addr = if_makeaddr(us->us_if.if_net, 0); sin = (struct sockaddr_in *)&us->us_if.if_broadaddr; sin->sin_family = AF_INET; sin->sin_addr = if_makeaddr(us->us_if.if_net, INADDR_ANY); us->us_if.if_flags |= IFF_BROADCAST; us->us_if.if_init = uninit; us->us_if.if_output = unoutput; us->us_if.if_ubareset = unreset; us->us_if.if_watchdog = unrestart; us->us_maxtime = 3; us->us_maxerr = 10; us->us_restart = 5 * 60 * HZ; us->us_ifuba.ifu_flags = UBA_CANTWAIT; #ifdef notdef us->us_ifuba.ifu_flags |= UBA_NEEDBDP; #endif if_attach(&us->us_if); } /* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */ unreset(unit, uban) int unit, uban; { register struct uba_device *ui; if (unit >= NUN || (ui = uninfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" un%d", unit); uninit(unit); } /* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */ uninit(unit) int unit; { register struct un_softc *us = &un_softc[unit]; register struct uba_device *ui = uninfo[unit]; register struct undevice *addr; int s; if (if_ubainit(&us->us_ifuba, ui->ui_ubanum, sizeof (struct un_header), (int)btoc(UNMTU)) == 0) { printf("un%d: can't initialize\n", unit); us->us_if.if_flags &= ~IFF_UP; return; } us->us_errcnt = 0; us->us_errtime = time; unwhoami(unit); /* * Reset U-B interface, thus causing an interrupt which * will start things going. */ addr = (struct undevice *)ui->ui_addr; s = splimp(); addr->csr = IE|UNRESET; addr->csr = IE|UNRESET|GO; us->us_state = US_RESET; splx(s); } /* * Try to start a write operation. * If interface is busy, it must be in idle state, so issue a reset. * Otherwise, get the datagram from the output queue, map it onto * the UNIBUS, and start the write. This routine should not be * called if the output queue is empty. */ unstart(dev) dev_t dev; { int unit = UNUNIT(dev); struct uba_device *ui = uninfo[unit]; register struct un_softc *us = &un_softc[unit]; register struct undevice *addr = (struct undevice *)ui->ui_addr; struct mbuf *m; int dataaddr, datalen; register short cmdcsr; if (us->us_state != US_NULL) { addr->csr = IE|UNRESET; addr->csr = IE|UNRESET|GO; us->us_state = US_RESET; } else { IF_DEQUEUE(&us->us_if.if_snd, m); if (m == 0) return; us->us_state = US_WRITE; datalen = if_wubaput(&us->us_ifuba, m); if (us->us_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(us->us_ifuba.ifu_uba, us->us_ifuba.ifu_w.ifrw_bdp); dataaddr = us->us_ifuba.ifu_w.ifrw_info; addr->bar = dataaddr & 0xffff; addr->wcr = -(((datalen + 1) >> 1) + 1); cmdcsr = ((dataaddr >> 12) & 0x30) | IE | UNOUT; addr->csr = cmdcsr; addr->csr = cmdcsr | GO; } } /* * Ungermann-Bass interface interrupt handler. * Determines reason for interrupt and acts accordingly. */ unintr(unit) int unit; { register struct un_softc *us = &un_softc[unit]; struct undevice *addr = (struct undevice *)uninfo[unit]->ui_addr; register struct un_header *un; struct mbuf *m; int len; register struct ifqueue *inq; int cmdcsr; if ((addr->dar & RESETACK) && us->us_state != US_RESET) { if ((us->us_if.if_flags & IFF_UP) == 0) return; printf("un%d: unexpected reset\n", unit); unerror(unit); } switch (us->us_state) { case US_NULL: printf("un%d: stray interrupt\n", unit); break; case US_RESET: if (!(addr->dar & RESETACK)) { addr->csr = IE|UNRESET; addr->csr = IE|UNRESET|GO; return; } break; case US_IDLE: break; case US_READ: us->us_if.if_ipackets++; if (us->us_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(us->us_ifuba.ifu_uba, us->us_ifuba.ifu_r.ifrw_bdp); if (addr->csr & STATA) { if ((us->us_if.if_flags & IFF_UP) == 0) return; printf("un%d: input error csr=%b\n", unit, addr->csr&0xffff, UNBITS); us->us_if.if_ierrors++; unerror(unit); break; } un = (struct un_header *)(us->us_ifuba.ifu_r.ifrw_addr); switch (un->un_ptype) { #ifdef INET case UNTYPE_IP: len = htons((u_short)((struct ip *) (un+1))->ip_len); schednetisr(NETISR_IP); inq = &ipintrq; break; #endif case UNTYPE_INQUIRE: { struct sockaddr_in *sin; us->us_if.if_host[0] = un->un_dport << 16 | htons(un->un_dniu); sin = (struct sockaddr_in *)&us->us_if.if_addr; sin->sin_addr = if_makeaddr(us->us_if.if_net, us->us_if.if_host[0]); us->us_if.if_flags |= IFF_UP; if_rtinit(&us->us_if, RTF_UP); goto setup; } default: printf("un%d: bad packet type %d\n", un->un_ptype); goto setup; } m = if_rubaget(&us->us_ifuba, len, 0); if (m != 0) if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); } else IF_ENQUEUE(inq, m); break; case US_WRITE: us->us_if.if_opackets++; if (addr->csr & STATA) { if ((us->us_if.if_flags & IFF_UP) == 0) return; printf("un%d: output error csr=%b\n", unit, addr->csr, UNBITS); us->us_if.if_oerrors++; unerror(unit); } if (us->us_ifuba.ifu_xtofree) { m_freem(us->us_ifuba.ifu_xtofree); us->us_ifuba.ifu_xtofree = 0; } break; default: printf("un%d: invalid state %d csr=%b\n", us->us_state, addr->csr, UNBITS); } setup: us->us_state = US_NULL; if (addr->csr & STATB) { us->us_state = US_READ; addr->wcr = -((sizeof (struct un_header) + UNMTU + 1)/2+1); addr->bar = us->us_ifuba.ifu_r.ifrw_info & 0xffff; cmdcsr = ((us->us_ifuba.ifu_r.ifrw_info >> 12) & 0x30); cmdcsr |= IE|UNRDDG; addr->csr = cmdcsr; addr->csr = cmdcsr | GO; } else if (us->us_if.if_snd.ifq_head != 0 && (addr->csr & STATC)) unstart(unit); if (us->us_state == US_NULL) { us->us_state = US_IDLE; addr->csr = IE|UNIDLE; addr->csr = IE|UNIDLE|GO; } } /* * Ungermann-Bass output routine. * Encapsulate a packet destined for dst for the local net. */ unoutput(ifp, m0, dst) struct ifnet *ifp; struct mbuf *m0; struct sockaddr *dst; { int type, destniu, destport, len; register struct mbuf *m = m0; register struct un_header *un; register struct un_softc *us = &un_softc[ifp->if_unit]; int s; if ((us->us_if.if_flags & IFF_UP) == 0) return (ENETDOWN); switch (dst->sa_family) { #ifdef INET case AF_INET: { struct sockaddr_in *sin = (struct sockaddr_in *)dst; struct ip *ip = mtod(m, struct ip *); if (sin->sin_addr.s_addr & 0xffffff00) { destniu = sin->sin_addr.s_addr >> 24; destport = (sin->sin_addr.s_addr >> 8) & 0xff; } else { destniu = 0xffff; destport = 0xff; } len = htons((u_short) ip->ip_len); type = UNTYPE_IP; break; } #endif default: printf("un%d: can't handle af%d\n", ifp->if_unit, dst->sa_family); m_freem(m0); return (EAFNOSUPPORT); } /* * Add local net header. If no space in first mbuf, * allocate another. */ if (m->m_off > MMAXOFF || MMINOFF + sizeof (struct un_header) > m->m_off) { m = m_get(M_DONTWAIT); if (m == 0) { m_freem(m0); return (ENOBUFS); } m->m_next = m0; m->m_off = MMINOFF; m->m_len = sizeof (struct un_header); } else { m->m_off -= sizeof (struct un_header); m->m_len += sizeof (struct un_header); } un = mtod(m, struct un_header *); bzero((caddr_t)un, sizeof (struct un_header)); un->un_length = htons((u_short)(len + sizeof (struct un_header))); un->un_dniu = htons((u_short)destniu); un->un_dport = destport; un->un_dtype = 5; un->un_sniu = htons((u_short)(ifp->if_host[0] >> 24)); un->un_sport = (ifp->if_host[0] >> 8) & 0xff; un->un_stype = 5; un->un_ptype = type; /* * Queue message on interface, and start output if interface * not yet active. */ s = splimp(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); m_freem(m); splx(s); return (ENOBUFS); } IF_ENQUEUE(&ifp->if_snd, m); if (us->us_state == US_IDLE) unstart(ifp->if_unit); splx(s); return (0); } /* * U-B error handler, if maxerr errors have occured * in maxtime seconds, disable the interface. */ unerror(unit) int unit; { register struct un_softc *us = &un_softc[unit]; struct undevice *addr = (struct undevice *)uninfo[unit]->ui_addr; if (time - us->us_errtime > us->us_maxtime) { us->us_errtime = time; us->us_errcnt = 1; } else if (++us->us_errcnt >= us->us_maxerr) { printf("un%d: error limit exceeded\n", unit); us->us_if.if_flags &= ~IFF_UP; addr->csr = 0; us->us_if.if_timer = us->us_restart; } } unrestart(unit) int unit; { register struct un_softc *us = &un_softc[unit]; struct undevice *addr = (struct undevice *)uninfo[unit]->ui_addr; int s; us->us_if.if_flags |= IFF_UP; printf("un%d: restarting\n", unit); unwhoami(unit); s = splimp(); addr->csr = IE|UNRESET; addr->csr = IE|UNRESET|GO; us->us_state = US_RESET; splx(s); } /* * Send a "Who am I?" message to the interface. * Interface should respond with an copy of the * packet with its real address filled in. The * message is placed at the head of the output queue. * An interface reset should be done next to start * things rolling. */ unwhoami(unit) int unit; { register struct mbuf *m; register struct un_softc *us = &un_softc[unit]; register struct un_header *un; int s; if ((m = m_get(M_DONTWAIT)) == 0) return; m->m_off = MMINOFF; m->m_len = sizeof(struct un_header); un = mtod(m, struct un_header *); bzero((caddr_t)un, sizeof (struct un_header)); un->un_length = htons(sizeof (struct un_header)); un->un_dtype = un->un_stype = 5; un->un_ptype = UNTYPE_INQUIRE; s = splimp(); IF_PREPEND(&us->us_if.if_snd, m); splx(s); } #endif NUN return; us->us_state = US_WRITE; datalen = if_wubaput(&us->us_ifuba, m); if (us->us_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(us->us_ifuba.ifu_uba, us->us_ifuba.ifu_w.ifrw_bdp); dataaddr = us->us_ifuba.isys/OTHERS/ra/ 755 0 12 0 4056740220 6166 sys/OTHERS/ra/stand.ra.c 444 3 12 7315 4056737723 10156 /* * Copyright (c) 1982 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * RAxx disk device driver * RQDX1 (rx50,rd50,rd51,rd52,rd53) */ #include #include #ifndef u_char #define u_char char #endif #include #include #include "../saio.h" /* * RA Communications Area */ struct rdca { short ca_xxx1; /* unused */ char ca_xxx2; /* unused */ char ca_bdp; /* BDP to purge */ short ca_cmdint; /* command queue transition interrupt flag */ short ca_rspint; /* response queue transition interrupt flag */ short ca_rspl; /* response descriptors */ short ca_rsph; short ca_cmdl; /* command descriptors */ short ca_cmdh; }; #define ca_ringbase ca_rspl #define RA_OWN 0x8000 /* RQ owns this descriptor */ #define RA_INT 0x4000 /* allow interrupt on ring transition */ static struct radevice *RDADDR = ((struct radevice *)0172150); static struct ra { struct rdca ra_ca; struct mscp ra_rsp; struct mscp ra_cmd; } rd; struct mscp *racmd(); static int rdinit; static long rdonline[8]; static int rd_boff[] = { 0, 5868, 0, 8468, -1, -1, -1, -1 }; raopen(io) register struct iob *io; { register struct mscp *mp; int i; if( rdinit == 0 ) { RDADDR->raip = 0; while((RDADDR->rasa & RA_STEP1) == 0); RDADDR->rasa = RA_ERR; while((RDADDR->rasa & RA_STEP2) == 0); RDADDR->rasa = (short)&rd.ra_ca.ca_ringbase; while((RDADDR->rasa & RA_STEP3) == 0); RDADDR->rasa = (short)(segflag & 3); while((RDADDR->rasa & RA_STEP4) == 0); RDADDR->rasa = RA_GO; rd.ra_ca.ca_rspl = (short)&rd.ra_rsp.m_cmdref; rd.ra_ca.ca_rsph = (short)(segflag & 3); rd.ra_ca.ca_cmdl = (short)&rd.ra_cmd.m_cmdref; rd.ra_ca.ca_cmdh = (short)(segflag & 3); rd.ra_cmd.m_cntflgs = 0; if( racmd(M_O_STCON, io->i_unit) < 0 ) { printf("RD: controller init error, STCON\n"); return(-1); } rdinit = 1; } if( rdonline[io->i_unit & 7] == 0 ) if( ramount(io) == -1 ) return(-1); if( (io->i_boff < 0) || (io->i_boff > 7) || (rd_boff[io->i_boff] == -1) ) { printf("RD: bad partition for unit=%d",io->i_unit & 7); } io->i_boff = rd_boff[io->i_boff]; return(0); } raclose(io) register struct iob *io; { rdonline[io->i_unit & 7] = 0; return(0); } ramount(io) register struct iob *io; { if( racmd(M_O_ONLIN,io->i_unit) < 0 ) { printf("RD: bring online error, unit=%d\n",io->i_unit & 7); return(-1); } rdonline[io->i_unit & 7] = rd.ra_rsp.m_uslow + ((long)(rd.ra_rsp.m_ushigh) << 16); return(0); } struct mscp * racmd(op,unit) int op,unit; { register struct mscp *mp; register int i; rd.ra_cmd.m_opcode = op; rd.ra_cmd.m_unit = unit & 7; rd.ra_rsp.m_header.ra_msglen = sizeof(struct mscp); rd.ra_cmd.m_header.ra_msglen = sizeof(struct mscp); rd.ra_ca.ca_rsph = RA_OWN | (segflag & 3); rd.ra_ca.ca_cmdh = RA_OWN | (segflag & 3); i = RDADDR->raip; while ((rd.ra_ca.ca_cmdh & RA_INT) == 0) ; while ((rd.ra_ca.ca_rsph & RA_INT) == 0) ; rd.ra_ca.ca_rspint = 0; rd.ra_ca.ca_cmdint = 0; mp = &rd.ra_rsp; if( ((mp->m_opcode & 0xff) != (op | M_O_END)) || ((mp->m_status & M_S_MASK) != M_S_SUCC) ) { printf("RD: command error, unit=%d, opcode=%x, status=%x\n", unit & 7, mp->m_opcode & 0xff, mp->m_status); return(-1); } return(0); } rastrategy(io, func) register struct iob *io; { register struct mscp *mp; if( io->i_bn >= rdonline[io->i_unit & 7] ) return(0); mp = &rd.ra_cmd; mp->m_lbn_l = loint(io->i_bn); mp->m_lbn_h = hiint(io->i_bn); mp->m_bytecnt = io->i_cc; mp->m_buf_l = io->i_ma; mp->m_buf_h = segflag & 3; if( racmd(func == READ ? M_O_READ : M_O_WRITE,io->i_unit) < 0 ) return(-1); return(io->i_cc); } device driver * RQDX1 (rx50,rd50,rd51,rd52,rd53) */ #include #include #ifndef u_char #define u_char char #endif #include #include #include "../saio.h" /* * RA Communications Area */ struct rdca { short ca_xxx1; /* unused */ char ca_xxx2; /* unsys/OTHERS/ra/mdec.rauboot.s 444 3 12 16101 4056740204 11043 From osmail!egdorf@LANL.ARPA Tue Jan 28 14:10:11 1986 Received: by seismo.CSS.GOV; Tue, 28 Jan 86 14:09:00 EST Received: by LANL.ARPA (4.12/4.7) id AA25151; Tue, 28 Jan 86 10:48:19 mst Date: Tue, 28 Jan 86 10:48:19 mst From: osmail!egdorf@LANL.ARPA Message-Id: <8601281748.AA25151@LANL.ARPA> To: lanl!keith Subject: mdec/rauboot.s Status: R / RA bootstrap. / / disk boot program to load and transfer to a unix entry. / for use with 1 KB byte blocks, CLSIZE is 2. / NDIRIN is the number of direct inode addresses (currently 4) / assembled size must be <= 512; if > 494, the 16-byte a.out header / must be removed / / Note: this is a complex boot, but then MSCP is complex!!!! / / a.out header must be removed from boot block! / MSCPSIZE = 64. / One MSCP command packet is 64bytes long (need 2) RASEMAP = 100000 / RA controller owner semaphore RAFLAG = 040000 / RA controller is done with descriptor. RAERR = 100000 / error bit RASTEP1 = 04000 / step1 has started RAGO = 01 / start operation, after init RASTCON = 4 / Setup controller info RAONLIN = 11 / Put unit on line RAREAD = 41 / Read command code RAWRITE = 42 / Write command code RAEND = 200 / End command code RACMDI = 4. / Command Interrupt RARSPI = 6. / Response Interrupt RARING = 8. / Ring base RARSPL = 8. / Response Command low RARSPH = 10. / Response Command high RACMDL = 12. / Command to controller low RACMDH = 14. / Command to controller high RARSPS = 16. / Response packet length (location) RARSPREF = 20. / Response reference number RACMDS = 80. / Command packet length (location) RACMDREF = 84. / Command reference number RAUNIT = 88. / Command packet unit RAOPCODE = 92. / Command opcode offset RABYTECT = 96. / Transfer byte count RABUFL = 100. / Buffer location (16 bit addressing only) RABUFH = 102. / Buffer location high 6 bits RALBNL = 112. / Logical block number low RALBNH = 114. / Logical block number high raip = 172150 / initialization and polling register rasa = 172152 / address and status register cyl = 0. / cylinder offset of filesys to read from / / options: / autoboot= 0 / 1->code for autoboot. 0->no autoboot, saves 12 bytes mxvboot = 1 / 0->normal, 1->adds check done by MXV11 boot ROMS unit = 0 / # of unit to load boot from / / constants: / CLSIZE = 2. / physical disk blocks per logical block CLSHFT = 1. / shift to multiply by CLSIZE BSIZE = 512.*CLSIZE / logical block size INOSIZ = 64. / size of inode in bytes NDIRIN = 4. / number of direct inode addresses ADDROFF = 12. / offset of first address in inode INOPB = BSIZE\/INOSIZ / inodes per logical block INOFF = 31. / inode offset = (INOPB * (SUPERB+1)) - 1 / / The boot options and device are placed in the last SZFLAGS bytes / at the end of core by the kernel if this is an autoboot. / ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 CHECKWORD= 6 .. = ENDCORE-512.-SZFLAGS / save room for boot flags / entry is made by jsr pc,*$0 / so return can be rts pc / establish sp, copy / program up to end of core. .if mxvboot 0240 / These two lines must be present or DEC br start / boot ROMs will refuse to run boot block! .endif start: mov $..,sp mov sp,r1 clr r0 1: mov (r0)+,(r1)+ cmp r1,$end blo 1b jmp *$2f / On error, restart from here. restart: / clear core to make things clean 2: clr (r0)+ cmp r0,sp blo 2b / / RA initialize controller / mov $RASTEP1,r0 mov $raip,r1 clr (r1)+ / go through controller init seq. mov $icons,r2 1: bit r0,(r1) beq 1b mov (r2)+,(r1) asl r0 bpl 1b mov $ra+RARSPREF,*$ra+RARSPL / set controller characteristics mov $ra+RACMDREF,*$ra+RACMDL mov $RASTCON,r0 jsr pc,racmd mov $unit,*$ra+RAUNIT / bring boot unit online mov $RAONLIN,r0 jsr pc,racmd / spread out in array 'names', one / component every 14 bytes. mov $names,r1 1: mov r1,r2 2: jsr pc,getc cmp r0,$'\n beq 1f cmp r0,$'/ beq 3f movb r0,(r2)+ br 2b 3: cmp r1,r2 beq 2b add $14.,r1 br 1b / now start reading the inodes / starting at the root and / going through directories 1: mov $names,r1 mov $2,r0 1: clr bno jsr pc,iget tst (r1) beq 1f 2: jsr pc,rmblk br restart mov $buf,r2 3: mov r1,r3 mov r2,r4 add $16.,r2 tst (r4)+ beq 5f 4: cmpb (r3)+,(r4)+ bne 5f cmp r4,r2 blo 4b mov -16.(r2),r0 add $14.,r1 br 1b 5: cmp r2,$buf+BSIZE blo 3b br 2b / read file into core until / a mapping error, (no disk address) 1: clr r1 1: jsr pc,rmblk br 1f mov $buf,r2 2: mov (r2)+,(r1)+ cmp r2,$buf+BSIZE blo 2b br 1b / relocate core around / assembler header 1: clr r0 cmp (r0),$407 bne 2f 1: mov 20(r0),(r0)+ cmp r0,sp blo 1b / enter program and / restart if return 2: .if autoboot mov ENDCORE-BOOTOPTS, r4 mov ENDCORE-BOOTDEV, r3 mov ENDCORE-CHECKWORD, r2 .endif jsr pc,*$0 / br restart / get the inode specified in r0 iget: add $INOFF,r0 mov r0,r5 ash $-4.,r0 bic $!7777,r0 mov r0,dno clr r0 jsr pc,rblk bic $!17,r5 mul $INOSIZ,r5 add $buf,r5 mov $inod,r4 1: mov (r5)+,(r4)+ cmp r4,$inod+INOSIZ blo 1b rts pc / read a mapped block / offset in file is in bno. / skip if success, no skip if fail / the algorithm only handles a single / indirect block. that means that / files longer than NDIRIN+128 blocks cannot / be loaded. rmblk: add $2,(sp) mov bno,r0 cmp r0,$NDIRIN blt 1f mov $NDIRIN,r0 1: mov r0,-(sp) asl r0 add (sp)+,r0 add $addr+1,r0 movb (r0)+,dno movb (r0)+,dno+1 movb -3(r0),r0 bne 1f tst dno beq 2f 1: jsr pc,rblk mov bno,r0 inc bno sub $NDIRIN,r0 blt 1f ash $2,r0 mov buf+2(r0),dno mov buf(r0),r0 bne rblk tst dno bne rblk 2: sub $2,(sp) 1: rts pc read = 4 go = 1 / / RA MSCP read block routine. This is very primative, so don't expect / too much from it. Note that MSCP requires large data communications / space at end of ADDROFF for command area. / / dno -> 1k block # to load (low half) / buf -> address of buffer to put block into / BSIZE -> size of block to read / / Tim Tucker, Gould Electronics, August 23rd 1985 / rblk: mov dno,r0 asl r0 mov r0,*$ra+RALBNL / Put in disk block number mov $BSIZE,*$ra+RABYTECT / Put in byte to transfer mov $buf,*$ra+RABUFL / Put in disk buffer location mov $RAREAD,r0 jsr pc,racmd rts pc / / perform MSCP command -> response poll version / / / racmd: movb r0,*$ra+RAOPCODE / fill in command type mov $MSCPSIZE,r0 mov r0,*$ra+RARSPS / give controller struct sizes mov r0,*$ra+RACMDS mov $RASEMAP,r0 mov r0,*$ra+RARSPH / set mscp semaphores mov r0,*$ra+RACMDH mov raip,r0 / tap controllers shoulder mov $ra+RACMDH,r0 1: bit (r0),$RAFLAG beq 1b / Wait till command read mov $ra+RARSPH,r0 2: bit (r0),$RAFLAG beq 2b / Wait till response written rts pc / / Read a character at a time from the boot string, no console input / supported because boot block too large! / getc: movb *cp, r0 beq 2f inc cp 2: cmp r0,$'\r bne 1f mov $'\n,r0 1: rts pc icons: RAERR ra+RARING 0 RAGO cp: defnm defnm: end: inod = ..-512.-BSIZE / room for inod, buf, stack addr = inod+ADDROFF / first address in inod buf = inod+INOSIZ bno = buf+BSIZE dno = bno+2 ra = dno+2 / ra mscp communications area (BIG!) names = ra+146. ec + 1; } } else sc->sc_blkno = dbtofsb(bp->b_blkno); break; default: return; } htstart(); } htinit() { register ocs2; register omttc; omttc = HTADDR->httc & 03777; /* preserve old slave select, dens, format */ ocs2 = HTADDR->htcs2 & 07; /* preserve old unit */ HTADDR->htcs2 = HTCS2_CLR; HTADDR->htcs2 = ocs2; HTADDR->httc = omttc; HTADDR->htcs1 = HT_DCLR | HT_GO; } #ifdef HT_IOCTL /*ARGSUSED*/ htioctl(dev, csys/OTHERS/acucntrl 464 3 12 2561 4311210636 7413 A short preface to this is in order. We didn't include this fix because we do soft-carrier differently from 4.XBSD and we would have had to modify the drivers. Basically acucntrl is the wrong way to do this. The kernel should be modified to provide the service which acucntrl is trying to provide out in user-land; perhaps Chris Torek's multiple interface scheme is the right way to go ... This unfortunately doesn't help 4.3BSD and 2.10BSD people much. Following is an UNTESTED fix for /sys/pdpuba/dh.c. Similar fixes for dhu.c and dz.c are possible: *** /tmp/dh.c Wed Sep 7 03:31:38 1988 --- /sys/pdpuba/dh.c Thu Aug 18 17:49:17 1988 *************** *** 598,604 **** dm = unit >> 4; tp = &dh11[unit]; unit &= 0xf; ! if ((dev & 0200) || (dhinfo[dm].ui_flags & (1<> 4; tp = &dh11[unit]; unit &= 0xf; ! if (dev & 0200) dhsoftCAR[dm] |= (1<<(unit&0xf)); else dhsoftCAR[dm] &= ~(1<<(unit&0xf)); As stated above, we would far rather see Chris Torek's multiple interface code installed. That would allow uucico, tip and any other programs to simply use the right interface in their opens on the outgoing modems. The corresponding fixes to the various tty drivers are unfortunately fairly extensive. See Chris for the diffs ... s the right way to go ... This unfortunately doesn't help 4.3BSD and 2.10BSD people much. Following is an UNTESTED fix for /sys/pdpuba/dh.csys/OTHERS/de11/ 755 0 12 0 4020206507 6312 sys/OTHERS/de11/de.c 444 3 12 14523 4020206522 7156 #include "de.h" #if NDE > 0 #include "param.h" #include #include #include #include #include #include #define FREAD 01 #define FWRITE 02 struct tty de11[NDE]; extern struct dedevice *DEADDR; extern char partab[]; int destart(); int ttrstrt(); /* * DLV11E speed and control bit table. * The table index is the same as the speed-selector * number for the DH11. * Attempts to set the speed to a zero entry are ignored. */ short derstab[] = { 0, /* 0 baud */ 0x0000 | DE_PBREN, /* 50 baud */ 0x1000 | DE_PBREN, /* 75 baud */ 0x2000 | DE_PBREN, /* 110 baud */ 0x3000 | DE_PBREN, /* 134.5 baud */ 0x4000 | DE_PBREN, /* 150 baud */ 0x0000, /* 200 baud-Not Available */ 0x5000 | DE_PBREN, /* 300 baud */ 0x6000 | DE_PBREN, /* 600 baud */ 0x7000 | DE_PBREN, /* 1200 baud */ 0x8000 | DE_PBREN, /* 1800 baud */ 0xA000 | DE_PBREN, /* 2400 baud */ 0xC000 | DE_PBREN, /* 4800 baud */ 0xE000 | DE_PBREN, /* 9600 baud */ 0xF000 | DE_PBREN, /* 19200 baud */ 0 /* X1 */ }; /* * Open a DLV11E, waiting until carrier is established. * Default initial conditions are set up on the first open. * T_state's CARR_ON bit is a copy of the hardware * DE_CAR bit, and is only used to regularize * carrier tests in general tty routines. */ /*ARGSUSED*/ deopen(dev, flag) register dev_t dev; { register struct tty *tp; register struct dedevice *deaddr; extern klstart(); int s; if (minor(dev) >= NDE) { u.u_error = ENXIO; return; } tp = &de11[minor(dev)]; deaddr = DEADDR + minor(dev); if (tp->t_state & XCLUDE && u.u_uid != 0) { u.u_error = EBUSY; return; } tp->t_addr = (caddr_t)deaddr; /* Needed for klstart */ if ((tp->t_state & (ISOPEN | WOPEN)) == 0) { /* Is dev already or being open(ed) ? */ tp->t_iproc = NULL; tp->t_oproc = destart; ttychars(tp); /* Sets default cntrl chars */ tp->t_ispeed = B1200; tp->t_ospeed = B1200; tp->t_flags = ODDP | EVENP | ECHO; tp->t_line = DFLT_LDISC; deaddr->detcsr = derstab[B1200]; } #ifdef NODEMODEM if(dev & NODEMODEM) tp->t_state |= CARR_ON; else #endif NODEMODEM { s = spl5(); tp->t_state |= WOPEN; deaddr->dercsr |= DE_DSIE | DE_DTR; /* Enable int. for carrier det. */ if (deaddr->dercsr & DE_CAR) /* Copy the sofware state */ tp->t_state |= CARR_ON; /* if carr. det already on */ splx(s); } while ((tp->t_state & CARR_ON) == 0) { /* If not on, wait for carrier-interrupt */ sleep((caddr_t)&tp->t_rawq, TTIPRI); } deaddr->dercsr |= DE_RIE; deaddr->detcsr |= DE_TIE; ttyopen(dev, tp); } /* * Close a DE11 */ declose(dev) dev_t dev; { register struct tty *tp; int s; tp = &de11[minor(dev)]; /* We can shut it down completely if was exclusive open */ if(tp->t_state & XCLUDE && u.u_uid != 0) { s = spl5(); ((struct dedevice *) (tp->t_addr))->dercsr = DE_DTR; ((struct dedevice *) (tp->t_addr))->detcsr = 0; splx(s); } if (tp->t_state & HUPCLS) { ((struct dedevice *) (tp->t_addr))->dercsr &= ~DE_DTR; } ttyclose(tp); } /* * Read a DE11 */ deread(dev) dev_t dev; { register struct tty *tp; tp = &de11[minor(dev)]; (*linesw[tp->t_line].l_read)(tp); } /* * Write a DE11 */ dewrite(dev) dev_t dev; { register struct tty *tp; tp = &de11[minor(dev)]; (*linesw[tp->t_line].l_write)(tp); } /* * DE11 transmitter interrupt. */ dexint(dev) dev_t dev; { register struct tty *tp; register struct clist *cp; tp = &de11[minor(dev)]; ttstart(tp); if (tp->t_state & ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) { tp->t_state &= ~ASLEEP; #ifdef MPX_FILS /* to be added later */ HELP #endif MPX_FILS wakeup((caddr_t) &tp->t_outq); } } /* * DE11 receiver interrupt. */ derint(dev) dev_t dev; { register struct tty *tp; register int c, csr; tp = &de11[minor(dev)]; c = ((struct dedevice *) (tp->t_addr))->derbuf; /* * If carrier is off, and an open is not in progress, * knock down the CD lead to hang up the local dataset * and signal a hangup. */ if ((((csr = ((struct dedevice *)(tp->t_addr))->dercsr) & DE_CAR) == 0) #ifdef NODEMODEM && ( (tp->t_dev & NODEMODEM) == 0) /* Skip it if NODEMODEM here */ #endif NODEMODEM ) { if ((tp->t_state & WOPEN) == 0) { ((struct dedevice *) (tp->t_addr))->dercsr &= ~DE_DTR; if (tp->t_state & CARR_ON) gsignal(tp->t_pgrp, SIGHUP); flushtty(tp, FREAD|FWRITE); } tp->t_state &= ~CARR_ON; return; } if ((tp->t_state & ISOPEN) == 0) { if ((tp->t_state & WOPEN) && (csr & DE_CAR)) tp->t_state |= CARR_ON; wakeup((caddr_t) tp); /* Turn on software carr. if */ /* back in deopen wait loop */ return; } /* Parity check to be fixed * csr &= ((struct dedevice *)(tp->t_addr))->derbuf & 0400; * if ((csr && ((tp->t_flags & (EVENP | ODDP)) == ODDP)) || * (!csr && ((tp->t_flags & (EVENP | ODDP)) == EVENP))) */ (*linesw[tp->t_line].l_input)(c, tp); } /* * DE11 stty/gtty. * Perform general functions and set speeds. */ deioctl(dev, cmd, addr, flag) dev_t dev; caddr_t addr; int cmd, flag; { register struct tty *tp; register r; tp = &de11[minor(dev)]; switch (ttioctl(tp, cmd, addr, flag)) { case TIOCSETP: case TIOCSETN: r = derstab[tp->t_ispeed]; if(tp->t_ispeed){ /* Hang up line */ ((struct dedevice *) (tp->t_addr))->detcsr = r; ((struct dedevice *) (tp->t_addr))->dercsr |= DE_RIE; ((struct dedevice *) (tp->t_addr))->detcsr |= DE_TIE; } else ((struct dedevice *) (tp->t_addr))->dercsr &= ~DE_DTR; break; #ifdef DE_IOCTL case TIOCSBRK: ((struct dedevice *) (tp->t_addr))->detcsr |= DE_BRK; break; case TIOCCBRK: ((struct dedevice *) (tp->t_addr))->detcsr &= ~DE_BRK; break; case TIOCSDTR: ((struct dedevice *) (tp->t_addr))->dercsr &= DE_DTR; break; case TIOCCDTR: ((struct dedevice *) (tp->t_addr))->dercsr &= ~DE_DTR; break; #endif DE_IOCTL default: u.u_error = ENOTTY; case 0: break; } } destart(tp) register struct tty *tp; { register c; register struct dedevice *addr; addr = (struct dedevice *) tp->t_addr; if ((addr->detcsr & DETCSR_RDY) == 0) return; if ((c=getc(&tp->t_outq)) >= 0) { if (tp->t_flags & RAW) addr->detbuf = c; else if (c<=0177) addr->detbuf = c /* dlf terminal parity mod */ #ifdef OUT_PAR | (partab[c] & 0200) #endif ; /* end of dlf termnal parity mod */ else { timeout(ttrstrt, (caddr_t)tp, (c & 0177) + DEDELAY); tp->t_state |= TIMEOUT; } } } #endif NDE EMAP,r0 mov r0,*$ra+RARSPH / set mscp semaphores mov r0,*$ra+RACMDH mov raip,r0 / tap controllers shoulder mov $ra+RACMDH,r0 1: bit (r0),$RAFLAG beq 1b / Wait tilsys/OTHERS/de11/de_locore 444 3 12 737 4020206477 10253 #if NDE > 0 . = ZERO+300 dein; br4+0. deou; br4+0. klin; br4+5. klou; br4+5. #endif #if NDE > 0 .globl _derint dein: jsr r0,call; jmp _derint .globl _dexint deou: jsr r0,call; jmp _dexint #endif #include "de.h" #if NDE > 0 int deopen(), declose(), deread(), dewrite(), deioctl(); extern struct tty de11[]; #else #define deopen nodev #define declose nodev #define deread nodev #define dewrite nodev #define deioctl nodev #define de11 ((struct tty *) NULL) #endif NDE sys/OTHERS/de11/dereg.h 444 3 12 3522 4020206066 7641 From likewise!bandit!dlf Wed Dec 18 19:06:48 1985 Received: from likewise.UUCP by seismo.CSS.GOV with UUCP; Wed, 18 Dec 85 15:05:07 EST Received: by likewise.UUCP (4.12/4.7) id AA10578; Wed, 18 Dec 85 11:18:25 est Received: by bandit.UUCP (4.12/4.7) id AA16395; Wed, 18 Dec 85 11:10:38 est Date: Wed, 18 Dec 85 11:10:38 est From: likewise!bandit!dlf (mh6692) Message-Id: <8512181610.AA16395@bandit.UUCP> To: bandit!likewise!seismo!keith Subject: include/sys/dereg.h Status: R struct dedevice { short dercsr; /* receiver status register */ short derbuf; short detcsr; short detbuf; }; /* bits in dercsr */ #define DE_DSI 0100000 #define DE_RING 0040000 #define DE_CTS 0020000 /* clear to send */ #define DE_CAR 0010000 /* carrier detect */ #define DE_RCVA 0004000 /* receiver active */ #define DE_SECR 0002000 /* secondary receive */ /* bits 9-8 are not used */ #define DE_DONE 0000200 /* receiver done */ #define DE_RIE 0000100 /* interrupt rcvr enable */ #define DE_DSIE 0000040 /* data set interrupt enable */ /* bit 4 is not used */ #define DE_SXDATA 0000010 /* supervisory transmit */ #define DE_RTS 0000004 /* request to send */ #define DE_DTR 0000002 /* data terminal ready */ /* bit 0 is not used */ /* bits in derbuf */ #define DE_ERR 0100000 /* any error */ #define DE_OERR 0040000 /* overrun error */ #define DE_FERR 0020000 /* framing error */ #define DE_PERR 0010000 /* parity error */ /* bits in detcsr */ /* bits 15-12 are the transmitter speed select */ #define DE_PBREN 0004000 /* bits 10-8 are not used */ #define DETCSR_RDY 0000200 /* ready */ #define DE_TIE 0000100 /* transmit interrupt enable */ /* bits 5-3 are unused */ #define DETCSR_MM 0000004 /* maintenance */ /* bit one is not used */ #define DE_BRK 0000001 /* break */ #define DEDELAY 0000004 /* Extra delay for DEs */ s. */ /*ARGSUSED*/ deopen(dev, flag) register dev_t dev; { register struct tty *tp; register struct dedevice *deaddr; extern klstart(); int s; if (minor(dev) >= NDE) sys/OTHERS/rm02.03.05/ 755 0 12 0 5325716403 7016 sys/OTHERS/rm02.03.05/rm.c 444 3 12 37015 5321515243 7707 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)rm.c 1.2 (2.11BSD GTE) 1/2/93 */ /* * RJM02/RWM03, RM02/03/05 disk driver * For simplicity we use hpreg.h instead of an rmreg.h. The bits * are the same. Only the register names have been changed to * protect the innocent. * * Added RM_RM05 #ifdef (RM_NTRAC gets updated) for RM05 type drive. * Put this #define in the rm.h file. */ #include "rm.h" #if NRM > 0 #include "param.h" #include "systm.h" #include "buf.h" #include "conf.h" #include "user.h" #include "hpreg.h" #ifdef RM_DUMP #include "seg.h" #endif #include "uba.h" #include "dkbad.h" #include "dk.h" #include "xp.h" struct hpdevice *RMADDR = (struct hpdevice *)0176700; #if NXPD > 0 extern struct size { daddr_t nblocks; int cyloff; } rm_sizes[8]; #else !NXPD struct size { daddr_t nblocks; int cyloff; } rm_sizes[8] = { 4800, 0, /* cyl 0 - 29 */ 4800, 30, /* cyl 30 - 59 */ 122080, 60, /* cyl 60 - 822 */ 62720, 60, /* cyl 60 - 451 */ 59360, 452, /* cyl 452 - 822 */ 0, 0, /* Not Defined */ 0, 0, /* Not Defined */ 131680, 0, /* cyl 0 - 822 */ }; #endif NXPD int rm_offset[] = { HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, 0, 0, 0, 0 }; #define RM_NSECT 32 #ifdef RM_RM05 #define RM_NTRAC 19 /* RM05 */ #else #define RM_NTRAC 5 /* RM02/03 */ #endif #define RM_NCYL 823 #define RM_SDIST 2 #define RM_RDIST 6 struct buf rmtab; #if NRM > 1 struct buf rmutab[NRM]; #endif #ifdef BADSECT struct dkbad rmbad[NRM]; struct buf brmbuf[NRM]; bool_t rm_init[NRM]; #endif #if NRM > 1 int rmcc[NRM]; /* Current cylinder */ #endif void rmroot() { rmattach(RMADDR, 0); } rmattach(addr, unit) register struct hpdevice *addr; { if (unit != 0) return(0); if ((addr != (struct hpdevice *) NULL) && (fioword(addr) != -1)) { RMADDR = addr; if (fioword(&(addr->hpbae)) != -1) rmtab.b_flags |= B_RH70; return(1); } RMADDR = (struct hpdevice *) NULL; return(0); } rmstrategy(bp) register struct buf *bp; { register struct buf *dp; register unit; long bn; unit = minor(bp->b_dev) & 077; if (unit >= (NRM << 3) || (RMADDR == (struct hpdevice *) NULL)) { bp->b_error = ENXIO; goto errexit; } if (bp->b_blkno < 0 || (bn = dkblock(bp)) + (long) ((bp->b_bcount + 511) >> 9) > rm_sizes[unit & 07].nblocks) { bp->b_error = EINVAL; errexit: bp->b_flags |= B_ERROR; iodone(bp); return; } if ((rmtab.b_flags & B_RH70) == 0) mapalloc(bp); bp->b_cylin = bn / (RM_NSECT * RM_NTRAC) + rm_sizes[unit & 07].cyloff; unit = dkunit(bp); #if NRM > 1 dp = &rmutab[unit]; #else dp = &rmtab; #endif (void) _spl5(); disksort(dp, bp); if (dp->b_active == 0) { #if NRM > 1 rmustart(unit); if (rmtab.b_active == 0) rmstart(); #else rmstart(); #endif } (void) _spl0(); } #if NRM > 1 rmustart(unit) register unit; { register struct hpdevice *rmaddr = RMADDR; register struct buf *dp; struct buf *bp; daddr_t bn; int sn, cn, csn; rmaddr->hpcs2.w = unit; rmaddr->hpcs1.c[0] = HP_IE; rmaddr->hpas = 1 << unit; if (unit >= NRM) return; #ifdef RM_DKN dk_busy &= ~(1 << (unit + RM_DKN)); #endif dp = &rmutab[unit]; if ((bp=dp->b_actf) == NULL) return; /* * If we have already positioned this drive, * then just put it on the ready queue. */ if (dp->b_active) goto done; dp->b_active++; /* * If drive has just come up, * set up the pack. */ #ifdef BADSECT if (((rmaddr->hpds & HPDS_VV) == 0) || (rm_init[unit] == 0)) #else if ((rmaddr->hpds & HPDS_VV) == 0) #endif { #ifdef BADSECT struct buf *bbp = &brmbuf[unit]; rm_init[unit] = 1; #endif /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ rmaddr->hpcs1.c[0] = HP_IE | HP_PRESET | HP_GO; rmaddr->hpof = HPOF_FMT22; #ifdef BADSECT bbp->b_flags = B_READ | B_BUSY | B_PHYS; bbp->b_dev = bp->b_dev; bbp->b_bcount = sizeof(struct dkbad); bbp->b_un.b_addr = (caddr_t)&rmbad[unit]; bbp->b_blkno = (daddr_t)RM_NCYL * (RM_NSECT*RM_NTRAC) - RM_NSECT; bbp->b_cylin = RM_NCYL - 1; if ((rmtab.b_flags & B_RH70) == 0) mapalloc(bbp); dp->b_actf = bbp; bbp->av_forw = bp; bp = bbp; #endif BADSECT } /* * If drive is offline, forget about positioning. */ if ((rmaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL)) goto done; bn = dkblock(bp); cn = bp->b_cylin; sn = bn % (RM_NSECT * RM_NTRAC); sn = (sn + RM_NSECT - RM_SDIST) % RM_NSECT; if (rmcc[unit] != cn) goto search; csn = (rmaddr->hpla >> 6) - sn + RM_SDIST - 1; if (csn < 0) csn += RM_NSECT; if (csn > RM_NSECT - RM_RDIST) goto done; search: rmaddr->hpdc = cn; rmaddr->hpda = sn; rmaddr->hpcs1.c[0] = HP_IE | HP_SEARCH | HP_GO; rmcc[unit] = cn; /* * Mark unit busy for iostat. */ #ifdef RM_DKN unit += RM_DKN; dk_busy |= 1 << unit; dk_numb[unit]++; #endif return; done: /* * Device is ready to go. * Put it on the ready queue for the controller. */ dp->b_forw = NULL; if (rmtab.b_actf == NULL) rmtab.b_actf = dp; else rmtab.b_actl->b_forw = dp; rmtab.b_actl = dp; } #endif /* * Start up a transfer on a drive. */ rmstart() { register struct hpdevice *rmaddr = RMADDR; register struct buf *bp; struct buf *dp; register unit; daddr_t bn; int dn, sn, tn, cn; loop: /* * Pull a request off the controller queue. */ #if NRM == 1 dp = &rmtab; if ((bp = dp->b_actf) == NULL) return; #else if ((dp = rmtab.b_actf) == NULL) return; if ((bp = dp->b_actf) == NULL) { rmtab.b_actf = dp->b_forw; goto loop; } #endif /* * Mark controller busy and * determine destination of this request. */ rmtab.b_active++; unit = minor(bp->b_dev) & 077; dn = dkunit(bp); /* * Select drive. */ rmaddr->hpcs2.w = dn; #if NRM == 1 /* * If drive has just come up, * set up the pack. */ #ifdef BADSECT if (((rmaddr->hpds & HPDS_VV) == 0) || (rm_init[dn] == 0)) #else if ((rmaddr->hpds & HPDS_VV) == 0) #endif { #ifdef BADSECT struct buf *bbp = &brmbuf[dn]; rm_init[dn] = 1; #endif /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ rmaddr->hpcs1.c[0] = HP_IE | HP_PRESET | HP_GO; rmaddr->hpof = HPOF_FMT22; #ifdef BADSECT bbp->b_flags = B_READ | B_BUSY | B_PHYS; bbp->b_dev = bp->b_dev; bbp->b_bcount = sizeof(struct dkbad); bbp->b_un.b_addr = (caddr_t)&rmbad[dn]; bbp->b_blkno = (daddr_t)RM_NCYL * (RM_NSECT*RM_NTRAC) - RM_NSECT; bbp->b_cylin = RM_NCYL - 1; if ((rmtab.b_flags & B_RH70) == 0) mapalloc(bbp); dp->b_actf = bbp; bbp->av_forw = bp; bp = bbp; #endif BADSECT } #endif bn = dkblock(bp); cn = bp->b_cylin; sn = bn % (RM_NSECT * RM_NTRAC); tn = sn / RM_NSECT; sn = sn % RM_NSECT; /* * Check that it is ready and online. */ if ((rmaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL)) { rmtab.b_active = 0; rmtab.b_errcnt = 0; dp->b_actf = bp->av_forw; bp->b_flags |= B_ERROR; iodone(bp); goto loop; } if (rmtab.b_errcnt >= 16 && (bp->b_flags & B_READ)) { rmaddr->hpof = rm_offset[rmtab.b_errcnt & 017] | HPOF_FMT22; rmaddr->hpcs1.w = HP_OFFSET | HP_GO; while ((rmaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY) ; } rmaddr->hpdc = cn; rmaddr->hpda = (tn << 8) + sn; rmaddr->hpba = bp->b_un.b_addr; if (rmtab.b_flags & B_RH70) rmaddr->hpbae = bp->b_xmem; rmaddr->hpwc = -(bp->b_bcount >> 1); /* * Warning: unit is being used as a temporary. */ unit = ((bp->b_xmem & 3) << 8) | HP_IE | HP_GO; #ifdef RM_FORMAT if (minor(bp->b_dev) & 0200) unit |= bp->b_flags & B_READ? HP_RHDR : HP_WHDR; else unit |= bp->b_flags & B_READ? HP_RCOM : HP_WCOM; #else if (bp->b_flags & B_READ) unit |= HP_RCOM; else unit |= HP_WCOM; #endif rmaddr->hpcs1.w = unit; #ifdef RM_DKN dk_busy |= 1 << (RM_DKN + NRM); dk_numb[RM_DKN + NRM]++; dk_wds[RM_DKN + NRM] += bp->b_bcount >> 6; #endif } /* * Handle a disk interrupt. */ rmintr() { register struct hpdevice *rmaddr = RMADDR; register struct buf *bp, *dp; short unit; int as, i, j; as = rmaddr->hpas & 0377; if (rmtab.b_active) { #ifdef RM_DKN dk_busy &= ~(1 << (RM_DKN + NRM)); #endif /* * Get device and block structures. Select the drive. */ #if NRM > 1 dp = rmtab.b_actf; #else dp = &rmtab; #endif bp = dp->b_actf; #ifdef BADSECT if (bp->b_flags&B_BAD) if (rmecc(bp, CONT)) return; #endif unit = dkunit(bp); rmaddr->hpcs2.c[0] = unit; /* * Check for and process errors. */ if (rmaddr->hpcs1.w & HP_TRE) { /* error bit */ while ((rmaddr->hpds & HPDS_DRY) == 0) ; if (rmaddr->hper1 & HPER1_WLE) { /* * Give up on write locked devices * immediately. */ printf("rm%d: write locked\n", unit); bp->b_flags |= B_ERROR; #ifdef BADSECT } else if (rmaddr->rmer2 & RMER2_BSE) { #ifdef RM_FORMAT /* * Allow this error on format devices. */ if (minor(bp->b_dev) & 0200) goto errdone; #endif if (rmecc(bp, BSE)) return; else goto hard; #endif BADSECT } else { /* * After 28 retries (16 without offset and * 12 with offset positioning), give up. */ if (++rmtab.b_errcnt > 28) { hard: harderr(bp, "rm"); printf("cs2=%b er1=%b\n", rmaddr->hpcs2.w, HPCS2_BITS, rmaddr->hper1, HPER1_BITS); bp->b_flags |= B_ERROR; } else rmtab.b_active = 0; } /* * If soft ecc, correct it (continuing * by returning if necessary). * Otherwise, fall through and retry the transfer. */ if((rmaddr->hper1 & (HPER1_DCK|HPER1_ECH)) == HPER1_DCK) if (rmecc(bp, ECC)) return; errdone: rmaddr->hpcs1.w = HP_TRE | HP_IE | HP_DCLR | HP_GO; if ((rmtab.b_errcnt & 07) == 4) { rmaddr->hpcs1.w = HP_RECAL | HP_IE | HP_GO; while ((rmaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY) ; } #if NRM > 1 rmcc[unit] = -1; #endif } if (rmtab.b_active) { if (rmtab.b_errcnt) { rmaddr->hpcs1.w = HP_RTC | HP_GO; while ((rmaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY) ; } rmtab.b_errcnt = 0; #if NRM > 1 rmtab.b_active = 0; rmtab.b_actf = dp->b_forw; rmcc[unit] = bp->b_cylin; #endif dp->b_active = 0; dp->b_actf = bp->b_actf; bp->b_resid = - (rmaddr->hpwc << 1); iodone(bp); rmaddr->hpcs1.w = HP_IE; #if NRM > 1 if (dp->b_actf) rmustart(unit); #endif } #if NRM > 1 as &= ~(1 << unit); #endif } else { if (as == 0) rmaddr->hpcs1.w = HP_IE; rmaddr->hpcs1.c[1] = HP_TRE >> 8; } #if NRM > 1 for(unit = 0; unit < NRM; unit++) if (as & (1 << unit)) rmustart(unit); #endif rmstart(); } #define exadr(x,y) (((long)(x) << 16) | (unsigned)(y)) /* * Correct an ECC error and restart the i/o to complete * the transfer if necessary. This is quite complicated because * the correction may be going to an odd memory address base * and the transfer may cross a sector boundary. */ rmecc(bp, flag) register struct buf *bp; { register struct hpdevice *rmaddr = RMADDR; register unsigned byte; ubadr_t bb, addr; long wrong; int bit, wc; unsigned ndone, npx; int ocmd; int cn, tn, sn; daddr_t bn; struct ubmap *ubp; int unit; /* * ndone is #bytes including the error * which is assumed to be in the last disk page transferred. */ unit = dkunit(bp); #ifdef BADSECT if (flag == CONT) { npx = bp->b_error; bp->b_error = 0; ndone = npx * NBPG; wc = ((int)(ndone - bp->b_bcount)) / NBPW; } else #endif { wc = rmaddr->hpwc; ndone = (wc * NBPW) + bp->b_bcount; npx = ndone / NBPG; } ocmd = (rmaddr->hpcs1.w & ~HP_RDY) | HP_IE | HP_GO; bb = exadr(bp->b_xmem, bp->b_un.b_addr); bn = dkblock(bp); cn = bp->b_cylin - bn / (RM_NSECT * RM_NTRAC); bn += npx; cn += bn / (RM_NSECT * RM_NTRAC); sn = bn % (RM_NSECT * RM_NTRAC); tn = sn / RM_NSECT; sn %= RM_NSECT; switch (flag) { case ECC: printf("rm%d%c: soft ecc bn %D\n", unit, 'a' + (minor(bp->b_dev) & 07), bp->b_blkno + (npx - 1)); wrong = rmaddr->hpec2; if (wrong == 0) { rmaddr->hpof = HPOF_FMT22; rmaddr->hpcs1.w |= HP_IE; return (0); } /* * Compute the byte/bit position of the err * within the last disk page transferred. * Hpec1 is origin-1. */ byte = rmaddr->hpec1 - 1; bit = byte & 07; byte >>= 3; byte += ndone - NBPG; wrong <<= bit; /* * Correct until mask is zero or until end of transfer, * whichever comes first. */ while (byte < bp->b_bcount && wrong != 0) { addr = bb + byte; if (bp->b_flags & (B_MAP|B_UBAREMAP)) { /* * Simulate UNIBUS map if UNIBUS transfer. */ ubp = UBMAP + ((addr >> 13) & 037); addr = exadr(ubp->ub_hi, ubp->ub_lo) + (addr & 017777); } putmemc(addr, getmemc(addr) ^ (int) wrong); byte++; wrong >>= 8; } break; #ifdef BADSECT case BSE: if ((bn = isbad(&rmbad[unit], cn, tn, sn)) < 0) return(0); bp->b_flags |= B_BAD; bp->b_error = npx + 1; bn = (daddr_t)RM_NCYL * (RM_NSECT * RM_NTRAC) - RM_NSECT - 1 - bn; cn = bn/(RM_NSECT * RM_NTRAC); sn = bn%(RM_NSECT * RM_NTRAC); tn = sn/RM_NSECT; sn %= RM_NSECT; #ifdef DEBUG printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); #endif wc = -(512 / NBPW); break; case CONT: bp->b_flags &= ~B_BAD; #ifdef DEBUG printf("rmecc CONT: bn %D cn %d tn %d sn %d\n", bn, cn, tn, sn); #endif break; #endif BADSECT } rmtab.b_active++; if (wc == 0) return (0); /* * Have to continue the transfer. Clear the drive * and compute the position where the transfer is to continue. * We have completed npx sectors of the transfer already. */ rmaddr->hpcs2.w = unit; rmaddr->hpcs1.w = HP_TRE | HP_DCLR | HP_GO; addr = bb + ndone; rmaddr->hpdc = cn; rmaddr->hpda = (tn << 8) + sn; rmaddr->hpwc = wc; rmaddr->hpba = (caddr_t)addr; if (rmtab.b_flags & B_RH70) rmaddr->hpbae = (short)(addr >> 16); rmaddr->hpcs1.w = ocmd; return (1); } #ifdef RM_DUMP /* * Dump routine for RM02/RM03. * Dumps from dumplo to end of memory/end of disk section for minor(dev). */ #define DBSIZE 16 /* number of blocks to write */ rmdump(dev) dev_t dev; { register struct hpdevice *rmaddr = RMADDR; daddr_t bn, dumpsize; long paddr; register sn; register count; register struct ubmap *ubp; if ((bdevsw[major(dev)].d_strategy != rmstrategy) /* paranoia */ || ((dev=minor(dev)) > (NRM << 3))) return(EINVAL); dumpsize = rm_sizes[dev & 07].nblocks; if ((dumplo < 0) || (dumplo >= dumpsize)) return(EINVAL); dumpsize -= dumplo; rmaddr->hpcs2.w = dev >> 3; if ((rmaddr->hpds & HPDS_VV) == 0) { rmaddr->hpcs1.w = HP_DCLR | HP_GO; rmaddr->hpcs1.w = HP_PRESET | HP_GO; rmaddr->hpof = HPOF_FMT22; } if ((rmaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL)) return(EFAULT); dev &= 07; ubp = &UBMAP[0]; for (paddr = 0L; dumpsize > 0; dumpsize -= count) { count = dumpsize>DBSIZE? DBSIZE: dumpsize; bn = dumplo + (paddr >> PGSHIFT); rmaddr->hpdc = bn / (RM_NSECT*RM_NTRAC) + rm_sizes[dev].cyloff; sn = bn % (RM_NSECT * RM_NTRAC); rmaddr->hpda = ((sn / RM_NSECT) << 8) | (sn % RM_NSECT); rmaddr->hpwc = -(count << (PGSHIFT - 1)); if (ubmap && ((rmtab.b_flags & B_RH70) == 0)) { ubp->ub_lo = loint(paddr); ubp->ub_hi = hiint(paddr); rmaddr->hpba = 0; rmaddr->hpcs1.w = HP_WCOM | HP_GO; } else { /* * Non-UNIBUS map, or 11/70 RM03 (MASSBUS) */ rmaddr->hpba = loint(paddr); if (rmtab.b_flags & B_RH70) rmaddr->hpbae = hiint(paddr); rmaddr->hpcs1.w = HP_WCOM | HP_GO | ((paddr >> 8) & (03 << 8)); } while (rmaddr->hpcs1.w & HP_GO) ; if (rmaddr->hpcs1.w & HP_TRE) { if (rmaddr->hpcs2.w & HPCS2_NEM) return(0); /* made it to end of memory */ return(EIO); } paddr += (DBSIZE << PGSHIFT); } return(0); /* filled disk minor dev */ } #endif RM_DUMP #endif NRM case MTWEOF: callcount = mtop.mt_count; fcount = 1; break; case MTFSF: case MTBSF: callcount = mtop.mt_count; fcount = INF; break; case MTFSR: case MTBSR: callcount = 1; fcount = mtop.mt_count; break; case MTREW: case MTOFFL: case MTNOP: callcount = 1; fcount = 1; break; default: u.u_error = ENXIO; return; } if (callcount <= 0 || fcount <= 0) { u.u_error = ENXIO; return; } wsys/OTHERS/rm02.03.05/rm_conf.c 444 3 12 1011 4021122110 10636 #include "rm.h" #if NRM > 0 int rmstrategy(), rmread(), rmwrite(), rmroot(); extern struct buf rmtab; #define rmopen nulldev #define rmclose nulldev #define _rmtab &rmtab #else #define rmopen nodev #define rmclose nodev #define rmroot nulldev #define rmstrategy nodev #define rmread nodev #define rmwrite nodev #define _rmtab ((struct buf *) NULL) #endif NRM /* rm = XX */ rmopen, rmclose, rmread, rmwrite, nodev, nulldev, 0, SELECT(seltrue) /* rm = X */ rmopen, rmclose, rmstrategy, rmroot, _rmtab, (RM_DKN + NRM)); #endif /* * Get device and block structures. Sect the drive. */ #if NRM > 1 dp = rmtab.b_actf; #else dp = &rmtab; #endif bp = dp->b_actf; #ifdef BADSECT if (bp->b_flags&B_BAD) if (rmecc(bp, CONT)) return; #endif unit = dkunit(bp); rmaddr->hpcs2.c[0] = unit; /* * Check for and process errors. */ if (rmaddr->hpcs1.w & HP_TRE) { /* error bit */ while ((rmaddr->hpds & HPDS_DRY) == 0) ; if (rmaddr->hper1 & HPER1_WLE) { /* * Gsys/OTHERS/rm02.03.05/rm_scb.s 444 3 12 247 4021122101 10472 #include "rm.h" #if NRM > 0 /* RJM02/RWM03, RM02/03/05 */ DEVTRAP(254, rmintr, br5) #endif #if NRM > 0 /* RJM02/RWM03, RM02/03/05 */ HANDLER(rmintr) #endif sys/OTHERS/rm02.03.05/rm_autoconfig 444 3 12 64 4021121617 11610 "rm", xpprobe, /* rm -- rjm02/rwm03, rm02/03/05 */ onf.crm_scb.s5 rm_autoconfig  rm_GENERICig  rm_config  rm_stand.cigsys/OTHERS/rm02.03.05/rm_GENERIC 444 3 12 250 4021131301 10532 # Use NXP rather than NRM if possible. NRM 0 # RJM02/RWM03, RM02/03/05 RM_DKN 0 # drive # for iostat disk monitoring RM_RM05 YES # drive type is RM05, not RM02/3 sys/OTHERS/rm02.03.05/rm_config 444 3 12 376 4021131325 10742 echo "#define NRM $NRM" > ../$MACHINE/rm.h echo "#define RM_DKN $RM_DKN" >> ../$MACHINE/rm.h if [ $DUMPROUTINE = rmdump ]; then echo "#define RM_DUMP" >> ../$MACHINE/rm.h fi if [ $RM_RM05 = YES ]; then echo "#define RM_RM05" >> ../$MACHINE/rm.h fi sys/OTHERS/rm02.03.05/rm_stand.c 444 3 12 5612 4001144343 11047 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)rm.c 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * RM02/3 disk driver */ #include #include #include "saio.h" struct device { union { int w; char c[2]; } rmcs1; /* Control and Status register 1 */ int rmwc; /* Word count register */ caddr_t rmba; /* UNIBUS address register */ int rmda; /* Desired address register */ union { int w; char c[2]; } rmcs2; /* Control and Status register 2*/ int rmds; /* Drive Status */ int rmer1; /* Error register 1 */ int rmas; /* Attention Summary */ int rmla; /* Look ahead */ int rmdb; /* Data buffer */ int rmmr1; /* Maintenance register 1 */ int rmdt; /* Drive type */ int rmsn; /* Serial number */ int rmof; /* Offset register */ int rmdc; /* Desired Cylinder register*/ int rmhr; /* Holding register - unused*/ int rmmr2; /* Maintenence register 2 */ int rmer2; /* Error register 2 */ int rmec1; /* Burst error bit position */ int rmec2; /* Burst error bit pattern */ int rmbae; /* 11/70 bus extension */ int rmcs3; }; #define RMADDR ((struct device *)0176700) #define NSECT 32 #define NTRAC 5 #define SDIST 2 #define RDIST 6 #define P400 020 #define M400 0220 #define P800 040 #define M800 0240 #define P1200 060 #define M1200 0260 #define GO 01 #define PRESET 020 #define RTC 016 #define OFFSET 014 #define SEARCH 030 #define RECAL 06 #define DCLR 010 #define WCOM 060 #define RCOM 070 #define IE 0100 #define PIP 020000 #define DRY 0200 #define ERR 040000 #define TRE 040000 #define DCK 0100000 #define WLE 04000 #define ECH 0100 #define VV 0100 #define FMT16 010000 rmstrategy(io, func) register struct iob *io; { register unit; register i; daddr_t bn; int sn, cn, tn; if (((unit = io->i_unit) & 04) == 0) bn = io->i_bn; else { unit &= 03; bn = io->i_bn; bn -= io->i_boff; i = unit + 1; unit = bn%i; bn /= i; bn += io->i_boff; } RMADDR->rmcs2.w = unit; if((RMADDR->rmds & VV) == 0) { RMADDR->rmcs1.c[0] = PRESET|GO; RMADDR->rmof = FMT16; } cn = bn/(NSECT*NTRAC); sn = bn%(NSECT*NTRAC); tn = sn/NSECT; sn = sn%NSECT; RMADDR->rmdc = cn; RMADDR->rmda = (tn << 8) + sn; RMADDR->rmba = io->i_ma; RMADDR->rmwc = -(io->i_cc>>1); unit = (segflag << 8) | GO; if (func == READ) unit |= RCOM; else if (func == WRITE) unit |= WCOM; RMADDR->rmcs1.w = unit; while ((RMADDR->rmcs1.w&DRY) == 0) ; if (RMADDR->rmcs1.w & TRE) { printf("disk error: cyl=%d track=%d sect=%d cs2=%o, er1=%o\n", cn, tn, sn, RMADDR->rmcs2, RMADDR->rmer1); return(-1); } return(io->i_cc); } & (1 << unit)) rmustart(unit); #endif rmstart(); } #define exadr(x,y) (((long)(x) << 16) | (unsigned)(y)) /* *sys/OTHERS/rx01/ 755 0 12 0 5325716404 6365 sys/OTHERS/rx01/rx.c 444 3 12 16241 5321514352 7266 /* * Rx disk driver */ #ifdef never static char SCCS_ID[] = "@(#)rx.c Ver. 1.2 6/83"; #endif /* This was taken and adapted from V7 unix * The baroque ifdefs were to identify changes * I made to handle UCB's Unibus Mapping routines * They can be removed as soon as you're * sure it works. */ #include "rx.h" #if NRX > 0 #include "param.h" #include #include #include #include #include #include #include #define DK_N 0 /* Monitoring device number */ #define HZ 60 /* line frequency */ #define NRXDR 4 /* Nbr logical drives per controller */ #define RXSIZE 2002 /* Size of rx disk in sectors */ #define RXBLK BSIZE/NRXBYTE /* Size of block (512 bytes) in rx sectors */ #define RXBLKTR 26 /* Nbr blocks per track */ #define NRXBYTE 128 /* Nbr bytes in rx block */ #define MAXERR 10 /* Nbr retries after error */ #define RXHANG 300 /* Maximum hang on a TR or DONE bit */ #define RXBUSY 1 /* Busy flag */ #define RXERROR 2 /* Error flag */ #define RXINIT 4 /* Initialize flag */ #define rxsa rxdb /* Sector Address Register */ #define rxta rxdb /* Track Address Register */ #define rxes rxdb /* Error Status Register */ #define trwait() { register int n; \ for (n = RXHANG; (rp->rxcs & TR) == 0; n -= 1) \ if (n == 0) { dp->b_active |= RXERROR; break; } } #define donewait() { register int n; \ for (n = RXHANG; (rp->rxcs & DONE) == 0; n -= 1) \ if (n == 0) { dp->b_active |= RXERROR; break; } } #define getdb(n) { trwait (); n = rp->rxdb; } #define putdb(n) { trwait (); rp->rxdb = n; } #define errtst (((rp->rxcs & (ERROR|DONE)) != DONE) \ || ((rp->rxdb & (CRC|PARITY|IDONE)) != 0) \ || ((dp->b_active & RXERROR) != 0)) #define exadr(x, y) (((long) x << 16) | (unsigned) (y)) /* * Minor device field coding constants */ #define RXLDR 03 /* Logical drive mask */ #define RXILEAVE 04 /* Interleave mask */ #define RXCTLR 03 /* Controller shift */ extern struct rxdevice *rx_addr[]; /* * Rx handler work areas */ struct buf rxtab, rxutab[NRX]; /* rxdevice tables */ /* * Rx strategy */ rxstrategy (bp) register struct buf *bp; { register struct buf *dp; register int ctlr; ctlr = minor (bp->b_dev) >> RXCTLR; dp = &rxutab[ctlr]; if(bp->b_flags & B_PHYS) mapalloc(bp); /* link buffer into i/o queue and start i/o */ bp->b_resid = bp->b_bcount; bp->b_error = 0; spl4 (); bp->av_forw = NULL; if (dp->b_actf == NULL) dp->b_actf = bp; else dp->b_actl->av_forw = bp; dp->b_actl = bp; if (!dp->b_active) rxstart (ctlr); spl0 (); } /* * Do something */ rxstart (ctlr) int ctlr; { register struct buf *dp, *bp; register struct rxdevice *rp; unsigned int bx; char *ptr; long blk, lptr; int trk, sct, wd; struct ubmap *ubp; dp = &rxutab[ctlr]; rp = rx_addr[ctlr]; retry: if ((bp = dp->b_actf) == NULL) return; dp->b_active = RXBUSY; if ((bp->b_flags & B_READ) == 0) { /* output characters to buffer */ rp->rxcs = FILL|GO; lptr = exadr(bp->b_xmem, bp->b_un.b_addr); if(bp->b_flags & (B_MAP|B_UBAREMAP)) { /* * Simulate UNIBUS map if UNIBUS transfer * This is untested. */ ubp = UBMAP + ((lptr >> 13) & 037); lptr = exadr(ubp->ub_hi, ubp->ub_lo) + (lptr & 017777); } lptr += (long) (bp->b_bcount - bp->b_resid); for (bx = 0; bx < NRXBYTE; bx += 1) { wd = (bp->b_resid > bx) ? getmemc(lptr) : 0; putdb(wd); lptr++; } donewait (); if (errtst) { if (rxerror (ctlr)) goto retry; return; } } /* calculate drive, block, track and sector number for i/o */ blk = (bp->b_blkno << 2) + (bp->b_bcount - bp->b_resid) / NRXBYTE; if ((blk >= RXSIZE) || (blk < 0)) { if ((blk > ((RXSIZE+RXBLK-1)/RXBLK*RXBLK)) || (blk < 0) || ((bp->b_flags & B_READ) == 0)) { /* errors on writes don't actually do any good; * nobody listens to them */ bp->b_flags |= B_ERROR; bp->b_error = ENXIO; } rxdone (ctlr); goto retry; } trk = blk / RXBLKTR; sct = blk % RXBLKTR; /* if indicated, interleave sectors using DEC's RT-11 algorithm */ if (minor (bp->b_dev) & RXILEAVE) { if ((sct <<= 1) >= RXBLKTR){ sct++; } sct = (sct + 6 * trk) % RXBLKTR; if (++trk >= (RXSIZE / RXBLKTR)){ trk = 0; } } sct += 1; /* perform read/write */ rp->rxcs = IENABLE | GO | (bp->b_flags & B_READ ? READ : WRITE) | ((minor (bp->b_dev) & RXLDR) << 4); putdb (sct); putdb (trk); } /* * Initialize a controller */ rxinit (ctlr) int ctlr; { register struct buf *dp; int rxwaker (); dp = &rxutab[ctlr]; if ((dp->b_active & RXINIT) == 0) { rx_addr[ctlr]->rxcs = INIT; dp->b_active |= RXINIT; timeout (rxwaker, ctlr, HZ*3/2); } } /* * Wake up after initialize operation */ rxwaker (ctlr) int ctlr; { register struct buf *dp; register struct rxdevice *rp; dp = &rxutab[ctlr]; rp = rx_addr[ctlr]; dp->b_active &= ~RXINIT; if (((rp->rxcs & (DONE|ERROR)) != DONE) || ((rp->rxes & IDONE) == 0)) { if (rxerror (ctlr)) rxstart (ctlr); return; } rxstart (ctlr); } /* * Restart after power fail */ rxrstrt (flg) int flg; { register struct buf *dp; register int ctlr; if (flg == 0) { for (ctlr = 0; ctlr < NRX; ctlr += 1) { dp = &rxutab[ctlr]; if ((dp->b_active & RXBUSY) != 0) dp->b_active |= RXERROR; } } else { for (ctlr = 0; ctlr < NRX; ctlr += 1) { dp = &rxutab[ctlr]; if ((dp->b_active & RXBUSY) != 0) if (rxerror (ctlr)) rxstart (ctlr); } } } /* * Interrupt-time stuff */ rxintr (ctlr) int ctlr; { register struct buf *dp, *bp; register struct rxdevice *rp; unsigned int bx; char *ptr, byte; long lptr; int wd; struct ubmap *ubp; dp = &rxutab[ctlr]; if (!dp->b_active) { return; } rp = rx_addr[ctlr]; bp = dp->b_actf; if (errtst) { if (rxerror (ctlr)) rxstart (ctlr); return; } if (bp->b_flags & B_READ) { /* input data from buffer */ rp->rxcs = EMPTY|GO; lptr = exadr(bp->b_xmem, bp->b_un.b_addr); if(bp->b_flags & (B_MAP|B_UBAREMAP)) { /* * Simulate UNIBUS map if UNIBUS transfer * This is untested. */ ubp = UBMAP + ((lptr >> 13) & 037); lptr = exadr(ubp->ub_hi, ubp->ub_lo) + (lptr & 017777); } lptr += (long) (bp->b_bcount - bp->b_resid); for (bx = 0; bx < NRXBYTE; bx += 1) { getdb(byte); putmemc(lptr, ((bp->b_resid > bx) ? byte : 0)); lptr++; } donewait (); if (errtst) { if (rxerror (ctlr)) rxstart (ctlr); return; } } if (bp->b_resid <= NRXBYTE) { bp->b_resid = 0; rxdone (ctlr); } else { bp->b_resid -= NRXBYTE; dp->b_errcnt = 0; } rxstart (ctlr); } rxdone (ctlr) int ctlr; { register struct buf *dp, *bp; dp = &rxutab[ctlr]; bp = dp->b_actf; dp->b_active = 0; dp->b_errcnt = 0; dp->b_actf = bp->av_forw; iodone (bp); } rxerror (ctlr) int ctlr; { register struct buf *dp, *bp; register struct rxdevice *rp; dp = &rxutab[ctlr]; bp = dp->b_actf; rp = rx_addr[ctlr]; dp->b_active &= ~RXERROR; /* quit if too many errors */ dp->b_errcnt += 1; if (dp->b_errcnt > MAXERR) { #ifdef UCB_DEVERR harderr (bp, "rx"); printf("active=%d, cs=0%o", dp->b_active, rp->rxcs); #else deverror (bp, dp->b_active, rp->rxcs); #endif bp->b_flags |= B_ERROR; rxdone (ctlr); } else if (!(rp->rxcs & DONE) || !(rp->rxes & (CRC|PARITY))) { rxinit (ctlr); return (0); } return (1); } #endif NRX 0); /* * Have to continue the transfer. Clear the drive * and compute the position where the transfer is to continue. * We have completed npx sectors of the transfer already. */ rmaddr->hpcs2.w = unit; rmaddr->hpcs1.w = HP_TRE | HP_DCLR | HP_GO; addr = bb + ndone; rmaddr->hpdc = cn; rmaddr->hpda = (tn << 8) + sn; rmaddr->hpwc = wc;sys/OTHERS/rx01/rx.h 444 3 12 17 4057146011 7203 # define NRX 2 . .. rx.cS rx.hSrxreg.hxREADMExsys/OTHERS/rx01/rxreg.h 444 3 12 1124 4057146012 7742 /* * Rx device register definitions */ struct rxdevice { int rxcs; /* Command & Status Register */ int rxdb; /* Data Buffer Register */ }; /* * Rxcs definitions */ #define GO 01 #define FILL 00 #define EMPTY 02 #define WRITE 04 #define READ 06 #define NOP 010 #define RSTATUS 012 #define RERROR 016 #define UNIT 020 #define DONE 040 #define IENABLE 0100 #define TR 0200 #define INIT 040000 #define ERROR 0100000 /* * Rxes definitions */ #define CRC 01 /* CRC error */ #define PARITY 02 /* Parity error */ #define IDONE 04 /* Initialize done */ #define DRVRDY 0200 /* Drive 0 ready */ tegy (bp) register struct buf *bp; { register struct buf *dp; register int ctlr; ctlr = minor (bp->b_dev) >> RXCTLR; dp = &rxutab[ctlr]; if(bp->b_flags & B_PHYS) mapalloc(bp); /* link buffer into i/o queue and start i/o */ bp->b_resid = bp->b_bcount; bp->b_error = 0; spl4 (); bp->av_forw = NULL; if (dp->b_actf == NULL) dp->b_actf = bp; else dp->b_actl->av_forw = bp; dp->b_actl = bp; if (!dp->b_active) sys/OTHERS/rx01/README 444 3 12 726 4057147266 7325 rx.c a working rx01 driver. Two interleave factors are supported, non-interleaved (IBM standard) and DEC interleaving, used in RT-11. Special minor device numbers are used to access the different interleaving factors, see the source code for details. rxreg.h this is /usr/include/sys/rxreg.h. In contains register definitions for the rx01 driver Keith Packard 5440 SE 41st Portland, OR 97202 ...!tektronix!azure!keithp ...!tektronix!reed!motel6!keith sys/OTHERS/versatec/ 755 0 12 0 5325716404 7407 sys/OTHERS/versatec/vp.c 444 3 12 16023 5321515046 10303 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)vp.c 1.2 (2.11BSD GTE) 1/2/93 */ /* * Versatec printer/plotter driver for model c-pdp11(dma) controller * * Thomas Ferrin, UCSF Computer Graphics Laboratory, April 1979 * * Uses the same user interface as Bell Labs' driver but runs in raw * mode, since even the small 11" versatec outputs ~53kbytes/inch! */ #include "vp.h" #if NVP > 0 #include "param.h" #include "user.h" #include "buf.h" #include "proc.h" #include "vcmd.h" /* #define NOMESG /* no console messages if defined */ /* #define VP_TWOSCOMPL /* use two's-complement bytecount */ #define PRINTADR ((struct devregs *)0177514) /* printer csr */ #define PLOTADR ((struct devregs *)0177510) /* plotter csr */ /* * Note that there is really only 1 csr! Changes to 'PRINTADR' * csr are reflected in 'PLOTADR' csr and vice versa. Referencing * the particular csr sets the device into that mode of operation. */ #define DMA ((struct dmaregs *)0177500) /* dma register base */ #define ERROR 0100000 #define DTCENABLE 040000 /* interrupt on data xfer complete */ #define IENABLE 0100 /* interrupt on ready or error */ #define READY 0200 /* previous operation complete */ #define REOT 010 /* remote end-of-transmission */ #define RESET 02 #define CMDS 076 #define SPP 01 /* simultaneous print/plot mode */ struct buf vpbuf; #ifndef NOMESG char *vperr = "\nVersatec needs attention\n"; #endif struct devregs { short csr; }; struct dmaregs { short plotbytes; short addrext; short printbytes; unsigned short addr; }; struct { int state; unsigned bytecount; int alive; } vp11; /* states */ #define PPLOT 0400 /* low 6 bits reserved for hardware functions */ #define PLOT 0200 #define PRINT 0100 #define MODE 0700 #define ERRMSG 01000 #define NOSTART 02000 #define WBUSY 04000 /* * This driver should be converted to use a single VPADDR pointer. * Until then, the attach only marks the unit as alive. */ vpattach(addr, unit) struct vpdevice *addr; { if (((u_int) unit == 0) || (addr == (struct vpdevice *)DMA)) { vp11.alive++; return 1; } return 0; } /* ARGSUSED */ vpopen(dev, flag) dev_t dev; { register short *vpp; if (!vp11.alive || vp11.state&MODE) return(ENXIO); vpp = &PRINTADR->csr; vp11.state = PRINT; vpbuf.b_flags = B_DONE; *vpp = IENABLE | RESET; /* * Contrary to the implication in the operator's manual, it is an * error to have the bits for both an operation complete interrupt * and a data transmission complete interrupt set at the same time. * Doing so will cause erratic operation of 'READY' interrupts. */ if (vperror()) *vpp = vp11.state = 0; return(0); } /* ARGSUSED */ vpclose(dev, flag) dev_t dev; { register short *vpp; vperror(); vpp = (vp11.state&PLOT)? &PLOTADR->csr : &PRINTADR->csr; *vpp = IENABLE | REOT; /* page eject past toner bath */ vperror(); *vpp = vp11.state = 0; } vpwrite(dev, uio) dev_t dev; struct uio *uio; { int vpstart(); if ((vp11.bytecount=uio->uio_resid) == 0) /* true byte count */ return; if (uio->uio_resid&01) /* avoid EFAULT error in physio() */ uio->uio_resid++; if (vperror()) return; return (physio(vpstart, &vpbuf, dev, B_WRITE, uio)); /* note that newer 1200A's print @ 1000 lines/min = 2.2kbytes/sec */ } #ifdef V6 vpctl(dev, v) dev_t dev; int *v; { register int ctrl; register short *vpp; if (v) { *v = vp11.state; return; } if (vperror()) return; ctrl = u.u_arg[0]; vp11.state = (vp11.state&~MODE) | (ctrl&MODE); vpp = (ctrl&PLOT)? &PLOTADR->csr : &PRINTADR->csr; if (ctrl&CMDS) { *vpp = IENABLE | (ctrl&CMDS) | (vp11.state&SPP); vperror(); } if (ctrl&PPLOT) { vp11.state |= SPP; *vpp = DTCENABLE | SPP; } else if (ctrl&PRINT) { vp11.state &= ~SPP; *vpp = IENABLE; } else *vpp = IENABLE | (vp11.state&SPP); } #else /* ARGSUSED */ vpioctl(dev, cmd, data, flag) dev_t dev; u_int cmd; register caddr_t data; int flag; { register int ctrl; register short *vpp; register struct buf *bp; struct uio uio; struct iovec iov; switch (cmd) { case GETSTATE: *(int *)data = vp11.state; break; case SETSTATE: ctrl = *(int *)data; if (vperror()) return; vp11.state = (vp11.state&~MODE) | (ctrl&MODE); vpp = (ctrl&PLOT)? &PLOTADR->csr : &PRINTADR->csr; if (ctrl&CMDS) { *vpp = IENABLE | (ctrl&CMDS) | (vp11.state&SPP); vperror(); } if (ctrl&PPLOT) { vp11.state |= SPP; *vpp = DTCENABLE | SPP; } else if (ctrl&PRINT) { vp11.state &= ~SPP; *vpp = IENABLE; } else *vpp = IENABLE | (vp11.state&SPP); return (0); #ifdef THIS_IS_NOT_USEABLE case BUFWRITE: uio.uio_iovcnt = 1; uio.uio_iov = &iov; iov.iov_base = fuword(addr); iov.iov_len = uio.uio_resid = fuword(addr+NBPW); if ((int)iov.iov_base == -1 || iov.iov_len == -1) { u.u_error = EFAULT; return; } bp = &vpbuf; if (vp11.state&WBUSY) { /* wait for previous write */ (void) _spl4(); while ((bp->b_flags&B_DONE) == 0) sleep(bp, PRIBIO); u.u_procp->p_flag &= ~SLOCK; bp->b_flags &= ~B_BUSY; vp11.state &= ~WBUSY; (void) _spl0(); return(geterror(bp)); } if (uio.uio_resid == 0) return; /* simulate a write without starting i/o */ (void) _spl4(); vp11.state |= NOSTART; vpwrite(dev); vp11.state &= ~NOSTART; if (u.u_error) { (void) _spl0(); return; } /* fake write was ok, now do it for real */ bp->b_flags = B_BUSY | B_PHYS | B_WRITE; u.u_procp->p_flag |= SLOCK; vp11.state |= WBUSY; vpstart(bp); (void) _spl0(); return; #endif THIS_IS_NOT_USEABLE default: return (ENOTTY); } return (0); } #endif vperror() { register int state, err; state = vp11.state & PLOT; (void) _spl4(); while ((err=(state? PLOTADR->csr : PRINTADR->csr)&(READY|ERROR))==0) sleep((caddr_t)&vp11, PRIBIO); (void) _spl0(); if (err&ERROR) { u.u_error = EIO; #ifndef NOMESG if (!(vp11.state&ERRMSG)) { printf(vperr); vp11.state |= ERRMSG; } #endif } else vp11.state &= ~ERRMSG; return(err&ERROR); } vpstart(bp) register struct buf *bp; { register struct dmaregs *vpp = DMA; if (vp11.state&NOSTART) { bp->b_flags |= B_DONE; /* fake it */ return; } mapalloc(bp); vpp->addr = (short)(bp->b_un.b_addr); vpp->addrext = (bp->b_xmem & 03) << 4; #ifndef VP_TWOSCOMPL if (vp11.state&PLOT) vpp->plotbytes = vp11.bytecount; else vpp->printbytes = vp11.bytecount; #else if (vp11.state&PLOT) vpp->plotbytes = -vp11.bytecount; else vpp->printbytes = -vp11.bytecount; #endif } vpintr() { register struct buf *bp = &vpbuf; /* * Hardware botch. Interrupts occur a few usec before the 'READY' * bit actually sets. On fast processors it is unreliable to test * this bit in the interrupt service routine! */ if (bp->b_flags&B_DONE) { wakeup((caddr_t)&vp11); return; } if (((vp11.state&PLOT)? PLOTADR->csr : PRINTADR->csr) < 0) { #ifndef NOMESG if (!(vp11.state&ERRMSG)) { printf(vperr); vp11.state |= ERRMSG; } #endif bp->b_flags |= B_ERROR; bp->b_error = EIO; wakeup((caddr_t)&vp11); } iodone(bp); } #endif NVP = 0L; dumpsize > 0; dumpsize -= count) { count = dumpsize>DBSIZE? DBSIZE: dumpsize; bn = dumplo + (paddr >> PGSHIFT); rmaddr->hpdc = bn / (RM_NSECT*RM_NTRAC) + rm_sizes[dev].cyloff; sn = bn % (RM_NSECT * RM_NTRAC); rmaddr->hpda = ((sn / RM_NSECT) << 8) | (sn % RM_NSECT); rmaddr->hpwc = -(count << (PGSHIFT - 1)); if (ubmap && ((rmtab.b_flags & B_RH70) == 0)) { ubp->ub_lo = loint(paddr); ubp->ub_hi = hiint(paddr); rmaddr->hpba = 0; rmaddr->hpcs1.w = HP_WCOM | HP_GOsys/OTHERS/versatec/vpauto.c 444 3 12 1504 4001417256 11150 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)vpauto.c 1.1 (2.10BSD Berkeley) 12/1/86 */ #include "param.h" #include "../machine/autoconfig.h" #include "../machine/machparam.h" #include "vpreg.h" vpprobe(addr) struct vpdevice *addr; { extern int errno; errno = 0; /* * Use the plot csr now, to distinguish from a line printer. */ stuff(VP_IENABLE | VP_CLRCOM, (&(addr->plcsr))); DELAY(10000); /* * Make sure that the DMA registers are there. */ grab(&(addr->plbcr)); /* * Write the print csr this time, to leave it in print mode. */ stuff(0, (&(addr->prcsr))); /* * Possibly an LP csr, but no plot regs */ return(errno ? ACP_NXDEV : ACP_IFINTR); } (struct devregs *)0177510) /* plotter csr */ /* * Note that there is really only 1 csr! Changes to 'PRINTADR' * csr are reflected in 'PLOTADR' csr and vice versa. Referencing * the parsys/OTHERS/versatec/vpreg.h 444 3 12 1264 4001144747 10767 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)vpreg.h 1.1 (2.10BSD Berkeley) 12/1/86 */ #define VPPRI (PZERO-1) struct vpdevice { short plbcr; short pbxaddr; short prbcr; u_short pbaddr; short plcsr; short plbuf; short prcsr; u_short prbuf; }; #define VP_ERROR 0100000 #define VP_DTCINTR 0040000 #define VP_DMAACT 0020000 #define VP_READY 0000200 #define VP_IENABLE 0000100 #define VP_TERMCOM 0000040 #define VP_FFCOM 0000020 #define VP_EOTCOM 0000010 #define VP_CLRCOM 0000004 #define VP_RESET 0000002 #define VP_SPP 0000001 t in print mode. */ stuff(0, (&(addr->prcsr))); /* * Possibly an LP csr, but no plot regs */ return(errno ? ACP_NXDEV : ACP_IFINTR); } (struct devregs *)0177510) /* plotter csr */ /* * Note that there is really only 1 csr! Changes to 'PRINTADR' * csr are reflected in 'PLOTADR' csr and vice versa. Referencing * the parsys/OTHERS/versatec/vp_autoconfig 444 3 12 64 4021121662 12207 int vpprobe(); "vp", vpprobe, /* vp -- Versatec */ to.c5vpreg.h5 vp_autoconfig vp_conf.cvp_scb.s vp_GENERICig vp_configh.vcmd.hX pdpuba.vcmd.hsys/OTHERS/versatec/vp_conf.c 444 3 12 420 4021121775 11240 #include "vp.h" #if NVP > 0 int vpopen(), vpclose(), vpwrite(), vpioctl(); #else #define vpopen nodev #define vpclose nodev #define vpwrite nodev #define vpioctl nodev #endif NVP /* vp = XX */ vpopen, vpclose, nodev, vpwrite, vpioctl, nulldev, 0, SELECT(nodev) sys/OTHERS/versatec/vp_scb.s 444 3 12 421 4021122154 11073 #include "vp.h" #if NVP > 0 int vpopen(), vpclose(), vpwrite(), vpioctl(); #else #define vpopen nodev #define vpclose nodev #define vpwrite nodev #define vpioctl nodev #endif NVP /* vp = XX */ vpopen, vpclose, nodev, vpwrite, vpioctl, nulldev, 0, SELECT(nodev) sys/OTHERS/versatec/vp_GENERIC 444 3 12 123 4021131347 11142 NVP 0 # Versatec VP_TWOSCOMPL NO # interface needs two's complement bytecount autoconfig vp_conf.cvp_scb.s vp_GENERICig vp_configh.vcmd.hX pdpuba.vcmd.hsys/OTHERS/versatec/vp_config 444 3 12 203 4021131357 11333 echo "#define NVP $NVP" > ../$MACHINE/vp.h if [ $VP_TWOSCOMPL = YES ] ; then echo "#define VP_TWOSCOMPL" >> ../$MACHINE/vp.h fi vp_GENERICig vp_configh.vcmd.hX pdpuba.vcmd.hsys/OTHERS/versatec/h.vcmd.h 444 3 12 722 4053130007 10770 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)vcmd.h 7.1 (Berkeley) 6/4/86 */ #ifndef _IOCTL_ #ifdef KERNEL #include "ioctl.h" #else #include #endif #endif #define VPRINT 0100 #define VPLOT 0200 #define VPRINTPLOT 0400 #define VGETSTATE _IOR(v, 0, int) #define VSETSTATE _IOW(v, 1, int) sys/OTHERS/versatec/pdpuba.vcmd.h 444 3 12 640 4001144727 12022 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)vcmd.h 1.1 (2.10BSD Berkeley) 12/1/86 */ #define VPRINT 0100 #define VPLOT 0200 #define VPRINTPLOT 0400 #define GETSTATE (('v'<<8)|0) #define SETSTATE (('v'<<8)|1) #define BUFWRITE (('v'<<8)|2) /* async write */ sys/OTHERS/rp04.06/ 755 0 12 0 5325716403 6603 sys/OTHERS/rp04.06/hp.c 444 3 12 37432 5321514714 7472 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)hp.c 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * This driver has been modified to perform bad-sector forwarding. * It has not been tested after that modification. * If you want to use it, install it instead of the normal hp driver, * AND TEST BOTH BAD-SECTOR FORWARDING AND ECC CORRECTION. * The driver does not know how to distinguish RP04's from RP05/6's; * make sure that the definition of HP_NCYL is correct for all * of your HP's, or add some way to distinguish (by drive * number or something). */ /* * RJP04/RWP04/RJP06/RWP06 disk driver */ #include "hp.h" #if NHP > 0 #include "param.h" #include "../machine/seg.h" #include "systm.h" #include "buf.h" #include "conf.h" #include "user.h" #include "hpreg.h" #include "uba.h" #include "dkbad.h" #include "dk.h" #include "xp.h" #define HP_NCYL 815 #define HP_NSECT 32 #define HP_NTRAC 19 #define HP_SDIST 2 #define HP_RDIST 6 #if NXPD > 0 extern struct size { daddr_t nblocks; int cyloff; } hp_sizes[8]; #else !NXPD struct size { daddr_t nblocks; int cyloff; } hp_sizes[8] = { 9614, 0, /* cyl 0 - 22 */ 8778, 23, /* cyl 23 - 43 */ 153406, 44, /* cyl 44 - 410 (rp04, rp05, rp06) */ 168872, 411, /* cyl 411 - 814 (rp06) */ 322278, 44, /* cyl 44 - 814 (rp06) */ 0, 0, 171798, 0, /* cyl 0 - 410 (whole rp04/5) */ 340670, 0 /* cyl 0 - 814 (whole rp06) */ }; #endif NXPD struct hpdevice *HPADDR = (struct hpdevice *)0176700; #ifdef HPDEBUG int hpdebug = 1; #endif int hp_offset[] = { HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, 0, 0, 0, 0 }; struct buf hptab; struct buf hputab[NHP]; #ifdef BADSECT struct dkbad hpbad[NHP]; struct buf bhpbuf[NHP]; bool_t hp_init[NHP]; #endif void hproot() { hpattach(HPADDR, 0); } hpattach(addr, unit) register struct hpdevice *addr; { if (unit != 0) return(0); if ((addr != (struct hpdevice *) NULL) && (fioword(addr) != -1)) { HPADDR = addr; if (fioword(&(addr->hpbae)) != -1) hptab.b_flags |= B_RH70; return(1); } HPADDR = (struct hpdevice *) NULL; return(0); } hpstrategy(bp) register struct buf *bp; { register struct buf *dp; register unit; long bn; unit = minor(bp->b_dev) & 077; if (unit >= (NHP << 3) || (HPADDR == (struct hpdevice *) NULL)) { bp->b_error = ENXIO; goto errexit; } if (bp->b_blkno < 0 || (bn = dkblock(bp)) + (long) ((bp->b_bcount + 511) >> 9) > hp_sizes[unit & 07].nblocks) { bp->b_error = EINVAL; errexit: bp->b_flags |= B_ERROR; iodone(bp); return; } if ((hptab.b_flags & B_RH70) == 0) mapalloc(bp); bp->b_cylin = bn / (HP_NSECT * HP_NTRAC) + hp_sizes[unit & 07].cyloff; unit = dkunit(bp); dp = &hputab[unit]; (void) _spl5(); disksort(dp, bp); if (dp->b_active == 0) { hpustart(unit); if (hptab.b_active == 0) hpstart(); } (void) _spl0(); } /* * Unit start routine. * Seek the drive to where the data are * and then generate another interrupt * to actually start the transfer. * If there is only one drive on the controller * or we are very close to the data, don't * bother with the search. If called after * searching once, don't bother to look * where we are, just queue for transfer (to avoid * positioning forever without transferring). */ hpustart(unit) register unit; { register struct hpdevice *hpaddr = HPADDR; register struct buf *dp; struct buf *bp; daddr_t bn; int sn, cn, csn; hpaddr->hpcs2.w = unit; hpaddr->hpcs1.c[0] = HP_IE; hpaddr->hpas = 1 << unit; if (unit >= NHP) return; #ifdef HP_DKN dk_busy &= ~(1 << (unit + HP_DKN)); #endif HP_DKN dp = &hputab[unit]; if ((bp = dp->b_actf) == NULL) return; /* * If we have already positioned this drive, * then just put it on the ready queue. */ if (dp->b_active) goto done; dp->b_active++; /* * If drive has just come up, * set up the pack. */ #ifdef BADSECT if (((hpaddr->hpds & HPDS_VV) == 0) || (hp_init[unit] == 0)) #else if ((hpaddr->hpds & HPDS_VV) == 0) #endif { #ifdef BADSECT struct buf *bbp = &bhpbuf[unit]; hp_init[unit] = 1; #endif /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ hpaddr->hpcs1.c[0] = HP_IE | HP_PRESET | HP_GO; hpaddr->hpof = HPOF_FMT22; #ifdef BADSECT bbp->b_flags = B_READ | B_BUSY | B_PHYS; bbp->b_dev = bp->b_dev; bbp->b_bcount = sizeof(struct dkbad); bbp->b_un.b_addr = (caddr_t)&hpbad[unit]; bbp->b_blkno = (daddr_t)HP_NCYL * (HP_NSECT*HP_NTRAC) - HP_NSECT; bbp->b_cylin = HP_NCYL - 1; if ((hptab.b_flags & B_RH70) == 0) mapalloc(bbp); dp->b_actf = bbp; bbp->av_forw = bp; bp = bbp; #endif BADSECT } #if NHP > 1 /* * If drive is offline, forget about positioning. */ if ((hpaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL)) goto done; /* * Figure out where this transfer is going to * and see if we are close enough to justify not searching. */ bn = dkblock(bp); cn = bp->b_cylin; sn = bn % (HP_NSECT * HP_NTRAC); sn = (sn + HP_NSECT - HP_SDIST) % HP_NSECT; if (hpaddr->hpcc != cn) goto search; csn = (hpaddr->hpla >> 6) - sn + HP_SDIST - 1; if (csn < 0) csn += HP_NSECT; if (csn > HP_NSECT - HP_RDIST) goto done; search: hpaddr->hpdc = cn; hpaddr->hpda = sn; hpaddr->hpcs1.c[0] = HP_IE | HP_SEARCH | HP_GO; #ifdef HP_DKN /* * Mark unit busy for iostat. */ unit += HP_DKN; dk_busy |= 1 << unit; dk_numb[unit]++; #endif HP_DKN return; #endif NHP > 1 done: /* * Device is ready to go. * Put it on the ready queue for the controller. */ dp->b_forw = NULL; if (hptab.b_actf == NULL) hptab.b_actf = dp; else hptab.b_actl->b_forw = dp; hptab.b_actl = dp; } /* * Start up a transfer on a drive. */ hpstart() { register struct hpdevice *hpaddr = HPADDR; register struct buf *bp; register unit; struct buf *dp; daddr_t bn; int dn, sn, tn, cn; loop: /* * Pull a request off the controller queue. */ if ((dp = hptab.b_actf) == NULL) return; if ((bp = dp->b_actf) == NULL) { hptab.b_actf = dp->b_forw; goto loop; } /* * Mark controller busy and * determine destination of this request. */ hptab.b_active++; unit = minor(bp->b_dev) & 077; dn = dkunit(bp); bn = dkblock(bp); cn = bn / (HP_NSECT * HP_NTRAC) + hp_sizes[unit & 07].cyloff; sn = bn % (HP_NSECT * HP_NTRAC); tn = sn / HP_NSECT; sn = sn % HP_NSECT; /* * Select drive. */ hpaddr->hpcs2.w = dn; /* * Check that it is ready and online. */ if ((hpaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL)) { hptab.b_active = 0; hptab.b_errcnt = 0; dp->b_actf = bp->av_forw; bp->b_flags |= B_ERROR; iodone(bp); goto loop; } if (hptab.b_errcnt >= 16 && (bp->b_flags & B_READ)) { hpaddr->hpof = hp_offset[hptab.b_errcnt & 017] | HPOF_FMT22; hpaddr->hpcs1.w = HP_OFFSET | HP_GO; while ((hpaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY) ; } hpaddr->hpdc = cn; hpaddr->hpda = (tn << 8) + sn; hpaddr->hpba = bp->b_un.b_addr; if (hptab.b_flags & B_RH70) hpaddr->hpbae = bp->b_xmem; hpaddr->hpwc = -(bp->b_bcount >> 1); /* * Warning: unit is being used as a temporary. */ unit = ((bp->b_xmem & 3) << 8) | HP_IE | HP_GO; #ifdef HP_FORMAT if (minor(bp->b_dev) & 0200) unit |= bp->b_flags & B_READ? HP_RHDR : HP_WHDR; else unit |= bp->b_flags & B_READ? HP_RCOM : HP_WCOM; #else if (bp->b_flags & B_READ) unit |= HP_RCOM; else unit |= HP_WCOM; #endif hpaddr->hpcs1.w = unit; #ifdef HP_DKN dk_busy |= 1 << (HP_DKN + NHP); dk_numb[HP_DKN + NHP]++; dk_wds[HP_DKN + NHP] += bp->b_bcount >> 6; #endif HP_DKN } /* * Handle a disk interrupt. */ hpintr() { register struct hpdevice *hpaddr = HPADDR; register struct buf *dp; register unit; struct buf *bp; int as, i, j; as = hpaddr->hpas & 0377; if (hptab.b_active) { #ifdef HP_DKN dk_busy &= ~(1 << (HP_DKN + NHP)); #endif HP_DKN /* * Get device and block structures. Select the drive. */ dp = hptab.b_actf; bp = dp->b_actf; #ifdef BADSECT if (bp->b_flags&B_BAD) if (hpecc(bp, CONT)) return; #endif unit = dkunit(bp); hpaddr->hpcs2.c[0] = unit; /* * Check for and process errors. */ if (hpaddr->hpcs1.w & HP_TRE) { #ifdef HPDEBUG if (hpdebug) { printf("cs2=%b ds=%b er=%b\n", hpaddr->hpcs2.w, HPCS2_BITS, hpaddr->hpds, HPDS_BITS, hpaddr->hper1, HPER1_BITS); } #endif while ((hpaddr->hpds & HPDS_DRY) == 0) ; if (hpaddr->hper1 & HPER1_WLE) { /* * Give up on write locked devices * immediately. */ printf("hp%d: write locked\n", unit); bp->b_flags |= B_ERROR; #ifdef BADSECT } else if (hpaddr->hper1 & HPER1_FER) { #ifdef HP_FORMAT /* * Allow this error on format devices. */ if (minor(bp->b_dev) & 0200) goto errdone; #endif if (hpecc(bp, BSE)) return; else goto hard; #endif BADSECT } else { /* * After 28 retries (16 without offset and * 12 with offset positioning), give up. */ hard: if (++hptab.b_errcnt > 28) { bp->b_flags |= B_ERROR; harderr(bp, "hp"); printf("cs2=%b er1=%b\n", hpaddr->hpcs2.w, HPCS2_BITS, hpaddr->hper1, HPER1_BITS); } else hptab.b_active = 0; } /* * If soft ecc, correct it (continuing * by returning if necessary). * Otherwise, fall through and retry the transfer. */ if((hpaddr->hper1 & (HPER1_DCK|HPER1_ECH)) == HPER1_DCK) if (hpecc(bp, ECC)) return; errdone: hpaddr->hpcs1.w = HP_TRE | HP_IE | HP_DCLR | HP_GO; if ((hptab.b_errcnt & 07) == 4) { hpaddr->hpcs1.w = HP_RECAL | HP_IE | HP_GO; while ((hpaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY) ; } } if (hptab.b_active) { if (hptab.b_errcnt) { hpaddr->hpcs1.w = HP_RTC | HP_GO; while ((hpaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY) ; } hptab.b_active = 0; hptab.b_errcnt = 0; hptab.b_actf = dp->b_forw; dp->b_active = 0; dp->b_actf = bp->av_forw; bp->b_resid = - (hpaddr->hpwc << 1); iodone(bp); hpaddr->hpcs1.w = HP_IE; if (dp->b_actf) hpustart(unit); } as &= ~(1 << unit); } else { if (as == 0) hpaddr->hpcs1.w = HP_IE; hpaddr->hpcs1.c[1] = HP_TRE >> 8; } for (unit = 0; unit < NHP; unit++) if (as & (1 << unit)) hpustart(unit); hpstart(); } #define exadr(x,y) (((long)(x) << 16) | (unsigned)(y)) /* * Correct an ECC error and restart the i/o to complete * the transfer if necessary. This is quite complicated because * the correction may be going to an odd memory address base * and the transfer may cross a sector boundary. */ hpecc(bp, flag) register struct buf *bp; { register struct hpdevice *hpaddr = HPADDR; register unsigned byte; ubadr_t bb, addr; long wrong; int bit, wc; unsigned ndone, npx; int ocmd; int cn, tn, sn; daddr_t bn; struct ubmap *ubp; int unit; /* * ndone is #bytes including the error * which is assumed to be in the last disk page transferred. */ unit = dkunit(bp); #ifdef BADSECT if (flag == CONT) { npx = bp->b_error; bp->b_error = 0; ndone = npx * NBPG; wc = ((int)(ndone - bp->b_bcount)) / NBPW; } else #endif { wc = hpaddr->hpwc; ndone = (wc * NBPW) + bp->b_bcount; npx = ndone / NBPG; } ocmd = (hpaddr->hpcs1.w & ~HP_RDY) | HP_IE | HP_GO; bb = exadr(bp->b_xmem, bp->b_un.b_addr); bn = dkblock(bp); cn = bp->b_cylin - bn / (HP_NSECT * HP_NTRAC); bn += npx; cn += bn / (HP_NSECT * HP_NTRAC); sn = bn % (HP_NSECT * HP_NTRAC); tn = sn / HP_NSECT; sn %= HP_NSECT; switch (flag) { case ECC: printf("hp%d%c: soft ecc bn %D\n", unit, 'a' + (minor(bp->b_dev) & 07), bp->b_blkno + (npx - 1)); wrong = hpaddr->hpec2; if (wrong == 0) { hpaddr->hpof = HPOF_FMT22; hpaddr->hpcs1.w |= HP_IE; return (0); } /* * Compute the byte/bit position of the err * within the last disk page transferred. * Hpec1 is origin-1. */ byte = hpaddr->hpec1 - 1; bit = byte & 07; byte >>= 3; byte += ndone - NBPG; wrong <<= bit; /* * Correct until mask is zero or until end of transfer, * whichever comes first. */ while (byte < bp->b_bcount && wrong != 0) { addr = bb + byte; if (bp->b_flags & (B_MAP|B_UBAREMAP)) { /* * Simulate UNIBUS map if UNIBUS transfer. */ ubp = UBMAP + ((addr >> 13) & 037); addr = exadr(ubp->ub_hi, ubp->ub_lo) + (addr & 017777); } putmemc(addr, getmemc(addr) ^ (int) wrong); byte++; wrong >>= 8; } break; #ifdef BADSECT case BSE: #ifdef HPDEBUG if (hpdebug) printf("hpecc: BSE: bn %D cn %d tn %d sn %d\n", bn, cn, tn, sn); #endif if ((bn = isbad(&hpbad[unit], cn, tn, sn)) < 0) return(0); bp->b_flags |= B_BAD; bp->b_error = npx + 1; bn = (daddr_t)HP_NCYL * (HP_NSECT * HP_NTRAC) - HP_NSECT - 1 - bn; cn = bn/(HP_NSECT * HP_NTRAC); sn = bn%(HP_NSECT * HP_NTRAC); tn = sn/HP_NSECT; sn %= HP_NSECT; #ifdef HPDEBUG if (hpdebug) printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); #endif wc = -(512 / NBPW); break; case CONT: bp->b_flags &= ~B_BAD; #ifdef HPDEBUG if (hpdebug) printf("hpecc, CONT: bn %D cn %d tn %d sn %d\n", bn,cn,tn,sn); #endif break; #endif BADSECT } hptab.b_active++; if (wc == 0) return (0); /* * Have to continue the transfer. Clear the drive * and compute the position where the transfer is to continue. * We have completed npx sectors of the transfer already. */ hpaddr->hpcs2.w = unit; hpaddr->hpcs1.w = HP_TRE | HP_DCLR | HP_GO; addr = bb + ndone; hpaddr->hpdc = cn; hpaddr->hpda = (tn << 8) + sn; hpaddr->hpwc = wc; hpaddr->hpba = (caddr_t)addr; if (hptab.b_flags & B_RH70) hpaddr->hpbae = (int) (addr >> 16); hpaddr->hpcs1.w = ocmd; return (1); } #ifdef HP_DUMP /* * Dump routine for RP04/05/06. * Dumps from dumplo to end of memory/end of disk section for minor(dev). * It uses the UNIBUS map to dump all of memory if there is a UNIBUS map * and this isn't an RH70. */ #define DBSIZE 16 /* number of blocks to write */ hpdump(dev) dev_t dev; { register struct hpdevice *hpaddr = HPADDR; daddr_t bn, dumpsize; long paddr; register sn; register count; long mem; extern size_t physmem; /* number of clicks of real memory */ register struct ubmap *ubp; mem = ((long)physmem) * ctob(1); /* real memory in bytes */ if ((bdevsw[major(dev)].d_strategy != hpstrategy) /* paranoia */ || ((dev=minor(dev)) > (NHP << 3))) return(EINVAL); dumpsize = hp_sizes[dev & 07].nblocks; if ((dumplo < 0) || (dumplo >= dumpsize)) return(EINVAL); dumpsize -= dumplo; hpaddr->hpcs2.w = dev >> 3; if ((hpaddr->hpds & HPDS_VV) == 0) { hpaddr->hpcs1.w = HP_DCLR | HP_GO; hpaddr->hpcs1.w = HP_PRESET | HP_GO; hpaddr->hpof = HPOF_FMT22; } if ((hpaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL)) return(EFAULT); dev &= 07; ubp = &UBMAP[0]; for (paddr = 0L; dumpsize > 0; dumpsize -= count) { count = dumpsize>DBSIZE? DBSIZE: dumpsize; bn = dumplo + (paddr >> PGSHIFT); hpaddr->hpdc= bn / (HP_NSECT*HP_NTRAC) + hp_sizes[dev].cyloff; sn = bn % (HP_NSECT * HP_NTRAC); hpaddr->hpda = ((sn / HP_NSECT) << 8) | (sn % HP_NSECT); hpaddr->hpwc = -(count << (PGSHIFT - 1)); /* * If map exists, use * the map, unless on an 11/70 with RH70. */ if (ubmap && ((hptab.b_flags & B_RH70) == 0)) { ubp->ub_lo = loint(paddr); ubp->ub_hi = hiint(paddr); hpaddr->hpba = 0; hpaddr->hpcs1.w = HP_WCOM | HP_GO; } else { /* * Non-UNIBUS map, or 11/70 RH70 (MASSBUS) */ hpaddr->hpba = loint(paddr); if (hptab.b_flags & B_RH70) hpaddr->hpbae = hiint(paddr); hpaddr->hpcs1.w = HP_WCOM | HP_GO | ((paddr >> 8) & (03 << 8)); } while (hpaddr->hpcs1.w & HP_GO) ; if (hpaddr->hpcs1.w & HP_TRE) { if (hpaddr->hpcs2.w & HPCS2_NEM) return(0); /* made it to end of memory */ return(EIO); } paddr += (DBSIZE << PGSHIFT); if (paddr >= mem) return(0); } return(0); /* filled disk minor dev */ } #endif HP_DUMP #endif NHP pdevice *hpaddr = HPADDR; register struct buf *bp; register unit; struct buf *dp; daddr_t bn; int dn, sn, tn, cn; loop: /* * Pull a request off the controller queue. */ if ((dp = hptab.b_actf) == NULL) return; if ((sys/OTHERS/rp04.06/hpreg.h 444 3 12 26271 4001144565 10171 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)hpreg.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * Definitions for SMD-type disk drives and drivers. That includes DIVA's, * RM02/03/05, RP04/05/06, and everything using the XP driver. */ #if NXPD > 0 /* * Structures used in the xp driver * to describe drives, controllers, and topology */ struct xp_controller { struct buf *xp_actf; /* pointer to next active xputab */ struct buf *xp_actl; /* pointer to last active xputab */ struct hpdevice *xp_addr; /* csr address */ char xp_flags; /* controller-type flags */ char xp_active; /* nonzero if doing a transfer */ }; struct xp_drive { struct xp_controller *xp_ctlr; /* controller to which slave attached */ char xp_type; /* drive type */ char xp_unit; /* slave number */ struct size *xp_sizes; /* pointer to sizes array */ char xp_nsect; char xp_ntrack; int xp_nspc; /* sectors/cylinder */ int xp_cc; /* current cylinder, for RM's */ #ifdef BADSECT int xp_ncyl; /* cylinders per pack */ #endif BADSECT }; /* * bits in xp_flags: */ #define XP_NOCC 1 /* has no current cylinder register */ #define XP_RH70 2 /* uses 22-bit addressing */ #define XP_NOSEARCH 4 /* won't do search commands */ /* * Defines for disk drive type registers */ #define RP 022 /* RP04/5/6 */ #define RM03 024 /* RM03 */ #define RM02 025 /* RM02 */ #define RM05 027 /* RM05 */ /* * These three drive types are dummies because the actual numbers conflict * with DEC controllers. The RM5X and the RM2X actually read as 25; the * Diva Comp VI reads as 22. Xp_drive must be patched at boot time or * initialized. */ #define RM2X 075 /* Fuji 160 with Emulex Controller SC01B */ #define RM5X 076 /* Ampex 815 cyl. RM05 with Emulex Controller */ #define DV 077 /* Diva Comp VI Controller */ #define HP_SECT 22 #define HP_TRAC 19 #define RP06_CYL 815 #define RP04_CYL 411 #define RM_SECT 32 #define RM_TRAC 5 #define RM_CYL 823 #define RM5_SECT 32 #define RM5_TRAC 19 #define RM5_CYL 823 #define RM5X_CYL 815 #define DV_SECT 33 #define DV_TRAC 19 #define DV_CYL 815 #define SI_SECT 48 /* SI Eagle */ #define SI_TRAC 20 #define SI_CYL 842 #define SI_SN_MSK 017400 /* SI serial number mask */ #define SI_SN_DT 07400 /* SI serial number drive type */ #define RM2X_SECT 32 /* Fuji 160 */ #define RM2X_TRAC 10 #define RM2X_CYL 823 #ifdef BADSECT #define NCYL(x) (x) #else !BADSECT #define NCYL(x) /* not used */ #endif BADSECT #ifndef XP_PROBE /* * Macros to inititialize xp_drive entries. These can be used as examples, * or as the actual initializers in ioconf.c. The arguments are the number * of the controller to which the drive is attached, and the physical * drive unit number. Used only if XP_PROBE is not defined. See xp.c * for more information. */ #define RM02_INIT(c,u) \ { &xp_controller[c], RM02, u, &rm_sizes, \ RM_SECT, RM_TRAC, RM_SECT*RM_TRAC, 0, NCYL(RM_CYL) } #define RM03_INIT(c,u) \ { &xp_controller[c], RM03, u, &rm_sizes, \ RM_SECT, RM_TRAC, RM_SECT*RM_TRAC, 0, NCYL(RM_CYL) } #define RM05_INIT(c,u) \ { &xp_controller[c], RM05, u, &rm5_sizes, \ RM5_SECT, RM5_TRAC, RM5_SECT*RM5_TRAC, 0, NCYL(RM5_CYL) } #define RM05X_INIT(c,u) \ { &xp_controller[c], RM05X, u, &rm5_sizes, \ RM5_SECT, RM5_TRAC, RM5_SECT*RM5_TRAC, 0, NCYL(RM5X_CYL) } #define RP06_INIT(c,u) \ { &xp_controller[c], RP, u, &hp_sizes, \ HP_SECT, HP_TRAC, HP_SECT*HP_TRAC, 0, NCYL(RP06_CYL) } #define RP05_INIT(c,u) RP06_INIT(c,u) #define RP04_INIT(c,u) \ { &xp_controller[c], RP, u, &hp_sizes, \ HP_SECT, HP_TRAC, HP_SECT*HP_TRAC, 0, NCYL(RP04_CYL) } #define SI_INIT(c,u) \ { &xp_controller[c], RM05, u, &si_sizes, \ SI_SECT, SI_TRAC, SI_SECT*SI_TRAC, 0, NCYL(SI_CYL) } #define DV_INIT(c,u) \ { &xp_controller[c], DV, u, &dv_sizes, \ DV_SECT, DV_TRAC, DV_SECT*DV_TRAC, 0, NCYL(DV_CYL) } #define RM2X_INIT(c,u) \ { &xp_controller[c], RM2X, u, &rm2x_sizes, \ RM2X_SECT, RM2X_TRAC, RM2X_SECT*RM2X_TRAC, 0, NCYL(RM2X_CYL) } #endif !XP_PROBE #endif NXPD /* * Controller registers and bits */ struct hpdevice { union { int w; char c[2]; } hpcs1; /* control and status 1 register */ short hpwc; /* word count register */ caddr_t hpba; /* UNIBUS address register */ short hpda; /* desired address register */ union { int w; char c[2]; } hpcs2; /* control and status 2 register */ short hpds; /* drive status register */ short hper1; /* error register 1 */ short hpas; /* attention summary register */ short hpla; /* look ahead register */ short hpdb; /* data buffer register */ short hpmr; /* maintenance register (1) */ short hpdt; /* drive type register */ short hpsn; /* serial number register */ short hpof; /* offset register */ short hpdc; /* desired cylinder address register */ short hpcc; /* HP: current cylinder register */ #define rmhr hpcc; /* RM: holding register */ short hper2; /* HP: error register 2 */ #define rmmr2 hper2 /* RM: maintenance register 2 */ short hper3; /* HP: error register 3 */ #define rmer2 hper3 /* RM: error register 2 */ short hpec1; /* burst error bit position */ short hpec2; /* burst error bit pattern */ short hpbae; /* bus address extension register (RH70 only) */ short hpcs3; /* control and status 3 register (RH70 only) */ }; /* Other bits of hpcs1 */ #define HP_SC 0100000 /* special condition */ #define HP_TRE 0040000 /* transfer error */ #define HP_MCPE 0020000 /* MASSBUS control bus read parity error */ /* bit 12 is unused */ #define HP_DVA 0004000 /* drive available */ /* bits 9 and 8 are the extended address bits */ #define HP_RDY 0000200 /* controller ready */ #define HP_IE 0000100 /* interrupt enable */ /* bits 5-1 are the command */ #define HP_GO 0000001 #define HP_BITS \ "\10\20SC\17TRE\16MCPE\14DVA\10RDY\7IE\1GO" /* commands */ #define HP_NOP 000 #define HP_SEEK 004 /* seek */ #define HP_RECAL 006 /* recalibrate */ #define HP_DCLR 010 /* drive clear */ #define HP_RELEASE 012 /* release */ #define HP_OFFSET 014 /* offset */ #define HP_RTC 016 /* return to center-line */ #define HP_PRESET 020 /* read-in preset */ #define HP_PACK 022 /* pack acknowledge */ #define HP_SEARCH 030 /* search */ #define HP_WCDATA 050 /* write check data */ #define HP_WCHDR 052 /* write check header and data */ #define HP_WCOM 060 /* write */ #define HP_WHDR 062 /* write header and data */ #define HP_RCOM 070 /* read data */ #define HP_RHDR 072 /* read header and data */ /* The following two are optionally enabled on some non-DEC controllers */ #define HP_BOOT 074 /* boot */ #define HP_FORMAT 076 /* format */ /* hpcs2 */ #define HPCS2_DLT 0100000 /* data late */ #define HPCS2_WCE 0040000 /* write check error */ #define HPCS2_UPE 0020000 /* UNIBUS parity error */ #define HPCS2_NED 0010000 /* nonexistent drive */ #define HPCS2_NEM 0004000 /* nonexistent memory */ #define HPCS2_PGE 0002000 /* programming error */ #define HPCS2_MXF 0001000 /* missed transfer */ #define HPCS2_MDPE 0000400 /* MASSBUS data read parity error */ #define HPCS2_OR 0000200 /* output ready */ #define HPCS2_IR 0000100 /* input ready */ #define HPCS2_CLR 0000040 /* controller clear */ #define HPCS2_PAT 0000020 /* parity test */ #define HPCS2_BAI 0000010 /* address increment inhibit */ /* bits 2-0 are drive select */ #define HPCS2_BITS \ "\10\20DLT\17WCE\16UPE\15NED\14NEM\13PGE\12MXF\11MDPE\ \10OR\7IR\6CLR\5PAT\4BAI" /* hpds */ #define HPDS_ATA 0100000 /* attention active */ #define HPDS_ERR 0040000 /* composite drive error */ #define HPDS_PIP 0020000 /* positioning in progress */ #define HPDS_MOL 0010000 /* medium on line */ #define HPDS_WRL 0004000 /* write locked */ #define HPDS_LST 0002000 /* last sector transferred */ #define HPDS_DAE 0001000 /* dual access enabled (programmable) */ #define HPDS_DPR 0000400 /* drive present */ #define HPDS_DRY 0000200 /* drive ready */ #define HPDS_VV 0000100 /* volume valid */ /* bits 5-1 are spare */ #define HPDS_OM 0000001 /* offset mode */ #define HPDS_DREADY (HPDS_DPR|HPDS_DRY|HPDS_MOL|HPDS_VV) #define HPDS_BITS \ "\10\20ATA\17ERR\16PIP\15MOL\14WRL\13LST\12DAE\11DPR\10DRY\7VV\1OM" /* hper1 */ #define HPER1_DCK 0100000 /* data check */ #define HPER1_UNS 0040000 /* drive unsafe */ #define HPER1_OPI 0020000 /* operation incomplete */ #define HPER1_DTE 0010000 /* drive timing error */ #define HPER1_WLE 0004000 /* write lock error */ #define HPER1_IAE 0002000 /* invalid address error */ #define HPER1_AOE 0001000 /* address overflow error */ #define HPER1_HCRC 0000400 /* header crc error */ #define HPER1_HCE 0000200 /* header compare error */ #define HPER1_ECH 0000100 /* ecc hard error */ #define HPER1_WCF 0000040 /* write clock fail (0) */ #define HPER1_FER 0000020 /* format error */ #define HPER1_PAR 0000010 /* parity error */ #define HPER1_RMR 0000004 /* register modification refused */ #define HPER1_ILR 0000002 /* illegal register */ #define HPER1_ILF 0000001 /* illegal function */ #define HPER1_BITS \ "\10\20DCK\17UNS\16OPI\15DTE\14WLE\13IAE\12AOE\11HCRC\10HCE\ \7ECH\6WCF\5FER\4PAR\3RMR\2ILR\1ILF" /* hpdt */ #define HPDT_NBA 0100000 /* not block addressed; always 0 */ #define HPDT_TAPE 0040000 /* tape drive; always 0 */ #define HPDT_MH 0020000 /* moving head; always 1 */ /* bit 12 is unused */ #define HPDT_DRR 0004000 /* drive request required */ /* bits 10-9 are unused */ /* bits 8-0 are drive type; the correct values are hard to determine */ #define HPDT_RM05SP 0000047 /* single ported rm05 */ #define HPDT_RM05DP 0000027 /* dual ported rm05 */ #define HPDT_RM02 0000025 /* rm02, possibly rm03? */ #define HPDT_RM03 0000024 /* rm03 */ #define HPDT_RP06 0000022 /* rp06 */ /* hpof */ #define HPOF_FMT22 0010000 /* 16 bit format */ #define HPOF_ECI 0004000 /* ecc inhibit */ #define HPOF_HCI 0002000 /* header compare inhibit */ /* THE SC21 ACTUALLY JUST IMPLEMENTS ADVANCE/RETARD... */ #define HPOF_P400 0020 /* +400 uinches */ #define HPOF_M400 0220 /* -400 uinches */ #define HPOF_P800 0040 /* +800 uinches */ #define HPOF_M800 0240 /* -800 uinches */ #define HPOF_P1200 0060 /* +1200 uinches */ #define HPOF_M1200 0260 /* -1200 uinches */ #define HPOF_BITS \ "\10\15FMT22\14ECI\13HCI\10OD" /* rmer2: These are the bits for an RM error register 2 */ #define RMER2_BSE 0100000 /* bad sector error */ #define RMER2_SKI 0040000 /* seek incomplete */ #define RMER2_DPE 0020000 /* drive plug error */ #define RMER2_IVC 0010000 /* invalid command */ #define RMER2_LSC 0004000 /* loss of system clock */ #define RMER2_LBC 0002000 /* loss of bit clock */ /* bits 9-8 are unused */ #define RMER2_DVC 0000200 /* device check */ /* bits 6-4 are unused */ #define RMER2_MDPE 0000010 /* MASSBUS data read parity error */ /* bits 2-0 are unused */ #define RMER2_BITS \ "\10\20BSE\17SKI\16DPE\15IVC\14LSC\13LBC\10DVC\4MDPE" /* hpcs3 */ #define HPCS3_APE 0100000 /* address parity error */ #define HPCS3_DPE 0060000 /* data parity error */ #define HPCS3_WCE 0017000 /* write check error */ #define HPCS3_DW 0002000 /* double word */ /* bits 9-8 are unused */ #define HPCS3_IE 0000100 /* interrupt enable */ /* bits 5-4 are unused */ /* bits 3-0 are inverted parity check */ #define HPCS3_BITS \ "\10\20APE\17DPE\15WCE\13DW\7IE" nit; struct buf *bp; int as, i, j; as = hpaddr->hpas & 0377; if (hptab.b_active) { #ifdef HP_DKN dk_busy &= ~(1 << (HP_DKN + NHP)); #endif HP_DKN /* * Get device and block structures. Select the drive. */ dp = hptab.b_actf; bp = dp->b_actf; #ifdef BADSECT if (bp->b_flags&B_BAD) if (hpecc(bp, CONT)) sys/OTHERS/rp04.06/hp_config 444 3 12 262 4021147623 10522 echo "#define NHP $NHP" > ../$MACHINE/hp.h echo "#define HP_DKN $HP_DKN" >> ../$MACHINE/hp.h if [ $DUMPROUTINE = hpdump ]; then echo "#define HP_DUMP" >> ../$MACHINE/hp.h fi sys/OTHERS/rp04.06/hpauto.c 444 3 12 47 4021150026 10257 The RP can use the XP probe routines. c0hpreg.hm hp_confighpauto.c hp_conf.chp_scb.s hp_GENERIC.h| hp_autoconfigsys/OTHERS/rp04.06/hp_conf.c 444 3 12 723 5067142260 10430 #include "hp.h" #if NHP > 0 int hpstrategy(), hproot(); extern struct buf hptab; #define hpopen nulldev #define hpclose nulldev #define _hptab &hptab #else #define hpopen nodev #define hpclose nodev #define hproot nulldev #define hpstrategy nodev #define _hptab ((struct buf *) NULL) #endif NHP /* hp = 6 */ hpopen, hpclose, hpstrategy, hproot, _hptab, /* hp = 14 */ hpopen, hpclose, hpread, hpwrite, nodev, nulldev, 0, SELECT(seltrue), hpstrategy, sys/OTHERS/rp04.06/hp_scb.s 444 3 12 214 4021147536 10265 #if NHP > 0 /* RJP04/06, RWP04/06 */ DEVTRAP(254, hpintr, br5) #endif #if NHP > 0 /* RJP04/06, RWP04/06 */ HANDLER(hpintr) #endif h| hp_autoconfigsys/OTHERS/rp04.06/hp_GENERIC 444 3 12 157 4021147650 10334 NHP 0 # RJP04/06, RWP04/06 HP_DKN 0 # drive # for iostat disk monitoring #BOOTDEV rp # rp03 boot device hp_scb.s hp_GENERIC.h| hp_autoconfigsys/OTHERS/rp04.06/hp_autoconfig 444 3 12 57 4021147772 11402 "hp", xpprobe, /* hp -- rjp04/06, rwp04/06 */ hpreg.hm hp_confighpauto.c hp_conf.chp_scb.s hp_GENERIC.h| hp_autoconfigsys/OTHERS/dig_anal/ 755 0 12 0 4056741630 7330 sys/OTHERS/dig_anal/ds.4l 444 3 12 14025 4056741630 10307 .TH DS 4 .LOCAL 4 .SH NAME ds \- digital to analog and analog to digital converters .SH SYNOPSIS device ds0 at uba? csr 0165400 vector dsintr .SH DESCRIPTION .I ds provides the interface to the Digital Systems Corporation DSC 200 converters. .PP The DSC converters are usually used with the programs .I play or .IR record , this description is for those that wish to control the converters directly. .PP The node .B /dev/ds? is the entry to the device for both the analog to digital converters and the digital to analog converters and is closely coupled with the disk where the samples are stored. The ds driver interacts directly with the disk; if the node is opened for reading then analog to digital conversion is assumed and samples are written on the disk, if opened for writing then digital to analog conversion is assumed and samples are read from the disk. (Disk I/O can be completely disabled; see below.) .PP After opening the file for the appropriate conversion one must do several .I ioctl calls to set up the converters. Some are mandatory, the rest are optional and give further control over the converters. (Note that some of these may not be implemented yet or are no longer implemented.) Because some of the .IR ioctl commands require a .I long instead of a .I short there are several structures used for the .IR ioctl s. The first structure is used for setting up various parameters; sequence rams, sample rate, etc., the second for file information. The appropriate declaration for these structures is in the include file .IR : .PP .ta .5i 1i .nf .ft 3 struct ds_seq { short conv; short dirt; short reg; }; .sp struct ds_fs { daddr_t bnosiz; short fs_unused; }; .ft R .fi .PP First we cover the mandatory .IR ioctl s. .PP For setting up the sequence rams several .B DSSEQ .I ioctl calls must be made, this uses the .I ds_seq structure where .I conv specifies a particular converter, .I dirt specifies the direction (either .B AD or .BR DA ), and .I reg selects one of the sequence ram registers. One should consult a local ds oracle to divine what are appropriate values for .I conv as this will vary at each installation, in the current incarnation of the DSC 200 .I reg is restricted to be between 0 and 15 inclusive. After the sequence ram registers are set a .B DSLAST .I ioctl call must be made, this also uses the .I ds_seq structure, the .I reg element contains the number of the last register of a sample frame. .PP To set the sample rate one loads .I dirt of the .I ds_seq structure with the appropriate sample rate and uses the .B DSRATE .I ioctl call. The other fields are ignored. .PP To specify which mass storage device to use the .B DSDEV .I ioctl is used with the .I ds_seq structure with .I dirt containing the number of the mass storage device. Numbers for valid mass storage devices should be obtained from the system guru. .PP Because the .I ds driver interacts directly with the sound storage disk several .IR ioctl s must be made which set up parameters for both converter and disk I/O. These specify the size of the file, the starting block number of the file and the amount of the file to be converted. These .IR ioctl s use the .I ds_fs structure and in all cases the field .I fs_unused is ignored. To set the amount of the file to be converted one loads .I bnosiz with the appropriate value and uses the .B DSCOUNT .IR ioctl . To set the starting block number one loads .I bnosiz and uses the .BR DSBNO .IR ioctl . For .B DSCOUNT the amount specified should be in bytes even though the converters only deal with short integers. .PP Once the conversion parameters are set one merely issues a single .I read (for analog to digital conversion) or .I write (for digital to analog conversion) and the second argument is a buffer that is used by the converters, this buffer is split in half by .I ds since the converters are double buffered, the third argument specifies the total size of the buffer. This buffer must be no smaller than .B DnMINDSB * .B NDSB where .I n selects a mass storage device (see DSDEV). .PP Next we discuss several .I ioctl calls that give one further control over the converters. These .I ioctl calls change with the weather and can vary at each installation, so the include file should be consulted for the most up-to-date information. .PP There are several .I ioctl calls that control the converters' filters. In each of these the pointed-to structure is ignored and can be .BR NULL . .B DS20KHZ specifies that the 20 kHz filters be used, .B DS10KHZ specifies that the 10 kHz filters be used, .B DS5KHZ specifies that the 5 kHz filters be used, and .B DSBYPASS specifies that no filters be used. .PP The .B DSNODSK .I ioctl specifies that no disk I/O be performed. .PP The .B DSBOFF .I ioctl specifies a byte offset within the first buffer, normally the converters take samples from the first location within the buffer, this forces them to start at some point further in the buffer. This only affects the first I/O, after the first buffer all I/O is done at the beginning of the buffer. In an analogous manner one may stop the conversion prematurely in the last buffer by specifying a short count with the .B DSCOUNT .BR ioctl . .PP Finally there is an .I ioctl that gives one a limited ability to determine what went wrong when a conversion is bolixed. This uses the structure .IR ds_errs : .PP .ta .5i 1i .nf .ft 3 struct ds_err { short dma_csr; short asc_csr; short errors; }; .ft R .fi .PP and the .I ioctl call is .BR DSERRS . The .I errors field has bits set according to particular errors, the encoding of these bits is in the include file. .SH FILES /dev/ds? .SH "SEE ALSO" ioctl(2), play(c), record(c) .SH BUGS The .I ds_fs structure is 8 bytes on the VAX because of longword alignment, but since the .I fs_unused field is not used this doesn't seem to be a problem. .PP There is currently no way to have both analog to digital and digital to analog conversion at the same time. .PP No check is made for running off the end of the file. .PP On the VAX the buffer must be page aligned or you'll get clicking when doing d/a conversions. Use valloc(3) to get the buffer. NAME ds \- digital to analog and analog to digital converters .SH SYNOPSIS device ds0 at uba? csr 0165400 vector dsintr .SH DESCRIPTION .I ds provides the interface to the Digital Systems Corporation DSC 200 converters. .PP The DSC converters are usually used with the programs .I play or .IR record , this description is for those that wish to control the converters directly. .PP The node .B /dev/ds? is the entry to the device for both the analog to digital converters and the digital tosys/OTHERS/dig_anal/ds.c 444 3 12 75172 4610731511 10215 /* %M% %I% (CARL) %G% %U% */ static char RCSid[] = "$Header: ds.c,v 1.8 84/10/03 04:44:51 lepreau Exp $"; #include "ds.h" #if NDS > 0 /* * DSC System 200 driver * via DSC dma11. * vax 4.2bsd version */ /* * *=*=*=* BUGS *=*=*=* * * 1. if you #define ZEROBUF it has unpleasant * side effects: it crashes the vax. */ /* * !!! WARNING !!! WARNING !!! WARNING !!! * * since the disk driver strategy routine * is called from the converters' interrupt * level the processor level must not be set * to 0 in the disk driver. also where the * processor level is raised before fiddling * with the buffer list it must not be "raised" * to lower than the dma11's interrupt level. * change the code in the strategy routine to * look something like this: * * (* the following #define causes data lates and was taken out *) * (* # define spl5 spl6 (* converters run at level 6 *) * * opl = spl5(); (* CHANGED *) * dp = &xxutab[ui->ui_unit]; * disksort(dp, bp); * if (dp->b_active == 0) { * xxustart(ui); * bp = &ui->ui_mi->um_tab; * if ((bp->b_actf != NULL) && (bp->b_active == 0)) * xxstart(ui->ui_mi); * } * (void) splx(opl); (* CHANGED *) * * i suspect that you should also bracket the entire disk * interrupt routine with "opl = spl6() ... splx(opl)" but * we get data lates when this is done. the next paragraph * should be read with this in mind. * * the other alternative is to fix your dma11 so that it * interrupts at level 5 instead of level 6. dsc can give * you the information on how to do this. in either event * the strategy routine must be fixed as shown above. */ #include "../h/param.h" #include "../h/systm.h" #include "../h/mount.h" #include "../h/dir.h" #include "../h/user.h" #include "../machine/pte.h" #include "../h/map.h" #include "../h/buf.h" #include "../h/kernel.h" #include "../vaxuba/ubavar.h" #include "../h/conf.h" #include "../h/proc.h" #include "../h/uio.h" #include "../h/file.h" #include "../vaxuba/dsc.h" #include "../vaxuba/dsreg.h" /* * THESE ARE SITE-SPECIFIC * * bulk storage devices * * these can be tape, disk, bubble * or whatever. */ #include "up.h" #include "hp.h" #include "tu.h" #include "te.h" #include "ra.h" #if NSC > 0 extern int upstrategy(); #endif NSC #if NRA > 0 extern int udstrategy(); #endif NRA #if NHT > 0 extern int htstrategy(); #endif NHT #if NHP > 0 extern int hpstrategy(); #endif NHP #if NTE > 0 extern int tmstrategy(); #endif NTE struct bs { dev_t d_cdev; /* chrdev; major+minor */ dev_t d_bdev; /* blkdev; major+minor */ int d_flags; /* buffer flags */ int (*d_io)(); /* strategy routine */ } bs[] = { #if NHP > 0 /* rhp2b */ /* hp2b */ { makedev(4, 17), makedev(0, 17), 0, hpstrategy }, #endif NHP #if NTE > 0 /* rmt8 */ /* mt8 */ { makedev(14,8), makedev(5,8), B_TAPE, tmstrategy } #endif NTE #ifdef NOTDEFED #if NUP > 0 /* rup0c */ /* up0c */ { makedev(13, 2), makedev(2, 2), 0, upstrategy }, /* rup1f */ /* up1f */ { makedev(13, 13), makedev(2, 13), 0, upstrategy }, #endif NUP #if NRA > 0 /* rra0f */ /* ra0f */ { makedev(9, 5), makedev(9, 5), 0, udstrategy }, /* rra1f */ /* ra1f */ { makedev(9, 13), makedev(9, 13), 0, udstrategy }, /* rra2f */ /* ra1f */ { makedev(9, 21), makedev(9, 21), 0, udstrategy }, #endif NRA #if NHT > 0 /* rmt8 */ /* mt8 */ { makedev(14, 8), makedev(5, 8), B_TAPE, htstrategy }, #endif NHT #endif NOTDEFED }; # define NBS (sizeof(bs) / sizeof(bs[0])) /* * THESE ARE SITE-SPECIFIC * * starting base for the * d/a and a/d converters, * for setting up sequence ram. */ # define ADBASE 040 # define DABASE 050 /* * reset device */ # define RESETDEV bit(4) /* * used to be a macro * * # define dsblock(sf) \ * ((((sf)->f_todo - (sf)->f_dcnt) / 512) + (sf)->f_bno) */ extern daddr_t dsblock(); # define size(sf, cnt) \ ((cnt > (sf)->f_bsize) ? (sf)->f_bsize : cnt) # define dsseq(ui, reg, conv, dir) \ ((struct dsdevice *) (ui)->ui_addr)->ascseq[reg] = conv | ((dir & 01) << 6) /* * ds flags */ # define DS_CLOSED 0 # define DS_OPEN bit(0) # define DS_BSY bit(1) # define DS_NDSK bit(2) # define DS_MON bit(3) # define DS_BRD bit(4) /* * params to driver */ # define A_TODO bit(0) # define A_BNO bit(1) # define A_CNT bit(2) # define A_SEQ bit(3) # define A_DEV bit(4) # define A_NBLKS bit(5) # define A_BLIST bit(6) # define MINARG (A_BNO | A_CNT | A_SEQ | A_DEV) # define DSPRI (PZERO-1) /* size of the buffer holding the block list */ # define LISTSIZE MAXBSIZE /* number of disk addresses per buffer */ # define NDADDRS (LISTSIZE / sizeof(daddr_t)) /* * relevant information * about the dma and asc */ struct ds_softc { int c_dmacsr; /* copy of dma csr on error */ int c_asccsr; /* copy of asc csr on error */ int c_flags; /* internal flags */ int c_errs; /* errors, returned via ioctl */ int c_bufno; /* dsubinfo/buffer */ int c_uid; /* user id */ int c_args; /* args received from user */ int c_wticks; /* watch dog */ int c_ubinfo[NDSB]; /* uba info */ int c_bubinfo; /* uba info, 1st buffer, once only */ int c_nblist; /* length of block list */ int c_blkno; /* current block in blist */ int c_mode; /* mode opened for */ struct buf c_dsb[NDSB]; /* bs buffers */ struct buf c_blist; /* block list */ struct buf *c_curb; /* current buffer in block list */ } ds_softc[NDS]; /* * relevant information * about the disking and * other truck */ struct ds_softf { daddr_t f_bno; /* starting block */ off_t f_todo; /* amnt. of file to convert */ off_t f_ccnt; /* amnt. of data not converted */ off_t f_dcnt; /* amnt. of file not diskio'd */ off_t f_icnt; /* amnt. of file not seen by dsintr */ int f_bsize; /* size of each buffer */ int f_boff; /* offset into buffer of first i/o */ int f_dev; /* bs device to use */ } ds_softf[NDS]; int dsprobe(), dsattach(), dsintr(); struct uba_device *dsdinfo[NDS]; u_short dsstd[] = { 0165400, 0 }; struct uba_driver dsdriver = { dsprobe, 0, dsattach, 0, dsstd, "ds", dsdinfo }; /* ARGSUSED */ dsopen(dev, mode) dev_t dev; { register struct dsdevice *dsaddr; register struct uba_device *ui; register struct ds_softc *sc; register struct ds_softf *sf; register int unit; if ((unit = (minor(dev) & ~RESETDEV)) >= NDS) goto bad; if ((ui = dsdinfo[unit]) == NULL) goto bad; if (ui->ui_alive == 0) goto bad; sc = &ds_softc[ui->ui_unit]; sf = &ds_softf[ui->ui_unit]; /* * if this is the reset device * then just do a reset and return. */ if (minor(dev) & RESETDEV) { /* * if the converters are in use then * only the current user or root can * do a reset. */ if (sc->c_flags & DS_OPEN) { if ((sc->c_uid != u.u_ruid) && (u.u_uid != 0)) { return(ENXIO); } } if (dsinit(unit)) { uprintf("ds%d: asc offline\n", ui->ui_unit); return(EIO); } return(0); } /* * only one person can use it * at a time */ if (sc->c_flags & DS_OPEN) bad: return(ENXIO); sc->c_mode = mode; /* * initialize */ if (dsinit(unit)) { uprintf("ds%d: asc offline\n", ui->ui_unit); return(EIO); } sc->c_uid = u.u_ruid; sc->c_flags = DS_OPEN; return(0); } /* ARGSUSED */ dsclose(dev, flag) { register int unit; unit = minor(dev) & ~RESETDEV; ds_softc[unit].c_flags = DS_CLOSED; (void) dsinit(unit); return(0); } dsinit(unit) { register struct dsdevice *dsaddr; register struct uba_device *ui; register struct ds_softc *sc; register struct ds_softf *sf; register short dummy; register int offl; int flts; int odd; if (unit >= NDS) return(1); if ((ui = dsdinfo[unit]) == NULL) return(1); dsaddr = (struct dsdevice *) ui->ui_addr; if (dsaddr->dmacsr & DMA_OFL) offl = 1; else { flts = dsaddr->asccsr & ASC_HZMSK; /* save filters */ dsaddr->asccsr = flts; dsaddr->ascrst = 0; offl = 0; } sc = &ds_softc[ui->ui_unit]; sf = &ds_softf[ui->ui_unit]; odd = 0; /* * flush out last remaining buffer */ if ((sc->c_mode & FREAD) && (sf->f_dcnt > 0) && (sc->c_flags & DS_BSY) && (! (sc->c_flags & DS_NDSK))) { register struct buf *bp; bp = &sc->c_dsb[sc->c_bufno % NDSB]; /* BEGIN DEBUG */ if (sf->f_bsize == 0) { uprintf("dsinit: zero bsize\n"); sc->c_errs |= EDS_CERR; goto out; } /* END DEBUG */ /* sometimes dmawc is odd? */ bp->b_bcount = ~ dsaddr->dmawc; if ((bp->b_bcount % sizeof(short)) != 0) odd = bp->b_bcount; bp->b_bcount -= bp->b_bcount % sizeof(short); bp->b_blkno = dsblock(sf, sc); bp->b_flags &= ~ (B_DONE | B_ERROR); (*bs[sf->f_dev].d_io)(bp); sf->f_dcnt -= sf->f_bsize; out:; } dsfreeall(&sc->c_blist); dsaddr->dmablr = 0; dsaddr->dmasax = 0; dsaddr->dmasar = 0; dsaddr->dmacsr = 0; dsaddr->dmawc = 0; dsaddr->dmaacx = 0; dsaddr->dmaac = 0; dsaddr->dmadr = 0; dsaddr->dmaiva = 0; dsaddr->dmaclr = 0; dsaddr->dmacls = 0; dummy = dsaddr->dmasar; /* clears sar flag */ #ifdef notdef /* * put converters in monitor mode */ if (offl == 0) { dsseq(ui, 0, ADBASE+0, AD); dsseq(ui, 1, ADBASE+1, AD); dsaddr->ascseq[1] |= bit(7); /* last sequence reg */ flts = dsaddr->asccsr & ASC_HZMSK; /* save filters */ dsaddr->asccsr = flts | ASC_RUN | ASC_MON; } #endif notdef /* reset ds_softc */ sc->c_dmacsr = 0; sc->c_asccsr = 0; sc->c_flags = 0; sc->c_errs = 0; sc->c_bufno = 0; sc->c_args = 0; sc->c_blkno = 0; sc->c_mode = 0; /* reset ds_softf */ sf = &ds_softf[ui->ui_unit]; sf->f_bno = 0; sf->f_todo = 0; sf->f_ccnt = 0; sf->f_dcnt = 0; sf->f_icnt = 0; sf->f_bsize = 0; sf->f_boff = 0; sf->f_dev = 0; /* * terminate current run */ sc->c_flags &= ~ DS_BSY; wakeup((caddr_t) &ds_softc[ui->ui_unit]); if (sc->c_flags & DS_BSY) sc->c_errs |= EDS_RST; if (odd) printf("ds%d: dsinit: odd dmawc (%d)\n", ui->ui_unit, odd); return(offl); } /* * f_bsize is the size of the buffers used for the i/o. the buffers are * obtained by taking the user buffer and splitting it into NDSB buffers. * the user buffer should be a multiple of the track size of the disk. * this is for efficiency of disk i/o. * * using uio_resid, iov_base, and f_bsize each buffer header is set up. * the converters only need the base address of the buffer and the word * count. the disk needs these in addition to the block number. if we * are doing d/a conversions then we start the disk up to fill up the * buffers. * * after everything is ready to go we turn on the RUN bit and let 'em rip. */ dsstart(unit, rw, uio) struct uio *uio; { register struct dsdevice *dsaddr; register struct uba_device *ui; register struct ds_softc *sc; register struct ds_softf *sf; register struct iovec *iov; register struct buf *bp; int dummy; int bits; int blr; int opl; int i; sc = &ds_softc[unit]; sf = &ds_softf[unit]; iov = uio->uio_iov; sf->f_bsize = (iov->iov_len / NDSB); /* begin debug */ if (sf->f_bsize == 0) { uprintf("dsstart: zero bsize (1st check)\n"); goto bad; } /* end debug */ /* * make sure we have all * necessary info. */ if ((sc->c_args & MINARG) != MINARG) { sc->c_errs |= EDS_ARGS; goto bad; } /* * either the converters will be writing * to memory or the disk will be. */ if (useracc(iov->iov_base, iov->iov_len, B_WRITE) == NULL) { sc->c_errs |= EDS_ACC; return(EFAULT); } /* * check for misaligned buffer. * * the "% DEV_BSIZE" check isn't correct. it doesn't hurt * though. it probably should be deleted. */ if (((iov->iov_len % DEV_BSIZE) != 0) || (iov->iov_len & 01)) { sc->c_errs |= EDS_MOD; goto bad; } /* * check for tiny buffer */ if (sf->f_bsize < DEV_BSIZE) { sc->c_errs |= EDS_SIZE; goto bad; } /* * check for unreasonable buffer * offset for first buffer */ if (sf->f_boff >= sf->f_bsize) { sc->c_errs |= EDS_ARGS; goto bad; } u.u_procp->p_flag |= SPHYSIO; sc->c_flags |= DS_BSY; vslock(iov->iov_base, (int) iov->iov_len); /* fasten seat belts */ /* * point each c_dsb somewhere into * the user's buffer, set up each c_dsb. * the buffer's rw flag is set to the * inverse of our operation since it * applies to the bulk storage device * i/o to be done. */ for (i = 0; i < NDSB; i++) { bp = &sc->c_dsb[i]; bp->b_un.b_addr = iov->iov_base + (i * sf->f_bsize); bp->b_error = 0; bp->b_proc = u.u_procp; bp->b_flags = bs[sf->f_dev].d_flags | B_PHYS | ((rw == B_READ) ? B_WRITE : B_READ); bp->b_dev = bs[sf->f_dev].d_cdev; bp->b_bcount = sf->f_bsize; bp->b_flags |= B_BUSY; if (rw == B_WRITE) { if ((sc->c_flags & DS_NDSK) == 0) { /* begin debug */ if (sf->f_bsize == 0) { uprintf("dsstart: zero bsize"); uprintf(" i=%d, unit=%d\n", i, unit); /* for printf in wait loop below */ ui = dsdinfo[unit]; sc->c_errs |= EDS_ARGS; goto out; } /* end debug */ bp->b_blkno = dsblock(sf, sc); sc->c_blkno++; /* uprintf("dsstart: blk=%ld, count=%d\n", bp->b_blkno, bp->b_bcount); */ (*bs[sf->f_dev].d_io)(bp); /* iodone will wake us up */ while ((bp->b_flags & B_DONE) == 0) sleep((caddr_t) bp, DSPRI); /* oops */ if (bp->b_flags & B_ERROR) { /* printf("dsstart: disk error (block=%ld)\n", bp->b_blkno); */ sc->c_errs |= EDS_DISK; goto out; } } else bp->b_flags |= B_DONE; sf->f_dcnt -= sf->f_bsize; } else bp->b_flags |= B_DONE; } ui = dsdinfo[unit]; dsaddr = (struct dsdevice *) ui->ui_addr; opl = spl6(); /* * if reading then going to * memory so set W2M */ if (rw == B_WRITE) dsaddr->asccsr |= ASC_PLAY; else { dsaddr->asccsr |= ASC_RECORD; dsaddr->dmacsr |= DMA_W2M; } dsaddr->dmacsr |= DMA_CHN | DMA_SFL; dummy = dsaddr->dmasar; dsaddr->asccsr &= ~ ASC_MON; dummy = dsaddr->ascrst; dsaddr->asccsr |= ASC_IE; dsaddr->dmacls = 0; dsaddr->dmacsr |= DMA_IE; dsaddr->dmawc = -1; /* * if there is a buffer offset * then adjust b_addr temporarily. * this fudging around is done * unconditionally since f_boff * is zeroed in dsopen so if the user * hasn't specified a boff then this * shouldn't affect b_addr. */ if ((blr = size(sf, sf->f_ccnt) - sf->f_boff) <= 0) { sc->c_errs |= EDS_ARGS; goto bad; } sc->c_ubinfo[0] = ubasetup(ui->ui_ubanum, &sc->c_dsb[0], UBA_NEEDBDP); sc->c_bubinfo = sc->c_ubinfo[0] + sf->f_boff; dsaddr->dmablr = ~ (blr >> 1); dsaddr->dmasax = (sc->c_bubinfo >> 16) & 03; dsaddr->dmasar = sc->c_bubinfo; sf->f_ccnt -= blr; #ifdef debug if (sf->f_ccnt <= 0) uprintf("dsstart: dsb0: f_ccnt=%d\n", sf->f_ccnt); #endif debug sc->c_ubinfo[1] = ubasetup(ui->ui_ubanum, &sc->c_dsb[1], UBA_NEEDBDP); /* * set monitor mode or * broadcast mode. */ bits = 0; if (sc->c_flags & DS_MON) bits |= ASC_MON; if (sc->c_flags & DS_BRD) bits |= ASC_BRD; /* * as they say in california, * ``go for it'' */ dsaddr->asccsr |= ASC_RUN | bits; /* * if the file is so small and only uses the first * buffer we would load dmablr with 0 but we can't * do that because we get errors (data late, external * interrupt), so we fudge and give it f_bsize. dsintr * will shut down the converters before it tries to play * the 2nd (bogus) block. */ if ((blr = size(sf, sf->f_ccnt)) <= 0) { #ifdef debug uprintf("dsstart: dsb1: blr=%d\n", blr); #endif debug blr = sf->f_bsize; } dsaddr->dmablr = ~ (blr >> 1); dsaddr->dmasax = (sc->c_ubinfo[1] >> 16) & 03; dsaddr->dmasar = sc->c_ubinfo[1]; sf->f_ccnt -= blr; #ifdef debug if (sf->f_ccnt <= 0) uprintf("dsstart: dsb1: f_ccnt=%d\n", sf->f_ccnt); #endif debug splx(opl); /* * wait for interrupt routine to signal * end of conversions. */ while (sc->c_flags & DS_BSY) sleep((caddr_t) &ds_softc[ui->ui_unit], DSPRI); /* * wait for disk i/o to complete. * release unibus resources. */ out: for (i = 0; i < NDSB; i++) { if ((sc->c_dsb[i].b_flags & B_DONE) == 0) { int waittime; for (waittime = 0; waittime < 7; waittime++) { sleep((caddr_t) &lbolt, DSPRI); if (sc->c_dsb[i].b_flags & B_DONE) goto done; } printf("ds%d: dsb%d: wait timeout\n", ui->ui_unit, i); } done: if (sc->c_ubinfo[i] != 0) { ubarelse(ui->ui_ubanum, &sc->c_ubinfo[i]); sc->c_ubinfo[i] = 0; } } /* * either the disk or the * converters were writing * to memory, thus the B_READ. */ vsunlock(iov->iov_base, (int) iov->iov_len, B_READ); u.u_procp->p_flag &= ~ SPHYSIO; if (sc->c_errs) bad: return(EIO); return(0); } /* * this is where the real work is done. we copy any device registers that * we will be looking at to decrease the amount of traffic on the ds 200 * bus. also you can't do a "read-modify-write" (I think that this is called * a DATIP followed by a DATO in DEC manuals) on any of the ds registers * while the converters are running. * * note that you must write something to the dma11 clear status register * or you'll never get any more interrupts. * * c_wticks gets cleared on each interrupt. dswatch() increments * c_wticks and if c_wticks gets over a threshold then the * addacs are assumed to have hung and we do a reset. */ dsintr(dev) dev_t dev; { register struct dsdevice *dsaddr; register struct ds_softc *sc; register struct ds_softf *sf; register struct buf *bp; register int bufno; register int i; int unit; int blr; unit = minor(dev) & ~RESETDEV; sc = &ds_softc[unit]; sf = &ds_softf[unit]; /* * reset c_wticks */ sc->c_wticks = 0; dsaddr = (struct dsdevice *) dsdinfo[unit]->ui_addr; sc->c_asccsr = dsaddr->asccsr; sc->c_dmacsr = dsaddr->dmacsr; /* * get current buffer */ bufno = sc->c_bufno % NDSB; bp = &sc->c_dsb[bufno]; /* * check to see if any disking * needs to be done */ if (sf->f_dcnt > 0) { if ((bp->b_flags & B_DONE) == 0) { /* printf("dsintr: block not done\n"); */ sc->c_errs |= EDS_DISK; goto out; } if ((sc->c_flags & DS_NDSK) == 0) { /* begin debug */ if (sf->f_bsize == 0) { uprintf("dsintr: zero bsize\n"); sc->c_errs |= EDS_CERR; goto out; } /* end debug */ bp->b_blkno = dsblock(sf, sc); sc->c_blkno++; bp->b_flags &= ~ (B_DONE | B_ERROR); /* uprintf("dsintr: blk=%d, count=%d\n", bp->b_blkno, bp->b_bcount); */ (*bs[sf->f_dev].d_io)(bp); } else bp->b_flags |= B_DONE; sf->f_dcnt -= sf->f_bsize; } /* * check to see if converting * is finished */ if ((sf->f_icnt -= sf->f_bsize) <= 0) goto out; /* * check for converter error. * all errors and normal termination * come here. */ if ((sc->c_dmacsr & (DMA_ERR | DMA_BSY)) != DMA_BSY) { int flts; sc->c_errs |= EDS_CERR; printf("ds%d error: asccsr=%b, dmacsr=%b\n", unit, sc->c_asccsr, ASC_BITS, sc->c_dmacsr, DMA_BITS); out: sc->c_flags &= ~ DS_BSY; flts = dsaddr->asccsr & ASC_HZMSK; /* save filters */ dsaddr->asccsr = flts; /* clears run */ dsaddr->dmacsr = 0; /* turn off dma11 */ wakeup((caddr_t) &ds_softc[unit]); return(0); } /* * reinitialize dma11 */ dsaddr->dmacls = 0; /* * load dma11 registers */ blr = size(sf, sf->f_ccnt); if (sf->f_ccnt > 0) { dsaddr->dmablr = ~ (blr >> 1); dsaddr->dmasax = (sc->c_ubinfo[bufno] >> 16) & 03; dsaddr->dmasar = sc->c_ubinfo[bufno]; } /* * try to catch disk errors */ for (i = 0; i < NDSB; i++) { if (sc->c_dsb[i].b_flags & B_ERROR) { /* printf("dsintr: disk error (block=%ld)\n", sc->c_dsb[i].b_blkno); */ sc->c_errs |= EDS_DISK; goto out; } } /* * update converted byte count. * update buffers converted count. */ sf->f_ccnt -= blr; sc->c_bufno++; #ifdef ZEROBUF /* * last buffer is full of * zeroes */ if (sf->f_ccnt <= sf->f_bsize) { bufno = sc->c_bufno % NDSB; dsbclr(sc->c_dsb[bufno].b_un.b_addr, sc->c_dsb[bufno].b_bcount); } #endif ZEROBUF return(0); } /* * last time i checked, this * didn't work */ dsbclr(base, bcnt) caddr_t base; unsigned int bcnt; { /* debugging stuff */ if (! kernacc(base, bcnt, B_READ)) { uprintf("can't dsbclr\n"); return; } ; /* Avoid asm() label botch */ /* end debugging stuff */ { asm(" movc5 $0,(sp),$0,8(ap),*4(ap)"); } } /* * a/d conversion */ dsread(dev, uio) dev_t dev; struct uio *uio; { int unit; unit = minor(dev) & ~RESETDEV; return(dsstart(unit, B_READ, uio)); /* writes on disk */ } /* * d/a conversion */ dswrite(dev, uio) dev_t dev; struct uio *uio; { int unit; unit = minor(dev) & ~RESETDEV; return(dsstart(unit, B_WRITE, uio)); /* reads from disk */ } /* ARGSUSED */ dsioctl(dev, cmd, addr, flag) dev_t dev; caddr_t addr; { register struct dsdevice *dsaddr; register struct ds_softc *sc; register struct ds_softf *sf; register struct ds_seq *dq; register struct ds_err *de; register struct ds_fs *df; register struct bs *bsp; struct uba_device *ui; struct ds_seq ds_seq; struct ds_err ds_err; struct ds_fs ds_fs; int unit; int flts; int i; unit = minor(dev) & ~RESETDEV; sc = &ds_softc[unit]; sf = &ds_softf[unit]; ui = dsdinfo[unit]; dsaddr = (struct dsdevice *) ui->ui_addr; switch (cmd) { /* put in broadcast mode */ case DSBRD: if (! (sc->c_args & A_SEQ)) { sc->c_errs |= EDS_ARGS; return(EINVAL); } sc->c_flags |= DS_BRD; break; /* put in monitor mode */ case DSMON: if (! (sc->c_args & A_SEQ)) { sc->c_errs |= EDS_ARGS; return(EINVAL); } sc->c_flags |= DS_MON; break; /* set sequence */ case DSSEQ: dq = &ds_seq; bcopy(addr, (caddr_t) dq, sizeof(struct ds_seq)); if ((dq->reg > 15) || (dq->reg < 0)) return(EINVAL); dsseq(ui, (int) dq->reg, (int) dq->conv, (int) dq->dirt); break; /* mark last sequence register */ case DSLAST: dq = &ds_seq; bcopy(addr, (caddr_t) dq, sizeof(struct ds_seq)); if ((dq->reg > 15) || (dq->reg < 0)) return(EINVAL); dsaddr->ascseq[dq->reg] |= bit(7); sc->c_args |= A_SEQ; break; /* starting block number */ case DSBNO: df = &ds_fs; bcopy(addr, (caddr_t) df, sizeof(struct ds_fs)); if (df->bnosiz < 0) return(EINVAL); sf->f_bno = df->bnosiz; sc->c_args |= A_BNO; break; /* no. of bytes to convert */ case DSCOUNT: df = &ds_fs; bcopy(addr, (caddr_t) df, sizeof(struct ds_fs)); /* * DSCOUNT is in bytes so * must be modulo sizeof(short) */ if ((df->bnosiz & 01) || (df->bnosiz <= 0)) return(EINVAL); sf->f_todo = sf->f_dcnt = sf->f_ccnt = sf->f_icnt = df->bnosiz; sc->c_args |= A_CNT; break; /* bs device to use */ case DSDEV: dq = &ds_seq; bcopy(addr, (caddr_t) dq, sizeof(struct ds_seq)); #ifdef MAJMIN for (bsp = &bs[0]; bsp < &bs[NBS]; bsp++) { if (dq->dirt == bsp->d_cdev) break; } if (bsp == &bs[NBS]) return(EINVAL); if (bsdevchk(dq->dirt) == -1) return(EBUSY); #else MAJMIN if ((dq->dirt >= NBS) || (dq->dirt < 0)) return(EINVAL); if (bsdevchk(bs[dq->dirt].d_bdev) == -1) return(EBUSY); #endif MAJMIN sf->f_dev = dq->dirt; sc->c_args |= A_DEV; break; /* set sample rate */ case DSRATE: dq = &ds_seq; bcopy(addr, (caddr_t) dq, sizeof(struct ds_seq)); dsaddr->ascsrt = dq->dirt; break; case DS20KHZ: dsaddr->asccsr &= ~ ASC_HZMSK; dsaddr->asccsr |= ASC_HZ20; /* set 20kHz filter */ break; case DS10KHZ: dsaddr->asccsr &= ~ ASC_HZMSK; dsaddr->asccsr |= ASC_HZ10; /* set 10kHz filter */ break; case DS5KHZ: dsaddr->asccsr &= ~ ASC_HZMSK; dsaddr->asccsr |= ASC_HZ05; /* set 5kHz filter */ break; case DSBYPAS: dsaddr->asccsr &= ~ ASC_HZMSK; dsaddr->asccsr |= ASC_BYPASS; /* set bypass */ break; /* no bs device i/o */ case DSNODSK: sc->c_flags |= DS_NDSK; sc->c_args |= A_DEV | A_BNO; break; /* fetch errors */ case DSERRS: de = &ds_err; de->dma_csr = sc->c_dmacsr; de->asc_csr = sc->c_asccsr; de->errors = sc->c_errs; bcopy((caddr_t) de, addr, sizeof(struct ds_err)); break; /* byte offset into 1st buffer */ case DSBOFF: df = &ds_fs; bcopy(addr, (caddr_t) df, sizeof(struct ds_fs)); /* * DSBOFF is in bytes so * must be modulo sizeof(short) */ if ((df->bnosiz & 01) || (df->bnosiz < 0)) return(EINVAL); sf->f_boff = df->bnosiz; break; /* how many samples actually converted */ case DSDONE: df = &ds_fs; df->bnosiz = sf->f_todo - sf->f_icnt; df->bnosiz += ~ dsaddr->dmawc; bcopy((caddr_t) df, addr, sizeof(struct ds_fs)); break; case DSNBLKS: df = &ds_fs; bcopy(addr, (caddr_t) df, sizeof(struct ds_fs)); if (df->bnosiz < 1) return(EINVAL); sc->c_nblist = df->bnosiz; sc->c_args |= A_NBLKS; break; case DSBLKS: if ((sc->c_args & A_NBLKS) == 0) { sc->c_errs |= EDS_ARGS; return(EINVAL); } for (i = sc->c_nblist * sizeof(daddr_t); i > 0; i -= LISTSIZE) { struct buf *bp; unsigned int amt; bp = geteblk(LISTSIZE); clrbuf(bp); amt = i > LISTSIZE ? LISTSIZE : i; if (copyin(*(caddr_t *)addr, bp->b_un.b_addr, amt)) { dsfreeall(&sc->c_blist); return(EFAULT); } *(caddr_t *)addr += amt; dslink(&sc->c_blist, bp); } sc->c_curb = sc->c_blist.av_forw; sc->c_args |= A_BNO | A_BLIST; break; default: return(ENOTTY); break; } return(0); } /* * link a buffer onto the buffer list * of blocks */ dslink(dp, bp) register struct buf *dp, *bp; { dp->av_back->av_forw = bp; bp->av_back = dp->av_back; dp->av_back = bp; bp->av_forw = dp; } /* * return all of the buffers to * the system */ dsfreeall(dp) register struct buf *dp; { register struct buf *bp; for (bp = dp->av_forw; bp != dp; bp = dp->av_forw) { bp->av_back->av_forw = bp->av_forw; bp->av_forw->av_back = bp->av_back; brelse(bp); } } daddr_t dsblock(sf, sc) register struct ds_softf *sf; register struct ds_softc *sc; { daddr_t blkno; daddr_t *daddrs; register struct buf *bp; if (sc->c_args & A_BLIST) { /* circular block list */ blkno = sc->c_blkno % sc->c_nblist; /* * if we're at the end of this buffer then * move on to the next one. */ if ((blkno % NDADDRS) == 0) { /* special case for first time only */ if (sc->c_bufno != 0) sc->c_curb = sc->c_curb->av_forw; } /* * convert the buffer data from an array of * bytes to an array of longs, then index * into that to get the block. */ daddrs = (daddr_t *) sc->c_curb->b_un.b_addr; blkno = daddrs[blkno % NDADDRS]; } else blkno = ((sf->f_todo - sf->f_dcnt) / 512) + sf->f_bno; return(blkno); } /* * user level entry to dsinit. check that * unit is valid and call dsinit. this is * used by user programs via the dsinit * system call to reset the dacs. */ dsuinit() { register struct uba_device *ui; register struct ds_softc *sc; register int unit; register struct a { int dsunit; } *uap; uap = (struct a *) u.u_ap; if ((unit = uap->dsunit) >= NDS) return(ENXIO); if ((ui = dsdinfo[unit]) == NULL) return(ENXIO); sc = &ds_softc[ui->ui_unit]; /* * possible abnormal termination; * only the current user or root can * terminate an active run */ if (sc->c_flags & DS_OPEN) { if (sc->c_uid != u.u_ruid) { if (u.u_uid != 0) return(ENXIO); } } if (dsinit(ui->ui_unit)) { uprintf("ds%d: asc offline\n", ui->ui_unit); return(EIO); } return(0); } /* * set up asc sequence registers. * dir == 0 means d/a transfer, * dir == 1 means a/d transfer. * * this has been transformed into * a macro * dsseq(ui, reg, conv, dir) register struct uba_device *ui; { register struct dsdevice *dsaddr; register int i, j; dsaddr = (struct dsdevice *) ui->ui_addr; dir = ((dir & 01) << 6); dsaddr->ascseq[reg] = conv | dir; } */ /* * check to see if the indicated bulk storage * device is a mounted filesystem. */ bsdevchk(bsdev) register int bsdev; { register struct mount *mp; for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { if (bsdev == mp->m_dev) { return(EBUSY); } } return(0); } /* * all this just to generate * an interrupt; rather * involved isn't it? */ dsprobe(reg) caddr_t reg; { register int br, cvec; /* value-result */ register struct dsdevice *dsaddr; int dummy; int offl; #ifdef lint br = 0; cvec = br; br = cvec; #endif lint dsaddr = (struct dsdevice *) reg; dsaddr->dmacsr = 0; dsaddr->dmacls = 0; dsaddr->ascseq[0] = DABASE+0 | ((DA & 01) << 6); dsaddr->ascseq[0] |= bit(7); /* last sequence register */ dsaddr->ascsrt = 0100; dsaddr->dmacsr = DMA_IE; dsaddr->asccsr = ASC_RUN | ASC_IE; DELAY(40000); /* * now shut everything down. * too bad we have to duplicate * the code from dsinit but to * call dsinit we need to give * it a unit. */ if ((dsaddr->dmacsr & DMA_OFL) == 0) { dsaddr->asccsr = 0; dsaddr->ascrst = 0; offl = 0; } else offl = 1; dsaddr->dmablr = 0; dsaddr->dmasax = 0; dsaddr->dmasar = 0; dsaddr->dmacsr = 0; dsaddr->dmawc = 0; dsaddr->dmaacx = 0; dsaddr->dmaac = 0; dsaddr->dmadr = 0; dsaddr->dmaiva = 0; dsaddr->dmaclr = 0; dsaddr->dmacls = 0; dummy = dsaddr->dmasar; /* clears sar flag */ #ifdef notdef /* * put converters in monitor mode */ if (offl == 0) { dsaddr->ascseq[0] = ADBASE+0 | ((AD & 01) << 6); dsaddr->ascseq[1] = ADBASE+1 | ((AD & 01) << 6); dsaddr->ascseq[1] |= bit(7); /* last sequence register */ dsaddr->asccsr = ASC_RUN | ASC_MON; } #endif notdef return(sizeof(struct dsdevice)); } dsattach(ui) struct uba_device *ui; { extern int dswatch(); static int dswstart = 0; register struct ds_softc *sc; /* * set up the blist linked list * to the empty list. this must * be done first because dsinit() * calls dsfreeall(). */ sc = &ds_softc[ui->ui_unit]; sc->c_blist.av_forw = &sc->c_blist; sc->c_blist.av_back = &sc->c_blist; (void) dsinit(ui->ui_unit); /* * start watchdog */ if (dswstart == 0) { timeout(dswatch, (caddr_t) 0, hz); dswstart++; } return(0); } /* * c_wticks gets cleared on each interrupt. dswatch() * increments c_wticks and if c_wticks gets over * a threshold then the addacs are assumed to have * hung and we do a reset. */ dswatch() { register struct uba_device *ui; register struct ds_softc *sc; register int ds; /* requeue us */ timeout(dswatch, (caddr_t) 0, hz); for (ds = 0; ds < NDS; ds++) { if ((ui = dsdinfo[ds]) == NULL) continue; if (ui->ui_alive == 0) continue; sc = &ds_softc[ds]; if ((sc->c_flags & DS_BSY) == 0) { sc->c_wticks = 0; continue; } sc->c_wticks++; if (sc->c_wticks >= 25) { sc->c_wticks = 0; printf("ds%d: lost interrupt\n", ds); ubareset(ui->ui_ubanum); } } return(0); } /* * zero uba vector. * shut off converters. * set error bit. */ dsreset(uban) { register struct uba_device *ui; register struct ds_softc *sc; register int ds; register int i; for (ds = 0; ds < NDS; ds++) { if ((ui = dsdinfo[ds]) == NULL) continue; if (ui->ui_alive == 0) continue; if (ui->ui_ubanum != uban) continue; printf(" ds%d", ds); sc = &ds_softc[ds]; /* * this used to be after the ubarelse's, * seems like it should go before them */ if (dsinit(ds)) printf(""); /* * release unibus resources */ for (i = 0; i < NDSB; i++) { if (sc->c_ubinfo[i] != 0) { printf("<%d>", (sc->c_ubinfo[i] >> 28) & 0xf); sc->c_ubinfo[i] = 0; } } } return(0); } #else dsuinit() { return(0); } #endif NVAL); } sc->c_flags |= DS_BRD; break; /* put in monitor mode */ case DSMON: if (! (sc->c_args & A_SEQ)) { sc->c_errs |= EDS_ARGS; return(EINVAL); } sc->c_flags |= DS_MON; break; /* set sequence */ case DSSEQ: dq = &ds_seq; bcopy(addr, (caddr_t) dq, sizeof(struct ds_seq)); if ((dq->reg > 15) || (dq->reg < 0)) return(EINVAL); dssesys/OTHERS/dig_anal/dsc.h 444 3 12 14247 4056741630 10370 /* dsc.h 1.2 (CARL) 1/14/84 09:56:11 */ #include /* * these values are critical; * dsseq depends on da being 0 * and ad being 1 */ # define DA (0) # define AD (1) /* * Errors. * Returned in ds_err.errors. */ # define EDS_ARGS 01 /* missing arguments/parameters */ # define EDS_ACC 02 /* converters in use */ # define EDS_MOD 04 /* buffer size wasn't modulo MINDSB */ # define EDS_SIZE 010 /* buffer size was too small */ # define EDS_DISK 020 /* disk error */ # define EDS_CERR 040 /* converter error */ # define EDS_RST 0100 /* dsreset clobbered us */ /* * Ioctl commands. */ # define DSSEQ _IOW(s, 0, struct ds_seq) /* sequence */ # define DSRATE _IOW(s, 1, struct ds_seq) /* rate */ # define DS20KHZ _IO(s, 2) /* 20kHz filter */ # define DS10KHZ _IO(s, 3) /* 10kHz filter */ # define DS5KHZ _IO(s, 4) /* 5kHz filter */ # define DSBYPAS _IO(s, 5) /* bypass filter */ # define DSERRS _IOR(s, 6, struct ds_err) /* get errors */ # define DSBNO _IOW(s, 7, struct ds_fs) /* starting block */ # define DSTODO _IO(s, 8) /* # of bytes to do */ # define DSCOUNT _IOW(s, 9, struct ds_fs) /* amnt. to convert */ # define DSBOFF _IOW(s, 10, struct ds_fs) /* 1st buffer offset */ # define DSNODSK _IO(s, 11) /* no disking */ # define DSLAST _IOW(s, 12, struct ds_seq) /* last seq ram */ # define DSDEV _IOW(s, 13, struct ds_seq) /* disk to use */ # define DSDONE _IOR(s, 14, struct ds_fs) /* amnt. done */ # define DSMON _IO(s, 15) /* set monitor mode */ # define DSBRD _IO(s, 16) /* set broadcast mode */ # define DSNBLKS _IOW(s, 17, struct ds_fs) /* size of block list */ /* * this one is peculiar. instead of * letting the system do the copyin * for us we do it ourselves. */ # define DSBLKS _IO(s, 18) /* block list */ # define NDSB 2 /* number of buffers chaining with */ /* * THIS IS SITE-SPECIFIC * CONFIGURED FOR DSP-VAX * produces 49152 Hz sampling rate when ASCSRT is set to 0x80 * 4 dacs, 2 adcs, 20KHz and 6.5KHz filters */ # define D0BLPT 32 /* number of blocks per CDC track */ # define D0MINDSB (D0BLPT*512) # define DSCMRCLK 4000000 /* clock frequency */ # define DSCMRTIC (DSCMRCLK/2) # define DSCSRATE 49152.0 # define MAXDACS 2 # define MAXADCS 2 # define DSCFLT0 15000.0 /* 15.0KHz */ # define DSCFLT1 7000.0 /* 7.0KHz */ # define DSCFLT2 0.0 /* bypass mode */ # define DSCFLT3 4000.0 /* 4.0KHz */ # define DSHASDAF0 1 /* has flt0 */ # define DSHASDAF1 1 /* has flt1 */ # define DSHASDAF2 1 /* has bypass */ # define DSHASDAF3 1 /* has flt2 */ # define DSHASADF0 1 /* has flt0 */ # define DSHASADF1 1 /* has flt1 */ # define DSHASADF2 1 /* has bypass */ # define DSHASADF3 1 /* has flt2 */ # ifdef CARL /* * THIS IS SITE-SPECIFIC * CONFIGURED FOR CARL * produces 49152 Hz sampling rate when ASCSRT is set to 0x80 * 4 dacs, 2 adcs, 20KHz and 6.5KHz filters */ # define D0BLPT 32 /* number of blocks per CDC track */ # define D1BLPT 51 /* number of blocks per ra81 track */ # define D0MINDSB (D0BLPT*512) # define D1MINDSB (D0BLPT*512) # define D2MINDSB (D1BLPT*512) # define DSCMRCLK 6291456 /* clock frequency */ # define DSCMRTIC (DSCMRCLK/2) # define DSCSRATE 49152.0 # define MAXDACS 4 # define MAXADCS 2 # define DSCFLT0 20000.0 /* 20.0KHz */ # define DSCFLT1 6.5 /* 6.5KHz */ # define DSCFLT2 0.0 /* bypass mode */ # define DSCFLT3 0.0 /* not installed */ # define DSHASDAF0 1 /* has flt0 */ # define DSHASDAF1 1 /* has flt1 */ # define DSHASDAF2 1 /* has bypass */ # define DSHASDAF3 0 /* not installed */ # define DSHASADF0 1 /* has flt0 */ # define DSHASADF1 1 /* has flt1 */ # define DSHASADF2 1 /* has bypass */ # define DSHASADF3 0 /* not installed */ # endif CARL # ifdef IRCAM /* * THIS IS SITE-SPECIFIC * CONFIGURED FOR IRCAM * produces 48000 Hz sampling rate when ASCSRT is set to 0x80 * 2 dacs, 2 adcs, 12.8KHz and 6.4KHz filters */ # define D0BLPT 31 /* number of blocks per rm80 track */ # define D1BLPT 31 /* additional disks go here */ # define D0MINDSB (D0BLPT*512) # define D1MINDSB (D1BLPT*512) /* additional disks go here */ # define DSCMRCLK 7680000 # define DSCMRTIC (DSCMRCLK/2) # define DSCSRATE 48000.0 # define MAXDACS 2 # define MAXADCS 2 # define DSCFLT0 12800.0 /* 12.8KHz */ # define DSCFLT1 6400.0 /* 6.4KHz */ # define DSCFLT2 0.0 /* bypass mode */ # define DSCFLT3 0.0 /* not installed */ # define DSHASDAF0 1 /* has flt0 */ # define DSHASDAF1 0 /* not installed */ # define DSHASDAF2 1 /* has bypass */ # define DSHASDAF3 0 /* not installed */ # define DSHASADF0 1 /* has flt0 */ # define DSHASADF1 0 /* not installed */ # define DSHASADF2 1 /* has bypass */ # define DSHASADF3 0 /* not installed */ # endif IRCAM # ifdef AMOS /* * THIS IS SITE-SPECIFIC * CONFIGURED FOR AMOS * produces 49152.0 Hz sampling rate when ASCSRT is set to 0x80 * 2 dacs, 1 adc, no filters */ # define D0BLPT 32 /* number of blocks per FUJI track */ # define D1BLPT 32 /* additional disks go here */ # define D0MINDSB (D0BLPT*512) # define D1MINDSB (D0BLPT*512) /* additional disks go here */ # define DSCMRCLK 6291456 /* clock frequency */ # define DSCMRTIC (DSCMRCLK/2) # define DSCSRATE 49152 # define MAXDACS 2 # define MAXADCS 1 # define DSCFLT0 0.0 /* not installed*/ # define DSCFLT1 0.0 /* not installed */ # define DSCFLT2 0.0 /* no bypass mode */ # define DSCFLT3 0.0 /* not installed */ # define DSHASF0 0 /* no flt0 */ # define DSHASF1 0 /* disabled */ # define DSHASF2 0 /* no bypass */ # define DSHASF3 0 /* not installed */ # endif AMOS /* * reg specifies a sequence register (0-15). * conv specifies a converter. * dirt specifies the direction when * setting up the sequence ram (DSSEQ) or the * sampling rate (DSRATE). */ struct ds_seq { short reg; short conv; short dirt; /* shared by DSSEQ and DSRATE */ }; /* * Format of returned converter * errors. */ struct ds_err { short dma_csr; short asc_csr; short errors; }; /* * File information. * The member bnosiz is used for * lots of things; starting block number * of the file, size of the file, amount * to convert, etc. * On the vax this structure * is the wrong size; 8 bytes instead * of the desired 6; fs_unused isn't * used so this shouldn't be a problem. */ struct ds_fs { daddr_t bnosiz; short fs_unused; }; dr_t blkno; daddr_t *daddrs; register struct buf *bp; if (sc->c_args & A_BLIST) { /* circular block list */ blkno = sc->c_blkno % sc->c_nblist; /* * if we're at the end of this buffer then * move on to the next one. */ if ((blkno % NDADDRS) == 0) { /* special case for first time only */ if (sc->c_bufno != 0) sys/OTHERS/dig_anal/dsreg.h 444 3 12 5232 4056741630 10675 /* * DSC System 200 via DSC dma11 * registers and bits */ struct dsdevice { /* dma registers */ short dmablr; /* block length */ u_short dmasax; /* starting address extension */ u_short dmasar; /* starting address */ u_short dmacsr; /* command status */ short dmawc; /* word count */ u_short dmaacx; /* address count extension */ u_short dmaac; /* address count */ u_short dmadr; /* data */ u_short dmaiva; /* interrupt vector */ u_short dmacls; /* clear status */ u_short dmaclr; /* clear device */ u_short unused1; /* asc registers */ u_short ascdis; /* display register */ u_short asccsr; /* command status register */ u_short ascsrt; /* sample rate register */ u_short ascrst; /* reset */ u_short ascseq[16]; /* sequence rams */ /* converter registers */ u_short adc[8]; /* analog to digital converters */ u_short dac[8]; /* digital to analog converters */ }; # define bit(x) ((1) << (x)) /* * ASC csr bits */ # define ASC_RUN bit(0) /* run conversion */ # define ASC_HZ20 (0) /* filter, 20kHz */ # define ASC_HZ10 bit(1) /* filter, 10kHz */ # define ASC_BYPASS bit(2) /* external filter */ # define ASC_HZ05 (bit(1)|bit(2)) /* filter, 5kHz */ # define ASC_RECORD bit(3) /* a/d */ # define ASC_PLAY bit(4) /* d/a */ # define ASC_BRD bit(5) /* broadcast */ # define ASC_MON bit(6) /* monitor */ # define ASC_IE bit(7) /* interrupt enable */ # define ASC_BA bit(8) /* bus abort */ # define ASC_DCN bit(9) /* dc not ok */ # define ASC_DNP bit(12) /* device not present */ # define ASC_DER bit(13) /* device error */ # define ASC_DLT bit(14) /* data late */ # define ASC_ERR bit(15) /* error */ # define ASC_HZMSK (bit(1)|bit(2)) /* to turn off all filter bits */ # define ASC_BITS "\10\01RUN\02HZ10\03BYPASS\04RECORD\05PLAY\06BRD\07MON\10IE\11BA\12DCN\15DNP\16DER\17DLT\20ERR" /* * DMA csr bits */ # define DMA_DRF bit(0) /* data register full */ # define DMA_AMPS bit(1) /* memory port select */ # define DMA_AMPE bit(2) /* memory parity error */ # define DMA_XBA bit(3) /* external buss abort */ # define DMA_W2M bit(4) /* write to memory */ # define DMA_CHN bit(5) /* chain */ # define DMA_IE bit(6) /* interrupt enable */ # define DMA_BSY bit(7) /* busy */ # define DMA_SFL bit(9) /* starting address register full */ # define DMA_OFL bit(10) /* offline */ # define DMA_XIN bit(11) /* external interrupt */ # define DMA_IIN bit(12) /* internal interrrupt */ # define DMA_XER bit(13) /* external error */ # define DMA_UBA bit(14) /* unibus abort */ # define DMA_ERR bit(15) /* error */ # define DMA_BITS "\10\01DRF\02AMPS\03AMPE\04XBA\05W2M\06CHN\07IE\10BSY\12SFL\13OFL\14XIN\15IIN\16XER\17UBA\20ERR" e MAXDACS 2 # define MAXADCS 2 # define DSCFLT0 15000.0 /* 15.0KHz */ # define DSCFLT1 7000.0 /* 7.0KHz */ # define DSCFLT2 0.0 /* bypass mode */ # define DSCFLT3 4000.0 /* 4.0KHz */ # define DSHASDAF0 1 /* has flt0 */ # define DSHASDAF1 1 /* has flt1 */ # define DSHASDAF2 1 /* has bypass */ # define DSHASDAF3 1 /* has flt2 */ # define DSHASADF0 sys/OTHERS/fuji_160/ 755 0 12 0 5325716402 7114 sys/OTHERS/fuji_160/README 444 3 12 713 4056743402 10043 From dual!amd!megatest!cadvax.roman Sat Oct 12 18:34:56 1985 Date: Thu, 10 Oct 85 10:49:07 pdt From: dual!amd!megatest!cadvax.roman (Roman Rycerz) To: lll-crg!seismo!keith Subject: FUJI160 xp driver here is the modified xp driver for FUJI-160's on sc01b and sc03b (emulex) disk controllers... basicly its a double density rm02 disk... also the are changes in the standalone driver as well -roman {lbl-csam,decvax!decwrl![sun|amd|fortune]}!megatest!roman sys/OTHERS/fuji_160/xp.h 444 3 12 311 4056743455 7765 #define NXP 1 #define NXP_CONTROLLER 1 /* #define XP_DKN 0 /* drive # for iostat disk monitoring */ #define XP_DUMP /* include dump routine */ /* #define XP_PROBE /* check drive types at boot */ sys/OTHERS/fuji_160/ioconf.c 444 3 12 11547 5316275713 10660 #include "param.h" #include #include "hk.h" #include "hp.h" #include "hs.h" #include "rk.h" #include "rl.h" #include "rm.h" #include "rp.h" #include "xp.h" dev_t rootdev = makedev(6,0); dev_t swapdev = makedev(6,1); dev_t pipedev = makedev(6,0); int nswap; #ifdef UCB_AUTOBOOT /* * If dumpdev is NODEV, no dumps will be taken automatically. * dump can point to nodev, just to resolve the reference. */ dev_t dumpdev = makedev(6,1); daddr_t dumplo = (daddr_t) 9000; int xpdump(); int (*dump)() = xpdump; #endif UCB_AUTOBOOT /* * Device configuration information. */ #if NHK > 0 struct hkdevice *HKADDR = 0177440; struct size hk_sizes[] = { 5940, 0, /* cyl 0 - 89 */ 2376, 90, /* cyl 90 - 125 */ 45474, 126, /* cyl 126 - 814 */ 18810, 126, /* cyl 126 - 410 */ 0, 0, 0, 0, 27126, 0, /* cyl 0 - 410, whole RK06 */ 53790, 0 /* cyl 0 - 814, whole RK07 */ }; #endif NHK #if NHP > 0 struct hpdevice *HPADDR = 0176700; #endif #if NHP > 0 || NXP > 0 struct size hp_sizes[] = { 9614, 0, /* cyl 0 - 22 */ 8778, 23, /* cyl 23 - 43 */ 153406, 44, /* cyl 44 - 410 (rp04, rp05, rp06) */ 168872, 411, /* cyl 411 - 814 (rp06) */ 322278, 44, /* cyl 44 - 814 (rp06) */ 0, 0, 171798, 0, /* cyl 0 - 410 (whole rp04/5) */ 340670, 0 /* cyl 0 - 814 (whole rp06) */ }; #endif NHP #if NHS > 0 struct hsdevice *HSADDR = 0172040; #endif NHS struct dldevice *KLADDR = 0177560; #if NRK > 0 struct rkdevice *RKADDR = 0177400; #endif NRK #if NRL > 0 struct rldevice *RLADDR = 0174400; #endif NRL #if NRM > 0 struct rmdevice *RMADDR = 0176700; #endif #if NRM > 0 || NXP > 0 struct size rm_sizes[] = { 4800, 0, /* cyl 0 - 29 */ 4800, 30, /* cyl 30 - 59 */ 122080, 60, /* cyl 60 - 822 */ 62720, 60, /* cyl 60 - 451 */ 59360, 452, /* cyl 452 - 822 */ 0, 0, 0, 0, 131680, 0, /* cyl 0 - 822 */ }; #endif NRM #if NRP > 0 struct rpdevice *RPADDR = 0176710; struct size rp_sizes[] = { 10400, 0, /* cyl 0 - 51 */ 5200, 52, /* cyl 52 - 77 */ 67580, 78, /* cyl 78 - 414 */ 0, 0, 0, 0, 0, 0, 0, 0, 83180, 0 /* cyl 0 - 414 */ }; #endif NRP #if NXP > 0 #include /* RM05 */ struct size rm5_sizes[] = { 9120, 0, /* cyl 0 - 14 */ 9120, 15, /* cyl 15 - 29 */ 234080, 30, /* cyl 30 - 414 */ 248064, 415, /* cyl 415 - 822 */ 164160, 30, /* cyl 30 - 299 */ 152000, 300, /* cyl 300 - 549 */ 165376, 550, /* cyl 550 - 822 */ 500384, 0 /* cyl 0 - 822 */ }; /* SI Eagle */ struct size si_sizes[] = { 11520, 0, /* cyl 0 - 11 */ 11520, 12, /* cyl 12 - 23 */ 474240, 24, /* cyl 24 - 517 */ 92160, 518, /* cyl 518 - 613 */ 214080, 614, /* cyl 614 - 836, reserve 5 cyls */ 0, 0, 0, 0, 808320, 0 /* cyl 0 - 841 (everything) */ }; /* Diva Comp V + Ampex 9300 in direct mode */ struct size dv_sizes[] = { 9405, 0, /* cyl 0 - 14 */ 9405, 15, /* cyl 15 - 29 */ 241395, 30, /* cyl 30 - 414 */ 250800, 415, /* cyl 415 - 814 */ 169290, 30, /* cyl 30 - 299 */ 156750, 300, /* cyl 300 - 549 */ 165528, 550, /* cyl 550 - 814 */ 511005, 0 /* cyl 0 - 814 */ }; #ifdef MEGATEST /* FUJI 160 */ struct size rm2x_sizes[] = { 9600, 0, /* cyl 0 - 29 */ 9600, 30, /* cyl 30 - 59 */ 244160, 60, /* cyl 60 - 822 */ 125440, 60, /* cyl 60 - 451 */ 118720, 452, /* cyl 452 - 822 */ 59520, 452, /* cyl 452 - 637 */ 59200, 638, /* cyl 638 - 822 */ 263360, 0 /* cyl 0 - 822 */ }; #endif MEGATEST /* * Xp_controller structure: one line per controller. * Only the address need be initialized in the controller structure * if XP_PROBE is defined (at least the address for the root device); * otherwise the flags must be here also. * The XP_NOCC flag is set for RM02/03/05's (with no current cylinder * register); XP_NOSEARCH is set for Diva's without the search command. * The XP_RH70 flag need not be set here, the driver will always check that. */ struct xp_controller xp_controller[NXP_CONTROLLER] = { /* 0 0 addr flags 0 */ 0, 0, 0176700, XP_NOCC|XP_NOSEARCH, 0 }; /* * Xp_drive structure: one entry per drive. * The drive structure must be initialized if XP_PROBE is not enabled. * Macros are provided in hpreg.h to initialize entries according * to drive type, and controller and drive numbers. * See those for examples on how to set up other types of drives. * With XP_PROBE defined, xpslave will fill in this structure, * and any initialization will be overridden. There is one exception; * if the drive-type field is set, it will be used instead of the * drive-type register to determine the drive's type. */ struct xp_drive xp_drive[NXP] = { #ifndef XP_PROBE #ifdef MEGATEST RM2X_INIT(0,0) /* Expanded RM02, controller 0, drive 0 */ #else RM02_INIT(0,0), /* RM02, controller 0, drive 0 */ RM02_INIT(0,1), /* RM02, controller 0, drive 1 */ RM05X_INIT(0,2) /* 815-cyl RM05, controller 0, drive 2 */ #endif #endif XP_PROBE }; #endif NXP * dump can point to nodev, just to resolve the reference. */ dev_t dumpdev = makedev(6,1); daddr_t dumplo = (daddr_t) 9000; int xpdump(); int (*dump)() sys/OTHERS/fuji_160/include/ 755 0 12 0 4056743456 10550 sys/OTHERS/fuji_160/include/hpreg.h 444 3 12 25675 4056743456 12153 /* * Definitions for SMD-type disk drives and drivers. * This file is used for RM02/03/05, RP04/05/06, * and Diva controllers. */ #if NXP > 0 /* * Structures used in the xp driver * to describe drives, controllers, and topology */ struct xp_controller { struct buf *xp_actf; /* pointer to next active xputab */ struct buf *xp_actl; /* pointer to last active xputab */ struct hpdevice *xp_addr; /* csr address */ char xp_flags; /* controller-type flags */ char xp_active; /* nonzero if doing a transfer */ }; struct xp_drive { struct xp_controller *xp_ctlr; /* controller to which slave attached */ char xp_type; /* drive type */ char xp_unit; /* slave number */ struct size *xp_sizes; /* pointer to sizes array */ char xp_nsect; char xp_ntrack; int xp_nspc; /* sectors/cylinder */ int xp_cc; /* current cylinder, for RM's */ #ifdef BADSECT int xp_ncyl; /* cylinders per pack */ #endif }; /* * bits in xp_flags: */ #define XP_NOCC 1 /* has no current cylinder register */ #define XP_RH70 2 /* uses 22-bit addressing */ #define XP_NOSEARCH 4 /* won't do search commands */ /* * Defines for disk drive type registers */ #define RP 022 /* RP04/5/6 */ #define RM03 024 /* RM03 */ #define RM02 025 /* RM02 */ #define RM05 027 /* RM05 */ /* * These two drive types are dummies because the actual numbers conflict * with DEC controllers. The RM5X actually reads as 25; the Diva Comp VI * reads as 22. Xp_drive must be patched at boot time or initialized. */ #define RM5X 076 /* Ampex 815 cyl. RM05 with Emulex Controller */ #define DV 077 /* Diva Comp VI Controller */ #ifdef MEGATEST #define RM2X 075 /* Fuji 160 with Emulex Controller SC01B */ #endif #define HP_SECT 22 #define HP_TRAC 19 #define RP06_CYL 815 #define RP04_CYL 411 #define RM_SECT 32 #define RM_TRAC 5 #define RM_CYL 823 #define RM5_SECT 32 #define RM5_TRAC 19 #define RM5_CYL 823 #define RM5X_CYL 815 #define DV_SECT 33 #define DV_TRAC 19 #define DV_CYL 815 /* * SI Eagle */ #define SI_SECT 48 #define SI_TRAC 20 #define SI_CYL 842 #define SI_SN_MSK 017400 /* SI serial number mask */ #define SI_SN_DT 07400 /* SI serial number drive type */ #ifdef BADSECT #define NCYL(x) (x) #else #define NCYL(x) /* not used */ #endif BADSECT #ifdef MEGATEST /* * Fuji 160 */ #define RM2X_SECT 32 #define RM2X_TRAC 10 #define RM2X_CYL 823 #endif MEGATEST /* * Macros to inititialize xp_drive entries. These can be used as examples, * or as the actual initializers in ioconf.c. The arguments are the number * of the controller to which the drive is attached, and the physical * drive unit number. Used only if XP_PROBE is not defined. */ #define RM02_INIT(c,u) \ { &xp_controller[c], RM02, u, &rm_sizes, \ RM_SECT, RM_TRAC, RM_SECT*RM_TRAC, 0, NCYL(RM_CYL) } #define RM03_INIT(c,u) \ { &xp_controller[c], RM03, u, &rm_sizes, \ RM_SECT, RM_TRAC, RM_SECT*RM_TRAC, 0, NCYL(RM_CYL) } #define RM05_INIT(c,u) \ { &xp_controller[c], RM05, u, &rm5_sizes, \ RM5_SECT, RM5_TRAC, RM5_SECT*RM5_TRAC, 0, NCYL(RM5_CYL) } #define RM05X_INIT(c,u) \ { &xp_controller[c], RM05X, u, &rm5_sizes, \ RM5_SECT, RM5_TRAC, RM5_SECT*RM5_TRAC, 0, NCYL(RM5X_CYL) } #define RP06_INIT(c,u) \ { &xp_controller[c], RP, u, &hp_sizes, \ HP_SECT, HP_TRAC, HP_SECT*HP_TRAC, 0, NCYL(RP06_CYL) } #define RP05_INIT(c,u) RP06_INIT(c,u) #define RP04_INIT(c,u) \ { &xp_controller[c], RP, u, &hp_sizes, \ HP_SECT, HP_TRAC, HP_SECT*HP_TRAC, 0, NCYL(RP04_CYL) } #define SI_INIT(c,u) \ { &xp_controller[c], RM05, u, &si_sizes, \ SI_SECT, SI_TRAC, SI_SECT*SI_TRAC, 0, NCYL(SI_CYL) } #define DV_INIT(c,u) \ { &xp_controller[c], DV, u, &dv_sizes, \ DV_SECT, DV_TRAC, DV_SECT*DV_TRAC, 0, NCYL(DV_CYL) } #ifdef MEGATEST #define RM2X_INIT(c,u) \ { &xp_controller[c], RM2X, u, &rm2x_sizes, \ RM2X_SECT, RM2X_TRAC, RM2X_SECT*RM2X_TRAC, 0, NCYL(RM2X_CYL) } #endif MEGATEST #endif NXP /* * Controller registers and bits */ struct hpdevice { union { int w; char c[2]; } hpcs1; /* control and status 1 register */ short hpwc; /* word count register */ caddr_t hpba; /* UNIBUS address register */ short hpda; /* desired address register */ union { int w; char c[2]; } hpcs2; /* control and status 2 register */ short hpds; /* drive status register */ short hper1; /* error register 1 */ short hpas; /* attention summary register */ short hpla; /* look ahead register */ short hpdb; /* data buffer register */ short hpmr; /* maintenance register (1) */ short hpdt; /* drive type register */ short hpsn; /* serial number register */ short hpof; /* offset register */ short hpdc; /* desired cylinder address register */ short hpcc; /* HP: current cylinder register */ #define rmhr hpcc; /* RM: holding register */ short hper2; /* HP: error register 2 */ #define rmmr2 hper2 /* RM: maintenance register 2 */ short hper3; /* HP: error register 3 */ #define rmer2 hper3 /* RM: error register 2 */ short hpec1; /* burst error bit position */ short hpec2; /* burst error bit pattern */ short hpbae; /* bus address extension register (RH70 only) */ short hpcs3; /* control and status 3 register (RH70 only) */ }; /* Other bits of hpcs1 */ #define HP_SC 0100000 /* special condition */ #define HP_TRE 0040000 /* transfer error */ #define HP_MCPE 0020000 /* MASSBUS control bus read parity error */ /* bit 12 is unused */ #define HP_DVA 0004000 /* drive available */ /* bits 9 and 8 are the extended address bits */ #define HP_RDY 0000200 /* controller ready */ #define HP_IE 0000100 /* interrupt enable */ /* bits 5-1 are the command */ #define HP_GO 0000001 #define HP_BITS \ "\10\20SC\17TRE\16MCPE\14DVA\10RDY\7IE\1GO" /* commands */ #define HP_NOP 000 #define HP_SEEK 004 /* seek */ #define HP_RECAL 006 /* recalibrate */ #define HP_DCLR 010 /* drive clear */ #define HP_RELEASE 012 /* release */ #define HP_OFFSET 014 /* offset */ #define HP_RTC 016 /* return to center-line */ #define HP_PRESET 020 /* read-in preset */ #define HP_PACK 022 /* pack acknowledge */ #define HP_SEARCH 030 /* search */ #define HP_WCDATA 050 /* write check data */ #define HP_WCHDR 052 /* write check header and data */ #define HP_WCOM 060 /* write */ #define HP_WHDR 062 /* write header and data */ #define HP_RCOM 070 /* read data */ #define HP_RHDR 072 /* read header and data */ /* The following two are optionally enabled on some non-DEC controllers */ #define HP_BOOT 074 /* boot */ #define HP_FORMAT 076 /* format */ /* hpcs2 */ #define HPCS2_DLT 0100000 /* data late */ #define HPCS2_WCE 0040000 /* write check error */ #define HPCS2_UPE 0020000 /* UNIBUS parity error */ #define HPCS2_NED 0010000 /* nonexistent drive */ #define HPCS2_NEM 0004000 /* nonexistent memory */ #define HPCS2_PGE 0002000 /* programming error */ #define HPCS2_MXF 0001000 /* missed transfer */ #define HPCS2_MDPE 0000400 /* MASSBUS data read parity error */ #define HPCS2_OR 0000200 /* output ready */ #define HPCS2_IR 0000100 /* input ready */ #define HPCS2_CLR 0000040 /* controller clear */ #define HPCS2_PAT 0000020 /* parity test */ #define HPCS2_BAI 0000010 /* address increment inhibit */ /* bits 2-0 are drive select */ #define HPCS2_BITS \ "\10\20DLT\17WCE\16UPE\15NED\14NEM\13PGE\12MXF\11MDPE\ \10OR\7IR\6CLR\5PAT\4BAI" /* hpds */ #define HPDS_ATA 0100000 /* attention active */ #define HPDS_ERR 0040000 /* composite drive error */ #define HPDS_PIP 0020000 /* positioning in progress */ #define HPDS_MOL 0010000 /* medium on line */ #define HPDS_WRL 0004000 /* write locked */ #define HPDS_LST 0002000 /* last sector transferred */ #define HPDS_DAE 0001000 /* dual access enabled (programmable) */ #define HPDS_DPR 0000400 /* drive present */ #define HPDS_DRY 0000200 /* drive ready */ #define HPDS_VV 0000100 /* volume valid */ /* bits 5-1 are spare */ #define HPDS_OM 0000001 /* offset mode */ #define HPDS_DREADY (HPDS_DPR|HPDS_DRY|HPDS_MOL|HPDS_VV) #define HPDS_BITS \ "\10\20ATA\17ERR\16PIP\15MOL\14WRL\13LST\12DAE\11DPR\10DRY\7VV\1OM" /* hper1 */ #define HPER1_DCK 0100000 /* data check */ #define HPER1_UNS 0040000 /* drive unsafe */ #define HPER1_OPI 0020000 /* operation incomplete */ #define HPER1_DTE 0010000 /* drive timing error */ #define HPER1_WLE 0004000 /* write lock error */ #define HPER1_IAE 0002000 /* invalid address error */ #define HPER1_AOE 0001000 /* address overflow error */ #define HPER1_HCRC 0000400 /* header crc error */ #define HPER1_HCE 0000200 /* header compare error */ #define HPER1_ECH 0000100 /* ecc hard error */ #define HPER1_WCF 0000040 /* write clock fail (0) */ #define HPER1_FER 0000020 /* format error */ #define HPER1_PAR 0000010 /* parity error */ #define HPER1_RMR 0000004 /* register modification refused */ #define HPER1_ILR 0000002 /* illegal register */ #define HPER1_ILF 0000001 /* illegal function */ #define HPER1_BITS \ "\10\20DCK\17UNS\16OPI\15DTE\14WLE\13IAE\12AOE\11HCRC\10HCE\ \7ECH\6WCF\5FER\4PAR\3RMR\2ILR\1ILF" /* hpdt */ #define HPDT_NBA 0100000 /* not block addressed; always 0 */ #define HPDT_TAPE 0040000 /* tape drive; always 0 */ #define HPDT_MH 0020000 /* moving head; always 1 */ /* bit 12 is unused */ #define HPDT_DRR 0004000 /* drive request required */ /* bits 10-9 are unused */ /* bits 8-0 are drive type; the correct values are hard to determine */ #define HPDT_RM05SP 0000047 /* single ported rm05 */ #define HPDT_RM05DP 0000027 /* dual ported rm05 */ #define HPDT_RM02 0000025 /* rm02, possibly rm03? */ #define HPDT_RM03 0000024 /* rm03 */ #define HPDT_RP06 0000022 /* rp06 */ /* hpof */ #define HPOF_FMT22 0010000 /* 16 bit format */ #define HPOF_ECI 0004000 /* ecc inhibit */ #define HPOF_HCI 0002000 /* header compare inhibit */ /* THE SC21 ACTUALLY JUST IMPLEMENTS ADVANCE/RETARD... */ #define HPOF_P400 0020 /* +400 uinches */ #define HPOF_M400 0220 /* -400 uinches */ #define HPOF_P800 0040 /* +800 uinches */ #define HPOF_M800 0240 /* -800 uinches */ #define HPOF_P1200 0060 /* +1200 uinches */ #define HPOF_M1200 0260 /* -1200 uinches */ #define HPOF_BITS \ "\10\15FMT22\14ECI\13HCI\10OD" /* rmer2: These are the bits for an RM error register 2 */ #define RMER2_BSE 0100000 /* bad sector error */ #define RMER2_SKI 0040000 /* seek incomplete */ #define RMER2_DPE 0020000 /* drive plug error */ #define RMER2_IVC 0010000 /* invalid command */ #define RMER2_LSC 0004000 /* loss of system clock */ #define RMER2_LBC 0002000 /* loss of bit clock */ /* bits 9-8 are unused */ #define RMER2_DVC 0000200 /* device check */ /* bits 6-4 are unused */ #define RMER2_MDPE 0000010 /* MASSBUS data read parity error */ /* bits 2-0 are unused */ #define RMER2_BITS \ "\10\20BSE\17SKI\16DPE\15IVC\14LSC\13LBC\10DVC\4MDPE" /* hpcs3 */ #define HPCS3_APE 0100000 /* address parity error */ #define HPCS3_DPE 0060000 /* data parity error */ #define HPCS3_WCE 0017000 /* write check error */ #define HPCS3_DW 0002000 /* double word */ /* bits 9-8 are unused */ #define HPCS3_IE 0000100 /* interrupt enable */ /* bits 5-4 are unused */ /* bits 3-0 are inverted parity check */ #define HPCS3_BITS \ "\10\20APE\17DPE\15WCE\13DW\7IE" initializers in ioconf.c. The arguments are the number * of the sys/OTHERS/fuji_160/dev/ 755 0 12 0 5325716402 7672 sys/OTHERS/fuji_160/dev/xp.c 444 3 12 42343 5321514543 10577 /* * SCCS id @(#)xp.c 2.1 (Berkeley) 8/23/83 */ /* * RM02/03/05, RP04/05/06, DIVA disk driver. * Fuji 160 added 11/2/84. r2 megatest * SI Eagle added 9/20/83. * This driver will handle most variants of SMD drives * on one or more controllers. * If XP_PROBE is defined, it includes a probe routine * that will determine the number and type of drives attached * to each controller; otherwise, the data structures must be * initialized. * * For simplicity we use hpreg.h instead of an xpreg.h. The bits * are the same. */ #include "xp.h" #if NXP > 0 #include "param.h" #include #include #include #include #include #include #include #ifndef INTRLVE #include #endif #include #define XP_SDIST 2 #define XP_RDIST 6 int xp_offset[] = { HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, 0, 0, 0, 0 }; /* * Xp_drive and xp_controller may be initialized in ioconf.c, * or they may be filled in at boot time if XP_PROBE is enabled. * Xp_controller address fields must be initialized for any boot devices, * however. */ struct xp_drive xp_drive[NXP]; struct xp_controller xp_controller[NXP_CONTROLLER]; struct buf xptab; struct buf xputab[NXP]; #ifdef INTRLVE extern daddr_t dkblock(); #endif /* * Attach controllers whose addresses are known at boot time. * Stop at the first not found, so that the drive numbering * won't get confused. */ xproot() { register i; register struct hpdevice *xpaddr; for (i = 0; i < NXP_CONTROLLER; i++) if (((xpaddr = xp_controller[i].xp_addr) == 0) || (xpattach(xpaddr, i) == 0)) break; } /* * Attach controller at xpaddr. * Mark as nonexistent if xpaddr is 0; * otherwise attach slaves if probing. * NOTE: if probing for drives, this routine must be called * once per controller, in ascending controller numbers. */ xpattach(xpaddr, unit) register struct hpdevice *xpaddr; { register struct xp_controller *xc = &xp_controller[unit]; #ifdef XP_PROBE static int last_attached = -1; #endif if ((unsigned) unit >= NXP_CONTROLLER) return(0); if ((xpaddr != 0) && (fioword(xpaddr) != -1)) { xc->xp_addr = xpaddr; if (fioword(&(xpaddr->hpbae)) != -1) xc->xp_flags |= XP_RH70; #ifdef XP_PROBE /* * If already attached, ignore (don't want to renumber drives) */ if (unit > last_attached) { last_attached = unit; xpslave(xpaddr, xc); } #endif return(1); } xc->xp_addr = 0; return(0); } #ifdef XP_PROBE /* * Determine what drives are attached to a controller; * guess their types and fill in the drive structures. */ xpslave(xpaddr, xc) register struct hpdevice *xpaddr; struct xp_controller *xc; { register struct xp_drive *xd; int j, dummy; static int nxp = 0; #ifdef MEGATEST extern struct size dv_sizes[],hp_sizes[],rm_sizes[],rm5_sizes[],si_sizes[],rm2x_sizes[]; #else extern struct size dv_sizes[],hp_sizes[],rm_sizes[],rm5_sizes[],si_sizes[]; #endif for (j = 0; j < 8; j++) { xpaddr->hpcs1.w = 0; xpaddr->hpcs2.w = j; dummy = xpaddr->hpds; if (xpaddr->hpcs2.w & HPCS2_NED) { xpaddr->hpcs2.w = HPCS2_CLR; continue; } if (nxp < NXP) { xd = &xp_drive[nxp++]; xd->xp_ctlr = xc; xd->xp_unit = j; /* * If drive type is initialized, * believe it. */ if (xd->xp_type == 0) xd->xp_type = xpaddr->hpdt & 077; switch (xd->xp_type) { case RM02: case RM03: xd->xp_nsect = RM_SECT; xd->xp_ntrack = RM_TRAC; xd->xp_nspc = RM_SECT * RM_TRAC; xd->xp_sizes = &rm_sizes; xd->xp_ctlr->xp_flags |= XP_NOCC; break; #ifdef MEGATEST case RM2X: xd->xp_nsect = RM2X_SECT; xd->xp_ntrack = RM2X_TRAC; xd->xp_nspc = RM2X_SECT * RM2X_TRAC; xd->xp_sizes = &rm2x_sizes; xd->xp_ctlr->xp_flags |= XP_NOCC; break; #endif MEGATEST case RM05: case RM5X: if ((xpaddr->hpsn & SI_SN_MSK) == SI_SN_DT) { xd->xp_nsect = SI_SECT; xd->xp_ntrack = SI_TRAC; xd->xp_nspc = SI_SECT * SI_TRAC; xd->xp_sizes = &si_sizes; xd->xp_ctlr->xp_flags |= XP_NOCC; } else { xd->xp_nsect = RM5_SECT; xd->xp_ntrack = RM5_TRAC; xd->xp_nspc = RM5_SECT * RM5_TRAC; xd->xp_sizes = &rm5_sizes; xd->xp_ctlr->xp_flags |= XP_NOCC; } break; case RP: xd->xp_nsect = HP_SECT; xd->xp_ntrack = HP_TRAC; xd->xp_nspc = HP_SECT * HP_TRAC; xd->xp_sizes = &hp_sizes; break; case DV: xd->xp_nsect = DV_SECT; xd->xp_ntrack = DV_TRAC; xd->xp_nspc = DV_SECT * DV_TRAC; xd->xp_sizes = &dv_sizes; xd->xp_ctlr->xp_flags |= XP_NOSEARCH; break; default: printf("xp%d: drive type %o unrecognized\n", nxp - 1, xd->xp_type); xd->xp_ctlr = NULL; break; } } } } #endif XP_PROBE xpstrategy(bp) register struct buf *bp; { register struct xp_drive *xd; register unit; struct buf *dp; short pseudo_unit; int s; long bn; unit = dkunit(bp); pseudo_unit = minor(bp->b_dev) & 07; if ((unit >= NXP) || ((xd = &xp_drive[unit])->xp_ctlr == 0) || (xd->xp_ctlr->xp_addr == 0)) { bp->b_error = ENXIO; goto errexit; } if ((bp->b_blkno < 0) || ((bn = dkblock(bp)) + ((bp->b_bcount + 511) >> 9) > xd->xp_sizes[pseudo_unit].nblocks)) { bp->b_error = EINVAL; errexit: bp->b_flags |= B_ERROR; iodone(bp); return; } if ((xd->xp_ctlr->xp_flags & XP_RH70) == 0) mapalloc(bp); #ifdef EXT_LSI if(bp->b_flags & B_PHYS) if(Sofub_alloc(bp) == 0) return; #endif bp->b_cylin = bn / xd->xp_nspc + xd->xp_sizes[pseudo_unit].cyloff; dp = &xputab[unit]; s = spl5(); disksort(dp, bp); if (dp->b_active == 0) { xpustart(unit); if (xd->xp_ctlr->xp_active == 0) xpstart(xd->xp_ctlr); } splx(s); } /* * Unit start routine. * Seek the drive to where the data are * and then generate another interrupt * to actually start the transfer. * If there is only one drive * or we are very close to the data, don't * bother with the search. If called after * searching once, don't bother to look * where we are, just queue for transfer (to avoid * positioning forever without transferring). */ xpustart(unit) int unit; { register struct xp_drive *xd; register struct hpdevice *xpaddr; register struct buf *dp; struct buf *bp; daddr_t bn; int sn, cn, csn; xd = &xp_drive[unit]; xpaddr = xd->xp_ctlr->xp_addr; xpaddr->hpcs2.w = xd->xp_unit; xpaddr->hpcs1.c[0] = HP_IE; xpaddr->hpas = 1 << xd->xp_unit; if (unit >= NXP) return; #ifdef XP_DKN dk_busy &= ~(1 << (unit + XP_DKN)); #endif dp = &xputab[unit]; if ((bp=dp->b_actf) == NULL) return; /* * If we have already positioned this drive, * then just put it on the ready queue. */ if (dp->b_active) goto done; dp->b_active++; /* * If drive has just come up, * set up the pack. */ if ((xpaddr->hpds & HPDS_VV) == 0) { /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ xpaddr->hpcs1.c[0] = HP_IE | HP_PRESET | HP_GO; xpaddr->hpof = HPOF_FMT22; } #if NXP > 1 /* * If drive is offline, forget about positioning. */ if ((xpaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL)) goto done; /* * Figure out where this transfer is going to * and see if we are close enough to justify not searching. */ bn = dkblock(bp); cn = bp->b_cylin; sn = bn % xd->xp_nspc; sn += xd->xp_nsect - XP_SDIST; sn %= xd->xp_nsect; if (((xd->xp_ctlr->xp_flags & XP_NOCC) && (xd->xp_cc != cn)) || xpaddr->hpcc != cn) goto search; if (xd->xp_ctlr->xp_flags & XP_NOSEARCH) goto done; csn = (xpaddr->hpla >> 6) - sn + XP_SDIST - 1; if (csn < 0) csn += xd->xp_nsect; if (csn > xd->xp_nsect - XP_RDIST) goto done; search: xpaddr->hpdc = cn; xpaddr->hpda = sn; xpaddr->hpcs1.c[0] = (xd->xp_ctlr->xp_flags & XP_NOSEARCH)? (HP_IE | HP_SEEK | HP_GO) : (HP_IE | HP_SEARCH | HP_GO); xd->xp_cc = cn; #ifdef XP_DKN /* * Mark unit busy for iostat. */ unit += XP_DKN; dk_busy |= 1 << unit; dk_numb[unit]++; #endif XP_DKN return; #endif NXP > 1 done: /* * Device is ready to go. * Put it on the ready queue for the controller. */ dp->b_forw = NULL; if (xd->xp_ctlr->xp_actf == NULL) xd->xp_ctlr->xp_actf = dp; else xd->xp_ctlr->xp_actl->b_forw = dp; xd->xp_ctlr->xp_actl = dp; } /* * Start up a transfer on a controller. */ xpstart(xc) register struct xp_controller *xc; { register struct hpdevice *xpaddr; register struct buf *bp; struct xp_drive *xd; struct buf *dp; int unit; short pseudo_unit; daddr_t bn; int sn, tn, cn; xpaddr = xc->xp_addr; loop: /* * Pull a request off the controller queue. */ if ((dp = xc->xp_actf) == NULL) return; if ((bp = dp->b_actf) == NULL) { xc->xp_actf = dp->b_forw; goto loop; } /* * Mark controller busy and * determine destination of this request. */ xc->xp_active++; pseudo_unit = minor(bp->b_dev) & 07; unit = dkunit(bp); xd = &xp_drive[unit]; bn = dkblock(bp); cn = xd->xp_sizes[pseudo_unit].cyloff; cn += bn / xd->xp_nspc; sn = bn % xd->xp_nspc; tn = sn / xd->xp_nsect; sn = sn % xd->xp_nsect; /* * Select drive. */ xpaddr->hpcs2.w = xd->xp_unit; /* * Check that it is ready and online. */ if ((xpaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL)) { xc->xp_active = 0; dp->b_errcnt = 0; dp->b_actf = bp->av_forw; bp->b_flags |= B_ERROR; iodone(bp); goto loop; } if (dp->b_errcnt >= 16 && (bp->b_flags & B_READ)) { xpaddr->hpof = xp_offset[dp->b_errcnt & 017] | HPOF_FMT22; xpaddr->hpcs1.w = HP_OFFSET | HP_GO; while ((xpaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY) ; } xpaddr->hpdc = cn; xpaddr->hpda = (tn << 8) + sn; xpaddr->hpba = bp->b_un.b_addr; if (xc->xp_flags & XP_RH70) xpaddr->hpbae = bp->b_xmem; xpaddr->hpwc = -(bp->b_bcount >> 1); /* * Warning: unit is being used as a temporary. */ unit = ((bp->b_xmem & 3) << 8) | HP_IE | HP_GO; if (bp->b_flags & B_READ) unit |= HP_RCOM; else unit |= HP_WCOM; xpaddr->hpcs1.w = unit; #ifdef XP_DKN unit = xc - &xp_controller[0] + XP_DKN + NXP; dk_busy |= 1 << unit; dk_numb[unit]++; dk_wds[unit] += bp->b_bcount >> 6; #endif } /* * Handle a disk interrupt. */ xpintr(dev) int dev; { register struct hpdevice *xpaddr; register struct buf *dp; struct xp_controller *xc; struct xp_drive *xd; struct buf *bp; register unit; int as, i, j; xc = &xp_controller[dev]; xpaddr = xc->xp_addr; as = xpaddr->hpas & 0377; if (xc->xp_active) { #ifdef XP_DKN dk_busy &= ~(1 << (dev + XP_DKN + NXP)); #endif /* * Get device and block structures. Select the drive. */ dp = xc->xp_actf; bp = dp->b_actf; unit = dkunit(bp); xd = &xp_drive[unit]; xpaddr->hpcs2.c[0] = xd->xp_unit; /* * Check for and process errors. */ if (xpaddr->hpcs1.w & HP_TRE) { while ((xpaddr->hpds & HPDS_DRY) == 0) ; if (xpaddr->hper1 & HPER1_WLE) { /* * Give up on write locked deviced * immediately. */ printf("xp%d: write locked\n", unit); bp->b_flags |= B_ERROR; } else { /* * After 28 retries (16 without offset and * 12 with offset positioning), give up. */ if (++dp->b_errcnt > 28) { #ifdef UCB_DEVERR harderr(bp, "xp"); printf("cs2=%b er1=%b\n", xpaddr->hpcs2.w, HPCS2_BITS, xpaddr->hper1, HPER1_BITS); #else deverror(bp, xpaddr->hpcs2.w, xpaddr->hper1); #endif bp->b_flags |= B_ERROR; } else xc->xp_active = 0; } #ifdef UCB_ECC /* * If soft ecc, correct it (continuing * by returning if necessary). * Otherwise, fall through and retry the transfer. */ if((xpaddr->hper1 & (HPER1_DCK|HPER1_ECH)) == HPER1_DCK) if (xpecc(bp)) return; #endif xpaddr->hpcs1.w = HP_TRE | HP_IE | HP_DCLR | HP_GO; if ((dp->b_errcnt & 07) == 4) { xpaddr->hpcs1.w = HP_RECAL | HP_IE | HP_GO; while ((xpaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY) ; } xd->xp_cc = -1; } if (xc->xp_active) { if (dp->b_errcnt) { xpaddr->hpcs1.w = HP_RTC | HP_GO; while ((xpaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY) ; } xc->xp_active = 0; xc->xp_actf = dp->b_forw; dp->b_active = 0; dp->b_errcnt = 0; dp->b_actf = bp->b_actf; xd->xp_cc = bp->b_cylin; bp->b_resid = - (xpaddr->hpwc << 1); #ifdef EXT_LSI if(bp->b_flags & B_PHYS) Sofub_relse(bp,bp->b_bcount); #endif iodone(bp); xpaddr->hpcs1.w = HP_IE; if (dp->b_actf) xpustart(unit); } as &= ~(1 << xp_drive[unit].xp_unit); } else { if (as == 0) xpaddr->hpcs1.w = HP_IE; xpaddr->hpcs1.c[1] = HP_TRE >> 8; } for (unit = 0; unit < NXP; unit++) if ((xp_drive[unit].xp_ctlr == xc) && (as & (1 << xp_drive[unit].xp_unit))) xpustart(unit); xpstart(xc); } #ifdef UCB_ECC #define exadr(x,y) (((long)(x) << 16) | (unsigned)(y)) /* * Correct an ECC error and restart the i/o to complete * the transfer if necessary. This is quite complicated because * the correction may be going to an odd memory address base * and the transfer may cross a sector boundary. */ xpecc(bp) register struct buf *bp; { register struct xp_drive *xd; register struct hpdevice *xpaddr; register unsigned byte; ubadr_t bb, addr; long wrong; int bit, wc; unsigned ndone, npx; int ocmd; int cn, tn, sn; daddr_t bn; struct ubmap *ubp; int unit; /* * ndone is #bytes including the error * which is assumed to be in the last disk page transferred. */ unit = dkunit(bp); xd = &xp_drive[unit]; xpaddr = xd->xp_ctlr->xp_addr; wc = xpaddr->hpwc; ndone = (wc * NBPW) + bp->b_bcount; npx = ndone / PGSIZE; printf("xp%d%c: soft ecc bn %D\n", unit, 'a' + (minor(bp->b_dev) & 07), bp->b_blkno + (npx - 1)); wrong = xpaddr->hpec2; if (wrong == 0) { xpaddr->hpof = HPOF_FMT22; xpaddr->hpcs1.w |= HP_IE; return (0); } /* * Compute the byte/bit position of the err * within the last disk page transferred. * Hpec1 is origin-1. */ byte = xpaddr->hpec1 - 1; bit = byte & 07; byte >>= 3; byte += ndone - PGSIZE; bb = exadr(bp->b_xmem, bp->b_un.b_addr); wrong <<= bit; /* * Correct until mask is zero or until end of transfer, * whichever comes first. */ while (byte < bp->b_bcount && wrong != 0) { addr = bb + byte; if (bp->b_flags & (B_MAP|B_UBAREMAP)) { /* * Simulate UNIBUS map if UNIBUS transfer. */ ubp = UBMAP + ((addr >> 13) & 037); addr = exadr(ubp->ub_hi, ubp->ub_lo) + (addr & 017777); } putmemc(addr, getmemc(addr) ^ (int) wrong); byte++; wrong >>= 8; } xd->xp_ctlr->xp_active++; if (wc == 0) return (0); /* * Have to continue the transfer. Clear the drive * and compute the position where the transfer is to continue. * We have completed npx sectors of the transfer already. */ ocmd = (xpaddr->hpcs1.w & ~HP_RDY) | HP_IE | HP_GO; xpaddr->hpcs2.w = xd->xp_unit; xpaddr->hpcs1.w = HP_TRE | HP_DCLR | HP_GO; bn = dkblock(bp); cn = bp->b_cylin - (bn / xd->xp_nspc); bn += npx; addr = bb + ndone; cn += bn / xd->xp_nspc; sn = bn % xd->xp_nspc; /* tn = sn / xd->xp_nsect; CC complains about this ??? */ tn = sn; tn /= xd->xp_nsect; sn %= xd->xp_nsect; xpaddr->hpdc = cn; xpaddr->hpda = (tn << 8) + sn; xpaddr->hpwc = ((int)(ndone - bp->b_bcount)) / NBPW; xpaddr->hpba = (int) addr; if (xd->xp_ctlr->xp_flags & XP_RH70) xpaddr->hpbae = (int) (addr >> 16); xpaddr->hpcs1.w = ocmd; return (1); } #endif UCB_ECC #if defined(XP_DUMP) && defined(UCB_AUTOBOOT) /* * Dump routine. * Dumps from dumplo to end of memory/end of disk section for minor(dev). */ #define DBSIZE 16 /* number of blocks to write */ xpdump(dev) dev_t dev; { /* ONLY USE 2 REGISTER VARIABLES, OR C COMPILER CHOKES */ register struct xp_drive *xd; register struct hpdevice *xpaddr; daddr_t bn, dumpsize; long paddr; int sn, count; extern bool_t ubmap; struct ubmap *ubp; if ((bdevsw[major(dev)].d_strategy != xpstrategy) /* paranoia */ || ((dev=minor(dev)) > (NXP << 3))) return(EINVAL); xd = &xp_drive[dev >> 3]; dev &= 07; if (xd->xp_ctlr == 0) return(EINVAL); xpaddr = xd->xp_ctlr->xp_addr; dumpsize = xd->xp_sizes[dev].nblocks; if ((dumplo < 0) || (dumplo >= dumpsize)) return(EINVAL); dumpsize -= dumplo; xpaddr->hpcs2.w = xd->xp_unit; if ((xpaddr->hpds & HPDS_VV) == 0) { xpaddr->hpcs1.w = HP_DCLR | HP_GO; xpaddr->hpcs1.w = HP_PRESET | HP_GO; xpaddr->hpof = HPOF_FMT22; } if ((xpaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL)) return(EFAULT); ubp = &UBMAP[0]; for (paddr = 0L; dumpsize > 0; dumpsize -= count) { count = dumpsize>DBSIZE? DBSIZE: dumpsize; bn = dumplo + (paddr >> PGSHIFT); xpaddr->hpdc = bn / xd->xp_nspc + xd->xp_sizes[dev].cyloff; sn = bn % xd->xp_nspc; xpaddr->hpda = ((sn / xd->xp_nsect) << 8) | (sn % xd->xp_nsect); xpaddr->hpwc = -(count << (PGSHIFT - 1)); if (ubmap && ((xd->xp_ctlr->xp_flags & XP_RH70) == 0)) { ubp->ub_lo = loint(paddr); ubp->ub_hi = hiint(paddr); xpaddr->hpba = 0; xpaddr->hpcs1.w = HP_WCOM | HP_GO; } else { /* * Non-UNIBUS map, or 11/70 RH70 (MASSBUS) */ xpaddr->hpba = loint(paddr); if (xd->xp_ctlr->xp_flags & XP_RH70) xpaddr->hpbae = hiint(paddr); xpaddr->hpcs1.w = HP_WCOM | HP_GO | ((paddr >> 8) & (03 << 8)); } while (xpaddr->hpcs1.w & HP_GO) ; if (xpaddr->hpcs1.w & HP_TRE) { if (xpaddr->hpcs2.w & HPCS2_NEM) return(0); /* made it to end of memory */ return(EIO); } paddr += (DBSIZE << PGSHIFT); } return(0); /* filled disk minor dev */ } #endif XP_DUMP #endif NXP bp); cn = bp->b_cylin; sn = bn % xd->xp_nspc; sn += xd->xp_nsect - XP_SDIST; sn %= xd->xp_nsect; if (((xd->xp_ctlr->xp_flags & XP_NOCC) && (xd->xp_cc != cn)) || xpaddr->hpcc != cn) goto search; if (xd->xp_ctlr->xp_flags & XP_NOSEARCH) goto done; csn = (xpaddr->hpla >>sys/OTHERS/fuji_160/libsa/ 755 0 12 0 4056743526 10215 sys/OTHERS/fuji_160/libsa/xp.c 444 3 12 10254 4056743462 11117 /* * RP04/RP06 disk driver */ #include #include #include "../saio.h" struct device { union { int w; char c[2]; } xpcs1; /* Control and Status register 1 */ int xpwc; /* Word count register */ caddr_t xpba; /* UNIBUS address register */ int xpda; /* Desired address register */ union { int w; char c[2]; } xpcs2; /* Control and Status register 2*/ int xpds; /* Drive Status */ int xper1; /* Error register 1 */ int xpas; /* Attention Summary */ int xpla; /* Look ahead */ int xpdb; /* Data buffer */ int xpmr; /* Maintenance register */ int xpdt; /* Drive type */ int xpsn; /* Serial number */ int xpof; /* Offset register */ int xpdc; /* Desired Cylinder address register*/ int xpcc; /* Current Cylinder */ int xper2; /* Error register 2 */ int xper3; /* Error register 3 */ int xpec1; /* Burst error bit position */ int xpec2; /* Burst error bit pattern */ int xpbae; /* 11/70 bus extension */ int xpcs3; }; #define XPADDR ((struct device *)0176700) /* * Defines for Disk Type Independence */ #define RP 022 /* RP04/5/6 */ #define RM2 025 /* RM02/3 */ #define RM3 024 /* RM02/3 */ #define RM5 027 /* RM05 */ #define RM5X 076 /* Emulex + Ampex 9300CD */ #define DVHP 077 /* Diva */ #ifdef MEGATEST #define RM2X 075 /* Emulex SC01B + Fuji 160 */ #endif MEGATEST #define HP_SECT 22 #define HP_TRAC 19 #define RM_SECT 32 #define RM_TRAC 5 #ifdef MEGATEST #define RM2X_SECT 32 #define RM2X_TRAC 10 #endif MEGATEST #define DV_TRAC 19 #define DV_SECT 33 #define P400 020 #define M400 0220 #define P800 040 #define M800 0240 #define P1200 060 #define M1200 0260 #define GO 01 #define PRESET 020 #define RTC 016 #define OFFSET 014 #define SEARCH 030 #define RECAL 06 #define DCLR 010 #define WCOM 060 #define RCOM 070 #define IE 0100 #define PIP 020000 #define DRY 0200 #define ERR 040000 #define TRE 040000 #define DCK 0100000 #define WLE 04000 #define ECH 0100 #define VV 0100 #define FMT22 010000 extern char haveCSW; /* bool, set if switch register exists */ #ifdef MEGATEST int xptype = RM2X; /* drive type; declared so we can patch */ #else int xptype = RM2; /* drive type; declared so we can patch */ #endif MEGATEST xpstrategy(io, func) register struct iob *io; { register unit; register i; register nm_sect_per_cyl,nsect; daddr_t bn; int sn, cn, tn; if (((unit = io->i_unit) & 04) == 0) bn = io->i_bn; else { unit &= 03; bn = io->i_bn; bn -= io->i_boff; i = unit + 1; unit = bn%i; bn /= i; bn += io->i_boff; } XPADDR->xpcs2.w = unit; if((XPADDR->xpds & VV) == 0) { XPADDR->xpcs1.c[0] = PRESET|GO; XPADDR->xpof = FMT22; } /* * This next weirdness handled the look up into the Drive Type * register to tell what type of disk we have here. * Look in switch register first (if there is one). * * Note: No need to look up after the first time. */ if (xptype == 0) { if (haveCSW && (*CSW == RM2 || *CSW == RM3 || *CSW == RM5 || *CSW == RM5X || *CSW == RP || *CSW == DVHP #ifdef MEGATEST || *CSW == RM2X #endif MEGATEST )) xptype = *CSW; else xptype = (XPADDR->xpdt & 077); } switch(xptype) { case RM2: case RM3: nm_sect_per_cyl = RM_SECT * RM_TRAC; nsect = RM_SECT; break; #ifdef MEGATEST case RM2X: nm_sect_per_cyl = RM2X_SECT * RM2X_TRAC; nsect = RM2X_SECT; break; #endif MEGATEST case RM5: case RM5X: nm_sect_per_cyl = RM_SECT * HP_TRAC; nsect = RM_SECT; break; case RP: nm_sect_per_cyl = HP_SECT * HP_TRAC; nsect = HP_SECT; break; case DVHP: nm_sect_per_cyl = DV_SECT * DV_TRAC; nsect = DV_SECT; break; default: printf("xp: unknown device type 0%o\n", xptype); return(-1); } cn = bn/(nm_sect_per_cyl); sn = bn%(nm_sect_per_cyl); tn = sn/nsect; sn = sn%nsect; XPADDR->xpdc = cn; XPADDR->xpda = (tn << 8) + sn; XPADDR->xpba = io->i_ma; XPADDR->xpwc = -(io->i_cc>>1); unit = (segflag << 8) | GO; if (func == READ) unit |= RCOM; else if (func == WRITE) unit |= WCOM; XPADDR->xpcs1.w = unit; while ((XPADDR->xpcs1.w&DRY) == 0) ; if (XPADDR->xpcs1.w & TRE) { printf("disk error: cyl=%d track=%d sect=%d cs2=%o, er1=%o\n", cn, tn, sn, XPADDR->xpcs2, XPADDR->xper1); return(-1); } return(io->i_cc); } == 0) ; if (xpaddr->hper1 & HPER1_WLE) { /* * Give up on write locked deviced * immediately. */ printf("xp%d: write locked\n", unit); bp->b_flags |= B_ERROR; } else { /* * After 28 retries (16 without offset and * 12 with offset positioning), give up. */ if (++dp->b_errcnt > 28) sys/OTHERS/tektronix/ 755 0 12 0 5123225245 7614 sys/OTHERS/tektronix/tektronix 444 3 12 7637 5067140664 11701 From hao!cires!david Mon Nov 25 19:33:46 1985 From: hao!cires!david Date: Mon, 25 Nov 85 14:50:27 mst To: hao!seismo!bostic Also, I've attached a fast Tektronix driver that seems to work -- the only change I made from the old USGS version was to add the UCB_DEVERR stuff. It doesn't autoconfigure so l.s and c.c have to be modified appropriately. Thanks again for your help, David ------------- cut here for fast_tek.c -------------- #include #include #include #include #include #include #include /* * fast_tty: * Special device driver to utilize the USGS fast * tektronix interface (DR11-B to Minibus). Essentially, * the tektronix is connected by both a serial line * and a parallel line. If the output requires no * translation, then raw dma from the user's buffer is * done via the dr11-b. Ordinary output and input are * routed through the serial line and the serial line's * device driver.The association table of which serial * line goes with which parallel unit is given in conf.c */ #define NDR11 1 /* number of fast tty's */ #define DRPRI (PZERO+20) #define SYN 026 /* ascii "syn" char-- invisable to tek's */ /* drst control bits */ #define GO 1 #define WRITE 0400 /* actually unused */ #define IE 0100 /* internal state bits */ #define ACTIVE 1 /* output via dr11-b */ #define ODDB 2 /* single byte output via dr11-b */ struct device { int drwc; caddr_t drba; int drst; int drdb; } *fast_dr[NDR11] = { 0172410 }; /* last number (11) in following line is tty port mapping */ dev_t fast_map[NDR11] = { (4<<8)+11 }; struct { int state; int bc; } fast[NDR11]; int wd; struct buf fast_buf; extern fast_start(); fast_open(dev, flag) dev_t dev; int flag; { int d; d=minor(dev); if(d >= NDR11) { u.u_error = ENXIO; return; } (*cdevsw[major(fast_map[d])].d_open)(fast_map[d],flag); fast[d].state = 0; fast_buf.b_flags = B_DONE; } fast_close(dev,flag) dev_t dev; int flag; { int d; d = minor(dev); fast[d].state = 0; (*cdevsw[major(fast_map[d])].d_close)(fast_map[d],flag); } fast_read(dev) dev_t dev; { register d; d = minor(dev); (*cdevsw[major(fast_map[d])].d_read)(fast_map[d]); } fast_write(dev, uio) dev_t dev; struct uio *uio; { register d; register struct device *addr; d = minor(dev); if(fast[d].state&ACTIVE) { addr = fast_dr[d]; if(u.u_base&1) { /* odd base address */ wd = fuword(u.u_base)& ~0377 + SYN; fast[d].state |= ODDB; addr->drba = &wd; addr->drwc = -1; addr->drst = WRITE+GO+IE; while( fast[d].state&ODDB) sleep((caddr_t)&fast[d].state,DRPRI); u.u_base++; u.u_count--; } if(u.u_count) { fast[d].bc = u.u_count; if(u.u_count&1) u.u_count++; physio(fast_start, &fast_buf, dev, B_WRITE, uio); } } else { /* do it via the serial line */ (*cdevsw[major(fast_map[d])].d_write)(fast_map[d]); } } fast_ioctl(dev, cmd, addr, flag) dev_t dev; int cmd; caddr_t addr; int flag; { switch(cmd) { case ('x'<<8)+0: fast[minor(dev)].state = ACTIVE; break; case ('x'<<8)+1: fast[minor(dev)].state = 0; break; default: (*cdevsw[major(fast_map[minor(dev)])].d_ioctl) (fast_map[minor(dev)], cmd, addr, flag); } } fast_start(bp) register struct buf *bp; { register struct device *addr; if(bp->b_flags&B_PHYS) mapalloc(bp); addr=fast_dr[minor(bp->b_dev)]; addr->drba = bp->b_un.b_addr; addr->drwc = - (bp->b_bcount>>1); addr->drst = ((bp->b_xmem&3)<<4)+IE+WRITE+GO; } fast_intr(dev) dev_t dev; { register struct device *addr; register struct buf *bp = &fast_buf; addr = fast_dr[dev]; if(addr->drst <0) #ifdef UCB_DEVERR { harderr(bp, "fast"); printf("st=%o wc=%o\n", addr->drst, addr->drwc); } #else deverror(bp, addr->drst, addr->drwc); #endif UCB_DEVERR if(fast[dev].state&ODDB) { fast[dev].state &= ~ODDB; wakeup(&fast[dev].state); } else iodone(bp); addr->drst=0; /* resets dr11b status, ewh, cires 5-29-80 */ } 11-b */ struct device { int drwc; caddr_t drba; int drst; int drdb; } *fast_dr[NDR11] = { 01sys/OTHERS/kl/ 755 0 12 0 4057146233 6177 sys/OTHERS/kl/kl.c 444 3 12 26520 4057146226 7066 /* * KL/DL-11 driver * */ #include "kl.h" #include "param.h" #include #include #include #include #include #include #include /* * SCCS id @(#)kl.c 2.1 (Berkeley) 9/1/83 * * modified 12/84 by keith packard to make a new * minor device type that doesn't wait for * carrier on open; useful for dial out modem lines * * modified 11/84 by keith packard to handle modem control * on dlv11e cards several more constants added to * /usr/include/sys/klreg.h * * modified 9/84 by Keith Packard for use with dl11-e cards * which have programmable baud rate selection. Also see * the modified /usr/include/sys/klreg.h which has another * constant added for this change. You must define * MIN_SPEED, MAX_SPEED and MIN_MODEM, MAX_MODEM to select * which devices have this feature by editing kl.h. */ #ifdef MIN_MODEM # define KLNOWAIT 0100 # define klunit(d) (minor(d) & ~KLNOWAIT) # define klignore(d) (minor(d) & KLNOWAIT) int klwait[MAX_MODEM - MIN_MODEM + 1]; /* * KLIGNORE is set when the ignore-carrier device * is opened. */ # define KLIGNORE 1 /* * KLSOFTCAR is set while the ignore-carrier device * is actually ignoring carrier. It stops ignoring * carrier when carrier is detected - this way * when carrier drops, the dial-out program can * detect it. */ # define KLSOFTCAR 2 /* * KLWAIT is set when a process is waiting for the * modem to become dial-in again */ # define KLWAIT 4 #else MIN_MODEM # define klunit(d) minor(d) #endif MIN_MODEM extern struct dldevice *KLADDR; /* * Normal addressing: * minor 0 addresses KLADDR * minor 1 thru n-1 address from KLBASE (0176600), * where n is the number of additional KL11's * minor n on address from DLBASE (0176500) */ struct tty kl11[NKL]; int nkl11 = NKL; /* for pstat */ int klstart(); int ttrstrt(); extern char partab[]; klattach(addr, unit) struct dldevice *addr; { if ((unsigned) unit <= NKL) { kl11[unit].t_addr = addr; return(1); } return(0); } /*ARGSUSED*/ klopen(dev, flag) dev_t dev; { register struct dldevice *addr; register struct tty *tp; register d; d = klunit(dev); tp = &kl11[d]; if ((d == 0) && (tp->t_addr == 0)) tp->t_addr = KLADDR; if ((d >= NKL) || ((addr = tp->t_addr) == 0)) { u.u_error = ENXIO; return; } tp->t_oproc = klstart; tp->t_state |= WOPEN; /* * set up default if the device is not open yet */ if ((tp->t_state & ISOPEN) == 0) { tp->t_flags = ODDP | EVENP | ECHO | XTABS | CRMOD; tp->t_line = DFLT_LDISC; tp->t_ispeed = B1200; tp->t_ospeed = B1200; ttychars(tp); klparam(d); #ifdef MIN_MODEM /* * don't allow both kinds of open (non-modem and modem) * on modem lines at the same time. */ } else if ((tp->t_state & XCLUDE || (tp->t_dev && dev != tp->t_dev)) && u.u_uid != 0) { #else } else if (tp->t_state & XCLUDE && u.u_uid != 0) { #endif u.u_error = EBUSY; return; } #ifdef MIN_MODEM addr->dlrcsr = DL_RIE | DL_DTR | DL_DIE | DL_RTS; kleopen (dev); #else MIN_MODEM tp->t_state |= CARR_ON; addr->dlrcsr |= DL_RIE | DL_DTR | DL_RE; #endif MIN_MODEM addr->dlxcsr |= DLXCSR_TIE; ttyopen(dev, tp); } /*ARGSUSED*/ klclose(dev, flag) dev_t dev; int flag; { register struct tty *tp; register int unit; register struct dldevice *addr; int s, j; unit = klunit(dev); #ifdef MIN_MODEM tp = &kl11[unit]; addr = tp->t_addr; s = spl5 (); /* * wake up sleeping processes * that await the modem controlled line * line and don't reset the device if * someone is there waiting */ if (klignore (tp->t_dev) && MIN_MODEM <= unit && unit <= MAX_MODEM) { klwait [unit - MIN_MODEM] &= ~KLIGNORE; if ((klwait [unit - MIN_MODEM] & KLWAIT) != 0) { wakeup ((caddr_t) &klwait[unit - MIN_MODEM]); addr->dlrcsr = DL_RIE | DL_DTR | DL_DIE | DL_RTS; goto noreset; } } if (tp->t_state & HUPCLS) addr->dlrcsr &= ~(DL_DTR | DL_DIE | DL_RIE | DL_RTS); else addr->dlrcsr &= ~(DL_DIE | DL_RIE | DL_RTS); j = addr->dlrbuf; noreset: ; splx (s); tp->t_dev = 0; #endif MIN_MODEM ttyclose(&kl11[unit]); } klread(dev) dev_t dev; { register struct tty *tp; tp = &kl11[klunit(dev)]; (*linesw[tp->t_line].l_read)(tp); } klwrite(dev) dev_t dev; { register struct tty *tp; tp = &kl11[klunit(dev)]; (*linesw[tp->t_line].l_write)(tp); } klxint(dev) dev_t dev; { register struct tty *tp; tp = &kl11[klunit(dev)]; ttstart(tp); if (tp->t_state & ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) #ifdef MPX_FILS if (tp->t_chan) mcstart(tp->t_chan, (caddr_t) &tp->t_outq); else #endif wakeup((caddr_t) &tp->t_outq); } klrint(dev) dev_t dev; { register int c; register struct dldevice *addr; register struct tty *tp; int unit, flags; int s; unit = klunit(dev); tp = &kl11[unit]; addr = (struct dldevice *) tp->t_addr; #ifdef MIN_MODEM flags = addr->dlrcsr; c = addr->dlrbuf; if (MIN_MODEM <= unit && unit <= MAX_MODEM && (flags & DL_DSI)) { wakeup ((caddr_t)&tp->t_rawq); if (!(flags & DL_CARDET) && (tp->t_state & CARR_ON)) { /* * carrier dropped */ #ifdef UCB_NTTY if ((tp->t_state & WOPEN) == 0 && (tp->t_local & LMDMBUF)) { tp->t_state &= ~CARR_ON; tp->t_state |= TTSTOP; } else #endif UCB_NTTY if ((tp->t_state & WOPEN)==0 #ifdef UCB_NTTY && (tp->t_local & LNOHANG)==0 #endif UCB_NTTY /* * send this signal only if carrier * used to be up. */ && (!(klwait[unit-MIN_MODEM] & KLSOFTCAR))) { tp->t_state &= ~CARR_ON; gsignal(tp->t_pgrp, SIGHUP); flushtty(tp, FREAD|FWRITE); } } else if ((flags & DL_CARDET) && !(tp->t_state & CARR_ON)) { /* * carrier up */ tp->t_state |= CARR_ON; /* * once we have seen a carrier, * stop ignoring it's transitions */ klwait[unit-MIN_MODEM] &= ~KLSOFTCAR; #ifdef UCB_NTTY if ((tp->t_state & WOPEN) == 0 && (tp->t_local & LMDMBUF)) { tp->t_state &= ~TTSTOP; ttstart (tp); } #endif UCB_NTTY } else if ((flags & DL_CTS) && (tp->t_state & TTSTOP)) { tp->t_state &= ~TTSTOP; ttstart (tp); } else if (!(flags & DL_CTS) && !(tp->t_state & TTSTOP)) tp->t_state |= TTSTOP; } if (flags & DL_RDONE) (*linesw[tp->t_line].l_input)(c, tp); #else MIN_MODEM c = addr->dlrbuf; addr->dlrcsr |= DL_RE; (*linesw[tp->t_line].l_input)(c, tp); #endif MIN_MODEM } klioctl(dev, cmd, addr, flag) caddr_t addr; dev_t dev; { register int unit; register struct dldevice *dl; int s; unit = klunit(dev); switch (ttioctl(&kl11[unit], cmd, addr, flag)) { #ifdef MIN_SPEED case TIOCSETN: case TIOCSETP: if (MIN_SPEED <= unit && unit <= MAX_SPEED) klparam (unit); break; #endif MIN_SPEED #ifdef MIN_MODEM case TIOCSDTR: if (MIN_MODEM <= unit && unit <= MAX_MODEM) { dl = (struct dldevice *) kl11[unit].t_addr; s = spl5 (); dl->dlrcsr |= DL_DTR; splx (s); } else u.u_error = ENOTTY; break; case TIOCCDTR: if (MIN_MODEM <= unit && unit <= MAX_MODEM) { dl = (struct dldevice *) kl11[unit].t_addr; s = spl5 (); dl->dlrcsr &= ~DL_DTR; splx (s); } else u.u_error = ENOTTY; break; #endif MIN_MODEM case 0: break; default: u.u_error = ENOTTY; } } #ifdef MIN_SPEED /* * handle baud rate selection for DLV11-E boards * * map dh baud rate selection to DLV11-E baud rate * selection */ int klbaudmap [] = { 7, /* 0 B0 = 1200*/ 0, /* 1 B50 = 50*/ 1, /* 2 B75 = 75*/ 2, /* 3 B110 = 110*/ 3, /* 4 B134 = 134*/ 4, /* 5 B150 = 150*/ 7, /* 6 B200 = 1200*/ 5, /* 7 B300 = 300*/ 6, /* 8 B600 = 600*/ 7, /* 9 B1200 = 1200*/ 8, /* 10 B1800 = 1800*/ 10, /* 11 B2400 = 2400*/ 12, /* 12 B4800 = 4800*/ 14, /* 13 B9600 = 9600*/ 15, /* 14 B19200=19200*/ 11, /* 15 EXTB = 3600*/ }; klparam (unit) int unit; { register struct tty *tp; register struct dldevice *dl; int s; register int speed; tp = &kl11[unit]; if (tp->t_ispeed != tp->t_ospeed) { u.u_error = ENOTTY; return; } dl = (struct dldevice *) tp->t_addr; speed = klbaudmap [tp->t_ospeed & 017]; s = spl5(); dl->dlxcsr = DLXCSR_TIE | DLXCSR_PSE | speed << 12; splx (s); return; } #endif MIN_SPEED klstart(tp) register struct tty *tp; { register c; register struct dldevice *addr; int s; addr = (struct dldevice *) tp->t_addr; if ((addr->dlxcsr & DLXCSR_TRDY) == 0) return; if ((c=getc(&tp->t_outq)) >= 0) { if (tp->t_state & CARR_ON) { if (c <= 0177 || (tp->t_flags & RAW) || (tp->t_local & LLITOUT)) addr->dlxbuf = c; else { timeout(ttrstrt, (caddr_t)tp, (c & 0177) + DLDELAY); s = spl5 (); tp->t_state |= TIMEOUT; splx (s); } } } } char *msgbufp = msgbuf; /* Next saved printf character */ /* * Print a character on console (or users terminal if touser). * Attempts to save and restore device * status. * If the last character input from the console was a break * (null or del), all printing is inhibited. * * Whether or not printing is inhibited, * the last MSGBUFS characters * are saved in msgbuf for inspection later. */ #ifdef UCB_UPRINTF putchar(c, touser) #else putchar(c) #endif register c; { register s; register struct dldevice *kladdr = KLADDR; long timo; extern char *panicstr; #ifdef UCB_UPRINTF if (touser) { register struct tty *tp = u.u_ttyp; if (tp && (tp->t_state & CARR_ON)) { register s = spl6(); if (c == '\n') (*linesw[tp->t_line].l_output)('\r', tp); (*linesw[tp->t_line].l_output)(c, tp); ttstart(tp); splx(s); } return; } #endif if (c != '\0' && c != '\r' && c != 0177) { *msgbufp++ = c; if (msgbufp >= &msgbuf[MSGBUFS]) msgbufp = msgbuf; } /* * If last char was a break or null, don't print */ if (panicstr == (char *) 0) if ((kladdr->dlrbuf & 0177) == 0) return; timo = 60000L; /* * Try waiting for the console tty to come ready, * otherwise give up after a reasonable time. */ while((kladdr->dlxcsr & DLXCSR_TRDY) == 0) if (--timo == 0L) break; if (c == 0) return; s = kladdr->dlxcsr; kladdr->dlxcsr = 0; kladdr->dlxbuf = c; if (c == '\n') { #ifdef UCB_UPRINTF putchar('\r', 0); putchar(0177, 0); putchar(0177, 0); #else putchar('\r'); putchar(0177); putchar(0177); #endif } #ifdef UCB_UPRINTF putchar(0, 0); #else putchar(0); #endif kladdr->dlxcsr = s; } #ifdef MIN_MODEM /* * Turn on the line associated with the kl device dev. */ kleopen(dev) dev_t dev; { register struct tty *tp; register struct dldevice *addr; register unit; int s, ignore; unit = klunit(dev); ignore = klignore (dev); tp = &kl11[unit]; s = spl5(); if (unit < MIN_MODEM || MAX_MODEM < unit) { tp->t_state |= CARR_ON; splx (s); return; } if (ignore) klwait[unit - MIN_MODEM] |= KLIGNORE; addr = tp->t_addr; if (addr->dlrcsr & DL_CARDET) { carup: ; tp->t_state |= CARR_ON; splx (s); return; } else if (ignore) { /* * set the soft carrier bit, * while the carrier remains * down this bit will let * us talk to the device anyway */ klwait[unit - MIN_MODEM] |= KLSOFTCAR; goto carup; } tp->t_state &= ~CARR_ON; while ((tp->t_state & CARR_ON)==0) { sleep((caddr_t) &tp->t_rawq, TTIPRI); /* * wait for the line that doesn't ignore * carrier to open up, setting a bit * so that we get woken up when * the non-hanging line is closed */ while ((klwait [unit - MIN_MODEM] & KLIGNORE) != 0) { klwait [unit - MIN_MODEM] |= KLWAIT; sleep ((caddr_t) &klwait[unit - MIN_MODEM], TTIPRI); klwait [unit - MIN_MODEM] &= ~KLWAIT; } } splx(s); } #endif MIN_MODEM DL_DIE | DL_RIE | DL_RTS); else addr->dlrcsr &= ~(DL_DIE | DL_RIE | DL_RTS); j = addr->dlrbuf; noreset: ; splx (s); tp->t_dev = 0; #endif MIN_MODEM ttyclose(&kl11[unit])sys/OTHERS/kl/kl.h 444 3 12 346 4057146226 7031 /* * NKL11 includes both KL11's and DL11's. * It should always be at least 1 (the console). */ #define NKL 4 /* * set up for DLV11-E boards */ #define MIN_SPEED 2 #define MAX_SPEED 3 #define MIN_MODEM 3 #define MAX_MODEM 3 sys/OTHERS/kl/klreg.h 444 3 12 3560 4057146226 7550 /* * KL11/DL11 registers and bits */ struct dldevice { short dlrcsr; short dlrbuf; short dlxcsr; short dlxbuf; }; /* bits in dlrcsr */ #define DL_DSI 0100000 /* data set interrupt (read only) */ #define DL_RNG 0040000 /* ring indicator (read only) */ #define DL_CTS 0020000 /* clear to send (read only) */ #define DL_CARDET 0010000 /* carrier detector (read only) */ #define DL_RA 0004000 /* receiver active (read only) */ #define DL_SRD 0002000 /* secondary received data (read only) */ /* bits 9-8 are unused */ #define DL_RDONE 0000200 /* receiver done (read only) */ #define DL_RIE 0000100 /* receiver interrupt enable */ #define DL_DIE 0000040 /* dataset interrupt enable */ /* bit 4 is unused */ #define DL_STD 0000010 /* secondary transmitted data */ #define DL_RTS 0000004 /* request to send */ #define DL_DTR 0000002 /* data terminal ready */ #define DL_RE 0000001 /* reader enable (write only) */ #define DL_BITS \ "\10\20DSI\17RNG\16CTS\15CARDET\14RA\13SRD\10RDONE\7RIE\6DIE\4STD\3RTS\2DTR\1RE" /* bits in dlrbuf */ #define DLRBUF_ERR 0100000 /* error (read only) */ #define DLRBUF_OVR 0040000 /* overrun (read only) */ #define DLRBUF_FRE 0020000 /* framing error (read only) */ #define DLRBUF_RDPE 0010000 /* receive data parity error (read only) */ #define DLRBUF_BITS \ "\10\20ERR\17OVR\16FRE\15RDPE" /* bits in dlxcsr */ /* bits 15-12 select baud rate when bit 11 is high on DLV11-E only */ #define DLXCSR_PSE 0004000 /* programable rate enable for DLV11-E*/ /* bits 10-8 are unused */ #define DLXCSR_TRDY 0000200 /* transmitter ready (read only) */ #define DLXCSR_TIE 0000100 /* transmitter interrupt enable */ /* bits 5-3 are unused */ #define DLXCSR_MM 0000004 /* maintenance */ /* bit 1 is unused */ #define DLXCSR_BRK 0000001 /* break */ #define DLXCSR_BITS \ "\10\10TRDY\7TIE\3MM\1BRK" #define DLDELAY 0000004 /* Extra delay for DLs */ = '\r' && c != 0177) { *msgbufp++ = c; if (msgbufp >= &msgbuf[MSGBUFS]) msgbufp = msgbuf; } /* * If last char was a break or null, sys/OTHERS/kl/README 444 3 12 1275 4057147224 7153 kl.c modified kl driver to support dlv11-e/f cards and dialin/dialout on same line. To enable modem-controll, define MIN_MODEM and MAX_MODEM in kl.h to be the minimum (maximum) minor device number that should support modem control. Note that if these refer to non-modem control lines you will not be able to access those lines as you will wait (perpetually) for carrier. To enable speed selection, define MIN_SPEED and MAX_SPEED similarly. klreg.h a new version of /usr/include/sys/klreg.h. It includes the definitions for the extended capapbilities of the e and f cards. Keith Packard 5440 SE 41st Portland, OR 97202 ...!tektronix!azure!keithp ...!tektronix!reed!motel6!keith */ /* bit 4 is unused */ #define DL_STD 0000010 /* secondary transmitted data */ #define DL_RTS 0000004 /* request to send */ #define DL_DTR 0000002 /* data terminal ready */ #define DL_RE 0000001 /* reader enable (write only) */ #define DL_BITS \ "\10\20DSI\17RNG\16CTS\15CARDET\14RA\13SRD\10RDONE\7RIE\6DIE\4STD\sys/OTHERS/scsi2/ 755 0 12 0 5123225244 6607 sys/OTHERS/scsi2/xe.c 444 3 12 23025 5067140747 7512 /* * xe.c * * version 3 * * xebec winchester controller * */ # include "xe.h" # if NXE > 0 # include # include # include # include # include # include # include # include # include # include /* * kernal data PAR base */ #ifdef KERN_NONSEP # define KDSA0 ((u_short *) 0172340) #else # define KDSA0 ((u_short *) 0172360) #endif bool_t xe_alive = 1; struct xedevice *XEADDR = (struct xedevice *) 0177460; struct buf xetab; struct xecommand xec; u_short xecaddr[2]; struct xeinit xei[NXE]; u_short xeiaddr[NXE][2]; int xeicur = -1; /* * local struct buf for partial read requests */ struct buf parbuf; /* * actual data buffer for partial reads */ char pardat[512 + 64]; /* * physical address of pardat * computed when needed */ u_short paraddr[2]; u_short parclick; /* * device parameters */ /* 17, 153, 6, 128, 153, 2, 0, /* t603s */ /* nsect ntrac nhead rwcur wpc seek isset */ struct xep xeparam [NXE] = { 17, 306, 4, 306, 128, 7, 0, /* hh612 */ 17, 829, 3, 829, 829, 7, 0, /* micropolis */ }; /* * size of logical devices */ /* size start */ struct xesize xe_sizes[NXE][8] = { { 6144, 0, /* 0 */ 2048, 6144, /* 1 */ 12616, 8192, /* 2 */ 0, 0, /* 3 */ 0, 0, /* 4 */ 0, 0, /* 5 */ 0, 0, /* 6 */ 0, 0, /* 7 */ }, #ifdef T603S { 2048, 0, /* 1 */ 4096, 2048, /* 2 */ 9462, 6144, /* 3 */ 0, 0, /* 4 */ 0, 0, /* 5 */ 0, 0, /* 6 */ 0, 0, /* 7 */ 0, 0, /* 8 */ }, #else { 4096, 0, /* 1 */ 8192, 4092, /* 2 */ 29821, 12288, /* 3 reserved 10 tracks for bad tracks */ 0, 0, /* 4 */ 0, 0, /* 5 */ 0, 0, /* 6 */ 0, 0, /* 7 */ 0, 0, /* 8 */ }, }; xestrategy (bp) register struct buf *bp; { register struct buf *dp; register int unit; int device; daddr_t bn; int s; unit = minor (bp->b_dev) & 077; device = unit >> 3; unit = unit & 07; if (device >= NXE || !xe_alive || bp->b_blkno < 0) { printf ("error on xe device: %d unit: %d bp->b_blkno: %D\n", device, unit, bp->b_blkno); bp->b_flags |= B_ERROR; iodone (bp); return; } bn = bp->b_blkno; if (!xecaddr[0]) { /* * map the xec address to physical bus addr */ map(&xec, xecaddr); /* * map the partial data block address */ map((pardat + 64) & ~(077), paraddr); parclick = ((paraddr[0] >> 6) & 01777) | (paraddr[1] << 10); } if (bn + (((bp->b_bcount + 511) >> 9) & 0177) > xe_sizes[device][unit].nblocks) { printf ("error reading past end of disk, device: %d unit: %d block: %D\n", device, unit, bn); bp->b_flags |= B_ERROR; iodone (bp); return; } /* * detect reads requiring partial block transfers and * use the local buffer to read the last block first. */ if ((bp->b_bcount & 511) && (bp->b_flags & B_READ)) { xepartial (bp); if (bp->b_flags & B_ERROR) return; /* * if the block was only a partial transfer, * we are done. */ if (!(bp->b_bcount & ~511)) { bp->b_resid = 0; iodone (bp); return; } } bp->b_cylin = (bn + xe_sizes[device][unit].blkoff) / (xeparam[device].xe_nsect * xeparam[device].xe_nhead); dp = &xetab; s = spl5(); disksort (dp, bp); if (dp->b_active == 0) xestart (); splx(s); } xepartial (bp) register struct buf *bp; { int s; unsigned toc, count; /* * make sure the transfer will work */ if ((bp->b_bcount & 077) || (bp->b_un.b_addr & 077)) { printf ("bad count or addr on partial read: 0%o, 0%o\n", bp->b_bcount, bp->b_un.b_addr); bp->b_flags |= B_ERROR; iodone (bp); return; } /* * get parbuf */ s = spl6(); while (parbuf.b_flags&B_BUSY) { parbuf.b_flags |= B_WANTED; sleep((caddr_t)&parbuf, PSWP+1); } parbuf.b_flags = B_READ | B_BUSY; splx(s); /* * fill in the parbuf fields */ parbuf.b_un.b_addr = paraddr[0]; parbuf.b_xmem = paraddr[1]; parbuf.b_blkno = bp->b_blkno + ((bp->b_bcount >> 9) & 0177); parbuf.b_bcount = 512; parbuf.b_dev = bp->b_dev; parbuf.b_error = 0; /* * read the partial portion */ xestrategy (&parbuf); /* * wait for it to finish */ s = spl6 (); while ((parbuf.b_flags & B_DONE) == 0) sleep ((caddr_t) &parbuf, PSWP); splx (s); if (parbuf.b_flags & B_ERROR) { bp->b_flags |= B_ERROR; iodone (bp); return; } /* * copy the partial block */ toc = ((bp->b_un.b_addr >> 6) & 01777) + (((bp->b_bcount & ~511) >> 6) & 01777); toc += bp->b_xmem << 10; count = (bp->b_bcount & 511) >> 6; copy (parclick, toc, count); /* * release parbuf */ parbuf.b_flags &= ~B_BUSY; if (parbuf.b_flags & B_WANTED) { parbuf.b_flags &= B_WANTED; wakeup ((caddr_t) &parbuf); } } /* * set up real[0] and real[1] to be the * physical address of virtual */ map (virtual, real) u_short virtual; u_short real[2]; { u_short nb, ts; nb = (virtual >> 6) & 01777; ts = KDSA0[nb >> 7] + (nb & 0177); real[0] = ((ts << 6) + (virtual & 077)); real[1] = (ts >> 10) & 077; } xeselect (device) int device; { register struct xedevice *xe = XEADDR; int s; /* * initialize this unit */ if (!xeparam[device].xe_isset) { xei[device].xeihtrac = (xeparam[device].xe_ntrac >> 8) & 0377; xei[device].xeiltrac = xeparam[device].xe_ntrac & 0377; xei[device].xeinhead = xeparam[device].xe_nhead; xei[device].xeihrwcur = (xeparam[device].xe_rwcur >> 8) & 0377; xei[device].xeilrwcur = xeparam[device].xe_rwcur & 0377; xei[device].xeihwpc = (xeparam[device].xe_wpc >> 8) & 0377; xei[device].xeilwpc = xeparam[device].xe_wpc & 0377; xei[device].xeiecc = 11; xe->xecsr = CSRRESET; map(&xei[device], xeiaddr[device]); } xec.xeop = XEINIT; xec.xeunit = device << 5; xec.xehblk = 0; xec.xelblk = 0; xec.xecount = 0; xec.xecntl = xeparam[device].xe_seek; xe->xecar = xecaddr[0]; xe->xedar = xeiaddr[device][0]; xe->xexcar = xecaddr[1] >> 4; xe->xexdar = xeiaddr[device][1] >> 4; xe->xecsr = CSRGO | ((xecaddr[1] & 017) << 8) | ((xeiaddr[device][1] & 017) << 2); /* * wait a reasonable amount of time * for completion. */ s = 30000; while (!(xe->xecsr & CSRDONE)) { s--; if (s == 0) goto initerr; } if ((s = xe->xecsr) & CSRERROR) { initerr: ; printf ("error initing drive"); printf ("csr=%b ccsr=%b\n", s, XECSR_BITS, xe->xeccsr, XECCSR_BITS); return 0; } if (!xeparam[device].xe_isset) { xec.xeop = XERDY; xec.xeunit = device << 5; xec.xehblk = 0; xec.xelblk = 0; xec.xecount = 0; xec.xecntl = xeparam[device].xe_seek; xe->xecar = xecaddr[0]; xe->xedar = xeiaddr[device][0]; xe->xexcar = xecaddr[1] >> 4; xe->xexdar = xeiaddr[device][1] >> 4; xe->xecsr = CSRGO | ((xecaddr[1] & 017) << 8) | ((xeiaddr[device][1] & 017) << 2); while (!(xe->xecsr & CSRDONE)) ; if ((s = xe->xecsr) & CSRERROR) { printf ("error initing drive"); printf ("csr=%b ccsr=%b\n", s, XECSR_BITS, xe->xeccsr, XECCSR_BITS); return 0; } ++xeparam[device].xe_isset; } xeicur = device; return 1; } /* * start up a transfer onto a drive */ xestart () { register struct xedevice *xeaddr = XEADDR; register struct buf *bp; register unit; struct buf *dp; daddr_t bn; int device, i; loop: /* * pull a request off the controller queue. */ dp = &xetab; if ((bp = dp->b_actf) == NULL) { return; } /* * mark controller busy and * determine destination of this request. */ dp->b_active++; unit = minor (bp->b_dev) & 077; device = unit >> 3; /* * if the xebec is not currently * setup for this device, set it * up. */ if (device != xeicur) { if (!xeselect (device)) { printf ("oops, the controller could not select %d\n", device); bp->b_flags |= B_ERROR; bp->b_resid = bp->b_bcount; iodone (bp); dp->b_actf = bp->av_forw; dp->b_active = 0; goto loop; } } unit &= 7; bn = bp->b_blkno + xe_sizes[device][unit].blkoff; /* * select disk block and device */ xec.xelblk = bn & 0377; i = bn >> 8; xec.xehblk = i & 0377; i >>= 8; xec.xeunit = (device << 5) | (i & 0037); /* * select seek rate */ xec.xecntl = xeparam[device].xe_seek; if (bp->b_flags & B_READ) { xec.xecount = (bp->b_bcount >> 9) & 0177; xec.xeop = XEREAD; } else { if (bp->b_bcount & 511) xec.xecount = ((bp->b_bcount + 511) >> 9) & 0177; else xec.xecount = (bp->b_bcount >> 9) & 0177; xec.xeop = XEWRITE; } /* * if we aren't doing a whole block, * then ignore the request and fetch * another from the queue */ if (xec.xecount == 0) { dp->b_actf = bp->av_forw; bp->b_resid = 0; iodone (bp); dp->b_active = 0; goto loop; } xeaddr->xexcar = (xecaddr[1] >> 4) & 03; xeaddr->xexdar = (bp->b_xmem >> 4) & 03; xeaddr->xecar = xecaddr[0]; xeaddr->xedar = bp->b_un.b_addr; /* * warning: unit is being used as temporary */ unit = ((xecaddr[1] & 017) << 8) | CSRIE | ((bp->b_xmem & 017) << 2) | CSRGO; /* * run it */ xeaddr->xecsr = unit; } /* * handle a disk interrupt */ xeintr() { register struct xedevice *xeaddr = XEADDR; register struct buf *dp; register struct buf *bp; int i, j; dp = &xetab; if (dp->b_active) { bp = dp->b_actf; j = xeaddr->xeccsr; i = xeaddr->xecsr; /* * check for and process errors on * either the drive or the controller */ dp->b_active = 0; if (i & CSRERROR) { #ifdef UCB_DEVERR harderr (bp, "xe"); printf ("csr=%b ccsr=%b\n", i, XECSR_BITS, j, XECCSR_BITS); #else deverror (bp, i, j) #endif if (xeselect ((minor (bp->b_dev) >> 3) & 07)) { /* * if we haven't gotten 10 errors yet, * retry the transfer */ if (++dp->b_errcnt <= 10) { xestart (); return; } } bp->b_flags |= B_ERROR; } dp->b_errcnt = 0; bp->b_resid = 0; dp->b_actf = bp->av_forw; iodone (bp); } xestart (); } #endif NXE HP_GO; xpaddr->hpcs1.w = HP_PRESET | HP_GO; xpaddr->hpof = HPOF_FMT22; } if ((xpaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL)) return(EFAULT); ubp = &UBMAP[0]; for (paddr = 0L; dumpsize > 0; dumpsize -= count) { count = dumpsize>DBSIZE? DBSIZE: dumpsize; bn = dumplo + (paddr >> PGSHIFT); xpaddr->hpdc = bn / xd->xp_nspc + xd->xp_sizes[dev].cyloff; sn = bn % xd->xp_nspc; xpaddr->hpda = ((sn / xd->xp_nsect) << 8) | (sn % xd->xp_nsect); xpaddr->hpwc sys/OTHERS/scsi2/xereg.h 444 3 12 7620 4057146013 10166 /* * xereg.h * * defines for the DTC-XEBEC combination controller * on a Q-bus */ struct xedevice { short xeccsr; short xecsr; short xedar; short xecar; short xexdar; short xexcar; }; struct xep { int xe_nsect; int xe_ntrac; int xe_nhead; int xe_rwcur; int xe_wpc; int xe_seek; int xe_isset; }; struct xesize { daddr_t nblocks; daddr_t blkoff; }; struct xecommand { char xeop; /* opcode and command class */ char xeunit; /* drive number and bits 20-16 of blk no */ char xehblk; /* bits 15-8 of block number */ char xelblk; /* bits 7-0 of block number */ char xecount; /* block count */ char xecntl; /* control field (stepping option) */ }; struct xeinit { char xeihtrac; /* high order number of cylinders */ char xeiltrac; /* low order number of cylinders */ char xeinhead; /* number of heads */ char xeihrwcur; /* high order reduced current cylinder number */ char xeilrwcur; /* low order reduced current cylinder number */ char xeihwpc; /* high order write precomp cylinder number */ char xeilwpc; /* low order write precomp cylinder number */ char xeiecc /* ecc error correction length, usually 11 */ }; struct xeiblock { short xeimagic; /* magic number to check validity */ char xeibnsect; /* number of sectors/track */ char xeibnhead; /* number of heads */ short xeibntrac; /* number of cylinders */ short xeibrwcur; /* reduced write current cylinder number */ short xeibwpc; /* write precomp cylinder */ char xeibecc; /* ecc error correction length */ char xeibseek; /* seek parameter */ struct xesize xeibsizes[8]; /* size of each logical device */ }; # define XEIMAGIC 0077000 /* magic number */ /* * command completion status register bits */ # define CCSRSEQER 0177400 /* sequence error bits 15-8 */ # define CCSRLUN 0000340 /* logical unit number bits 7-5 */ # define CCSRCDE 0000002 /* controller/drive error bit 1 */ # define CCSRPE 0000001 /* parity error bit 0 */ # define XECCSR_BITS "\02CCSRCDE\01CCSRPE" /* * control/status register bits */ # define CSRERROR 0100000 /* any error detected bit 15 */ # define CSRNXM 0040000 /* non-existant memory bit 14 */ # define CSRPE 0020000 /* parity error bit 13 */ # define CSRCXMA 0007400 /* bits 19-16 of com block addr bits 11-8 */ # define CSRDONE 0000200 /* done bit 7 */ # define CSRIE 0000100 /* interrupt enable bit 6 */ # define CSRDXMA 0000074 /* bits 19-16 of data block addr bits 5-2 */ # define CSRRESET 0000002 /* force reset bit 1 */ # define CSRGO 0000001 /* go bit 0 */ # define XECSR_BITS "\20CSRERROR\17CSRNXM\16CSRPE\10CSRDONE\7CSRIE\2CSRRESET\1CSRGO" /* * data address register */ # define DARADDR 0177777 /* low order data address bits 15-0 */ /* * command address register */ # define CARADDR 0177777 /* low order command address bits 15-0 */ /* * extension data address register */ # define XDARADDR 0000003 /* bits 21-20 of data address bits 1-0 */ /* * extension command address register */ # define XCARADDR 0000003 /* bits 21-20 of command address bits 1-0 */ /* * commands to the xebec board */ # define XERDY 000 /* select and verify drive ready */ # define XEHOME 001 /* home to track 0 */ # define XERSS 003 /* read sense error information */ # define XEFMT 004 /* format drive */ # define XECFMT 005 /* check drive format */ # define XETFMT 006 /* format track */ # define XEBTRK 007 /* set bad track bit */ # define XEREAD 010 /* read N blocks */ # define XEWRITE 012 /* write N blocks */ # define XESEEK 013 /* seek to block N */ # define XEINIT 014 /* initialize drive charactistics */ # define XERECC 015 /* read ecc burst error length */ # define XEFAT 016 /* format alternate track */ # define XEWSB 017 /* write sector buffer */ # define XERSB 020 /* read sector buffer */ # define XERAMT 0340 /* ram test */ # define XEDRVT 0343 /* drive diagnostic */ # define XECID 0344 /* controller internal diagnostics */ # define XERL 0345 /* read long */ # define XEWL 0346 /* write long */ dev; parbuf.b_error = 0; /* * read the partial portion */ xestrategy (&parbuf); /* * wait for it to fisys/OTHERS/scsi2/xestand.c 444 3 12 7324 4057146013 10516 /* * Xebec disk driver for bootstrap */ #include #include #include #include #include "../saio.h" #define XEADDR ((struct xedevice *)0177460) #define NXE 2 /* * memory management registers */ # define UISA0 ((unsigned short *) 0177640) # define UDSA0 ((unsigned short *) 0177660) # define KISA0 ((unsigned short *) 0172340) # define KDSA0 ((unsigned short *) 0172360) # define PSW ((unsigned short *) 0177776) # define KERNEL 00 # define SUPER 01 # define USER 03 # define mode(p) (((p) >> 14) & 03) struct xeinit xei; struct xecommand xec; u_short xeiaddr[2]; u_short xecaddr[2]; struct xep xeparam[NXE] = { 17, 306, 4, 306, 128, 7, 0, 17, 1024, 3, 1024, 1024, 7, 0, }; xestrategy(io, func) register struct iob *io; { register unsigned short i; register struct xedevice *xeaddr = XEADDR; daddr_t bn; int dn; xeset(io->i_unit); map (&xec, xecaddr); bn = io->i_bn; dn = io->i_unit; /* * select disk block */ xec.xelblk = bn & 0377; i = bn >> 8; xec.xehblk = i & 0377; i >>= 8; xec.xeunit = (dn << 5) | (i & 0037); xec.xecount = io->i_cc >> 9; xec.xecntl = xeparam[dn].xe_seek; if (func == READ) xec.xeop = XEREAD; else xec.xeop = XEWRITE; xeaddr->xexcar = (xecaddr[1] >> 4) & 03; xeaddr->xexdar = (segflag >> 4) & 03; xeaddr->xecar = xecaddr[0]; xeaddr->xedar = io->i_ma; /* * warning: i is being used as temporary */ i = ((xecaddr[1] & 017) << 8) | ((segflag & 017) << 2) | CSRGO; /* * run it */ xeaddr->xecsr = i; while (!((i = xeaddr->xecsr) & (CSRDONE | CSRERROR))) ; if (i & CSRERROR) { printf("disk error: block=%D, er=%o\n", bn, xeaddr->xecsr); return(-1); } return(io->i_cc); } map (virtual, real) u_short virtual; u_short real[2]; { u_short nb, ts; u_short psw; nb = (virtual >> 6) & 01777; psw = *(PSW); switch (mode (psw)) { case USER: ts = UDSA0[nb >> 7] + (nb & 0177); break; case KERNEL: ts = KDSA0[nb >> 7] + (nb & 0177); break; default: printf ("unknown memory management mode: 0%o\n", psw); exit (); } real[0] = ((ts << 6) + (virtual & 077)); real[1] = (ts >> 10) & 077; } char xeerr[4]; short xeeaddr[2]; int ccsr; xeset (unit) { register struct xedevice *xe = XEADDR; unsigned s; /* * init the drive */ map (&xec, xecaddr); map (&xei, xeiaddr); xec.xeop = XEINIT; xec.xeunit = 0; xec.xehblk = 0; xec.xelblk = 0; xec.xecount = 0; xei.xeihtrac = xeparam[unit].xe_ntrac >> 8; xei.xeiltrac = xeparam[unit].xe_ntrac & 0377; xei.xeinhead = xeparam[unit].xe_nhead; xei.xeihrwcur = xeparam[unit].xe_rwcur >> 8; xei.xeilrwcur = xeparam[unit].xe_rwcur & 0377; xei.xeihwpc = xeparam[unit].xe_wpc >> 8; xei.xeilwpc = xeparam[unit].xe_wpc & 0377; xei.xeiecc = 11; /* * initialize this unit */ xe->xecsr = CSRRESET; if ((s = xe->xecsr) & CSRERROR) { printf ("disk error: csr: 0%o, ccsr: 0%o\n", s, xe->xeccsr); return; } xe->xecar = xecaddr[0]; xe->xedar = xeiaddr[0]; xe->xexcar = (xecaddr[1] >> 4) & 03; xe->xexdar = (xeiaddr[1] >> 4) & 03; s = CSRGO | ((xecaddr[1] & 017) << 8) | ((xeiaddr[1] & 017) << 2); xe->xecsr = s; while (!((s = xe->xecsr) & (CSRDONE | CSRERROR))) ; if (s & CSRERROR) { for (ccsr = 0; ccsr < 4; ccsr++) xeerr[ccsr] = 0; map (&xeerr, xeeaddr); printf ("error initing drive"); ccsr = xe->xeccsr; printf ("csr=%o ccsr=%o\n", s, ccsr); xec.xeop = XERSS; xec.xeunit = (ccsr >> 5) & 7; xe->xecar = xecaddr[0]; xe->xedar = xeeaddr[0]; xe->xexcar = xecaddr[1] >> 4; xe->xexdar = xeeaddr[1] >> 4; s = CSRGO | ((xecaddr[1] & 017) << 8) | ((xeeaddr[1] & 017) << 2); xe->xecsr = s; while (!((s = xe->xecsr) & (CSRDONE | CSRERROR))) ; for (ccsr = 0; ccsr < 4; ccsr++) printf ("status: 0%o\n", xeerr [ccsr]); return 0; } return 1; } am test */ # define XEDRVT 0343 /* drive diagnostic */ # define XECID 0344 /* controller internal diagnostics */ # define XERL 0345 /* read long */ # define XEWL 0346 /* write long */ dev; parbuf.b_error = 0; /* * read the partial portion */ xestrategy (&parbuf); /* * wait for it to fisys/OTHERS/scsi2/xeuboot.s 444 3 12 14065 4057146014 10576 / ex:set ts=8 sw=8: / Xebec bootstrap. / disk boot program to load and transfer / to a unix entry. / for use with 1 KB byte blocks, CLSIZE is 2. / NDIRIN is the number of direct inode addresses (currently 4) / assembled size must be <= 512; if > 494, the 16-byte a.out header / must be removed / options: nohead = 0 / 0->normal, 1->this boot must have a.out / header removed. Saves 10 bytes. readname= 0 / 1->normal, if default not found, read name / from console. 0->loop on failure, saves 36 bytes prompt = 0 / 1->prompt (':') before reading from console / 0-> no prompt, saves 8 bytes autoboot= 1 / 1->code for autoboot. 0->no autoboot, saves 12 bytes echo = 1 / 1->code for echoing file name. 0->no echo / constants: CLSIZE = 2. / physical disk blocks per logical block CLSHFT = 1. / shift to multiply by CLSIZE BSIZE = 512.*CLSIZE / logical block size INOSIZ = 64. / size of inode in bytes NDIRIN = 4. / number of direct inode addresses ADDROFF = 12. / offset of first address in inode INOPB = BSIZE\/INOSIZ / inodes per logical block INOFF = 31. / inode offset = (INOPB * (SUPERB+1)) - 1 / The boot options and device are placed in the last SZFLAGS bytes / at the end of core by the kernel if this is an autoboot. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 CHECKWORD= 6 .. = ENDCORE-512.-SZFLAGS / save room for boot flags / entry is made by jsr pc,*$0 / so return can be rts pc / establish sp, copy / program up to end of core. start: mov $..,sp mov sp,r1 clr r0 .if nohead-1 / if nohead != 1? cmp (r0),$407 bne 1f mov $20,r0 .endif 1: mov (r0)+,(r1)+ cmp r1,$end blo 1b jmp *$2f / On error, restart from here. restart: / clear core to make things clean clr r0 2: clr (r0)+ cmp r0,sp blo 2b / initialize xebec jsr pc, xereset / at origin, read pathname .if prompt mov $':, r0 jsr pc, putc .endif / spread out in array 'names', one / component every 14 bytes. mov $names,r1 1: mov r1,r2 2: jsr pc,getc cmp r0,$'\n beq 1f cmp r0,$'/ beq 3f movb r0,(r2)+ br 2b 3: cmp r1,r2 beq 2b add $14.,r1 br 1b / now start reading the inodes / starting at the root and / going through directories 1: mov $names,r1 mov $2,r0 1: clr bno jsr pc,iget tst (r1) beq 1f 2: jsr pc,rmblk br restart mov $buf,r2 3: mov r1,r3 mov r2,r4 add $16.,r2 tst (r4)+ beq 5f 4: cmpb (r3)+,(r4)+ bne 5f cmp r4,r2 blo 4b mov -16.(r2),r0 add $14.,r1 br 1b 5: cmp r2,$buf+BSIZE blo 3b br 2b / read file into core until / a mapping error, (no disk address) 1: clr r1 1: jsr pc,rmblk br 1f mov $buf,r2 2: mov (r2)+,(r1)+ cmp r2,$buf+BSIZE blo 2b br 1b / relocate core around / assembler header 1: clr r0 cmp (r0),$407 bne 2f 1: mov 20(r0),(r0)+ cmp r0,sp blo 1b / enter program and / restart if return 2: .if autoboot mov ENDCORE-BOOTOPTS, r4 mov ENDCORE-BOOTDEV, r3 mov ENDCORE-CHECKWORD, r2 .endif jsr pc,*$0 br restart / get the inode specified in r0 iget: add $INOFF,r0 mov r0,r5 ash $-4.,r0 bic $!7777,r0 mov r0,dno clr r0 jsr pc,rblk bic $!17,r5 mul $INOSIZ,r5 add $buf,r5 mov $inod,r4 1: mov (r5)+,(r4)+ cmp r4,$inod+INOSIZ blo 1b rts pc / read a mapped block / offset in file is in bno. / skip if success, no skip if fail / the algorithm only handles a single / indirect block. that means that / files longer than NDIRIN+128 blocks cannot / be loaded. rmblk: add $2,(sp) mov bno,r0 cmp r0,$NDIRIN blt 1f mov $NDIRIN,r0 1: mov r0,-(sp) asl r0 add (sp)+,r0 add $addr+1,r0 movb (r0)+,dno movb (r0)+,dno+1 movb -3(r0),r0 bne 1f tst dno beq 2f 1: jsr pc,rblk mov bno,r0 inc bno sub $NDIRIN,r0 blt 1f ash $2,r0 mov buf+2(r0),dno mov buf(r0),r0 bne rblk tst dno bne rblk 2: sub $2,(sp) 1: rts pc / / csr bits / err = 0100000 done = 0200 reset = 02 go = 01 waitfor = err+done / / command op-codes / read = 010 init = 014 / / bus addrs of regs / xeccs = 0177460 xecs = 0177462 xeda = 0177464 xeca = 0177466 xexda = 0177470 xexca = 0177472 / / initialization block / note that the words here are backwards! / .even xei: .byte 1; .byte 50. / 306 cylinders .byte 4 / 4 heads .byte 1; .byte 50. / reduce write current at cyl 306 .byte 0; .byte 128. / write precomp at cyl 128 .byte 11. / 11 bytes max ecc correction (standard) / / reset xebec / / .even xereset: movb $init,xeop clrb xeunit mov $xei,*$xeda mov $xec,*$xeca clr *$xexda clr *$xexca jmp xego / / / xebec disk driver. / / low order address in dno, / high order in r0. rblk: mov r1,-(sp) mov dno,r1 .if CLSIZE-1 ashc $CLSHFT,r0 .endif swab r1 mov r1,xehblk / mov both high and low at once bic $0177740,r0 / clear out any naughty bits movb r0,xeunit / save highest order blkno movb $read,xeop / only do reads here movb $CLSIZE,xecnt / snatch block count movb $7,xecntl / 15us buffered seek mov $buf,*$xeda / data memory addr mov $xec,*$xeca / command memory addr clr *$xexda / no extension bits clr *$xexca / not for command either mov (sp)+,r1 xego: mov $go,*$xecs / here we go... 1: bit $waitfor,*$xecs beq 1b rts pc tks = 177560 tkb = 177562 / read and echo a teletype character / if *cp is nonzero, it is the next char to simulate typing / after the defnm is tried once, read a name from the console getc: movb *cp, r0 beq 2f inc cp .if readname br putc 2: mov $tks,r0 inc (r0) 1: tstb (r0) bge 1b mov tkb,r0 bic $!177,r0 cmp r0,$'A blo 2f cmp r0,$'Z bhi 2f add $'a-'A,r0 .endif 2: .if readname+prompt+echo tps = 177564 tpb = 177566 / print a teletype character putc: tstb *$tps bge putc mov r0,*$tpb cmp r0,$'\r bne 1f mov $'\n,r0 br putc 1: .endif rts pc cp: defnm defnm: end: inod = ..-512.-BSIZE / room for inod, buf, stack addr = inod+ADDROFF / first address in inod buf = inod+INOSIZ / disk buffer bno = buf+BSIZE / local storage for logical blockno dno = bno+2 / local storage for physical blockno xec = dno+2 / command block for drive xeop = xec xeunit = xeop + 1 xehblk = xeunit + 1 xelblk = xehblk + 1 xecnt = xelblk + 1 xecntl = xecnt + 1 names = xecntl+1 / storage for file names k = 0; xec.xecount = 0; xec.xecntl = xeparam[device].xe_seek; xe->xecar = xecaddr[0]; xe->xedar = xeiaddr[device][0]; xe->xexcar = xecaddr[1] >> 4; xe->xexdar = xeiaddr[device][1] >> 4; xe->xecsr = CSRGO | ((xecaddr[1] & 017) << 8) | ((xeiaddr[device][1] & 017) << 2); /* * wait a reasonable amount of time * for completion. */ s = 30000; while (!(xe->xecsr & CSRDONE)) { s--; if (s == 0) goto initerr; } if ((s = xe->xecsr) & CSRsys/OTHERS/scsi2/README 444 3 12 1335 4057147340 7564 xe.c a working driver for the DTC-11 Q-bus/SCSI interface card that drives a Xebec 1410 card. It supports different drive sizes on a single Xebec card and (partially) partial-block transfers. See the code for details on how to set up the parameters for your drive. xereg.h this is /usr/include/sys/xereg.h. Register definitions for the xe driver xeuboot.s a boot block for use with the DTC-11 -- Xebec S1410 pair. It too is device dependent and needs to be modified to suit your drive xestand.c a standalone version of the driver. It, as well, is device dependent and must be edited to fit your drives. Keith Packard 5440 SE 41st Portland, OR 97202 ...!tektronix!azure!keithp ...!tektronix!reed!motel6!keith is an autoboot. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 CHECKWORD= 6 .. = ENDCORE-512.-SZFLAGS / save room for boot flags / entry is made by jsr pc,*$0 / so return can be rts psys/OTHERS/ts/ 755 0 12 0 5123225247 6215 sys/OTHERS/ts/ts.c_Q22 444 3 12 34236 5067141405 7551 /* * SCCS id @(#)ts.c 2.1 (Berkeley) 8/5/83 */ /* * TS11 tape driver */ #include "ts.h" #if NTS > 0 #include "param.h" #include #include #include #include #include #include #include #ifdef TS_IOCTL #include #endif /* * Software state per tape transport: * * 1. A tape drive is a unique-open device: we refuse opens when it is already. * 2. We keep track of the current position on a block tape and seek * before operations by forward/back spacing if necessary. * 3. We remember if the last operation was a write on a tape, so if a tape * is open read write and the last thing done is a write we can * write a standard end of tape mark (two eofs). * 4. We remember the status registers after the last command, using * them internally and returning them to the SENSE ioctl. */ struct ts_softc { char sc_openf; char sc_lastiow; short sc_resid; daddr_t sc_blkno; daddr_t sc_nxrec; char sc_pad[4]; /* allow mod 4 alignment of sc_cmd */ struct ts_cmd sc_cmd; struct ts_sts sc_sts; struct ts_char sc_char; } ts_softc[NTS]; struct buf tstab; struct buf ctsbuf; struct tsdevice *TSADDR; #define INF ((daddr_t) ((u_short) 65535)) #define T_NOREWIND 0200 #define TSUNIT(dev) (minor(dev) & 03) #define tswait(r) while (((TSADDR->(r)) & TS_SSR) == 0) /* command code definitions */ /* * States for tstab.b_active, the state flag. * This is used to sequence control in the driver. */ #define SSEEK 1 /* seeking */ #define SIO 2 /* doing seq. i/o */ #define SCOM 3 /* sending a control command */ #define SREW 4 /* sending a drive rewind */ tsattach(addr, unit) struct tsdevice *addr; { /* * This driver supports only one controller. */ if (unit == 0) { TSADDR = addr; return(1); } return(0); } /* * Open the device. Tapes are unique open * devices so we refuse if it is already open. * We also check that a tape is available and * don't block waiting here: if you want to wait * for a tape you should timeout in user code. */ tsopen(dev, flag) dev_t dev; { register tsunit; register struct ts_softc *sc; tsunit = TSUNIT(dev); if (TSADDR == (struct tsdevice *) NULL || tsunit >= NTS || (sc = &ts_softc[tsunit])->sc_openf) { u.u_error = ENXIO; return; } if(tsinit(tsunit)) { u.u_error = ENXIO; return; } tstab.b_flags |= B_TAPE; tscommand(dev, TS_SENSE, 1); if ((sc->sc_sts.s_xs0 & TS_ONL) == 0) { uprintf("ts%d: not online\n", tsunit); u.u_error = EIO; return; } if ((flag & (FREAD | FWRITE)) == FWRITE && (sc->sc_sts.s_xs0 & TS_WLK)) { uprintf("ts%d: no write ring\n", tsunit); u.u_error = EIO; return; } sc->sc_openf = 1; sc->sc_blkno = (daddr_t) 0; sc->sc_nxrec = INF; sc->sc_lastiow = 0; } /* * Close tape device. * * If tape was open for writing or last operation was * a write, then write two EOF's and backspace over the last one. * Unless his is a non-rewinding special file, rewind the tape. * Make the tape available to others. */ tsclose(dev, flag) register dev_t dev; { register struct ts_softc *sc = &ts_softc[TSUNIT(dev)]; if(flag == FWRITE || ((flag & FWRITE) && sc->sc_lastiow)) { tscommand(dev, TS_WEOF, 1); tscommand(dev, TS_WEOF, 1); tscommand(dev, TS_SREV, 1); } if ((minor(dev) & T_NOREWIND) == 0 ) /* * 0 count means don't hang waiting for rewind complete. * Rather ctsbuf stays busy until the operation completes * preventing further opens from completing by * preventing a TS_SENSE from completing. */ tscommand(dev, TS_REW, 0); sc->sc_openf = 0; } /* * Execute a command on the tape drive * a specified number of times. */ tscommand(dev, com, count) dev_t dev; register u_short count; { register s; register struct buf *bp; bp = &ctsbuf; s = spl5(); while(bp->b_flags & B_BUSY) { /* * This special check is because B_BUSY never * gets cleared in the non-waiting rewind case. */ if (bp->b_repcnt == 0 && (bp->b_flags & B_DONE)) break; bp->b_flags |= B_WANTED; sleep((caddr_t) bp, PRIBIO); } bp->b_flags = B_BUSY | B_READ; splx(s); bp->b_dev = dev; bp->b_repcnt = -count; bp->b_command = com; bp->b_blkno = (daddr_t) 0; tsstrategy(bp); /* * In case of rewind from close, don't wait. * This is the only case where count can be 0. */ if (count == 0) return; iowait(bp); if(bp->b_flags & B_WANTED) wakeup((caddr_t) bp); bp->b_flags &= B_ERROR; } /* * Queue a tape operation. */ tsstrategy(bp) register struct buf *bp; { register s; register struct ts_softc *sc; #ifdef UNIBUS_MAP if (bp != &ctsbuf) mapalloc(bp); #endif /* * This is almost certainly wrong. See /sys/pdpuba/ts.c for how it's * really done. */ sc = &ts_softc[TSUNIT(bp->b_dev)]; sc->sc_blkno = dbtofsb(u.u_offset >> 9); sc->sc_nxrec = sc->sc_blkno + 1; bp->av_forw = NULL; s = spl5(); if (tstab.b_actf == NULL) tstab.b_actf = bp; else tstab.b_actl->av_forw = bp; tstab.b_actl = bp; /* * If the controller is not busy, get * it going. */ if (tstab.b_active == 0) tsstart(); splx(s); } /* * Start activity on a ts controller. */ tsstart() { daddr_t blkno; int cmd, s, tsunit; register struct ts_softc *sc; register struct ts_cmd *tc; register struct buf *bp; /* * Start the controller if there is something for it to do. */ loop: if ((bp = tstab.b_actf) == NULL) return; tsunit = TSUNIT(bp->b_dev); sc = &ts_softc[tsunit]; tc = (unsigned)(&sc->sc_cmd) & ~3; /* * Default is that last command was NOT a write command; * if we do a write command we will notice this in tsintr(). */ sc->sc_lastiow = 0; if (sc->sc_openf < 0 || (TSADDR->tssr & TS_OFL)) { /* * Have had a hard error on a non-raw tape * or the tape unit is now unavailable * (e.g. taken off line). */ bp->b_flags |= B_ERROR; goto next; } if (bp == &ctsbuf) { /* * Execute control operation with the specified count. */ tstab.b_active = bp->b_command == TS_REW ? SREW : SCOM; tc->c_repcnt = bp->b_repcnt; goto dobpcmd; } /* * The following checks handle boundary cases for operation * on non-raw tapes. On raw tapes the initialization of * sc->sc_nxrec by tsphys causes them to be skipped normally * (except in the case of retries). */ if(dbtofsb(bp->b_blkno) > sc->sc_nxrec) { /* * Can't read past known end-of-file. */ bp->b_flags |= B_ERROR; bp->b_error = ENXIO; goto next; } if(dbtofsb(bp->b_blkno) == sc->sc_nxrec && bp->b_flags & B_READ) { /* * Reading at end of file returns 0 bytes. * Buffer will be cleared (if written) in writei. */ bp->b_resid = bp->b_bcount; goto next; } if((bp->b_flags & B_READ) == 0) sc->sc_nxrec = dbtofsb(bp->b_blkno) + 1; /* * If the data transfer command is in the correct place, * set up all registers and do the transfer. */ if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) { tc->c_size = bp->b_bcount; tc->c_loba = bp->b_un.b_addr; tc->c_hiba = bp->b_xmem; if ((bp->b_flags & B_READ) == 0) cmd = TS_WCOM; else cmd = TS_RCOM; if (tstab.b_errcnt) cmd |= TS_RETRY; tstab.b_active = SIO; tc->c_cmd = TS_ACK | TS_CVC | TS_IE | cmd; TSADDR->tsdb = tc; return; } /* * Tape positioned incorrectly; * set to seek forward or backward to the correct spot. * This happens for raw tapes only on error retries. */ tstab.b_active = SSEEK; if(blkno < dbtofsb(bp->b_blkno)) { bp->b_command = TS_SFORW; bp->b_repcnt = dbtofsb(bp->b_blkno) - blkno; } else { bp->b_command = TS_SREV; bp->b_repcnt = blkno - dbtofsb(bp->b_blkno); } dobpcmd: /* * Do the command in bp. */ tc->c_cmd = TS_ACK | TS_CVC | TS_IE | bp->b_command; TSADDR->tsdb = tc; return; next: tstab.b_errcnt = 0; tstab.b_actf = bp->av_forw; iodone(bp); goto loop; } /* * TS interrupt routine */ tsintr() { register state; register struct buf *bp; register struct ts_softc *sc; int tsunit, err; if((bp = tstab.b_actf) == NULL) return; tsunit = TSUNIT (bp->b_dev); /* * 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 (tstab.b_active == SREW) { tstab.b_active = SCOM; if ((TSADDR->tssr & TS_SSR) == 0) return; } /* * An operation completed... record status */ sc = &ts_softc[tsunit]; if ((bp->b_flags & B_READ) == 0) sc->sc_lastiow = 1; state = tstab.b_active; tstab.b_active = 0; /* * Check for errors. */ if(TSADDR->tssr & TS_SC) { switch (TSADDR->tssr & TS_TC) { case TS_UNREC: /* unrecoverable */ case TS_FATAL: /* fatal error */ case TS_ATTN: /* attention (shouldn't happen) */ case TS_RECNM: /* recoverable, no motion */ break; case TS_SUCC: /* successful termination */ goto ignoreerr; /*NOTREACHED*/ case TS_ALERT: /* tape status alert */ /* * If we hit the end of the tape file, * update our position. */ if (sc->sc_sts.s_xs0 & (TS_TMK | TS_EOT)) { tsseteof(bp); /* set blkno and nxrec */ state = SCOM; /* force completion */ /* * Stuff bc so it will be unstuffed * correctly later to get resid. */ sc->sc_sts.s_rbpcr = bp->b_bcount; goto opdone; /*NOTREACHED*/ } /* * If we were reading raw tape and the record * was too long or too short, then we don't * consider this an error. */ if (bp->b_flags & B_PHYS && (bp->b_flags & B_READ) && sc->sc_sts.s_xs0 & (TS_RLS | TS_RLL)) goto ignoreerr; /*NOTREACHED*/ case TS_RECOV: /* recoverable, tape moved */ /* * If this was an i/o operation, * retry up to 8 times. */ if (state == SIO) { if (++tstab.b_errcnt < 7) goto opcont; else sc->sc_blkno++; } else { /* * Non-i/o errors on non-raw tape * cause it to close. */ if (sc->sc_openf > 0 && !(bp->b_flags & B_PHYS)) sc->sc_openf = -1; } break; case TS_REJECT: if (state == SIO && sc->sc_sts.s_xs0 & TS_WLE) printf("ts%d: no write ring\n", tsunit); if ((sc->sc_sts.s_xs0 & TS_ONL) == 0) printf("ts%d: not online\n", tsunit); break; } /* * Couldn't recover error. */ #ifdef UCB_DEVERR printf("ts%d: hard error bn%d xs0=%b\n", TSUNIT(bp->b_dev), bp->b_blkno, sc->sc_sts.s_xs0, TSXS0_BITS); if (sc->sc_sts.s_xs1) printf(" xs1=%b\n", sc->sc_sts.s_xs1, TSXS1_BITS); if (sc->sc_sts.s_xs2) printf(" xs2=%b\n", sc->sc_sts.s_xs2, TSXS2_BITS); if (sc->sc_sts.s_xs3) printf(" xs3=%b\n", sc->sc_sts.s_xs3, TSXS3_BITS); #else deverror(bp, sc->sc_sts.s_xs0, sc->sc_sts.s_xs1); printf("%o,%o\n", sc->sc_sts.s_xs2, sc->sc_sts.s_xs3); #endif bp->b_flags |= B_ERROR; goto opdone; /*NOTREACHED*/ } /* * Advance tape control finite state machine. */ ignoreerr: switch (state) { case SIO: /* * Read/write increments tape block number. */ sc->sc_blkno++; goto opdone; /*NOTREACHED*/ case SCOM: /* * For forward/backward space record * update current position. */ if (bp == &ctsbuf) switch (bp->b_command) { case TS_SFORW: sc->sc_blkno += bp->b_repcnt; break; case TS_SREV: sc->sc_blkno -= bp->b_repcnt; break; } goto opdone; /*NOTREACHED*/ case SSEEK: sc->sc_blkno = dbtofsb(bp->b_blkno); goto opcont; /*NOTREACHED*/ default: panic("tsintr"); /*NOTREACHED*/ } opdone: /* * Reset error count and remove * from device queue. */ tstab.b_errcnt = 0; tstab.b_actf = bp->av_forw; bp->b_resid = sc->sc_sts.s_rbpcr; iodone(bp); opcont: tsstart(); } tsseteof(bp) register struct buf *bp; { register tsunit = TSUNIT(bp->b_dev); register struct ts_softc *sc = &ts_softc[tsunit]; if (bp == &ctsbuf) { if (sc->sc_blkno > dbtofsb(bp->b_blkno)) { /* reversing */ sc->sc_nxrec = dbtofsb(bp->b_blkno) - sc->sc_sts.s_rbpcr; sc->sc_blkno = sc->sc_nxrec; } else { /* spacing forward */ sc->sc_blkno = dbtofsb(bp->b_blkno) - sc->sc_sts.s_rbpcr; sc->sc_nxrec = sc->sc_blkno - 1; } return; } else /* eof on read */ sc->sc_nxrec = dbtofsb(bp->b_blkno); } /* * Initialize the TS11. */ tsinit(tsunit) { register struct tsdevice *tsaddr = TSADDR; struct ts_softc *sc = &ts_softc[tsunit]; register struct ts_cmd *tcmd; register struct ts_char *tchar = &sc->sc_char; tcmd = (unsigned)(&sc->sc_cmd) & ~3; if (tsaddr->tssr & (TS_NBA | TS_OFL)) { tsaddr->tssr = 0; /* subsystem initialize */ tswait(tssr); tchar->char_bptr = &sc->sc_sts; tchar->char_bae = 0; tchar->char_size = sizeof(struct ts_sts); tchar->char_mode = TS_ESS; tcmd->c_cmd = TS_ACK | TS_SETCHR; tcmd->c_loba = tchar; tcmd->c_hiba = 0; tcmd->c_size = sizeof(struct ts_char); tsaddr->tsdb = tcmd; tswait(tssr); if (tsaddr->tssr & TS_NBA) return (1); } return(0); } #ifdef TS_IOCTL /*ARGSUSED*/ tsioctl(dev, cmd, addr, flag) dev_t dev; caddr_t addr; { register struct ts_softc *sc = &ts_softc[TSUNIT(dev)]; register struct buf *bp = &ctsbuf; register callcount; u_short fcount; struct mtop mtop; struct mtget mtget; /* we depend on the values and order of the MT codes here */ static tsops[] = {TS_WEOF,TS_SFORW,TS_SREV,TS_SFORW,TS_SREV,TS_REW,TS_OFFL,TS_SENSE}; switch (cmd) { case MTIOCTOP: /* tape operation */ if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) { u.u_error = EFAULT; return; } switch(mtop.mt_op) { case MTWEOF: callcount = mtop.mt_count; fcount = 1; break; case MTFSF: case MTBSF: case MTFSR: case MTBSR: callcount = 1; fcount = mtop.mt_count; break; case MTREW: case MTOFFL: case MTNOP: callcount = 1; fcount = 1; break; default: u.u_error = ENXIO; return; } if (callcount <= 0 || fcount <= 0) { u.u_error = ENXIO; return; } while (--callcount >= 0) { tscommand(dev, tsops[mtop.mt_op], fcount); if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) && bp->b_resid) { u.u_error = EIO; break; } if ((bp->b_flags & B_ERROR) || sc->sc_sts.s_xs0 & TS_BOT) break; } geterror(bp); return; case MTIOCGET: mtget.mt_dsreg = 0; mtget.mt_erreg = sc->sc_sts.s_xs0; mtget.mt_resid = sc->sc_resid; mtget.mt_type = MT_ISTS; if (copyout((caddr_t)&mtget, addr, sizeof(mtget))) u.u_error = EFAULT; return; default: u.u_error = ENXIO; } } #endif TS_IOCTL #endif NTS In case of rewind from close, don't wait. * This is the only case where count can be 0. */ if (count == 0) return; iowait(bp); if(bp->b_flags & B_WANTED) wakeup((caddr_t) bp); bp->b_flags &= B_ERROR; } /* * Queue a tape operation. */ tsstrategy(bp) register struct buf *bp; { register s; register struct ts_softc *sc; #ifdef UNIBUS_MAP sys/OTHERS/ts/ts.c 444 3 12 16440 4057152641 7124 From osmail!egdorf@LANL Thu May 2 12:04:38 1985 Date: Thu, 2 May 85 09:58:16 mdt From: osmail!egdorf@LANL.ARPA To: lanl!keith@seismo Subject: 2.9 ts.c Keith, here is a diff -c of the original ts.c and my fixes. The driver has been tested on 11/23, 11/34, and 11/73. The two remaining areas of bugs are probably in error handling, and unibus-map stuff (note no tests on any machine with a ubmap). The driver in the standalone boot DOES seem to work already. Sorry about the delay in sending this stuff to you, but as you have already said, Things take longer than expected. I have my mods for use with the 11/73 if you would like them. I can send either diffs or source over the net, or I can make a tape. What would you prefer? >*** ts.c.orig Tue Dec 18 15:41:04 1984 >--- ts.c Sun Feb 3 16:45:31 1985 >*************** >*** 15,20 > #include > #include > #include > #ifdef TS_IOCTL > #include > #endif > >--- 15,21 ----- > #include > #include > #include >+ #include > #ifdef TS_IOCTL > #include > #endif >*************** >*** 37,42 > short sc_resid; > daddr_t sc_blkno; > daddr_t sc_nxrec; > struct ts_cmd sc_cmd; > struct ts_sts sc_sts; > struct ts_char sc_char; > >--- 38,44 ----- > short sc_resid; > daddr_t sc_blkno; > daddr_t sc_nxrec; >+ char sc_pad[4]; /* allow mod 4 alignment of sc_cmd */ > struct ts_cmd sc_cmd; > struct ts_sts sc_sts; > struct ts_char sc_char; >*************** >*** 150,156 > * preventing further opens from completing by > * preventing a TS_SENSE from completing. > */ >! tscommand(dev, TS_REV, 0); > sc->sc_openf = 0; > } > > >--- 152,158 ----- > * preventing further opens from completing by > * preventing a TS_SENSE from completing. > */ >! tscommand(dev, TS_REW, 0); > sc->sc_openf = 0; > } > >*************** >*** 243,249 > return; > tsunit = TSUNIT(bp->b_dev); > sc = &ts_softc[tsunit]; >! tc = &sc->sc_cmd; > /* > * Default is that last command was NOT a write command; > * if we do a write command we will notice this in tsintr(). > >--- 245,251 ----- > return; > tsunit = TSUNIT(bp->b_dev); > sc = &ts_softc[tsunit]; >! tc = (unsigned)(&sc->sc_cmd) & ~3; > /* > * Default is that last command was NOT a write command; > * if we do a write command we will notice this in tsintr(). >*************** >*** 296,301 > */ > if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) { > tc->c_size = bp->b_bcount; > if ((bp->b_flags & B_READ) == 0) > cmd = TS_WCOM; > else > >--- 298,305 ----- > */ > if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) { > tc->c_size = bp->b_bcount; >+ tc->c_loba = bp->b_un.b_addr; >+ tc->c_hiba = bp->b_xmem; > if ((bp->b_flags & B_READ) == 0) > cmd = TS_WCOM; > else >*************** >*** 304,310 > cmd |= TS_RETRY; > tstab.b_active = SIO; > tc->c_cmd = TS_ACK | TS_CVC | TS_IE | cmd; >! TSADDR->tsdb = &sc->sc_cmd.c_cmd; > return; > } > /* > >--- 308,314 ----- > cmd |= TS_RETRY; > tstab.b_active = SIO; > tc->c_cmd = TS_ACK | TS_CVC | TS_IE | cmd; >! TSADDR->tsdb = tc; > return; > } > /* >*************** >*** 327,333 > * Do the command in bp. > */ > tc->c_cmd = TS_ACK | TS_CVC | TS_IE | bp->b_command; >! TSADDR->tsdb = &sc->sc_cmd.c_cmd; > return; > > next: > >--- 331,337 ----- > * Do the command in bp. > */ > tc->c_cmd = TS_ACK | TS_CVC | TS_IE | bp->b_command; >! TSADDR->tsdb = tc; > return; > > next: >*************** >*** 444,450 > * Couldn't recover error. > */ > #ifdef UCB_DEVERR >! printf("ts%d: hard error bn%d xs0=%b", TSUNIT(bp->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); > >--- 448,454 ----- > * Couldn't recover error. > */ > #ifdef UCB_DEVERR >! printf("ts%d: hard error bn%d xs0=%b\n", TSUNIT(bp->b_dev), > bp->b_blkno, sc->sc_sts.s_xs0, TSXS0_BITS); > if (sc->sc_sts.s_xs1) > printf(" xs1=%b\n", sc->sc_sts.s_xs1, TSXS1_BITS); >*************** >*** 447,453 > printf("ts%d: hard error bn%d xs0=%b", TSUNIT(bp->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) > >--- 451,457 ----- > printf("ts%d: hard error bn%d xs0=%b\n", TSUNIT(bp->b_dev), > bp->b_blkno, sc->sc_sts.s_xs0, TSXS0_BITS); > if (sc->sc_sts.s_xs1) >! printf(" xs1=%b\n", sc->sc_sts.s_xs1, TSXS1_BITS); > if (sc->sc_sts.s_xs2) > printf(" xs2=%b\n", sc->sc_sts.s_xs2, TSXS2_BITS); > if (sc->sc_sts.s_xs3) >*************** >*** 449,455 > 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\n", sc->sc_sts.s_xs3, TSXS3_BITS); > #else > >--- 453,459 ----- > if (sc->sc_sts.s_xs1) > printf(" xs1=%b\n", sc->sc_sts.s_xs1, TSXS1_BITS); > if (sc->sc_sts.s_xs2) >! printf(" xs2=%b\n", sc->sc_sts.s_xs2, TSXS2_BITS); > if (sc->sc_sts.s_xs3) > printf(" xs3=%b\n", sc->sc_sts.s_xs3, TSXS3_BITS); > #else >*************** >*** 547,553 > { > register struct tsdevice *tsaddr = TSADDR; > struct ts_softc *sc = &ts_softc[tsunit]; >! register struct ts_cmd *tcmd = &sc->sc_cmd; > register struct ts_char *tchar = &sc->sc_char; > > if (tsaddr->tssr & (TS_NBA | TS_OFL)) { > >--- 551,557 ----- > { > register struct tsdevice *tsaddr = TSADDR; > struct ts_softc *sc = &ts_softc[tsunit]; >! register struct ts_cmd *tcmd; > register struct ts_char *tchar = &sc->sc_char; > > tcmd = (unsigned)(&sc->sc_cmd) & ~3; >*************** >*** 550,555 > register struct ts_cmd *tcmd = &sc->sc_cmd; > register struct ts_char *tchar = &sc->sc_char; > > if (tsaddr->tssr & (TS_NBA | TS_OFL)) { > tsaddr->tssr = 0; /* subsystem initialize */ > tswait(tssr); > >--- 554,560 ----- > register struct ts_cmd *tcmd; > register struct ts_char *tchar = &sc->sc_char; > >+ tcmd = (unsigned)(&sc->sc_cmd) & ~3; > if (tsaddr->tssr & (TS_NBA | TS_OFL)) { > tsaddr->tssr = 0; /* subsystem initialize */ > tswait(tssr); >*************** >*** 553,562 > if (tsaddr->tssr & (TS_NBA | TS_OFL)) { > tsaddr->tssr = 0; /* subsystem initialize */ > tswait(tssr); >- if (((u_short) tcmd) & 03) { >- printf("ts%d: addr mod 4 != 0\n", tsunit); >- return (1); >- } > tchar->char_bptr = &sc->sc_sts; > tchar->char_bae = 0; > tchar->char_size = sizeof(struct ts_sts); > >--- 558,563 ----- > if (tsaddr->tssr & (TS_NBA | TS_OFL)) { > tsaddr->tssr = 0; /* subsystem initialize */ > tswait(tssr); > tchar->char_bptr = &sc->sc_sts; > tchar->char_bae = 0; > tchar->char_size = sizeof(struct ts_sts); >*************** >*** 570,577 > if (tsaddr->tssr & TS_NBA) > return (1); > } >! else >! return(0); > } > > tsread(dev) > >--- 571,577 ----- > if (tsaddr->tssr & TS_NBA) > return (1); > } >! return(0); > } > > tsread(dev) >*************** >*** 674,676 > } > #endif TS_IOCTL > #endif NTS > >--- 674,677 ----- > } > #endif TS_IOCTL > #endif NTS >+ :31 1985 >*************** >*** 15,20 > #include > #include > #include > #ifdef TS_IOCTL > #include > #endif > >--- 15,21 ----- > #include > #include #include #include #include "saio.h" #include "tk_saio.h" /* * UQPORT registers and structures */ struct device { int tkaip; /* initialization and polling */ int tkasa; /* status and address */ }; struct device *tk_csr; #define TK_ERR 0100000 /* error bit */ #define TK_STEP4 0040000 /* step 4 has started */ #define TK_STEP3 0020000 /* step 3 has started */ #define TK_STEP2 0010000 /* step 2 has started */ #define TK_STEP1 0004000 /* step 1 has started */ #define TK_SMASK 0074000 /* mask for checking step bit */ #define TK_NV 0002000 /* no host settable interrupt vector */ #define TK_QB 0001000 /* controller supports Q22 bus */ #define TK_DI 0000400 /* controller implements diagnostics */ #define TK_IE 0000200 /* interrupt enable */ #define TK_PI 0000001 /* host requests adapter purge interrupts */ #define TK_GO 0000001 /* start operation, after init */ #define TK_DELI 200 /* SA reg checking loop count (see tkbits) */ /* * Parameters for the communications area */ #define NRSPL2 0 /* log2 number of response packets */ #define NCMDL2 0 /* log2 number of command packets */ #define NRSP (1<i_unit&7; if(unit >= NTK) { printf("\nNo such device"); return(-1); } tkaddr = (struct device *)devsw[io->i_ino.i_dev].dv_csr; tk_csr = tkaddr; /* save CSR for tkcmd() */ if(tk_drv.tk_openf) { printf("\n%s ONLINE already", tk_dct); return(-1); } p = (caddr_t)&tk; for(i=0; ii_boff > 0) { /* skip if offset is not zero */ tk.tk_cmd[0].m_modifier = 0; tk.tk_cmd[0].m_tmcnt = io->i_boff; tk.tk_cmd[0].m_bytecnt = 0; tk.tk_cmd[0].m_zzz2 = 0; if(tkcmd(M_O_REPOS) == 0) { printf("\n%s REPOS FAILED: no such address", tk_dct); return(-1); } } tk_drv.tk_openf++; return(0); } tkclose(io) register struct iob *io; { tk.tk_cmd[0].m_modifier = M_M_REWND; tk.tk_cmd[0].m_tmcnt = 0; tk.tk_cmd[0].m_buf_h = 0; tk.tk_cmd[0].m_bytecnt = 0; tk.tk_cmd[0].m_zzz2 = 0; tkcmd(M_O_REPOS); /* rewind to the BOT */ tk_drv.tk_openf = 0; } struct tmscp * tkcmd(op) int op; { struct tmscp *mp; int i; register struct device *tkaddr; tkaddr = tk_csr; tk.tk_cmd[0].m_opcode = op; if (op == M_O_ONLIN) tk.tk_cmd[0].m_modifier |= M_M_CLSEX; tk.tk_ca.ca_rspdsc[0].rh |= TK_OWN; tk.tk_ca.ca_cmddsc[0].ch |= TK_OWN; i = tkaddr->tkaip; while(tk.tk_ca.ca_cmddsc[0].ch & TK_OWN) ; while(tk.tk_ca.ca_rspdsc[0].rh & TK_OWN) ; tk.tk_ca.ca_rspint = 0; mp = &tk.tk_rsp[0]; tk_stat = mp->m_status; tk_ecode = mp->m_opcode&0377; tk_eflags = mp->m_flags&0377; if ((mp->m_opcode & 0377) != (op|M_O_END) || mp->m_status != M_S_SUCC) return(0); return(mp); } tkstrategy(io, func) register struct iob *io; { register struct tmscp *mp; int i,unit, op; char *p; unit = io->i_unit&7; if(unit >= NTK) { printf("\nNo such device"); return(-1); } p = 0; if(devsw[io->i_ino.i_dev].dv_flags == DV_TAPE) { i = (tk_ctid>>4) & 07; if (i != TK50 && i != TU81) p = "TK50/TU81 "; } else p = ""; if(p) { printf("\n%s: unit %d not %smagtape!\n", tk_dct, unit, p); tk_drv.tk_openf = 0; return(-1); } mp = &tk.tk_cmd[0]; mp->m_unit = unit; mp->m_bytecnt = io->i_cc; mp->m_zzz2 = 0; mp->m_buf_l = io->i_ma; mp->m_buf_h = segflag; if(func == READ) op = M_O_READ; else op = M_O_WRITE; if((mp = tkcmd(op)) == 0) { printf("\n%s magtape error: ", tk_dct); printf("endcode=%o flags=%o status=%o\n", tk_ecode, tk_eflags, tk_stat); printf("(FATAL ERROR)\n"); return(-1); } return(io->i_cc); } /* * Initialize a drive, * do GET UNIT STATUS and ONLINE commands * and save the results. */ tkinit(unit) register int unit; { register struct tmscp *mp; tk.tk_cmd[0].m_unit = unit; mp = &tk.tk_rsp[0]; tk_drv.tk_online = 0; /* mark unit off-line */ tk_drv.tk_dt = 0; /* mark unit non-existent */ tk.tk_cmd[0].m_modifier = 0; if(tkcmd(M_O_ONLIN) != 0) { /* ON-LINE command */ tk_drv.tk_online = 1; /* unit is on-line */ tk_drv.tk_dt = *((int *)&mp->m_mediaid) & 0177; } return(tk_drv.tk_online); } tkqinit(addr) register struct device *addr; { register i, j; for (j=0; j<3; j++) { addr->tkaip = 0; /* start initialization */ i = 0; while(addr->tkasa != 0) { if (++i > 1000) break; } if(tkbits(addr, TK_DELI, TK_STEP1)) continue; addr->tkasa = TK_ERR; if(tkbits(addr, TK_DELI, TK_STEP2)) continue; addr->tkasa = (short)&tk.tk_ca.ca_ringbase; if(tkbits(addr, TK_DELI, TK_STEP3)) continue; addr->tkasa = segflag; if(tkbits(addr, TK_DELI, TK_STEP4)) continue; tk_ctid = addr->tkasa & 0377; /* save controller ID */ switch((tk_ctid>>4) & 017) { case TK50: tk_dct = "TK50"; break; case TU81: tk_dct = "TU81"; break; default: tk_dct = "TMSCP"; break; } addr->tkasa = TK_GO; tk.tk_ca.ca_rspdsc[0].rl = &tk.tk_rsp[0].m_cmdref; tk.tk_ca.ca_rspdsc[0].rh = segflag; tk.tk_rsp[0].m_header.tk_msglen = sizeof(struct tmscp) - sizeof(struct tmscp_header); tk.tk_ca.ca_cmddsc[0].cl = &tk.tk_cmd[0].m_cmdref; tk.tk_ca.ca_cmddsc[0].ch = segflag; tk.tk_cmd[0].m_header.tk_msglen = sizeof(struct tmscp) - sizeof(struct tmscp_header); tk.tk_cmd[0].m_header.tk_vcid = 1; tk.tk_cmd[0].m_cntflgs = 0; /* need to set the density if TU81 */ if (tkcmd(M_O_STCON) == 0) { printf("\n%s STCON FAILED: can't init controller", tk_dct); return(TK_ERR); } return(0); } return(TK_ERR); } tkbits(addr, delay, step) register struct device *addr; int delay; int step; { register int i; if(step == TK_STEP1) { for(i=0; i<32767; i++) ; if((addr->tkasa&TK_SMASK) != TK_STEP1) return(TK_ERR); else return(0); } else { while(1) { for(i=0; itkasa & step) == 0) continue; if((addr->tkasa & TK_SMASK) != step) return(TK_ERR); else return(0); } } } tkerror(str, addr) char *str; struct device *addr; { printf("\nTMSCP cntrl at %o: %s (SA=%o)\n", addr, str, addr->tkasa); } arted */ #define TK_STEP3 0020000 /* step 3 has started */ #define TK_STEP2 0010000 /* step 2 has started *sys/OTHERS/tk/pdpstand/tk_saio.h 440 3 12 1402 4301135510 11671 /********************************************************************** * Copyright (c) Digital Equipment Corporation 1984, 1985, 1986. * * All Rights Reserved. * * Reference "/usr/src/COPYRIGHT" for applicable restrictions. * **********************************************************************/ /* * SCCSID: @(#)tk_saio.h 3.0 4/21/86 * * Common definitions for all standalone programs * that must deal with TK type magtape. * * * Chung_wu Lee 2/8/85 * */ #define TK50 3 #define TU81 5 #define NTK 1 struct tk_drv { /* TK drive information */ char tk_dt; /* TK drive type, 0 = NODRIVE */ char tk_online; /* TK drive on-line flag */ char tk_openf; /* TK drive in use flag */ char tk_flags; /* TK drive misc. flag */ }; eturn(0); } } } tkerror(str, addr) char *str; struct device *addr; { printf("\nTMSCP cntrl at %o: %s (SA=%o)\n", addr, str, addr->tkasa); } arted */ #define TK_STEP3 0020000 /* step 3 has started */ #define TK_STEP2 0010000 /* step 2 has started *sys/OTHERS/tk/pdpstand/tkboot.s 440 3 12 11352 4301135510 11602 / ////////////////////////////////////////////////////////////////////// / Copyright (c) Digital Equipment Corporation 1984, 1985, 1986. / / All Rights Reserved. / / Reference "/usr/src/COPYRIGHT" for applicable restrictions. / ////////////////////////////////////////////////////////////////////// / / ULTRIX-11 Block Zero Bootstrap for TMSCP Magtape / / SCCSID: @(#)tkboot.s 3.0 4/21/86 / / On entry boot leaves: / r0 = unit # / r1 = aip register address / / magtape boot program to load and transfer / to a unix entry / / Chung_wu Lee 2/8/85 / nop = 240 s1 = 4000 go = 1 core = 28. .. = [core*2048.]-512. / establish sp and check if running below / intended origin, if so, copy / program up to 'core' K words. start: nop / DEC boot block standard br 1f / " 1: mov $..,sp clr r4 mov sp,r5 cmp pc,r5 bhis 2f cmp (r4),$407 bne 1f mov $20,r4 1: mov (r4)+,(r5)+ cmp r5,$end blo 1b jmp (sp) / Clear core to make things clean, 2: clr (r4)+ cmp r4,sp blo 2b / TK initialization mov r0,bdunit / save unit # booted from mov r1,tkaip / save aip register address clr (r1)+ / start tk init sequence / move pointer to tksa register mov $s1,r5 / set tk state test bit to step 1 mov $1f,r4 / address of init seq table br 2f / branch around table 1: 100000 / TK_ERR, init step 1 ring / address of ringbase 0 / hi ringbase address go / TK go bit 2: tst (r1) / error ? bmi . / yes, hang - can't restart !!! bit r5,(r1) / current step done ? beq 2b / no mov (r4)+,(r1) / yes, load next step info from table asl r5 / change state test bit to next step bpl 2b / if all steps not done, go back / r5 now = 100000, TK_OWN bit mov $400,cmdhdr+2 / tape VCID = 1 mov $36.,cmdhdr / command packet length / don't set response packet length, / little shakey but it works. mov r0,tkcmd+4. / load unit number mov $11,tkcmd+8. / on-line command opcode mov $20000,tkcmd+10. / set clear serious exception mov $ring,r2 / initialize cmd/rsp ring mov $tkrsp,(r2)+ / address of response packet mov r5,(r2)+ / set TK owner mov $tkcmd,(r2)+ / address of command packet mov r5,(r2)+ / set TK owner mov -2(r1),r0 / start TK polling 3: tst ring+2 / wait for response, TK_OWN goes to zero bmi 3b tstb tkrsp+10. / does returned status = SUCCESS ? bne . / no, hang (try it again ???) / Pass boot device type ID and unit number to Boot: mov tkrsp+28.,bdmtil / media type ID lo mov tkrsp+30.,bdmtih / media type ID hi / rewind tape to BOT tstart: jsr pc,tkrew clr r1 mov $2,bc jsr pc,tkread /* skip the first two blocks clr r1 mov $1,bc jsr pc,tkread /* read the first block / Find out how big boot is mov *$2,r0 / text segment size add *$4,r0 / data segment size / sub $512.,r0 / They forgot to skip the a.out header! sub $496.,r0 add $511.,r0 / Convert size to block count clc / UNSIGNED! ror r0 ash $-8.,r0 beq 1f / In case boot size < 496 bytes (FAT CHANCE!) mov r0,bc jsr pc,tkread / read file into core / load boot device type info into r0 -> r4 / relocate core around / assembler header 1: jsr pc,tkrew mov bdunit,r0 / unit number mov $12.,r1 / boot device type code 12 = TK (TMSCP) mov bdmtil,r2 / media type ID mov bdmtih,r3 mov tkaip,r4 / TMSCP controller CSR address clr r5 1: mov 20(r5),(r5)+ cmp r5,sp blo 1b / enter program clr pc / TK driver rewind routine tkrew: / mov $24.,cmdhdr / length of command packet mov $45,tkcmd+8. / reposition opcode mov $0,tkcmd+12. / clear record/object count mov $0,tkcmd+16. / clear tape mark count mov $20002,tkcmd+10. / set rewind & clear serious exception mov $100000,ring+2 / set TK owner of response mov $100000,ring+6 / set TK owner of command mov *tkaip,r0 / start TK polling 1: tst ring+2 / wait for response bmi 1b tstb tkrsp+10. / does returned status = SUCCESS ? beq 1f / yes, return jmp tstart / no, error (try it again) 1: rts pc tkread: mov bc,r3 / mov $32.,cmdhdr / length of command packet mov $41,tkcmd+8. / read opcode mov $20000,tkcmd+10. / set clear serious exception mov $512.,tkcmd+12. / byte count mov $buf,tkcmd+16. / buffer descriptor 1: mov $100000,ring+2 / set TK owner of response mov $100000,ring+6 / set TK owner of command mov *tkaip,r0 / start TK polling 2: tst ring+2 / wait for response bmi 2b tstb tkrsp+10. / does returned status = SUCCESS ? beq 2f / yes jmp tstart / no, error (try it again) 2: mov $buf,r2 mov tkrsp+12.,r4 / byte count asr r4 / word count 3: dec r4 / decrement word count bmi 3f mov (r2)+,(r1)+ br 3b 3: sob r3,1b rts pc end: tkaip = ..-1024. cmdint = tkaip+2. rspint = cmdint+2. ring = rspint+2. rsphdr = ring+8. tkrsp = rsphdr+4. cmdhdr = tkrsp+48. tkcmd = cmdhdr+4. bdunit = tkcmd+48. bdmtil = bdunit+2. bdmtih = bdmtil+2. buf = bdmtih+2. bc = buf+512. ier |= M_M_CLSEX; tk.tk_ca.ca_rspdsc[0].rh |= TK_OWN; tk.tk_ca.ca_cmddsc[0].ch |= TK_OWN; i = tkaddr->tkaip; while(tk.tk_ca.ca_cmddsc[0].ch & TK_OWN) ; while(tk.tk_ca.ca_rspdsc[0].rh & TK_OWN) ; tk.tk_ca.ca_rspint = 0; mp = &tk.tk_rsp[0]; tk_stat = mp->m_status; tk_ecosys/OTHERS/tk/bin/ 755 3 12 0 4301136461 6754 sys/OTHERS/tk/bin/tk.c 440 3 12 7652 4301136461 7627 /********************************************************************** * Copyright (c) Digital Equipment Corporation 1984, 1985, 1986. * * All Rights Reserved. * * Reference "/usr/src/COPYRIGHT" for applicable restrictions. * **********************************************************************/ /* * optimize output for Tek 4014 */ static char Sccsid[] = "@(#)tk.c 3.0 4/22/86"; #include #include #define MAXY 3071 #define LINE 47 #define XOFF 248 #define US 037 #define GS 035 #define ESC 033 #define CR 015 #define FF 014 #define SO 016 #define SI 017 int pl = 66*LINE; int yyll = -1; char obuf[BUFSIZ]; int xx = XOFF; int xoff = XOFF; int coff = 0; int ncol = 0; int maxcol = 1; int yy = MAXY; int ohy = -1; int ohx = -1; int oxb = -1; int oly = -1; int olx = -1; int alpha; int ry; FILE *ttyin; main(argc, argv) int argc; char **argv; { register i, j; extern ex(); while (--argc > 0 && (++argv)[0][0]=='-') switch(argv[0][1]) { case 'p': if (i = atoi(&argv[0][2])) pl = i; yyll = MAXY + 1 - pl; break; default: if (i = atoi(&argv[0][1])) { maxcol = i; xx = xoff = 0; coff = 4096/i; } break; } if ((ttyin = fopen("/dev/tty", "r")) != NULL) setbuf(ttyin, (char *)NULL); if (argc) { if (freopen(argv[0], "r", stdin) == NULL) { fprintf(stderr, "tk: cannot open %s\n", argv[0]); exit(1); } } signal(SIGINT, ex); setbuf(stdout, obuf); ncol = maxcol; init(); while ((i = getchar()) != EOF) { switch(i) { case FF: yy = 0; case '\n': xx = xoff; yy -= LINE; alpha = 0; if (yy < yyll) { ncol++; yy = 0; sendpt(0); putchar(US); fflush(stdout); if (ncol >= maxcol) kwait(); init(); } continue; case CR: xx = xoff; alpha = 0; continue; case ' ': xx += 31; alpha = 0; continue; case '\t': /*tabstops at 8*31=248*/ j = ((xx-xoff)/248) + 1; xx += j*248 - (xx-xoff); alpha = 0; continue; case '\b': xx -= 31; alpha = 0; continue; case ESC: switch(i = getchar()) { case '7': yy += LINE; alpha = 0; continue; case '8': yy += (LINE + ry)/2; ry = (LINE + ry)%2; alpha = 0; continue; case '9': yy -= (LINE - ry)/2; ry = -(LINE - ry)%2; alpha = 0; continue; default: continue; } default: sendpt(alpha); if (alpha==0) { putchar(US); alpha = 1; } putchar(i); if (i>' ') xx += 31; continue; } } xx = xoff; yy = 0; sendpt(0); putchar(US); kwait(); ex(); } init() { ohx = oxb = olx = ohy = oly = -1; if (ncol >= maxcol) { ncol = 0; if (maxcol > 1) xoff = 0; else xoff = XOFF; } else xoff += coff; xx = xoff; yy = MAXY; if (ncol==0) fputs("\033\014\033;", stdout); sendpt(0); } ex() { yy = MAXY; xx = 0; fputs("\033;\037", stdout); sendpt(1); exit(0); } kwait() { register c; fflush(stdout); if (ttyin==NULL) return; while ((c=getc(ttyin))!='\n') { if (c=='!') { execom(); printf("!\n"); fflush(stdout); continue; } if (c==EOF) ex(); } } execom() { int (*si)(), (*sq)(); if (fork() != 0) { si = signal(SIGINT, SIG_IGN); sq = signal(SIGQUIT, SIG_IGN); wait((int *)NULL); signal(SIGINT, si); signal(SIGQUIT, sq); return; } if (isatty(fileno(stdin)) == 0) { if (freopen("/dev/tty", "r", stdin)==NULL) freopen("/dev/null", "r", stdin); } execl("/bin/sh", "sh", "-t", 0); } sendpt(a) { register zz; int hy,xb,ly,hx,lx; if (a) return; if ((zz = yy) < 0) zz = 0; hy = ((zz>>7) & 037); xb = ((xx & 03) + ((zz<<2) & 014) & 017); ly = ((zz>>2) & 037); hx = ((xx>>7) & 037); lx = ((xx>>2) & 037); putchar(GS); if (hy != ohy) putchar(hy | 040); if (xb != oxb) putchar(xb | 0140); if ((ly != oly) || (hx != ohx) || (xb != oxb)) putchar(ly | 0140); if (hx != ohx) putchar(hx | 040); putchar(lx | 0100); ohy = hy; oxb = xb; oly = ly; ohx = hx; olx = lx; alpha = 0; } read file into core / load boot device type info into r0 -> r4 / relocate core aroundsys/OTHERS/tk/pdpuba/ 755 3 12 0 5123225245 7461 sys/OTHERS/tk/pdpuba/tk.c 440 3 12 75313 5067141462 10360 /********************************************************************** * Copyright (c) Digital Equipment Corporation 1984, 1985, 1986. * * All Rights Reserved. * * Reference "/usr/src/COPYRIGHT" for applicable restrictions. * **********************************************************************/ /* * ULTRIX-11 TK50/TU81 - TMSCP tape driver * * SCCSID: @(#)tk.c 3.18 4/21/86 * * Chung-Wu Lee, Jan-10-86 * * enable CACHE/NOCACHE. * * Chung-Wu Lee, Dec-31-85 * * start supporting up tp 4 controllers per system. * * Chung-Wu Lee, Aug-09-85 * * add ioctl routine. * * Chung-Wu Lee, Jan-22-85 */ #define PANIC 1 /* panic on fatal controller error */ #define NOPANIC 0 #include #include #include #include #include #include #include #include #include #include #include #include /* tk_info.h inlcudes tmscp.h */ int wakeup(); extern int hz; struct tk_info tk_info[]; /* information for MTIOCGET */ char tk_on[]; /* 1 = doing online when open */ char tk_rew[]; /* 1 = rewinding */ char tk_wait[]; /* 1 = open is waiting during the rewinding */ char tk_eot[]; /* 1 = tape hits the EOT */ char tk_nrwt[]; /* 1 = don't wait on rewinding */ char tk_clex[]; /* 1 = current reposition is clear serious exception only */ char tk_fmt[]; /* Tmscp format */ char tk_cache[]; /* Tmscp cache */ char tk_cse[]; /* 1 = clear serious exception */ int tk_csr[]; /* (c.c) Hardware register I/O page address */ int tk_ivec[]; /* (c.c) TMSCP controller interrupt vector addressess */ int ntk; /* (c.c) number of TMSCP been configured */ char *tk_dct[]; /* TMSCP cntlr type for error messages (TK50 or TU81) */ struct tk_drv tk_drv[]; /* drive types, status, unit size */ char tk_ctid[]; /* controller type ID + U-code rev */ #ifdef TKDBUG int tk_error = 0; /* set to cause hex dump of error log packets */ #endif TKDBUG struct tk_softc tk_softc[]; struct tk tk[]; struct tmscp *tkgetcp(); /* * block I/O device error log buffer. */ struct tk_ebuf tk_ebuf[]; int tk_elref[]; /* used with command reference number to */ /* associate datagrams with end messages */ struct buf tktab[]; /* controller queue */ struct buf tkwtab; /* I/O wait queue */ struct buf ctkbuf[]; /* buffer for tkcmd */ /* * Initialize the device and set the unit online. */ tkopen(dev, flag) dev_t dev; int flag; /* -1 = called from main(), don't set u.u_error */ { register struct tk_softc *sc; register struct tmscp *mp; register struct tk_regs *tkaddr; register struct tk_drv *tp; int unit, s, i; /* * The B_TAPE flag tells the system this is a MAGTAPE, i.e., * no delayed writes, no read ahead, and don't allow tape * device to suck up all the system buffers. */ unit = minor(dev) & 7; s = spl5(); if(unit >= ntk) goto bad; tktab[unit].b_flags |= B_TAPE; tkaddr = tk_csr[unit]; tp = &tk_drv[unit]; if(tkaddr == 0) { if (flag < 0) { tk_ctid[unit] = 0; return; } else goto bad; } if(flag >= 0) { if(flag&FNDELAY) { tp->tk_openf = 1; splx(s); return; } if(tp->tk_openf != 0 || tk_wait[unit] != 0) { /* unit online or an open is waiting already */ u.u_error = ETO; splx(s); return; } else if(tk_rew[unit] == 1) { /* rewinding */ tk_wait[unit] = 1; tp->tk_flags |= TK_REWT; sleep((caddr_t)&tk_wait[unit], PSWP+1); if (tp->tk_flags & TK_REWT) goto wbad; } } tp->tk_flags &= TK_DEOT; tk_nrwt[unit] = 0; tk_clex[unit] = 0; sc = &tk_softc[unit]; if (sc->sc_state != S_RUN) { if (sc->sc_state == S_IDLE) if(tkinit(unit)) goto bad; /* fatal cntlr error */ /* wait for initialization to complete */ s = spl6(); timeout(wakeup,(caddr_t)&tk_softc[unit],15*hz); sleep((caddr_t)&tk_softc[unit], PSWP+1); splx(s); s = spl5(); if (sc->sc_state != S_RUN) goto bad; } /* * Get the status of the unit and save it, * by attempting to force unit online. */ if(flag >= 0) { if(tp->tk_online == 0) { if (((tk_ctid[unit] >> 4) & 017) == TU81) { if (minor(dev) & 0100) tk_fmt[unit] = M_TF_GCR; else tk_fmt[unit] = M_TF_PE; } else tk_fmt[unit] = 0; tkcommand(unit,M_O_ONLIN,0); if(tp->tk_online == 0) goto bad; } else { if (((tk_ctid[unit] >> 4) & 017) == TU81) { i = 0; if (minor(dev) & 0100) { if (tk_fmt[unit] != M_TF_GCR) { tk_fmt[unit] = M_TF_GCR; i = 1; } } else { if (tk_fmt[unit] != M_TF_PE) { tk_fmt[unit] = M_TF_PE; i = 1; } } if(i == 1) tkcommand(unit,M_O_SETUC,0); } } tkcommand(unit,M_O_GTUNT,0); /* Status saved from response packet by interrupt routine tkrsp() */ if(tp->tk_online == 0) /* NED or off-line */ goto bad; if (tp->tk_flags & TK_EOT) { tp->tk_flags &= ~TK_EOT; tk_eot[unit] = 1; } else tk_eot[unit] = 0; if ((flag & FWRITE) && (tp->tk_flags & TK_WRTP)) { tp->tk_flags &= ~TK_WRTP; u.u_error = ETWL; /* write locked */ } if (u.u_error == 0) tp->tk_openf = 1; else tp->tk_openf = 0; } splx(s); return; bad: if(flag >= 0) tp->tk_openf = 0; wbad: if(flag >= 0) u.u_error = ENXIO; splx(s); } tkclose(dev, flag) dev_t dev; int flag; { register int unit; register struct tk_softc *sc; register struct tk_drv *tp; unit = minor(dev) & 7; sc = &tk_softc[unit]; tp = &tk_drv[unit]; if(tp->tk_online != 0 && tp->tk_openf != 0) { if(((flag & (FWRITE|FREAD)) == FWRITE) || ((flag&FWRITE) && (tp->tk_flags&TK_WRITTEN))) { if (tkcmd(dev, TMS_WRITM, 1) == -1) goto badcls; if (tkcmd(dev, TMS_WRITM, 1) == -1) goto badcls; if (tkcmd(dev, TMS_BSF, 1) == -1) goto badcls; } if((minor(dev) & 0200) == 0) { tk_nrwt[unit] = 1; if (tkcmd(dev, TMS_REW, 0) == -1) goto badcls; } else if (tkcmd(dev, TMS_CSE, 0) == -1) goto badcls; } tp->tk_openf= 0; tk_cse[unit] = 0; return; badcls: u.u_error = ENXIO; return; } tkioctl(dev, cmd, data, flag) dev_t dev; int cmd; caddr_t data; int flag; { register struct tk_softc *sc; register struct buf *bp; register struct tk_drv *tp; struct buf *wbp, *wdp, *xbp; register callcount; /* number of times to call cmd routine */ struct mtop *mtop; /* mag tape cmd op to perform */ struct mtget *mtget; /* mag tape struct to get info in */ int fcount; /* number of files (or records) to space */ int unit, wunit, s; /* we depend of the values and order of the TMS ioctl codes here */ static tmsops[] = {TMS_WRITM,TMS_FSF,TMS_BSF,TMS_FSR,TMS_BSR,TMS_REW,TMS_OFFL,TMS_SENSE, TMS_CACHE,TMS_NOCACHE,TMS_CSE,TMS_CLX,TMS_CLS,TMS_ASYNC,TMS_NOASYNC, TMS_ENAEOT,TMS_DISEOT}; unit = minor(dev) & 7; tp = &tk_drv[unit]; sc = &tk_softc[unit]; bp = &ctkbuf[unit]; callcount = fcount = 0; switch (cmd) { case MTIOCTOP: /* tape operation */ mtop = (struct mtop *)data; switch (mtop->mt_op) { case MTWEOF: callcount = mtop->mt_count; fcount = 1; break; case MTBSF: case MTBSR: case MTFSF: case MTFSR: callcount = 1; fcount = mtop->mt_count; break; case MTREW: case MTOFFL: tk_nrwt[unit] = 1; case MTCACHE: case MTNOCACHE: callcount = 1; fcount = 1; break; case MTASYNC: case MTNOASYNC: return(0); case MTCLX: case MTCLS: wdp = &tkwtab; wbp = wdp->av_forw; while (wbp != 0 && wbp != wdp) { xbp = wbp->av_forw; wunit = minor(wbp->b_dev) & 7; /* * Unlink buffer from I/O wait queue. */ if (wunit == unit) { wbp->av_back->av_forw = wbp->av_forw; wbp->av_forw->av_back = wbp->av_back; if (wbp != bp) { wbp->b_error = EIO; wbp->b_flags |= B_ERROR; iodone(wbp); } } wbp = xbp; } while ((wbp = tktab[unit].b_actf) != NULL) { tktab[unit].b_actf = wbp->av_forw; if (wbp != bp) { wbp->b_error = EIO; wbp->b_flags |= B_ERROR; iodone(wbp); } } if (tp->tk_flags&TK_BUSY) { bp->b_flags &= ~B_BUSY; tp->tk_flags &= ~TK_BUSYF; iodone(bp); } if (tp->tk_flags&TK_WAIT) { bp->b_flags &= ~B_WANTED; tp->tk_flags &= ~TK_WAITF; wakeup((caddr_t)bp); } if (tk_wait[unit] != 0) { tk_wait[unit] = 0; wakeup((caddr_t)&tk_wait[unit]); } if(tkinit(unit)) { u.u_error = ENXIO; return(0); } s = spl6(); timeout(wakeup,(caddr_t)&tk_softc[unit],15*hz); sleep((caddr_t)&tk_softc[unit], PSWP+1); splx(s); s = spl5(); if (sc->sc_state != S_RUN) { u.u_error = ENXIO; return(0); } tk_rew[unit] = 0; tk_eot[unit] = 0; tk_nrwt[unit] = 0; tk_clex[unit] = 0; tk_fmt[unit] = 0; tp->tk_flags &= TK_DEOT; tp->tk_online = 0; tp->tk_openf= 0; /* tkstart(unit); /* for multi-driver */ return(0); case MTENAEOT: tp->tk_flags &= ~TK_DEOT; return(0); case MTDISEOT: tp->tk_flags |= TK_DEOT; return(0); case MTCSE: tp->tk_flags |= TK_CSE; callcount = 1; fcount = 1; break; default: return (ENXIO); } /* end switch mtop->mt_op */ if (callcount <= 0 || fcount <= 0) return (EINVAL); while (--callcount >= 0) { tkcmd(dev, tmsops[mtop->mt_op], fcount); if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && bp->b_resid) return (EIO); if (mtop->mt_op == MTOFFL || mtop->mt_op == MTREW) { tk_eot[unit] = 0; if (mtop->mt_op == MTOFFL) { tp->tk_online = 0; tp->tk_openf = 0; } } if (bp->b_flags & B_ERROR) /* like hitting BOT */ break; } return (geterror(bp)); case MTIOCGET: mtget = (struct mtget *)data; mtget->mt_type = MT_ISTK; mtget->mt_dsreg = tk_info[unit].tk_flags << 8; mtget->mt_dsreg |= tk_info[unit].tk_endcode; mtget->mt_erreg = tk_info[unit].tk_status; mtget->mt_resid = tk_info[unit].tk_resid; mtget->mt_softstat = 0; if (tk_eot[unit]) mtget->mt_softstat |= MT_EOT; if (tp->tk_flags&TK_DEOT) mtget->mt_softstat |= MT_DISEOT; if (tk_cache[unit]) mtget->mt_softstat |= MT_CACHE; break; default: return (ENXIO); } return (0); } /* * Initialize a TK50, * initialize data structures, and start hardware * initialization sequence. */ static tkinit(unit) { register struct tk_softc *sc; register struct tk_regs *tkaddr; unsigned cnt; sc = &tk_softc[unit]; tkaddr = tk_csr[unit]; /* * Start the hardware initialization sequence. */ if(tkaddr->tkasa & TK_ERR) { /* fatal cntlr error */ bad: tkfatal(unit, NOPANIC, sc->sc_state, tkaddr->tkasa); return(1); } tkaddr->tkaip = 0; /* start initialization */ cnt = 0177777; /* cntlr should enter S1 by 100us */ while ((tkaddr->tkasa & TK_STEP1) == 0) { if(--cnt == 0) goto bad; } tkaddr->tkasa = TK_ERR|(NCMDL2<<11)|(NRSPL2<<8)|TK_IE|(tk_ivec[unit]/4); /* * Initialization continues in interrupt routine. */ sc->sc_state = S_STEP1; sc->sc_credits = 0; return(0); } tkstrategy(bp) register struct buf *bp; { register daddr_t *p; int unit, s, fs; mapalloc(bp); unit = minor(bp->b_dev) & 7; if((unit >= ntk) || (tk_drv[unit].tk_dt == 0)) { bp->b_error = ENXIO; bp->b_flags |= B_ERROR; if (bp == &ctkbuf[unit]) tk_drv[unit].tk_flags &= ~TK_BUSY; iodone(bp); return; } s = spl5(); /* * Link the buffer onto the controller queue, */ bp->av_forw = 0; if(tktab[unit].b_actf == NULL) tktab[unit].b_actf = bp; else tktab[unit].b_actl->av_forw = bp; tktab[unit].b_actl = bp; if(tktab[unit].b_active == NULL) tkstart(unit); splx(s); } static tkstart(unit) { register struct buf *bp, *dp; register struct tmscp *mp; struct tk_softc *sc; struct tk_regs *tkaddr; int i; sc = &tk_softc[unit]; loop: if((bp = tktab[unit].b_actf) == NULL) { tktab[unit].b_active = NULL; return; } tktab[unit].b_active++; el_bdact |= (1 << TK_BMAJ); /* tell error log cntlr active */ tkaddr = tk_csr[unit]; if ((tkaddr->tkasa&TK_ERR) || sc->sc_state != S_RUN) { /* tkinit(unit); */ /* SHOULD REQUEUE OUTSTANDING REQUESTS, LIKE TKRESET */ /* return; */ tkfatal(unit, PANIC, sc->sc_state, tkaddr->tkasa); } if ((tk_drv[unit].tk_flags & TK_DEOT) == 0) { if (tk_eot[unit] == 1 && (tk_drv[unit].tk_flags&TK_CSE) == 0 && bp != &ctkbuf[unit]) goto next; } /* * If no credits, can't issue any commands * until some outstanding commands complete. */ if (sc->sc_credits < 2) return (0); if(tk_drv[unit].tk_online == 0) { tk_cse[unit] = 0; tkcommand(unit,M_O_ONLIN,1); goto loop; } if ((mp = tkgetcp(unit)) == NULL) return (0); sc->sc_credits--; /* committed to issuing a command */ mp->m_cmdref = bp; /* pointer to get back */ mp->m_elref = tk_elref[unit]++; /* error log ref # */ mp->m_unit = 0; if (tk_cse[unit]) { tk_cse[unit] = 0; mp->m_modifier = M_M_CLSEX; } else mp->m_modifier = 0; if (bp == &ctkbuf[unit]) { mp->m_bytecnt = 0; /* object count lo */ mp->m_zzz2 = 0; /* object count hi */ mp->m_tmcnt = 0; /* tape mark count lo */ mp->m_buf_h = 0; /* tape mark count hi */ switch (bp->b_resid) { case TMS_WRITM: mp->m_opcode = M_O_WRITM; break; case TMS_FSF: mp->m_opcode = M_O_REPOS; mp->m_modifier |= M_M_DLEOT; mp->m_tmcnt = bp->b_bcount; break; case TMS_BSF: mp->m_opcode = M_O_REPOS; mp->m_modifier |= M_M_REVRS; mp->m_tmcnt = bp->b_bcount; break; case TMS_FSR: mp->m_opcode = M_O_REPOS; mp->m_modifier |= M_M_OBJCT; mp->m_reccnt = bp->b_bcount; break; case TMS_BSR: mp->m_opcode = M_O_REPOS; mp->m_modifier |= (M_M_REVRS | M_M_OBJCT); mp->m_reccnt = bp->b_bcount; break; case TMS_REW: mp->m_opcode = M_O_REPOS; mp->m_modifier |= (M_M_REWND | M_M_CLSEX); tk_eot[unit] = 0; break; case TMS_OFFL: mp->m_opcode = M_O_AVAIL; mp->m_modifier |= (M_M_UNLOD | M_M_CLSEX); break; case TMS_CSE: mp->m_opcode = M_O_REPOS; mp->m_modifier |= M_M_CLSEX; mp->m_tmcnt = 0; tk_clex[unit] = 1; break; case TMS_CACHE: case TMS_NOCACHE: tk_cache[unit] = 0; if (bp->b_resid == TMS_CACHE) tk_cache[unit] = M_U_WBKNV; mp->m_opcode = M_O_SETUC; mp->m_format = tk_fmt[unit]; mp->m_unitflgs = tk_cache[unit]; mp->m_param = 0; mp->m_speed = 0; break; default: printf("Bad ioctl on tms unit %d\n", unit); mp->m_opcode = M_O_REPOS; break; } } else { tk_drv[unit].tk_flags &= ~TK_WRITTEN; mp->m_opcode = bp->b_flags&B_READ ? M_O_READ : M_O_WRITE; mp->m_bytecnt = bp->b_bcount; mp->m_zzz2 = 0; mp->m_buf_l = bp->b_un.b_addr; mp->m_buf_h = bp->b_xmem; } *((int *)mp->m_dscptr + 1) |= TK_OWN|TK_INT; i = tkaddr->tkaip; /* initiate polling */ /* * Move the buffer to the I/O wait queue. */ tktab[unit].b_actf = bp->av_forw; dp = &tkwtab; if(dp->av_forw == 0) { /* * Init I/O wait queue links. */ dp->av_forw = dp; dp->av_back = dp; } bp->av_forw = dp; bp->av_back = dp->av_back; dp->av_back->av_forw = bp; dp->av_back = bp; goto loop; next: tktab[unit].b_actf = bp->av_forw; bp->b_resid = bp->b_bcount; bp->b_error = ENOSPC; bp->b_flags |= B_ERROR; tk_info[unit].tk_status = M_S_SEX; tk_info[unit].tk_endcode = bp->b_flags&B_READ ? M_O_READ : M_O_WRITE; tk_info[unit].tk_flags = M_E_EOT|M_E_SEREX; tk_info[unit].tk_resid = 0; iodone(bp); goto loop; } /* * TK50 interrupt routine. */ tkintr(dev) { register struct tk_regs *tkaddr; register struct tk_softc *sc; register struct tk *tkp; struct tmscp *mp; int unit, i; char *ubm_off; /* address offset (if UB map used) */ if(ubmaps) ubm_off = (char *)&cfree; /* cfree = UB virtual addr 0 */ else ubm_off = 0; unit = minor(dev) & 7; tkp = &tk[unit]; tkaddr = tk_csr[unit]; sc = &tk_softc[unit]; switch (sc->sc_state) { case S_IDLE: logsi(tkaddr); return; case S_STEP1: #define STEP1MASK 0174377 #define STEP1GOOD (TK_STEP2|TK_IE|(NCMDL2<<3)|NRSPL2) if (tkmask(unit, STEP1MASK, STEP1GOOD, 1000, 30)) return; tkaddr->tkasa = ((char *)&tk[unit].tk_ca.ca_kringbase-ubm_off); /* tkaddr->tkasa = ((int)&tk[unit].tk_ca.ca_kringbase); */ sc->sc_state = S_STEP2; return; case S_STEP2: #define STEP2MASK 0174377 #define STEP2GOOD (TK_STEP3|TK_IE|(tk_ivec[unit]/4)) if (tkmask(unit, STEP2MASK, STEP2GOOD, 200, 100)) return; tkaddr->tkasa = 0; /* ringbase will always be in low 64kb */ sc->sc_state = S_STEP3; return; case S_STEP3: #define STEP3MASK 0174000 #define STEP3GOOD TK_STEP4 if (tkmask(unit, STEP3MASK, STEP3GOOD, 200, 100)) return; tk_ctid[unit] = tkaddr->tkasa & 0377; /* save controller type ID */ i = (tk_ctid[unit] >> 4) & 017; /* cntlr type for error msg's */ if(i == TK50) tk_dct[unit] = "TK50"; else if(i == TU81) tk_dct[unit] = "TU81"; else tk_dct[unit] = "TMSCP"; /* * Tell the controller to start normal operations. * Also set the NPR burst size to the default, * which is controller dependent. */ tkaddr->tkasa = TK_GO; sc->sc_state = S_SCHAR; /* * Initialize the data structures. */ for (i = 0; i < NRSP; i++) { tkp->tk_ca.ca_rspdsc[i].rh = TK_OWN|TK_INT; tkp->tk_ca.ca_rspdsc[i].rl = &tkp->tk_rsp[i].m_cmdref; (char *)tkp->tk_ca.ca_rspdsc[i].rl -= ubm_off; tkp->tk_rsp[i].m_dscptr = &tkp->tk_ca.ca_rspdsc[i].rl; tkp->tk_rsp[i].m_header.tk_msglen = sizeof(struct tmscp) - sizeof(struct tmscp_header); } for (i = 0; i < NCMD; i++) { tkp->tk_ca.ca_cmddsc[i].ch = TK_INT; tkp->tk_ca.ca_cmddsc[i].cl = &tkp->tk_cmd[i].m_cmdref; (char *)tkp->tk_ca.ca_cmddsc[i].cl -= ubm_off; tkp->tk_cmd[i].m_dscptr = &tkp->tk_ca.ca_cmddsc[i].cl; tkp->tk_cmd[i].m_header.tk_msglen = sizeof(struct tmscp) - sizeof(struct tmscp_header); tkp->tk_cmd[i].m_header.tk_vcid = 1; /* tape VCID=1 */ } sc->sc_lastcmd = 0; sc->sc_lastrsp = 0; if ((mp = tkgetcp(unit)) == NULL) { sc->sc_state = S_IDLE; wakeup((caddr_t)&tk_softc[unit]); return; } mp->m_opcode = M_O_STCON; mp->m_modifier = 0; mp->m_cntflgs = M_C_ATTN|M_C_MISC|M_C_THIS; *((int *)mp->m_dscptr + 1) |= TK_OWN|TK_INT; i = tkaddr->tkaip; /* initiate polling */ return; case S_SCHAR: case S_RUN: break; default: logsi(tkaddr); /* will print SI followed by address */ printf("\n%s unit %d: state=%d\n", tk_dct[unit], unit, sc->sc_state); return; } if (tkaddr->tkasa&TK_ERR) { /* printf("%s unit %d: fatal error (%o)\n", tk_dct[unit], unit, tkaddr->tkasa); tkaddr->tkaip = 0; wakeup((caddr_t)&tk_softc[unit]); */ tkfatal(unit, PANIC, sc->sc_state, tkaddr->tkasa); } /* * Check for response ring transition. */ if (tkp->tk_ca.ca_rspint) { tkp->tk_ca.ca_rspint = 0; for (i = sc->sc_lastrsp;; i++) { i %= NRSP; if (tkp->tk_ca.ca_rspdsc[i].rh&TK_OWN) break; tkrsp(unit, tkp, sc, i); tkp->tk_ca.ca_rspdsc[i].rh |= TK_OWN; } sc->sc_lastrsp = i; } /* * Check for command ring transition. */ if (tkp->tk_ca.ca_cmdint) { tkp->tk_ca.ca_cmdint = 0; wakeup((caddr_t)&tk[unit].tk_ca.ca_cmdint); } tkstart(unit); } /* * Process a response packet */ tkrsp(unit, tkp, sc, i) register struct tk *tkp; register struct tk_softc *sc; int i; { register struct tmscp *mp; register struct tk_drv *tp; struct buf *bp; int st; int opcode, flags; int msglen; tp = &tk_drv[unit]; mp = &tkp->tk_rsp[i]; /* need changes */ msglen = mp->m_header.tk_msglen; mp->m_header.tk_msglen = sizeof(struct tmscp)-sizeof(struct tmscp_header); sc->sc_credits += mp->m_header.tk_credits & 017; if(sc->sc_tcmax < sc->sc_credits) /* save xfer credit limit */ sc->sc_tcmax = sc->sc_credits; if ((mp->m_header.tk_credits & 0360) > 020) return; /* * If it's an error log message (datagram), * pass it on for more extensive processing. */ if ((mp->m_header.tk_credits & 0360) == 020) { tkerror(unit, (struct tmslg *)mp, msglen); return; } if (mp->m_unit != 0) return; /* * store information if not clear serious exception */ if (tk_clex[unit] == 0) { tk_info[unit].tk_status = mp->m_status; tk_info[unit].tk_endcode = mp->m_opcode; tk_info[unit].tk_flags = mp->m_flags; tk_info[unit].tk_resid = 0; } else tk_clex[unit] = 0; st = mp->m_status&M_S_MASK; opcode = mp->m_opcode&0377; flags = mp->m_flags&0377; switch (opcode) { case M_O_STCON|M_O_END: if (st == M_S_SUCC) sc->sc_state = S_RUN; else sc->sc_state = S_IDLE; el_bdact &= ~(1 << TK_BMAJ); tktab[unit].b_active = 0; wakeup((caddr_t)&tk_softc[unit]); break; case M_O_ONLIN|M_O_END: if (flags != 0 && ((flags&M_E_SEREX) || (flags&M_E_PLS))) tp->tk_online = 0; /* mark drive offline */ else if ((st == M_S_SUCC) || (st == M_S_OFFLN)) { tp->tk_dt = *((int *)&mp->m_mediaid)&0177; if(st == M_S_SUCC) tp->tk_online = 1; else tp->tk_online = 0; } else { tp->tk_dt = 0; /* mark drive NED */ tp->tk_online = 0; /* mark drive offline */ } if(tp->tk_online == 0) { printf("\n%s unit %d OFFLINE: status=%o\n", tk_dct[unit], unit, mp->m_status); while((bp = tktab[unit].b_actf) != NULL) { tktab[unit].b_actf = bp->av_forw; bp->b_error = ENXIO; bp->b_flags |= B_ERROR; if (bp == &ctkbuf[unit]) tp->tk_flags &= ~TK_BUSY; iodone(bp); } } if(mp->m_cmdref) wakeup((caddr_t)mp->m_cmdref); break; /* * The AVAILABLE ATTENTION messages occurs when the * unit becomes available after spinup, * marking the unit offline will force an online command * prior to using the unit and also make sure it will * do the initialization if there is off and on happen. */ case M_O_AVATN: tk_eot[unit] = 0; /* magtape not at EOT */ tp->tk_online = 0; /* mark unit offline */ break; case M_O_END: /* * An endcode without an opcode (0200) is an invalid command. An illegal * opcode or parameter error will cause an invalid command error. */ printf("\n%s unit %d: inv cmd err, ", tk_dct[unit], unit); printf("endcd=%o, stat=%o\n", opcode, mp->m_status); if ((char *)mp->m_cmdref == &tk_drv[unit].tk_dt) { tp->tk_online = 0; /* mark drive offline */ wakeup((caddr_t)mp->m_cmdref); } else { bp = (struct buf *)mp->m_cmdref; /* * Unlink buffer from I/O wait queue. */ bp->av_back->av_forw = bp->av_forw; bp->av_forw->av_back = bp->av_back; bp->b_error = EIO; bp->b_flags |= B_ERROR; iodone(bp); } break; case M_O_SETUC|M_O_END: if ((char *)mp->m_cmdref == &tk_drv[unit].tk_dt) { if(st != M_S_SUCC) tp->tk_online = 0; /* mark drive offline */ wakeup((caddr_t)mp->m_cmdref); break; } case M_O_WRITE|M_O_END: case M_O_READ|M_O_END: case M_O_REPOS|M_O_END: case M_O_WRITM|M_O_END: case M_O_AVAIL|M_O_END: /* Say last op was a write (need to write TMs on close) */ if (opcode == (M_O_WRITE|M_O_END)) tp->tk_flags |= TK_WRITTEN; bp = (struct buf *)mp->m_cmdref; /* * Unlink buffer from I/O wait queue. */ bp->av_back->av_forw = bp->av_forw; bp->av_forw->av_back = bp->av_back; if (st == M_S_TAPEM || st == M_S_LED || st == M_S_BOT) { if (opcode == (M_O_READ|M_O_END)) { if((bp->b_flags&B_PHYS) == 0) clrbuf(bp); bp->b_resid = bp->b_bcount; tk_info[unit].tk_resid = bp->b_resid; } tk_cse[unit] = 1; iodone(bp); break; } /* * Fatal I/O error, * format a block device error log record and * log it if possible, print error message if not. */ if (st != M_S_SUCC) { bp->b_flags |= B_ERROR; if (st&M_S_BOT) tk_eot[unit] = 0; } if (mp->m_status & M_SS_EOT) { if (tp->tk_flags & TK_DEOT) tk_cse[unit] = 1; tk_eot[unit] = 1; } else if (mp->m_flags & M_E_EOT) { tk_eot[unit] = 1; } else { tk_eot[unit] = 0; tp->tk_flags &= ~TK_CSE; } if((bp->b_flags&B_ERROR) || (mp->m_flags&M_E_ERLOG)) { fmtbde(bp, &tk_ebuf[unit], (int *)mp, ((sizeof(struct tmscp_header)/2)+(msglen/2)), 0); tk_ebuf[unit].tk_bdh.bd_csr = tk_csr[unit]; /* hi byte of XMEM is drive type for ELP ! */ tk_ebuf[unit].tk_bdh.bd_xmem |= (tp->tk_dt << 8); tk_ebuf[unit].tk_reg[0] = msglen; /* real message length */ if(st == M_S_SUCC) tk_ebuf[unit].tk_bdh.bd_errcnt = 2; /* soft error */ else tk_ebuf[unit].tk_bdh.bd_errcnt = 0; /* hard error */ if (st == M_S_OFFLN || st == M_S_AVLBL) { tp->tk_online = 0; /* mark unit offline */ printf("%s unit %d Offline\n", tk_dct[unit], unit); } else if((mp->m_status&M_S_MASK) == M_S_WRTPR) printf("%s unit %d Write Locked\n",tk_dct[unit],unit); else { if(!logerr(E_BD, &tk_ebuf[unit], (sizeof(struct elrhdr) + sizeof(struct el_bdh) + msglen + sizeof(struct tmscp_header)))) deverror(bp, ((mp->m_opcode&0377) | (mp->m_flags<<8)), mp->m_status); } } bp->b_resid = bp->b_bcount - mp->m_bytecnt; tk_info[unit].tk_resid = bp->b_resid; if (tk_nrwt[unit] == 1) { tk_rew[unit] = 0; tk_nrwt[unit] = 0; if (tk_wait[unit] != 0) { tk_wait[unit] = 0; tp->tk_flags &= ~TK_REWT; wakeup((caddr_t)&tk_wait[unit]); } } else { if (bp == &ctkbuf[unit]) tp->tk_flags &= ~TK_BUSY; iodone(bp); } break; case M_O_GTUNT|M_O_END: if (mp->m_flags & M_E_EOT) tp->tk_flags |= TK_EOT; if (mp->m_unitflgs & (M_U_WRPH|M_U_WRPS)) tp->tk_flags |= TK_WRTP; if (mp->m_unitflgs&M_U_WBKNV) tk_cache[unit] = M_U_WBKNV; else tk_cache[unit] = 0; if (st != M_S_SUCC) { tp->tk_online = 0; /* mark unit offline */ printf("%s unit %d Offline\n", tk_dct[unit], unit); } wakeup((caddr_t)mp->m_cmdref); break; default: printf("\n%s unit %d: bad/unexp packet, len=%d opcode=%o\n", tk_dct[unit], unit, msglen, opcode); } /* * If no commands outstanding, say controller * is no longer active. */ if(sc->sc_credits == sc->sc_tcmax) el_bdact &= ~(1 << TK_BMAJ); } /* * Process an error log message * * Format an error log record of the type, tk datagram, * and log it if possible. * Also print a cryptic error message, this may change later ! */ tkerror(unit, mp, msglen) register struct tmslg *mp; { register int i; register int *p; struct buf *bp; if((mp->me_unit != 0) || (unit >= ntk) || /* THIS CHECK MUST STAY */ (mp->me_cmdref & 1)) { return; } tk_ebuf[unit].tk_hdr.e_time = time; /* * The following test will not work if error log * reference numbers are added to non data transfer commands. */ bp = (struct buf *)mp->me_cmdref; if(bp && mp->me_elref) { /* only for xfer commands */ tk_ebuf[unit].tk_bdh.bd_dev = bp->b_dev; } else tk_ebuf[unit].tk_bdh.bd_dev = ((TK_BMAJ<<8)|unit); tk_ebuf[unit].tk_bdh.bd_flags = 0100000; /* say TK datagram */ /* hi byte of XMEM is drive type for ELP ! */ tk_ebuf[unit].tk_bdh.bd_xmem = (tk_drv[unit].tk_dt << 8); tk_ebuf[unit].tk_bdh.bd_act = el_bdact; if((mp->me_flags & (M_LF_SUCC | M_LF_CONT)) == 0) tk_ebuf[unit].tk_bdh.bd_errcnt = 0; /* hard error */ else tk_ebuf[unit].tk_bdh.bd_errcnt = 2; /* soft error */ tk_ebuf[unit].tk_bdh.bd_nreg = ((msglen/2) + (sizeof(struct tmscp_header)/2)); p = (int *)mp; for(i=0; i<((msglen/2)+(sizeof(struct tmscp_header)/2)); i++) tk_ebuf[unit].tk_reg[i] = *p++; tk_ebuf[unit].tk_reg[0] = msglen; /* real message length */ if(logerr(E_BD, &tk_ebuf[unit], (sizeof(struct elrhdr) + sizeof(struct el_bdh) + msglen + sizeof(struct tmscp_header)))) return; /* no msg printed if error logged */ printf("\n%s unit %d: %s err, ", tk_dct[unit], unit, mp->me_flags&(M_LF_SUCC | M_LF_CONT) ? "soft" : "hard"); switch (mp->me_format&0377) { case M_F_CNTERR: printf("cont err, event=0%o\n", mp->me_event); break; case M_F_BUSADDR: printf("host mem access err, event=0%o, addr=%o 0%o\n", mp->me_event, mp->me_busaddr[1], mp->me_busaddr[0]); break; case M_F_TAPETRN: printf("xfer err, unit=%d, event=0%o\n", unit, mp->me_event); break; case M_F_STIERR: printf("STI err, unit=%d, event=0%o\n", unit, mp->me_event); break; case M_F_STIDEL: printf("STI drv err, unit=%d, event=0%o\n", unit, mp->me_event); break; case M_F_STIFEL : printf("STI fmt err, unit=%d, event=0%o\n", unit, mp->me_event); break; default: printf("unknown err, unit=%d, format=0%o, event=0%o\n", unit, mp->me_format&0377, mp->me_event); } /* * The tkaerror flag is normally set to zero, * setting it to one with ADB will cause the entire * error log packet to be printed as octal words, * for some poor sole to decode. */ #ifdef TKDBUG if (tk_error) { p = (int *)mp; for(i=0; i<((msglen + sizeof(struct tmscp_header))/2); i++) { printf("%o ", *p++); if((i&07) == 07) printf("\n"); } printf("\n"); } #endif TKDBUG } /* * Find an unused command packet * Only an immediate command can take the * last command descriptor. */ struct tmscp * tkgetcp(unit) { register struct tmscp *mp; register struct tkca *cp; register struct tk_softc *sc; int i; cp = &tk[unit].tk_ca; sc = &tk_softc[unit]; i = sc->sc_lastcmd; if ((cp->ca_cmddsc[i].ch & (TK_OWN|TK_INT)) == TK_INT) { cp->ca_cmddsc[i].ch &= ~TK_INT; mp = &tk[unit].tk_cmd[i]; mp->m_unit = mp->m_modifier = 0; mp->m_opcode = mp->m_flags = 0; mp->m_bytecnt = mp->m_zzz2 = 0; mp->m_buf_l = mp->m_buf_h = 0; mp->m_elgfll = mp->m_elgflh = 0; mp->m_copyspd = 0; sc->sc_lastcmd = (i + 1) % NCMD; return(mp); } return(NULL); } tkfatal(unit, tkp, st, sa) { printf("\nTMSCP cntlr %d fatal error: ", unit); printf("CSR=%o SA=%o state=%d\n", tk_csr[unit], sa, st); if(tkp) panic("TMSCP fatal"); } static tkcmd(dev, com, count) { register struct buf *bp; register struct tk_drv *tp; int unit; unit = minor(dev) & 7; tp = &tk_drv[unit]; bp = &ctkbuf[unit]; spl5(); while(bp->b_flags&B_BUSY) { bp->b_flags |= B_WANTED; tp->tk_flags |= (TK_WAIT|TK_WAITF); sleep((caddr_t)bp, PRIBIO); if ((tp->tk_flags&TK_WAITF) == 0) return(-1); } spl0(); bp->b_dev = dev; bp->b_resid = com; bp->b_bcount = count; bp->b_blkno = 0; tp->tk_flags |= (TK_BUSY|TK_BUSYF); bp->b_flags = B_BUSY|B_READ; tkstrategy(bp); if(tk_nrwt[unit] == 1) { tp->tk_flags &= ~TK_BUSY; tk_rew[unit] = 1; } else { iowait(bp); if (tp->tk_flags&TK_WAIT) { tp->tk_flags &= ~TK_BUSY; return(-1); } } if(bp->b_flags&B_WANTED) { tp->tk_flags &= ~TK_BUSY; wakeup((caddr_t)bp); } bp->b_flags &= B_ERROR; } tkcommand(unit,op,flag) { register struct tk_softc *sc; register struct tmscp *mp; struct tk_regs *tkaddr; int i; while((mp = tkgetcp(unit)) == NULL) { if (flag) return(1); else sleep((caddr_t)&tk[unit].tk_ca.ca_cmdint, PSWP+1); } tkaddr = tk_csr[unit]; sc = &tk_softc[unit]; sc->sc_credits--; mp->m_opcode = op; mp->m_modifier = 0; mp->m_unit = 0; if (op != M_O_GTUNT) { mp->m_format = tk_fmt[unit]; mp->m_modifier = M_M_CLSEX; mp->m_unitflgs = tk_cache[unit]; mp->m_param = 0; mp->m_speed = 0; } if (flag) mp->m_cmdref = 0; else mp->m_cmdref = &tk_drv[unit].tk_dt; mp->m_elref = 0; /* MBZ, see tkerror() */ *((int *)mp->m_dscptr + 1) |= TK_OWN|TK_INT; i = tkaddr->tkaip; if (flag == 0) sleep((caddr_t)mp->m_cmdref, PSWP+1); return(0); } tkmask(unit, mask, good, delay, times) int unit, mask, good, delay, times; { struct tk_regs *tkaddr; struct tk_softc *sc; register i, j; tkaddr = tk_csr[unit]; sc = &tk_softc[unit]; j = 0; while(1) { if ((tkaddr->tkasa&mask) != good) { for(i=0;isc_state = S_IDLE; wakeup((caddr_t)&tk_softc[unit]); return(1); } else return(0); } } p); } } if(mp->m_cmdref) wakeup((caddr_t)mp->m_cmdref); break; /* * The AVAILABLE ATTENTION messages occurs when the * unit becomes available after spinup, * marking the unit offline will force an online command * prior to using the unit and also make sure it will * do the initialization ifsys/OTHERS/tk/4.3BSD/ 755 3 12 0 4301136514 7040 sys/OTHERS/tk/4.3BSD/tmscp.h 440 3 12 26042 4301136211 10434 /* @(#)tmscp.h 7.2 (Berkeley) 5/27/88 */ /* * @(#)tmscp.h 1.3 10/21/85 * Definitions for the Tape Mass Storage Control Protocol */ /**************************************************************** * * * Licensed from Digital Equipment Corporation * * Copyright (c) * * Digital Equipment Corporation * * Maynard, Massachusetts * * 1985, 1986 * * All rights reserved. * * * * The Information in this software is subject to change * * without notice and should not be construed as a commitment * * by Digital Equipment Corporation. Digital makes no * * representations about the suitability of this software for * * any purpose. It is supplied "As Is" without expressed or * * implied warranty. * * * * If the Regents of the University of California or its * * licensees modify the software in a manner creating * * diriviative copyright rights, appropriate copyright * * legends may be placed on the drivative work in addition * * to that set forth above. * * * **************************************************************** * * Modification history: /sys/vax/tmscp.h * * 18-Oct-85 - afd * Added: defines for tape format (density) flag values. * * 18-Jul-85 - afd * Added: #define M_UF_WBKNV 0000100 * for write back (which enables cache). ************************************************************************/ /* * Control message opcodes */ #define M_OP_ABORT 0001 /* Abort command */ #define M_OP_GTCMD 0002 /* Get command status command */ #define M_OP_GTUNT 0003 /* Get unit status command */ #define M_OP_STCON 0004 /* Set controller characteristics command */ #define M_OP_AVAIL 0010 /* Available command */ #define M_OP_ONLIN 0011 /* Online command */ #define M_OP_STUNT 0012 /* Set unit characteristics command */ #define M_OP_DTACP 0013 /* Determine access paths command */ #define M_OP_ACCES 0020 /* Access command */ #define M_OP_CMPCD 0021 /* Compare controller data command */ #define M_OP_ERASE 0022 /* Erase command */ #define M_OP_FLUSH 0023 /* Flush command */ #define M_OP_ERGAP 0026 /* Erase gap command */ #define M_OP_COMP 0040 /* Compare host data command */ #define M_OP_READ 0041 /* Read command */ #define M_OP_WRITE 0042 /* Write command */ #define M_OP_WRITM 0044 /* Write tape mark command */ #define M_OP_REPOS 0045 /* Reposition command */ #define M_OP_AVATN 0100 /* Available attention message */ #define M_OP_DUPUN 0101 /* Duplicate unit number attention message */ #define M_OP_ACPTH 0102 /* Access path attention message */ #define M_OP_END 0200 /* End message flag */ /* * Generic command modifiers */ #define M_MD_COMP 0040000 /* Compare */ #define M_MD_CLSEX 0020000 /* Clear serious exception */ #define M_MD_SECOR 0001000 /* Suppress error correction */ #define M_MD_SEREC 0000400 /* Suppress error recovery */ #define M_MD_STWRP 0000004 /* Set write protect */ #define M_MD_ALLCD 0000002 /* All class drivers */ #define M_MD_NXUNT 0000001 /* Next unit */ /* * TMSCP command modifiers */ #define M_MD_DLEOT 0000200 /* Delete LEOT */ #define M_MD_IMMED 0000100 /* Immediate completion */ #define M_MD_EXCAC 0000040 /* Exclusive access */ #define M_MD_UNLOD 0000020 /* Unload */ #define M_MD_REVRS 0000010 /* reverse */ #define M_MD_OBJCT 0000004 /* object count */ #define M_MD_REWND 0000002 /* rewind */ /* * End message flags */ #define M_EF_ERLOG 0040 /* Error log generated */ #define M_EF_SEREX 0020 /* Serious exception */ #define M_EF_EOT 0010 /* End of tape encountered */ #define M_EF_PLS 0004 /* Position lost */ /* * Controller flags */ #define M_CF_ATTN 0200 /* Enable attention messages */ #define M_CF_MISC 0100 /* Enable miscellaneous error log messages */ #define M_CF_OTHER 0040 /* Enable other host's error log messages */ #define M_CF_THIS 0020 /* Enable this host's error log messages */ /* * Unit flags */ #define M_UF_WRTPH 0020000 /* Write protect (hardware) */ #define M_UF_WRTPS 0010000 /* Write protect (software or volume) */ #define M_UF_WBKNV 0000100 /* Write back (enables cache) */ #define M_UF_VSMSU 0000040 /* Variable speed mode suppression */ #define M_UF_VARSP 0000020 /* Variable speed unit */ #define M_UF_CMPWR 0000002 /* Compare writes */ #define M_UF_CMPRD 0000001 /* Compare reads */ /* * Status codes */ #define M_ST_MASK 037 /* Status code mask */ #define M_ST_SUCC 000 /* Success */ #define M_ST_ICMD 001 /* Invalid command */ #define M_ST_ABRTD 002 /* Command aborted */ #define M_ST_OFFLN 003 /* Unit offline */ #define M_ST_AVLBL 004 /* Unit available */ #define M_ST_WRTPR 006 /* Write protected */ #define M_ST_COMP 007 /* Compare error */ #define M_ST_DATA 010 /* Data error */ #define M_ST_HSTBF 011 /* Host buffer access error */ #define M_ST_CNTLR 012 /* Controller error */ #define M_ST_DRIVE 013 /* Drive error */ #define M_ST_FMTER 014 /* Formatter error */ #define M_ST_BOT 015 /* BOT encountered */ #define M_ST_TAPEM 016 /* Tape mark encountered */ #define M_ST_RDTRN 020 /* Record data truncated */ #define M_ST_PLOST 021 /* Position lost */ #define M_ST_SEX 022 /* Serious exception */ #define M_ST_LED 023 /* LEOT detected */ #define M_ST_DIAG 037 /* Message from an internal diagnostic */ /* * An MSCP packet */ struct mscp { struct mscp_header mscp_header;/* device specific header */ long mscp_cmdref; /* command reference number */ short mscp_unit; /* unit number */ short mscp_xxx1; /* unused */ u_char mscp_opcode; /* opcode */ u_char mscp_flags; /* end message flags */ short mscp_modifier; /* modifiers */ union { struct { long Mscp_bytecnt; /* byte count */ long Mscp_buffer; /* buffer descriptor */ long Mscp_mapbase; /* physical addr of map registers */ long Mscp_xxx2; /* unused */ long Mscp_lbn; /* logical block number */ long Mscp_xxx4; /* unused */ long *Mscp_dscptr; /* pointer to descriptor (software) */ long Mscp_sftwds[17];/* software words, padding */ } mscp_generic; struct { short Mscp_version; /* MSCP version */ short Mscp_cntflgs; /* controller flags */ short Mscp_hsttmo; /* host timeout */ short Mscp_usefrac; /* use fraction */ quad Mscp_time; /* time and date */ long Mscp_cntdep; /* controller dependent parameters */ } mscp_setcntchar; struct { short Mscp_multunt; /* multi-unit code */ short Mscp_unitflgs; /* unit flags */ long Mscp_hostid; /* host identifier */ quad Mscp_unitid; /* unit identifier */ long Mscp_mediaid; /* media type identifier */ short Mscp_format; /* format (tape density) */ short Mscp_speed; /* tape speed = (ips * bpi) /1000 */ short Mscp_fmtmenu; /* format menu */ short Mscp_group; /* group size */ short Mscp_cylinder; /* cylinder size */ short Mscp_xxx3; /* reserved */ short Mscp_rctsize; /* RCT table size */ char Mscp_rbns; /* RBNs / track */ char Mscp_rctcpys; /* RCT copies */ } mscp_getunitsts; } mscp_un; short mscp_fil1; short mscp_fil2; short mscp_fil3; }; #define mscp_msglen (sizeof (struct mscp) - sizeof(struct mscp_header)) /* * generic packet */ #define mscp_bytecnt mscp_un.mscp_generic.Mscp_bytecnt #define mscp_buffer mscp_un.mscp_generic.Mscp_buffer #define mscp_mapbase mscp_un.mscp_generic.Mscp_mapbase #define mscp_lbn mscp_un.mscp_generic.Mscp_lbn #define mscp_dscptr mscp_un.mscp_generic.Mscp_dscptr #define mscp_sftwds mscp_un.mscp_generic.Mscp_sftwds #define mscp_status mscp_modifier /* * Abort / Get Command Status packet */ #define mscp_outref mscp_bytecnt /* * Set Controller Characteristics packet */ #define mscp_version mscp_un.mscp_setcntchar.Mscp_version #define mscp_cntflgs mscp_un.mscp_setcntchar.Mscp_cntflgs #define mscp_hsttmo mscp_un.mscp_setcntchar.Mscp_hsttmo #define mscp_usefrac mscp_un.mscp_setcntchar.Mscp_usefrac #define mscp_time mscp_un.mscp_setcntchar.Mscp_time #define mscp_cntdep mscp_un.mscp_setcntchar.Mscp_cntdep /* * Reposition command packet fields */ #define mscp_reccnt mscp_bytecnt /* record/object count */ #define mscp_tmkcnt mscp_buffer /* tape mark count */ /* * Get Unit Status end packet */ #define mscp_multunt mscp_un.mscp_getunitsts.Mscp_multunt #define mscp_unitflgs mscp_un.mscp_getunitsts.Mscp_unitflgs #define mscp_hostid mscp_un.mscp_getunitsts.Mscp_hostid #define mscp_unitid mscp_un.mscp_getunitsts.Mscp_unitid #define mscp_mediaid mscp_un.mscp_getunitsts.Mscp_mediaid #define mscp_format mscp_un.mscp_getunitsts.Mscp_format /* density:0=high */ #define mscp_speed mscp_un.mscp_getunitsts.Mscp_speed /* (ips*bpi)/1000 */ #define mscp_fmtmenu mscp_un.mscp_getunitsts.Mscp_fmtmenu /* * Online / Set Unit Characteristics end packet */ #define mscp_maxwrt mscp_dscptr /* max write byte count */ #define mscp_noiserec mscp_cylinder /* noise record */ /* * Set Controller Characteristics end packet */ #define mscp_cnttmo mscp_hsttmo /* controller timeout */ #define mscp_cntcmdl mscp_usefrac /* controller soft & hardware version */ #define mscp_cntid mscp_unitid /* controller id */ /* * Error Log message format codes */ #define M_FM_CNTERR 0 /* Controller error */ #define M_FM_BUSADDR 1 /* Host memory access error */ #define M_FM_TAPETRN 5 /* Tape transfer error */ #define M_FM_STIERR 6 /* STI communication or command failure */ #define M_FM_STIDEL 7 /* STI drive error log */ #define M_FM_STIFEL 010 /* STI formatter error log */ /* * Error Log message flags */ #define M_LF_SUCC 0200 /* Operation successful */ #define M_LF_CONT 0100 /* Operation continuing */ #define M_LF_SQNRS 0001 /* Sequence number reset */ /* * Tape Format Flag Values */ #define M_TF_800 001 /* NRZI 800 bpi */ #define M_TF_PE 002 /* Phase Encoded 1600 bpi */ #define M_TF_GCR 004 /* Group Code Recording 6250 bpi */ #define M_TF_BLK 010 /* Cartridge Block Mode */ /* * MSCP Error Log packet * * NOTE: MSCP packet must be padded to this size. */ struct mslg { struct mscp_header mslg_header;/* device specific header */ long mslg_cmdref; /* command reference number */ short mslg_unit; /* unit number */ short mslg_seqnum; /* sequence number */ u_char mslg_format; /* format */ u_char mslg_flags; /* error log message flags */ short mslg_event; /* event code */ quad mslg_cntid; /* controller id */ u_char mslg_cntsvr; /* controller software version */ u_char mslg_cnthvr; /* controller hardware version */ short mslg_multunt; /* multi-unit code */ quad mslg_unitid; /* unit id */ u_char mslg_unitsvr; /* unit software version */ u_char mslg_unithvr; /* unit hardware version */ short mslg_group; /* group; retry + level */ long mslg_position; /* position (object count) */ u_char mslg_fmtsvr; /* formatter software version */ u_char mslg_fmthvr; /* formatter hardware version */ short mslg_xxx2; /* unused */ char mslg_stiunsucc[62]; /* STI status information */ }; #define mslg_busaddr mslg_unitid.val[0] #define mslg_sdecyl mslg_group [unit] = 1; } else { tk_eot[unit] = 0; tp->tk_flags &= ~TK_CSE; } if((bp->b_flags&B_ERROR) || (mp->m_flags&M_E_ERLOG)) { fmtbde(bp, &tk_ebuf[unit], (int *)mp, ((sizeof(struct tmscp_header)/2)+(msglen/2)), 0); tk_ebuf[unit].tk_bdh.bd_csr = tk_csr[unit]; /* hi byte of XMEM is drive type for ELP ! */ tk_ebuf[unit].tk_bdh.bd_xmem |= (tp->tk_dt << 8); tk_ebuf[unit].tk_reg[0] = msglen; /* real message length */ if(st == M_S_SUCC) tk_ebuf[usys/OTHERS/18bit_22bit/ 755 3 12 0 5350247055 7526 sys/OTHERS/18bit_22bit/README 640 3 12 1722 4307412457 10472 From nelslab!local@vax.cs.pittsburgh.edu Mon May 30 10:56:13 1988 Date: Sun, 29 May 88 21:31:27 EDT From: nelslab!local@vax.cs.pittsburgh.edu (Jack Nelson) To: bostic@ucbvax.Berkeley.EDU Subject: Using 18 bit devices with Q22 defined ... Status: RO Dear Keith, Here is the stuff I mentioned which comes from Matt Jacobs who was once at dual systems. I am using it with 2.10 so that I can access 18-bit tm11 tape drive (cipher 910 via western digital tc-151) in an otherwise 22bit environment. I define SOFUB_MAP, SOME18BIT as well as Q22, for reasons which should be clear below. I put my defines in a separate "jpn.h" just to keep from recompiling everything dependent on param.h. UUCP: { akgua | allegra | cmcl2 | idis | ihnp4 | mi-cec | pitt | psuvax1 | sun | sunrise | vax135 } ! cadre ! nelslab ! jack ARPA: jack@cadre.dsl.pittsburgh.edu John P. Nelson, M.D., 3811 O'Hara St, Pittsburgh, PA 15213, t:412-624-1769 Dept. of Psychiatry, U. of Pittsburgh 010 /* Data error */ #define M_ST_HSTBF 011 sys/OTHERS/18bit_22bit/machdep3.c 640 3 12 13707 4307412303 11456 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)machdep3.c 1.1 (2.10BSD Berkeley) 12/1/86 * jpn added Matt Jacobs code */ #include "jpn.h" #include "param.h" #include "../machine/seg.h" #include "../machine/iopage.h" #include "inode.h" #include "time.h" #include "resource.h" #include "proc.h" #include "fs.h" #include "map.h" #include "buf.h" #include "text.h" #include "file.h" #include "clist.h" #include "uba.h" #include "callout.h" #include "reboot.h" #include "errno.h" #include "systm.h" #include "ram.h" #ifdef SOFUB_MAP /* * sofmap - implement soft unibus map * for 22-bit q-bus systems * generally only used by the tape * driver (for tar and dump) * * matt jacob * University of California at Davis * 22-Nov-84 * Available to all Unix Licence holders * */ #define QMEG ((long)(256L*1024L)) #define exad(x,y) ((long)((long)x<<16|(unsigned)y)) #define B_UBUF exad(bp->b_xmem,(u_int)bp->b_un.b_addr) #define E_UBUF (B_UBUF + (long) bp->b_bcount) size_t sofub_addr; size_t sofub_off; memaddr sofub_base; unsigned sofub_size; int sofub_cnt; #ifdef SOFUB_DEBUG int bpxm; int bpadd; #endif /* * Sofub_alloc - allocate usage of soft unibus map * only one at a time for now... * * called from strategy routine of pertinent * device driver * * returns 0 if not okay, else returns 1. * expects a buffer pointer as an argument * expects all addresses in bp already validated (by physio) * sets appropriate bits and calls iodone if error * */ int Sofub_alloc(bp) register struct buf *bp; { register int s; register int count; size_t uaddr; memaddr sbase; extern size_t sofub_addr, sofub_off; extern memaddr sofub_base; extern unsigned sofub_size; extern int sofub_cnt; if(E_UBUF < QMEG) return(1); /* okay, < 256kb */ else if(bp->b_bcount > sofub_size) { uprintf("I/O > 256kb on device (%d,%d)\n\ Base = %ld, End = %ld\nSee System Manager.\n" ,major(bp->b_dev),minor(bp->b_dev),B_UBUF,E_UBUF); bp->b_flags |= B_ERROR; bp->b_error = EFAULT; iodone(bp); return(0); } /* * if map is busy, sleep on it... * */ while(sofub_cnt != 0) { #ifdef SOFUB_DEBUG printf("sleeping on sofub_cnt\n"); #endif sleep((caddr_t) &sofub_cnt,PSWP+2); } /* * now grab it... * */ sofub_cnt++; /* * now calculate virtual address of user buffer... * */ sofub_off = (size_t)((u_int)bp->b_un.b_addr & 077); sofub_addr = (size_t)(((u_int)bp->b_un.b_addr>>6)&01777) | (((int) bp->b_xmem) << 10); #ifdef SOFUB_DEBUG bpadd = (u_int)bp->b_un.b_addr; bpxm = bp->b_xmem; #endif /* * if this is a write, we have to fetch data from user buffer * first * */ if((bp->b_flags & B_READ) == 0) { count = bp->b_bcount; uaddr = sofub_addr; sbase = sofub_base; /* * first, copy all 8kb-1click segments.. * */ s = spl5(); while(count > (8192-64)) { copyv(uaddr,sofub_off,sbase,0,(8192-64)); count -= (8192-64); uaddr += 0177; /* add 8192-64 bytes */ sbase += 0177; } /* * copy last residual segment * */ copyv(uaddr,sofub_off,sbase,0,count); splx(s); } /* * put in new 18 bit address * */ bp->b_un.b_addr = (caddr_t)ctob((long)sofub_base); /* * don't turn sofub_base to clicks here * because half the work is done by * having it in click form here, i.e., * bp->b_xmem would equal * ctob(x)>>16 (hi six bits of 18) * */ bp->b_xmem = (sofub_base >> 10)&3; /* * and return with a good value * */ return(1); } /* * Sofub_relse - release sofub_map * * passed a buffer pointer * and a transfer byte count... * (for use if was a read) * * note, we are called at interrupt level... * so we save mapping context.. * */ Sofub_relse(bp,count) register struct buf *bp; register unsigned count; { register int s; size_t uaddr; memaddr sbase; mapinfo map; extern size_t sofub_addr, sofub_off; extern memaddr sofub_base; extern unsigned sofub_size; extern int sofub_cnt; /* * It is not clear that I have to save mapping here, * but it is probably just as well to do so, and to * conform to the 2.9 kernel interrupt protocol.... * */ savemap(map); if(sofub_cnt == 0) { restormap(map); return; /* not being used */ } else if(bp->b_flags & B_READ) { uaddr = sofub_addr; sbase = sofub_base; /* * first, copy all 8kb-1click segments.. * */ s = spl5(); while(count > (8192-64)) { copyv(sbase,0,uaddr,sofub_off,(8192-64)); count -= (8192-64); uaddr += 0177; /* add 8192-64 bytes */ sbase += 0177; } /* * copy last residual segment * */ copyv(sbase,0,uaddr,sofub_off,count); splx(s); } bp->b_un.b_addr = (caddr_t)((sofub_addr << 6) | sofub_off); bp->b_xmem = ((u_int)sofub_addr >> 10) & 077; #ifdef SOFUB_DEBUG if(bp->b_un.b_addr != bpadd || bp->b_xmem != bpxm) { printf("mismatch: new bp=(%o,%o), old bp=(%o,%o)\n", bp->b_un.b_addr,(int)bp->b_xmem,bpadd,bpxm); bp->b_flags |= B_ERROR; bp->b_error = EFAULT; } #endif /* * decrement reference count to map * */ sofub_cnt = MAX(0,sofub_cnt-1); /* * and wake up anyone waiting on it.... * */ if(sofub_cnt > 0) { printf("waking up on sofub_cnt\n"); wakeup((caddr_t) &sofub_cnt); } restormap(map); } /* * Sofub_init - initialize soft unibus map * * return # of clicks consumed.... * */ int Sofub_init() { extern size_t sofub_addr, sofub_off; extern memaddr sofub_base; extern unsigned sofub_size; extern int sofub_cnt; /* allocate a a 10 kb buffer for 18-bit raw xfers on q-bus */ #define B 10240+64 /* #define B 5120+64 */ sofub_cnt = 0; sofub_size = (unsigned) B; if ((sofub_base = malloc(coremap, btoc(B))) == 0) panic("Sofmap: no mem"); else if(((sofub_base+btoc(B))>>10) > 3) /* > 256kb! */ panic("Sofmap: > 256kb"); else { sofub_addr = sofub_base; /* for safety... */ sofub_off = (sofub_base>>10)&3; return(btoc(B)); } #undef B } #endif SOFUB_MAP MSCP Error Log packet * * NOTE: MSCP packet must be pasys/OTHERS/18bit_22bit/machdep2.dfc 640 3 12 5440 4307412304 11743 *** orgs/machdep2.c Sat Sep 5 13:52:25 1987 --- machdep2.c Wed Apr 13 11:02:32 1988 *************** *** 7,12 **** --- 7,13 ---- */ #include "param.h" + #include "jpn.h" #include "../machine/seg.h" #include "../machine/iopage.h" *************** *** 89,104 **** * 18-bit DMA disk or tape peripherals attached to 22-bit Q-BUS * machines. See extended notes in /sys/conf/GENERIC. */ #define MAXCLICK_16 896 /* 16 bit UNIBUS or QBUS */ #define MAXCLICK_18 3968 /* 18 bit UNIBUS or QBUS */ #define MAXCLICK_22U 61440 /* 22 bit UNIBUS (UNIBUS mapping) */ ! #define MAXCLICK_22 65408 /* 22 bit QBUS */ ! #ifdef Q22 maxclick = ubmap ? MAXCLICK_22U : MAXCLICK_22; ! #else maxclick = ubmap ? MAXCLICK_22U : MAXCLICK_18; ! #endif i = freebase = *ka6 + USIZE; UISD[0] = ((stoc(1) - 1) << 8) | RW; for (;;) { --- 90,116 ---- * 18-bit DMA disk or tape peripherals attached to 22-bit Q-BUS * machines. See extended notes in /sys/conf/GENERIC. */ + /* + * jpn added SOME18BIT define in jpn.h to indicate at least one + * controller has 18bit expectations, but may be 22bit bus and + * need Q22 defined so that high order address bits get set in + * the 22bit controllers, etc. So Q22 should always be defined + * if any 22bit controllers are on the bus. + */ #define MAXCLICK_16 896 /* 16 bit UNIBUS or QBUS */ #define MAXCLICK_18 3968 /* 18 bit UNIBUS or QBUS */ #define MAXCLICK_22U 61440 /* 22 bit UNIBUS (UNIBUS mapping) */ ! #define MAXCLICK_22 65407 /* 22 bit QBUS */ ! #ifdef Q22 ! # if defined(SOME18BIT) && defined(SOFUB_MAP) maxclick = ubmap ? MAXCLICK_22U : MAXCLICK_22; ! # else maxclick = ubmap ? MAXCLICK_22U : MAXCLICK_18; ! # endif ! #else Q22 ! maxclick = ubmap ? MAXCLICK_22U : MAXCLICK_18; ! #endif Q22 i = freebase = *ka6 + USIZE; UISD[0] = ((stoc(1) - 1) << 8) | RW; for (;;) { *************** *** 140,145 **** --- 152,161 ---- #else clstaddr = (ubadr_t)cfree; #endif + #ifdef SOFUB_MAP + maxmem -= Sofub_init(); + printf("done Sofub_init()\n"); + #endif #define B (size_t)(((long)nbuf * (MAXBSIZE)) / ctob(1)) if ((bpaddr = malloc(coremap, B)) == 0) *************** *** 162,172 **** maxmem -= ramsize; #endif - if (MAXMEM < maxmem) - maxmem = MAXMEM; - printf("phys mem = %D\n", ctob((long)physmem)); printf("avail mem = %D\n", ctob((long)maxmem)); printf("user mem = %D\n", ctob((long)maxmem)); #if NRAM > 0 printf("ram disk = %D\n", ctob((long)ramsize)); --- 178,187 ---- maxmem -= ramsize; #endif printf("phys mem = %D\n", ctob((long)physmem)); printf("avail mem = %D\n", ctob((long)maxmem)); + if (MAXMEM < maxmem) + maxmem = MAXMEM; printf("user mem = %D\n", ctob((long)maxmem)); #if NRAM > 0 printf("ram disk = %D\n", ctob((long)ramsize)); b_bcount; uaddr = sofub_addr; sbase = sofub_base; /* * first, copy all 8kb-1click segments.. * */ s = spl5(); while(count > (8192-64)) { copyv(uaddr,sofub_off,sbase,0,(8192-64)); count -= (8192-sys/OTHERS/18bit_22bit/mch_click.dfc 640 3 12 1772 5316470453 12212 *** orgs/mch_click.s Sat Aug 22 02:16:41 1987 --- mch_click.s Fri Dec 4 12:56:51 1987 *************** *** 8,13 **** --- 8,14 ---- #include "DEFS.h" #include "../machine/mch_iopage.h" + #include "jpn.h" /* *************** *** 225,231 **** #endif CGL_RTP ! #ifdef INET /* * copyv(fromaddr, toaddr, count) * virtual_addr fromaddr, --- 226,232 ---- #endif CGL_RTP ! #if defined(INET) || defined(SOFUB_MAP) /* * copyv(fromaddr, toaddr, count) * virtual_addr fromaddr, *************** *** 262,268 **** --- 263,271 ---- mov PS,-(sp) / save current PS bit $0340,(sp) / are we currently at SPL? bne 2f + #ifdef INET SPLNET / nope, lock out the network + #endif 2: mov KDSA5,-(sp) / save seg5 mov KDSD5,-(sp) *************** *** 298,304 **** 4: clr r0 / clear r0 and r1 (why?) rts pc / and return ! #endif /* --- 301,307 ---- 4: clr r0 / clear r0 and r1 (why?) rts pc / and return ! #endif INET | SOFUB_MAP /* added sys/OTHERS/emulex-cs02/ 755 3 12 0 5325716401 7637 sys/OTHERS/emulex-cs02/cs02-q22-fixes 640 3 12 15015 5317777574 12175 Received: from lanai.cs.ucla.edu (lanai.cs.ucla.edu.ARPA) by corwyn.cognet.ucla.edu (4.12/1.1) id AA02393; Wed, 17 Aug 88 12:45:53 pdt Return-Path: Received: from okeeffe.Berkeley.EDU by lanai.cs.ucla.edu (Sendmail 5.58.2/2.10) id AA02195; Wed, 17 Aug 88 12:43:36 PDT Received: by okeeffe.Berkeley.EDU (5.60/1.29) id AA01264; Wed, 17 Aug 88 12:45:18 PDT Date: Wed, 17 Aug 88 12:45:18 PDT From: bostic@okeeffe.Berkeley.EDU (Keith Bostic) Message-Id: <8808171945.AA01264@okeeffe.Berkeley.EDU> To: casey@cs.ucla.edu Subject: fix to dh Status: RO Not sure if we should put this in -- maybe as part of the man page for the dh? Or a README? Your choice... --keith > From tcdmath!ajudge@jade.berkeley.edu Wed Aug 17 11:02:26 1988 > Date: Wed, 17 Aug 88 18:21:39 BST > From: Alan Judge > Subject: New Release of 2.10 and Ethernetting > To: bostic@okeeffe.Berkeley.EDU > X-Fortune: Mix a little foolishness with your serious plans; it's lovely to be > silly at the right moment. -- Horace Also when we installed 2.10 we had a problem with port-boards because of a slight difference between Emulex CS-02 boards in DH-11/DM-11 emulation and the real thing. The rules for 22-bit QBUS operation are different. Anyway at the time we fixed the problem locally and since we were not on the net reliably I don't think we told anybody. In case the problem still remains unfixed I include patches for 2.10 for the problem. You can then post a fix to news if necessary. -- Alan Judge, System Administrator School of Mathematics, Trinity College, Dublin. ajudge@maths.tcd.ie RCS file: RCS/dh.c,v retrieving revision 1.1 diff -c -r1.1 dh.c *** /tmp/,RCSt1011296 Wed Aug 17 18:14:33 1988 --- dh.c Sun Nov 8 19:37:11 1987 *************** *** 405,413 **** --- 405,419 ---- #else { ubadr_t car; + #if defined(CS02) + struct dmdevice *dmaddr = (struct dmdevice *)dmi nfo[dh].ui_addr; + car = (ubadr_t)addr->dhcar; + car |= ((ubadr_t)(dmaddr->dmlst_h&077) << 16); + #else car = (ubadr_t) addr->dhcar | (ubadr_t)(addr->dhsilo & 0300) << 10; + #endif cntr = car - cpaddr(tp->t_outq.c_cf); ndflush(&tp->t_outq, cntr); } *************** *** 492,500 **** --- 498,514 ---- addr->dhcar = (u_short)cpaddr(tp->t_outq.c_cf); #else ubadr_t uba; + #if defined(CS02) + struct dmdevice *dmaddr = (struct dmdevice *)dminfo[dh].ui_addr; + #endif uba = cpaddr(tp->t_outq.c_cf); + #if defined(CS02) + addr->un.dhcsrl = (unit&017) | DH_IE; + dmaddr->dmlst_h = hiint(uba) & 077; + #else addr->un.dhcsrl = (unit&017) | DH_IE | ((hiint(uba)<<4)&060); + #endif addr->dhcar = loint(uba); #endif { short word = 1 << unit; =================================================================== RCS file: RCS/dmreg.h,v retrieving revision 1.1 diff -c -r1.1 dmreg.h *** /tmp/,RCSt1011296 Wed Aug 17 18:14:39 1988 --- dmreg.h Sun Nov 8 19:37:43 1987 *************** *** 11,19 **** --- 11,30 ---- */ struct dmdevice { short dmcsr; /* control status register */ + #if defined(CS02) + union { /* Need to access high byte independently */ + short dmlst_w; + char dmlst_b[2]; + } cs02un; + #define dmlstat cs02un.dmlst_w + #define dmlst_l cs02un.dmlst_b[0] /* low byte */ + #define dmlst_h cs02un.dmlst_b[1] /* high byte */ + #else short dmlstat; /* line status register */ + #endif short dmpad1[2]; }; + /* bits in dm csr */ #define DM_RF 0100000 /* ring flag */ Return-Path: tcdmath!@CUNYVM.CUNY.EDU:ajudge Return-Path: Received: from CUNYVM.CUNY.EDU (cunyvm.cuny.edu.ARPA) by corwyn.cognet.ucla.edu (4.12/1.1) id AA00331; Mon, 26 Sep 88 16:46:33 pdt Received: from CUNYVM.BITNET by CUNYVM.CUNY.EDU (IBM VM SMTP R1.1) with BSMTP id 7572; Mon, 26 Sep 88 18:48:06 EDT Received: from CUNYVM by CUNYVM.BITNET (Mailer X2.00) with BSMTP id 0180; Mon, 26 Sep 88 18:45:03 EDT Received: from IRLEARN.BITNET by CUNYVM.CUNY.EDU (IBM VM SMTP R1.1) with BSMTP id 7550; Mon, 26 Sep 88 18:45:01 EDT Received: from ccvax.ucd.ie by IRLEARN.BITNET (Mailer X1.24) with BSMTP id 0531; Sat, 24 Sep 88 19:39:42 GMT Received: from cs.tcd.ie by ccvax.ucd.ie; Sat, 24 Sep 88 19:35 GMT Received: from csclnb.uucp by cs.tcd.ie; Sat, 24 Sep 88 19:35 GMT Received: from maths by csclnb.cs.tcd.ie id aa28619; 24 Sep 88 19:33 EDT Date: Sat, 24 Sep 88 17:49:15 BST From: Alan Judge Subject: Re: Your fixes for pdpuba/dh.c To: casey@cognet.ucla.edu X-Fortune: If everything seems to be going well, you have obviously overlooked something. In-Reply-To: Your message of Mon, 29 Aug 88 00:58:18 -0700 . Message-Id: <8809241749.aa011619@hamilton.maths.tcd.ie> > Alan, > This is my third attempt to get through to you. Keith Bostic forwarded > your note about the changes you had to make to dh.c to get it to work > with the Emulex CS-02. I'd like to know if these changes are specific to > the Emulex, or to *any* DH on a QBUS. In particular, I wasn't aware that > there was any DH available for the QBUS. Is Emulex's the only such or > does DEC also supply one? Please answer as soon as possible. > > Casey I am just back from holidays and this message arrived today. It seems that this message arrived was delayed in IRLEARN.BITNET (a site in another irish university) for 3 weeks. None of your other messages have yet arrived. Normally the through-time by this link is less than an hour. Hopefully mail to ajudge@maths.tcd.ie should only take a matter of hours from the states. Something must have gone wrong while I was away. The manual for the CS02/H1 says that the board can emulate either one DH11/DM11 or 2 DHV11's. This and the programming section seems to imply that there is a DEC product. Unfortunately I don't know for sure. The Emulex board may be emulating the DH on some other bus. However the DEC product probably does not support 22-bit addressing as Emulex use part of the LSR (line status register for this). The patches ARE specific to 22-bit addressing on a Q-BUS, they may be specific to Emulex if DEC does have a 22-bit Q-BUS DH. -- Alan /* multi-unit code */ quad mslg_unitid; /* unit id */ u_char mslg_unitsvr; /* unit software version */ u_char mslg_unithvr; /* unit hardware version */ short mslg_group; /* group; retry + level */ long mslg_position; /* position (object count) */ u_char mslg_fmtsvr; /* formatter software version */ u_char mslg_fmthvr; /* formatter hardware version */ short mslg_xxx2; /* unused */ char mslg_stiunsucc[62]; /* STI status information */ }; #define mslg_busaddr mslg_unitid.val[0sys/OTHERS/pdpstand/ 755 3 12 0 4355044437 7415 sys/OTHERS/pdpstand/tm-ts-pred 640 3 12 5021 4355044437 11413 Replied: Fri, 30 Sep 88 02:27:16 -0700 Return-Path: cdl@mplvax.nosc.mil Received: from hera.cs.ucla.edu (cs.ucla.edu.ARPA) by corwyn.cognet.ucla.edu (4.12/1.1) id AA01375; Thu, 29 Sep 88 13:02:51 pdt Return-Path: Received: from mplvax.nosc.mil by hera.cs.ucla.edu (Sendmail 5.58.2/2.12) id AA19980; Thu, 29 Sep 88 13:01:52 PDT Received: by mplvax (5.51/5.0) id AA09749 for casey@cs.ucla.edu; Thu, 29 Sep 88 12:59:22 PDT Date: Thu, 29 Sep 88 12:59:22 PDT From: Carl Lowenstein Message-Id: <8809291959.AA09749@mplvax> To: casey@CS.UCLA.EDU Subject: how to tell a tm11 Newsgroups: comp.bugs.2bsd In-Reply-To: <16291@shemp.CS.UCLA.EDU> Organization: U.C. San Diego, Marine Physical Laboratory Cc: cdl Status: R In article <16291@shemp.CS.UCLA.EDU> you write: > The problem is that the TS and the TM share the same CSR address >(0172520), but the *standard* TS CSR is only two words long: > > /* > * TS11 controller registers > */ > struct tsdevice { > u_short tsdb; /* data buffer */ > u_short tssr; /* status register */ > }; > >and the TM CSR is seven words long: > > /* > * TM11 controller registers > */ > struct tmdevice { > u_short tmer; /* error register, per drive */ > u_short tmcs; /* control-status register */ > short tmbc; /* byte/frame count */ > caddr_t tmba; /* address */ > short tmdb; /* data buffer */ > short tmrd; /* read lines */ > short tmmr; /* maintenance register */ > }; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Thanks to networked computers, I got hold of my RT11 sources without having to leave this chair. DEC tells the difference between TS11 and TM11 with the following PDP11 assembly language (paraphrased): (this is DEC-flavor not unix-flavor assembly language) ;;;;;;;;;;;;;;;;;; MOV #MTCSR, R0 ; point to control-status MOV #1000, 2(R0) ; try to select unit 2 BIT #1000, 2(R0) ; did it work? BNE GOOD ; yes, it is a TM11 BAD: ; no, it isn't . . . GOOD: ;;;;;;;;;;;;;;;;;; I would take a first cut at translating this into C as: TMADDR->tmcs = 01000; /* try to select unit 2 */ if (TMADDR->tmcs & 01000) { /* do tm11 things */ } else { /* do ts11 things */ } /* note that selecting unit 2 is a benign thing to do even if you have only one TM11 drive. The controller can select up to 8 drives even if they are not present. Of course, the non-existent drive doesn't report that it is ready. */ carl carl lowenstein marine physical lab u.c. san diego {decvax|ucbvax} !ucsd!mplvax!cdl cpaddr(tp->t_outq.c_cf); #else ubadr_t uba; + #if defined(CS02) + struct dmdevice *dmaddr = (struct dmdevice *)dminfo[dh].ui_addr; + #endif uba = cpaddr(tp->t_outq.c_cf); + #if defined(CS02) + addr->un.dhcsrl = (unit&017) | DH_IE; + dmaddr->dmlst_h = hiint(uba) & 077; + #else addr->un.dhcsrl = (unit&017) | DH_IE | ((hiint(uba)<<4)&060); + #endif addr->dhcar = loint(uba); #endifsys/OTHERS/EXOS.204/ 755 3 12 0 4356067046 6664 sys/OTHERS/EXOS.204/if_ex.c.diffs 640 3 12 37577 4333656220 11331 The following are diffs from an slightly earlier version of the 4.3BSD Excelan driver found in /sys/vaxif. The work was done by: Kenichi Katsumi Engineering Computing Management Division. SONY/TEKTRONIX Corp. ...kddlab!muse!katsumi *** if_ex.c Fri Oct 14 17:06:14 1988 --- /sys/vaxif/if_ex.c Tue Sep 27 17:16:42 1988 *************** *** 1,9 **** ! /* ! * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)if_ex.c 7.1 (Berkeley) 6/5/86 */ --- 1,8 ---- ! /* Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)if_ex.c 7.2 (Berkeley) 10/13/86 */ *************** *** 17,63 **** * Excelan Inc. */ ! #include "../machine/pte.h" #include "param.h" ! #include "systm.h" #include "mbuf.h" - #include "buf.h" #include "protosw.h" #include "socket.h" - #include "vmmac.h" #include "ioctl.h" #include "errno.h" #include "../net/if.h" #include "../net/netisr.h" #include "../net/route.h" - #ifdef INET - #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netinet/in_var.h" #include "../netinet/ip.h" #include "../netinet/if_ether.h" - #endif - - #ifdef NS #include "../netns/ns.h" #include "../netns/ns_if.h" - #endif ! #include "../vax/cpu.h" ! #include "../vax/mtpr.h" ! #include "if_exreg.h" ! #include "if_uba.h" ! #include "../vaxuba/ubareg.h" ! #include "../vaxuba/ubavar.h" #define DEBUG /* check for "impossible" events */ #define NH2X 4 /* a sufficient number is critical */ #define NX2H 4 /* this is pretty arbitrary */ ! #define EXWATCHINTVL 10 /* call exwatch() every 10 seconds */ int exprobe(), exattach(), excdint(); struct uba_device *exinfo[NEX]; --- 16,66 ---- * Excelan Inc. */ ! /* ! * Modification from Berkeley 4.3BSD ! * for PDP11/44 2.10BSD ! * ! * Kenichi Katsumi ! * SONY/TEKTRONIX Corp. ! * 88/09/20 ! */ #include "param.h" ! #include "../machine/seg.h" ! ! #include "short_names.h" #include "mbuf.h" #include "protosw.h" #include "socket.h" #include "ioctl.h" #include "errno.h" + #ifdef BSD2_10 + # include "buf.h" + #endif + + #include "pdpuba/ubavar.h" + #include "../net/if.h" #include "../net/netisr.h" #include "../net/route.h" #include "../netinet/in_systm.h" + #include "../netinet/in.h" #include "../netinet/in_var.h" #include "../netinet/ip.h" #include "../netinet/if_ether.h" #include "../netns/ns.h" #include "../netns/ns_if.h" ! #include "../vaxif/if_uba.h" ! #include "../vaxif/if_exreg.h" #define DEBUG /* check for "impossible" events */ #define NH2X 4 /* a sufficient number is critical */ #define NX2H 4 /* this is pretty arbitrary */ ! #define EXWATCHINTVL 60 /* call exwatch() every 60 seconds */ int exprobe(), exattach(), excdint(); struct uba_device *exinfo[NEX]; *************** *** 94,102 **** #define EX_SETADDR (1<<3) /* physaddr has been changed */ struct ex_msg *xs_h2xnext; /* host pointer to request queue */ struct ex_msg *xs_x2hnext; /* host pointer to reply queue */ ! int xs_ubaddr; /* map info for structs below */ ! #define UNIADDR(x) ((u_long)(x)&0x3FFFF) ! #define P_UNIADDR(x) ((u_long)(x)&0x3FFF0) /* the following structures are always mapped in */ u_short xs_h2xhdr; /* EXOS's request queue header */ u_short xs_x2hhdr; /* EXOS's reply queue header */ --- 97,105 ---- #define EX_SETADDR (1<<3) /* physaddr has been changed */ struct ex_msg *xs_h2xnext; /* host pointer to request queue */ struct ex_msg *xs_x2hnext; /* host pointer to reply queue */ ! ubadr_t xs_ubaddr; /* map info for structs below */ ! #define UNIADDR(x) ((u_long)(x)&0x3FFFFL) ! #define P_UNIADDR(x) ((u_long)(x)&0x3FFF0L) /* the following structures are always mapped in */ u_short xs_h2xhdr; /* EXOS's request queue header */ u_short xs_x2hhdr; /* EXOS's reply queue header */ *************** *** 105,111 **** struct confmsg xs_cm; /* configuration message */ struct stat_array xs_xsa; /* EXOS writes stats here */ /* end mapped area */ ! #define INCORE_BASE(p) ((caddr_t)((u_long)(&(p)->xs_h2xhdr) & 0xFFFFFFF0)) #define RVAL_OFF(unit, n) \ ((caddr_t)(&(ex_softc[unit].n)) - INCORE_BASE(&ex_softc[unit])) #define LVAL_OFF(unit, n) \ --- 108,114 ---- struct confmsg xs_cm; /* configuration message */ struct stat_array xs_xsa; /* EXOS writes stats here */ /* end mapped area */ ! #define INCORE_BASE(p) ((caddr_t)((u_long)(&(p)->xs_h2xhdr) & 0xFFFFFFF0L)) #define RVAL_OFF(unit, n) \ ((caddr_t)(&(ex_softc[unit].n)) - INCORE_BASE(&ex_softc[unit])) #define LVAL_OFF(unit, n) \ *************** *** 142,148 **** * We program the EXOS interrupt vector, like dmf device. */ br = 0x15; ! cvec = (uba_hd[numuba].uh_lastiv -= 4); ex_cvecs[ex_ncall].xc_csraddr = addr; ex_cvecs[ex_ncall].xc_cvec = cvec; /* --- 145,151 ---- * We program the EXOS interrupt vector, like dmf device. */ br = 0x15; ! cvec = 0770; ex_cvecs[ex_ncall].xc_csraddr = addr; ex_cvecs[ex_ncall].xc_cvec = cvec; /* *************** *** 162,168 **** excdint(0); #endif ex_ncall++; ! return (sizeof(struct exdevice)); } /* --- 165,171 ---- excdint(0); #endif ex_ncall++; ! return (1); } /* *************** *** 179,184 **** --- 182,190 ---- register struct exdevice *addr = (struct exdevice *)ui->ui_addr; register struct ex_msg *bp; int unit = ui->ui_unit; + + if (ex_ncall == 0) + exinfo[unit] = ui; ifp->if_unit = ui->ui_unit; ifp->if_name = "ex"; ifp->if_mtu = ETHERMTU; *************** *** 318,323 **** --- 324,331 ---- int i; u_long shiftreg; + if (ex_ncall == 0) + exprobe(addr); xs->xs_flags = 0; /* * Reset EXOS, wait for self-test to complete *************** *** 331,340 **** cm->cm_1rsrv = 1; cm->cm_cc = 0xFF; cm->cm_opmode = 0; /* link-level controller mode */ ! cm->cm_dfo = 0x0101; /* enable host data order conversion */ cm->cm_dcn1 = 1; ! cm->cm_2rsrv[0] = ! cm->cm_2rsrv[1] = 0; cm->cm_ham = 3; /* absolute address mode */ cm->cm_3rsrv = 0; cm->cm_mapsiz = 0; --- 339,348 ---- cm->cm_1rsrv = 1; cm->cm_cc = 0xFF; cm->cm_opmode = 0; /* link-level controller mode */ ! cm->cm_dfo = 0x0101L; /* enable host data order conversion */ cm->cm_dcn1 = 1; ! cm->cm_2rsrv[0] = 0; ! cm->cm_2rsrv[1] = 0; cm->cm_ham = 3; /* absolute address mode */ cm->cm_3rsrv = 0; cm->cm_mapsiz = 0; *************** *** 342,352 **** cm->cm_byteptrn[1] = 0x03; /* by looking at this pattern */ cm->cm_byteptrn[2] = 0x07; cm->cm_byteptrn[3] = 0x0F; ! cm->cm_wordptrn[0] = 0x0103; ! cm->cm_wordptrn[1] = 0x070F; ! cm->cm_lwordptrn = 0x0103070F; for (i=0; i<20; i++) cm->cm_rsrvd[i] = 0; ! cm->cm_mba = 0xFFFFFFFF; cm->cm_nproc = 0xFF; cm->cm_nmbox = 0xFF; cm->cm_nmcast = 0xFF; --- 350,360 ---- cm->cm_byteptrn[1] = 0x03; /* by looking at this pattern */ cm->cm_byteptrn[2] = 0x07; cm->cm_byteptrn[3] = 0x0F; ! cm->cm_wordptrn[0] = 0x0103L; ! cm->cm_wordptrn[1] = 0x070FL; ! cm->cm_lwordptrn = 0x0103070FL; for (i=0; i<20; i++) cm->cm_rsrvd[i] = 0; ! cm->cm_mba = 0xFFFFFFFFL; cm->cm_nproc = 0xFF; cm->cm_nmbox = 0xFF; cm->cm_nmcast = 0xFF; *************** *** 402,408 **** * configuration to complete (guaranteed response * within 2 seconds). */ ! shiftreg = (u_long)0x0000FFFF; for (i = 0; i < 8; i++) { if (i == 4) shiftreg = P_UNIADDR(xs->xs_ubaddr) + CM_OFFSET(unit); --- 410,416 ---- * configuration to complete (guaranteed response * within 2 seconds). */ ! shiftreg = (u_long)0x0000FFFFL; for (i = 0; i < 8; i++) { if (i == 4) shiftreg = P_UNIADDR(xs->xs_ubaddr) + CM_OFFSET(unit); *************** *** 411,417 **** --- 419,428 ---- addr->xd_portb = (u_char)(shiftreg & 0xFF); shiftreg >>= 8; } + { + long i; for (i = 1000000; (cm->cm_cc == 0xFF) && i; --i); + } if (cm->cm_cc) printf("ex%d: configuration failed; cc = %x\n", unit, cm->cm_cc); *************** *** 555,561 **** --- 566,575 ---- struct mbuf *m; register int len, off, resid; register struct ifqueue *inq; + int s; + mapinfo map; + savemap(map); xs->xs_if.if_ipackets++; len = bp->mb_er.er_blks[0].bb_len - sizeof(struct ether_header) - 4; if (bp->mb_rply != LL_OK) { *************** *** 562,570 **** xs->xs_if.if_ierrors++; printf("ex%d: receive error=%b\n", unit, bp->mb_rply, RECV_BITS); return; } ! eh = (struct ether_header *)(xs->xs_ifuba.ifu_r.ifrw_addr); /* * Deal with trailer protocol: if type is trailer --- 576,586 ---- xs->xs_if.if_ierrors++; printf("ex%d: receive error=%b\n", unit, bp->mb_rply, RECV_BITS); + restormap(map); return; } ! mapseg5(xs->xs_ifuba.ifu_r.ifrw_click, MBMAPSIZE); ! eh = (struct ether_header *)MBX; /* * Deal with trailer protocol: if type is trailer *************** *** 576,592 **** if (eh->ether_type >= ETHERTYPE_TRAIL && eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { off = (eh->ether_type - ETHERTYPE_TRAIL) * 512; ! if (off >= ETHERMTU) return; /* sanity */ eh->ether_type = ntohs(*exdataaddr(eh, off, u_short *)); resid = ntohs(*(exdataaddr(eh, off+2, u_short *))); ! if (off + resid > len) return; /* sanity */ len = off + resid; } else off = 0; ! if (len == 0) return; /* * Pull packet off interface. Off is nonzero if packet --- 592,614 ---- if (eh->ether_type >= ETHERTYPE_TRAIL && eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { off = (eh->ether_type - ETHERTYPE_TRAIL) * 512; ! if (off >= ETHERMTU) { ! restormap(map); return; /* sanity */ + } eh->ether_type = ntohs(*exdataaddr(eh, off, u_short *)); resid = ntohs(*(exdataaddr(eh, off+2, u_short *))); ! if (off + resid > len) { ! restormap(map); return; /* sanity */ + } len = off + resid; } else off = 0; ! if (len == 0) { ! restormap(map); return; + } /* * Pull packet off interface. Off is nonzero if packet *************** *** 595,602 **** * the type and length which are at the front of any trailer data. */ m = if_rubaget(&xs->xs_ifuba, len, off, &xs->xs_if); ! if (m == 0) return; if (off) { struct ifnet *ifp; --- 617,626 ---- * the type and length which are at the front of any trailer data. */ m = if_rubaget(&xs->xs_ifuba, len, off, &xs->xs_if); ! if (m == 0) { ! restormap(map); return; + } if (off) { struct ifnet *ifp; *************** *** 615,620 **** --- 639,645 ---- case ETHERTYPE_ARP: arpinput(&xs->xs_ac, m); + restormap(map); return; #endif #ifdef NS *************** *** 626,640 **** #endif default: m_freem(m); return; } if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); ! return; ! } ! IF_ENQUEUE(inq, m); } /* --- 651,668 ---- #endif default: m_freem(m); + restormap(map); return; } + s = splimp(); if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); ! } else ! IF_ENQUEUE(inq, m); ! splx(s); ! restormap(map); } /* *************** *** 677,683 **** --- 705,713 ---- register struct ether_header *eh; register int off; int usetrailers; + segm save5; + saveseg5(save5); if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { error = ENETDOWN; goto bad; *************** *** 687,694 **** #ifdef INET case AF_INET: idst = ((struct sockaddr_in *)dst)->sin_addr; ! if (!arpresolve(&xs->xs_ac, m, &idst, edst, &usetrailers)) return (0); /* if not yet resolved */ off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; if (usetrailers && off > 0 && (off & 0x1ff) == 0 && m->m_off >= MMINOFF + 2 * sizeof (u_short)) { --- 717,726 ---- #ifdef INET case AF_INET: idst = ((struct sockaddr_in *)dst)->sin_addr; ! if (!arpresolve(&xs->xs_ac, m, &idst, edst, &usetrailers)) { ! restorseg5(save5); return (0); /* if not yet resolved */ + } off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; if (usetrailers && off > 0 && (off & 0x1ff) == 0 && m->m_off >= MMINOFF + 2 * sizeof (u_short)) { *************** *** 786,795 **** --- 818,829 ---- } #endif splx(s); + restorseg5(save5); return (0); bad: m_freem(m0); + restorseg5(save5); return (error); } *************** *** 897,903 **** if (physaddr) { xs->xs_flags |= EX_SETADDR; ! bcopy((caddr_t)physaddr, (caddr_t)xs->xs_addr, 6); } if (! (xs->xs_flags & EX_RUNNING)) return; --- 931,937 ---- if (physaddr) { xs->xs_flags |= EX_SETADDR; ! bcopy(physaddr, xs->xs_addr, 6); } if (! (xs->xs_flags & EX_RUNNING)) return; *************** *** 905,911 **** bp->mb_rqst = LLNET_ADDRS; bp->mb_na.na_mask = READ_OBJ|WRITE_OBJ; bp->mb_na.na_slot = PHYSSLOT; ! bcopy((caddr_t)xs->xs_addr, (caddr_t)bp->mb_na.na_addrs, 6); bp->mb_status |= MH_EXOS; addr->xd_portb = EX_NTRUPT; bp = xs->xs_x2hnext; --- 939,945 ---- bp->mb_rqst = LLNET_ADDRS; bp->mb_na.na_mask = READ_OBJ|WRITE_OBJ; bp->mb_na.na_slot = PHYSSLOT; ! bcopy(xs->xs_addr, bp->mb_na.na_addrs, 6); bp->mb_status |= MH_EXOS; addr->xd_portb = EX_NTRUPT; bp = xs->xs_x2hnext; *************** *** 928,931 **** while ((bp->mb_status & MH_OWNER) == MH_EXOS) /* poll for reply */ ; } ! #endif --- 962,965 ---- while ((bp->mb_status & MH_OWNER) == MH_EXOS) /* poll for reply */ ; } ! #endif NEX *** if_exreg.h Fri Oct 14 17:06:19 1988 --- /sys/vaxif/if_exreg.h Tue Sep 27 17:16:55 1988 *************** *** 6,11 **** --- 6,18 ---- * @(#)if_exreg.h 7.1 (Berkeley) 6/5/86 */ + /* + * Modification from Berkeley 4.3BSD + * + * Kenichi Katsumi + * SONY/TEKTRONIX Corp. + * 88/09/20 + */ struct exdevice { char xd_porta; /* write on porta resets EXOS */ *************** *** 193,200 **** --- 200,212 ---- struct net_addrs mb_net_addrs; struct net_recv mb_net_recv; struct net_ststcs mb_net_ststcs; + #ifndef pdp11 struct enet_xmit mb_enet_xmit; struct enet_recv mb_enet_recv; + #else + struct enet_xmit mbenet_xmit; + struct enet_recv mbenet_recv; + #endif } mb_all; /* following field is used only by host, not read by board */ struct ex_msg *mb_next; /* host's pointer to next message */ *************** *** 203,210 **** --- 215,227 ---- #define mb_na mb_all.mb_net_addrs #define mb_nr mb_all.mb_net_recv #define mb_ns mb_all.mb_net_ststcs + #ifndef pdp11 #define mb_et mb_all.mb_enet_xmit #define mb_er mb_all.mb_enet_recv + #else + #define mb_et mb_all.mbenet_xmit + #define mb_er mb_all.mbenet_recv + #endif #define mb_rqst mb_nm.nm_rqst #define mb_rply mb_nm.nm_rply #define MBDATALEN (sizeof(union mb_all)+6) *** scb.s Fri Oct 14 17:12:59 1988 --- /sys/machine/scb.s Tue Sep 13 00:09:16 1988 *************** *** 11,16 **** --- 11,17 ---- #include "../machine/mch_iopage.h" #include "../machine/koverlay.h" /* for OVLY_TABLE_BASE */ + #include "ex.h" #include "de.h" #include "dh.h" #include "dhu.h" *************** *** 192,197 **** --- 193,202 ---- #endif + #if NEX > 0 /* EXOS 204 */ + DEVTRAP(770, excdint, br5+0.) + #endif + /* * End of floating vectors. Endvec should be past vector space if NONSEP, * should be at least 450. *************** *** 388,391 **** --- 393,400 ---- #if NDZ > 0 /* DZ */ HANDLER(dzrint) + #endif + + #if NEX > 0 + HANDLER(excdint) /* EXOS204 */ #endif *** dtab Fri Oct 14 17:15:24 1988 --- /etc/dtab Wed Sep 28 16:18:28 1988 *************** *** 36,38 **** --- 36,39 ---- # kw ? 172540 100 6 hardclock # kw11-p clock # sr ? 500 5 srirint srixint # sri dr11-c arpanet imp # vv ? 161000 350 5 vvrint vvxint # pronet + # ex ? 164100 770 5 excdint # excelan exos204 uf[unit].tk_bdh.bd_flags = 0100000; /* say TK datagram */ /* hi byte of XMEM is drive type for ELP ! */ tk_ebuf[unit].tk_bdh.bdsys/OTHERS/bad144/ 755 0 12 0 5710615265 6553 sys/OTHERS/bad144/bad144.c 640 0 12 34446 5710333627 10011 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if defined(DOSCCS) && !defined(lint) char copyright[] = "@(#) Copyright (c) 1980 Regents of the University of California.\n\ All rights reserved.\n"; static char sccsid[] = "@(#)bad144.c 5.4.2 (2.11BSD GTE) 1/21/95"; #endif not lint /* * bad144 * * This program prints and/or initializes a bad block record for a pack, * in the format used by the DEC standard 144. * It can also add bad sector(s) to the record, moving the sector * replacements as necessary. * * It is preferable to write the bad information with a standard formatter, * but this program will do. * * RP06 sectors are marked as bad by inverting the format bit in the * header; on other drives the valid-sector bit is cleared. */ #include #include #include #include #include #include #include #define RETRIES 10 /* number of retries on reading old sectors */ int fflag, add, copy, verbose, nflag; int maxbad = MAXBAD; int compare(); union dkbbuf { struct dkbad bad; char buf[512]; } dkbbuf; #define dkbad dkbbuf.bad union dkbbuf oldbuf; #define oldbad oldbuf.bad daddr_t size, getold(), badsn(); struct disktab *dp; char name[BUFSIZ]; char *malloc(); off_t lseek(); long atol(); main(argc, argv) int argc; char *argv[]; { register struct bt_bad *bt; daddr_t sn, bn[126]; long bad; int i, f, nbad, new, errs; int toomany = 0; argc--, argv++; while (argc > 0 && **argv == '-') { (*argv)++; while (**argv) { switch (**argv) { case 'f': fflag++; break; case 'a': add++; break; case 'c': copy++; break; case 'v': verbose++; break; case 'n': nflag++; verbose++; break; } (*argv)++; } argc--, argv++; } if (argc < 2) { fprintf(stderr, "usage: bad144 [ -f ] type disk [ snum [ bn ... ] ]\n"); fprintf(stderr, "to read or overwrite bad-sector table, e.g.: bad144 rk07 hk0\n"); fprintf(stderr, "or bad144 -a [ -f ] [ -c ] type disk bn ...\n"); fprintf(stderr, "where options are:\n"); fprintf(stderr, "\t-a add new bad sectors to the table\n"); fprintf(stderr, "\t-f reformat listed sectors as bad\n"); fprintf(stderr, "\t-c copy original sector to replacement\n"); exit(1); } dp = getdiskbyname(argv[0]); if (dp == NULL) { fprintf(stderr, "%s: unknown disk type\n", argv[0]); exit(1); } size = (daddr_t)dp->d_nsectors * dp->d_ntracks * dp->d_ncylinders; #ifdef HACK printf("name \"%s\" type \"%s\" size %ld\n", dp->d_name, dp->d_type, size); printf("secsize %d ntracks %d nsectors %d ncylinders %d\n", dp->d_secsize, dp->d_ntracks, dp->d_nsectors, dp->d_ncylinders); printf("rpm %d badsectforw %d sectoffset %d\n", dp->d_rpm, dp->d_badsectforw, dp->d_sectoffset); for(i=0; i<8; i++) { printf(" %s%c size %ld bsize %d fsize %d\n", argv[1], "abcdefgh"[i], dp->d_partitions[i].p_size, dp->d_partitions[i].p_bsize, dp->d_partitions[i].p_fsize); } exit(0); #endif if (argv[1][0] != '/') #ifdef pdp11 (void)sprintf(name, "/dev/r%sh", argv[1]); #else (void)sprintf(name, "/dev/r%sc", argv[1]); #endif else (void)strcpy(name, argv[1]); argc -= 2; argv += 2; if (argc == 0) { f = open(name, O_RDONLY); if (f < 0) Perror(name); sn = getold(f, &dkbad); printf("bad block information at sector %ld in %s:\n", sn, name); printf("cartridge serial number: %ld(10)\n", dkbad.bt_csn); switch (dkbad.bt_flag) { case -1: printf("alignment cartridge\n"); break; case 0: break; default: printf("bt_flag=%x(16)?\n", dkbad.bt_flag); break; } bt = dkbad.bt_bad; for (i = 0; i < 126; i++) { bad = ((daddr_t)bt->bt_cyl<<16) + bt->bt_trksec; if (bad < 0) break; if (!toomany && i >= MAXBAD) { toomany++; printf("More bad sectors than system supports.\n"); printf("The remainder are not being replaced automatically...\n"); } printf("sn=%ld, cn=%d, tn=%d, sn=%d\n", badsn(bt), bt->bt_cyl, bt->bt_trksec>>8, bt->bt_trksec&0xff); bt++; } (void) checkold(); exit(0); } f = open(name, (fflag || add)? O_RDWR: O_WRONLY); if (f < 0) Perror(name); if (add) { /* * Read in the old badsector table. * Verify that it makes sense, and the bad sectors * are in order. Copy the old table to the new one. */ (void) getold(f, &oldbad); i = checkold(); if (verbose) printf("Had %d bad sectors\n", i); if (i + argc > maxbad) { printf("bad144: system not configured for %d more sectors\n", argc); printf("limited to %d by current configuration\n", maxbad); } else if (i + argc > 126) { printf("bad144: not enough room for %d more sectors\n", argc); printf("limited to 126 by information format\n"); exit(1); } dkbbuf = oldbuf; } else { dkbad.bt_csn = atol(*argv++); argc--; dkbad.bt_mbz = 0; if (argc > maxbad) { printf("bad144: system not configured for %d more sectors\n", argc); printf("limited to %d by current configuration\n", maxbad); } else if (argc > 126) { printf("bad144: too many bad sectors specified\n"); printf("limited to 126 by information format\n"); exit(1); } i = 0; } errs = 0; new = argc; while (argc > 0) { daddr_t sn = atol(*argv++); argc--; if (sn < 0 || sn >= size) { printf("%ld: out of range [0,%ld) for %s\n", sn, size, dp->d_name); errs++; continue; } bn[i] = sn; dkbad.bt_bad[i].bt_cyl = sn / (dp->d_nsectors*dp->d_ntracks); sn %= (dp->d_nsectors*dp->d_ntracks); dkbad.bt_bad[i].bt_trksec = ((sn/dp->d_nsectors) << 8) + (sn%dp->d_nsectors); i++; } if (errs) exit(1); nbad = i; while (i < 126) { dkbad.bt_bad[i].bt_trksec = -1; dkbad.bt_bad[i].bt_cyl = -1; i++; } if (add) { /* * Sort the new bad sectors into the list. * Then shuffle the replacement sectors so that * the previous bad sectors get the same replacement data. */ qsort((char *)dkbad.bt_bad, nbad, sizeof (struct bt_bad), compare); shift(f, nbad, nbad-new); } for (i = 0; i < 10 && i < dp->d_nsectors; i += 2) { if (lseek(f, (off_t)dp->d_secsize * (size - dp->d_nsectors + i), L_SET) < 0) Perror("lseek"); if (verbose) printf("write badsect file at %ld\n", size - dp->d_nsectors + i); if (nflag == 0 && write(f, (caddr_t)&dkbad, 512) != 512) { char msg[80]; (void)sprintf(msg, "bad144: write bad sector file %d", i/2); perror(msg); } } if (fflag) for (i = nbad - new; i < nbad; i++) format(f, bn[i]); exit(0); } daddr_t getold(f, bad) union dkbbuf *bad; { register int i; daddr_t sn; char msg[80]; for (i = 0; i < 10 && i < dp->d_nsectors; i += 2) { sn = size - dp->d_nsectors + i; if (lseek(f, (off_t)sn * dp->d_secsize, L_SET) < 0) Perror("lseek"); if (read(f, (char *)bad, 512) == 512) { if (i > 0) printf("Using bad-sector file %d\n", i/2); return(sn); } (void)sprintf(msg, "bad144: read bad sector file at sn %ld", sn); perror(msg); } fprintf(stderr, "bad144: %s: can't read bad block info\n", name); exit(1); /*NOTREACHED*/ } checkold() { register int i; register struct bt_bad *bt; daddr_t sn, lsn; int errors = 0, warned = 0; if (oldbad.bt_flag != 0) { fprintf(stderr, "bad144: %s: bad flag in bad-sector table\n", name); errors++; } if (oldbad.bt_mbz != 0) { fprintf(stderr, "bad144: %s: bad magic number\n", name); errors++; } lsn = 0L; bt = oldbad.bt_bad; for (i = 0; i < 126; i++, bt++) { if (bt->bt_cyl == -1 && bt->bt_trksec == -1) break; if ((bt->bt_cyl >= dp->d_ncylinders) || ((bt->bt_trksec >> 8) >= dp->d_ntracks) || ((bt->bt_trksec & 0xff) >= dp->d_nsectors)) { fprintf(stderr, "bad144: cyl/trk/sect out of range in existing entry: "); fprintf(stderr, "sn=%ld, cn=%d, tn=%d, sn=%d\n", badsn(bt), bt->bt_cyl, bt->bt_trksec>>8, bt->bt_trksec & 0xff); errors++; } sn = (bt->bt_cyl * dp->d_ntracks + (bt->bt_trksec >> 8)) * dp->d_nsectors + (bt->bt_trksec & 0xff); if (sn < lsn && !warned) { fprintf(stderr, "bad144: bad sector file out of order\n"); errors++; warned++; } lsn = sn; } if (errors) exit(1); return (i); } /* * Move the bad sector replacements * to make room for the new bad sectors. * new is the new number of bad sectors, old is the previous count. */ shift(f, new, old) { daddr_t repl; /* * First replacement is last sector of second-to-last track. */ repl = size - dp->d_nsectors - 1; new--; old--; while (new >= 0 && new != old) { if (old < 0 || compare(&dkbad.bt_bad[new], &oldbad.bt_bad[old]) > 0) { /* * Insert new replacement here-- copy original * sector if requested and possible, * otherwise write a zero block. */ if (!copy || !blkcopy(f, badsn(&dkbad.bt_bad[new]), repl - new)) blkzero(f, repl - new); } else { if (blkcopy(f, repl - old, repl - new) == 0) fprintf(stderr, "Can't copy replacement sector %d to %d\n", repl-old, repl-new); old--; } new--; } } char *buf; /* * Copy disk sector s1 to s2. */ blkcopy(f, s1, s2) daddr_t s1, s2; { register tries, n; if (buf == (char *)NULL) { buf = malloc((unsigned)dp->d_secsize); if (buf == (char *)NULL) { fprintf(stderr, "Out of memory\n"); exit(20); } } if (lseek(f, (off_t)dp->d_secsize * s1, L_SET) < 0) Perror("lseek"); for (tries = 0; tries < RETRIES; tries++) if ((n = read(f, buf, dp->d_secsize)) == dp->d_secsize) break; if (n != dp->d_secsize) { fprintf(stderr, "bad144: can't read sector, %ld: ", s1); if (n < 0) perror((char *)0); return(0); } if (lseek(f, (off_t)dp->d_secsize * s2, L_SET) < 0) Perror("lseek"); if (verbose) printf("copying %ld to %ld\n", s1, s2); if (nflag == 0 && write(f, buf, dp->d_secsize) != dp->d_secsize) { fprintf(stderr, "bad144: can't write replacement sector, %ld: ", s2); perror((char *)0); return(0); } return(1); } char *zbuf; blkzero(f, sn) daddr_t sn; { if (zbuf == (char *)NULL) { zbuf = malloc((unsigned)dp->d_secsize); if (zbuf == (char *)NULL) { fprintf(stderr, "Out of memory\n"); exit(20); } } if (lseek(f, (off_t)dp->d_secsize * sn, L_SET) < 0) Perror("lseek"); if (verbose) printf("zeroing %ld\n", sn); if (nflag == 0 && write(f, zbuf, dp->d_secsize) != dp->d_secsize) { fprintf(stderr, "bad144: can't write replacement sector, %ld: ", sn); perror((char *)0); } } compare(b1, b2) register struct bt_bad *b1, *b2; { if (b1->bt_cyl > b2->bt_cyl) return(1); if (b1->bt_cyl < b2->bt_cyl) return(-1); return (b1->bt_trksec - b2->bt_trksec); } daddr_t badsn(bt) register struct bt_bad *bt; { return (((daddr_t)bt->bt_cyl*dp->d_ntracks + (bt->bt_trksec>>8)) * dp->d_nsectors + (bt->bt_trksec&0xff)); } struct rp06hdr { short h_cyl; short h_trksec; short h_key1; short h_key2; char h_data[512]; #define RP06_FMT 010000 /* 1 == 16 bit, 0 == 18 bit */ }; /* * Most massbus and unibus drives * have headers of this form */ struct hpuphdr { u_short hpup_cyl; u_char hpup_sect; u_char hpup_track; char hpup_data[512]; #define HPUP_OKSECT 0xc000 /* this normally means sector is good */ #define HPUP_16BIT 0x1000 /* 1 == 16 bit format */ }; int rp06format(), hpupformat(); struct formats { char *f_name; /* disk name */ int f_bufsize; /* size of sector + header */ int f_bic; /* value to bic in hpup_cyl */ int (*f_routine)(); /* routine for special handling */ } formats[] = { { "rp06", sizeof (struct rp06hdr), RP06_FMT, rp06format }, { "eagle", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat }, { "capricorn", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat }, { "rm03", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat }, { "rm05", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat }, { "9300", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat }, { "9766", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat }, { 0, 0, 0, 0 } }; /*ARGSUSED*/ hpupformat(fp, dp, blk, buf, count) struct formats *fp; struct disktab *dp; daddr_t blk; char *buf; int count; { struct hpuphdr *hdr = (struct hpuphdr *)buf; int sect; if (count < sizeof(struct hpuphdr)) { hdr->hpup_cyl = (HPUP_OKSECT | HPUP_16BIT) | (blk / (dp->d_nsectors * dp->d_ntracks)); sect = blk % (dp->d_nsectors * dp->d_ntracks); hdr->hpup_track = (u_char)(sect / dp->d_nsectors); hdr->hpup_sect = (u_char)(sect % dp->d_nsectors); } return (0); } /*ARGSUSED*/ rp06format(fp, dp, blk, buf, count) struct formats *fp; struct disktab *dp; daddr_t blk; char *buf; int count; { if (count < sizeof(struct rp06hdr)) { fprintf(stderr, "Can't read header on blk %ld, can't reformat\n", blk); return (-1); } return (0); } format(fd, blk) int fd; daddr_t blk; { register struct formats *fp; static char *buf; static char bufsize; int n; for (fp = formats; fp->f_name; fp++) if (strcmp(dp->d_name, fp->f_name) == 0) break; if (fp->f_name == 0) { fprintf(stderr, "bad144: don't know how to format %s disks\n", dp->d_name); exit(2); } if (buf && bufsize < fp->f_bufsize) { free(buf); buf = NULL; } if (buf == NULL) buf = malloc((unsigned)fp->f_bufsize); if (buf == NULL) { fprintf(stderr, "bad144: can't allocate sector buffer\n"); exit(3); } bufsize = fp->f_bufsize; /* * Here we do the actual formatting. All we really * do is rewrite the sector header and flag the bad sector * according to the format table description. If a special * purpose format routine is specified, we allow it to * process the sector as well. */ if (lseek(fd, (off_t)blk * dp->d_secsize, L_SET) < 0) Perror("lseek"); if (verbose) printf("format blk %ld\n", blk); if (ioctl(fd, DKIOCHDR, (char *)0) < 0) Perror("ioctl DKIOCHDR 1"); if ((n = read(fd, buf, fp->f_bufsize)) < 0) bzero(buf, fp->f_bufsize); if (fp->f_bic) { struct hpuphdr *xp = (struct hpuphdr *)buf; xp->hpup_cyl &= ~fp->f_bic; } if (fp->f_routine) if ((*fp->f_routine)(fp, dp, blk, buf, n) != 0) return; if (lseek(fd, (off_t)blk * dp->d_secsize, L_SET) < 0) Perror("lseek"); if (nflag) return; if (ioctl(fd, DKIOCHDR, (char *)0) < 0) Perror("ioctl DKIOCHDR 2"); if (write(fd, buf, fp->f_bufsize) != fp->f_bufsize) { char msg[80]; (void)sprintf(msg, "bad144: write format %d", blk); perror(msg); } } Perror(op) char *op; { fprintf(stderr, "bad144: "); perror(op); exit(4); } { daddr_t sn = atol(*argv++); argc--; if (sn < 0 || sn >= size) { printf("%ld: out of range [0,%ld) for %s\n", sn, size, dp->d_name); errs++; continue; } bn[i] = sn; dkbad.bt_bad[i].bt_cyl =sys/OTHERS/bad144/dkio.h 640 0 12 750 4357251672 7721 struct drv_info { short type; /* RMDT register */ short model; /* model byte */ short trk; /* tracks/cyl */ short sec; /* sec/trk */ short nspc; /* sec/cyl */ short ncyl; /* no. of cyls */ char name[48]; struct sizes { daddr_t nblocks; int cyloff; } fs[8]; }; /* disk i/o controls */ #define DKIOCHDR _IO(d, 1) /* next i/o includes header */ #define DKREINIT _IO(d, 6) /* reread bad block forwarding table */ #define DKINFO _IOR(d, 7, struct drv_info) /* get drive info */ sys/OTHERS/bad144/xp.c 640 0 12 66547 5321514206 7460 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)xp.c 1.2 (2.11BSD GTE) 1/2/93 */ /* $Header: xp.c,v 1.3 88/06/18 08:10:08 jbj Locked $ */ /* $Log: xp.c,v $ * Revision 1.3 88/06/18 08:10:08 jbj * Patch to fix bad sector forwarding (John Nelson, jack@cadre.dsl.pittsburgh.edu) * * Revision 1.2 88/06/18 08:02:25 jbj * ioctl calls for SI bad sector forwarding. * * Revision 1.1 88/06/18 07:54:42 jbj * Initial revision * */ /* * RM02/03/05, RP04/05/06, Ampex 9300, CDC 9766, DIVA, Fuji 160, and SI * Eagle. This driver will handle most variants of SMD drives on one or more * controllers. If XP_PROBE is defined, it includes a probe routine that * will determine the number and type of drives attached to each controller; * otherwise, the data structures must be initialized. * * For simplicity we use hpreg.h instead of an xpreg.h. * The bits are the same. */ #include "xp.h" #if NXPD > 0 #include "param.h" #include "../machine/seg.h" #include "systm.h" #include "buf.h" #include "conf.h" #include "user.h" #include "ioctl.h" #include "dkio.h" #include "hpreg.h" #include "dkbad.h" #include "dk.h" #include "map.h" #include "uba.h" #define XP_SDIST 2 #define XP_RDIST 6 #define xpunit(dev) ((minor(dev) >> 3) & 07) int xp_offset[] = { HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, 0, 0, 0, 0, }; /* * xp_drive and xp_controller may be initialized here, or filled in at boot * time if XP_PROBE is enabled. xp_controller address fields must be * initialized for any boot devices, however. * * xp_controller structure: one line per controller. Only the address need * be initialized in the controller structure if XP_PROBE is defined (at least * the address for the root device); otherwise the flags must be here also. * The XP_NOCC flag is set for RM02/03/05's (with no current cylinder * register); XP_NOSEARCH is set for Diva's without the search command. The * XP_RH70 flag need not be set here, the driver will always check that. */ #define XPADDR ((struct hpdevice *)0176700) struct xp_controller xp_controller[NXPC] = { /* 0 0 addr flags 0 */ #ifdef XP_PROBE 0, 0, XPADDR, 0, 0 #else 0, 0, XPADDR, XP_NOCC|XP_NOSEARCH, 0 #endif }; /* * xp_drive structure: one entry per drive. The drive structure must be * initialized if XP_PROBE is not enabled. Macros are provided in hpreg.h * to initialize entries according to drive type, and controller and drive * numbers. See those for examples on how to set up other types of drives. * With XP_PROBE defined, xpslave will fill in this structure, and any * initialization will be overridden. There is one exception; if the * drive-type field is set, it will be used instead of the drive-type register * to determine the drive's type. */ struct xp_drive xp_drive[NXPD] #ifndef XP_PROBE = { RM02_INIT(0,0), /* RM02, controller 0, drive 0 */ RM02_INIT(0,1), /* RM02, controller 0, drive 1 */ RM2X_INIT(0,0) /* Fuji 160, controller 0, drive 0 */ RM2X_INIT(0,1) /* Fuji 160, controller 0, drive 1 */ RM05X_INIT(0,2) /* 815-cyl RM05, controller 0, drive 2 */ } #endif ; /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ struct size { daddr_t nblocks; int cyloff; } rm_sizes[8] = { /* RM02/03 */ #ifdef FOXNPUP 32000, 0, /* a: cyl 0 - 199 */ 32000, 200, /* b: cyl 200 - 399 */ 32000, 423, /* c: cyl 423 - 622 */ 31840, 623, /* d: cyl 623 - 821 */ 3520, 400, /* e: cyl 400 - 422 */ 63840, 423, /* f: cyl 423 - 821, overlaps c & d */ 99360, 200, /* g: cyl 200 - 821, overlaps b thru end */ /* CAUTION: Partition g should not be */ /* used on the root device if swap is */ /* defined on partition e. */ 131680, 0, /* h: cyl 0 - 822 */ #else 4800, 0, /* a: cyl 0 - 29 */ 4800, 30, /* b: cyl 30 - 59 */ 122080, 60, /* c: cyl 60 - 822 */ 62720, 60, /* d: cyl 60 - 451 */ 59360, 452, /* e: cyl 452 - 822 */ 9600, 0, /* f: cyl 0 - 59, overlaps a & b */ 0, 0, /* g: Not Defined */ 131680, 0, /* h: cyl 0 - 822 */ #endif }, rm5_sizes[8] = { /* RM05, CDC 9766 */ 9120, 0, /* a: cyl 0 - 14 */ 9120, 15, /* b: cyl 15 - 29 */ 234080, 30, /* c: cyl 30 - 414 */ 248064, 415, /* d: cyl 415 - 822 */ 164160, 30, /* e: cyl 30 - 299 */ 152000, 300, /* f: cyl 300 - 549 */ 165984, 550, /* g: cyl 550 - 822 */ 500384, 0, /* h: cyl 0 - 822 */ }, si5_sizes[8] = { /* SI9775, direct mapping */ 10240, 0, /* a: cyl 0 - 7 */ 10240, 8, /* b: cyl 8 - 15 */ 510720, 16, /* c: cyl 16 - 414 */ 547840, 415, /* d: cyl 415 - 842 */ 363520, 16, /* e: cyl 16 - 299 */ 320000, 300, /* f: cyl 300 - 549 */ 375040, 550, /* g: cyl 550 - 842 */ 1079040, 0, /* h: cyl 0 - 842 */ }, hp_sizes[8] = { /* RP04/05/06 */ 9614, 0, /* a: cyl 0 - 22 */ 8778, 23, /* b: cyl 23 - 43 */ 153406, 44, /* c: cyl 44 - 410, RP04/05 */ 168872, 411, /* d: cyl 411 - 814, RP06 */ 322278, 44, /* e: cyl 44 - 814, RP06 */ 0, 0, /* f: Not Defined */ 171798, 0, /* g: cyl 0 - 410, whole RP04/05 */ 340670, 0 /* h: cyl 0 - 814, whole RP06 */ }, dv_sizes[8] = { /* Diva Comp V, Ampex 9300 in direct mode */ 9405, 0, /* a: cyl 0 - 14 */ 9405, 15, /* b: cyl 15 - 29 */ 241395, 30, /* c: cyl 30 - 414 */ 250800, 415, /* d: cyl 415 - 814 */ 169290, 30, /* e: cyl 30 - 299 */ 156750, 300, /* f: cyl 300 - 549 */ 166155, 550, /* g: cyl 550 - 814 */ 511005, 0 /* h: cyl 0 - 814 */ }, rm2x_sizes[8] = { /* Fuji 160 */ 9600, 0, /* a: cyl 0 - 29 */ 9600, 30, /* b: cyl 30 - 59 */ 244160, 60, /* c: cyl 60 - 822 */ 125440, 60, /* d: cyl 60 - 451 */ 118720, 452, /* e: cyl 452 - 822 */ 59520, 452, /* f: cyl 452 - 637 */ 59200, 638, /* g: cyl 638 - 822 */ 263360, 0 /* h: cyl 0 - 822 */ }, cap_sizes[8] = { /* SI Capricorn */ 16384, 0, /* a: cyl 0 thru 31 */ 33792, 32, /* b: cyl 32 thru 97 */ 291840, 98, /* c: cyl 98 thru 667 */ 16384, 668, /* d: cyl 668 thru 699 */ 56320, 700, /* e: cyl 700 thru 809 */ 109568, 810, /* f: cyl 810 thru 1023 */ 182272, 668, /* g: cyl 668 thru 1023 */ 524288, 0, /* h: cyl 0 thru 1023 */ }, si_sizes[8] = { /* SI Eagle */ 11520, 0, /* a: cyl 0 - 11 */ 11520, 12, /* b: cyl 12 - 23 */ 474240, 24, /* c: cyl 24 - 517 */ 92160, 518, /* d: cyl 518 - 613 */ 218880, 614, /* e: cyl 614 - 841 */ 0, 0, /* f: Not Defined */ 0, 0, /* g: Not Defined */ 808320, 0 /* h: cyl 0 - 841 (everything) */ }; /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ #ifdef XP_PROBE struct xpst { short type; /* value from controller type register */ short nsect; /* number of sectors/track */ short ntrack; /* number of tracks/cylinder */ short ncyl; /* number of cylinders */ struct size *sizes; /* partition tables */ short flags; /* controller flags */ } xpst[] = { { RM02, RM_SECT, RM_TRAC, RM_CYL, rm_sizes, XP_NOCC }, { RM2X, RM2X_SECT, RM2X_TRAC, RM2X_CYL, rm2x_sizes, XP_NOCC }, { RM03, RM_SECT, RM_TRAC, RM_CYL, rm_sizes, XP_NOCC }, { RM05, RM5_SECT, RM5_TRAC, RM5_CYL, rm5_sizes, XP_NOCC }, { RM5X, RM5X_SECT, RM5X_TRAC, RM5X_CYL, rm5_sizes, XP_NOCC }, { SI5, SI5_SECT, SI5_TRAC, SI5_CYL, si5_sizes, XP_NOCC }, { RP04, HP_SECT, HP_TRAC, RP04_CYL, hp_sizes, 0 }, { RP05, HP_SECT, HP_TRAC, RP04_CYL, hp_sizes, 0 }, { RP06, HP_SECT, HP_TRAC, RP06_CYL, hp_sizes, 0 }, { DV, DV_SECT, DV_TRAC, DV_CYL, dv_sizes, XP_NOSEARCH }, { CAP, CAP_SECT, CAP_TRAC, CAP_CYL, cap_sizes, XP_NOCC }, { SI, SI_SECT, SI_TRAC, SI_CYL, si_sizes, XP_NOCC }, { 0, 0, 0, 0, 0 } }; #endif struct buf xptab; struct buf xputab[NXPD]; #ifdef BADSECT int maxbad = MAXBAD; /* KLUDGE: no. of bad blocks in table */ struct dkbad xpbad[NXPD]; /* replacement block number */ struct buf bxpbuf[NXPD]; bool_t xp_init[NXPD]; /* drive initialized */ bool_t xp_rwhdr[8*NXPD]; /* next i/o includes header */ #endif #ifdef UCB_METER static int xp_dkn = -1; /* number for iostat */ #endif /* * Attach controllers whose addresses are known at boot time. Stop at the * first not found, so that the drive numbering won't get confused. */ xproot() { register int i; register struct hpdevice *xpaddr; for (i = 0; i < NXPC; i++) if (((xpaddr = xp_controller[i].xp_addr) == 0) || (xpattach(xpaddr, i) == 0)) break; } /* * Attach controller at xpaddr. Mark as nonexistent if xpaddr is 0; otherwise * attach slaves if probing. NOTE: if probing for drives, this routine must * be called once per controller, in ascending controller numbers. */ xpattach(xpaddr, unit) register struct hpdevice *xpaddr; int unit; { register struct xp_controller *xc = &xp_controller[unit]; #ifdef XP_PROBE static int last_attached = -1; #endif #ifdef UCB_METER if (xp_dkn < 0) { dk_alloc(&xp_dkn, NXPD+NXPC, "xp", 0L); #ifndef XP_PROBE /* * Hard coded drive configuration - snag the number of * sectors per track for each drive and compute drive * transfer rate assuming 3600rpm (the Fujitsu Eagle 2351A * (SI Eagle) is actually 3961rpm; it's just not worth the * effort to fix the assumption.) If XP_PROBE is defined we * grab the number of sectors/track for each drive in * xpslave. */ if (xp_dkn >= 0) { register int i; register long *lp; for (i = 0, lp = &dk_wps[xp_dkn]; i < NXPD; i++) *lp++ = (long)xp_drive[i].xp_nsect * (60L * 256L); } #endif } #endif if ((unsigned)unit >= NXPC) return(0); if ((xpaddr != 0) && (fioword(xpaddr) != -1)) { xc->xp_addr = xpaddr; if (fioword(&xpaddr->hpbae) != -1) xc->xp_flags |= XP_RH70; #ifdef XP_PROBE /* * If already attached, ignore (don't want to renumber drives) */ if (unit > last_attached) { last_attached = unit; xpslave(xpaddr, xc); } #endif return(1); } xc->xp_addr = 0; return(0); } #ifdef XP_PROBE /* * Determine what drives are attached to a controller; guess their types and * fill in the drive structures. */ xpslave(xpaddr, xc) register struct hpdevice *xpaddr; struct xp_controller *xc; { register struct xp_drive *xd; register struct xpst *st; int j, dummy; static int nxp = 0; for (j = 0; j < 8; j++) { { int x = 6000; while (--x); /* delay */ } xpaddr->hpcs1.w = 0; xpaddr->hpcs2.w = j; xpaddr->hpcs1.w = HP_GO; /* testing... */ { int x = 6000; while (--x); /* delay */ } dummy = xpaddr->hpds; if (xpaddr->hpcs2.w & HPCS2_NED) { xpaddr->hpcs2.w = HPCS2_CLR; continue; } if (nxp < NXPD) { xd = &xp_drive[nxp++]; xd->xp_ctlr = xc; xd->xp_unit = j; /* If drive type is initialized, believe it. */ if (xd->xp_type == 0) { xd->xp_type = xpaddr->hpdt & 077; xd->xp_type = xpmaptype(xd, xpaddr->hpsn); } for (st = xpst; st->type; st++) if (st->type == xd->xp_type) { xd->xp_nsect = st->nsect; xd->xp_ntrack = st->ntrack; xd->xp_nspc = st->nsect * st->ntrack; #ifdef BADSECT xd->xp_ncyl = st->ncyl; #endif xd->xp_sizes = st->sizes; xd->xp_ctlr->xp_flags |= st->flags; break; } if (!st->type) { printf("xp%d: drive type %o unrecognized\n",nxp - 1, xd->xp_type); xd->xp_ctlr = NULL; } #ifdef UCB_METER if (xp_dkn >= 0 && xd->xp_ctlr) dk_wps[xd - &xp_drive[0]] = (long)xd->xp_nsect * (60L * 256L); #endif } } } static xpmaptype(xd, hpsn) register struct xp_drive *xd; register u_short hpsn; { register u_short type = xd->xp_type; /* * Model-byte processing for SI controllers. * NB: Only deals with RM02, RM03 and RM05 emulations. */ if ((type == RM02 || type == RM03 || type == RM05) && (hpsn & SIMB_LU) == xd->xp_unit) { switch (hpsn & (SIMB_MB & ~(SIMB_S6|SIMB_XX|SIRM03|SIRM05))) { case SI9775D: type = SI5; break; case SI9775M: type = RM05; break; case SI9730D: type = RM2X; break; case SI9766: type = RM05; break; case SI9762: type = RM03; break; case SICAPD: type = CAP; break; case SI9751D: type = SI; break; } } return(type); } #endif XP_PROBE xpopen(dev) dev_t dev; { register struct xp_drive *xd; register int unit = xpunit(dev); if (unit >= NXPD || !(xd = &xp_drive[unit])->xp_ctlr || !xd->xp_ctlr->xp_addr) return (ENXIO); return (0); } xpstrategy(bp) register struct buf *bp; { register struct xp_drive *xd; register unit; struct buf *dp; short pseudo_unit; int s; long bn; unit = dkunit(bp); pseudo_unit = minor(bp->b_dev) & 07; if ((unit >= NXPD) || ((xd = &xp_drive[unit])->xp_ctlr == 0) || (xd->xp_ctlr->xp_addr == 0)) { bp->b_error = ENXIO; goto errexit; } if ((bp->b_blkno < 0) || ((bn = dkblock(bp)) + ((bp->b_bcount + 511) >> 9) > xd->xp_sizes[pseudo_unit].nblocks)) { bp->b_error = EINVAL; errexit: bp->b_flags |= B_ERROR; iodone(bp); return; } if ((xd->xp_ctlr->xp_flags & XP_RH70) == 0) mapalloc(bp); bp->b_cylin = bn / xd->xp_nspc + xd->xp_sizes[pseudo_unit].cyloff; dp = &xputab[unit]; s = spl5(); disksort(dp, bp); if (dp->b_active == 0) { xpustart(unit); if (xd->xp_ctlr->xp_active == 0) xpstart(xd->xp_ctlr); } splx(s); } /* * Unit start routine. Seek the drive to where the data are and then generate * another interrupt to actually start the transfer. If there is only one * drive or we are very close to the data, don't bother with the search. If * called after searching once, don't bother to look where we are, just queue * for transfer (to avoid positioning forever without transferring). */ xpustart(unit) int unit; { register struct xp_drive *xd; register struct hpdevice *xpaddr; register struct buf *dp; struct buf *bp; daddr_t bn; int sn, cn, csn; xd = &xp_drive[unit]; xpaddr = xd->xp_ctlr->xp_addr; xpaddr->hpcs2.w = xd->xp_unit; xpaddr->hpcs1.c[0] = HP_IE; xpaddr->hpas = 1 << xd->xp_unit; if (unit >= NXPD) return; #ifdef UCB_METER if (xp_dkn >= 0) dk_busy &= ~(1 << (xp_dkn + unit)); #endif dp = &xputab[unit]; if ((bp=dp->b_actf) == NULL) return; /* * If we have already positioned this drive, * then just put it on the ready queue. */ if (dp->b_active) goto done; dp->b_active++; /* * If drive has just come up, set up the pack. */ #ifdef BADSECT if (((xpaddr->hpds & HPDS_VV) == 0) || (xp_init[unit] == 0)) { struct buf *bbp = &bxpbuf[unit]; #else if ((xpaddr->hpds & HPDS_VV) == 0) { #endif /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ #ifdef XP_DEBUG printf("preset-unit=%d\n", unit); #endif xpaddr->hpcs1.c[0] = HP_IE | HP_PRESET | HP_GO; #ifdef XP_DEBUG printf("preset done\n"); #endif xpaddr->hpof = HPOF_FMT22; #ifdef BADSECT xp_init[unit] = 1; bbp->b_flags = B_READ | B_BUSY | B_PHYS; bbp->b_dev = bp->b_dev | 7; /* "h" partition whole disk */ bbp->b_bcount = sizeof(struct dkbad); bbp->b_un.b_addr = (caddr_t)&xpbad[unit]; bbp->b_blkno = (daddr_t)xd->xp_ncyl * xd->xp_nspc - xd->xp_nsect; bbp->b_cylin = xd->xp_ncyl - 1; if ((xd->xp_ctlr->xp_flags & XP_RH70) == 0) mapalloc(bbp); dp->b_actf = bbp; bbp->av_forw = bp; bp = bbp; #endif BADSECT } #if NXPD > 1 /* * If drive is offline, forget about positioning. */ if ((xpaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL)) goto done; /* * Figure out where this transfer is going to * and see if we are close enough to justify not searching. */ bn = dkblock(bp); cn = bp->b_cylin; sn = bn % xd->xp_nspc; sn += xd->xp_nsect - XP_SDIST; sn %= xd->xp_nsect; if (((xd->xp_ctlr->xp_flags & XP_NOCC) && (xd->xp_cc != cn)) || xpaddr->hpcc != cn) goto search; if (xd->xp_ctlr->xp_flags & XP_NOSEARCH) goto done; csn = (xpaddr->hpla >> 6) - sn + XP_SDIST - 1; if (csn < 0) csn += xd->xp_nsect; if (csn > xd->xp_nsect - XP_RDIST) goto done; search: xpaddr->hpdc = cn; xpaddr->hpda = sn; xpaddr->hpcs1.c[0] = (xd->xp_ctlr->xp_flags & XP_NOSEARCH) ? (HP_IE | HP_SEEK | HP_GO) : (HP_IE | HP_SEARCH | HP_GO); xd->xp_cc = cn; #ifdef UCB_METER /* * Mark unit busy for iostat. */ if (xp_dkn >= 0) { int dkn = xp_dkn + unit; dk_busy |= 1< 1 done: /* * Device is ready to go. * Put it on the ready queue for the controller. */ dp->b_forw = NULL; if (xd->xp_ctlr->xp_actf == NULL) xd->xp_ctlr->xp_actf = dp; else xd->xp_ctlr->xp_actl->b_forw = dp; xd->xp_ctlr->xp_actl = dp; } /* * Start up a transfer on a controller. */ xpstart(xc) register struct xp_controller *xc; { register struct hpdevice *xpaddr; register struct buf *bp; struct xp_drive *xd; struct buf *dp; short pseudo_unit; daddr_t bn; int unit, sn, tn, cn, cmd; xpaddr = xc->xp_addr; loop: /* * Pull a request off the controller queue. */ if ((dp = xc->xp_actf) == NULL) return; if ((bp = dp->b_actf) == NULL) { xc->xp_actf = dp->b_forw; goto loop; } /* * Mark controller busy and determine destination of this request. */ xc->xp_active++; pseudo_unit = minor(bp->b_dev) & 07; unit = dkunit(bp); xd = &xp_drive[unit]; bn = dkblock(bp); cn = xd->xp_sizes[pseudo_unit].cyloff; cn += bn / xd->xp_nspc; sn = bn % xd->xp_nspc; tn = sn / xd->xp_nsect; sn = sn % xd->xp_nsect; /* * Select drive. */ xpaddr->hpcs2.w = xd->xp_unit; /* * Check that it is ready and online. */ if ((xpaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL)) { xc->xp_active = 0; dp->b_errcnt = 0; dp->b_actf = bp->av_forw; bp->b_flags |= B_ERROR; iodone(bp); goto loop; } if (dp->b_errcnt >= 16 && (bp->b_flags & B_READ)) { xpaddr->hpof = xp_offset[dp->b_errcnt & 017] | HPOF_FMT22; xpaddr->hpcs1.w = HP_OFFSET | HP_GO; while ((xpaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY); } xpaddr->hpdc = cn; xpaddr->hpda = (tn << 8) + sn; xpaddr->hpba = bp->b_un.b_addr; if (xc->xp_flags & XP_RH70) xpaddr->hpbae = bp->b_xmem; xpaddr->hpwc = -(bp->b_bcount >> 1); /* * Initiate i/o command. */ cmd = ((bp->b_xmem & 3) << 8) | HP_IE | HP_GO; #ifdef XP_FORMAT if (minor(bp->b_dev) & 0200 || xp_rwhdr[unit]) { cmd |= bp->b_flags & B_READ ? HP_RHDR : HP_WHDR; } else #endif cmd |= bp->b_flags & B_READ ? HP_RCOM : HP_WCOM; xpaddr->hpcs1.w = cmd; #ifdef UCB_METER if (xp_dkn >= 0) { int dkn = xp_dkn + NXPD + (xc - &xp_controller[0]); dk_busy |= 1<b_bcount>>6; } #endif } /* * Handle a disk interrupt. */ xpintr(dev) int dev; { register struct hpdevice *xpaddr; register struct buf *dp; struct xp_controller *xc; struct xp_drive *xd; struct buf *bp; register int unit; int as; xc = &xp_controller[dev]; xpaddr = xc->xp_addr; as = xpaddr->hpas & 0377; if (xc->xp_active) { #ifdef UCB_METER if (xp_dkn >= 0) dk_busy &= ~(1 << (xp_dkn + NXPD + dev)); #endif /* * Get device and block structures. Select the drive. */ dp = xc->xp_actf; bp = dp->b_actf; #ifdef BADSECT if (bp->b_flags & B_BAD) if (xpecc(bp, CONT)) return; #endif unit = dkunit(bp); xd = &xp_drive[unit]; xpaddr->hpcs2.c[0] = xd->xp_unit; /* * Check for and process errors. */ if (xpaddr->hpcs1.w & HP_TRE) { while ((xpaddr->hpds & HPDS_DRY) == 0); if (xpaddr->hper1 & HPER1_WLE) { /* * Give up on write locked deviced immediately. */ printf("xp%d: write locked\n", unit); bp->b_flags |= B_ERROR; #ifdef BADSECT } else if ((xpaddr->rmer2 & RMER2_BSE) || (xpaddr->hper1 & HPER1_FER)) { #ifdef XP_FORMAT /* * Allow this error on format devices. */ if (minor(bp->b_dev) & 0200) goto errdone; #endif if (xpecc(bp, BSE)) return; else goto hard; #endif BADSECT } else { /* * After 28 retries (16 without offset and * 12 with offset positioning), give up. */ if (++dp->b_errcnt > 28) { hard: harderr(bp, "xp"); #ifdef XP_DEBUG /* * for RM drives */ printf("cs2=%b er1=%b er2=%b %s\n", xpaddr->hpcs2.w, HPCS2_BITS, xpaddr->hper1, HPER1_BITS, xpaddr->rmer2, RMER2_BITS, ((xp_rwhdr[unit]) ? " (hdr i/o)" : "")); #else printf("cs2=%b er1=%b %s\n", xpaddr->hpcs2.w, HPCS2_BITS, xpaddr->hper1, HPER1_BITS, ((xp_rwhdr[unit]) ? " (hdr i/o)" : "")); #endif bp->b_flags |= B_ERROR; bp->b_flags &= ~B_BAD; } else xc->xp_active = 0; } /* * If soft ecc, correct it (continuing by returning if * necessary). Otherwise, fall through and retry the * transfer. */ if((xpaddr->hper1 & (HPER1_DCK|HPER1_ECH)) == HPER1_DCK) if (xpecc(bp, ECC)) return; errdone: xpaddr->hpcs1.w = HP_TRE | HP_IE | HP_DCLR | HP_GO; if ((dp->b_errcnt & 07) == 4) { xpaddr->hpcs1.w = HP_RECAL | HP_IE | HP_GO; while ((xpaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY); } xd->xp_cc = -1; } if (xc->xp_active) { if (dp->b_errcnt) { xpaddr->hpcs1.w = HP_RTC | HP_GO; while ((xpaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY); } xc->xp_active = 0; xc->xp_actf = dp->b_forw; dp->b_active = 0; dp->b_errcnt = 0; dp->b_actf = bp->b_actf; xd->xp_cc = bp->b_cylin; bp->b_resid = - (xpaddr->hpwc << 1); xp_rwhdr[unit] = 0; iodone(bp); xpaddr->hpcs1.w = HP_IE; if (dp->b_actf) xpustart(unit); } as &= ~(1 << xp_drive[unit].xp_unit); } else { if (as == 0) xpaddr->hpcs1.w = HP_IE; xpaddr->hpcs1.c[1] = HP_TRE >> 8; } for (unit = 0; unit < NXPD; unit++) if ((xp_drive[unit].xp_ctlr == xc) && (as & (1 << xp_drive[unit].xp_unit))) xpustart(unit); xpstart(xc); } xpioctl(dev, cmd, data, flag) dev_t dev; u_int cmd; caddr_t data; { int unit = xpunit(dev); switch(cmd) { case DKIOCHDR: /* do header read/write */ xp_rwhdr[unit] = 1; return(0); case DKREINIT: /* reread BBF table */ xp_init[unit] = 0; return(0); case DKINFO: /* get drive info */ { struct drv_info *xo = (struct drv_info *)data; register struct xp_drive *xd = &xp_drive[unit]; xo->type = xd->xp_type; xo->model = 0; xo->trk = xd->xp_ntrack; xo->sec = xd->xp_nsect; xo->nspc = xd->xp_nspc; xo->ncyl = xd->xp_ncyl; xo->name[0] = '\0'; bcopy(xd->xp_sizes, xo->fs, 48); } return(0); } return(EINVAL); } #define exadr(x,y) (((long)(x) << 16) | (unsigned)(y)) /* * Correct an ECC error and restart the i/o to complete the transfer if * necessary. This is quite complicated because the correction may be going * to an odd memory address base and the transfer may cross a sector boundary. */ xpecc(bp, flag) register struct buf *bp; { register struct xp_drive *xd; register struct hpdevice *xpaddr; register unsigned byte; ubadr_t bb, addr; long wrong; int bit, wc; unsigned ndone, npx; int ocmd; int cn, tn, sn; daddr_t bn; struct ubmap *ubp; int unit; /* * ndone is #bytes including the error which is assumed to be in the * last disk page transferred. */ unit = dkunit(bp); xd = &xp_drive[unit]; xpaddr = xd->xp_ctlr->xp_addr; #ifdef BADSECT if (flag == CONT) { npx = bp->b_error; bp->b_error = 0; ndone = npx * NBPG; wc = -((short)(bp->b_bcount - ndone) / (short)NBPW); } else { #endif wc = xpaddr->hpwc; ndone = bp->b_bcount - ((unsigned)(-wc) * NBPW); npx = ndone / NBPG; #ifdef BADSECT } #endif ocmd = (xpaddr->hpcs1.w & ~HP_RDY) | HP_IE | HP_GO; bb = exadr(bp->b_xmem, bp->b_un.b_addr); bn = dkblock(bp); cn = bp->b_cylin - (bn / xd->xp_nspc); bn += npx; cn += bn / xd->xp_nspc; sn = bn % xd->xp_nspc; tn = sn; tn /= xd->xp_nsect; sn %= xd->xp_nsect; switch (flag) { case ECC: printf("xp%d%c: soft ecc sn%D\n",unit, 'a' + (minor(bp->b_dev) & 07), bp->b_blkno + (npx - 1)); wrong = xpaddr->hpec2; if (wrong == 0) { xpaddr->hpof = HPOF_FMT22; xpaddr->hpcs1.w |= HP_IE; return (0); } /* * Compute the byte/bit position of the err * within the last disk page transferred. * Hpec1 is origin-1. */ byte = xpaddr->hpec1 - 1; bit = byte & 07; byte >>= 3; byte += ndone - NBPG; wrong <<= bit; /* * Correct until mask is zero or until end of * transfer, whichever comes first. */ while (byte < bp->b_bcount && wrong != 0) { addr = bb + byte; if (bp->b_flags & (B_MAP|B_UBAREMAP)) { /* * Simulate UNIBUS map if UNIBUS * transfer. */ ubp = UBMAP + ((addr >> 13) & 037); addr = exadr(ubp->ub_hi, ubp->ub_lo) + (addr & 017777); } putmemc(addr, getmemc(addr) ^ (int) wrong); byte++; wrong >>= 8; } break; #ifdef BADSECT case BSE: if ((bn = isbad(&xpbad[unit], cn, tn, sn)) < 0) return(0); bp->b_flags |= B_BAD; bp->b_error = npx + 1; bn = (daddr_t)xd->xp_ncyl * xd->xp_nspc - xd->xp_nsect - 1 - bn; cn = bn/xd->xp_nspc; sn = bn%xd->xp_nspc; tn = sn; tn /= xd->xp_nsect; sn %= xd->xp_nsect; #ifdef XP_DEBUG printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); #endif wc = -(512 / (short)NBPW); break; case CONT: bp->b_flags &= ~B_BAD; #ifdef XP_DEBUG printf("xpecc CONT: bn %D cn %d tn %d sn %d\n", bn, cn, tn, sn); #endif break; #endif BADSECT } xd->xp_ctlr->xp_active++; if (wc == 0) return (0); /* * Have to continue the transfer. Clear the drive and compute the * position where the transfer is to continue. We have completed * npx sectors of the transfer already. */ xpaddr->hpcs2.w = xd->xp_unit; xpaddr->hpcs1.w = HP_TRE | HP_DCLR | HP_GO; addr = bb + ndone; xpaddr->hpdc = cn; xpaddr->hpda = (tn << 8) + sn; xpaddr->hpwc = wc; xpaddr->hpba = (caddr_t)addr; if (xd->xp_ctlr->xp_flags & XP_RH70) xpaddr->hpbae = (int)(addr >> 16); xpaddr->hpcs1.w = ocmd; return (1); } #ifdef XP_DUMP /* * Dump routine. Dumps from dumplo to end of memory/end of disk section for * minor(dev). */ #define DBSIZE 16 /* unit of transfer, same number */ xpdump(dev) dev_t dev; { /* * ONLY USE 2 REGISTER VARIABLES, OR C COMPILER CHOKES */ register struct xp_drive *xd; register struct hpdevice *xpaddr; daddr_t bn, dumpsize; long paddr; int sn, count; struct ubmap *ubp; if ((bdevsw[major(dev)].d_strategy != xpstrategy) /* paranoia */ || ((dev=minor(dev)) > (NXPD << 3))) return(EINVAL); xd = &xp_drive[dev >> 3]; dev &= 07; if (xd->xp_ctlr == 0) return(EINVAL); xpaddr = xd->xp_ctlr->xp_addr; dumpsize = xd->xp_sizes[dev].nblocks; if ((dumplo < 0) || (dumplo >= dumpsize)) return(EINVAL); dumpsize -= dumplo; xpaddr->hpcs2.w = xd->xp_unit; if ((xpaddr->hpds & HPDS_VV) == 0) { xpaddr->hpcs1.w = HP_DCLR | HP_GO; xpaddr->hpcs1.w = HP_PRESET | HP_GO; xpaddr->hpof = HPOF_FMT22; } if ((xpaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL)) return(EFAULT); ubp = &UBMAP[0]; for (paddr = 0L; dumpsize > 0; dumpsize -= count) { count = dumpsize>DBSIZE? DBSIZE: dumpsize; bn = dumplo + (paddr >> PGSHIFT); xpaddr->hpdc = bn / xd->xp_nspc + xd->xp_sizes[dev].cyloff; sn = bn % xd->xp_nspc; xpaddr->hpda = ((sn / xd->xp_nsect) << 8) | (sn % xd->xp_nsect); xpaddr->hpwc = -(count << (PGSHIFT - 1)); if (ubmap && ((xd->xp_ctlr->xp_flags & XP_RH70) == 0)) { ubp->ub_lo = loint(paddr); ubp->ub_hi = hiint(paddr); xpaddr->hpba = 0; xpaddr->hpcs1.w = HP_WCOM | HP_GO; } else { /* * Non-UNIBUS map, or 11/70 RH70 (MASSBUS) */ xpaddr->hpba = loint(paddr); if (xd->xp_ctlr->xp_flags & XP_RH70) xpaddr->hpbae = hiint(paddr); xpaddr->hpcs1.w = HP_WCOM | HP_GO | ((paddr >> 8) & (03 << 8)); } while (xpaddr->hpcs1.w & HP_GO); if (xpaddr->hpcs1.w & HP_TRE) { if (xpaddr->hpcs2.w & HPCS2_NEM) return(0); /* made it to end of memory */ return(EIO); } paddr += (DBSIZE << PGSHIFT); } return(0); /* filled disk minor dev */ } #endif XP_DUMP #endif NXPD e(bp); goto loop; } if (dp->b_errcnt >= 16 && (bp->b_flags & B_READ)) { xpaddr->hpof = xp_offset[dp->b_errcnt & 017] | HPOF_FMT22; xpaddr->hpcs1.sys/OTHERS/bad144/conf.c.diff 640 0 12 2115 4357252237 10635 *** /sys/pdp/conf.c Thu Aug 25 18:52:49 1988 --- /tmp/conf.c Sat Dec 31 14:27:49 1988 *************** *** 58,64 **** #include "xp.h" #if NXPD > 0 ! int xpopen(), xpstrategy(), xpread(), xpwrite(), xproot(); #define xpclose nulldev #else #define xpopen nodev --- 58,64 ---- #include "xp.h" #if NXPD > 0 ! int xpopen(), xpstrategy(), xpread(), xpwrite(), xproot(), xpioctl(); #define xpclose nulldev #else #define xpopen nodev *************** *** 67,72 **** --- 67,73 ---- #define xpstrategy nodev #define xpread nodev #define xpwrite nodev + #define xpioctl nodev #endif #include "br.h" *************** *** 363,369 **** nodev, nulldev, 0, seltrue, /* xp = 19 */ xpopen, xpclose, xpread, xpwrite, ! nodev, nulldev, 0, seltrue, /* br = 20 */ bropen, brclose, brread, brwrite, nodev, nulldev, 0, seltrue, --- 364,370 ---- nodev, nulldev, 0, seltrue, /* xp = 19 */ xpopen, xpclose, xpread, xpwrite, ! xpioctl, nulldev, 0, seltrue, /* br = 20 */ bropen, brclose, brread, brwrite, nodev, nulldev, 0, seltrue, ub_lo) + (addr & 017777); } putmemc(addr, getmemc(addr) ^ (int) wrong); byte++; wrong >>= 8; } break; #ifdef BADSECT case BSE: if ((bn = isbad(&xpbad[unit], cn, tn, sn)) < 0) return(0); bp->b_flags |= B_BAD; bp->b_error = npx + 1; bn = (daddr_t)xd->xp_ncyl * xd->xp_nspc - xd->xp_nsect - 1 - bn; cn = bn/xd->xp_nspc; sn = bn%xd->xp_nspc; tn = sn; tn /= xd->xp_nsect; sn %= xd->xp_sys/vaxuba/ 755 0 12 0 4117335745 6060 sys/vaxuba/rxreg.h 444 0 12 6466 4017155001 7437 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)rxreg.h 7.1 (Berkeley) 6/5/86 */ #ifdef KERNEL #include "ioctl.h" #else #include #endif /* * RX02 registers */ struct rxdevice { short rxcs; /* control/status register */ short rxdb; /* data buffer register */ }; /* * RX211 Command and Status Register (RX2CS) */ #define RX_DRV0 0x0000 /* select drive 0 */ #define RX_DRV1 0x0010 /* select drive 1 */ #define RX_DONE 0x0020 /* function complete */ #define RX_INTR 0x0040 /* interrupt enable */ #define RX_TREQ 0x0080 /* transfer request (data only) */ #define RX_SDEN 0x0000 /* single density */ #define RX_DDEN 0x0100 /* double density */ #define RX_EXT 0x3000 /* extended address bits */ #define RX_INIT 0x4000 /* initialize RX211 interface */ #define RX_ERR 0x8000 /* general error bit */ /* * RX211 control function bits (0-3 of RX2CS) */ #define RX_FILL 0x0001 /* fill the buffer */ #define RX_EMPTY 0x0003 /* empty the buffer */ #define RX_WRITE 0x0005 /* write the buffer to disk */ #define RX_READ 0x0007 /* read a disk sector to the buffer */ #define RX_FORMAT 0x0009 /* set the media density (format) */ #define RX_RDSTAT 0x000b /* read the disk status */ #define RX_WDDS 0x000d /* write a deleted-data sector */ #define RX_RDERR 0x000f /* read the error registers */ #define RXCS_BITS \ "\20\20RX_ERR\17RX_INIT\11RX_DDEN\10RX_TREQ\7RX_IE\6RX_DONE\5RX_DRV1" /* * RX211 Error and Status Register (RX2ES) -- * information is located in RX2DB after completion of function. * The READY bit's value is available only after a "read status". */ #define RXES_CRCERR 0x0001 /* CRC error (data read error) */ #define RXES_IDONE 0x0004 /* reinitialization complete */ #define RXES_DENERR 0x0010 /* density error */ #define RXES_DBLDEN 0x0020 /* set if double density */ #define RXES_DDMARK 0x0040 /* deleted-data mark */ #define RXES_READY 0x0080 /* drive is ready */ #define RXES_BITS \ "\20\14RXES_NXM\13RXES_WCOF\11RXES_DRV1\10RXES_RDY\7RXES_DDMK\6RXES_DDEN\5\ RXES_DNER\4RXES_ACLO\3RXES_ID\1RXES_CRC" /* * Ioctl commands, move to dkio.h later */ #define RXIOC_FORMAT _IOW(d, 1, int) /* format the disk */ #define RXIOC_WDDS _IOW(d, 2, int) /* write `deleted data' mark */ /* on next sector */ #define RXIOC_RDDSMK _IOR(d, 3, int) /* did last read sector contain */ /* `deleted data'?*/ #define RXIOC_GDENS _IOR(d, 4, int) /* return density of current disk */ #ifdef RXDEFERR /* * Table of values for definitive error code (rxxt[0] & 0xff) */ struct rxdeferr { short errval; char *errmsg; } rxdeferr[] = { { 0010, "Can't find home on drive 0" }, { 0020, "Can't find home on drive 1" }, { 0040, "Bad track number requested" }, { 0050, "Home found too soon" }, { 0070, "Can't find desired sector" }, { 0110, "No SEP clock seen" }, { 0120, "No preamble found" }, { 0130, "Preamble, but no ID mark" }, { 0140, "Header CRC error"}, { 0150, "Track addr wrong in header" }, { 0160, "Too many tries for ID AM" }, { 0170, "No data AM found" }, { 0200, "Data CRC error" }, { 0220, "Maintenance test failure" }, { 0230, "Word count overflow" }, { 0240, "Density error" }, { 0250, "Set-density protocol bad" }, { 0, "Undefined error code" } }; #endif ty */ #define RX_EXT 0x3000 /* extended address bits */ #define RX_INIT 0x4000 /* initialize RX211 interface */ #define RX_ERR 0x8000 /* general error bit */ /* * RX211 control function bits (0-3 osys/vaxuba/tags 751 0 12 0 6045325337 10663 2../sys/tagssys/pdpif/ 755 0 12 0 5757543305 5700 sys/pdpif/if_acc.h 444 0 12 3255 4001145502 7317 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_acc.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * ACC LH/DH-11 interface */ struct accdma { short csr; /* control and status */ short db; /* data buffer */ u_short ba; /* buss address */ short wc; /* word count */ }; struct accdevice { struct accdma input; struct accdma output; }; #define icsr input.csr #define iba input.ba #define iwc input.wc #define ocsr output.csr #define oba output.ba #define owc output.wc /* * Bits Common to both input and out CSR's */ #define ACC_ERR 0x8000 /* error present */ #define ACC_NXM 0x4000 /* non-existant memory */ #define ACC_RDY 0x0080 /* ready */ #define ACC_IE 0x0040 /* interrupt enable */ #define ACC_RESET 0x0002 /* reset interface */ #define ACC_GO 0x0001 /* start operation */ /* * Input Control Status Register */ #define IN_EOM 0x2000 /* end-of-message recieved */ #define IN_HRDY 0x0800 /* host ready */ #define IN_IMPBSY 0x0400 /* IMP not ready */ #define IN_RMR 0x0200 /* receive master ready error */ #define IN_IBF 0x0100 /* input data buffer full */ #define IN_WEN 0x0008 /* write enable */ #define IN_MRDY 0x0004 /* master ready */ #define ACC_INBITS \ "\20\20ERR\17NXM\16EOM\14HRDY\13IMPBSY\12RMR\11IBF\10RDY\7IE\ \4WEN\3MRDY\2RESET\1GO" /* * Output Control Status Register */ #define OUT_TMR 0x0200 /* transmit master ready error */ #define OUT_BBACK 0x0008 /* bus back */ #define OUT_ENLB 0x0004 /* enable last bit */ #define ACC_OUTBITS \ "\20\20ERR\17NXM\12TMR\10RDY\7IE\4BBACK\3ENLB\2RESET\1GO" available only after a "read status". */ #define RXES_CRCERR 0x0001 /* CRC error (data read error) */ #define RXES_IDONE 0x0004 /* reinitialization complete */ #define RXES_DENERR 0x0010 /* density error */ #define RXES_DBLDEN 0x0020 /* set if double density */ #define RXES_DDMARK 0x0040 /* deleted-data mark */ #define RXES_READY 0x0080sys/pdpif/if_css.h 444 0 12 4166 4001145506 7367 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_css.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * DEC/CSS IMP11-A ARPAnet interface */ struct cssdma { short wc; /* word count */ u_short ba; /* bus address (low 16 bits) */ short csr; /* status register */ short db; /* data buffer*/ }; struct cssdevice { struct cssdma css_output; /* transmit DR11-B */ struct cssdma css_hole; /* unclever gap */ struct cssdma css_input; /* receive DR11-B */ }; #define css_icsr css_input.csr #define css_iba css_input.ba #define css_iwc css_input.wc #define css_ocsr css_output.csr #define css_oba css_output.ba #define css_owc css_output.wc /* * Bits Common to both input and out CSR's */ #define CSS_ERR 0x8000 /* error present */ #define CSS_NXM 0x4000 /* non-existant memory */ #define CSS_ATTN 0x2000 /* attention */ #define CSS_MAINT 0x1000 /* maintenance mode */ #define CSS_CYCLE 0x0100 /* force bus cycle */ #define CSS_RDY 0x0080 /* ready */ #define CSS_IE 0x0040 /* interrupt enable */ #define CSS_XA 0x0030 /* extended address bits */ #define CSS_CLR 0x0020 /* clear status (reset) */ #define CSS_GO 0x0001 /* start operation */ /* * Input Control Status Register */ #define IN_EOM 0x0800 /* end-of-message recieved */ #define IN_IMPNR 0x0400 /* IMP not ready */ #define IN_RLE 0x0200 /* ready line error */ #define IN_WEN 0x0008 /* write enable */ #define IN_HRDY 0x0004 /* host ready */ #define CSS_INBITS \ "\20\20ERR\17NXM\16ATTN\15MAINT\14EOM\13IMPNR\12RLE\11CYCLE\10RDY\7IE\6XBA17\5XBA16\4WE\3HRDY\2CLR\1GO" /* * Output Control Status Register */ #define OUT_TXEC 0x0008 /* tx error clear */ #define OUT_ENLB 0x0004 /* enable last bit */ #define CSS_OUTBITS \ "\20\20ERR\17NXM\16ATTN\15MAINT\11CYCLE\10RDY\7IE\6XBA17\5XBA16\4TXEC\3ENLB\2CLR\1GO" RXES_DNER\4RXES_ACLO\3RXES_ID\1RXES_CRC" /* * Ioctl commands, move to dkio.h later */ #define RXIOC_FORMAT _IOW(d, 1, int) /* format the disk */ #define RXIOC_WDDS _IOW(d, 2, int) /* write `deleted data' mark */ /* on next sector */ #define RXIOC_RDDSMK _IOR(d, 3, int) /* did last read sector contain */ /* `deleted data'?*/ #define RXIOC_GDENS _IOR(d, 4, int) /* return densitysys/pdpif/if_de.h 444 0 12 12120 5511225451 7201 /* * SCCSID: @(#)if_de.h 1.1 (2.11BSD GTE) 12/31/93 */ /* Header files and definitons to support multiple DEUNAs */ #include "socket.h" #include "../net/if.h" #include "../net/netisr.h" #include "../net/route.h" #ifdef INET #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netinet/in_var.h" #include "../netinet/ip.h" #include "../netinet/if_ether.h" #endif /* INET */ #ifdef NS #include "../netns/ns.h" #include "../netns/ns_if.h" #endif /* NS */ #include "../pdpif/if_dereg.h" #include "../pdpuba/ubavar.h" #include "../pdpif/if_uba.h" /* * These numbers are based on the amount of space that is allocated * int netinit() to miobase, for 4 + 6, miosize must be 16384 instead * of the 8192 allocated originally. m_ioget() gets a click address * within the allocated region. NOTE: the UMR handling has been fixed * in 2.11BSD to allocate only the number of UMRs required by the size * of the m_ioget I/O region - a UMR per buffer is NO LONGER THE CASE! * Note that the size of a buffer is: * 1500 (ETHERMTU) + sizeof(ether_header) + some rounding from btoc() = * 1536 bytes or 24 clicks. */ #define NXMT 4 /* number of transmit buffers */ #define NRCV 6 /* number of receive buffers (must be > 1) */ #ifdef DE_DO_MULTI /* * Multicast address list structure */ struct de_m_add { u_char dm_char[6]; }; #define MULTISIZE sizeof(struct de_m_add) #define NMULTI 10 /* # of multicast addrs on the DEUNA */ #endif /* DE_DO_MULTI */ /* * The deuba structures generalizes the ifuba structure * to an arbitrary number of receive and transmit buffers. */ struct deuba { u_short ifu_hlen; /* local net header length */ struct ifrw difu_r[NRCV]; /* receive information */ struct ifrw difu_w[NXMT]; /* transmit information */ short difu_flags; }; /* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * ds_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... * We also have, for each interface, a UBA interface structure, which * contains information about the UNIBUS resources held by the interface: * map registers, buffered data paths, etc. Information is cached in this * structure for use by the if_uba.c routines in running the interface * efficiently. */ struct de_softc { struct arpcom ds_ac; /* Ethernet common part */ #define ds_if ds_ac.ac_if /* network-visible interface */ #define ds_addr ds_ac.ac_enaddr /* hardware Ethernet address */ char ds_flags; /* Has the board be initialized? */ #define DSF_LOCK 1 #define DSF_RUNNING 2 #define DSF_SETADDR 4 char ds_devid; /* device id DEUNA=0, DELUA=1 */ ubadr_t ds_ubaddr; /* map info for incore structs */ struct deuba ds_deuba; /* unibus resource structure */ /* the following structures are always mapped in */ struct de_pcbb ds_pcbb; /* port control block */ struct de_ring ds_xrent[NXMT]; /* transmit ring entrys */ struct de_ring ds_rrent[NRCV]; /* receive ring entrys */ struct de_udbbuf ds_udbbuf; /* UNIBUS data buffer */ #ifdef DE_DO_MULTI struct de_m_add ds_multicast[NMULTI]; /* multicast addr list */ #endif /* DE_DO_MULTI */ #ifdef DE_DO_BCTRS struct de_counters ds_counters;/* counter block */ #endif /* DE_DO_BCTRS */ /* end mapped area */ #define INCORE_BASE(p) ((char *)&(p)->ds_pcbb) #define RVAL_OFF(n) ((char *)&de_softc[0].n - INCORE_BASE(&de_softc[0])) #define LVAL_OFF(n) ((char *)de_softc[0].n - INCORE_BASE(&de_softc[0])) #define PCBB_OFFSET RVAL_OFF(ds_pcbb) #define XRENT_OFFSET LVAL_OFF(ds_xrent) #define RRENT_OFFSET LVAL_OFF(ds_rrent) #define UDBBUF_OFFSET RVAL_OFF(ds_udbbuf) #ifdef DE_DO_MULTI #define MULTI_OFFSET RVAL_OFF(ds_multicast[0]) #endif /* DE_DO_MULTI */ #ifdef DE_DO_BCTRS #define COUNTER_OFFSET RVAL_OFF(ds_counters) #endif /* DE_DO_BCTRS */ #define INCORE_SIZE RVAL_OFF(ds_xindex) u_char ds_xindex; /* UNA index into transmit chain */ u_char ds_rindex; /* UNA index into receive chain */ u_char ds_xfree; /* index for next transmit buffer */ u_char ds_nxmit; /* # of transmits in progress */ #ifdef DE_DO_MULTI u_char ds_muse[NMULTI]; /* multicast address use */ #endif /* DE_DO_MULTI */ #ifdef DE_DO_BCTRS long ds_ztime; /* time counters were last zeroed */ u_short ds_unrecog; /* unrecognized frame destination */ #endif /* DE_DO_BCTRS */ }; /* * These are the Ultrix ioctl's that are specific to this driver */ #ifdef DE_DO_PHYSADDR #define SIOCSPHYSADDR _IOWR(i,23, struct ifreq) /* Set phys. ad.*/ #define SIOCRPHYSADDR _IOWR(i,28, struct ifdevea) /* Read phy. ad.*/ #endif /* DE_DO_PHYSADDR */ #ifdef DE_DO_MULTI #define SIOCADDMULTI _IOWR(i,24, struct ifreq) /* Add m.c. ad. */ #define SIOCDELMULTI _IOWR(i,25, struct ifreq) /* Dele. m.c.ad.*/ #endif /* DE_DO_MULTI */ #ifdef DE_DO_BCTRS #define SIOCRDCTRS _IOWR(i,26, struct ctrreq) /* Read if cntr.*/ #define SIOCRDZCTRS _IOWR(i,27, struct ctrreq) /* Read/0 if c. */ #endif /* DE_DO_BCTRS */ #ifdef DE_INT_LOOPBACK #define SIOCDISABLBACK _IOW(i,34, struct ifreq) /* Cl.in.ex.lpb.*/ #define SIOCENABLBACK _IOW(i,33, struct ifreq) /* Set in.ex.lb.*/ #endif /* DE_INT_LOOPBACK */ = xd->xp_unit; if ((xpaddr->hpds & HPDS_VV) == 0) { xpaddr->hpcs1.w = HP_DCLR | HP_GO; xpaddr->hpcs1.w = HP_PRESET | HP_GO; xpaddr->hpof = HPOF_FMT22; } if ((xpaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL)) return(EFAULT); ubp = &UBMAP[0]; for (paddr = 0L; dumpsize > 0; dumpsize -= count) { count = dumpsize>DBSIZE? DBSIZE: dumpsize; bn = dumplo + (paddr >> PGSHIFT); xpaddr->hpdc = bn / xd->xp_nsys/pdpif/if_dmc.h 444 0 12 3453 4001145515 7340 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_dmc.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * DMC-11 Interface */ struct dmcdevice { union { char b[8]; short w[4]; } un; }; #define bsel0 un.b[0] #define bsel1 un.b[1] #define bsel2 un.b[2] #define bsel3 un.b[3] #define bsel4 un.b[4] #define bsel5 un.b[5] #define bsel6 un.b[6] #define bsel7 un.b[7] #define sel0 un.w[0] #define sel2 un.w[1] #define sel4 un.w[2] #define sel6 un.w[3] #define DMCMTU (2048) #define RDYSCAN 16 /* loop delay for RDYI after RQI */ /* defines for bsel0 */ #define DMC_BACCI 0 #define DMC_CNTLI 1 #define DMC_PERR 2 #define DMC_BASEI 3 #define DMC_WRITE 0 /* transmit block */ #define DMC_READ 4 /* read block */ #define DMC_RQI 0040 /* port request bit */ #define DMC_IEI 0100 /* enable input interrupts */ #define DMC_RDYI 0200 /* port ready */ /* defines for bsel1 */ #define DMC_MCLR 0100 /* DMC11 Master Clear */ #define DMC_RUN 0200 /* clock running */ /* defines for bsel2 */ #define DMC_BACCO 0 #define DMC_CNTLO 1 #define DMC_OUX 0 /* transmit block */ #define DMC_OUR 4 /* read block */ #define DMC_IEO 0100 /* enable output interrupts */ #define DMC_RDYO 0200 /* port available */ /* defines for CNTLI mode */ #define DMC_HDPLX 02000 /* half duplex DDCMP operation */ #define DMC_SEC 04000 /* half duplex secondary station */ #define DMC_MAINT 00400 /* enter maintenance mode */ /* defines for BACCI/O and BASEI mode */ #define DMC_XMEM 0140000 /* xmem bit position */ #define DMC_CCOUNT 0037777 /* character count mask */ #define DMC_RESUME 0002000 /* resume (BASEI only) */ /* defines for CNTLO */ #define DMC_CNTMASK 01777 #define DMC_FATAL 01620 e INCORE_SIZE RVAL_OFF(ds_xindex) u_char ds_xindex; /* UNA index into transmit chain */ u_char ds_rindex; /* UNA index into receive chain */ u_char ds_xfree; /* index for next transmit buffer */ u_char ds_nsys/pdpif/if_en.h 444 0 12 1324 4001145524 7172 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_en.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * Structure of a Ethernet header. */ struct en_header { u_char en_shost; u_char en_dhost; u_short en_type; }; #define ENPUP_PUPTYPE 0x0400 /* PUP protocol */ #define ENPUP_IPTYPE 0x0800 /* IP protocol */ /* * The ENPUP_NTRAILER packet types starting at ENPUP_TRAIL have * (type-ENPUP_TRAIL)*512 bytes of data followed * by a PUP type (as given above) and then the (variable-length) header. */ #define ENPUP_TRAIL 0x1000 /* Trailer PUP */ #define ENPUP_NTRAILER 16 efine DMC_CNTLI 1 #define DMC_PERR 2 #define DMC_BASEI 3 #define DMC_WRITE 0 /* transmit block */ #define DMC_READ 4 /* read block */ #define DMC_RQI 0040 /* port request bit */ #define DMC_IEI 0100 /* enable input interrupts */ #define DMC_RDYI 0200 /* port ready */ /* defines for bsel1 */ sys/pdpif/if_il.h 444 0 12 3223 5511225503 7177 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_il.h 1.2 (2.11BSD GTE) 12/31/93 */ /* * Structure of an Ethernet header -- receive format */ struct il_rheader { u_char ilr_status; /* Frame Status */ u_char ilr_fill1; u_short ilr_length; /* Frame Length */ u_char ilr_dhost[6]; /* Destination Host */ u_char ilr_shost[6]; /* Source Host */ u_short ilr_type; /* Type of packet */ }; /* * Structure of statistics record */ struct il_stats { u_short ils_fill1; u_short ils_length; /* Length (should be 62) */ u_char ils_addr[6]; /* Ethernet Address */ u_short ils_frames; /* Number of Frames Received */ u_short ils_rfifo; /* Number of Frames in Receive FIFO */ u_short ils_xmit; /* Number of Frames Transmitted */ u_short ils_xcollis; /* Number of Excess Collisions */ u_short ils_frag; /* Number of Fragments Received */ u_short ils_lost; /* Number of Times Frames Lost */ u_short ils_multi; /* Number of Multicasts Accepted */ u_short ils_rmulti; /* Number of Multicasts Rejected */ u_short ils_crc; /* Number of CRC Errors */ u_short ils_align; /* Number of Alignment Errors */ u_short ils_collis; /* Number of Collisions */ u_short ils_owcollis; /* Number of Out-of-window Collisions */ u_short ils_fill2[8]; char ils_module[8]; /* Module ID */ char ils_firmware[8]; /* Firmware ID */ }; /* * Structure of Collision Delay Time Record */ struct il_collis { u_short ilc_fill1; u_short ilc_length; /* Length (should be 0-32) */ u_short ilc_delay[16]; /* Delay Times */ }; haracter count mask */ #define DMC_RESUME 0002000 /* resume (BASEI only) */ /* defines for CNTLO */ #define DMC_CNTMASK 01777 #define DMC_FATAL 01620 e INCORE_SIZE RVAL_OFF(ds_xindex) u_char ds_xindex; /* UNA index into transmit chain */ u_char ds_rindex; /* UNA index into receive chain */ u_char ds_xfree; /* index for next transmit buffer */ u_char ds_nsys/pdpif/if_sri.h 444 0 12 2655 4001145543 7376 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_sri.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * SRI dr11c interface */ struct sridevice { u_short csr; /* control/status */ u_short obf; /* out buffer */ u_short ibf; /* in buffer */ }; /* * control and status register. */ #define SRI_IREQ 0x8000 /* input request or error */ #define SRI_OREQ 0x0080 /* output request */ #define SRI_OINT 0x0040 /* output intr enable */ #define SRI_IINT 0x0020 /* input intr enable */ #define SRI_IENB 0x0002 /* input enable */ #define SRI_OENB 0x0001 /* output enable */ /* * input buffer register. */ #define IN_CHECK 0x8000 /* check input or error */ #define IN_HNRDY 0x2000 /* host not ready */ #define IN_INRDY 0x1000 /* imp not ready */ #define IN_LAST 0x0800 /* last bit */ /* * output buffer register. */ #define OUT_LAST IN_LAST /* last bit */ #define OUT_HNRDY IN_HNRDY /* host not ready */ #define OUT_HRDY 0x1000 /* host ready */ #define SRI_INBITS \ "\20\20CHECK\16HNRDY\15INRDY\14LAST" #define SRI_BITS \ "\20\20IREQ\10OREQ\7OINT\6IINT\2IENB\1OENB" ar ils_firmware[8]; /* Firmware ID */ }; /* * Structure of Collision Delay Time Rsys/pdpif/if_uba.h 444 0 12 3516 5316460757 7366 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_uba.h 1.2 (2.11BSD GTE) 12/24/92 */ /* * Structure and routine definitions * for UNIBUS network interfaces. */ #define IF_MAXNUBAMR 10 /* * Each interface has one of these structures giving information * about UNIBUS resources held by the interface. * * We hold IF_NUBAMR map registers for datagram data, starting * at ifr_mr. Map register ifr_mr[-1] maps the local network header * ending on the page boundary. Bdp's are reserved for read and for * write, given by ifr_bdp. The prototype of the map register for * read and for write is saved in ifr_proto. * * When write transfers are not full pages on page boundaries we just * copy the data into the pages mapped on the UNIBUS and start the * transfer. If a write transfer is of a (1024 byte) page on a page * boundary, we swap in UNIBUS pte's to reference the pages, and then * remap the initial pages (from ifu_wmap) when the transfer completes. * * When read transfers give whole pages of data to be input, we * allocate page frames from a network page list and trade them * with the pages already containing the data, mapping the allocated * pages to replace the input pages for the next UNIBUS data input. */ struct ifuba { short ifu_hlen; /* local net header length */ struct ifrw { u_int ifrw_click; /* MMU click address */ u_long ifrw_info; /* value from ubaalloc */ } ifu_r, ifu_w; short ifu_flags; struct mbuf *ifu_xtofree; /* pages being dma'd out */ }; #ifdef SUPERVISOR struct mbuf *if_rubaget(); #endif #if defined(KERNEL) && defined(INET) #define ubarelse(a,b) #define useracc(a,c,m) (1) ubadr_t uballoc(), ubmalloc(); #endif u_char ds_xindex; /* UNA index into transmit chain */ u_char ds_rindex; /* UNA index into receive chain */ u_char ds_xfree; /* index for next transmit buffer */ u_char ds_nsys/pdpif/if_un.h 444 0 12 1324 4001145551 7212 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_un.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * Structure of a Ungermann-Bass datagram header. */ struct un_header { u_short un_length; u_char un_type; u_char un_control; u_short un_dnet; u_short un_dniu; u_char un_dport; u_char un_dtype; u_short un_snet; u_short un_sniu; u_char un_sport; u_char un_stype; u_char un_option; u_char un_bcc; u_short un_ptype; /* protocol type */ }; /* * Protocol types */ #define UNTYPE_INQUIRE 1 /* inquire - "Who am I?" */ #define UNTYPE_IP 2 /* Internet Protocol */ er for * read and for write is saved in ifr_proto. * * When write transfers are not full pages on page boundaries we just * copy the data into the pages mapped on the UNIBUS and start the * transfer. If a write transfer is of a (1024 byte) page on a page * boundary, we swap in UNIBUS pte's tosys/pdpif/if_vv.h 444 0 12 7472 4476147446 7262 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_vv.h 2.0 (2.10.1BSD Berkeley) 8/25/89 */ /* * ECO 176-748 changed the braodcast address from 0 to 0xff, at * CTL (p1002) serial number around 150. * It was implemented in August, 1982. This is a field-installable ECO, * which improves net reliability. If the broadcast address has not been * changed, comment out the following line. */ #define NEW_BROADCAST /* new chip for broadcast problem */ /* * Local network header for proNET Ring * This is arbitrated by "jas@proteon" * (aka John Shriver, 617-655-3340) */ struct vv_header { /* the first two fields are required by the hardware */ u_char vh_dhost; /* destination address */ u_char vh_shost; /* source address */ /* the next three fields are the local network header */ u_char vh_version; /* header version */ u_char vh_type; /* packet type => protocol number */ short vh_info; /* protocol-specific information */ }; #define RING_VERSION 2 /* current version of v2lni header */ /* * Packet types (protocol numbers) in proNET protocol header * Other types are defined, but are proprietary. */ #define RING_IP 1 #define RING_TRAILER 2 /* offset now in vh_info only */ #define RING_ARP 3 #define RING_HDLC 4 #define RING_VAXDB 5 #define RING_RINGWAY 6 #define RING_RINGWAYM 8 #define RING_NOVELL 10 #define RING_PUP 12 #define RING_XNS 14 #define RING_DIAGNOSTICS 15 /* protocol type for testing */ #define RING_ECHO 16 #define RING_WHOAMI 0xa5 /* insure some bit transitions */ #ifdef NEW_BROADCAST #define VV_BROADCAST 0xff /* hardware-defined broadcast address */ #else #define VV_BROADCAST 0x00 /* hardware-defined broadcast address */ #endif /* * Proteon proNET Hardware definitions * register bit definitions */ #define VV_ENB 01 /* Enable Operation */ #define VV_DEN 02 /* Enable DMA */ #define VV_HEN 04 /* Host Relay Enable (Rcv) */ #define VV_CPB 04 /* Clear Packet Buffer (Xmit) */ #define VV_STE 010 /* Self Test Enable (Rcv) */ #define VV_UT1 010 /* Unused (Xmit) */ #define VV_LPB 020 /* Modem Disable (Rcv) */ #define VV_INR 020 /* Initialize Ring (Xmit) */ #define VV_RST 040 /* Reset */ #define VV_IEN 0100 /* Interrupt Enable */ #define VV_RDY 0200 /* Done */ #define VV_DPR 0400 /* Data Present (Rcv) */ #define VV_RFS 0400 /* Refused (Xmit) */ #define VV_NXM 01000 /* Non Existent Memory */ #define VV_OVR 02000 /* Overrun */ #define VV_ODB 04000 /* Odd Byte (Rcv) */ #define VV_UT2 04000 /* Unused (Xmit) */ #define VV_LDE 010000 /* Parity on 10 megabit (Rcv), */ /* Link Data Error on 80 megabit (Rcv) */ #define VV_OPT 010000 /* Output Timeout (Xmit) */ #define VV_NOK 020000 /* Ring Not OK */ #define VV_BDF 040000 /* Bad Format in Operation */ #define VV_NIR 0100000 /* Not in Ring */ #define VVXERR (VV_NXM|VV_OVR|VV_OPT|VV_BDF) /* Xmit errs */ #define VVRERR (VV_NXM|VV_OVR|VV_ODB|VV_BDF|VV_DPR) /* Rcv errs */ #define VVFE (VV_NXM|VV_OVR) /* Fatal errors */ #define VV_IBITS \ "\10\20NIR\17BDF\16NOK\15LDE\14ODB\13OVR\12NXM\11DPR\10RDY\7IEN\6RST\5LPB\4STE\3HEN\2DEN\1ENB" #define VV_OBITS \ "\10\20NIR\17BDF\16NOK\15OPT\13OVR\12NXM\11RFS\10RDY\7IEN\6RST\5INR\3HEN\2DEN\1ENB" /* device registers */ struct vvreg { short vvicsr; /* input csr */ u_short vviwc; /* input word count */ u_short vviba; /* input addr lo */ u_short vviea; /* input addr hi */ short vvocsr; /* output csr */ u_short vvowc; /* output word count */ u_short vvoba; /* output addr lo */ u_short vvoea; /* output addr hi */ }; #define VVRETRY 7 /* output retry limit */ #define VVIDENTSUCC 5 /* number of successes required in self-test */ #define VVIDENTRETRY 10 /* identify loop attempt limit */ #define VVTIMEOUT 60 /* seconds before a transmit timeout */ CTL (p1002) serial number around 150. * It was implemented in August, 1982. This is a field-installable ECO, * which improves net reliability. If the broadcast address has not been * changed, cosys/pdpif/if_ilreg.h 444 0 12 10274 4066535413 7731 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_ilreg.h 1.1 (2.10BSD Berkeley) 12/1/86 */ /* * Interlan Ethernet Communications Controller interface */ struct ildevice { short il_csr; /* Command and Status Register */ short il_bar; /* Buffer Address Register */ short il_bcr; /* Byte Count Register */ short il_ber; /* Bus Extension Register */ }; /* * Command and status bits */ #define IL_EUA 0xc000 /* Extended Unibus Address */ #define IL_CMD 0x3f00 /* Command Function Code */ #define IL_CDONE 0x0080 /* Command Done */ #define IL_CIE 0x0040 /* Command Interrupt Enable */ #define IL_RDONE 0x0020 /* Receive DMA Done */ #define IL_RIE 0x0010 /* Receive Interrupt Enable */ #define IL_STATUS 0x000f /* Command Status Code */ #define IL_BITS "\20\10CDONE\7CIE\6RDONE\5RIE" /* command definitions */ #define ILC_MLPBAK 0x0100 /* Set Module Interface Loopback Mode */ #define ILC_ILPBAK 0x0200 /* Set Internal Loopback Mode */ #define ILC_CLPBAK 0x0300 /* Clear Loopback Mode */ #define ILC_PRMSC 0x0400 /* Set Promiscuous Receive Mode */ #define ILC_CLPRMSC 0x0500 /* Clear Promiscuous Receive Mode */ #define ILC_RCVERR 0x0600 /* Set Receive-On-Error Bit */ #define ILC_CRCVERR 0x0700 /* Clear Receive-On-Error Bit */ #define ILC_OFFLINE 0x0800 /* Go Offline */ #define ILC_ONLINE 0x0900 /* Go Online */ #define ILC_DIAG 0x0a00 /* Run On-board Diagnostics */ #define ILC_ISA 0x0d00 /* Set Insert Source Address Mode */ #define ILC_CISA 0x0e00 /* Clear Insert Source Address Mode */ #define ILC_DEFPA 0x0f00 /* Set Physical Address to Default */ #define ILC_ALLMC 0x1000 /* Set Receive All Multicast Packets */ #define ILC_CALLMC 0x1100 /* Clear Receive All Multicast */ #define ILC_STAT 0x1800 /* Report and Reset Statistics */ #define ILC_DELAYS 0x1900 /* Report Collision Delay Times */ #define ILC_RCV 0x2000 /* Supply Receive Buffer */ #define ILC_LDXMIT 0x2800 /* Load Transmit Data */ #define ILC_XMIT 0x2900 /* Load Transmit Data and Send */ #define ILC_LDGRPS 0x2a00 /* Load Group Addresses */ #define ILC_RMGRPS 0x2b00 /* Delete Group Addresses */ #define ILC_LDPA 0x2c00 /* Load Physical Address */ #define ILC_FLUSH 0x3000 /* Flush Receive BAR/BCR Queue */ #define ILC_RESET 0x3f00 /* Reset */ /* * Error codes found in the status bits of the csr. */ #define ILERR_SUCCESS 0 /* command successful */ #define ILERR_RETRIES 1 /* " " with retries */ #define ILERR_BADCMD 2 /* illegal command */ #define ILERR_INVCMD 3 /* invalid command */ #define ILERR_RECVERR 4 /* receiver error */ #define ILERR_BUFSIZ 5 /* buffer size too big */ #define ILERR_FRAMESIZ 6 /* frame size too small */ #define ILERR_COLLISIONS 8 /* excessive collisions */ #define ILERR_BUFALIGNMENT 10 /* buffer not word aligned */ #define ILERR_NXM 15 /* non-existent memory */ #define NILERRS 16 #ifdef ILERRS char *ilerrs[NILERRS] = { "success", /* 0 */ "success with retries", /* 1 */ "illegal command", /* 2 */ "inappropriate command", /* 3 */ "failure", /* 4 */ "buffer size exceeded", /* 5 */ "frame too small", /* 6 */ 0, /* 7 */ "excessive collisions", /* 8 */ 0, /* 9 */ "buffer alignment error", /* 10 */ 0, /* 11 */ 0, /* 12 */ 0, /* 13 */ 0, /* 14 */ "non-existent memory" /* 15 */ }; #endif /* * Diagnostics codes. */ #define ILDIAG_SUCCESS 0 /* no problems */ #define ILDIAG_CHKSUMERR 1 /* ROM/RAM checksum error */ #define ILDIAG_DMAERR 2 /* DMA not working */ #define ILDIAG_XMITERR 3 /* xmit circuitry failure */ #define ILDIAG_RECVERR 4 /* rcvr circuitry failure */ #define ILDIAG_LOOPBACK 5 /* loopback test failed */ #define NILDIAGS 6 #ifdef ILDIAGS char *ildiag[NILDIAGS] = { "success", /* 0 */ "checksum error", /* 1 */ "NM10 dma error", /* 2 */ "transmitter error", /* 3 */ "receiver error", /* 4 */ "loopback failure", /* 5 */ }; #endif /* * Frame status bits, returned in frame status byte * at the top of each received packet. */ #define ILFSTAT_C 0x1 /* CRC error */ #define ILFSTAT_A 0x2 /* alignment error */ #define ILFSTAT_L 0x4 /* 1+ frames lost just before */ return(0); /* made it to end of memory */ return(EIO); } paddr += (DBSIZE << PGSHIFT); } return(0); /* filled disk minor dev */ } #endif XP_DUMP #endif NXPD e(bp); goto loop; } if (dp->b_errcnt >= 16 && (bp->b_flags & B_READ)) { xpaddr->hpof = xp_offset[dp->b_errcnt & 017] | HPOF_FMT22; xpaddr->hpcs1.sys/pdpif/if_qereg.h 444 0 12 12743 4236242555 7736 /* @(#)if_qereg.h 7.1 (Berkeley) 6/5/86 */ /* @(#)if_qereg.h 1.2 (ULTRIX) 1/3/85 */ /**************************************************************** * * * Licensed from Digital Equipment Corporation * * Copyright (c) * * Digital Equipment Corporation * * Maynard, Massachusetts * * 1985, 1986 * * All rights reserved. * * * * The Information in this software is subject to change * * without notice and should not be construed as a commitment * * by Digital Equipment Corporation. Digital makes no * * representations about the suitability of this software for * * any purpose. It is supplied "As Is" without expressed or * * implied warranty. * * * * If the Regents of the University of California or its * * licensees modify the software in a manner creating * * diriviative copyright rights, appropriate copyright * * legends may be placed on the drivative work in addition * * to that set forth above. * * * ****************************************************************/ /* --------------------------------------------------------------------- * Modification History * * 13 Feb. 84 -- rjl * * Initial version of driver. derived from IL driver. * * --------------------------------------------------------------------- */ /* * Digital Q-BUS to NI Adapter */ #ifdef pdp11 #define qe_rcvlist_lo qe_LOrcv #define qe_rcvlist_hi qe_HIrcv #define qe_xmtlist_lo qe_LOxmt #define qe_xmtlist_hi qe_HIxmt #define qe_status1 qe_stat1 #define qe_status2 qe_stat2 #define qe_odd_begin qe_begin_odd #define qe_odd_end qe_end_odd #define qe_addr_hi qe_HIaddr #define qe_addr_lo qe_LOaddr #endif pdp11 struct qedevice { u_short qe_sta_addr[2]; /* Station address (actually 6 */ u_short qe_rcvlist_lo; /* Receive list lo address */ u_short qe_rcvlist_hi; /* Receive list hi address */ u_short qe_xmtlist_lo; /* Transmit list lo address */ u_short qe_xmtlist_hi; /* Transmit list hi address */ u_short qe_vector; /* Interrupt vector */ u_short qe_csr; /* Command and Status Register */ }; /* * Command and status bits (csr) */ #define QE_RCV_ENABLE 0x0001 /* Receiver enable */ #define QE_RESET 0x0002 /* Software reset */ #define QE_NEX_MEM_INT 0x0004 /* Non existant mem interrupt */ #define QE_LOAD_ROM 0x0008 /* Load boot/diag from rom */ #define QE_XL_INVALID 0x0010 /* Transmit list invalid */ #define QE_RL_INVALID 0x0020 /* Receive list invalid */ #define QE_INT_ENABLE 0x0040 /* Interrupt enable */ #define QE_XMIT_INT 0x0080 /* Transmit interrupt */ #define QE_ILOOP 0x0100 /* Internal loopback */ #define QE_ELOOP 0x0200 /* External loopback */ #define QE_STIM_ENABLE 0x0400 /* Sanity timer enable */ #define QE_POWERUP 0x1000 /* Tranceiver power on */ #define QE_CARRIER 0x2000 /* Carrier detect */ #define QE_RCV_INT 0x8000 /* Receiver interrupt */ /* * Transmit and receive ring discriptor --------------------------- * * The QNA uses the flag, status1 and the valid bit as a handshake/semiphore * mechinism. * * The flag word is written on ( bits 15,15 set to 1 ) when it reads the * descriptor. If the valid bit is set it considers the address to be valid. * When it uses the buffer pointed to by the valid address it sets status word * one. */ struct qe_ring { u_short qe_flag; /* Buffer utilization flags */ u_short qe_addr_hi:6, /* Hi order bits of buffer addr */ qe_odd_begin:1, /* Odd byte begin and end (xmit)*/ qe_odd_end:1, qe_fill1:4, qe_setup:1, /* Setup packet */ qe_eomsg:1, /* End of message flag */ qe_chain:1, /* Chain address instead of buf */ qe_valid:1; /* Address field is valid */ u_short qe_addr_lo; /* Low order bits of address */ short qe_buf_len; /* Negative buffer length */ u_short qe_status1; /* Status word one */ u_short qe_status2; /* Status word two */ }; /* * Status word definations (receive) * word1 */ #define QE_OVF 0x0001 /* Receiver overflow */ #define QE_CRCERR 0x0002 /* CRC error */ #define QE_FRAME 0x0004 /* Framing alignment error */ #define QE_SHORT 0x0008 /* Packet size < 10 bytes */ #define QE_RBL_HI 0x0700 /* Hi bits of receive len */ #define QE_RUNT 0x0800 /* Runt packet */ #define QE_DISCARD 0x1000 /* Discard the packet */ #define QE_ESETUP 0x2000 /* Looped back setup or eloop */ #define QE_ERROR 0x4000 /* Receiver error */ #define QE_LASTNOT 0x8000 /* Not the last in the packet */ /* word2 */ #define QE_RBL_LO 0x00ff /* Low bits of receive len */ /* * Status word definations (transmit) * word1 */ #define QE_CCNT 0x00f0 /* Collision count this packet */ #define QE_FAIL 0x0100 /* Heart beat check failure */ #define QE_ABORT 0x0200 /* Transmission abort */ #define QE_STE16 0x0400 /* Sanity timer default on */ #define QE_NOCAR 0x0800 /* No carrier */ #define QE_LOSS 0x1000 /* Loss of carrier while xmit */ /* word2 */ #define QE_TDR 0x3fff /* Time domain reflectometry */ /* * General constant definations */ #define QEALLOC 0 /* Allocate an mbuf */ #define QENOALLOC 1 /* No mbuf allocation */ #define QEDEALLOC 2 /* Release an mbuf chain */ #define QEREALLOC 3 /* Reallocate an mbuf */ #define QE_NOTYET 0x8000 /* Descriptor not in use yet */ #define QE_INUSE 0x4000 /* Descriptor being used by QNA */ #define QE_MASK 0xc000 /* Lastnot/error/used mask */ er */ #ifdef pdp11 #definsys/pdpif/if_acc.c 444 0 12 22257 4617135673 7362 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_acc.c 1.1 (2.10BSD Berkeley) 12/1/86 */ #include "acc.h" #if NACC > 0 /* * ACC LH/DH ARPAnet IMP interface driver. * Define "PLI" if connected to a PLI, to take care of PLI ready-line problems */ #include "param.h" #include "../machine/seg.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "domain.h" #include "protosw.h" #include "socket.h" #include "../pdpuba/ubavar.h" #include "../net/if.h" #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netimp/if_imp.h" #include "if_acc.h" #include "if_uba.h" int accprobe(), accattach(), accrint(), accxint(); struct uba_device *accinfo[NACC]; u_short accstd[] = { 0 }; struct uba_driver accdriver = { accprobe, 0, accattach, 0, accstd, "acc", accinfo }; #define ACCUNIT(x) minor(x) int accinit(), accstart(), accreset(); /* * "Lower half" of IMP interface driver. * * Each IMP interface is handled by a common module which handles * the IMP-host protocol and a hardware driver which manages the * hardware specific details of talking with the IMP. * * The hardware portion of the IMP driver handles DMA and related * management of UNIBUS resources. The IMP protocol module interprets * contents of these messages and "controls" the actions of the * hardware module during IMP resets, but not, for instance, during * UNIBUS resets. * * The two modules are coupled at "attach time", and ever after, * through the imp interface structure. Higher level protocols, * e.g. IP, interact with the IMP driver, rather than the ACC. */ struct acc_softc { struct ifnet *acc_if; /* pointer to IMP's ifnet struct */ struct impcb *acc_ic; /* data structure shared with IMP */ struct ifuba acc_ifuba; /* UNIBUS resources */ struct mbuf *acc_iq; /* input reassembly queue */ short acc_olen; /* size of last message sent */ char acc_flush; /* flush remainder of message */ } acc_softc[NACC]; /* * Reset the IMP and cause a transmitter interrupt by * performing a null DMA. */ accprobe(reg) caddr_t reg; { #if !pdp11 register int br, cvec; /* r11, r10 value-result */ register struct accdevice *addr = (struct accdevice *)reg; #ifdef lint br = 0; cvec = br; br = cvec; accrint(0); accxint(0); #endif addr->icsr = ACC_RESET; DELAY(5000L); addr->ocsr = ACC_RESET; DELAY(5000L); addr->ocsr = OUT_BBACK; DELAY(5000L); addr->owc = 0; addr->ocsr = ACC_IE | ACC_GO; DELAY(5000L); addr->ocsr = 0; if (cvec && cvec != 0x200) /* transmit -> receive */ cvec -= 4; #ifdef ECHACK br = 0x16; #endif return (1); #endif !pdp11 } /* * Call the IMP module to allow it to set up its internal * state, then tie the two modules together by setting up * the back pointers to common data structures. */ accattach(ui) struct uba_device *ui; { register struct acc_softc *sc = &acc_softc[ui->ui_unit]; register struct impcb *ip; struct ifimpcb { struct ifnet ifimp_if; struct impcb ifimp_impcb; } *ifimp; if ((ifimp = (struct ifimpcb *)impattach(ui, accreset)) == 0) panic("accattach"); sc->acc_if = &ifimp->ifimp_if; ip = &ifimp->ifimp_impcb; sc->acc_ic = ip; ip->ic_init = accinit; ip->ic_start = accstart; sc->acc_ifuba.ifu_flags = UBA_CANTWAIT; #ifdef notdef sc->acc_ifuba.ifu_flags |= UBA_NEEDBDP; #endif } /* * Reset interface after UNIBUS reset. * If interface is on specified uba, reset its state. */ accreset(unit, uban) int unit, uban; { register struct uba_device *ui; struct acc_softc *sc; if (unit >= NACC || (ui = accinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" acc%d", unit); sc = &acc_softc[unit]; /* must go through IMP to allow it to set state */ (*sc->acc_if->if_init)(unit); } /* * Initialize interface: clear recorded pending operations, * and retrieve, and initialize UNIBUS resources. Note * return value is used by IMP init routine to mark IMP * unavailable for outgoing traffic. */ accinit(unit) int unit; { register struct acc_softc *sc; register struct uba_device *ui; register struct accdevice *addr; long info; int i; if (unit >= NACC || (ui = accinfo[unit]) == 0 || ui->ui_alive == 0) { printf("acc%d: not alive\n", unit); return (0); } sc = &acc_softc[unit]; /* * Header length is 0 since we have to passs * the IMP leader up to the protocol interpretation * routines. If we had the header length as * sizeof(struct imp_leader), then the if_ routines * would asssume we handle it on input and output. */ if (if_ubainit(&sc->acc_ifuba, ui->ui_ubanum, 0, (int)btoc(IMPMTU)) == 0) { printf("acc%d: can't initialize\n", unit); ui->ui_alive = 0; return (0); } addr = (struct accdevice *)ui->ui_addr; /* * Reset the imp interface; * the delays are pure guesswork. */ addr->ocsr = ACC_RESET; DELAY(5000L); addr->ocsr = OUT_BBACK; DELAY(5000L); /* reset host master ready */ addr->ocsr = 0; if (accinputreset(addr, unit) == 0) { ui->ui_alive = 0; return (0); } /* * Put up a read. We can't restart any outstanding writes * until we're back in synch with the IMP (i.e. we've flushed * the NOOPs it throws at us). * Note: IMPMTU includes the leader. */ info = sc->acc_ifuba.ifu_r.ifrw_info; addr->iba = (u_short)info; addr->iwc = -(IMPMTU >> 1); #ifdef LOOPBACK addr->ocsr |= OUT_BBACK; #endif addr->icsr = IN_MRDY | ACC_IE | IN_WEN | ((info & 0x30000) >> 12) | ACC_GO; return (1); } accinputreset(addr, unit) register struct accdevice *addr; register int unit; { register int i; addr->icsr = ACC_RESET; DELAY(5000L); addr->icsr = IN_MRDY | IN_WEN; /* close the relay */ DELAY(10000L); /* YECH!!! */ for (i = 0; i < 500; i++) { if ((addr->icsr & IN_HRDY) || (addr->icsr & (IN_RMR | IN_IMPBSY)) == 0) return (1); addr->icsr = IN_MRDY | IN_WEN; DELAY(10000L); /* keep turning IN_RMR off */ } printf("acc%d: imp doesn't respond, icsr=%b\n", unit, addr->icsr, ACC_INBITS); return (0); } /* * Start output on an interface. */ accstart(dev) dev_t dev; { int unit = ACCUNIT(dev); long info; register struct acc_softc *sc = &acc_softc[unit]; register struct accdevice *addr; struct mbuf *m; u_short cmd; if (sc->acc_ic->ic_oactive) goto restart; /* * Not already active, deqeue a request and * map it onto the UNIBUS. If no more * requeusts, just return. */ IF_DEQUEUE(&sc->acc_if->if_snd, m); if (m == 0) { sc->acc_ic->ic_oactive = 0; return; } sc->acc_olen = if_wubaput(&sc->acc_ifuba, m); restart: /* * Have request mapped to UNIBUS for * transmission; start the output. */ addr = (struct accdevice *)accinfo[unit]->ui_addr; info = sc->acc_ifuba.ifu_w.ifrw_info; addr->oba = (u_short)info; addr->owc = -((sc->acc_olen + 1) >> 1); cmd = ACC_IE | OUT_ENLB | ((info & 0x30000) >> 12) | ACC_GO; #ifdef LOOPBACK cmd |= OUT_BBACK; #endif addr->ocsr = cmd; sc->acc_ic->ic_oactive = 1; } /* * Output interrupt handler. */ accxint(unit) { register struct acc_softc *sc = &acc_softc[unit]; register struct accdevice *addr; addr = (struct accdevice *)accinfo[unit]->ui_addr; if (sc->acc_ic->ic_oactive == 0) { printf("acc%d: stray xmit interrupt, csr=%b\n", unit, addr->ocsr, ACC_OUTBITS); goto out; } sc->acc_if->if_opackets++; sc->acc_ic->ic_oactive = 0; if (addr->ocsr & ACC_ERR) { printf("acc%d: output error, ocsr=%b, icsr=%b\n", unit, addr->ocsr, ACC_OUTBITS, addr->icsr, ACC_INBITS); sc->acc_if->if_oerrors++; } if (sc->acc_ifuba.ifu_xtofree) { m_freem(sc->acc_ifuba.ifu_xtofree); sc->acc_ifuba.ifu_xtofree = 0; } if (sc->acc_if->if_snd.ifq_head) accstart(unit); out: } /* * Input interrupt handler */ accrint(unit) { register struct acc_softc *sc = &acc_softc[unit]; register struct accdevice *addr; struct mbuf *m; int len; long info; addr = (struct accdevice *)accinfo[unit]->ui_addr; sc->acc_if->if_ipackets++; #ifndef PLI if (addr->icsr & ACC_ERR) { #else if (addr->icsr & (ACC_ERR|IN_RMR)) { #endif PLI printf("acc%d: input error, csr=%b\n", unit, addr->icsr, ACC_INBITS); sc->acc_if->if_ierrors++; sc->acc_flush = 1; if(addr->icsr & IN_IMPBSY #ifdef PLI || ((addr->icsr&IN_RMR) && (addr->icsr&IN_HRDY)) #endif PLI ){ /* IMP ready line dropped */ impinput(unit, (struct mbuf *)0); goto out; /* Do NOT re-enable interrupts!!! */ } } if (sc->acc_flush) { if (addr->icsr & IN_EOM) sc->acc_flush = 0; goto setup; } len = IMPMTU + (addr->iwc << 1); if (len < 0 || len > IMPMTU) { printf("acc%d: bad length=%d\n", len); sc->acc_if->if_ierrors++; goto setup; } /* * The next to last parameter is always 0 since using * trailers on the ARPAnet is insane. */ m = if_rubaget(&sc->acc_ifuba, len, 0, &sc->acc_if); if (m == 0) goto setup; if ((addr->icsr & IN_EOM) == 0) { if (sc->acc_iq) m_cat(sc->acc_iq, m); else sc->acc_iq = m; goto setup; } if (sc->acc_iq) { m_cat(sc->acc_iq, m); m = sc->acc_iq; sc->acc_iq = 0; } impinput(unit, m); setup: /* * Setup for next message. */ info = sc->acc_ifuba.ifu_r.ifrw_info; addr->iba = (u_short)info; addr->iwc = -(IMPMTU >> 1); addr->icsr = IN_MRDY | ACC_IE | IN_WEN | ((info & 0x30000) >> 12) | ACC_GO; out: } #endif s the * hardware specific details of talking with the IMP. * * The hardware portion of the IMP driver handles DMA and related * management of UNIBUS resources. The IMP protocol module interprets * contents of these messages and "controls" the actions of the * hardware module during IMP resets, but not, for instance, during * UNsys/pdpif/if_css.c 444 0 12 22773 4617135650 7422 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_css.c 1.1 (2.10BSD Berkeley) 12/1/86 */ #include "css.h" #if NCSS > 0 /* * DEC/CSS IMP11-A ARPAnet IMP interface driver. * Since "imp11a" is such a mouthful, it is called * "css" after the LH/DH being called "acc". * * Configuration notes: * * As delivered from DEC/CSS, it * is addressed and vectored as two DR11-B's. This makes * Autoconfig almost IMPOSSIBLE. To make it work, the * interrupt vectors must be restrapped to make the vectors * consecutive. The 020 hole between the CSR addresses is * tolerated, althought that could be cleaned-up also. * * Additionally, the TRANSMIT side of the IMP11-A has the * lower address of the two subunits, so the vector ordering * in the CONFIG file is reversed from most other devices. * It should be: * * device css0 .... cssxint cssrint * * If you get it wrong, it will still autoconfig, but will just * sit there with RECIEVE IDLE indicated on the front panel. */ #include "param.h" #include "../machine/seg.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "domain.h" #include "protosw.h" #include "socket.h" #include "pdpuba/ubavar.h" #include "../net/if.h" #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netimp/if_imp.h" #include "if_css.h" #include "if_uba.h" int cssprobe(), cssattach(), cssrint(), cssxint(); int cssinit(), cssstart(), cssreset(); struct uba_device *cssinfo[NCSS]; u_short cssstd[] = { 0 }; struct uba_driver cssdriver = { cssprobe, 0, cssattach, 0, cssstd, "css", cssinfo }; #define CSSUNIT(x) minor(x) /* * "Lower half" of IMP interface driver. * * Each IMP interface is handled by a common module which handles * the IMP-host protocol and a hardware driver which manages the * hardware specific details of talking with the IMP. * * The hardware portion of the IMP driver handles DMA and related * management of UNIBUS resources. The IMP protocol module interprets * contents of these messages and "controls" the actions of the * hardware module during IMP resets, but not, for instance, during * UNIBUS resets. * * The two modules are coupled at "attach time", and ever after, * through the imp interface structure. Higher level protocols, * e.g. IP, interact with the IMP driver, rather than the CSS. */ struct css_softc { struct ifnet *css_if; /* pointer to IMP's ifnet struct */ struct impcb *css_ic; /* data structure shared with IMP */ struct ifuba css_ifuba; /* UNIBUS resources */ struct mbuf *css_iq; /* input reassembly queue */ short css_olen; /* size of last message sent */ char css_flush; /* flush remainder of message */ } css_softc[NCSS]; /* * Reset the IMP and cause a transmitter interrupt by * performing a null DMA. */ cssprobe(reg) caddr_t reg; { #if !pdp11 register int br, cvec; /* r11, r10 value-result */ register struct cssdevice *addr = (struct cssdevice *)reg; #ifdef lint br = 0; cvec = br; br = cvec; cssrint(0); cssxint(0); #endif addr->css_icsr = CSS_CLR; addr->css_ocsr = CSS_CLR; DELAY(50000L); addr->css_icsr = 0; addr->css_ocsr = 0; DELAY(50000L); addr->css_oba = 0; addr->css_owc = -1; addr->css_ocsr = CSS_IE | CSS_GO; /* enable interrupts */ DELAY(50000L); addr->css_ocsr = 0; return (1); #endif !pdp11 } /* * Call the IMP module to allow it to set up its internal * state, then tie the two modules together by setting up * the back pointers to common data structures. */ cssattach(ui) struct uba_device *ui; { register struct css_softc *sc = &css_softc[ui->ui_unit]; register struct impcb *ip; struct ifimpcb { struct ifnet ifimp_if; struct impcb ifimp_impcb; } *ifimp; if ((ifimp = (struct ifimpcb *)impattach(ui, cssreset)) == 0) panic("cssattach"); /* XXX */ sc->css_if = &ifimp->ifimp_if; ip = &ifimp->ifimp_impcb; sc->css_ic = ip; ip->ic_init = cssinit; ip->ic_start = cssstart; sc->css_ifuba.ifu_flags = UBA_CANTWAIT | UBA_NEED16; #ifdef notdef sc->css_ifuba.ifu_flags |= UBA_NEEDBDP; #endif } /* * Reset interface after UNIBUS reset. * If interface is on specified uba, reset its state. */ cssreset(unit, uban) int unit, uban; { register struct uba_device *ui; struct css_softc *sc; if (unit >= NCSS || (ui = cssinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" css%d", unit); sc = &css_softc[unit]; /* must go through IMP to allow it to set state */ (*sc->css_if->if_init)(unit); } /* * Initialize interface: clear recorded pending operations, * and retrieve, and reinitialize UNIBUS resources. */ cssinit(unit) int unit; { register struct css_softc *sc; register struct uba_device *ui; register struct cssdevice *addr; int x; long info; if (unit >= NCSS || (ui = cssinfo[unit]) == 0 || ui->ui_alive == 0) { printf("css%d: not alive\n", unit); return(0); } sc = &css_softc[unit]; /* * Header length is 0 to if_ubainit since we have to pass * the IMP leader up to the protocol interpretaion * routines. If we had the deader length as * sizeof(struct imp_leader), then the if_ routines * would assume we handle it on input and output. */ if (if_ubainit(&sc->css_ifuba, ui->ui_ubanum, 0,(int)btoc(IMPMTU)) == 0) { printf("css%d: can't initialize\n", unit); ui->ui_alive = 0; return(0); } addr = (struct cssdevice *)ui->ui_addr; /* reset the imp interface. */ x = splimp(); addr->css_icsr = CSS_CLR; addr->css_ocsr = CSS_CLR; DELAY(100L); addr->css_icsr = 0; addr->css_ocsr = 0; addr->css_icsr = IN_HRDY; /* close the relay */ DELAY(5000L); splx(x); /* * This may hang if the imp isn't really there. * Will test and verify safe operation. */ x = 5; while (x-- > 0) { if ((addr->css_icsr & (IN_HRDY|IN_IMPNR)) == IN_HRDY) break; addr->css_icsr = IN_HRDY; /* close the relay */ DELAY(5000L); } if (x <= 0) { /* printf("css%d: imp doesn't respond, icsr=%b\n", unit, CSS_INBITS, addr->css_icsr); */ goto down; } /* * Put up a read. We can't restart any outstanding writes * until we're back in synch with the IMP (i.e. we've flushed * the NOOPs it throws at us). * Note: IMPMTU includes the leader. */ x = splimp(); info = sc->css_ifuba.ifu_r.ifrw_info; addr->css_iba = (u_short)info; addr->css_iwc = -(IMPMTU >> 1); addr->css_icsr = IN_HRDY | CSS_IE | IN_WEN | ((info & 0x30000) >> 12) | CSS_GO; splx(x); return(1); down: ui->ui_alive = 0; return(0); } /* * Start output on an interface. */ cssstart(dev) dev_t dev; { int unit = CSSUNIT(dev); long info; struct uba_device *ui = cssinfo[unit]; register struct css_softc *sc = &css_softc[unit]; register struct cssdevice *addr; struct mbuf *m; u_short cmd; if (sc->css_ic->ic_oactive) goto restart; /* * Not already active, deqeue a request and * map it onto the UNIBUS. If no more * requeusts, just return. */ IF_DEQUEUE(&sc->css_if->if_snd, m); if (m == 0) { sc->css_ic->ic_oactive = 0; return; } sc->css_olen = if_wubaput(&sc->css_ifuba, m); restart: addr = (struct cssdevice *)ui->ui_addr; info = sc->css_ifuba.ifu_w.ifrw_info; addr->css_oba = (u_short)info; addr->css_owc = -((sc->css_olen + 1) >> 1); cmd = CSS_IE | OUT_ENLB | ((info & 0x30000) >> 12) | CSS_GO; addr->css_ocsr = cmd; sc->css_ic->ic_oactive = 1; } /* * Output interrupt handler. */ cssxint(unit) { register struct uba_device *ui = cssinfo[unit]; register struct css_softc *sc = &css_softc[unit]; register struct cssdevice *addr; addr = (struct cssdevice *)ui->ui_addr; if (sc->css_ic->ic_oactive == 0) { printf("css%d: stray output interrupt csr=%b\n", unit, addr->css_ocsr, CSS_OUTBITS); goto out; } sc->css_if->if_opackets++; sc->css_ic->ic_oactive = 0; if (addr->css_ocsr & CSS_ERR){ sc->css_if->if_oerrors++; printf("css%d: output error, ocsr=%b icsr=%b\n", unit, addr->css_ocsr, CSS_OUTBITS, addr->css_icsr, CSS_INBITS); } if (sc->css_ifuba.ifu_xtofree) { m_freem(sc->css_ifuba.ifu_xtofree); sc->css_ifuba.ifu_xtofree = 0; } if (sc->css_if->if_snd.ifq_head) cssstart(unit); out: } /* * Input interrupt handler */ cssrint(unit) { register struct css_softc *sc = &css_softc[unit]; register struct cssdevice *addr; register struct ifqueue *inq; struct mbuf *m; int len; long info; sc->css_if->if_ipackets++; addr = (struct cssdevice *)cssinfo[unit]->ui_addr; if (addr->css_icsr & CSS_ERR) { printf("css%d: recv error, csr=%b\n", unit, addr->css_icsr, CSS_INBITS); sc->css_if->if_ierrors++; sc->css_flush = 1; if (addr->css_icsr & IN_IMPNR) { impinput(unit,(struct mbuf *)0); goto out; } } if (sc->css_flush) { if (addr->css_icsr & IN_EOM) sc->css_flush = 0; goto setup; } len = IMPMTU + (addr->css_iwc << 1); if (len < 0 || len > IMPMTU) { printf("css%d: bad length=%d\n", len); sc->css_if->if_ierrors++; goto setup; } /* * The next to last parameter is always 0 since using * trailers on the ARPAnet is insane. */ m = if_rubaget(&sc->css_ifuba, len, 0, &sc->css_if); if (m == 0) goto setup; if ((addr->css_icsr & IN_EOM) == 0) { if (sc->css_iq) m_cat(sc->css_iq, m); else sc->css_iq = m; goto setup; } if (sc->css_iq) { m_cat(sc->css_iq, m); m = sc->css_iq; sc->css_iq = 0; } impinput(unit, m); setup: /* * Setup for next message. */ info = sc->css_ifuba.ifu_r.ifrw_info; addr->css_iba = (u_short)info; addr->css_iwc = - (IMPMTU >> 1); addr->css_icsr = IN_HRDY | CSS_IE | IN_WEN | ((info & 0x30000) >> 12) | CSS_GO; out: } #endif NCSS cssxisys/pdpif/if_de.c 444 0 12 107334 5511210351 7221 /* * SCCSID: @(#)if_de.c 1.1 (2.11BSD GTE) 12/31/93 * 2.11BSD - Remove dereset since 1) it was never called, and 2) * wouldn't work if it were called. Also uballoc and * ubmalloc calling convention changed. - sms */ #include "de.h" #if NDE > 0 /* * DEC DEUNA interface * * Lou Salkind * New York University * * TODO: * timeout routine (get statistics) */ #include "param.h" #include "../machine/seg.h" #include "systm.h" #include "mbuf.h" #include "domain.h" #include "protosw.h" #include "ioctl.h" #include "errno.h" #include "time.h" /* * Define DE_DO_BCTRS to get the DEUNA/DELUA to add code to allow * ioctl() for clearing/getting I/O stats from the board. #define DE_DO_BCTRS */ /* * Define DE_DO_PHYSADDR to get the DEUNA/DELUA to add code to allow * ioctl() for setting/getting physical hardware address. #define DE_DO_PHYSADDR */ /* * Define DE_DO_MULTI to get the DEUNA/DELUA to handle multi-cast addresses #define DE_DO_MULTI */ /* * Define DE_INT_LOOPBACK to get the DEUNA/DELUA internal loopback code turned on #define DE_INT_LOOPBACK */ /* * Define DE_DEBUG to get the DEUNA/DELUA debug code turned on #define DE_DEBUG */ #include "../pdpif/if_de.h" #ifndef YES #define YES 1 #else /* YES */ #undef YES #define YES 1 #endif /* YES */ #ifndef NO #define NO 0 #else /* NO */ #undef NO #define NO 0 #endif /* NO */ #define MAPBUFDESC (((btoc(ETHERMTU+sizeof(struct ether_header)) - 1) << 8 ) | RW) #define CRC_LEN 4 /* Length of CRC added to packet by board */ struct de_softc de_softc[NDE]; #ifdef DE_DEBUG /* * Setting dedebug turns on the level of debugging, iff DE_DEBUG * was defined at compile time. The current levels are: * 1 - added informative messages and error messages * 2 - more added messages * 3 - still more messages, like one for every loop packet seen, etc. */ #define DE_DEBUG_LEVEL 1 int dedebug = DE_DEBUG_LEVEL; #endif /* DE_DEBUG */ #ifdef DE_DO_MULTI u_char unused_multi[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; #endif /* DE_DO_MULTI */ #ifdef not_on_pdp extern struct protosw *iftype_to_proto(), *iffamily_to_proto(); #endif /* not_on_pdp */ int deprobe(), deattach(), deintr(), deinit(), deoutput(), deioctl(); struct mbuf *deget(); u_short destd[] = { 0174510 }; struct uba_device *deinfo[NDE]; struct uba_driver dedriver = { deprobe, 0, deattach, 0, destd, "de", deinfo }; #ifdef DE_INT_LOOPBACK #define DELUA_LOOP_LEN (32 - sizeof(struct ether_header)) #endif /* DE_INT_LOOPBACK */ #ifdef DE_DO_BCTRS extern struct timeval time; struct timeval atv; #endif /* DE_DO_BCTRS */ deprobe(reg) caddr_t reg; { #ifdef not_on_pdp register int br, cvec; /* r11, r10 value-result */ register struct dedevice *addr = (struct dedevice *)reg; register i; #ifdef lint br = 0; cvec = br; br = cvec; i = 0; derint(i); deintr(i); #endif /* lint */ /* * Make sure self-test is finished * Self-test on a DELUA can take 15 seconds. */ for (i = 0; i < 160 && (addr->pcsr0 & PCSR0_FATI) == 0 && (addr->pcsr1 & PCSR1_STMASK) == STAT_RESET; ++i) DELAY(100000); if ((addr->pcsr0 & PCSR0_FATI) != 0 || (addr->pcsr1 & PCSR1_STMASK) != STAT_READY) return(0); addr->pcsr0 = 0; addr->pcsr0 = PCSR0_RSET; /* * just in case this is not a deuna or delua * dont wait for more than 30 secs */ for (i = 0; i < 300 && (addr->pcsr0 & PCSR0_INTR) == 0; i++) DELAY(100000); if ((addr->pcsr0 & PCSR0_INTR) == 0) return(0); /* make board interrupt by executing a GETPCBB command */ addr->pcsr0 = PCSR0_INTE; addr->pcsr2 = 0; addr->pcsr3 = 0; addr->pcsr0 = PCSR0_INTE|CMD_GETPCBB; DELAY(100000); #endif /* not_on_pdp */ return(1); } /* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. We get the ethernet address here. */ deattach(ui) struct uba_device *ui; { register struct de_softc *ds = &de_softc[ui->ui_unit]; register struct ifnet *ifp = &ds->ds_if; register struct dedevice *addr = (struct dedevice *)ui->ui_addr; int i; u_short csr1; /* * Is it a DEUNA or a DELULA? Save the device id. */ csr1 = addr->pcsr1; ds->ds_devid = (csr1 & PCSR1_DEVID) >> 4; #ifdef DE_DEBUG if (dedebug >= 1) printf("de%d: Device Type: %s\n", ui->ui_unit, (ds->ds_devid == DEUNA) ? "DEUNA" : "DELUA"); #endif /* DE_DEBUG */ /* * Board Status Check */ if (csr1 & 0xff80) { if (ds->ds_devid == DEUNA) printf("de%d: hardware error, pcsr1=%b\n", ui->ui_unit, csr1, PCSR1_BITS); else printf("de%d: hardware error, pcsr1=%b\n", ui->ui_unit, csr1, PCSR1_BITS_DELUA); } ifp->if_unit = ui->ui_unit; ifp->if_name = "de"; ifp->if_mtu = ETHERMTU; ifp->if_flags |= IFF_BROADCAST; #ifdef DE_DEBUG ifp->if_flags |= IFF_DEBUG; printf("de%d: DEBUG enabled level=%d\n",ifp->if_unit,dedebug); #endif /* DE_DEBUG */ #ifdef DE_DO_MULTI /* * Fill the multicast address table with unused entries (broadcast * address) so that we can always give the full table to the device * and we don't have to worry about gaps. */ for (i=0; i < NMULTI; i++) bcopy(unused_multi,(u_char *)&ds->ds_multicast[i],MULTISIZE); #endif /* DE_DO_MULTI */ /* * Reset the board and map the pcbb buffer onto the Unibus. */ addr->pcsr0 = PCSR0_RSET; (void) dewait(ui, "board reset", YES, NO); ds->ds_ubaddr = uballoc(INCORE_BASE(ds), INCORE_SIZE); addr->pcsr2 = ds->ds_ubaddr & 0xffff; addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3; addr->pclow = CMD_GETPCBB; (void) dewait(ui, "get pcbb", YES, NO); ds->ds_pcbb.pcbb0 = FC_RDPHYAD; addr->pclow = CMD_GETCMD; (void) dewait(ui, "read addr", YES, NO); bcopy((caddr_t)&ds->ds_pcbb.pcbb2,(caddr_t)ds->ds_addr, sizeof (ds->ds_addr)); #ifdef DE_DEBUG if (dedebug >= 1) printf("de%d: hardware address %s\n", ui->ui_unit, ether_sprintf(ds->ds_addr)); #endif /* DE_DEBUG */ ifp->if_init = deinit; ifp->if_output = deoutput; ifp->if_ioctl = deioctl; ifp->if_reset = 0; ds->ds_deuba.difu_flags = UBA_CANTWAIT; if_attach(ifp); } /* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */ deinit(unit) int unit; { register struct de_softc *ds = &de_softc[unit]; register struct uba_device *ui = deinfo[unit]; register struct dedevice *addr; register struct ifrw *ifrw; struct ifnet *ifp = &ds->ds_if; int s; struct de_ring *rp; ubadr_t incaddr; /* not yet, if address still unknown */ /* DECnet must set this somewhere to make device happy */ if (ifp->if_addrlist == (struct ifaddr *)0) return; if (ds->ds_flags & DSF_RUNNING) return; if ((ifp->if_flags & IFF_RUNNING) == 0) { /* First time */ /* * Only allocate the resources ONCE. * ~IFF_RUNNING && ~DSF_RUNNING */ if (de_ubainit(&ds->ds_deuba, ui->ui_ubanum, sizeof (struct ether_header), (int) btoc(ETHERMTU)) == 0) { printf("de%d: can't initialize\n", unit); ds->ds_if.if_flags &= ~IFF_UP; return; } } addr = (struct dedevice *)ui->ui_addr; /* * Set up the PCBB - this is done in deattach() also, but * has to be redone here in case the board is reset (PCSR0_RSET) * and this routine is called. Note that ds->ds_ubaddr is set * in deattach() and all we do here is tell the * DEUNA/DELUA where it can find its PCBB. */ addr->pcsr2 = ds->ds_ubaddr & 0xffff; addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3; addr->pclow = CMD_GETPCBB; (void) dewait(ui, "get pcbb", YES, NO); /* * Set the transmit and receive ring header addresses */ incaddr = ds->ds_ubaddr + UDBBUF_OFFSET; ds->ds_pcbb.pcbb0 = FC_WTRING; ds->ds_pcbb.pcbb2 = incaddr & 0xffff; ds->ds_pcbb.pcbb4 = (incaddr >> 16) & 0x3; incaddr = ds->ds_ubaddr + XRENT_OFFSET; ds->ds_udbbuf.b_tdrbl = incaddr & 0xffff; ds->ds_udbbuf.b_tdrbh = (incaddr >> 16) & 0x3; ds->ds_udbbuf.b_telen = sizeof (struct de_ring) / sizeof (short); ds->ds_udbbuf.b_trlen = NXMT; incaddr = ds->ds_ubaddr + RRENT_OFFSET; ds->ds_udbbuf.b_rdrbl = incaddr & 0xffff; ds->ds_udbbuf.b_rdrbh = (incaddr >> 16) & 0x3; ds->ds_udbbuf.b_relen = sizeof (struct de_ring) / sizeof (short); ds->ds_udbbuf.b_rrlen = NRCV; addr->pclow = CMD_GETCMD; (void) dewait(ui, "wtring", NO, NO); /* * Initialize the board's mode */ ds->ds_pcbb.pcbb0 = FC_WTMODE; /* * Let hardware do padding & set MTCH bit on broadcast */ ds->ds_pcbb.pcbb2 = MOD_TPAD|MOD_HDX; addr->pclow = CMD_GETCMD; (void) dewait(ui, "wtmode", NO, NO); /* * Set up the receive and transmit ring entries */ ifrw = &ds->ds_deuba.difu_w[0]; for (rp = &ds->ds_xrent[0]; rp < &ds->ds_xrent[NXMT]; rp++) { rp->r_segbl = ifrw->ifrw_info & 0xffff; rp->r_segbh = (ifrw->ifrw_info >> 16) & 0x3; rp->r_flags = 0; ifrw++; } ifrw = &ds->ds_deuba.difu_r[0]; for (rp = &ds->ds_rrent[0]; rp < &ds->ds_rrent[NRCV]; rp++) { rp->r_slen = sizeof (struct de_buf); rp->r_segbl = ifrw->ifrw_info & 0xffff; rp->r_segbh = (ifrw->ifrw_info >> 16) & 0x3; rp->r_flags = RFLG_OWN; /* hang receive */ ifrw++; } /* * Start up the board (rah rah) */ s = splimp(); ds->ds_nxmit = ds->ds_rindex = ds->ds_xindex = ds->ds_xfree = 0; ds->ds_if.if_flags |= IFF_RUNNING; destart(unit); /* queue output packets */ addr->pclow = PCSR0_INTE; /* avoid interlock */ ds->ds_flags |= DSF_RUNNING; #ifdef NS if (ds->ds_flags & DSF_SETADDR) de_setaddr(ds->ds_addr, unit); #endif /* NS */ addr->pclow = CMD_START | PCSR0_INTE; splx(s); #ifdef DE_DO_BCTRS cpfromkern(&time, &atv, sizeof(struct timeval)); ds->ds_ztime = atv.tv_sec; #endif /* DE_DO_BCTRS */ } /* * Setup output on interface. * Get another datagram to send off of the interface queue, * and map it to the interface before starting the output. */ static destart(unit) int unit; { int len; register struct uba_device *ui = deinfo[unit]; struct dedevice *addr = (struct dedevice *)ui->ui_addr; register struct de_softc *ds = &de_softc[unit]; register struct de_ring *rp; struct mbuf *m; register int nxmit; if (ds->ds_flags & DSF_LOCK) return; for (nxmit = ds->ds_nxmit; nxmit < NXMT; nxmit++) { IF_DEQUEUE(&ds->ds_if.if_snd, m); if (m == 0) break; rp = &ds->ds_xrent[ds->ds_xfree]; if (rp->r_flags & XFLG_OWN) panic("deuna xmit in progress"); len = deput(&ds->ds_deuba, ds->ds_xfree, m); rp->r_slen = len; rp->r_tdrerr = 0; rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN; ds->ds_xfree++; if (ds->ds_xfree == NXMT) ds->ds_xfree = 0; } if (ds->ds_nxmit != nxmit) { ds->ds_nxmit = nxmit; if (ds->ds_flags & DSF_RUNNING) addr->pclow = PCSR0_INTE|CMD_PDMD; } else if (ds->ds_nxmit == NXMT) { /* * poke device if we have something to send and * transmit ring is full. */ #ifdef DE_DEBUG if (dedebug >= 1) { rp = &ds->ds_xrent[0]; printf("de%d: did not transmit: %d, %d, %d, flag0=%x, flag1=%x\n", unit, ds->ds_xindex, ds->ds_nxmit, ds->ds_xfree, rp->r_flags, (rp+1)->r_flags); } #endif /* DE_DEBUG */ if (ds->ds_flags & DSF_RUNNING) addr->pclow = PCSR0_INTE|CMD_PDMD; } } /* * Command done interrupt. */ deintr(unit) int unit; { struct uba_device *ui = deinfo[unit]; register struct dedevice *addr = (struct dedevice *)ui->ui_addr; register struct de_softc *ds = &de_softc[unit]; register struct de_ring *rp; register struct ifrw *ifrw; short csr0; /* save flags right away - clear out interrupt bits */ csr0 = addr->pcsr0; addr->pchigh = csr0 >> 8; if (csr0 & PCSR0_FATI) { if (ds->ds_devid == DEUNA) printf( "de%d: unsolicited state change, csr0=%b, csr1=%b\n", unit, csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS); else printf( "de%d: unsolicited state change, csr0=%b, csr1=%b\n", unit, csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS_DELUA); } if (csr0 & PCSR0_SERI) { if (ds->ds_devid == DEUNA) printf("de%d: status error, csr0=%b, csr1=%b\n", unit, csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS); else printf("de%d: status error, csr0=%b, csr1=%b\n", unit, csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS_DELUA); } ds->ds_flags |= DSF_LOCK; /* * if receive, put receive buffer on mbuf * and hang the request again */ rp = &ds->ds_rrent[ds->ds_rindex]; if ((rp->r_flags & RFLG_OWN) == 0) derecv(unit); /* * Poll transmit ring and check status. * Be careful about loopback requests. * Then free buffer space and check for * more transmit requests. */ for ( ; ds->ds_nxmit > 0; ds->ds_nxmit--) { rp = &ds->ds_xrent[ds->ds_xindex]; if (rp->r_flags & XFLG_OWN) break; ds->ds_if.if_opackets++; ifrw = &ds->ds_deuba.difu_w[ds->ds_xindex]; /* check for unusual conditions */ if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) { if (rp->r_flags & XFLG_ERRS) { /* output error */ ds->ds_if.if_oerrors++; #ifdef DE_DEBUG if (dedebug >= 1) printf("de%d: oerror, flags=%b tdrerr=%b (len=%d)\n", unit, rp->r_flags, XFLG_BITS, rp->r_tdrerr, XERR_BITS, rp->r_slen); #endif /* DE_DEBUG */ } else { if (rp->r_flags & XFLG_ONE) { /* one collision */ ds->ds_if.if_collisions++; } else if (rp->r_flags & XFLG_MORE) { /* more than one collision */ ds->ds_if.if_collisions += 2; /*guess*/ } if ((rp->r_flags & XFLG_MTCH) && !(ds->ds_if.if_flags & IFF_LOOPBACK)) { /* received our own packet */ ds->ds_if.if_ipackets++; #ifdef DE_DEBUG if (dedebug >= 3) printf("de%d: loopback packet\n", unit); #endif /* DE_DEBUG */ deread(ds, ifrw, rp->r_slen - sizeof (struct ether_header)); } } } /* check if next transmit buffer also finished */ ds->ds_xindex++; if (ds->ds_xindex >= NXMT) ds->ds_xindex = 0; } ds->ds_flags &= ~DSF_LOCK; destart(unit); if (csr0 & PCSR0_RCBI) { ds->ds_if.if_ierrors++; #ifdef DE_DEBUG if (dedebug >= 1) printf("de%d: buffer unavailable\n", ui->ui_unit); #endif /* DE_DEBUG */ addr->pclow = PCSR0_INTE|CMD_PDMD; } } /* * Ethernet interface receiver interface. * If input error just drop packet. * Otherwise purge input buffered data path and examine * packet to determine type. If can't determine length * from type, then have to drop packet. Othewise decapsulate * packet based on type and pass to type specific higher-level * input routine. */ static derecv(unit) int unit; { register struct de_softc *ds = &de_softc[unit]; register struct de_ring *rp; register int len; struct ether_header *eh; rp = &ds->ds_rrent[ds->ds_rindex]; while ((rp->r_flags & RFLG_OWN) == 0) { ds->ds_if.if_ipackets++; len = (rp->r_lenerr&RERR_MLEN) - sizeof (struct ether_header) - CRC_LEN; /* don't forget checksum! */ if( ! (ds->ds_if.if_flags & IFF_LOOPBACK) ) { /* check for errors */ if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) || (rp->r_flags&(RFLG_STP|RFLG_ENP)) != (RFLG_STP|RFLG_ENP) || (rp->r_lenerr & (RERR_BUFL|RERR_UBTO|RERR_NCHN)) || len < ETHERMIN || len > ETHERMTU) { ds->ds_if.if_ierrors++; #ifdef DE_DEBUG if (dedebug >= 1) printf("de%d: ierror, flags=%b lenerr=%b (len=%d)\n", unit, rp->r_flags, RFLG_BITS, rp->r_lenerr, RERR_BITS, len); #endif /* DE_DEBUG */ } else deread(ds, &ds->ds_deuba.difu_r[ds->ds_rindex], len); } else { int ret; segm sav5; saveseg5(sav5); mapseg5(ds->ds_deuba.difu_r[ds->ds_rindex].ifrw_click, MAPBUFDESC); eh = (struct ether_header *) SEG5; ret = bcmp(eh->ether_dhost, ds->ds_addr, 6); restorseg5(sav5); if (ret == NULL) deread(ds, &ds->ds_deuba.difu_r[ds->ds_rindex], len); } /* hang the receive buffer again */ rp->r_lenerr = 0; rp->r_flags = RFLG_OWN; /* check next receive buffer */ ds->ds_rindex++; if (ds->ds_rindex >= NRCV) ds->ds_rindex = 0; rp = &ds->ds_rrent[ds->ds_rindex]; } } /* * Pass a packet to the higher levels. * We deal with the trailer protocol here. */ static deread(ds, ifrw, len) register struct de_softc *ds; struct ifrw *ifrw; int len; { struct ether_header *eh; struct mbuf *m; struct protosw *pr; int off, resid, s; struct ifqueue *inq; segm sav5; int type; /* * Deal with trailer protocol: if type is trailer * get true type from first 16-bit word past data. * Remember that type was trailer by setting off. */ saveseg5(sav5); mapseg5(ifrw->ifrw_click, MAPBUFDESC); eh = (struct ether_header *) SEG5; type = eh->ether_type = ntohs((u_short)eh->ether_type); #define dedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off)))) if (type >= ETHERTYPE_TRAIL && type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { off = (type - ETHERTYPE_TRAIL) * 512; if (off >= ETHERMTU) { restorseg5(sav5); return; /* sanity */ } type = ntohs(*dedataaddr(eh, off, u_short *)); resid = ntohs(*(dedataaddr(eh, off+2, u_short *))); if (off + resid > len) { restorseg5(sav5); return; /* sanity */ } len = off + resid; } else off = 0; if (len == 0) { restorseg5(sav5); return; } restorseg5(sav5); /* * Pull packet off interface. Off is nonzero if packet * has trailing header; deget will then force this header * information to be at the front, but we still have to drop * the type and length which are at the front of any trailer data. */ m = deget(&ds->ds_deuba, ifrw, len, off, &ds->ds_if); if (m == 0) return; if (off) { struct ifnet *ifp; ifp = *(mtod(m, struct ifnet **)); m->m_off += 2 * sizeof (u_short); m->m_len -= 2 * sizeof (u_short); *(mtod(m, struct ifnet **)) = ifp; } switch (type) { #ifdef INET case ETHERTYPE_IP: schednetisr(NETISR_IP); inq = &ipintrq; break; case ETHERTYPE_ARP: arpinput(&ds->ds_ac, m); return; #endif /* INET */ default: #ifdef not_on_pdp /* * see if other protocol families defined * and call protocol specific routines. * If no other protocols defined then dump message. */ if (pr=iftype_to_proto(type)) { if ((m = (struct mbuf *)(*pr->pr_ifinput)(m, &ds->ds_if, &inq)) == 0) return; } else { #endif /* not_on_pdp */ #ifdef DE_DEBUG if(dedebug >= 1) printf("de%d: Unknow Packet Type 0%o(%d)\n", ds->ds_if.if_unit, type, type); #endif /* DE_DEBUG */ #ifdef DE_DO_BCTRS if (ds->ds_unrecog != 0xffff) ds->ds_unrecog++; #endif /* DE_DO_BCTRS */ m_freem(m); return; #ifdef not_on_pdp } #endif /* not_on_pdp */ } s = splimp(); if (IF_QFULL(inq)) { IF_DROP(inq); splx(s); #ifdef DE_DEBUG if (dedebug >= 1) printf("de%d: Packet Dropped(deread)\n", ds->ds_if.if_unit); #endif /* DE_DEBUG */ m_freem(m); return; } IF_ENQUEUE(inq, m); splx(s); } /* * Ethernet output routine. * Encapsulate a packet of type family for the local net. * Use trailer local net encapsulation if enough data in first * packet leaves a multiple of 512 bytes of data in remainder. */ deoutput(ifp, m0, dst) struct ifnet *ifp; struct mbuf *m0; struct sockaddr *dst; { int type, s, error; u_char edst[6]; struct in_addr idst; struct protosw *pr; register struct de_softc *ds = &de_softc[ifp->if_unit]; register struct mbuf *m = m0; register struct ether_header *eh; register int off; int usetrailers; if((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { error = ENETDOWN; goto bad; } switch (dst->sa_family) { #ifdef INET case AF_INET: idst = ((struct sockaddr_in *)dst)->sin_addr; if (!arpresolve(&ds->ds_ac, m, &idst, edst, &usetrailers)) return (0); /* if not yet resolved */ off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; /* need per host negotiation */ if (usetrailers && off > 0 && (off & 0x1ff) == 0 && m->m_off >= MMINOFF + 2 * sizeof (u_short)) { type = ETHERTYPE_TRAIL + (off>>9); m->m_off -= 2 * sizeof (u_short); m->m_len += 2 * sizeof (u_short); *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); goto gottrailertype; } type = ETHERTYPE_IP; off = 0; goto gottype; #endif /* INET */ #ifdef NS case AF_NS: type = ETHERTYPE_NS; bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), (caddr_t)edst, sizeof (edst)); off = 0; goto gottype; #endif /* NS */ case AF_UNSPEC: eh = (struct ether_header *)dst->sa_data; bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); type = eh->ether_type; goto gottype; default: #ifdef DE_INT_LOOPBACK /* * If we are in loopback mode check the length and * device type. DELUA can only loopback frames of 36 bytes * or less including crc. */ if ((ifp->if_flags & IFF_LOOPBACK) && (m->m_len > DELUA_LOOP_LEN) && (ds->ds_devid == DELUA)) return(EINVAL); #endif /* DE_INT_LOOPBACK */ #ifdef not_on_pdp /* * try to find other address families and call protocol * specific output routine. */ if (pr=iffamily_to_proto(dst->sa_family)) { (*pr->pr_ifoutput)(ifp, m0, dst, &type, (char *)edst); goto gottype; } else { #endif /* not_on_pdp */ printf("de%d: can't handle af%d", ifp->if_unit, dst->sa_family); error = EAFNOSUPPORT; goto bad; #ifdef not_on_pdp } #endif /* not_on_pdp */ } gottrailertype: /* * Packet to be sent as trailer: move first packet * (control information) to end of chain. */ while (m->m_next) m = m->m_next; m->m_next = m0; m = m0->m_next; m0->m_next = 0; m0 = m; gottype: /* * Add local net header. If no space in first mbuf, * allocate another. */ if (m->m_off > MMAXOFF || MMINOFF + sizeof (struct ether_header) > m->m_off) { m = m_get(M_DONTWAIT, MT_HEADER); if (m == 0) { error = ENOBUFS; goto bad; } m->m_next = m0; m->m_off = MMINOFF; m->m_len = sizeof (struct ether_header); } else { m->m_off -= sizeof (struct ether_header); m->m_len += sizeof (struct ether_header); } eh = mtod(m, struct ether_header *); eh->ether_type = htons((u_short)type); bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); /* DEUNA fills in source address */ bcopy((caddr_t)ds->ds_addr, (caddr_t)eh->ether_shost, sizeof(ds->ds_addr)); /* * Queue message on interface, and start output if interface * not yet active. */ s = splimp(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); splx(s); #ifdef DE_DEBUG if (dedebug >= 1) printf("de%d: Packet Dropped(deoutput)\n", ifp->if_unit); #endif /* DE_DEBUG */ m_freem(m); return (ENOBUFS); } IF_ENQUEUE(&ifp->if_snd, m); destart(ifp->if_unit); splx(s); return (0); bad: m_freem(m0); return (error); } /* * Routines supporting UNIBUS network interfaces. */ /* * Init UNIBUS for interface. We map the i/o area * onto the UNIBUS. We then split up the i/o area among * all the receive and transmit buffers. */ static de_ubainit(ifu, uban, hlen, nmr) register struct deuba *ifu; int uban, hlen, nmr; { register caddr_t cp, dp; register struct ifrw *ifrw; int i, ncl; /* * If the ring already has core allocated, quit now. */ if (ifu->difu_r[0].ifrw_click) return(1); nmr = ctob(nmr); nmr += hlen; for (i = 0; i < NRCV; i++) { ifu->difu_r[i].ifrw_click = m_ioget(nmr); if (ifu->difu_r[i].ifrw_click == 0) { ifu->difu_r[0].ifrw_click = 0; if (i) printf("de: lost some space\n"); return(0); } } for (i = 0; i < NXMT; i++) { ifu->difu_w[i].ifrw_click = m_ioget(nmr); if (ifu->difu_w[i].ifrw_click == 0) { ifu->difu_w[0].ifrw_click = 0; ifu->difu_r[0].ifrw_click = 0; if (i) printf("de: lost some space\n"); return(0); } } for (i = 0; i < NRCV; i++) ifu->difu_r[i].ifrw_info = ubmalloc(ifu->difu_r[i].ifrw_click); for (i = 0; i < NXMT; i++) ifu->difu_w[i].ifrw_info = ubmalloc(ifu->difu_w[i].ifrw_click); ifu->ifu_hlen = hlen; return (1); } /* * Pull read data off a interface. * Len is length of data, with local net header stripped. * Off is non-zero if a trailer protocol was used, and * gives the offset of the trailer information. * We copy the trailer information and then all the normal * data into mbufs. */ static struct mbuf * deget(ifu, ifrw, totlen, off0, ifp) register struct deuba *ifu; register struct ifrw *ifrw; int totlen, off0; struct ifnet *ifp; { struct mbuf *top, **mp, *m; int off = off0, len; register caddr_t cp = (caddr_t) ifu->ifu_hlen; u_int click; top = 0; mp = ⊤ click = ifrw->ifrw_click; while (totlen > 0) { MGET(m, M_DONTWAIT, MT_DATA); if (m == 0) goto bad; if (off) { len = totlen - off; cp = (caddr_t)(ifu->ifu_hlen + off); } else len = totlen; m->m_off = MMINOFF; if (ifp) { /* * Leave Room for the ifp */ m->m_len = MIN(MLEN - sizeof(ifp), len); m->m_off += sizeof(ifp); } else m->m_len = MIN(MLEN, len); mbcopyin(click, cp, mtod(m, char *), (u_int) m->m_len); cp += m->m_len; *mp = m; mp = &m->m_next; if (off) { /* sort of an ALGOL-W style for statement... */ off += m->m_len; if (off == totlen) { cp = (caddr_t) ifu->ifu_hlen; off = 0; totlen = off0; } } else totlen -= m->m_len; if (ifp) { /* * Prepend interface pointer to first mbuf */ m->m_len += sizeof(ifp); m->m_off -= sizeof(ifp); *(mtod(m, struct ifnet **)) = ifp; ifp = (struct ifnet *) 0; } } return (top); bad: m_freem(top); return (0); } /* * Map a chain of mbufs onto a network interface * in preparation for an i/o operation. * The argument chain of mbufs includes the local network * header which is copied to be in the mapped, aligned * i/o space. */ static deput(ifu, n, m) struct deuba *ifu; int n; register struct mbuf *m; { register struct mbuf *mp; register u_short off, click; click = ifu->difu_w[n].ifrw_click; off = 0; while (m) { mbcopyout(mtod(m, char *), click, off, (u_int) m->m_len); off += m->m_len; MFREE(m, mp); m = mp; } return (off); } /* * Process an ioctl request. */ deioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { register struct de_softc *ds = &de_softc[ifp->if_unit]; register struct uba_device *ui = deinfo[ifp->if_unit]; register struct dedevice *addr = (struct dedevice *)ui->ui_addr; struct protosw *pr; struct sockaddr *sa; struct ifreq *ifr = (struct ifreq *)data; struct ifdevea *ifd = (struct ifdevea *)data; register struct ifaddr *ifa = (struct ifaddr *)data; int s = splimp(), error = 0; switch (cmd) { #ifdef DE_INT_LOOPBACK case SIOCENABLBACK: printf("de%d: internal loopback enable requested\n", ifp->if_unit); if ( (error = deloopback(ifp, ds, addr, YES)) != NULL ) break; ifp->if_flags |= IFF_LOOPBACK; break; case SIOCDISABLBACK: printf("de%d: internal loopback disable requested\n", ifp->if_unit); if ( (error = deloopback(ifp, ds, addr, NO)) != NULL ) break; ifp->if_flags &= ~IFF_LOOPBACK; deinit(ifp->if_unit); break; #endif /* DE_INT_LOOPBACK */ #ifdef DE_DO_PHYSADDR case SIOCRPHYSADDR: /* * read default hardware address. */ ds->ds_pcbb.pcbb0 = FC_RDDEFAULT; addr->pclow = CMD_GETCMD|((ds->ds_flags & DSF_RUNNING) ? PCSR0_INTE : 0); if (dewait(ui, "read default hardware address", NO, YES)) { error = EIO; break; } /* * copy current physical address and default hardware address * for requestor. */ bcopy(&ds->ds_pcbb.pcbb2, ifd->default_pa, 6); bcopy(ds->ds_addr, ifd->current_pa, 6); break; case SIOCSPHYSADDR: /* Set the DNA address as the de's physical address */ ds->ds_pcbb.pcbb0 = FC_WTPHYAD; bcopy (ifr->ifr_addr.sa_data, &ds->ds_pcbb.pcbb2, 6); addr->pclow = CMD_GETCMD|((ds->ds_flags & DSF_RUNNING) ? PCSR0_INTE : 0); (void) dewait(ui, "write physical address", NO, YES); bcopy((caddr_t)&ds->ds_pcbb.pcbb2,(caddr_t)ds->ds_addr, sizeof (ds->ds_addr)); deinit(ifp->if_unit); break; #endif /* DE_DO_PHYSADDR */ #ifdef DE_DO_MULTI case SIOCDELMULTI: case SIOCADDMULTI: { int i,j = -1,incaddr = ds->ds_ubaddr + MULTI_OFFSET; if (cmd==SIOCDELMULTI) { for (i = 0; i < NMULTI; i++) if (bcmp(&ds->ds_multicast[i],ifr->ifr_addr.sa_data,MULTISIZE) == 0) { if (--ds->ds_muse[i] == 0) bcopy(unused_multi,&ds->ds_multicast[i],MULTISIZE); } } else { for (i = 0; i < NMULTI; i++) { if (bcmp(&ds->ds_multicast[i],ifr->ifr_addr.sa_data,MULTISIZE) == 0) { ds->ds_muse[i]++; goto done; } if (bcmp(&ds->ds_multicast[i],unused_multi,MULTISIZE) == 0) j = i; } if (j == -1) { printf("de%d: mtmulti failed, multicast list full: %d\n", ui->ui_unit, NMULTI); error = ENOBUFS; goto done; } bcopy(ifr->ifr_addr.sa_data, &ds->ds_multicast[j], MULTISIZE); ds->ds_muse[j]++; } ds->ds_pcbb.pcbb0 = FC_WTMULTI; ds->ds_pcbb.pcbb2 = incaddr & 0xffff; ds->ds_pcbb.pcbb4 = (NMULTI << 8) | ((incaddr >> 16) & 03); addr->pclow = CMD_GETCMD|((ds->ds_flags & DSF_RUNNING) ? PCSR0_INTE : 0); (void) dewait(ui, "set multicast address", NO, YES); break; } #endif /* DE_DO_MULTI */ #ifdef DE_DO_BCTRS case SIOCRDCTRS: case SIOCRDZCTRS: { register struct ctrreq *ctr = (struct ctrreq *)data; ubadr_t incaddr; ds->ds_pcbb.pcbb0 = cmd == SIOCRDCTRS ? FC_RDCNTS : FC_RCCNTS; incaddr = ds->ds_ubaddr + COUNTER_OFFSET; ds->ds_pcbb.pcbb2 = incaddr & 0xffff; ds->ds_pcbb.pcbb4 = (incaddr >> 16) & 0x3; ds->ds_pcbb.pcbb6 = sizeof(struct de_counters) / sizeof (short); addr->pclow = CMD_GETCMD|((ds->ds_flags & DSF_RUNNING) ? PCSR0_INTE : 0); if (dewait(ui, "read counts", NO, YES)) { error = ENOBUFS; break; } bzero(&ctr->ctr_ether, sizeof(struct estat)); ctr->ctr_type = CTR_ETHER; cpfromkern(&time, &atv, sizeof(struct timeval)); ctr->ctr_ether.est_seconds = (atv.tv_sec - ds->ds_ztime) > 0xfffe ? 0xffff : (atv.tv_sec - ds->ds_ztime); ctr->ctr_ether.est_byrcvd = *(long *)ds->ds_counters.c_brcvd; ctr->ctr_ether.est_bysent = *(long *)ds->ds_counters.c_bsent; ctr->ctr_ether.est_mbyrcvd = *(long *)ds->ds_counters.c_mbrcvd; ctr->ctr_ether.est_blrcvd = *(long *)ds->ds_counters.c_prcvd; ctr->ctr_ether.est_blsent = *(long *)ds->ds_counters.c_psent; ctr->ctr_ether.est_mblrcvd = *(long *)ds->ds_counters.c_mprcvd; ctr->ctr_ether.est_deferred = *(long *)ds->ds_counters.c_defer; ctr->ctr_ether.est_single = *(long *)ds->ds_counters.c_single; ctr->ctr_ether.est_multiple = *(long *)ds->ds_counters.c_multiple; ctr->ctr_ether.est_sf = ds->ds_counters.c_snderr; ctr->ctr_ether.est_sfbm = ds->ds_counters.c_sbm & 0xff; ctr->ctr_ether.est_collis = ds->ds_counters.c_collis; ctr->ctr_ether.est_rf = ds->ds_counters.c_rcverr; ctr->ctr_ether.est_rfbm = ds->ds_counters.c_rbm & 0xff; ctr->ctr_ether.est_unrecog = ds->ds_unrecog; ctr->ctr_ether.est_sysbuf = ds->ds_counters.c_ibuferr; ctr->ctr_ether.est_userbuf = ds->ds_counters.c_lbuferr; if (cmd == SIOCRDZCTRS) { cpfromkern(&time, &atv, sizeof(struct timeval)); ds->ds_ztime = atv.tv_sec; ds->ds_unrecog = 0; } break; } #endif /* DE_DO_BCTRS */ case SIOCSIFADDR: ifp->if_flags |= IFF_UP; deinit(ifp->if_unit); switch (ifa->ifa_addr.sa_family) { #ifdef INET case AF_INET: ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr; arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); break; #endif /* INET */ #ifdef NS case AF_NS: { register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); if (ns_nullhost(*ina)) { ina->x_host = * (union ns_host *) (de_softc[ifp->if_unit].ds_addr); } else { de_setaddr(ina->x_host.c_host,ifp->if_unit); } break; } #endif /* NS */ default: #ifdef not_on_pdp if (pr=iffamily_to_proto(ifa->ifa_addr.sa_family)) { error = (*pr->pr_ifioctl)(ifp, cmd, data); } #endif /* not_on_pdp */ #ifdef DE_DEBUG if (dedebug >= 1) printf("de%d: SIOCSIFADDR Unknown address family\n", ifp->if_unit); #endif /* DE_DEBUG */ error = EAFNOSUPPORT; break; } break; case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_UP) == 0 && ds->ds_flags & DSF_RUNNING) { ((struct dedevice *) (deinfo[ifp->if_unit]->ui_addr))->pclow = PCSR0_RSET; (void) dewait(deinfo[ifp->if_unit], "board reset(deioctl)", YES, NO); ds->ds_flags &= ~(DSF_LOCK | DSF_RUNNING); #ifdef DE_DEBUG if (dedebug >= 1) printf("de%d: reset and marked down\n",ifp->if_unit); #endif /* DE_DEBUG */ } else if (ifp->if_flags & IFF_UP && (ds->ds_flags & DSF_RUNNING) == 0) { deinit(ifp->if_unit); #ifdef DE_DEBUG if (dedebug >= 1) printf("de%d: reinitialized and marked up\n",ifp->if_unit); #endif /* DE_DEBUG */ } #ifdef DE_DEBUG if ((ifp->if_flags & IFF_DEBUG) == 0) { if (dedebug != 0) { dedebug = 0; printf("de%d: DEBUG disabled\n",ifp->if_unit); } } else { if (dedebug == 0) { dedebug = DE_DEBUG_LEVEL; printf("de%d: DEBUG enabled level=%d\n",ifp->if_unit,dedebug); } } #endif /* DE_DEBUG */ break; default: #ifdef not_on_pdp if (pr=iffamily_to_proto(ifa->ifa_addr.sa_family)) error = (*pr->pr_ifioctl)(ifp, cmd, data); else #endif /* not_on_pdp */ error = EINVAL; } done: splx(s); return (error); } #ifdef DE_INT_LOOPBACK /* * enable or disable internal loopback */ static deloopback(ifp, ds, addr, lb_ctl ) register struct ifnet *ifp; register struct de_softc *ds; register struct dedevice *addr; u_char lb_ctl; { register struct uba_device *ui = deinfo[ifp->if_unit]; /* * read current mode register. */ ds->ds_pcbb.pcbb0 = FC_RDMODE; addr->pclow = CMD_GETCMD|((ds->ds_flags & DSF_RUNNING) ? PCSR0_INTE : 0); if (dewait(ui, "read mode register", NO, YES)) return(EIO); /* * set or clear the loopback bit as a function of lb_ctl and * return mode register to driver. */ if ( lb_ctl == YES ) { ds->ds_pcbb.pcbb2 |= MOD_LOOP; if (ds->ds_devid == DELUA) ds->ds_pcbb.pcbb2 |= MOD_INTL; else ds->ds_pcbb.pcbb2 &= ~MOD_HDX; } else { ds->ds_pcbb.pcbb2 &= ~MOD_LOOP; if (ds->ds_devid == DELUA) ds->ds_pcbb.pcbb2 &= ~MOD_INTL; else ds->ds_pcbb.pcbb2 |= MOD_HDX; } ds->ds_pcbb.pcbb0 = FC_WTMODE; addr->pclow = CMD_GETCMD|((ds->ds_flags & DSF_RUNNING) ? PCSR0_INTE : 0); if(dewait(ui, "write mode register", NO, YES)) return(EIO); return(NULL); } #endif /* DE_INT_LOOPBACK */ dewait(ui, fn, no_port, only_dni) register struct uba_device *ui; char *fn; int no_port; int only_dni; { register struct de_softc *ds = &de_softc[ui->ui_unit]; register struct dedevice *addr = (struct dedevice *)ui->ui_addr; register csr0; if (only_dni) while ((addr->pcsr0 & PCSR0_DNI) == 0) ; else while ((addr->pcsr0 & PCSR0_INTR) == 0) ; csr0 = addr->pcsr0; addr->pchigh = csr0 >> 8; if ((csr0 & PCSR0_PCEI) || (no_port && (csr0 & PCSR0_DNI)==0)) { if (ds->ds_devid == DEUNA) printf("de%d: %s failed, csr0=%b, csr1=%b\n", ui->ui_unit, fn, csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS); else printf("de%d: %s failed, csr0=%b, csr1=%b\n", ui->ui_unit, fn, csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS_DELUA); } return(csr0 & PCSR0_PCEI); } #ifdef NS /* * Set the ethernet address for the unit, this sets the board's * hardware address to physaddr. This is only used if you have * NS defined. */ de_setaddr(physaddr, unit) u_char *physaddr; int unit; { register struct de_softc *ds = &de_softc[unit]; struct uba_device *ui = deinfo[unit]; register struct dedevice *addr = (struct dedevice *)ui->ui_addr; if (! (ds->ds_flags & DSF_RUNNING)) return; bcopy(physaddr, &ds->ds_pcbb.pcbb2, 6); ds->ds_pcbb.pcbb0 = FC_WTPHYAD; addr->pclow = PCSR0_INTE | CMD_GETCMD; if (dewait(ui, "address changed", NO, NO) == 0) { ds->ds_flags |= DSF_SETADDR; bcopy(physaddr, ds->ds_addr, 6); } } #endif /* NS */ #endif /* NDE > 0 */ if_unit]; register struct dedevice *addr = (struct dedevice *)ui->ui_addr; struct protosw *pr; struct sockaddr *sa; struct ifreq *ifr = (struct ifreq *)data; struct ifdevea *ifd = (struct ifdevea *)data; register struct ifaddr *ifa = (struct ifaddr *)data; int s = splimp(), error = 0;sys/pdpif/if_ec.c 444 0 12 52605 4310331475 7207 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_ec.c 7.1 (Berkeley) 6/5/86 * 1.0 (2.10BSD EATON IMSD sms@etn-wlv.eaton.com 12/28/87) */ #include "ec.h" #if NEC > 0 /* * 3Com Ethernet Controller interface * * Adapted from the 4.3BSD version to run on 2.10BSD. Major differences: * * 1) static instead of autoconfiguration, 'autoconfig' has problems with * our triple vector. * 2) reduction of the number of buffers from 16 to 12, this is because * the unibus memory for this device is 'enabled' by clipping resistors * on the cpu board and must start on a mod 4 UMR boundary and we only * have UMRs 28, 29 and 30. The number of UMRs available has to be * reduced in ubinit() (/sys/pdp/machdep2.c) if this driver is to * be used. * 3) Buffers are mapped thru APR5, copyv() is used to go to/from mbufs. * 4) Exponential backup redone to use a count instead of a mask. * 5) The ec_softc structure reduced in size to remove unused fields. * 6) Modified to run in supervisor mode, about all this required was * changing the macros in seg.h to use supervisor registers if * SUPERVISOR is defined (from the makefiles) AND changing where * SEG5 is mapped in/out. Use mbcopyin/out instead of copyv. * 7) Broken ethernet cable showed up a problem in collision handling, * the backoff being done via a DELAY loop effectively hangs the system. * Changed to use a timeout with the number of ticks being the number * of collisions (up to 16 max). * * Who knows if trailers and NS work, i don't. Coding style changed to reflect * personal preferences, conditional vax code removed to improve readability. * * Oh, one more thing. The 3Com board is hardwired to interrupt at spl6 for * the receiver, spl5 for the collision detect, and spl4 for the transmitter. * References to splimp() have been replaced in this driver with splhigh(). * you'll have to change splimp() to be spl6 and recompile the whole kernel * in order to avoid recursive interrupts caused by the receiver using splimp * anywhere in its path. TRUST ME, you crash if you don't do this. Better * to lose a few clock ticks than the system! */ #include "param.h" #include "../machine/seg.h" #include "mbuf.h" #include "buf.h" #include "domain.h" #include "protosw.h" #include "socket.h" #include "ioctl.h" #include "errno.h" #include "../net/if.h" #include "../net/netisr.h" #include "../net/route.h" #ifdef INET #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netinet/in_var.h" #include "../netinet/ip.h" #include "../netinet/if_ether.h" #endif #ifdef NS #include "../netns/ns.h" #include "../netns/ns_if.h" #endif #include "if_ecreg.h" #include "if_uba.h" #include "../pdpuba/ubavar.h" #define MAPBUFDESC (((btoc(2048) - 1) << 8 ) | RW) #define BUFP ((caddr_t)0120000) #undef ECRHBF #define ECRHBF 11 #define ECNUMBUFS (ECRHBF + 1) extern struct ifnet loif; int ecattach(), ecinit(), ecioctl(), ecoutput(), ecunjam(); struct uba_device *ecinfo[NEC]; u_short ecstd[] = { 0 }; struct uba_driver ecdriver = { 0, 0, ecattach, 0, ecstd, "ec", ecinfo }; struct mbuf *ecget(); /* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * es_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... */ struct ec_softc { struct arpcom es_ac; /* common Ethernet structures */ #define es_if es_ac.ac_if /* network-visible interface */ #define es_addr es_ac.ac_enaddr /* hardware Ethernet address */ u_char es_mask; /* mask for current output delay */ u_char es_oactive; /* is output active? */ memaddr es_buf[ECNUMBUFS]; /* virtual click buffer addresses */ } ec_softc[NEC]; /* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */ ecattach(ui) struct uba_device *ui; { struct ec_softc *es = &ec_softc[ui->ui_unit]; register struct ifnet *ifp = &es->es_if; register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr; int i, j; u_char *cp; ifp->if_unit = ui->ui_unit; ifp->if_name = "ec"; ifp->if_mtu = ETHERMTU; /* Read the ethernet address off the board, one nibble at a time. */ addr->ec_xcr = EC_UECLR; /* zero address pointer */ addr->ec_rcr = EC_AROM; cp = es->es_addr; #define NEXTBIT addr->ec_rcr = EC_AROM|EC_ASTEP; addr->ec_rcr = EC_AROM for (i=0; i < sizeof (es->es_addr); i++) { *cp = 0; for (j=0; j<=4; j+=4) { *cp |= ((addr->ec_rcr >> 8) & 0xf) << j; NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT; } cp++; } printf("ec%d: addr %s\n", ui->ui_unit, ether_sprintf(es->es_addr)); ifp->if_init = ecinit; ifp->if_ioctl = ecioctl; ifp->if_output = ecoutput; ifp->if_reset = 0; ifp->if_flags = IFF_BROADCAST; /* * the (memaddr)(0177000) below is UMR28 translated into clicks. */ for (i = 0; i < ECNUMBUFS; i++) es->es_buf[i] = (memaddr)(0177000) + (memaddr)(btoc(2048) * i); if_attach(ifp); } /* * Initialization of interface; clear recorded pending operations. */ ecinit(unit) int unit; { struct ec_softc *es = &ec_softc[unit]; struct ecdevice *addr; register struct ifnet *ifp = &es->es_if; int i, s; /* not yet, if address still unknown */ if (ifp->if_addrlist == (struct ifaddr *)0) return; /* * Hang receive buffers and start any pending writes. * Writing into the rcr also makes sure the memory * is turned on. */ if ((ifp->if_flags & IFF_RUNNING) == 0) { addr = (struct ecdevice *)ecinfo[unit]->ui_addr; s = splhigh(); /* * write our ethernet address into the address recognition ROM * so we can always use the same EC_READ bits (referencing ROM), * in case we change the address sometime. * Note that this is safe here as the receiver is NOT armed. */ ec_setaddr(es->es_addr, unit); /* * Arm the receiver */ for (i = ECRHBF; i >= ECRLBF; i--) addr->ec_rcr = EC_READ | i; es->es_oactive = 0; es->es_mask = 1; es->es_if.if_flags |= IFF_RUNNING; if (es->es_if.if_snd.ifq_head) ecstart(unit); splx(s); } } /* * Start output on interface. Get another datagram to send * off of the interface queue, and copy it to the interface * before starting the output. */ ecstart(unit) int unit; { register struct ec_softc *es = &ec_softc[unit]; struct ecdevice *addr; struct mbuf *m; if ((es->es_if.if_flags & IFF_RUNNING) == 0) return; IF_DEQUEUE(&es->es_if.if_snd, m); if (m == 0) return; ecput(es->es_buf[ECTBF], m); addr = (struct ecdevice *)ecinfo[unit]->ui_addr; addr->ec_xcr = EC_WRITE|ECTBF; es->es_oactive = 1; } /* * Ethernet interface transmitter interrupt. * Start another output if more data to send. */ ecxint(unit) int unit; { register struct ec_softc *es = &ec_softc[unit]; register struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr; register int s; if (es->es_oactive == 0) return; if (!(addr->ec_xcr&EC_XDONE) || (addr->ec_xcr&EC_XBN) != ECTBF) { printf("ec%d: stray xint, xcr=%b\n",unit,addr->ec_xcr,EC_XBITS); es->es_oactive = 0; addr->ec_xcr = EC_XCLR; return; } es->es_if.if_opackets++; es->es_oactive = 0; es->es_mask = 1; addr->ec_xcr = EC_XCLR; s = splimp(); if (es->es_if.if_snd.ifq_head) ecstart(unit); splx(s); } /* * Collision on ethernet interface. Do exponential * backoff, and retransmit. If have backed off all * the way print warning diagnostic, and drop packet. */ eccollide(unit) int unit; { register struct ec_softc *es = &ec_softc[unit]; register struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr; register int i; long delay; es->es_if.if_collisions++; if (es->es_oactive == 0) return; if (es->es_mask++ >= 16) { es->es_if.if_oerrors++; printf("ec%d: send err\n", unit); /* * Reset interface, then requeue rcv buffers. * Some incoming packets may be lost, but that * can't be helped. */ addr->ec_xcr = EC_UECLR; for (i=ECRHBF; i>=ECRLBF; i--) addr->ec_rcr = EC_READ|i; /* * Reset and transmit next packet (if any). */ es->es_oactive = 0; es->es_mask = 1; if (es->es_if.if_snd.ifq_head) ecstart(unit); return; } /* * use a timeout instead of a delay loop - the loop hung the system * when someone unscrewed a terminator on the net. * * this isn't exponential, but it sure beats a hung up system in the * face of a broken cable. */ TIMEOUT(ecunjam, addr, es->es_mask); } ecunjam(addr) struct ecdevice *addr; { /* * Clear the controller's collision flag, thus enabling retransmit. */ addr->ec_xcr = EC_CLEAR; } /* * Ethernet interface receiver interrupt. * If input error just drop packet. * Otherwise examine packet to determine type. If can't determine length * from type, then have to drop packet. Othewise decapsulate * packet based on type and pass to type specific higher-level * input routine. */ ecrint(unit) int unit; { struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr; while (addr->ec_rcr & EC_RDONE) ecread(unit); } ecread(unit) int unit; { register struct ec_softc *es = &ec_softc[unit]; register struct ether_header *ec; register struct ifqueue *inq; struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr; struct mbuf *m; int len, off = 0, resid, ecoff, rbuf, type; u_char *ecbuf; segm sav5; es->es_if.if_ipackets++; rbuf = addr->ec_rcr & EC_RBN; if (rbuf < ECRLBF || rbuf > ECRHBF) panic("ecrint"); /* sanity */ /* * we change SDSA5 only while NOT looking at mbufs (there might be some on SEG5) * and carefully restore it before calling 'ecget' who uses mbcopyin(). * the save/restore seg routines are ifdef'd on SUPERVISOR (which had better * be set when compiling the network stuff!!). */ saveseg5(sav5); mapseg5(es->es_buf[rbuf], MAPBUFDESC); ecbuf = (u_char *)SEG5; ecoff = *(short *)SEG5; if (ecoff <= ECRDOFF || ecoff > 2046) { es->es_if.if_ierrors++; #ifdef notyet printf("ec%d ecoff=0%o rbuf=0%o\n", unit, ecoff, rbuf); #endif goto setup; } /* * Get input data length. * Get pointer to ethernet header (in input buffer). * Deal with trailer protocol: if type is trailer type * get true type from first 16-bit word past data. * Remember that type was trailer by setting off. */ len = ecoff - ECRDOFF - sizeof (struct ether_header); ec = (struct ether_header *)(ecbuf + ECRDOFF); ec->ether_type = ntohs((u_short)ec->ether_type); #ifdef weliketrailers #define ecdataaddr(ec, off, type) ((type)(((caddr_t)((ec)+1)+(off)))) if (ec->ether_type >= ETHERTYPE_TRAIL && ec->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { off = (ec->ether_type - ETHERTYPE_TRAIL) * 512; if (off >= ETHERMTU) goto setup; /* sanity */ ec->ether_type = ntohs(*ecdataaddr(ec, off, u_short *)); resid = ntohs(*(ecdataaddr(ec, off+2, u_short *))); if (off + resid > len) goto setup; /* sanity */ len = off + resid; } else off = 0; if (!len) goto setup; #else if (!len || (ec->ether_type >= ETHERTYPE_TRAIL && ec->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER)) { printf("ec%d type=%x len=%d\n", unit, ec->ether_type,len); es->es_if.if_ierrors++; goto setup; } #endif /* * Pull packet off interface. Off is nonzero if packet * has trailing header; ecget will then force this header * information to be at the front, but we still have to drop * the type and length which are at the front of any trailer data. */ type = ec->ether_type; /* save before restoring mapping */ restorseg5(sav5); /* put it back now! */ m = ecget(es->es_buf[rbuf], len, off, &es->es_if); if (m == 0) goto setup; #ifdef weliketrailers if (off) { struct ifnet *ifp; ifp = *(mtod(m, struct ifnet **)); m->m_off += 2 * sizeof (u_short); m->m_len -= 2 * sizeof (u_short); *(mtod(m, struct ifnet **)) = ifp; } #endif switch (type) { #ifdef INET case ETHERTYPE_IP: schednetisr(NETISR_IP); inq = &ipintrq; break; case ETHERTYPE_ARP: arpinput(&es->es_ac, m); goto setup; #endif #ifdef NS case ETHERTYPE_NS: schednetisr(NETISR_NS); inq = &nsintrq; break; #endif default: m_freem(m); goto setup; } if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); goto setup; } IF_ENQUEUE(inq, m); setup: /* Reset for next packet. */ restorseg5(sav5); /* put it back before leaving */ addr->ec_rcr = EC_READ|EC_RCLR|rbuf; } /* * Ethernet output routine. * Encapsulate a packet of type family for the local net. * Use trailer local net encapsulation if enough data in first * packet leaves a multiple of 512 bytes of data in remainder and trailers * are allowed (which we should NEVER do). * If destination is this address or broadcast, send packet to * loop device to kludge around the fact that 3com interfaces can't * talk to themselves. */ ecoutput(ifp, m0, dst) struct ifnet *ifp; struct mbuf *m0; struct sockaddr *dst; { int type, s, error, usetrailers; u_char edst[6]; struct in_addr idst; struct ec_softc *es = &ec_softc[ifp->if_unit]; register struct mbuf *m = m0; register struct ether_header *ec; register int off; u_short *p; struct mbuf *mcopy = (struct mbuf *)0; if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { error = ENETDOWN; goto bad; } switch (dst->sa_family) { #ifdef INET case AF_INET: idst = ((struct sockaddr_in *)dst)->sin_addr; if (!arpresolve(&es->es_ac, m, &idst, edst, &usetrailers)) return(0); /* if not yet resolved */ if (!bcmp(edst, etherbroadcastaddr, sizeof(edst))) mcopy = m_copy(m, 0, (int)M_COPYALL); off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; /* need per host negotiation */ if (usetrailers && off > 0 && (off & 0x1ff) == 0 && m->m_off >= MMINOFF + 2 * sizeof (u_short)) { type = ETHERTYPE_TRAIL + (off>>9); m->m_off -= 2 * sizeof (u_short); m->m_len += 2 * sizeof (u_short); p = mtod(m, u_short *); *p++ =ntohs((u_short)ETHERTYPE_IP); *p = ntohs((u_short)m->m_len); goto gottrailertype; } type = ETHERTYPE_IP; off = 0; goto gottype; #endif #ifdef NS case AF_NS: bcopy(&(((struct sockaddr_ns *)dst)->sns_addr.x_host), edst, sizeof (edst)); if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof(edst))) mcopy = m_copy(m, 0, (int)M_COPYALL); else if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))) return(looutput(&loif, m, dst)); type = ETHERTYPE_NS; off = 0; goto gottype; #endif case AF_UNSPEC: ec = (struct ether_header *)dst->sa_data; bcopy(ec->ether_dhost, (caddr_t)edst, sizeof (edst)); type = ec->ether_type; goto gottype; default: printf("ec%d: af%d\n", ifp->if_unit, dst->sa_family); error = EAFNOSUPPORT; goto bad; } gottrailertype: /* * Packet to be sent as trailer: move first packet * (control information) to end of chain. */ while (m->m_next) m = m->m_next; m->m_next = m0; m = m0->m_next; m0->m_next = 0; m0 = m; gottype: /* * Add local net header. If no space in first mbuf, * allocate another. */ if (m->m_off > MMAXOFF || MMINOFF + sizeof (struct ether_header) > m->m_off) { m = m_get(M_DONTWAIT, MT_HEADER); if (m == 0) { error = ENOBUFS; goto bad; } m->m_next = m0; m->m_off = MMINOFF; m->m_len = sizeof (struct ether_header); } else { m->m_off -= sizeof (struct ether_header); m->m_len += sizeof (struct ether_header); } ec = mtod(m, struct ether_header *); bcopy((caddr_t)edst, (caddr_t)ec->ether_dhost, sizeof (edst)); bcopy(es->es_addr, (caddr_t)ec->ether_shost, sizeof(ec->ether_shost)); ec->ether_type = htons((u_short)type); /* * Queue message on interface, and start output if interface * not yet active. */ s = splhigh(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); error = ENOBUFS; goto qfull; } IF_ENQUEUE(&ifp->if_snd, m); if (es->es_oactive == 0) ecstart(ifp->if_unit); splx(s); error = mcopy ? looutput(&loif, mcopy, dst) : 0; return(error); qfull: m0 = m; splx(s); bad: m_freem(m0); if (mcopy) m_freem(mcopy); return(error); } /* * Routine to copy from mbuf chain to transmit * buffer in UNIBUS memory. * If packet size is less than the minimum legal size, * the buffer is expanded. We probably should zero out the extra * bytes for security, but that would slow things down. */ ecput(ecbuf, m) memaddr ecbuf; struct mbuf *m; { register struct mbuf *mp; register u_short off; segm sav5; for (off = 2048, mp = m; mp; mp = mp->m_next) off -= mp->m_len; if (2048 - off < ETHERMIN + sizeof (struct ether_header)) off = 2048 - ETHERMIN - sizeof (struct ether_header); saveseg5(sav5); mapseg5(ecbuf, MAPBUFDESC); *(u_short *)SEG5 = off; restorseg5(sav5); for (mp = m; mp; mp = mp->m_next) { register unsigned len = mp->m_len; if (len == 0) continue; mbcopyout(mtod(mp, caddr_t), ecbuf, off, len); off += len; } m_freem(m); } /* * Routine to copy from UNIBUS memory into mbufs. */ struct mbuf * ecget(ecbuf, totlen, off0, ifp) memaddr ecbuf; int totlen, off0; struct ifnet *ifp; { register struct mbuf *m; register int off = off0, len; struct mbuf *top = 0, **mp = ⊤ u_short distance; distance = ECRDOFF + sizeof (struct ether_header); while (totlen > 0) { MGET(m, M_DONTWAIT, MT_DATA); if (m == 0) goto bad; if (off) { len = totlen - off; distance = ECRDOFF + off + sizeof (struct ether_header); } else len = totlen; if (ifp) len += sizeof(ifp); if (len >= NBPG) { MCLGET(m); if (m->m_len == CLBYTES) m->m_len = len = MIN(len, CLBYTES); else m->m_len = len = MIN(MLEN, len); } else m->m_len = len = MIN(MLEN, len); if (ifp) { /* Prepend interface pointer to first mbuf. */ *(mtod(m, struct ifnet **)) = ifp; len -= sizeof(ifp); } mbcopyin(ecbuf, distance, ifp ? mtod(m,caddr_t)+sizeof(ifp) : mtod(m,caddr_t), len); ifp = (struct ifnet *)0; distance += len; *mp = m; mp = &m->m_next; if (off == 0) { totlen -= len; continue; } off += len; if (off == totlen) { distance = ECRDOFF + sizeof (struct ether_header); off = 0; totlen = off0; } } return(top); bad: m_freem(top); return(0); } /* * Process an ioctl request. */ ecioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { register struct ifaddr *ifa = (struct ifaddr *)data; struct ec_softc *es = &ec_softc[ifp->if_unit]; struct ecdevice *addr; int s = splhigh(), error = 0; addr = (struct ecdevice *)ecinfo[ifp->if_unit]->ui_addr; switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; switch (ifa->ifa_addr.sa_family) { #ifdef INET case AF_INET: ecinit(ifp->if_unit); ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr; arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); break; #endif #ifdef NS case AF_NS: { register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); if (ns_nullhost(*ina)) ina->x_host = *(union ns_host *) (es->es_addr); else { /* * The manual says we can't change the address * while the receiver is armed, * so reset everything */ ifp->if_flags &= ~IFF_RUNNING; bcopy(ina->x_host.c_host, es->es_addr, sizeof(es->es_addr)); } ecinit(ifp->if_unit); /* do ec_setaddr*/ break; } #endif default: ecinit(ifp->if_unit); break; } break; case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) { addr->ec_xcr = EC_UECLR; ifp->if_flags &= ~IFF_RUNNING; } else if (ifp->if_flags & IFF_UP && (ifp->if_flags & IFF_RUNNING) == 0) ecinit(ifp->if_unit); break; default: error = EINVAL; } splx(s); return(error); } ec_setaddr(physaddr,unit) u_char *physaddr; int unit; { struct ec_softc *es = &ec_softc[unit]; struct uba_device *ui = ecinfo[unit]; struct ecdevice *addr = (struct ecdevice *)ui->ui_addr; register char nibble; register int i, j; /* * Use the ethernet address supplied * Note that we do a UECLR here, so the receive buffers * must be requeued. */ #ifdef DEBUG printf("ec_setaddr: setting address for unit %d = %s", unit, ether_sprintf(physaddr)); #endif addr->ec_xcr = EC_UECLR; addr->ec_rcr = 0; /* load requested address */ for (i = 0; i < 6; i++) { /* 6 bytes of address */ es->es_addr[i] = physaddr[i]; nibble = physaddr[i] & 0xf; /* lower nibble */ addr->ec_rcr = (nibble << 8); addr->ec_rcr = (nibble << 8) + EC_AWCLK; /* latch nibble */ addr->ec_rcr = (nibble << 8); for (j=0; j < 4; j++) { addr->ec_rcr = 0; addr->ec_rcr = EC_ASTEP; /* step counter */ addr->ec_rcr = 0; } nibble = (physaddr[i] >> 4) & 0xf; /* upper nibble */ addr->ec_rcr = (nibble << 8); addr->ec_rcr = (nibble << 8) + EC_AWCLK; /* latch nibble */ addr->ec_rcr = (nibble << 8); for (j=0; j < 4; j++) { addr->ec_rcr = 0; addr->ec_rcr = EC_ASTEP; /* step counter */ addr->ec_rcr = 0; } } #ifdef DEBUG /* * Read the ethernet address off the board, one nibble at a time. */ addr->ec_xcr = EC_UECLR; addr->ec_rcr = 0; /* read RAM */ cp = es->es_addr; #undef NEXTBIT #define NEXTBIT addr->ec_rcr = EC_ASTEP; addr->ec_rcr = 0 for (i=0; i < sizeof (es->es_addr); i++) { *cp = 0; for (j=0; j<=4; j+=4) { *cp |= ((addr->ec_rcr >> 8) & 0xf) << j; NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT; } cp++; } printf("ec_setaddr: RAM address for unit %d = %s", unit, ether_sprintf(physaddr)); #endif } #endif ont of any trailer data. */ type = ec->ether_type; /* save before restoring mapping */ restorseg5(sav5); /* put it basys/pdpif/if_en.c 444 0 12 32327 5511225542 7222 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_en.c 1.2 (2.11BSD GTE) 12/31/93 */ #include "en.h" #if NEN > 0 /* * Xerox prototype (3 Mb) Ethernet interface driver. */ #include "param.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "domain.h" #include "protosw.h" #include "socket.h" #include "pdpuba/ubavar.h" #ifdef notdef #include "enreg.h" #endif notdef #include "netinet/in.h" #include "netinet/in_systm.h" #include "net/if.h" #include "pdpif/if_en.h" #include "pdpif/if_uba.h" #include "netinet/ip.h" #include "netinet/ip_var.h" #include "net/route.h" #include "errno.h" #define ENMTU (1024+512) #define ENMRU (1024+512+16) /* 16 is enough to receive trailer */ int enprobe(), enattach(), enrint(), enxint(), encollide(); struct uba_device *eninfo[NEN]; u_short enstd[] = { 0 }; struct uba_driver endriver = { enprobe, 0, enattach, 0, enstd, "en", eninfo }; #define ENUNIT(x) minor(x) int eninit(),enoutput(),enreset(); /* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * es_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... * We also have, for each interface, a UBA interface structure, which * contains information about the UNIBUS resources held by the interface: * map registers, buffered data paths, etc. Information is cached in this * structure for use by the if_uba.c routines in running the interface * efficiently. */ struct en_softc { struct ifnet es_if; /* network-visible interface */ struct ifuba es_ifuba; /* UNIBUS resources */ short es_delay; /* current output delay */ short es_mask; /* mask for current output delay */ short es_lastx; /* host last transmitted to */ short es_oactive; /* is output active? */ short es_olen; /* length of last output */ } en_softc[NEN]; /* * Do output DMA to determine interface presence and * interrupt vector. DMA is too short to disturb other hosts. */ enprobe(reg) caddr_t reg; { register int br, cvec; /* r11, r10 value-result */ register struct endevice *addr = (struct endevice *)reg; #ifndef pdp11 #ifdef lint br = 0; cvec = br; br = cvec; enrint(0); enxint(0); encollide(0); #endif addr->en_istat = 0; addr->en_owc = -1; addr->en_oba = 0; addr->en_ostat = EN_IEN|EN_GO; DELAY(100000L); addr->en_ostat = 0; #ifdef ECHACK br = 0x16; #endif #endif return (1); } /* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */ enattach(ui) struct uba_device *ui; { register struct en_softc *es = &en_softc[ui->ui_unit]; register struct sockaddr_in *sin; es->es_if.if_unit = ui->ui_unit; es->es_if.if_name = "en"; es->es_if.if_mtu = ENMTU; es->es_if.if_net = ui->ui_flags; es->es_if.if_host[0] = (~(((struct endevice *)eninfo[ui->ui_unit]->ui_addr)->en_addr)) & 0xff; sin = (struct sockaddr_in *)&es->es_if.if_addr; sin->sin_family = AF_INET; sin->sin_addr = if_makeaddr(es->es_if.if_net, es->es_if.if_host[0]); sin = (struct sockaddr_in *)&es->es_if.if_broadaddr; sin->sin_family = AF_INET; sin->sin_addr = if_makeaddr(es->es_if.if_net, 0); es->es_if.if_flags = IFF_BROADCAST; es->es_if.if_init = eninit; es->es_if.if_output = enoutput; es->es_if.if_ubareset = enreset; es->es_ifuba.ifu_flags = UBA_NEEDBDP | UBA_NEED16 | UBA_CANTWAIT; if_attach(&es->es_if); } /* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */ enreset(unit, uban) int unit, uban; { register struct uba_device *ui; if (unit >= NEN || (ui = eninfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" en%d", unit); eninit(unit); } /* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */ eninit(unit) int unit; { register struct en_softc *es = &en_softc[unit]; register struct uba_device *ui = eninfo[unit]; register struct endevice *addr; int s; if (if_ubainit(&es->es_ifuba, ui->ui_ubanum, sizeof (struct en_header), (int)btoc(ENMRU)) == 0) { printf("en%d: can't initialize\n", unit); es->es_if.if_flags &= ~IFF_UP; return; } addr = (struct endevice *)ui->ui_addr; addr->en_istat = addr->en_ostat = 0; /* * Hang a receive and start any * pending writes by faking a transmit complete. */ s = splimp(); addr->en_iba = es->es_ifuba.ifu_r.ifrw_info; addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1; addr->en_istat = EN_IEN|EN_GO; es->es_oactive = 1; es->es_if.if_flags |= IFF_UP; enxint(unit); splx(s); if_rtinit(&es->es_if, RTF_UP); } int enalldelay = 0; int enlastdel = 50; int enlastmask = (~0) << 5; /* * Start or restart output on interface. * If interface is already active, then this is a retransmit * after a collision, and just restuff registers and delay. * If interface is not already active, get another datagram * to send off of the interface queue, and map it to the interface * before starting the output. */ enstart(dev) dev_t dev; { int unit = ENUNIT(dev); struct uba_device *ui = eninfo[unit]; register struct en_softc *es = &en_softc[unit]; register struct endevice *addr; struct mbuf *m; int dest; if (es->es_oactive) goto restart; /* * Not already active: dequeue another request * and map it to the UNIBUS. If no more requests, * just return. */ IF_DEQUEUE(&es->es_if.if_snd, m); if (m == 0) { es->es_oactive = 0; return; } dest = mtod(m, struct en_header *)->en_dhost; es->es_olen = if_wubaput(&es->es_ifuba, m); /* * Ethernet cannot take back-to-back packets (no * buffering in interface. To help avoid overrunning * receivers, enforce a small delay (about 1ms) in interface: * * between all packets when enalldelay * * whenever last packet was broadcast * * whenever this packet is to same host as last packet */ if (enalldelay || es->es_lastx == 0 || es->es_lastx == dest) { es->es_delay = enlastdel; es->es_mask = enlastmask; } es->es_lastx = dest; restart: addr = (struct endevice *)ui->ui_addr; addr->en_oba = (int)es->es_ifuba.ifu_w.ifrw_info; addr->en_odelay = es->es_delay; addr->en_owc = -((es->es_olen + 1) >> 1); addr->en_ostat = EN_IEN|EN_GO; es->es_oactive = 1; } /* * Ethernet interface transmitter interrupt. * Start another output if more data to send. */ enxint(unit) int unit; { register struct uba_device *ui = eninfo[unit]; register struct en_softc *es = &en_softc[unit]; register struct endevice *addr = (struct endevice *)ui->ui_addr; if (es->es_oactive == 0) return; if (es->es_mask && (addr->en_ostat&EN_OERROR)) { es->es_if.if_oerrors++; endocoll(unit); return; } es->es_if.if_opackets++; es->es_oactive = 0; es->es_delay = 0; es->es_mask = ~0; if (es->es_ifuba.ifu_xtofree) { m_freem(es->es_ifuba.ifu_xtofree); es->es_ifuba.ifu_xtofree = 0; } if (es->es_if.if_snd.ifq_head == 0) { es->es_lastx = 256; /* putatively illegal */ return; } enstart(unit); } /* * Collision on ethernet interface. Do exponential * backoff, and retransmit. If have backed off all * the way print warning diagnostic, and drop packet. */ encollide(unit) int unit; { struct en_softc *es = &en_softc[unit]; es->es_if.if_collisions++; if (es->es_oactive == 0) return; endocoll(unit); } endocoll(unit) int unit; { register struct en_softc *es = &en_softc[unit]; /* * Es_mask is a 16 bit number with n low zero bits, with * n the number of backoffs. When es_mask is 0 we have * backed off 16 times, and give up. */ if (es->es_mask == 0) { printf("en%d: send error\n", unit); enxint(unit); return; } /* * Another backoff. Restart with delay based on n low bits * of the interval timer. */ es->es_mask <<= 1; es->es_delay = mfpr(ICR) &~ es->es_mask; enstart(unit); } struct sockaddr_pup pupsrc = { AF_PUP }; struct sockaddr_pup pupdst = { AF_PUP }; struct sockproto pupproto = { PF_PUP }; /* * Ethernet interface receiver interrupt. * If input error just drop packet. * Otherwise purge input buffered data path and examine * packet to determine type. If can't determine length * from type, then have to drop packet. Othewise decapsulate * packet based on type and pass to type specific higher-level * input routine. */ enrint(unit) int unit; { register struct en_softc *es = &en_softc[unit]; struct endevice *addr = (struct endevice *)eninfo[unit]->ui_addr; register struct en_header *en; struct mbuf *m; int len, plen; short resid; register struct ifqueue *inq; int off; es->es_if.if_ipackets++; if (addr->en_istat&EN_IERROR) { es->es_if.if_ierrors++; goto setup; } /* * Calculate input data length. * Get pointer to ethernet header (in input buffer). * Deal with trailer protocol: if type is PUP trailer * get true type from first 16-bit word past data. * Remember that type was trailer by setting off. */ resid = addr->en_iwc; if (resid) resid |= 0176000; len = (((sizeof (struct en_header) + ENMRU) >> 1) + resid) << 1; len -= sizeof (struct en_header); if (len > ENMRU) goto setup; /* sanity */ en = (struct en_header *)(es->es_ifuba.ifu_r.ifrw_addr); #define endataaddr(en, off, type) ((type)(((caddr_t)((en)+1)+(off)))) if (en->en_type >= ENPUP_TRAIL && en->en_type < ENPUP_TRAIL+ENPUP_NTRAILER) { off = (en->en_type - ENPUP_TRAIL) * 512; if (off > ENMTU) goto setup; /* sanity */ en->en_type = *endataaddr(en, off, u_short *); resid = *(endataaddr(en, off+2, u_short *)); if (off + resid > len) goto setup; /* sanity */ len = off + resid; } else off = 0; if (len == 0) goto setup; /* * Pull packet off interface. Off is nonzero if packet * has trailing header; if_rubaget will then force this header * information to be at the front, but we still have to drop * the type and length which are at the front of any trailer data. */ m = if_rubaget(&es->es_ifuba, len, off, &es->es_if); if (m == 0) goto setup; if (off) { m->m_off += 2 * sizeof (u_short); m->m_len -= 2 * sizeof (u_short); } switch (en->en_type) { #ifdef INET case ENPUP_IPTYPE: schednetisr(NETISR_IP); inq = &ipintrq; break; #endif #ifdef PUP case ENPUP_PUPTYPE: { struct pup_header *pup = mtod(m, struct pup_header *); pupproto.sp_protocol = pup->pup_type; pupdst.spup_addr = pup->pup_dport; pupsrc.spup_addr = pup->pup_sport; raw_input(m, &pupproto, (struct sockaddr *)&pupsrc, (struct sockaddr *)&pupdst); goto setup; } #endif default: m_freem(m); goto setup; } if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); } else IF_ENQUEUE(inq, m); setup: /* * Reset for next packet. */ addr->en_iba = es->es_ifuba.ifu_r.ifrw_info; addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1; addr->en_istat = EN_IEN|EN_GO; } /* * Ethernet output routine. * Encapsulate a packet of type family for the local net. * Use trailer local net encapsulation if enough data in first * packet leaves a multiple of 512 bytes of data in remainder. */ enoutput(ifp, m0, dst) struct ifnet *ifp; struct mbuf *m0; struct sockaddr *dst; { int type, dest, s, error; register struct mbuf *m = m0; register struct en_header *en; register int off; switch (dst->sa_family) { #ifdef INET case AF_INET: dest = ((struct sockaddr_in *)dst)->sin_addr.s_addr; if (dest & 0x00ffff00) { error = EPERM; /* ??? */ goto bad; } dest = (dest >> 24) & 0xff; off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; if (off > 0 && (off & 0x1ff) == 0 && m->m_off >= MMINOFF + 2 * sizeof (u_short)) { type = ENPUP_TRAIL + (off>>9); m->m_off -= 2 * sizeof (u_short); m->m_len += 2 * sizeof (u_short); *mtod(m, u_short *) = ENPUP_IPTYPE; *(mtod(m, u_short *) + 1) = m->m_len; goto gottrailertype; } type = ENPUP_IPTYPE; off = 0; goto gottype; #endif #ifdef PUP case AF_PUP: dest = ((struct sockaddr_pup *)dst)->spup_addr.pp_host; type = ENPUP_PUPTYPE; off = 0; goto gottype; #endif default: printf("en%d: can't handle af%d\n", ifp->if_unit, dst->sa_family); error = EAFNOSUPPORT; goto bad; } gottrailertype: /* * Packet to be sent as trailer: move first packet * (control information) to end of chain. */ while (m->m_next) m = m->m_next; m->m_next = m0; m = m0->m_next; m0->m_next = 0; m0 = m; gottype: /* * Add local net header. If no space in first mbuf, * allocate another. */ if (m->m_off > MMAXOFF || MMINOFF + sizeof (struct en_header) > m->m_off) { m = m_get(M_DONTWAIT); if (m == 0) { error = ENOBUFS; goto bad; } m->m_next = m0; m->m_off = MMINOFF; m->m_len = sizeof (struct en_header); } else { m->m_off -= sizeof (struct en_header); m->m_len += sizeof (struct en_header); } en = mtod(m, struct en_header *); en->en_shost = ifp->if_host[0]; en->en_dhost = dest; en->en_type = type; /* * Queue message on interface, and start output if interface * not yet active. */ s = splimp(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); error = ENOBUFS; goto qfull; } IF_ENQUEUE(&ifp->if_snd, m); if (en_softc[ifp->if_unit].es_oactive == 0) enstart(ifp->if_unit); splx(s); return (0); qfull: m0 = m; splx(s); bad: m_freem(m0); return (error); } #endif NEN > 0 ; if (unit >= NEN || (ui = eninfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" en%d", unit); eninit(unit); } /* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */ eninit(unit) int unit; { register ssys/pdpif/if_il.c 644 3 12 46100 5703424507 7230 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_il.c 2.2 (2.11BSD GTE) 1/6/95 * * 1/6/95 - sms: start of network data was already computed in sys_net.c, * it should no longer be done in this driver. Using 'startnet' * as an initialization done flag caused the driver to skip * testing for a UNIBUS MAP on an 11/44. *crash*. * Trailer output capability was removed (it was already gone from * the receive routine as well as several other ether drivers). * 12/29/92 - sms: remove Q22 ifdefs, replacing them with runtime tests * for a Unibus Map. * 2.11BSD - Remove ilreset since that's a vax'ism and is never * called on a pdp-11. Since the unibus resources are * allocated in the attach routine and ubarelse is a noop * remove the second allocation in ilinit. uballoc calling * convention altered - sms 9/7/90 */ #include "il.h" #if NIL > 0 /* * Interlan Ethernet Communications Controller interface */ #include "param.h" #include "../machine/seg.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "domain.h" #include "protosw.h" #include "socket.h" #include "ioctl.h" #include "if_ilreg.h" #include "if_il.h" #include "if_uba.h" #include "errno.h" #include "../pdpuba/ubavar.h" #include "map.h" #include "uba.h" #include "../net/if.h" #include "../net/netisr.h" #ifdef INET #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netinet/in_var.h" #include "../netinet/ip.h" #include "../netinet/ip_var.h" #include "../netinet/if_ether.h" #endif #ifdef NS #include "../netns/ns.h" #include "../netns/ns_if.h" #endif int ilprobe(), ilattach(), ilrint(), ilcint(); struct uba_device *ilinfo[NIL]; u_short ilstd[] = { 0 }; struct uba_driver ildriver = { ilprobe, 0, ilattach, 0, ilstd, "il", ilinfo }; #define ILUNIT(x) minor(x) int ilinit(),iloutput(),ilioctl(),ilwatch(); int ildebug = 0; static short ilub; extern long startnet; /* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * is_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... * We also have, for each interface, a UBA interface structure, which * contains information about the UNIBUS resources held by the interface: * map registers, buffered data paths, etc. Information is cached in this * structure for use by the if_uba.c routines in running the interface * efficiently. */ struct il_softc { struct arpcom is_ac; /* Ethernet common part */ #define is_if is_ac.ac_if /* network-visible interface */ #define is_addr is_ac.ac_enaddr /* hardware Ethernet address */ struct ifuba is_ifuba; /* UNIBUS resources */ int is_flags; #define ILF_OACTIVE 0x1 /* output is active */ #define ILF_RCVPENDING 0x2 /* start rcv in ilcint */ #define ILF_STATPENDING 0x4 /* stat cmd pending */ #define ILF_RUNNING 0x8 /* board is running */ #define ILF_SETADDR 0x10 /* physical address is changed */ short is_lastcmd; /* can't read csr, so must save it */ short is_scaninterval; /* interval of stat collection */ #define ILWATCHINTERVAL 60 /* once every 60 seconds */ struct il_stats is_stats; /* holds on-board statistics */ struct il_stats is_sum; /* summation over time */ long is_ubaddr; /* mapping registers of is_stats */ } il_softc[NIL]; ilprobe(reg) caddr_t reg; { #ifdef notdef register int br, cvec; /* r11, r10 value-result */ register struct ildevice *addr = (struct ildevice *)reg; register i; #ifdef lint br = 0; cvec = br; br = cvec; i = 0; ilrint(i); ilcint(i); ilwatch(i); #endif addr->il_csr = ILC_OFFLINE|IL_CIE; DELAY(100000L); i = addr->il_csr; /* clear CDONE */ if (cvec > 0 && cvec != 0x200) cvec -= 4; return (1); #endif } /* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. A STATUS command is done to get the ethernet * address and other interesting data. */ ilattach(ui) struct uba_device *ui; { register struct il_softc *is = &il_softc[ui->ui_unit]; register struct ifnet *ifp = &is->is_if; register struct ildevice *addr = (struct ildevice *)ui->ui_addr; ilub = mfkd(&ubmap); /* get copy of kernel UBmap flag */ ifp->if_unit = ui->ui_unit; ifp->if_name = "il"; ifp->if_mtu = ETHERMTU; ifp->if_flags = IFF_BROADCAST; /* * Reset the board and map the statistics * buffer onto the Unibus. */ addr->il_csr = ILC_RESET; (void)ilwait(ui, "reset"); if (ilub) { is->is_ubaddr = uballoc((caddr_t)&is->is_stats,sizeof(struct il_stats)); addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT; } else { is->is_ubaddr = (long)((caddr_t)&is->is_stats) + startnet; addr->il_ber = hiint(is->is_ubaddr) & 077; addr->il_csr = ILC_STAT; } addr->il_bar = loint(is->is_ubaddr); addr->il_bcr = sizeof (struct il_stats); (void)ilwait(ui, "status"); ubarelse(ui->ui_ubanum, &is->is_ubaddr); /* NOOP on pdp-11 */ if (ildebug) printf("il%d: module=%s firmware=%s\n", ui->ui_unit, is->is_stats.ils_module, is->is_stats.ils_firmware); bcopy((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr, sizeof (is->is_addr)); printf("il%d: hardware address %s\n", ui->ui_unit, ether_sprintf(is->is_addr)); ifp->if_init = ilinit; ifp->if_output = iloutput; ifp->if_ioctl = ilioctl; ifp->if_reset = 0; is->is_ifuba.ifu_flags = UBA_CANTWAIT; if_attach(ifp); } ilwait(ui, op) struct uba_device *ui; char *op; { register struct ildevice *addr = (struct ildevice *)ui->ui_addr; while ((addr->il_csr&IL_CDONE) == 0) ; if (addr->il_csr&IL_STATUS) { printf("il%d: %s failed, csr=%b\n", ui->ui_unit, op, addr->il_csr, IL_BITS); return (-1); } return (0); } /* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */ ilinit(unit) int unit; { register struct il_softc *is = &il_softc[unit]; register struct uba_device *ui = ilinfo[unit]; register struct ildevice *addr; struct ifnet *ifp = &is->is_if; int s; /* not yet, if address still unknown */ if (ifp->if_addrlist == (struct ifaddr *)0) return; if (is->is_flags & ILF_RUNNING) return; if ((ifp->if_flags & IFF_RUNNING) == 0) { if (if_ubainit(&is->is_ifuba, ui->ui_ubanum, sizeof (struct il_rheader), (int)btoc(ETHERMTU)) == 0) { printf("il%d: can't initialize\n", unit); is->is_if.if_flags &= ~IFF_UP; return; } /* * since is->is_ubaddr is set in ilattach and ubarelse is a NOOP the * allocation of unibus resources here has been removed. */ } ifp->if_watchdog = ilwatch; is->is_scaninterval = ILWATCHINTERVAL; ifp->if_timer = is->is_scaninterval; addr = (struct ildevice *)ui->ui_addr; /* * Turn off source address insertion (it's faster this way), * and set board online. Former doesn't work if board is * already online (happens on ubareset), so we put it offline * first. */ s = splimp(); addr->il_csr = ILC_RESET; if (ilwait(ui, "hardware diag")) { is->is_if.if_flags &= ~IFF_UP; splx(s); return; } addr->il_csr = ILC_CISA; while ((addr->il_csr & IL_CDONE) == 0) ; /* * If we must reprogram this board's physical ethernet * address (as for secondary NS interfaces), we do so * before putting it on line, and starting receive requests. * If you try this on an older 1010 board, it will total * wedge the board. */ if (is->is_flags & ILF_SETADDR) { bcopy((caddr_t)is->is_addr, (caddr_t)&is->is_stats, sizeof is->is_addr); addr->il_bar = loint(is->is_ubaddr); addr->il_bcr = sizeof is->is_addr; if (!ilub) { addr->il_ber = hiint(is->is_ubaddr) & 077; addr->il_csr = ILC_LDPA; } else addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_LDPA; if (ilwait(ui, "setaddr")) return; addr->il_bar = loint(is->is_ubaddr); addr->il_bcr = sizeof (struct il_stats); if (!ilub) { addr->il_ber = hiint(is->is_ubaddr) & 077; addr->il_csr = ILC_STAT; } else addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT; if (ilwait(ui, "verifying setaddr")) return; if (bcmp((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr, sizeof (is->is_addr)) != 0) { printf("il%d: setaddr didn't work\n", ui->ui_unit); return; } } /* * Set board online. * Hang receive buffer and start any pending * writes by faking a transmit complete. * Receive bcr is not a multiple of 8 so buffer * chaining can't happen. */ addr->il_csr = ILC_ONLINE; while ((addr->il_csr & IL_CDONE) == 0) ; addr->il_bar = loint(is->is_ifuba.ifu_r.ifrw_info); addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6; if (!ilub) { addr->il_ber = hiint(is->is_ifuba.ifu_r.ifrw_info) & 077; addr->il_csr = ILC_RCV|IL_RIE; } else addr->il_csr = ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE; while ((addr->il_csr & IL_CDONE) == 0) ; is->is_flags = ILF_OACTIVE; is->is_if.if_flags |= IFF_RUNNING; is->is_flags |= ILF_RUNNING; is->is_lastcmd = 0; ilcint(unit); splx(s); } /* * Start output on interface. * Get another datagram to send off of the interface queue, * and map it to the interface before starting the output. */ ilstart(dev) dev_t dev; { int unit = ILUNIT(dev), len; struct uba_device *ui = ilinfo[unit]; register struct il_softc *is = &il_softc[unit]; register struct ildevice *addr; struct mbuf *m; short csr; IF_DEQUEUE(&is->is_if.if_snd, m); addr = (struct ildevice *)ui->ui_addr; if (m == 0) { if ((is->is_flags & ILF_STATPENDING) == 0) return; addr->il_bar = loint(is->is_ubaddr); addr->il_bcr = sizeof (struct il_stats); if (!ilub) { addr->il_ber = hiint(is->is_ubaddr) & 077; csr = ILC_STAT|IL_RIE|IL_CIE; } else csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT|IL_RIE|IL_CIE; is->is_flags &= ~ILF_STATPENDING; goto startcmd; } len = if_wubaput(&is->is_ifuba, m); /* * Ensure minimum packet length. * This makes the safe assumtion that there are no virtual holes * after the data. * For security, it might be wise to zero out the added bytes, * but we're mainly interested in speed at the moment. */ if (len - sizeof(struct ether_header) < ETHERMIN) len = ETHERMIN + sizeof(struct ether_header); addr->il_bar = loint(is->is_ifuba.ifu_w.ifrw_info); addr->il_bcr = len; if (!ilub) { addr->il_ber = hiint(is->is_ifuba.ifu_w.ifrw_info) & 077; csr = ILC_XMIT|IL_CIE|IL_RIE; } else csr = ((is->is_ifuba.ifu_w.ifrw_info >> 2) & IL_EUA)|ILC_XMIT|IL_CIE|IL_RIE; startcmd: is->is_lastcmd = csr & IL_CMD; addr->il_csr = csr; is->is_flags |= ILF_OACTIVE; } /* * Command done interrupt. */ ilcint(unit) int unit; { register struct il_softc *is = &il_softc[unit]; struct uba_device *ui = ilinfo[unit]; register struct ildevice *addr = (struct ildevice *)ui->ui_addr; short csr; if ((is->is_flags & ILF_OACTIVE) == 0) { printf("il%d: stray xmit interrupt, csr=%b\n", unit, addr->il_csr, IL_BITS); return; } csr = addr->il_csr; /* * Hang receive buffer if it couldn't * be done earlier (in ilrint). */ if (is->is_flags & ILF_RCVPENDING) { int s; addr->il_bar = loint(is->is_ifuba.ifu_r.ifrw_info); addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6; if (!ilub) { addr->il_ber = hiint(is->is_ifuba.ifu_r.ifrw_info)&077; addr->il_csr = ILC_RCV|IL_RIE; } else addr->il_csr = ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE; s = splhigh(); while ((addr->il_csr & IL_CDONE) == 0) ; splx(s); is->is_flags &= ~ILF_RCVPENDING; } is->is_flags &= ~ILF_OACTIVE; csr &= IL_STATUS; switch (is->is_lastcmd) { case ILC_XMIT: is->is_if.if_opackets++; if (csr > ILERR_RETRIES) is->is_if.if_oerrors++; break; case ILC_STAT: if (csr == ILERR_SUCCESS) iltotal(is); break; } if (is->is_ifuba.ifu_xtofree) { m_freem(is->is_ifuba.ifu_xtofree); is->is_ifuba.ifu_xtofree = 0; } ilstart(unit); } /* * Ethernet interface receiver interrupt. * If input error just drop packet. * Otherwise purge input buffered data path and examine * packet to determine type. If can't determine length * from type, then have to drop packet. Othewise decapsulate * packet based on type and pass to type specific higher-level * input routine. */ ilrint(unit) int unit; { register struct il_softc *is = &il_softc[unit]; struct ildevice *addr = (struct ildevice *)ilinfo[unit]->ui_addr; register struct il_rheader *il; struct mbuf *m; int len, off, resid, s; int status; /* save status locally so only one restorseg5 */ register struct ifqueue *inq; register int type; segm sav5; #define MAPBUFDESC (((btoc(sizeof(struct il_rheader) + ETHERMTU)-1)<<8)|RW) is->is_if.if_ipackets++; saveseg5(sav5); mapseg5(is->is_ifuba.ifu_r.ifrw_click, MAPBUFDESC); il = (struct il_rheader *)SEG5; len = il->ilr_length - sizeof(struct il_rheader); type = ntohs((u_short)il->ilr_type); status = il->ilr_status; restorseg5(sav5); if ((status&(ILFSTAT_A|ILFSTAT_C)) || len < ETHERMIN || len > ETHERMTU) { is->is_if.if_ierrors++; goto setup; } /* * Ignore zero length packets and packets with trailers. */ if (!len || type >= ETHERTYPE_TRAIL && type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) goto setup; /* * Pull packet off interface. */ m = if_rubaget(&is->is_ifuba, len, 0, &is->is_if); if (m == 0) goto setup; switch (type) { #ifdef INET case ETHERTYPE_IP: schednetisr(NETISR_IP); inq = &ipintrq; break; case ETHERTYPE_ARP: arpinput(&is->is_ac, m); goto setup; #endif #ifdef NS case ETHERTYPE_NS: schednetisr(NETISR_NS); inq = &nsintrq; break; #endif default: m_freem(m); goto setup; } s = splimp(); if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); } else IF_ENQUEUE(inq, m); splx(s); setup: /* * Reset for next packet if possible. * If waiting for transmit command completion, set flag * and wait until command completes. */ if (is->is_flags & ILF_OACTIVE) { is->is_flags |= ILF_RCVPENDING; return; } addr->il_bar = loint(is->is_ifuba.ifu_r.ifrw_info); addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6; if (!ilub) { addr->il_ber = hiint(is->is_ifuba.ifu_r.ifrw_info) & 077; addr->il_csr = ILC_RCV|IL_RIE; } else addr->il_csr = ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE; s = splhigh(); while ((addr->il_csr & IL_CDONE) == 0) ; splx(s); } /* * Ethernet output routine. * Encapsulate a packet of type family for the local net. * Use trailer local net encapsulation if enough data in first * packet leaves a multiple of 512 bytes of data in remainder. */ iloutput(ifp, m0, dst) struct ifnet *ifp; struct mbuf *m0; struct sockaddr *dst; { int type, s; u_char edst[6]; struct in_addr idst; register struct il_softc *is = &il_softc[ifp->if_unit]; register struct mbuf *m = m0; register struct ether_header *il; register int off; int usetrailers; if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { m_freem(m); return(ENETDOWN); } switch (dst->sa_family) { #ifdef INET case AF_INET: idst = ((struct sockaddr_in *)dst)->sin_addr; if (!arpresolve(&is->is_ac, m, &idst, edst, &usetrailers)) return (0); /* if not yet resolved */ type = ETHERTYPE_IP; off = 0; goto gottype; #endif #ifdef NS case AF_NS: type = ETHERTYPE_NS; bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), (caddr_t)edst, sizeof (edst)); off = 0; goto gottype; #endif case AF_UNSPEC: il = (struct ether_header *)dst->sa_data; bcopy((caddr_t)il->ether_dhost, (caddr_t)edst, sizeof (edst)); type = il->ether_type; goto gottype; default: printf("il%d: can't handle af%d\n", ifp->if_unit, dst->sa_family); m_freem(m); return(EAFNOSUPPORT); } gottype: /* * Add local net header. If no space in first mbuf, * allocate another. */ if (m->m_off > MMAXOFF || MMINOFF + sizeof (struct ether_header) > m->m_off) { m = m_get(M_DONTWAIT, MT_HEADER); if (m == 0) { m_freem(m0); return(ENOBUFS); } m->m_next = m0; m->m_off = MMINOFF; m->m_len = sizeof (struct ether_header); } else { m->m_off -= sizeof (struct ether_header); m->m_len += sizeof (struct ether_header); } il = mtod(m, struct ether_header *); il->ether_type = htons((u_short)type); bcopy((caddr_t)edst, (caddr_t)il->ether_dhost, sizeof (edst)); bcopy((caddr_t)is->is_addr, (caddr_t)il->ether_shost, sizeof(il->ether_shost)); /* * Queue message on interface, and start output if interface * not yet active. */ s = splimp(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); splx(s); m_freem(m); return(ENOBUFS); } IF_ENQUEUE(&ifp->if_snd, m); if ((is->is_flags & ILF_OACTIVE) == 0) ilstart(ifp->if_unit); splx(s); return (0); } /* * Watchdog routine, request statistics from board. */ ilwatch(unit) int unit; { register struct il_softc *is = &il_softc[unit]; register struct ifnet *ifp = &is->is_if; int s; if (is->is_flags & ILF_STATPENDING) { ifp->if_timer = is->is_scaninterval; return; } s = splimp(); is->is_flags |= ILF_STATPENDING; if ((is->is_flags & ILF_OACTIVE) == 0) ilstart(ifp->if_unit); splx(s); ifp->if_timer = is->is_scaninterval; } /* * Total up the on-board statistics. */ iltotal(is) register struct il_softc *is; { register u_short *interval, *sum, *end; interval = &is->is_stats.ils_frames; sum = &is->is_sum.ils_frames; end = is->is_sum.ils_fill2; while (sum < end) *sum++ += *interval++; is->is_if.if_collisions = is->is_sum.ils_collis; } /* * Process an ioctl request. */ ilioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { register struct ifaddr *ifa = (struct ifaddr *)data; register struct il_softc *is = &il_softc[ifp->if_unit]; int s = splimp(), error = 0; /* printf("\tilioctl new:%X\n", ntohl(IA_SIN(ifa)->sin_addr.s_addr));/**/ switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; ilinit(ifp->if_unit); switch (ifa->ifa_addr.sa_family) { #ifdef INET case AF_INET: ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr; arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); break; #endif INET #ifdef NS case AF_NS: { register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); if (ns_nullhost(*ina)) { ina->x_host = * (union ns_host *) (il_softc[ifp->if_unit].is_addr); } else { il_setaddr(ina->x_host.c_host, ifp->if_unit); return (0); } break; } #endif NS } break; case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_UP) == 0 && is->is_flags & ILF_RUNNING) { ((struct ildevice *) (ilinfo[ifp->if_unit]->ui_addr))->il_csr = ILC_RESET; is->is_flags &= ~ILF_RUNNING; } else if (ifp->if_flags & IFF_UP && (is->is_flags & ILF_RUNNING) == 0) ilinit(ifp->if_unit); break; default: error = EINVAL; } splx(s); return (error); } /* * set ethernet address for unit */ #ifdef NS /* NS way to set addr */ il_setaddr(physaddr, unit) u_char *physaddr; int unit; { register struct il_softc *is = &il_softc[unit]; if (! (is->is_flags & ILF_RUNNING)) return; bcopy((caddr_t)physaddr, (caddr_t)is->is_addr, sizeof is->is_addr); is->is_flags &= ~ILF_RUNNING; is->is_flags |= ILF_SETADDR; ilinit(unit); } #endif NS #endif NIL am to send off of the interface queue, * and map it to the interface before starting the output. */ ilstart(dev) dev_t dev; { int unit = ILUNIT(dev), len; struct uba_device *ui = ilinfo[unit]; register struct il_softc *is = &il_softc[unit]; register struct ildevice *addr; struct mbuf *m; short csr; IF_DEQUEUE(&is->is_if.if_snd, m); addr = (struct ildevice *)ui->ui_addr; if (m == 0) { if ((is->is_flags & ILF_STATPENDING) ==sys/pdpif/if_dmc.c 444 0 12 22430 4672541565 7372 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_dmc.c 1.1 (2.10BSD Berkeley) 12/1/86 */ #include "dmc.h" #if NDMC > 0 #define printd if(dmcdebug)printf int dmcdebug = 1; /* * DMC11 device driver, internet version * * TODO * allow more than one outstanding read or write. */ #include "param.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "ioctl.h" #include "tty.h" #include "domain.h" #include "protosw.h" #include "socket.h" #include "pdpuba/ubavar.h" #include "netinet/in.h" #include "netinet/in_systm.h" #include "net/if.h" #include "pdpif/if_uba.h" #include "pdpif/if_dmc.h" #include "netinet/ip.h" #include "netinet/in_var.h" #include "netinet/ip_var.h" #include "net/route.h" #include "net/netisr.h" #include "errno.h" /* * Driver information for auto-configuration stuff. */ int dmcprobe(), dmcattach(), dmcinit(), dmcoutput(); struct uba_device *dmcinfo[NDMC]; u_short dmcstd[] = { 0 }; struct uba_driver dmcdriver = { dmcprobe, 0, dmcattach, 0, dmcstd, "dmc", dmcinfo }; #define DMC_AF 0xff /* 8 bits of address type in ui_flags */ #define DMC_NET 0xffffff00 /* 24 bits of net number in ui_flags */ /* * DMC software status per interface. * * Each interface is referenced by a network interface structure, * sc_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... * We also have, for each interface, a UBA interface structure, which * contains information about the UNIBUS resources held by the interface: * map registers, buffered data paths, etc. Information is cached in this * structure for use by the if_uba.c routines in running the interface * efficiently. */ struct dmc_softc { struct ifnet sc_if; /* network-visible interface */ struct ifuba sc_ifuba; /* UNIBUS resources */ short sc_flag; /* flags */ short sc_oactive; /* output active */ int sc_ubinfo; /* UBA mapping info for base table */ struct clist sc_que; /* command queue */ } dmc_softc[NDMC]; /* flags */ #define DMCRUN 01 #define DMCBMAPPED 02 /* base table mapped */ struct dmc_base { short d_base[128]; /* DMC base table */ } dmc_base[NDMC]; #define loword(x) ((short *)&x)[0] #define hiword(x) ((short *)&x)[1] dmcprobe(reg) caddr_t reg; { register int br, cvec; register struct dmcdevice *addr = (struct dmcdevice *)reg; register int i; #ifdef lint br = 0; cvec = br; br = cvec; dmcrint(0); dmcxint(0); #endif addr->bsel1 = DMC_MCLR; for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--) ; if ((addr->bsel1 & DMC_RUN) == 0) return (0); addr->bsel1 &= ~DMC_MCLR; addr->bsel0 = DMC_RQI|DMC_IEI; DELAY(100000L); addr->bsel1 = DMC_MCLR; for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--) ; #ifdef ECHACK br = 0x16; #endif return (1); } /* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */ dmcattach(ui) register struct uba_device *ui; { register struct dmc_softc *sc = &dmc_softc[ui->ui_unit]; register struct sockaddr_in *sin; sc->sc_if.if_unit = ui->ui_unit; sc->sc_if.if_name = "dmc"; sc->sc_if.if_mtu = DMCMTU; sc->sc_if.if_init = dmcinit; sc->sc_if.if_output = dmcoutput; sc->sc_if.if_reset = 0; sc->sc_if.if_flags = IFF_POINTOPOINT; /* DON'T KNOW IF THIS WILL WORK WITH A BDP AT HIGH SPEEDS */ sc->sc_ifuba.ifu_flags = UBA_NEEDBDP | UBA_CANTWAIT; if_attach(&sc->sc_if); } /* * Initialization of interface; reinitialize UNIBUS usage. */ dmcinit(unit) int unit; { register struct dmc_softc *sc = &dmc_softc[unit]; register struct uba_device *ui = dmcinfo[unit]; register struct dmcdevice *addr; int base; printd("dmcinit\n"); if ((sc->sc_flag&DMCBMAPPED) == 0) { sc->sc_ubinfo = uballoc((caddr_t)&dmc_base[unit], sizeof (struct dmc_base)); sc->sc_flag |= DMCBMAPPED; } if (if_ubainit(&sc->sc_ifuba, ui->ui_ubanum, 0, (int)btoc(DMCMTU)) == 0) { printf("dmc%d: can't initialize\n", unit); sc->sc_if.if_flags &= ~IFF_UP; return; } addr = (struct dmcdevice *)ui->ui_addr; addr->bsel2 |= DMC_IEO; base = sc->sc_ubinfo & 0x3ffff; printd(" base 0x%x\n", base); dmcload(sc, DMC_BASEI, base, (base>>2)&DMC_XMEM); dmcload(sc, DMC_CNTLI, 0, 0); base = sc->sc_ifuba.ifu_r.ifrw_info & 0x3ffff; dmcload(sc, DMC_READ, base, ((base>>2)&DMC_XMEM)|DMCMTU); printd(" first read queued, addr 0x%x\n", base); sc->sc_if.if_flags |= IFF_UP; } /* * Start output on interface. Get another datagram * to send from the interface queue and map it to * the interface before starting output. */ dmcstart(dev) dev_t dev; { int unit = minor(dev); struct uba_device *ui = dmcinfo[unit]; register struct dmc_softc *sc = &dmc_softc[unit]; int addr, len; struct mbuf *m; printd("dmcstart\n"); /* * Dequeue a request and map it to the UNIBUS. * If no more requests, just return. */ IF_DEQUEUE(&sc->sc_if.if_snd, m); if (m == 0) return; len = if_wubaput(&sc->sc_ifuba, m); addr = sc->sc_ifuba.ifu_w.ifrw_info & 0x3ffff; printd(" len %d, addr 0x%x, ", len, addr); printd("mr 0x%lx\n", sc->sc_ifuba.ifu_w.ifrw_info); dmcload(sc, DMC_WRITE, addr, (len&DMC_CCOUNT)|((addr>>2)&DMC_XMEM)); sc->sc_oactive = 1; } /* * Utility routine to load the DMC device registers. */ dmcload(sc, type, w0, w1) register struct dmc_softc *sc; int type, w0, w1; { register struct dmcdevice *addr; register int unit, sps, n; printd("dmcload: 0x%x 0x%x 0x%x\n", type, w0, w1); unit = sc - dmc_softc; addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr; sps = splimp(); if ((n = sc->sc_que.c_cc) == 0) addr->bsel0 = type | DMC_RQI; else (void) putc(type | DMC_RQI, &sc->sc_que); (void) putw(w0, &sc->sc_que); (void) putw(w1, &sc->sc_que); if (n == 0) dmcrint(unit); splx(sps); } /* * DMC interface receiver interrupt. * Ready to accept another command, * pull one off the command queue. */ dmcrint(unit) int unit; { register struct dmc_softc *sc; register struct dmcdevice *addr; register int n; addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr; sc = &dmc_softc[unit]; while (addr->bsel0&DMC_RDYI) { addr->sel4 = getw(&sc->sc_que); addr->sel6 = getw(&sc->sc_que); addr->bsel0 &= ~(DMC_IEI|DMC_RQI); while (addr->bsel0&DMC_RDYI) ; if (sc->sc_que.c_cc == 0) return; addr->bsel0 = getc(&sc->sc_que); n = RDYSCAN; while (n-- && (addr->bsel0&DMC_RDYI) == 0) ; } if (sc->sc_que.c_cc) addr->bsel0 |= DMC_IEI; } /* * DMC interface transmitter interrupt. * A transfer has completed, check for errors. * If it was a read, notify appropriate protocol. * If it was a write, pull the next one off the queue. */ dmcxint(unit) int unit; { register struct dmc_softc *sc; struct uba_device *ui = dmcinfo[unit]; struct dmcdevice *addr; struct mbuf *m; register struct ifqueue *inq; int arg, cmd, len; addr = (struct dmcdevice *)ui->ui_addr; arg = addr->sel6; cmd = addr->bsel2&7; addr->bsel2 &= ~DMC_RDYO; sc = &dmc_softc[unit]; printd("dmcxint\n"); switch (cmd) { case DMC_OUR: /* * A read has completed. Purge input buffered * data path. Pass packet to type specific * higher-level input routine. */ sc->sc_if.if_ipackets++; len = arg & DMC_CCOUNT; printd(" read done, len %d\n", len); switch (sc->sc_flag & DMC_AF) { #ifdef INET case AF_INET: schednetisr(NETISR_IP); inq = &ipintrq; break; #endif default: printf("dmc%d: unknown address type %d\n", unit, sc->sc_flag & DMC_AF); goto setup; } m = if_rubaget(&sc->sc_ifuba, len, 0, &sc->sc_if); if (m == 0) goto setup; if (IF_QFULL(inq)) { IF_DROP(inq); (void) m_freem(m); } else IF_ENQUEUE(inq, m); setup: arg = sc->sc_ifuba.ifu_r.ifrw_info & 0x3ffff; dmcload(sc, DMC_READ, arg, ((arg >> 2) & DMC_XMEM) | DMCMTU); return; case DMC_OUX: /* * A write has completed, start another * transfer if there is more data to send. */ if (sc->sc_oactive == 0) return; /* SHOULD IT BE A FATAL ERROR? */ printd(" write done\n"); sc->sc_if.if_opackets++; sc->sc_oactive = 0; if (sc->sc_ifuba.ifu_xtofree) { (void) m_freem(sc->sc_ifuba.ifu_xtofree); sc->sc_ifuba.ifu_xtofree = 0; } if (sc->sc_if.if_snd.ifq_head == 0) return; dmcstart(unit); return; case DMC_CNTLO: arg &= DMC_CNTMASK; if (arg&DMC_FATAL) { addr->bsel1 = DMC_MCLR; sc->sc_flag &= ~DMCRUN; /*** DO SOMETHING TO RESTART DEVICE ***/ printf("DMC FATAL ERROR 0%o\n", arg); } else { /* ACCUMULATE STATISTICS */ printf("DMC SOFT ERROR 0%o\n", arg); } return; default: printf("dmc%d: bad control %o\n", unit, cmd); } } /* * DMC output routine. * Just send the data, header was supplied by * upper level protocol routines. */ dmcoutput(ifp, m, dst) register struct ifnet *ifp; register struct mbuf *m; struct sockaddr *dst; { struct uba_device *ui = dmcinfo[ifp->if_unit]; int s; printd("dmcoutput\n"); if (dst->sa_family != AF_INET) { printf("dmc%d: af%d not supported\n", ifp->if_unit, AF_INET); m_freem(m); return (EAFNOSUPPORT); } s = splimp(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); m_freem(m); splx(s); return (ENOBUFS); } IF_ENQUEUE(&ifp->if_snd, m); if (dmc_softc[ifp->if_unit].sc_oactive == 0) dmcstart(ifp->if_unit); splx(s); return (0); } #endif NDMC ("dmcinit\n"); if ((sc->sc_flag&DMCBMAPPED) == 0) { sc->sc_ubinfo = uballoc((caddr_t)&dmc_base[unit], sizeof (struct dmc_base)); sc->sc_flag |= DMCBMAPPED; } if (if_ubainit(&sc->sc_ifuba, ui->ui_ubanum, 0, (int)btosys/pdpif/if_qe.c 644 0 12 57350 5757535331 7246 /* @(#)if_qe.c 1.2 (2.11BSD) 1995/05/20 */ /**************************************************************** * * * Licensed from Digital Equipment Corporation * * Copyright (c) * * Digital Equipment Corporation * * Maynard, Massachusetts * * 1985, 1986 * * All rights reserved. * * * * The Information in this software is subject to change * * without notice and should not be construed as a commitment * * by Digital Equipment Corporation. Digital makes no * * representations about the suitability of this software for * * any purpose. It is supplied "As Is" without expressed or * * implied warranty. * * * * If the Regents of the University of California or its * * licensees modify the software in a manner creating * * derivative copyright rights, appropriate copyright * * legends may be placed on the derivative work in addition * * to that set forth above. * * * ****************************************************************/ /* --------------------------------------------------------------------- * Modification History * * 16-Nov-90 -- sms@wlv.imsd.contel.com * Ported from 4.3BSD to 2.11BSD as a replacement for the previous * 2.10BSD deqna driver which was flakey. 'trailers' are completely * removed from this version - they are a bad idea and never really * worked. Advantage is taken of this being a Qbus driver - memory * is allocated from the system and physical addresses computed. * * 15-Apr-86 -- afd * Rename "unused_multi" to "qunused_multi" for extending Generic * kernel to MicroVAXen. * * 18-mar-86 -- jaw br/cvec changed to NOT use registers. * * 12 March 86 -- Jeff Chase * Modified to handle the new MCLGET macro * Changed if_qe_data.c to use more receive buffers * Added a flag to poke with adb to log qe_restarts on console * * 19 Oct 85 -- rjl * Changed the watch dog timer from 30 seconds to 3. VMS is using * less than 1 second in their's. Also turned the printf into an * mprintf. * * 09/16/85 -- Larry Cohen * Add 43bsd alpha tape changes for subnet routing * * 1 Aug 85 -- rjl * Panic on a non-existent memory interrupt and the case where a packet * was chained. The first should never happen because non-existant * memory interrupts cause a bus reset. The second should never happen * because we hang 2k input buffers on the device. * * 1 Aug 85 -- rich * Fixed the broadcast loopback code to handle Clusters without * wedging the system. * * 27 Feb. 85 -- ejf * Return default hardware address on ioctl request. * * 12 Feb. 85 -- ejf * Added internal extended loopback capability. * * 27 Dec. 84 -- rjl * Fixed bug that caused every other transmit descriptor to be used * instead of every descriptor. * * 21 Dec. 84 -- rjl * Added watchdog timer to mask hardware bug that causes device lockup. * * 18 Dec. 84 -- rjl * Reworked driver to use q-bus mapping routines. MicroVAX-I now does * copying instead of m-buf shuffleing. * A number of deficencies in the hardware/firmware were compensated * for. See comments in qestart and qerint. * * 14 Nov. 84 -- jf * Added usage counts for multicast addresses. * Updated general protocol support to allow access to the Ethernet * header. * * 04 Oct. 84 -- jf * Added support for new ioctls to add and delete multicast addresses * and set the physical address. * Add support for general protocols. * * 14 Aug. 84 -- rjl * Integrated Shannon changes. (allow arp above 1024 and ? ) * * 13 Feb. 84 -- rjl * * Initial version of driver. derived from IL driver. * --------------------------------------------------------------------- */ #include "qe.h" #if NQE > 0 /* * Digital Q-BUS to NI Adapter */ #include "param.h" #include "pdp/seg.h" #include "pdp/psl.h" #include "map.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "protosw.h" #include "socket.h" #include "ioctl.h" #include "errno.h" #include "syslog.h" #include "time.h" #include "kernel.h" #include "../net/if.h" #include "../net/netisr.h" #include "../net/route.h" #ifdef INET #include "domain.h" #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netinet/in_var.h" #include "../netinet/ip.h" #include "../netinet/if_ether.h" #endif #ifdef NS #include "../netns/ns.h" #include "../netns/ns_if.h" #endif #include "if_qereg.h" #include "if_uba.h" #include "../pdpuba/ubavar.h" #define NRCV 13 /* Receive descriptors (was 25) */ #define NXMT 5 /* Transmit descriptors */ #define NTOT (NXMT + NRCV) /* * This constant should really be 60 because the qna adds 4 bytes of crc. * However when set to 60 our packets are ignored by deuna's , 3coms are * okay ?????????????????????????????????????????? */ #define MINDATA 64 /* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * is_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... */ struct qe_softc { struct arpcom is_ac; /* Ethernet common part */ #define is_if is_ac.ac_if /* network-visible interface */ #define is_addr is_ac.ac_enaddr /* hardware Ethernet address */ struct ifuba qe_ifr[NRCV]; /* for receive buffers; */ struct ifuba qe_ifw[NXMT]; /* for xmit buffers; */ int qe_flags; /* software state */ #define QEF_RUNNING 0x01 #define QEF_SETADDR 0x02 long setupaddr; /* physaddr info for setup pkts */ long rringaddr; /* physaddr info for rings */ long tringaddr; /* "" */ struct qe_ring rring[NRCV+1]; /* Receive ring descriptors */ struct qe_ring tring[NXMT+1]; /* Transmit ring descriptors */ u_char setup_pkt[16][8]; /* Setup packet */ u_char rindex; /* Receive index */ u_char tindex; /* Transmit index */ int otindex; /* Old transmit index */ int qe_intvec; /* Interrupt vector */ struct qedevice *addr; /* device addr */ u_char setupqueued; /* setup packet queued */ u_char nxmit; /* Transmits in progress */ int timeout; /* watchdog */ int qe_restarts; /* timeouts */ } qe_softc[NQE]; struct uba_device *qeinfo[NQE]; int qeattach(), qeintr(), qewatch(), qeinit(),qeoutput(),qeioctl(); extern struct ifnet loif; u_short qestd[] = { 0 }; struct uba_driver qedriver = { 0, 0, qeattach, 0, qestd, "qe", qeinfo }; #define QE_TIMEO (15) #define QEUNIT(x) minor(x) int watchrun = 0; /* watchdog running */ /* * The deqna shouldn't receive more than ETHERMTU + sizeof(struct ether_header) * but will actually take in up to 2048 bytes. To guard against the receiver * chaining buffers (which we aren't prepared to handle) we allocate 2kb * size buffers. */ #define MAXPACKETSIZE 2048 /* Should really be ETHERMTU */ /* * The C compiler's propensity for prepending '_'s to names is the reason * for the routine below. We need the "handler" address (the code which * sets up the interrupt stack frame) in order to initialize the vector. */ static int qefoo() { asm("mov $qeintr, r0"); /* return value is in r0 */ } /* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */ qeattach(ui) struct uba_device *ui; { register struct qe_softc *sc = &qe_softc[ui->ui_unit]; register struct ifnet *ifp = &sc->is_if; struct qedevice *addr = (struct qedevice *)ui->ui_addr; register int i; extern int nextiv(); ifp->if_unit = ui->ui_unit; ifp->if_name = "qe"; ifp->if_mtu = ETHERMTU; ifp->if_flags = IFF_BROADCAST; /* * Read the address from the prom and save it. */ for ( i=0 ; i<6 ; i++ ) sc->setup_pkt[i][1] = sc->is_addr[i] = addr->qe_sta_addr[i] & 0xff; /* * Allocate a floating vector and initialize it with the address of * the interrupt handler and PSW (supervisor mode, priority 4, unit * number in the low bits. */ i = SKcall(nextiv, 0); sc->qe_intvec = i; mtkd(i, qefoo()); mtkd(i+2, PSL_CURSUP | PSL_BR4 | ifp->if_unit); /* * map the communications area onto the device */ sc->rringaddr = startnet + (long)sc->rring; sc->tringaddr = startnet + (long)sc->tring; sc->setupaddr = startnet + (long)sc->setup_pkt; /* * init buffers and maps */ if (qbaini(sc->qe_ifr, NRCV) == 0) sc->is_if.if_flags &= ~IFF_UP; if (qbaini(sc->qe_ifw, NXMT) == 0) sc->is_if.if_flags &= ~IFF_UP; ifp->if_init = qeinit; ifp->if_output = qeoutput; ifp->if_ioctl = qeioctl; ifp->if_reset = 0; if_attach(ifp); } /* * Initialization of interface. */ qeinit(unit) int unit; { register struct qe_softc *sc = &qe_softc[unit]; register struct uba_device *ui = qeinfo[unit]; register struct qedevice *addr = (struct qedevice *)ui->ui_addr; register struct ifnet *ifp = &sc->is_if; register i; int s; /* address not known */ if (ifp->if_addrlist == (struct ifaddr *)0) return; /* * Init the buffer descriptors and indexes for each of the lists and * loop them back to form a ring. */ for (i = 0; i < NRCV; i++) { qeinitdesc(&sc->rring[i], sc->qe_ifr[i].ifu_r.ifrw_info, MAXPACKETSIZE); sc->rring[i].qe_flag = sc->rring[i].qe_status1 = QE_NOTYET; sc->rring[i].qe_valid = 1; } qeinitdesc(&sc->rring[i], (long)NULL, 0); sc->rring[i].qe_addr_lo = loint(sc->rringaddr); sc->rring[i].qe_addr_hi = hiint(sc->rringaddr); sc->rring[i].qe_chain = 1; sc->rring[i].qe_flag = sc->rring[i].qe_status1 = QE_NOTYET; sc->rring[i].qe_valid = 1; for( i = 0 ; i <= NXMT ; i++ ) qeinitdesc(&sc->tring[i], (long)NULL, 0); i--; sc->tring[i].qe_addr_lo = loint(sc->tringaddr); sc->tring[i].qe_addr_hi = hiint(sc->tringaddr); sc->tring[i].qe_chain = 1; sc->tring[i].qe_flag = sc->tring[i].qe_status1 = QE_NOTYET; sc->tring[i].qe_valid = 1; sc->nxmit = sc->otindex = sc->tindex = sc->rindex = 0; /* * Take the interface out of reset, program the vector, * enable interrupts, and tell the world we are up. */ s = splimp(); addr->qe_vector = sc->qe_intvec; sc->addr = addr; addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT | QE_ILOOP; addr->qe_rcvlist_lo = loint(sc->rringaddr); addr->qe_rcvlist_hi = hiint(sc->rringaddr); ifp->if_flags |= IFF_UP | IFF_RUNNING; sc->qe_flags |= QEF_RUNNING; qesetup(sc); qestart(unit); splx(s); } /* * Start output on interface. * */ qestart(dev) dev_t dev; { int unit = QEUNIT(dev); struct uba_device *ui = qeinfo[unit]; register struct qe_softc *sc = &qe_softc[unit]; register struct qedevice *addr; register struct qe_ring *rp; register index; struct mbuf *m; int len, s; long buf_addr; s = splimp(); addr = (struct qedevice *)ui->ui_addr; /* * The deqna doesn't look at anything but the valid bit * to determine if it should transmit this packet. If you have * a ring and fill it the device will loop indefinately on the * packet and continue to flood the net with packets until you * break the ring. For this reason we never queue more than n-1 * packets in the transmit ring. * * The microcoders should have obeyed their own defination of the * flag and status words, but instead we have to compensate. */ for( index = sc->tindex; sc->tring[index].qe_valid == 0 && sc->nxmit < (NXMT-1) ; sc->tindex = index = ++index % NXMT){ rp = &sc->tring[index]; if( sc->setupqueued ) { buf_addr = sc->setupaddr; len = 128; rp->qe_setup = 1; sc->setupqueued = 0; } else { IF_DEQUEUE(&sc->is_if.if_snd, m); if( m == 0 ){ splx(s); return; } buf_addr = sc->qe_ifw[index].ifu_w.ifrw_info; len = if_wubaput(&sc->qe_ifw[index], m); } /* * Does buffer end on odd byte ? */ if( len & 1 ) { len++; rp->qe_odd_end = 1; } if( len < MINDATA ) len = MINDATA; rp->qe_buf_len = -(len/2); rp->qe_flag = rp->qe_status1 = QE_NOTYET; rp->qe_addr_lo = loint(buf_addr); rp->qe_addr_hi = hiint(buf_addr); rp->qe_eomsg = 1; rp->qe_flag = rp->qe_status1 = QE_NOTYET; rp->qe_valid = 1; sc->nxmit++; /* * If the watchdog time isn't running kick it. */ sc->timeout=1; if (watchrun == 0) { watchrun++; TIMEOUT(qewatch, (caddr_t)0, QE_TIMEO); } /* * See if the xmit list is invalid. */ if( addr->qe_csr & QE_XL_INVALID ) { buf_addr = sc->tringaddr + (index * sizeof (struct qe_ring)); addr->qe_xmtlist_lo = loint(buf_addr); addr->qe_xmtlist_hi = hiint(buf_addr); } } splx(s); } /* * Ethernet interface interrupt processor */ qeintr(unit) int unit; { register struct qe_softc *sc = &qe_softc[unit]; struct qedevice *addr = (struct qedevice *)qeinfo[unit]->ui_addr; int s, csr; long buf_addr; s = splimp(); csr = addr->qe_csr; addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT | QE_ILOOP; if (csr & QE_RCV_INT) qerint(unit); if (csr & QE_XMIT_INT) qetint(unit); if (csr & QE_NEX_MEM_INT) panic("qe: Non existant memory interrupt"); if( addr->qe_csr & QE_RL_INVALID && sc->rring[sc->rindex].qe_status1 == QE_NOTYET ) { buf_addr = sc->rringaddr + (sc->rindex * sizeof(struct qe_ring)); addr->qe_rcvlist_lo = loint(buf_addr); addr->qe_rcvlist_hi = hiint(buf_addr); } splx(s); } /* * Ethernet interface transmit interrupt. */ qetint(unit) int unit; { register struct qe_softc *sc = &qe_softc[unit]; register struct qe_ring *rp; int status1, setupflag; short len; while (sc->otindex != sc->tindex && sc->tring[sc->otindex].qe_status1 != QE_NOTYET && sc->nxmit > 0) { /* * Save the status words from the descriptor so that it can * be released. */ rp = &sc->tring[sc->otindex]; status1 = rp->qe_status1; setupflag = rp->qe_setup; len = (-rp->qe_buf_len) * 2; if (rp->qe_odd_end) len++; /* * Init the buffer descriptor */ bzero((caddr_t)rp, sizeof(struct qe_ring)); if (--sc->nxmit == 0) sc->timeout = 0; if (!setupflag) { /* * Do some statistics. */ sc->is_if.if_opackets++; sc->is_if.if_collisions += (status1 & QE_CCNT) >> 4; if (status1 & QE_ERROR) sc->is_if.if_oerrors++; } sc->otindex = ++sc->otindex % NXMT; } qestart(unit); } /* * Ethernet interface receiver interrupt. * If can't determine length from type, then have to drop packet. * Othewise decapsulate packet based on type and pass to type specific * higher-level input routine. */ qerint(unit) int unit; { register struct qe_softc *sc = &qe_softc[unit]; register struct qe_ring *rp; int len, status1, status2; long bufaddr; /* * Traverse the receive ring looking for packets to pass back. * The search is complete when we find a descriptor not in use. * * As in the transmit case the deqna doesn't honor it's own protocols * so there exists the possibility that the device can beat us around * the ring. The proper way to guard against this is to insure that * there is always at least one invalid descriptor. We chose instead * to make the ring large enough to minimize the problem. With a ring * size of 4 we haven't been able to see the problem. To be safe we * increased that to 5. * */ for( ; sc->rring[sc->rindex].qe_status1 != QE_NOTYET ; sc->rindex = ++sc->rindex % NRCV ){ rp = &sc->rring[sc->rindex]; status1 = rp->qe_status1; status2 = rp->qe_status2; bzero((caddr_t)rp, sizeof(struct qe_ring)); if ((status1 & QE_MASK) == QE_MASK) panic("qe: chained packet"); len = ((status1 & QE_RBL_HI) | (status2 & QE_RBL_LO)) + 60; sc->is_if.if_ipackets++; if (status1 & QE_ERROR) sc->is_if.if_ierrors++; else { /* * We don't process setup packets. */ if (!(status1 & QE_ESETUP)) qeread(sc, &sc->qe_ifr[sc->rindex], len - sizeof(struct ether_header)); } /* * Return the buffer to the ring */ bufaddr = sc->qe_ifr[sc->rindex].ifu_r.ifrw_info; rp->qe_buf_len = -((MAXPACKETSIZE)/2); rp->qe_addr_lo = loint(bufaddr); rp->qe_addr_hi = hiint(bufaddr); rp->qe_flag = rp->qe_status1 = QE_NOTYET; rp->qe_valid = 1; } } /* * Ethernet output routine. * Encapsulate a packet of type family for the local net. */ qeoutput(ifp, m0, dst) struct ifnet *ifp; struct mbuf *m0; struct sockaddr *dst; { int type, s, error; u_char edst[6]; struct in_addr idst; register struct qe_softc *is = &qe_softc[ifp->if_unit]; register struct mbuf *m = m0; register struct ether_header *eh; int usetrailers; struct mbuf *mcopy = (struct mbuf *)0; if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { error = ENETDOWN; goto bad; } switch (dst->sa_family) { #ifdef INET case AF_INET: idst = ((struct sockaddr_in *)dst)->sin_addr; if (!arpresolve(&is->is_ac, m, &idst, edst, &usetrailers)) return (0); /* if not yet resolved */ if (!bcmp(edst, etherbroadcastaddr,sizeof (edst))) mcopy = m_copy(m, 0, (int)M_COPYALL); type = ETHERTYPE_IP; goto gottype; #endif #ifdef NS case AF_NS: type = ETHERTYPE_NS; bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), (caddr_t)edst, sizeof (edst)); if (!bcmp(edst, &ns_broadcast, sizeof (edst))) return(looutput(&loif, m, dst)); goto gottype; #endif case AF_UNSPEC: eh = (struct ether_header *)dst->sa_data; bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); type = eh->ether_type; goto gottype; default: printf("qe%d: can't handle af%d\n", ifp->if_unit, dst->sa_family); error = EAFNOSUPPORT; goto bad; } gottype: /* * Add local net header. If no space in first mbuf, * allocate another. */ if (m->m_off > MMAXOFF || MMINOFF + sizeof (struct ether_header) > m->m_off) { m = m_get(M_DONTWAIT, MT_HEADER); if (m == 0) { error = ENOBUFS; goto bad; } m->m_next = m0; m->m_off = MMINOFF; m->m_len = sizeof (struct ether_header); } else { m->m_off -= sizeof (struct ether_header); m->m_len += sizeof (struct ether_header); } eh = mtod(m, struct ether_header *); eh->ether_type = htons((u_short)type); bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); bcopy((caddr_t)is->is_addr, (caddr_t)eh->ether_shost, sizeof (is->is_addr)); /* * Queue message on interface, and start output if interface * not yet active. */ s = splimp(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); splx(s); m_freem(m); if (mcopy) m_freem(mcopy); return (ENOBUFS); } IF_ENQUEUE(&ifp->if_snd, m); qestart(ifp->if_unit); splx(s); return(mcopy ? looutput(&loif, mcopy, dst) : 0); bad: m_freem(m0); if (mcopy) m_freem(mcopy); return(error); } /* * Process an ioctl request. */ qeioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { struct qe_softc *sc = &qe_softc[ifp->if_unit]; struct ifaddr *ifa = (struct ifaddr *)data; int s = splimp(), error = 0; switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; qeinit(ifp->if_unit); switch(ifa->ifa_addr.sa_family) { #ifdef INET case AF_INET: ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr; arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); break; #endif #ifdef NS case AF_NS: { register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); if (ns_nullhost(*ina)) ina->x_host = *(union ns_host *)(sc->is_addr); else qe_setaddr(ina->x_host.c_host, ifp->if_unit); break; } #endif } break; case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_UP) == 0 && sc->qe_flags & QEF_RUNNING) { ((struct qedevice *) (qeinfo[ifp->if_unit]->ui_addr))->qe_csr = QE_RESET; sc->qe_flags &= ~QEF_RUNNING; } else if (ifp->if_flags & IFF_UP && (sc->qe_flags & QEF_RUNNING) == 0) qerestart(sc); break; default: error = EINVAL; } splx(s); return (error); } /* * set ethernet address for unit */ qe_setaddr(physaddr, unit) u_char *physaddr; int unit; { register struct qe_softc *sc = &qe_softc[unit]; register int i; for (i = 0; i < 6; i++) sc->setup_pkt[i][1] = sc->is_addr[i] = physaddr[i]; sc->qe_flags |= QEF_SETADDR; if (sc->is_if.if_flags & IFF_RUNNING) qesetup(sc); qeinit(unit); } /* * Initialize a ring descriptor with mbuf allocation side effects */ qeinitdesc(rp, addr, len) register struct qe_ring *rp; long addr; /* physical address */ int len; { /* * clear the entire descriptor */ bzero((caddr_t)rp, sizeof(struct qe_ring)); if( len ) { rp->qe_buf_len = -(len/2); rp->qe_addr_lo = loint(addr); rp->qe_addr_hi = hiint(addr); } } /* * Build a setup packet - the physical address will already be present * in first column. */ qesetup( sc ) struct qe_softc *sc; { register i, j; /* * Copy the target address to the rest of the entries in this row. */ for ( j = 0; j < 6 ; j++ ) for ( i = 2 ; i < 8 ; i++ ) sc->setup_pkt[j][i] = sc->setup_pkt[j][1]; /* * Duplicate the first half. */ bcopy((caddr_t)sc->setup_pkt[0], (caddr_t)sc->setup_pkt[8], 64); /* * Fill in the broadcast address. */ for ( i = 0; i < 6 ; i++ ) sc->setup_pkt[i][2] = 0xff; sc->setupqueued++; } /* * Pass a packet to the higher levels. */ qeread(sc, ifuba, len) register struct qe_softc *sc; struct ifuba *ifuba; int len; { struct ether_header *eh; struct mbuf *m; struct ifqueue *inq; register int type; segm seg5; /* * Count trailers as errors and drop the packet. * SEG5 is mapped out briefly to peek at the packet type, swap the * bytes and then SEG5 is restored. */ saveseg5(seg5); mapseg5(ifuba->ifu_r.ifrw_click, 077406); /* 8k r/w for 1 word */ eh = (struct ether_header *)SEG5; eh->ether_type = ntohs((u_short)eh->ether_type); type = eh->ether_type; restorseg5(seg5); if (len == 0 || type >= ETHERTYPE_TRAIL && type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { sc->is_if.if_ierrors++; return; } /* * Pull packet off interface. */ m = if_rubaget(ifuba, len, 0, &sc->is_if); if (m == 0) return; switch (type) { #ifdef INET case ETHERTYPE_IP: schednetisr(NETISR_IP); inq = &ipintrq; break; case ETHERTYPE_ARP: arpinput(&sc->is_ac, m); return; #endif #ifdef NS case ETHERTYPE_NS: schednetisr(NETISR_NS); inq = &nsintrq; break; #endif default: m_freem(m); return; } if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); return; } IF_ENQUEUE(inq, m); } /* * Watchdog timer routine. There is a condition in the hardware that * causes the board to lock up under heavy load. This routine detects * the hang up and restarts the device. */ qewatch() { register struct qe_softc *sc; register int i; int inprogress=0; for (i = 0; i < NQE; i++) { sc = &qe_softc[i]; if (sc->timeout) if (++sc->timeout > 3 ) { printf("qerestart: restarted qe%d %d\n", i, ++sc->qe_restarts); qerestart(sc); } else inprogress++; } if (inprogress) { TIMEOUT(qewatch, (caddr_t)0, QE_TIMEO); watchrun++; } else watchrun=0; } /* * Restart for board lockup problem. */ qerestart(sc) register struct qe_softc *sc; { register struct ifnet *ifp = &sc->is_if; register struct qedevice *addr = sc->addr; register struct qe_ring *rp; register i; addr->qe_csr = QE_RESET; addr->qe_csr &= ~QE_RESET; sc->timeout = 0; qesetup( sc ); for (i = 0, rp = sc->tring; i < NXMT; rp++, i++) { rp->qe_flag = rp->qe_status1 = QE_NOTYET; rp->qe_valid = 0; } sc->nxmit = sc->otindex = sc->tindex = sc->rindex = 0; addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT | QE_ILOOP; addr->qe_rcvlist_lo = loint(sc->rringaddr); addr->qe_rcvlist_hi = hiint(sc->rringaddr); sc->qe_flags |= QEF_RUNNING; qestart(ifp->if_unit); } qbaini(ifuba, num) struct ifuba *ifuba; int num; { register int i; register memaddr click; for (i = 0; i < num; i++) { click = m_ioget(MAXPACKETSIZE); if (click == 0) { click = MALLOC(coremap, btoc(MAXPACKETSIZE)); if (click == 0) { printf("qe: can't get dma memory\n"); return(0); } } ifuba[i].ifu_hlen = sizeof (struct ether_header); ifuba[i].ifu_w.ifrw_click = ifuba[i].ifu_r.ifrw_click = click; ifuba[i].ifu_w.ifrw_info = ifuba[i].ifu_r.ifrw_info = ctob((long)click); } return(1); } #endif 0; if (!setupflag) { /* * Do some statistics. */ sc->is_if.if_opackets++; sc->is_if.if_collisions += (status1 & QE_CCNT) >> 4; if (status1 & QE_ERROR) sc->is_if.if_oerrors++; } sc->otindex = ++sc->otindex % NXMT; } qestart(unit); } /* * Ethernesys/pdpif/tags 751 0 12 0 6045325354 10476 2../sys/tagssys/pdpif/if_uba.c 444 0 12 12176 5357467174 7410 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_uba.c 1.2 (2.11BSD GTE) 4/3/93 * * 2.11BSD - uballoc and ubmalloc calling conventions changed. * ubmalloc now only performs address computation, the * necessary UMRs are allocated at network startup. * sms@wlv.imsd.contel.com - 9/8/90 */ #include "param.h" #include "../machine/seg.h" #include "systm.h" #include "domain.h" #include "protosw.h" #include "mbuf.h" #include "buf.h" #include "pdpuba/ubavar.h" #include "map.h" #include "uba.h" #include "socket.h" #include "netinet/in.h" #include "netinet/in_systm.h" #include "net/if.h" #include "pdpif/if_uba.h" /* * Routines supporting UNIBUS network interfaces. */ if_ubainit(ifu, uban, hlen, nmr) register struct ifuba *ifu; int uban, hlen, nmr; /* nmr in 64 byte clicks */ { if (ifu->ifu_r.ifrw_click) return(1); nmr = ctob(nmr); /* convert clicks back to bytes */ ifu->ifu_r.ifrw_click = m_ioget(nmr+hlen); ifu->ifu_w.ifrw_click = m_ioget(nmr+hlen); if (ifu->ifu_r.ifrw_click == 0 || ifu->ifu_w.ifrw_click == 0) { ifu->ifu_r.ifrw_click = ifu->ifu_w.ifrw_click = 0; return(0); } ifu->ifu_r.ifrw_info = ubmalloc(ifu->ifu_r.ifrw_click); ifu->ifu_w.ifrw_info = ubmalloc(ifu->ifu_w.ifrw_click); ifu->ifu_hlen = hlen; return(1); } /* * Pull read data off a interface. * Len is length of data, with local net header stripped. * Off is non-zero if a trailer protocol was used, and * gives the offset of the trailer information. * We copy the trailer information and then all the normal * data into mbufs. */ struct mbuf * if_rubaget(ifu, totlen, off0, ifp) register struct ifuba *ifu; int totlen, off0; struct ifnet *ifp; { register caddr_t cp = (caddr_t)ifu->ifu_hlen; register struct mbuf *m; struct mbuf *top, **mp; int click = ifu->ifu_r.ifrw_click; int off = off0, len; top = 0; mp = ⊤ while (totlen > 0) { MGET(m, M_DONTWAIT, MT_DATA); if (m == 0) { m_freem(top); top = 0; goto out; } if (off) { len = totlen - off; cp = (caddr_t) (ifu->ifu_hlen + off); } else len = totlen; if (len >= NBPG) { if (ifp) goto nopage; MCLGET(m); if (m->m_len != CLBYTES) goto nopage; m->m_len = MIN(len, CLBYTES); goto copy; } nopage: m->m_off = MMINOFF; if (ifp) { /* * Leave room for ifp. */ m->m_len = MIN(MLEN - sizeof(ifp), len); m->m_off += sizeof(ifp); } else m->m_len = MIN(MLEN, len); copy: mbcopyin(click, cp, mtod(m, char *), (u_int)m->m_len); cp += m->m_len; nocopy: *mp = m; mp = &m->m_next; if (off) { /* sort of an ALGOL-W style for statement... */ off += m->m_len; if (off == totlen) { cp = (caddr_t) ifu->ifu_hlen; off = 0; totlen = off0; } } else totlen -= m->m_len; if (ifp) { /* * Prepend interface pointer to first mbuf. */ m->m_len += sizeof(ifp); m->m_off -= sizeof(ifp); *(mtod(m, struct ifnet **)) = ifp; ifp = NULL; } } out: return(top); } /* * Map a chain of mbufs onto a network interface * in preparation for an i/o operation. * The argument chain of mbufs includes the local network * header. */ if_wubaput(ifu, m) struct ifuba *ifu; register struct mbuf *m; { register struct mbuf *mp; register u_short off = 0; u_short click = ifu->ifu_w.ifrw_click; while (m) { mbcopyout(mtod(m, char *), click, off, (u_int)m->m_len); off += m->m_len; MFREE(m, mp); m = mp; } return(off); } #define KDSA ((u_short *)0172260) /* supervisor - was 172360.KERNEL */ /* * Map UNIBUS virtual memory over some address in supervisor data * space. We're similar to the "mapalloc" routine used for * raw I/O, but for different objects. The kernel's 'ubmap' is * tested since the network's "fake" 'ubmap' has gone away (this * routine was the only one to use it). */ ubadr_t uballoc(addr, size) caddr_t addr; u_int size; { register int nregs; register struct ubmap *ubp; ubadr_t paddr, vaddr; u_int click, first; int page, offset; page = (((int)addr >> 13) & 07); offset = ((int)addr & 017777); click = KDSA[page]; paddr = (ubadr_t)click << 6; paddr += offset; if (!mfkd(&ubmap)) return(paddr); nregs = (int)btoub(size); first = MALLOC(ub_map, nregs); #ifdef DIAGNOSTIC /* * Should never happen since this is only called by initialization routines * in the network drivers. */ if (!first) panic("uballoc"); #endif ubp = &UBMAP[first]; vaddr = (ubadr_t)first << 13; while (nregs--) { ubp->ub_lo = loint(paddr); ubp->ub_hi = hiint(paddr); ubp++; paddr += (ubadr_t) UBPAGE; } return(vaddr); } /* * Computes a physical address within the mapped I/O area managed by * m_ioget. For a UNIBUS machine, the m_ioget arena is * already mapped by UMRs and mioumr and miostart have the base * virtual and click addresses of the mapped arena. For Q22 machines * mioumr and miostart are 0, turning the calculation into a ctob * of the input click address. */ ubadr_t ubmalloc(addr) memaddr addr; /* pdp11 "clicks" */ { extern ubadr_t mioumr; extern memaddr miostart; return(((ubadr_t)(addr - miostart) << 6) + mioumr); } r_hi = hiint(addr); } } /* * Build a setup packet - the physical address will already be present * in first column. */ qesetup( sc ) struct qe_softc *sc; { register i, j; /* * Copy the target address to the rest of the entries in this row. */ for ( j = 0; j < 6 ; j++ ) for ( i = 2 ; i < 8 ; i++ ) sc->setup_pkt[j][i] = sc->setup_pkt[j][1]; /* * Duplicate the firssys/pdpif/if_vv.c 644 0 12 57441 4503633541 7263 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_vv.c 2.0 (2.10.1BSD Berkeley) 8/25/89 */ #include "vv.h" #if NVV > 0 /* * Proteon proNET-10 and proNET-80 token ring driver. * The name of this device driver derives from the old MIT * name of V2LNI for the proNET hardware, would would abbreviate * to "v2", but this won't work right. Thus the name is "vv". * * This driver is compatible with the proNET 10 meagbit and * 80 megabit token ring interfaces (models p1000 and p1080). * A unit may be marked as 80 megabit using "flags 1" in the * config file. * * TRAILERS: This driver has a new implementation of trailers that * is at least a tolerable neighbor on the ring. The offset is not * stored in the protocol type, but instead only in the vh_info * field. Also, the vh_info field, and the two shorts before the * trailing header, are in network byte order, not VAX byte order. * * Of course, nothing but BSD UNIX supports trailers on ProNET. * If you need interoperability with anything else, turn off * trailers using the -trailers option to /etc/ifconfig! * * HARDWARE COMPATABILITY: This driver prefers that the HSBU (p1001) * have a serial number >= 040, which is about March, 1982. Older * HSBUs do not carry across 64kbyte boundaries. They can be supported * by adding "| UBA_NEED16" to the vs_ifuba.ifu_flags initialization * in vvattach(). * * The old warning about use without Wire Centers applies only to CTL * (p1002) cards with serial <= 057, which have not received ECO 176-743, * which was implemented in March, 1982. Most such CTLs have received * this ECO. */ #include "param.h" #include "../machine/seg.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "domain.h" #include "protosw.h" #include "socket.h" #include "ioctl.h" #include "pdpif/if_vv.h" #include "pdpif/if_uba.h" #include "errno.h" #include "pdpuba/ubavar.h" #include "net/if.h" #include "net/netisr.h" #include "net/route.h" #ifdef INET #include "netinet/in.h" #include "netinet/in_systm.h" #include "netinet/in_var.h" #include "netinet/ip.h" #include "netinet/ip_var.h" #endif /* * maximum transmission unit definition -- * you can set VVMTU at anything from 576 to 2024. * 1536 is a popular "large" value, because it is a multiple * of 512, which the trailer scheme likes. * The absolute maximum size is 2024, which is enforced. */ #define VVMTU (1536) #define VVMRU (VVMTU + 16) #define VVBUFSIZE (VVMRU + sizeof(struct vv_header)) #if VVMTU>2024 #undef VVMTU #undef VVMRU #undef VVBUFSIZE #define VVBUFSIZE (2046) #define VVMRU (VVBUFSIZE - sizeof (struct vv_header)) #define VVMTU (VVMRU - 16) #endif /* * debugging and tracing stuff */ int vv_tracehdr = 0; /* 1 => trace headers (slowly!!) */ #define vvtracehdr if (vv_tracehdr) vvprt_hdr #define vvprintf if (vs->vs_if.if_flags & IFF_DEBUG) printf /* * externals, types, etc. */ int vvprobe(), vvattach(), vvreset(), vvinit(); int vvidentify(), vvstart(), vvxint(), vvwatchdog(); int vvrint(), vvoutput(), vvioctl(); struct uba_device *vvinfo[NVV]; u_short vvstd[] = { 0 }; struct uba_driver vvdriver = { vvprobe, 0, vvattach, 0, vvstd, "vv", vvinfo }; #define VVUNIT(x) minor(x) #define LOOPBACK /* use loopback for packets meant for us */ #ifdef LOOPBACK extern struct ifnet loif; #endif /* * Software status of each interface. * * Each interface is referenced by a network interface structure, * vs_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... * We also have, for each interface, a UBA interface structure, which * contains information about the UNIBUS resources held by the interface: * map registers, buffered data paths, etc. Information is cached in this * structure for use by the if_uba.c routines in running the interface * efficiently. */ struct vv_softc { struct ifnet vs_if; /* network-visible interface */ struct ifuba vs_ifuba; /* UNIBUS resources */ u_short vs_host; /* this interface address */ short vs_oactive; /* is output active */ short vs_is80; /* is 80 megabit version */ short vs_olen; /* length of last output */ u_short vs_lastx; /* address of last packet sent */ u_short vs_lastr; /* address of last packet received */ short vs_tries; /* transmit current retry count */ short vs_init; /* number of ring inits */ short vs_refused; /* number of packets refused */ short vs_timeouts; /* number of transmit timeouts */ short vs_otimeout; /* number of output timeouts */ short vs_ibadf; /* number of input bad formats */ short vs_parity; /* number of parity errors on 10 meg, */ /* link data errors on 80 meg */ } vv_softc[NVV]; #define NOHOST 0xffff /* illegal host number */ vvprobe(reg) caddr_t reg; { #ifdef notdef register int br, cvec; register struct vvreg *addr; #ifdef lint br = 0; cvec = br; br = cvec; #endif addr = (struct vvreg *)reg; /* reset interface, enable, and wait till dust settles */ addr->vvicsr = VV_RST; addr->vvocsr = VV_RST; DELAY(100000L); /* generate interrupt by doing 1 word DMA from 0 in uba space!! */ addr->vvoba = 0; /* low 16 bits */ addr->vvoea = 0; /* extended bits */ addr->vvowc = -1; /* for 1 word */ addr->vvocsr = VV_IEN | VV_DEN; /* start the DMA, with interrupt */ DELAY(100000L); addr->vvocsr = VV_RST; /* clear out the CSR */ if (cvec && cvec != 0x200) cvec -= 4; /* backup so vector => receive */ #endif return(1); } /* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */ vvattach(ui) struct uba_device *ui; { register struct vv_softc *vs; vs = &vv_softc[ui->ui_unit]; vs->vs_if.if_unit = ui->ui_unit; vs->vs_if.if_name = "vv"; vs->vs_if.if_mtu = VVMTU; vs->vs_if.if_flags = IFF_BROADCAST; vs->vs_if.if_init = vvinit; vs->vs_if.if_ioctl = vvioctl; vs->vs_if.if_output = vvoutput; vs->vs_if.if_reset = vvreset; vs->vs_if.if_timer = 0; vs->vs_if.if_watchdog = vvwatchdog; vs->vs_ifuba.ifu_flags = UBA_CANTWAIT | UBA_NEEDBDP; /* use flag to determine if this is proNET-80 */ vs->vs_is80 = (short)(ui->ui_flags & 01); #if defined(VAX750) /* don't chew up 750 bdp's */ if (cpu == VAX_750 && ui->ui_unit > 0) vs->vs_ifuba.ifu_flags &= ~UBA_NEEDBDP; #endif if_attach(&vs->vs_if); } /* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */ vvreset(unit, uban) int unit, uban; { register struct uba_device *ui; if (unit >= NVV || (ui = vvinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" vv%d", unit); vvinit(unit); } /* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */ vvinit(unit) int unit; { register struct vv_softc *vs; register struct uba_device *ui; register struct vvreg *addr; register int s; ubadr_t ubainfo; vs = &vv_softc[unit]; ui = vvinfo[unit]; if (vs->vs_if.if_addrlist == (struct ifaddr *)0) return; addr = (struct vvreg *)ui->ui_addr; if (if_ubainit(&vs->vs_ifuba, ui->ui_ubanum, sizeof (struct vv_header), (int)btoc(VVMTU)) == 0) { printf("vv%d: can't initialize, if_ubainit() failed\n", unit); vs->vs_if.if_flags &= ~IFF_UP; return; } /* * Now that the uba is set up, figure out our address and * update complete our host address. */ if ((vs->vs_host = vvidentify(unit)) == NOHOST) { vs->vs_if.if_flags &= ~IFF_UP; return; } printf("vv%d: host %u\n", unit, vs->vs_host); /* * Reset the interface, and stay in the ring */ addr->vvocsr = VV_RST; /* take over output */ addr->vvocsr = VV_CPB; /* clear packet buffer */ addr->vvicsr = VV_RST | VV_HEN; /* take over input, */ /* keep relay closed */ DELAY(500000L); /* let contacts settle */ vs->vs_init = 0; /* clear counters, etc. */ vs->vs_refused = 0; vs->vs_timeouts = 0; vs->vs_otimeout = 0; vs->vs_ibadf = 0; vs->vs_parity = 0; vs->vs_lastx = 256; /* an invalid address */ vs->vs_lastr = 256; /* an invalid address */ /* * Hang a receive and start any * pending writes by faking a transmit complete. */ s = splimp(); ubainfo = vs->vs_ifuba.ifu_r.ifrw_info; addr->vviba = (u_short)ubainfo; addr->vviea = (u_short)(ubainfo >> 16); addr->vviwc = -(VVBUFSIZE) >> 1; addr->vvicsr = VV_IEN | VV_HEN | VV_DEN | VV_ENB; vs->vs_oactive = 1; vs->vs_if.if_flags |= IFF_RUNNING; vvxint(unit); splx(s); } /* * Return our host address. */ vvidentify(unit) int unit; { register struct vv_softc *vs; register struct uba_device *ui; register struct vvreg *addr; register struct mbuf *m; register struct vv_header *v; register int attempts, waitcount; ubadr_t ubainfo; segm seg5; u_short host; u_char type; /* * Build a multicast message to identify our address */ vs = &vv_softc[unit]; ui = vvinfo[unit]; addr = (struct vvreg *)ui->ui_addr; attempts = 0; /* total attempts, including bad msg type */ m = m_get(M_DONTWAIT, MT_HEADER); if (m == NULL) { printf("vv%d: can't initialize, m_get() failed\n", unit); return (NOHOST); } m->m_next = 0; m->m_off = MMINOFF; m->m_len = sizeof(struct vv_header); v = mtod(m, struct vv_header *); v->vh_dhost = VV_BROADCAST; /* multicast destination address */ v->vh_shost = 0; /* will be overwritten with ours */ v->vh_version = RING_VERSION; v->vh_type = RING_WHOAMI; v->vh_info = 0; /* map xmit message into uba */ vs->vs_olen = if_wubaput(&vs->vs_ifuba, m); /* * Reset interface, establish Digital Loopback Mode, and * send the multicast (to myself) with Input Copy enabled. */ retry: ubainfo = vs->vs_ifuba.ifu_r.ifrw_info; addr->vvicsr = VV_RST; addr->vviba = (u_short) ubainfo; addr->vviea = (u_short) (ubainfo >> 16); addr->vviwc = -(sizeof (struct vv_header) + VVMTU) >> 1; addr->vvicsr = VV_STE | VV_DEN | VV_ENB | VV_LPB; /* let flag timers fire so ring will initialize */ DELAY(2000000L); /* about 2 SECONDS on a 780!! */ addr->vvocsr = VV_RST | VV_CPB; /* clear packet buffer */ ubainfo = vs->vs_ifuba.ifu_w.ifrw_info; addr->vvoba = (u_short) ubainfo; addr->vvoea = (u_short) (ubainfo >> 16); addr->vvowc = -((vs->vs_olen + 1) >> 1); addr->vvocsr = VV_CPB | VV_DEN | VV_INR | VV_ENB; /* * Wait for receive side to finish. * Extract source address (which will be our own), * and post to interface structure. */ DELAY(10000L); for (waitcount = 0; (addr->vvicsr & VV_RDY) == 0; waitcount++) { if (waitcount < 10) { DELAY(1000L); continue; } if (attempts++ < VVIDENTRETRY) goto retry; break; } /* deallocate mbuf used for send packet */ if (vs->vs_ifuba.ifu_xtofree) { m_freem(vs->vs_ifuba.ifu_xtofree); vs->vs_ifuba.ifu_xtofree = 0; } if (attempts >= VVIDENTRETRY) { printf("vv%d: can't initialize after %d tries, icsr = %b\n", unit, VVIDENTRETRY, 0xffff&(addr->vvicsr), VV_IBITS); return (NOHOST); } m = if_rubaget(&vs->vs_ifuba, sizeof(struct vv_header), 0, &vs->vs_if); if (m != NULL) m_freem(m); /* * Check message type before we believe the source host address */ saveseg5(seg5); mapseg5(vs->vs_ifuba.ifu_r.ifrw_click, 077406); v = (struct vv_header *) SEG5; type = v->vh_type; host = (u_short)v->vh_shost; restorseg5(seg5); if (type != (u_char)RING_WHOAMI) goto retry; return(host); } /* * Start or restart output on interface. * If interface is active, this is a retransmit, so just * restuff registers and go. * If interface is not already active, get another datagram * to send off of the interface queue, and map it to the interface * before starting the output. */ vvstart(dev) dev_t dev; { register struct uba_device *ui; register struct vv_softc *vs; register struct vvreg *addr; register struct mbuf *m; register int unit, dest, s; ubadr_t ubainfo; segm save5; unit = VVUNIT(dev); ui = vvinfo[unit]; vs = &vv_softc[unit]; if (vs->vs_oactive) goto restart; /* * Not already active: dequeue another request * and map it to the UNIBUS. If no more requests, * just return. */ s = splimp(); IF_DEQUEUE(&vs->vs_if.if_snd, m); splx(s); if (m == NULL) { vs->vs_oactive = 0; return; } dest = mtod(m, struct vv_header *)->vh_dhost; vs->vs_olen = if_wubaput(&vs->vs_ifuba, m); vs->vs_lastx = dest; restart: /* * Have request mapped to UNIBUS for transmission. * Purge any stale data from this BDP, and start the output. * * Make sure this packet will fit in the interface. */ if (vs->vs_olen > VVBUFSIZE) { printf("vv%d vs_olen: %d > VVBUFSIZE\n", unit, vs->vs_olen); panic("vvdriver vs_olen botch"); } vs->vs_if.if_timer = VVTIMEOUT; vs->vs_oactive = 1; /* ship it */ addr = (struct vvreg *)ui->ui_addr; ubainfo = vs->vs_ifuba.ifu_w.ifrw_info; addr->vvoba = (u_short) ubainfo; addr->vvoea = (u_short) (ubainfo >> 16); addr->vvowc = -((vs->vs_olen + 1) >> 1); addr->vvowc = -((vs->vs_olen + 1) >> 1); /* extra byte is garbage */ if (addr->vvocsr & VV_NOK) vs->vs_init++; /* count ring inits */ addr->vvocsr = VV_IEN | VV_CPB | VV_DEN | VV_INR | VV_ENB; } /* * proNET transmit interrupt * Start another output if more data to send. */ vvxint(unit) int unit; { register struct uba_device *ui; register struct vv_softc *vs; register struct vvreg *addr; register int oc; ui = vvinfo[unit]; vs = &vv_softc[unit]; vs->vs_if.if_timer = 0; addr = (struct vvreg *)ui->ui_addr; oc = 0xffff & (addr->vvocsr); if (vs->vs_oactive == 0) { vvprintf("vv%d: stray interrupt vvocsr = %b\n", unit, oc, VV_OBITS); return; } /* * we retransmit on soft error * TODO: sort retransmits to end of queue if possible! */ if (oc & (VV_OPT | VV_RFS)) { if (vs->vs_tries++ < VVRETRY) { if (oc & VV_OPT) vs->vs_otimeout++; if (oc & VV_RFS) { vs->vs_if.if_collisions++; vs->vs_refused++; } vvstart(unit); /* restart this message */ return; } } vs->vs_if.if_opackets++; vs->vs_oactive = 0; vs->vs_tries = 0; if (oc & VVXERR) { vs->vs_if.if_oerrors++; vvprintf("vv%d: error vvocsr = %b\n", unit, 0xffff & oc, VV_OBITS); } if (vs->vs_ifuba.ifu_xtofree) { m_freem(vs->vs_ifuba.ifu_xtofree); vs->vs_ifuba.ifu_xtofree = 0; } vvstart(unit); } /* * Transmit watchdog timer routine. * This routine gets called when we lose a transmit interrupt. * The best we can do is try to restart output. */ vvwatchdog(unit) int unit; { register struct vv_softc *vs; register int s; vs = &vv_softc[unit]; vvprintf("vv%d: lost a transmit interrupt.\n", unit); vs->vs_timeouts++; s = splimp(); vvstart(unit); splx(s); } /* * proNET interface receiver interrupt. * If input error just drop packet. * Otherwise purge input buffered data path and examine * packet to determine type. If can't determine length * from type, then have to drop packet. Otherwise decapsulate * packet based on type and pass to type specific higher-level * input routine. */ vvrint(unit) int unit; { register struct vv_softc *vs; register struct vvreg *addr; register struct vv_header *vv; register struct ifqueue *inq; register struct mbuf *m; int len, off, s; ubadr_t ubainfo; segm save5; short resid; u_short type, shost; saveseg5(save5); vs = &vv_softc[unit]; vs->vs_if.if_ipackets++; addr = (struct vvreg *)vvinfo[unit]->ui_addr; if (addr->vvicsr & VVRERR) { vvprintf("vv%d: receive error, vvicsr = %b\n", unit, 0xffff&(addr->vvicsr), VV_IBITS); if (addr->vvicsr & VV_BDF) vs->vs_ibadf++; goto dropit; } /* * parity errors? */ if (addr->vvicsr & VV_LDE) { /* we don't have to clear it because the receive command */ /* writes 0 to parity bit */ vs->vs_parity++; /* * only on 10 megabit proNET is VV_LDE an end-to-end parity * bit. On 80 megabit, it returns to the intended use of * node-to-node parity. End-to-end parity errors on 80 megabit * give VV_BDF. */ if (vs->vs_is80 == 0) goto dropit; } /* * Get packet length from residual word count * * Compute header offset if trailer protocol * * Pull packet off interface. Off is nonzero if packet * has trailing header; if_rubaget will then force this header * information to be at the front. The vh_info field * carries the offset to the trailer data in trailer * format packets. */ mapseg5(vs->vs_ifuba.ifu_r.ifrw_click, (btoc(VVMRU) << 8) | RW); vv = (struct vv_header *) SEG5; vvtracehdr("vi", vv); resid = addr->vviwc & 01777; /* only low 10 bits valid */ if (resid) resid |= 0176000; /* high 6 bits are undefined */ len = ((VVBUFSIZE >> 1) + resid) << 1; len -= sizeof(struct vv_header); if ((addr->vvicsr & VV_DPR) || len > VVMRU || len <= 0) { vvprintf("vv%d: len too long or short, \ len = %d, vvicsr = %b\n", unit, len, 0xffff&(addr->vvicsr), VV_IBITS); goto dropit; } /* check the protocol header version */ if (vv->vh_version != RING_VERSION) { vvprintf("vv%d: bad protocol header version %d\n", unit, vv->vh_version & 0xff); goto dropit; } #define vvdataaddr(vv, off, type) ((type)(((caddr_t)((vv)+1)+(off)))) if (vv->vh_type == RING_TRAILER ) { off = ntohs((u_short)vv->vh_info); if (off > VVMTU) { vvprintf("vv%d: off > VVMTU, off = %d, vvicsr = %b\n", unit, off, 0xffff&(addr->vvicsr), VV_IBITS); goto dropit; } vv->vh_type = ntohs(*vvdataaddr(vv, off, u_short *)); resid = ntohs(*(vvdataaddr(vv, off+sizeof(u_short), u_short *))); if (off + resid > len) { vvprintf("vv%d: trailer packet too short\n", unit); vvprintf("vv%d: off = %d, resid = %d, vvicsr = %b\n", unit, off, resid, 0xffff&(addr->vvicsr), VV_IBITS); goto dropit; } len = off + resid; } else off = 0; if (len == 0) { vvprintf("vv%d: len is zero, vvicsr = %b\n", unit, 0xffff&(addr->vvicsr), VV_IBITS); goto dropit; } /* * have to restore the mapping before manipulating mbufs because * there may be mbufs in SEG5. save the 'type' and 'shost' then * restore the mapping. */ type = vv->vh_type; shost = vv->vh_shost; restorseg5(save5); m = if_rubaget(&vs->vs_ifuba, len, off, &vs->vs_if); if (m == NULL) { vvprintf("vv%d: if_rubaget() failed, vvicsr = %b\n", unit, 0xffff&(addr->vvicsr), VV_IBITS); goto dropit; } if (off) { struct ifnet *ifp; ifp = *(mtod(m, struct ifnet **)); m->m_off += 2 * sizeof (u_short); m->m_len -= 2 * sizeof (u_short); *(mtod(m, struct ifnet **)) = ifp; } /* Keep track of source address of this packet */ vs->vs_lastr = shost; /* * Demultiplex on packet type */ switch (type) { #ifdef INET case RING_IP: schednetisr(NETISR_IP); inq = &ipintrq; break; #endif default: vvprintf("vv%d: unknown pkt type 0x%x\n", unit, type); m_freem(m); goto setup; } s = splimp(); if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); } else IF_ENQUEUE(inq, m); splx(s); /* * Reset for the next packet. */ setup: restorseg5(save5); ubainfo = vs->vs_ifuba.ifu_r.ifrw_info; addr->vviba = (u_short) ubainfo; addr->vviea = (u_short) (ubainfo >> 16); addr->vviwc = -(VVBUFSIZE) >> 1; addr->vvicsr = VV_HEN | VV_IEN | VV_DEN | VV_ENB; return; /* * Drop packet on floor -- count them!! */ dropit: vs->vs_if.if_ierrors++; goto setup; } /* * proNET output routine. * Encapsulate a packet of type family for the local net. * Use trailer local net encapsulation if enough data in first * packet leaves a multiple of 512 bytes of data in remainder. */ vvoutput(ifp, m0, dst) struct ifnet *ifp; struct mbuf *m0; struct sockaddr *dst; { register struct mbuf *m; register struct vv_header *vv; register int off; register int unit; register struct vvreg *addr; register struct vv_softc *vs; register int s; int type, error; u_long dest; segm save5; saveseg5(save5); m = m0; unit = ifp->if_unit; addr = (struct vvreg *)vvinfo[unit]->ui_addr; vs = &vv_softc[unit]; /* * Check to see if the input side has wedged. * * We are lower than device ipl when we enter this routine, * so if the interface is ready with an input packet then * an input interrupt must have slipped through the cracks. * * Avoid the race with an input interrupt by watching to see * if any packets come in. */ s = vs->vs_if.if_ipackets; if (addr->vvicsr & VV_RDY && s == vs->vs_if.if_ipackets) { vvprintf("vv%d: lost a receive interrupt, icsr = %b\n", unit, 0xffff&(addr->vvicsr), VV_IBITS); s = splimp(); vvrint(unit); splx(s); } switch (dst->sa_family) { #ifdef INET case AF_INET: if (in_broadcast(((struct sockaddr_in *)dst)->sin_addr)) dest = VV_BROADCAST; else dest = in_lnaof(((struct sockaddr_in *)dst)->sin_addr); /* Rene Nieuwboer reneni@psy.vu.nl suggests a 'dest &= 0xff;' at this point */ /* dest is contrained in the 'if' a few lines down, i don't see why the & */ #ifdef LOOPBACK if (dest == vs->vs_host && (loif.if_flags & IFF_UP)) return (looutput(&loif, m0, dst)); #endif LOOPBACK if (dest >= 0x100) { error = EPERM; goto bad; } off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; /* * Trailerize, if the configuration allows it. * TODO: Need per host negotiation. */ if ((ifp->if_flags & IFF_NOTRAILERS) == 0) if (off > 0 && (off & 0x1ff) == 0 && m->m_off >= MMINOFF + 2 * sizeof (u_short)) { type = RING_TRAILER; m->m_off -= 2 * sizeof (u_short); m->m_len += 2 * sizeof (u_short); *mtod(m, u_short *) = htons((short)RING_IP); *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); goto gottrailertype; } type = RING_IP; off = 0; goto gottype; #endif default: printf("vv%d: can't handle af%d\n", unit, dst->sa_family); error = EAFNOSUPPORT; goto bad; } gottrailertype: /* * Packet to be sent as trailer: move first packet * (control information) to end of chain. */ while (m->m_next) m = m->m_next; m->m_next = m0; m = m0->m_next; m0->m_next = 0; m0 = m; gottype: /* * Add local net header. If no space in first mbuf, * allocate another. */ if (m->m_off > MMAXOFF || MMINOFF + sizeof (struct vv_header) > m->m_off) { m = m_get(M_DONTWAIT, MT_HEADER); if (m == NULL) { error = ENOBUFS; goto bad; } m->m_next = m0; m->m_off = MMINOFF; m->m_len = sizeof (struct vv_header); } else { m->m_off -= sizeof (struct vv_header); m->m_len += sizeof (struct vv_header); } vv = mtod(m, struct vv_header *); vv->vh_shost = vs->vs_host; vv->vh_dhost = dest; vv->vh_version = RING_VERSION; vv->vh_type = type; vv->vh_info = htons((u_short)off); vvtracehdr("vo", vv); /* * Queue message on interface, and start output if interface * not yet active. */ s = splimp(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); error = ENOBUFS; goto qfull; } IF_ENQUEUE(&ifp->if_snd, m); if (vs->vs_oactive == 0) vvstart(unit); splx(s); return (0); qfull: m0 = m; splx(s); bad: m_freem(m0); return(error); } /* * Process an ioctl request. */ vvioctl(ifp, cmd, data) register struct ifnet *ifp; u_int cmd; caddr_t data; { struct ifaddr *ifa = (struct ifaddr *) data; int s = splimp(), error = 0; switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; if ((ifp->if_flags & IFF_RUNNING) == 0) vvinit(ifp->if_unit); /* * Did self-test succeed? */ if ((ifp->if_flags & IFF_UP) == 0) error = ENETDOWN; /* * Attempt to check agreement of protocol address * and board address. */ switch (ifa->ifa_addr.sa_family) { case AF_INET: /* Rene Nieuwboer reneni@psy.vu.nl suggests a '& 0xff;' below */ if ((u_short)(in_lnaof(IA_SIN(ifa)->sin_addr)) != vv_softc[ifp->if_unit].vs_host) error = EADDRNOTAVAIL; break; } break; default: error = EINVAL; } splx(s); return (error); } /* * vvprt_hdr(s, v) print the local net header in "v" * with title is "s" */ vvprt_hdr(s, v) char *s; register struct vv_header *v; { printf("%s: dsvti: 0x%x 0x%x 0x%x 0x%x 0x%x\n", s, 0xff & (int)(v->vh_dhost), 0xff & (int)(v->vh_shost), 0xff & (int)(v->vh_version), 0xff & (int)(v->vh_type), 0xffff & (int)(v->vh_info)); } #endif NVV s->vs_if.if_opackets++; vs->vs_oactive = 0; vs->vs_tries = 0; if (oc & VVXERR) { vs->vs_if.if_oerrors++; vvprintf("vv%d: error vvocsr = %b\n", unit, 0xffff & oc, VV_OBITS); } if (vs->vs_ifuba.ifu_xtofree) { sys/pdpif/if_sri.c 444 0 12 25716 4617136267 7434 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_sri.c 1.1 (2.10BSD Berkeley) 12/1/86 */ #include "sri.h" #if NSRI > 0 /* * SRI dr11c ARPAnet IMP interface driver. */ #include "param.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "domain.h" #include "protosw.h" #include "socket.h" #include "pdpuba/ubavar.h" #include "netinet/in.h" #include "netinet/in_systm.h" #include "net/if.h" #include "pdpif/if_sri.h" #include "netimp/if_imp.h" #include "pdpif/if_uba.h" int sriprobe(), sriattach(), srirint(), srixint(); struct uba_device *sriinfo[NSRI]; u_short sristd[] = { 0 }; struct uba_driver sridriver = { sriprobe, 0, sriattach, 0, sristd, "sri", sriinfo }; #define SRIUNIT(x) minor(x) #define IFRADDR sc->sri_ifuba.ifu_r.ifrw_info #define IFWADDR sc->sri_ifuba.ifu_w.ifrw_info int sriinit(), sristart(), srireset(); /* * "Lower half" of IMP interface driver. * * Each IMP interface is handled by a common module which handles * the IMP-host protocol and a hardware driver which manages the * hardware specific details of talking with the IMP. * * The hardware portion of the IMP driver handles DMA and related * management of UNIBUS resources. The IMP protocol module interprets * contents of these messages and "controls" the actions of the * hardware module during IMP resets, but not, for instance, during * UNIBUS resets. * * The two modules are coupled at "attach time", and ever after, * through the imp interface structure. Higher level protocols, * e.g. IP, interact with the IMP driver, rather than the SRI. */ struct sri_softc { /* pdma registers, shared with assembly helper */ struct sridevice *sri_addr; /* hardware address */ char *sri_iba; /* in byte addr */ short sri_ibc; /* in byte count */ short sri_iclick; /* in click addr */ short sri_ibf; /* in buf (last byte, plus flags) */ short sri_ibusy; /* in dma busy flag */ char *sri_oba; /* out byte addr */ short sri_obc; /* out byte count */ short sri_oclick; /* out click addr */ short sri_oend; /* out end flags */ /* end pdma */ struct ifnet *sri_if; /* pointer to IMP's ifnet struct */ struct impcb *sri_ic; /* data structure shared with IMP */ struct ifuba sri_ifuba; /* UNIBUS resources */ struct mbuf *sri_iq; /* input reassembly queue */ short sri_olen; /* size of last message sent */ char sri_flush; /* flush remainder of message */ } sri_softc[NSRI]; /* * Reset the IMP and cause a transmitter interrupt. */ sriprobe(reg) caddr_t reg; { #if !pdp11 register int br, cvec; /* r11, r10 value-result */ register struct sridevice *addr = (struct sridevice *)reg; int i; #ifdef lint br = 0; cvec = br; br = cvec; srirint(0); srixint(0); #endif addr->csr = 0; addr->obf = OUT_HRDY; DELAY(100000L); addr->csr = SRI_OINT|SRI_OENB; addr->obf = OUT_LAST; DELAY(100000L); addr->csr = 0; addr->obf = OUT_HNRDY; if(cvec && cvec != 0x200) return(1); addr->csr = SRI_IINT|SRI_IENB; i = addr->ibf; DELAY(100000L); addr->csr = 0; if(cvec && cvec != 0x200) cvec -= 4; /* report as xmit intr */ return(1); #endif } /* * Call the IMP module to allow it to set up its internal * state, then tie the two modules together by setting up * the back pointers to common data structures. */ sriattach(ui) struct uba_device *ui; { register struct sri_softc *sc = &sri_softc[ui->ui_unit]; register struct impcb *ip; struct ifimpcb { struct ifnet ifimp_if; struct impcb ifimp_impcb; } *ifimp; if ((ifimp = (struct ifimpcb *)impattach(ui, srireset)) == 0) panic("sriattach"); sc->sri_if = &ifimp->ifimp_if; ip = &ifimp->ifimp_impcb; sc->sri_ic = ip; ip->ic_init = sriinit; ip->ic_start = sristart; sc->sri_if->if_reset = srireset; sc->sri_addr = (struct sridevice *) ui->ui_addr; } /* * Reset interface after UNIBUS reset. * If interface is on specified uba, reset its state. */ srireset(unit, uban) int unit, uban; { register struct uba_device *ui; struct sri_softc *sc; if (unit >= NSRI || (ui = sriinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" sri%d", unit); sc = &sri_softc[unit]; /* must go through IMP to allow it to set state */ (*sc->sri_if->if_init)(unit); } /* * Initialize interface: clear recorded pending operations, * and retrieve, and initialize UNIBUS resources. Note * return value is used by IMP init routine to mark IMP * unavailable for outgoing traffic. */ sriinit(unit) int unit; { register struct sri_softc *sc; register struct uba_device *ui; register struct sridevice *addr; int x, info; if (unit >= NSRI || (ui = sriinfo[unit]) == 0 || ui->ui_alive == 0) { printf("sri%d: not alive\n", unit); return (0); } sc = &sri_softc[unit]; /* * Header length is 0 since we have to passs * the IMP leader up to the protocol interpretation * routines. If we had the header length as * sizeof(struct imp_leader), then the if_ routines * would asssume we handle it on input and output. */ if (if_ubainit(&sc->sri_ifuba, ui->ui_ubanum, 0, (int)btoc(IMPMTU)) == 0) { printf("sri%d: can't initialize\n", unit); goto down; } addr = (struct sridevice *)ui->ui_addr; #if pdp11 sc->sri_iclick = (sc->sri_ifuba.ifu_r.ifrw_click); sc->sri_oclick = (sc->sri_ifuba.ifu_w.ifrw_click); #endif /* * Reset the imp interface; * the delays are pure guesswork. */ addr->csr = 0; DELAY(5000L); addr->obf = OUT_HRDY; /* close the relay */ DELAY(10000L); addr->obf = 0; /* YECH!!! */ x = 5; /* was 500 before rdy line code!!! */ while (x-- > 0) { if ((addr->ibf & IN_INRDY) == 0 ) break; DELAY(10000L); } if (x <= 0) { /* printf("sri%d: imp doesn't respond, ibf=%b\n", unit, addr->ibf, SRI_INBITS); */ return(0); /* goto down;*/ } /* * Put up a read. We can't restart any outstanding writes * until we're back in synch with the IMP (i.e. we've flushed * the NOOPs it throws at us). * Note: IMPMTU includes the leader. */ x = splimp(); sc->sri_iba = (char *)IFRADDR; sc->sri_ibc = IMPMTU; sc->sri_ibusy = -1; /* skip leading zeros */ addr->csr |= (SRI_IINT|SRI_IENB); splx(x); return (1); down: ui->ui_alive = 0; return (0); } /* * Start output on an interface. */ sristart(dev) dev_t dev; { int unit = SRIUNIT(dev), info; register struct sri_softc *sc = &sri_softc[unit]; register struct sridevice *addr; struct mbuf *m; u_short cmd; if (sc->sri_ic->ic_oactive) goto restart; /* * Not already active, deqeue a request and * map it onto the UNIBUS. If no more * requeusts, just return. */ IF_DEQUEUE(&sc->sri_if->if_snd, m); if (m == 0) { sc->sri_ic->ic_oactive = 0; return; } sc->sri_olen = ((if_wubaput(&sc->sri_ifuba, m) + 1 ) & ~1); restart: addr = (struct sridevice *)sriinfo[unit]->ui_addr; sc->sri_oba = (char *)IFWADDR; sc->sri_obc = sc->sri_olen; sc->sri_oend = OUT_LAST; sc->sri_obc--; addr->csr |= (SRI_OENB|SRI_OINT); addr->obf = (*sc->sri_oba++ & 0377); sc->sri_ic->ic_oactive = 1; } /* * Output interrupt handler. */ srixint(unit) { register struct sri_softc *sc = &sri_softc[unit]; register struct sridevice *addr = sc->sri_addr; int burst,delay; register int x; burst = 0; while(sc->sri_obc > 0) { x = (*sc->sri_oba++ & 0377); if(--sc->sri_obc <= 0) x |= sc->sri_oend; addr->obf = x; if(++burst > 16) goto out; for(delay=0 ;; delay++) { if(delay > 12) goto out; if(addr->csr&SRI_OREQ) break; } } addr->csr &= ~SRI_OINT; if (sc->sri_ic->ic_oactive == 0) { printf("sri%d: stray xmit interrupt\n", unit); goto out; } sridump("out",IFWADDR,sc->sri_olen); sc->sri_if->if_opackets++; sc->sri_ic->ic_oactive = 0; if (sc->sri_obc != 0) { /* only happens if IMP ready drop */ printf("sri%d: output error, csr=%b\n", unit, addr->csr, SRI_BITS); sc->sri_if->if_oerrors++; } if (sc->sri_ifuba.ifu_xtofree) { m_freem(sc->sri_ifuba.ifu_xtofree); sc->sri_ifuba.ifu_xtofree = 0; } if (sc->sri_if->if_snd.ifq_head) sristart(unit); out: return; } /* * Input interrupt handler */ srirint(unit) { register struct sri_softc *sc = &sri_softc[unit]; struct mbuf *m; int len, info; register struct sridevice *addr = sc->sri_addr; int burst,delay; register int x; burst = 0; for(;;) { addr->csr &= ~SRI_IENB; /* prevents next read from starting */ sc->sri_ibf = x = addr->ibf; if(x & IN_CHECK) break; /* LAST or error */ if(sc->sri_ibc <= 0) break; /* spurrious int */ x &= 0377; if(sc->sri_ibusy < 0) { /* flushing leading zeros */ if(x == 0) goto next; sc->sri_ibusy = 1; } *sc->sri_iba++ = x; if(--sc->sri_ibc <= 0) break; /* count exhausted */ next: addr->csr |= SRI_IENB; /* start next read */ if(++burst > 16) goto out; for(delay=0 ;; delay++) { if(delay > 12) goto out; if(addr->csr&SRI_IREQ) break; } } x = sc->sri_ibf; /* grab the last byte if EOM */ if((x & IN_LAST) && !(x & IN_INRDY) && sc->sri_ibc > 0) { *sc->sri_iba++ = (x & 0377); sc->sri_ibc--; } addr->csr &= ~SRI_IINT; sc->sri_if->if_ipackets++; if ((x & IN_INRDY)) { printf("sri%d: input error, ibf=%b\n", unit, x, SRI_INBITS); sc->sri_if->if_ierrors++; sc->sri_flush = 1; if(sc->sri_obc > 0) { /* if output active */ sc->sri_obc = -1; /* flush it */ srixint(unit); } /* tell "other half" of module that ready line just dropped */ /* Kludge, I know, but the alternative is to create an mbuf */ impinput(unit, (struct mbuf *) 0); /* ready line dropped */ goto out; /* leave interrupts un-enabled */ /* FIX THIS!!!! */ } if (sc->sri_flush) { if (x & IN_LAST) sc->sri_flush = 0; goto setup; } len = IMPMTU - sc->sri_ibc; if (len < 10 || len > IMPMTU) { printf("sri%d: bad length=%d\n", len); sc->sri_if->if_ierrors++; goto setup; } sridump("in ",IFRADDR,len); /* * The next to last parameter is always 0 since using * trailers on the ARPAnet is insane. */ m = if_rubaget(&sc->sri_ifuba, len, 0, &sc->sri_if); if (m == 0) goto setup; if ((x & IN_LAST) == 0) { if (sc->sri_iq) m_cat(sc->sri_iq, m); else sc->sri_iq = m; goto setup; } if (sc->sri_iq) { m_cat(sc->sri_iq, m); m = sc->sri_iq; sc->sri_iq = 0; } impinput(unit, m); setup: /* * Setup for next message. */ sc->sri_iba = (char *)IFRADDR; sc->sri_ibc = IMPMTU; sc->sri_ibusy = -1; /* skip leading zeros */ addr->csr |= (SRI_IINT|SRI_IENB); out: return; } sridump(str,aba,abc) char *str,*aba; { int col,i; if(str[0] != 07) if(!sridebug()) return; printf("%s ",str); col = 0; for(; abc ; abc--) { i = *aba++ & 0377; printf("%o ",i); if(++col > 31) { col = 0; printf("\n "); } } printf("\n"); } #if vax sridebug() { return( (mfpr(RXCS) & RXCS_DONE) == 0 && (mfpr(RXDB) & 0177) == 07); } #endif #if pdp11 sridebug() { return( (*(char *)0177560 & 0200) == 0 && (*(char *)0177562 & 0177) == 07); } #endif #endif NSRI nit(), sristart(), srireset(); /* * "Lower half"sys/pdpif/if_ecreg.h 444 0 12 4142 4165537447 7702 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_ecreg.h 7.1 (Berkeley) 6/5/86 */ /* * 3Com Ethernet controller registers. */ struct ecdevice { short ec_rcr; /* Receive Control Register */ short ec_xcr; /* Transmit Control Register */ }; /* * Control and status bits -- rcr */ #define EC_SPIE 0x8000 /* set parity interrupt enable */ #define EC_ASTEP 0x4000 /* increment address counter */ #define EC_AROM 0x2000 /* 1: Use address ROM, 0: use RAM */ #define EC_PE 0x2000 /* Parity error */ #define EC_AWCLK 0x1000 /* address write clock bit */ #define EC_PIE 0x1000 /* Parity interrupt enable (read) */ #define EC_ADATA 0x0f00 /* address/filtering */ #define EC_RDONE 0x0080 /* receive done */ #define EC_MDISAB 0x0080 /* memory disable */ #define EC_RINTEN 0x0040 /* receive interrupt enable */ #define EC_RCLR 0x0020 /* clear RDONE bit */ #define EC_RWBN 0x0010 /* submit buffer for receive */ #define EC_RBN 0x000f /* buffer number */ #define EC_RBITS "\10\16PE\15PIE\10RDONE\7RINTEN" /* * Control and status bits -- xcr */ #define EC_JAM 0x8000 /* collision dectected */ #define EC_JINTEN 0x4000 /* collision interrupt enable */ #define EC_JCLR 0x2000 /* clear collision detect */ #define EC_UECLR 0x0100 /* reset controller */ #define EC_XDONE 0x0080 /* transmit done */ #define EC_XINTEN 0x0040 /* transmit interrupt enable */ #define EC_XCLR 0x0020 /* clear XDONE bit */ #define EC_XWBN 0x0010 /* submit buffer for transmit */ #define EC_XBN 0x000f /* buffer number */ #define EC_XBITS "\10\20JAM\17JINTEN\10XDONE\7XINTEN" /* * Useful combinations */ #define EC_READ (0x600|EC_RINTEN|EC_RWBN) #define EC_WRITE (EC_JINTEN|EC_XINTEN|EC_XWBN) #define EC_CLEAR (EC_JINTEN|EC_XINTEN|EC_JCLR) /* * Buffer number definitions */ #define ECTBF 0 /* Buffer for transmit */ #define ECRLBF 1 /* First buffer for receive */ #define ECRHBF 15 /* Last buffer for receive */ #define ECRDOFF 528 /* Packet offset in read buffer */ *sri_oba; /* out byte addr */ short sri_obc; /* out byte count */ short sri_oclick; /* out click addr */ short sri_oend; /* out end flags */ /* end pdma */ struct ifnet *sri_if; /* pointer to IMP's ifnet struct */ struct impcb *sri_ic; /* data structure shared with IMP */ struct ifuba sri_ifuba; /* UNIBUS resources */ struct mbuf *sri_iq; sys/pdpif/if_dereg.h 444 0 12 23475 5511225567 7726 /* * SCCSID: @(#)if_dereg.h 1.1 (2.11BSD GTE) 12/31/93 * * DEC DEUNA interface */ /* * Define unibus ehternet controller types */ #define DEUNA 0 #define DELUA 1 struct dedevice { union { short p0_w; char p0_b[2]; } u_p0; #define pcsr0 u_p0.p0_w #define pclow u_p0.p0_b[0] #define pchigh u_p0.p0_b[1] short pcsr1; short pcsr2; short pcsr3; }; /* * PCSR 0 bit descriptions */ #define PCSR0_SERI 0x8000 /* Status error interrupt */ #define PCSR0_PCEI 0x4000 /* Port command error interrupt */ #define PCSR0_RXI 0x2000 /* Receive done interrupt */ #define PCSR0_TXI 0x1000 /* Transmit done interrupt */ #define PCSR0_DNI 0x0800 /* Done interrupt */ #define PCSR0_RCBI 0x0400 /* Receive buffer unavail intrpt */ #define PCSR0_FATI 0x0100 /* Fatal error interrupt */ #define PCSR0_INTR 0x0080 /* Interrupt summary */ #define PCSR0_INTE 0x0040 /* Interrupt enable */ #define PCSR0_RSET 0x0020 /* DEUNA reset */ #define PCSR0_CMASK 0x000f /* command mask */ #define PCSR0_BITS "\20\20SERI\17PCEI\16RXI\15TXI\14DNI\13RCBI\11FATI\10INTR\7INTE\6RSET" /* bits 0-3 are for the PORT_COMMAND */ #define CMD_NOOP 0x0 #define CMD_GETPCBB 0x1 /* Get PCB Block */ #define CMD_GETCMD 0x2 /* Execute command in PCB */ #define CMD_STEST 0x3 /* Self test mode */ #define CMD_START 0x4 /* Reset xmit and receive ring ptrs */ #define CMD_BOOT 0x5 /* Boot DEUNA */ #define CMD_PDMD 0x8 /* Polling demand */ #define CMD_TMRO 0x9 /* Sanity timer on */ #define CMD_TMRF 0xa /* Sanity timer off */ #define CMD_RSTT 0xb /* Reset sanity timer */ #define CMD_STOP 0xf /* Suspend operation */ /* * PCSR 1 bit descriptions */ #define PCSR1_XPWR 0x8000 /* Transceiver power BAD */ #define PCSR1_ICAB 0x4000 /* Interconnect cabling BAD */ #define PCSR1_STCODE 0x3f00 /* Self test error code */ #define PCSR1_PCTO 0x0080 /* Port command timed out */ #define PCSR1_DEVID 0x0070 /* Device id DEUNA=0, DELUA=1 */ #define PCSR1_STMASK 0x0007 /* State */ /* bit 0-3 are for STATE */ #define STAT_RESET 0x0 #define STAT_PRIMLD 0x1 /* Primary load */ #define STAT_READY 0x2 #define STAT_RUN 0x3 #define STAT_UHALT 0x5 /* UNIBUS halted */ #define STAT_NIHALT 0x6 /* NI halted */ #define STAT_NIUHALT 0x7 /* NI and UNIBUS Halted */ #define PCSR1_BITS "\20\20XPWR\17ICAB\10PCTO" #define PCSR1_BITS_DELUA "\10\10PCTO" /* * Port Control Block Base */ struct de_pcbb { short pcbb0; /* function */ short pcbb2; /* command specific */ short pcbb4; short pcbb6; }; /* PCBB function codes */ #define FC_NOOP 0x00 /* NO-OP */ #define FC_LSUADDR 0x01 /* Load and start microaddress */ #define FC_RDDEFAULT 0x02 /* Read default physical address */ #define FC_RDPHYAD 0x04 /* Read physical address */ #define FC_WTPHYAD 0x05 /* Write physical address */ #define FC_RDMULTI 0x06 /* Read multicast address list */ #define FC_WTMULTI 0x07 /* Read multicast address list */ #define FC_RDRING 0x08 /* Read ring format */ #define FC_WTRING 0x09 /* Write ring format */ #define FC_RDCNTS 0x0a /* Read counters */ #define FC_RCCNTS 0x0b /* Read and clear counters */ #define FC_RDMODE 0x0c /* Read mode */ #define FC_WTMODE 0x0d /* Write mode */ #define FC_RDSTATUS 0x0e /* Read port status */ #define FC_RCSTATUS 0x0f /* Read and clear port status */ #define FC_DUMPMEM 0x10 /* Dump internal memory */ #define FC_LOADMEM 0x11 /* Load internal memory */ #define FC_RDSYSID 0x12 /* Read system ID parameters */ #define FC_WTSYSID 0x13 /* Write system ID parameters */ #define FC_RDSERAD 0x14 /* Read load server address */ #define FC_WTSERAD 0x15 /* Write load server address */ /* * Unibus Data Block Base (UDBB) for ring buffers */ struct de_udbbuf { short b_tdrbl; /* Transmit desc ring base low 16 bits */ char b_tdrbh; /* Transmit desc ring base high 2 bits */ char b_telen; /* Length of each transmit entry */ short b_trlen; /* Number of entries in the XMIT desc ring */ short b_rdrbl; /* Receive desc ring base low 16 bits */ char b_rdrbh; /* Receive desc ring base high 2 bits */ char b_relen; /* Length of each receive entry */ short b_rrlen; /* Number of entries in the RECV desc ring */ }; /* * Transmit/Receive Ring Entry */ struct de_ring { short r_slen; /* Segment length */ short r_segbl; /* Segment address (low 16 bits) */ char r_segbh; /* Segment address (hi 2 bits) */ u_char r_flags; /* Status flags */ u_short r_tdrerr; /* Errors */ #define r_lenerr r_tdrerr short r_rid; /* Request ID */ }; #define XFLG_OWN 0x80 /* If 0 then owned by driver */ #define XFLG_ERRS 0x40 /* Error summary */ #define XFLG_MTCH 0x20 /* Address match on xmit request */ #define XFLG_MORE 0x10 /* More than one entry required */ #define XFLG_ONE 0x08 /* One collision encountered */ #define XFLG_DEF 0x04 /* Transmit deferred */ #define XFLG_STP 0x02 /* Start of packet */ #define XFLG_ENP 0x01 /* End of packet */ #define XFLG_BITS "\10\10OWN\7ERRS\6MTCH\5MORE\4ONE\3DEF\2STP\1ENP" #define XERR_BUFL 0x8000 /* Buffer length error */ #define XERR_UBTO 0x4000 /* UNIBUS tiemout #define XERR_UFLO 0x2000 /* Underflow transmit */ #define XERR_LCOL 0x1000 /* Late collision */ #define XERR_LCAR 0x0800 /* Loss of carrier */ #define XERR_RTRY 0x0400 /* Failed after 16 retries */ #define XERR_TDR 0x03ff /* TDR value */ #define XERR_BITS "\20\20BUFL\17UBTO\16UFLO\15LCOL\14LCAR\13RTRY" #define RFLG_OWN 0x80 /* If 0 then owned by driver */ #define RFLG_ERRS 0x40 /* Error summary */ #define RFLG_FRAM 0x20 /* Framing error */ #define RFLG_OFLO 0x10 /* Message overflow */ #define RFLG_CRC 0x08 /* CRC error */ #define RFLG_STP 0x02 /* Start of packet */ #define RFLG_ENP 0x01 /* End of packet */ #define RFLG_BITS "\10\10OWN\7ERRS\6FRAM\5OFLO\4CRC\2STP\1ENP" #define RERR_BUFL 0x8000 /* Buffer length error */ #define RERR_UBTO 0x4000 /* UNIBUS tiemout */ #define RERR_NCHN 0x2000 /* No data chaining */ #define RERR_OVRN 0x1000 /* overrun message error */ #define RERR_MLEN 0x0fff /* Message length */ #define RERR_BITS "\20\20BUFL\17UBTO\16NCHN\15OVRN" /* mode description bits */ #define MOD_HDX 0x0001 /* Half duplex mode */ #define MOD_LOOP 0x0004 /* Enable loopback */ #define MOD_DTCR 0x0008 /* Disables CRC generation */ #define MOD_INTL 0x0040 /* Internal loopback enable */ #define MOD_DMNT 0x0200 /* Disable maintenance features */ #define MOD_ECT 0x0400 /* Enable collision test */ #define MOD_TPAD 0x1000 /* Transmit message pad enable */ #define MOD_DRDC 0x2000 /* Disable data chaining */ #define MOD_ENAL 0x4000 /* Enable all multicast */ #define MOD_PROM 0x8000 /* Enable promiscuous mode */ struct de_buf { struct ether_header db_head; /* header */ char db_data[ETHERMTU]; /* packet data */ long db_crc; /* CRC - on receive only */ }; #ifdef DE_DO_PHYSADDR /* * structure used to query de and qe for physical addresses */ struct ifdevea { char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */ u_char default_pa[6]; /* default hardware address */ u_char current_pa[6]; /* current physical address */ }; #endif /* DE_DO_PHYSADDR */ #ifdef DE_DO_BCTRS /* * Counter list */ struct de_counters { short c_length; /* returned data block length */ u_short c_seconds; /* seconds since last zeroed */ u_short c_prcvd[2]; /* packets received */ u_short c_mprcvd[2]; /* multicast packets received */ u_short c_rbm; /* receive error bitmap */ u_short c_rcverr; /* packets received with error */ u_short c_brcvd[2]; /* bytes received */ u_short c_mbrcvd[2]; /* multicast bytes received */ u_short c_ibuferr; /* packets lost - internal buffer error */ u_short c_lbuferr; /* packets lost - local buffer error */ u_short c_psent[2]; /* packets sent */ u_short c_mpsent[2]; /* multicast packets sent */ u_short c_multiple[2]; /* packets sent - multiple collisions */ u_short c_single[2]; /* packets sent - single collision */ u_short c_defer[2]; /* packets sent - initially deferred */ u_short c_bsent[2]; /* bytes sent */ u_short c_mbsent[2]; /* multicast bytes sent */ u_short c_sbm; /* send error bitmap */ u_short c_snderr; /* send packet errors */ u_short c_collis; /* collision check failure */ u_short c_rsvd; /* reserved field */ }; /* * interface statistics structures */ struct estat { /* Ethernet interface statistics */ u_short est_seconds; /* seconds since last zeroed */ u_long est_byrcvd; /* bytes received */ u_long est_bysent; /* bytes sent */ u_long est_blrcvd; /* data blocks received */ u_long est_blsent; /* data blocks sent */ u_long est_mbyrcvd; /* multicast bytes received */ u_long est_mblrcvd; /* multicast blocks received */ u_long est_deferred; /* blocks sent, initially deferred */ u_long est_single; /* blocks sent, single collision */ u_long est_multiple; /* blocks sent, multiple collisions */ u_short est_sfbm; /* 0 - Excessive collisions */ /* 1 - Carrier check failed */ /* 2 - Short circuit */ /* 3 - Open circuit */ /* 4 - Frame too long */ /* 5 - Remote failure to defer */ u_short est_sf; /* send failures: (bit map)*/ u_short est_collis; /* Collision detect check failure */ u_short est_rfbm; /* 0 - Block check error */ /* 1 - Framing error */ /* 2 - Frame too long */ u_short est_rf; /* receive failure: (bit map) */ u_short est_unrecog; /* unrecognized frame destination */ u_short est_overrun; /* data overrun */ u_short est_sysbuf; /* system buffer unavailable */ u_short est_userbuf; /* user buffer unavailable */ }; /* * interface counter ioctl request */ struct ctrreq { char ctr_name[IFNAMSIZ]; /* if name */ char ctr_type; /* type of interface */ struct estat ctr_ether;/* ethernet counters */ }; #define CTR_ETHER 0 /* Ethernet interface */ #define CTR_DDCMP 1 /* DDCMP pt-to-pt interface */ #define CTR_HDRCRC 0 /* header crc bit index */ #define CTR_DATCRC 1 /* data crc bit index */ #define CTR_BUFUNAVAIL 0 /* buffer unavailable bit index */ #endif /* DE_DO_BCTRS */ r_lenerr r_tdrerr short r_rid; /* Request ID */ }; #define XFLG_OWN 0x80 /* If 0 then owned by driver */ #define XFLG_ERRS 0x40 /* Error summary */ #define XFLG_MTCH 0x20 /* Address matchsys/pdpif/if_enreg.h 444 0 12 2360 3671247546 7714 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_enreg.h 7.1 (Berkeley) 6/5/86 */ /* * Xerox experimental ethernet registers. * * N.B.: status register and device address are read/write, * device address is read-only, rest are WRITE ONLY! */ struct endevice { short en_owc; /* output word count (10 bits) */ short en_oba; /* output buffer address */ short en_ostat; /* output control and status */ short en_odelay; /* output start delay, 25usec units */ short en_iwc; /* input word count */ short en_iba; /* input buffer address */ short en_istat; /* input csr */ short en_addr; /* ~device address (low 8 bits) */ }; /* * Control and status bits. */ #define EN_IERROR 0x8000 /* CRC error, buf ovflo or overrun */ #define EN_OERROR 0x8000 /* collision or output underrun */ #define EN_OPDONE 0x0080 /* previous operation completed */ #define EN_IEN 0x0040 /* enable interrupt when DONE */ #define EN_PROMISCUOUS 0x0002 /* promiscuous, input any packet */ #define EN_GO 0x0001 /* start op bit */ #define EN_BITS "\10\20ERR\10OPDONE\7IEN\2PROM\1GO" #define spl_enet() spl5() ; /* if name, e.g. "en0" */ u_char default_pa[6]; /* default hardware address */ u_char current_pa[6]; /* current physical address */ }; #endif /* DE_DO_PHYSADDR */ #ifdef DE_DO_BCTRS /* * Counter list */sys/pdpif/if_qtreg.h 644 0 0 11453 5343610606 7725 /* @(#)if_qtreg.h 1.0 (GTE) 10/12/92 */ /* * Modification History * 26 Feb 93 -- sms * Add defines for number of receive and transmit ring descriptors. * * 12 Oct 92 -- Steven M. Schultz (sms) * Created from the DELQA-PLUS Addendum to the DELQA User's Guide. */ #define QT_MAX_RCV 32 #define QT_MAX_XMT 12 /* Receive ring descriptor and bit/field definitions */ struct qt_rring { short rmd0; short rmd1; short rmd2; short rmd3; short rmd4; short rmd5; struct qt_uba *rhost0; short rhost1; }; #define RMD0_ERR3 0x4000 /* Error summary. FRA|CRC|OFL|BUF */ #define RMD0_FRA 0x2000 /* Framing error */ #define RMD0_OFL 0x1000 /* Overflow error. Oversized packet */ #define RMD0_CRC 0x0800 /* CRC error */ #define RMD0_BUF 0x0400 /* Internal device buffer error */ #define RMD0_STP 0x0200 /* Start of packet */ #define RMD0_ENP 0x0100 /* End of packet */ #define RMD1_MCNT 0x0fff /* Message byte count */ #define RMD2_ERR4 0x8000 /* Error summary. BBL|CER|MIS */ #define RMD2_BBL 0x4000 /* Babble error on transmit */ #define RMD2_CER 0x2000 /* Collision error on transmit */ #define RMD2_MIS 0x1000 /* Packet lost on receive */ #define RMD2_EOR 0x0800 /* End of receive ring */ #define RMD2_RON 0x0020 /* Receiver on */ #define RMD2_TON 0x0010 /* Transmitter on */ #define RMD3_OWN 0x8000 /* Ownership field. */ #define RMD4_LADR 0xfff8 /* Octabyte aligned low address bits */ #define RMD5_HADR 0x003f /* High 6 bits of buffer address */ #define RMD0_BITS "\010\016FRA\015OFL\014CRC\013BUF\012STP\011ENP" #define RMD2_BITS "\010\017BBL\014CER\013MIS\012EOR\06RON\05TON" /* Transmit ring descriptor and bit/field definitions */ struct qt_tring { short tmd0; short tmd1; short tmd2; short tmd3; short tmd4; short tmd5; struct qt_uba *thost0; short thost1; }; #define TMD0_ERR1 0x4000 /* Error summary. LCO|LCA|RTR */ #define TMD0_MOR 0x1000 /* More than one retry on transmit */ #define TMD0_ONE 0x0800 /* One retry on transmit */ #define TMD0_DEF 0x0400 /* Deferral during transmit */ #define TMD1_LCO 0x1000 /* Late collision on transmit */ #define TMD1_LCA 0x0800 /* Loss of carrier on transmit */ #define TMD1_RTR 0x0400 /* Retry error on transmit */ #define TMD1_TDR 0x03ff /* Time Domain Reflectometry value */ #define TMD2_ERR2 0x8000 /* Error summary. BBL|CER|MIS */ #define TMD2_BBL 0x4000 /* Babble error on transmit */ #define TMD2_CER 0x2000 /* Collision error on transmit */ #define TMD2_MIS 0x1000 /* Packet lost on receive */ #define TMD2_EOR 0x0800 /* Endof Receive ring reached */ #define TMD2_RON 0x0020 /* Receiver on */ #define TMD2_TON 0x0010 /* Transmitter on */ #define TMD3_OWN 0x8000 /* Ownership field */ #define TMD3_FOT 0x4000 /* First of two flag */ #define TMD3_BCT 0x0fff /* Byte count */ #define TMD4_LADR 0xfff8 /* Octabyte aligned low address bits */ #define TMD5_HADR 0x003f /* High 6 bits of buffer address */ #define TMD1_BITS "\010\015LCO\014LCA\013RTR" #define TMD2_BITS "\010\017BBL\016CER\015MIS\014EOR\06RON\05TON" /* DELQA-YM CSR layout */ struct qtcsr0 { short Ibal; short Ibah; short Icr; short pad0; short Srqr; short pad1; }; struct qtdevice { union { u_char Sarom[12]; struct qtcsr0 csr0; } qt_un0; short srr; short arqr; }; #define ibal qt_un0.csr0.Ibal #define ibah qt_un0.csr0.Ibah #define srqr qt_un0.csr0.Srqr #define icr qt_un0.csr0.Icr #define sarom qt_un0.Sarom /* SRR definitions */ #define SRR_FES 0x8000 #define SRR_CHN 0x4000 #define SRR_NXM 0x1000 #define SRR_PER 0x0800 #define SRR_IME 0x0400 #define SRR_TBL 0x0200 #define SRR_RESP 0x0003 #define SRR_BITS "\010\017CHN\015NXM\014PER\013IME\012TBL" /* SRQR definitions */ #define SRQR_REQ 0x0003 /* ARQR definitions */ #define ARQR_TRQ 0x8000 #define ARQR_RRQ 0x0080 #define ARQR_SR 0x0002 /* define ICR definitions */ #define ICR_CMD 0x0001 /* DELQA registers used to shift into -T mode */ #define xcr0 qt_un0.csr0.Ibal #define xcr1 qt_un0.csr0.Ibah /* INIT block structure and definitions */ struct qt_init { short mode; u_char paddr[6]; /* 48 bit physical address */ u_char laddr[8]; /* 64 bit logical address filter */ u_short rx_lo; /* low 16 bits of receive ring addr */ u_short rx_hi; /* high 6 bits of receive ring addr */ u_short tx_lo; /* low 16 bits of transmit ring addr */ u_short tx_hi; /* high 6 bits of transmit ring addr */ u_short options; u_short vector; u_short hit; char passwd[6]; }; #define INIT_MODE_PRO 0x8000 /* Promiscuous mode */ #define INIT_MODE_INT 0x0040 /* Internal Loopback */ #define INIT_MODE_DRT 0x0020 /* Disable Retry */ #define INIT_MODE_DTC 0x0008 /* Disable Transmit CRC */ #define INIT_MODE_LOP 0x0004 /* Loopback */ #define INIT_OPTIONS_HIT 0x0002 /* Host Inactivity Timeout Flag */ #define INIT_OPTIONS_INT 0x0001 /* Interrupt Enable Flag */ ; #define TMD0_ERR1 0x4000 /* Error summary. LCO|LCA|RTR */ #define TMD0_MOR 0x1000 /* More than one retry on transmit */ #define TMD0_ONE 0x0800 /* One retry on transmit */ #define TMD0_DEF 0x0400 /* Deferrsys/pdpif/if_qt.c 644 0 0 55330 5344014307 7221 /* @(#)if_qt.c 1.2 (2.11BSD) 2/20/93 * * Modification History * 23-Feb-92 -- sms * Rewrite the buffer handling so that fewer than the maximum number of * buffers may be used (32 receive and 12 transmit buffers consume 66+kb * of main system memory in addition to the internal structures in the * networking code). A freelist of available buffers is maintained now. * When I/O operations complete the associated buffer is placed on the * freelist (a single linked list for simplicity) and when an I/O is * started a buffer is pulled off the list. * * 20-Feb-92 -- sms * It works! Darned board couldn't handle "short" rings - those rings * where only half the entries were made available to the board (the * ring descriptors were the full size, merely half the entries were * flagged as belonging always to the driver). Grrrr. Would have thought * the board could skip over those entries reserved by the driver. * Now to find a way not to have to allocated 32+12 times 1.5kb worth of * buffers... * * 03-Feb-92 -- sms * Released but still not working. The driver now responds to arp and * ping requests. The board is apparently not returning ring descriptors * to the driver so eventually we run out of buffers. Back to the * drawing board. * * 28-Dec-92 -- sms * Still not released. Hiatus in finding free time and thin-netting * the systems (many thanks Terry!). * Added logic to dynamically allocate a vector and initialize it. * * 23-Oct-92 -- sms * The INIT block must (apparently) be quadword aligned [no thanks to * the manual for not mentioning that fact]. The necessary alignment * is achieved by allocating the INIT block from main memory ('malloc' * guarantees click alignment) and mapping it as needed (which is _very_ * infrequently). A check for quadword alignment of the ring descriptors * was added - at present the descriptors are properly aligned, if this * should change then something will have to be done (like do it "right"). * Darned alignment restrictions! * * A couple of typos were corrected (missing parentheses, reversed * arguments to printf calls, etc). * * 13-Oct-92 -- sms@wlv.iipo.gtegsc.com * Created based on the DELQA-PLUS addendum to DELQA User's Guide. * This driver ('qt') is selected at system configuration time. If the * board * is not a DELQA-YM an error message will be printed and the * interface will not be attached. */ #include "qt.h" #if NQT > 0 #include "param.h" #include "pdp/psl.h" #include "pdp/seg.h" #include "map.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "protosw.h" #include "socket.h" #include "ioctl.h" #include "errno.h" #include "syslog.h" #include "time.h" #include "kernel.h" #include "../net/if.h" #include "../net/netisr.h" #include "../net/route.h" #ifdef INET #include "domain.h" #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netinet/in_var.h" #include "../netinet/ip.h" #include "../netinet/if_ether.h" #endif #ifdef NS #include "../netns/ns.h" #include "../netns/ns_if.h" #endif #include "if_qtreg.h" #include "if_uba.h" #include "../pdpuba/ubavar.h" #define NRCV 16 /* Receive descriptors (must be <= 32) */ #define NXMT 6 /* Transmit descriptors (must be <= 12) */ #if NRCV > 32 || NXMT > 12 generate an error #endif struct qt_uba { struct qt_uba *next; /* link to next buffer in list or * NULL if the last buffer */ struct ifuba ubabuf; /* buffer descriptor */ }; struct qt_softc { struct arpcom is_ac; /* common part - must be first */ #define is_if is_ac.ac_if /* network-visible interface */ #define is_addr is_ac.ac_enaddr /* hardware Ethernet address */ struct qt_uba *freelist; /* list of available buffers */ struct qt_uba ifrw[NRCV + NXMT]; u_short initclick; /* click addr of the INIT block */ struct qt_rring *rring; /* Receive ring address */ struct qt_tring *tring; /* Transmit ring address */ char r_align[QT_MAX_RCV * sizeof (struct qt_rring) + 8]; char t_align[QT_MAX_XMT * sizeof (struct qt_tring) + 8]; short qt_flags; /* software state */ #define QTF_RUNNING 0x1 #define QTF_STARTUP 0x2 /* Waiting for start interrupt */ char rindex; /* Receive Completed Index */ char nxtrcv; /* Next Receive Index */ char nrcv; /* Number of Receives active */ char tindex; /* Transmit index */ char otindex; /* Old transmit index */ char nxmit; /* # of xmits in progress */ struct qtdevice *addr; /* device CSR addr */ } qt_softc[NQT]; struct uba_device *qtinfo[NQT]; int qtattach(), qtintr(), qtinit(), qtoutput(), qtioctl(); extern struct ifnet loif; u_short qtstd[] = { 0 }; struct uba_driver qtdriver = { 0, 0, qtattach, 0, qtstd, "qe", qtinfo }; /* * Maximum packet size needs to include 4 bytes for the CRC * on received packets. */ #define MAXPACKETSIZE (ETHERMTU + sizeof (struct ether_header) + 4) #define MINPACKETSIZE 64 /* * The C compiler's propensity for prepending '_'s to names is the reason * for the hack below. We need the "handler" address (the code which * sets up the interrupt stack frame) in order to initialize the vector. */ static int qtfoo() { asm("mov $qtintr, r0"); /* return value is in r0 */ } /* * Interface exists. More accurately, something exists at the CSR (see * sys/sys_net.c) -- there's no guarantee it's a DELQA-YM. * * The ring descriptors are initialized, the buffers allocated using first the * DMA region allocated at network load time and then later main memory. The * INIT block is filled in and the device is poked/probed to see if it really * is a DELQA-YM. If the device is not a -YM then a message is printed and * the 'if_attach' call is skipped. For a -YM the START command is issued, * but the device is not marked as running|up - that happens at interrupt level * when the device interrupts to say it has started. */ qtattach(ui) struct uba_device *ui; { register struct qt_softc *sc = &qt_softc[ui->ui_unit]; register struct ifnet *ifp = &sc->is_if; register struct qt_init *iniblk = (struct qt_init *)SEG5; segm seg5; long bufaddr; extern int nextiv(); ifp->if_unit = ui->ui_unit; ifp->if_name = "qe"; ifp->if_mtu = ETHERMTU; ifp->if_flags = IFF_BROADCAST; /* * Fill in most of the INIT block: vector, options (interrupt enable), ring * locations. The physical address is copied from the ROMs as part of the * -YM testing proceedure. The CSR is saved here rather than in qtinit() * because the qtturbo() routine needs it. * * The INIT block must be quadword aligned. Using malloc() guarantees click * (64 byte) alignment. Since the only time the INIT block is referenced is * at 'startup' or 'reset' time there is really no time penalty (and a modest * D space savings) involved. */ sc->addr = (struct qtdevice *)ui->ui_addr; sc->initclick = MALLOC(coremap, btoc(sizeof (struct qt_init))); saveseg5(seg5); mapseg5(sc->initclick, 077406); bzero(iniblk, sizeof (struct qt_init)); sc->rring = (struct qt_rring *)(((int)sc->r_align + 7) & ~7); sc->tring = (struct qt_tring *)(((int)sc->t_align + 7) & ~7); /* * Fetch the next available interrupt vector. The routine is in the kernel * (for several reasons) so use SKcall. Then initialize the vector with * the address of our 'handler' and PSW of supervisor, priority 4 and unit */ iniblk->vector = SKcall(nextiv, 0); mtkd(iniblk->vector, qtfoo()); mtkd(iniblk->vector + 2, PSL_CURSUP | PSL_BR4 | ifp->if_unit); iniblk->options = INIT_OPTIONS_INT; bufaddr = startnet + (long)sc->rring; iniblk->rx_lo = loint(bufaddr); iniblk->rx_hi = hiint(bufaddr); bufaddr = startnet + (long)sc->tring; iniblk->tx_lo = loint(bufaddr); iniblk->tx_hi = hiint(bufaddr); restorseg5(seg5); /* * Now allocate the buffers and initialize the buffers. This should _never_ * fail because main memory is allocated after the DMA pool is used up. */ if (!qbaini(sc, NRCV + NXMT)) return; /* XXX */ ifp->if_init = qtinit; ifp->if_output = qtoutput; ifp->if_ioctl = qtioctl; ifp->if_reset = 0; if (qtturbo(sc)) if_attach(ifp); } qtturbo(sc) register struct qt_softc *sc; { register int i; register struct qtdevice *addr = sc->addr; struct qt_init *iniblk = (struct qt_init *)SEG5; segm seg5; /* * Issue the software reset. Delay 150us. The board should now be in * DELQA-Normal mode. Set ITB and DEQTA select. If both bits do not * stay turned on then the board is not a DELQA-YM. */ addr->arqr = ARQR_SR; addr->arqr = 0; delay(150L); addr->srr = 0x8001; /* MS | ITB */ i = addr->srr; addr->srr = 0x8000; /* Turn off ITB, set DELQA select */ if (i != 0x8001) { printf("qt@%o !-YM\n", addr); return(0); } /* * Board is a DELQA-YM. Send the commands to enable Turbo mode. Delay * 1 second, testing the SRR register every millisecond to see if the * board has shifted to Turbo mode. */ addr->xcr0 = 0x0baf; addr->xcr1 = 0xff00; for (i = 0; i < 1000; i++) { if ((addr->srr & SRR_RESP) == 1) break; delay(1000L); } if (i >= 1000) { printf("qt@%o !Turbo\n", addr); return(0); } /* * Board has entered Turbo mode. Now copy the physical address from the * ROMs to the INIT block. Fill in the address in the part of the structure * "visible" to the rest of the system. */ saveseg5(seg5); mapseg5(sc->initclick, 077406); sc->is_addr[0] = addr->sarom[0]; sc->is_addr[1] = addr->sarom[2]; sc->is_addr[2] = addr->sarom[4]; sc->is_addr[3] = addr->sarom[6]; sc->is_addr[4] = addr->sarom[8]; sc->is_addr[5] = addr->sarom[10]; bcopy(sc->is_addr, iniblk->paddr, 6); restorseg5(seg5); return(1); } qtinit(unit) int unit; { int s; register struct qt_softc *sc = &qt_softc[unit]; struct qtdevice *addr = sc->addr; struct ifnet *ifp = &sc->is_if; struct qt_rring *rp; struct qt_tring *tp; register struct qt_uba *xp; register int i; long buf_adr; if (!ifp->if_addrlist) /* oops! */ return; /* * Now initialize the receive ring descriptors. Because this routine can be * called with outstanding I/O operations we check the ring descriptors for * a non-zero 'rhost0' (or 'thost0') word and place those buffers back on * the free list. */ for (i = 0, rp = sc->rring; i < QT_MAX_RCV; i++, rp++) { rp->rmd3 = RMD3_OWN; if (xp = rp->rhost0) { rp->rhost0 = 0; xp->next = sc->freelist; sc->freelist = xp; } } for (i = 0, tp = sc->tring ; i < QT_MAX_XMT; i++, tp++) { sc->tring[i].tmd3 = TMD3_OWN; if (xp = tp->thost0) { tp->thost0 = 0; xp->next = sc->freelist; sc->freelist = xp; } } sc->nxmit = 0; sc->otindex = 0; sc->tindex = 0; sc->rindex = 0; sc->nxtrcv = 0; sc->nrcv = 0; s = splimp(); /* * Now we tell the device the address of the INIT block. The device * _must_ be in the Turbo mode at this time. The "START" command is * then issued to the device. A 1 second timeout is then started. * When the interrupt occurs the IFF_UP|IFF_RUNNING state is entered and * full operations will proceed. If the timeout expires without an interrupt * being received an error is printed, the flags cleared and the device left * marked down. */ buf_adr = ctob((long)sc->initclick); addr->ibal = loint(buf_adr); addr->ibah = hiint(buf_adr); addr->srqr = 2; /* * set internal state to 'startup' and start a one second timer. the interrupt * service routine will be entered either 1) when the device posts the 'start' * interrupt or 2) when the timer expires. The interrupt routine will fill * the receive rings, etc. */ sc->qt_flags = QTF_STARTUP; TIMEOUT(qtintr, unit, 60); splx(s); } /* * Start output on interface. */ qtstart(unit) int unit; { int len, s; register struct qt_softc *sc = &qt_softc[unit]; register struct qt_tring *rp; struct mbuf *m; long buf_addr; register struct qt_uba *xp; s = splimp(); while (sc->nxmit < NXMT) { IF_DEQUEUE(&sc->is_if.if_snd, m); if (m == 0) break; rp = &sc->tring[sc->tindex]; #ifdef QTDEBUG if ((rp->tmd3 & TMD3_OWN) == 0) printf("qt xmit in progress\n"); #endif /* * Now pull a buffer off of the freelist. Guaranteed to be a buffer * because both the receive and transmit sides limit themselves to * NRCV and NXMT buffers respectively. */ xp = sc->freelist; sc->freelist = xp->next; buf_addr = xp->ubabuf.ifu_w.ifrw_info; len = if_wubaput(&xp->ubabuf, m); if (len < MINPACKETSIZE) len = MINPACKETSIZE; rp->tmd4 = loint(buf_addr); rp->tmd5 = hiint(buf_addr) & TMD5_HADR; rp->tmd3 = len & TMD3_BCT; /* set length,clear ownership */ rp->thost0 = xp; /* set entry active */ sc->addr->arqr = ARQR_TRQ; /* tell device it has buffer */ sc->nxmit++; if (++sc->tindex >= QT_MAX_XMT) sc->tindex = 0; } splx(s); } /* * General interrupt service routine. Receive, transmit, device start * interrupts and timeouts come here. Check for hard device errors and print a * message if any errors are found. If we are waiting for the device to * START then check if the device is now running. */ qtintr(unit) int unit; { register struct qt_softc *sc = &qt_softc[unit]; register int status; int s; status = sc->addr->srr; if (status < 0) /* should we reset the device after a bunch of these errs? */ qtsrr(unit, status); if (sc->qt_flags == QTF_STARTUP) { if ((status & SRR_RESP) == 2) { sc->qt_flags = QTF_RUNNING; sc->is_if.if_flags |= (IFF_UP | IFF_RUNNING); } else printf("qt%d !start\n", unit); } s = splimp(); qtrint(unit); if (sc->nxmit) qttint(unit); qtstart(unit); splx(s); } /* * Transmit interrupt service. Only called if there are outstanding transmit * requests which could have completed. The DELQA-YM doesn't provide the * status bits telling the kind (receive, transmit) of interrupt. */ #define BBLMIS (TMD2_BBL|TMD2_MIS) qttint(unit) int unit; { register struct qt_softc *sc = &qt_softc[unit]; register struct qt_tring *rp; register struct qt_uba *xp; while (sc->nxmit > 0) { rp = &sc->tring[sc->otindex]; if ((rp->tmd3 & TMD3_OWN) == 0) break; /* * Now check the buffer address (the first word in the ring descriptor * available for the host's use). If it is NULL then we have already seen * and processed (or never presented to the board in the first place) this * entry and the ring descriptor should not be counted. */ xp = rp->thost0; if (xp == 0) break; /* * Clear the buffer address from the ring descriptor and put the * buffer back on the freelist for future use. */ rp->thost0 = 0; xp->next = sc->freelist; sc->freelist = xp; sc->nxmit--; sc->is_if.if_opackets++; /* * Collisions don't count as output errors, but babbling and missing packets * do count as output errors. */ if (rp->tmd2 & TMD2_CER) sc->is_if.if_collisions++; if ((rp->tmd0 & TMD0_ERR1) || ((rp->tmd2 & TMD2_ERR2) && (rp->tmd2 & BBLMIS))) { #ifdef QTDEBUG printf("qt%d tmd2 %b\n", unit, rp->tmd2, TMD2_BITS); #endif sc->is_if.if_oerrors++; } if (++sc->otindex >= QT_MAX_XMT) sc->otindex = 0; } } /* * Receive interrupt service. Pull packet off the interface and put into * a mbuf chain for processing later. */ qtrint(unit) int unit; { register struct qt_softc *sc = &qt_softc[unit]; register struct qt_rring *rp; register struct qt_uba *xp; int len; long bufaddr; while (sc->rring[sc->rindex].rmd3 & RMD3_OWN) { rp = &sc->rring[sc->rindex]; /* * If the host word is 0 then this is a buffer either already seen or not * presented to the device in the first place. */ xp = rp->rhost0; if (xp == 0) break; if ((rp->rmd0 & (RMD0_STP|RMD0_ENP)) != (RMD0_STP|RMD0_ENP)) { printf("qt%d chained packet\n", unit); sc->is_if.if_ierrors++; goto rnext; } len = (rp->rmd1 & RMD1_MCNT) - 4; /* -4 for CRC */ sc->is_if.if_ipackets++; if ((rp->rmd0 & RMD0_ERR3) || (rp->rmd2 & RMD2_ERR4)) { sc->is_if.if_ierrors++; #ifdef QTDEBUG printf("qt%d rmd0 %b\n", unit, rp->rmd0, RMD0_BITS); printf("qt%d rmd2 %b\n", unit, rp->rmd2, RMD2_BITS); #endif } else qtread(sc, &xp->ubabuf, len - sizeof (struct ether_header)); rnext: --sc->nrcv; if (++sc->rindex >= QT_MAX_RCV) sc->rindex = 0; /* * put the buffer back on the free list and clear the first host word * in the ring descriptor so we don't process this one again. */ xp->next = sc->freelist; sc->freelist = xp; rp->rhost0 = 0; } while (sc->nrcv < NRCV) { rp = &sc->rring[sc->nxtrcv]; #ifdef QTDEBUG if ((rp->rmd3 & RMD3_OWN) == 0) printf("qtrint: !OWN\n"); #endif xp = sc->freelist; sc->freelist = xp->next; bufaddr = xp->ubabuf.ifu_r.ifrw_info; rp->rmd1 = MAXPACKETSIZE; rp->rmd4 = loint(bufaddr); rp->rmd5 = hiint(bufaddr); rp->rhost0 = xp; rp->rmd3 = 0; /* clear RMD3_OWN */ ++sc->nrcv; sc->addr->arqr = ARQR_RRQ; /* tell device it has buffer */ if (++sc->nxtrcv >= QT_MAX_RCV) sc->nxtrcv = 0; } } /* * Place data on the appropriate queue and call the start routine to * send the data to the device. */ qtoutput(ifp, m0, dst) struct ifnet *ifp; struct mbuf *m0; struct sockaddr *dst; { int type, s, trail; u_char edst[6]; struct in_addr idst; register struct ether_header *eh; register struct qt_softc *is = &qt_softc[ifp->if_unit]; register struct mbuf *m = m0; struct mbuf *mcopy = (struct mbuf *)0; if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { m_freem(m0); return(ENETDOWN); } switch (dst->sa_family) { #ifdef INET case AF_INET: idst = ((struct sockaddr_in *)dst)->sin_addr; if (!arpresolve(&is->is_ac, m, &idst, edst,&trail)) return(0); /* wait for arp to finish */ if (!bcmp(edst, etherbroadcastaddr,sizeof (edst))) mcopy = m_copy(m, 0, (int)M_COPYALL); type = ETHERTYPE_IP; break; #endif #ifdef NS case AF_NS: type = ETHERTYPE_NS; bcopy(&(((struct sockaddr_ns *)dst)->sns_addr.x_host), edst, sizeof (edst)); if (!bcmp(edst, &ns_broadcast, sizeof (edst))) return(looutput(&loif, m, dst)); break; #endif case AF_UNSPEC: eh = (struct ether_header *)dst->sa_data; bcopy(eh->ether_dhost, (caddr_t)edst, sizeof (edst)); type = eh->ether_type; break; default: printf("qt%d can't handle af%d\n", ifp->if_unit, dst->sa_family); m_freem(m); return(EAFNOSUPPORT); } /* * Add local net header. If no space in first mbuf, allocate another. */ if (m->m_off > MMAXOFF || MMINOFF + sizeof (struct ether_header) > m->m_off) { m = m_get(M_DONTWAIT, MT_HEADER); if (m == 0) { m_freem(m0); nobufs: if (mcopy) m_freem(mcopy); return(ENOBUFS); } m->m_next = m0; m->m_off = MMINOFF; m->m_len = sizeof (struct ether_header); } else { m->m_off -= sizeof (struct ether_header); m->m_len += sizeof (struct ether_header); } eh = mtod(m, struct ether_header *); eh->ether_type = htons((u_short)type); bcopy(edst, (caddr_t)eh->ether_dhost, sizeof (edst)); bcopy(is->is_addr, (caddr_t)eh->ether_shost, sizeof (is->is_addr)); s = splimp(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); m_freem(m); splx(s); goto nobufs; } IF_ENQUEUE(&ifp->if_snd, m); qtstart(ifp->if_unit); splx(s); return(mcopy ? looutput(&loif, mcopy, dst) : 0); } qtioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { struct qt_softc *sc = &qt_softc[ifp->if_unit]; struct ifaddr *ifa = (struct ifaddr *)data; int s = splimp(), error = 0; #ifdef NS register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); #endif switch (cmd) { case SIOCSIFADDR: /* * Resetting the board is probably overkill, but then again this is only * done when the system comes up or possibly when a reset is needed after a * major network fault (open wire, etc). */ qtrestart(sc); switch (ifa->ifa_addr.sa_family) { #ifdef INET case AF_INET: ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr; arpwhohas(ifp, &IA_SIN(ifa)->sin_addr); break; #endif #ifdef NS case AF_NS: if (ns_nullhost(*ina)) ina->x_host = *(union ns_host *)(sc->is_addr); else { qt_ns(ina->x_host.c_host); qtrestart(sc); } break; #endif } break; case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_UP) == 0 && sc->qt_flags & QTF_RUNNING) { /* * We've been asked to stop the board and leave it that way. qtturbo() * does this with the side effect of placing the device back in Turbo mode. */ qtturbo(sc); sc->qt_flags &= ~QTF_RUNNING; } else if (ifp->if_flags & IFF_UP && !(sc->qt_flags & QTF_RUNNING)) qtrestart(sc); break; default: error = EINVAL; } splx(s); return(error); } #ifdef NS qt_ns(cp) register char *cp; { segm seg5; register struct qt_init *iniblk = (struct qt_init *)SEG5; saveseg5(seg5); mapseg5(sc->initclick, 077406); bcopy(cp, sc->is_addr, 6); bcopy(cp, iniblk->paddr, 6); restorseg5(seg5); } #endif /* * Pull the data off of the board and pass back to the upper layers of * the networking code. Trailers are counted as errors and the packet * dropped. SEG5 is saved and restored (used to peek at the packet type). */ qtread(sc, ifuba, len) register struct qt_softc *sc; struct ifuba *ifuba; int len; { struct ether_header *eh; register struct mbuf *m; struct ifqueue *inq; int type; segm seg5; saveseg5(seg5); mapseg5(ifuba->ifu_r.ifrw_click, 077406); eh = (struct ether_header *)SEG5; eh->ether_type = ntohs((u_short)eh->ether_type); type = eh->ether_type; restorseg5(seg5); if (len == 0 || type >= ETHERTYPE_TRAIL && type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { sc->is_if.if_ierrors++; return; } m = if_rubaget(ifuba, len, 0, &sc->is_if); if (m == 0) return; switch (type) { #ifdef INET case ETHERTYPE_IP: schednetisr(NETISR_IP); inq = &ipintrq; break; case ETHERTYPE_ARP: arpinput(&sc->is_ac, m); return; #endif #ifdef NS case ETHERTYPE_NS: schednetisr(NETISR_NS); inq = &nsintrq; break; #endif default: m_freem(m); return; } if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); return; } IF_ENQUEUE(inq, m); } qtsrr(unit, srrbits) int unit, srrbits; { printf("qt%d srr=%b\n", unit, srrbits, SRR_BITS); } /* * Reset the device. This moves it from DELQA-T mode to DELQA-Normal mode. * After the reset put the device back in -T mode. Then call qtinit() to * reinitialize the ring structures and issue the 'timeout' for the "device * started interrupt". */ qtrestart(sc) register struct qt_softc *sc; { qtturbo(sc); qtinit(sc - qt_softc); } qbaini(sc, num) struct qt_softc *sc; int num; { register int i; register memaddr click; struct qt_uba *xp; register struct ifuba *ifuba; for (i = 0; i < num; i++) { xp = &sc->ifrw[i]; ifuba = &xp->ubabuf; click = m_ioget(MAXPACKETSIZE); if (click == 0) { click = MALLOC(coremap, btoc(MAXPACKETSIZE)); if (click == 0) return(0); /* _can't_ happen */ } ifuba->ifu_hlen = sizeof (struct ether_header); ifuba->ifu_w.ifrw_click = ifuba->ifu_r.ifrw_click = click; ifuba->ifu_w.ifrw_info = ifuba->ifu_r.ifrw_info = ctob((long)click); xp->next = sc->freelist; sc->freelist = xp; } return(1); } #endif ntr(unit) int unit; { register struct qt_softc *sc = &qt_softc[unit]; register int status; int s; status = sc->addr->srr; if (status < 0) /* should we reset the device after a bunch of these errs? */ qtsrr(unit, status); if (sc->qt_flags == QTF_STARTUP) { if ((status & SRR_RESPsys/pdpmba/ 755 0 12 0 4057702414 6027 sys/pdpmba/tags 751 0 12 0 6045325362 10636 2../sys/tagssys/pdpdist/ 755 0 12 0 6016521566 6237 sys/pdpdist/MAKEDEV 755 0 12 22434 5770745770 7366 #!/bin/sh - # # Copyright (c) 1980 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)MAKEDEV 4.27.2 (2.11BSD GTE) 1995/06/17 # # Device "make" file. Valid arguments: # std standard devices # local configuration specific devices # Tapes: # ht* unibus tu77 & te16 # tm* unibus tm11 & te10 emulations (e.g. Emulex tc-11) # ts* unibus ts11 # tu* tmscp (tk50/tu81) # Disks: # br* unibus Eaton br1538 or br1711 # hk* unibus rk06 and rk07 # ra* unibus uda50 w/ ra?? # rk* unibus rk05 # rl* unibus rl01/rl02 # rx* unibus rx02 # si* unibus cdc 9766 w/ si 9500 # xp* unibus rm02/03/05, rp04/05/06, diva, eagle, cdc9766, fuji 160. # Terminal multiplexors: # dl* dl-11 units other than the console # dz* unibus dz11 and dz32 # dh* unibus dh11 and emulations (e.g. Able dmax, Emulex cs-11) # dmf* unibus dmf32 # dhu* unibus dhu11 # dmz* unibus dmz32 # dhv* qbus dhv11 # Pseudo terminals: # pty* set of 16 master and slave pseudo terminals # Printers: # lp* unibus lp11 parallel interface # va* unibus varian parallel interface # vp* unibus versatec parallel interface # Call units: # Special purpose devices: # dr* unibus dr11 # ram* memory disk # dn* dn11 dialer # ingreslock Ingres lock driver. umask 77 for i do case $i in std) /etc/mknod console c 0 0 # /etc/mknod kUmem c 1 3 ; chmod 600 kUmem ;: untested /etc/mknod kmem c 1 1 ; chmod 640 kmem ; chgrp kmem kmem /etc/mknod mem c 1 0 ; chmod 640 mem ; chgrp kmem mem /etc/mknod null c 1 2 ; chmod 666 null /etc/mknod tty c 9 0 ; chmod 666 tty /etc/mknod klog c 22 0 ; chmod 600 klog ;; ht*|tm*|ts*|tu*) umask 0 ; ctlr=`expr $i : '..\(.*\)'` ctlr=`expr $ctlr '*' 64` case $i in ht*) blk=0; chr=6;; tm*) blk=1; chr=7;; ts*) blk=2; chr=8;; tu*) blk=12; chr=23;; esac # Maximum of 4 controllers in a system case $ctlr in 0|64|128|192) # Maximum of 4 units per controller # for unit in 0 1 2 3 for unit in 0 1 do zero=`expr $ctlr + $unit + 0` four=`expr $zero + 4` ; eight=`expr $zero + 8` twelve=`expr $zero + 12` sixteen=`expr $zero + 16` twenty=`expr $zero + 20` twentyfour=`expr $zero + 24` twentyeight=`expr $zero + 28` /etc/mknod mt$zero b $blk $zero /etc/mknod mt$four b $blk $four /etc/mknod mt$eight b $blk $eight /etc/mknod mt$twelve b $blk $twelve /etc/mknod nmt$zero b $blk $four ;: v7 compatibility /etc/mknod nmt$eight b $blk $twelve ;: ditto /etc/mknod nrmt$zero c $chr $four ;: ditto /etc/mknod nrmt$eight c $chr $twelve ;: ditto /etc/mknod rmt$zero c $chr $zero /etc/mknod rmt$four c $chr $four /etc/mknod rmt$eight c $chr $eight /etc/mknod rmt$twelve c $chr $twelve if [ `expr $i : '\(..\)'` = tu ] then /etc/mknod mt$sixteen b $blk $sixteen /etc/mknod mt$twenty b $blk $twenty /etc/mknod mt$twentyfour b $blk $twentyfour /etc/mknod mt$twentyeight b $blk $twentyeight /etc/mknod nmt$sixteen b $blk $twenty ;: v7 compatibility /etc/mknod nmt$twentyfour b $blk $twentyeight ;: ditto /etc/mknod nrmt$sixteen c $chr $twenty ;: ditto /etc/mknod nrmt$twentyfour c $chr $twentyeight ;: ditto /etc/mknod rmt$sixteen c $chr $sixteen /etc/mknod rmt$twenty c $chr $twenty /etc/mknod rmt$twentyfour c $chr $twentyfour /etc/mknod rmt$twentyeight c $chr $twentyeight fi if [ `expr $i : '\(..\)'` = ut ] then /etc/mknod mt$twenty b $blk $twenty /etc/mknod rmt$twenty c $chr $twenty fi done ;; *) echo bad controller for tape in: $1 ;; esac umask 77 ;; rk*) # The 2.11BSD rk driver doesn't support partitions. We create # a single block and charater inode pair for each unit and # call it rkNh. umask 2 ; unit=`expr $i : '..\(.*\)'` case $i in rk*) name=rk; blk=6; chr=15;; esac /etc/mknod ${name}${unit}h b ${blk} ${unit} /etc/mknod r${name}${unit}h c ${chr} ${unit} chgrp operator ${name}${unit}h r${name}${unit}h chmod 640 ${name}${unit}h r${name}${unit}h ;; rx*) umask 2 name=rx; blk=8; chr=17 mknod ${name}0a b ${blk} 0 mknod ${name}1a b ${blk} 1 mknod ${name}0b b ${blk} 2 mknod ${name}1b b ${blk} 3 mknod r${name}0a c ${chr} 0 mknod r${name}1a c ${chr} 1 mknod r${name}0b c ${chr} 2 mknod r${name}1b c ${chr} 3 chgrp operator ${name}[01][ab] r${name}[01][ab] chmod 640 ${name}[01][ab] r${name}[01][ab] ;; ram*) # Note, this must come *before* the "ra*". The entry "rram" is for # auto fscks when ram is mentioned in /etc/fstab. umask 2 /etc/mknod ram b 3 0 ln ram rram chgrp operator ram chmod 640 ram umask 77 ;; br*|hk*|ra*|si*|xp*|rl*) umask 2 ; unit=`expr $i : '..\(.*\)'` case $i in br*) name=rp; blk=11; chr=20;; hk*) name=hk; blk=4; chr=13;; ra*) name=ra; blk=5; chr=14;; si*) name=si; blk=9; chr=18;; xp*) name=xp; blk=10; chr=19;; rl*) name=rl; blk=7; chr=16;; esac case $unit in 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|\ 17|18|19|20|21|22|23|24|25|26|27|28|29|30|31) /etc/mknod ${name}${unit}a b $blk `expr $unit '*' 8 + 0` /etc/mknod ${name}${unit}b b $blk `expr $unit '*' 8 + 1` /etc/mknod ${name}${unit}c b $blk `expr $unit '*' 8 + 2` /etc/mknod ${name}${unit}d b $blk `expr $unit '*' 8 + 3` /etc/mknod ${name}${unit}e b $blk `expr $unit '*' 8 + 4` /etc/mknod ${name}${unit}f b $blk `expr $unit '*' 8 + 5` /etc/mknod ${name}${unit}g b $blk `expr $unit '*' 8 + 6` /etc/mknod ${name}${unit}h b $blk `expr $unit '*' 8 + 7` /etc/mknod r${name}${unit}a c $chr `expr $unit '*' 8 + 0` /etc/mknod r${name}${unit}b c $chr `expr $unit '*' 8 + 1` /etc/mknod r${name}${unit}c c $chr `expr $unit '*' 8 + 2` /etc/mknod r${name}${unit}d c $chr `expr $unit '*' 8 + 3` /etc/mknod r${name}${unit}e c $chr `expr $unit '*' 8 + 4` /etc/mknod r${name}${unit}f c $chr `expr $unit '*' 8 + 5` /etc/mknod r${name}${unit}h c $chr `expr $unit '*' 8 + 7` /etc/mknod r${name}${unit}g c $chr `expr $unit '*' 8 + 6` chgrp operator ${name}${unit}[a-h] r${name}${unit}[a-h] chmod 640 ${name}${unit}[a-h] r${name}${unit}[a-h] ;; *) echo bad unit for disk in: $i ;; esac umask 77 ;; dz*) unit=`expr $i : 'dz\(.*\)'` case $unit in 0|1|2|3|4|5|6|7) eval `echo $unit | awk ' { u = $1 } END { for (i = 0; i < 8; i++) printf("/etc/mknod tty%02d c 2 %d; ",u*8+i,u*8+i); }'` ;; *) echo bad unit for dz in: $i ;; esac ;; # # we may want dmz and dmf someday... # dhu*|dh*|dmf*|dmz*) dhv*|dhu*|dh*) case $i in # dmz*) name=dmz; major=37; count=24; # unit=`expr $i : "$name\(.*\)"` # case $unit in # 0) ch=a ;; 1) ch=b ;; 2) ch=c ;; 3) ch=e ;; # 4) ch=f ;; 5) ch=g ;; # *) echo bad unit for $name in: $i ;; # esac;; # dmf*) name=dmf; major=22; count=8; # unit=`expr $i : "$name\(.*\)"` # case $unit in # 0) ch=A ;; 1) ch=B ;; 2) ch=C ;; 3) ch=E ;; # 4) ch=F ;; 5) ch=G ;; 6) ch=H ;; 7) ch=I ;; # *) echo bad unit for $name in: $i ;; # esac;; dhv*) name=dhv; major=24; count=8; unit=`expr $i : "$name\(.*\)"`; case $unit in 0) ch=S ;; 1) ch=T ;; 2) ch=U ;; 3) ch=V ;; 4) ch=W ;; 5) ch=X ;; 6) ch=Y ;; 7) ch=Z ;; *) echo bad unit for $name in: $i ;; esac;; dhu*) name=dhu; major=4; count=16; unit=`expr $i : "$name\(.*\)"`; case $unit in 0) ch=S ;; 1) ch=T ;; 2) ch=U ;; 3) ch=V ;; 4) ch=W ;; 5) ch=X ;; 6) ch=Y ;; 7) ch=Z ;; *) echo bad unit for $name in: $i ;; esac;; dh*) name=dh; major=3; count=16; unit=`expr $i : "$name\(.*\)"` case $unit in 0) ch=h ;; 1) ch=i ;; 2) ch=j ;; 3) ch=k ;; *) echo bad unit for $name in: $i ;; esac;; esac eval `echo $ch $unit $major $count | awk ' { ch = $1; u = $4 * $2; m = $3; cnt = $4 } END { for (i = 0; i < cnt; i++) if (i < 10) printf("/etc/mknod tty%s%x c %d %d; ",ch,i,m,u+i); else printf("/etc/mknod tty%s%c c %d %d; ",ch,87+i,m,u+i); }'` ;; # extra DL-11 units not including the console. unit numbers start at 1 because # the console is always unit 0. Seven units (1 - 7) are defined for the 11/93 # and 11/94. Device name is "ttyl?". The DH range was restricted from 'h'-'o' # to 'h' - 'k' (very unlikely that more than 64 channels of DH-11 will or could # be put on an 11. dl*) name=dl; major=0; ch=l unit=`expr $i : "$name\(.*\)"` case $unit in 1|2|3|4|5|6|7) /etc/mknod tty${ch}${unit} c $major $unit; ;; *) echo bad unit for $name in: $i ;; esac ;; # we may want va and vp someday... # lp*|va*|vp*) lp*|dn*) case $i in lp*) name=lp; major=5;; dn*) name=dn; major=21;; # va*) name=va; major=10;; # vp*) name=vp; major=6;; esac unit=`expr $i : "$name\(.*\)"` case $unit in 0|1|2|3|4|5|6|7) /etc/mknod $i c $major $unit; chmod 666 $i ;; *) echo bad unit for $name in: $i ;; esac ;; pty*) class=`expr $i : 'pty\(.*\)'` case $class in 0) offset=0 name=p;; 1) offset=16 name=q;; 2) offset=32 name=r;; 3) offset=48 name=s;; 4) offset=64 name=t;; 5) offset=80 name=u;; *) echo bad unit for pty in: $i;; esac case $class in 0|1|2|3|4|5) umask 0 eval `echo $offset $name | awk ' { b=$1; n=$2 } END { for (i = 0; i < 16; i++) printf("/etc/mknod tty%s%x c 11 %d; \ /etc/mknod pty%s%x c 10 %d; ", \ n, i, b+i, n, i, b+i); }'` umask 77 ;; esac ;; dr*) unit=`expr $i : '..\(.*\)'` case $i in dr*) name=dr; chr=12;; esac case $unit in 0|1|2|3|4|5|6|7) umask 0 /etc/mknod ${name}${unit} c ${chr} ${unit} umask 77 ;; *) echo bad unit for ${name} in: $i ;; esac ;; ingreslock) mknod ingreslock c 25 0 chown ingres ingreslock chmod 200 ingreslock ;; local) sh MAKEDEV.local ;; esac done ns don't count as output errors, but babbling and missing packets * do count as output errors. */ if (rp->tmd2 & TMD2_CER) sc->is_if.if_collisions++; if ((rp->tmd0 & TMD0_ERR1) || ((rp->tmd2 & TMD2_ERR2) && (rp->tmdsys/pdpdist/motd 644 3 12 127 4733730010 7163 2.11 BSD UNIX #1: Fri Jun 6 19:55:29 PDT 1986 Would you like to play a (slow) game? rc.localhserviceshshellshprintcaph ttyss syslog.confs inetd.confs groupdisktabnf dtabsnetstartfsys/pdpdist/passwd 444 0 12 567 4704162461 7533 root::0:1:The Man:/:/bin/csh daemon:*:1:1:The devil himself:/:/bin/sh operator:*:2:5:System &:/usr/guest/operator:/bin/csh bin:*:3:20:Binaries Commands and Source:/:/bin/csh nobody:*:32767:31:Nobody:/nonexistent:/dev/null uucp:*:66:1:UNIX-to-UNIX Copy:/usr/spool/uucppublic:/usr/lib/uucp/uucico sms:*:10:10:Steven M. Schultz (sms@wlv.imsd.contel.com):/usr/guest/sms:/bin/csh sys/pdpdist/rc 744 3 12 7210 5316470103 6647 HOME=/; export HOME PATH=/etc:/bin:/usr/ucb:/usr/bin; export PATH # If you have a ram disk configured into your system which is listed in # /etc/fstab, you'll have to do a mkfs on it here and probably change the # ownership and modes below after the standard file systems have been # mounted. # RAMSIZE=0 RAMFS=/tmp RAMOWNER=root RAMGROUP=wheel RAMMODE=1777 if [ ${RAMSIZE} != 0 ] then /etc/mkfs /dev/ram ${RAMSIZE} 1 2 fi if [ "$2" = powerfail ] then echo REBOOTING AFTER POWER FAILURE >/dev/console 2>&1 fi if [ "$1" = fastboot ] then echo Fast boot ... skipping disk checks >/dev/console 2>&1 elif [ "$1" = autoboot ] then echo Automatic reboot in progress... >/dev/console 2>&1 date >/dev/console 2>&1 # this will *only* work if fsck can do your root file system # without a temporary file, and if the root file system is # checked alone in a pass by itself -- be careful! This can # *seriously* mess you up. fsck -p -t /_FSCK_TMP_FILE >/dev/console 2>&1 case $? in 0) date >/dev/console 2>&1 ;; 2) exit 1 ;; 4) reboot -n ;; 8) echo "Automatic reboot failed... help!" >/dev/console 2>&1 exit 1 ;; 12) echo "Reboot interrupted" >/dev/console 2>&1 exit 1 ;; *) echo "Unknown error in reboot" >/dev/console 2>&1 exit 1 ;; esac else date >/dev/console 2>&1 fi # attempt to rationally recover the passwd file if needed if [ -s /etc/ptmp ] then echo 'password file may be incorrect' > /dev/console fi umount -a cp /dev/null /etc/mtab mount -a >/dev/console 2>&1 if [ ${RAMSIZE} != 0 ] then chown ${RAMOWNER}.${RAMGROUP} ${RAMFS} chmod ${RAMMODE} ${RAMFS} fi echo -n 'checking quotas:' >/dev/console 2>&1 quotacheck -a -p >/dev/console 2>&1 echo ' done.' >/dev/console 2>&1 quotaon -a ps -U >/dev/console 2>&1 rm -f /etc/nologin rm -f /usr/spool/uucp/LCK.* rm -f /usr/spool/uucp/STST/* chmod 666 /dev/tty[pqrs]* # set hostname and INET, turn on network . /etc/netstart if [ $INET = YES ]; then echo 'starting system logger' >/dev/console 2>&1 rm -f /dev/log syslogd fi # /etc/crash should be a symbolic link to the crash directory # if core dumps are to be saved. if [ -d /etc/crash ]; then echo 'checking for core dump... ' >/dev/console 2>&1 savecore /etc/crash >/dev/console 2>&1 fi echo preserving editor files >/dev/console 2>&1 (cd /tmp; /usr/lib/ex3.7preserve -a) echo clearing /tmp >/dev/console 2>&1 (cd /tmp; find . ! -name . ! -name lost+found ! -name quotas -exec rm -r {} \; ) echo -n standard daemons: >/dev/console 2>&1 update; echo -n ' update' >/dev/console 2>&1 cron; echo -n ' cron' >/dev/console 2>&1 accton /usr/adm/acct; echo -n ' accounting' >/dev/console 2>&1 echo '.' >/dev/console 2>&1 if [ $INET = YES ]; then echo -n starting network daemons: >/dev/console 2>&1 # $routedflags is imported from /etc/netstart; # if $routedflags == NO, routed isn't run. if [ "${routedflags-NO}" != NO ]; then routed $routedflags; echo -n ' routed' >/dev/console 2>&1 fi # $named is imported from /etc/netstart; # if $named is set to something other than NO, named is run. if [ "${named-NO}" != NO ]; then named; echo -n ' named'>/dev/console 2>&1 fi inetd; echo -n ' inetd' >/dev/console 2>&1 # $rwhod is imported from /etc/netstart; # if $rwhod is set to something other than NO, rwhod is run. if [ "${rwhod-NO}" != NO ]; then rwhod; echo -n ' rwhod' >/dev/console 2>&1 fi rm -f /dev/printer /usr/lib/lpd; echo -n ' printer' >/dev/console 2>&1 echo '.' >/dev/console 2>&1 else # lpd will run even with out networking. echo starting lpd >/dev/console 2>&1 /usr/lib/lpd fi . /etc/rc.local date >/dev/console 2>&1 exit 0 tc/mknod r${name}${unit}h c $chr `expr $unit '*' 8 + 7` /etc/mknod r${name}${unit}g c $chr `expr $unit '*' 8 + 6` chgrp operator ${name}${unit}[a-h] r${name}${unit}[a-h] chmod 640 ${name}${unit}[a-h] r${name}${unit}[a-h] ;; *) echo bad unit for disk in: $i ;; esac umask 77 ;; dz*) unit=`expr $i : 'dz\(.*\)'` case $unit in 0|1|2|3|4|5|6|7) eval `echo $usys/pdpdist/rc.local 744 3 12 1116 5316470117 7744 #! /bin/sh - # site-specific startup actions, daemons strings /vmunix | grep UNIX >/tmp/t1 tail +2 /etc/motd >>/tmp/t1 mv /tmp/t1 /etc/motd chmod 666 /etc/motd echo -n starting local daemons: >/dev/console 2>&1 #if [ $INET = YES -a -f /etc/timed ]; then # timed & echo -n ' timed' >/dev/console 2>&1 #fi if [ -f /usr/lib/sendmail ]; then (cd /usr/spool/mqueue; rm -f lf*) if [ $INET = YES ]; then /usr/lib/sendmail -bd -q30m; echo -n ' sendmail'>/dev/console 2>&1 else /usr/lib/sendmail -q30m; echo -n ' sendmail' >/dev/console 2>&1 fi fi echo '.' >/dev/console 2>&1 faed... help!" >/dev/console 2>&1 exit 1 ;; 12) echo "Reboot interrupted" >/dev/console 2>&1 exit 1 ;; *) echo "Unknown error in reboot" >/dev/console 2>&1 exit 1 ;; esac else date >/dev/console 2>&1 fi # attempt to rationally recover the passwd file if needed if [ -s /etc/ptmp ] then echo 'password file may be incorrect' > /dev/console fi umount -a cp /dev/null /etc/mtab mount -a >/dev/console 2>&sys/pdpdist/services 444 0 12 3052 4666310315 10065 # @(#)services 1.16 (Berkeley) 86/04/20 # # Network services, Internet style # echo 7/tcp echo 7/udp discard 9/tcp sink null discard 9/udp sink null systat 11/tcp users daytime 13/tcp daytime 13/udp netstat 15/tcp qotd 17/tcp quote chargen 19/tcp ttytst source chargen 19/udp ttytst source ftp 21/tcp telnet 23/tcp smtp 25/tcp mail time 37/tcp timserver time 37/udp timserver rlp 39/udp resource # resource location nameserver 42/tcp name # IEN 116 whois 43/tcp nicname domain 53/tcp nameserver # name-domain server domain 53/udp nameserver mtp 57/tcp # deprecated tftp 69/udp rje 77/tcp netrjs finger 79/tcp link 87/tcp ttylink supdup 95/tcp hostnames 101/tcp hostname # usually from sri-nic #csnet-cs 105/? pop 109/tcp postoffice sunrpc 111/tcp sunrpc 111/udp auth 113/tcp authentication sftp 115/tcp uucp-path 117/tcp nntp 119/tcp readnews untp # USENET News Transfer Protocol ntp 123/udp ntpd ntp # network time protocol (exp) # # UNIX specific services # exec 512/tcp biff 512/udp comsat login 513/tcp who 513/udp whod shell 514/tcp cmd # no passwords used syslog 514/udp printer 515/tcp spooler # line printer spooler talk 517/udp ntalk 518/udp efs 520/tcp # for LucasFilm route 520/udp router routed timed 525/udp timeserver tempo 526/tcp newdate courier 530/tcp rpc conference 531/tcp chat netnews 532/tcp readnews netwall 533/udp # -for emergency broadcasts uucp 540/tcp uucpd # uucp daemon remotefs 556/tcp rfs_server rfs # Brunhoff remote filesystem ingreslock 1524/tcp ould be a symbolic link to the crash directory # if core dumps are to be saved. if [ -d /etc/crash ]; then echo 'checking for core dump... ' >/dev/console 2>&1 savecore /etc/crash >/dev/console 2>&1 fi echo preserving editor files >/dev/console 2>&1 (cd /tmp; /usr/lib/ex3.7preserve -a) echo clearing /tmp >/dev/console 2>&1 (cd /tmp; find . ! -name . ! -name lost+found ! -name quotas -exec rm -r {} \; ) echo -n standard daemons: >/dev/console 2>&1sys/pdpdist/shells 444 0 12 215 4116340553 7507 # List of acceptable shells for chsh/passwd -s # Ftpd will not allow users to connect who do not have one of these shells # /bin/sh /bin/csh rintcaph ttyss syslog.confs inetd.confs groupdisktabnf dtabsnetstartfsys/pdpdist/printcap 444 0 12 115 4116340540 10030 lp|local line printer:\ :lp=/dev/lp:sd=/usr/spool/lpd:lf=/usr/adm/lpd-errs: rcdisrc.localhserviceshshellshprintcaph ttyss syslog.confs inetd.confs groupdisktabnf dtabsnetstartfsys/pdpdist/ttys 444 0 12 1446 4666310613 7253 # # name getty type status comments # console "/etc/getty Console-1200" unknown on secure tty00 "/etc/getty std.9600" unknown on secure tty01 "/etc/getty std.9600" unknown on secure tty02 "/etc/getty std.9600" unknown on secure tty03 "/etc/getty std.9600" unknown on secure tty04 "/etc/getty std.9600" unknown on secure tty05 "/etc/getty std.9600" unknown on secure tty06 "/etc/getty std.9600" unknown on secure tty07 "/etc/getty std.9600" unknown on secure ttyp0 none network ttyp1 none network ttyp2 none network ttyp3 none network ttyp4 none network ttyp5 none network ttyp6 none network ttyp7 none network ttyp8 none network ttyp9 none network ttypa none network ttypb none network ttypc none network ttypd none network ttype none network ttypf none network 11/udp auth 113/tcp authentication sftp 115/tcp uucp-path 117/tcp nntp 119/tcp readnews untp # USENET News Transfer Protocol ntp 123/udp ntpd ntp # network time protocol (exp) # # UNIX specific services # exec sys/pdpdist/syslog.conf 644 0 12 577 4506177754 10514 local7.debug /dev/null *.crit;*.err;kern.debug;auth.notice,local7.none /dev/console *.err;auth.notice;*.info;kern.debug;local3,local7,mail,daemon,lpr.none /usr/adm/messages lpr.debug /usr/adm/lpd-errs mail.debug /usr/spool/mqueue/syslog mark.debug;daemon.debug /usr/adm/daemonlog user.debug /usr/adm/debuglog *.alert;kern.err operator,root *.emerg * sys/pdpdist/inetd.conf 644 0 12 1761 4432144471 10277 # # Internet server configuration database # ftp stream tcp nowait root /etc/ftpd ftpd -l telnet stream tcp nowait root /etc/telnetd telnetd shell stream tcp nowait root /etc/rshd rshd login stream tcp nowait root /etc/rlogind rlogind exec stream tcp nowait root /etc/rexecd rexecd #uucpd stream tcp nowait root /etc/uucpd uucpd #nntp stream tcp nowait usenet /etc/nntpd nntpd #finger stream tcp nowait nobody /etc/fingerd fingerd #tftp dgram udp wait nobody /etc/tftpd tftpd comsat dgram udp wait root /etc/comsat comsat #talk dgram udp wait root /etc/talkd talkd #ntalk dgram udp wait root /etc/ntalkd ntalkd echo stream tcp nowait root internal #discard stream tcp nowait root internal #chargen stream tcp nowait root internal #daytime stream tcp nowait root internal #time stream tcp nowait root internal echo dgram udp wait root internal #discard dgram udp wait root internal #chargen dgram udp wait root internal #daytime dgram udp wait root internal time dgram udp wait root internal rvices # exec sys/pdpdist/group 444 0 12 230 4666307371 7361 wheel:*:0:root daemon:*:1:daemon kmem:*:2:root sys:*:3:root tty:*:4:root operator:*:5:root staff:*:10:root bin:*:20: guest:*:31:root ingres:*:74:ingres ttyss syslog.confs inetd.confs groupdisktabnf dtabsnetstartfsys/pdpdist/disktab 644 0 24 55372 6015267347 7732 # @(#)disktab 1.2 (2.11BSD) 1995/07/13 # # Disk geometry and partition layout tables. # Key: # dt controller type # ty type of disk (fixed, removeable, simulated) # d[0-4] drive-type-dependent parameters # ns #sectors/track # nt #tracks/cylinder # nc #cylinders/disk # sc #sectors/cylinder, nc*nt default # su #sectors/unit, sc*nc default # se sector size, 512 default (getdiskbyname always sets 512) # rm rpm, 3600 default # sf supports bad144-style bad sector forwarding # sk sector skew per track, default 0 # cs sector skew per cylinder, default 0 # hs headswitch time, default 0 # ts one-cylinder seek time, default 0 # il sector interleave (n:1), 1 default # bs boot block size, default BBSIZE (getdiskbyname returns BBSIZE) # sb superblock size, default SBSIZE (getdiskbyname returns SBSIZE) # b0 block zero dead start primary bootstrap # o[a-h] partition offsets in sectors # p[a-h] partition sizes in sectors # b[a-h] partition block sizes in bytes # f[a-h] partition fragment sizes in bytes # t[a-h] partition types (filesystem, swap, etc) # # On drives that contain bad-sector replacement areas the 'h' (and in some # cases 'c') partitions do NOT overlap the bad-sector track. # # Entries may also be used for other compatible drives # with the same geometry. # # Drives on xp # # These partition tables are a mess. Several of them overlap the bad # sector area, others do not overlap but end up with not cylinder sized # filesystems. Many of these aren't even in use any longer. A couple # did not even match the tables that were in the kernel. # # I've done my best to match these up with the old partition tables in # the 'xp' driver but a typo or arithmetic error could easily have crept in. # # RM02/03 - 'c' and 'h' partitions are whole drive except bad sector track. # rm02|RM02|rm03|RM03|DEC RM02/03:\ :ty=removable:ns#32:nt#5:nc#823:sf:\ :b0=/mdec/rm03uboot:\ :pa#9600:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#9600:ob#9600:bb#1024:fb#1024:tb=swap:\ :pc#131520:oc#0:bc#1024:fc#1024:\ :pf#121920:of#9600:bf#1024:ff#1024:tf=2.11BSD:\ :pg#112320:og#19200:bg#1024:fg#1024:tg=2.11BSD:\ :ph#131520:oh#0:bh#1024:fh#1024:th=2.11BSD # RM05: rm05|RM05|cdc9766|CDC9766|9766|DEC RM05, CDC 9766:\ :ty=removable:ns#32:nt#19:nc#823:sf:\ :b0=/mdec/rm05uboot:\ :pa#9120:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#9120:ob#9120:bb#1024:fb#1024:tb=swap:\ :pc#234080:oc#18240:bc#1024:fc#1024:tc=2.11BSD:\ :pd#247906:od#252320:bd#1024:fd#1024:td=2.11BSD:\ :pe#164160:oe#18240:be#1024:fe#1024:te=2.11BSD:\ :pf#152000:of#182400:bf#1024:ff#1024:tf=2.11BSD:\ :pg#165826:og#334400:bg#1024:fg#1024:tg=2.11BSD:\ :ph#500226:oh#0:bh#1024:fh#1024:th=2.11BSD 9775|CDC 9775:\ :ty=fixed:ns#32:nt#40:nc#842:sf:\ :pa#10240:oa#0:ba#1024:fa#1024:ty=2.11BSD:\ :pb#10240:ob#10240:bb#1024:fb#1024:tb=swap:\ :pc#510720:oc#20480:bc#1024:fc#1024:tc=2.11BSD:\ :pd#541440:od#531200:bd#1024:fd#1024:td=2.11BSD:\ :pe#363520:oe#20480:be#1024:fe#1024:te=2.11BSD:\ :pf#320000:of#384000:bf#1024:ff#1024:tf=2.11BSD:\ :pg#368640:og#704000:bg#1024:fg#1024:tg=2.11BSD:\ :ph#1072640:oh#0:bh#1024:fh#1024:th=2.11BSD # EATON BR1537 or 1711 controller. The CSR set looks like an RP03, # that's about all. # br1538d|BR1538D|EATON 1538D, 1711:\ :ty=removable:ns#32:nt#19:nc#815:so:\ :b0=/mdec/bruboot:\ :pa#18240:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#12160:ob#18240:bb#1024:fb#1024:tb=swap:\ :pc#232256:oc#30400:bc#1024:fc#1024:tc=2.11BSD:\ :pd#232256:od#262656:bd#4096:fd#1024:td=2.11BSD:\ :ph#494912:oh#0:bh#1024:fh#1024:th=2.11BSD rp04|RP04|rp05|RP05|DEC RP04/05:\ :ty=removable:ns#22:nt#19:nc#411:sf:\ :b0=/mdec/hpuboot:\ :pa#9614:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#8778:ob#9614:bb#1024:fb#1024:tb=swap:\ :pc#152988:oc#18392:bc#1024:fc#1024:tc=2.11BSD:\ :pg#171650:og#0:bg#1024:fg#1024:tg=2.11BSD rp06|RP06|DEC RP06:\ :ty=removable:ns#22:nt#19:nc#815:sf:\ :b0=/mdec/hpuboot:\ :pa#9614:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#8778:ob#9614:bb#1024:fb#1024:tb=swap:\ :pc#153406:oc#18392:bc#1024:fc#1024:tc=2.11BSD:\ :pd#168724:od#171798:bd#1024:fd#1024:td=2.11BSD:\ :pe#322130:oe#18392:be#1024:fe#1024:te=2.11BSD:\ :pg#171798:og#0:bg#1024:fg#1024:tg=2.11BSD:\ :ph#340522:oh#0:bh#1024:fh#1024:th=2.11BSD rp07|RP07|DEC RP07:\ :ty=fixed:ns#50:nt#32:nc#630:sf:\ :b0=/mdec/hpuboot:\ :pa#19200:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#51200:ob#19200:bb#1024:fb#1024:tb=swap:\ :pc#1006400:oc#0:bc#1024:fc#1024:\ :pd#320000:od#70400:bd#1024:fd#1024:td=2.11BSD:\ :pe#320000:oe#390400:be#1024:fe#1024:te=2.11BSD:\ :pf#296000:of#710400:bf#1024:ff#1024:tf=2.11BSD:\ :pg#936000:og#70400:bg#1024:fg#1024:tg=2.11BSD:\ :ph#1006400:oh#0:bh#1024:fh#1024:th=2.11BSD rm2x|160|fuji|fuji160|Fujitsu 160:\ :ty=fixed:ns#32:nt#10:nc#823:sf:\ :b0=/mdec/si94uboot:\ :pa#9600:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#9600:ob#9600:bb#1024:fb#1024:tb=swap:\ :pc#244160:oc#19200:bc#1024:fc#1024:tc=2.11BSD:\ :pd#164800:od#19200:bd#1024:fd#1024:td=unused:\ :pe#79360:oe#184000:be#1024:fe#1024:te=unused:\ :pf#39680:of#184000:bf#1024:ff#1024:tf=unused:\ :pg#39680:og#223680:bg#1024:fg#1024:tg=unused:\ :ph#263360:oh#0:bh#1024:fh#1024:th=unused diva|DIVA|9300|Diva Comp V, Ampex 9300 (in direct mode):\ :ty=fixed:ns#33:nt#19:nc#815:sf:\ :b0=/mdec/dvhpuboot:\ :pa#9405:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#9405:ob#9405:bb#1024:fb#1024:tb=swap:\ :pc#241395:oc#18810:bc#1024:fc#1024:tc=2.11BSD:\ :pd#250641:od#260205:bd#1024:fd#1024:td=2.11BSD:\ :pe#169290:oe#18810:be#1024:fe#1024:te=2.11BSD:\ :pf#156750:of#188100:bf#1024:ff#1024:tf=2.11BSD:\ :pg#165996:og#344850:bg#1024:fg#1024:tg=2.11BSD:\ :ph#510846:oh#0:bh#1024:fh#1024:th=2.11BSD 330|capricorn|Capricorn|Ampex Capricorn:\ :ty=fixed:ns#32:nt#16:nc#1024:sf:\ :pa#16384:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#33792:ob#16384:bb#1024:fb#1024:tb=swap:\ :pc#291840:oc#50176:bc#1024:fc#1024:tc=2.11BSD:\ :pd#16384:od#342016:bd#4096:fd#1024:td=2.11BSD:\ :pe#56320:oe#358400:be#1024:fe#1024:te=2.11BSD:\ :pf#107008:of#414720:bf#1024:ff#1024:tf=2.11BSD:\ :pg#179712:og#342016:bg#1024:fg#1024:tg=2.11BSD:\ :ph#521728:bh#1024:fh#1024:th=2.11BSD si_eagle|SI_Eagle|2351|2351A|Fujitsu Eagle 2351A (48 sectors):\ :ty=fixed:ns#48:nt#20:nc#842:rm#3961:sf:\ :b0=/mdec/si51uboot:\ :pa#11520:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#11520:ob#11520:bb#1024:fb#1024:tb=swap:\ :pc#474240:oc#23040:bc#1024:fc#1024:tc=2.11BSD:\ :pd#92160:od#497280:bd#1024:fd#1024:td=2.11BSD:\ :pe#218880:oe#589440:be#1024:fd#1024:te=2.11BSD:\ :ph#803520:oh#0:bh#1024:fh#1024:th=2.11BSD si9766|si9766|CDC 9766 on SI 9500 controller:\ :ty=removable:ns#32:nt#19:nc#823:sf:\ :b0=/mdec/si95uboot:\ :pa#9120:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#9120:ob#9120:bb#1024:fb#1024:tb=swap:\ :pc#234080:oc#18240:bc#1024:fc#1024:tc=2.11BSD:\ :pd#244866:od#252320:bd#4096:fd#1024:td=2.11BSD:\ :pe#164160:oe#18240:be#1024:fe#1024:te=2.11BSD:\ :pf#152000:of#182400:bf#1024:ff#1024:tf=2.11BSD:\ :pg#162786:og#334400:bg#1024:fg#1024:tg=2.11BSD:\ :ph#497344:oh#0:bh#1024:fh#1024:th=2.11BSD rk06|RK06|DEC RK06:\ :ty=removable:ns#22:nt#3:nc#411:sf:\ :b0=/mdec/hkuboot:\ :pa#8316:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#8316:ob#8316:bb#1024:fb#1024:tb=swap:\ :pc#27126:oc#0:bc#1024:fc#1024:tc=unused:\ :pg#10428:og#16632:bg#1024:fg#1024:tg=2.11BSD:\ :ph#27060:oh#0:bh#1024:fh#1024:th=2.11BSD rk07|RK07|DEC RK07:\ :ty=removable:ns#22:nt#3:nc#815:sf:bt=hkuboot:\ :b0=/mdec/hkuboot:\ :pa#8316:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#8316:ob#8316:bb#1024:fb#1024:tb=swap:\ :pc#53790:oc#0:bc#1024:fc#1024:tc=unused:\ :pg#37092:og#16632:bg#1024:fg#1024:tg=2.11BSD:\ :ph#53724:oh#0:bh#1024:fh#1024:th=2.11BSD # The RL02 and RL01 have 256 byte sectors, getdiskbyname ignores 'se' # (thankfully) but partitions are still in units of 512-byte sectors. rl01|RL01|DEC RL01:\ :ty=removable:se#256:ns#20:nt#2:nc#256:\ :b0=/mdec/rluboot:\ :ph#10240:oh#0:bh#1024:fh#1024:th=2.11BSD rl02|RL02|DEC RL02:\ :ty=removable:se#256:ns#20:nt#2:nc#512:\ :b0=/mdec/rluboot:\ :pa#15360:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#5120:ob#15360:bb#1024:fb#1024:tb=swap:\ :ph#20480:oh#0:bh#1024:fh#1024:th=2.11BSD rk05|RK05|DEC RK05:\ :ty=removable:ns#12:nt#2:nc#203:bt=rkuboot:\ :b0=/mdec/rkuboot:\ :ph#4872:oh#0:bh#1024:fh#1024:th=2.11BSD # # Disks on a UDA50 # ra60|RA60|DEC RA60 Removable|OLD STYLE PARTITIONS:\ :dt=MSCP:ty=removable:ns#42:nt#4:nc#2382:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0ba#1024:fa#1024:ta=2.11BSD:\ :pb#33440:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#193282:oc#49324:bc#1024:fc#1024:tc=2.11BSD:\ :pd#15884:od#242606:bd#1024:fd#1024:td=2.11BSD:\ :pe#140686:oe#258490:be#1024:fe#1024:te=2.11BSD:\ :pg#156570:og#242606:bg#1024:fg#1024:tg=2.11BSD:\ :ph#399176:oh#0:bh#1024:fh#1024:th=2.11BSD ra80|RA80|DEC RA80 Winchester|OLD STYLE PARTITIONS:\ :dt=MSCP:ty=fixed:ns#31:nt#14:nc#559:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#33440:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#186888:oc#49324:bc#1024:fc#1024:tc=2.11BSD:\ :ph#236212:oh#0:bh#1024:fh#1024:th=2.11BSD ra81|RA81|DEC RA81 Winchester|OLD STYLE PARTITIONS:\ :dt=MSCP:ty=fixed:ns#51:nt#14:nc#1248:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#33440:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#193282:oc#49324:bc#1024:fc#1024:tc=2.11BSD:\ :pd#15884:od#242606:bd#1024:fd#1024:td=2.11BSD:\ :pe#307200:oe#258490:be#1024:fe#1024:te=2.11BSD:\ :pf#324382:of#565690:bf#1024:ff#1024:tf=2.11BSD:\ :pg#647466:og#242606:bg#1024:fg#1024:tg=2.11BSD:\ :ph#890072:oh#0:bh#1024:fh#1024:th=2.11BSD ra81x|RA81X|Extended DEC RA81 Winchester|OLD STYLE PARTITIONS:\ :dt=MSCP:ty=fixed:ns#51:nt#14:nc#1815:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#33440:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#193282:oc#49324:bc#1024:fc#1024:tc=2.11BSD:\ :pd#15884:od#242606:bd#1024:fd#1024:td=2.11BSD:\ :pe#307200:oe#258490:be#1024:fe#1024:te=2.11BSD:\ :pf#728952:of#565690:bf#1024:ff#1024:tf=2.11BSD:\ :pg#1052036:og#242606:bg#1024:fg#1024:\ :ph#1294642:oh#0:bh#1024:fh#1024:th=2.11BSD rd52|RD52|DEC RD52|OLD STYLE PARTITIONS:\ :dt=MSCP:ty=fixed:ns#18:nt#7:nc#480:so:\ :b0=/mdec/rauboot:\ :pa#9700:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#17300:ob#9700:bb#1024:fb#1024:tb=2.11BSD:\ :pc#3100:oc#27000:bc#1024:fc#1024:tc=swap:\ :pd#30348:od#30100:bd#1024:fd#1024:td=2.11BSD:\ :pg#50748:og#9700:bg#1024:fg#1024:tg=2.11BSD:\ :ph#60448:oh#0:bh#1024:fh#1024:th=2.11BSD rd53|RD53||DEC RD53|OLD STYLE PARTITIONS:\ :dt=MSCP:ty=fixed:ns#18:nt#8:nc#963:so:\ :b0=/mdec/rauboot:\ :pa#9700:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#17300:ob#9700:bb#1024:fb#1024:tb=2.11BSD:\ :pc#3100:oc#27000:bc#1024:fc#1024:tc=swap:\ :pd#108540:od#30100:bd#1024:fd#1024:td=2.11BSD:\ :pg#128940:og#9700:bg#1024:fg#1024:tg=2.11BSD:\ :ph#138640:oh#0:bh#1024:fh#1024:th=2.11BSD rc25|RC25|rcf25|RCF25|DEC RC25 and RC25F:\ :dt=MSCP:ty=removable:ns#42:nt#4:nc#2382:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#8360:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#50902:oc#0:bc#1024:fc#1024:tc=2.11BSD:\ :pg#26658:og#24244:bg#1024:fg#1024:tg=2.11BSD rd31|RD31|DEC RD31:\ :dt=MSCP:ty=fixed:ns#17:nt#4:nc#615:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#8360:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#41560:oc#0:bc#1024:fc#1024:tc=2.11BSD:\ :pg#17316:og#24244:bg#1024:fg#1024:tg=2.11BSD rd32|RD32|DEC RD32:\ :dt=MSCP:ty=fixed:ns#17:nt#6:nc#820:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#8360:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#83236:oc#0:bc#1024:fc#1024:tc=2.11BSD:\ :pg#58992:og#24244:bg#1024:fg#1024:tg=2.11BSD rd33|RD33|DEC RD33:\ :dt=MSCP:ty=fixed:ns#17:nt#7:nc#1170:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#8360:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#138565:oc#0:bc#1024:fc#1024:tc=2.11BSD:\ :pg#114321:og#24244:bg#1024:fg#1024:tg=2.11BSD rd51|RD51|DEC RD51:\ :dt=MSCP:ty=fixed:ns#18:nt#4:nc#300:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#5716:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#21600:oc#0:bc#1024:fc#1024:tc=2.11BSD rd52new|RD52new|DEC RD52|NEW STYLE PARTITIONS:\ :dt=MSCP:ty=fixed:ns#18:nt#7:nc#480:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#8360:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#60480:oc#0:bc#1024:fc#1024:tc=2.11BSD:\ :pg#36236:og#24244:bg#1024:fg#1024:tg=2.11BSD rd53new|RD53new|DEC RD53|NEW STYLE PARTITIONS:\ :dt=MSCP:ty=fixed:ns#17:nt#8:nc#1024:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#8360:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#138672:oc#0:bc#1024:fc#1024:tc=2.11BSD:\ :pg#114428:og#24244:bg#1024:fg#1024:tg=2.11BSD\ rd54|RD54|DEC RD54:\ :dt=MSCP:ty=fixed:ns#17:nt#15:nc#1221:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#16720:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#311200:oc#0:bc#1024:fc#1024:tc=unused:\ :pg#278596:og#32604:bg#1024:fg#1024:tg=2.11BSD rx23|RX23|DEC RX23:\ :dt=MSCP:ty=floppy:ns#18:nt#2:nc#80:\ :b0=/mdec/rauboot:\ :pa#2880:oa#0:ba#1024:fa#1024:ta=2.11BSD rx26|RX26|DEC RX26:\ :dt=MSCP:ty=floppy:ns#36:nt#2:nc#80:\ :b0=/mdec/rauboot:\ :pa#5760:oa#0:ba#1024:fa#1024:ta=2.11BSD rx33|RX33|DEC RX33:\ :dt=MSCP:ty=floppy:ns#15:nt#2:nc#80:\ :b0=/mdec/rauboot:\ :pa#2400:oa#0:ba#1024:fa#1024:ta=2.11BSD rx50|RX50|DEC RX50:\ :dt=MSCP:ty=removable:ns#10:nt#1:nc#80:\ :b0=/mdec/rauboot:\ :pa#800:oa#0:ba#1024:fa#1024:2.11BSD ra60new|RA60new|DEC RA60|NEW STYLE PARTITIONS:\ :dt=MSCP:ty=removable:ns#42:nt#4:nc#2382:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#16720:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#400176:oc#0:bc#1024:fc#1024:\ :pd#227136:od#32604:bd#1024:fd#1024:td=2.11BSD:\ :pe#140436:oe#259740:be#1024:fe#1024:te=2.11BSD:\ :pg#367572:og#32604:bg#1024:fg#1024:tg=2.11BSD ra70|RA70|DEC RA70:\ :dt=MSCP:ty=fixed:ns#33:nt#11:nc#1507:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#16720:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#547041:oc#0:bc#1024:fc#1024:\ :pd#227136:od#32604:bd#1024:fd#1024:td=2.11BSD:\ :pe#287301:oe#259740:be#1024:fe#1024:te=2.11BSD:\ :pg#514437:og#32604:bg#1024:fg#1024:tg=2.11BSD ra71|RA71|DEC RA71:\ :dt=MSCP:ty=fixed:ns#51:nt#14:nc#1915:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#16720:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#1367310:oc#0:bc#1024:fc#1024:\ :pd#227136:od#32604:bd#1024:fd#1024:td=2.11BSD:\ :pe#409600:oe#259740:be#1024:fe#1024:te=2.11BSD:\ :pf#182464:of#669340:bf#1024:ff#1024:tf=2.11BSD:\ :pg#819200:og#32604:bg#1024:fg#1024:tg=2.11BSD:\ :ph#515506:oh#851804:bh#1024:fh#1024:th=2.11BSD ra72|RA72|DEC RA72:\ :dt=MSCP:ty=fixed:ns#51:nt#20:nc#1915:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#16720:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#1953300:oc#0:bc#1024:fc#1024:\ :pd#227136:od#32604:bd#1024:fd#1024:td=2.11BSD:\ :pe#409600:oe#259740:be#1024:fe#1024:te=2.11BSD:\ :pf#182464:of#669340:bf#1024:ff#1024:tf=2.11BSD:\ :pg#819200:og#32604:bg#1024:fg#1024:tg=2.11BSD:\ :ph#1101496:oh#851804:bh#1024:fh#1024:th=2.11BSD ra73|RA73|DEC RA73:\ :dt=MSCP:ty=fixed:ns#70:nt#21:nc#2667:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#16720:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#3920490:oc#0:bc#1024:fc#1024:\ :pd#227136:od#32604:bd#1024:fd#1024:td=2.11BSD:\ :pe#409600:oe#259740:be#1024:fe#1024:te=2.11BSD:\ :pf#182464:of#669340:bf#1024:ff#1024:tf=2.11BSD:\ :pg#819200:og#32604:bg#1024:fg#1024:tg=2.11BSD:\ :ph#3068686:oh#851804:bh#1024:fh#1024:th=2.11BSD ra80new|RA80new|DEC RA80|NEW STYLE PARTITIONS:\ :dt=MSCP:ty=fixed:ns#31:nt#14:nc#546:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#16720:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#237212:oc#0:bc#1024:fc#1024:\ :pg#204608:og#32604:bg#1024:fg#1024:tg=2.11BSD ra81new|RA81new|DEC RA81|NEW STYLE PARTITIONS:\ :dt=MSCP:ty=fixed:ns#51:nt#14:nc#1248:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#16720:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#891072:oc#0:bc#1024:fc#1024:\ :pd#227136:od#32604:bd#1024:fd#1024:td=2.11BSD:\ :pe#409600:oe#259740:be#1024:fe#1024:te=2.11BSD:\ :pf#182464:of#669340:bf#1024:ff#1024:tf=2.11BSD:\ :pg#819200:og#32604:bg#1024:fg#1024:tg=2.11BSD:\ :ph#39268:oh#851804:bh#1024:fh#1024:th=2.11BSD ra82|RA82|DEC RA82:\ :dt=MSCP:ty=fixed:ns#57:nt#15:nc#1423:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#16720:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#1216665:oc#0:bc#1024:fc#1024:\ :pd#227136:od#32604:bd#1024:fd#1024:td=2.11BSD:\ :pe#409600:oe#259740:be#1024:fe#1024:te=2.11BSD:\ :pf#182464:of#669340:bf#1024:ff#1024:tf=2.11BSD:\ :pg#819200:og#32604:bg#1024:fg#1024:tg=2.11BSD:\ :ph#364861:oh#851804:bh#1024:fh#1024:th=2.11BSD ra90|RA90|DEC RA90:\ :dt=MSCP:ty=fixed:ns#69:nt#13:nc#2649:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#16720:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#2376153:oc#0:bc#1024:fc#1024:\ :pd#227136:od#32604:bd#1024:fd#1024:td=2.11BSD:\ :pe#409600:oe#259740:be#1024:fe#1024:te=2.11BSD:\ :pf#182464:of#669340:bf#1024:ff#1024:tf=2.11BSD:\ :pg#819200:og#32604:bg#1024:fg#1024:tg=2.11BSD:\ :ph#1524349:oh#851804:bh#1024:fh#1024:th=2.11BSD ra92|RA92|DEC RA92:\ :dt=MSCP:ty=fixed:ns#69:nt#13:nc#3279:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#16720:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#2940951:oc#0:bc#1024:fc#1024:\ :pd#227136:od#32604:bd#1024:fd#1024:td=2.11BSD:\ :pe#409600:oe#259740:be#1024:fe#1024:te=2.11BSD:\ :pf#182464:of#669340:bf#1024:ff#1024:tf=2.11BSD:\ :pg#819200:og#32604:bg#1024:fg#1024:tg=2.11BSD:\ :ph#2089147:oh#851804:bh#1024:fh#1024:th=2.11BSD rz22|RZ22|DEC RZ22:\ :dt=MSCP:ty=fixed:ns#33:nt#4:nc#776:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#8360:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#102432:oc#0:bc#1024:fc#1024:\ :pg#78188:og#24244:bg#1024:fg#1024:tg=2.11BSD rz23|RZ23|DEC RZ23:\ :dt=MSCP:ty=fixed:ns#33:nt#8:nc#776:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#8360:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#204864:oc#0:bc#1024:fc#1024:\ :pg#180620:og#24244:bg#1024:fg#1024:tg=2.11BSD rz23l|RZ23L|DEC RZ23L:\ :dt=MSCP:ty=fixed:ns#39:nt#4:nc#1524:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#8360:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#237588:oc#0:bc#1024:fc#1024:\ :pg#213344:og#24244:bg#1024:fg#1024:tg=2.11BSD rz24|RZ24|DEC RZ24:\ :dt=MSCP:ty=fixed:ns#38:nt#8:nc#1348:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#16720:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#409792:oc#0:bc#1024:fc#1024:\ :pd#227136:od#32604:bd#1024:fd#1024:td=2.11BSD:\ :pe#150052:oe#259740:be#1024:fe#1024:te=2.11BSD:\ :pg#377188:og#32604:bg#1024:fg#1024:tg=2.11BSD rz24l|RZ24L|DEC RZ24L:\ :dt=MSCP:ty=fixed:ns#65:nt#4:nc#1818:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#16720:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#479350:oc#0:bc#1024:fc#1024:\ :pd#227136:od#32604:bd#1024:fd#1024:td=2.11BSD:\ :pe#219610:oe#259740:be#1024:fe#1024:te=2.11BSD:\ :pg#446746:og#32604:bg#1024:fg#1024:tg=2.11BSD rz25|RZ25|DEC RZ25:\ :dt=MSCP:ty=fixed:ns#62:nt#9:nc#1476:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#16720:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#832527:oc#0:bc#1024:fc#1024:\ :pd#227136:od#32604:bd#1024:fd#1024:td=2.11BSD:\ :pe#409600:oe#259740:be#1024:fe#1024:te=2.11BSD:\ :pf#130590:of#669340:bf#1024:ff#1024:tf=2.11BSD:\ :pg#799923:og#32604:bg#1024:fg#1024:tg=2.11BSD: rz26|RZ26|DEC RZ26:\ :dt=MSCP:ty=fixed:ns#57:nt#14:nc#2570:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#16720:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#2050860:oc#0:bc#1024:fc#1024:\ :pd#227136:od#32604:bd#1024:fd#1024:td=2.11BSD:\ :pe#409600:oe#259740:be#1024:fe#1024:te=2.11BSD:\ :pf#182464:of#669340:bf#1024:ff#1024:tf=2.11BSD:\ :pg#819200:og#32604:bg#1024:fg#1024:tg=2.11BSD:\ :ph#1199056:oh#851804:bh#1024:fh#1024:th=2.11BSD rz55|RZ55|DEC RZ55:\ :dt=MSCP:ty=fixed:ns#36:nt#15:nc#1224:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#16720:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#649040:oc#0:bc#1024:fc#1024:\ :pd#227136:od#32604:bd#1024:fd#1024:td=2.11BSD:\ :pe#389300:oe#259740:be#1024:fe#1024:te=2.11BSD:\ :pg#616436:og#32604:bg#1024:fg#1024:tg=2.11BSD rz56|RZ56|DEC RZ56:\ :dt=MSCP:ty=fixed:ns#54:nt#15:nc#1632:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#16720:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#1299174:oc#0:bc#1024:fc#1024:\ :pd#227136:od#32604:bd#1024:fd#1024:td=2.11BSD:\ :pe#409600:oe#259740:be#1024:fe#1024:te=2.11BSD:\ :pf#182464:of#669340:bf#1024:ff#1024:tf=2.11BSD:\ :pg#819200:og#32604:bg#1024:fg#1024:tg=2.11BSD:\ :ph#447370:oh#851804:bh#1024:fh#1024:th=2.11BSD rz57|RZ57|DEC RZ57:\ :dt=MSCP:ty=fixed:ns#71:nt#15:nc#1854:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#16720:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#1954050:oc#0:bc#1024:fc#1024:\ :pd#227136:od#32604:bd#1024:fd#1024:td=2.11BSD:\ :pe#409600:oe#259740:be#1024:fe#1024:te=2.11BSD:\ :pf#182464:of#669340:bf#1024:ff#1024:tf=2.11BSD:\ :pg#819200:og#32604:bg#1024:fg#1024:tg=2.11BSD:\ :ph#1102246:oh#851804:bh#1024:fh#1024:th=2.11BSD rz58|RZ58|DEC RZ58:\ :dt=MSCP:ty=fixed:ns#85:nt#15:nc#2112:so:\ :b0=/mdec/rauboot:\ :pa#15884:oa#0:ba#1024:fa#1024:ta=2.11BSD:\ :pb#16270:ob#15884:bb#1024:fb#1024:tb=swap:\ :pc#2698061:oc#0:bc#1024:fc#1024:\ :pd#227136:od#32604:bd#1024:fd#1024:td=2.11BSD:\ :pe#409600:oe#259740:be#1024:fe#1024:te=2.11BSD:\ :pf#182464:of#669340:bf#1024:ff#1024:tf=2.11BSD:\ :pg#819200:og#32604:bg#1024:fg#1024:tg=2.11BSD:\ :ph#1846257:oh#851804:bh#1024:fh#1024:th=2.11BSD # The RX driver uses partition 'a' to select single density and 'b' to # select double density. Partition sizes are in units of 512-byte sectors # even though the rx01 uses 128 byte hardware sectors and the rx02 256 byte # sectors. This really doesn't work too well for the RX01 due to the odd # number of sectors - are there any of them still running? rx01|RX01|DEC RX01:\ :ty=floppy:se#128:ns#13:nt#1:nc#77:\ :pa#500:ba#1024:fa#1024:\ rx02|RX02|DEC RX02:\ :ty=floppy:se#256:ns#13:nt#1:nc#77:\ :pb#1001:bb#1024:fb#1024: # # RAM disk # ram|RAM|Ram disk:\ :ty=simulated:ns#2:nt#1024:nc#4096: ty=floppy:ns#18:nt#2:nc#80:\ :b0=/mdec/rauboot:\ :pa#2880:oa#0:ba#1024:fa#1024:ta=2.11BSD rx26|RX26|DEC RX26:\ :dt=MSCP:ty=floppy:ns#36:nt#2:nc#80:\ :b0=/mdec/rauboot:\ :pa#5760:oa#0:ba#1024:fa#1024:ta=2.11BSD rx33|RX33|DEC RX33:\ :dt=MSCP:ty=floppy:ns#1sys/pdpdist/dtab 644 0 12 3721 5125225723 7160 # Device Configuration Table #Name Unit# Addr Vector Br Handler(s) # Comments # dr ? 172410 124 5 drintr # dr11-w (b-bus emulator) # dr ? 172430 130 5 drintr # dr11-w (gc-bus emulator) # dr ? 172450 134 5 drintr # dr11-w (em-2 interface) # du ? 160020 310 5 dhurint dhuxint # dhu11 terminal mux # dhv ? 160020 310 5 dhvrint dhvxint # dhv terminal mux # dm ? 170500 310 4 dmintr # dm11 dh modem control # dh ? 160020 320 5 dhrint dhxint # dh11 terminal mux # dz ? 160100 310 5 dzrint dzdma # dz11 terminal mux hk ? 177440 210 5 hkintr # rk611/711 rk06/07 # hp ? 176700 254 5 hpintr # rjp04/06, rwp04/06 ht ? 172440 224 5 htintr # tu 16 massbus tape # vp ? 177500 174 4 vpintr # Versatec; should be before lp # lp ? 177514 200 4 lpintr # lp-11 line printer ra ? 172150 154 5 raintr # uda50, rqdx1/2/3 # rk ? 177400 220 5 rkintr # rk05 rl ? 174400 160 5 rlintr # rl-01/02 # rm ? 176700 254 5 rmintr # rjm02/rwm03, rm02/03/05 # br ? 176710 254 5 brintr # Eaton br1537/br1711 # rx ? 177170 264 5 rxintr # rx01/02 # si ? 176700 170 5 siintr # si9500 tm ? 172520 224 5 tmintr # tm11 driver tms ? 174500 260 5 tmsintr # tmscp driver ts ? 172520 224 5 tsintr # ts11 driver xp ? 176700 254 5 xpintr # xp driver # If you have DL11s, you must give each line an explicit unit number instead # of using a '?' as above. If you use a '?', autoconfig(8) will start # assigning unit numbers starting at 0 which will effectively move your # console to that first line. Start your unit numbers with '1'. # # cn 1 176500 300 5 cnrint cnxint # kl/dl-11 (on mvx11-aa) # The following entries are provided for information only, actual # configuration is done elsewhere. # acc ? 167600 5 accin accout # lhdh driver # de ? 120 5 deintr # deuna # qe ? 174440 400 5 qeintr # deqna ethernet # il ? 163000 340 5 ilrint ilcint # interlan ethernet # kw ? 172540 100 6 hardclock # kw11-p clock # sr ? 500 5 srirint srixint # sri dr11-c arpanet imp # vv ? 161000 350 5 vvrint vvxint # pronet z ? 160100 310 5 dzrint dzdma # dz11 terminal msys/pdpdist/netstart 644 0 12 2564 5316470060 10114 #!/bin/sh - # @(#)netstart 5.2 (Berkeley) 7/16/88 INET=`/etc/testnet` if [ $INET = YES ]; then echo Assuming NETWORKING system ... >/dev/console 2>&1 else echo Assuming non-networking system ... >/dev/console 2>&1 fi export INET # DON'T EVEN THINK ABOUT RUNNING ROUTED ON A PDP-11!!! Just set routedflags # to "NO" and set up a default gateway below. # routedflags=NO rwhod=NO named=NO # myname is my symbolic name # my-netmask is specified in /etc/networks # my-default-address should be set to some machine where you # want to send all your packets, by default. # hostname=myname.my.domain netmask=my-net-mask broadcast=my-broadcast-address default=my-default-address hostname $hostname >/dev/console 2>&1 hostid $hostname >/dev/console 2>&1 if [ $INET = YES ]; then # /etc/ifconfig imp0 inet netmask $netmask $hostname broadcast $broadcast up -trailers >/dev/console 2>&1 # /etc/ifconfig en0 inet netmask $netmask $hostname broadcast $broadcast up -trailers >/dev/console 2>&1 # /etc/ifconfig il0 inet netmask $netmask $hostname broadcast $broadcast up -trailers >/dev/console 2>&1 # /etc/ifconfig qe0 inet netmask $netmask $hostname broadcast $broadcast up -trailers >/dev/console 2>&1 /etc/ifconfig lo0 inet localhost up -trailers >/dev/console 2>&1 /etc/route add $hostname localhost 0 >/dev/console 2>&1 /etc/route add default $default 1 >/dev/console 2>&1 fi starting at 0 which will effectively move your # console to that first line. Start your unit numbers with '1'. # # cn 1 176500 300 5 cnrinsys/SMS/ 775 0 0 0 6045336251 5206 sys/SMS/NETSPLFIX 664 0 0 1443 5520357160 6573 g/jsr pc,__spl0/s//clrb 177776/ g/jsr pc,__spl\([1-7]\)/s//movb $40*\1, 177776/ g/jsr pc,__splsoftclock/s//movb $40, 177776/ g/jsr pc,__splnet/s//movb $100, 177776/ g/jsr pc,__splimp/s//movb $240, 177776/ g/jsr pc,__splbio/s//movb $240, 177776/ g/jsr pc,__spltty/s//movb $240, 177776/ g/jsr pc,__splclock/s//movb $300, 177776/ g/jsr pc,__splhigh/s//movb $340, 177776/ g/jsr pc,_spl0/s//mfps r0;clrb 177776/ g/jsr pc,_spl\([1-7]\)/s//mfps r0;movb $40*\1, 177776/ g/jsr pc,_splsoftclock/s//mfps r0;movb $40, 177776/ g/jsr pc,_splnet/s//mfps r0;movb $100, 177776/ g/jsr pc,_splbio/s//mfps r0;movb $240, 177776/ g/jsr pc,_splimp/s//mfps r0;movb $240, 177776/ g/jsr pc,_spltty/s//mfps r0;movb $240, 177776/ g/jsr pc,_splclock/s//mfps r0;movb $300, 177776/ g/jsr pc,_splhigh/s//mfps r0;movb $340, 177776/ w q g imp0 inet netmask $netmask $hostname broadcast $broadcast up -trailers >/dev/console 2>&1 # /etc/ifconfig en0 inet netmask $netmask $hostname broadcast $broadcast up -trailers >/dev/console 2>&1 # /etc/ifconfig il0 insys/SMS/SPLFIX 664 0 0 1100 5520357250 6212 g/jsr pc,__spl\([0-7]\)/s//spl \1/ g/jsr pc,__splsoftclock/s//spl 1/ g/jsr pc,__splnet/s//spl 2/ g/jsr pc,__splbio/s//spl 5/ g/jsr pc,__splimp/s//spl 5/ g/jsr pc,__spltty/s//spl 5/ g/jsr pc,__splclock/s//spl 6/ g/jsr pc,__splhigh/s//spl 7/ g/jsr pc,_spl\([0-7]\)/s//mfps r0;spl \1/ g/jsr pc,_splsoftclock/s//mfps r0;spl 1/ g/jsr pc,_splnet/s//mfps r0;spl 2/ g/jsr pc,_splbio/s//mfps r0;spl 5/ g/jsr pc,_splimp/s//mfps r0;spl 5/ g/jsr pc,_spltty/s//mfps r0;spl 5/ g/jsr pc,_splclock/s//mfps r0;spl 6/ g/jsr pc,_splhigh/s//mfps r0;spl 7/ g/movb \(.*[^,]\),\*$-2/s//mtps \1/ w q o/s//mfps r0;mov$240, 177776/ g/jsr pc,_splimp/s//mfps r0;movb $240, 177776/ g/jsr pc,_spltty/s//mfps r0;movb $240, 177776/ g/jsr pc,_splclock/s//mfps r0;movb $300, 177776/ g/jsr pc,_splhigh/s//mfps r0;movb $340, 177776/ w q g imp0 inet netmask $netmask $hostname broadcast $broadcast up -trailers >/dev/console 2>&1 # /etc/ifconfig en0 inet netmask $netmask $hostname broadcast $broadcast up -trailers >/dev/console 2>&1 # /etc/ifconfig il0 insys/SMS/boot.s 664 0 0 10651 5320215175 6441 /* * SCCS id @(#)raboot.s 2.0 (2.11BSD) 4/13/91 */ #include "localopts.h" / The boot options and device are placed in the last SZFLAGS bytes / at the end of core for the bootstrap. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 / boot unit CHECKWORD= 6 .globl _doboot, hardboot, _bootcsr .text _doboot: mov 4(sp),r4 / boot options mov 2(sp),r3 / boot device #ifndef KERN_NONSEP / If running separate I/D, need to turn off memory management. / Call the routine unmap in low text, after setting up a jump / in low data where the PC will be pointing. .globl unmap mov $137,*$unmap+2 / jmp *$hardboot mov $hardboot,*$unmap+4 jmp unmap / "return" from unmap will be to hardboot in data .data #else / Reset to turn off memory management reset #endif / On power fail, hardboot is the entry point (map is already off) / and the args are in r4 (RB_POWRFAIL), r3 (rootdev) hardboot: mov r4, ENDCORE-BOOTOPTS ash $-3,r3 / shift out the partition number bic $!7,r3 / save only the drive number mov r3, ENDCORE-BOOTDEV com r4 / if CHECKWORD == ~bootopts, flags are believed mov r4, ENDCORE-CHECKWORD 1: reset / The remainder of the code is dependent on the boot device. / If you have a bootstrap ROM, just jump to the correct entry. / Otherwise, use a BOOT opcode, if available; / if necessary, read in block 0 to location 0 "by hand". / / RA bootstrap. / / Note: this is a complex boot, but then MSCP is complex!!!! / / Bootstrap for mscp disk controller tucker@gswd-vms / MSCPSIZE = 64. / One MSCP command packet is 64bytes long (need 2) RASEMAP = 140000 / RA controller owner semaphore RAERR = 100000 / error bit RASTEP1 = 04000 / step1 has started RAGO = 01 / start operation, after init RASTCON = 4 / Setup controller info RAONLIN = 11 / Put unit on line RAREAD = 41 / Read command code RAWRITE = 42 / Write command code RAEND = 200 / End command code RACMDI = 4. / Command Interrupt RARSPI = 6. / Response Interrupt RARING = 8. / Ring base RARSPL = 8. / Response Command low RARSPH = 10. / Response Command high RACMDL = 12. / Command to controller low RACMDH = 14. / Command to controller high RARSPS = 16. / Response packet length (location) RARSPREF = 20. / Response reference number RACMDS = 80. / Command packet length (location) RACMDREF = 84. / Command reference number RAUNIT = 88. / Command packet unit RAOPCODE = 92. / Command opcode offset RABYTECT = 96. / Transfer byte count RABUFL = 100. / Buffer location (16 bit addressing only) RABUFH = 102. / Buffer location high 6 bits RALBNL = 112. / Logical block number low RALBNH = 114. / Logical block number high BSIZE = 512. / Size of boot block / / Clear RA MSCP command area! / mov $ra,r0 mov $BSIZE,r1 mov r0,sp add r1,sp 1: clr (r0)+ sob r1,1b / / RA initialize controller / mov $RASTEP1,r0 mov _bootcsr,r1 / get csr of boot controller clr (r1)+ / go through controller init seq. mov $icons,r2 1: bit r0,(r1) beq 1b mov (r2)+,(r1) asl r0 bpl 1b mov $ra+RARSPREF,*$ra+RARSPL / set controller characteristics mov $ra+RACMDREF,*$ra+RACMDL mov $RASTCON,r0 jsr pc,racmd mov ENDCORE-BOOTDEV,*$ra+RAUNIT / bring boot unit online mov $RAONLIN,r0 jsr pc,racmd / / Read in block zero and jump to it / / / RA MSCP read block routine. This is very primative, so don't expect / too much from it. Note that MSCP requires large data communications / space at end of ADDROFF for command area. / / Load block zero into memory location zero. / BSIZE -> size of block to read / / Tim Tucker, Gould Electronics, August 23rd 1985 / clr *$ra+RALBNL / Put in logical block number mov $BSIZE,*$ra+RABYTECT / Put in byte to transfer clr *$ra+RABUFL / Put in disk buffer location mov $RAREAD,r0 jsr pc,racmd mov ENDCORE-BOOTDEV,r0 / put unit and mov _bootcsr,r1 / csr where bootblock expects them clr pc / and away we go / / perform MSCP command -> response poll version / racmd: movb r0,*$ra+RAOPCODE / fill in command type mov $MSCPSIZE,*$ra+RARSPS / give controller struct sizes mov $MSCPSIZE,*$ra+RACMDS mov $RASEMAP,*$ra+RARSPH / set mscp semaphores mov $RASEMAP,*$ra+RACMDH mov *_bootcsr,r0 / tap controllers shoulder mov $ra+RACMDI,r0 1: tst (r0) beq 1b / Wait till command read clr (r0)+ / Tell controller we saw it, ok. 2: tst (r0) beq 2b / Wait till response written clr (r0) / Tell controller we got it rts pc icons: RAERR ra+RARING 0 RAGO ra: 0 / and the args are in r4 (RB_POWRFAIL), r3 (rootdev) hardboot: mov r4, ENDCORE-BOOTOsys/SMS/ioconf.c 664 0 0 714 5672263641 6705 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ioconf.c 2.0 (2.11BSD GTE) 12/24/92 */ #include "param.h" #include "systm.h" dev_t rootdev = makedev(5,0), swapdev = makedev(5,1), pipedev = makedev(5,0); dev_t dumpdev = makedev(5,1); daddr_t dumplo = (daddr_t)1024; int radump(); int (*dump)() = radump; ts.h tms.h vv.h acc.hhk.hsys/SMS/param.c 664 0 0 6603 5350005610 6532 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)param.c 2.0 (2.11BSD GTE) 3/11/93 */ #include "../h/param.h" #include "../h/systm.h" #include "../h/buf.h" #include "../h/time.h" #include "../h/resource.h" #include "../h/proc.h" #include "../h/text.h" #include "../h/file.h" #include "../h/dir.h" #include "../h/inode.h" #include "../h/fs.h" #include "../h/mount.h" #include "../h/callout.h" #include "../h/map.h" #include "../h/clist.h" #include "../machine/seg.h" /* * System parameter formulae. * * This file is copied into each directory where we compile * the kernel; it should be modified there to suit local taste * if necessary. * */ #define MAXUSERS 20 #define NBUF 128 int hz = LINEHZ; struct timezone tz = { 480, 1 }; #define NPROC (10 + 7 * MAXUSERS) int nproc = NPROC; #define NTEXT (26 + MAXUSERS) int ntext = NTEXT; #define NINODE ((NPROC + 16 + MAXUSERS) + 22) int ninode = NINODE; #define NFILE ((8 * NINODE / 10) + 20) int nfile = NFILE; #define NCALL (16 + MAXUSERS) int ncallout = NCALL; int nbuf = NBUF; #define NCLIST (20 + 8 * MAXUSERS) #if NCLIST > (8192 / 32) /* 8K / sizeof(struct cblock) */ #undef NCLIST #define NCLIST (8192 / 32) #endif int nclist = NCLIST; /* * These have to be allocated somewhere; allocating * them here forces loader errors if this file is omitted * (if they've been externed everywhere else; hah!). */ struct proc *procNPROC; struct text *textNTEXT; struct inode inode[NINODE], *inodeNINODE; struct file *fileNFILE; struct callout callout[NCALL]; struct mount mount[NMOUNT]; struct buf buf[NBUF], bfreelist[BQUEUES]; struct bufhd bufhash[BUFHSZ]; #ifdef UCB_CLIST u_int clstdesc = ((((btoc(NCLIST*sizeof(struct cblock)))-1) << 8) | RW); int ucb_clist = 1; #else struct cblock cfree[NCLIST]; int ucb_clist = 0; #endif #define CMAPSIZ NPROC /* size of core allocation map */ #define SMAPSIZ ((9 * NPROC) / 10) /* size of swap allocation map */ struct mapent _coremap[CMAPSIZ]; struct map coremap[1] = { _coremap, &_coremap[CMAPSIZ], "coremap", }; struct mapent _swapmap[SMAPSIZ]; struct map swapmap[1] = { _swapmap, &_swapmap[SMAPSIZ], "swapmap", }; #ifdef QUOTA #include "../h/quota.h" struct BigQ { struct quota xquota[NQUOTA]; /* the quotas themselves */ struct dquot *ixdquot[NINODE]; /* 2.11 equiv of i_dquot */ struct dquot xdquot[NDQUOT]; /* the dquots themselves */ struct qhash xqhash[NQHASH]; struct dqhead xdqhash[NDQHASH]; }; QUOini() { extern struct qhash *qhash; extern struct dqhead *dqhead; quota = ((struct BigQ *)SEG5)->xquota; dquot = ((struct BigQ *)SEG5)->xdquot; qhash = ((struct BigQ *)SEG5)->xqhash; dqhead = ((struct BigQ *)SEG5)->xdqhash; ndquot = NDQUOT; nquota = NQUOTA; ix_dquot = ((struct BigQ *)SEG5)->ixdquot; dquotNDQUOT = &dquot[ndquot]; quotaNQUOTA = "a[nquota]; } #endif /* * Declarations of structures loaded last and allowed to reside in the * 0120000-140000 range (where buffers and clists are mapped). These * structures must be extern everywhere else, and the asm output of cc * is edited to move these structures from comm to bss (which is last) * (see the script :comm-to-bss). They are in capital letters so that * the edit script doesn't find some other occurrence. */ struct proc PROC[NPROC]; struct file FILE[NFILE]; struct text TEXT[NTEXT]; data communications / space at end of ADDROFF for command area. / / Load block zero into memory location zero. / BSIZE -> sisys/SMS/loop.h 664 0 0 20 5320215202 6330 #define NLOOP 1 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/css.h 664 0 0 17 5320215204 6157 #define NCSS 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/de.h 664 0 0 16 5320215205 5757 #define NDE 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/dh.h 664 0 0 34 5320215205 5762 #define NDH 0 #define NDM 0  NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/dn.h 664 0 0 16 5320215206 5771 #define NDN 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/dhu.h 664 0 0 17 5320215206 6151 #define NDHU 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/dhv.h 664 0 0 17 5320215206 6152 #define NDHV 1 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/dmc.h 664 0 0 17 5320215207 6135 #define NDMC 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/dr.h 664 0 0 16 5320215207 5776 #define NDR 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/dz.h 664 0 0 16 5320215207 6006 #define NDZ 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/ec.h 664 0 0 16 5320215207 5760 #define NEC 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/en.h 664 0 0 16 5320215210 5765 #define NEN 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/ether.h 664 0 0 21 5320215210 6466 #define NETHER 1  .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/ht.h 664 0 0 16 5320215210 5776 #define NHT 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/hy.h 664 0 0 16 5320215210 6003 #define NHY 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/il.h 664 0 0 16 5320215211 5770 #define NIL 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/imp.h 664 0 0 17 5320215211 6152 #define NIMP 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/cn.h 664 0 0 16 5320215211 5764 #define NKL 2 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/lp.h 664 0 0 44 5320215212 6001 #define NLP 0 #define LP_MAXCOL 132 NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/pty.h 664 0 0 20 5320215212 6174 #define NPTY 12 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/qe.h 664 0 0 16 5320215212 5772 #define NQE 1 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/qt.h 664 0 0 16 5320215213 6012 #define NQT 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/ram.h 664 0 0 17 5320215213 6146 #define NRAM 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/rk.h 664 0 0 16 5320215213 6002 #define NRK 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/rx.h 664 0 0 16 5320215214 6020 #define NRX 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/sl.h 664 0 0 16 5320215214 6005 #define NSL 1 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/sri.h 664 0 0 17 5320215214 6165 #define NSRI 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/tb.h 664 0 0 16 5320215214 5774 #define NTB 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/ts.h 664 0 0 16 5320215215 6016 #define NTS 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/tms.h 664 0 0 40 5320215215 6170 #define NTMSCP 2 #define NTMS 3  NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/vv.h 664 0 0 16 5320215216 6024 #define NVV 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/acc.h 664 0 0 17 5320215216 6120 #define NACC 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/hk.h 664 0 0 16 5320215217 5774 #define NHK 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h  css.h  de.h  dh.h  dn.h  dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/SMS/ra.h 664 0 0 60 5320215220 5765 #define NRAC 2 #define NRAD 4 #define RA_DUMP 1 si.h tm.h xp.hMakefileMake.netMake.pdp Make.pdpmbas Make.pdpnets Make.pdpubasMake.sysb localopts.hs(ingres.h.assym.h. init_main.os init_sysent.o kern_acct.oo kern_clock.o, kern_exec.okern_descrip.old kern_exit.o.o kern_fork.o.o kern_mman.o.o kern_proc.o.o kern_prot.o.o kern_sig.o.otty.sys/SMS/rl.h 664 0 0 16 5320215220 6001 #define NRL 0 ra.h rl.h br.h si.h tm.h xp.hMakefileMake.netMake.pdp Make.pdpmbas Make.pdpnets Make.pdpubasMake.sysb localopts.hs(ingres.h.assym.h. init_main.os init_sysent.o kern_acct.oo kern_clock.o, kern_exec.okern_descrip.old kern_exit.o.o kern_fork.o.o kern_mman.o.o kern_proc.o.o kern_prot.o.o kern_sig.o.otty.sys/SMS/br.h 664 0 0 16 5320215221 5770 #define NBR 0 ra.h rl.h br.h si.h tm.h xp.hMakefileMake.netMake.pdp Make.pdpmbas Make.pdpnets Make.pdpubasMake.sysb localopts.hs(ingres.h.assym.h. init_main.os init_sysent.o kern_acct.oo kern_clock.o, kern_exec.okern_descrip.old kern_exit.o.o kern_fork.o.o kern_mman.o.o kern_proc.o.o kern_prot.o.o kern_sig.o.otty.sys/SMS/si.h 664 0 0 16 5320215222 6001 #define NSI 0 ra.h rl.h br.h si.h tm.h xp.hMakefileMake.netMake.pdp Make.pdpmbas Make.pdpnets Make.pdpubasMake.sysb localopts.hs(ingres.h.assym.h. init_main.os init_sysent.o kern_acct.oo kern_clock.o, kern_exec.okern_descrip.old kern_exit.o.o kern_fork.o.o kern_mman.o.o kern_proc.o.o kern_prot.o.o kern_sig.o.otty.sys/SMS/tm.h 664 0 0 37 5320215223 6012 #define NTM 0 #define AVIVTM 1 h br.h si.h tm.h xp.hMakefileMake.netMake.pdp Make.pdpmbas Make.pdpnets Make.pdpubasMake.sysb localopts.hs(ingres.h.assym.h. init_main.os init_sysent.o kern_acct.oo kern_clock.o, kern_exec.okern_descrip.old kern_exit.o.o kern_fork.o.o kern_mman.o.o kern_proc.o.o kern_prot.o.o kern_sig.o.otty.sys/SMS/xp.h 664 0 0 36 6004072545 6030 #define NXPD 0 #define NXPC 0 .h br.h si.h tm.h xp.hMakefileMake.netMake.pdp Make.pdpmbas Make.pdpnets Make.pdpubasMake.sysb localopts.hs(ingres.h.assym.h. init_main.os init_sysent.o kern_acct.oo kern_clock.o, kern_exec.okern_descrip.old kern_exit.o.o kern_fork.o.o kern_mman.o.o kern_proc.o.o kern_prot.o.o kern_sig.o.otty.sys/SMS/Makefile 664 0 0 15443 5757704725 7000 OPTS=-DSMS -DUCB_METER -DINET -DQUOTA -DUCB_CLIST # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # %W% (Berkeley) %G% # ######################################################### # Networking, separate I/D kernel # ######################################################### H= ../h I= /usr/include M= ../machine N1= ../net N2= ../netimp N3= ../netinet N4= ../netns N6= ../pdpif S= ../sys U= ../pdpuba MB= ../pdpmba DEFS= -DKERNEL ${OPTS} -I. -I${H} CFLAGS= -O ${DEFS} CPP= /lib/cpp -P ${DEFS} AS= /bin/as -V ED= /bin/ed SUB= sys pdp pdpuba pdpmba net pdpnet # GENERAL RULES: # scb.o MUST be loaded first, param.o MUST be loaded last, # boot.o must be loaded in the base well above 0 data. # enable34.o must be in the base segment for overlaid kernels. # Don't forget the "-i" flag for split I/D, use "-n" otherwise. # # CONF Non-network assembly binaries. scb.o must be first! # boot.o should be close to the end. # NCONF Network (network space) assembly binaries. net_scb.o # doesn't have to be first. CONF= scb.o libc_bcmp.o libc_bcopy.o libc_bzero.o libc_ffs.o \ libc_insque.o libc_ldiv.o libc_lmul.o libc_lrem.o libc_remque.o \ libc_udiv.o libc_uldiv.o libc_ulsh.o \ libc_strlen.o mch_backup.o mch_click.o mch_copy.o mch_csv.o \ mch_dump.o mch_dzpdma.o mch_KScall.o mch_profile.o \ mch_start.o mch_trap.o mch_vars.o mch_xxx.o conf.o ioconf.o boot.o NCONF= libc_bcmp.o libc_bcopy.o libc_bzero.o libc_ffs.o libc_htonl.o \ libc_htons.o libc_insque.o libc_ldiv.o libc_lmul.o libc_lrem.o \ libc_uldiv.o libc_ulsh.o \ libc_remque.o libc_strlen.o libc_udiv.o net_copy.o net_csv.o \ net_mbuf.o net_scb.o net_SKcall.o net_trap.o net_xxx.o BASE= br.o cons.o dh.o dhu.o dhv.o dr.o dz.o hk.o ht.o init_sysent.o \ kern_clock.o kern_descrip.o kern_mman.o kern_proc.o kern_prot.o \ kern_subr.o kern_synch.o lp.o machdep.o ra.o ram.o \ rk.o rl.o rx.o si.o subr_rmap.o sys_inode.o sys_kern.o \ tm.o ts.o tty.o tty_conf.o tty_subr.o tty_tb.o ufs_alloc.o \ ufs_bio.o ufs_fio.o ufs_inode.o ufs_namei.o \ vm_proc.o vm_sched.o vm_swap.o xp.o quota_subr.o OV1= sys_generic.o ufs_syscalls.o OV2= kern_acct.o kern_exec.o kern_exit.o kern_fork.o kern_resource.o OV3= kern_time.o sys_process.o ufs_mount.o ufs_subr.o uipc_syscalls.o OV4= dkbad.o kern_sig.o mem.o subr_xxx.o trap.o tty_pty.o tty_tty.o OV5= quota_kern.o quota_ufs.o quota_sys.o ufs_bmap.o \ sys_pipe.o # OV6 gets the (hopefully) never used routines OV6= clock.o dn.o init_main.o kern_pdp.o machdep2.o subr_prf.o syscalls.o \ subr_log.o toy.o vm_swp.o OV7= tmscp.o ufs_disksubr.o ufs_dsort.o OV8= mch_fpsim.o kern_sysctl.o kern_xxx.o ingreslock.o vm_text.o KERNOBJ=${CONF} ${BASE} ${OV1} ${OV2} ${OV3} ${OV4} ${OV5} \ ${OV6} ${OV7} ${OV8} ${OV9} ${OV10} ${OV11} ${OV12} \ ${OV13} ${OV14} ${OV15} \ enable34.o vers.o param.o # param.o must be last! enable34.o must be in base. LD_KOBJ=${CONF} ${BASE} \ -Z ${OV1} -Z ${OV2} -Z ${OV3} -Z ${OV4} -Z ${OV5} -Z ${OV6} \ -Z ${OV7} -Z ${OV8} -Z ${OV9} -Z ${OV10} -Z ${OV11} -Z ${OV12} \ -Z ${OV13} -Z ${OV14} -Z ${OV15} -Y \ enable34.o vers.o param.o NETOBJ= ${NCONF} af.o idp_usrreq.o if.o if_acc.o if_css.o if_de.o \ if_dmc.o if_ec.o if_en.o if_ether.o if_il.o if_imp.o if_imphost.o \ if_loop.o if_qe.o if_qt.o if_sl.o if_sri.o if_uba.o if_vv.o in.o \ in_cksum.o in_pcb.o in_proto.o ip_icmp.o ip_input.o ip_output.o \ ns.o ns_error.o ns_input.o ns_ip.o ns_output.o ns_pcb.o \ ns_proto.o raw_cb.o raw_imp.o raw_ip.o \ raw_usrreq.o route.o spp_debug.o spp_usrreq.o sys_socket.o \ sys_net.o tcp_debug.o tcp_input.o tcp_output.o tcp_subr.o \ tcp_timer.o tcp_usrreq.o udp_usrreq.o uipc_domain.o uipc_mbuf.o \ uipc_proto.o uipc_socket.o uipc_socket2.o uipc_usrreq.o all: unix netnix # d.unix.o must be last object file in the dependency list! unix: ${SUB} ${KERNOBJ} d.unix.o checksys ld -X -i -o unix ${LD_KOBJ} d.unix.o size unix @echo Compacting symbol table -symcompact unix @echo Compacting strings table - this will take a few minutes -strcompact unix @echo rearranging symbols -symorder ../pdp/symbols.sort unix ./checksys unix # d.netnix.o must be the last object file in the dependency list! netnix: d.netnix.o -ld -X -i -o netnix ${NETOBJ} d.netnix.o size netnix @echo Compacting symbol table -symcompact netnix @echo Compacting strings table - this will take a few minutes -strcompact netnix @echo rearranging symbols -symorder ../pdp/symbols.sort netnix # Resolve all references between the kernel and the net. Always regenerate!!! # This was a constant source of problems during development. Should really # include ${NETOBJ} and ${KERNOBJ} on dependency line, but the pdp make doesn't # have enough table space. d.unix.o d.netnix.o: netbind FRC ld -q -r -d -X -i -o unix.o ${LD_KOBJ} ld -q -r -d -X -i -o netnix.o ${NETOBJ} ./netbind unix.o netnix.o rm unix.o netnix.o ${AS} - -o d.unix.o d.unix.s ${AS} - -o d.netnix.o d.netnix.s vers.o: FRC sh ../conf/newvers.sh ${CC} -c vers.c boot.o: boot.s ${CPP} boot.s > boot.i ${AS} -o boot.o boot.i rm -f boot.i param.o: ${CC} -S ${CFLAGS} param.c ${ED} - param.s < ../conf/:comm-to-bss ${AS} - -o param.o param.s rm -f param.s ioconf.o: ioconf.c ${CC} -c ${CFLAGS} ioconf.c checksys: ../conf/checksys.c ${CC} ${CFLAGS} -o $@ ../conf/checksys.c netbind: ../conf/netbind.c ${CC} ${CFLAGS} -o $@ ../conf/netbind.c sys pdp pdpuba pdpmba: make -f Make.$@ I=${I} H=${H} M=${M} AS="${AS}" CPP="${CPP}" \ CFLAGS="${CFLAGS}" ED="${ED}" net pdpnet: make -f Make.$@ I=${I} H=${H} M=${M} AS="${AS}" \ CPP="${CPP} -DSUPERVISOR" CFLAGS="${CFLAGS} -DSUPERVISOR" \ ED="${ED}" clean: rm -f unix core mklog *.o *.i assym.h genassym checksys rm -f netnix netbind d.unix.s d.netnix.s install: install -c -o root -g kmem -m 744 unix ${DESTDIR}/unix install -c -o root -g kmem -m 744 netnix ${DESTDIR}/netnix depend: FRC for i in ${SUB}; do \ make -f Make.$$i CFLAGS="${CFLAGS}" depend; done mkdep ${CFLAGS} param.c ioconf.c ../conf/checksys.c ../conf/netbind.c TAGSFILE= ${S}/tags TLIST= ${H} ${I} ${N1} ${N2} ${N3} ${N4} ${N5} ${N6} ${M} ${S} ${U} ${MB} ${SS} tags: FRC rm -f ${TAGSFILE} for i in ${TLIST}; do \ (cd ${S}; /usr/ucb/ctags -a -t $$i/*.[ch]); done /usr/bin/egrep "^ASENTRY|^ENTRY" ${M}/*.s | \ /bin/sed 's;\([^:]*\):\([^(]*\)(\([^)]*\));\3 \1 /^\2(\3)$$/;' \ >> ${TAGSFILE} /usr/bin/sort -o ${TAGSFILE} ${TAGSFILE} FRC: # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. .o sys_kern.o \ tm.o ts.o tty.o tty_conf.o tty_subr.o tty_tb.o ufs_alloc.o \ ufs_bio.o ufs_fio.o ufs_inode.o ufs_namei.o \ vm_proc.o vm_sched.o vm_swap.o xp.o quota_subr.o OV1= sys_generic.o ufs_syscalls.o OV2= kern_acsys/SMS/Make.net 664 0 0 5022 5266714304 6662 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # %W% (Berkeley) %G% # N1= ../net N1C= ${N1}/af.c ${N1}/if.c ${N1}/if_loop.c ${N1}/if_sl.c \ ${N1}/raw_cb.c ${N1}/raw_usrreq.c ${N1}/route.c N1O= af.o if.o if_loop.o if_sl.o raw_cb.o raw_usrreq.o route.o N2= ../netimp N2C= ${N2}/if_imp.c ${N2}/if_imphost.c ${N2}/raw_imp.c N2O= if_imp.o if_imphost.o raw_imp.o N3= ../netinet N3C= ${N3}/if_ether.c ${N3}/in.c ${N3}/in_pcb.c ${N3}/in_proto.c \ ${N3}/ip_icmp.c ${N3}/ip_input.c ${N3}/ip_output.c \ ${N3}/raw_ip.c ${N3}/tcp_debug.c ${N3}/tcp_input.c \ ${N3}/tcp_output.c ${N3}/tcp_subr.c ${N3}/tcp_timer.c \ ${N3}/tcp_usrreq.c ${N3}/udp_usrreq.c N3O= if_ether.o in.o in_pcb.o in_proto.o ip_icmp.o ip_input.o \ ip_output.o raw_ip.o tcp_debug.o tcp_input.o tcp_output.o \ tcp_subr.o tcp_timer.o tcp_usrreq.o udp_usrreq.o N5= ../netns N5C= ${N5}/ns.c ${N5}/ns_pcb.c ${N5}/ns_proto.c ${N5}/ns_error.c \ ${N5}/ns_ip.c ${N5}/ns_input.c ${N5}/ns_output.c \ ${N5}/idp_usrreq.c ${N5}/spp_usrreq.c ${N5}/spp_debug.c N5O= ns.o ns_pcb.o ns_proto.o ns_error.o ns_ip.o ns_input.o \ ns_output.o idp_usrreq.o spp_usrreq.o spp_debug.o N6= ../pdpif N6C= ${N6}/if_acc.c ${N6}/if_css.c ${N6}/if_de.c ${N6}/if_dmc.c \ ${N6}/if_ec.c ${N6}/if_en.c ${N6}/if_il.c ${N6}/if_qe.c \ ${N6}/if_qt.c ${N6}/if_sri.c ${N6}/if_uba.c ${N6}/if_vv.c N6O= if_acc.o if_css.o if_de.o if_dmc.o if_ec.o if_en.o if_il.o \ if_qe.o if_qt.o if_sri.o if_uba.o if_vv.o S= ../sys SC= ${S}/sys_socket.c ${S}/sys_net.c ${S}/uipc_domain.c \ ${S}/uipc_mbuf.c ${S}/uipc_proto.c ${S}/uipc_socket.c \ ${S}/uipc_socket2.c ${S}/uipc_usrreq.c SO= sys_socket.o sys_net.o uipc_domain.o uipc_mbuf.o uipc_proto.o \ uipc_socket.o uipc_socket2.o uipc_usrreq.o VPATH= ../net:../netimp:../netinet:../netns:../pdpif:../sys SRCS= ${N1C} ${N2C} ${N3C} ${N5C} ${N6C} ${SC} OBJS= ${N1O} ${N2O} ${N3O} ${N5O} ${N6O} ${SO} .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < NETSPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s all: ${OBJS} depend: mkdep -f Make.net ${CFLAGS} ${SRCS} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. ern_exit.o kern_fork.o kern_resource.o OV3= kern_time.o sys_process.o ufs_mount.o ufs_subr.o uipc_syscalls.o OV4= dkbad.o kern_sig.o mem.o subr_xxx.o trap.o tty_pty.o tty_tty.o OV5= quota_kern.o quota_ufs.o quota_sys.o ufs_bmap.o \ sys_pipe.o # OV6 gets the (hopefully) never used routines OV6= clock.o dn.o init_main.o kern_pdp.o machdep2.o subr_prf.o syscalls.o \ subr_log.o toy.o vm_swp.o OV7= tmscp.o ufs_disksubr.o ufs_dsort.o OV8= mch_fpsim.o kern_sysctl.o kern_xxx.o ingreslock.o vm_tesys/SMS/Make.pdp 664 0 0 5036 5757755537 6706 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # 2.0 (2.11BSD GTE) 1995/05/21 # M= ../machine VPATH= ../machine CFILES= ${M}/clock.c ${M}/conf.c ${M}/cons.c ${M}/kern_pdp.c \ ${M}/machdep.c ${M}/machdep2.c ${M}/mem.c ${M}/ram.c ${M}/trap.c COBJS= clock.o conf.o cons.o kern_pdp.o machdep.o machdep2.o mem.o \ ram.o trap.o # We compile mch_KScall here rather than in Make.pdpnet so that it gets # compiled with the right flags. This means that it gets compiled for all # kernel, but is only included in the networking kernel. As it only takes # a few seconds to compile it, it isn't worth trashing up Make.pdpnet to # compile it there. SFILES= ${M}/libc_bcmp.s ${M}/libc_bcopy.s ${M}/libc_bzero.s \ ${M}/libc_ffs.s ${M}/libc_insque.s ${M}/libc_ldiv.s \ ${M}/libc_lmul.s ${M}/libc_lrem.s ${M}/libc_remque.s \ ${M}/libc_uldiv.s ${M}/libc_ulsh.s \ ${M}/libc_strlen.s ${M}/libc_udiv.s ${M}/mch_backup.s \ ${M}/mch_click.s ${M}/mch_copy.s ${M}/mch_csv.s ${M}/mch_dump.s \ ${M}/mch_dzpdma.s ${M}/mch_fpsim.s ${M}/mch_KScall.s \ ${M}/mch_profile.s ${M}/mch_start.s ${M}/mch_trap.s \ ${M}/mch_vars.s ${M}/mch_xxx.s ${M}/scb.s ${M}/toy.s SOBJS= libc_bcmp.o libc_bcopy.o libc_bzero.o libc_ffs.o libc_insque.o \ libc_ldiv.o libc_lmul.o libc_lrem.o libc_remque.o libc_strlen.o \ libc_uldiv.o libc_ulsh.o \ libc_udiv.o mch_backup.o mch_click.o mch_copy.o mch_csv.o \ mch_dump.o mch_dzpdma.o mch_fpsim.o mch_KScall.o mch_profile.o \ mch_start.o mch_trap.o mch_vars.o mch_xxx.o scb.o toy.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s .s.o: ${CPP} $*.s | ${AS} -u -o $*.o all: assym.h ${COBJS} ${SOBJS} ../pdp/symbols.sort assym.h: genassym ./genassym > $@ genassym: ${CC} -O ${CFLAGS} ${M}/genassym.c -o $@ # it's a tab character in the sed statement below not a space. ../pdp/symbols.sort: ../pdp/symbols.raw grep -v '^#' ../pdp/symbols.raw \ | sed 's/^ //' | sort -u > ../pdp/symbols.sort depend: assym.h mkdep -f Make.pdp ${CFLAGS} ${CFILES} ${SFILES} ${M}/genassym.c # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. ern_fork.o kern_resource.o OV3= kern_time.o sys_process.o ufs_mount.o ufs_subr.o uipc_syscalls.o OV4= dkbad.o kern_sig.o mem.o subr_xxx.o trap.o tty_pty.o tty_tty.o OV5= quota_kern.o quota_ufs.o quota_sys.o ufs_bmap.o \ sys_pipe.o # OV6 gets the (hopefully) never used routines OV6= clock.o dn.o init_main.o kern_pdp.o machdep2.o subr_prf.o syscalls.o \ subr_log.o toy.o vm_swp.o OV7= tmscp.o ufs_disksubr.o ufs_dsort.o OV8= mch_fpsim.o kern_sysctl.o kern_xxx.o ingreslock.o vm_tesys/SMS/Make.pdpmba 664 0 0 1466 4263626577 7361 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # %W% (Berkeley) %G% # U= ../pdpmba VPATH= ../pdpmba CFILES= OBJS= .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s all: ${OBJS} depend: mkdep -f Make.pdpmba ${CFLAGS} ${CFILES} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. ke.pdpnet so that it gets # compiled with the right flags. This means that it gets compiled for all # kernel, but is only included in the networking kernel. As it only takes # a few seconds to compilesys/SMS/Make.pdpnet 664 0 0 2701 5757757237 7410 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # 2.0 (2.11BSD GTE) 1995/05/21 # M= ../machine VPATH= ../machine CFILES= ${M}/enable34.c ${M}/in_cksum.c COBJS= enable34.o in_cksum.o SFILES= ${M}/libc_htonl.s ${M}/libc_htons.s ${M}/net_copy.s \ ${M}/net_csv.s ${M}/net_mbuf.s ${M}/net_scb.s ${M}/net_SKcall.s \ ${M}/net_trap.s ${M}/net_xxx.s SOBJS= libc_htonl.o libc_htons.o mch_KScall.o net_copy.o net_csv.o \ net_mbuf.o net_scb.o net_SKcall.o net_trap.o net_xxx.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < NETSPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s .s.o: ${CPP} $*.s | ${AS} -u -o $*.o all: ${COBJS} ${SOBJS} in_cksum.o: ${CC} ${CFLAGS} -S ${M}/in_cksum.c ${ED} - < ${M}/cksum-fix > /dev/null in_cksum.s ${ED} - < NETSPLFIX in_cksum.s ${AS} - -o $@ in_cksum.s rm -f in_cksum.s depend: assym.h mkdep -f Make.pdpnet ${CFLAGS} ${CFILES} ${SFILES} assym.h: make -f Make.pdp CFLAGS="${CFLAGS}" assym.h # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. KScall.s \ ${M}/mch_profile.s ${M}/mch_start.s ${M}/mch_trap.ssys/SMS/Make.pdpuba 664 0 0 2200 5125225325 7334 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # %W% (Berkeley) %G% # U= ../pdpuba VPATH= ../pdpuba CFILES= ${U}/br.c ${U}/dh.c ${U}/dn.c ${U}/dhu.c ${U}/dhv.c ${U}/dkbad.c \ ${U}/dr.c ${U}/dz.c ${U}/hk.c ${U}/ht.c ${U}/lp.c ${U}/ra.c ${U}/rk.c \ ${U}/rl.c ${U}/rx.c ${U}/si.c ${U}/tm.c ${U}/tmscp.c ${U}/ts.c ${U}/xp.c OBJS= br.o dh.o dhu.o dhv.o dkbad.o dn.o dr.o dz.o hk.o ht.o lp.o ra.o rk.o \ rl.o rx.o si.o tm.o tmscp.o ts.o xp.o dn.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s all: ${OBJS} depend: mkdep -f Make.pdpuba ${CFLAGS} ${CFILES} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. dev/null in_cksum.s ${ED} - < NETSPLFIX in_cksum.s ${AS} - -o $@ in_cksum.s rm -f in_cksum.s depend: assym.h mkdep -f Make.pdpnet ${CFLAGS} ${CFILES} ${SFILES} assym.h: make -f Make.pdp CFLAGS="${CFLAGS}" assym.h # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. KScall.s \ ${M}/mch_profile.s ${M}/mch_start.s ${M}/mch_trap.ssys/SMS/Make.sys 664 0 0 5010 5743377446 6723 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # 2.2 (2.11BSD GTE) 1994/04/13 # S= ../sys VPATH= ../sys CFILES= ${S}/init_main.c ${S}/init_sysent.c ${S}/kern_acct.c \ ${S}/kern_clock.c ${S}/kern_descrip.c ${S}/kern_exec.c \ ${S}/kern_exit.c ${S}/kern_fork.c ${S}/kern_mman.c \ ${S}/kern_proc.c ${S}/kern_prot.c ${S}/kern_resource.c \ ${S}/kern_sig.c ${S}/kern_subr.c ${S}/kern_sysctl.c \ ${S}/kern_synch.c ${S}/kern_time.c ${S}/kern_xxx.c \ ${S}/quota_sys.c ${S}/quota_kern.c ${S}/quota_ufs.c \ ${S}/quota_subr.c ${S}/subr_log.c ${S}/subr_prf.c ${S}/subr_rmap.c \ ${S}/subr_xxx.c ${S}/sys_generic.c ${S}/sys_inode.c \ ${S}/sys_kern.c ${S}/sys_pipe.c \ ${S}/ingreslock.c \ ${S}/sys_process.c ${S}/syscalls.c ${S}/tty.c ${S}/tty_conf.c \ ${S}/tty_pty.c ${S}/tty_subr.c ${S}/tty_tb.c ${S}/tty_tty.c \ ${S}/ufs_alloc.c ${S}/ufs_bio.c ${S}/ufs_bmap.c \ ${S}/ufs_dsort.c ${S}/ufs_fio.c ${S}/ufs_inode.c \ ${S}/ufs_mount.c ${S}/ufs_namei.c ${S}/ufs_subr.c \ ${S}/ufs_disksubr.c \ ${S}/ufs_syscalls.c ${S}/uipc_syscalls.c ${S}/vm_proc.c \ ${S}/vm_sched.c ${S}/vm_swap.c ${S}/vm_swp.c ${S}/vm_text.c OBJS= init_main.o init_sysent.o kern_acct.o kern_clock.o \ kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o \ kern_proc.o kern_prot.o kern_resource.o kern_sig.o kern_sysctl.o \ kern_subr.o kern_synch.o kern_time.o kern_xxx.o quota_sys.o \ quota_kern.o quota_ufs.o quota_subr.o subr_log.o subr_prf.o subr_rmap.o \ ingreslock.o \ subr_xxx.o sys_generic.o sys_inode.o sys_kern.o \ sys_pipe.o sys_process.o syscalls.o tty.o tty_conf.o tty_pty.o \ tty_subr.o tty_tb.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o \ ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o \ ufs_subr.o ufs_syscalls.o uipc_syscalls.o vm_proc.o vm_sched.o \ ufs_disksubr.o \ vm_swap.o vm_swp.o vm_text.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s all: ${OBJS} depend: mkdep -f Make.sys ${CFLAGS} ${CFILES} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. NE, IT WILL GO AWAY. ern_fork.o kern_resource.o OV3= kern_time.o sys_process.o ufs_mount.o ufs_subr.o uipc_syscalls.o OV4= dkbad.o kern_sig.o mem.o subr_xxx.o trap.o tty_pty.o tty_tty.o OV5= quota_kern.o quota_ufs.o quota_sys.o ufs_bmap.o \ sys_pipe.o # OV6 gets the (hopefully) never used routines OV6= clock.o dn.o init_main.o kern_pdp.o machdep2.o subr_prf.o syscalls.o \ subr_log.o toy.o vm_swp.o OV7= tmscp.o ufs_disksubr.o ufs_dsort.o OV8= mch_fpsim.o kern_sysctl.o kern_xxx.o ingreslock.o vm_tesys/SMS/localopts.h 664 0 0 516 5320215231 7413 /* * This file is generated by the configuration script sys/conf/config. * * It contains a list the kernel options not prepended to the Makefile * as -Dxxxx commands to the compiler. MAXMEM was moved to param.h leaving * only LINEHZ and EXTERNALITIMES to be placed in localopts.h */ #define LINEHZ 60 #define EXTERNALITIMES 1 .o, kern_exec.okern_descrip.old kern_exit.o.o kern_fork.o.o kern_mman.o.o kern_proc.o.o kern_prot.o.o kern_sig.o.otty.sys/SMS/ingres.h 640 0 0 22 5720310200 6640 #define NINGRES 1 .h rl.h br.h si.h tm.h xp.hMakefileMake.netMake.pdp Make.pdpmbas Make.pdpnets Make.pdpubasMake.sysb localopts.hs(ingres.h.assym.h. init_main.os init_sysent.o kern_acct.oo kern_clock.o, kern_exec.okern_descrip.old kern_exit.o.o kern_fork.o.o kern_mman.o.o kern_proc.o.o kern_prot.o.o kern_sig.o.otty.sys/SMS/version 664 0 0 4 6044571315 6616 174 (if_dmc.oqif_ec.o.if_en.o.if_il.o.if_qe.o.if_qt.o.if_sri.o.if_uba.o.if_vv.o. sys_net.o( sys_socket.o libc_htonl.o uipc_domain.o uipc_mbuf.oo uipc_proto.o$ uipc_socket.o net_scb.o versiono net_xxx.overs.c.o uipc_usrreq.ouipc_socket2.od enable34.o2.o in_cksum.o2.o libc_htons.oo net_copy.ooo, net_mbuf.oooioconf.osys/SMS/vers.c 664 0 0 172 6044571315 6377 char version[] = "2.11 BSD UNIX #174: Sat Oct 28 20:19:40 PDT 1995\n sms1@sms.sms.iipo.gtegsc.com:/usr/src/sys/SMS\n"; if_uba.o.if_vv.o. sys_net.o( sys_socket.o libc_htonl.o uipc_domain.o uipc_mbuf.oo uipc_proto.o$ uipc_socket.o net_scb.o versiono net_xxx.overs.c.o uipc_usrreq.ouipc_socket2.od enable34.o2.o in_cksum.o2.o libc_htons.oo net_copy.ooo, net_mbuf.oooioconf.osys/vaxdist/ 755 0 12 0 4361177222 6247 sys/vaxdist/buildmini 444 0 12 741 4106142715 10207 #!/bin/sh # # Copyright (c) 1983 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)buildmini 4.8 (Berkeley) 6/6/86 # miniroot=hp0d minitype=rm80 # date umount /dev/${miniroot} newfs -s 4096 ${miniroot} ${minitype} fsck /dev/r${miniroot} mount /dev/${miniroot} /mnt cd /mnt; sh /sys/dist/get cd /sys/dist; sync umount /dev/${miniroot} fsck /dev/${miniroot} date rc.local0 tpdissys/vaxdist/get 444 0 12 5717 4106142715 7042 #!/bin/sh # # Copyright (c) 1983 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)get 4.25 (Berkeley) 6/6/86 # # Shell script to build a mini-root file system # in preparation for building a distribution tape. # The file system created here is image copied onto # tape, then image copied onto disk as the "first" # step in a cold boot of 4.3 systems. # DISTROOT=/nbsd # if [ `pwd` = '/' ] then echo You just '(almost)' destroyed the root exit fi cp $DISTROOT/sys/GENERIC/vmunix . rm -rf bin; mkdir bin rm -rf etc; mkdir etc rm -rf a; mkdir a rm -rf tmp; mkdir tmp rm -rf usr; mkdir usr usr/mdec rm -rf sys; mkdir sys sys/floppy sys/cassette sys/consolerl cp $DISTROOT/etc/disktab etc cp $DISTROOT/etc/newfs etc cp $DISTROOT/etc/mkfs etc cp $DISTROOT/etc/restore etc cp $DISTROOT/etc/init etc cp $DISTROOT/etc/mount etc cp $DISTROOT/etc/mknod etc cp $DISTROOT/etc/fsck etc cp $DISTROOT/etc/umount etc cp $DISTROOT/etc/arff etc cp $DISTROOT/etc/flcopy etc cp $DISTROOT/bin/mt bin cp $DISTROOT/bin/ls bin cp $DISTROOT/bin/sh bin cp $DISTROOT/bin/mv bin cp $DISTROOT/bin/sync bin cp $DISTROOT/bin/cat bin cp $DISTROOT/bin/mkdir bin cp $DISTROOT/bin/stty bin; ln bin/stty bin/STTY cp $DISTROOT/bin/echo bin cp $DISTROOT/bin/rm bin cp $DISTROOT/bin/cp bin cp $DISTROOT/bin/expr bin cp $DISTROOT/bin/[ bin cp $DISTROOT/bin/awk bin cp $DISTROOT/bin/make bin cp $DISTROOT/usr/mdec/* usr/mdec cp $DISTROOT/sys/floppy/[Ma-z0-9]* sys/floppy cp $DISTROOT/sys/consolerl/[Ma-z0-9]* sys/consolerl cp -r $DISTROOT/sys/cassette/[Ma-z0-9]* sys/cassette cp $DISTROOT/sys/stand/boot boot cp $DISTROOT/sys/stand/pcs750.bin pcs750.bin cp $DISTROOT/.profile .profile cat >etc/passwd <etc/group <etc/fstab <xtr <<'EOF' : ${disk?'Usage: disk=xx0 type=tt tape=yy xtr'} : ${type?'Usage: disk=xx0 type=tt tape=yy xtr'} : ${tape?'Usage: disk=xx0 type=tt tape=yy xtr'} echo 'Build root file system' newfs ${disk}a ${type} sync echo 'Check the file system' fsck /dev/r${disk}a mount /dev/${disk}a /a cd /a echo 'Rewind tape' mt -f /dev/${tape}0 rew echo 'Restore the dump image of the root' restore rsf 3 /dev/${tape}0 cd / sync umount /dev/${disk}a sync fsck /dev/r${disk}a echo 'Root filesystem extracted' echo echo 'If this is an 8650 or 8600, update the console rl02' echo 'If this is a 780 or 785, update the floppy' echo 'If this is a 730, update the cassette' EOF chmod +x xtr rm -rf dev; mkdir dev cp $DISTROOT/sys/dist/MAKEDEV dev chmod +x dev/MAKEDEV cp /dev/null dev/MAKEDEV.local cd dev ./MAKEDEV std hp0 hk0 up0 ra0 rb0 ./MAKEDEV ts0; mv rmt12 ts0; rm *mt*; ./MAKEDEV tm0; mv rmt12 tm0; rm *mt*; ./MAKEDEV ht0; mv rmt12 ht0; rm *mt*; ./MAKEDEV ut0; mv rmt12 ut0; rm *mt*; ./MAKEDEV mt0; mv rmt12 xt0; rm *mt*; mv xt0 mt0 cd .. sync sim.o kern_sysctl.o kern_xxx.o ingreslock.o vm_tesys/vaxdist/README 444 0 12 1561 4106142715 7211 Sun Jun 23 16:31:26 PDT 1985 The scripts needed to build a boot tape for 4.2 and beyond live here. Before trying anything look at the scripts buildmini get maketape To construct a tape suitable for bootstrapping a system first find a spare file system for a ``mini root'' and patch the buildmini shell script to reflect its location. Second, decide where your ``distribution'' source is located and patch the get and maketape scripts. Then do the following: % buildmini % maketape [ 6250 | 1600 [ tapename [ remotetapemachine ] ] ] This builds a distribution on one tape at 6250bpi, two tapes at 1600bpi. The tape drive may be on a remote machine if the last optional arg is given. For 1600bpi, be sure and check whether /usr/src will fit on one tape. The current distribution is about 80+ megabytes and easily fits on one tape at 6250bpi with a blocking factor of 20. ore etc cp $DISTROOT/etc/init etc cp $DISTROOT/etc/mount etc cp $DISTROOT/etc/mknod etc cp $DISTROOT/etc/fsck etc cp $DISTROOT/etc/umount etc csys/vaxdist/MAKEDEV 444 0 12 21720 4106142715 7347 #!/bin/sh - # # Copyright (c) 1980 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)MAKEDEV 4.29 (Berkeley) 7/18/87 # # Device "make" file. Valid arguments: # std standard devices # local configuration specific devices # Tapes: # ht* massbus tm03 & tu?? # tm* unibus tm11 & te10 emulations (e.g. Emulex tc-11) # ts* unibus ts11 # mt* massbus tu78 # ut* unibus tu45 emulations (e.g.si 9700) # uu* tu58 cassettes on dl11 controller # Disks: # hp* massbus rm?? # hk* unibus rk06 and rk07 # up* other unibus devices (e.g. on Emulex sc-21v controller) # ra* unibus uda50 w/ ra?? # rl* unibus rl02 # rb* 730 idc w/ rb80 and/or rb02 # rx* unibus rx211 floppy disk # Terminal multiplexors: # dz* unibus dz11 and dz32 # dh* unibus dh11 and emulations (e.g. Able dmax, Emulex cs-11) # dmf* unibus dmf32 # dhu* unibus dhu11 # dmz* unibus dmz32 # Pseudo terminals: # pty* set of 16 master and slave pseudo terminals # Printers: # ct* unibus parallel interface to CAT typesetter # lp* unibus lp11 parallel interface # va* unibus varian parallel interface # vp* unibus versatec parallel interface # Call units: # dn* unibus dn11 and emulations (e.g. Able Quadracall) # Special purpose devices: # ik* unibus interface to ikonas frame buffer # ps* unibus interface to e&s picture system 2 # ad* unibus interface to data translation a/d converter # np* unibus ethernet co-processor interface, for downloading. # qv* qvss (microvax) display # ttyv0 qvss (microvax) display reserved pty umask 77 for i do case $i in std) /etc/mknod console c 0 0 /etc/mknod drum c 7 0 ; chmod 640 drum ; chgrp kmem drum /etc/mknod floppy c 8 0 /etc/mknod crl c 35 0 /etc/mknod tu0 b 8 0 /etc/mknod tu1 b 8 1 /etc/mknod kUmem c 3 3 ; chmod 600 kUmem /etc/mknod kmem c 3 1 ; chmod 640 kmem ; chgrp kmem kmem /etc/mknod mem c 3 0 ; chmod 640 mem ; chgrp kmem mem /etc/mknod null c 3 2 ; chmod 666 null /etc/mknod tty c 2 0 ; chmod 666 tty /etc/mknod klog c 33 0 ; chmod 600 klog ;; ht*|tm*|ts*|ut*) umask 0 ; unit=`expr $i : '..\(.*\)'` case $i in ht*) blk=1; chr=5 ;; tm*) blk=5; chr=14;; ts*) blk=6; chr=16;; ut*) blk=10; chr=17;; esac case $unit in 0|1|2|3|4|5|6|7) four=`expr $unit + 4` ; eight=`expr $unit + 8` twelve=`expr $unit + 12`; twenty=`expr $unit + 20` /etc/mknod mt$unit b $blk $unit /etc/mknod mt$four b $blk $four /etc/mknod mt$eight b $blk $eight /etc/mknod mt$twelve b $blk $twelve /etc/mknod nmt$unit b $blk $four ;: sanity w/pdp11 v7 /etc/mknod nmt$eight b $blk $twelve ;: ditto /etc/mknod nrmt$unit c $chr $four ;: sanity w/pdp11 v7 /etc/mknod nrmt$eight c $chr $twelve ;: ditto /etc/mknod rmt$unit c $chr $unit /etc/mknod rmt$four c $chr $four /etc/mknod rmt$eight c $chr $eight /etc/mknod rmt$twelve c $chr $twelve if [ $i = ut ] then /etc/mknod mt$twenty b $blk $twenty /etc/mknod rmt$twenty c $chr $twenty fi ;; *) echo bad unit for tape in: $1 ;; esac umask 77 ;; mt*) umask 0 ; unit=`expr $i : '..\(.*\)'` case $i in mt*) blk=7; chr=19;; esac case $unit in 0|1|2|3|4|5|6|7) eight=`expr $unit + 0`; twelve=`expr $unit + 4`; sixteen=`expr $unit + 8`; twenty=`expr $unit + 12`; /etc/mknod mt8 b $blk $eight /etc/mknod mt12 b $blk $twelve /etc/mknod mt16 b $blk $sixteen /etc/mknod mt20 b $blk $twenty /etc/mknod nmt8 b $blk $twelve ;: ditto /etc/mknod nrmt8 c $chr $twelve ;: ditto /etc/mknod rmt8 c $chr $eight /etc/mknod rmt12 c $chr $twelve /etc/mknod rmt16 c $chr $sixteen /etc/mknod rmt20 c $chr $twenty /etc/mknod nmt16 b $blk $twenty ;: ditto /etc/mknod nrmt16 c $blk $twenty ;: ditto ;; *) echo bad unit for tape in: $1 ;; esac umask 77 ;; hp*|hk*|up*|ra*|rl*|rb*) umask 2 ; unit=`expr $i : '..\(.*\)'` case $i in hp*) name=hp; blk=0; chr=4;; hk*) name=hk; blk=3; chr=11;; up*) name=up; blk=2; chr=13;; ra*) name=ra; blk=9; chr=9;; rb*) name=rb; blk=11; chr=23;; rl*) name=rl; blk=14; chr=32;; esac case $unit in 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|\ 17|18|19|20|21|22|23|24|25|26|27|28|29|30|31) /etc/mknod ${name}${unit}a b $blk `expr $unit '*' 8 + 0` /etc/mknod ${name}${unit}b b $blk `expr $unit '*' 8 + 1` /etc/mknod ${name}${unit}c b $blk `expr $unit '*' 8 + 2` /etc/mknod ${name}${unit}g b $blk `expr $unit '*' 8 + 6` /etc/mknod r${name}${unit}a c $chr `expr $unit '*' 8 + 0` /etc/mknod r${name}${unit}b c $chr `expr $unit '*' 8 + 1` /etc/mknod r${name}${unit}c c $chr `expr $unit '*' 8 + 2` /etc/mknod r${name}${unit}g c $chr `expr $unit '*' 8 + 6` if [ $name != hk ] then /etc/mknod ${name}${unit}d b $blk `expr $unit '*' 8 + 3` /etc/mknod ${name}${unit}e b $blk `expr $unit '*' 8 + 4` /etc/mknod ${name}${unit}f b $blk `expr $unit '*' 8 + 5` /etc/mknod ${name}${unit}h b $blk `expr $unit '*' 8 + 7` /etc/mknod r${name}${unit}d c $chr `expr $unit '*' 8 + 3` /etc/mknod r${name}${unit}e c $chr `expr $unit '*' 8 + 4` /etc/mknod r${name}${unit}f c $chr `expr $unit '*' 8 + 5` /etc/mknod r${name}${unit}h c $chr `expr $unit '*' 8 + 7` fi chgrp operator ${name}${unit}[a-h] r${name}${unit}[a-h] chmod 640 ${name}${unit}[a-h] r${name}${unit}[a-h] ;; *) echo bad unit for disk in: $i ;; esac umask 77 ;; rx*) unit=`expr $i : '..\(.*\)'` name=rx; chr=30; blk=12; case $unit in 0|1|2|3|4|5|6|7) /etc/mknod ${name}${unit} b $blk `expr $unit '*' 8 + 0` /etc/mknod r${name}${unit}a c $chr `expr $unit '*' 8 + 0` /etc/mknod r${name}${unit}b c $chr `expr $unit '*' 8 + 1` /etc/mknod r${name}${unit}c c $chr `expr $unit '*' 8 + 2` /etc/mknod r${name}${unit}d c $chr `expr $unit '*' 8 + 3` ;; *) echo bad unit for floppy disk in: $i ;; esac ;; uu*) unit=`expr $i : '..\(.*\)'` name=uu; blk=13; case $unit in 0|1|2|3) /etc/mknod ${name}${unit} b $blk `expr $unit '*' 2 + 0` /etc/mknod ${name}${unit}a b $blk `expr $unit '*' 2 + 1` ;; *) echo bad unit for uu cassette in: $i ;; esac ;; dz*) unit=`expr $i : 'dz\(.*\)'` case $unit in 0|1|2|3|4|5|6|7) eval `echo $unit | awk ' { u = $1 } END { for (i = 0; i < 8; i++) printf("/etc/mknod tty%02d c 1 %d; ",u*8+i,u*8+i); }'` ;; *) echo bad unit for dz in: $i ;; esac ;; dhu*|dh*|dmf*|dmz*) case $i in dmz*) name=dmz; major=37; count=24; unit=`expr $i : "$name\(.*\)"` case $unit in 0) ch=a ;; 1) ch=b ;; 2) ch=c ;; 3) ch=e ;; 4) ch=f ;; 5) ch=g ;; *) echo bad unit for $name in: $i ;; esac;; dmf*) name=dmf; major=22; count=8; unit=`expr $i : "$name\(.*\)"` case $unit in 0) ch=A ;; 1) ch=B ;; 2) ch=C ;; 3) ch=E ;; 4) ch=F ;; 5) ch=G ;; 6) ch=H ;; 7) ch=I ;; *) echo bad unit for $name in: $i ;; esac;; dhu*) name=dhu; major=34; count=16; unit=`expr $i : "$name\(.*\)"`; case $unit in 0) ch=S ;; 1) ch=T ;; 2) ch=U ;; 3) ch=V ;; 4) ch=W ;; 5) ch=X ;; 6) ch=Y ;; 7) ch=Z ;; *) echo bad unit for $name in: $i ;; esac;; dh*) name=dh; major=12; count=16; unit=`expr $i : "$name\(.*\)"` case $unit in 0) ch=h ;; 1) ch=i ;; 2) ch=j ;; 3) ch=k ;; 4) ch=l ;; 5) ch=m ;; 6) ch=n ;; 7) ch=o ;; *) echo bad unit for $name in: $i ;; esac;; esac eval `echo $ch $unit $major $count | awk ' { ch = $1; u = $4 * $2; m = $3; cnt = $4 } END { for (i = 0; i < cnt; i++) if (i < 10) printf("/etc/mknod tty%s%x c %d %d; ",ch,i,m,u+i); else printf("/etc/mknod tty%s%c c %d %d; ",ch,87+i,m,u+i); }'` ;; lp*|va*|vp*) case $i in lp*) name=lp; major=15;; va*) name=va; major=10;; vp*) name=vp; major=6;; esac unit=`expr $i : "$name\(.*\)"` case $unit in 0|1|2|3|4|5|6|7) /etc/mknod $i c $major $unit; chmod 666 $i ;; *) echo bad unit for $name in: $i ;; esac ;; pty*) class=`expr $i : 'pty\(.*\)'` case $class in 0) offset=0 name=p;; 1) offset=16 name=q;; 2) offset=32 name=r;; 3) offset=48 name=s;; 4) offset=64 name=t;; 5) offset=80 name=u;; *) echo bad unit for pty in: $i;; esac case $class in 0|1|2|3|4|5) umask 0 eval `echo $offset $name | awk ' { b=$1; n=$2 } END { for (i = 0; i < 16; i++) printf("/etc/mknod tty%s%x c 20 %d; \ /etc/mknod pty%s%x c 21 %d; ", \ n, i, b+i, n, i, b+i); }'` umask 77 ;; esac ;; np*) class=`expr $i : 'np\(.*\)'` case $class in 0) offset=0 name=0;; 1) offset=16 name=1;; 2) offset=32 name=2;; *) echo bad unit for np in: $i;; esac case $class in 0|1|2) eval `echo $offset | awk ' { b=$1 } END { for (i = 0; i < 4; i++) printf("/etc/mknod np%02d c 39 %d;", \ b+i, b+i); }'` ;; esac ;; dn*|ik*|ps*|ad*|ct*) unit=`expr $i : '..\(.*\)'` case $i in ct*) name=ct; chr=18;; dn*) name=cu; chr=24;; ps*) name=ps; chr=27;; ad*) name=ad; chr=29;; ik*) name=ik; chr=31;; esac case $unit in 0|1|2|3|4|5|6|7) umask 0 /etc/mknod ${name}${unit} c ${chr} ${unit} umask 77 ;; *) echo bad unit for ${name} in: $i ;; esac ;; qv0) /etc/mknod qv0 c 40 0 /etc/mknod qvcons c 40 1 /etc/mknod mouse c 40 2 ;; ttyv0) if [ ! -f ttyqf ]; then sh ./MAKEDEV pty1; fi mv ttyqf ttyv0 mv ptyqf ptyv0 ;; local) sh MAKEDEV.local ;; esac done #32604:bd#1024:fd#1024:td=2.11BSD:\ :pe#140436sys/vaxdist/maketape 444 0 12 6124 4106142715 10043 #!/bin/sh # # Copyright (c) 1983 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)maketape 4.31 (Berkeley) 6/6/86 # # maketape [ 6250 | 1600 [ tapename [ remotetapemachine ] ] ] miniroot=hp0d tape=/dev/rmt12 type=1600 if [ $# -gt 0 ]; then type=$1; fi if [ $# -gt 1 ]; then tape=$2; fi tartape=$tape if [ $# -gt 2 ]; then remote=$3; tartape='-'; fi # trap "rm -f /tmp/tape.$$; exit" 0 1 2 3 13 15 $remote mt -t ${tape} rew date umount /dev/hp2g umount /dev/hp2a mount -r /dev/hp2a /c/nbsd mount -r /dev/hp2g /c/nbsd/usr cd tp tp cmf /tmp/tape.$$ boot copy format cd /nbsd/sys/mdec echo "Build 1st level boot block file" cat tsboot htboot tmboot mtboot utboot noboot noboot /tmp/tape.$$ | \ $remote dd of=${tape} obs=512 conv=sync cd /nbsd sync echo "Add dump of mini-root file system" eval dd if=/dev/r${miniroot} count=205 bs=20b conv=sync ${remote+'|'} \ ${remote-"of=$tape"} ${remote+'/usr/local/20b ">" $tape'} echo "Add full dump of real file system" /etc/${remote+r}dump 0uf $remote${remote+:}${tape} /c/nbsd echo "Add tar image of /usr" cd /nbsd/usr; eval tar cf ${tartape} adm bin dict doc games \ guest hosts include lib local man mdec msgs new \ preserve pub spool tmp ucb \ ${remote+'| $remote /usr/local/20b ">" $tape'} if [ ${type} != '6250' ] then echo "Done, rewinding first tape" $remote mt -t ${tape} rew & echo "Mount second tape and hit return when ready" echo "(or type name of next tape drive)" read x if [ "$x" != "" ] then tape=$x fi fi echo "Add tar image of system sources" cd /nbsd/sys; eval tar cf ${tartape} . \ ${remote+'| $remote /usr/local/20b ">" $tape'} echo "Add user source code" cd /nbsd/usr/src; eval tar cf ${tartape} Makefile bin etc games \ include lib local old ucb undoc usr.bin usr.lib \ ${remote+'| $remote /usr/local/20b ">" $tape'} echo "Add varian fonts" cd /usr/lib/vfont; eval tar cf ${tartape} . \ ${remote+'| $remote /usr/local/20b ">" $tape'} if [ ${type} != '6250' ] then echo "Done, rewinding second tape" $remote mt -t ${tape} rew & echo "Mount third tape and hit return when ready" echo "(or type name of next tape drive)" read x if [ "$x" != "" ] then tape=$x fi fi echo "Add user contributed software" if [ ${type} != '6250' ] then cd /nbsd/usr/src/new; eval tar cf ${tartape} \ README Makefile \ B X ansi apl bib courier cpm dipress dsh emacs enet help \ hyper icon jove kermit mh mkmf mmdf.tar.Z news notes nntp \ np100 patch pathalias rcs rn spms sumacc.tar.Z sunrpc \ tac tools umodem xns \ ${remote+'| $remote /usr/local/20b ">" $tape'} else cd /nbsd/usr/src/new; eval tar cf ${tartape} \ README Makefile \ B X ansi apl bib courier cpm dipress dsh emacs enet help \ hyper icon jove kermit mh mkmf mmdf news notes nntp \ np100 patch pathalias rcs rn spms sumacc sunrpc \ tac tools umodem xns \ ${remote+'| $remote /usr/local/20b ">" $tape'} fi echo "Add ingres source" cd /nbsd/usr/ingres; eval tar cf ${tartape} . \ ${remote+'| $remote /usr/local/20b ">" $tape'} echo "Done, rewinding tape" $remote mt -t ${tape} rew & c/mknod nrmt$unit c $chr $four ;: sanity w/pdp11 v7 /etc/mknod nrmt$eight c $chr $twelve ;: ditto /etc/mknod rmt$unit c $chr $unit /etc/mknod rmt$four c $chr $four /etc/mknod rmt$eight c $chr $eight /etc/mknod rmt$twelve c $chr $twelve if [ $i = ut ] then /etc/mknod mt$twenty b $blk $twenty /etc/mknod rmt$twenty c $chr $twenty fi ;; *) echo bad unit for tape in: $1 ;; esac umask 77 ;; mt*) sys/vaxdist/disktab 444 0 12 34525 4106142716 7724 # # Copyright (c) 1983,1986 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)disktab 4.14 (Berkeley) 6/19/87 # # Disk geometry and partition layout tables. # Key: # dt controller type # ty type of disk (fixed, removeable, simulated) # d[0-4] drive-type-dependent parameters # ns #sectors/track # nt #tracks/cylinder # nc #cylinders/disk # sc #sectors/cylinder, nc*nt default # su #sectors/unit, sc*nc default # se sector size, DEV_BSIZE default # rm rpm, 3600 default # sf supports bad144-style bad sector forwarding # sk sector skew per track, default 0 # cs sector skew per cylinder, default 0 # hs headswitch time, default 0 # ts one-cylinder seek time, default 0 # il sector interleave (n:1), 1 default # bs boot block size, default BBSIZE # sb superblock size, default SBSIZE # o[a-h] partition offsets in sectors # p[a-h] partition sizes in sectors # b[a-h] partition block sizes in bytes # f[a-h] partition fragment sizes in bytes # t[a-h] partition types (filesystem, swap, etc) # # WARNING: # On drives that contain bad-sector replacement areas, # `c' partitions DO overlap the bad-sector replacements. # This may change again. # Other partitions do not overlap the bad-sector replacement area. # # Existing entries may also be used for other compatible drives # with the same geometry. # # Drives on hp # # drive-type parameters for SMD disks: # d0 binary flags: 1=skip-sector support (RM80) # d1 mindist (closest #sectors from desired for starting transfer) # d2 maxdist (farthest #sectors from desired for starting transfer) # d3 sdist (distance from desired sector for search) # NOTE: c partitions include bad-sector replacement areas! rm03|RM03|DEC RM03:\ :ty=removable:ns#32:nt#5:nc#823:sf:\ :dt=SMD:d0#0:d1#1:d2#4:d3#7:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#33440:ob#16000:bb#8192:fb#1024:tb=swap:\ :pc#131680:oc#0:bc#8192:fc#1024:\ :pd#15884:od#49440:bd#4096:fd#512:\ :pe#55936:oe#65440:be#8192:fe#1024:\ :pf#10080:of#121440:bf#8192:ff#1024:\ :pg#82080:og#49440:bg#8192:fg#1024: # :pc#131520:oc#0:bc#8192:fc#1024: rm05|RM05|DEC RM05:\ :ty=removable:ns#32:nt#19:nc#823:sf:\ :dt=SMD:d0#0:d1#1:d2#4:d3#7:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#33440:ob#16416:bb#8192:fb#1024:tb=swap:\ :pc#500384:oc#0:bc#8192:fc#1024:\ :pd#15884:od#341696:bd#4096:fd#512:\ :pe#55936:oe#358112:be#8192:fe#1024:\ :pf#86176:of#414048:bf#8192:ff#1024:\ :pg#158528:og#341696:bg#8192:fg#1024:\ :ph#291346:oh#49856:bh#8192:fh#1024: # :pc#500224:oc#0:bc#8192:fc#1024: rp06|RP06|DEC RP06:\ :ty=removable:ns#22:nt#19:nc#815:sf:\ :dt=SMD:d0#0:d1#1:d2#4:d3#7:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#33440:ob#15884:bb#8192:fb#1024:tb=swap:\ :pc#340670:oc#0:bc#8192:fc#1024:\ :pd#15884:od#49324:bd#4096:fd#512:\ :pe#55936:oe#65208:be#8192:fe#1024:\ :pf#219296:of#121220:bf#8192:ff#1024:\ :pg#291192:og#49324:bg#8192:fg#1024: # :pc#340516:oc#0:bc#8192:fc#1024: rm80|RM80|DEC RM80:\ :ty=winchester:ns#31:nt#14:nc#559:sf:\ :dt=SMD:d0#1:d1#1:d2#4:d3#7:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#33440:ob#16058:bb#8192:fb#1024:tb=swap:\ :pc#242606:oc#0:bc#8192:fc#1024:\ :pd#15884:od#49910:bd#4096:fd#512:\ :pe#55936:oe#65968:be#8192:fe#1024:\ :pf#120466:of#121954:bf#8192:ff#1024:\ :pg#192510:og#49910:bg#8192:fg#1024: # :pc#242420:oc#0:bc#8192:fc#1024: rp05|RP05|DEC RP05:\ :ty=removable:ns#22:nt#19:nc#411:sf:\ :dt=SMD:d0#0:d1#1:d2#4:d3#7:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#33440:ob#15884:bb#8192:fb#1024:tb=swap:\ :pc#171798:oc#0:bc#8192:fc#1024:\ :pd#15884:od#49324:bd#4096:fd#512:\ :pe#55936:oe#65208:be#8192:fe#1024:\ :pf#50424:of#121220:bf#8192:ff#1024:\ :pg#122320:og#49324:bg#8192:fg#1024: # :pc#171644:oc#0:bc#8192:fc#1024: rp07|RP07|DEC RP07:\ :ty=winchester:ns#50:nt#32:nc#630:sf:\ :dt=SMD:d0#0:d1#1:d2#4:d3#7:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#66880:ob#16000:bb#8192:fb#1024:tb=swap:\ :pc#1008000:oc#0:bc#8192:fc#1024:\ :pd#15884:od#376000:bd#4096:fd#512:\ :pe#307200:oe#392000:be#8192:fe#1024:\ :pf#308600:of#699200:bf#8192:ff#1024:\ :pg#631800:og#376000:bg#8192:fg#1024:\ :ph#291346:oh#83200:bh#8192:fh#1024: # :pc#1007800:oc#0:bc#8192:fc#1024: ml11|ml11a|ml11b|ML11A|ML11B|DEC disk emulator:\ :ty=simulated:dt=SMD:ns#1:nt#1:nc#2000: 9775|CDC 9775:\ :ty=winchester:ns#32:nt#40:nc#842:sf:\ :dt=SMD:d0#0:d1#1:d2#4:d3#7:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#66880:ob#16640:bb#8192:fb#1024:tb=swap:\ :pc#1077760:oc#0:bc#8192:fc#1024:\ :pd#15884:od#376320:bd#4096:fd#512:\ :pe#307200:oe#392960:be#8192:fe#1024:\ :pf#377440:of#700160:bf#8192:ff#1024:\ :pg#701280:og#376320:bg#8192:fg#1024:\ :ph#291346:oh#84480:bh#8192:fh#1024: # :pc#1077600:oc#0:bc#8192:fc#1024: 9730|CDC 9730:\ :ty=removable:ns#32:nt#10:nc#823:sf:\ :dt=SMD:d0#0:d1#1:d2#4:d3#7:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#33440:ob#16000:bb#8192:fb#1024:tb=swap:\ :pc#263360:oc#0:bc#8192:fc#1024:\ :pd#15884:od#49600:bd#4096:fd#512:\ :pe#55936:oe#65600:be#8192:fe#1024:\ :pf#141600:of#121600:bf#8192:ff#1024:\ :pg#213600:og#49600:bg#8192:fg#1024: # :pc#263200:oc#0:bc#8192:fc#1024: capricorn|330|Capricorn|Ampex Capricorn:\ :ty=winchester:ns#32:nt#16:nc#1024:sf:\ :dt=smd:d0#0:d1#1:d2#4:d3#7:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#33440:ob#16384:bb#8192:fb#1024:tb=swap:\ :pc#524488:oc#0:bc#8192:fc#1024:\ :pd#15884:od#342016:bd#4096:fd#512:\ :pe#55936:oe#358400:be#8192:fe#1024:\ :pf#109408:of#414720:bf#8192:ff#1024:\ :pg#182112:og#342016:bg#8192:fg#1024:\ :ph#291346:oh#50176:bh#8192:fh#1024: # :pc#524128:oc#0:bc#8192:fc#1024: eagle|Eagle|2351|2351A|Fujitsu Eagle 2351A (48 sectors):\ :ty=winchester:ns#48:nt#20:nc#842:rm#3961:sf:\ :dt=smd:d0#0:d1#3:d2#8:d3#15:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#66880:ob#16320:bb#8192:fb#1024:tb=swap:\ :pc#808320:oc#0:bc#8192:fc#1024:\ :pd#15884:od#375360:bd#4096:fd#512:\ :pe#307200:oe#391680:be#8192:fe#1024:\ :pf#109248:of#698880:bf#8192:ff#1024:\ :pg#432768:og#375360:bg#8192:fg#1024:\ :ph#291346:oh#83520:bh#8192:fh#1024: # :pc#808128:oc#0:bc#8192:fc#1024: 2361|doubleeagle|Fujitsu 2361 (Double Eagle, 64 sectors):\ :ty=winchester:ns#64:nt#20:nc#842:sf:\ :dt=SMD:d0#0:d1#3:d2#8:d3#15:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#66880:ob#16640:bb#8192:fb#1024:tb=swap:\ :pc#1077760:oc#0:bc#8192:fc#1024:\ :pd#15884:od#376320:bd#4096:fd#512:\ :pe#307200:oe#392960:be#8192:fe#1024:\ :pf#377408:of#700160:bf#8192:ff#1024:\ :pg#701248:og#376320:bg#8192:fg#1024:\ :ph#291346:oh#84480:bh#8192:fh#1024: # :pc#1077568:oc#0:bc#8192:fc#1024: 2361a|doubleeagle|Fujitsu 2361 (Double Eagle, 68 sectors):\ :ty=winchester:ns#68:nt#20:nc#842:sf:\ :dt=SMD:d0#0:d1#3:d2#8:d3#15:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#66880:ob#16320:bb#8192:fb#1024:tb=swap:\ :pc#1145120:oc#0:bc#8192:fc#1024:\ :pd#15884:od#376720:bd#4096:fd#512:\ :pe#307200:oe#393040:be#8192:fe#1024:\ :pf#444516:of#700400:bf#8192:ff#1024:\ :pg#768196:og#376720:bg#8192:fg#1024:\ :ph#291346:oh#84320:bh#8192:fh#1024: # :pc#1144916:oc#0:bc#8192:fc#1024: # # IDC disks # # RL02/RB02 have 256-byte sectors, # but partitions are still in units of 512-byte sectors rb02|RB02|DEC RL02 on 730 IDC:\ :ty=removable:se#256:ns#40:nt#2:nc#512:\ :dt=old DEC:\ :pa#15884:oa#0:ba#4096:fa#1024:\ :pb#4480:ob#16000:bb#4096:fb#512:tb=swap:\ :pc#20480:oc#0:bc#4096:fc#512: rb80|RB80|DEC R80 on 730 IDC:\ :ty=winchester:ns#31:nt#14:nc#559:\ :dt=old DEC:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#33440:ob#16058:bb#8192:fb#1024:tb=swap:\ :pc#242606:oc#0:bc#8192:fc#1024:\ :pg#82080:og#49910:bg#4096:fg#512:\ :ph#192696:oh#132270:bh#8192:fh#1024: # # Disks for rk # rk06|RK06|DEC RK06:\ :ty=removable:ns#22:nt#3:nc#411:sf:\ :dt=old DEC:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#11154:ob#15906:bb#4096:fb#512:tb=swap:\ :pc#27126:oc#0:bc#4096:fc#512: # :pc#26978:oc#0:bc#4096:fc#512: rk07|RK07|DEC RK07:\ :ty=removable:ns#22:nt#3:nc#815:sf:\ :dt=old DEC:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#10032:ob#15906:bb#8192:fb#1024:tb=swap:\ :pc#53790:oc#0:bc#4096:fc#512:\ :pd#15884:od#25938:bd#4096:fd#512:\ :pf#11792:of#41844:bf#4096:ff#1024:\ :pg#27698:og#25938:bg#4096:fg#512: # :pc#53636:oc#0:bc#4096:fc#512: # # Disks normally on up # 160|fuji|fuji160|Fujitsu 160:\ :ty=winchester:ns#32:nt#10:nc#823:sf:\ :dt=SMD:d0#0:d1#1:d2#4:d3#7:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#33440:ob#16000:bb#8192:fb#1024:tb=swap:\ :pc#263360:oc#0:bc#8192:fc#1024:\ :pd#15884:od#49600:bd#4096:fd#512:\ :pe#55936:oe#65600:be#8192:fe#1024:\ :pf#141600:of#121600:bf#8192:ff#1024:\ :pg#213600:og#49600:bg#8192:fg#1024: # :pc#263200:oc#0:bc#8192:fc#1024: 9300|Ampex 9300:\ :ty=removable:ns#32:nt#19:nc#815:sf:\ :dt=SMD:d0#0:d1#1:d2#4:d3#7:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#33440:ob#16416:bb#8192:fb#1024:tb=swap:\ :pc#495520:oc#0:bc#8192:fc#1024:\ :pd#15884:od#341696:bd#4096:fd#512:\ :pe#55936:oe#358112:be#8192:fe#1024:\ :pf#81312:of#414048:bf#8192:ff#1024:\ :pg#153664:og#341696:bg#8192:fg#1024:\ :ph#291346:oh#49856:bh#8192:fh#1024: # :pc#495360:oc#0:bc#8192:fc#1024: 9766|CDC 9766:\ :ty=removable:ns#32:nt#19:nc#823:sf:\ :dt=SMD:d0#0:d1#1:d2#4:d3#7:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#33440:ob#16416:bb#8192:fb#1024:tb=swap:\ :pc#500384:oc#0:bc#8192:fc#1024:\ :pd#15884:od#341696:bd#4096:fd#512:\ :pe#55936:oe#358112:be#8192:fe#1024:\ :pf#86176:of#414048:bf#8192:ff#1024:\ :pg#158528:og#341696:bg#8192:fg#1024:\ :ph#291346:oh#49856:bh#8192:fh#1024: # :pc#500224:oc#0:bc#8192:fc#1024: 980|9762|AMPEX DM980|CDC 9762:\ :ty=removable:ns#32:nt#5:nc#823:sf:\ :dt=SMD:d0#0:d1#1:d2#4:d3#7:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#33440:ob#16000:bb#8192:fb#1024:tb=swap:\ :pc#131680:oc#0:bc#8192:fc#1024:\ :pd#15884:od#49440:bd#4096:fd#512:\ :pe#55936:oe#65440:be#8192:fe#1024:\ :pf#10080:of#121440:bf#8192:ff#1024:\ :pg#82080:og#49440:bg#8192:fg#1024: # :pc#131520:oc#0:bc#8192:fc#1024: # # Disk on a UDA50 # NOTE: new partition sizes since 4.2. # # RA60: standard use a-b-f # 4.2 compatible use a-b-d-e where 4.2 g == d; 4.2 h == e # UCB compatible use a-b-h-g where UCB h == h; UCB g == g ra60|RA60|DEC RA60 Removable:\ :ty=removable:ns#42:nt#4:nc#2382:\ :dt=MSCP:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#33440:ob#15884:bb#8192:fb#1024:tb=swap:\ :pc#400176:oc#0:bc#8192:fc#1024:\ :pd#82080:od#49324:bd#4096:fd#512:\ :pe#268772:oe#131404:be#4096:fe#512:\ :pf#350852:of#49324:bf#4096:ff#512:\ :pg#157570:og#242606:bg#4096:fg#1024:\ :ph#193282:oh#49324:bh#4096:fh#512: # # RA80: standard use a-b-g # 4.2 compatible use a-b-f-h where 4.2 g == f; 4.2 h == h # UCB compatible use a-b-e where UCB h == e ra80|RA80|DEC RA80 Winchester:\ :ty=winchester:ns#31:nt#14:nc#546:\ :dt=MSCP:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#33440:ob#15884:bb#8192:fb#1024:tb=swap:\ :pc#236964:oc#0:bc#8192:fc#1024:\ :pe#187640:oe#49324:be#4096:fe#512:\ :pf#82080:of#49324:bf#4096:ff#512:\ :pg#187054:og#49910:bg#4096:fg#1024:\ :ph#105560:oh#131404:bh#4096:fh#512: # # RA81: standard use a-b-h-g or a-b-h-d-e-f # When compiled as COMPAT_42 d-e-f are used for 4.2 compatible as: # 4.2 g == d; 4.2 h == e; 4.2 f == f ra81|RA81|DEC RA81 Winchester:\ :ty=winchester:ns#51:nt#14:nc#1248:\ :dt=MSCP:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#66880:ob#16422:bb#8192:fb#1024:tb=swap:\ :pc#891072:oc#0:bc#8192:fc#1024:\ :pd#15884:od#375564:bd#4096:fd#512:\ :pe#307200:oe#391986:be#8192:fe#1024:\ :pf#191352:of#699720:bf#8192:ff#1024:\ :pg#515508:og#375564:bg#8192:fg#1024:\ :ph#291346:oh#83538:bh#8192:fh#1024: # RACOMPAT RA81: should you need to create more of these awful partitions # When compiled as RACOMPAT d-e-f are used for 4.2 compatible as: # 4.2 g == d; 4.2 h == e; 4.2 f == f racompat81|compat_42ra81|COMPAT_42RA81|DEC COMPAT_42RA81 Winchester:\ :ty=winchester:ns#51:nt#14:nc#1248:\ :dt=MSCP:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#66880:ob#16422:bb#8192:fb#1024:tb=swap:\ :pc#891072:oc#0:bc#8192:fc#1024:\ :pd#82080:od#49324:bd#4096:fd#512:\ :pe#759668:oe#131404:be#4096:fe#512:\ :pf#478582:of#412490:bf#4096:ff#512: :pg#515508:og#375564:bg#8192:fg#1024:\ :ph#291346:oh#83538:bh#8192:fh#1024: # # UCB RA81: use a-b-h-g or a-b-h-d-e-f ucbra81|UCBRA81|DEC UCBRA81 Winchester:\ :ty=winchester:ns#51:nt#14:nc#1248:\ :dt=MSCP:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#33440:ob#15884:bb#4096:fb#512:tb=swap:\ :pc#891072:oc#0:bc#8192:fc#1024:\ :pd#15884:od#242606:bd#4096:fd#512:\ :pe#307200:oe#258490:be#8192:fe#1024:\ :pf#325382:of#565690:bf#4096:ff#512:\ :pg#648466:og#242606:bg#4096:fg#1024:\ :ph#193282:oh#49324:bh#4096:fh#512: # # RA82: standard, use a-b-h-g or a-b-h-d-e-f ra82|RA81|DEC RA82 Winchester:\ :ty=winchester:ns#57:nt#15:nc#1423:\ :dt=MSCP:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#66880:ob#16245:bb#8192:fb#1024:tb=swap:\ :pc#1216665:oc#0:bc#8192:fc#1024:\ :pd#15884:od#375345:bd#4096:fd#512:\ :pe#307200:oe#391590:be#8192:fe#1024:\ :pf#517275:of#699390:bf#8192:ff#1024:\ :pg#841320:og#375345:bg#8192:fg#1024:\ :ph#291346:oh#83790:bh#8192:fh#1024: # RA70 ra70|RA70|DEC RA70:\ :ty=winchester:ns#33:nt#11:nc#1507:\ :dt=MSCP:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#33440:ob#15972:bb#8192:fb#1024:tb=swap:\ :pc#547041:oc#0:bc#8192:fc#1024:\ :pd#15884:od#341220:bd#4096:fd#512:\ :pe#55936:oe#357192:be#8192:fe#1024:\ :pf#133584:of#413457:bf#8192:ff#1024:\ :pg#205821:og#341220:bg#8192:fg#1024:\ :ph#291346:oh#49731:bh#8192:fh#1024: # # RC25 rc25|RC25:\ :ty=winchester:ns#42:nt#4:nc#302:\ :dt=MSCP:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#10032:ob#15884:bb#8192:fb#1024:tb=swap:\ :pc#50736:oc#0:bc#8192:fc#1024:\ :pg#24820:og#25916:bg#8192:fg#1024: # # Disks on RQDX Q-bus controllers rd52|RD52|DEC RD52 on Microvax:\ :ty=winchester:ns#18:nt#7:nc#480:\ :dt=MSCP:\ :pa#15884:oa#0:ba#4096:fa#1024:\ :pb#9766:ob#15884:bb#4096:fb#512:tb=swap:\ :pc#60480:oc#0:bc#4096:fc#512:\ :pg#34830:og#25650:bg#4096:fg#512:\ # rd53|RD53|DEC RD53 on Microvax:\ :ty=winchester:ns#18:nt#8:nc#963:\ :dt=MSCP:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#33440:ob#15884:bb#4096:fb#512:tb=swap:\ :pc#138672:oc#0:bc#4096:fc#512:\ :pe#33440:oe#0:be#4096:fe#512:\ :pf#105232:of#33440:bf#4096:ff#512:\ :pg#89348:og#49324:bg#4096:fg#512: :ph#122788:oh#15884:bh#4096:fh#512:\ # rd54|RD54|DEC RD54 on Microvax:\ :ty=winchester:ns#17:nt#15:nc#1225:\ :dt=MSCP:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#33440:ob#16065:bb#8192:fb#1024:tb=swap:\ :pc#312375:oc#0:bc#8192:fc#1024:\ :pd#15884:od#49725:bd#4096:fd#512:\ :pe#55936:oe#65790:be#8192:fe#1024:\ :pf#190485:of#121890:bf#8192:ff#1024:\ :pg#262650:og#49725:bg#8192:fg#1024: # # RX02 floppy disk drives # rx02|RX02|DEC RX02:\ :ty=removable:ns#13:nt#1:nc#77:\ :dt=floppy:\ :pa#1001:oa#0:ba#4096:fa#512: ss in 0|1|2|3|4|5) umask 0 eval `echo $offset $name | awk ' { b=$1; n=$2 } END { for (i = 0; i < 16; i++) printf("/etc/mknod tty%s%x c 20 %d; \ /etc/mknodsys/vaxdist/group 444 0 12 216 4106142716 7365 wheel:*:0:root daemon:*:1:daemon kmem:*:2:root sys:*:3:root tty:*:4:root operator:*:5:root staff:*:10:root guest:*:31:root ingres:*:74:ingres tab.hp fstab.ra60oo fstab.ra80oo fstab.ra81oo fstab.rb80oo fstab.rk07oo fstab.rm03oo fstab.rm05oo fstab.rm80oo MAKEHOSTS fstab.rp06oo fstab.rp07oofstab.up7 fstab.up160mo fstab.up300mo motdspasswd30 rcdisprintcap0rc.local0 tpdissys/vaxdist/fstab.hp 444 0 12 77 4106142716 7723 /dev/hp0a:/:rw:1:1 /dev/hp0g:/usr:rw:1:3 /dev/hp0h:/mnt:rw:1:2 READMEiMAKEDEVimaketapedisktab groupfstab.hp fstab.ra60oo fstab.ra80oo fstab.ra81oo fstab.rb80oo fstab.rk07oo fstab.rm03oo fstab.rm05oo fstab.rm80oo MAKEHOSTS fstab.rp06oo fstab.rp07oofstab.up7 fstab.up160mo fstab.up300mo motdspasswd30 rcdisprintcap0rc.local0 tpdissys/vaxdist/fstab.ra60 444 0 12 77 4106142716 10064 /dev/ra0a:/:rw:1:1 /dev/ra0g:/mnt:rw:1:3 /dev/ra0h:/usr:rw:1:2 READMEiMAKEDEVimaketapedisktab groupfstab.hp fstab.ra60oo fstab.ra80oo fstab.ra81oo fstab.rb80oo fstab.rk07oo fstab.rm03oo fstab.rm05oo fstab.rm80oo MAKEHOSTS fstab.rp06oo fstab.rp07oofstab.up7 fstab.up160mo fstab.up300mo motdspasswd30 rcdisprintcap0rc.local0 tpdissys/vaxdist/fstab.ra80 444 0 12 77 4106142716 10066 /dev/ra0a:/:rw:1:1 /dev/ra0g:/mnt:rw:1:3 /dev/ra0h:/usr:rw:1:2 READMEiMAKEDEVimaketapedisktab groupfstab.hp fstab.ra60oo fstab.ra80oo fstab.ra81oo fstab.rb80oo fstab.rk07oo fstab.rm03oo fstab.rm05oo fstab.rm80oo MAKEHOSTS fstab.rp06oo fstab.rp07oofstab.up7 fstab.up160mo fstab.up300mo motdspasswd30 rcdisprintcap0rc.local0 tpdissys/vaxdist/fstab.ra81 444 0 12 77 4106142717 10070 /dev/ra0a:/:rw:1:1 /dev/ra0g:/mnt:rw:1:3 /dev/ra0h:/usr:rw:1:2 READMEiMAKEDEVimaketapedisktab groupfstab.hp fstab.ra60oo fstab.ra80oo fstab.ra81oo fstab.rb80oo fstab.rk07oo fstab.rm03oo fstab.rm05oo fstab.rm80oo MAKEHOSTS fstab.rp06oo fstab.rp07oofstab.up7 fstab.up160mo fstab.up300mo motdspasswd30 rcdisprintcap0rc.local0 tpdissys/vaxdist/fstab.rb80 444 0 12 77 4106142717 10070 /dev/rb0a:/:rw:1:1 /dev/rb0g:/mnt:rw:1:3 /dev/rb0h:/usr:rw:1:2 READMEiMAKEDEVimaketapedisktab groupfstab.hp fstab.ra60oo fstab.ra80oo fstab.ra81oo fstab.rb80oo fstab.rk07oo fstab.rm03oo fstab.rm05oo fstab.rm80oo MAKEHOSTS fstab.rp06oo fstab.rp07oofstab.up7 fstab.up160mo fstab.up300mo motdspasswd30 rcdisprintcap0rc.local0 tpdissys/vaxdist/fstab.rk07 444 0 12 157 4106142717 10117 /dev/hk0a:/:rw:1:1 /dev/hk0g:/usr:rw:1:3 /dev/hk1a:/mnt:rw:1:2 /dev/hk1g:/usr/src:rw:1:3 /dev/hk1a:/tmp:xx:1:2 disktab groupfstab.hp fstab.ra60oo fstab.ra80oo fstab.ra81oo fstab.rb80oo fstab.rk07oo fstab.rm03oo fstab.rm05oo fstab.rm80oo MAKEHOSTS fstab.rp06oo fstab.rp07oofstab.up7 fstab.up160mo fstab.up300mo motdspasswd30 rcdisprintcap0rc.local0 tpdissys/vaxdist/fstab.rm03 444 0 12 51 4106142717 10066 /dev/hp0a:/:rw:1:1 /dev/hp0g:/usr:rw:1:2 mini getisREADMEiMAKEDEVimaketapedisktab groupfstab.hp fstab.ra60oo fstab.ra80oo fstab.ra81oo fstab.rb80oo fstab.rk07oo fstab.rm03oo fstab.rm05oo fstab.rm80oo MAKEHOSTS fstab.rp06oo fstab.rp07oofstab.up7 fstab.up160mo fstab.up300mo motdspasswd30 rcdisprintcap0rc.local0 tpdissys/vaxdist/fstab.rm05 444 0 12 77 4106142717 10100 /dev/hp0a:/:rw:1:1 /dev/hp0g:/usr:rw:1:3 /dev/hp0h:/mnt:rw:1:2 READMEiMAKEDEVimaketapedisktab groupfstab.hp fstab.ra60oo fstab.ra80oo fstab.ra81oo fstab.rb80oo fstab.rk07oo fstab.rm03oo fstab.rm05oo fstab.rm80oo MAKEHOSTS fstab.rp06oo fstab.rp07oofstab.up7 fstab.up160mo fstab.up300mo motdspasswd30 rcdisprintcap0rc.local0 tpdissys/vaxdist/fstab.rm80 444 0 12 51 4106142720 10065 /dev/hp0a:/:rw:1:1 /dev/hp0g:/usr:rw:1:2 mini getisREADMEiMAKEDEVimaketapedisktab groupfstab.hp fstab.ra60oo fstab.ra80oo fstab.ra81oo fstab.rb80oo fstab.rk07oo fstab.rm03oo fstab.rm05oo fstab.rm80oo MAKEHOSTS fstab.rp06oo fstab.rp07oofstab.up7 fstab.up160mo fstab.up300mo motdspasswd30 rcdisprintcap0rc.local0 tpdissys/vaxdist/MAKEHOSTS 444 0 12 1344 4106142720 7605 #! /bin/sh -x # address search pattern to recognize local hosts LOCALADDR='^128\.32' # awk pattern for uninteresting (eg, long form) alias SKIP='/^ucb|\.berkeley\.edu$|^$/' # Special entries that don't get generated normally SPECIAL='ucbvax ucbarpa' cd ${DESTDIR}/usr/hosts # # We want to save ourselves while cleaning up. The funny sequence is to # minimize the window where the machine could crash and leave MAKEHOSTS # misplaced. # mv MAKEHOSTS .MAKEHOSTS rm -f M* mv .MAKEHOSTS MAKEHOSTS rm -f [A-LN-Za-z]* for i in `egrep "$LOCALADDR" ${DESTDIR}/etc/hosts | awk "\\$2 !~ $SKIP {print \\$2} \\$3 !~ $SKIP {print \\$3} \\$4 !~ $SKIP {print \\$4}"`; do ln -s /usr/ucb/rsh $i done for i in $SPECIAL do ln -s /usr/ucb/rsh $i done sf:\ :dt=old DEC:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#10032:ob#15906:bb#8192:fb#1024:tb=swap:\ :pc#53790:oc#0:bc#4096:fc#512:\ :pd#15884:od#25938:bd#4096:fd#512:\ :pf#11792:of#41844:bf#4096:ff#1024:\ :pg#27698:og#25938:bg#4096:fg#512: # :pc#53636:oc#0:bc#4096:fc#512: # # Dissys/vaxdist/fstab.rp06 444 0 12 51 4106142720 10066 /dev/hp0a:/:rw:1:1 /dev/hp0g:/usr:rw:1:2 mini getisREADMEiMAKEDEVimaketapedisktab groupfstab.hp fstab.ra60oo fstab.ra80oo fstab.ra81oo fstab.rb80oo fstab.rk07oo fstab.rm03oo fstab.rm05oo fstab.rm80oo MAKEHOSTS fstab.rp06oo fstab.rp07oofstab.up7 fstab.up160mo fstab.up300mo motdspasswd30 rcdisprintcap0rc.local0 tpdissys/vaxdist/fstab.rp07 444 0 12 77 4106142720 10077 /dev/hp0a:/:rw:1:1 /dev/hp0g:/mnt:rw:1:3 /dev/hp0h:/usr:rw:1:2 READMEiMAKEDEVimaketapedisktab groupfstab.hp fstab.ra60oo fstab.ra80oo fstab.ra81oo fstab.rb80oo fstab.rk07oo fstab.rm03oo fstab.rm05oo fstab.rm80oo MAKEHOSTS fstab.rp06oo fstab.rp07oofstab.up7 fstab.up160mo fstab.up300mo motdspasswd30 rcdisprintcap0rc.local0 tpdissys/vaxdist/fstab.up 444 0 12 77 4106142720 7733 /dev/up0a:/:rw:1:1 /dev/up0g:/usr:rw:1:3 /dev/up0h:/mnt:rw:1:2 READMEiMAKEDEVimaketapedisktab groupfstab.hp fstab.ra60oo fstab.ra80oo fstab.ra81oo fstab.rb80oo fstab.rk07oo fstab.rm03oo fstab.rm05oo fstab.rm80oo MAKEHOSTS fstab.rp06oo fstab.rp07oofstab.up7 fstab.up160mo fstab.up300mo motdspasswd30 rcdisprintcap0rc.local0 tpdissys/vaxdist/fstab.up160m 444 0 12 51 4106142721 10330 /dev/up0a:/:rw:1:1 /dev/up0g:/usr:rw:1:2 mini getisREADMEiMAKEDEVimaketapedisktab groupfstab.hp fstab.ra60oo fstab.ra80oo fstab.ra81oo fstab.rb80oo fstab.rk07oo fstab.rm03oo fstab.rm05oo fstab.rm80oo MAKEHOSTS fstab.rp06oo fstab.rp07oofstab.up7 fstab.up160mo fstab.up300mo motdspasswd30 rcdisprintcap0rc.local0 tpdissys/vaxdist/fstab.up300m 444 0 12 77 4106142721 10334 /dev/up0a:/:rw:1:1 /dev/up0g:/usr:rw:1:3 /dev/up0h:/mnt:rw:1:2 READMEiMAKEDEVimaketapedisktab groupfstab.hp fstab.ra60oo fstab.ra80oo fstab.ra81oo fstab.rb80oo fstab.rk07oo fstab.rm03oo fstab.rm05oo fstab.rm80oo MAKEHOSTS fstab.rp06oo fstab.rp07oofstab.up7 fstab.up160mo fstab.up300mo motdspasswd30 rcdisprintcap0rc.local0 tpdissys/vaxdist/motd 444 0 12 117 4106142721 7170 4.3 BSD UNIX #1: Fri Jun 6 19:55:29 PDT 1986 Would you like to play a game? MAKEDEVimaketapedisktab groupfstab.hp fstab.ra60oo fstab.ra80oo fstab.ra81oo fstab.rb80oo fstab.rk07oo fstab.rm03oo fstab.rm05oo fstab.rm80oo MAKEHOSTS fstab.rp06oo fstab.rp07oofstab.up7 fstab.up160mo fstab.up300mo motdspasswd30 rcdisprintcap0rc.local0 tpdissys/vaxdist/passwd 444 0 12 4020 4106142721 7543 root::0:10:Charlie &:/:/bin/csh toor::0:10:Bourne-again Superuser:/: daemon:*:1:31:The devil himself:/: operator::2:28:System &:/usr/guest/operator:/bin/csh uucp::66:1:UNIX-to-UNIX Copy:/usr/spool/uucppublic:/usr/lib/uucp/uucico nobody:*:32767:9999:Unprivileged user:/nonexistent:/dev/null notes:*:5:31:Notesfile maintainer:/usr/spool/notes:/bin/csh karels:QOrZFUGpxDUlo:6:10:Mike &:/usr/guest/karels:/bin/csh sam:Yd6H6R7ejeIP2:7:10:& Leffler:/usr/guest/sam:/bin/csh wnj:ZDjXDBwXle2gc:8:10:Bill Joy:/usr/guest/wnj:/bin/csh mckusick:6l7zMyp8dZLZU:201:10:Kirk &:/usr/guest/mckusick:/bin/csh dmr:AiInt5qKdjmHs:10:31:Dennis Ritchie:/usr/guest/dmr: ken:sq5UDrPlKj1nA:11:31:& Thompson:/usr/guest/ken: shannon:NYqgD2jjeuozk:12:31:Bill &:/usr/guest/shannon:/bin/csh peter:y5G5mbEX4HhOY:13:31:peter b. kessler:/usr/guest/peter:/bin/csh kre:vpyVBWM3ARc0.:14:31:Robert Elz:/usr/guest/kre:/bin/csh ingres:64c19dZOElp9I:267:74:& Group:/usr/ingres:/bin/csh ralph:s.EZm/wQTqbro:16:31:& Campbell:/usr/guest/ralph:/bin/csh linton:1/WWIjn5Sd8qM:19:31:Mark &:/usr/guest/linton:/bin/csh sklower:p0taJy06Qye1g:20:31:Keith &:/usr/guest/sklower:/bin/csh eric:PcEfNNJN.UHpM:22:31:& Allman:/usr/guest/eric:/usr/new/csh rrh:lj1vXnxTAPnDc:23:31:Robert R. Henry:/usr/guest/rrh:/bin/csh arnold:5vTJh54EqjZsU:25:31:Kenneth C R C &:/usr/guest/arnold:/bin/csh jkf:G6cip/I8C792U:26:31:John Foderaro:/usr/guest/jkf:/bin/csh ghg:FA/4weg1/wy2c:32:31:George Goble:/usr/guest/ghg:/bin/csh bloom:n0QtVD80F82MM:33:10:Jim &:/usr/guest/bloom:/bin/csh miriam:hnZ1ZK5H2qapE:36:10:& Amos:/usr/guest/miriam:/bin/csh kjd:ogYPQZGnihezk:37:10:Kevin Dunlap:/usr/guest/kjd:/bin/csh rwh:LReNSwE9gQF7w:38:10:Robert W. Henry:/usr/guest/rwh:/bin/csh tef:OciUqGHcs9YOw:39:31:Thomas Ferrin:/usr/guest/tef:/bin/csh van:STpwu/Ggmk78A:40:31:& Jacobson:/usr/guest/van:/bin/csh rich:uxxJaRZvgyiPg:41:31:& Hyde:/usr/guest/rich:/bin/csh jim:.6s.pzMqjyMrU:42:10:& McKie:/usr/guest/jim:/bin/csh donn:5cJ5uHclmVJKA:43:31:& Seeley:/usr/guest/donn:/bin/csh falcon:.MTZpW8TC8tqs:32766:31:Prof. Steven &:/usr/games:/usr/games/wargames bc#8192:fc#1024:\ :pd#15884:od#341696:bd#4096:fd#512:\ :pe#55936:oe#358112:be#8192:fe#1024:\ :pf#86176:of#414048:bf#8192:ff#1024:\ :pg#158528:og#341696:bg#8192:fg#1024:\ :ph#291346:oh#49856:bh#8192:fh#1024: # :pc#500224:oc#0:bc#8192:fc#1024: 980|9762|AMPEX DM980|CDC 9762:\ :ty=removable:ns#32:nt#5:nc#823:sf:\ :dt=SMD:d0#0:d1#1:d2#4:d3#7:\ :pa#15884:oa#0:ba#8192:fa#1024:\ :pb#33440:ob#16000:bb#8192:fb#1024:tb=swap:\ :pc#131680:oc#0:bc#8192:fc#1024:\ :pd#15884:od#49440:bd#4096:fd#51sys/vaxdist/rc 644 3 12 5334 4361177077 6703 HOME=/; export HOME PATH=/etc:/bin:/usr/ucb:/usr/bin; export PATH if [ -r /fastboot ] then rm -f /fastboot echo Fast boot ... skipping disk checks >/dev/console elif [ $1x = autobootx ] then echo Automatic reboot in progress... >/dev/console date >/dev/console fsck -p >/dev/console 2>&1 case $? in 0) date >/dev/console ;; 2) exit 1 ;; 4) reboot -n ;; 8) echo "Automatic reboot failed... help!" >/dev/console exit 1 ;; 12) echo "Reboot interrupted" >/dev/console exit 1 ;; *) echo "Unknown error in reboot" > /dev/console exit 1 ;; esac else date >/dev/console fi # attempt to rationally recover the passwd file if needed if [ -s /etc/ptmp ] then if [ -s /etc/passwd ] then ls -l /etc/passwd /etc/ptmp >/dev/console rm -f /etc/ptmp # should really remove the shorter else echo 'passwd file recovered from ptmp' >/dev/console mv /etc/ptmp /etc/passwd fi elif [ -r /etc/ptmp ] then echo 'removing passwd lock file' >/dev/console rm -f /etc/ptmp fi umount -a : >/etc/mtab swapon -a >/dev/console 2>&1 mount -a >/dev/console 2>&1 echo -n 'checking quotas:' >/dev/console quotacheck -a -p >/dev/console 2>&1 echo ' done.' >/dev/console quotaon -a ps -U >/dev/console 2>&1 rm -f /etc/nologin rm -f /usr/spool/uucp/LCK.* rm -f /usr/spool/uucp/STST/* chmod 666 /dev/tty[pqrs]* # set hostname, turn on network . /etc/netstart echo 'starting system logger' >/dev/console rm -f /dev/log syslogd # /etc/crash should be a symbolic link to the crash directory # if core dumps are to be saved. if [ -d /etc/crash ]; then echo 'checking for core dump... ' >/dev/console savecore /etc/crash >/dev/console 2>&1 fi echo preserving editor files >/dev/console (cd /tmp; /usr/lib/ex3.7preserve -a) echo clearing /tmp >/dev/console (cd /tmp; find . ! -name . ! -name lost+found ! -name quotas -exec rm -r {} \; ) echo -n standard daemons: >/dev/console update; echo -n ' update' >/dev/console cron; echo -n ' cron' >/dev/console accton /usr/adm/acct; echo -n ' accounting' >/dev/console echo '.' >/dev/console echo -n starting network daemons: >/dev/console # $routedflags is imported from /etc/netstart; # if $routedflags == NO, routed isn't run. if [ ${routedflags-X} != "NO" ]; then routed $routedflags; echo -n ' routed' >/dev/console fi named; echo -n ' named' >/dev/console inetd; echo -n ' inetd' >/dev/console # $rwhod is imported from /etc/netstart; # if $rwhod is set to something other than NO, rwhod is run. if [ ${rwhod-NO} != "NO" ]; then rwhod; echo -n ' rwhod' >/dev/console fi rm -f /dev/printer /usr/lib/lpd; echo -n ' printer' >/dev/console echo '.' >/dev/console sh /etc/rc.local date >/dev/console exit 0 -U >/dev/console 2>&1 rm -f /etc/nologin rm -f /usr/spool/uucp/LCK.* rm -f /usr/spool/uucp/STST/* chmod 666 /dev/tty[pqrs]* # set hostname, turn on network . /etc/netstart echo 'starting system logger' >/dev/console rm -f /dev/log syslogd # /etc/crash should be a symbolic link tosys/vaxdist/printcap 444 0 12 115 4106142721 10043 lp|local line printer:\ :lp=/dev/lp:sd=/usr/spool/lpd:lf=/usr/adm/lpd-errs: MAKEDEVimaketapedisktab groupfstab.hp fstab.ra60oo fstab.ra80oo fstab.ra81oo fstab.rb80oo fstab.rk07oo fstab.rm03oo fstab.rm05oo fstab.rm80oo MAKEHOSTS fstab.rp06oo fstab.rp07oofstab.up7 fstab.up160mo fstab.up300mo motdspasswd30 rcdisprintcap0rc.local0 tpdissys/vaxdist/rc.local 644 3 12 672 4361177141 7744 # site-specific startup actions, daemons strings /vmunix | grep UNIX >/tmp/t1 tail +2 /etc/motd >>/tmp/t1 mv /tmp/t1 /etc/motd chmod 666 /etc/motd echo -n starting local daemons: >/dev/console #if [ -f /etc/timed ]; then # timed -M & echo -n ' timed' >/dev/console #fi if [ -f /usr/lib/sendmail ]; then (cd /usr/spool/mqueue; rm -f lf*) /usr/lib/sendmail -bd -q30m; echo -n ' sendmail' >/dev/console fi echo '.' >/dev/console sswd30 rcdisprintcap0rc.local0 tpdissys/vaxdist/tp/ 755 0 12 0 4106142723 6665 sys/vaxdist/tp/copy 444 0 12 56600 4106142722 7673 Џ^2HPԀP^ =IΌ^߭VHP߭EHP[ݏ(͔ݭP͐PP%\[ HiB[HZB͐׏(͐ݏ([G5B͐׏(2(͔͐͐ݭP͌P~\[G͌͐͌͐[GA1l[11ݬ HAݬtDݬ ݬ;P[[P ^Ь[˔!P˘!P˔!Q Q QQP P˔!Q˔!QQQT!QxݬE1hթ8 ݬE1WݬBPԭ[߭-PZ1j<PPZ~ݬBPjP ^Ь[ЫYk<1$!kYPPZ<PPkjZP,!PxPkݭYPP1{x@!PPɸPYѭ Px,!PPѩP[ ЬP֬` [ PѬŏ@P@Yi UPiiAЬ ЬǏPɸPYP[ [ U[P PP<< Ь [P YX1˨HΨPPxPѭ PxPPPѩ^ԭŏ@P ݭݬ>6M;^Ь[k[2PPKP`PʏkЭP^Ь[ k[2PPKP`PʏkЭPЬ[[2PPKP`Ь[[2PPKP`Ь[ݬ ݬ[2PPKP` P^>v8POOPP<g<1xPP`C:PxPP`P֭v>==H>==ԭ==|ԭЭԭѭ1ONN 7~7խ Џ[[ ^Ь[˴ZxZPxPPP`PZQxQQQP ZP@XxZ~ 1-ЭPˏVW2GAPPVWGA+=X  hP@@H ЭP2$ˏZ~Wݭ PhhP P@@Y(@k 2P2QQP2iQQPx ZP@<2 W P WWE<2Wx ZP PxWQQP`x ZP PxWQQPWW~hP P@@Y˸˸˸P@ 2<+˸P2@P2QQPP˸<^Ь[˴ZxZPxPPCP`xZPxPP/P`PZQxQQQP ZP@YiP P@o?2ӏktЭPӏ@! iP@?H ЭP2$ЭܭԭЭPЭQ2PPQЭP2PPQRPRRQЭPЭQ2aQQPЭQ2aQQPRQRRPRPPR2XXЭPӏЭPiP@d>H ЭPЭЭPЭ(xPPЭQPݬ[JP4ЭPӏ ЭЭЭЭPЭPӏ 2XXЭPӏ@ЭPӏ_ЭPˏȏPPPЭPˏˏ4ӏ@׭ЭPЭQ2PPQЭP2PPQRPRRQЭPЭQ2aQQPЭQ2aQQPRQRRPf9ЭPˏ~ݭݭݭݭn9/:ݭ9ݭ9/ЭPݠݠ$έ~:l/$ʏk[P1 Z9//1RiP@r<[1tiP@I<H3P1P/PPP PЬP PPP P PѬ 1k<,ˏ,PPdZZk<,ˏ,PPdZZk<,ˏ,PPԭ P2xPPP$ P2zPPP P2~PPP ֭ѭѭݭݭݭx4M&Ь kЭPѬ Ѭ1P^Ь[x˴PxPPP`Pˏ˴QxQQQPYԭЭPˏQ2@24PPQ֭ЭP@4"4ox˴~ i[M˸Z)[6PЏXX[ZPZPЬ[[^Ь[x˴PxPP8P`Pˏ˴QxQQQPWY2ZW gZ$Ѭ gPѬѬݬ[DgWЧXЧX gXX gPf3ˏ~3ˏX~2$Y 3n$PY[ 1?Y x3I$2PP Ь[ЫZZЬ[x˴PxPPP`Z˸˸ Y3 x˴PPjZЪY˴PxPPɏPjZx˴PPjZӏjj3#34ЪYЪYӏj#˴P@˸P2@2PďP"˴P@˸P2@x2P(PPPPP˸˸˴2 ^Ь[ԭx˴PxPPP`Z[P˴2P@OBǏPPPPPPPPPQQQPQQP2QQPx PPIxPƏPPPxP(PQ(QQPQQxP(PPQQQQPQQ(P2QQPxPPP챭2P2PP좭2PPxPP2QxQQȏQQPj2PxPP2QxQQQP2QQP 2PxPPPjZʏj2PxPѬ  ɏjˏ2PP2PxPP2QxQQQP2QQP ЭjZӏjN$1j2~2~2~2~0+!ѭ k1!ݭ[P֭1:խ [1 2PƏPP2PP1 ݭ[P Ь[ˏ~kPP ZZZ P ^Ь[x˴PxPPzP`x˴PxPPdP`Pˏ˴QxQQQPZP PˏPP PЭ ɏ֭ЭPPЭQPЭPЭ ӏ@k ЭPȏ$ˏkPPOPVPSPgP dP [PXPO ʏkP9[8P1;["ЭPӏ@3)+ ^Ь[x˴PxPP P`x˴PxPPP`Pˏ˴QxQQQPdZZЭPӏxPﵼP`[xPPPP寮PxPP^Ь[x˴PxPPrP`Pˏ˴QxQQQPYԭЭPˏQ2@.PPQ֭ЭP@..x˴~K2@DXXӏDЩ,Щ[3˸Z[ZPZPЬ[[^Ь[x˴PxPPP`Pˏ˴QxQQQPWx˴PxPPhP`Zӏˏ,~-AЧѬѬ/ݬ[ЭPӏˏX+PxPPȬPP0ˏYˏ,XЧXPPVS$SS$$$$$$$$$$$}ˏ~-2@DVVӏD&PA)-f1l-VPˏ~A-<Z Z1Z N-!P Ь[x˴PxPP P 8-QȏQQ`Z˸P@$- ˸˸ -u˸P2@,PŏBP˸ Z ^Ь[x˴PxPPP ,QȏQQ`Zԭ[[P˴ǏBPPPPPPPPPQQQPQQjZjZ2PxPP2QPQQxPPPPxPʏPɏPѬjZ2 PPݭ[F2jPPXC,2 ~,2~2~2~2~+VjZ6ѭ J,5P֭1խ E,PЬ[k PЬ[x˴PxPPP ,QȏQQ`Z,YX˸P@+ ˸˸ +P x˴PPPjZC<Pʏ PPXXг@jX + +x˴PPPjZ<Pʏ?PPPP˴i˸P2@H+PxPPPP(PP˸$^Ь[x˴PxPPP +QȏQQ`Z+Yԭ[P(PPPPPPPPPPPPPЭ2PxPP2QQP2PPP2QPQM˴iխ έPxPPPxPP2QxQQQPP2iPxPPPPj2PPP2QQPP2jPʏ~PP2PxPPP(PP2PxPP2QQPP<PPPPPP2iPxPPxQʏQQPѬ  j2jPʏ~PP2jPP1@j92iPxPPPPjZ< 2iPxPPPPjZ)ݭ)2jPˏP~2~2~2~)2iPxPPPPjZ<Pʏ?PPPPѭ )P֭11ݭ[3P<QQP1ݭ[խ )FPЬ[k P Ь[[3˸Z[ZPZPЬ[[^Ь[x˴PxPPֳP )QȏQQ`W˴YXWxYZ[PPPѬZP)ѬZPѬ  ZPPPZPPP<dVVݭ[G1}WPxPPPPPYP1խ,PL >L&@ 2H RFra: open error, STCONra: open error, ONLINra: bad unituda%d: don't support ra%d's ra: bad partitionra: I/O error tj error: cs1=%b er=%b cs2=%b ds=%bSCTRE DVARDYIEGOCORUNSOPI DTE NEF CS FCE NSGPEFINCDPARFMTRPERMRILRILFDLTWCEPE NED NEM PGE MXF RPEORIRCLRPATBAIATAERRPIP MOL WRL EOT GCR DPRDRYSSCPESSDWNIDBTMBOTSLA recovered by retry 0123456789abcdef ^< Pʏ~PP[qP19 2 k[LP1ЭP1խԳ@ ݭݭsys/vaxdist/tp/boot 444 0 12 61044 4106142722 7662 Џ^KPԀP^(KnԃS ԃSK<L^LVE[[ LCE!GK!E PP1[1VԭЭPPP@yKfЭPPP@iKѭ\ЭZVP0Pf0f9 PQPQ0QVPxPPPPxPPPZPxPPPZV*HxPPPZȏZiݭZ[ݭ [J1$^Ь[ЬZЬ Y ߭YAPXX ѭ!ѭ ѭ J ݭJCѭ ݏY3P1ݭYPЭѭ ѭ֭ӏݭ?JaCݭݭY~PIݭJ7CX֭XXݭICI ^>)FPPPPP_yIIBݏc߭F)߭GPP+֭ЭP`I߭G߭PZݏ.ZwP,߭XI2BZ Z PЏ[YZZi Z2Џ[2YXXZZiZXiZZZȏZZ{>DP~HARH ^Ь[˔!P˘!P˔!Q Q QQP P˔!Q˔!QQQT!QxݬF1hթ8 ݬF1WݬBPԭ[߭-PZ1j<PPZ~ݬ[CPjP ^Ь[ЫYk<1$!kYPPZ<PPkjZP,!PxPkݭYPP1{x@!PPɸPYѭ Px,!PPѩP[ ЬP֬` [ PѬŏ@P@Yi PiiAЬ ЬǏPɸPYP[ [ [[P PP<< Ь [P YX1˨HΨPPxPѭ PxPPPѩ6Q<^Ь[k[2PPNP`PʏkЭP^Ь[ k[2PPNP`PʏkЭPЬ[[2PPNP`Ь[[2PPNP`Ь[ݬ ݬ[2PPNP` P^>v8PQ|QPP<g<1xP]P`B;PxPDP`P֭v> >!>H>>>ԭ>>ԭЭԭѭ1OPP 7~7խ Џ[[ ^Ь[˴ZxZPxPP]P`PZQxQQQP ZP@KXxZ~ 1-ЭPˏVW2GAPPVWGA>X  hP@AH ЭP2$ˏZ~Wݭ PhhP P@AY(@k 2P2QQP2iQQPx ZP@2 W P WWEg=2Wx ZP,PxWQQP`x ZP,PxWQQPWW~hP P@@Y˸˸˸P@ =+˸P2@P2QQPP˸<^Ь[˴ZxZPxPPP`xZPxPP{P`PZQxQQQP ZP@iYiP P@S@2ӏkЭPӏ@! iP@?H ЭP2$ЭܭԭЭPЭQ2PPQЭP2PPQRPRRQЭPЭQ2aQQPЭQ2aQQPRQRRPRPPR2XXЭPӏЭPiP@H?H ЭPЭЭPЭ(xPPЭQPݬ[JP4ЭPӏ ЭЭЭЭPЭPӏ 2XXЭPӏ@ЭPӏ_ЭPˏȏP)PPЭPˏˏ4ӏ@׭ЭPЭQ2PPQЭP2PPQRPRRQЭPЭQ2aQQPЭQ2aQQPRQRRPf:ЭPˏ~ݭݭݭݭR:/:ݭ:ݭ:/ЭPݠݠ$έ~:l/$ʏk[P1 Z://1RiP@V=[1tiP@-=H3 $1\ h 2ӏȏ$PѬѬ1L hݭg7*ЭP2QQP2QQPRQRRPЭP2fQQP2fQQPRQRRP ݭݭݭx ZP@-P12P2QQP2fQQPPíPЭP2QQP2QQPRQRRPЭP2fQQP2fQQPRQRRP2 ) PPݭݭݭ6))ʏ$Э(xPPk[n 2ӏˏPݬW61 ^ЬP[ [P@ ZjP P@6x[PxPPP`P[QxQQQPЬPPd]dk8 P PЭPӏ@ЭPЬ Q( `aЭPӏ@x [P$PЬ Q(`aЬ Ь ЭPӏ@ӏ@ȏ@ЭP2PЭQ2RPRR1qӏ@ʏ@ЭPʏ$ЭP2PЭQ2RPRØjP@5P P ^Ь[լѬlЫ PP CˏPP>P1P/PPP PЬP PPP P PѬ 1k<,ˏ,PPdZZk<,ˏ,PPdZZk<,ˏ,PPԭ P2TPP$ P2TPP P2"TPP ֭ѭѭݭݭݭ\5M&Ь kЭPѬ Ѭ1P^Ь[x˴PxPP^P`Pˏ˴QxQQQPYԭЭPˏQ2@5PPQ֭ЭP@55ox˴~ i[M˸Z)[6PЏXX[ZPZPЬ[[^Ь[x˴PxPPP`Pˏ˴QxQQQPWY2ZW gZ$Ѭ gPѬѬݬ[DgWЧXЧX gXX gPJ4ˏ~3ˏX~3$Y j4n$PY[ 1?Y \4I$2PP Ь[ЫZZЬ[x˴PxPPiP`Z˸˸ =4 x˴PPjZЪY˴PxPPɏPjZx˴PPjZӏjj3#34ЪYЪYӏj#˴P@F˸P2@3PďP"˴P@$˸P2@\3P(PPPPP˸˸˴3 ^Ь[ԭx˴PxPPDP`Z[P˴2P@BǏPPPPPPPPPQQQPQQP2QQPx PPIxPƏPPPxP(PQ(QQPQQxP(PPQQQQPQQ(P2QQPxPPP챭2P2PP좭2PPxPP2QxQQȏQQPj2PxPP2QxQQQP2QQP 2PxPPPjZʏj2PxPѬ  ɏjˏ2PP2PxPP2QxQQQP2QQP ЭjZӏjN2j2~2~2~2~1+!ѭ O2!ݭ[P֭1:խ ?2 2PƏPP2PP1 ݭ[P Ь[ˏ~kPP ZZZ P ^Ь[x˴PxPPP`x˴PxPPP`Pˏ˴QxQQQPZP PˏPP PЭ ɏ֭ЭPPЭQPЭPЭ ӏ@k ЭPȏ$ˏkPPOPVPSPgP dP [PXPO ʏkP9[8P1;["ЭPӏ@3)+ ^Ь[x˴PxPPXP`x˴PxPPBP`Pˏ˴QxQQQPdZZЭPӏxPP`[xPPPPPxPP޾^Ь[x˴PxPPᄒP`Pˏ˴QxQQQPYԭЭPˏQ2@/PPQ֭ЭP@//x˴~K2@DXXӏDЩ,Щ[3˸Z[ZPZPЬ[[^Ь[x˴PxPPP`Pˏ˴QxQQQPWx˴PxPPﴽP`Zӏˏ,~.AЧѬѬ/ݬ[ЭPӏˏX+PxPPȬPP0ˏYˏ,XЧXPPVS$SS$$$$$$$$$$$}ˏ~h.2@DVVӏD&PA .f1P.VPˏ~%.<Z Z1Z 2.!P Ь[x˴PxPPUP .QȏQQ`Z˸P@. ˸˸ .u˸P2@-PŏBP˸ Z ^Ь[x˴PxPPֻP -QȏQQ`Zԭ[[P˴ǏBPPPPPPPPPQQQPQQjZjZ2PxPP2QPQQxPPPPxPʏPɏPѬjZ2 PPݭ[F2jPPX'-2 ~,2~2~2~2~,VjZ6ѭ .-5P֭1խ )-PЬ[k PЬ[x˴PxPP9P -QȏQQ`Z-YX˸P@, ˸˸ ,P x˴PPPjZC<Pʏ PPXXг@jX , ,x˴PPPjZ<Pʏ?PPPP˴i˸P2@,,PxPPPP(PP˸$^Ь[x˴PxPP,P +QȏQQ`Z+Yԭ[P(PPPPPPPPPPPPPЭ2PxPP2QQP2PPP2QPQM˴iխ έPxPPPxPP2QxQQQPP2iPxPPPPj2PPP2QQPP2jPʏ~PP2PxPPP(PP2PxPP2QQPP<PPPPPP2iPxPPxQʏQQPѬ  j2jPʏ~PP2jPP1@j92iPxPPPPjZ< 2iPxPPPPjZ*ݭ*2jPˏP~2~2~2~g*2iPxPPPPjZ<Pʏ?PPPPѭ *P֭11ݭ[3P<QQP1ݭ[խ m*FPЬ[k P Ь[[3˸Z[ZPZPЬ[[^Ь[x˴PxPP"P )QȏQQ`W˴YXWxYZ[PPPѬZP)ѬZPѬ  ZPPPZPPP<dVVݭ[G1}WPxPPPPPYP1խ,PL >L&@ 2H RFra: open error, STCONra: open error, ONLINra: bad unituda%d: don't support ra%d's ra: bad partitionra: I/O error tj error: cs1=%b er=%b cs2=%b ds=%bSCTRE DVARDYIEGOCORUNSOPI DTE NEF CS FCE NSGPEFINCDPARFMTRPERMRILRILFDLTWCEPE NED NEM PGE MXF RPEORIRCLRPATBAIATAERRPIP MOL WRL EOT GCR DPRDRYSSCPESSDWNIDBTMBOTSLA recovered by retry 0123456789abcdef{Pլ׭ݭ<$~<&~ݭ#s P P@-$VЭP2QQP2QQPRQRRPЭP2fQQP2fQQPRQRRPլ1<&ݭY4# ЭZԭ Z֭xZZZѭبݭ# P<$PPZZZPxP԰ @g1PPP1ѭ؏gPPPӏkRPˏP~ݭ"R xحPQPQQPˏP~"" ֭ѭ1\PѬ1 @gݭݭݭx YP@,: P12P2QQP2fQQPsys/vaxdist/tp/format 444 0 12 50450 4106142723 10207 Џ^R@PԀP^mF ^A7APP;PPԭԭЭP@@X P߭ݏdݭa2~2~2~xAD7ݏ dݭ6PPPP P'ݏ dݭ̠έ^A6߭ P1$aA6ݏdݭݏdݭݏdݭݭݏ dݭ2PŏP2PPx Pݭ PݭPԭ-1(ݭ@.6ݭݭ 2PPP2QQP[2PPP2QQQP2QQP1[P2QQP[P2QQQPRQRRPR2PPRԭ; PP7PPzѭr1Gog_wW_gi7<Fԭ߭ЭP@Cݭ֭ѭ&6߭ݭa߭ݭFM=2ԭЭP@m@;=2bY~={22PPcP2PPPPTOL1==2ԭ1xPxP~2P2QQP2QQP~*=1ԭѭ 1ЭP2QPQ2P2QQP2QQPPx P~ݭ ݏQݭ]ЭP~ЭP<PP~<~߭ݭkP<L1֭ѭ <.1ݏ dݭ ݭ Ь[ЬZkjPkjPP Ь[ЬZ(V P.6(6PP<g<1xPP`K%PxPP`P֭v-d,e,VH -9,:,+ԭ,, ԭЭԭѭ1Oa5X5 7^խ Џ[[ ^Ь[˴ZxZPxPPP`PZQxQQQP ZP@XxZ~1-ЭPˏVW2G0PPVWG0/,$  hP@/H ЭP2$ˏZ~Wݭ PhhP P@/Y(@k 2P2QQP2iQQPx ZP@ 2 W P WWE+Wx ZPPxWQQP`x ZPPxWQQPWW~hP P@/Y˸˸˸P@ 6+˸P2@P2QQPP˸<^Ь[˴ZxZPxPPӶP`xZPxPP￶P`PZQxQQQP ZP@YiP P@s.2TӏkDЭPӏ@! iP@.H ЭP2$ЭܭԭЭPЭQ2PPQЭP2PPQRPRRQЭPЭQ2aQQPЭQ2aQQPRQRRPRPPR2XXЭPӏЭPiP@h-H ЭPЭЭPЭ(xPPЭQPݬ[ P4ЭPӏ ЭЭЭЭPЭPӏ 2XXЭPӏ@ЭPӏ_ЭPˏȏPPPЭPˏˏ4ӏ@׭ЭPЭQ2PPQЭP2PPQRPRRQЭPЭQ2aQQPЭQ2aQQPRQRRPf(ЭPˏ~ݭݭݭݭr()ݭ(ݭ(gЭPݠݠ$έ~ )L$ʏk[P1 Z(1RiP@v+[1tiP@M+H3P1P/PPP PЬP PPP P PѬ 1k<,ˏ,PPdZZk<,ˏ,PPdZZk<,ˏ,PPԭ P2LPP$ P2LPP P2LPP ֭ѭѭݭݭݭ|#-Ь kЭPѬ Ѭ1P ^Ь[x˴PxPPP`x˴PxPPP`Pˏ˴QxQQQPZP PˏPP PЭ ɏ֭ЭPPЭQPЭPЭ ӏ@k ЭPȏ$ˏkPPOPVPSPgP dP [PXPO ʏkP9[8P1;["ЭPӏ@3)+ ^Ь[x˴PxPP4P`x˴PxPPP`Pˏ˴QxQQQPdZZЭPӏxPݨP`[xPPPPΨPxPPﺨ$^Ь[˴Z ZP@q4X˸˸ a!nxZPxPPwP .!QȏQQ`YZPxPPPZPPih1 YZ P P P@#W˸P@ (@k$2P2QQP2gQQPx ؿP@2$V$P VVE  Vx ZP PxVQQP`x ZP PxVQQPVV~hP P@-#W˸P2@P2QQPP˸ʏk0^Ь[˴ZxZPxPPP QȏQQ`Y ZP@2ЭPP P@"Xԭ2~ӏknZPxPPPZPP@  ii Z P[dPPPPԭԭ2PPPPPPPPխ%ЭPݭݭ2~&8 ݭ[P3ݭ[1i WWWWi@ @i2PPPP?PP< Pӏ@P׭ЭP2QQP2QQPRQRRPЭP2hQQP2hQQPRQRRPЭPHݭݭݭݭTL2~<"~< ~t<~Nԭ֭ѭWW 峏 Z1<"PPk[P1e ^< Pʏ~PP[qP19 2 k[LP1ЭP1խԳ@ ݭݭݭݭ92<"~< ~W<~7 @iЭ1i WW @iˏPP+iWW iWW 1ˏP@P PP i WWP2QPQPPQQ1֭1ЭP,^Ь[˴Y YP@.XxYPxPP「P tQȏQQ`W2xPP[Pլ׭ݭ<$~<&~ݭP P@EVЭP2QQP2QQPRQRRPЭP2fQQP2fQQPRQRRPլ1<&ݭYLAЭZԭ Z֭xZZZѭبݭ2P<$PPZZZPxP԰ @g1hPPP1ѭ؏GPPPӏkRPˏP~ݭxحPQPQQPˏP~^֭ѭ1\PѬ1 @gݭݭݭx YP@vP12P2QQP2fQQPPíP2PrPhPPPPݭݭgݭ[FPg@ @gPP1lխ1,1$^Ь[x˴PxPP P QȏQQ`Z ˴P@+YP P@XЬP2QQPRQRRPЭP2hQQP2hPЭQPQRPRRQЬP2QQPPxPPPˏkPPOPLPHPDP @P 7P3P* ʏkP9jP1j;j3j)j+j^ЬP P@*[P P@ЬPPdBI* P PЭPЬ Q( `ax P PЬ Q(`aЬ Ь  ^Ь[kPxPPPPPKZ2PP<QQPEÏPZP P<~ݬkdխ6֭ ЭP Z ^Ь[P PˏPP PPPѬ Ԭԭx˴PxPPP`PxQQPZxPɏPլ  ɭ֭׭ԊxPx QQPȭPPP[PP 7 ЬPxPxPPP@`Px[QQPȏ`ЬPxPxPPלP@`Px[QQPȏ``\~ݬ^Ь[ЬZXXXX%1HPba1PO1PD ZY YYYjJjYWWWPxPYPPX XWЊYjЭP֭`~YԭYЭP֭`Wխ>G1}WPxPPPPPYP1խ,P" $tape'} else cd /nbsd/usr/src/new; eval tar cf ${tartape} \ B X ansi apl bib courier cpm dipress dsh emacs enet help \ hyper icon jove kermit mh mkmf mmdf news notes \ np100 patch pathalias rcs rn spms sumacc sunrpc \ tac tools umodem xns \ ${remote+'| $remote /usr/local/20b ">" $tape'} fi echo "Add ingres source" cd /nbsd/usr/ingres; eval tar cf ${tartape} . \ ${remote+'| $remote /usr/local/20b ">" $tape'} echo "Done, rewinding tape" $remote mt -t ${tape} rew & ll 533/udp # -for emergency broadcasts uucp 540/tcp uucpd # uucp daemon remotefs 556/tcp rfs_server rfs # Brunhoff remote filesystem ingreslock 1524/tcp ppedRH750 sys/vaxdist/inetd.conf 444 0 12 1736 4106142724 10307 # # Internet server configuration database # ftp stream tcp nowait root /etc/ftpd ftpd telnet stream tcp nowait root /etc/telnetd telnetd shell stream tcp nowait root /etc/rshd rshd login stream tcp nowait root /etc/rlogind rlogind exec stream tcp nowait root /etc/rexecd rexecd # Run as user "uucp" if you don't want uucpd's wtmp entries. #uucp stream tcp nowait root /etc/uucpd uucpd finger stream tcp nowait nobody /etc/fingerd fingerd #tftp dgram udp wait nobody /etc/tftpd tftpd comsat dgram udp wait root /etc/comsat comsat talk dgram udp wait root /etc/talkd talkd ntalk dgram udp wait root /etc/ntalkd ntalkd echo stream tcp nowait root internal discard stream tcp nowait root internal chargen stream tcp nowait root internal daytime stream tcp nowait root internal time stream tcp nowait root internal echo dgram udp wait root internal discard dgram udp wait root internal chargen dgram udp wait root internal daytime dgram udp wait root internal time dgram udp wait root internal acs enet help \ hyper icon jove sys/vaxdist/syslog.conf 444 0 12 376 4106142724 10503 *.err;kern.debug;auth.notice /dev/console kern.debug;daemon,auth.notice;*.err;mail.crit /usr/adm/messages lpr.debug /usr/adm/lpd-errs mail.debug /usr/spool/mqueue/syslog *.alert;kern.err;daemon.err operator *.alert root *.emerg * sys/vaxdist/maketape2 444 0 12 6164 4106142724 10131 #!/bin/sh # # Copyright (c) 1983 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)maketape 4.31 (Berkeley) 6/6/86 # # maketape [ 6250 | 1600 [ tapename [ remotetapemachine ] ] ] miniroot=hp0d tape=/dev/rmt12 type=1600 if [ $# -gt 0 ]; then type=$1; fi if [ $# -gt 1 ]; then tape=$2; fi tartape=$tape if [ $# -gt 2 ]; then remote=$3; tartape='-'; fi # trap "rm -f /tmp/tape.$$; exit" 0 1 2 3 13 15 #$remote mt -t ${tape} rew date #umount /dev/hp2g #umount /dev/hp2a #mount -r /dev/hp2a /c/nbsd #mount -r /dev/hp2g /c/nbsd/usr #cd tp #tp cmf /tmp/tape.$$ boot copy format #cd /nbsd/sys/mdec #echo "Build 1st level boot block file" #cat tsboot htboot tmboot mtboot utboot noboot noboot /tmp/tape.$$ | \ # $remote dd of=${tape} obs=512 conv=sync cd /nbsd sync #echo "Add dump of mini-root file system" #eval dd if=/dev/r${miniroot} count=205 bs=20b conv=sync ${remote+'|'} \ # ${remote-"of=$tape"} ${remote+'/usr/local/20b ">" $tape'} #echo "Add full dump of real file system" #/etc/${remote+r}dump 0uf $remote${remote+:}${tape} /c/nbsd #echo "Add tar image of /usr" #cd /nbsd/usr; eval tar cf ${tartape} adm bin dict doc games \ # guest hosts include lib local man mdec msgs new \ # preserve pub spool tmp ucb \ # ${remote+'| $remote /usr/local/20b ">" $tape'} #if [ ${type} != '6250' ] #then # echo "Done, rewinding first tape" # $remote mt -t ${tape} rew & # echo "Mount second tape and hit return when ready" # echo "(or type name of next tape drive)" # read x # if [ "$x" != "" ] # then tape=$x # fi #fi echo "Add tar image of system sources" cd /nbsd/sys; eval tar cf ${tartape} . \ ${remote+'| $remote /usr/local/20b ">" $tape'} echo "Add user source code" cd /nbsd/usr/src; eval tar cf ${tartape} Makefile bin etc games \ include lib local old ucb undoc usr.bin usr.lib \ ${remote+'| $remote /usr/local/20b ">" $tape'} echo "Add varian fonts" cd /usr/lib/vfont; eval tar cf ${tartape} . \ ${remote+'| $remote /usr/local/20b ">" $tape'} if [ ${type} != '6250' ] then echo "Done, rewinding second tape" $remote mt -t ${tape} rew & echo "Mount third tape and hit return when ready" echo "(or type name of next tape drive)" read x if [ "$x" != "" ] then tape=$x fi fi echo "Add user contributed software" if [ ${type} != '6250' ] then cd /nbsd/usr/src/new; eval tar cf ${tartape} \ README Makefile \ B X ansi apl bib courier cpm dipress dsh emacs enet help \ hyper icon jove kermit mh mkmf mmdf.tar.Z news notes nntp \ np100 patch pathalias rcs rn spms sumacc.tar.Z sunrpc \ tac tools umodem xns \ ${remote+'| $remote /usr/local/20b ">" $tape'} else cd /nbsd/usr/src/new; eval tar cf ${tartape} \ README Makefile \ B X ansi apl bib courier cpm dipress dsh emacs enet help \ hyper icon jove kermit mh mkmf mmdf news notes nntp \ np100 patch pathalias rcs rn spms sumacc sunrpc \ tac tools umodem xns \ ${remote+'| $remote /usr/local/20b ">" $tape'} fi echo "Add ingres source" cd /nbsd/usr/ingres; eval tar cf ${tartape} . \ ${remote+'| $remote /usr/local/20b ">" $tape'} echo "Done, rewinding tape" $remote mt -t ${tape} rew & "HI 7K `7K/K/LK2 @vL$L$L (K4L @7DL TL0JdL 7K `/K `7KRM02 with %d sectors, %d tracks, %d cylinders?  00up bad unitunknown drive typeup bad unitUnable to read bad sector table up%d not readywc=%d o=%d i_bn=%d bn=%d sys/vaxdist/netstart 444 3 12 514 4361177222 10104 #!/bin/sh - # @(#)netstart 5.2 (Berkeley) 7/16/88 routedflags=-q rwhod=NO # myname is my symbolic name # my-netmask is specified in /etc/networks # hostname=myname.my.domain ifconfig imp0 inet $hostname ifconfig ace0 inet $hostname netmask my-netmask ifconfig lo0 inet localhost route add $hostname localhost 0 hostid $hostname sys/GENERIC/ 775 0 0 0 6045336157 5625 sys/GENERIC/SPLFIX 664 0 0 1542 5520357455 6645 g/jsr pc,__spl0/s//clrb 177776/ g/jsr pc,__spl\([1-7]\)/s//movb $40*\1, 177776/ g/jsr pc,__splsoftclock/s//movb $40, 177776/ g/jsr pc,__splnet/s//movb $100, 177776/ g/jsr pc,__splimp/s//movb $240, 177776/ g/jsr pc,__splbio/s//movb $240, 177776/ g/jsr pc,__spltty/s//movb $240, 177776/ g/jsr pc,__splclock/s//movb $300, 177776/ g/jsr pc,__splhigh/s//movb $340, 177776/ g/jsr pc,_spl0/s//movb 177776,r0;clrb 177776/ g/jsr pc,_spl\([1-7]\)/s//movb 177776,r0;movb $40*\1, 177776/ g/jsr pc,_splsoftclock/s//movb 177776,r0;movb $40, 177776/ g/jsr pc,_splnet/s//movb 177776,r0;movb $100, 177776/ g/jsr pc,_splbio/s//movb 177776,r0;movb $240, 177776/ g/jsr pc,_splimp/s//movb 177776,r0;movb $240, 177776/ g/jsr pc,_spltty/s//movb 177776,r0;movb $240, 177776/ g/jsr pc,_splclock/s//movb 177776,r0;movb $300, 177776/ g/jsr pc,_splhigh/s//movb 177776,r0;movb $340, 177776/ w q /nbsd sync #echo "Add dump of mini-root file system" #eval dd if=/dev/r${miniroot} count=205 bs=20b conv=sync ${remote+'|'} \ # ${remote-"of=$tape"} ${remote+sys/GENERIC/boot.s 664 0 0 436 5320364740 7016 /* * SCCS id @(#)NONEboot.s 1.2 (Berkeley) 2/19/87 */ / The intention is for this file to be used if a boot program isn't / available for a particulare drive/controller, or the autoboot / feature isn't desired. halt = 0 .globl _doboot, hardboot _doboot: hardboot: halt / die ... il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/ioconf.c 664 0 0 711 5320364741 7305 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ioconf.c 2.0 (2.11BSD GTE) 12/24/92 */ #include "param.h" #include "systm.h" dev_t rootdev = makedev(10,0), swapdev = makedev(10,1), pipedev = makedev(10,0); dev_t dumpdev = NODEV; daddr_t dumplo = (daddr_t)512; int nulldev(); int (*dump)() = nulldev; ms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/param.c 664 0 0 6601 5350005530 7143 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)param.c 2.0 (2.11BSD GTE) 3/11/93 */ #include "../h/param.h" #include "../h/systm.h" #include "../h/buf.h" #include "../h/time.h" #include "../h/resource.h" #include "../h/proc.h" #include "../h/text.h" #include "../h/file.h" #include "../h/dir.h" #include "../h/inode.h" #include "../h/fs.h" #include "../h/mount.h" #include "../h/callout.h" #include "../h/map.h" #include "../h/clist.h" #include "../machine/seg.h" /* * System parameter formulae. * * This file is copied into each directory where we compile * the kernel; it should be modified there to suit local taste * if necessary. * */ #define MAXUSERS 4 #define NBUF 32 int hz = LINEHZ; struct timezone tz = { 480, 1 }; #define NPROC (10 + 7 * MAXUSERS) int nproc = NPROC; #define NTEXT (26 + MAXUSERS) int ntext = NTEXT; #define NINODE ((NPROC + 16 + MAXUSERS) + 22) int ninode = NINODE; #define NFILE ((8 * NINODE / 10) + 20) int nfile = NFILE; #define NCALL (16 + MAXUSERS) int ncallout = NCALL; int nbuf = NBUF; #define NCLIST (20 + 8 * MAXUSERS) #if NCLIST > (8192 / 32) /* 8K / sizeof(struct cblock) */ #undef NCLIST #define NCLIST (8192 / 32) #endif int nclist = NCLIST; /* * These have to be allocated somewhere; allocating * them here forces loader errors if this file is omitted * (if they've been externed everywhere else; hah!). */ struct proc *procNPROC; struct text *textNTEXT; struct inode inode[NINODE], *inodeNINODE; struct file *fileNFILE; struct callout callout[NCALL]; struct mount mount[NMOUNT]; struct buf buf[NBUF], bfreelist[BQUEUES]; struct bufhd bufhash[BUFHSZ]; #ifdef UCB_CLIST u_int clstdesc = ((((btoc(NCLIST*sizeof(struct cblock)))-1) << 8) | RW); int ucb_clist = 1; #else struct cblock cfree[NCLIST]; int ucb_clist = 0; #endif #define CMAPSIZ NPROC /* size of core allocation map */ #define SMAPSIZ ((9 * NPROC) / 10) /* size of swap allocation map */ struct mapent _coremap[CMAPSIZ]; struct map coremap[1] = { _coremap, &_coremap[CMAPSIZ], "coremap", }; struct mapent _swapmap[SMAPSIZ]; struct map swapmap[1] = { _swapmap, &_swapmap[SMAPSIZ], "swapmap", }; #ifdef QUOTA #include "../h/quota.h" struct BigQ { struct quota xquota[NQUOTA]; /* the quotas themselves */ struct dquot *ixdquot[NINODE]; /* 2.11 equiv of i_dquot */ struct dquot xdquot[NDQUOT]; /* the dquots themselves */ struct qhash xqhash[NQHASH]; struct dqhead xdqhash[NDQHASH]; }; QUOini() { extern struct qhash *qhash; extern struct dqhead *dqhead; quota = ((struct BigQ *)SEG5)->xquota; dquot = ((struct BigQ *)SEG5)->xdquot; qhash = ((struct BigQ *)SEG5)->xqhash; dqhead = ((struct BigQ *)SEG5)->xdqhash; ndquot = NDQUOT; nquota = NQUOTA; ix_dquot = ((struct BigQ *)SEG5)->ixdquot; dquotNDQUOT = &dquot[ndquot]; quotaNQUOTA = "a[nquota]; } #endif /* * Declarations of structures loaded last and allowed to reside in the * 0120000-140000 range (where buffers and clists are mapped). These * structures must be extern everywhere else, and the asm output of cc * is edited to move these structures from comm to bss (which is last) * (see the script :comm-to-bss). They are in capital letters so that * the edit script doesn't find some other occurrence. */ struct proc PROC[NPROC]; struct file FILE[NFILE]; struct text TEXT[NTEXT]; 00up bad unitunknown drive typeup bad unitUnable to read bad sector table up%d not readywc=%d o=%d i_bn=%d bn=%d sys/GENERIC/loop.h 664 0 0 20 5320364745 6763 #define NLOOP 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/css.h 664 0 0 17 5320364747 6612 #define NCSS 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/de.h 664 0 0 16 5320364750 6403 #define NDE 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/dh.h 664 0 0 34 5321665460 6411 #define NDH 0 #define NDM 0 KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/dn.h 664 0 0 16 5320364751 6415 #define NDN 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/dhu.h 664 0 0 17 5321665464 6603 #define NDHU 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/dhv.h 664 0 0 17 5320364752 6577 #define NDHV 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/dmc.h 664 0 0 17 5320364752 6561 #define NDMC 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/dr.h 664 0 0 16 5320364752 6422 #define NDR 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/dz.h 664 0 0 16 5320364753 6433 #define NDZ 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/ec.h 664 0 0 16 5320364753 6405 #define NEC 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/en.h 664 0 0 16 5320364753 6420 #define NEN 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/ether.h 664 0 0 21 5320364754 7122 #define NETHER 0  ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/ht.h 664 0 0 16 5320364754 6432 #define NHT 2 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/hy.h 664 0 0 16 5320364754 6437 #define NHY 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/il.h 664 0 0 16 5320364755 6424 #define NIL 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/imp.h 664 0 0 17 5320364755 6606 #define NIMP 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/cn.h 664 0 0 16 5320364755 6420 #define NKL 1 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/lp.h 664 0 0 44 5320364756 6435 #define NLP 0 #define LP_MAXCOL 132 SPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/pty.h 664 0 0 17 5320364756 6636 #define NPTY 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/qe.h 664 0 0 16 5320364757 6427 #define NQE 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/qt.h 664 0 0 16 5320364757 6446 #define NQT 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/ram.h 664 0 0 17 5320364757 6602 #define NRAM 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/rk.h 664 0 0 16 5320364760 6430 #define NRK 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/rx.h 664 0 0 16 5743412014 6440 #define NRX 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/sl.h 664 0 0 16 5320364760 6432 #define NSL 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/sri.h 664 0 0 17 5320364761 6613 #define NSRI 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/tb.h 664 0 0 16 5320364761 6422 #define NTB 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/ts.h 664 0 0 16 5320364761 6443 #define NTS 2 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/tms.h 664 0 0 40 5320364762 6616 #define NTMSCP 2 #define NTMS 2 SPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/vv.h 664 0 0 16 5320364763 6452 #define NVV 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/acc.h 664 0 0 17 5320364763 6546 #define NACC 0 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/hk.h 664 0 0 16 5320364764 6422 #define NHK 2 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/ra.h 664 0 0 66 5754565571 6441 #define NRAC 2 #define NRAD 3 /* #define RA_DUMP 1 */ ot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/rl.h 664 0 0 16 5320364766 6437 #define NRL 2 . ..KSPLFIXJboot.sIioconf.cHparam.cGloop.hF css.hE de.hID dh.hIC dn.hIB dhu.hA dhv.h@ dmc.h? dr.hI> dz.hI= ec.hI< en.hI;ether.h: ht.hI9 hy.hI8 il.hI7 imp.h6 cn.hI5 lp.hI4 pty.h3 qe.hI2 qt.hI1 ram.h0 rk.hI/ rx.hI. sl.hI- sri.h, tb.hI+ ts.hI* tms.h) vv.hI( acc.h' hk.hI& ra.hI%sys/GENERIC/br.h 664 0 0 16 5743412022 6411 #define NBR 0 br.hI# si.hI" tm.hI! xp.hI MakefileMake.sys Make.pdpubaoMake.pdpb Make.pdpmbao$ localopts.hoassym.hs.Tingres.h. init_main.oo init_sysent.o kern_acct.oo kern_clock.o, kern_exec.okern_descrip.od kern_exit.o.o kern_fork.o.o kern_mman.o.o kern_proc.o.o kern_prot.o.o , kern_sig.o.o kern_resource.od ( kern_sysctl.o  kern_subr.oosys/GENERIC/si.h 664 0 0 16 5743412010 6416 #define NSI 0 br.hI# si.hI" tm.hI! xp.hI MakefileMake.sys Make.pdpubaoMake.pdpb Make.pdpmbao$ localopts.hoassym.hs.Tingres.h. init_main.oo init_sysent.o kern_acct.oo kern_clock.o, kern_exec.okern_descrip.od kern_exit.o.o kern_fork.o.o kern_mman.o.o kern_proc.o.o kern_prot.o.o , kern_sig.o.o kern_resource.od ( kern_sysctl.o  kern_subr.oosys/GENERIC/tm.h 664 0 0 37 5320364770 6440 #define NTM 2 #define AVIVTM 1 hI" tm.hI! xp.hI MakefileMake.sys Make.pdpubaoMake.pdpb Make.pdpmbao$ localopts.hoassym.hs.Tingres.h. init_main.oo init_sysent.o kern_acct.oo kern_clock.o, kern_exec.okern_descrip.od kern_exit.o.o kern_fork.o.o kern_mman.o.o kern_proc.o.o kern_prot.o.o , kern_sig.o.o kern_resource.od ( kern_sysctl.o  kern_subr.oosys/GENERIC/xp.h 664 0 0 36 6004075066 6443 #define NXPD 2 #define NXPC 1 .hI" tm.hI! xp.hI MakefileMake.sys Make.pdpubaoMake.pdpb Make.pdpmbao$ localopts.hoassym.hs.Tingres.h. init_main.oo init_sysent.o kern_acct.oo kern_clock.o, kern_exec.okern_descrip.od kern_exit.o.o kern_fork.o.o kern_mman.o.o kern_proc.o.o kern_prot.o.o , kern_sig.o.o kern_resource.od ( kern_sysctl.o  kern_subr.oosys/GENERIC/Makefile 664 0 0 10450 5770441011 7360 OPTS=-DGENERIC # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # %W% (Berkeley) %G% # ######################################################### # Non-network, but separate I/D kernel # ######################################################### H= ../h I= /usr/include M= ../machine S= ../sys U= ../pdpuba MB= ../pdpmba DEFS= -DKERNEL ${OPTS} -I. -I${H} CFLAGS= -O ${DEFS} CPP= /lib/cpp -P ${DEFS} AS= /bin/as -V ED= /bin/ed SUB= sys pdp pdpuba pdpmba # GENERAL RULES: # scb.o MUST be loaded first, param.o MUST be loaded last, # boot.o must be loaded in the base well above 0 data. # Don't forget the "-i" flag for split I/D, use "-n" otherwise. # # CONF Non-network assembly binaries. scb.o must be first! # boot.o should be close to the end. CONF= scb.o libc_bcmp.o libc_bcopy.o libc_bzero.o libc_ffs.o \ libc_insque.o libc_ldiv.o libc_lmul.o libc_lrem.o libc_remque.o \ libc_udiv.o libc_uldiv.o libc_ulsh.o \ libc_strlen.o mch_backup.o mch_click.o mch_copy.o mch_csv.o \ mch_dump.o mch_dzpdma.o mch_profile.o mch_start.o \ mch_trap.o mch_vars.o mch_xxx.o conf.o ioconf.o boot.o BASE= br.o dh.o dhu.o dhv.o dkbad.o dr.o dz.o init_sysent.o kern_clock.o \ kern_descrip.o kern_mman.o kern_proc.o kern_sig.o kern_subr.o \ kern_synch.o lp.o machdep.o ra.o ram.o rk.o rx.o si.o \ subr_rmap.o subr_xxx.o sys_inode.o sys_pipe.o trap.o tty.o \ tty_conf.o tty_subr.o tty_tb.o tty_tty.o ufs_alloc.o ufs_bio.o \ ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_namei.o \ ufs_subr.o vm_sched.o xp.o OV1= sys_generic.o ufs_syscalls.o OV2= kern_acct.o kern_exec.o kern_exit.o kern_fork.o kern_resource.o OV3= clock.o cons.o kern_pdp.o kern_time.o \ kern_xxx.o machdep2.o quota_sys.o subr_prf.o sys_process.o \ syscalls.o ufs_mount.o OV4= hk.o init_main.o kern_prot.o tty_pty.o quota_kern.o quota_subr.o \ quota_ufs.o subr_log.o vm_swp.o vm_swap.o vm_proc.o toy.o OV5= ht.o tm.o ts.o mem.o OV6= tmscp.o ufs_disksubr.o OV7= mch_fpsim.o kern_sysctl.o ingreslock.o OV8= vm_text.o rl.o KERNOBJ=${CONF} ${BASE} ${OV1} ${OV2} ${OV3} ${OV4} ${OV5} \ ${OV6} ${OV7} ${OV8} ${OV9} ${OV10} ${OV11} ${OV12} \ ${OV13} ${OV14} ${OV15} \ vers.o param.o # param.o must be last! LD_KOBJ=${CONF} ${BASE} \ -Z ${OV1} -Z ${OV2} -Z ${OV3} -Z ${OV4} -Z ${OV5} -Z ${OV6} \ -Z ${OV7} -Z ${OV8} -Z ${OV9} -Z ${OV10} -Z ${OV11} -Z ${OV12} \ -Z ${OV13} -Z ${OV14} -Z ${OV15} -Y \ vers.o param.o all: unix unix: ${SUB} ${KERNOBJ} checksys ld -X -i -o unix ${LD_KOBJ} size unix @echo Compacting symbol table -symcompact unix @echo Compacting strings table - this will take a few minutes -strcompact unix @echo rearranging symbols -symorder ../pdp/symbols.sort unix ./checksys unix vers.o: FRC sh ../conf/newvers.sh ${CC} -c vers.c boot.o: boot.s ${CPP} boot.s > boot.i ${AS} -o boot.o boot.i rm -f boot.i param.o: ${CC} -S ${CFLAGS} param.c ${ED} - param.s < ../conf/:comm-to-bss ${AS} - -o param.o param.s rm -f param.s ioconf.o: ioconf.c ${CC} -c ${CFLAGS} ioconf.c sys pdp pdpuba pdpmba: make -f Make.$@ I=${I} H=${H} M=${M} AS="${AS}" CPP="${CPP}" \ CFLAGS="${CFLAGS}" ED="${ED}" checksys: ../conf/checksys.c ${CC} ${CFLAGS} -o $@ ../conf/checksys.c clean: rm -f unix core mklog *.o *.i assym.h genassym checksys install: install -c -o root -g kmem -m 744 unix ${DESTDIR}/unix depend: FRC for i in ${SUB}; do \ make -f Make.$$i CFLAGS="${CFLAGS}" depend; done mkdep ${CFLAGS} param.c ioconf.c ../conf/checksys.c TAGSFILE= ${S}/tags TLIST= ${H} ${I} ${N1} ${N2} ${N3} ${N4} ${N5} ${N6} ${M} ${S} ${U} ${MB} ${SS} tags: FRC rm -f ${TAGSFILE} for i in ${TLIST}; do \ (cd ${S}; /usr/ucb/ctags -a -t $$i/*.[ch]); done /usr/bin/egrep "^ASENTRY|^ENTRY" ${M}/*.s | \ /bin/sed 's;\([^:]*\):\([^(]*\)(\([^)]*\));\3 \1 /^\2(\3)$$/;' \ >> ${TAGSFILE} /usr/bin/sort -o ${TAGSFILE} ${TAGSFILE} FRC: # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. b.o tty_tty.o ufs_alloc.o ufs_bio.o \ ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_namei.o \ ufs_subr.o vm_sched.o xp.o OV1= sys_generic.o ufs_syscalls.o OV2= kern_acct.o kern_exec.o kern_exit.o kern_fork.o kersys/GENERIC/Make.sys 664 0 0 5010 5743377445 7334 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # 2.2 (2.11BSD GTE) 1994/04/13 # S= ../sys VPATH= ../sys CFILES= ${S}/init_main.c ${S}/init_sysent.c ${S}/kern_acct.c \ ${S}/kern_clock.c ${S}/kern_descrip.c ${S}/kern_exec.c \ ${S}/kern_exit.c ${S}/kern_fork.c ${S}/kern_mman.c \ ${S}/kern_proc.c ${S}/kern_prot.c ${S}/kern_resource.c \ ${S}/kern_sig.c ${S}/kern_subr.c ${S}/kern_sysctl.c \ ${S}/kern_synch.c ${S}/kern_time.c ${S}/kern_xxx.c \ ${S}/quota_sys.c ${S}/quota_kern.c ${S}/quota_ufs.c \ ${S}/quota_subr.c ${S}/subr_log.c ${S}/subr_prf.c ${S}/subr_rmap.c \ ${S}/subr_xxx.c ${S}/sys_generic.c ${S}/sys_inode.c \ ${S}/sys_kern.c ${S}/sys_pipe.c \ ${S}/ingreslock.c \ ${S}/sys_process.c ${S}/syscalls.c ${S}/tty.c ${S}/tty_conf.c \ ${S}/tty_pty.c ${S}/tty_subr.c ${S}/tty_tb.c ${S}/tty_tty.c \ ${S}/ufs_alloc.c ${S}/ufs_bio.c ${S}/ufs_bmap.c \ ${S}/ufs_dsort.c ${S}/ufs_fio.c ${S}/ufs_inode.c \ ${S}/ufs_mount.c ${S}/ufs_namei.c ${S}/ufs_subr.c \ ${S}/ufs_disksubr.c \ ${S}/ufs_syscalls.c ${S}/uipc_syscalls.c ${S}/vm_proc.c \ ${S}/vm_sched.c ${S}/vm_swap.c ${S}/vm_swp.c ${S}/vm_text.c OBJS= init_main.o init_sysent.o kern_acct.o kern_clock.o \ kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o \ kern_proc.o kern_prot.o kern_resource.o kern_sig.o kern_sysctl.o \ kern_subr.o kern_synch.o kern_time.o kern_xxx.o quota_sys.o \ quota_kern.o quota_ufs.o quota_subr.o subr_log.o subr_prf.o subr_rmap.o \ ingreslock.o \ subr_xxx.o sys_generic.o sys_inode.o sys_kern.o \ sys_pipe.o sys_process.o syscalls.o tty.o tty_conf.o tty_pty.o \ tty_subr.o tty_tb.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o \ ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o \ ufs_subr.o ufs_syscalls.o uipc_syscalls.o vm_proc.o vm_sched.o \ ufs_disksubr.o \ vm_swap.o vm_swp.o vm_text.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s all: ${OBJS} depend: mkdep -f Make.sys ${CFLAGS} ${CFILES} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. QHASH]; }; QUOini() { extern struct qhash *qhash; extern struct dqhead *dqhead; quota = ((struct BigQ *)SEG5)->xquota; dquot = ((struct BigQ *)SEG5)->xdquot; qhash = ((struct BigQ *)SEG5)->xqhash; dqhead = ((struct BigQ *)SEG5)->xdqhash; ndquot = NDQUOT; nquota = NQUOTA; ix_dquot = ((struct BigQ *)SEG5)->ixdquot; dquotNDQUOT = &dquot[ndquot]; quotaNQUOTA = "a[nquota]; } #endif /* * Declarations of structures loaded last and allowed to reside in the * 0120000-140000 range (where bsys/GENERIC/Make.pdpuba 664 0 0 2200 5320364776 7761 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # %W% (Berkeley) %G% # U= ../pdpuba VPATH= ../pdpuba CFILES= ${U}/br.c ${U}/dh.c ${U}/dn.c ${U}/dhu.c ${U}/dhv.c ${U}/dkbad.c \ ${U}/dr.c ${U}/dz.c ${U}/hk.c ${U}/ht.c ${U}/lp.c ${U}/ra.c ${U}/rk.c \ ${U}/rl.c ${U}/rx.c ${U}/si.c ${U}/tm.c ${U}/tmscp.c ${U}/ts.c ${U}/xp.c OBJS= br.o dh.o dhu.o dhv.o dkbad.o dn.o dr.o dz.o hk.o ht.o lp.o ra.o rk.o \ rl.o rx.o si.o tm.o tmscp.o ts.o xp.o dn.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s all: ${OBJS} depend: mkdep -f Make.pdpuba ${CFLAGS} ${CFILES} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. {S}/sys_process.c ${S}/syscalls.c ${S}/tty.c ${S}/tty_conf.c \ ${S}/tty_pty.c ${S}/tty_subr.c ${S}/tty_tb.c ${S}/tty_tty.c \ ${S}/ufs_alloc.c ${S}/ufs_bio.c ${S}/ufs_bmap.c \ ${S}/ufs_dsort.c ${S}/ufs_fio.c ${S}/ufs_inode.c \ ${S}/ufs_mount.c ${S}/ufs_namei.c ${S}/ufs_subr.c \ ${S}/ufs_disksubr.c \ ${S}/ufs_syscalls.c ${S}/uipc_syscalls.c ${S}/vm_proc.c \ ${S}/vm_sys/GENERIC/Make.pdp 664 0 0 5036 5757755537 7320 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # 2.0 (2.11BSD GTE) 1995/05/21 # M= ../machine VPATH= ../machine CFILES= ${M}/clock.c ${M}/conf.c ${M}/cons.c ${M}/kern_pdp.c \ ${M}/machdep.c ${M}/machdep2.c ${M}/mem.c ${M}/ram.c ${M}/trap.c COBJS= clock.o conf.o cons.o kern_pdp.o machdep.o machdep2.o mem.o \ ram.o trap.o # We compile mch_KScall here rather than in Make.pdpnet so that it gets # compiled with the right flags. This means that it gets compiled for all # kernel, but is only included in the networking kernel. As it only takes # a few seconds to compile it, it isn't worth trashing up Make.pdpnet to # compile it there. SFILES= ${M}/libc_bcmp.s ${M}/libc_bcopy.s ${M}/libc_bzero.s \ ${M}/libc_ffs.s ${M}/libc_insque.s ${M}/libc_ldiv.s \ ${M}/libc_lmul.s ${M}/libc_lrem.s ${M}/libc_remque.s \ ${M}/libc_uldiv.s ${M}/libc_ulsh.s \ ${M}/libc_strlen.s ${M}/libc_udiv.s ${M}/mch_backup.s \ ${M}/mch_click.s ${M}/mch_copy.s ${M}/mch_csv.s ${M}/mch_dump.s \ ${M}/mch_dzpdma.s ${M}/mch_fpsim.s ${M}/mch_KScall.s \ ${M}/mch_profile.s ${M}/mch_start.s ${M}/mch_trap.s \ ${M}/mch_vars.s ${M}/mch_xxx.s ${M}/scb.s ${M}/toy.s SOBJS= libc_bcmp.o libc_bcopy.o libc_bzero.o libc_ffs.o libc_insque.o \ libc_ldiv.o libc_lmul.o libc_lrem.o libc_remque.o libc_strlen.o \ libc_uldiv.o libc_ulsh.o \ libc_udiv.o mch_backup.o mch_click.o mch_copy.o mch_csv.o \ mch_dump.o mch_dzpdma.o mch_fpsim.o mch_KScall.o mch_profile.o \ mch_start.o mch_trap.o mch_vars.o mch_xxx.o scb.o toy.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s .s.o: ${CPP} $*.s | ${AS} -u -o $*.o all: assym.h ${COBJS} ${SOBJS} ../pdp/symbols.sort assym.h: genassym ./genassym > $@ genassym: ${CC} -O ${CFLAGS} ${M}/genassym.c -o $@ # it's a tab character in the sed statement below not a space. ../pdp/symbols.sort: ../pdp/symbols.raw grep -v '^#' ../pdp/symbols.raw \ | sed 's/^ //' | sort -u > ../pdp/symbols.sort depend: assym.h mkdep -f Make.pdp ${CFLAGS} ${CFILES} ${SFILES} ${M}/genassym.c # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. e VPATH= ../machine CFILES= ${M}/clock.c ${M}/conf.c ${M}/cons.c ${M}/kern_pdp.c \ ${M}/machdep.c ${M}/machdep2.c ${M}/mem.c ${M}/ram.c ${M}/trap.c COBJS= clock.o conf.o cons.o kern_pdp.o machdep.o machdep2.o mem.o \ ram.o trap.o # We compile mch_KScall here rather than in Make.pdpnet so that it gets # compiled with the right flags. This means that it gets compiled for all # kernel, but is only included in the networking kernel. As it only takes # a few seconds to compilesys/GENERIC/Make.pdpmba 664 0 0 1466 5320364776 7766 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # %W% (Berkeley) %G% # U= ../pdpmba VPATH= ../pdpmba CFILES= OBJS= .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s all: ${OBJS} depend: mkdep -f Make.pdpmba ${CFLAGS} ${CFILES} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. ke.pdpnet so that it gets # compiled with the right flags. This means that it gets compiled for all # kernel, but is only included in the networking kernel. As it only takes # a few seconds to compilesys/GENERIC/localopts.h 664 0 0 516 5320364776 10050 /* * This file is generated by the configuration script sys/conf/config. * * It contains a list the kernel options not prepended to the Makefile * as -Dxxxx commands to the compiler. MAXMEM was moved to param.h leaving * only LINEHZ and EXTERNALITIMES to be placed in localopts.h */ #define LINEHZ 60 #define EXTERNALITIMES 1 xit.o.o kern_fork.o.o kern_mman.o.o kern_proc.o.o kern_prot.o.o , kern_sig.o.o kern_resource.od ( kern_sysctl.o  kern_subr.oosys/GENERIC/ingres.h 640 0 0 22 5720307512 7266 #define NINGRES 0 .hI# si.hI" tm.hI! xp.hI MakefileMake.sys Make.pdpubaoMake.pdpb Make.pdpmbao$ localopts.hoassym.hs.Tingres.h. init_main.oo init_sysent.o kern_acct.oo kern_clock.o, kern_exec.okern_descrip.od kern_exit.o.o kern_fork.o.o kern_mman.o.o kern_proc.o.o kern_prot.o.o , kern_sig.o.o kern_resource.od ( kern_sysctl.o  kern_subr.oosys/GENERIC/version 664 0 0 3 6044624346 7232 77 @dkbad.on| dr.oI{ dz.oIz hk.oIy ht.oIxversionow lp.oIvvers.cou ra.oIt rk.oIs rl.oIr rx.oIq si.oIp tm.oIots.oIntmscp.oom<xp.oIlioconf.ok vers.ojboot.oichecksyshparam.osys/GENERIC/vers.c 664 0 0 175 6044624346 7017 char version[] = "2.11 BSD UNIX #77: Sun Oct 29 00:10:29 PDT 1995\n sms1@sms.sms.iipo.gtegsc.com:/usr/src/sys/GENERIC\n"; a.oIt rk.oIs rl.oIr rx.oIq si.oIp tm.oIots.oIntmscp.oom<xp.oIlioconf.ok vers.ojboot.oichecksyshparam.osys/vaxif/ 755 0 12 0 4332170002 5665 sys/vaxif/if_dmc.c 444 0 12 56015 3671424335 7404 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_dmc.c 7.1 (Berkeley) 6/5/86 */ #include "dmc.h" #if NDMC > 0 /* * DMC11 device driver, internet version * * Bill Nesheim * Cornell University * * Lou Salkind * New York University */ /* #define DEBUG /* for base table dump on fatal error */ #include "../machine/pte.h" #include "param.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "ioctl.h" /* must precede tty.h */ #include "tty.h" #include "protosw.h" #include "socket.h" #include "syslog.h" #include "vmmac.h" #include "errno.h" #include "../net/if.h" #include "../net/netisr.h" #include "../net/route.h" #ifdef INET #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netinet/in_var.h" #include "../netinet/ip.h" #endif #include "../vax/cpu.h" #include "../vax/mtpr.h" #include "if_uba.h" #include "if_dmc.h" #include "../vaxuba/ubareg.h" #include "../vaxuba/ubavar.h" #include "../h/time.h" #include "../h/kernel.h" int dmctimer; /* timer started? */ int dmc_timeout = 8; /* timeout value */ int dmcwatch(); /* * Driver information for auto-configuration stuff. */ int dmcprobe(), dmcattach(), dmcinit(), dmcioctl(); int dmcoutput(), dmcreset(); struct uba_device *dmcinfo[NDMC]; u_short dmcstd[] = { 0 }; struct uba_driver dmcdriver = { dmcprobe, 0, dmcattach, 0, dmcstd, "dmc", dmcinfo }; #define NRCV 7 #define NXMT 3 #define NCMDS (NRCV+NXMT+4) /* size of command queue */ #define printd if(dmcdebug)printf int dmcdebug = 0; /* error reporting intervals */ #define DMC_RPNBFS 50 #define DMC_RPDSC 1 #define DMC_RPTMO 10 #define DMC_RPDCK 10 struct dmc_command { char qp_cmd; /* command */ short qp_ubaddr; /* buffer address */ short qp_cc; /* character count || XMEM */ struct dmc_command *qp_next; /* next command on queue */ }; struct dmcbufs { int ubinfo; /* from uballoc */ short cc; /* buffer size */ short flags; /* access control */ }; #define DBUF_OURS 0 /* buffer is available */ #define DBUF_DMCS 1 /* buffer claimed by somebody */ #define DBUF_XMIT 4 /* transmit buffer */ #define DBUF_RCV 8 /* receive buffer */ /* * DMC software status per interface. * * Each interface is referenced by a network interface structure, * sc_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... * We also have, for each interface, a set of 7 UBA interface structures * for each, which * contain information about the UNIBUS resources held by the interface: * map registers, buffered data paths, etc. Information is cached in this * structure for use by the if_uba.c routines in running the interface * efficiently. */ struct dmc_softc { struct ifnet sc_if; /* network-visible interface */ struct dmcbufs sc_rbufs[NRCV]; /* receive buffer info */ struct dmcbufs sc_xbufs[NXMT]; /* transmit buffer info */ struct ifubinfo sc_ifuba; /* UNIBUS resources */ struct ifrw sc_ifr[NRCV]; /* UNIBUS receive buffer maps */ struct ifxmt sc_ifw[NXMT]; /* UNIBUS receive buffer maps */ short sc_oused; /* output buffers currently in use */ short sc_iused; /* input buffers given to DMC */ short sc_flag; /* flags */ int sc_nticks; /* seconds since last interrupt */ int sc_ubinfo; /* UBA mapping info for base table */ int sc_errors[4]; /* non-fatal error counters */ #define sc_datck sc_errors[0] #define sc_timeo sc_errors[1] #define sc_nobuf sc_errors[2] #define sc_disc sc_errors[3] /* command queue stuff */ struct dmc_command sc_cmdbuf[NCMDS]; struct dmc_command *sc_qhead; /* head of command queue */ struct dmc_command *sc_qtail; /* tail of command queue */ struct dmc_command *sc_qactive; /* command in progress */ struct dmc_command *sc_qfreeh; /* head of list of free cmd buffers */ struct dmc_command *sc_qfreet; /* tail of list of free cmd buffers */ /* end command queue stuff */ } dmc_softc[NDMC]; /* flags */ #define DMC_ALLOC 0x01 /* unibus resources allocated */ #define DMC_BMAPPED 0x02 /* base table mapped */ #define DMC_RESTART 0x04 /* software restart in progress */ #define DMC_ACTIVE 0x08 /* device active */ #define DMC_RUNNING 0x20 /* device initialized */ struct dmc_base { short d_base[128]; /* DMC base table */ } dmc_base[NDMC]; /* queue manipulation macros */ #define QUEUE_AT_HEAD(qp, head, tail) \ (qp)->qp_next = (head); \ (head) = (qp); \ if ((tail) == (struct dmc_command *) 0) \ (tail) = (head) #define QUEUE_AT_TAIL(qp, head, tail) \ if ((tail)) \ (tail)->qp_next = (qp); \ else \ (head) = (qp); \ (qp)->qp_next = (struct dmc_command *) 0; \ (tail) = (qp) #define DEQUEUE(head, tail) \ (head) = (head)->qp_next;\ if ((head) == (struct dmc_command *) 0)\ (tail) = (head) dmcprobe(reg) caddr_t reg; { register int br, cvec; register struct dmcdevice *addr = (struct dmcdevice *)reg; register int i; #ifdef lint br = 0; cvec = br; br = cvec; dmcrint(0); dmcxint(0); #endif addr->bsel1 = DMC_MCLR; for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--) ; if ((addr->bsel1 & DMC_RUN) == 0) { printf("dmcprobe: can't start device\n" ); return (0); } addr->bsel0 = DMC_RQI|DMC_IEI; /* let's be paranoid */ addr->bsel0 |= DMC_RQI|DMC_IEI; DELAY(1000000); addr->bsel1 = DMC_MCLR; for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--) ; return (1); } /* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */ dmcattach(ui) register struct uba_device *ui; { register struct dmc_softc *sc = &dmc_softc[ui->ui_unit]; sc->sc_if.if_unit = ui->ui_unit; sc->sc_if.if_name = "dmc"; sc->sc_if.if_mtu = DMCMTU; sc->sc_if.if_init = dmcinit; sc->sc_if.if_output = dmcoutput; sc->sc_if.if_ioctl = dmcioctl; sc->sc_if.if_reset = dmcreset; sc->sc_if.if_flags = IFF_POINTOPOINT; sc->sc_ifuba.iff_flags = UBA_CANTWAIT; if (dmctimer == 0) { dmctimer = 1; timeout(dmcwatch, (caddr_t) 0, hz); } if_attach(&sc->sc_if); } /* * Reset of interface after UNIBUS reset. * If interface is on specified UBA, reset its state. */ dmcreset(unit, uban) int unit, uban; { register struct uba_device *ui; register struct dmc_softc *sc = &dmc_softc[unit]; if (unit >= NDMC || (ui = dmcinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" dmc%d", unit); sc->sc_flag = 0; sc->sc_if.if_flags &= ~IFF_RUNNING; dmcinit(unit); } /* * Initialization of interface; reinitialize UNIBUS usage. */ dmcinit(unit) int unit; { register struct dmc_softc *sc = &dmc_softc[unit]; register struct uba_device *ui = dmcinfo[unit]; register struct dmcdevice *addr; register struct ifnet *ifp = &sc->sc_if; register struct ifrw *ifrw; register struct ifxmt *ifxp; register struct dmcbufs *rp; register struct dmc_command *qp; struct ifaddr *ifa; int base; int s; addr = (struct dmcdevice *)ui->ui_addr; /* * Check to see that an address has been set * (both local and destination for an address family). */ for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) if (ifa->ifa_addr.sa_family && ifa->ifa_dstaddr.sa_family) break; if (ifa == (struct ifaddr *) 0) return; if ((addr->bsel1&DMC_RUN) == 0) { printf("dmcinit: DMC not running\n"); ifp->if_flags &= ~IFF_UP; return; } /* map base table */ if ((sc->sc_flag & DMC_BMAPPED) == 0) { sc->sc_ubinfo = uballoc(ui->ui_ubanum, (caddr_t)&dmc_base[unit], sizeof (struct dmc_base), 0); sc->sc_flag |= DMC_BMAPPED; } /* initialize UNIBUS resources */ sc->sc_iused = sc->sc_oused = 0; if ((ifp->if_flags & IFF_RUNNING) == 0) { if (if_ubaminit(&sc->sc_ifuba, ui->ui_ubanum, sizeof(struct dmc_header), (int)btoc(DMCMTU), sc->sc_ifr, NRCV, sc->sc_ifw, NXMT) == 0) { printf("dmc%d: can't allocate uba resources\n", unit); ifp->if_flags &= ~IFF_UP; return; } ifp->if_flags |= IFF_RUNNING; } sc->sc_flag |= DMC_RUNNING; /* initialize buffer pool */ /* receives */ ifrw = &sc->sc_ifr[0]; for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) { rp->ubinfo = ifrw->ifrw_info & 0x3ffff; rp->cc = DMCMTU + sizeof (struct dmc_header); rp->flags = DBUF_OURS|DBUF_RCV; ifrw++; } /* transmits */ ifxp = &sc->sc_ifw[0]; for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++) { rp->ubinfo = ifxp->ifw_info & 0x3ffff; rp->cc = 0; rp->flags = DBUF_OURS|DBUF_XMIT; ifxp++; } /* set up command queues */ sc->sc_qfreeh = sc->sc_qfreet = sc->sc_qhead = sc->sc_qtail = sc->sc_qactive = (struct dmc_command *)0; /* set up free command buffer list */ for (qp = &sc->sc_cmdbuf[0]; qp < &sc->sc_cmdbuf[NCMDS]; qp++) { QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet); } /* base in */ base = sc->sc_ubinfo & 0x3ffff; dmcload(sc, DMC_BASEI, base, (base>>2) & DMC_XMEM); /* specify half duplex operation, flags tell if primary */ /* or secondary station */ if (ui->ui_flags == 0) /* use DDCMP mode in full duplex */ dmcload(sc, DMC_CNTLI, 0, 0); else if (ui->ui_flags == 1) /* use MAINTENENCE mode */ dmcload(sc, DMC_CNTLI, 0, DMC_MAINT ); else if (ui->ui_flags == 2) /* use DDCMP half duplex as primary station */ dmcload(sc, DMC_CNTLI, 0, DMC_HDPLX); else if (ui->ui_flags == 3) /* use DDCMP half duplex as secondary station */ dmcload(sc, DMC_CNTLI, 0, DMC_HDPLX | DMC_SEC); /* enable operation done interrupts */ sc->sc_flag &= ~DMC_ACTIVE; while ((addr->bsel2 & DMC_IEO) == 0) addr->bsel2 |= DMC_IEO; s = spl5(); /* queue first NRCV buffers for DMC to fill */ for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) { rp->flags |= DBUF_DMCS; dmcload(sc, DMC_READ, rp->ubinfo, (((rp->ubinfo>>2)&DMC_XMEM) | rp->cc)); sc->sc_iused++; } splx(s); } /* * Start output on interface. Get another datagram * to send from the interface queue and map it to * the interface before starting output. * * Must be called at spl 5 */ dmcstart(dev) dev_t dev; { int unit = minor(dev); register struct dmc_softc *sc = &dmc_softc[unit]; struct mbuf *m; register struct dmcbufs *rp; register int n; /* * Dequeue up to NXMT requests and map them to the UNIBUS. * If no more requests, or no dmc buffers available, just return. */ n = 0; for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++ ) { /* find an available buffer */ if ((rp->flags & DBUF_DMCS) == 0) { IF_DEQUEUE(&sc->sc_if.if_snd, m); if (m == 0) return; /* mark it dmcs */ rp->flags |= (DBUF_DMCS); /* * Have request mapped to UNIBUS for transmission * and start the output. */ rp->cc = if_ubaput(&sc->sc_ifuba, &sc->sc_ifw[n], m); rp->cc &= DMC_CCOUNT; sc->sc_oused++; dmcload(sc, DMC_WRITE, rp->ubinfo, rp->cc | ((rp->ubinfo>>2)&DMC_XMEM)); } n++; } } /* * Utility routine to load the DMC device registers. */ dmcload(sc, type, w0, w1) register struct dmc_softc *sc; int type, w0, w1; { register struct dmcdevice *addr; register int unit, sps; register struct dmc_command *qp; unit = sc - dmc_softc; addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr; sps = spl5(); /* grab a command buffer from the free list */ if ((qp = sc->sc_qfreeh) == (struct dmc_command *)0) panic("dmc command queue overflow"); DEQUEUE(sc->sc_qfreeh, sc->sc_qfreet); /* fill in requested info */ qp->qp_cmd = (type | DMC_RQI); qp->qp_ubaddr = w0; qp->qp_cc = w1; if (sc->sc_qactive) { /* command in progress */ if (type == DMC_READ) { QUEUE_AT_HEAD(qp, sc->sc_qhead, sc->sc_qtail); } else { QUEUE_AT_TAIL(qp, sc->sc_qhead, sc->sc_qtail); } } else { /* command port free */ sc->sc_qactive = qp; addr->bsel0 = qp->qp_cmd; dmcrint(unit); } splx(sps); } /* * DMC interface receiver interrupt. * Ready to accept another command, * pull one off the command queue. */ dmcrint(unit) int unit; { register struct dmc_softc *sc; register struct dmcdevice *addr; register struct dmc_command *qp; register int n; addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr; sc = &dmc_softc[unit]; if ((qp = sc->sc_qactive) == (struct dmc_command *) 0) { printf("dmc%d: dmcrint no command\n", unit); return; } while (addr->bsel0&DMC_RDYI) { addr->sel4 = qp->qp_ubaddr; addr->sel6 = qp->qp_cc; addr->bsel0 &= ~(DMC_IEI|DMC_RQI); /* free command buffer */ QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet); while (addr->bsel0 & DMC_RDYI) { /* * Can't check for RDYO here 'cause * this routine isn't reentrant! */ DELAY(5); } /* move on to next command */ if ((sc->sc_qactive = sc->sc_qhead) == (struct dmc_command *)0) break; /* all done */ /* more commands to do, start the next one */ qp = sc->sc_qactive; DEQUEUE(sc->sc_qhead, sc->sc_qtail); addr->bsel0 = qp->qp_cmd; n = RDYSCAN; while (n-- > 0) if ((addr->bsel0&DMC_RDYI) || (addr->bsel2&DMC_RDYO)) break; } if (sc->sc_qactive) { addr->bsel0 |= DMC_IEI|DMC_RQI; /* VMS does it twice !*$%@# */ addr->bsel0 |= DMC_IEI|DMC_RQI; } } /* * DMC interface transmitter interrupt. * A transfer may have completed, check for errors. * If it was a read, notify appropriate protocol. * If it was a write, pull the next one off the queue. */ dmcxint(unit) int unit; { register struct dmc_softc *sc; register struct ifnet *ifp; struct uba_device *ui = dmcinfo[unit]; struct dmcdevice *addr; struct mbuf *m; struct ifqueue *inq; int arg, pkaddr, cmd, len, s; register struct ifrw *ifrw; register struct dmcbufs *rp; register struct ifxmt *ifxp; struct dmc_header *dh; int off, resid; addr = (struct dmcdevice *)ui->ui_addr; sc = &dmc_softc[unit]; ifp = &sc->sc_if; while (addr->bsel2 & DMC_RDYO) { cmd = addr->bsel2 & 0xff; arg = addr->sel6 & 0xffff; /* reconstruct UNIBUS address of buffer returned to us */ pkaddr = ((arg&DMC_XMEM)<<2) | (addr->sel4 & 0xffff); /* release port */ addr->bsel2 &= ~DMC_RDYO; switch (cmd & 07) { case DMC_OUR: /* * A read has completed. * Pass packet to type specific * higher-level input routine. */ ifp->if_ipackets++; /* find location in dmcuba struct */ ifrw= &sc->sc_ifr[0]; for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) { if(rp->ubinfo == pkaddr) break; ifrw++; } if (rp >= &sc->sc_rbufs[NRCV]) panic("dmc rcv"); if ((rp->flags & DBUF_DMCS) == 0) printf("dmc%d: done unalloc rbuf\n", unit); len = (arg & DMC_CCOUNT) - sizeof (struct dmc_header); if (len < 0 || len > DMCMTU) { ifp->if_ierrors++; printd("dmc%d: bad rcv pkt addr 0x%x len 0x%x\n", unit, pkaddr, len); goto setup; } /* * Deal with trailer protocol: if type is trailer * get true type from first 16-bit word past data. * Remember that type was trailer by setting off. */ dh = (struct dmc_header *)ifrw->ifrw_addr; dh->dmc_type = ntohs((u_short)dh->dmc_type); #define dmcdataaddr(dh, off, type) ((type)(((caddr_t)((dh)+1)+(off)))) if (dh->dmc_type >= DMC_TRAILER && dh->dmc_type < DMC_TRAILER+DMC_NTRAILER) { off = (dh->dmc_type - DMC_TRAILER) * 512; if (off >= DMCMTU) goto setup; /* sanity */ dh->dmc_type = ntohs(*dmcdataaddr(dh, off, u_short *)); resid = ntohs(*(dmcdataaddr(dh, off+2, u_short *))); if (off + resid > len) goto setup; /* sanity */ len = off + resid; } else off = 0; if (len == 0) goto setup; /* * Pull packet off interface. Off is nonzero if * packet has trailing header; dmc_get will then * force this header information to be at the front, * but we still have to drop the type and length * which are at the front of any trailer data. */ m = if_ubaget(&sc->sc_ifuba, ifrw, len, off, ifp); if (m == 0) goto setup; if (off) { ifp = *(mtod(m, struct ifnet **)); m->m_off += 2 * sizeof (u_short); m->m_len -= 2 * sizeof (u_short); *(mtod(m, struct ifnet **)) = ifp; } switch (dh->dmc_type) { #ifdef INET case DMC_IPTYPE: schednetisr(NETISR_IP); inq = &ipintrq; break; #endif default: m_freem(m); goto setup; } s = splimp(); if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); } else IF_ENQUEUE(inq, m); splx(s); setup: /* is this needed? */ rp->ubinfo = ifrw->ifrw_info & 0x3ffff; dmcload(sc, DMC_READ, rp->ubinfo, ((rp->ubinfo >> 2) & DMC_XMEM) | rp->cc); break; case DMC_OUX: /* * A write has completed, start another * transfer if there is more data to send. */ ifp->if_opackets++; /* find associated dmcbuf structure */ ifxp = &sc->sc_ifw[0]; for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++) { if(rp->ubinfo == pkaddr) break; ifxp++; } if (rp >= &sc->sc_xbufs[NXMT]) { printf("dmc%d: bad packet address 0x%x\n", unit, pkaddr); break; } if ((rp->flags & DBUF_DMCS) == 0) printf("dmc%d: unallocated packet 0x%x\n", unit, pkaddr); /* mark buffer free */ if (ifxp->ifw_xtofree) { (void)m_freem(ifxp->ifw_xtofree); ifxp->ifw_xtofree = 0; } rp->flags &= ~DBUF_DMCS; sc->sc_oused--; sc->sc_nticks = 0; sc->sc_flag |= DMC_ACTIVE; break; case DMC_CNTLO: arg &= DMC_CNTMASK; if (arg & DMC_FATAL) { log(LOG_ERR, "dmc%d: fatal error, flags=%b\n", unit, arg, CNTLO_BITS); dmcrestart(unit); break; } /* ACCUMULATE STATISTICS */ switch(arg) { case DMC_NOBUFS: ifp->if_ierrors++; if ((sc->sc_nobuf++ % DMC_RPNBFS) == 0) goto report; break; case DMC_DISCONN: if ((sc->sc_disc++ % DMC_RPDSC) == 0) goto report; break; case DMC_TIMEOUT: if ((sc->sc_timeo++ % DMC_RPTMO) == 0) goto report; break; case DMC_DATACK: ifp->if_oerrors++; if ((sc->sc_datck++ % DMC_RPDCK) == 0) goto report; break; default: goto report; } break; report: printd("dmc%d: soft error, flags=%b\n", unit, arg, CNTLO_BITS); if ((sc->sc_flag & DMC_RESTART) == 0) { /* * kill off the dmc to get things * going again by generating a * procedure error */ sc->sc_flag |= DMC_RESTART; arg = sc->sc_ubinfo & 0x3ffff; dmcload(sc, DMC_BASEI, arg, (arg>>2)&DMC_XMEM); } break; default: printf("dmc%d: bad control %o\n", unit, cmd); break; } } dmcstart(unit); return; } /* * DMC output routine. * Encapsulate a packet of type family for the dmc. * Use trailer local net encapsulation if enough data in first * packet leaves a multiple of 512 bytes of data in remainder. */ dmcoutput(ifp, m0, dst) register struct ifnet *ifp; register struct mbuf *m0; struct sockaddr *dst; { int type, error, s; register struct mbuf *m = m0; register struct dmc_header *dh; register int off; switch (dst->sa_family) { #ifdef INET case AF_INET: off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; if ((ifp->if_flags & IFF_NOTRAILERS) == 0) if (off > 0 && (off & 0x1ff) == 0 && m->m_off >= MMINOFF + 2 * sizeof (u_short)) { type = DMC_TRAILER + (off>>9); m->m_off -= 2 * sizeof (u_short); m->m_len += 2 * sizeof (u_short); *mtod(m, u_short *) = htons((u_short)DMC_IPTYPE); *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); goto gottrailertype; } type = DMC_IPTYPE; off = 0; goto gottype; #endif case AF_UNSPEC: dh = (struct dmc_header *)dst->sa_data; type = dh->dmc_type; goto gottype; default: printf("dmc%d: can't handle af%d\n", ifp->if_unit, dst->sa_family); error = EAFNOSUPPORT; goto bad; } gottrailertype: /* * Packet to be sent as a trailer; move first packet * (control information) to end of chain. */ while (m->m_next) m = m->m_next; m->m_next = m0; m = m0->m_next; m0->m_next = 0; m0 = m; gottype: /* * Add local network header * (there is space for a uba on a vax to step on) */ if (m->m_off > MMAXOFF || MMINOFF + sizeof(struct dmc_header) > m->m_off) { m = m_get(M_DONTWAIT, MT_HEADER); if (m == 0) { error = ENOBUFS; goto bad; } m->m_next = m0; m->m_off = MMINOFF; m->m_len = sizeof (struct dmc_header); } else { m->m_off -= sizeof (struct dmc_header); m->m_len += sizeof (struct dmc_header); } dh = mtod(m, struct dmc_header *); dh->dmc_type = htons((u_short)type); /* * Queue message on interface, and start output if interface * not yet active. */ s = splimp(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); m_freem(m); splx(s); return (ENOBUFS); } IF_ENQUEUE(&ifp->if_snd, m); dmcstart(ifp->if_unit); splx(s); return (0); bad: m_freem(m0); return (error); } /* * Process an ioctl request. */ /* ARGSUSED */ dmcioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { int s = splimp(), error = 0; register struct dmc_softc *sc = &dmc_softc[ifp->if_unit]; switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; if ((ifp->if_flags & IFF_RUNNING) == 0) dmcinit(ifp->if_unit); break; case SIOCSIFDSTADDR: if ((ifp->if_flags & IFF_RUNNING) == 0) dmcinit(ifp->if_unit); break; case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_UP) == 0 && sc->sc_flag & DMC_RUNNING) { ((struct dmcdevice *) (dmcinfo[ifp->if_unit]->ui_addr))->bsel1 = DMC_MCLR; sc->sc_flag &= ~DMC_RUNNING; } else if (ifp->if_flags & IFF_UP && (sc->sc_flag & DMC_RUNNING) == 0) dmcrestart(ifp->if_unit); break; default: error = EINVAL; } splx(s); return (error); } /* * Restart after a fatal error. * Clear device and reinitialize. */ dmcrestart(unit) int unit; { register struct dmc_softc *sc = &dmc_softc[unit]; register struct uba_device *ui = dmcinfo[unit]; register struct dmcdevice *addr; register struct ifxmt *ifxp; register int i; addr = (struct dmcdevice *)ui->ui_addr; #ifdef DEBUG /* dump base table */ printf("dmc%d base table:\n", unit); for (i = 0; i < sizeof (struct dmc_base); i++) printf("%o\n" ,dmc_base[unit].d_base[i]); #endif /* * Let the DMR finish the MCLR. At 1 Mbit, it should do so * in about a max of 6.4 milliseconds with diagnostics enabled. */ addr->bsel1 = DMC_MCLR; for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--) ; /* Did the timer expire or did the DMR finish? */ if ((addr->bsel1 & DMC_RUN) == 0) { log(LOG_ERR, "dmc%d: M820 Test Failed\n", unit); return; } for (ifxp = sc->sc_ifw; ifxp < &sc->sc_ifw[NXMT]; ifxp++) { if (ifxp->ifw_xtofree) { (void) m_freem(ifxp->ifw_xtofree); ifxp->ifw_xtofree = 0; } } /* restart DMC */ dmcinit(unit); sc->sc_flag &= ~DMC_RESTART; sc->sc_if.if_collisions++; /* why not? */ } /* * Check to see that transmitted packets don't * lose interrupts. The device has to be active. */ dmcwatch() { register struct uba_device *ui; register struct dmc_softc *sc; struct dmcdevice *addr; register int i; for (i = 0; i < NDMC; i++) { sc = &dmc_softc[i]; if ((sc->sc_flag & DMC_ACTIVE) == 0) continue; if ((ui = dmcinfo[i]) == 0 || ui->ui_alive == 0) continue; if (sc->sc_oused) { sc->sc_nticks++; if (sc->sc_nticks > dmc_timeout) { sc->sc_nticks = 0; addr = (struct dmcdevice *)ui->ui_addr; log(LOG_ERR, "dmc%d hung: bsel0=%b bsel2=%b\n", i, addr->bsel0 & 0xff, DMC0BITS, addr->bsel2 & 0xff, DMC2BITS); dmcrestart(i); } } } timeout(dmcwatch, (caddr_t) 0, hz); } #endif a write, pull the next one off the queue. */ dmcxint(unit) int unit; { register struct dmc_softc *sc; register struct ifnet *ifp; struct uba_device *ui = dmcinfo[unit]; struct dmcdevice *addr; struct mbuf *m; struct ifqueue *inq; int arg, pkaddr, cmd, len, s; register struct ifrw *ifrw; register struct dmcbufs *rp; register struct ifxmt *ifxp; struct dmc_header *dh; int off, resid; addr = (struct dmcdevice *)ui->ui_addr; sc = &dmc_softc[unit]; ifp = &sc->sc_if; while (addr-sys/vaxif/if_acc.c 640 0 12 22704 4206353150 7352 /* * Copyright (c) 1982,1986,1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * %W% (Berkeley) %G% */ #include "acc.h" #if NACC > 0 /* * ACC LH/DH ARPAnet IMP interface driver. */ #include "../machine/pte.h" #include "param.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "protosw.h" #include "socket.h" #include "vmmac.h" #include "../net/if.h" #include "../netimp/if_imp.h" #include "../vax/cpu.h" #include "../vax/mtpr.h" #include "if_accreg.h" #include "if_uba.h" #include "../vaxuba/ubareg.h" #include "../vaxuba/ubavar.h" int accprobe(), accattach(), accrint(), accxint(); struct uba_device *accinfo[NACC]; u_short accstd[] = { 0 }; struct uba_driver accdriver = { accprobe, 0, accattach, 0, accstd, "acc", accinfo }; int accinit(), accoutput(), accdown(), accreset(); /* * "Lower half" of IMP interface driver. * * Each IMP interface is handled by a common module which handles * the IMP-host protocol and a hardware driver which manages the * hardware specific details of talking with the IMP. * * The hardware portion of the IMP driver handles DMA and related * management of UNIBUS resources. The IMP protocol module interprets * contents of these messages and "controls" the actions of the * hardware module during IMP resets, but not, for instance, during * UNIBUS resets. * * The two modules are coupled at "attach time", and ever after, * through the imp interface structure. Higher level protocols, * e.g. IP, interact with the IMP driver, rather than the ACC. */ struct acc_softc { struct imp_softc *acc_imp; /* data structure shared with IMP */ struct ifuba acc_ifuba; /* UNIBUS resources */ struct mbuf *acc_iq; /* input reassembly queue */ short acc_olen; /* size of last message sent */ char acc_flush; /* flush remainder of message */ } acc_softc[NACC]; /* * Reset the IMP and cause a transmitter interrupt by * performing a null DMA. */ accprobe(reg) caddr_t reg; { register int br, cvec; /* r11, r10 value-result */ register struct accdevice *addr = (struct accdevice *)reg; #ifdef lint br = 0; cvec = br; br = cvec; accrint(0); accxint(0); #endif addr->icsr = ACC_RESET; DELAY(5000); addr->ocsr = ACC_RESET; DELAY(5000); addr->ocsr = OUT_BBACK; DELAY(5000); addr->owc = 0; addr->ocsr = ACC_IE | ACC_GO; DELAY(5000); addr->ocsr = 0; if (cvec && cvec != 0x200) /* transmit -> receive */ cvec -= 4; return (1); } /* * Call the IMP module to allow it to set up its internal * state, then tie the two modules together by setting up * the back pointers to common data structures. */ accattach(ui) register struct uba_device *ui; { register struct acc_softc *sc = &acc_softc[ui->ui_unit]; register struct impcb *ip; if ((sc->acc_imp = impattach(ui->ui_driver->ud_dname, ui->ui_unit, accreset)) == 0) return; ip = &sc->acc_imp->imp_cb; ip->ic_init = accinit; ip->ic_output = accoutput; ip->ic_down = accdown; sc->acc_ifuba.ifu_flags = UBA_CANTWAIT; #ifdef notdef sc->acc_ifuba.ifu_flags |= UBA_NEEDBDP; #endif } /* * Reset interface after UNIBUS reset. * If interface is on specified uba, reset its state. */ accreset(unit, uban) int unit, uban; { register struct uba_device *ui; struct acc_softc *sc; if (unit >= NACC || (ui = accinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" acc%d", unit); sc = &acc_softc[unit]; sc->acc_imp->imp_if.if_flags &= ~IFF_RUNNING; /* must go through IMP to allow it to set state */ (*sc->acc_imp->imp_if.if_init)(sc->acc_imp->imp_if.if_unit); } /* * Initialize interface: clear recorded pending operations, * and retrieve, and initialize UNIBUS resources. Note * return value is used by IMP init routine to mark IMP * unavailable for outgoing traffic. */ accinit(unit) int unit; { register struct acc_softc *sc; register struct uba_device *ui; register struct accdevice *addr; int info; if (unit >= NACC || (ui = accinfo[unit]) == 0 || ui->ui_alive == 0) { printf("acc%d: not alive\n", unit); return (0); } sc = &acc_softc[unit]; /* * Header length is 0 since we have to passs * the IMP leader up to the protocol interpretation * routines. If we had the header length as * sizeof(struct imp_leader), then the if_ routines * would asssume we handle it on input and output. */ if ((sc->acc_imp->imp_if.if_flags & IFF_RUNNING) == 0 && if_ubainit(&sc->acc_ifuba, ui->ui_ubanum, 0, (int)btoc(IMP_RCVBUF)) == 0) { printf("acc%d: can't initialize\n", unit); sc->acc_imp->imp_if.if_flags &= ~(IFF_UP | IFF_RUNNING); return (0); } sc->acc_imp->imp_if.if_flags |= IFF_RUNNING; addr = (struct accdevice *)ui->ui_addr; /* * Reset the imp interface; * the delays are pure guesswork. */ addr->ocsr = ACC_RESET; DELAY(5000); addr->ocsr = OUT_BBACK; DELAY(5000); /* reset host master ready */ addr->ocsr = 0; if (accinputreset(addr, unit) == 0) { ui->ui_alive = 0; return (0); } /* * Put up a read. We can't restart any outstanding writes * until we're back in synch with the IMP (i.e. we've flushed * the NOOPs it throws at us). * Note: IMP_RCVBUF includes the leader. */ info = sc->acc_ifuba.ifu_r.ifrw_info; addr->iba = (u_short)info; addr->iwc = -((IMP_RCVBUF) >> 1); #ifdef LOOPBACK addr->ocsr |= OUT_BBACK; #endif addr->icsr = IN_MRDY | ACC_IE | IN_WEN | ((info & 0x30000) >> 12) | ACC_GO; return (1); } accinputreset(addr, unit) register struct accdevice *addr; register int unit; { register int i; addr->icsr = ACC_RESET; DELAY(5000); addr->icsr = IN_MRDY | IN_WEN; /* close the relay */ DELAY(10000); /* YECH!!! */ for (i = 0; i < 500; i++) { if ((addr->icsr & IN_HRDY) || (addr->icsr & (IN_RMR | IN_IMPBSY)) == 0) return (1); addr->icsr = IN_MRDY | IN_WEN; DELAY(10000); /* keep turning IN_RMR off */ } printf("acc%d: imp doesn't respond, icsr=%b\n", unit, addr->icsr, ACC_INBITS); return (0); } /* * Drop the host ready line to mark host down. */ accdown(unit) int unit; { register struct accdevice *addr; addr = (struct accdevice *)(accinfo[unit]->ui_addr); addr->ocsr = ACC_RESET; DELAY(5000); addr->ocsr = OUT_BBACK; /* reset host master ready */ return (1); } /* * Start output on an interface. */ accoutput(unit, m) int unit; struct mbuf *m; { int info; register struct acc_softc *sc = &acc_softc[unit]; register struct accdevice *addr; u_short cmd; sc->acc_olen = if_wubaput(&sc->acc_ifuba, m); /* * Have request mapped to UNIBUS for * transmission; start the output. */ if (sc->acc_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(sc->acc_ifuba.ifu_uba, sc->acc_ifuba.ifu_w.ifrw_bdp); addr = (struct accdevice *)accinfo[unit]->ui_addr; info = sc->acc_ifuba.ifu_w.ifrw_info; addr->oba = (u_short)info; addr->owc = -((sc->acc_olen + 1) >> 1); cmd = ACC_IE | OUT_ENLB | ((info & 0x30000) >> 12) | ACC_GO; #ifdef LOOPBACK cmd |= OUT_BBACK; #endif addr->ocsr = cmd; sc->acc_imp->imp_cb.ic_oactive = 1; } /* * Output interrupt handler. */ accxint(unit) int unit; { register struct acc_softc *sc = &acc_softc[unit]; register struct accdevice *addr; addr = (struct accdevice *)accinfo[unit]->ui_addr; if (sc->acc_imp->imp_cb.ic_oactive == 0) { printf("acc%d: stray xmit interrupt, csr=%b\n", unit, addr->ocsr, ACC_OUTBITS); return; } sc->acc_imp->imp_if.if_opackets++; sc->acc_imp->imp_cb.ic_oactive = 0; if (addr->ocsr & ACC_ERR) { printf("acc%d: output error, ocsr=%b, icsr=%b\n", unit, addr->ocsr, ACC_OUTBITS, addr->icsr, ACC_INBITS); sc->acc_imp->imp_if.if_oerrors++; } if (sc->acc_ifuba.ifu_xtofree) { m_freem(sc->acc_ifuba.ifu_xtofree); sc->acc_ifuba.ifu_xtofree = 0; } impstart(sc->acc_imp); } /* * Input interrupt handler */ accrint(unit) int unit; { register struct acc_softc *sc = &acc_softc[unit]; register struct accdevice *addr; struct mbuf *m; int len, info; addr = (struct accdevice *)accinfo[unit]->ui_addr; sc->acc_imp->imp_if.if_ipackets++; /* * Purge BDP; flush message if error indicated. */ if (sc->acc_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(sc->acc_ifuba.ifu_uba, sc->acc_ifuba.ifu_r.ifrw_bdp); if (addr->icsr & ACC_ERR) { printf("acc%d: input error, csr=%b\n", unit, addr->icsr, ACC_INBITS); sc->acc_imp->imp_if.if_ierrors++; sc->acc_flush = 1; } if (sc->acc_flush) { if (addr->icsr & IN_EOM) sc->acc_flush = 0; goto setup; } len = IMP_RCVBUF + (addr->iwc << 1); if (len < 0 || len > IMP_RCVBUF) { printf("acc%d: bad length=%d\n", unit, len); sc->acc_imp->imp_if.if_ierrors++; goto setup; } /* * The offset parameter is always 0 since using * trailers on the ARPAnet is insane. */ m = if_rubaget(&sc->acc_ifuba, len, 0, &sc->acc_imp->imp_if); if (m == 0) goto setup; if ((addr->icsr & IN_EOM) == 0) { if (sc->acc_iq) m_cat(sc->acc_iq, m); else sc->acc_iq = m; goto setup; } if (sc->acc_iq) { m_cat(sc->acc_iq, m); m = sc->acc_iq; sc->acc_iq = 0; } impinput(unit, m); setup: /* * Setup for next message. */ info = sc->acc_ifuba.ifu_r.ifrw_info; addr->iba = (u_short)info; addr->iwc = -((IMP_RCVBUF)>> 1); addr->icsr = IN_MRDY | ACC_IE | IN_WEN | ((info & 0x30000) >> 12) | ACC_GO; } #endif #include "../vaxuba/ubavar.h" int accprobe(), accattacsys/vaxif/if_accreg.h 444 0 12 3255 3671247421 10047 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_accreg.h 7.1 (Berkeley) 6/5/86 */ /* * ACC LH/DH-11 interface */ struct accdma { short csr; /* control and status */ short db; /* data buffer */ u_short ba; /* buss address */ short wc; /* word count */ }; struct accdevice { struct accdma input; struct accdma output; }; #define icsr input.csr #define iba input.ba #define iwc input.wc #define ocsr output.csr #define oba output.ba #define owc output.wc /* * Bits Common to both input and out CSR's */ #define ACC_ERR 0x8000 /* error present */ #define ACC_NXM 0x4000 /* non-existant memory */ #define ACC_RDY 0x0080 /* ready */ #define ACC_IE 0x0040 /* interrupt enable */ #define ACC_RESET 0x0002 /* reset interface */ #define ACC_GO 0x0001 /* start operation */ /* * Input Control Status Register */ #define IN_EOM 0x2000 /* end-of-message recieved */ #define IN_HRDY 0x0800 /* host ready */ #define IN_IMPBSY 0x0400 /* IMP not ready */ #define IN_RMR 0x0200 /* receive master ready error */ #define IN_IBF 0x0100 /* input data buffer full */ #define IN_WEN 0x0008 /* write enable */ #define IN_MRDY 0x0004 /* master ready */ #define ACC_INBITS \ "\20\20ERR\17NXM\16EOM\14HRDY\13IMPBSY\12RMR\11IBF\10RDY\7IE\ \4WEN\3MRDY\2RESET\1GO" /* * Output Control Status Register */ #define OUT_TMR 0x0200 /* transmit master ready error */ #define OUT_BBACK 0x0008 /* bus back */ #define OUT_ENLB 0x0004 /* enable last bit */ #define ACC_OUTBITS \ "\20\20ERR\17NXM\12TMR\10RDY\7IE\4BBACK\3ENLB\2RESET\1GO" ring IMP resets, but not, for instance, during * UNIBUS resets. * * The two modules are coupled at "attach time", and ever after, * through the imp interface structure. Higher level protocols, * e.g. IP, interact with the IMP driver, rather than the ACC. */ struct acc_softc { struct imp_softc *acc_imp; /* data structure shared wisys/vaxif/if_css.c 640 0 12 26523 4206113172 7415 /* * Copyright (c) 1982,1986,1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * %W% (Berkeley) %G% */ #include "css.h" #if NCSS > 0 /* * DEC/CSS IMP11-A ARPAnet IMP interface driver. * Since "imp11a" is such a mouthful, it is called * "css" after the LH/DH being called "acc". * * Configuration notes: * * As delivered from DEC/CSS, it * is addressed and vectored as two DR11-B's. This makes * Autoconfig almost IMPOSSIBLE. To make it work, the * interrupt vectors must be restrapped to make the vectors * consecutive. The 020 hole between the CSR addresses is * tolerated, althought that could be cleaned-up also. * * Additionally, the TRANSMIT side of the IMP11-A has the * lower address of the two subunits, so the vector ordering * in the CONFIG file is reversed from most other devices. * It should be: * * device css0 .... cssxint cssrint * * If you get it wrong, it will still autoconfig, but will just * sit there with RECEIVE IDLE indicated on the front panel. */ #include "param.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "protosw.h" #include "socket.h" #include "vmmac.h" #include "../machine/pte.h" #include "../net/if.h" #include "../netimp/if_imp.h" #include "../vax/cpu.h" #include "../vax/mtpr.h" #include "if_cssreg.h" #include "if_uba.h" #include "../vaxuba/ubareg.h" #include "../vaxuba/ubavar.h" int cssprobe(), cssattach(), cssrint(), cssxint(); struct uba_device *cssinfo[NCSS]; u_short cssstd[] = { 0 }; struct uba_driver cssdriver = { cssprobe, 0, cssattach, 0, cssstd, "css", cssinfo }; int cssinit(), cssoutput(), cssdown(), cssreset(); /* * "Lower half" of IMP interface driver. * * Each IMP interface is handled by a common module which handles * the IMP-host protocol and a hardware driver which manages the * hardware specific details of talking with the IMP. * * The hardware portion of the IMP driver handles DMA and related * management of UNIBUS resources. The IMP protocol module interprets * contents of these messages and "controls" the actions of the * hardware module during IMP resets, but not, for instance, during * UNIBUS resets. * * The two modules are coupled at "attach time", and ever after, * through the imp interface structure. Higher level protocols, * e.g. IP, interact with the IMP driver, rather than the CSS. */ struct css_softc { struct imp_softc *css_imp; /* pointer to IMP's imp_softc struct */ struct ifuba css_ifuba; /* UNIBUS resources */ struct mbuf *css_iq; /* input reassembly queue */ short css_olen; /* size of last message sent */ char css_flush; /* flush remainder of message */ } css_softc[NCSS]; /* * Reset the IMP and cause a transmitter interrupt by * performing a null DMA. */ cssprobe(reg) caddr_t reg; { register int br, cvec; /* r11, r10 value-result */ register struct cssdevice *addr = (struct cssdevice *)reg; #ifdef lint br = 0; cvec = br; br = cvec; cssrint(0); cssxint(0); #endif addr->css_icsr = CSS_CLR; addr->css_ocsr = CSS_CLR; DELAY(50000); addr->css_icsr = 0; addr->css_ocsr = 0; DELAY(50000); addr->css_oba = 0; addr->css_owc = -1; addr->css_ocsr = CSS_IE | CSS_GO; /* enable interrupts */ DELAY(50000); addr->css_ocsr = 0; return (1); } /* * Call the IMP module to allow it to set up its internal * state, then tie the two modules together by setting up * the back pointers to common data structures. */ cssattach(ui) register struct uba_device *ui; { register struct css_softc *sc = &css_softc[ui->ui_unit]; register struct impcb *ip; if ((sc->css_imp = impattach(ui->ui_driver->ud_dname, ui->ui_unit, cssreset)) == 0) return; ip = &sc->css_imp->imp_cb; ip->ic_init = cssinit; ip->ic_output = cssoutput; ip->ic_down = cssdown; sc->css_ifuba.ifu_flags = UBA_CANTWAIT | UBA_NEED16; #ifdef notdef sc->css_ifuba.ifu_flags |= UBA_NEEDBDP; #endif } /* * Reset interface after UNIBUS reset. * If interface is on specified uba, reset its state. */ cssreset(unit, uban) int unit, uban; { register struct uba_device *ui; register struct css_softc *sc; if (unit >= NCSS || (ui = cssinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" css%d", unit); sc = &css_softc[unit]; sc->css_imp->imp_if.if_flags &= ~IFF_RUNNING; /* must go through IMP to allow it to set state */ (*sc->css_imp->imp_if.if_init)(sc->css_imp->imp_if.if_unit); } /* * Initialize interface: clear recorded pending operations, * and retrieve, and reinitialize UNIBUS resources. */ cssinit(unit) int unit; { register struct css_softc *sc; register struct uba_device *ui; register struct cssdevice *addr; int x, info; if (unit >= NCSS || (ui = cssinfo[unit]) == 0 || ui->ui_alive == 0) { printf("css%d: not alive\n", unit); return(0); } sc = &css_softc[unit]; /* * Header length is 0 to if_ubainit since we have to pass * the IMP leader up to the protocol interpretaion * routines. If we had the deader length as * sizeof(struct imp_leader), then the if_ routines * would assume we handle it on input and output. */ if ((sc->css_imp->imp_if.if_flags & IFF_RUNNING) == 0 && if_ubainit(&sc->css_ifuba, ui->ui_ubanum, 0, (int)btoc(IMP_RCVBUF)) == 0) { printf("css%d: can't initialize\n", unit); ui->ui_alive = 0; sc->css_imp->imp_if.if_flags &= ~(IFF_UP | IFF_RUNNING); return(0); } sc->css_imp->imp_if.if_flags |= IFF_RUNNING; addr = (struct cssdevice *)ui->ui_addr; /* reset the imp interface. */ x = spl5(); addr->css_icsr = CSS_CLR; addr->css_ocsr = CSS_CLR; DELAY(100); addr->css_icsr = 0; addr->css_ocsr = 0; addr->css_icsr = IN_HRDY; /* close the relay */ DELAY(5000); splx(x); /* * This may hang if the imp isn't really there. * Will test and verify safe operation. */ x = 500; while (x-- > 0) { if ((addr->css_icsr & (IN_HRDY|IN_IMPNR)) == IN_HRDY) break; addr->css_icsr = IN_HRDY; /* close the relay */ DELAY(5000); } if (x <= 0) { printf("css%d: imp doesn't respond, icsr=%b\n", unit, CSS_INBITS, addr->css_icsr); goto down; } /* * Put up a read. We can't restart any outstanding writes * until we're back in synch with the IMP (i.e. we've flushed * the NOOPs it throws at us). * Note: IMP_RCVBUF includes the leader. */ x = spl5(); info = sc->css_ifuba.ifu_r.ifrw_info; addr->css_iba = (u_short)info; addr->css_iwc = -(IMP_RCVBUF >> 1); addr->css_icsr = IN_HRDY | CSS_IE | IN_WEN | ((info & 0x30000) >> 12) | CSS_GO; splx(x); return(1); down: ui->ui_alive = 0; return(0); } /* * Drop the host ready line to mark host down. * UNTESTED. */ cssdown(unit) int unit; { register struct cssdevice *addr; int x; addr = (struct cssdevice *)(cssinfo[unit]->ui_addr); /* reset the imp interface. */ x = spl5(); addr->css_icsr = CSS_CLR; addr->css_ocsr = CSS_CLR; DELAY(100); addr->css_icsr = 0; addr->css_ocsr = 0; splx(x); return (1); } /* * Start output on an interface. */ cssoutput(unit, m) int unit; struct mbuf *m; { int info; struct uba_device *ui = cssinfo[unit]; register struct css_softc *sc = &css_softc[unit]; register struct cssdevice *addr; sc->css_olen = if_wubaput(&sc->css_ifuba, m); /* * Have request mapped to UNIBUS for transmission. * Purge any stale data from the BDP, and start the output. */ if (sc->css_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(sc->css_ifuba.ifu_uba, sc->css_ifuba.ifu_w.ifrw_bdp); addr = (struct cssdevice *)ui->ui_addr; info = sc->css_ifuba.ifu_w.ifrw_info; addr->css_oba = (u_short)info; addr->css_owc = -((sc->css_olen + 1) >> 1); addr->css_ocsr = (u_short)(CSS_IE | OUT_ENLB | ((info & 0x30000) >> 12) | CSS_GO); sc->css_imp->imp_cb.ic_oactive = 1; } /* * Output interrupt handler. */ cssxint(unit) { register struct uba_device *ui = cssinfo[unit]; register struct css_softc *sc = &css_softc[unit]; register struct cssdevice *addr; addr = (struct cssdevice *)ui->ui_addr; if (sc->css_imp->imp_cb.ic_oactive == 0) { printf("css%d: stray output interrupt csr=%b\n", unit, addr->css_ocsr, CSS_OUTBITS); return; } sc->css_imp->imp_if.if_opackets++; sc->css_imp->imp_cb.ic_oactive = 0; if (addr->css_ocsr & CSS_ERR){ sc->css_imp->imp_if.if_oerrors++; printf("css%d: output error, ocsr=%b icsr=%b\n", unit, addr->css_ocsr, CSS_OUTBITS, addr->css_icsr, CSS_INBITS); } if (sc->css_ifuba.ifu_xtofree) { m_freem(sc->css_ifuba.ifu_xtofree); sc->css_ifuba.ifu_xtofree = 0; } impstart(sc->css_imp); } /* * Input interrupt handler */ cssrint(unit) { register struct css_softc *sc = &css_softc[unit]; register struct cssdevice *addr; struct mbuf *m; int len, info; sc->css_imp->imp_if.if_ipackets++; /* * Purge BDP; flush message if error indicated. */ addr = (struct cssdevice *)cssinfo[unit]->ui_addr; if (sc->css_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(sc->css_ifuba.ifu_uba, sc->css_ifuba.ifu_r.ifrw_bdp); if (addr->css_icsr & CSS_ERR) { printf("css%d: recv error, csr=%b\n", unit, addr->css_icsr, CSS_INBITS); sc->css_imp->imp_if.if_ierrors++; sc->css_flush = 1; } if (sc->css_flush) { if (addr->css_icsr & IN_EOM) sc->css_flush = 0; goto setup; } len = IMP_RCVBUF + (addr->css_iwc << 1); if (len < 0 || len > IMP_RCVBUF) { printf("css%d: bad length=%d\n", len); sc->css_imp->imp_if.if_ierrors++; goto setup; } /* * The offset parameter is always 0 since using * trailers on the ARPAnet is insane. */ m = if_rubaget(&sc->css_ifuba, len, 0, &sc->css_imp->imp_if); if (m == 0) goto setup; if ((addr->css_icsr & IN_EOM) == 0) { if (sc->css_iq) m_cat(sc->css_iq, m); else sc->css_iq = m; goto setup; } if (sc->css_iq) { m_cat(sc->css_iq, m); m = sc->css_iq; sc->css_iq = 0; } impinput(unit, m); setup: /* * Setup for next message. */ info = sc->css_ifuba.ifu_r.ifrw_info; addr->css_iba = (u_short)info; addr->css_iwc = - (IMP_RCVBUF >> 1); addr->css_icsr = IN_HRDY | CSS_IE | IN_WEN | ((info & 0x30000) >> 12) | CSS_GO; } #endif e == 0) { printf("css%d: not alive\n", unit); return(0); } sc = &css_softc[unit]; /* * Header length is 0 to if_ubainit since we have to pass * the IMP leader upsys/vaxif/if_cssreg.h 444 0 12 4165 3671247433 10115 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_cssreg.h 7.1 (Berkeley) 6/5/86 */ /* * DEC/CSS IMP11-A ARPAnet interface */ struct cssdma { short wc; /* word count */ u_short ba; /* bus address (low 16 bits) */ short csr; /* status register */ short db; /* data buffer*/ }; struct cssdevice { struct cssdma css_output; /* transmit DR11-B */ struct cssdma css_hole; /* unclever gap */ struct cssdma css_input; /* receive DR11-B */ }; #define css_icsr css_input.csr #define css_iba css_input.ba #define css_iwc css_input.wc #define css_ocsr css_output.csr #define css_oba css_output.ba #define css_owc css_output.wc /* * Bits Common to both input and out CSR's */ #define CSS_ERR 0x8000 /* error present */ #define CSS_NXM 0x4000 /* non-existant memory */ #define CSS_ATTN 0x2000 /* attention */ #define CSS_MAINT 0x1000 /* maintenance mode */ #define CSS_CYCLE 0x0100 /* force bus cycle */ #define CSS_RDY 0x0080 /* ready */ #define CSS_IE 0x0040 /* interrupt enable */ #define CSS_XA 0x0030 /* extended address bits */ #define CSS_CLR 0x0020 /* clear status (reset) */ #define CSS_GO 0x0001 /* start operation */ /* * Input Control Status Register */ #define IN_EOM 0x0800 /* end-of-message recieved */ #define IN_IMPNR 0x0400 /* IMP not ready */ #define IN_RLE 0x0200 /* ready line error */ #define IN_WEN 0x0008 /* write enable */ #define IN_HRDY 0x0004 /* host ready */ #define CSS_INBITS \ "\20\20ERR\17NXM\16ATTN\15MAINT\14EOM\13IMPNR\12RLE\11CYCLE\10RDY\7IE\6XBA17\5XBA16\4WE\3HRDY\2CLR\1GO" /* * Output Control Status Register */ #define OUT_TXEC 0x0008 /* tx error clear */ #define OUT_ENLB 0x0004 /* enable last bit */ #define CSS_OUTBITS \ "\20\20ERR\17NXM\16ATTN\15MAINT\11CYCLE\10RDY\7IE\6XBA17\5XBA16\4TXEC\3ENLB\2CLR\1GO" * Purge any stale data from the BDP, and start the output. */ if (sc->css_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(sc->css_ifuba.ifu_uba, sc->css_ifuba.ifu_w.ifrw_bdp); addr = (struct cssdevice *)ui->ui_addr; info = sc->css_ifuba.ifu_w.ifrw_info; addr->css_oba = (u_short)info; addr->css_owc = -((sc->css_olen + 1) >> 1); addr->css_ocsr = sys/vaxif/if_ec.c 444 0 12 55701 3671424424 7230 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_ec.c 7.1 (Berkeley) 6/5/86 */ #include "ec.h" #if NEC > 0 /* * 3Com Ethernet Controller interface */ #include "../machine/pte.h" #include "param.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "protosw.h" #include "socket.h" #include "syslog.h" #include "vmmac.h" #include "ioctl.h" #include "errno.h" #include "../net/if.h" #include "../net/netisr.h" #include "../net/route.h" #ifdef INET #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netinet/in_var.h" #include "../netinet/ip.h" #include "../netinet/if_ether.h" #endif #ifdef NS #include "../netns/ns.h" #include "../netns/ns_if.h" #endif #include "../vax/cpu.h" #include "../vax/mtpr.h" #include "if_ecreg.h" #include "if_uba.h" #include "../vaxuba/ubareg.h" #include "../vaxuba/ubavar.h" #if CLSIZE == 2 #define ECBUFSIZE 32 /* on-board memory, clusters */ #endif int ecubamem(), ecprobe(), ecattach(), ecrint(), ecxint(), eccollide(); struct uba_device *ecinfo[NEC]; u_short ecstd[] = { 0 }; struct uba_driver ecdriver = { ecprobe, 0, ecattach, 0, ecstd, "ec", ecinfo, 0, 0, 0, ecubamem }; int ecinit(),ecioctl(),ecoutput(),ecreset(); struct mbuf *ecget(); extern struct ifnet loif; /* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * es_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... * We also have, for each interface, a UBA interface structure, which * contains information about the UNIBUS resources held by the interface: * map registers, buffered data paths, etc. Information is cached in this * structure for use by the if_uba.c routines in running the interface * efficiently. */ struct ec_softc { struct arpcom es_ac; /* common Ethernet structures */ #define es_if es_ac.ac_if /* network-visible interface */ #define es_addr es_ac.ac_enaddr /* hardware Ethernet address */ struct ifuba es_ifuba; /* UNIBUS resources */ short es_mask; /* mask for current output delay */ short es_oactive; /* is output active? */ u_char *es_buf[16]; /* virtual addresses of buffers */ } ec_softc[NEC]; /* * Configure on-board memory for an interface. * Called from autoconfig and after a uba reset. * The address of the memory on the uba is supplied in the device flags. */ ecubamem(ui, uban) register struct uba_device *ui; { register caddr_t ecbuf = (caddr_t) &umem[uban][ui->ui_flags]; register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr; /* * Make sure csr is there (we run before ecprobe). */ if (badaddr((caddr_t)addr, 2)) return (-1); #if VAX780 if (cpu == VAX_780 && uba_hd[uban].uh_uba->uba_sr) { uba_hd[uban].uh_uba->uba_sr = uba_hd[uban].uh_uba->uba_sr; return (-1); } #endif /* * Make sure memory is turned on */ addr->ec_rcr = EC_AROM; /* * Tell the system that the board has memory here, so it won't * attempt to allocate the addresses later. */ if (ubamem(uban, ui->ui_flags, ECBUFSIZE*CLSIZE, 1) == 0) { printf("ec%d: cannot reserve uba addresses\n", ui->ui_unit); addr->ec_rcr = EC_MDISAB; /* disable memory */ return (-1); } /* * Check for existence of buffers on Unibus. */ if (badaddr((caddr_t)ecbuf, 2)) { bad: printf("ec%d: buffer mem not found\n", ui->ui_unit); (void) ubamem(uban, ui->ui_flags, ECBUFSIZE*2, 0); addr->ec_rcr = EC_MDISAB; /* disable memory */ return (-1); } #if VAX780 if (cpu == VAX_780 && uba_hd[uban].uh_uba->uba_sr) { uba_hd[uban].uh_uba->uba_sr = uba_hd[uban].uh_uba->uba_sr; goto bad; } #endif if (ui->ui_alive == 0) /* Only printf from autoconfig */ printf("ec%d: mem %x-%x\n", ui->ui_unit, ui->ui_flags, ui->ui_flags + ECBUFSIZE*CLBYTES - 1); ui->ui_type = 1; /* Memory on, allocated */ return (0); } /* * Do output DMA to determine interface presence and * interrupt vector. DMA is too short to disturb other hosts. */ ecprobe(reg, ui) caddr_t reg; struct uba_device *ui; { register int br, cvec; /* r11, r10 value-result */ register struct ecdevice *addr = (struct ecdevice *)reg; register caddr_t ecbuf = (caddr_t) &umem[ui->ui_ubanum][ui->ui_flags]; #ifdef lint br = 0; cvec = br; br = cvec; ecrint(0); ecxint(0); eccollide(0); #endif /* * Check that buffer memory was found and enabled. */ if (ui->ui_type == 0) return(0); /* * Make a one byte packet in what should be buffer #0. * Submit it for sending. This should cause an xmit interrupt. * The xmit interrupt vector is 8 bytes after the receive vector, * so adjust for this before returning. */ *(u_short *)ecbuf = (u_short) 03777; ecbuf[03777] = '\0'; addr->ec_xcr = EC_XINTEN|EC_XWBN; DELAY(100000); addr->ec_xcr = EC_XCLR; if (cvec > 0 && cvec != 0x200) { if (cvec & 04) { /* collision interrupt */ cvec -= 04; br += 1; /* rcv is collision + 1 */ } else { /* xmit interrupt */ cvec -= 010; br += 2; /* rcv is xmit + 2 */ } } return (1); } /* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */ ecattach(ui) struct uba_device *ui; { struct ec_softc *es = &ec_softc[ui->ui_unit]; register struct ifnet *ifp = &es->es_if; register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr; int i, j; u_char *cp; ifp->if_unit = ui->ui_unit; ifp->if_name = "ec"; ifp->if_mtu = ETHERMTU; /* * Read the ethernet address off the board, one nibble at a time. */ addr->ec_xcr = EC_UECLR; /* zero address pointer */ addr->ec_rcr = EC_AROM; cp = es->es_addr; #define NEXTBIT addr->ec_rcr = EC_AROM|EC_ASTEP; addr->ec_rcr = EC_AROM for (i=0; i < sizeof (es->es_addr); i++) { *cp = 0; for (j=0; j<=4; j+=4) { *cp |= ((addr->ec_rcr >> 8) & 0xf) << j; NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT; } cp++; } printf("ec%d: hardware address %s\n", ui->ui_unit, ether_sprintf(es->es_addr)); ifp->if_init = ecinit; ifp->if_ioctl = ecioctl; ifp->if_output = ecoutput; ifp->if_reset = ecreset; ifp->if_flags = IFF_BROADCAST; for (i=0; i<16; i++) es->es_buf[i] = (u_char *)&umem[ui->ui_ubanum][ui->ui_flags + 2048*i]; if_attach(ifp); } /* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */ ecreset(unit, uban) int unit, uban; { register struct uba_device *ui; if (unit >= NEC || (ui = ecinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" ec%d", unit); ec_softc[unit].es_if.if_flags &= ~IFF_RUNNING; ecinit(unit); } /* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */ ecinit(unit) int unit; { struct ec_softc *es = &ec_softc[unit]; struct ecdevice *addr; register struct ifnet *ifp = &es->es_if; int i, s; /* not yet, if address still unknown */ if (ifp->if_addrlist == (struct ifaddr *)0) return; /* * Hang receive buffers and start any pending writes. * Writing into the rcr also makes sure the memory * is turned on. */ if ((ifp->if_flags & IFF_RUNNING) == 0) { addr = (struct ecdevice *)ecinfo[unit]->ui_addr; s = splimp(); /* * write our ethernet address into the address recognition ROM * so we can always use the same EC_READ bits (referencing ROM), * in case we change the address sometime. * Note that this is safe here as the receiver is NOT armed. */ ec_setaddr(es->es_addr, unit); /* * Arm the receiver */ for (i = ECRHBF; i >= ECRLBF; i--) addr->ec_rcr = EC_READ | i; es->es_oactive = 0; es->es_mask = ~0; es->es_if.if_flags |= IFF_RUNNING; if (es->es_if.if_snd.ifq_head) ecstart(unit); splx(s); } } /* * Start output on interface. Get another datagram to send * off of the interface queue, and copy it to the interface * before starting the output. */ ecstart(unit) { register struct ec_softc *es = &ec_softc[unit]; struct ecdevice *addr; struct mbuf *m; if ((es->es_if.if_flags & IFF_RUNNING) == 0) return; IF_DEQUEUE(&es->es_if.if_snd, m); if (m == 0) return; ecput(es->es_buf[ECTBF], m); addr = (struct ecdevice *)ecinfo[unit]->ui_addr; addr->ec_xcr = EC_WRITE|ECTBF; es->es_oactive = 1; } /* * Ethernet interface transmitter interrupt. * Start another output if more data to send. */ ecxint(unit) int unit; { register struct ec_softc *es = &ec_softc[unit]; register struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr; if (es->es_oactive == 0) return; if ((addr->ec_xcr&EC_XDONE) == 0 || (addr->ec_xcr&EC_XBN) != ECTBF) { printf("ec%d: stray xmit interrupt, xcr=%b\n", unit, addr->ec_xcr, EC_XBITS); es->es_oactive = 0; addr->ec_xcr = EC_XCLR; return; } es->es_if.if_opackets++; es->es_oactive = 0; es->es_mask = ~0; addr->ec_xcr = EC_XCLR; if (es->es_if.if_snd.ifq_head) ecstart(unit); } /* * Collision on ethernet interface. Do exponential * backoff, and retransmit. If have backed off all * the way print warning diagnostic, and drop packet. */ eccollide(unit) int unit; { register struct ec_softc *es = &ec_softc[unit]; register struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr; register i; int delay; es->es_if.if_collisions++; if (es->es_oactive == 0) return; /* * Es_mask is a 16 bit number with n low zero bits, with * n the number of backoffs. When es_mask is 0 we have * backed off 16 times, and give up. */ if (es->es_mask == 0) { es->es_if.if_oerrors++; log(LOG_ERR, "ec%d: send error\n", unit); /* * Reset interface, then requeue rcv buffers. * Some incoming packets may be lost, but that * can't be helped. */ addr->ec_xcr = EC_UECLR; for (i=ECRHBF; i>=ECRLBF; i--) addr->ec_rcr = EC_READ|i; /* * Reset and transmit next packet (if any). */ es->es_oactive = 0; es->es_mask = ~0; if (es->es_if.if_snd.ifq_head) ecstart(unit); return; } /* * Do exponential backoff. Compute delay based on low bits * of the interval timer (1 bit for each transmission attempt, * but at most 5 bits). Then delay for that number of * slot times. A slot time is 51.2 microseconds (rounded to 51). * This does not take into account the time already used to * process the interrupt. */ es->es_mask <<= 1; delay = mfpr(ICR) & 0x1f &~ es->es_mask; DELAY(delay * 51); /* * Clear the controller's collision flag, thus enabling retransmit. */ addr->ec_xcr = EC_CLEAR; } /* * Ethernet interface receiver interrupt. * If input error just drop packet. * Otherwise examine * packet to determine type. If can't determine length * from type, then have to drop packet. Othewise decapsulate * packet based on type and pass to type specific higher-level * input routine. */ ecrint(unit) int unit; { struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr; while (addr->ec_rcr & EC_RDONE) ecread(unit); } ecread(unit) int unit; { register struct ec_softc *es = &ec_softc[unit]; struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr; register struct ether_header *ec; struct mbuf *m; int len, off, resid, ecoff, rbuf; register struct ifqueue *inq; u_char *ecbuf; es->es_if.if_ipackets++; rbuf = addr->ec_rcr & EC_RBN; if (rbuf < ECRLBF || rbuf > ECRHBF) panic("ecrint"); ecbuf = es->es_buf[rbuf]; ecoff = *(short *)ecbuf; if (ecoff <= ECRDOFF || ecoff > 2046) { es->es_if.if_ierrors++; #ifdef notdef if (es->es_if.if_ierrors % 100 == 0) printf("ec%d: += 100 input errors\n", unit); #endif goto setup; } /* * Get input data length. * Get pointer to ethernet header (in input buffer). * Deal with trailer protocol: if type is trailer type * get true type from first 16-bit word past data. * Remember that type was trailer by setting off. */ len = ecoff - ECRDOFF - sizeof (struct ether_header); ec = (struct ether_header *)(ecbuf + ECRDOFF); ec->ether_type = ntohs((u_short)ec->ether_type); #define ecdataaddr(ec, off, type) ((type)(((caddr_t)((ec)+1)+(off)))) if (ec->ether_type >= ETHERTYPE_TRAIL && ec->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { off = (ec->ether_type - ETHERTYPE_TRAIL) * 512; if (off >= ETHERMTU) goto setup; /* sanity */ ec->ether_type = ntohs(*ecdataaddr(ec, off, u_short *)); resid = ntohs(*(ecdataaddr(ec, off+2, u_short *))); if (off + resid > len) goto setup; /* sanity */ len = off + resid; } else off = 0; if (len == 0) goto setup; /* * Pull packet off interface. Off is nonzero if packet * has trailing header; ecget will then force this header * information to be at the front, but we still have to drop * the type and length which are at the front of any trailer data. */ m = ecget(ecbuf, len, off, &es->es_if); if (m == 0) goto setup; if (off) { struct ifnet *ifp; ifp = *(mtod(m, struct ifnet **)); m->m_off += 2 * sizeof (u_short); m->m_len -= 2 * sizeof (u_short); *(mtod(m, struct ifnet **)) = ifp; } switch (ec->ether_type) { #ifdef INET case ETHERTYPE_IP: schednetisr(NETISR_IP); inq = &ipintrq; break; case ETHERTYPE_ARP: arpinput(&es->es_ac, m); goto setup; #endif #ifdef NS case ETHERTYPE_NS: schednetisr(NETISR_NS); inq = &nsintrq; break; #endif default: m_freem(m); goto setup; } if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); goto setup; } IF_ENQUEUE(inq, m); setup: /* * Reset for next packet. */ addr->ec_rcr = EC_READ|EC_RCLR|rbuf; } /* * Ethernet output routine. * Encapsulate a packet of type family for the local net. * Use trailer local net encapsulation if enough data in first * packet leaves a multiple of 512 bytes of data in remainder. * If destination is this address or broadcast, send packet to * loop device to kludge around the fact that 3com interfaces can't * talk to themselves. */ ecoutput(ifp, m0, dst) struct ifnet *ifp; struct mbuf *m0; struct sockaddr *dst; { int type, s, error; u_char edst[6]; struct in_addr idst; register struct ec_softc *es = &ec_softc[ifp->if_unit]; register struct mbuf *m = m0; register struct ether_header *ec; register int off; struct mbuf *mcopy = (struct mbuf *)0; int usetrailers; if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { error = ENETDOWN; goto bad; } switch (dst->sa_family) { #ifdef INET case AF_INET: idst = ((struct sockaddr_in *)dst)->sin_addr; if (!arpresolve(&es->es_ac, m, &idst, edst, &usetrailers)) return (0); /* if not yet resolved */ if (!bcmp((caddr_t)edst, (caddr_t)etherbroadcastaddr, sizeof(edst))) mcopy = m_copy(m, 0, (int)M_COPYALL); off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; /* need per host negotiation */ if (usetrailers && off > 0 && (off & 0x1ff) == 0 && m->m_off >= MMINOFF + 2 * sizeof (u_short)) { type = ETHERTYPE_TRAIL + (off>>9); m->m_off -= 2 * sizeof (u_short); m->m_len += 2 * sizeof (u_short); *mtod(m, u_short *) = ntohs((u_short)ETHERTYPE_IP); *(mtod(m, u_short *) + 1) = ntohs((u_short)m->m_len); goto gottrailertype; } type = ETHERTYPE_IP; off = 0; goto gottype; #endif #ifdef NS case AF_NS: bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), (caddr_t)edst, sizeof (edst)); if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof(edst))) { mcopy = m_copy(m, 0, (int)M_COPYALL); } else if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))) { return(looutput(&loif, m, dst)); } type = ETHERTYPE_NS; off = 0; goto gottype; #endif case AF_UNSPEC: ec = (struct ether_header *)dst->sa_data; bcopy((caddr_t)ec->ether_dhost, (caddr_t)edst, sizeof (edst)); type = ec->ether_type; goto gottype; default: printf("ec%d: can't handle af%d\n", ifp->if_unit, dst->sa_family); error = EAFNOSUPPORT; goto bad; } gottrailertype: /* * Packet to be sent as trailer: move first packet * (control information) to end of chain. */ while (m->m_next) m = m->m_next; m->m_next = m0; m = m0->m_next; m0->m_next = 0; m0 = m; gottype: /* * Add local net header. If no space in first mbuf, * allocate another. */ if (m->m_off > MMAXOFF || MMINOFF + sizeof (struct ether_header) > m->m_off) { m = m_get(M_DONTWAIT, MT_HEADER); if (m == 0) { error = ENOBUFS; goto bad; } m->m_next = m0; m->m_off = MMINOFF; m->m_len = sizeof (struct ether_header); } else { m->m_off -= sizeof (struct ether_header); m->m_len += sizeof (struct ether_header); } ec = mtod(m, struct ether_header *); bcopy((caddr_t)edst, (caddr_t)ec->ether_dhost, sizeof (edst)); bcopy((caddr_t)es->es_addr, (caddr_t)ec->ether_shost, sizeof(ec->ether_shost)); ec->ether_type = htons((u_short)type); /* * Queue message on interface, and start output if interface * not yet active. */ s = splimp(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); error = ENOBUFS; goto qfull; } IF_ENQUEUE(&ifp->if_snd, m); if (es->es_oactive == 0) ecstart(ifp->if_unit); splx(s); return (mcopy ? looutput(&loif, mcopy, dst) : 0); qfull: m0 = m; splx(s); bad: m_freem(m0); if (mcopy) m_freem(mcopy); return (error); } /* * Routine to copy from mbuf chain to transmit * buffer in UNIBUS memory. * If packet size is less than the minimum legal size, * the buffer is expanded. We probably should zero out the extra * bytes for security, but that would slow things down. */ ecput(ecbuf, m) u_char *ecbuf; struct mbuf *m; { register struct mbuf *mp; register int off; u_char *bp; for (off = 2048, mp = m; mp; mp = mp->m_next) off -= mp->m_len; if (2048 - off < ETHERMIN + sizeof (struct ether_header)) off = 2048 - ETHERMIN - sizeof (struct ether_header); *(u_short *)ecbuf = off; bp = (u_char *)(ecbuf + off); for (mp = m; mp; mp = mp->m_next) { register unsigned len = mp->m_len; u_char *mcp; if (len == 0) continue; mcp = mtod(mp, u_char *); if ((unsigned)bp & 01) { *bp++ = *mcp++; len--; } if (off = (len >> 1)) { register u_short *to, *from; to = (u_short *)bp; from = (u_short *)mcp; do *to++ = *from++; while (--off > 0); bp = (u_char *)to, mcp = (u_char *)from; } if (len & 01) *bp++ = *mcp++; } m_freem(m); } /* * Routine to copy from UNIBUS memory into mbufs. * Similar in spirit to if_rubaget. * * Warning: This makes the fairly safe assumption that * mbufs have even lengths. */ struct mbuf * ecget(ecbuf, totlen, off0, ifp) u_char *ecbuf; int totlen, off0; struct ifnet *ifp; { register struct mbuf *m; struct mbuf *top = 0, **mp = ⊤ register int off = off0, len; u_char *cp; cp = ecbuf + ECRDOFF + sizeof (struct ether_header); while (totlen > 0) { register int words; u_char *mcp; MGET(m, M_DONTWAIT, MT_DATA); if (m == 0) goto bad; if (off) { len = totlen - off; cp = ecbuf + ECRDOFF + sizeof (struct ether_header) + off; } else len = totlen; if (ifp) len += sizeof(ifp); if (len >= NBPG) { MCLGET(m); if (m->m_len == CLBYTES) m->m_len = len = MIN(len, CLBYTES); else m->m_len = len = MIN(MLEN, len); } else { m->m_len = len = MIN(MLEN, len); m->m_off = MMINOFF; } mcp = mtod(m, u_char *); if (ifp) { /* * Prepend interface pointer to first mbuf. */ *(mtod(m, struct ifnet **)) = ifp; mcp += sizeof(ifp); len -= sizeof(ifp); ifp = (struct ifnet *)0; } if (words = (len >> 1)) { register u_short *to, *from; to = (u_short *)mcp; from = (u_short *)cp; do *to++ = *from++; while (--words > 0); mcp = (u_char *)to; cp = (u_char *)from; } if (len & 01) *mcp++ = *cp++; *mp = m; mp = &m->m_next; if (off == 0) { totlen -= len; continue; } off += len; if (off == totlen) { cp = ecbuf + ECRDOFF + sizeof (struct ether_header); off = 0; totlen = off0; } } return (top); bad: m_freem(top); return (0); } /* * Process an ioctl request. */ ecioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { register struct ifaddr *ifa = (struct ifaddr *)data; struct ec_softc *es = &ec_softc[ifp->if_unit]; struct ecdevice *addr; int s = splimp(), error = 0; addr = (struct ecdevice *)(ecinfo[ifp->if_unit]->ui_addr); switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; switch (ifa->ifa_addr.sa_family) { #ifdef INET case AF_INET: ecinit(ifp->if_unit); /* before arpwhohas */ ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr; arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); break; #endif #ifdef NS case AF_NS: { register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); if (ns_nullhost(*ina)) ina->x_host = *(union ns_host *)(es->es_addr); else { /* * The manual says we can't change the address * while the receiver is armed, * so reset everything */ ifp->if_flags &= ~IFF_RUNNING; bcopy((caddr_t)ina->x_host.c_host, (caddr_t)es->es_addr, sizeof(es->es_addr)); } ecinit(ifp->if_unit); /* does ec_setaddr() */ break; } #endif default: ecinit(ifp->if_unit); break; } break; case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) { addr->ec_xcr = EC_UECLR; ifp->if_flags &= ~IFF_RUNNING; } else if (ifp->if_flags & IFF_UP && (ifp->if_flags & IFF_RUNNING) == 0) ecinit(ifp->if_unit); break; default: error = EINVAL; } splx(s); return (error); } ec_setaddr(physaddr,unit) u_char *physaddr; int unit; { struct ec_softc *es = &ec_softc[unit]; struct uba_device *ui = ecinfo[unit]; register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr; register char nibble; register int i, j; /* * Use the ethernet address supplied * Note that we do a UECLR here, so the receive buffers * must be requeued. */ #ifdef DEBUG printf("ec_setaddr: setting address for unit %d = %s", unit, ether_sprintf(physaddr)); #endif addr->ec_xcr = EC_UECLR; addr->ec_rcr = 0; /* load requested address */ for (i = 0; i < 6; i++) { /* 6 bytes of address */ es->es_addr[i] = physaddr[i]; nibble = physaddr[i] & 0xf; /* lower nibble */ addr->ec_rcr = (nibble << 8); addr->ec_rcr = (nibble << 8) + EC_AWCLK; /* latch nibble */ addr->ec_rcr = (nibble << 8); for (j=0; j < 4; j++) { addr->ec_rcr = 0; addr->ec_rcr = EC_ASTEP; /* step counter */ addr->ec_rcr = 0; } nibble = (physaddr[i] >> 4) & 0xf; /* upper nibble */ addr->ec_rcr = (nibble << 8); addr->ec_rcr = (nibble << 8) + EC_AWCLK; /* latch nibble */ addr->ec_rcr = (nibble << 8); for (j=0; j < 4; j++) { addr->ec_rcr = 0; addr->ec_rcr = EC_ASTEP; /* step counter */ addr->ec_rcr = 0; } } #ifdef DEBUG /* * Read the ethernet address off the board, one nibble at a time. */ addr->ec_xcr = EC_UECLR; addr->ec_rcr = 0; /* read RAM */ cp = es->es_addr; #undef NEXTBIT #define NEXTBIT addr->ec_rcr = EC_ASTEP; addr->ec_rcr = 0 for (i=0; i < sizeof (es->es_addr); i++) { *cp = 0; for (j=0; j<=4; j+=4) { *cp |= ((addr->ec_rcr >> 8) & 0xf) << j; NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT; } cp++; } printf("ec_setaddr: RAM address for unit %d = %s", unit, ether_sprintf(physaddr)); #endif } #endif NETISR_IP); inq = &ipintrq; break; case ETHERTYPE_ARP: sys/vaxif/if_dmc.h 444 0 12 5306 3671247506 7371 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_dmc.h 7.1 (Berkeley) 6/5/86 */ /* * DMC-11 Interface */ struct dmcdevice { char bsel0; char bsel1; char bsel2; char bsel3; short sel4; short sel6; }; /* * dmc software packet encapsulation. This allows the dmc * link to be multiplexed among several protocols. * The first eight bytes of the dmc header are garbage, * since on a vax the uba has been known to mung these * bytes. The next two bytes encapsulate packet type. */ struct dmc_header { char dmc_buf[8]; /* space for uba on vax */ short dmc_type; /* encapsulate packet type */ }; /* packet types */ #define DMC_IPTYPE 1 #define DMC_TRAILER 2 #define DMC_NTRAILER 16 /* * DMCMTU includes space for data (1024) + * protocol header (256) + trailer descriptor (4). * The software link encapsulation header (dmc_header) * is handled separately. */ #define DMCMTU 1284 #define RDYSCAN 16 /* loop delay for RDYI after RQI */ /* defines for bsel0 */ #define DMC_BACCI 0 #define DMC_CNTLI 1 #define DMC_PERR 2 #define DMC_BASEI 3 #define DMC_WRITE 0 /* transmit block */ #define DMC_READ 4 /* read block */ #define DMC_RQI 0040 /* port request bit */ #define DMC_IEI 0100 /* enable input interrupts */ #define DMC_RDYI 0200 /* port ready */ #define DMC0BITS "\10\8RDI\7IEI\6RQI" /* defines for bsel1 */ #define DMC_MCLR 0100 /* DMC11 Master Clear */ #define DMC_RUN 0200 /* clock running */ #define DMC1BITS "\10\8RUN\7MCLR" /* defines for bsel2 */ #define DMC_BACCO 0 #define DMC_CNTLO 1 #define DMC_OUX 0 /* transmit block */ #define DMC_OUR 4 /* read block */ #define DMC_IEO 0100 /* enable output interrupts */ #define DMC_RDYO 0200 /* port available */ #define DMC2BITS "\10\8RDO\7IEO" /* defines for CNTLI mode */ #define DMC_HDPLX 02000 /* half duplex DDCMP operation */ #define DMC_SEC 04000 /* half duplex secondary station */ #define DMC_MAINT 00400 /* enter maintenance mode */ /* defines for BACCI/O and BASEI mode */ #define DMC_XMEM 0140000 /* xmem bit position */ #define DMC_CCOUNT 0037777 /* character count mask */ #define DMC_RESUME 0002000 /* resume (BASEI only) */ /* defines for CNTLO */ #define DMC_CNTMASK 01777 #define DMC_DATACK 01 #define DMC_TIMEOUT 02 #define DMC_NOBUFS 04 #define DMC_MAINTREC 010 #define DMC_LOSTDATA 020 #define DMC_DISCONN 0100 #define DMC_START 0200 #define DMC_NEXMEM 0400 #define DMC_ERROR 01000 #define DMC_FATAL (DMC_ERROR|DMC_NEXMEM|DMC_START|DMC_LOSTDATA|DMC_MAINTREC) #define CNTLO_BITS \ "\10\12ERROR\11NEXMEM\10START\7DISC\5LSTDATA\4MAINT\3NOBUF\2TIMEO\1DATACK" themselves. */ ecoutput(ifp, m0, dst) struct ifnet *ifp; struct mbuf *m0; struct sockaddr *dst; { int type, s, error; u_char edst[6]; struct in_addr idst; register struct ec_softc *es = &ec_softc[ifp->if_unit]; register struct mbuf *m = m0; register struct ether_header *ec; register int off; struct sys/vaxif/if_uba.c 640 0 12 22020 4061747313 7371 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_uba.c 7.5.1.1 (Berkeley) 6/4/87 */ #include "../machine/pte.h" #include "param.h" #include "systm.h" #include "mbuf.h" #include "map.h" #include "buf.h" #include "cmap.h" #include "vmmac.h" #include "socket.h" #include "syslog.h" #include "../net/if.h" #include "../vax/mtpr.h" #include "if_uba.h" #include "../vaxuba/ubareg.h" #include "../vaxuba/ubavar.h" /* * Routines supporting UNIBUS network interfaces. * * TODO: * Support interfaces using only one BDP statically. */ /* * Init UNIBUS for interface on uban whose headers of size hlen are to * end on a page boundary. We allocate a UNIBUS map register for the page * with the header, and nmr more UNIBUS map registers for i/o on the adapter, * doing this once for each read and once for each write buffer. We also * allocate page frames in the mbuffer pool for these pages. */ if_ubaminit(ifu, uban, hlen, nmr, ifr, nr, ifw, nw) register struct ifubinfo *ifu; int uban, hlen, nmr, nr, nw; register struct ifrw *ifr; register struct ifxmt *ifw; { register caddr_t p; caddr_t cp; int i, ncl, off; if (hlen) off = CLBYTES - hlen; else off = 0; ncl = clrnd(nmr) / CLSIZE; if (hlen) ncl++; if (ifr[0].ifrw_addr) cp = ifr[0].ifrw_addr - off; else { cp = m_clalloc((nr + nw) * ncl, MPG_SPACE, M_DONTWAIT); if (cp == 0) return (0); p = cp; for (i = 0; i < nr; i++) { ifr[i].ifrw_addr = p + off; p += ncl * CLBYTES; } for (i = 0; i < nw; i++) { ifw[i].ifw_base = p; ifw[i].ifw_addr = p + off; p += ncl * CLBYTES; } ifu->iff_hlen = hlen; ifu->iff_uban = uban; ifu->iff_uba = uba_hd[uban].uh_uba; } for (i = 0; i < nr; i++) if (if_ubaalloc(ifu, &ifr[i], nmr) == 0) { nr = i; nw = 0; goto bad; } for (i = 0; i < nw; i++) if (if_ubaalloc(ifu, &ifw[i].ifrw, nmr) == 0) { nw = i; goto bad; } while (--nw >= 0) { for (i = 0; i < nmr; i++) ifw[nw].ifw_wmap[i] = ifw[nw].ifw_mr[i]; ifw[nw].ifw_xswapd = 0; ifw[nw].ifw_flags = IFRW_W; ifw[nw].ifw_nmr = nmr; } return (1); bad: while (--nw >= 0) ubarelse(ifu->iff_uban, &ifw[nw].ifw_info); while (--nr >= 0) ubarelse(ifu->iff_uban, &ifr[nr].ifrw_info); m_pgfree(cp, (nr + nw) * ncl); ifr[0].ifrw_addr = 0; return (0); } /* * Setup an ifrw structure by allocating UNIBUS map registers, * possibly a buffered data path, and initializing the fields of * the ifrw structure to minimize run-time overhead. */ static if_ubaalloc(ifu, ifrw, nmr) struct ifubinfo *ifu; register struct ifrw *ifrw; int nmr; { register int info; info = uballoc(ifu->iff_uban, ifrw->ifrw_addr, nmr*NBPG + ifu->iff_hlen, ifu->iff_flags); if (info == 0) return (0); ifrw->ifrw_info = info; ifrw->ifrw_bdp = UBAI_BDP(info); ifrw->ifrw_proto = UBAMR_MRV | (UBAI_BDP(info) << UBAMR_DPSHIFT); ifrw->ifrw_mr = &ifu->iff_uba->uba_map[UBAI_MR(info) + (ifu->iff_hlen? 1 : 0)]; return (1); } /* * Pull read data off a interface. * Len is length of data, with local net header stripped. * Off is non-zero if a trailer protocol was used, and * gives the offset of the trailer information. * We copy the trailer information and then all the normal * data into mbufs. When full cluster sized units are present * on the interface on cluster boundaries we can get them more * easily by remapping, and take advantage of this here. * Prepend a pointer to the interface structure, * so that protocols can determine where incoming packets arrived. * Note: we may be called to receive from a transmit buffer by some * devices. In that case, we must force normal mapping of the buffer, * so that the correct data will appear (only unibus maps are * changed when remapping the transmit buffers). */ struct mbuf * if_ubaget(ifu, ifr, totlen, off0, ifp) struct ifubinfo *ifu; register struct ifrw *ifr; int totlen, off0; struct ifnet *ifp; { struct mbuf *top, **mp; register struct mbuf *m; int off = off0, len; register caddr_t cp = ifr->ifrw_addr + ifu->iff_hlen, pp; top = 0; mp = ⊤ if (ifr->ifrw_flags & IFRW_W) rcv_xmtbuf((struct ifxmt *)ifr); while (totlen > 0) { MGET(m, M_DONTWAIT, MT_DATA); if (m == 0) { m_freem(top); top = 0; goto out; } if (off) { len = totlen - off; cp = ifr->ifrw_addr + ifu->iff_hlen + off; } else len = totlen; if (len >= CLBYTES/2) { struct pte *cpte, *ppte; int x, *ip, i; /* * If doing the first mbuf and * the interface pointer hasn't been put in, * put it in a separate mbuf to preserve alignment. */ if (ifp) { len = 0; goto nopage; } MCLGET(m); if (m->m_len != CLBYTES) goto nopage; m->m_len = MIN(len, CLBYTES); if (!claligned(cp)) goto copy; /* * Switch pages mapped to UNIBUS with new page pp, * as quick form of copy. Remap UNIBUS and invalidate. */ pp = mtod(m, char *); cpte = &Mbmap[mtocl(cp)*CLSIZE]; ppte = &Mbmap[mtocl(pp)*CLSIZE]; x = btop(cp - ifr->ifrw_addr); ip = (int *)&ifr->ifrw_mr[x]; for (i = 0; i < CLSIZE; i++) { struct pte t; t = *ppte; *ppte++ = *cpte; *cpte = t; *ip++ = cpte++->pg_pfnum|ifr->ifrw_proto; mtpr(TBIS, cp); cp += NBPG; mtpr(TBIS, (caddr_t)pp); pp += NBPG; } goto nocopy; } nopage: m->m_off = MMINOFF; if (ifp) { /* * Leave room for ifp. */ m->m_len = MIN(MLEN - sizeof(ifp), len); m->m_off += sizeof(ifp); } else m->m_len = MIN(MLEN, len); copy: bcopy(cp, mtod(m, caddr_t), (unsigned)m->m_len); cp += m->m_len; nocopy: *mp = m; mp = &m->m_next; if (off) { /* sort of an ALGOL-W style for statement... */ off += m->m_len; if (off == totlen) { cp = ifr->ifrw_addr + ifu->iff_hlen; off = 0; totlen = off0; } } else totlen -= m->m_len; if (ifp) { /* * Prepend interface pointer to first mbuf. */ m->m_len += sizeof(ifp); m->m_off -= sizeof(ifp); *(mtod(m, struct ifnet **)) = ifp; ifp = (struct ifnet *)0; } } out: if (ifr->ifrw_flags & IFRW_W) restor_xmtbuf((struct ifxmt *)ifr); return (top); } /* * Change the mapping on a transmit buffer so that if_ubaget may * receive from that buffer. Copy data from any pages mapped to Unibus * into the pages mapped to normal kernel virtual memory, so that * they can be accessed and swapped as usual. We take advantage * of the fact that clusters are placed on the xtofree list * in inverse order, finding the last one. */ static rcv_xmtbuf(ifw) register struct ifxmt *ifw; { register struct mbuf *m; struct mbuf **mprev; register i; char *cp; while (i = ffs((long)ifw->ifw_xswapd)) { cp = ifw->ifw_base + i * CLBYTES; i--; ifw->ifw_xswapd &= ~(1<ifw_xtofree; for (m = ifw->ifw_xtofree; m && m->m_next; m = m->m_next) mprev = &m->m_next; if (m == NULL) break; bcopy(mtod(m, caddr_t), cp, CLBYTES); (void) m_free(m); *mprev = NULL; } ifw->ifw_xswapd = 0; for (i = 0; i < ifw->ifw_nmr; i++) ifw->ifw_mr[i] = ifw->ifw_wmap[i]; } /* * Put a transmit buffer back together after doing an if_ubaget on it, * which may have swapped pages. */ static restor_xmtbuf(ifw) register struct ifxmt *ifw; { register i; for (i = 0; i < ifw->ifw_nmr; i++) ifw->ifw_wmap[i] = ifw->ifw_mr[i]; } /* * Map a chain of mbufs onto a network interface * in preparation for an i/o operation. * The argument chain of mbufs includes the local network * header which is copied to be in the mapped, aligned * i/o space. */ if_ubaput(ifu, ifw, m) struct ifubinfo *ifu; register struct ifxmt *ifw; register struct mbuf *m; { register struct mbuf *mp; register caddr_t cp, dp; register int i; int xswapd = 0; int x, cc, t; cp = ifw->ifw_addr; while (m) { dp = mtod(m, char *); if (claligned(cp) && claligned(dp) && (m->m_len == CLBYTES || m->m_next == (struct mbuf *)0)) { struct pte *pte; int *ip; pte = &Mbmap[mtocl(dp)*CLSIZE]; x = btop(cp - ifw->ifw_addr); ip = (int *)&ifw->ifw_mr[x]; for (i = 0; i < CLSIZE; i++) *ip++ = ifw->ifw_proto | pte++->pg_pfnum; xswapd |= 1 << (x>>(CLSHIFT-PGSHIFT)); mp = m->m_next; m->m_next = ifw->ifw_xtofree; ifw->ifw_xtofree = m; cp += m->m_len; } else { bcopy(mtod(m, caddr_t), cp, (unsigned)m->m_len); cp += m->m_len; MFREE(m, mp); } m = mp; } /* * Xswapd is the set of clusters we just mapped out. Ifu->iff_xswapd * is the set of clusters mapped out from before. We compute * the number of clusters involved in this operation in x. * Clusters mapped out before and involved in this operation * should be unmapped so original pages will be accessed by the device. */ cc = cp - ifw->ifw_addr; x = ((cc - ifu->iff_hlen) + CLBYTES - 1) >> CLSHIFT; ifw->ifw_xswapd &= ~xswapd; while (i = ffs((long)ifw->ifw_xswapd)) { i--; if (i >= x) break; ifw->ifw_xswapd &= ~(1<ifw_mr[i] = ifw->ifw_wmap[i]; i++; } } ifw->ifw_xswapd |= xswapd; return (cc); } (struct ether_header) > m->m_off) { m = m_get(M_DONTWAIT, MT_HEADER); if (m == 0) { error = ENOBUFS; goto bad; } m->m_next = m0; m->m_off = MMINOFF; m->m_len = sizeof (struct ether_header); } else { m->m_off -= sizeof (struct ether_header); m->m_len += sizeof (struct ether_header); } ec = mtod(m, struct ether_header *); bcopy((caddr_t)edst, (caddr_t)ec->ether_dhost, sizeof (edst)); bcopy((caddr_t)es->es_addr, (caddr_t)ec->ether_shost, sizeof(ec->ether_shost))sys/vaxif/if_il.c 444 0 12 46256 3671425074 7254 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_il.c 7.1 (Berkeley) 6/5/86 */ #include "il.h" #if NIL > 0 /* * Interlan Ethernet Communications Controller interface */ #include "../machine/pte.h" #include "param.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "protosw.h" #include "socket.h" #include "vmmac.h" #include "ioctl.h" #include "errno.h" #include "../net/if.h" #include "../net/netisr.h" #include "../net/route.h" #ifdef INET #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netinet/in_var.h" #include "../netinet/ip.h" #include "../netinet/if_ether.h" #endif #ifdef NS #include "../netns/ns.h" #include "../netns/ns_if.h" #endif #include "../vax/cpu.h" #include "../vax/mtpr.h" #include "if_il.h" #include "if_ilreg.h" #include "if_uba.h" #include "../vaxuba/ubareg.h" #include "../vaxuba/ubavar.h" int ilprobe(), ilattach(), ilrint(), ilcint(); struct uba_device *ilinfo[NIL]; u_short ilstd[] = { 0 }; struct uba_driver ildriver = { ilprobe, 0, ilattach, 0, ilstd, "il", ilinfo }; #define ILUNIT(x) minor(x) int ilinit(),iloutput(),ilioctl(),ilreset(),ilwatch(); int ildebug = 0; /* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * is_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... * We also have, for each interface, a UBA interface structure, which * contains information about the UNIBUS resources held by the interface: * map registers, buffered data paths, etc. Information is cached in this * structure for use by the if_uba.c routines in running the interface * efficiently. */ struct il_softc { struct arpcom is_ac; /* Ethernet common part */ #define is_if is_ac.ac_if /* network-visible interface */ #define is_addr is_ac.ac_enaddr /* hardware Ethernet address */ struct ifuba is_ifuba; /* UNIBUS resources */ int is_flags; #define ILF_OACTIVE 0x1 /* output is active */ #define ILF_RCVPENDING 0x2 /* start rcv in ilcint */ #define ILF_STATPENDING 0x4 /* stat cmd pending */ #define ILF_RUNNING 0x8 /* board is running */ #define ILF_SETADDR 0x10 /* physical address is changed */ short is_lastcmd; /* can't read csr, so must save it */ short is_scaninterval; /* interval of stat collection */ #define ILWATCHINTERVAL 60 /* once every 60 seconds */ struct il_stats is_stats; /* holds on-board statistics */ struct il_stats is_sum; /* summation over time */ int is_ubaddr; /* mapping registers of is_stats */ } il_softc[NIL]; ilprobe(reg) caddr_t reg; { register int br, cvec; /* r11, r10 value-result */ register struct ildevice *addr = (struct ildevice *)reg; register i; #ifdef lint br = 0; cvec = br; br = cvec; i = 0; ilrint(i); ilcint(i); ilwatch(i); #endif addr->il_csr = ILC_OFFLINE|IL_CIE; DELAY(100000); i = addr->il_csr; /* clear CDONE */ if (cvec > 0 && cvec != 0x200) cvec -= 4; return (1); } /* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. A STATUS command is done to get the ethernet * address and other interesting data. */ ilattach(ui) struct uba_device *ui; { register struct il_softc *is = &il_softc[ui->ui_unit]; register struct ifnet *ifp = &is->is_if; register struct ildevice *addr = (struct ildevice *)ui->ui_addr; ifp->if_unit = ui->ui_unit; ifp->if_name = "il"; ifp->if_mtu = ETHERMTU; ifp->if_flags = IFF_BROADCAST; /* * Reset the board and map the statistics * buffer onto the Unibus. */ addr->il_csr = ILC_RESET; (void)ilwait(ui, "reset"); is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_stats, sizeof (struct il_stats), 0); addr->il_bar = is->is_ubaddr & 0xffff; addr->il_bcr = sizeof (struct il_stats); addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT; (void)ilwait(ui, "status"); ubarelse(ui->ui_ubanum, &is->is_ubaddr); if (ildebug) printf("il%d: module=%s firmware=%s\n", ui->ui_unit, is->is_stats.ils_module, is->is_stats.ils_firmware); bcopy((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr, sizeof (is->is_addr)); printf("il%d: hardware address %s\n", ui->ui_unit, ether_sprintf(is->is_addr)); ifp->if_init = ilinit; ifp->if_output = iloutput; ifp->if_ioctl = ilioctl; ifp->if_reset = ilreset; is->is_ifuba.ifu_flags = UBA_CANTWAIT; if_attach(ifp); } ilwait(ui, op) struct uba_device *ui; char *op; { register struct ildevice *addr = (struct ildevice *)ui->ui_addr; while ((addr->il_csr&IL_CDONE) == 0) ; if (addr->il_csr&IL_STATUS) { printf("il%d: %s failed, csr=%b\n", ui->ui_unit, op, addr->il_csr, IL_BITS); return (-1); } return (0); } /* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */ ilreset(unit, uban) int unit, uban; { register struct uba_device *ui; if (unit >= NIL || (ui = ilinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" il%d", unit); il_softc[unit].is_if.if_flags &= ~IFF_RUNNING; il_softc[unit].is_flags &= ~ILF_RUNNING; ilinit(unit); } /* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */ ilinit(unit) int unit; { register struct il_softc *is = &il_softc[unit]; register struct uba_device *ui = ilinfo[unit]; register struct ildevice *addr; register struct ifnet *ifp = &is->is_if; int s; /* not yet, if address still unknown */ if (ifp->if_addrlist == (struct ifaddr *)0) return; if (is->is_flags & ILF_RUNNING) return; if ((ifp->if_flags & IFF_RUNNING) == 0) { if (if_ubainit(&is->is_ifuba, ui->ui_ubanum, sizeof (struct il_rheader), (int)btoc(ETHERMTU)) == 0) { printf("il%d: can't initialize\n", unit); is->is_if.if_flags &= ~IFF_UP; return; } is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_stats, sizeof (struct il_stats), 0); } ifp->if_watchdog = ilwatch; is->is_scaninterval = ILWATCHINTERVAL; ifp->if_timer = is->is_scaninterval; addr = (struct ildevice *)ui->ui_addr; /* * Turn off source address insertion (it's faster this way), * and set board online. Former doesn't work if board is * already online (happens on ubareset), so we put it offline * first. */ s = splimp(); addr->il_csr = ILC_RESET; if (ilwait(ui, "hardware diag")) { is->is_if.if_flags &= ~IFF_UP; splx(s); return; } addr->il_csr = ILC_CISA; while ((addr->il_csr & IL_CDONE) == 0) ; /* * If we must reprogram this board's physical ethernet * address (as for secondary XNS interfaces), we do so * before putting it on line, and starting receive requests. * If you try this on an older 1010 board, it will total * wedge the board. */ if (is->is_flags & ILF_SETADDR) { bcopy((caddr_t)is->is_addr, (caddr_t)&is->is_stats, sizeof is->is_addr); addr->il_bar = is->is_ubaddr & 0xffff; addr->il_bcr = sizeof is->is_addr; addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_LDPA; if (ilwait(ui, "setaddr")) return; addr->il_bar = is->is_ubaddr & 0xffff; addr->il_bcr = sizeof (struct il_stats); addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT; if (ilwait(ui, "verifying setaddr")) return; if (bcmp((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr, sizeof (is->is_addr)) != 0) { printf("il%d: setaddr didn't work\n", ui->ui_unit); return; } } /* * Set board online. * Hang receive buffer and start any pending * writes by faking a transmit complete. * Receive bcr is not a multiple of 8 so buffer * chaining can't happen. */ addr->il_csr = ILC_ONLINE; while ((addr->il_csr & IL_CDONE) == 0) ; addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff; addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6; addr->il_csr = ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE; while ((addr->il_csr & IL_CDONE) == 0) ; is->is_flags = ILF_OACTIVE; is->is_if.if_flags |= IFF_RUNNING; is->is_flags |= ILF_RUNNING; is->is_lastcmd = 0; ilcint(unit); splx(s); } /* * Start output on interface. * Get another datagram to send off of the interface queue, * and map it to the interface before starting the output. */ ilstart(dev) dev_t dev; { int unit = ILUNIT(dev), len; struct uba_device *ui = ilinfo[unit]; register struct il_softc *is = &il_softc[unit]; register struct ildevice *addr; struct mbuf *m; short csr; IF_DEQUEUE(&is->is_if.if_snd, m); addr = (struct ildevice *)ui->ui_addr; if (m == 0) { if ((is->is_flags & ILF_STATPENDING) == 0) return; addr->il_bar = is->is_ubaddr & 0xffff; addr->il_bcr = sizeof (struct il_stats); csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT|IL_RIE|IL_CIE; is->is_flags &= ~ILF_STATPENDING; goto startcmd; } len = if_wubaput(&is->is_ifuba, m); /* * Ensure minimum packet length. * This makes the safe assumtion that there are no virtual holes * after the data. * For security, it might be wise to zero out the added bytes, * but we're mainly interested in speed at the moment. */ if (len - sizeof(struct ether_header) < ETHERMIN) len = ETHERMIN + sizeof(struct ether_header); if (is->is_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_w.ifrw_bdp); addr->il_bar = is->is_ifuba.ifu_w.ifrw_info & 0xffff; addr->il_bcr = len; csr = ((is->is_ifuba.ifu_w.ifrw_info >> 2) & IL_EUA)|ILC_XMIT|IL_CIE|IL_RIE; startcmd: is->is_lastcmd = csr & IL_CMD; addr->il_csr = csr; is->is_flags |= ILF_OACTIVE; } /* * Command done interrupt. */ ilcint(unit) int unit; { register struct il_softc *is = &il_softc[unit]; struct uba_device *ui = ilinfo[unit]; register struct ildevice *addr = (struct ildevice *)ui->ui_addr; short csr; if ((is->is_flags & ILF_OACTIVE) == 0) { printf("il%d: stray xmit interrupt, csr=%b\n", unit, addr->il_csr, IL_BITS); return; } csr = addr->il_csr; /* * Hang receive buffer if it couldn't * be done earlier (in ilrint). */ if (is->is_flags & ILF_RCVPENDING) { int s; addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff; addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6; addr->il_csr = ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE; s = splhigh(); while ((addr->il_csr & IL_CDONE) == 0) ; splx(s); is->is_flags &= ~ILF_RCVPENDING; } is->is_flags &= ~ILF_OACTIVE; csr &= IL_STATUS; switch (is->is_lastcmd) { case ILC_XMIT: is->is_if.if_opackets++; if (csr > ILERR_RETRIES) is->is_if.if_oerrors++; break; case ILC_STAT: if (csr == ILERR_SUCCESS) iltotal(is); break; } if (is->is_ifuba.ifu_xtofree) { m_freem(is->is_ifuba.ifu_xtofree); is->is_ifuba.ifu_xtofree = 0; } ilstart(unit); } /* * Ethernet interface receiver interrupt. * If input error just drop packet. * Otherwise purge input buffered data path and examine * packet to determine type. If can't determine length * from type, then have to drop packet. Othewise decapsulate * packet based on type and pass to type specific higher-level * input routine. */ ilrint(unit) int unit; { register struct il_softc *is = &il_softc[unit]; struct ildevice *addr = (struct ildevice *)ilinfo[unit]->ui_addr; register struct il_rheader *il; struct mbuf *m; int len, off, resid, s; register struct ifqueue *inq; is->is_if.if_ipackets++; if (is->is_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_r.ifrw_bdp); il = (struct il_rheader *)(is->is_ifuba.ifu_r.ifrw_addr); len = il->ilr_length - sizeof(struct il_rheader); if ((il->ilr_status&(ILFSTAT_A|ILFSTAT_C)) || len < 46 || len > ETHERMTU) { is->is_if.if_ierrors++; #ifdef notdef if (is->is_if.if_ierrors % 100 == 0) printf("il%d: += 100 input errors\n", unit); #endif goto setup; } /* * Deal with trailer protocol: if type is trailer type * get true type from first 16-bit word past data. * Remember that type was trailer by setting off. */ il->ilr_type = ntohs((u_short)il->ilr_type); #define ildataaddr(il, off, type) ((type)(((caddr_t)((il)+1)+(off)))) if (il->ilr_type >= ETHERTYPE_TRAIL && il->ilr_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { off = (il->ilr_type - ETHERTYPE_TRAIL) * 512; if (off >= ETHERMTU) goto setup; /* sanity */ il->ilr_type = ntohs(*ildataaddr(il, off, u_short *)); resid = ntohs(*(ildataaddr(il, off+2, u_short *))); if (off + resid > len) goto setup; /* sanity */ len = off + resid; } else off = 0; if (len == 0) goto setup; /* * Pull packet off interface. Off is nonzero if packet * has trailing header; ilget will then force this header * information to be at the front, but we still have to drop * the type and length which are at the front of any trailer data. */ m = if_rubaget(&is->is_ifuba, len, off, &is->is_if); if (m == 0) goto setup; if (off) { struct ifnet *ifp; ifp = *(mtod(m, struct ifnet **)); m->m_off += 2 * sizeof (u_short); m->m_len -= 2 * sizeof (u_short); *(mtod(m, struct ifnet **)) = ifp; } switch (il->ilr_type) { #ifdef INET case ETHERTYPE_IP: schednetisr(NETISR_IP); inq = &ipintrq; break; case ETHERTYPE_ARP: arpinput(&is->is_ac, m); goto setup; #endif #ifdef NS case ETHERTYPE_NS: schednetisr(NETISR_NS); inq = &nsintrq; break; #endif default: m_freem(m); goto setup; } s = splimp(); if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); } else IF_ENQUEUE(inq, m); splx(s); setup: /* * Reset for next packet if possible. * If waiting for transmit command completion, set flag * and wait until command completes. */ if (is->is_flags & ILF_OACTIVE) { is->is_flags |= ILF_RCVPENDING; return; } addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff; addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6; addr->il_csr = ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE; s = splhigh(); while ((addr->il_csr & IL_CDONE) == 0) ; splx(s); } /* * Ethernet output routine. * Encapsulate a packet of type family for the local net. * Use trailer local net encapsulation if enough data in first * packet leaves a multiple of 512 bytes of data in remainder. */ iloutput(ifp, m0, dst) struct ifnet *ifp; struct mbuf *m0; struct sockaddr *dst; { int type, s, error; u_char edst[6]; struct in_addr idst; register struct il_softc *is = &il_softc[ifp->if_unit]; register struct mbuf *m = m0; register struct ether_header *il; register int off; int usetrailers; if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { error = ENETDOWN; goto bad; } switch (dst->sa_family) { #ifdef INET case AF_INET: idst = ((struct sockaddr_in *)dst)->sin_addr; if (!arpresolve(&is->is_ac, m, &idst, edst, &usetrailers)) return (0); /* if not yet resolved */ off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; if (usetrailers && off > 0 && (off & 0x1ff) == 0 && m->m_off >= MMINOFF + 2 * sizeof (u_short)) { type = ETHERTYPE_TRAIL + (off>>9); m->m_off -= 2 * sizeof (u_short); m->m_len += 2 * sizeof (u_short); *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); goto gottrailertype; } type = ETHERTYPE_IP; off = 0; goto gottype; #endif #ifdef NS case AF_NS: type = ETHERTYPE_NS; bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), (caddr_t)edst, sizeof (edst)); off = 0; goto gottype; #endif case AF_UNSPEC: il = (struct ether_header *)dst->sa_data; bcopy((caddr_t)il->ether_dhost, (caddr_t)edst, sizeof (edst)); type = il->ether_type; goto gottype; default: printf("il%d: can't handle af%d\n", ifp->if_unit, dst->sa_family); error = EAFNOSUPPORT; goto bad; } gottrailertype: /* * Packet to be sent as trailer: move first packet * (control information) to end of chain. */ while (m->m_next) m = m->m_next; m->m_next = m0; m = m0->m_next; m0->m_next = 0; m0 = m; gottype: /* * Add local net header. If no space in first mbuf, * allocate another. */ if (m->m_off > MMAXOFF || MMINOFF + sizeof (struct ether_header) > m->m_off) { m = m_get(M_DONTWAIT, MT_HEADER); if (m == 0) { error = ENOBUFS; goto bad; } m->m_next = m0; m->m_off = MMINOFF; m->m_len = sizeof (struct ether_header); } else { m->m_off -= sizeof (struct ether_header); m->m_len += sizeof (struct ether_header); } il = mtod(m, struct ether_header *); il->ether_type = htons((u_short)type); bcopy((caddr_t)edst, (caddr_t)il->ether_dhost, sizeof (edst)); bcopy((caddr_t)is->is_addr, (caddr_t)il->ether_shost, sizeof(il->ether_shost)); /* * Queue message on interface, and start output if interface * not yet active. */ s = splimp(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); splx(s); m_freem(m); return (ENOBUFS); } IF_ENQUEUE(&ifp->if_snd, m); if ((is->is_flags & ILF_OACTIVE) == 0) ilstart(ifp->if_unit); splx(s); return (0); bad: m_freem(m0); return (error); } /* * Watchdog routine, request statistics from board. */ ilwatch(unit) int unit; { register struct il_softc *is = &il_softc[unit]; register struct ifnet *ifp = &is->is_if; int s; if (is->is_flags & ILF_STATPENDING) { ifp->if_timer = is->is_scaninterval; return; } s = splimp(); is->is_flags |= ILF_STATPENDING; if ((is->is_flags & ILF_OACTIVE) == 0) ilstart(ifp->if_unit); splx(s); ifp->if_timer = is->is_scaninterval; } /* * Total up the on-board statistics. */ iltotal(is) register struct il_softc *is; { register u_short *interval, *sum, *end; interval = &is->is_stats.ils_frames; sum = &is->is_sum.ils_frames; end = is->is_sum.ils_fill2; while (sum < end) *sum++ += *interval++; is->is_if.if_collisions = is->is_sum.ils_collis; } /* * Process an ioctl request. */ ilioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { register struct ifaddr *ifa = (struct ifaddr *)data; register struct il_softc *is = &il_softc[ifp->if_unit]; int s = splimp(), error = 0; switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; ilinit(ifp->if_unit); switch (ifa->ifa_addr.sa_family) { #ifdef INET case AF_INET: ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr; arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); break; #endif #ifdef NS case AF_NS: { register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); if (ns_nullhost(*ina)) { ina->x_host = * (union ns_host *) (il_softc[ifp->if_unit].is_addr); } else { il_setaddr(ina->x_host.c_host, ifp->if_unit); return (0); } break; } #endif } break; case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_UP) == 0 && is->is_flags & ILF_RUNNING) { ((struct ildevice *) (ilinfo[ifp->if_unit]->ui_addr))->il_csr = ILC_RESET; is->is_flags &= ~ILF_RUNNING; } else if (ifp->if_flags & IFF_UP && (is->is_flags & ILF_RUNNING) == 0) ilinit(ifp->if_unit); break; default: error = EINVAL; } splx(s); return (error); } /* * set ethernet address for unit */ il_setaddr(physaddr, unit) u_char *physaddr; int unit; { register struct il_softc *is = &il_softc[unit]; if (! (is->is_flags & ILF_RUNNING)) return; bcopy((caddr_t)physaddr, (caddr_t)is->is_addr, sizeof is->is_addr); is->is_flags &= ~ILF_RUNNING; is->is_flags |= ILF_SETADDR; ilinit(unit); } #endif (is->is_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_w.ifrw_bdp); addr->il_bar = is->is_ifuba.ifu_w.ifrw_info & 0xffff; addr->il_bcr = len; csr = ((is->is_ifuba.ifu_w.ifrw_info >> 2) & IL_EUA)|ILC_XMIT|IL_CIE|IL_RIE; startcmd: is->is_lastcmd = csr & IL_CMD; addr->il_csr = csr; is->is_flags sys/vaxif/if_hy.h 444 0 12 22167 3671247644 7275 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_hy.h 7.1 (Berkeley) 6/5/86 */ /* * 4.2 BSD Unix Kernel - Vax Network Interface Support * * $Header: if_hy.h,v 10.0 84/06/30 19:51:21 steveg Stable $ * $Locker: $ * * Modifications from Berkeley 4.2 BSD * Copyright (c) 1983, Tektronix Inc. * All Rights Reserved * * * $Log: if_hy.h,v $ * Revision 10.0 84/06/30 19:51:21 steveg * Big Build * * Revision 3.13 84/05/30 19:40:58 steveg * update hy_stat to reflect new microcode * * Revision 3.12 84/05/30 19:06:57 steveg * move driver state number definition here from if_hy.c * * Revision 3.11 84/05/30 18:56:15 steveg * add definition of HYE_MAX and HYE_SIZE * * Revision 3.10 84/05/30 17:14:04 steveg * add hyl_filter * * Revision 3.9 84/05/30 13:45:24 steveg * rework logging * * Revision 3.8 84/05/04 05:18:59 steveg * hyr_key now a u_long * * Revision 3.7 84/05/01 22:45:20 steveg * add H_RLOOPBK for A710 remote end loopback command * * */ /* * Structure of a HYPERchannel adapter header */ struct hy_hdr { short hyh_ctl; /* control */ short hyh_access; /* access code */ union { short hyh_addr; char hyh_baddr[2]; } hyh_uto, hyh_ufrom; /* to/from address */ short hyh_param; /* parameter word */ short hyh_type; /* record type */ }; #define hyh_to hyh_uto.hyh_addr #define hyh_to_port hyh_uto.hyh_baddr[1] #define hyh_to_adapter hyh_uto.hyh_baddr[0] #define hyh_from hyh_ufrom.hyh_addr #define hyh_from_port hyh_ufrom.hyh_baddr[1] #define hyh_from_adapter hyh_ufrom.hyh_baddr[0] /* * Structure of a HYPERchannel message header (from software) */ struct hym_hdr { struct { short hymd_mplen; /* message proper len, if associated data */ } hym_d; struct hy_hdr hym_h; /* hardware header, MUST BE LAST */ }; #define hym_mplen hym_d.hymd_mplen #define hym_ctl hym_h.hyh_ctl #define hym_access hym_h.hyh_access #define hym_param hym_h.hyh_param #define hym_type hym_h.hyh_type #define hym_to hym_h.hyh_to #define hym_to_port hym_h.hyh_to_port #define hym_to_adapter hym_h.hyh_to_adapter #define hym_from hym_h.hyh_from #define hym_from_port hym_h.hyh_from_port #define hym_from_adapter hym_h.hyh_from_adapter #define HYM_SWLEN (sizeof(struct hym_hdr) - sizeof(struct hy_hdr)) /* * HYPERchannel header word control bits */ #define H_XTRUNKS 0x00F0 /* transmit trunks */ #define H_RTRUNKS 0x000F /* remote trunks to transmit on for loopback */ #define H_ASSOC 0x0100 /* has associated data */ #define H_LOOPBK 0x00FF /* loopback command */ #define H_RLOOPBK 0x008F /* A710 remote loopback command */ /* * Hyperchannel record types */ #define HYLINK_IP 0 /* Internet Protocol Packet */ /* * Routing database */ #define HYRSIZE 37 /* max number of adapters in routing tables */ struct hy_route { time_t hyr_lasttime; /* last update time */ u_char hyr_gateway[256]; struct hyr_hash { u_long hyr_key; /* desired address */ u_short hyr_flags; /* status flags - see below */ u_short hyr_size; /* number of entries */ union { /* * direct entry (can get there directly) */ struct { u_short hyru_dst; /* adapter number & port */ u_short hyru_ctl; /* trunks to try */ u_short hyru_access; /* access code (mostly unused) */ } hyr_d; #define hyr_dst hyr_u.hyr_d.hyru_dst #define hyr_ctl hyr_u.hyr_d.hyru_ctl #define hyr_access hyr_u.hyr_d.hyru_access /* * indirect entry (one or more hops required) */ struct { u_char hyru_pgate; /* 1st gateway slot */ u_char hyru_egate; /* # gateways */ u_char hyru_nextgate; /* gateway to use next */ } hyr_i; #define hyr_pgate hyr_u.hyr_i.hyru_pgate #define hyr_egate hyr_u.hyr_i.hyru_egate #define hyr_nextgate hyr_u.hyr_i.hyru_nextgate } hyr_u; } hyr_hash[HYRSIZE]; }; /* * routing table set/get structure * * used to just pass the entire routing table through, but 4.2 ioctls * limit the data part of an ioctl to 128 bytes or so and use the * interface name to get things sent the right place. * see ../net/if.h for additional details. */ struct hyrsetget { char hyrsg_name[IFNAMSIZ]; /* if name, e.g. "hy0" */ struct hy_route *hyrsg_ptr; /* pointer to routing table */ unsigned hyrsg_len; /* size of routing table provided */ }; #define HYR_INUSE 0x01 /* entry in use */ #define HYR_DIR 0x02 /* direct entry */ #define HYR_GATE 0x04 /* gateway entry */ #define HYR_LOOP 0x08 /* hardware loopback entry */ #define HYR_RLOOP 0x10 /* remote adapter hardware loopback entry */ #define HYRHASH(x) (((x) ^ ((x) >> 16)) % HYRSIZE) #define HYSETROUTE _IOW(i, 0x80, struct hyrsetget) #define HYGETROUTE _IOW(i, 0x81, struct hyrsetget) struct hylsetget { char hylsg_name[IFNAMSIZ]; /* if name, e.g. "hy0" */ int hylsg_cmd; /* logging command */ caddr_t hylsg_ptr; /* pointer to table */ u_long hylsg_len; /* size of table provided */ }; #define HYSETLOG _IOW(i, 0x82, struct hylsetget) #define HYGETLOG _IOW(i, 0x83, struct hylsetget) #define HYGETELOG _IOW(i, 0x84, struct hylsetget) /* * Structure of Statistics Record (counters) */ struct hy_stat { u_char hyc_df0[3]; /* # data frames trunk 0 */ u_char hyc_df1[3]; /* # data frames trunk 1 */ u_char hyc_df2[3]; /* # data frames trunk 2 */ u_char hyc_df3[3]; /* # data frames trunk 3 */ u_char hyc_cancel[2]; /* # cancel operations */ u_char hyc_abort[2]; /* # aborts */ u_char hyc_ret0[3]; /* # retransmissions trunk 0 */ u_char hyc_ret1[3]; /* # retransmissions trunk 1 */ u_char hyc_ret2[3]; /* # retransmissions trunk 2 */ u_char hyc_ret3[3]; /* # retransmissions trunk 3 */ u_char hyc_atype[3]; /* adapter type and revision level */ u_char hyc_uaddr; /* adapter unit number */ }; /* * Structure of the Status Record */ struct hy_status { u_char hys_gen_status; /* general status byte */ u_char hys_last_fcn; /* last function code issued */ u_char hys_resp_trunk; /* trunk response byte */ u_char hys_status_trunk; /* trunk status byte */ u_char hys_recd_resp; /* recieved response byte */ u_char hys_error; /* error code */ u_char hys_caddr; /* compressed addr of 1st msg on chain */ u_char hys_pad; /* not used */ }; /* * Get port number from status record */ #define PORTNUM(p) (((p)->hys_gen_status >> 6) & 0x03) #define HYL_SIZE 16*1024 struct hy_log { struct hy_log *hyl_self; u_char hyl_enable; /* logging enabled? */ u_char hyl_onerr; /* state to enter on error */ u_short hyl_wait; /* number of bytes till next wakeup */ u_short hyl_count; /* number of samples till stop */ u_short hyl_icount; /* initial value of hyl_count */ u_long hyl_filter; /* log items with specific bits set */ u_char *hyl_eptr; /* &hy_log.hyl_buf[HYL_SIZE] */ u_char *hyl_ptr; /* pointer into hyl_buf */ u_char hyl_buf[HYL_SIZE]; /* log buffer space */ }; #define HYL_NOP 0 #define HYL_UP 1 /* markup */ #define HYL_STATUS 2 /* status results (struct hy_status) */ #define HYL_STATISTICS 3 /* statistics (struct hy_stat) */ #define HYL_XMIT 4 /* packed being send (struct hym_hdr) */ #define HYL_RECV 5 /* recieved pkt (short len; struct hym_hdr) */ #define HYL_CMD 6 /* cmd issued (uchar cmd, state; short count) */ #define HYL_INT 7 /* interrupt (short csr, wcr) */ #define HYL_CANCEL 8 /* cancel transmit attempt */ #define HYL_RESET 9 /* hyinit or unibus reset */ #define HYL_IOCTL 10 /* hyioctl */ #define HYL_DISABLED 0 /* logging disabled */ #define HYL_CONTINUOUS 1 /* continuous logging */ #define HYL_CATCHN 2 /* hyl_count transactions being captured */ /* * error code histograms */ #define HYE_MAX 0x18 /* maximum adapter error code */ #define HYE_BINS 4 /* number of command bins */ #define HYE_SIZE (HYE_MAX+1)*HYE_BINS /* size of histogram buffer */ /* * Requests for service (in order by descending priority). */ #define RQ_ENDOP 001 /* end the last adapter function */ #define RQ_REISSUE 002 /* reissue previous cmd after status */ #define RQ_STATUS 004 /* get the status of the adapter */ #define RQ_STATISTICS 010 /* get the statistics of the adapter */ #define RQ_MARKDOWN 020 /* mark this adapter port down */ #define RQ_MARKUP 040 /* mark this interface up */ #define RQ_XASSOC 0100 /* associated data to transmit */ /* * Driver states. */ #define STARTUP 0 /* initial state (before fully there) */ #define IDLE 1 /* idle state */ #define STATSENT 2 /* status cmd sent to adapter */ #define ENDOPSENT 3 /* end operation cmd sent */ #define RECVSENT 4 /* input message cmd sent */ #define RECVDATASENT 5 /* input data cmd sent */ #define XMITSENT 6 /* transmit message cmd sent */ #define XMITDATASENT 7 /* transmit data cmd sent */ #define WAITING 8 /* waiting for messages */ #define CLEARSENT 9 /* clear wait for message cmd sent */ #define MARKPORT 10 /* mark this host's adapter port down issued */ #define RSTATSENT 11 /* read statistics cmd sent to adapter */ #ifdef HYLOG char *hy_state_names[] = { "Startup", "Idle", "Status Sent", "End op Sent", "Recieve Message Proper Sent", "Recieve Data Sent", "Transmit Message Proper Sent", "Transmit Data Sent", "Wait for Message Sent", "Clear Wait for Message Sent", "Mark Port Down Sent", "Read Statistics Sent" }; #endif is->is_flags |= ILF_SETADDR; ilinit(unit); } #endif (is->is_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_w.ifrw_bdp); addr->il_bar = is->is_ifuba.ifu_w.ifrw_info & 0xffff; addr->il_bcr = len; csr = ((is->is_ifuba.ifu_w.ifrw_info >> 2) & IL_EUA)|ILC_XMIT|IL_CIE|IL_RIE; startcmd: is->is_lastcmd = csr & IL_CMD; addr->il_csr = csr; is->is_flags sys/vaxif/if_enreg.h 444 0 12 2360 3671247546 7727 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_enreg.h 7.1 (Berkeley) 6/5/86 */ /* * Xerox experimental ethernet registers. * * N.B.: status register and device address are read/write, * device address is read-only, rest are WRITE ONLY! */ struct endevice { short en_owc; /* output word count (10 bits) */ short en_oba; /* output buffer address */ short en_ostat; /* output control and status */ short en_odelay; /* output start delay, 25usec units */ short en_iwc; /* input word count */ short en_iba; /* input buffer address */ short en_istat; /* input csr */ short en_addr; /* ~device address (low 8 bits) */ }; /* * Control and status bits. */ #define EN_IERROR 0x8000 /* CRC error, buf ovflo or overrun */ #define EN_OERROR 0x8000 /* collision or output underrun */ #define EN_OPDONE 0x0080 /* previous operation completed */ #define EN_IEN 0x0040 /* enable interrupt when DONE */ #define EN_PROMISCUOUS 0x0002 /* promiscuous, input any packet */ #define EN_GO 0x0001 /* start op bit */ #define EN_BITS "\10\20ERR\10OPDONE\7IEN\2PROM\1GO" #define spl_enet() spl5() f2[3]; /* # data frames trunk 2 */ u_char hyc_df3[3]; /* # data frames trunk 3 */ u_char hyc_cancel[2]; /* # cancel operations */ u_char hyc_abort[2]; /* # aborts */ u_char hyc_ret0[3]; /* # retransmissions trunk 0 */ u_char hyc_ret1[3]; /* # retransmissions trsys/vaxif/tags 751 0 12 0 6045325661 10512 2../sys/tagssys/vaxif/if_ddn.c 444 0 12 133041 3671424222 7414 /* @(#)if_ddn.c 7.1 (Berkeley) 6/5/86 */ /************************************************************************\ ________________________________________________________ / \ | AAA CCCCCCCCCCCCCC CCCCCCCCCCCCCC | | AAAAA CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC | | AAAAAAA CCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCC | | AAAA AAAA CCCC CCCC | | AAAA AAAA CCCC CCCC | | AAAA AAAA CCCC CCCC | | AAAA AAAA CCCC CCCC | | AAAA AAAAAAAAAAA CCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCC | | AAAA AAAAAAAAAAA CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC | | AAAA AAAAAAAAA CCCCCCCCCCCCCC CCCCCCCCCCCCCC | \________________________________________________________/ Copyright (c) 1985 by Advanced Computer Communications 720 Santa Barbara Street, Santa Barbara, California 93101 (805) 963-9431 This software may be duplicated and used on systems which are licensed to run U.C. Berkeley versions of the UNIX operating system. Any duplication of any part of this software must include a copy of ACC's copyright notice. File: if_ddn.c Author: Art Berggreen Project: 4.2 DDN X.25 network driver Function: This is a network device driver for BSD 4.2 UNIX which provides an interface between IP and ACC's ACP625 (IF-11/X25) for connecting to the Defense Data Network. Components: Revision History: 16-May-1985: V1.0 - First release. Art Berggreen. \************************************************************************/ /* if_ddn.c V1.0 5/16/85 */ /* * ACC ACP625 DDN/X.25 Network device driver */ /* #define DDNDEBUG 1 /* Enable definition for Debug code */ #include "ddn.h" #if NDDN > 0 #include "../machine/pte.h" #include "param.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "protosw.h" #include "socket.h" #include "vmmac.h" #include "errno.h" #include "time.h" #include "kernel.h" #include "ioctl.h" #include "../net/if.h" #include "../net/netisr.h" #include "../net/route.h" #ifdef INET #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netinet/in_var.h" #include "../netinet/ip.h" #endif #include "../vax/cpu.h" #include "../vax/mtpr.h" #include "if_ddnreg.h" #include "if_ddnvar.h" #include "if_uba.h" #include "../vaxuba/ubareg.h" #include "../vaxuba/ubavar.h" /* declare global functions */ int ddnprobe(); int ddnattach(); int ddnreset(); int ddninit(); int ddnoutput(); int ddntimer(); int ddnioctl(); int ddnintr(); /* declare local functions */ static void x25_init(); static struct ddn_cb *locate_x25_lcn(); static boolean convert_ip_addr(); static int convert_x25_addr(); static boolean make_x25_call(); static void ddn_start(); static void ddn_iorq(); static void start_chn(); static void ddn_data(); static void ddn_supr(); static void supr_msg(); static boolean decode_ring(); static void clear_lcn(); static void send_restart(); static void send_supr(); #ifdef DDNDEBUG static void prt_addr(); static void prt_bytes(); #endif DDNDEBUG struct uba_device *ddninfo[NDDN]; /* ptrs to device info */ u_short ddnstd[] = { 0766740, 0 }; /* standard addresses */ struct uba_driver ddndriver = /* device driver info */ { ddnprobe, /* device probe routine */ 0, /* slave probe routine */ ddnattach, /* device attach routine */ 0, /* "dmago" routine */ ddnstd, /* device address */ "ddn", /* device name */ ddninfo /* ptr to device info ptrs */ }; static u_char init_msg[] = { LINE_CNTL, /* set command code */ 0x00, /* not used */ 0x00, /* not used */ 0x00, /* extension length (set at runtime) */ LINK_DISABLE, /* link disable */ /* LINK_LOOPBACK, /* loopback mode */ /* LOOP_INTERNAL, /* = internal loopback */ PKT_SIZE, /* packet size */ 0x80, /* 128 - LSB */ 0x00, /* 128 - MSB */ PKT_WINDOW, /* packet window */ 0x02, /* = 2 */ LINK_ENABLE /* link enable */ }; u_char cb_cmnd[4] = { CALL, 0, 0, 0 }; u_char cb_called_addr[16] = {0}; u_char cb_calling_addr[16] = {0}; u_char cb_facilities[64] = {0}; u_char cb_protocol[5] = {0}; u_char cb_user_data[1] = {0}; #ifdef DDNDEBUG int ddn_debug = 1; /* values 0-8 cause increasing verbosity */ #endif DDNDEBUG /***********************************************************************\ * * * Information for each device unit is maintained in an array * * of structures named ddn_softc[]. The array is indexed by * * unit number. Each entry includes the network interface * * structure (ddn_if) used by the routing code to locate the * * interface, an array of Logical Channel control blocks which * * maintain information about each of the Logical Channels (LCNs) * * through which X.25 virtual calls are established, a queue of * * I/O requests pending for the UMC, the UNIBUS interrupt vector * * for the unit and misc flags. The Logical Channel Control * * blocks maintain information about the state of each LCN, * * a queue of outbound data, Half Duplex Channel (HDX) blocks * * used for queuing I/O requests to the UMC and an ifuba * * structure which records the UNIBUS resources being held by * * the LCN. * * * \***********************************************************************/ struct sioq /* Start I/O queue head */ { struct hdx_chan *sq_head; /* queue head */ struct hdx_chan *sq_tail; /* queue tail */ }; struct hdx_chan /* HDX channel block */ { struct hdx_chan *hc_next; /* link to next HDX channel */ u_char hc_chan; /* HDX channel number */ u_char hc_adx; /* address bits 17-16 */ u_short hc_addr; /* address bits 15-00 */ u_short hc_cnt; /* byte count */ u_char hc_func; /* I/O function */ u_char hc_sbfc; /* I/O subfunction */ }; struct ddn_cb /* Logical Channel control block */ { struct in_addr dc_inaddr; /* remote Internet address */ u_char dc_lcn; /* LCN number */ u_char dc_state; /* LCN state */ u_short dc_timer; /* LCN timer */ struct ifqueue dc_oq; /* LCN output queue */ struct hdx_chan dc_rchan; /* LCN read HDX channel */ struct hdx_chan dc_wchan; /* LCN write HDX channel */ struct ifuba dc_ifuba; /* UNIBUS resources */ u_short dc_flags; /* misc flags */ }; struct ddn_softc /* device control structure */ { struct ifnet ddn_if; /* network-visible interface */ struct ddn_cb ddn_cb[NDDNCH+1]; /* Logical Channel cntl blks */ struct sioq ddn_sioq; /* start I/O queue */ int ddn_vector; /* UNIBUS interrupt vector */ u_short ddn_flags; /* misc flags */ struct in_addr ddn_ipaddr; /* local IP address */ } ddn_softc[NDDN]; /***********************************************************************\ * ddnprobe() * ************************************************************************* * * * This routine probes the device to obtain the UNIBUS interrupt * * vector. Since the UMC is a soft vector device, we obtain * * an unused vector from the uba structure and return that. * * The UMC is given the vector and the board is reset. * * In order to save the vector in the device info structure, we * * place it in a static temporary where the attach routine can * * find it and save it in the device info structure. This is * * necessary because probe only provides a pointer to the device * * and we have no idea which unit is being referenced. This * * works in 4.2 because the attach routine is called immediately * * after a successful probe. * * * \***********************************************************************/ #define INIT_DELAY (100 * 2) /* time for board initialization */ /* ( in 10 millisecond ticks) */ static int savevec; /* static variable for vector */ ddnprobe(reg) caddr_t reg; { register int br, cvec; /* r11, r10 value-result */ register struct ddnregs *addr = (struct ddnregs *)reg; register int delay_time; #ifdef lint br = 0; cvec = br; br = cvec; ddnintr(0); #endif cvec = savevec = (uba_hd[numuba].uh_lastiv -= 4); /* return vector */ br = 0x15; /* return bus level */ addr->ioini = 0; /* clear handshake flags */ addr->ionmi = 0; addr->staack = 0; addr->xfrgnt = 0; addr->iovect = cvec >> 2; /* pass vector to UMC */ addr->csr = DDN_RST; /* reset the board */ delay_time = mfpr(TODR) + INIT_DELAY; while(delay_time > mfpr(TODR)) /* wait */ ; return (sizeof(struct ddnregs)); } /***********************************************************************\ * ddnattach * ************************************************************************* * * * This routine attaches the device to the network software. * * The network interface structure is filled in. The device * * will be initialized when the system is ready to accept packets. * * * \***********************************************************************/ ddnattach(ui) struct uba_device *ui; { register struct ddn_softc *ds = &ddn_softc[ui->ui_unit]; ds->ddn_vector = savevec; /* save vector from probe() */ ds->ddn_if.if_unit = ui->ui_unit; /* set unit number */ ds->ddn_if.if_name = "ddn"; /* set device name */ ds->ddn_if.if_mtu = DDNMTU; /* set max msg size */ ds->ddn_if.if_init = ddninit; /* set init routine addr */ ds->ddn_if.if_ioctl = ddnioctl; /* set ioctl routine addr */ ds->ddn_if.if_output = ddnoutput; /* set output routine addr */ ds->ddn_if.if_reset = ddnreset; /* set reset routine addr */ ds->ddn_if.if_watchdog = ddntimer; /* set timer routine addr */ if_attach(&ds->ddn_if); } /***********************************************************************\ * ddnreset() * ************************************************************************* * * * Reset of interface after UNIBUS reset. * * If interface is on specified uba, reset its state. * * * \***********************************************************************/ ddnreset(unit, uban) int unit, uban; { register struct uba_device *ui; register struct ddnregs *addr; register int delay_time; if (unit >= NDDN || (ui = ddninfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" ddn%d", unit); addr = (struct ddnregs *)ui->ui_addr; addr->ioini = 0; /* clear handshake flags */ addr->ionmi = 0; addr->staack = 0; addr->xfrgnt = 0; addr->iovect = ddn_softc[unit].ddn_vector >> 2; /* pass vector to UMC */ addr->csr = DDN_RST; /* reset the board */ delay_time = mfpr(TODR) + INIT_DELAY; while(delay_time > mfpr(TODR)) /* wait */ ; ddninit(unit); } /***********************************************************************\ * ddninit() * ************************************************************************* * * * This routine initializes the interface for operation. The * * device control blocks are initialized, UNIBUS resources are * * allocated and an X.25 initialization message is sent to the * * UMC. * * * \***********************************************************************/ ddninit(unit) int unit; { register struct ddn_softc *ds = &ddn_softc[unit]; register struct ddn_cb *dc; register struct uba_device *ui = ddninfo[unit]; int lcn, s; #ifdef DDNDEBUG if (ddn_debug > 0) { printf("ddn%d: ddninit()\n", unit); } #endif DDNDEBUG if (ds->ddn_if.if_addrlist == 0) /* if we have no internet addr */ return; /* don't init yet */ dc = ds->ddn_cb; /* setup ptr to first LCN cntl block */ for(lcn = 0; lcn <= NDDNCH; lcn++) /* for all LCN's ... */ { dc->dc_lcn = lcn; /* record LCN */ dc->dc_inaddr.s_addr = 0; /* clear remote internet addr */ dc->dc_state = LC_DOWN; /* init LCN state */ dc->dc_timer = TMO_OFF; /* turn LCN timer off */ /* init LCN output queue */ dc->dc_oq.ifq_head = (struct mbuf *)0; dc->dc_oq.ifq_tail = (struct mbuf *)0; dc->dc_oq.ifq_len = 0; dc->dc_oq.ifq_maxlen = DDN_OQMAX; dc->dc_oq.ifq_drops = 0; /* init HDX channels */ dc->dc_rchan.hc_next = (struct hdx_chan *)0; dc->dc_rchan.hc_chan = lcn * 2; dc->dc_wchan.hc_next = (struct hdx_chan *)0; dc->dc_wchan.hc_chan = (lcn * 2) + 1; /* init UNIBUS resources */ if (if_ubainit(&dc->dc_ifuba, ui->ui_ubanum, 0, (int)btoc(DDNMTU)) == 0) { printf("ddn%d: failed getting UBA resources for lcn %d\n", unit, lcn); ds->ddn_if.if_flags &= ~(IFF_RUNNING | IFF_UP); return; } dc->dc_flags = 0; /* initialize flags */ dc++; /* point at next cntl blk */ } ds->ddn_sioq.sq_head = (struct hdx_chan *)0; ds->ddn_sioq.sq_tail = (struct hdx_chan *)0; ds->ddn_if.if_flags |= IFF_RUNNING; s = splimp(); dc = ds->ddn_cb; /* setup ptr to first LCN cntl block */ for(lcn = 0; lcn <= NDDNCH; lcn++) /* issue reads on all LCNs */ { ddn_iorq(ds, dc, DDNMTU, DDNRDB+DDNSTR); dc++; } x25_init(ds); /* init the X.25 board */ splx(s); ddntimer(unit); /* start timers */ } /***********************************************************************\ * ddnoutput() * ************************************************************************* * * * This routine is called by the network software when it has * * an IP datagram to send out this interface. An attempt is * * made to find a LCN which has a virtual circuit open to the * * indicated host. If an LCN is found the packet is queued for * * output on that LCN. * * * \***********************************************************************/ ddnoutput(ifp, m0, dst) struct ifnet *ifp; struct mbuf *m0; struct sockaddr_in *dst; { register struct mbuf *m = m0; register struct ddn_softc *ds = &ddn_softc[ifp->if_unit]; register struct ddn_cb *dc; register struct ifqueue *oq; int s; if ((ds->ddn_if.if_flags & IFF_UP) == 0) return (ENETDOWN); switch (dst->sin_family) { #ifdef INET case AF_INET: break; #endif INET default: printf("ddn%d: can't handle af%d\n", ifp->if_unit, dst->sin_family); m_freem(m0); return (EAFNOSUPPORT); } #ifdef DDNDEBUG if (ddn_debug > 6) { printf("ddnoutput(): dst = "); prt_addr(dst->sin_addr.s_addr); printf("\n"); } #endif DDNDEBUG s = splimp(); /* try to find an LCN */ if (dc = locate_x25_lcn(ds, dst->sin_addr)) { /* if found */ oq = &(dc->dc_oq); /* point to output queue */ dc->dc_state = LC_DATA_IDLE; dc->dc_timer = TMO_DATA_IDLE; if (IF_QFULL(oq)) /* if q full */ { IF_DROP(oq); /* drop the data */ m_freem(m); splx(s); return (ENOBUFS); } IF_ENQUEUE(oq, m); /* otherwise queue it */ ddn_start(ds, dc); /* and try to output */ splx(s); return (0); } else /* if no circuit available */ { IF_DROP(&ifp->if_snd); /* drop the data */ m_freem(m); splx(s); return (EHOSTUNREACH); } } /***********************************************************************\ * ddntimer() * ************************************************************************* * * * This routine is entered once a second to perform timer * * managment. The LCN table is scanned for active timers, * * (nonzero) which are decremented. If a timer expires * * (becomes zero), the proper action is taken. * * * \***********************************************************************/ int ddntimer(unit) int unit; { register struct ddn_softc *ds = &ddn_softc[unit]; register struct ddn_cb *dc; register int s, lcn; #ifdef DDNDEBUG if (ddn_debug > 7) { printf("ddntimer()\n"); } #endif DDNDEBUG ds->ddn_if.if_timer = DDN_TIMEOUT; /* restart timer */ dc = ds->ddn_cb; s = splimp(); for(lcn = 0; lcn <= NDDNCH; lcn++) /* scan all LCN's */ { if (dc->dc_timer && (--(dc->dc_timer) == 0)) { /* if a timer expired */ if (dc->dc_state == LC_RESTART) { /* if a restart was out */ send_restart(ds); /* send another one */ break; } else /* otherwise */ { clear_lcn(ds, dc); /* clear the LCN */ } } dc++; } splx(s); } /***********************************************************************\ * ddnioctl() * ************************************************************************* * * * This routine processes device dependent ioctl's. Currently, * * the only ioctl supported is used to set the host's internet * * address for this network interface. * * * \***********************************************************************/ ddnioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { struct ifaddr *ifa = (struct ifaddr *) data; int s = splimp(), error = 0; switch (cmd) { case SIOCSIFADDR: if (ifa->ifa_addr.sa_family != AF_INET) return(EINVAL); ifp->if_flags |= IFF_UP; if ((ifp->if_flags & IFF_RUNNING) == 0) ddninit(ifp->if_unit); ddn_softc[ifp->if_unit].ddn_ipaddr = IA_SIN(ifa)->sin_addr; break; default: error = EINVAL; break; } splx(s); return (error); } /***********************************************************************\ * ddnintr() * ************************************************************************* * * * This is the interrupt handler for UNIBUS interrupts from the * * UMC. The interrupting HDX channel and interrupt type are * * obtained from the completion comm regs. If the interrupt is * * an I/O request acknowledge, the next I/O request is passed * * to the UMC. If the interrupt is an I/O completion, the * * completion is processed depending on whether it is for the * * supervisor or a data channel. * * * \***********************************************************************/ ddnintr(unit) int unit; { register struct ddn_softc *ds = &ddn_softc[unit]; register struct hdx_chan *hc; register struct ddnregs *addr = (struct ddnregs *)ddninfo[unit]->ui_addr; int chan, type, cc, cnt; /* * Check for hardware errors. */ if (addr->csr & DDN_UER) { printf("ddn%d: hard error csr=%b\n", unit, addr->csr, DDN_BITS); addr->csr = 0; /* disable i/f */ return; } /* * Get logical channel info. */ if ((chan = addr->stachn) >= ((NDDNCH+1)*2)) { printf("ddn%d: unknown channel, chan=%d\n", unit, chan); return; } if (chan & 0x01) hc = &(ds->ddn_cb[chan/2].dc_wchan); else hc = &(ds->ddn_cb[chan/2].dc_rchan); type = addr->statyp; cc = addr->stacc; cnt = hc->hc_cnt - addr->stacnt; /* Figure out what kind of interrupt it was */ switch(type) { case DDNSACK: /* start i/o accepted */ if (hc != ds->ddn_sioq.sq_head) /* does ack match waiting req? */ { printf("ddn%d: STARTIO error chan=%d hc=%x sq=%x\n", unit, chan, hc, ds->ddn_sioq.sq_head); addr->csr = 0; /* disable UMC */ return; } /* dequeue old request by copying link to queue head */ /* and start next I/O request if queue has not gone empty */ if (ds->ddn_sioq.sq_head = ds->ddn_sioq.sq_head->hc_next) { start_chn(ds); } break; case DDNDONE: /* i/o completion */ switch (cc) { case DDNIOCABT: /* probably VCN flush */ break; case DDNIOCERR: printf("ddn%d: program error ", unit); goto daterr; case DDNIOCOVR: printf("ddn%d: overrun error ", unit); goto daterr; case DDNIOCUBE: printf("ddn%d: NXM timeout or UB parity error ", unit); daterr: printf("chan=%d func=%x\n", chan, hc->hc_func); if (hc->hc_func & DDNRDB) ds->ddn_if.if_ierrors++; else ds->ddn_if.if_oerrors++; } /* was it supervisor or data traffic? */ if (chan > 1) ddn_data(unit, chan, cc, cnt); else ddn_supr(unit, chan, cc); } /* * Ack the interrupt */ addr->staack = 1; if (!(addr->ionmi)) { addr->ionmi = 1; addr->csr = DDN_DMA|DDN_WRT|DDN_IEN|DDN_NMI; } } /***********************************************************************\ * x25_init() * ************************************************************************* * * * This routine builds and sends an X.25 initialization msg * * to the UMC. * * * \***********************************************************************/ static void x25_init(ds) struct ddn_softc *ds; { struct mbuf *m; #ifdef DDNDEBUG if (ddn_debug > 0) { printf("ddn%d: x25_init()\n", ds->ddn_if.if_unit); } #endif DDNDEBUG MGET(m, M_DONTWAIT, MT_DATA); /* try to get X25 init buffer */ if (m == 0) { printf("ddn%d: couldn't get X25 init buffer\n", ds->ddn_if.if_unit); return; } init_msg[3] = sizeof(init_msg) - 4; /* set cmnd ext length */ bcopy((caddr_t)init_msg, mtod(m, caddr_t), sizeof(init_msg)); m->m_len = sizeof(init_msg); /* set msg length */ IF_ENQUEUE(&(ds->ddn_cb[0].dc_oq), m); ddn_start(ds, &(ds->ddn_cb[0])); } /***********************************************************************\ * locate_x25_lcn() * ************************************************************************* * * * This routine tries to locate an X25 LCN associated with a * * remote internet address. A linear search of the LCN table * * is made for a matching address. If the search succeeds, the * * LCN is returned. If the search fails, the LCN table is * * searched for an unused table entry. If an unused table entry * * is found, an X25 call is generated to the host specified in * * the destination internet address. If no LCN is available, * * zero is returned. * * * \***********************************************************************/ static struct ddn_cb *locate_x25_lcn(ds, ip_addr) struct ddn_softc *ds; struct in_addr ip_addr; { register int lcn; register struct ddn_cb *dc; #ifdef DDNDEBUG if (ddn_debug > 6) { printf("locate_x25_lcn()\n"); } #endif DDNDEBUG dc = &(ds->ddn_cb[1]); for(lcn = 1; lcn <= NDDNCH; lcn++) /* scan LCN table for addr match */ { if (dc->dc_inaddr.s_addr == ip_addr.s_addr) /* if found */ return(dc); /* return LCN */ dc++; } dc = &(ds->ddn_cb[1]); for(lcn = 1; lcn <= NDDNCH; lcn++) /* scan LCN table for free entry */ { if (dc->dc_state == LC_IDLE) break; dc++; } if (lcn > NDDNCH) /* if we didn't find a free entry */ return(0); /* return empty handed */ if (convert_ip_addr(ip_addr, cb_called_addr) && make_x25_call(ds, dc)) { /* addr can be converted */ dc->dc_inaddr.s_addr = ip_addr.s_addr; return(dc); /* and return the LCN */ } else { return(0); /* give up */ } } /***********************************************************************\ * convert_ip_addr() * ************************************************************************* * * * This routine accepts an internet address and attempts to * * translate to an equivalent X25 address. For DDN this follows * * the guidelines in the DDN X25 interface spec. The resultant * * X25 address is stored in the X25 called addr buffer. The * * routine returns TRUE if successfull, FALSE otherwise. * * * * NOTE: Although IF-11/X25 was designed to accept ASCII coded * * digits for the address fields, we only supply the binary * * values. The front-end only uses the low four bits to extract * * the binary value from the ASCII digits, so this works out. * * * \***********************************************************************/ static boolean convert_ip_addr(ip_addr, x25addr) struct in_addr ip_addr; u_char x25addr[]; { register int temp; union { struct in_addr ip; struct { /* (assumes Class A network number) */ u_char s_net; u_char s_host; u_char s_lh; u_char s_impno; } imp; } imp_addr; imp_addr.ip = ip_addr; x25addr[0] = 14; /* set addr length */ x25addr[1] = 0; /* clear DNIC */ x25addr[2] = 0; x25addr[3] = 0; x25addr[4] = 0; if (imp_addr.imp.s_host < 64) /* Physical: 0000 0 IIIHH00 [SS] */ { /* s_impno -> III, s_host -> HH */ x25addr[5] = 0; /* set flag bit */ x25addr[6] = imp_addr.imp.s_impno / 100; x25addr[7] = (imp_addr.imp.s_impno % 100) / 10; x25addr[8] = imp_addr.imp.s_impno % 10; x25addr[9] = imp_addr.imp.s_host / 10; x25addr[10] = imp_addr.imp.s_host % 10; } else /* Logical: 0000 1 RRRRR00 [SS] */ { /* s_host * 256 + s_impno -> RRRRR */ temp = (imp_addr.imp.s_host << 8) + imp_addr.imp.s_impno; x25addr[5] = 1; x25addr[6] = temp / 10000; x25addr[7] = (temp % 10000) / 1000; x25addr[8] = (temp % 1000) / 100; x25addr[9] = (temp % 100) / 10; x25addr[10] = temp % 10; } x25addr[11] = 0; /* clear rest of addr */ x25addr[12] = 0; x25addr[13] = 0; x25addr[14] = 0; #ifdef DDNDEBUG if (ddn_debug > 4) { printf("convert_ip_addr(): "); prt_addr(ip_addr); printf(" ==> "); prt_bytes(x25addr, 14); printf("\n"); } #endif DDNDEBUG return(1); } /***********************************************************************\ * convert_x25_addr() * ************************************************************************* * * * This routine accepts an X25 address and attempts to translate * * to an equivalent internet address. For DDN this follows the * * guidelines in the DDN X25 interface spec. The resultant * * internet address is returned to the caller. * * * \***********************************************************************/ static int convert_x25_addr(x25addr) u_char x25addr[]; { register int cnt, temp; union { struct in_addr ip; struct { /* (assumes Class A network number) */ u_char s_net; u_char s_host; u_char s_lh; u_char s_impno; } imp; } imp_addr; if (((cnt = x25addr[0]) < 12) || (cnt > 14)) { printf("DDN: illegal X25 address length!\n"); return(0); } switch(x25addr[5] & 0x0f) { case 0: /* Physical: 0000 0 IIIHH00 [SS] */ imp_addr.imp.s_impno = ((int)(x25addr[6] & 0x0f) * 100) + ((int)(x25addr[7] & 0x0f) * 10) + ((int)(x25addr[8] & 0x0f)); imp_addr.imp.s_host = ((int)(x25addr[9] & 0x0f) * 10) + ((int)(x25addr[10] & 0x0f)); break; case 1: /* Logical: 0000 1 RRRRR00 [SS] */ temp = ((int)(x25addr[6] & 0x0f) * 10000) + ((int)(x25addr[7] & 0x0f) * 1000) + ((int)(x25addr[8] & 0x0f) * 100) + ((int)(x25addr[9] & 0x0f) * 10) + ((int)(x25addr[10] & 0x0f)); imp_addr.imp.s_host = temp >> 8; imp_addr.imp.s_impno = temp & 0xff; break; default: printf("DDN: illegal X25 address format!\n"); return(0); } imp_addr.imp.s_lh = 0; imp_addr.imp.s_net = 0; #ifdef DDNDEBUG if (ddn_debug > 4) { printf("convert_x25_addr(): "); prt_bytes(&x25addr[1], cnt); printf(" ==> "); prt_addr(imp_addr.ip); printf("\n"); } #endif DDNDEBUG return(imp_addr.ip.s_addr); } /***********************************************************************\ * make_x25_call() * ************************************************************************* * * * This routine places an X25 call using the X25 Call Msg * * buffer. The calling LCN is placed in the appropriate state * * and a timer is started. * * * \***********************************************************************/ static boolean make_x25_call(ds, dc) register struct ddn_softc *ds; register struct ddn_cb *dc; { register struct mbuf *m_callbfr; register caddr_t cb; MGET(m_callbfr, M_DONTWAIT, MT_DATA); /* try to get call cmnd buffer */ if (m_callbfr == 0) return(0); cb = mtod(m_callbfr, caddr_t); (void)convert_ip_addr(ds->ddn_ipaddr, cb_calling_addr); cb_protocol[0] = 4; cb_protocol[1] = X25_PROTO_IP; /* protocol = IP */ cb_protocol[2] = 0; cb_protocol[3] = 0; cb_protocol[4] = 0; cb_facilities[0] = 4; /* number facility bytes */ cb_facilities[1] = 0; /* options marker */ cb_facilities[2] = 0; cb_facilities[3] = X25_FACIL_DDN; /* DDN standard mode */ cb_facilities[4] = FAC_DDNSTD; cb_user_data[0] = 0; /* no user data */ cb_cmnd[0] = CALL; /* set command code */ cb_cmnd[1] = dc->dc_lcn << 1; /* set channel id */ cb_cmnd[2] = 0; cb_cmnd[3] = (cb_called_addr[0] + 1) + /* tally up cmnd ext length */ (cb_calling_addr[0] + 1) + (cb_protocol[0] + 1) + (cb_facilities[0] + 1) + (cb_user_data[0] + 1); m_callbfr->m_len = cb_cmnd[3] + 4; /* copy command header */ bcopy((caddr_t)cb_cmnd, cb, 4); cb += 4; /* copy called address */ bcopy((caddr_t)cb_called_addr, cb, cb_called_addr[0] + 1); cb += (cb_called_addr[0] + 1); /* copy calling address */ bcopy((caddr_t)cb_calling_addr, cb, cb_calling_addr[0] + 1); cb += (cb_calling_addr[0] + 1); /* copy protocol */ bcopy((caddr_t)cb_protocol, cb, cb_protocol[0] + 1); cb += (cb_protocol[0] + 1); /* copy facilities */ bcopy((caddr_t)cb_facilities, cb, cb_facilities[0] + 1); cb += (cb_facilities[0] + 1); /* copy user data */ bcopy((caddr_t)cb_user_data, cb, cb_user_data[0] + 1); cb += (cb_user_data[0] + 1); dc->dc_state = LC_CALL_PENDING; /* set state */ dc->dc_timer = TMO_CALL_PENDING; /* start call timeout */ #ifdef DDNDEBUG if (ddn_debug > 3) { printf("make_x25_call(): call_bfr = "); prt_bytes(mtod(m_callbfr, u_char *), m_callbfr->m_len); printf("\n"); } #endif DDNDEBUG IF_ENQUEUE(&(ds->ddn_cb[0].dc_oq), m_callbfr); ddn_start(ds, &(ds->ddn_cb[0])); return(1); } /***********************************************************************\ * ddn_start() * ************************************************************************* * * * This routine attempts to start output of data queued on a * * specific LCN. If the LCN was not already busy and data is * * available for output, the data is copied into the LCN's I/O * * buffer and an I/O request queued to the UMC. * * * \***********************************************************************/ static void ddn_start(ds, dc) register struct ddn_softc *ds; register struct ddn_cb *dc; { register struct mbuf *m; int len; /* * If output isn't active, attempt to * start sending a new packet. */ if ((dc->dc_flags & DC_OBUSY) || (dc->dc_oq.ifq_len == 0) || ((dc->dc_lcn != 0) && (dc->dc_state != LC_DATA_IDLE))) { return; } IF_DEQUEUE(&dc->dc_oq, m); len = if_wubaput(&dc->dc_ifuba, m); /* copy data to mapped mem */ dc->dc_flags |= DC_OBUSY; ddn_iorq(ds, dc, len, DDNWRT+DDNEOS); } /***********************************************************************\ * ddn_iorq() * ************************************************************************* * * * This routine builds UMC I/O requests and queues them for * * delivery to the UMC. If the UMC I/O request comm regs are * * not busy, the I/O request is passed to the UMC. * * * \***********************************************************************/ static void ddn_iorq(ds, dc, len, func) struct ddn_softc *ds; struct ddn_cb *dc; int len, func; { register struct hdx_chan *hc; register int info; /* get appropriate UNIBUS mapping info */ if (func & DDNRDB) /* read or write? */ { hc = &dc->dc_rchan; info = dc->dc_ifuba.ifu_r.ifrw_info; } else { hc = &dc->dc_wchan; info = dc->dc_ifuba.ifu_w.ifrw_info; } /* set channel info */ hc->hc_adx = (u_char)((info & 0x30000) >> 12); hc->hc_addr = (u_short)(info & 0xffff); hc->hc_cnt = len; hc->hc_func = (u_char)func; hc->hc_sbfc = 0; /* * If UMC comm regs busy, queue start i/o for later. */ if (ds->ddn_sioq.sq_head) { (ds->ddn_sioq.sq_tail)->hc_next = hc; ds->ddn_sioq.sq_tail = hc; hc->hc_next = 0; return; } /* start i/o on channel now */ ds->ddn_sioq.sq_head = hc; ds->ddn_sioq.sq_tail = hc; hc->hc_next = 0; start_chn(ds); } /***********************************************************************\ * start_chn() * ************************************************************************* * * * This routine copies UMC I/O requests into the UMC comm regs * * and notifies the UMC. * * * \***********************************************************************/ static void start_chn(ds) struct ddn_softc *ds; { register struct hdx_chan *hc = ds->ddn_sioq.sq_head; register struct ddnregs *addr = (struct ddnregs *)ddninfo[ds->ddn_if.if_unit]->ui_addr; /* * Set up comm regs. */ addr->iochn = hc->hc_chan; addr->ioadx = hc->hc_adx; addr->ioadl = hc->hc_addr; addr->iocnt = hc->hc_cnt; addr->iofcn = hc->hc_func; addr->iosbf = hc->hc_sbfc; addr->ioini = 1; /* signal UMC if necessary */ if (!(addr->ionmi)) { addr->ionmi = 1; addr->csr = DDN_DMA|DDN_WRT|DDN_IEN|DDN_NMI; } } /***********************************************************************\ * ddn_data() * ************************************************************************* * * * This routine is called when a data channel I/O completes. * * If the completion was for a write, an attempt is made to * * start output on the next packet waiting for output on that * * LCN. If the completion was for a read, the received packet * * is sent to the IP input queue (if no error) and another read * * is started on the LCN. * * * \***********************************************************************/ static void ddn_data(unit, chan, cc, rcnt) int unit, chan, cc, rcnt; { register struct ddn_softc *ds = &ddn_softc[unit]; register struct ddn_cb *dc = &(ds->ddn_cb[chan/2]); register struct ifqueue *inq = &ipintrq; register struct mbuf *m; if (chan & 0x01) /* was it read or write? */ { /* write, fire up next output */ ds->ddn_if.if_opackets++; dc->dc_flags &= ~DC_OBUSY; ddn_start(ds, dc); } else /* read, process rcvd packet */ { if (cc == DDNIOCOK) { /* Queue good packet for input */ ds->ddn_if.if_ipackets++; dc->dc_state = LC_DATA_IDLE; dc->dc_timer = TMO_DATA_IDLE; m = if_rubaget(&(dc->dc_ifuba), rcnt, 0, &ds->ddn_if); if (m) { if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); } else { IF_ENQUEUE(inq, m); schednetisr(NETISR_IP); } } } /* hang a new data read */ ddn_iorq(ds, dc, DDNMTU, DDNRDB+DDNSTR); } } /***********************************************************************\ * ddn_supr() * ************************************************************************* * * * This routine is called when a supervisor I/O completes. * * If the completion was for a write, an attempt is made to * * start output on the next supervisor command waiting for * * output. If the completion was for a read, the received * * supervisor message is processed and another read is started. * * * \***********************************************************************/ static void ddn_supr(unit, chan, cc) int unit, chan, cc; { register struct ddn_softc *ds = &ddn_softc[unit]; u_char *p; /* was it read or write? */ if (chan & 0x01) { ds->ddn_cb[0].dc_flags &= ~DC_OBUSY; ddn_start(ds, &(ds->ddn_cb[0])); } else { if (cc == DDNIOCOK) { p = (u_char *)(ds->ddn_cb[0].dc_ifuba.ifu_r.ifrw_addr); /* process supervisor message */ supr_msg(ds, p); } /* hang a new supr read */ ddn_iorq(ds, &(ds->ddn_cb[0]), DDNMTU, DDNRDB+DDNSTR); } } /***********************************************************************\ * supr_msg() * ************************************************************************* * * * This routine processes received supervisor messages. * * Depending on the message type, the appropriate action is * * taken. * * \***********************************************************************/ static void supr_msg(ds, p) struct ddn_softc *ds; u_char p[]; { register struct ddn_cb *dc; register int lcn; register struct mbuf *m; #ifdef DDNDEBUG if (ddn_debug > 5) { printf("supr_msg(): "); prt_bytes(p, 4+p[3]); printf("\n"); } #endif DDNDEBUG switch (p[0]) { case LINE_STATUS: /* link status msg */ if (p[2] == LINK_UP) /* if link came up */ { send_restart(ds); /* send restart msg */ } else /* if link went down */ { ds->ddn_if.if_flags &= ~IFF_UP; dc = ds->ddn_cb; for(lcn = 0; lcn <= NDDNCH; lcn++) /* for all LCN's */ { dc->dc_state = LC_DOWN; /* set state */ dc->dc_timer = TMO_OFF; /* stop timer */ dc++; } } break; case RESTART: /* restart received */ if (ds->ddn_cb[0].dc_state != LC_RESTART) /* if not restarting */ send_supr(ds, RSTRT_ACK, 0, 0); /* send restart ack */ /* fall thru */ case RSTRT_ACK: /* restart ack */ ds->ddn_if.if_flags |= IFF_UP; dc = ds->ddn_cb; for(lcn = 0; lcn <= NDDNCH; lcn++) /* for all LCN's */ { dc->dc_state = LC_IDLE; /* set state */ dc->dc_timer = TMO_OFF; /* stop timer */ dc->dc_inaddr.s_addr = 0; /* forget address */ while (dc->dc_oq.ifq_len) /* drop pending data */ { IF_DEQUEUE(&dc->dc_oq, m); m_freem(m); } dc++; } break; case ANSWER: /* call answered */ lcn = p[1] / 2; dc = &(ds->ddn_cb[lcn]); if (dc->dc_state == LC_CALL_PENDING) /* if a call pending */ { dc->dc_state = LC_DATA_IDLE; /* set state */ dc->dc_timer = TMO_DATA_IDLE; /* start timer */ ddn_start(ds, dc); /* try to send data */ } break; case RING: /* incoming call */ for(lcn = NDDNCH; lcn > 0; lcn--) /* search LCN's */ { if (ds->ddn_cb[lcn].dc_state == LC_IDLE) /* unused? */ break; } if (lcn && decode_ring(p)) /* if a free LCN found */ /* and ring looks ok */ { dc = &(ds->ddn_cb[lcn]); dc->dc_inaddr.s_addr = convert_x25_addr(cb_calling_addr); dc->dc_state = LC_DATA_IDLE; /* set state */ dc->dc_timer = TMO_DATA_IDLE; /* start timer */ send_supr(ds, ANSWER, lcn * 2, (int)p[2]); /* send answer */ } else /* if no free LCN's */ { send_supr(ds, CLEARVC, (int)p[2], 0); /* clear call */ } break; case CLEARLC: /* clear by LCN */ lcn = p[1] / 2; /* get LCN */ dc = &(ds->ddn_cb[lcn]); if (dc->dc_state != LC_CLR_PENDING) /* if no clear pending */ { send_supr(ds, CLEARLC, (int)p[1], 0); /* ack the clear */ } dc->dc_state = LC_IDLE; /* set state */ dc->dc_timer = TMO_OFF; /* stop timer */ dc->dc_inaddr.s_addr = 0; /* forget address */ while (dc->dc_oq.ifq_len) /* drop pending data */ { IF_DEQUEUE(&dc->dc_oq, m); m_freem(m); } break; case CLEARVC: /* clear by VCN */ send_supr(ds, CLEARVC, (int)p[1], 0); /* send clear ack */ break; case RESET: /* X25 reset */ send_supr(ds, RESET_ACK, (int)p[1], 0); /* send reset ack */ printf("X25 RESET on lcn = %d\n", p[1] / 2); /* log it */ break; case INTERRUPT: /* X25 interrupt */ printf("X25 INTERRUPT on lcn = %d, code = %d\n", /* log it */ p[1] / 2, p[2]); break; default: printf("ddn%d: supervisor error, code=%x\n", ds->ddn_if.if_unit, p[0]); } } /***********************************************************************\ * decode_ring() * ************************************************************************* * * * This routine parses and validates the incoming call msg. * * * \***********************************************************************/ static boolean decode_ring(p) register u_char *p; { register int cnt; #ifdef DDNDEBUG if (ddn_debug > 3) { printf("decode_ring()\n"); } #endif DDNDEBUG p += 3; /* skip to cmnd ext length */ if (*p++ < 5) /* is count appropriate */ return(0); /* return false if not */ /* called address */ if ((cnt = *p + 1) > 16) /* is called addr len legal? */ return(0); /* return false if not */ bcopy((caddr_t)p, (caddr_t)cb_called_addr, (unsigned)cnt); /* copy field */ p += cnt; /* calling address */ if ((cnt = *p + 1) > 16) /* is calling addr len legal? */ return(0); /* return false if not */ bcopy((caddr_t)p, (caddr_t)cb_calling_addr, (unsigned)cnt); /* copy field */ p += cnt; /* protocol part of user data */ if ((cnt = *p + 1) > 5) /* is protocol len legal? */ return(0); /* return false if not */ bcopy((caddr_t)p, (caddr_t)cb_protocol, (unsigned)cnt); /* copy field */ p += cnt; /* facilities */ if ((cnt = *p + 1) > 64) /* is facilities len legal? */ return(0); /* return false if not */ bcopy((caddr_t)p, (caddr_t)cb_facilities, (unsigned)cnt); /* copy field */ p += cnt; /* ignore rest of user data for now */ if ((cb_protocol[0] == 0) || (cb_protocol[1] != X25_PROTO_IP)) return(0); /* bad if not IP */ return(1); /* looks ok */ } /***********************************************************************\ * clear_lcn() * ************************************************************************* * * * This routine clears an X25 circuit and releases any buffers * * queued for transmission. * * * \***********************************************************************/ static void clear_lcn(ds, dc) struct ddn_softc *ds; struct ddn_cb *dc; { register struct mbuf *m; #ifdef DDNDEBUG if (ddn_debug > 3) { printf("clear_lcn(%d)\n", dc->dc_lcn); } #endif DDNDEBUG dc->dc_state = LC_CLR_PENDING; /* set state */ dc->dc_timer = TMO_CLR_PENDING; /* start clear timer */ dc->dc_inaddr.s_addr = 0; /* clear associated address */ while (dc->dc_oq.ifq_len) /* drop any pending data */ { IF_DEQUEUE(&dc->dc_oq, m); m_freem(m); } send_supr(ds, CLEARLC, (int)dc->dc_lcn * 2, 0); /* send clear msg */ } /***********************************************************************\ * send_restart() * ************************************************************************* * * * This routine marks all LCNs as being in a restarting state * * and sends a restart command to X25. * * * \***********************************************************************/ static void send_restart(ds) struct ddn_softc *ds; { register struct ddn_cb *dc; register int lcn; struct mbuf *m; #ifdef DDNDEBUG if (ddn_debug > 1) { printf("send_restart()\n"); } #endif DDNDEBUG dc = ds->ddn_cb; for(lcn = 0; lcn <= NDDNCH; lcn++) /* for all LCN's */ { dc->dc_state = LC_RESTART; /* set state */ dc->dc_timer = TMO_RESTART; /* start restart timeout */ dc->dc_inaddr.s_addr = 0; /* forget address */ while (dc->dc_oq.ifq_len) /* drop any pending data */ { IF_DEQUEUE(&dc->dc_oq, m); m_freem(m); } dc++; } send_supr(ds, RESTART, 0, 0); /* send restart msg */ } /***********************************************************************\ * send_supr() * ************************************************************************* * * * This routine is used to send short (4 bytes only) supervisor * * commands. * * * \***********************************************************************/ static void send_supr(ds, cmd, p1, p2) struct ddn_softc *ds; int cmd, p1, p2; { struct mbuf *m; register u_char *cp; #ifdef DDNDEBUG if (ddn_debug > 6) { printf("send_supr(): %x %x %x\n", cmd, p1, p2); } #endif DDNDEBUG MGET(m, M_DONTWAIT, MT_DATA); if (m == 0) { printf("ddn%d: failed to get supr msg bfr!\n", ds->ddn_if.if_unit); return; } cp = mtod(m, u_char *); /* build supervisor message */ *cp++ = (byte)cmd; *cp++ = (byte)p1; *cp++ = (byte)p2; *cp++ = 0; m->m_len = 4; IF_ENQUEUE(&(ds->ddn_cb[0].dc_oq), m); ddn_start(ds, &(ds->ddn_cb[0])); } #ifdef DDNDEBUG /***********************************************************************\ * prt_addr() * ************************************************************************* * * * This routine is used to print internet addresses in the * * standard A.B.C.D format. * * * \***********************************************************************/ static void prt_addr(addr) struct in_addr addr; { printf("%d.%d.%d.%d", addr.s_net, addr.s_host, addr.s_lh, addr.s_impno); } /***********************************************************************\ * prt_bytes() * ************************************************************************* * * * This routine is used to print a string of bytes in hex. * * * \***********************************************************************/ static void prt_bytes(bp, cnt) u_char *bp; int cnt; { while(cnt--) { printf(" %x", *bp++ & 0xff); } } #endif DDNDEBUG #endif NDDN _softc[unit]; u_char *p; /* was it read or write? */ if (chan & 0x01) { ds->ddn_cb[0].dc_flags &= ~DC_OBUSY; ddn_start(ds, &(ds->ddn_cb[0])); } else { if (cc == DDNIOCOK) { p = (u_char *)(ds->ddn_cb[0].dc_ifuba.ifu_r.ifrw_addr); /* process supervisor message */ supr_msg(ds, p); } /* hang a new supr read */ ddn_iorq(ds, &(ds->ddn_cb[0]), DDNMTU, DDNRDB+DDNSTR); } sys/vaxif/raw_hy.c 444 0 12 2754 3671425420 7431 /* * @(#)raw_hy.c 7.1 6/5/86 * * 4.3 BSD Unix kernel - NSC HYPERchannel support * * $Header: raw_hy.c,v 3.1 84/02/15 04:27:44 steveg Exp $ * $Locker: $ * * Copyright (c) 1984, Tektronix Inc. * All Rights Reserved * */ #include "hy.h" #if NHY > 0 #include "param.h" #include "mbuf.h" #include "socket.h" #include "protosw.h" #include "socketvar.h" #include "errno.h" #include "../net/if.h" #include "../net/route.h" #include "../net/raw_cb.h" #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netinet/in_var.h" #include "if_hy.h" /* * Raw interface to HYPERchannel. */ /* * Generate HYPERchannel leader and pass packet to hyoutput. * The user must create a skeletal leader in order to * communicate message type, message subtype, etc. * We don't really check the header supplied by the user. */ rhy_output(m, so) register struct mbuf *m; struct socket *so; { int error = 0; register struct sockaddr_in *sin; register struct rawcb *rp = sotorawcb(so); struct in_ifaddr *ia; /* * Verify user has supplied necessary space * for the header. */ if ((m->m_off > MMAXOFF || m->m_len < sizeof(struct hym_hdr)) && (m = m_pullup(m, sizeof(struct hym_hdr))) == 0) { error = EMSGSIZE; /* XXX */ goto bad; } sin = (struct sockaddr_in *)&rp->rcb_faddr; /* no routing here */ ia = in_iaonnetof(in_netof(sin->sin_addr)); if (ia) return (hyoutput(ia->ia_ifp, m, (struct sockaddr *)sin)); error = ENETUNREACH; bad: m_freem(m); return (error); } #endif dn_cb *dc; regissys/vaxif/if_ilreg.h 444 0 12 10212 3671247725 7743 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_ilreg.h 7.1 (Berkeley) 6/5/86 */ /* * Interlan Ethernet Communications Controller interface */ struct ildevice { short il_csr; /* Command and Status Register */ short il_bar; /* Buffer Address Register */ short il_bcr; /* Byte Count Register */ }; /* * Command and status bits */ #define IL_EUA 0xc000 /* Extended Unibus Address */ #define IL_CMD 0x3f00 /* Command Function Code */ #define IL_CDONE 0x0080 /* Command Done */ #define IL_CIE 0x0040 /* Command Interrupt Enable */ #define IL_RDONE 0x0020 /* Receive DMA Done */ #define IL_RIE 0x0010 /* Receive Interrupt Enable */ #define IL_STATUS 0x000f /* Command Status Code */ #define IL_BITS "\20\10CDONE\7CIE\6RDONE\5RIE" /* command definitions */ #define ILC_MLPBAK 0x0100 /* Set Module Interface Loopback Mode */ #define ILC_ILPBAK 0x0200 /* Set Internal Loopback Mode */ #define ILC_CLPBAK 0x0300 /* Clear Loopback Mode */ #define ILC_PRMSC 0x0400 /* Set Promiscuous Receive Mode */ #define ILC_CLPRMSC 0x0500 /* Clear Promiscuous Receive Mode */ #define ILC_RCVERR 0x0600 /* Set Receive-On-Error Bit */ #define ILC_CRCVERR 0x0700 /* Clear Receive-On-Error Bit */ #define ILC_OFFLINE 0x0800 /* Go Offline */ #define ILC_ONLINE 0x0900 /* Go Online */ #define ILC_DIAG 0x0a00 /* Run On-board Diagnostics */ #define ILC_ISA 0x0d00 /* Set Insert Source Address Mode */ #define ILC_CISA 0x0e00 /* Clear Insert Source Address Mode */ #define ILC_DEFPA 0x0f00 /* Set Physical Address to Default */ #define ILC_ALLMC 0x1000 /* Set Receive All Multicast Packets */ #define ILC_CALLMC 0x1100 /* Clear Receive All Multicast */ #define ILC_STAT 0x1800 /* Report and Reset Statistics */ #define ILC_DELAYS 0x1900 /* Report Collision Delay Times */ #define ILC_RCV 0x2000 /* Supply Receive Buffer */ #define ILC_LDXMIT 0x2800 /* Load Transmit Data */ #define ILC_XMIT 0x2900 /* Load Transmit Data and Send */ #define ILC_LDGRPS 0x2a00 /* Load Group Addresses */ #define ILC_RMGRPS 0x2b00 /* Delete Group Addresses */ #define ILC_LDPA 0x2c00 /* Load Physical Address */ #define ILC_FLUSH 0x3000 /* Flush Receive BAR/BCR Queue */ #define ILC_RESET 0x3f00 /* Reset */ /* * Error codes found in the status bits of the csr. */ #define ILERR_SUCCESS 0 /* command successful */ #define ILERR_RETRIES 1 /* " " with retries */ #define ILERR_BADCMD 2 /* illegal command */ #define ILERR_INVCMD 3 /* invalid command */ #define ILERR_RECVERR 4 /* receiver error */ #define ILERR_BUFSIZ 5 /* buffer size too big */ #define ILERR_FRAMESIZ 6 /* frame size too small */ #define ILERR_COLLISIONS 8 /* excessive collisions */ #define ILERR_BUFALIGNMENT 10 /* buffer not word aligned */ #define ILERR_NXM 15 /* non-existent memory */ #define NILERRS 16 #ifdef ILERRS char *ilerrs[NILERRS] = { "success", /* 0 */ "success with retries", /* 1 */ "illegal command", /* 2 */ "inappropriate command", /* 3 */ "failure", /* 4 */ "buffer size exceeded", /* 5 */ "frame too small", /* 6 */ 0, /* 7 */ "excessive collisions", /* 8 */ 0, /* 9 */ "buffer alignment error", /* 10 */ 0, /* 11 */ 0, /* 12 */ 0, /* 13 */ 0, /* 14 */ "non-existent memory" /* 15 */ }; #endif /* * Diagnostics codes. */ #define ILDIAG_SUCCESS 0 /* no problems */ #define ILDIAG_CHKSUMERR 1 /* ROM/RAM checksum error */ #define ILDIAG_DMAERR 2 /* DMA not working */ #define ILDIAG_XMITERR 3 /* xmit circuitry failure */ #define ILDIAG_RECVERR 4 /* rcvr circuitry failure */ #define ILDIAG_LOOPBACK 5 /* loopback test failed */ #define NILDIAGS 6 #ifdef ILDIAGS char *ildiag[NILDIAGS] = { "success", /* 0 */ "checksum error", /* 1 */ "NM10 dma error", /* 2 */ "transmitter error", /* 3 */ "receiver error", /* 4 */ "loopback failure", /* 5 */ }; #endif /* * Frame status bits, returned in frame status byte * at the top of each received packet. */ #define ILFSTAT_C 0x1 /* CRC error */ #define ILFSTAT_A 0x2 /* alignment error */ #define ILFSTAT_L 0x4 /* 1+ frames lost just before */ Receive Mode */ #define ILC_CLPRMSC 0x0500 /* Clear Promiscuous Receive Mode */ #define ILC_RCVERR 0x0600 /* Set Receive-On-Error Bit */ #define ILC_CRCVERR 0x0700 /* Clear Receive-On-Error Bit */ #define ILC_OFFLINE 0x0800 /* Go Offline */ #define ILC_ONLINE 0x0900 /* Go Online */ #define ILC_DIAG 0x0a00 /* Run On-board Diagnostics */ #define ILC_ISA 0x0d00 /* Ssys/vaxif/if_uba.h 444 0 12 6531 3671250027 7366 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_uba.h 7.1 (Berkeley) 6/5/86 */ /* * Structure and routine definitions * for UNIBUS network interfaces. */ #define IF_MAXNUBAMR 10 /* * Each interface has structures giving information * about UNIBUS resources held by the interface * for each send and receive buffer. * * We hold IF_NUBAMR map registers for datagram data, starting * at ifr_mr. Map register ifr_mr[-1] maps the local network header * ending on the page boundary. Bdp's are reserved for read and for * write, given by ifr_bdp. The prototype of the map register for * read and for write is saved in ifr_proto. * * When write transfers are not full pages on page boundaries we just * copy the data into the pages mapped on the UNIBUS and start the * transfer. If a write transfer is of a (1024 byte) page on a page * boundary, we swap in UNIBUS pte's to reference the pages, and then * remap the initial pages (from ifu_wmap) when the transfer completes. * * When read transfers give whole pages of data to be input, we * allocate page frames from a network page list and trade them * with the pages already containing the data, mapping the allocated * pages to replace the input pages for the next UNIBUS data input. */ /* * Information per interface. */ struct ifubinfo { short iff_uban; /* uba number */ short iff_hlen; /* local net header length */ struct uba_regs *iff_uba; /* uba regs, in vm */ short iff_flags; /* used during uballoc's */ }; /* * Information per buffer. */ struct ifrw { caddr_t ifrw_addr; /* virt addr of header */ short ifrw_bdp; /* unibus bdp */ short ifrw_flags; /* type, etc. */ #define IFRW_W 0x01 /* is a transmit buffer */ int ifrw_info; /* value from ubaalloc */ int ifrw_proto; /* map register prototype */ struct pte *ifrw_mr; /* base of map registers */ }; /* * Information per transmit buffer, including the above. */ struct ifxmt { struct ifrw ifrw; caddr_t ifw_base; /* virt addr of buffer */ struct pte ifw_wmap[IF_MAXNUBAMR]; /* base pages for output */ struct mbuf *ifw_xtofree; /* pages being dma'd out */ short ifw_xswapd; /* mask of clusters swapped */ short ifw_nmr; /* number of entries in wmap */ }; #define ifw_addr ifrw.ifrw_addr #define ifw_bdp ifrw.ifrw_bdp #define ifw_flags ifrw.ifrw_flags #define ifw_info ifrw.ifrw_info #define ifw_proto ifrw.ifrw_proto #define ifw_mr ifrw.ifrw_mr /* * Most interfaces have a single receive and a single transmit buffer, * and use struct ifuba to store all of the unibus information. */ struct ifuba { struct ifubinfo ifu_info; struct ifrw ifu_r; struct ifxmt ifu_xmt; }; #define ifu_uban ifu_info.iff_uban #define ifu_hlen ifu_info.iff_hlen #define ifu_uba ifu_info.iff_uba #define ifu_flags ifu_info.iff_flags #define ifu_w ifu_xmt.ifrw #define ifu_xtofree ifu_xmt.ifw_xtofree #ifdef KERNEL #define if_ubainit(ifuba, uban, hlen, nmr) \ if_ubaminit(&(ifuba)->ifu_info, uban, hlen, nmr, \ &(ifuba)->ifu_r, 1, &(ifuba)->ifu_xmt, 1) #define if_rubaget(ifu, totlen, off0, ifp) \ if_ubaget(&(ifu)->ifu_info, &(ifu)->ifu_r, totlen, off0, ifp) #define if_wubaput(ifu, m) \ if_ubaput(&(ifu)->ifu_info, &(ifu)->ifu_xmt, m) struct mbuf *if_ubaget(); #endif . * * * \***********************************************************************/ static void prt_addr(addr) struct in_addr addr; { printf("%d.%d.%dsys/vaxif/if_pclreg.h 444 0 12 4730 3671247760 10104 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_pclreg.h 7.1 (Berkeley) 6/5/86 */ /* * DEC CSS PCL-11B Parallel Communications Interface */ struct pcldevice { u_short pcl_tcr; /* Transmitter Command Register */ u_short pcl_tsr; /* Transmitter Status Register */ u_short pcl_tsdb; /* Transmitter Source Data Buffer */ short pcl_tsbc; /* Transmitter Source Byte Count */ u_short pcl_tsba; /* Transmitter Source Bus Address */ u_short pcl_tmmr; /* Transmitter Master/Maint Regs */ u_short pcl_tscrc; /* Transmitter Source CRC */ u_short pcl_spare; u_short pcl_rcr; /* Receiver Command Register */ u_short pcl_rsr; /* Receiver Status Register */ u_short pcl_rddb; /* Receiver Destination Data Buffer */ short pcl_rdbc; /* Receiver Destination Byte Count */ u_short pcl_rdba; /* Receiver Destination Bus Address */ u_short pcl_rdcrc; /* Receiver Destination CRC */ }; /* Transmitter Command and Status Bits */ #define PCL_STTXM (1<<0) /* Start transmission */ #define PCL_TXINIT (1<<1) /* Transmitter Initialize */ #define PCL_IE (1<<6) /* Interrupt Enable */ #define PCL_SNDWD (1<<13) /* Send word */ #define PCL_TXNPR (1<<14) /* Transmitter NPR */ #define PCL_RIB (1<<15) /* Retry if busy */ #define PCL_RESPA (3<<0) /* Response A bits (tsr & rsr) */ #define PCL_RESPB (3<<2) /* Response B bits (tsr & rsr) */ #define PCL_MSTDWN (1<<11) /* Master down */ #define PCL_ERR (1<<15) /* Error summary */ #define PCL_MASTER (1<<8) /* Set MASTER status */ #define PCL_AUTOADDR (1<<12) /* Auto time slicing */ /* Receiver Command and Status Bits */ #define PCL_RCVDAT (1<<0) /* Receive data */ #define PCL_RCINIT (1<<1) /* Receiver Initialize */ #define PCL_RCVWD (1<<13) /* Receive word */ #define PCL_RCNPR (1<<14) /* Receive NRP */ #define PCL_REJ (1<<15) /* Reject transmission */ #define PCL_BCOFL (1<<9) /* Byte Counter Overflow */ #define PCL_TERRBITS "\20\20ERR\17NXL\16MEM_OFL\15TXM_ERR\14MST_DWN\13TIM_OUT\12OVERRUN\11DTI_RDY\10SUC_TXF\07BUSY\06SOREJ\05TBS_BUSY" #define PCL_TCSRBITS "\20\20RIB\17TX_NPR\16SND_WD\10RD_SILO\07IE\04DTO_RDY\03INH_ADI\02TX_INIT\01START_TXM" #define PCL_RERRBITS "\20\20ERR\17NXL\16MEM_OFL\15TXM_ERR\14PARITY\13TIM_OUT\12BC_OFL\11DTO_RDY\10SUC_TXF\07BUSY\06REJ_COMP\05CHN_OPN" #define PCL_RCSRBITS "\20\20REJ\17RC_NPR\16RCV_WD\10LD_SILO\07IE\04DTI_RDY\03INH_ADI\02RC_INIT\01RCV_DAT" rw.ifrw_info #define ifw_proto ifrw.ifrwsys/vaxif/if_hy.c 444 0 12 111336 3671425006 7273 /* * @(#)if_hy.c 7.1 (Berkeley) 6/5/86 */ /* * 4.2 BSD Unix Kernel - Vax Network Interface Support * * $Header: if_hy.c,v 10.1 84/07/22 21:02:56 steveg Exp $ * $Locker: $ * * Modifications from Berkeley 4.2 BSD * Copyright (c) 1983, Tektronix Inc. * All Rights Reserved * * $Log: if_hy.c,v $ * Revision 10.1 84/07/22 21:02:56 steveg * define PI13 (moved from if_hyreg.h, somehow got dropped in the process) * rework hywatch to check for power fails first * * Revision 10.0 84/06/30 19:54:27 steveg * Big Build * * Revision 3.17 84/06/20 19:20:28 steveg * increment hy_ntime in hywatch * print out state name, csr, last command, and hy_flags when watchdog timer * expires * * Revision 3.16 84/06/20 19:09:34 steveg * turn on continuous logging by default * * Revision 3.15 84/05/30 22:19:09 steveg * changes to reflect new layout ot statistics data * * Revision 3.14 84/05/30 19:25:15 steveg * move driver states to if_hy.h so log printing programs can use them * * Revision 3.13 84/05/30 17:13:26 steveg * make it compile * * Revision 3.12 84/05/30 13:46:16 steveg * rework logging * * Revision 3.11 84/05/18 19:35:02 steveg * clear IFF_RUNNING and IFF_UP on unibus reset to force resource allocation * by the init routine * * Revision 3.10 84/05/04 12:14:44 steveg * more rework to make it actually work under 4.2 * * Revision 3.9 84/05/01 23:34:52 steveg * fix typo so it compiles (unit -> ui->ui_unit) * * Revision 3.8 84/05/01 23:18:30 steveg * changes after talking with rickk * - check power off more closely * - support remote loopback through A710 adapters * - IMPLINK -> HYLINK * - return EHOSTUNREACH on hyroute failure * - bump if_collisions on abnormal interrupts that aren't input or output * * */ #include "hy.h" #if NHY > 0 /* * Network Systems Copropration Hyperchanel interface */ #include "machine/pte.h" #include "param.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "protosw.h" #include "socket.h" #include "vmmac.h" #include "errno.h" #include "time.h" #include "kernel.h" #include "ioctl.h" #include "../net/if.h" #include "../net/netisr.h" #include "../net/route.h" #ifdef INET #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netinet/in_var.h" #include "../netinet/ip.h" #endif #include "../vax/cpu.h" #include "../vax/mtpr.h" #include "../vaxuba/ubareg.h" #include "../vaxuba/ubavar.h" /* * configuration specific paramters * - change as appropriate for particular installaions */ #define HYROUTE #define HYELOG #define HYLOG #define HYMTU 1100 #define PI13 #ifdef DEBUG #define HYLOG #endif #include "if_hy.h" #include "if_hyreg.h" #include "if_uba.h" int hyprobe(), hyattach(), hyinit(), hyioctl(); int hyoutput(), hyreset(), hywatch(); struct uba_device *hyinfo[NHY]; u_short hystd[] = { 0772410, 0 }; struct uba_driver hydriver = { hyprobe, 0, hyattach, 0, hystd, "hy", hyinfo }; /* * Hyperchannel software status per interface. * * Each interface is referenced by a network interface structure, * hy_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... * We also have, for each interface, a UBA interface structure, which * contains information about the UNIBUS resources held by the interface: * map registers, buffered data paths, etc. Information is cached in this * structure for use by the if_uba.c routines in running the interface * efficiently. */ struct hy_softc { struct ifnet hy_if; /* network-visible interface */ struct ifuba hy_ifuba; /* UNIBUS resources */ short hy_flags; /* flags */ short hy_state; /* driver state */ u_short hy_host; /* local host number */ struct in_addr hy_addr; /* internet address */ int hy_olen; /* packet length on output */ int hy_lastwcr; /* last command's word count */ short hy_savedstate; /* saved for reissue after status */ short hy_savedcmd; /* saved command for reissue */ int hy_savedcount; /* saved byte count for reissue */ int hy_savedaddr; /* saved unibus address for reissue */ int hy_ntime; /* number of timeouts since last cmd */ int hy_retry; /* retry counter */ struct hy_stat hy_stat; /* statistics */ struct hy_status hy_status; /* status */ } hy_softc[NHY]; #ifdef HYELOG u_long hy_elog[HYE_SIZE]; #endif #ifdef HYLOG struct hy_log hy_log; #endif #ifdef HYROUTE struct hy_route hy_route[NHY]; #endif #ifdef DEBUG #define printL printf #define printD if (hy_debug_flag) printf int hy_debug_flag = 0; /* * hy_nodebug bit 0x01 set hy_debug_flag on hycancel * hy_nodebug bit 0x02 set hy_debug_flag on command reissue * hy_nodebug bit 0x04 set hy_debug_flag on abnormal interrupt */ int hy_nodebug = 0x0; #endif #define SCANINTERVAL 10 /* seconds */ #define MAXINTERVAL 20 /* seconds (max action) */ /* * Cause a device interrupt. This code uses a buffer starting at * location zero on the unibus (which is already mapped by the * autoconfigure code in the kernel). */ hyprobe(reg) caddr_t reg; { register int br, cvec; /* r11, r10 value-result */ register struct hydevice *addr = (struct hydevice *) reg; #ifdef lint br = 0; cvec = br; br = cvec; hyint(0); #endif /* * request adapter status to a buffer starting at unibus location 0 */ addr->hyd_bar = 0; addr->hyd_wcr = -((sizeof(struct hy_status) + 1) >> 1); addr->hyd_dbuf = HYF_STATUS; #ifdef PI13 addr->hyd_csr |= S_GO | S_IE | S_IATTN; #else addr->hyd_csr |= S_GO | S_IE; #endif DELAY(10000); #ifdef PI13 addr->hyd_csr |= S_CLRINT; /* clear any stacked interrupts */ #endif addr->hyd_csr &= ~(S_IE | S_CLRINT); /* disable further interrupts */ return(sizeof(struct hydevice)); } /* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */ hyattach(ui) struct uba_device *ui; { register struct hy_softc *is = &hy_softc[ui->ui_unit]; register struct ifnet *ifp = &is->hy_if; ifp->if_unit = ui->ui_unit; ifp->if_name = "hy"; ifp->if_mtu = HYMTU; is->hy_state = STARTUP; /* don't allow state transitions yet */ ifp->if_init = hyinit; ifp->if_ioctl = hyioctl; ifp->if_output = hyoutput; ifp->if_reset = hyreset; ifp->if_watchdog = hywatch; ifp->if_timer = SCANINTERVAL; is->hy_ifuba.ifu_flags = UBA_CANTWAIT; #ifdef notdef is->hy_ifuba.ifu_flags |= UBA_NEEDBDP; #endif if_attach(ifp); } /* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */ hyreset(unit, uban) int unit, uban; { register struct uba_device *ui; register struct hy_softc *is; if (unit >= NHY || (ui = hyinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" hy%d", unit); is = &hy_softc[unit]; /* force unibus resource allocation */ is->hy_if.if_flags &= ~(IFF_UP|IFF_RUNNING); hyinit(unit); } /* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */ hyinit(unit) int unit; { register struct hy_softc *is = &hy_softc[unit]; register struct uba_device *ui = hyinfo[unit]; register struct mbuf *m; int s; if (is->hy_if.if_addrlist == 0) /* address still unknown */ return; if (is->hy_if.if_flags & IFF_RUNNING) /* just reset the device */ goto justreset; if (if_ubainit(&is->hy_ifuba, ui->ui_ubanum, sizeof (struct hym_hdr), (int)btoc(HYMTU)) == 0) { #ifdef DEBUG if (hy_nodebug & 4) hy_debug_flag = 1; #endif printf("hy%d: can't initialize\n", unit); is->hy_if.if_flags &= ~IFF_UP; return; } is->hy_if.if_flags |= IFF_RUNNING; justreset: /* * remove any left over outgoing messages, reset the hardware and * start the state machine */ s = splimp(); #ifdef HYLOG hylog(HYL_RESET, 0, (char *)0); #endif is->hy_state = IDLE; is->hy_flags = RQ_STATUS | RQ_STATISTICS | RQ_MARKUP; is->hy_retry = 0; for(;;) { IF_DEQUEUE(&is->hy_if.if_snd, m); if (m != NULL) m_freem(m); else break; } hycancel(ui); /* also bumps the state machine */ splx(s); } /* * Issue a command to the adapter */ hystart(ui, cmd, count, ubaddr) struct uba_device *ui; int cmd, count, ubaddr; { register struct hy_softc *is = &hy_softc[ui->ui_unit]; register struct hydevice *addr = (struct hydevice *)ui->ui_addr; #ifdef DEBUG printD("hy%d: hystart cmd = 0x%x count=%d ubaddr=0x%x\n", ui->ui_unit, cmd, count, ubaddr); printD("hy%d: - csr = 0x%b, bar = 0x%x, wcr = 0x%x\n", ui->ui_unit, addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar, addr->hyd_wcr); #endif if (((is->hy_flags & RQ_REISSUE) == 0) && (cmd != HYF_STATUS) && (cmd != HYF_END_OP) && (cmd != HYF_RSTATS)) { is->hy_savedstate = is->hy_state; is->hy_savedcmd = cmd; is->hy_savedcount = count; is->hy_savedaddr = ubaddr; } #ifdef PI13 if (addr->hyd_csr & S_POWEROFF) { printf("hy%d: \"Soft\" Adapter Power Failure (hystart)\n", ui->ui_unit); addr->hyd_csr |= S_POWEROFF; DELAY(100); if (addr->hyd_csr & S_POWEROFF) { printf( "hy%d: \"Hard\" Adapter Power Failure, Network Shutdown (hystart)\n", ui->ui_unit); if_down(&is->hy_if); is->hy_if.if_flags &= ~IFF_UP; is->hy_state = STARTUP; } else { printf("hy%d: Adapter Power Restored (hystart)\n", ui->ui_unit); } return; } #endif addr->hyd_bar = ubaddr & 0xffff; addr->hyd_wcr = is->hy_lastwcr = -((count+1) >> 1); addr->hyd_dbuf = cmd; #ifdef PI13 addr->hyd_csr = ((ubaddr >> XBASHIFT) & S_XBA) | S_GO | S_IE | S_IATTN; #else addr->hyd_csr = ((ubaddr >> XBASHIFT) & S_XBA) | S_GO | S_IE; #endif #ifdef DEBUG printD("hy%d: exit hystart - csr = 0x%b, bar = 0x%x, wcr = 0x%x\n", ui->ui_unit, addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar, addr->hyd_wcr); #endif #ifdef HYLOG { struct { u_char hcmd; u_char hstate; short hcount; } hcl; hcl.hcmd = cmd; hcl.hstate = is->hy_state; hcl.hcount = count; hylog(HYL_CMD, sizeof(hcl), (char *)&hcl); } #endif is->hy_ntime = 0; } int hyint_active = 0; /* set during hy interrupt */ /* * Hyperchannel interface interrupt. * * An interrupt can occur for many reasons. Examine the status of * the hyperchannel status bits to determine what to do next. * * If input error just drop packet. * Otherwise purge input buffered data path and examine * packet to determine type. Othewise decapsulate * packet based on type and pass to type specific higher-level * input routine. */ hyint(unit) int unit; { register struct hy_softc *is = &hy_softc[unit]; register struct uba_device *ui = hyinfo[unit]; register struct hydevice *addr = (struct hydevice *)ui->ui_addr; if (hyint_active) panic("RECURSIVE HYPERCHANNEL INTERRUPT"); hyint_active++; #ifdef DEBUG printD("hy%d: hyint enter - csr = 0x%b, bar = 0x%x, wcr = 0x%x\n", unit, addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar, addr->hyd_wcr); #endif #ifdef HYLOG logit: { struct { u_char hstate; u_char hflags; short hcsr; short hwcr; } hil; hil.hstate = is->hy_state; hil.hflags = is->hy_flags; hil.hcsr = addr->hyd_csr; hil.hwcr = addr->hyd_wcr; hylog(HYL_INT, sizeof(hil), (char *)&hil); } #endif if (HYS_ERROR(addr) && ((addr->hyd_csr & S_ATTN) == 0)) { /* * Error bit set, some sort of error in the interface. * * The adapter sets attn on command completion so that's not * a real error even though the interface considers it one. */ #ifdef DEBUG if (hy_nodebug & 4) hy_debug_flag = 1; #endif printf("csr = 0x%b\nbar = 0x%x\nwcr = 0x%x\n", addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar, addr->hyd_wcr); if (addr->hyd_csr & S_NEX) { printf("hy%d: NEX - Non Existant Memory\n", unit); #ifdef PI13 addr->hyd_csr |= S_NEX; /* as per PI13 manual */ #else addr->hyd_csr &= ~S_NEX; #endif hycancel(ui); #ifdef PI13 } else if (addr->hyd_csr & S_POWEROFF) { printf("hy%d: \"Soft\" Adapter Power Failure (hyint)\n", unit); addr->hyd_csr |= S_POWEROFF; DELAY(100); if (addr->hyd_csr & S_POWEROFF) { printf( "hy%d: \"Hard\" Adapter Power Failure, Network Shutdown (hyint)\n", unit); if_down(&is->hy_if); is->hy_if.if_flags &= ~IFF_UP; is->hy_state = STARTUP; } else { printf("hy%d: Adapter Power Restored (hyint)\n", unit); } #endif } else { printf("hy%d: BAR overflow\n", unit); hycancel(ui); } } else if (HYS_NORMAL(addr)) { /* * Normal interrupt, bump state machine unless in state * waiting and no data present (assumed to be word count * zero interrupt or other hardware botch). */ if (is->hy_state != WAITING || HYS_RECVDATA(addr)) hyact(ui); } else if (HYS_ABNORMAL(addr)) { /* * Abnormal termination. * bump error counts, retry the last function * 'MAXRETRY' times before kicking the bucket. * * Don't reissue the cmd if in certain states, abnormal * on a reissued cmd or max retry exceeded. */ #ifdef HYLOG if (hy_log.hyl_enable != hy_log.hyl_onerr) { hy_log.hyl_enable = hy_log.hyl_onerr; goto logit; } #endif #ifdef DEBUG if (hy_nodebug & 4) hy_debug_flag = 1; printD("hy%d: abnormal interrupt, driver state \"%s\" (%d)\n", unit, hy_state_names[is->hy_state], is->hy_state); printD("\tflags 0x%x olen %d lastwcr %d retry %d\n", is->hy_flags, is->hy_olen, is->hy_lastwcr, is->hy_retry); printD("\tsaved: state %d count %d cmd 0x%x ptr 0x%x\n", is->hy_savedstate, is->hy_savedcount, is->hy_savedaddr, is->hy_savedcmd); #endif #ifdef PI13 addr->hyd_csr &= ~S_C; /* clear the damned PI-13 */ #endif if (is->hy_state == XMITSENT || is->hy_state == XMITDATASENT) is->hy_if.if_oerrors++; else if (is->hy_state == RECVSENT || is->hy_state == RECVDATASENT) is->hy_if.if_ierrors++; else is->hy_if.if_collisions++; /* other errors */ if (is->hy_state == XMITDATASENT || is->hy_state == RECVSENT || is->hy_state == RECVDATASENT || (is->hy_flags & RQ_REISSUE) != 0 || is->hy_retry > MAXRETRY) hycancel(ui); else { #ifdef DEBUG if (hy_nodebug & 2) hy_debug_flag = 1; #endif is->hy_retry++; is->hy_flags |= RQ_ENDOP | RQ_STATUS | RQ_REISSUE; is->hy_state = IDLE; hyact(ui); } } else { /* * Interrupt is neither normal, abnormal, or interface error. * Ignore it. It's either stacked or a word count 0. */ #ifdef HYLOG if (hy_log.hyl_enable != hy_log.hyl_onerr) { hy_log.hyl_enable = hy_log.hyl_onerr; goto logit; } #endif #ifdef DEBUG printD("hy%d: possible stacked interrupt ignored\n", unit); #endif } #ifdef DEBUG printD("hy%d: hyint exit\n\n", unit); #endif hyint_active = 0; } int hyoutprint = 0; /* * Encapsulate a packet of type family for the local net. */ hyoutput(ifp, m0, dst) struct ifnet *ifp; struct mbuf *m0; struct sockaddr *dst; { register struct hym_hdr *hym; register struct mbuf *m; register char *mp; int dlen; /* packet size, incl hardware header, but not sw header */ int error = 0; int s; /* * Calculate packet length for later deciding whether it will fit * in a message proper or we also need associated data. */ dlen = 0; for (m = m0; m; m = m->m_next) dlen += m->m_len; m = m0; if (dst->sa_family == AF_HYLINK) { /* don't add header */ dlen -= HYM_SWLEN; goto headerexists; } /* * Add the software and hardware hyperchannel headers. * If there's not enough space in the first mbuf, allocate another. * If that should fail, drop this sucker. * No extra space for headers is allocated. */ mp = mtod(m, char *); /* save pointer to real message */ if (m->m_off > MMAXOFF || MMINOFF + sizeof(struct hym_hdr) > m->m_off) { m = m_get(M_DONTWAIT, MT_HEADER); if (m == 0) { m = m0; error = ENOBUFS; goto drop; } m->m_next = m0; m->m_off = MMINOFF; m->m_len = sizeof(struct hym_hdr); } else { m->m_off -= sizeof(struct hym_hdr); m->m_len += sizeof(struct hym_hdr); } dlen += sizeof(struct hym_hdr) - HYM_SWLEN; hym = mtod(m, struct hym_hdr *); bzero((caddr_t)hym, sizeof(struct hym_hdr)); switch(dst->sa_family) { #ifdef INET case AF_INET: { int i; /* * if loopback address, swizzle ip header so when * it comes back it looks like it was addressed to us */ i = hyroute(ifp, (u_long)in_lnaof(((struct sockaddr_in *)dst)->sin_addr), hym); if (i < 0) goto notfound; if (i > 0) { struct in_addr temp; temp.s_addr = ((struct ip *)mp)->ip_dst.s_addr; ((struct ip *)mp)->ip_dst.s_addr = ((struct ip *)mp)->ip_src.s_addr; ((struct ip *)mp)->ip_src.s_addr = temp.s_addr; } /* * If entire packet won't fit in message proper, just * send hyperchannel hardware header and ip header in * message proper. * * This insures that the associated data is at least a * TCP/UDP header in length and thus prevents potential * problems with very short word counts. */ if (dlen > MPSIZE) hym->hym_mplen = sizeof(struct hy_hdr) + (((struct ip *)mp)->ip_hl << 2); hym->hym_type = HYLINK_IP; break; } #endif default: printf("hy%d: can't handle af%d\n", ifp->if_unit, dst->sa_family); error = EAFNOSUPPORT; goto drop; } headerexists: /* * insure message proper is below the maximum */ if (hym->hym_mplen > MPSIZE || (dlen > MPSIZE && hym->hym_mplen == 0)) hym->hym_mplen = MPSIZE; hym->hym_from = htons(hy_softc[ifp->if_unit].hy_host); if (hym->hym_mplen) hym->hym_ctl |= H_ASSOC; else hym->hym_ctl &= ~H_ASSOC; if (hyoutprint) printf("hy%d: output mplen=%x ctl=%x access=%x to=%x from=%x param=%x type=%x\n", ifp->if_unit, hym->hym_mplen, hym->hym_ctl, hym->hym_access, hym->hym_to, hym->hym_from, hym->hym_param, hym->hym_type); #ifdef DEBUG printD("hy%d: output mplen=%x ctl=%x access=%x to=%x from=%x param=%x type=%x\n", ifp->if_unit, hym->hym_mplen, hym->hym_ctl, hym->hym_access, hym->hym_to, hym->hym_from, hym->hym_param, hym->hym_type); #endif s = splimp(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); error = ENOBUFS; splx(s); goto drop; } IF_ENQUEUE(&ifp->if_snd, m); if (hy_softc[ifp->if_unit].hy_state == WAITING) hyact(hyinfo[ifp->if_unit]); splx(s); return (0); notfound: error = EHOSTUNREACH; drop: m_freem(m); return (error); } int hyroute(ifp, dest, hym) register struct ifnet *ifp; u_long dest; register struct hym_hdr *hym; { #ifdef HYROUTE register struct hy_route *rt = &hy_route[ifp->if_unit]; register struct hyr_hash *rhash; register int i; #endif hym->hym_param = 0; #ifdef HYROUTE if (rt->hyr_lasttime != 0) { i = HYRHASH(dest); rhash = &rt->hyr_hash[i]; i = 0; while (rhash->hyr_key != dest) { if (rhash->hyr_flags == 0 || i > HYRSIZE) return(-1); rhash++; i++; if (rhash >= &rt->hyr_hash[HYRSIZE]) rhash = &rt->hyr_hash[0]; } if (rhash->hyr_flags & HYR_GATE) { i = rhash->hyr_nextgate; if (i >= rhash->hyr_egate) rhash->hyr_nextgate = rhash->hyr_pgate; else rhash->hyr_nextgate++; rhash = &rt->hyr_hash[rt->hyr_gateway[i]]; if ((rhash->hyr_flags & HYR_DIR) == 0) return(-1); } else if (rhash->hyr_flags & HYR_LOOP) { hym->hym_param = H_LOOPBK; /* adapter loopback */ } else if (rhash->hyr_flags & HYR_RLOOP) { hym->hym_param = H_RLOOPBK; /* A710 remote loopback */ } hym->hym_ctl = rhash->hyr_ctl; hym->hym_access = rhash->hyr_access; hym->hym_to = rhash->hyr_dst; } else { #endif hym->hym_ctl = H_XTRUNKS | H_RTRUNKS; hym->hym_access = 0; hym->hym_to = htons((u_short)dest); if (dest & 0x010000) hym->hym_param = H_LOOPBK; /* adapter loopback */ else if (dest & 0x020000) hym->hym_param = H_RLOOPBK; /* A710 remote loopback */ #ifdef HYROUTE } #endif if (hym->hym_param == 0) return(0); else return(1); } hyact(ui) register struct uba_device *ui; { register struct hy_softc *is = &hy_softc[ui->ui_unit]; register struct hydevice *addr = (struct hydevice *)ui->ui_addr; actloop: #ifdef DEBUG printD("hy%d: hyact, enter state \"%s\"\n", ui->ui_unit, hy_state_names[is->hy_state]); #endif switch (is->hy_state) { case STARTUP: goto endintr; case IDLE: { register rq = is->hy_flags; if (rq & RQ_STATUS) { is->hy_flags &= ~RQ_STATUS; is->hy_state = STATSENT; hystart(ui, HYF_STATUS, sizeof (is->hy_status), is->hy_ifuba.ifu_r.ifrw_info); } else if (rq & RQ_ENDOP) { is->hy_flags &= ~RQ_ENDOP; is->hy_state = ENDOPSENT; hystart(ui, HYF_END_OP, 0, 0); } else if (rq & RQ_STATISTICS) { is->hy_flags &= ~RQ_STATISTICS; is->hy_state = RSTATSENT; hystart(ui, HYF_RSTATS, sizeof (is->hy_stat), is->hy_ifuba.ifu_r.ifrw_info); } else if (HYS_RECVDATA(addr)) { is->hy_state = RECVSENT; is->hy_retry = 0; hystart(ui, HYF_INPUTMSG, MPSIZE, is->hy_ifuba.ifu_r.ifrw_info + HYM_SWLEN); } else if (rq & RQ_REISSUE) { is->hy_flags &= ~RQ_REISSUE; is->hy_state = is->hy_savedstate; #ifdef DEBUG printD("hy%d: reissue cmd=0x%x count=%d", ui->ui_unit, is->hy_savedcmd, is->hy_savedcount); printD(" ubaddr=0x%x retry=%d\n", is->hy_savedaddr, is->hy_retry); #endif hystart(ui, is->hy_savedcmd, is->hy_savedcount, is->hy_savedaddr); } else { register struct mbuf *m; IF_DEQUEUE(&is->hy_if.if_snd, m); if (m != NULL) { register struct hym_hdr *hym; register int mplen; register int cmd; is->hy_state = XMITSENT; is->hy_retry = 0; hym = mtod(m, struct hym_hdr *); #ifdef HYLOG hylog(HYL_XMIT, sizeof(struct hym_hdr), (char *)hym); #endif mplen = hym->hym_mplen; if (hym->hym_to_adapter == hym->hym_from_adapter) cmd = HYF_XMITLOCMSG; else cmd = HYF_XMITMSG; #ifdef DEBUG printD("hy%d: hym_hdr = ", ui->ui_unit); if (hy_debug_flag) hyprintdata((char *)hym, sizeof (struct hym_hdr)); #endif is->hy_olen = if_wubaput(&is->hy_ifuba, m) - HYM_SWLEN; if (is->hy_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(is->hy_ifuba.ifu_uba, is->hy_ifuba.ifu_w.ifrw_bdp); #ifdef DEBUG printD( "hy%d: sending packet (mplen = %d, hy_olen = %d) data = ", ui->ui_unit, mplen, is->hy_olen); if (hy_debug_flag) hyprintdata( is->hy_ifuba.ifu_w.ifrw_addr, is->hy_olen + HYM_SWLEN); #endif if (mplen == 0) { is->hy_flags &= ~RQ_XASSOC; mplen = is->hy_olen; } else { is->hy_flags |= RQ_XASSOC; } hystart(ui, cmd, mplen, is->hy_ifuba.ifu_w.ifrw_info + HYM_SWLEN); } else if (rq & RQ_MARKDOWN) { is->hy_flags &= ~(RQ_MARKUP | RQ_MARKDOWN); is->hy_state = MARKPORT; is->hy_retry = 0; /* * Port number is taken from status data */ hystart(ui, (int)(HYF_MARKP0|(PORTNUM(&is->hy_status)<<2)), 0, 0); } else if (rq & RQ_MARKUP) { register struct ifnet *ifp = &is->hy_if; is->hy_flags &= ~RQ_MARKUP; is->hy_retry = 0; /* * Fill in the host number * from the status buffer */ printf( "hy%d: unit number 0x%x port %d type %x microcode level 0x%x\n", ui->ui_unit, is->hy_stat.hyc_uaddr, PORTNUM(&is->hy_status), (is->hy_stat.hyc_atype[0]<<8) | is->hy_stat.hyc_atype[1], is->hy_stat.hyc_atype[2]); is->hy_host = (is->hy_stat.hyc_uaddr << 8) | PORTNUM(&is->hy_status); ifp->if_flags |= IFF_UP; #ifdef HYLOG hylog(HYL_UP, 0, (char *)0); #endif } else { is->hy_state = WAITING; is->hy_retry = 0; hystart(ui, HYF_WAITFORMSG, 0, 0); } } break; } case STATSENT: bcopy(is->hy_ifuba.ifu_r.ifrw_addr, (caddr_t)&is->hy_status, sizeof (struct hy_status)); #ifdef DEBUG printD("hy%d: status - %x %x %x %x %x %x %x %x\n", ui->ui_unit, is->hy_status.hys_gen_status, is->hy_status.hys_last_fcn, is->hy_status.hys_resp_trunk, is->hy_status.hys_status_trunk, is->hy_status.hys_recd_resp, is->hy_status.hys_error, is->hy_status.hys_caddr, is->hy_status.hys_pad); #endif is->hy_state = IDLE; #ifdef HYLOG hylog(HYL_STATUS, sizeof (struct hy_status), (char *)&is->hy_status); #endif #ifdef HYELOG { register int i; i = is->hy_status.hys_error; if (i > HYE_MAX) i = HYE_MAX; switch (is->hy_status.hys_last_fcn) { case HYF_XMITLOCMSG: i += HYE_MAX+1; /* fall through */ case HYF_XMITLSTDATA: i += HYE_MAX+1; /* fall through */ case HYF_XMITMSG: i += HYE_MAX+1; } hy_elog[i]++; } #endif break; case RSTATSENT: { register struct hy_stat *p = (struct hy_stat *)is->hy_ifuba.ifu_r.ifrw_addr; bcopy((caddr_t)p, (caddr_t)&is->hy_stat, sizeof(struct hy_stat)); #ifdef DEBUG printD("hy%d: statistics - df0 %d df1 %d df2 %d df3 %d\n", ui->ui_unit, (is->hy_stat.hyc_df0[0]<<16) | (is->hy_stat.hyc_df0[1]<<8) | is->hy_stat.hyc_df0[2], (is->hy_stat.hyc_df1[0]<<16) | (is->hy_stat.hyc_df1[1]<<8) | is->hy_stat.hyc_df1[2], (is->hy_stat.hyc_df2[0]<<16) | (is->hy_stat.hyc_df2[1]<<8) | is->hy_stat.hyc_df2[2], (is->hy_stat.hyc_df3[0]<<16) | (is->hy_stat.hyc_df3[1]<<8) | is->hy_stat.hyc_df3[2]); printD(" ret0 %d ret1 %d ret2 %d ret3 %d\n", (is->hy_stat.hyc_ret0[0]<<16) | (is->hy_stat.hyc_ret0[1]<<8) | is->hy_stat.hyc_ret0[2], (is->hy_stat.hyc_ret1[0]<<16) | (is->hy_stat.hyc_ret1[1]<<8) | is->hy_stat.hyc_ret1[2], (is->hy_stat.hyc_ret2[0]<<16) | (is->hy_stat.hyc_ret2[1]<<8) | is->hy_stat.hyc_ret2[2], (is->hy_stat.hyc_ret3[0]<<16) | (is->hy_stat.hyc_ret3[1]<<8) | is->hy_stat.hyc_ret3[2]); printD(" cancel %d abort %d atype %x %x %x uaddr %x\n", (is->hy_stat.hyc_cancel[0]<<8) | is->hy_stat.hyc_cancel[1], (is->hy_stat.hyc_abort[0]<<8) | is->hy_stat.hyc_abort[1], is->hy_stat.hyc_atype[0], is->hy_stat.hyc_atype[1], is->hy_stat.hyc_atype[2], is->hy_stat.hyc_uaddr); #endif is->hy_state = IDLE; #ifdef HYLOG hylog(HYL_STATISTICS, sizeof (struct hy_stat), (char *)&is->hy_stat); #endif break; } case CLEARSENT: is->hy_state = IDLE; break; case ENDOPSENT: is->hy_state = IDLE; break; case RECVSENT: { register struct hym_hdr *hym; register unsigned len; if (is->hy_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(is->hy_ifuba.ifu_uba, is->hy_ifuba.ifu_r.ifrw_bdp); hym = (struct hym_hdr *) (is->hy_ifuba.ifu_r.ifrw_addr); len = (0xffff & (addr->hyd_wcr - is->hy_lastwcr)) << 1; if (len > MPSIZE) { printf("hy%d: RECVD MP > MPSIZE (%d)\n", ui->ui_unit, len); is->hy_state = IDLE; #ifdef DEBUG hy_debug_flag = 1; printD("hy%d: csr = 0x%b, bar = 0x%x, wcr = 0x%x\n", ui->ui_unit, addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar, addr->hyd_wcr); #endif } hym->hym_mplen = len; #ifdef DEBUG printD("hy%d: recvd mp, len = %d, data = ", ui->ui_unit, len); if (hy_debug_flag) hyprintdata((char *)hym, len + HYM_SWLEN); #endif if (hym->hym_ctl & H_ASSOC) { is->hy_state = RECVDATASENT; is->hy_retry = 0; hystart(ui, HYF_INPUTDATA, (int)(HYMTU + sizeof (struct hy_hdr) - len), (int)(HYM_SWLEN + is->hy_ifuba.ifu_r.ifrw_info + len)); } else { hyrecvdata(ui, hym, (int)len + HYM_SWLEN); is->hy_state = IDLE; } break; } case RECVDATASENT: { register struct hym_hdr *hym; register unsigned len; if (is->hy_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(is->hy_ifuba.ifu_uba, is->hy_ifuba.ifu_r.ifrw_bdp); hym = (struct hym_hdr *) (is->hy_ifuba.ifu_r.ifrw_addr); len = (0xffff & (addr->hyd_wcr - is->hy_lastwcr)) << 1; #ifdef DEBUG printD("hy%d: recvd assoc data, len = %d, data = ", ui->ui_unit, len); if (hy_debug_flag) hyprintdata((char *)hym + hym->hym_mplen, len); #endif hyrecvdata(ui, hym, (int)(len + hym->hym_mplen + HYM_SWLEN)); is->hy_state = IDLE; break; } case XMITSENT: if (is->hy_flags & RQ_XASSOC) { register int len; is->hy_flags &= ~RQ_XASSOC; is->hy_state = XMITDATASENT; is->hy_retry = 0; len = (0xffff & (addr->hyd_wcr - is->hy_lastwcr)) << 1; if (len > is->hy_olen) { printf( "hy%d: xmit error - len > hy_olen [%d > %d]\n", ui->ui_unit, len, is->hy_olen); #ifdef DEBUG hy_debug_flag = 1; #endif } hystart(ui, HYF_XMITLSTDATA, is->hy_olen - len, is->hy_ifuba.ifu_w.ifrw_info + HYM_SWLEN + len); break; } /* fall through to ... */ case XMITDATASENT: hyxmitdata(ui); is->hy_state = IDLE; break; case WAITING: /* wait for message complete or output requested */ if (HYS_RECVDATA(addr)) is->hy_state = IDLE; else { is->hy_state = CLEARSENT; is->hy_retry = 0; hystart(ui, HYF_CLRWFMSG, 0, 0); } break; case MARKPORT: is->hy_state = STARTUP; if_down(&is->hy_if); is->hy_if.if_flags &= ~IFF_UP; goto endintr; default: printf("hy%d: DRIVER BUG - INVALID STATE %d\n", ui->ui_unit, is->hy_state); panic("HYPERCHANNEL IN INVALID STATE"); /*NOTREACHED*/ } if (is->hy_state == IDLE) goto actloop; endintr: ; #ifdef DEBUG printD("hy%d: hyact, exit at \"%s\"\n", ui->ui_unit, hy_state_names[is->hy_state]); #endif } struct sockproto hypproto = { PF_HYLINK }; struct sockaddr_in hypdst = { AF_HYLINK }; struct sockaddr_in hypsrc = { AF_HYLINK }; /* * Called from device interrupt when receiving data. * Examine packet to determine type. Decapsulate packet * based on type and pass to type specific higher-level * input routine. */ hyrecvdata(ui, hym, len) struct uba_device *ui; register struct hym_hdr *hym; int len; { register struct hy_softc *is = &hy_softc[ui->ui_unit]; struct mbuf *m; register struct ifqueue *inq; is->hy_if.if_ipackets++; #ifdef DEBUG printD("hy%d: recieved packet, len = %d\n", ui->ui_unit, len); #endif #ifdef HYLOG { struct { short hlen; struct hym_hdr hhdr; } hh; hh.hlen = len; hh.hhdr = *hym; hylog(HYL_RECV, sizeof(hh), (char *)&hh); } #endif if (len > HYMTU + MPSIZE || len == 0) return; /* sanity */ /* * Pull packet off interface. */ m = if_rubaget(&is->hy_ifuba, len, 0, &is->hy_if); if (m == NULL) return; /* * if normal or adapter loopback response packet believe hym_type, * otherwise, use the raw input queue cause it's a response from an * adapter command. */ if (hym->hym_param != 0 && (u_short)hym->hym_param != 0x80ff) goto rawlinkin; switch (hym->hym_type) { #ifdef INET case HYLINK_IP: schednetisr(NETISR_IP); inq = &ipintrq; break; #endif default: rawlinkin: { struct mbuf *m0; MGET(m0, M_DONTWAIT, MT_DATA); if (m0 == 0) { m_freem(m); return; } m0->m_off = MMINOFF; m0->m_len = sizeof(struct hym_hdr); m0->m_next = m; bcopy((caddr_t)hym, mtod(m0, caddr_t), sizeof(struct hym_hdr)); m = m0; hypproto.sp_protocol = 0; hypdst.sin_addr = is->hy_addr; hypsrc.sin_addr = is->hy_addr; raw_input(m, &hypproto, (struct sockaddr *)&hypsrc, (struct sockaddr *)&hypdst); return; } } if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); } else IF_ENQUEUE(inq, m); } /* * Transmit done, release resources, bump counters. */ hyxmitdata(ui) struct uba_device *ui; { register struct hy_softc *is = &hy_softc[ui->ui_unit]; is->hy_if.if_opackets++; if (is->hy_ifuba.ifu_xtofree) { m_freem(is->hy_ifuba.ifu_xtofree); is->hy_ifuba.ifu_xtofree = 0; } } hycancel(ui) register struct uba_device *ui; { register struct hy_softc *is = &hy_softc[ui->ui_unit]; if (is->hy_ifuba.ifu_xtofree) { m_freem(is->hy_ifuba.ifu_xtofree); is->hy_ifuba.ifu_xtofree = 0; } #ifdef HYLOG hylog(HYL_CANCEL, 0, (char *)0); #endif #ifdef DEBUG if (hy_nodebug & 1) hy_debug_flag = 1; #endif #ifdef DEBUG printD("hy%d: cancel from state \"%s\" cmd=0x%x count=%d ptr=0x%x\n", ui->ui_unit, hy_state_names[is->hy_state], is->hy_savedcmd, is->hy_savedcount, is->hy_savedaddr); printD("\tflags 0x%x olen %d lastwcr %d retry %d\n", is->hy_flags, is->hy_olen, is->hy_lastwcr, is->hy_retry); printD("\tsaved: state %d count %d ptr 0x%x cmd 0x%x\n", is->hy_savedstate, is->hy_savedcount, is->hy_savedaddr, is->hy_savedcmd); #endif is->hy_state = IDLE; is->hy_flags |= (RQ_ENDOP | RQ_STATUS); hyact(ui); } #ifdef DEBUG hyprintdata(cp, len) register char *cp; register int len; { register int count = 16; register char *fmt; static char regfmt[] = "\n\t %x"; fmt = ®fmt[2]; while (--len >= 0) { printL(fmt, *cp++ & 0xff); fmt = ®fmt[2]; if (--count <= 0) { fmt = ®fmt[0]; count = 16; } } printL("\n"); } #endif hywatch(unit) int unit; { register struct hy_softc *is = &hy_softc[unit]; register struct uba_device *ui = hyinfo[unit]; register struct hydevice *addr = (struct hydevice *)ui->ui_addr; int s; s = splimp(); #ifdef PI13 if ((addr->hyd_csr & S_POWEROFF) != 0) { addr->hyd_csr |= S_POWEROFF; DELAY(100); if ((addr->hyd_csr & S_POWEROFF) == 0) { printf("hy%d: Adapter Power Restored (hywatch)\n", unit); is->hy_state = IDLE; is->hy_flags |= (RQ_MARKUP | RQ_STATISTICS | RQ_ENDOP | RQ_STATUS); hyact(ui); } } #endif if (++is->hy_ntime >= 2 && is->hy_state != WAITING && is->hy_state != STARTUP && is->hy_state != IDLE) { #ifdef HYLOG printf("hy%d: watchdog timer expired in state \"%s\"\n", unit, hy_state_names[is->hy_state]); #else printf("hy%d: watchdog timer expired in state %d\n", unit, is->hy_state); #endif printf("hy%d: last command 0x%x, flags 0x%x, csr 0x%b\n", unit, is->hy_savedcmd, is->hy_flags, addr->hyd_csr, HY_CSR_BITS); hycancel(ui); } splx(s); is->hy_if.if_timer = SCANINTERVAL; } #ifdef HYLOG hylog(code, len, ptr) int code, len; char *ptr; { register unsigned char *p; int s; s = splimp(); if (hy_log.hyl_self != &hy_log) { hy_log.hyl_eptr = &hy_log.hyl_buf[HYL_SIZE]; hy_log.hyl_ptr = &hy_log.hyl_buf[0]; hy_log.hyl_self = &hy_log; hy_log.hyl_enable = HYL_CONTINUOUS; hy_log.hyl_onerr = HYL_CONTINUOUS; hy_log.hyl_count = 0; hy_log.hyl_icount = 16; hy_log.hyl_filter = 0xffff; /* enable all */ } if (hy_log.hyl_enable == HYL_DISABLED || ((1 << code) & hy_log.hyl_filter) == 0) goto out; p = hy_log.hyl_ptr; if (p + len + 3 >= hy_log.hyl_eptr) { bzero((caddr_t)p, (unsigned)(hy_log.hyl_eptr - p)); p = &hy_log.hyl_buf[0]; if (hy_log.hyl_enable != HYL_CONTINUOUS) { hy_log.hyl_enable = HYL_DISABLED; goto out; } } *p++ = code; *p++ = len; bcopy((caddr_t)ptr, (caddr_t)p, (unsigned)len); if (hy_log.hyl_count != 0 && --hy_log.hyl_count == 0) { *p++ = '\0'; hy_log.hyl_enable = HYL_DISABLED; hy_log.hyl_count = hy_log.hyl_icount; } p += len; if (hy_log.hyl_wait != 0) { /* wakeup HYGETLOG if wanted */ if (hy_log.hyl_wait <= p - hy_log.hyl_ptr) { wakeup((caddr_t)&hy_log); hy_log.hyl_wait = 0; } else hy_log.hyl_wait -= p - hy_log.hyl_ptr; } hy_log.hyl_ptr = p; out: splx(s); } #endif /*ARGSUSED*/ hyioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { struct ifaddr *ifa = (struct ifaddr *) data; struct hyrsetget *sg = (struct hyrsetget *)data; #if defined(HYLOG) || defined(HYELOG) struct hylsetget *sgl = (struct hylsetget *)data; #endif struct hy_route *r = (struct hy_route *)&hy_route[ifp->if_unit]; int s = splimp(), error = 0; #ifdef HYLOG struct hy_softc *is = &hy_softc[ifp->if_unit]; struct { u_char hstate; u_char hflags; u_short iflags; int hcmd; int herror; u_long haddr; u_long hmisc; } hil; hil.hmisc = -1; hil.hstate = is->hy_state; hil.hflags = is->hy_flags; hil.hcmd = cmd; #endif switch(cmd) { case SIOCSIFADDR: if (ifa->ifa_addr.sa_family != AF_INET) return(EINVAL); if ((ifp->if_flags & IFF_RUNNING) == 0) hyinit(ifp->if_unit); hy_softc[ifp->if_unit].hy_addr = IA_SIN(ifa)->sin_addr; #ifdef HYLOG hil.haddr = is->hy_addr.s_addr; #endif break; case HYSETROUTE: if (!suser()) { error = EPERM; goto out; } if (sg->hyrsg_len != sizeof(struct hy_route)) { error = EINVAL; goto out; } if (copyin((caddr_t)(sg->hyrsg_ptr), (caddr_t)r, sg->hyrsg_len)) { r->hyr_lasttime = 0; /* disable further routing if trouble */ error = EFAULT; goto out; } r->hyr_lasttime = time.tv_sec; #ifdef HYLOG hil.hmisc = r->hyr_lasttime; #endif break; case HYGETROUTE: if (sg->hyrsg_len < sizeof(struct hy_route)) { error = EINVAL; goto out; } if (copyout((caddr_t)r, (caddr_t) (sg->hyrsg_ptr), sizeof(struct hy_route))) { error = EFAULT; goto out; } break; #ifdef HYELOG case HYGETELOG: if (sgl->hylsg_len < sizeof(hy_elog)) { error = EINVAL; goto out; } if (copyout((caddr_t)hy_elog, sgl->hylsg_ptr, sizeof(hy_elog))) { error = EFAULT; goto out; } if (sgl->hylsg_cmd) { if (!suser()) { error = EPERM; goto out; } bzero((caddr_t)hy_elog, sizeof(hy_elog)); } break; #endif #ifdef HYLOG case HYSETLOG: if (!suser()) { error = EPERM; goto out; } hy_log.hyl_enable = HYL_DISABLED; hylog(HYL_NOP, 0, (char *)0); /* force log init */ hy_log.hyl_enable = sgl->hylsg_cmd & 0x0f; hy_log.hyl_onerr = (sgl->hylsg_cmd >> 4) & 0x0f; hy_log.hyl_filter = (sgl->hylsg_cmd >> 8) & 0xffffff; hy_log.hyl_count = hy_log.hyl_icount = sgl->hylsg_len; wakeup((caddr_t)&hy_log); /* wakeup sleeping HYGETLOG */ break; case HYGETLOG: if (sgl->hylsg_len < sizeof(hy_log)) { error = EINVAL; goto out; } if (sgl->hylsg_cmd != 0) { if (hy_log.hyl_wait) { error = EBUSY; goto out; } hy_log.hyl_wait = sgl->hylsg_cmd; sleep((caddr_t)&hy_log, PZERO - 1); } if (copyout((caddr_t)&hy_log, sgl->hylsg_ptr, sizeof(hy_log))) { error = EFAULT; goto out; } break; #endif default: error = EINVAL; break; } out: #ifdef HYLOG hil.herror = error; hil.iflags = ifp->if_flags; hil.haddr = is->hy_addr.s_addr; hylog(HYL_IOCTL, sizeof(hil), (char *)&hil); #endif splx(s); return (error); } #endif ui->ui_unit, len); if (hy_debug_flag) hyprintdata((char *)hym + hym->hym_mplen, len); #endif hyrecvdata(ui, hym, (int)(len + hym->hym_mplen + HYM_SWLEN)); is->hy_state = IDLE; break; } case XMITSENT: if (is->hy_flags & RQ_XASSOC) { register int len; is->hy_flags &=sys/vaxif/if_de.c 640 0 12 52606 4113407473 7225 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_de.c 7.2 (Berkeley) 7/18/86 */ #include "de.h" #if NDE > 0 /* * DEC DEUNA interface * * Lou Salkind * New York University * * TODO: * timeout routine (get statistics) */ #include "../machine/pte.h" #include "param.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "protosw.h" #include "socket.h" #include "vmmac.h" #include "ioctl.h" #include "errno.h" #include "syslog.h" #include "../net/if.h" #include "../net/netisr.h" #include "../net/route.h" #ifdef INET #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netinet/in_var.h" #include "../netinet/ip.h" #include "../netinet/if_ether.h" #endif #ifdef NS #include "../netns/ns.h" #include "../netns/ns_if.h" #endif #include "../vax/cpu.h" #include "../vax/mtpr.h" #include "if_dereg.h" #include "if_uba.h" #include "../vaxuba/ubareg.h" #include "../vaxuba/ubavar.h" #define NXMT 3 /* number of transmit buffers */ #define NRCV 7 /* number of receive buffers (must be > 1) */ int dedebug = 0; int deprobe(), deattach(), deintr(); struct uba_device *deinfo[NDE]; u_short destd[] = { 0 }; struct uba_driver dedriver = { deprobe, 0, deattach, 0, destd, "de", deinfo }; int deinit(),deoutput(),deioctl(),dereset(); /* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * ds_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... * We also have, for each interface, a UBA interface structure, which * contains information about the UNIBUS resources held by the interface: * map registers, buffered data paths, etc. Information is cached in this * structure for use by the if_uba.c routines in running the interface * efficiently. */ struct de_softc { struct arpcom ds_ac; /* Ethernet common part */ #define ds_if ds_ac.ac_if /* network-visible interface */ #define ds_addr ds_ac.ac_enaddr /* hardware Ethernet address */ int ds_flags; #define DSF_LOCK 1 /* lock out destart */ #define DSF_RUNNING 2 /* board is enabled */ #define DSF_SETADDR 4 /* physical address is changed */ int ds_ubaddr; /* map info for incore structs */ struct ifubinfo ds_deuba; /* unibus resource structure */ struct ifrw ds_ifr[NRCV]; /* unibus receive maps */ struct ifxmt ds_ifw[NXMT]; /* unibus xmt maps */ /* the following structures are always mapped in */ struct de_pcbb ds_pcbb; /* port control block */ struct de_ring ds_xrent[NXMT]; /* transmit ring entrys */ struct de_ring ds_rrent[NRCV]; /* receive ring entrys */ struct de_udbbuf ds_udbbuf; /* UNIBUS data buffer */ /* end mapped area */ #define INCORE_BASE(p) ((char *)&(p)->ds_pcbb) #define RVAL_OFF(n) ((char *)&de_softc[0].n - INCORE_BASE(&de_softc[0])) #define LVAL_OFF(n) ((char *)de_softc[0].n - INCORE_BASE(&de_softc[0])) #define PCBB_OFFSET RVAL_OFF(ds_pcbb) #define XRENT_OFFSET LVAL_OFF(ds_xrent) #define RRENT_OFFSET LVAL_OFF(ds_rrent) #define UDBBUF_OFFSET RVAL_OFF(ds_udbbuf) #define INCORE_SIZE RVAL_OFF(ds_xindex) int ds_xindex; /* UNA index into transmit chain */ int ds_rindex; /* UNA index into receive chain */ int ds_xfree; /* index for next transmit buffer */ int ds_nxmit; /* # of transmits in progress */ } de_softc[NDE]; deprobe(reg) caddr_t reg; { register int br, cvec; /* r11, r10 value-result */ register struct dedevice *addr = (struct dedevice *)reg; register i; #ifdef lint br = 0; cvec = br; br = cvec; i = 0; derint(i); deintr(i); #endif /* * Make sure self-test is finished before we screw with the board. * Self-test on a DELUA can take 15 seconds (argh). */ for (i = 0; i < 160 && (addr->pcsr0 & PCSR0_FATI) == 0 && (addr->pcsr1 & PCSR1_STMASK) == STAT_RESET; ++i) DELAY(100000); if ((addr->pcsr0 & PCSR0_FATI) != 0 || (addr->pcsr1 & PCSR1_STMASK) != STAT_READY) return(0); addr->pcsr0 = 0; DELAY(100); addr->pcsr0 = PCSR0_RSET; while ((addr->pcsr0 & PCSR0_INTR) == 0) ; /* make board interrupt by executing a GETPCBB command */ addr->pcsr0 = PCSR0_INTE; addr->pcsr2 = 0; addr->pcsr3 = 0; addr->pcsr0 = PCSR0_INTE|CMD_GETPCBB; DELAY(100000); return(1); } /* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. We get the ethernet address here. */ deattach(ui) struct uba_device *ui; { register struct de_softc *ds = &de_softc[ui->ui_unit]; register struct ifnet *ifp = &ds->ds_if; register struct dedevice *addr = (struct dedevice *)ui->ui_addr; int csr1; ifp->if_unit = ui->ui_unit; ifp->if_name = "de"; ifp->if_mtu = ETHERMTU; ifp->if_flags = IFF_BROADCAST; /* * What kind of a board is this? * The error bits 4-6 in pcsr1 are a device id as long as * the high byte is zero. */ csr1 = addr->pcsr1; if (csr1 & 0xff60) printf("de%d: broken\n", ui->ui_unit); else if (csr1 & 0x10) printf("de%d: delua\n", ui->ui_unit); else printf("de%d: deuna\n", ui->ui_unit); /* * Reset the board and temporarily map * the pcbb buffer onto the Unibus. */ addr->pcsr0 = 0; /* reset INTE */ DELAY(100); addr->pcsr0 = PCSR0_RSET; (void)dewait(ui, "reset"); ds->ds_ubaddr = uballoc(ui->ui_ubanum, (char *)&ds->ds_pcbb, sizeof (struct de_pcbb), 0); addr->pcsr2 = ds->ds_ubaddr & 0xffff; addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3; addr->pclow = CMD_GETPCBB; (void)dewait(ui, "pcbb"); ds->ds_pcbb.pcbb0 = FC_RDPHYAD; addr->pclow = CMD_GETCMD; (void)dewait(ui, "read addr "); ubarelse(ui->ui_ubanum, &ds->ds_ubaddr); bcopy((caddr_t)&ds->ds_pcbb.pcbb2, (caddr_t)ds->ds_addr, sizeof (ds->ds_addr)); printf("de%d: hardware address %s\n", ui->ui_unit, ether_sprintf(ds->ds_addr)); ifp->if_init = deinit; ifp->if_output = deoutput; ifp->if_ioctl = deioctl; ifp->if_reset = dereset; ds->ds_deuba.iff_flags = UBA_CANTWAIT; #ifdef notdef /* CAN WE USE BDP's ??? */ ds->ds_deuba.iff_flags |= UBA_NEEDBDP; #endif if_attach(ifp); } /* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */ dereset(unit, uban) int unit, uban; { register struct uba_device *ui; if (unit >= NDE || (ui = deinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" de%d", unit); de_softc[unit].ds_if.if_flags &= ~IFF_RUNNING; de_softc[unit].ds_flags &= ~(DSF_LOCK | DSF_RUNNING); deinit(unit); } /* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */ deinit(unit) int unit; { register struct de_softc *ds = &de_softc[unit]; register struct uba_device *ui = deinfo[unit]; register struct dedevice *addr; register struct ifrw *ifrw; register struct ifxmt *ifxp; struct ifnet *ifp = &ds->ds_if; int s; struct de_ring *rp; int incaddr; /* not yet, if address still unknown */ if (ifp->if_addrlist == (struct ifaddr *)0) return; if (ds->ds_flags & DSF_RUNNING) return; if ((ifp->if_flags & IFF_RUNNING) == 0) { if (if_ubaminit(&ds->ds_deuba, ui->ui_ubanum, sizeof (struct ether_header), (int)btoc(ETHERMTU), ds->ds_ifr, NRCV, ds->ds_ifw, NXMT) == 0) { printf("de%d: can't initialize\n", unit); ds->ds_if.if_flags &= ~IFF_UP; return; } ds->ds_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(ds), INCORE_SIZE, 0); } addr = (struct dedevice *)ui->ui_addr; /* set the pcbb block address */ incaddr = ds->ds_ubaddr + PCBB_OFFSET; addr->pcsr2 = incaddr & 0xffff; addr->pcsr3 = (incaddr >> 16) & 0x3; addr->pclow = 0; /* reset INTE */ DELAY(100); addr->pclow = CMD_GETPCBB; (void)dewait(ui, "pcbb"); /* set the transmit and receive ring header addresses */ incaddr = ds->ds_ubaddr + UDBBUF_OFFSET; ds->ds_pcbb.pcbb0 = FC_WTRING; ds->ds_pcbb.pcbb2 = incaddr & 0xffff; ds->ds_pcbb.pcbb4 = (incaddr >> 16) & 0x3; incaddr = ds->ds_ubaddr + XRENT_OFFSET; ds->ds_udbbuf.b_tdrbl = incaddr & 0xffff; ds->ds_udbbuf.b_tdrbh = (incaddr >> 16) & 0x3; ds->ds_udbbuf.b_telen = sizeof (struct de_ring) / sizeof (short); ds->ds_udbbuf.b_trlen = NXMT; incaddr = ds->ds_ubaddr + RRENT_OFFSET; ds->ds_udbbuf.b_rdrbl = incaddr & 0xffff; ds->ds_udbbuf.b_rdrbh = (incaddr >> 16) & 0x3; ds->ds_udbbuf.b_relen = sizeof (struct de_ring) / sizeof (short); ds->ds_udbbuf.b_rrlen = NRCV; addr->pclow = CMD_GETCMD; (void)dewait(ui, "wtring"); /* initialize the mode - enable hardware padding */ ds->ds_pcbb.pcbb0 = FC_WTMODE; /* let hardware do padding - set MTCH bit on broadcast */ ds->ds_pcbb.pcbb2 = MOD_TPAD|MOD_HDX; addr->pclow = CMD_GETCMD; (void)dewait(ui, "wtmode"); /* set up the receive and transmit ring entries */ ifxp = &ds->ds_ifw[0]; for (rp = &ds->ds_xrent[0]; rp < &ds->ds_xrent[NXMT]; rp++) { rp->r_segbl = ifxp->ifw_info & 0xffff; rp->r_segbh = (ifxp->ifw_info >> 16) & 0x3; rp->r_flags = 0; ifxp++; } ifrw = &ds->ds_ifr[0]; for (rp = &ds->ds_rrent[0]; rp < &ds->ds_rrent[NRCV]; rp++) { rp->r_slen = sizeof (struct de_buf); rp->r_segbl = ifrw->ifrw_info & 0xffff; rp->r_segbh = (ifrw->ifrw_info >> 16) & 0x3; rp->r_flags = RFLG_OWN; /* hang receive */ ifrw++; } /* start up the board (rah rah) */ s = splimp(); ds->ds_rindex = ds->ds_xindex = ds->ds_xfree = ds->ds_nxmit = 0; ds->ds_if.if_flags |= IFF_RUNNING; addr->pclow = PCSR0_INTE; /* avoid interlock */ destart(unit); /* queue output packets */ ds->ds_flags |= DSF_RUNNING; /* need before de_setaddr */ if (ds->ds_flags & DSF_SETADDR) de_setaddr(ds->ds_addr, unit); addr->pclow = CMD_START | PCSR0_INTE; splx(s); } /* * Setup output on interface. * Get another datagram to send off of the interface queue, * and map it to the interface before starting the output. */ destart(unit) int unit; { int len; struct uba_device *ui = deinfo[unit]; struct dedevice *addr = (struct dedevice *)ui->ui_addr; register struct de_softc *ds = &de_softc[unit]; register struct de_ring *rp; struct mbuf *m; register int nxmit; /* * the following test is necessary, since * the code is not reentrant and we have * multiple transmission buffers. */ if (ds->ds_flags & DSF_LOCK) return; for (nxmit = ds->ds_nxmit; nxmit < NXMT; nxmit++) { IF_DEQUEUE(&ds->ds_if.if_snd, m); if (m == 0) break; rp = &ds->ds_xrent[ds->ds_xfree]; if (rp->r_flags & XFLG_OWN) panic("deuna xmit in progress"); len = if_ubaput(&ds->ds_deuba, &ds->ds_ifw[ds->ds_xfree], m); if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) UBAPURGE(ds->ds_deuba.iff_uba, ds->ds_ifw[ds->ds_xfree].ifw_bdp); rp->r_slen = len; rp->r_tdrerr = 0; rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN; ds->ds_xfree++; if (ds->ds_xfree == NXMT) ds->ds_xfree = 0; } if (ds->ds_nxmit != nxmit) { ds->ds_nxmit = nxmit; if (ds->ds_flags & DSF_RUNNING) addr->pclow = PCSR0_INTE|CMD_PDMD; } } /* * Command done interrupt. */ deintr(unit) int unit; { struct uba_device *ui = deinfo[unit]; register struct dedevice *addr = (struct dedevice *)ui->ui_addr; register struct de_softc *ds = &de_softc[unit]; register struct de_ring *rp; register struct ifxmt *ifxp; short csr0; /* save flags right away - clear out interrupt bits */ csr0 = addr->pcsr0; addr->pchigh = csr0 >> 8; ds->ds_flags |= DSF_LOCK; /* prevent entering destart */ /* * if receive, put receive buffer on mbuf * and hang the request again */ derecv(unit); /* * Poll transmit ring and check status. * Be careful about loopback requests. * Then free buffer space and check for * more transmit requests. */ for ( ; ds->ds_nxmit > 0; ds->ds_nxmit--) { rp = &ds->ds_xrent[ds->ds_xindex]; if (rp->r_flags & XFLG_OWN) break; ds->ds_if.if_opackets++; ifxp = &ds->ds_ifw[ds->ds_xindex]; /* check for unusual conditions */ if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) { if (rp->r_flags & XFLG_ERRS) { /* output error */ ds->ds_if.if_oerrors++; if (dedebug) printf("de%d: oerror, flags=%b tdrerr=%b (len=%d)\n", unit, rp->r_flags, XFLG_BITS, rp->r_tdrerr, XERR_BITS, rp->r_slen); } else if (rp->r_flags & XFLG_ONE) { /* one collision */ ds->ds_if.if_collisions++; } else if (rp->r_flags & XFLG_MORE) { /* more than one collision */ ds->ds_if.if_collisions += 2; /* guess */ } else if (rp->r_flags & XFLG_MTCH) { /* received our own packet */ ds->ds_if.if_ipackets++; deread(ds, &ifxp->ifrw, rp->r_slen - sizeof (struct ether_header)); } } if (ifxp->ifw_xtofree) { m_freem(ifxp->ifw_xtofree); ifxp->ifw_xtofree = 0; } /* check if next transmit buffer also finished */ ds->ds_xindex++; if (ds->ds_xindex == NXMT) ds->ds_xindex = 0; } ds->ds_flags &= ~DSF_LOCK; destart(unit); if (csr0 & PCSR0_RCBI) { if (dedebug) log(LOG_WARNING, "de%d: buffer unavailable\n", unit); addr->pclow = PCSR0_INTE|CMD_PDMD; } } /* * Ethernet interface receiver interface. * If input error just drop packet. * Otherwise purge input buffered data path and examine * packet to determine type. If can't determine length * from type, then have to drop packet. Othewise decapsulate * packet based on type and pass to type specific higher-level * input routine. */ derecv(unit) int unit; { register struct de_softc *ds = &de_softc[unit]; register struct de_ring *rp; int len; rp = &ds->ds_rrent[ds->ds_rindex]; while ((rp->r_flags & RFLG_OWN) == 0) { ds->ds_if.if_ipackets++; if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) UBAPURGE(ds->ds_deuba.iff_uba, ds->ds_ifr[ds->ds_rindex].ifrw_bdp); len = (rp->r_lenerr&RERR_MLEN) - sizeof (struct ether_header) - 4; /* don't forget checksum! */ /* check for errors */ if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) || (rp->r_flags&(RFLG_STP|RFLG_ENP)) != (RFLG_STP|RFLG_ENP) || (rp->r_lenerr & (RERR_BUFL|RERR_UBTO|RERR_NCHN)) || len < ETHERMIN || len > ETHERMTU) { ds->ds_if.if_ierrors++; if (dedebug) printf("de%d: ierror, flags=%b lenerr=%b (len=%d)\n", unit, rp->r_flags, RFLG_BITS, rp->r_lenerr, RERR_BITS, len); } else deread(ds, &ds->ds_ifr[ds->ds_rindex], len); /* hang the receive buffer again */ rp->r_lenerr = 0; rp->r_flags = RFLG_OWN; /* check next receive buffer */ ds->ds_rindex++; if (ds->ds_rindex == NRCV) ds->ds_rindex = 0; rp = &ds->ds_rrent[ds->ds_rindex]; } } /* * Pass a packet to the higher levels. * We deal with the trailer protocol here. */ deread(ds, ifrw, len) register struct de_softc *ds; struct ifrw *ifrw; int len; { struct ether_header *eh; struct mbuf *m; int off, resid; int s; register struct ifqueue *inq; /* * Deal with trailer protocol: if type is trailer type * get true type from first 16-bit word past data. * Remember that type was trailer by setting off. */ eh = (struct ether_header *)ifrw->ifrw_addr; eh->ether_type = ntohs((u_short)eh->ether_type); #define dedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off)))) if (eh->ether_type >= ETHERTYPE_TRAIL && eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { off = (eh->ether_type - ETHERTYPE_TRAIL) * 512; if (off >= ETHERMTU) return; /* sanity */ eh->ether_type = ntohs(*dedataaddr(eh, off, u_short *)); resid = ntohs(*(dedataaddr(eh, off+2, u_short *))); if (off + resid > len) return; /* sanity */ len = off + resid; } else off = 0; if (len == 0) return; /* * Pull packet off interface. Off is nonzero if packet * has trailing header; if_ubaget will then force this header * information to be at the front, but we still have to drop * the type and length which are at the front of any trailer data. */ m = if_ubaget(&ds->ds_deuba, ifrw, len, off, &ds->ds_if); if (m == 0) return; if (off) { struct ifnet *ifp; ifp = *(mtod(m, struct ifnet **)); m->m_off += 2 * sizeof (u_short); m->m_len -= 2 * sizeof (u_short); *(mtod(m, struct ifnet **)) = ifp; } switch (eh->ether_type) { #ifdef INET case ETHERTYPE_IP: schednetisr(NETISR_IP); inq = &ipintrq; break; case ETHERTYPE_ARP: arpinput(&ds->ds_ac, m); return; #endif #ifdef NS case ETHERTYPE_NS: schednetisr(NETISR_NS); inq = &nsintrq; break; #endif default: m_freem(m); return; } s = splimp(); if (IF_QFULL(inq)) { IF_DROP(inq); splx(s); m_freem(m); return; } IF_ENQUEUE(inq, m); splx(s); } /* * Ethernet output routine. * Encapsulate a packet of type family for the local net. * Use trailer local net encapsulation if enough data in first * packet leaves a multiple of 512 bytes of data in remainder. */ deoutput(ifp, m0, dst) struct ifnet *ifp; struct mbuf *m0; struct sockaddr *dst; { int type, s, error; u_char edst[6]; struct in_addr idst; register struct de_softc *ds = &de_softc[ifp->if_unit]; register struct mbuf *m = m0; register struct ether_header *eh; register int off; int usetrailers; if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { error = ENETDOWN; goto bad; } switch (dst->sa_family) { #ifdef INET case AF_INET: idst = ((struct sockaddr_in *)dst)->sin_addr; if (!arpresolve(&ds->ds_ac, m, &idst, edst, &usetrailers)) return (0); /* if not yet resolved */ off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; if (usetrailers && off > 0 && (off & 0x1ff) == 0 && m->m_off >= MMINOFF + 2 * sizeof (u_short)) { type = ETHERTYPE_TRAIL + (off>>9); m->m_off -= 2 * sizeof (u_short); m->m_len += 2 * sizeof (u_short); *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); goto gottrailertype; } type = ETHERTYPE_IP; off = 0; goto gottype; #endif #ifdef NS case AF_NS: type = ETHERTYPE_NS; bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), (caddr_t)edst, sizeof (edst)); off = 0; goto gottype; #endif case AF_UNSPEC: eh = (struct ether_header *)dst->sa_data; bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); type = eh->ether_type; goto gottype; default: printf("de%d: can't handle af%d\n", ifp->if_unit, dst->sa_family); error = EAFNOSUPPORT; goto bad; } gottrailertype: /* * Packet to be sent as trailer: move first packet * (control information) to end of chain. */ while (m->m_next) m = m->m_next; m->m_next = m0; m = m0->m_next; m0->m_next = 0; m0 = m; gottype: /* * Add local net header. If no space in first mbuf, * allocate another. */ if (m->m_off > MMAXOFF || MMINOFF + sizeof (struct ether_header) > m->m_off) { m = m_get(M_DONTWAIT, MT_HEADER); if (m == 0) { error = ENOBUFS; goto bad; } m->m_next = m0; m->m_off = MMINOFF; m->m_len = sizeof (struct ether_header); } else { m->m_off -= sizeof (struct ether_header); m->m_len += sizeof (struct ether_header); } eh = mtod(m, struct ether_header *); eh->ether_type = htons((u_short)type); bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); /* DEUNA fills in source address */ /* * Queue message on interface, and start output if interface * not yet active. */ s = splimp(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); splx(s); m_freem(m); return (ENOBUFS); } IF_ENQUEUE(&ifp->if_snd, m); destart(ifp->if_unit); splx(s); return (0); bad: m_freem(m0); return (error); } /* * Process an ioctl request. */ deioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { register struct ifaddr *ifa = (struct ifaddr *)data; register struct de_softc *ds = &de_softc[ifp->if_unit]; int s = splimp(), error = 0; switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; deinit(ifp->if_unit); switch (ifa->ifa_addr.sa_family) { #ifdef INET case AF_INET: ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr; arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); break; #endif #ifdef NS case AF_NS: { register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); if (ns_nullhost(*ina)) ina->x_host = *(union ns_host *)(ds->ds_addr); else de_setaddr(ina->x_host.c_host,ifp->if_unit); break; } #endif } break; case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_UP) == 0 && ds->ds_flags & DSF_RUNNING) { ((struct dedevice *) (deinfo[ifp->if_unit]->ui_addr))->pclow = 0; DELAY(100); ((struct dedevice *) (deinfo[ifp->if_unit]->ui_addr))->pclow = PCSR0_RSET; ds->ds_flags &= ~(DSF_LOCK | DSF_RUNNING); } else if (ifp->if_flags & IFF_UP && (ds->ds_flags & DSF_RUNNING) == 0) deinit(ifp->if_unit); break; default: error = EINVAL; } splx(s); return (error); } /* * set ethernet address for unit */ de_setaddr(physaddr, unit) u_char *physaddr; int unit; { register struct de_softc *ds = &de_softc[unit]; struct uba_device *ui = deinfo[unit]; register struct dedevice *addr= (struct dedevice *)ui->ui_addr; if (! (ds->ds_flags & DSF_RUNNING)) return; bcopy(physaddr, &ds->ds_pcbb.pcbb2, 6); ds->ds_pcbb.pcbb0 = FC_WTPHYAD; addr->pclow = PCSR0_INTE|CMD_GETCMD; if (dewait(ui, "address change") == 0) { ds->ds_flags |= DSF_SETADDR; bcopy(physaddr, ds->ds_addr, 6); } } /* * Await completion of the named function * and check for errors. */ dewait(ui, fn) register struct uba_device *ui; char *fn; { register struct dedevice *addr = (struct dedevice *)ui->ui_addr; register csr0; while ((addr->pcsr0 & PCSR0_INTR) == 0) ; csr0 = addr->pcsr0; addr->pchigh = csr0 >> 8; if (csr0 & PCSR0_PCEI) printf("de%d: %s failed, csr0=%b csr1=%b\n", ui->ui_unit, fn, csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS); return (csr0 & PCSR0_PCEI); } #endif l about loopback requests. * Then free buffer space and check for * more transmit requests. */ for ( ; ds->ds_nxmitsys/vaxif/if_en.c 444 0 12 41775 3671424547 7257 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_en.c 7.1 (Berkeley) 6/5/86 */ #include "en.h" #if NEN > 0 /* * Xerox prototype (3 Mb) Ethernet interface driver. */ #include "../machine/pte.h" #include "param.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "protosw.h" #include "socket.h" #include "vmmac.h" #include "errno.h" #include "ioctl.h" #include "../net/if.h" #include "../net/netisr.h" #include "../net/route.h" #ifdef INET #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netinet/in_var.h" #include "../netinet/ip.h" #endif #ifdef PUP #include "../netpup/pup.h" #include "../netpup/ether.h" #endif #ifdef NS #include "../netns/ns.h" #include "../netns/ns_if.h" #endif #include "../vax/cpu.h" #include "../vax/mtpr.h" #include "if_en.h" #include "if_enreg.h" #include "if_uba.h" #include "../vaxuba/ubareg.h" #include "../vaxuba/ubavar.h" #define ENMTU (1024+512) #define ENMRU (1024+512+16) /* 16 is enough to receive trailer */ int enprobe(), enattach(), enrint(), enxint(), encollide(); struct uba_device *eninfo[NEN]; u_short enstd[] = { 0 }; struct uba_driver endriver = { enprobe, 0, enattach, 0, enstd, "en", eninfo }; #define ENUNIT(x) minor(x) int eninit(),enoutput(),enreset(),enioctl(); #ifdef notdef /* * If you need to byte swap IP's in the system, define * this and do a SIOCSIFFLAGS at boot time. */ #define ENF_SWABIPS 0x1000 #endif /* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * es_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... * We also have, for each interface, a UBA interface structure, which * contains information about the UNIBUS resources held by the interface: * map registers, buffered data paths, etc. Information is cached in this * structure for use by the if_uba.c routines in running the interface * efficiently. */ struct en_softc { struct ifnet es_if; /* network-visible interface */ struct ifuba es_ifuba; /* UNIBUS resources */ short es_host; /* hardware host number */ short es_delay; /* current output delay */ short es_mask; /* mask for current output delay */ short es_lastx; /* host last transmitted to */ short es_oactive; /* is output active? */ short es_olen; /* length of last output */ short es_nsactive; /* is interface enabled for ns? */ } en_softc[NEN]; /* * Do output DMA to determine interface presence and * interrupt vector. DMA is too short to disturb other hosts. */ enprobe(reg) caddr_t reg; { register int br, cvec; /* r11, r10 value-result */ register struct endevice *addr = (struct endevice *)reg; #ifdef lint br = 0; cvec = br; br = cvec; enrint(0); enxint(0); encollide(0); #endif addr->en_istat = 0; addr->en_owc = -1; addr->en_oba = 0; addr->en_ostat = EN_IEN|EN_GO; DELAY(100000); addr->en_ostat = 0; return (1); } /* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */ enattach(ui) struct uba_device *ui; { register struct en_softc *es = &en_softc[ui->ui_unit]; es->es_if.if_unit = ui->ui_unit; es->es_if.if_name = "en"; es->es_if.if_mtu = ENMTU; es->es_if.if_flags = IFF_BROADCAST; es->es_if.if_init = eninit; es->es_if.if_output = enoutput; es->es_if.if_ioctl = enioctl; es->es_if.if_reset = enreset; es->es_ifuba.ifu_flags = UBA_NEEDBDP | UBA_NEED16 | UBA_CANTWAIT; #if defined(VAX750) /* don't chew up 750 bdp's */ if (cpu == VAX_750 && ui->ui_unit > 0) es->es_ifuba.ifu_flags &= ~UBA_NEEDBDP; #endif if_attach(&es->es_if); } /* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */ enreset(unit, uban) int unit, uban; { register struct uba_device *ui; if (unit >= NEN || (ui = eninfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" en%d", unit); eninit(unit); } /* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */ eninit(unit) int unit; { register struct en_softc *es = &en_softc[unit]; register struct uba_device *ui = eninfo[unit]; register struct endevice *addr; int s; if (es->es_if.if_addrlist == (struct ifaddr *)0) return; if (if_ubainit(&es->es_ifuba, ui->ui_ubanum, sizeof (struct en_header), (int)btoc(ENMRU)) == 0) { printf("en%d: can't initialize\n", unit); es->es_if.if_flags &= ~IFF_UP; return; } addr = (struct endevice *)ui->ui_addr; addr->en_istat = addr->en_ostat = 0; /* * Hang a receive and start any * pending writes by faking a transmit complete. */ s = splimp(); addr->en_iba = es->es_ifuba.ifu_r.ifrw_info; addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1; addr->en_istat = EN_IEN|EN_GO; es->es_oactive = 1; es->es_if.if_flags |= IFF_RUNNING; enxint(unit); splx(s); } int enalldelay = 0; int enlastdel = 50; int enlastmask = (~0) << 5; /* * Start or restart output on interface. * If interface is already active, then this is a retransmit * after a collision, and just restuff registers and delay. * If interface is not already active, get another datagram * to send off of the interface queue, and map it to the interface * before starting the output. */ enstart(dev) dev_t dev; { int unit = ENUNIT(dev); struct uba_device *ui = eninfo[unit]; register struct en_softc *es = &en_softc[unit]; register struct endevice *addr; register struct en_header *en; struct mbuf *m; int dest; if (es->es_oactive) goto restart; /* * Not already active: dequeue another request * and map it to the UNIBUS. If no more requests, * just return. */ IF_DEQUEUE(&es->es_if.if_snd, m); if (m == 0) { es->es_oactive = 0; return; } en = mtod(m, struct en_header *); dest = en->en_dhost; en->en_shost = es->es_host; es->es_olen = if_wubaput(&es->es_ifuba, m); #ifdef ENF_SWABIPS /* * The Xerox interface does word at a time DMA, so * someone must do byte swapping of user data if high * and low ender machines are to communicate. It doesn't * belong here, but certain people depend on it, so... * * Should swab everybody, but this is a kludge anyway. */ if (es->es_if.if_flags & ENF_SWABIPS) { en = (struct en_header *)es->es_ifuba.ifu_w.ifrw_addr; if (en->en_type == ENTYPE_IP) enswab((caddr_t)(en + 1), (caddr_t)(en + 1), es->es_olen - sizeof (struct en_header) + 1); } #endif /* * Ethernet cannot take back-to-back packets (no * buffering in interface. To help avoid overrunning * receivers, enforce a small delay (about 1ms) in interface: * * between all packets when enalldelay * * whenever last packet was broadcast * * whenever this packet is to same host as last packet */ if (enalldelay || es->es_lastx == 0 || es->es_lastx == dest) { es->es_delay = enlastdel; es->es_mask = enlastmask; } es->es_lastx = dest; restart: /* * Have request mapped to UNIBUS for transmission. * Purge any stale data from this BDP, and start the otput. */ if (es->es_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_w.ifrw_bdp); addr = (struct endevice *)ui->ui_addr; addr->en_oba = (int)es->es_ifuba.ifu_w.ifrw_info; addr->en_odelay = es->es_delay; addr->en_owc = -((es->es_olen + 1) >> 1); addr->en_ostat = EN_IEN|EN_GO; es->es_oactive = 1; } /* * Ethernet interface transmitter interrupt. * Start another output if more data to send. */ enxint(unit) int unit; { register struct uba_device *ui = eninfo[unit]; register struct en_softc *es = &en_softc[unit]; register struct endevice *addr = (struct endevice *)ui->ui_addr; if (es->es_oactive == 0) return; if (es->es_mask && (addr->en_ostat&EN_OERROR)) { es->es_if.if_oerrors++; endocoll(unit); return; } es->es_if.if_opackets++; es->es_oactive = 0; es->es_delay = 0; es->es_mask = ~0; if (es->es_ifuba.ifu_xtofree) { m_freem(es->es_ifuba.ifu_xtofree); es->es_ifuba.ifu_xtofree = 0; } if (es->es_if.if_snd.ifq_head == 0) { es->es_lastx = 256; /* putatively illegal */ return; } enstart(unit); } /* * Collision on ethernet interface. Do exponential * backoff, and retransmit. If have backed off all * the way print warning diagnostic, and drop packet. */ encollide(unit) int unit; { struct en_softc *es = &en_softc[unit]; es->es_if.if_collisions++; if (es->es_oactive == 0) return; endocoll(unit); } endocoll(unit) int unit; { register struct en_softc *es = &en_softc[unit]; /* * Es_mask is a 16 bit number with n low zero bits, with * n the number of backoffs. When es_mask is 0 we have * backed off 16 times, and give up. */ if (es->es_mask == 0) { printf("en%d: send error\n", unit); enxint(unit); return; } /* * Another backoff. Restart with delay based on n low bits * of the interval timer. */ es->es_mask <<= 1; es->es_delay = mfpr(ICR) &~ es->es_mask; enstart(unit); } #ifdef notdef struct sockproto enproto = { AF_ETHERLINK }; struct sockaddr_en endst = { AF_ETHERLINK }; struct sockaddr_en ensrc = { AF_ETHERLINK }; #endif /* * Ethernet interface receiver interrupt. * If input error just drop packet. * Otherwise purge input buffered data path and examine * packet to determine type. If can't determine length * from type, then have to drop packet. Othewise decapsulate * packet based on type and pass to type specific higher-level * input routine. */ enrint(unit) int unit; { register struct en_softc *es = &en_softc[unit]; struct endevice *addr = (struct endevice *)eninfo[unit]->ui_addr; register struct en_header *en; struct mbuf *m; int len; short resid; register struct ifqueue *inq; int off, s; es->es_if.if_ipackets++; /* * Purge BDP; drop if input error indicated. */ if (es->es_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_r.ifrw_bdp); if (addr->en_istat&EN_IERROR) { es->es_if.if_ierrors++; goto setup; } /* * Calculate input data length. * Get pointer to ethernet header (in input buffer). * Deal with trailer protocol: if type is PUP trailer * get true type from first 16-bit word past data. * Remember that type was trailer by setting off. */ resid = addr->en_iwc; if (resid) resid |= 0176000; len = (((sizeof (struct en_header) + ENMRU) >> 1) + resid) << 1; len -= sizeof (struct en_header); if (len > ENMRU) goto setup; /* sanity */ en = (struct en_header *)(es->es_ifuba.ifu_r.ifrw_addr); en->en_type = ntohs(en->en_type); #define endataaddr(en, off, type) ((type)(((caddr_t)((en)+1)+(off)))) if (en->en_type >= ENTYPE_TRAIL && en->en_type < ENTYPE_TRAIL+ENTYPE_NTRAILER) { off = (en->en_type - ENTYPE_TRAIL) * 512; if (off > ENMTU) goto setup; /* sanity */ en->en_type = ntohs(*endataaddr(en, off, u_short *)); resid = ntohs(*(endataaddr(en, off+2, u_short *))); if (off + resid > len) goto setup; /* sanity */ len = off + resid; } else off = 0; if (len == 0) goto setup; #ifdef ENF_SWABIPS if (es->es_if.if_flags & ENF_SWABIPS && en->en_type == ENTYPE_IP) enswab((caddr_t)(en + 1), (caddr_t)(en + 1), len); #endif /* * Pull packet off interface. Off is nonzero if packet * has trailing header; if_rubaget will then force this header * information to be at the front, but we still have to drop * the type and length which are at the front of any trailer data. */ m = if_rubaget(&es->es_ifuba, len, off, &es->es_if); if (m == 0) goto setup; if (off) { struct ifnet *ifp; ifp = *(mtod(m, struct ifnet **)); m->m_off += 2 * sizeof (u_short); m->m_len -= 2 * sizeof (u_short); *(mtod(m, struct ifnet **)) = ifp; } switch (en->en_type) { #ifdef INET case ENTYPE_IP: schednetisr(NETISR_IP); inq = &ipintrq; break; #endif #ifdef PUP case ENTYPE_PUP: rpup_input(m); goto setup; #endif #ifdef NS case ETHERTYPE_NS: if (es->es_nsactive) { schednetisr(NETISR_NS); inq = &nsintrq; } else { m_freem(m); goto setup; } break; #endif default: #ifdef notdef enproto.sp_protocol = en->en_type; endst.sen_host = en->en_dhost; endst.sen_net = ensrc.sen_net = es->es_if.if_net; ensrc.sen_host = en->en_shost; raw_input(m, &enproto, (struct sockaddr *)&ensrc, (struct sockaddr *)&endst); #else m_freem(m); #endif goto setup; } s = splimp(); if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); } else IF_ENQUEUE(inq, m); splx(s); setup: /* * Reset for next packet. */ addr->en_iba = es->es_ifuba.ifu_r.ifrw_info; addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1; addr->en_istat = EN_IEN|EN_GO; } /* * Ethernet output routine. * Encapsulate a packet of type family for the local net. * Use trailer local net encapsulation if enough data in first * packet leaves a multiple of 512 bytes of data in remainder. */ enoutput(ifp, m0, dst) struct ifnet *ifp; struct mbuf *m0; struct sockaddr *dst; { int type, dest, s, error; register struct mbuf *m = m0; register struct en_header *en; register int off; if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { error = ENETDOWN; goto bad; } switch (dst->sa_family) { #ifdef INET case AF_INET: { struct in_addr in; in = ((struct sockaddr_in *)dst)->sin_addr; if (in_broadcast(in)) dest = EN_BROADCAST; else dest = in_lnaof(in); } if (dest >= 0x100) { error = EPERM; /* ??? */ goto bad; } off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; /* need per host negotiation */ if ((ifp->if_flags & IFF_NOTRAILERS) == 0) if (off > 0 && (off & 0x1ff) == 0 && m->m_off >= MMINOFF + 2 * sizeof (u_short)) { type = ENTYPE_TRAIL + (off>>9); m->m_off -= 2 * sizeof (u_short); m->m_len += 2 * sizeof (u_short); *mtod(m, u_short *) = htons((u_short)ENTYPE_IP); *(mtod(m, u_short *) + 1) = ntohs((u_short)m->m_len); goto gottrailertype; } type = ENTYPE_IP; off = 0; goto gottype; #endif #ifdef NS case AF_NS: { u_char *up; type = ETHERTYPE_NS; up = ((struct sockaddr_ns *)dst)->sns_addr.x_host.c_host; if (*up & 1) dest = EN_BROADCAST; else dest = up[5]; off = 0; goto gottype; } #endif #ifdef PUP case AF_PUP: dest = ((struct sockaddr_pup *)dst)->spup_host; type = ENTYPE_PUP; off = 0; goto gottype; #endif #ifdef notdef case AF_ETHERLINK: goto gotheader; #endif default: printf("en%d: can't handle af%d\n", ifp->if_unit, dst->sa_family); error = EAFNOSUPPORT; goto bad; } gottrailertype: /* * Packet to be sent as trailer: move first packet * (control information) to end of chain. */ while (m->m_next) m = m->m_next; m->m_next = m0; m = m0->m_next; m0->m_next = 0; m0 = m; gottype: /* * Add local net header. If no space in first mbuf, * allocate another. */ if (m->m_off > MMAXOFF || MMINOFF + sizeof (struct en_header) > m->m_off) { MGET(m, M_DONTWAIT, MT_HEADER); if (m == 0) { error = ENOBUFS; goto bad; } m->m_next = m0; m->m_off = MMINOFF; m->m_len = sizeof (struct en_header); } else { m->m_off -= sizeof (struct en_header); m->m_len += sizeof (struct en_header); } en = mtod(m, struct en_header *); /* add en_shost later */ en->en_dhost = dest; en->en_type = htons((u_short)type); #ifdef notdef gotheader: #endif /* * Queue message on interface, and start output if interface * not yet active. */ s = splimp(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); error = ENOBUFS; goto qfull; } IF_ENQUEUE(&ifp->if_snd, m); if (en_softc[ifp->if_unit].es_oactive == 0) enstart(ifp->if_unit); splx(s); return (0); qfull: m0 = m; splx(s); bad: m_freem(m0); return (error); } /* * Process an ioctl request. */ enioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { register struct en_softc *es = ((struct en_softc *)ifp); struct ifaddr *ifa = (struct ifaddr *) data; int s = splimp(), error = 0; struct endevice *enaddr; switch (cmd) { case SIOCSIFADDR: enaddr = (struct endevice *)eninfo[ifp->if_unit]->ui_addr; es->es_host = (~enaddr->en_addr) & 0xff; /* * Attempt to check agreement of protocol address * and board address. */ switch (ifa->ifa_addr.sa_family) { case AF_INET: if (in_lnaof(IA_SIN(ifa)->sin_addr) != es->es_host) return (EADDRNOTAVAIL); break; #ifdef NS case AF_NS: if (IA_SNS(ifa)->sns_addr.x_host.c_host[5] != es->es_host) return (EADDRNOTAVAIL); es->es_nsactive = 1; break; #endif } ifp->if_flags |= IFF_UP; if ((ifp->if_flags & IFF_RUNNING) == 0) eninit(ifp->if_unit); break; default: error = EINVAL; break; } splx(s); return (error); } #ifdef ENF_SWABIPS /* * Swab bytes * Jeffrey Mogul, Stanford */ enswab(from, to, n) register unsigned char *from, *to; register int n; { register unsigned long temp; if ((n <= 0) || (n > 0xFFFF)) { printf("enswab: bad len %d\n", n); return; } n >>= 1; n++; #define STEP {temp = *from++;*to++ = *from++;*to++ = temp;} /* round to multiple of 8 */ while ((--n) & 07) STEP; n >>= 3; while (--n >= 0) { STEP; STEP; STEP; STEP; STEP; STEP; STEP; STEP; } } #endif #endif /* sys/vaxif/if_hyreg.h 444 0 12 14730 3671247665 7773 /* * @(#)if_hyreg.h 7.1 (Berkeley) 6/5/86 * * $Header: if_hyreg.h,v 10.0 84/06/30 19:51:34 steveg Stable $ * $Locker: $ * * Modifications from Berkeley 4.2 BSD * Copyright (c) 1983, Tektronix Inc. * All Rights Reserved * */ /* * Network Systems Corporation Hyperchannel interface * * supports A410 adapter interfaced via a DEC DR-11B, NSC PI-13 or PI-14 * (PI-14 is a PI-13 with different line drivers, software is * identical to a PI-13) * * Written by Steve Glaser, Tektronix Inc., July 1982 * * NOTE: * * DR11B code has not been fully checked out with 4.1a. * The first adapters at Tek came with DR11Bs, and the code once worked, * but those have been upgraded to PI-13s. */ /* * The HYPERchannel driver sends and receives messages formatted: * * +---------------------------------------+ --- * | | /|\ * | HYPERchannel adapter header (hy_hdr) | | * | | | * +---------------------------------------+ | * | | | * | Internet Protocol header (ip) | message proper * | | (64 bytes max) * +---------------------------------------+ | * | | | * | TCP header + user data | | * | (if it all fits here) | | * | | \|/ * +---------------------------------------+ --- * * +---------------------------------------+ --- * | | /|\ * | | | * | TCP header + user data | associated data * | | | * | | \|/ * +---------------------------------------+ --- * * If all of the datagram will fit in the message proper (including * the TCP header and user data) the entire datagram is passed in * the message proper and the associated data feature of the HYPERchannel * is not used. * * The mapping from internet addresses to HYPERchannel addresses is: * * 0 7 8 15 16 31 * +---------+---------+-----------------------+ * | network | special | HYPERchannel address | * +---------+---------+-----------------------+ * * |<------------ internet address ----------->| * * The hyperchannel address is decoded as follows: * * 0 7 8 13 14 15 * +-------------------+----------------+------+ * | adapter number | zero | port | * +-------------------+----------------+------+ * * The low 2 bits are port number (interpreted by hyperchannel hardware). * * The encoding of special bits is: * * 00 normal packet * * 01 loop this packet back to the sender at the * specified adapter (ip header source/destination addresses * swapped before sending, command bits added to tell the * remote HYPERchannel adapter debug & performance studies] * this code acts like 02 (below) if the ip destination (before * any swapping) and the destination address don't match (e.g. * this packet is being routed through a gateway) * * 02 loop this packet back to the sender at the * specified adapter, but go through the specified adapter's * IP. This is for testing IP's store and forward mechanism. * * other undefined, currently treated as normal packet * */ #define MPSIZE 64 /* "Message Proper" size */ #define MAXRETRY 4 /* * Device registers */ struct hydevice { short hyd_wcr; /* word count (negated) */ u_short hyd_bar; /* bus address bits 15-0 */ u_short hyd_csr; /* control and status */ u_short hyd_dbuf; /* data buffer */ }; /* * CSR bit layout */ #define S_ERROR 0100000 /* error */ #define S_NEX 0040000 /* non-existent memory error */ #define S_ATTN 0020000 /* attn (always zero) */ #ifdef PI13 #define S_STKINTR 0010000 /* stacked interrupt */ #else #define S_MAINT 0010000 /* maintenance (not used) */ #endif #define S_A 0004000 /* device status A (recieve data available) */ #define S_B 0002000 /* device status B (normal termination) */ #define S_C 0001000 /* device status C (abnormal termination) */ #ifdef PI13 #define S_POWEROFF 0000400 /* power off indicator */ #else #define S_CYCLE 0000400 /* cycle (not used) */ #endif #define S_READY 0000200 /* ready */ #define S_IE 0000100 /* interrupt enable */ #define S_XBA 0000060 /* bus address bit bits 17 and 16 */ #define S_CLRINT 0000014 /* clear stacked interrupt */ #define S_IATTN 0000010 /* interrupt on attention only */ #define S_WC 0000004 /* interrupt on word count == 0 only */ #define S_IATTNWC 0000000 /* interrupt on word count == 0 and attention */ #define S_BURST 0000002 /* burst mode DMA (not used) */ #define S_GO 0000001 /* go */ #define XBASHIFT 12 #define HY_CSR_BITS "\20\ \20ERROR\17NEX\16ATTN\15STKINTR\14RECV_DATA\13NORMAL\12ABNORMAL\11POWER\ \10READY\07IENABLE\06XBA17\05XBA16\04IATTN\03IWC\02BURST\01GO" /* * PI13 status conditions */ #define HYS_RECVDATA(x) (((x)->hyd_csr & S_A) != 0) /* get adapter data */ #define HYS_NORMAL(x) (((x)->hyd_csr & S_B) != 0) /* done normally */ #define HYS_ABNORMAL(x) (((x)->hyd_csr & S_C) != 0) /* done abnormally */ #define HYS_ERROR(x) (((x)->hyd_csr & S_ERROR) != 0) /* error condition */ #define HYS_DONE(x) (((x)->hyd_csr & (S_ERROR|S_B|S_C)) != 0) /* * Function Codes for the Hyperchannel Adapter * The codes are offset so they can be "or"ed into * the reg data buffer */ #define HYF_XMITMSG 0x04 /* transmit message */ #define HYF_XMITDATA 0x08 /* transmit associated data */ #define HYF_XMITLSTDATA 0x0C /* transmit last associated data */ #define HYF_XMITLOCMSG 0x10 /* transmit local message */ #define HYF_INPUTMSG 0x24 /* input message proper */ #define HYF_INPUTDATA 0x28 /* input assiciated data */ #define HYF_STATUS 0x40 /* request status */ #define HYF_DUMPREGS 0x50 /* dump extention registers */ #define HYF_MARKP0 0x60 /* mark down port 0 */ #define HYF_MARKP1 0x64 /* mark down port 1 */ #define HYF_MARKP2 0x68 /* mark down port 2 */ #define HYF_MARKP3 0x6C /* mark down port 3 */ #define HYF_MP0RR 0x70 /* mark down port 0 and reroute messages */ #define HYF_MP1RR 0x74 /* mark down port 1 and reroute messages */ #define HYF_MP2RR 0x78 /* mark down port 2 and reroute messages */ #define HYF_MP3RR 0x7C /* mark down port 3 and reroute messages */ #define HYF_RSTATS 0xA0 /* read statistics */ #define HYF_RCSTATS 0xA4 /* read and clear statistics */ #define HYF_SETTEST 0xC0 /* enable test operations *set test mode) */ #define HYF_SADDR_LEN 0xC4 /* test mode: set address and length */ #define HYF_WBUFF 0xC8 /* test mode: write buffer */ #define HYF_RBUFF 0xCC /* test mode: read buffer */ #define HYF_CLRADAPTER 0xE0 /* clear adapter */ #define HYF_END_OP 0xE4 /* end operation */ #define HYF_CLRWFMSG 0xE6 /* clear wait for mwssage */ #define HYF_WAITFORMSG 0xE8 /* wait for message */ pped before sending, command bits added sys/vaxif/if_il.h 444 0 12 3224 3671247703 7226 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_il.h 7.1 (Berkeley) 6/5/86 */ /* * Structure of an Ethernet header -- receive format */ struct il_rheader { u_char ilr_status; /* Frame Status */ u_char ilr_fill1; u_short ilr_length; /* Frame Length */ u_char ilr_dhost[6]; /* Destination Host */ u_char ilr_shost[6]; /* Source Host */ u_short ilr_type; /* Type of packet */ }; /* * Structure of statistics record */ struct il_stats { u_short ils_fill1; u_short ils_length; /* Length (should be 62) */ u_char ils_addr[6]; /* Ethernet Address */ u_short ils_frames; /* Number of Frames Received */ u_short ils_rfifo; /* Number of Frames in Receive FIFO */ u_short ils_xmit; /* Number of Frames Transmitted */ u_short ils_xcollis; /* Number of Excess Collisions */ u_short ils_frag; /* Number of Fragments Received */ u_short ils_lost; /* Number of Times Frames Lost */ u_short ils_multi; /* Number of Multicasts Accepted */ u_short ils_rmulti; /* Number of Multicasts Rejected */ u_short ils_crc; /* Number of CRC Errors */ u_short ils_align; /* Number of Alignment Errors */ u_short ils_collis; /* Number of Collisions */ u_short ils_owcollis; /* Number of Out-of-window Collisions */ u_short ils_fill2[8]; char ils_module[8]; /* Module ID */ char ils_firmware[8]; /* Firmware ID */ }; /* * Structure of Collision Delay Time Record */ struct il_collis { u_short ilc_fill1; u_short ilc_length; /* Length (should be 0-32) */ u_short ilc_delay[16]; /* Delay Times */ }; C /* mark down port 3 */ #define HYF_MP0RR 0x70 /* mark down port 0 and reroute messages */ #define HYF_MP1RR 0x74 /* mark down port 1 and reroute messages */ #define HYF_MP2RR 0x78 /* mark down port 2 and reroute messages */ #define HYF_MP3RR 0x7C /* mark down port 3 and reroute messages */ #define HYF_RSTATS 0xA0 /* read statistics */ #define HYF_RCSTATS 0xA4 sys/vaxif/if_vv.h 444 0 12 7372 3671250041 7252 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_vv.h 7.1 (Berkeley) 6/5/86 */ /* * ECO 176-748 changed the braodcast address from 0 to 0xff, at * CTL (p1002) serial number around 150. * It was implemented in August, 1982. This is a field-installable ECO, * which improves net reliability. If the broadcast address has not been * changed, comment out the following line. */ #define NEW_BROADCAST /* new chip for broadcast problem */ /* * Local network header for proNET Ring * This is arbitrated by "jas@proteon" * (aka John Shriver, 617-655-3340) */ struct vv_header { /* the first two fields are required by the hardware */ u_char vh_dhost; /* destination address */ u_char vh_shost; /* source address */ /* the next three fields are the local network header */ u_char vh_version; /* header version */ u_char vh_type; /* packet type => protocol number */ short vh_info; /* protocol-specific information */ }; #define RING_VERSION 2 /* current version of v2lni header */ /* * Packet types (protocol numbers) in proNET protocol header * Other types are defined, but are proprietary. */ #define RING_IP 1 #define RING_TRAILER 2 /* offset now in vh_info only */ #define RING_ARP 3 #define RING_HDLC 4 #define RING_VAXDB 5 #define RING_RINGWAY 6 #define RING_RINGWAYM 8 #define RING_NOVELL 10 #define RING_PUP 12 #define RING_XNS 14 #define RING_DIAGNOSTICS 15 /* protocol type for testing */ #define RING_ECHO 16 #ifdef NEW_BROADCAST #define VV_BROADCAST 0xff /* hardware-defined broadcast address */ #else #define VV_BROADCAST 0x00 /* hardware-defined broadcast address */ #endif /* * Proteon proNET Hardware definitions * register bit definitions */ #define VV_ENB 01 /* Enable Operation */ #define VV_DEN 02 /* Enable DMA */ #define VV_HEN 04 /* Host Relay Enable (Rcv) */ #define VV_CPB 04 /* Clear Packet Buffer (Xmit) */ #define VV_STE 010 /* Self Test Enable (Rcv) */ #define VV_UT1 010 /* Unused (Xmit) */ #define VV_LPB 020 /* Modem Disable (Rcv) */ #define VV_INR 020 /* Initialize Ring (Xmit) */ #define VV_RST 040 /* Reset */ #define VV_IEN 0100 /* Interrupt Enable */ #define VV_RDY 0200 /* Done */ #define VV_DPR 0400 /* Data Present (Rcv) */ #define VV_RFS 0400 /* Refused (Xmit) */ #define VV_NXM 01000 /* Non Existent Memory */ #define VV_OVR 02000 /* Overrun */ #define VV_ODB 04000 /* Odd Byte (Rcv) */ #define VV_UT2 04000 /* Unused (Xmit) */ #define VV_LDE 010000 /* Parity on 10 megabit (Rcv), */ /* Link Data Error on 80 megabit (Rcv) */ #define VV_OPT 010000 /* Output Timeout (Xmit) */ #define VV_NOK 020000 /* Ring Not OK */ #define VV_BDF 040000 /* Bad Format in Operation */ #define VV_NIR 0100000 /* Not in Ring */ #define VVXERR (VV_NXM|VV_OVR|VV_OPT|VV_BDF) /* Xmit errs */ #define VVRERR (VV_NXM|VV_OVR|VV_ODB|VV_BDF|VV_DPR) /* Rcv errs */ #define VVFE (VV_NXM|VV_OVR) /* Fatal errors */ #define VV_IBITS \ "\10\20NIR\17BDF\16NOK\15LDE\14ODB\13OVR\12NXM\11DPR\10RDY\7IEN\6RST\5LPB\4STE\3HEN\2DEN\1ENB" #define VV_OBITS \ "\10\20NIR\17BDF\16NOK\15OPT\13OVR\12NXM\11RFS\10RDY\7IEN\6RST\5INR\3HEN\2DEN\1ENB" /* device registers */ struct vvreg { short vvicsr; /* input csr */ u_short vviwc; /* input word count */ u_short vviba; /* input addr lo */ u_short vviea; /* input addr hi */ short vvocsr; /* output csr */ u_short vvowc; /* output word count */ u_short vvoba; /* output addr lo */ u_short vvoea; /* output addr hi */ }; #define VVRETRY 7 /* output retry limit */ #define VVIDENTSUCC 5 /* number of successes required in self-test */ #define VVIDENTRETRY 10 /* identify loop attempt limit */ #define VVTIMEOUT 60 /* seconds before a transmit timeout */ rmination) */ #ifdef PI13 #define S_POWEROFF 0000400 /* power off indicator */ #else #define S_CYCLE 0000400 /* cycle (not used) */ #endif #define S_READY 0000200 /* ready */ #define S_IE 0000100 /* interrupt enable */ #define S_XBA 0000060 /* bus adsys/vaxif/if_dereg.h 444 0 12 15243 3671247475 7742 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_dereg.h 7.1 (Berkeley) 6/5/86 */ /* * DEC DEUNA interface */ struct dedevice { union { short p0_w; char p0_b[2]; } u_p0; #define pcsr0 u_p0.p0_w #define pclow u_p0.p0_b[0] #define pchigh u_p0.p0_b[1] short pcsr1; short pcsr2; short pcsr3; }; /* * PCSR 0 bit descriptions */ #define PCSR0_SERI 0x8000 /* Status error interrupt */ #define PCSR0_PCEI 0x4000 /* Port command error interrupt */ #define PCSR0_RXI 0x2000 /* Receive done interrupt */ #define PCSR0_TXI 0x1000 /* Transmit done interrupt */ #define PCSR0_DNI 0x0800 /* Done interrupt */ #define PCSR0_RCBI 0x0400 /* Receive buffer unavail intrpt */ #define PCSR0_FATI 0x0100 /* Fatal error interrupt */ #define PCSR0_INTR 0x0080 /* Interrupt summary */ #define PCSR0_INTE 0x0040 /* Interrupt enable */ #define PCSR0_RSET 0x0020 /* DEUNA reset */ #define PCSR0_CMASK 0x000f /* command mask */ #define PCSR0_BITS "\20\20SERI\17PCEI\16RXI\15TXI\14DNI\13RCBI\11FATI\10INTR\7INTE\6RSET" /* bits 0-3 are for the PORT_COMMAND */ #define CMD_NOOP 0x0 #define CMD_GETPCBB 0x1 /* Get PCB Block */ #define CMD_GETCMD 0x2 /* Execute command in PCB */ #define CMD_STEST 0x3 /* Self test mode */ #define CMD_START 0x4 /* Reset xmit and receive ring ptrs */ #define CMD_BOOT 0x5 /* Boot DEUNA */ #define CMD_PDMD 0x8 /* Polling demand */ #define CMD_TMRO 0x9 /* Sanity timer on */ #define CMD_TMRF 0xa /* Sanity timer off */ #define CMD_RSTT 0xb /* Reset sanity timer */ #define CMD_STOP 0xf /* Suspend operation */ /* * PCSR 1 bit descriptions */ #define PCSR1_XPWR 0x8000 /* Transceiver power BAD */ #define PCSR1_ICAB 0x4000 /* Interconnect cabling BAD */ #define PCSR1_STCODE 0x3f00 /* Self test error code */ #define PCSR1_PCTO 0x0080 /* Port command timed out */ #define PCSR1_ILLINT 0x0040 /* Illegal interrupt */ #define PCSR1_TIMEOUT 0x0020 /* Timeout */ #define PCSR1_POWER 0x0010 /* Power fail */ #define PCSR1_RMTC 0x0008 /* Remote console reserved */ #define PCSR1_STMASK 0x0007 /* State */ /* bit 0-3 are for STATE */ #define STAT_RESET 0x0 #define STAT_PRIMLD 0x1 /* Primary load */ #define STAT_READY 0x2 #define STAT_RUN 0x3 #define STAT_UHALT 0x5 /* UNIBUS halted */ #define STAT_NIHALT 0x6 /* NI halted */ #define STAT_NIUHALT 0x7 /* NI and UNIBUS Halted */ #define PCSR1_BITS "\20\20XPWR\17ICAB\10PCTO\7ILLINT\6TIMEOUT\5POWER\4RMTC" /* * Port Control Block Base */ struct de_pcbb { short pcbb0; /* function */ short pcbb2; /* command specific */ short pcbb4; short pcbb6; }; /* PCBB function codes */ #define FC_NOOP 0x00 /* NO-OP */ #define FC_LSUADDR 0x01 /* Load and start microaddress */ #define FC_RDDEFAULT 0x02 /* Read default physical address */ #define FC_RDPHYAD 0x04 /* Read physical address */ #define FC_WTPHYAD 0x05 /* Write physical address */ #define FC_RDMULTI 0x06 /* Read multicast address list */ #define FC_WTMULTI 0x07 /* Read multicast address list */ #define FC_RDRING 0x08 /* Read ring format */ #define FC_WTRING 0x09 /* Write ring format */ #define FC_RDCNTS 0x0a /* Read counters */ #define FC_RCCNTS 0x0b /* Read and clear counters */ #define FC_RDMODE 0x0c /* Read mode */ #define FC_WTMODE 0x0d /* Write mode */ #define FC_RDSTATUS 0x0e /* Read port status */ #define FC_RCSTATUS 0x0f /* Read and clear port status */ #define FC_DUMPMEM 0x10 /* Dump internal memory */ #define FC_LOADMEM 0x11 /* Load internal memory */ #define FC_RDSYSID 0x12 /* Read system ID parameters */ #define FC_WTSYSID 0x13 /* Write system ID parameters */ #define FC_RDSERAD 0x14 /* Read load server address */ #define FC_WTSERAD 0x15 /* Write load server address */ /* * Unibus Data Block Base (UDBB) for ring buffers */ struct de_udbbuf { short b_tdrbl; /* Transmit desc ring base low 16 bits */ char b_tdrbh; /* Transmit desc ring base high 2 bits */ char b_telen; /* Length of each transmit entry */ short b_trlen; /* Number of entries in the XMIT desc ring */ short b_rdrbl; /* Receive desc ring base low 16 bits */ char b_rdrbh; /* Receive desc ring base high 2 bits */ char b_relen; /* Length of each receive entry */ short b_rrlen; /* Number of entries in the RECV desc ring */ }; /* * Transmit/Receive Ring Entry */ struct de_ring { short r_slen; /* Segment length */ short r_segbl; /* Segment address (low 16 bits) */ char r_segbh; /* Segment address (hi 2 bits) */ u_char r_flags; /* Status flags */ u_short r_tdrerr; /* Errors */ #define r_lenerr r_tdrerr short r_rid; /* Request ID */ }; #define XFLG_OWN 0x80 /* If 0 then owned by driver */ #define XFLG_ERRS 0x40 /* Error summary */ #define XFLG_MTCH 0x20 /* Address match on xmit request */ #define XFLG_MORE 0x10 /* More than one entry required */ #define XFLG_ONE 0x08 /* One collision encountered */ #define XFLG_DEF 0x04 /* Transmit deferred */ #define XFLG_STP 0x02 /* Start of packet */ #define XFLG_ENP 0x01 /* End of packet */ #define XFLG_BITS "\10\10OWN\7ERRS\6MTCH\5MORE\4ONE\3DEF\2STP\1ENP" #define XERR_BUFL 0x8000 /* Buffer length error */ #define XERR_UBTO 0x4000 /* UNIBUS tiemout #define XERR_LCOL 0x1000 /* Late collision */ #define XERR_LCAR 0x0800 /* Loss of carrier */ #define XERR_RTRY 0x0400 /* Failed after 16 retries */ #define XERR_TDR 0x03ff /* TDR value */ #define XERR_BITS "\20\20BUFL\17UBTO\15LCOL\14LCAR\13RTRY" #define RFLG_OWN 0x80 /* If 0 then owned by driver */ #define RFLG_ERRS 0x40 /* Error summary */ #define RFLG_FRAM 0x20 /* Framing error */ #define RFLG_OFLO 0x10 /* Message overflow */ #define RFLG_CRC 0x08 /* CRC error */ #define RFLG_STP 0x02 /* Start of packet */ #define RFLG_ENP 0x01 /* End of packet */ #define RFLG_BITS "\10\10OWN\7ERRS\6FRAM\5OFLO\4CRC\2STP\1ENP" #define RERR_BUFL 0x8000 /* Buffer length error */ #define RERR_UBTO 0x4000 /* UNIBUS tiemout */ #define RERR_NCHN 0x2000 /* No data chaining */ #define RERR_MLEN 0x0fff /* Message length */ #define RERR_BITS "\20\20BUFL\17UBTO\16NCHN" /* mode description bits */ #define MOD_HDX 0x0001 /* Half duplex mode */ #define MOD_LOOP 0x0004 /* Enable internal loopback */ #define MOD_DTCR 0x0008 /* Disables CRC generation */ #define MOD_DMNT 0x0200 /* Disable maintenance features */ #define MOD_ECT 0x0400 /* Enable collision test */ #define MOD_TPAD 0x1000 /* Transmit message pad enable */ #define MOD_DRDC 0x2000 /* Disable data chaining */ #define MOD_ENAL 0x4000 /* Enable all multicast */ #define MOD_PROM 0x8000 /* Enable promiscuous mode */ struct de_buf { struct ether_header db_head; /* header */ char db_data[ETHERMTU]; /* packet data */ int db_crc; /* CRC - on receive only */ }; /* * Collision on ethernet interface. Do exponential * backoff, and retransmit. If have backed off all * the way print warning diagnostic, and drop packet. */ encollide(unit) int unit; { struct en_softc *es = &en_softc[unit]; es->es_if.if_collisions++; if (es->es_oactive == 0) return; endocoll(unit); } endocoll(unit) int unit; { rsys/vaxif/if_ix.h 444 0 12 4571 3671247743 7254 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_ix.h 7.1 (Berkeley) 6/5/86 */ union ix_stats { struct { /* General statistics below */ u_char macg_physaddr[6]; u_short macg_pad; u_long dlag_rcvmac; /* packets received by DLA from MAC */ u_long dlag_rcvpass; /* packets passed to users by DLA */ u_long dlag_txreq; /* packets sent by users to DLA */ u_long dlag_txsnt; /* packets sent by DLA to MAC */ u_short dlag_chaopn; /* channels open */ u_short dlag_maxopn; /* max channels opened concurrently */ u_long macg_frmtos; /* packets discarded by MAC */ u_long macg_frmpas; /* packets sent to DLA by MAC */ u_long macg_x2x; /* packets put on wire by MAC */ u_long macg_x2r; /* packets looped by MAC */ u_long macg_xrty; /* transmitter retries */ u_short macg_noap; /* open MAC paths */ u_short macg_nprom; /* open promiscuous paths */ u_short macg_conopn; /* max concurrent MAC paths */ u_short sysg_crce; /* CRC errors */ u_short sysg_alne; /* alignment errors */ u_short sysg_rsce; /* resource errors */ u_short sysg_ovre; /* overrun errors */ } ixg; struct { /* Channel statistics below */ u_long dabc_rcvacc; /* packets received */ u_long dabc_rcvtoss; /* packets discarded, queue full */ u_long dabc_rcvpass; /* packets passed to user */ u_long dabc_txreq; /* packets sent by user */ u_long dabc_txsent; /* packets sent to MAC */ u_long macc_rcvcnt; /* packets received by MAC */ u_long macc_txtcnt; /* packets sent by MAC to wire */ u_long macc_lowmem; /* packets discarded, no mem */ } ixc; }; #define IXC_MAP(a) (((a) << 6) | 0100077) #define IXC_OPEN IXC_MAP(1) /* Open Channel */ #define IXC_CLOSE IXC_MAP(2) /* Close Channel */ #define IXC_MCAST IXC_MAP(3) /* Set Multicast Addresses */ #define IXC_RECV IXC_MAP(4) /* Receive Frame */ #define IXC_RECVF IXC_MAP(5) /* Receive Fragment */ #define IXC_XMIT IXC_MAP(6) /* Send Frame */ #define IXC_GSTAT IXC_MAP(7) /* Get General Statistics */ #define IXC_CSTAT IXC_MAP(8) /* Get Channel Statistics */ #define IXC_GSCLR IXC_MAP(9) /* Clear General Statistics */ #define IXC_CSCLR IXC_MAP(10) /* Clear Channel Statistics */ #define IXC_RESET IXC_MAP(11) /* Reset DLA module */ #define IXC_LDPA IXC_MAP(12) /* Load Physical Address */ lted */ #define STAT_NIUHALT 0x7 /* NI and UNIBUS Halted */ #define PCSR1_BITS "\20\20XPWR\17ICAB\10PCTO\7ILLINT\6TIMEOUT\5POWER\4RMTsys/vaxif/if_ecreg.h 444 0 12 4142 3671247516 7711 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_ecreg.h 7.1 (Berkeley) 6/5/86 */ /* * 3Com Ethernet controller registers. */ struct ecdevice { short ec_rcr; /* Receive Control Register */ short ec_xcr; /* Transmit Control Register */ }; /* * Control and status bits -- rcr */ #define EC_SPIE 0x8000 /* set parity interrupt enable */ #define EC_ASTEP 0x4000 /* increment address counter */ #define EC_AROM 0x2000 /* 1: Use address ROM, 0: use RAM */ #define EC_PE 0x2000 /* Parity error */ #define EC_AWCLK 0x1000 /* address write clock bit */ #define EC_PIE 0x1000 /* Parity interrupt enable (read) */ #define EC_ADATA 0x0f00 /* address/filtering */ #define EC_RDONE 0x0080 /* receive done */ #define EC_MDISAB 0x0080 /* memory disable */ #define EC_RINTEN 0x0040 /* receive interrupt enable */ #define EC_RCLR 0x0020 /* clear RDONE bit */ #define EC_RWBN 0x0010 /* submit buffer for receive */ #define EC_RBN 0x000f /* buffer number */ #define EC_RBITS "\10\16PE\15PIE\10RDONE\7RINTEN" /* * Control and status bits -- xcr */ #define EC_JAM 0x8000 /* collision dectected */ #define EC_JINTEN 0x4000 /* collision interrupt enable */ #define EC_JCLR 0x2000 /* clear collision detect */ #define EC_UECLR 0x0100 /* reset controller */ #define EC_XDONE 0x0080 /* transmit done */ #define EC_XINTEN 0x0040 /* transmit interrupt enable */ #define EC_XCLR 0x0020 /* clear XDONE bit */ #define EC_XWBN 0x0010 /* submit buffer for transmit */ #define EC_XBN 0x000f /* buffer number */ #define EC_XBITS "\10\20JAM\17JINTEN\10XDONE\7XINTEN" /* * Useful combinations */ #define EC_READ (0x600|EC_RINTEN|EC_RWBN) #define EC_WRITE (EC_JINTEN|EC_XINTEN|EC_XWBN) #define EC_CLEAR (EC_JINTEN|EC_XINTEN|EC_JCLR) /* * Buffer number definitions */ #define ECTBF 0 /* Buffer for transmit */ #define ECRLBF 1 /* First buffer for receive */ #define ECRHBF 15 /* Last buffer for receive */ #define ECRDOFF 528 /* Packet offset in read buffer */ AT IXC_MAP(8) /* Get Channel Statistics */ #define IXC_GSCLR IXC_MAP(9) /* Clear General Statistics */ #define IXC_CSCLR IXC_MAP(10) /* Clear Channel Statistics */ #define IXC_RESET IXC_MAP(11) /* Reset DLA module */ #define IXC_LDPA IXC_MAP(12) /* Load Physical Address */ lted */ #define STAT_NIUHALT 0x7 /* NI and UNIBUS Halted */ #define PCSR1_BITS "\20\20XPWR\17ICAB\10PCTO\7ILLINT\6TIMEOUT\5POWER\4RMTsys/vaxif/if_exreg.h 444 0 12 23661 3671247600 7757 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_exreg.h 7.1 (Berkeley) 6/5/86 */ struct exdevice { char xd_porta; /* write on porta resets EXOS */ char xd_pad_a; char xd_portb; /* write on portb interrupts EXOS */ /* read on portb returns status bits */ char xd_pad_b; }; /* EXOS I/O PORT A write definitions */ #define EX_RESET 0 /* value doesn't really matter... */ /* EXOS I/O PORT B write definitions */ #define EX_NTRUPT 0 /* EXOS I/O PORT B read definitions */ #define EX_TESTOK 1 /* set when self-diagnostics passed */ #define EX_UNREADY (1<<3) /* set until EXOS ready to read from B */ /* message buffer status field definitions */ #define MH_OWNER 1 /* mask for status bit for owner */ #define MH_HOST 0 /* if 0, the host owns the buffer */ #define MH_EXOS 1 /* if 1, the EXOS owns the buffer */ /* EXOS Link Level request codes */ #define LLTRANSMIT 0xC /* send a packet */ #define LLRTRANSMIT 0xE /* send a packet, and self-receive */ #define LLRECEIVE 0xD /* receive a packet */ #define LLNET_MODE 0x8 /* read/write mode control objects */ #define LLNET_ADDRS 0x9 /* read/write receive address slots */ #define LLNET_RECV 0xA /* read/alter receive slot enable bit */ #define LLNET_STSTCS 0xB /* read/reset network statistics objects */ /* Link Level return codes common to all requests */ #define LL_OK 0 /* successful completion */ #define LLX_MODE 0xA1 /* EXOS not in link level mode (impossible) */ /* LLTRANSMIT unique return codes */ #define LLXM_1RTRY 0x1 /* successful xmission, 1 retry */ #define LLXM_RTRYS 0x2 /* successful xmission, more than 1 retry */ #define LLXM_NSQE 0x8 /* successful xmission, no SQE TEST signal */ #define LLXM_CLSN 0x10 /* xmission failed, excess retries */ #define LLXM_NCS 0x20 /* xmission failed, no carrier sense */ #define LLXM_LNGTH 0x40 /* xmission failed, bad packet length */ #define XMIT_BITS "\7\7LENGTH\6CARRIER\5XCLSNS\4SQETST" #define LLXM_ERROR (LLXM_NSQE|LLXM_CLSN|LLXM_NCS|LLXM_LNGTH) /* LLRECEIVE unique return codes */ #define LLRC_TRUNC 0x4 /* pkt received, but truncated to fit buffer */ #define LLRC_ALIGN 0x10 /* pkt received, but with alignment error */ #define LLRC_CRC 0x20 /* pkt received, but with CRC error */ #define LLRC_BUFLEN 0x40 /* no pkt received, buffer less than 64 bytes */ /* this should never happen here */ #define RECV_BITS "\7\7BUFLEN\6CRC\5ALIGN\3TRUNC" /* LLNET_ADDRS unique return codes */ #define LLNA_BADSLOT 0xD1 /* slot doesn't exist or can't be accessed */ #define LLNA_BADADDR 0xD3 /* invalid address for designated slot */ /* LLNET_RECV unique return codes */ #define LLNR_BADSLOT 0xD1 /* slot doesn't exist or can't be accessed */ #define LLNR_BADADDR 0xD2 /* designated slot was empty */ /* address slot object indices */ #define NULLSLOT 0 /* the null slot */ #define MINMCSLOT 1 /* minimum multicast slot index */ #define MAXMCSLOT 8 /* default maximum multicast slot index */ #define PHYSSLOT 253 /* physical slot index */ #define UNVRSSLOT 254 /* universal slot index */ #define BROADSLOT 255 /* broadcast slot index */ /* request mask bit definitions */ #define WRITE_OBJ 1 /* write the object */ #define READ_OBJ 2 /* read the object */ #define ENABLE_RCV 4 /* enable reception on designated slot */ /* NET_MODE options mask bit definitions */ #define OPT_ALIGN 0x10 /* receive packets with alignment errors */ #define OPT_CRC 0x20 /* receive packets with CRC errors */ #define OPT_DSABLE 0x80 /* disconnect controller hardware */ /* NET_MODE mode field value definitions */ #define MODE_OFF 0 /* stop transmission and reception */ #define MODE_PERF 1 /* perfect multicast address filtering */ #define MODE_HW 2 /* hardware-only multicast address filtering */ #define MODE_PROM 3 /* promiscuous reception */ #define NFRAGMENTS 1 /* number fragments that the EXOS will scatter/gather */ #define EXMAXRBUF 1520 /* per EXOS 101 manual 5.3.7 (maybe 1518 would do) */ /* * N.B. Structures below are carefully constructed so that * they correspond to the message formats that NX firmware * defines. None of them should contain any compiler-instigated * padding. Be especially careful about VAX C longword alignment! */ struct stat_array { u_long sa_fsent; /* frames sent without errors */ u_long sa_xsclsn; /* frames aborted excess collisions */ u_long sa_nsqe; /* frames subject to heartbeat failure */ u_long sa_undef; /* undefined (TDR on EXOS 101) */ u_long sa_frcvd; /* frames received no errors */ u_long sa_align; /* frames received alignment error */ u_long sa_crc; /* frames received crc error */ u_long sa_flost; /* frames lost */ }; struct buf_blk { /* packet/buffer block descriptor */ u_short bb_len; /* length of block, in bytes */ u_short bb_addr[2]; /* address of block */ /* * Array above is really a single u_long field. * We kludge its definition to defeat word-alignment. * Access would look like: * longaddr = *(u_long *)bp->.mb_er.er_blks[0].bb_addr; */ }; struct net_mode { /* read/write mode control objects */ /*12*/ u_char nm_rqst; /* request code */ /*13*/ u_char nm_rply; /* reply code */ /*14*/ u_char nm_mask; /* bit-wise switches for read, write */ /*15*/ u_char nm_optn; /* acceptable packet reception errors */ /*16*/ u_char nm_mode; /* EXOS filtering mode */ /*17*/ }; struct net_addrs { /* read/write receive address slots */ /*12*/ u_char na_rqst; /* request code */ /*13*/ u_char na_rply; /* reply code */ /*14*/ u_char na_mask; /* bit-wise switches for read, write */ /*15*/ u_char na_slot; /* index of address slot */ /*16*/ u_char na_addrs[6]; /* address read and/or written */ /*22*/ }; struct net_recv { /* read/alter receive slot enable bit */ /*12*/ u_char nr_rqst; /* request code */ /*13*/ u_char nr_rply; /* reply code */ /*14*/ u_char nr_mask; /* bit-wise switches for read, write */ /*15*/ u_char nr_slot; /* index of address slot */ /*16*/ }; struct net_ststcs { /* read/reset network statistics objects */ /*12*/ u_char ns_rqst; /* request code */ /*13*/ u_char ns_rply; /* reply code */ /*14*/ u_char ns_mask; /* bit-wise switches for read, write */ /*15*/ u_char ns_rsrv; /* reserved for EXOS */ /*16*/ u_short ns_nobj; /* number of objects to work on */ /*18*/ u_short ns_xobj; /* index of first object to work on */ /*20*/ u_long ns_bufp; /* pointer to statistics buffer */ /*24*/ }; struct enet_xmit { /* send a packet on the Ethernet */ /*12*/ u_char et_rqst; /* request code */ /*13*/ u_char et_rply; /* reply code */ /*14*/ u_char et_slot; /* address slot matching dest address */ /*15*/ u_char et_nblock; /* number of blocks composing packet */ /*16*/ struct buf_blk et_blks[NFRAGMENTS]; /* array of block descriptors */ /*22-64*/ }; struct enet_recv { /* receive a packet on the Ethernet */ /*12*/ u_char er_rqst; /* request code */ /*13*/ u_char er_rply; /* reply code */ /*14*/ u_char er_slot; /* address slot matching dest address */ /*15*/ u_char er_nblock; /* number of blocks composing buffer */ /*16*/ struct buf_blk er_blks[NFRAGMENTS]; /* array of block descriptors */ /*22-64*/ }; /* we send requests and receive replys with the EXOS using this structure */ struct ex_msg { /*00*/ u_short mb_link; /* address of next message buffer */ /*02*/ u_char mb_rsrv; /* reserved for use by EXOS */ /*03*/ u_char mb_status; /* used bit-wise for message protocol */ /*04*/ u_short mb_length; /* length, in bytes, of the rest */ /*06*/ short mb_1rsrv; /* reserved for used by EXOS */ /*08*/ long mb_mid; /* available to user */ /*12*/ union mb_all { struct net_mode mb_net_mode; struct net_addrs mb_net_addrs; struct net_recv mb_net_recv; struct net_ststcs mb_net_ststcs; struct enet_xmit mb_enet_xmit; struct enet_recv mb_enet_recv; } mb_all; /* following field is used only by host, not read by board */ struct ex_msg *mb_next; /* host's pointer to next message */ }; #define mb_nm mb_all.mb_net_mode #define mb_na mb_all.mb_net_addrs #define mb_nr mb_all.mb_net_recv #define mb_ns mb_all.mb_net_ststcs #define mb_et mb_all.mb_enet_xmit #define mb_er mb_all.mb_enet_recv #define mb_rqst mb_nm.nm_rqst #define mb_rply mb_nm.nm_rply #define MBDATALEN (sizeof(union mb_all)+6) struct confmsg { /*00*/ u_short cm_1rsrv; /* reserved, must be 1 */ /*02*/ char cm_vc[4]; /* returns ASCII version code */ /*06*/ u_char cm_cc; /* returns config completion code */ /*07*/ u_char cm_opmode; /* specifies operation mode */ /*08*/ u_short cm_dfo; /* specifies host data format option */ /*10*/ u_char cm_dcn1; /* reserved, must be 1 */ /*11*/ u_char cm_2rsrv[2]; /* reserved, must be 0 */ /*13*/ u_char cm_ham; /* specifies host address mode */ /*14*/ u_char cm_3rsrv; /* reserved, must be 0 */ /*15*/ u_char cm_mapsiz; /* reserved, must be 0 */ /*16*/ u_char cm_byteptrn[4]; /* host data format option test pattern */ /*20*/ u_short cm_wordptrn[2]; /*24*/ u_long cm_lwordptrn; /*28*/ u_char cm_rsrvd[20]; /*48*/ u_long cm_mba; /* use 0xFFFFFFFF in link level mode */ /*52*/ u_char cm_nproc; /* use 0xFF in link level mode */ /*53*/ u_char cm_nmbox; /* use 0xFF in link level mode */ /*54*/ u_char cm_nmcast; /* use 0xFF in link level mode */ /*55*/ u_char cm_nhost; /* use 1 in link level mode */ /* the next five parameters define the request message queue */ /*56*/ u_long cm_h2xba; /* base address of message queue */ /*60*/ u_short cm_h2xhdr; /* address offset of msg Q header */ /*62*/ u_char cm_h2xtyp; /* interrupt type */ /*63*/ u_char cm_h2xval; /* interrupt value (not used) */ /*64*/ u_short cm_h2xaddr; /* interrupt vector */ /*66*/ u_short cm_h2xpad; /* pad out unused portion of vector */ /* the next five parameters define the reply message queue */ /*68*/ u_long cm_x2hba; /* base address of message queue */ /*72*/ u_short cm_x2hhdr; /* address offset of msg Q header */ /*74*/ u_char cm_x2htyp; /* interrupt type */ /*75*/ u_char cm_x2hval; /* interrupt value (not used) */ /*76*/ u_short cm_x2haddr; /* interrupt vector */ /*78*/ u_short cm_x2hpad; /* pad out unused portion of vector */ /*80*/ }; ors */ #define OPT_CRC 0x20 /* receive packets with CRC errors */ #define OPT_sys/vaxif/if_ddnreg.h 444 0 12 10413 3671247445 10106 /* @(#)if_ddnreg.h 7.1 (Berkeley) 6/5/86 */ /************************************************************************\ ________________________________________________________ / \ | AAA CCCCCCCCCCCCCC CCCCCCCCCCCCCC | | AAAAA CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC | | AAAAAAA CCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCC | | AAAA AAAA CCCC CCCC | | AAAA AAAA CCCC CCCC | | AAAA AAAA CCCC CCCC | | AAAA AAAA CCCC CCCC | | AAAA AAAAAAAAAAA CCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCC | | AAAA AAAAAAAAAAA CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC | | AAAA AAAAAAAAA CCCCCCCCCCCCCC CCCCCCCCCCCCCC | \________________________________________________________/ Copyright (c) 1985 by Advanced Computer Communications 720 Santa Barbara Street, Santa Barbara, California 93101 (805) 963-9431 This software may be duplicated and used on systems which are licensed to run U.C. Berkeley versions of the UNIX operating system. Any duplication of any part of this software must include a copy of ACC's copyright notice. File: if_ddnreg.h Author: Art Berggreen Project: 4.2 DDN X.25 network driver Function: This file contains definitions of the hardware interface of the ACP625 (IF-11/X25). Components: Revision History: 16-May-1985: V1.0 - First release. Art Berggreen. \************************************************************************/ /* if_ddnvar.h V1.0 5/16/85 */ /* * ACC IF-11/DDN-X25 interface */ struct ddnregs { /* device registers */ u_short csr; /* control and status register */ u_char iochn; /* logical channel */ u_char ioadx; /* address extension (A16,A17) */ u_short ioadl; /* buffer address (A0-A15) */ u_short iocnt; /* byte count */ u_char iofcn; /* UMC funciton code */ u_char iosbf; /* UMC subfunction code */ u_char ioini; /* comm regs valid flag */ u_char staack; /* interrupt acknowledge flag */ u_char ionmi; /* NMI routine active flag */ u_char xfrgnt; /* UMR transfer grant flag */ u_char stachn; /* interrupt channel number */ u_char statyp; /* interrupt type code */ u_char stacc; /* completion function code */ u_char stacs; /* completion subfunction code */ u_short stacnt; /* completion byte count */ }; #define iovect iochn /* defines for CSR */ #define DDN_UER 0100000 /* UMC error condition */ #define DDN_NXM 0040000 /* non-existent memory error */ #define DDN_PER 0020000 /* UNIBUS parity error */ #define DDN_ZRUN 0010000 /* Z80 running */ #define DDN_ZGO 0004000 /* Z80 not in wait state */ #define DDN_MBLK 0000200 /* memory swap state (0=main, 1=srv) */ #define DDN_SRV 0000100 /* select UMC service memory */ #define DDN_MAIN 0000040 /* select UMC main memory */ #define DDN_DMA 0000020 /* DMA enable */ #define DDN_WRT 0000010 /* DMA write enable */ #define DDN_IEN 0000004 /* interrupt enable */ #define DDN_RST 0000002 /* reset */ #define DDN_NMI 0000001 /* cause NMI */ #define DDN_BITS \ "\10\20UER\17NXM\16PER\15ZRUN\14ZGO\10MBLK\7SRV\6MAIN\5DMA\4WRT\3IEN\2RST\1NMI" /* start i/o function code definitions */ #define DDNWRT 0 /* write to if-11 */ #define DDNRDB 1 /* read from if-11 */ #define DDNSTR 2 /* stream flag */ #define DDNEOS (4|DDNSTR) /* end of stream flag */ #define DDNABT 8 /* abort flag */ #define DDNUMR 16 /* UMR protocol flag */ /* interrupt type definitions */ #define DDNSACK 0 /* start i/o ack */ #define DDNDONE 1 /* i/o completion */ #define DDNXREQ 2 /* UMR protocol transfer request */ /* i/o completion codes */ #define DDNIOCOK 0001 /* successful completion */ #define DDNIOCOKP 0002 /* successful completion, more data pending */ #define DDNIOCABT 0361 /* i/o aborted */ #define DDNIOCERR 0321 /* program error */ #define DDNIOCOVR 0363 /* overrun error */ #define DDNIOCUBE 0374 /* non-existant memory or unibus error */ /* UMR protocol transfer grant code definitions */ #define DDNXEVN 1 /* start with even address */ #define DDNXODD 2 /* start with odd address */ #define DDNNUMR 4 /* non-UMR transfer */ #define DDNXABT 8 /* abort transfer */ t; /* frames sent without errors */ u_long sa_xsclsn; /* frames aborted excess collisions */ u_long sa_nsqe; /* frames subject to heartbeat failure */ u_long sa_undef; /* undefined (TDR on EXOS 101) */ u_long sa_frcvd; /* frames received no sys/vaxif/if_ex.c 444 0 12 60514 4060654076 7254 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_ex.c 7.2 (Berkeley) 10/13/86 */ #include "ex.h" #if NEX > 0 /* * Excelan EXOS 204 Interface * * George Powers * Excelan Inc. */ #include "../machine/pte.h" #include "param.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "protosw.h" #include "socket.h" #include "vmmac.h" #include "ioctl.h" #include "syslog.h" #include "errno.h" #include "../net/if.h" #include "../net/netisr.h" #include "../net/route.h" #ifdef INET #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netinet/in_var.h" #include "../netinet/ip.h" #include "../netinet/if_ether.h" #endif #ifdef NS #include "../netns/ns.h" #include "../netns/ns_if.h" #endif #include "../vax/cpu.h" #include "../vax/mtpr.h" #include "if_exreg.h" #include "if_uba.h" #include "../vaxuba/ubareg.h" #include "../vaxuba/ubavar.h" #define DEBUG /* check for "impossible" events */ #define NH2X 4 /* a sufficient number is critical */ #define NX2H 4 /* this is pretty arbitrary */ #define EXWATCHINTVL 10 /* call exwatch() every 10 seconds */ int exprobe(), exattach(), excdint(); struct uba_device *exinfo[NEX]; u_short exstd[] = { 0 }; struct uba_driver exdriver = { exprobe, 0, exattach, 0, exstd, "ex", exinfo }; int exinit(),exoutput(),exioctl(),exreset(),exwatch(); struct ex_msg *exgetcbuf(); /* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * xs_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... * We also have, for each interface, a UBA interface structure, which * contains information about the UNIBUS resources held by the interface: * map registers, buffered data paths, etc. Information is cached in this * structure for use by the if_uba.c routines in running the interface * efficiently. */ struct ex_softc { struct arpcom xs_ac; /* Ethernet common part */ #define xs_if xs_ac.ac_if /* network-visible interface */ #define xs_addr xs_ac.ac_enaddr /* hardware Ethernet address */ #ifdef DEBUG int xs_wait; #endif struct ifuba xs_ifuba; /* UNIBUS resources */ int xs_flags; /* private flags */ #define EX_XPENDING 1 /* xmit rqst pending on EXOS */ #define EX_STATPENDING (1<<1) /* stats rqst pending on EXOS */ #define EX_RUNNING (1<<2) /* board is running */ #define EX_SETADDR (1<<3) /* physaddr has been changed */ struct ex_msg *xs_h2xnext; /* host pointer to request queue */ struct ex_msg *xs_x2hnext; /* host pointer to reply queue */ int xs_ubaddr; /* map info for structs below */ #define UNIADDR(x) ((u_long)(x)&0x3FFFF) #define P_UNIADDR(x) ((u_long)(x)&0x3FFF0) /* the following structures are always mapped in */ u_short xs_h2xhdr; /* EXOS's request queue header */ u_short xs_x2hhdr; /* EXOS's reply queue header */ struct ex_msg xs_h2xent[NH2X]; /* request msg buffers */ struct ex_msg xs_x2hent[NX2H]; /* reply msg buffers */ struct confmsg xs_cm; /* configuration message */ struct stat_array xs_xsa; /* EXOS writes stats here */ /* end mapped area */ #define INCORE_BASE(p) ((caddr_t)((u_long)(&(p)->xs_h2xhdr) & 0xFFFFFFF0)) #define RVAL_OFF(unit, n) \ ((caddr_t)(&(ex_softc[unit].n)) - INCORE_BASE(&ex_softc[unit])) #define LVAL_OFF(unit, n) \ ((caddr_t)(ex_softc[unit].n) - INCORE_BASE(&ex_softc[unit])) #define H2XHDR_OFFSET(unit) RVAL_OFF(unit, xs_h2xhdr) #define X2HHDR_OFFSET(unit) RVAL_OFF(unit, xs_x2hhdr) #define H2XENT_OFFSET(unit) LVAL_OFF(unit, xs_h2xent) #define X2HENT_OFFSET(unit) LVAL_OFF(unit, xs_x2hent) #define CM_OFFSET(unit) RVAL_OFF(unit, xs_cm) #define SA_OFFSET(unit) RVAL_OFF(unit, xs_xsa) #define INCORE_SIZE(unit) RVAL_OFF(unit, xs_end) int xs_end; /* place holder */ } ex_softc[NEX]; /* * The following structure is a kludge to store a cvec value * between the time exprobe is called, and exconfig. */ struct ex_cvecs { struct exdevice *xc_csraddr; int xc_cvec; }ex_cvecs[NEX]; int ex_ncall = 0; /* counts calls to exprobe */ exprobe(reg) caddr_t reg; { register int br, cvec; /* r11, r10 value-result */ register struct exdevice *addr = (struct exdevice *)reg; register i; /* * We program the EXOS interrupt vector, like dmf device. */ br = 0x15; cvec = (uba_hd[numuba].uh_lastiv -= 4); ex_cvecs[ex_ncall].xc_csraddr = addr; ex_cvecs[ex_ncall].xc_cvec = cvec; /* * Reset EXOS and run self-test (guaranteed to * complete within 2 seconds). */ addr->xd_porta = EX_RESET; i = 2000; while (((addr->xd_portb & EX_TESTOK) == 0) && --i) DELAY(1000); if ((addr->xd_portb & EX_TESTOK) == 0) { printf("ex: self-test failed\n"); return 0; } #ifdef lint br = br; excdint(0); #endif ex_ncall++; return (sizeof(struct exdevice)); } /* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. Board is temporarily configured and issues * a NET_ADDRS command, only to get the Ethernet address. */ exattach(ui) struct uba_device *ui; { register struct ex_softc *xs = &ex_softc[ui->ui_unit]; register struct ifnet *ifp = &xs->xs_if; register struct exdevice *addr = (struct exdevice *)ui->ui_addr; register struct ex_msg *bp; int unit = ui->ui_unit; ifp->if_unit = ui->ui_unit; ifp->if_name = "ex"; ifp->if_mtu = ETHERMTU; /* * Temporarily map queues in order to configure EXOS */ xs->xs_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(xs), INCORE_SIZE(unit), 0); exconfig(ui, 0); /* without interrupts */ if (xs->xs_cm.cm_cc) goto badconf; bp = exgetcbuf(xs); bp->mb_rqst = LLNET_ADDRS; bp->mb_na.na_mask = READ_OBJ; bp->mb_na.na_slot = PHYSSLOT; bp->mb_status |= MH_EXOS; addr->xd_portb = EX_NTRUPT; bp = xs->xs_x2hnext; while ((bp->mb_status & MH_OWNER) == MH_EXOS) /* poll for reply */ ; printf("ex%d: HW %c.%c, NX %c.%c, hardware address %s\n", ui->ui_unit, xs->xs_cm.cm_vc[2], xs->xs_cm.cm_vc[3], xs->xs_cm.cm_vc[0], xs->xs_cm.cm_vc[1], ether_sprintf(bp->mb_na.na_addrs)); bcopy((caddr_t)bp->mb_na.na_addrs, (caddr_t)xs->xs_addr, sizeof (xs->xs_addr)); ifp->if_init = exinit; ifp->if_output = exoutput; ifp->if_ioctl = exioctl; ifp->if_reset = exreset; ifp->if_flags = IFF_BROADCAST; xs->xs_ifuba.ifu_flags = UBA_CANTWAIT; if_attach(ifp); badconf: ubarelse(ui->ui_ubanum, &xs->xs_ubaddr); } /* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */ exreset(unit, uban) int unit, uban; { register struct uba_device *ui; if (unit >= NEX || (ui = exinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" ex%d", unit); ex_softc[unit].xs_if.if_flags &= ~IFF_RUNNING; ex_softc[unit].xs_flags &= ~EX_RUNNING; exinit(unit); } /* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. * Called at boot time (with interrupts disabled?), * and at ifconfig time via exioctl, with interrupts disabled. */ exinit(unit) int unit; { register struct ex_softc *xs = &ex_softc[unit]; register struct uba_device *ui = exinfo[unit]; register struct exdevice *addr = (struct exdevice *)ui->ui_addr; register struct ifnet *ifp = &xs->xs_if; register struct ex_msg *bp; int s; /* not yet, if address still unknown */ if (ifp->if_addrlist == (struct ifaddr *)0) return; if (xs->xs_flags & EX_RUNNING) return; if ((ifp->if_flags & IFF_RUNNING) == 0) { if (if_ubainit(&xs->xs_ifuba, ui->ui_ubanum, sizeof (struct ether_header), (int)btoc(EXMAXRBUF-sizeof(struct ether_header))) == 0) { printf("ex%d: can't initialize\n", unit); xs->xs_if.if_flags &= ~IFF_UP; return; } xs->xs_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(xs), INCORE_SIZE(unit), 0); } exconfig(ui, 4); /* with vectored interrupts*/ /* * Put EXOS on the Ethernet, using NET_MODE command */ bp = exgetcbuf(xs); bp->mb_rqst = LLNET_MODE; bp->mb_nm.nm_mask = WRITE_OBJ; bp->mb_nm.nm_optn = 0; bp->mb_nm.nm_mode = MODE_PERF; bp->mb_status |= MH_EXOS; addr->xd_portb = EX_NTRUPT; bp = xs->xs_x2hnext; while ((bp->mb_status & MH_OWNER) == MH_EXOS) /* poll for reply */ ; bp->mb_length = MBDATALEN; bp->mb_status |= MH_EXOS; /* free up buffer */ addr->xd_portb = EX_NTRUPT; /* tell EXOS about it */ xs->xs_x2hnext = xs->xs_x2hnext->mb_next; ifp->if_watchdog = exwatch; ifp->if_timer = EXWATCHINTVL; s = splimp(); /* are interrupts always disabled here, anyway? */ exhangrcv(unit); /* hang receive request */ xs->xs_if.if_flags |= IFF_RUNNING; xs->xs_flags |= EX_RUNNING; if (xs->xs_flags & EX_SETADDR) ex_setaddr((u_char *)0, unit); exstart(unit); /* start transmits */ splx(s); } /* * Reset, test, and configure EXOS. This routine assumes * that message queues, etc. have already been mapped into * the UBA. It is called by exinit, and should also be * callable by exattach. */ exconfig(ui, itype) struct uba_device *ui; int itype; { register int unit = ui->ui_unit; register struct ex_softc *xs = &ex_softc[unit]; register struct exdevice *addr = (struct exdevice *) ui->ui_addr; register struct confmsg *cm = &xs->xs_cm; register struct ex_msg *bp; int i; u_long shiftreg; xs->xs_flags = 0; /* * Reset EXOS, wait for self-test to complete */ addr->xd_porta = EX_RESET; while ((addr->xd_portb & EX_TESTOK) == 0) ; /* * Set up configuration message. */ cm->cm_1rsrv = 1; cm->cm_cc = 0xFF; cm->cm_opmode = 0; /* link-level controller mode */ cm->cm_dfo = 0x0101; /* enable host data order conversion */ cm->cm_dcn1 = 1; cm->cm_2rsrv[0] = cm->cm_2rsrv[1] = 0; cm->cm_ham = 3; /* absolute address mode */ cm->cm_3rsrv = 0; cm->cm_mapsiz = 0; cm->cm_byteptrn[0] = 0x01; /* EXOS deduces data order of host */ cm->cm_byteptrn[1] = 0x03; /* by looking at this pattern */ cm->cm_byteptrn[2] = 0x07; cm->cm_byteptrn[3] = 0x0F; cm->cm_wordptrn[0] = 0x0103; cm->cm_wordptrn[1] = 0x070F; cm->cm_lwordptrn = 0x0103070F; for (i=0; i<20; i++) cm->cm_rsrvd[i] = 0; cm->cm_mba = 0xFFFFFFFF; cm->cm_nproc = 0xFF; cm->cm_nmbox = 0xFF; cm->cm_nmcast = 0xFF; cm->cm_nhost = 1; cm->cm_h2xba = P_UNIADDR(xs->xs_ubaddr); cm->cm_h2xhdr = H2XHDR_OFFSET(unit); cm->cm_h2xtyp = 0; /* should never wait for rqst buffer */ cm->cm_x2hba = cm->cm_h2xba; cm->cm_x2hhdr = X2HHDR_OFFSET(unit); cm->cm_x2htyp = itype; /* 0 for none, 4 for vectored */ for (i=0; (addr != ex_cvecs[i].xc_csraddr); i++) #ifdef DEBUG if (i >= NEX) panic("ex: matching csr address not found"); #endif ; cm->cm_x2haddr = ex_cvecs[i].xc_cvec; /* stashed here by exprobe */ /* * Set up message queues and headers. * First the request queue. */ for (bp = &xs->xs_h2xent[0]; bp < &xs->xs_h2xent[NH2X]; bp++) { bp->mb_link = (u_short)((char *)(bp+1)-INCORE_BASE(xs)); bp->mb_rsrv = 0; bp->mb_length = MBDATALEN; bp->mb_status = MH_HOST; bp->mb_next = bp+1; } xs->xs_h2xhdr = xs->xs_h2xent[NH2X-1].mb_link = (u_short)H2XENT_OFFSET(unit); xs->xs_h2xnext = xs->xs_h2xent[NH2X-1].mb_next = xs->xs_h2xent; /* Now the reply queue. */ for (bp = &xs->xs_x2hent[0]; bp < &xs->xs_x2hent[NX2H]; bp++) { bp->mb_link = (u_short)((char *)(bp+1)-INCORE_BASE(xs)); bp->mb_rsrv = 0; bp->mb_length = MBDATALEN; bp->mb_status = MH_EXOS; bp->mb_next = bp+1; } xs->xs_x2hhdr = xs->xs_x2hent[NX2H-1].mb_link = (u_short)X2HENT_OFFSET(unit); xs->xs_x2hnext = xs->xs_x2hent[NX2H-1].mb_next = xs->xs_x2hent; /* * Write config msg address to EXOS and wait for * configuration to complete (guaranteed response * within 2 seconds). */ shiftreg = (u_long)0x0000FFFF; for (i = 0; i < 8; i++) { if (i == 4) shiftreg = P_UNIADDR(xs->xs_ubaddr) + CM_OFFSET(unit); while (addr->xd_portb & EX_UNREADY) ; addr->xd_portb = (u_char)(shiftreg & 0xFF); shiftreg >>= 8; } for (i = 1000000; (cm->cm_cc == 0xFF) && i; --i); if (cm->cm_cc) printf("ex%d: configuration failed; cc = %x\n", unit, cm->cm_cc); } /* * Start or re-start output on interface. * Get another datagram to send off of the interface queue, * and map it to the interface before starting the output. * This routine is called by exinit(), exoutput(), and excdint(). * In all cases, interrupts by EXOS are disabled. */ exstart(unit) int unit; { struct uba_device *ui = exinfo[unit]; register struct ex_softc *xs = &ex_softc[unit]; register struct exdevice *addr = (struct exdevice *)ui->ui_addr; register struct ex_msg *bp; struct mbuf *m; int len; #ifdef DEBUG if (xs->xs_flags & EX_XPENDING) panic("exstart(): xmit still pending"); #endif IF_DEQUEUE(&xs->xs_if.if_snd, m); if (m == 0) return; len = if_wubaput(&xs->xs_ifuba, m); if (len - sizeof(struct ether_header) < ETHERMIN) len = ETHERMIN + sizeof(struct ether_header); /* * Place a transmit request. */ bp = exgetcbuf(xs); bp->mb_rqst = LLRTRANSMIT; bp->mb_et.et_nblock = 1; bp->mb_et.et_blks[0].bb_len = (u_short)len; *(u_long *)bp->mb_et.et_blks[0].bb_addr = UNIADDR(xs->xs_ifuba.ifu_w.ifrw_info); xs->xs_flags |= EX_XPENDING; bp->mb_status |= MH_EXOS; addr->xd_portb = EX_NTRUPT; } /* * Command done interrupt. */ excdint(unit) int unit; { register struct ex_softc *xs = &ex_softc[unit]; register struct ex_msg *bp = xs->xs_x2hnext; struct uba_device *ui = exinfo[unit]; struct exdevice *addr = (struct exdevice *)ui->ui_addr; while ((bp->mb_status & MH_OWNER) == MH_HOST) { switch (bp->mb_rqst) { case LLRECEIVE: exrecv(unit, bp); exhangrcv(unit); break; case LLRTRANSMIT: #ifdef DEBUG if ((xs->xs_flags & EX_XPENDING) == 0) panic("exxmit: no xmit pending"); #endif xs->xs_flags &= ~EX_XPENDING; xs->xs_if.if_opackets++; if (bp->mb_rply == LL_OK) { ; } else if (bp->mb_rply & LLXM_1RTRY) { xs->xs_if.if_collisions++; } else if (bp->mb_rply & LLXM_RTRYS) { xs->xs_if.if_collisions += 2; /* guess */ } else if (bp->mb_rply & LLXM_ERROR) { xs->xs_if.if_oerrors++; log(LOG_ERR, "ex%d: transmit error=%b\n", unit, bp->mb_rply, XMIT_BITS); } if (xs->xs_ifuba.ifu_xtofree) { m_freem(xs->xs_ifuba.ifu_xtofree); xs->xs_ifuba.ifu_xtofree = 0; } exstart(unit); break; case LLNET_STSTCS: xs->xs_if.if_ierrors = xs->xs_xsa.sa_crc; xs->xs_flags &= ~EX_STATPENDING; break; case LLNET_ADDRS: case LLNET_RECV: break; #ifdef DEBUG default: panic("ex%d: unknown reply"); #endif } /* end of switch */ bp->mb_length = MBDATALEN; bp->mb_status |= MH_EXOS; /* free up buffer */ addr->xd_portb = EX_NTRUPT; /* tell EXOS about it */ bp = xs->xs_x2hnext = xs->xs_x2hnext->mb_next; } } /* * Get a request buffer, fill in standard values, advance pointer. */ struct ex_msg * exgetcbuf(xs) struct ex_softc *xs; { register struct ex_msg *bp = xs->xs_h2xnext; #ifdef DEBUG if ((bp->mb_status & MH_OWNER) == MH_EXOS) panic("exgetcbuf(): EXOS owns message buffer"); #endif bp->mb_1rsrv = 0; bp->mb_length = MBDATALEN; xs->xs_h2xnext = xs->xs_h2xnext->mb_next; return bp; } /* * Process Ethernet receive completion: * If input error just drop packet. * Otherwise purge input buffered data path and examine * packet to determine type. If can't determine length * from type, then have to drop packet. Otherwise decapsulate * packet based on type and pass to type-specific higher-level * input routine. */ exrecv(unit, bp) int unit; register struct ex_msg *bp; { register struct ex_softc *xs = &ex_softc[unit]; register struct ether_header *eh; struct mbuf *m; register int len, off, resid; register struct ifqueue *inq; int s; xs->xs_if.if_ipackets++; len = bp->mb_er.er_blks[0].bb_len - sizeof(struct ether_header) - 4; if (bp->mb_rply != LL_OK) { xs->xs_if.if_ierrors++; log(LOG_ERR, "ex%d: receive error=%b\n", unit, bp->mb_rply, RECV_BITS); return; } eh = (struct ether_header *)(xs->xs_ifuba.ifu_r.ifrw_addr); /* * Deal with trailer protocol: if type is trailer * get true type from first 16-bit word past data. * Remember that type was trailer by setting off. */ eh->ether_type = ntohs((u_short)eh->ether_type); #define exdataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off)))) if (eh->ether_type >= ETHERTYPE_TRAIL && eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { off = (eh->ether_type - ETHERTYPE_TRAIL) * 512; if (off >= ETHERMTU) return; /* sanity */ eh->ether_type = ntohs(*exdataaddr(eh, off, u_short *)); resid = ntohs(*(exdataaddr(eh, off+2, u_short *))); if (off + resid > len) return; /* sanity */ len = off + resid; } else off = 0; if (len == 0) return; /* * Pull packet off interface. Off is nonzero if packet * has trailing header; if_rubaget will then force this header * information to be at the front, but we still have to drop * the type and length which are at the front of any trailer data. */ m = if_rubaget(&xs->xs_ifuba, len, off, &xs->xs_if); if (m == 0) return; if (off) { struct ifnet *ifp; ifp = *(mtod(m, struct ifnet **)); m->m_off += 2 * sizeof (u_short); m->m_len -= 2 * sizeof (u_short); *(mtod(m, struct ifnet **)) = ifp; } switch (eh->ether_type) { #ifdef INET case ETHERTYPE_IP: schednetisr(NETISR_IP); /* is this necessary */ inq = &ipintrq; break; case ETHERTYPE_ARP: arpinput(&xs->xs_ac, m); return; #endif #ifdef NS case ETHERTYPE_NS: schednetisr(NETISR_NS); inq = &nsintrq; break; #endif default: m_freem(m); return; } s = splimp(); if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); } else IF_ENQUEUE(inq, m); splx(s); } /* * Send receive request to EXOS. * This routine is called by exinit and excdint, * with interrupts disabled in both cases. */ exhangrcv(unit) int unit; { register struct ex_softc *xs = &ex_softc[unit]; register struct ex_msg *bp = exgetcbuf(xs); struct exdevice *addr = (struct exdevice *)exinfo[unit]->ui_addr; bp->mb_rqst = LLRECEIVE; bp->mb_er.er_nblock = 1; bp->mb_er.er_blks[0].bb_len = EXMAXRBUF; *(u_long *)bp->mb_er.er_blks[0].bb_addr = UNIADDR(xs->xs_ifuba.ifu_r.ifrw_info); bp->mb_status |= MH_EXOS; addr->xd_portb = EX_NTRUPT; } /* * Ethernet output routine. * Encapsulate a packet of type family for the local net. * Use trailer local net encapsulation if enough data in first * packet leaves a multiple of 512 bytes of data in remainder. */ exoutput(ifp, m0, dst) register struct ifnet *ifp; register struct mbuf *m0; struct sockaddr *dst; { int type, s, error; u_char edst[6]; struct in_addr idst; register struct ex_softc *xs = &ex_softc[ifp->if_unit]; register struct mbuf *m = m0; register struct ether_header *eh; register int off; int usetrailers; if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { error = ENETDOWN; goto bad; } switch (dst->sa_family) { #ifdef INET case AF_INET: idst = ((struct sockaddr_in *)dst)->sin_addr; if (!arpresolve(&xs->xs_ac, m, &idst, edst, &usetrailers)) return (0); /* if not yet resolved */ off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; if (usetrailers && off > 0 && (off & 0x1ff) == 0 && m->m_off >= MMINOFF + 2 * sizeof (u_short)) { type = ETHERTYPE_TRAIL + (off>>9); m->m_off -= 2 * sizeof (u_short); m->m_len += 2 * sizeof (u_short); *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); goto gottrailertype; } type = ETHERTYPE_IP; off = 0; goto gottype; #endif #ifdef NS case AF_NS: type = ETHERTYPE_NS; bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), (caddr_t)edst, sizeof (edst)); off = 0; goto gottype; #endif case AF_UNSPEC: eh = (struct ether_header *)dst->sa_data; bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); type = eh->ether_type; goto gottype; default: printf("ex%d: can't handle af%d\n", ifp->if_unit, dst->sa_family); error = EAFNOSUPPORT; goto bad; } gottrailertype: /* * Packet to be sent as trailer: move first packet * (control information) to end of chain. */ while (m->m_next) m = m->m_next; m->m_next = m0; m = m0->m_next; m0->m_next = 0; m0 = m; gottype: /* * Add local net header. If no space in first mbuf, * allocate another. */ if (m->m_off > MMAXOFF || MMINOFF + sizeof (struct ether_header) > m->m_off) { m = m_get(M_DONTWAIT, MT_HEADER); if (m == 0) { error = ENOBUFS; goto bad; } m->m_next = m0; m->m_off = MMINOFF; m->m_len = sizeof (struct ether_header); } else { m->m_off -= sizeof (struct ether_header); m->m_len += sizeof (struct ether_header); } eh = mtod(m, struct ether_header *); eh->ether_type = htons((u_short)type); bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); bcopy((caddr_t)xs->xs_addr, (caddr_t)eh->ether_shost, 6); /* * Queue message on interface, and start output if interface * not yet active. */ s = splimp(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); splx(s); m_freem(m); return (ENOBUFS); } IF_ENQUEUE(&ifp->if_snd, m); /* * If transmit request not already pending, then * kick the back end. */ if ((xs->xs_flags & EX_XPENDING) == 0) { exstart(ifp->if_unit); } #ifdef DEBUG else { xs->xs_wait++; } #endif splx(s); return (0); bad: m_freem(m0); return (error); } /* * Watchdog routine - place stats request to EXOS * (This could be dispensed with, if you don't care * about the if_ierrors count, or are willing to receive * bad packets in order to derive it.) */ exwatch(unit) int unit; { struct uba_device *ui = exinfo[unit]; struct exdevice *addr = (struct exdevice *)ui->ui_addr; register struct ex_softc *xs = &ex_softc[unit]; register struct ex_msg *bp; int s = splimp(); if (xs->xs_flags & EX_STATPENDING) goto exspnd; bp = exgetcbuf(xs); xs->xs_flags |= EX_STATPENDING; bp->mb_rqst = LLNET_STSTCS; bp->mb_ns.ns_mask = READ_OBJ; bp->mb_ns.ns_rsrv = 0; bp->mb_ns.ns_nobj = 8; /* read all 8 stats objects */ bp->mb_ns.ns_xobj = 0; /* starting with the 1st one */ bp->mb_ns.ns_bufp = P_UNIADDR(xs->xs_ubaddr) + SA_OFFSET(unit); bp->mb_status |= MH_EXOS; addr->xd_portb = EX_NTRUPT; exspnd: splx(s); xs->xs_if.if_timer = EXWATCHINTVL; } /* * Process an ioctl request. */ exioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { register struct ifaddr *ifa = (struct ifaddr *)data; register struct ex_softc *xs = &ex_softc[ifp->if_unit]; int s = splimp(), error = 0; switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; exinit(ifp->if_unit); switch (ifa->ifa_addr.sa_family) { #ifdef INET case AF_INET: ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr; arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); break; #endif #ifdef NS case AF_NS: { register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); if (ns_nullhost(*ina)) ina->x_host = *(union ns_host *)(xs->xs_addr); else ex_setaddr(ina->x_host.c_host,ifp->if_unit); break; } #endif } break; case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_UP) == 0 && xs->xs_flags & EX_RUNNING) { ((struct exdevice *) (exinfo[ifp->if_unit]->ui_addr))->xd_porta = EX_RESET; xs->xs_flags &= ~EX_RUNNING; } else if (ifp->if_flags & IFF_UP && (xs->xs_flags & EX_RUNNING) == 0) exinit(ifp->if_unit); break; default: error = EINVAL; } splx(s); return (error); } /* * set ethernet address for unit */ ex_setaddr(physaddr, unit) u_char *physaddr; int unit; { register struct ex_softc *xs = &ex_softc[unit]; struct uba_device *ui = exinfo[unit]; register struct exdevice *addr= (struct exdevice *)ui->ui_addr; register struct ex_msg *bp; if (physaddr) { xs->xs_flags |= EX_SETADDR; bcopy((caddr_t)physaddr, (caddr_t)xs->xs_addr, 6); } if (! (xs->xs_flags & EX_RUNNING)) return; bp = exgetcbuf(xs); bp->mb_rqst = LLNET_ADDRS; bp->mb_na.na_mask = READ_OBJ|WRITE_OBJ; bp->mb_na.na_slot = PHYSSLOT; bcopy((caddr_t)xs->xs_addr, (caddr_t)bp->mb_na.na_addrs, 6); bp->mb_status |= MH_EXOS; addr->xd_portb = EX_NTRUPT; bp = xs->xs_x2hnext; while ((bp->mb_status & MH_OWNER) == MH_EXOS) /* poll for reply */ ; #ifdef DEBUG log(LOG_ERR, "ex%d: reset addr %s\n", ui->ui_unit, ether_sprintf(bp->mb_na.na_addrs)); #endif /* * Now, re-enable reception on phys slot. */ bp = exgetcbuf(xs); bp->mb_rqst = LLNET_RECV; bp->mb_nr.nr_mask = ENABLE_RCV|READ_OBJ|WRITE_OBJ; bp->mb_nr.nr_slot = PHYSSLOT; bp->mb_status |= MH_EXOS; addr->xd_portb = EX_NTRUPT; bp = xs->xs_x2hnext; while ((bp->mb_status & MH_OWNER) == MH_EXOS) /* poll for reply */ ; } #endif ength = MBDATALEN; bp->mb_status |= MH_EXOS; /* free up buffer */ addr->xd_portb = EX_NTRUPT; /* tell EXOS about it */ bp = xs->xs_x2hnext = xs->xs_x2hnext->mb_next; } } sys/vaxif/if_hdh.c 640 0 12 36533 4206113331 7367 /* %W% (Berkeley) %G% */ /************************************************************************\ ________________________________________________________ / \ | AAA CCCCCCCCCCCCCC CCCCCCCCCCCCCC | | AAAAA CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC | | AAAAAAA CCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCC | | AAAA AAAA CCCC CCCC | | AAAA AAAA CCCC CCCC | | AAAA AAAA CCCC CCCC | | AAAA AAAA CCCC CCCC | | AAAA AAAAAAAAAAA CCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCC | | AAAA AAAAAAAAAAA CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC | | AAAA AAAAAAAAA CCCCCCCCCCCCCC CCCCCCCCCCCCCC | \________________________________________________________/ Copyright (c) 1984 by Advanced Computer Communications 720 Santa Barbara Street, Santa Barbara, California 93101 (805) 963-9431 This software may be duplicated and used on systems which are licensed to run U.C. Berkeley versions of the UNIX operating system. Any duplication of any part of this software must include a copy of ACC's copyright notice. File: if_hdh.c Author: Art Berggreen Project: 4.2BSD HDH Function: Device specific driver for IF-11/HDH under 4.2BSD networking code. Revision History: Converted to 4.3, updated, UCB. 31-Aug-1984: V1.0 - First Implementation. A.B. 6-Nov-1984: V1.1 - Supress extra "LINE DOWN" msgs. A.B. 13-Jan-1984: V1.2 - Add conditionals for TWG. A.B. \************************************************************************/ /* $Header$ */ #include "hdh.h" #ifdef NHDH > 0 /* * * ACC IF-11/HDH interface * */ #include "param.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "protosw.h" #include "socket.h" #include "vmmac.h" #include "../machine/pte.h" #include "../net/if.h" #include "../netimp/if_imp.h" #include "../vax/cpu.h" #include "../vax/mtpr.h" #include "../vaxuba/ubareg.h" #include "../vaxuba/ubavar.h" #include "if_hdhreg.h" #include "if_uba.h" int hdhprobe(), hdhattach(), hdhintr(); struct uba_device *hdhinfo[NHDH]; u_short hdhstd[] = { 0 }; struct uba_driver hdhdriver = { hdhprobe, 0, hdhattach, 0, hdhstd, "hdh", hdhinfo }; #define HDHUNIT(x) minor(x) int hdhinit(), hdhoutput(), hdhreset(); /* * "Lower half" of IMP interface driver. * * Each IMP interface is handled by a common module which handles * the IMP-host protocol and a hardware driver which manages the * hardware specific details of talking with the IMP. * * The hardware portion of the IMP driver handles DMA and related * management of UNIBUS resources. The IMP protocol module interprets * contents of these messages and "controls" the actions of the * hardware module during IMP resets, but not, for instance, during * UNIBUS resets. * * The two modules are coupled at "attach time", and ever after, * through the imp interface structure. Higher level protocols, * e.g. IP, interact with the IMP driver, rather than the HDH. */ #define NHDHCH 2 /* no. of FDX channels for HDH */ #define SUPR 0 /* supervisor channel */ #define DATA 1 /* data channel */ #define HDHSUPR 0 /* supervisor read */ #define HDHSUPW 1 /* supervisor write */ #define HDHDATR 2 /* data read */ #define HDHDATW 3 /* data write */ #define HDH_UP 2 /* HDH protocol is up */ #define HDH_STARTED 1 /* HDH has been initialized */ #define HCBUSY 1 /* HDH HDX channel busy flag */ /* /* The IF-11/HDH has four independent dath flow channels between the /* front-end and the host. Two are used for reading and writing /* control messages and two are used for data flow. Each IF-11/HDH /* has a device dependent data structure (hdh_softc) which contains /* an array of four channel dependent structures (hdh_chan) to maintain /* the context of each channel. Channel structures can be linked into /* a queue of I/O requests pending for the hardware interface. /* UNIBUS mapping resources are allocated for each channel pair. */ struct hdh_chan { /* HDH HDX channel structure */ struct hdh_chan *hc_next; /* link for Start I/O queuing */ char hc_chan; /* HDX chan number */ char hc_adx; /* extended UNIBUS address bits */ short hc_addr; /* lower UNIBUS address bits */ short hc_cnt; /* byte count */ char hc_func; /* UMC I/O function */ char hc_sbfc; /* UMC I/O subfunction */ short hc_flags; /* status flags */ }; struct hdh_sioq { /* Start I/O queue head structure */ struct hdh_chan *sioq_head; /* pointer to queue head */ struct hdh_chan *sioq_tail; /* pointer to queue tail */ }; struct hdh_softc { /* HDH device dependent structure */ struct imp_softc *hdh_imp; /* pointer to IMP's imp_softc struct */ struct ifuba hdh_ifuba[NHDHCH]; /* UNIBUS resources */ struct hdh_chan hdh_chan[2*NHDHCH]; /* HDX HDH channels */ struct hdh_sioq hdh_sioq; /* start i/o queue */ short hdh_flags; /* various status conditions */ } hdh_softc[NHDH]; /* * Normally, code goes here to cause the device to interrupt to determine its * interrupt vector. However, since the UMC must be told its vector in order * to interrupt, we allocate and return an unused vector and initialize the * UMC. */ hdhprobe(reg) caddr_t reg; { register int br, cvec; struct hdhregs *addr = (struct hdhregs *)reg; #ifdef lint br = 0; cvec = br; br = cvec; hdhintr(0); #endif br = 0x15; /* priority 21 (5 on UNIBUS) */ #ifdef HDHDEBUG cvec = 0270; /* use constant for now ... */ #else #ifdef VAXVMS /* if VMS */ cvec = 0270; /* we can't allocate vectors */ #else cvec = (uba_hd[numuba].uh_lastiv -= 4); /* available vector */ #endif VAXVMS #endif HDHDEBUG addr->ioini = (char) 0; /* init UMC regs */ addr->staack = (char) 0; /* pass vector */ addr->ionmi = (char) 0; /* and kick UMC */ addr->iochn = (char) (cvec >> 2); addr->csr = (short) HDH_RST; addr->csr = (short) (HDH_IEN|HDH_DMA|HDH_WRT); /* set enables */ DELAY(5000); /* give the UMC some time */ return(1); } /* * Call the IMP module to allow it to set up its internal * state, then tie the two modules together by setting up * the back pointers to common data structures. */ hdhattach(ui) register struct uba_device *ui; { register struct hdh_softc *sc = &hdh_softc[ui->ui_unit]; register struct impcb *ip; if ((sc->hdh_imp = impattach(ui->ui_driver->ud_dname, ui->ui_unit, hdhreset)) == 0) return; ip = &sc->hdh_imp->imp_cb; ip->ic_init = hdhinit; ip->ic_output = hdhoutput; sc->hdh_ifuba[ui->ui_unit].ifu_flags = UBA_CANTWAIT; } /* * Reset interface after UNIBUS reset. */ hdhreset(unit, uban) int unit, uban; { register struct uba_device *ui = hdhinfo[unit]; register struct hdh_softc *sc = &hdh_softc[unit]; #ifdef HDHDEBUG printf("HDH RESET\n"); #endif HDHDEBUG if ((unit >= NHDH) || (ui == 0) || (ui->ui_alive == 0) || (ui->ui_ubanum != uban)) return; printf(" hdh%d", unit); sc->hdh_imp->imp_if.if_flags &= ~IFF_RUNNING; sc->hdh_flags = 0; (*sc->hdh_imp->imp_if.if_init)(sc->hdh_imp->imp_if.if_unit); } /* * Initialize the imp interface. */ static char init_blk[] = { HDHINIT, /* SYSINIT opcode */ HDHRQUP & 0xff, /* control code (LSB) */ (HDHRQUP>>8) & 0xff, /* control code (MSB) */ 10, /* command extension len */ 0, /* loopback mode (off) */ 3, /* our address (3=DTE) */ 1, /* their address (1=DCE) */ 3, /* frame ack t1 timeout */ 3, /* poll ack timeout */ 30, /* adm wait timeout */ 3, /* rej wait timeout */ 10, /* max retries */ 3, /* watchdog timeout */ 0xaa /* baud rate (0xaa=38.4KB) */ /* (output on RS-232 pin 24, */ /* send/receive timing is always */ /* taken from pins 15/17) */ }; hdhinit(unit) int unit; { register struct hdh_softc *sc; register struct uba_device *ui; int i; #ifdef HDHDEBUG printf("HDH INIT\n"); #endif HDHDEBUG if (unit >= NHDH || (ui = hdhinfo[unit]) == NULL || ui->ui_alive == 0) { printf("hdh%d: not alive\n", unit); return(0); } sc = &hdh_softc[unit]; if (sc->hdh_flags & HDH_STARTED) return(1); /* * Alloc uba resources */ if ((sc->hdh_imp->imp_if.if_flags & IFF_RUNNING) == 0) for(i=0;ihdh_ifuba[i], ui->ui_ubanum, 0, (int)btoc(IMP_RCVBUF)) == 0) { printf("hdh%d: cannot get chan %d uba resources\n", unit, i); ui->ui_alive = 0; return(0); } } sc->hdh_imp->imp_if.if_flags |= IFF_RUNNING; sc->hdh_flags = HDH_STARTED; /* * hang a supervisor read (for line status) */ hdh_iorq(unit, HDHSUPR, IMP_RCVBUF, HDHRDB); /* * hang a data read */ hdh_iorq(unit, HDHDATR, IMP_RCVBUF, HDHRDB+HDHSTR); /* * bring up line to IMP */ snd_supr(unit, init_blk, sizeof(init_blk)); return(1); } /* * Start an output operation on an mbuf. */ hdhoutput(unit, m) int unit; struct mbuf *m; { register struct hdh_softc *sc = &hdh_softc[unit]; int len; /* * If output isn't active, attempt to * start sending a new packet. */ if (sc->hdh_imp->imp_cb.ic_oactive) { printf("hdh%d: start on active unit\n", unit); return; } if ((sc->hdh_flags & HDH_UP) == 0) { /* Link not up, can't xmit */ return; } len = if_wubaput(&sc->hdh_ifuba[DATA], m); /* copy data to mapped mem */ sc->hdh_imp->imp_cb.ic_oactive = 1; hdh_iorq(unit, HDHDATW, len, HDHWRT+HDHEOS); } /* * Start i/o operation on a UMC logical channel */ hdh_iorq(unit, lcn, len, func) int unit, lcn, len, func; { register struct hdh_softc *sc = &hdh_softc[unit]; register struct hdh_chan *hc = &sc->hdh_chan[lcn]; register int info, s; /* * If channel is busy (shouldn't be), drop. */ if (hc->hc_flags & HCBUSY) { printf("hdh%d: channel busy lcn=%d\n", unit, lcn); return; } /* get appropriate UNIBUS mapping info */ if (lcn & 1) /* read or write? */ info = sc->hdh_ifuba[lcn>>1].ifu_w.ifrw_info; else info = sc->hdh_ifuba[lcn>>1].ifu_r.ifrw_info; /* set channel info */ hc->hc_flags |= HCBUSY; hc->hc_chan = lcn; hc->hc_adx = (char)((info & 0x30000) >> 12); hc->hc_addr = (unsigned short)(info & 0xffff); hc->hc_cnt = len; hc->hc_func = (char)func; hc->hc_sbfc = 0; s = splimp(); /* * If UMC comm regs busy, queue start i/o for later. */ if (sc->hdh_sioq.sioq_head) { (sc->hdh_sioq.sioq_tail)->hc_next = hc; sc->hdh_sioq.sioq_tail = hc; hc->hc_next = 0; splx(s); return; } /* start i/o on channel now */ sc->hdh_sioq.sioq_head = hc; sc->hdh_sioq.sioq_tail = hc; hc->hc_next = 0; start_chn(unit); splx(s); } start_chn(unit) int unit; { register struct hdh_softc *sc = &hdh_softc[unit]; register struct hdh_chan *hc = sc->hdh_sioq.sioq_head; register struct hdhregs *addr = (struct hdhregs *)hdhinfo[unit]->ui_addr; /* * Set up comm regs. */ addr->iochn = hc->hc_chan; addr->ioadx = hc->hc_adx; addr->ioadl = hc->hc_addr; addr->iocnt = hc->hc_cnt; addr->iofcn = hc->hc_func; addr->iosbf = hc->hc_sbfc; addr->ioini = 1; /* signal UMC if necessary */ if (!(addr->ionmi)) { addr->ionmi = 1; addr->csr = HDH_DMA|HDH_WRT|HDH_IEN|HDH_NMI; } } /* * IF-11/HDH interrupt handler */ hdhintr(unit) int unit; { register struct hdh_softc *sc = &hdh_softc[unit]; register struct hdh_chan *hc; register struct hdhregs *addr = (struct hdhregs *)hdhinfo[unit]->ui_addr; int lcn, type, cc, cnt; /* * Check for hardware errors. */ if (addr->csr & HDH_UER) { printf("hdh%d: hard error csr=%b\n", unit, addr->csr, HDH_BITS); addr->csr = 0; /* disable i/f */ return; } /* * Get logical channel info. */ if ((lcn = addr->stachn) >= (NHDHCH*2)) { printf("hdh%d: unknown channel lcn=%d\n", unit, lcn); return; } hc = &sc->hdh_chan[lcn]; type = addr->statyp; cc = addr->stacc; cnt = hc->hc_cnt - addr->stacnt; /* Figure out what kind of interrupt it was */ switch(type) { case HDHSACK: /* start i/o accepted */ if (hc != sc->hdh_sioq.sioq_head) { printf("hdh%d: STARTIO error lcn=%d hc=%x sq=%x\n", unit, lcn, hc, sc->hdh_sioq.sioq_head); return; } /* try to start any queued i/o request */ if (sc->hdh_sioq.sioq_head = sc->hdh_sioq.sioq_head->hc_next) { start_chn(unit); } break; case HDHDONE: /* i/o completion */ switch (cc) { case HDHIOCABT: printf("hdh%d: I/O abort ", unit); goto daterr; case HDHIOCERR: printf("hdh%d: program error ", unit); goto daterr; case HDHIOCOVR: printf("hdh%d: overrun error ", unit); goto daterr; case HDHIOCUBE: printf("hdh%d: NXM timeout or UB parity error ", unit); daterr: printf("lcn=%d func=%x\n", lcn, hc->hc_func); if (hc->hc_func & HDHRDB) sc->hdh_imp->imp_if.if_ierrors++; else sc->hdh_imp->imp_if.if_oerrors++; } hc->hc_flags &= ~HCBUSY; /* was it supervisor or data traffic? */ if (lcn > HDHSUPW) hdh_data(unit, lcn, cc, cnt); else hdh_supr(unit, lcn, cc); } /* * Ack the interrupt */ addr->staack = 1; if (!(addr->ionmi)) { addr->ionmi = 1; addr->csr = HDH_DMA|HDH_WRT|HDH_IEN|HDH_NMI; } } /* * data channel interrupt completion handler */ hdh_data(unit, lcn, cc, rcnt) int unit, lcn, cc, rcnt; { register struct hdh_softc *sc = &hdh_softc[unit]; register struct hdh_chan *hc = &sc->hdh_chan[lcn]; register struct mbuf *m; /* was it read or write? */ if (hc->hc_func & HDHRDB) { if (cc == HDHIOCOK) { /* * Queue good packet for input */ sc->hdh_imp->imp_if.if_ipackets++; m = if_rubaget(&sc->hdh_ifuba[lcn>>1], rcnt, 0, &sc->hdh_imp->imp_if); impinput(unit, m); } /* hang a new data read */ hdh_iorq(unit, lcn, IMP_RCVBUF, HDHRDB+HDHSTR); } else { /* * fire up next output */ sc->hdh_imp->imp_if.if_opackets++; sc->hdh_imp->imp_cb.ic_oactive = 0; impstart(sc->hdh_imp->imp_if.if_unit); } } /* * supervisor channel interrupt completion handler */ hdh_supr(unit, lcn, cc) int unit, lcn, cc; { register struct hdh_softc *sc = &hdh_softc[unit]; register struct hdh_chan *hc = &sc->hdh_chan[lcn]; short *p; /* was it read or write? */ if (hc->hc_func & HDHRDB) { if (cc == HDHIOCOK) { p = (short *)(sc->hdh_ifuba[lcn>>1].ifu_r.ifrw_addr); /* figure out what kind of supervisor message */ switch (*p) { case HDHIACK: case HDHLNACK: break; case HDHLNUP: printf("hdh%d: LINE UP\n", unit); sc->hdh_flags |= HDH_UP; impstart(sc->hdh_imp->imp_if.if_unit); break; case HDHLNDN: if (sc->hdh_flags & HDH_UP) printf("hdh%d: LINE DOWN\n", unit); sc->hdh_flags &= ~HDH_UP; break; case HDHLOOP: break; case HDHSQERR: printf("hdh%d: HOST SEQUENCE ERROR\n", unit); break; case HDHSQRCV: printf("hdh%d: IMP SEQUENCE ERROR\n", unit); break; case HDHDTERR: printf("hdh%d: HOST DATA ERROR\n", unit); break; case HDHTIMO: printf("hdh%d: TIMEOUT\n", unit); break; default: printf("hdh%d: supervisor error, code=%x\n", unit, *p); } } /* hang a new supr read */ hdh_iorq(unit, HDHSUPR, IMP_RCVBUF, HDHRDB+HDHSTR); } } snd_supr(unit, msg, len) int unit, len; char *msg; { register struct hdh_softc *sc = &hdh_softc[unit]; register struct mbuf *m; register char *p; register int cnt; if ((m = m_get(M_DONTWAIT, MT_DATA)) == NULL) { printf("hdh%d: cannot get supervisor cmnd buffer\n", unit); return; } cnt = len; m->m_len = len; p = mtod(m, char *); while(cnt--) *p++ = *msg++; cnt = if_wubaput(&sc->hdh_ifuba[SUPR], m); hdh_iorq(unit, HDHSUPW, cnt, HDHWRT+HDHEOS); } #endif NHDH } eh = mtod(m, struct ether_header *); eh->ether_type = htons((u_short)type); bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); bcopy((caddr_t)xs->sys/vaxif/if_ddnvar.h 444 0 12 10104 3671247455 10117 /* @(#)if_ddnvar.h 7.1 (Berkeley) 6/5/86 */ /************************************************************************\ ________________________________________________________ / \ | AAA CCCCCCCCCCCCCC CCCCCCCCCCCCCC | | AAAAA CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC | | AAAAAAA CCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCC | | AAAA AAAA CCCC CCCC | | AAAA AAAA CCCC CCCC | | AAAA AAAA CCCC CCCC | | AAAA AAAA CCCC CCCC | | AAAA AAAAAAAAAAA CCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCC | | AAAA AAAAAAAAAAA CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC | | AAAA AAAAAAAAA CCCCCCCCCCCCCC CCCCCCCCCCCCCC | \________________________________________________________/ Copyright (c) 1985 by Advanced Computer Communications 720 Santa Barbara Street, Santa Barbara, California 93101 (805) 963-9431 This software may be duplicated and used on systems which are licensed to run U.C. Berkeley versions of the UNIX operating system. Any duplication of any part of this software must include a copy of ACC's copyright notice. File: if_ddnvar.h Author: Art Berggreen Project: 4.2 DDN X.25 network driver Function: This file contains definitions used to control and track the status of the ACP625 (IF-11/X25). Components: Revision History: 16-May-1985: V1.0 - First release. Art Berggreen. \************************************************************************/ /* if_ddnvar.h V1.0 5/16/85 */ /* program parameters */ #define DDNMTU 1006 /* maximum IP msg length */ #define DDN_OQMAX 8 /* max IP msgs on LCN output q */ #define NDDNCH 32 /* number of X.25 channels */ #define DELAY_CNT 50000 #define DDN_TIMEOUT 10 #define DC_OBUSY 0x01 typedef unsigned char byte; typedef int boolean; /* X25 LCN state definitions */ #define LC_DOWN 0 /* X25 circuit down */ #define LC_RESTART 1 /* X25 circuit restarting */ #define LC_IDLE 2 /* X25 circuit not in use */ #define LC_CALL_PENDING 3 /* X25 circuit call pending */ #define LC_DATA_IDLE 4 /* X25 circuit open */ #define LC_CLR_PENDING 5 /* X25 circuit clear pending */ /* Timeout definitions */ #define TMO_OFF 0 /* timer off */ #define TMO_RESTART ( 90/DDN_TIMEOUT) /* restart timeout */ #define TMO_CALL_PENDING (180/DDN_TIMEOUT) /* call timeout */ #define TMO_DATA_IDLE ( 30/DDN_TIMEOUT) /* idle circuit timeout */ #define TMO_CLR_PENDING ( 30/DDN_TIMEOUT) /* clear timeout */ /* Link status codes */ #define LINK_DOWN 0x00 /* Link layer is down */ #define LINK_UP 0x01 /* Link layer is up */ /* Line control codes */ #define LINK_DISABLE 0x00 /* Disable link layer */ #define LINK_ENABLE 0x01 /* Enable link layer */ #define LINK_LOOPBACK 0x42 /* Link layer loopback mode */ #define LOOP_OFF 0x00 /* Loopback off */ #define LOOP_EXTERNAL 0x01 /* Loopback external */ #define LOOP_INTERNAL 0x03 /* Loopback internal */ #define PKT_SIZE 0x90 /* Packet size */ #define PKT_WINDOW 0x4f /* Packet window */ /* X25 supervisor message codes */ #define CALL 0x00 /* outgoing call */ #define RING 0x01 /* incoming call */ #define CLEARVC 0x02 /* clear by VCN */ #define ANSWER 0x03 /* answer call */ #define CLEARLC 0x04 /* clear by LCN */ #define RESET 0x20 /* reset LCN */ #define RESET_ACK 0x21 /* reset ack */ #define INTERRUPT 0x22 /* X25 interrupt */ #define READY 0x23 /* flow control ready */ #define INTR_ACK 0x24 /* interrupt ack */ #define RESTART 0x40 /* X25 restart */ #define RSTRT_ACK 0x41 /* restart ack */ #define SYS_STATUS 0x42 /* system status msg */ #define LINE_CNTL 0x60 /* link control cmnd */ #define LINE_STATUS 0x61 /* link status resp */ /* X25 facilities */ #define X25_FACIL_DDN 0x04 /* DDN mode facility */ #define FAC_DDNSTD 0x01 /* DDN standard mode */ /* X25 protocols */ #define X25_PROTO_IP 0xcc /* X25 IP protocol type code */ nc; hc->hc_sbfc = 0; s = splimp(); /* * If UMC comm regs busy, queue start i/o for later. */ if (sc->hdh_sioq.sioq_head) { (sc->hdh_sioq.sioq_tail)->hc_next = hc; sc->hdh_sioq.sioq_tail = hc; hc->hc_next = 0; splx(s); return; } /* start i/o on channel now */ sc->hdh_sioq.sioq_head = hc; sc->hdh_sioq.sioq_tail = hc; hc->hc_next = 0; start_chn(unit); splx(s); } start_chn(unit) int unit; { register struct hdh_softsys/vaxif/if_pcl.c 444 0 12 30054 3671425141 7406 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_pcl.c 7.1 (Berkeley) 6/5/86 */ #include "pcl.h" #if NPCL > 0 /* * DEC CSS PCL-11B Parallel Communications Interface * * Written by Mike Muuss and Jeff Schwab. */ #include "../machine/pte.h" #include "param.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "protosw.h" #include "socket.h" #include "vmmac.h" #include "ioctl.h" #include "errno.h" #include "../net/if.h" #include "../net/netisr.h" #include "../net/route.h" #ifdef INET #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netinet/in_var.h" #include "../netinet/ip.h" #endif #include "../vax/cpu.h" #include "../vax/mtpr.h" #include "if_pclreg.h" #include "if_uba.h" #include "../vaxuba/ubareg.h" #include "../vaxuba/ubavar.h" /* The MTU has been carefully selected to prevent fragmentation <-> ArpaNet */ #define PCLMTU (1006) /* Max transmission unit (bytes) */ #define PCLMAXTDM 7 /* Max unit number on TDM bus */ int pclprobe(), pclattach(), pclrint(), pclxint(); int pclinit(), pclioctl(), pcloutput(), pclreset(); struct uba_device *pclinfo[NPCL]; u_short pclstd[] = { 0 }; #define PCLUNIT(x) minor(x) struct uba_driver pcldriver = { pclprobe, 0, pclattach, 0, pclstd, "pcl", pclinfo }; /* * PCL software status per interface. * * Each interface is referenced by a network interface structure, * sc_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... * We also have, for each interface, a UBA interface structure, which * contains information about the UNIBUS resources held by the interface: * map registers, buffered data paths, etc. Information is cached in this * structure for use by the if_uba.c routines in running the interface * efficiently. */ struct pcl_softc { struct ifnet sc_if; /* network-visible interface */ struct ifuba sc_ifuba; /* UNIBUS resources */ short sc_oactive; /* is output active? */ short sc_olen; /* length of last output */ short sc_lastdest; /* previous destination */ short sc_odest; /* current xmit destination */ short sc_bdest; /* buffer's stated destination */ short sc_pattern; /* identification pattern */ } pcl_softc[NPCL]; /* * Structure of "local header", which only goes between * pcloutput and pclstart. */ struct pcl_header { short pcl_dest; /* Destination PCL station */ }; /* * Do non-DMA output of 1 word to determine presence of interface, * and to find the interupt vector. 1 word messages are a special * case in the receiver routine, and will be discarded. */ pclprobe(reg) caddr_t reg; { register int br, cvec; /* r11, r10 value-result */ register struct pcldevice *addr = (struct pcldevice *)reg; #ifdef lint br = 0; cvec = br; br = cvec; pclrint(0); pclxint(0); #endif addr->pcl_rcr = PCL_RCINIT; addr->pcl_tcr = PCL_TXINIT; addr->pcl_tsba = 0xFFFE; /* going for 01777776 */ addr->pcl_tsbc = -4; /* really short */ addr->pcl_tcr = ((1 & 0xF) << 8) | PCL_TXNPR | PCL_SNDWD | PCL_STTXM | PCL_IE | 0x0030; DELAY(100000); addr->pcl_tcr = PCL_TXINIT; return (sizeof (struct pcldevice)); } /* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */ pclattach(ui) struct uba_device *ui; { register struct pcl_softc *sc = &pcl_softc[ui->ui_unit]; sc->sc_if.if_unit = ui->ui_unit; sc->sc_if.if_name = "pcl"; sc->sc_if.if_mtu = PCLMTU; sc->sc_if.if_init = pclinit; sc->sc_if.if_output = pcloutput; sc->sc_if.if_ioctl = pclioctl; sc->sc_if.if_reset = pclreset; sc->sc_if.if_flags = IFF_BROADCAST; sc->sc_ifuba.ifu_flags = UBA_NEEDBDP; if_attach(&sc->sc_if); } /* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */ pclreset(unit, uban) int unit, uban; { register struct uba_device *ui; if (unit >= NPCL || (ui = pclinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" pcl%d", unit); pclinit(unit); } /* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */ pclinit(unit) int unit; { register struct pcl_softc *sc = &pcl_softc[unit]; register struct uba_device *ui = pclinfo[unit]; register struct pcldevice *addr; int s; if (sc->sc_if.if_addrlist == (struct ifaddr *)0) return; if (if_ubainit(&sc->sc_ifuba, ui->ui_ubanum, 0, (int)btoc(PCLMTU)) == 0) { printf("pcl%d: can't init\n", unit); sc->sc_if.if_flags &= ~(IFF_UP | IFF_RUNNING); return; } sc->sc_if.if_flags |= IFF_RUNNING; addr = (struct pcldevice *)ui->ui_addr; addr->pcl_rcr = PCL_RCINIT; addr->pcl_tcr = PCL_TXINIT; /* * Hang a receive and start any * pending writes by faking a transmit complete. */ s = splimp(); addr->pcl_rdba = (short) sc->sc_ifuba.ifu_r.ifrw_info; addr->pcl_rdbc = -PCLMTU; addr->pcl_rcr = (((int)(sc->sc_ifuba.ifu_r.ifrw_info>>12))&0x0030) | PCL_RCNPR | PCL_RCVWD | PCL_RCVDAT | PCL_IE; sc->sc_oactive = 0; pclstart(unit); splx(s); } /* * PCL output routine. */ pcloutput(ifp, m, dst) struct ifnet *ifp; struct mbuf *m; struct sockaddr *dst; { int dest, s, error; struct pcl_header *pclp; struct mbuf *m2; switch (dst->sa_family) { #ifdef INET case AF_INET: if (in_broadcast(((struct sockaddr_in *)dst)->sin_addr)) dest = 0; else dest = in_lnaof(((struct sockaddr_in *)dst)->sin_addr); if (dest > PCLMAXTDM) { error = EHOSTUNREACH; goto bad; } break; #endif default: printf("pcl%d: can't handle af%d\n", ifp->if_unit, dst->sa_family); error = EAFNOSUPPORT; goto bad; } /* * Add pseudo local net header. * Actually, it does not get transmitted, but merely stripped * off and used by the START routine to route the packet. * If no space in first mbuf, allocate another. */ if (m->m_off > MMAXOFF || MMINOFF + sizeof (struct pcl_header) > m->m_off) { m2 = m_get(M_DONTWAIT, MT_HEADER); if (m2 == 0) { error = ENOBUFS; goto bad; } m2->m_next = m; m2->m_off = MMINOFF; m2->m_len = sizeof (struct pcl_header); m = m2; } else { m->m_off -= sizeof (struct pcl_header); m->m_len += sizeof (struct pcl_header); } pclp = mtod(m, struct pcl_header *); pclp->pcl_dest = dest; /* * Queue message on interface, and start output if interface * not yet active. */ s = splimp(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); error = ENOBUFS; goto qfull; } IF_ENQUEUE(&ifp->if_snd, m); if (pcl_softc[ifp->if_unit].sc_oactive == 0) pclstart(ifp->if_unit); splx(s); return (0); qfull: splx(s); bad: m_freem(m); return (error); } /* * Start or restart output on interface. * If interface is already active, then this is a retransmit. * If interface is not already active, get another datagram * to send off of the interface queue, and map it to the interface * before starting the output. */ pclstart(dev) dev_t dev; { int unit = PCLUNIT(dev); struct uba_device *ui = pclinfo[unit]; register struct pcl_softc *sc = &pcl_softc[unit]; register struct pcldevice *addr; struct mbuf *m; if (sc->sc_oactive) goto restart; /* * Not already active: dequeue another request * and map it to the UNIBUS. If no more requests, * just return. */ IF_DEQUEUE(&sc->sc_if.if_snd, m); if (m == 0) { sc->sc_oactive = 0; return; } /* * Pull destination node out of pseudo-local net header. * remove it from outbound data. * Note that if_wubaput calls m_bcopy, which is prepared for * m_len to be 0 in the first mbuf in the chain. */ sc->sc_bdest = mtod(m, struct pcl_header *)->pcl_dest; sc->sc_odest = sc->sc_bdest? sc->sc_bdest: 1; m->m_off += sizeof (struct pcl_header); m->m_len -= sizeof (struct pcl_header); /* Map out to the DMA area */ sc->sc_olen = if_wubaput(&sc->sc_ifuba, m); restart: /* * Have request mapped to UNIBUS for transmission. * Purge any stale data from this BDP, and start the output. */ if (sc->sc_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(sc->sc_ifuba.ifu_uba, sc->sc_ifuba.ifu_w.ifrw_bdp); addr = (struct pcldevice *)ui->ui_addr; addr->pcl_tcr = PCL_TXINIT; addr->pcl_tsba = (int)sc->sc_ifuba.ifu_w.ifrw_info; addr->pcl_tsbc = -sc->sc_olen; /* * RIB (retry if busy) is used on the second and subsequent packets * to a single host, because TCP often wants to transmit multiple * buffers in a row, * and if they are all going to the same place, the second and * subsequent ones may be lost due to receiver not ready again yet. * This can cause serious problems, because the TCP will resend the * whole window, which just repeats the problem. The result is that * a perfectly good link appears not to work unless we take steps here. */ addr->pcl_tcr = (((int)(sc->sc_ifuba.ifu_w.ifrw_info>>12))&0x0030) | ((sc->sc_odest & 0xF)<<8) | PCL_TXNPR | PCL_SNDWD | PCL_STTXM | PCL_IE | (sc->sc_odest == sc->sc_lastdest ? PCL_RIB : 0); sc->sc_lastdest = sc->sc_odest; sc->sc_oactive = 1; } /* * PCL transmitter interrupt. * Start another output if more data to send. */ pclxint(unit) int unit; { register struct uba_device *ui = pclinfo[unit]; register struct pcl_softc *sc = &pcl_softc[unit]; register struct pcldevice *addr = (struct pcldevice *)ui->ui_addr; if (sc->sc_oactive == 0) { printf ("pcl%d: stray interrupt\n", unit); return; } if (addr->pcl_tsr & PCL_ERR) { sc->sc_lastdest = 0; /* don't bother with RIB */ if (addr->pcl_tsr & PCL_MSTDWN) { addr->pcl_tmmr = PCL_MASTER|PCL_AUTOADDR; pclstart(unit); /* Retry */ printf("pcl%d: master\n", unit ); return; } #ifndef PCL_TESTING if ((addr->pcl_tsr & (PCL_ERR|PCL_RESPB)) == (PCL_ERR|0)) { ; /* Receiver Offline -- not exactly an error */ } else { #else { #endif /* Log as an error */ printf("pcl%d: send error, tcr=%b tsr=%b\n", unit, addr->pcl_tcr, PCL_TCSRBITS, addr->pcl_tsr, PCL_TERRBITS); sc->sc_if.if_oerrors++; } } else sc->sc_if.if_opackets++; if (sc->sc_bdest == 0 && sc->sc_odest < PCLMAXTDM) { sc->sc_odest++; /* do next host (broadcast) */ } else { sc->sc_oactive = 0; if (sc->sc_ifuba.ifu_xtofree) { m_freem(sc->sc_ifuba.ifu_xtofree); sc->sc_ifuba.ifu_xtofree = 0; } } pclstart(unit); } /* * PCL interface receiver interrupt. * If input error just drop packet. */ pclrint(unit) int unit; { register struct pcl_softc *sc = &pcl_softc[unit]; struct pcldevice *addr = (struct pcldevice *)pclinfo[unit]->ui_addr; struct mbuf *m; int len; register struct ifqueue *inq; sc->sc_if.if_ipackets++; /* * Purge BDP; drop if input error indicated. */ if (sc->sc_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(sc->sc_ifuba.ifu_uba, sc->sc_ifuba.ifu_r.ifrw_bdp); if (addr->pcl_rsr & PCL_ERR) { printf("pcl%d: rcv error, rcr=%b rsr=%b\n", unit, addr->pcl_rcr, PCL_RCSRBITS, addr->pcl_rsr, PCL_RERRBITS); sc->sc_if.if_ierrors++; goto setup; } len = PCLMTU + addr->pcl_rdbc; if (len <= 0 || len > PCLMTU) { printf("pcl%d: bad len=%d.\n", unit, len); sc->sc_if.if_ierrors++; goto setup; } /* Really short packets will be part of the startup sequence */ if (len <= 4) { /* Later, do comming-up processing here */ goto setup; /* drop packet */ } /* * Pull packet off interface. */ m = if_rubaget(&sc->sc_ifuba, len, 0, &sc->sc_if); if (m == 0) goto setup; schednetisr(NETISR_IP); inq = &ipintrq; if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); } else IF_ENQUEUE(inq, m); setup: /* * Reset for next packet. */ addr->pcl_rcr = PCL_RCINIT; addr->pcl_rdba = (int)sc->sc_ifuba.ifu_r.ifrw_info; addr->pcl_rdbc = -PCLMTU; addr->pcl_rcr = (((int)(sc->sc_ifuba.ifu_w.ifrw_info>>12))&0x0030) | PCL_RCNPR | PCL_RCVWD | PCL_RCVDAT | PCL_IE; } /* * Process an ioctl request. */ /* ARGSUSED */ pclioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { int s = splimp(), error = 0; switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; if ((ifp->if_flags & IFF_RUNNING) == 0) pclinit(ifp->if_unit); break; default: error = EINVAL; } splx(s); return (error); } #endif egister struct hdh_chan *hc = &sc->hdh_chan[lcn]; register struct mbuf *m; /* was it read or write? */ if (hc->hc_func & HDHRDB) { if (cc == HDHIOCOK) { /* * Queue good packet for input */ sc->hdh_imp->imp_if.if_ipackets++; m = if_rubaget(&sc->hdh_ifuba[lcn>>1], rcnt, 0, &sc->hdh_imp->imp_if); impinput(unit, m); } /* hang a new data read */ hdh_iorq(unit, lcn, IMP_RCVBUF, HDHRDB+HDHSTR); } else { /* * fire up next ousys/vaxif/if_en.h 444 0 12 1424 3671247532 7224 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_en.h 7.1 (Berkeley) 6/5/86 */ /* * Structure of a Ethernet header. */ struct en_header { u_char en_shost; u_char en_dhost; u_short en_type; }; #define ENTYPE_PUP 0x0200 /* PUP protocol */ #define ENTYPE_IP 0x0201 /* IP protocol */ /* * The ENTYPE_NTRAILER packet types starting at * ENTYPE_TRAIL have (type-ENTYPE_TRAIL)*512 bytes * of data followed by an Ethernet type (as given above) * and then the (variable-length) header. */ #define ENTYPE_TRAIL 0x1000 /* Trailer type */ #define ENTYPE_NTRAILER 16 #define EN_BROADCAST 0 /* Hardware broadcast address */ rely stripped * off and used by the START routine to route the packet. * If no space in first mbuf, allocate another. */ if (m->m_off > MMAXOFF || MMINOFF + sizeof (struct pcl_header) > m->m_off) { m2 = m_get(M_DONTWAIT, Msys/vaxif/if_hdhreg.h 444 0 12 7410 3671247617 10070 /* @(#)if_hdhreg.h 7.1 (Berkeley) 6/5/86 */ /* $Header$ */ /* * ACC IF-11/HDH interface */ struct hdhregs { /* device registers */ u_short csr; /* control and status register */ u_char iochn; /* logical channel */ u_char ioadx; /* address extension (A16,A17) */ u_short ioadl; /* buffer address (A0-A15) */ u_short iocnt; /* byte count */ u_char iofcn; /* UMC funciton code */ u_char iosbf; /* UMC subfunction code */ u_char ioini; /* comm regs valid flag */ u_char staack; /* interrupt acknowledge flag */ u_char ionmi; /* NMI routine active flag */ u_char ioxfrg; /* UMR transfer grant flag */ u_char stachn; /* interrupt channel number */ u_char statyp; /* interrupt type code */ u_char stacc; /* completion function code */ u_char stacs; /* completion subfunction code */ u_short stacnt; /* completion byte count */ }; /* defines for CSR */ #define HDH_UER 0100000 /* UMC error condition */ #define HDH_NXM 0040000 /* non-existent memory error */ #define HDH_PER 0020000 /* UNIBUS parity error */ #define HDH_ZRUN 0010000 /* Z80 running */ #define HDH_ZGO 0004000 /* Z80 not in wait state */ #define HDH_MBLK 0000200 /* memory swap state (0=main, 1=srv) */ #define HDH_SRV 0000100 /* select UMC service memory */ #define HDH_MAIN 0000040 /* select UMC main memory */ #define HDH_DMA 0000020 /* DMA enable */ #define HDH_WRT 0000010 /* DMA write enable */ #define HDH_IEN 0000004 /* interrupt enable */ #define HDH_RST 0000002 /* reset */ #define HDH_NMI 0000001 /* cause NMI */ #define HDH_BITS \ "\10\20UER\17NXM\16PER\15ZRUN\14ZGO\10MBLK\7SRV\6MAIN\5DMA\4WRT\3IEN\2RST\1NMI" /* start i/o function code definitions */ #define HDHWRT 0 /* write to if-11 */ #define HDHRDB 1 /* read from if-11 */ #define HDHSTR 2 /* stream flag */ #define HDHEOS 6 /* end of stream flag */ #define HDHABT 8 /* abort flag */ #define HDHUMR 16 /* UMR protocol flag */ /* interrupt type definitions */ #define HDHSACK 0 /* start i/o ack */ #define HDHDONE 1 /* i/o completion */ #define HDHXREQ 2 /* UMR protocol transfer request */ /* i/o completion codes */ #define HDHIOCOK 0001 /* successful completion */ #define HDHIOCOKP 0002 /* successful completion, more data pending */ #define HDHIOCABT 0361 /* i/o aborted */ #define HDHIOCERR 0321 /* program error */ #define HDHIOCOVR 0363 /* overrun error */ #define HDHIOCUBE 0374 /* non-existant memory or unibus error */ /* UMR protocol transfer grant code definitions */ #define HDHXEVN 1 /* start with even address */ #define HDHXODD 2 /* start with odd address */ #define HDHNUMR 4 /* non-UMR transfer */ #define HDHXABT 8 /* abort transfer */ /* HDH supervisor request code definitions */ #define HDHINIT 0x42 /* SYSINIT opcode */ #define HDHSUP 0xf0 /* supervisor HDH status/line control prefix */ #define HDHIMP 0x400 /* IMP line up modifier */ #define HDHREFL 0x800 /* reflect mode modifier */ #define HDHINLB 0x1000 /* internal loopback modifier */ #define HDHEXLP 0x2000 /* external loopback modifier */ #define HDHRQST (HDHSUP+0x0000) /* line status request */ #define HDHRQUP (HDHSUP+0x0100) /* line up request */ #define HDHRQDN (HDHSUP+0x0200) /* line down request */ /* HDH supervisor reply code definitions */ #define HDHIACK (HDHSUP+0x4200) /* line init ack */ #define HDHLNUP (HDHSUP+0x0100) /* line up reply */ #define HDHLNDN (HDHSUP+0x0200) /* line down reply */ #define HDHLNACK (HDHSUP+0x0300) /* ack line up request (but line is down now) */ #define HDHTIMO (HDHSUP+0x0400) /* line timeout */ #define HDHLOOP (HDHSUP+0x0500) /* loopback message */ #define HDHDTERR (HDHSUP+0x0600) /* host data error detected */ #define HDHSQRCV (HDHSUP+0x0700) /* HDLC sequence error detected by IMP */ #define HDHSQERR (HDHSUP+0x0800) /* HDLC sequence error detected by if-11 */ sy) is used on the second and subsequent packets * to a single host, because TCP often wants to transmit multiple * buffers in a row, * and if they are all going to the same place, the second and * subsequent ones may be lost due to receivesys/vaxif/if_vv.c 444 0 12 63300 3671425404 7265 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_vv.c 7.1 (Berkeley) 6/5/86 */ #include "vv.h" #if NVV > 0 /* * Proteon proNET-10 and proNET-80 token ring driver. * The name of this device driver derives from the old MIT * name of V2LNI for the proNET hardware, would would abbreviate * to "v2", but this won't work right. Thus the name is "vv". * * This driver is compatible with the proNET 10 meagbit and * 80 megabit token ring interfaces (models p1000 and p1080). * A unit may be marked as 80 megabit using "flags 1" in the * config file. * * TRAILERS: This driver has a new implementation of trailers that * is at least a tolerable neighbor on the ring. The offset is not * stored in the protocol type, but instead only in the vh_info * field. Also, the vh_info field, and the two shorts before the * trailing header, are in network byte order, not VAX byte order. * * Of course, nothing but BSD UNIX supports trailers on ProNET. * If you need interoperability with anything else, turn off * trailers using the -trailers option to /etc/ifconfig! * * HARDWARE COMPATABILITY: This driver prefers that the HSBU (p1001) * have a serial number >= 040, which is about March, 1982. Older * HSBUs do not carry across 64kbyte boundaries. They can be supported * by adding "| UBA_NEED16" to the vs_ifuba.ifu_flags initialization * in vvattach(). * * The old warning about use without Wire Centers applies only to CTL * (p1002) cards with serial <= 057, which have not received ECO 176-743, * which was implemented in March, 1982. Most such CTLs have received * this ECO. */ #include "../machine/pte.h" #include "param.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "protosw.h" #include "socket.h" #include "vmmac.h" #include "errno.h" #include "ioctl.h" #include "../net/if.h" #include "../net/netisr.h" #include "../net/route.h" #ifdef INET #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netinet/in_var.h" #include "../netinet/ip.h" #endif #include "../vax/cpu.h" #include "../vax/mtpr.h" #include "if_vv.h" #include "if_uba.h" #include "../vaxuba/ubareg.h" #include "../vaxuba/ubavar.h" /* * maximum transmission unit definition -- * you can set VVMTU at anything from 576 to 2024. * 1536 is a popular "large" value, because it is a multiple * of 512, which the trailer scheme likes. * The absolute maximum size is 2024, which is enforced. */ #define VVMTU (1536) #define VVMRU (VVMTU + 16) #define VVBUFSIZE (VVMRU + sizeof(struct vv_header)) #if VVMTU>2024 #undef VVMTU #undef VVMRU #undef VVBUFSIZE #define VVBUFSIZE (2046) #define VVMRU (VVBUFSIZE - sizeof (struct vv_header)) #define VVMTU (VVMRU - 16) #endif /* * debugging and tracing stuff */ int vv_tracehdr = 0; /* 1 => trace headers (slowly!!) */ #define vvtracehdr if (vv_tracehdr) vvprt_hdr #define vvprintf if (vs->vs_if.if_flags & IFF_DEBUG) printf /* * externals, types, etc. */ int vvprobe(), vvattach(), vvreset(), vvinit(); int vvidentify(), vvstart(), vvxint(), vvwatchdog(); int vvrint(), vvoutput(), vvioctl(); struct uba_device *vvinfo[NVV]; u_short vvstd[] = { 0 }; struct uba_driver vvdriver = { vvprobe, 0, vvattach, 0, vvstd, "vv", vvinfo }; #define VVUNIT(x) minor(x) #define LOOPBACK /* use loopback for packets meant for us */ #ifdef LOOPBACK extern struct ifnet loif; #endif /* * Software status of each interface. * * Each interface is referenced by a network interface structure, * vs_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... * We also have, for each interface, a UBA interface structure, which * contains information about the UNIBUS resources held by the interface: * map registers, buffered data paths, etc. Information is cached in this * structure for use by the if_uba.c routines in running the interface * efficiently. */ struct vv_softc { struct ifnet vs_if; /* network-visible interface */ struct ifuba vs_ifuba; /* UNIBUS resources */ u_short vs_host; /* this interface address */ short vs_oactive; /* is output active */ short vs_is80; /* is 80 megabit version */ short vs_olen; /* length of last output */ u_short vs_lastx; /* address of last packet sent */ u_short vs_lastr; /* address of last packet received */ short vs_tries; /* transmit current retry count */ short vs_init; /* number of ring inits */ short vs_refused; /* number of packets refused */ short vs_timeouts; /* number of transmit timeouts */ short vs_otimeout; /* number of output timeouts */ short vs_ibadf; /* number of input bad formats */ short vs_parity; /* number of parity errors on 10 meg, */ /* link data errors on 80 meg */ } vv_softc[NVV]; #define NOHOST 0xffff /* illegal host number */ /* * probe the interface to see that the registers exist, and then * cause an interrupt to find its vector */ vvprobe(reg) caddr_t reg; { register int br, cvec; register struct vvreg *addr; #ifdef lint br = 0; cvec = br; br = cvec; #endif addr = (struct vvreg *)reg; /* reset interface, enable, and wait till dust settles */ addr->vvicsr = VV_RST; addr->vvocsr = VV_RST; DELAY(100000); /* generate interrupt by doing 1 word DMA from 0 in uba space!! */ addr->vvoba = 0; /* low 16 bits */ addr->vvoea = 0; /* extended bits */ addr->vvowc = -1; /* for 1 word */ addr->vvocsr = VV_IEN | VV_DEN; /* start the DMA, with interrupt */ DELAY(100000); addr->vvocsr = VV_RST; /* clear out the CSR */ if (cvec && cvec != 0x200) cvec -= 4; /* backup so vector => receive */ return(1); } /* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */ vvattach(ui) struct uba_device *ui; { register struct vv_softc *vs; vs = &vv_softc[ui->ui_unit]; vs->vs_if.if_unit = ui->ui_unit; vs->vs_if.if_name = "vv"; vs->vs_if.if_mtu = VVMTU; vs->vs_if.if_flags = IFF_BROADCAST; vs->vs_if.if_init = vvinit; vs->vs_if.if_ioctl = vvioctl; vs->vs_if.if_output = vvoutput; vs->vs_if.if_reset = vvreset; vs->vs_if.if_timer = 0; vs->vs_if.if_watchdog = vvwatchdog; vs->vs_ifuba.ifu_flags = UBA_CANTWAIT | UBA_NEEDBDP; /* use flag to determine if this is proNET-80 */ vs->vs_is80 = (short)(ui->ui_flags & 01); #if defined(VAX750) /* don't chew up 750 bdp's */ if (cpu == VAX_750 && ui->ui_unit > 0) vs->vs_ifuba.ifu_flags &= ~UBA_NEEDBDP; #endif if_attach(&vs->vs_if); } /* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */ vvreset(unit, uban) int unit, uban; { register struct uba_device *ui; if (unit >= NVV || (ui = vvinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" vv%d", unit); vvinit(unit); } /* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */ vvinit(unit) int unit; { register struct vv_softc *vs; register struct uba_device *ui; register struct vvreg *addr; register int ubainfo, s; vs = &vv_softc[unit]; ui = vvinfo[unit]; if (vs->vs_if.if_addrlist == (struct ifaddr *)0) return; addr = (struct vvreg *)ui->ui_addr; if (if_ubainit(&vs->vs_ifuba, ui->ui_ubanum, sizeof (struct vv_header), (int)btoc(VVMTU)) == 0) { printf("vv%d: can't initialize, if_ubainit() failed\n", unit); vs->vs_if.if_flags &= ~IFF_UP; return; } /* * Now that the uba is set up, figure out our address and * update complete our host address. */ if ((vs->vs_host = vvidentify(unit)) == NOHOST) { vs->vs_if.if_flags &= ~IFF_UP; return; } printf("vv%d: host %u\n", unit, vs->vs_host); /* * Reset the interface, and stay in the ring */ addr->vvocsr = VV_RST; /* take over output */ addr->vvocsr = VV_CPB; /* clear packet buffer */ addr->vvicsr = VV_RST | VV_HEN; /* take over input, */ /* keep relay closed */ DELAY(500000); /* let contacts settle */ vs->vs_init = 0; /* clear counters, etc. */ vs->vs_refused = 0; vs->vs_timeouts = 0; vs->vs_otimeout = 0; vs->vs_ibadf = 0; vs->vs_parity = 0; vs->vs_lastx = 256; /* an invalid address */ vs->vs_lastr = 256; /* an invalid address */ /* * Hang a receive and start any * pending writes by faking a transmit complete. */ s = splimp(); ubainfo = vs->vs_ifuba.ifu_r.ifrw_info; addr->vviba = (u_short)ubainfo; addr->vviea = (u_short)(ubainfo >> 16); addr->vviwc = -(VVBUFSIZE) >> 1; addr->vvicsr = VV_IEN | VV_HEN | VV_DEN | VV_ENB; vs->vs_oactive = 1; vs->vs_if.if_flags |= IFF_RUNNING; vvxint(unit); splx(s); } /* * Do a moderately thorough self-test in all three modes. Mostly * to keeps defective nodes off the ring, rather than to be especially * thorough. The key issue is to detect any cable breaks before joining * the ring. Return our node address on success, return -1 on failure. * */ /* the three self-test modes */ static u_short vv_modes[] = { VV_STE|VV_LPB, /* digital loopback */ VV_STE, /* analog loopback */ VV_HEN /* network mode */ }; vvidentify(unit) int unit; { register struct vv_softc *vs; register struct uba_device *ui; register struct vvreg *addr; register struct mbuf *m; register struct vv_header *v; register int ubainfo; register int i, successes, failures, waitcount; u_short shost = NOHOST; vs = &vv_softc[unit]; ui = vvinfo[unit]; addr = (struct vvreg *)ui->ui_addr; /* * Build a multicast message to identify our address * We need do this only once, since nobody else is about to use * the intermediate transmit buffer (ifu_w.ifrw_addr) that * if_ubainit() aquired for us. */ m = m_get(M_DONTWAIT, MT_HEADER); if (m == NULL) { printf("vv%d: can't initialize, m_get() failed\n", unit); return (0); } m->m_next = 0; m->m_off = MMINOFF; m->m_len = sizeof(struct vv_header); v = mtod(m, struct vv_header *); v->vh_dhost = VV_BROADCAST; /* multicast destination address */ v->vh_shost = 0; /* will be overwritten with ours */ v->vh_version = RING_VERSION; v->vh_type = RING_DIAGNOSTICS; v->vh_info = 0; /* map xmit message into uba, copying to intermediate buffer */ vs->vs_olen = if_wubaput(&vs->vs_ifuba, m); /* * For each of the modes (digital, analog, network), go through * a self-test that requires me to send VVIDENTSUCC good packets * in VVIDENTRETRY attempts. Use broadcast destination to find out * who I am, then use this as my address to check my address match * logic. Only data checked is the vh_type field. */ for (i = 0; i < 3; i++) { successes = 0; /* clear successes for this mode */ failures = 0; /* and clear failures, too */ /* take over device, and leave ring */ addr->vvicsr = VV_RST; addr->vvocsr = VV_RST; addr->vvicsr = vv_modes[i]; /* test mode */ /* * let the flag and token timers pop so that the init ring bit * will be allowed to work, by waiting about 1 second */ DELAY(1000000L); /* * retry loop */ while ((successes < VVIDENTSUCC) && (failures < VVIDENTRETRY)) { /* start a receive */ ubainfo = vs->vs_ifuba.ifu_r.ifrw_info; addr->vvicsr = VV_RST | vv_modes[i]; /* abort last */ addr->vviba = (u_short) ubainfo; addr->vviea = (u_short) (ubainfo >> 16); addr->vviwc = -(VVBUFSIZE) >> 1; addr->vvicsr = vv_modes[i] | VV_DEN | VV_ENB; /* purge stale data from BDP */ if (vs->vs_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(vs->vs_ifuba.ifu_uba, vs->vs_ifuba.ifu_w.ifrw_bdp); /* do a transmit */ ubainfo = vs->vs_ifuba.ifu_w.ifrw_info; addr->vvocsr = VV_RST; /* abort last try */ addr->vvoba = (u_short) ubainfo; addr->vvoea = (u_short) (ubainfo >> 16); addr->vvowc = -((vs->vs_olen + 1) >> 1); addr->vvocsr = VV_CPB | VV_DEN | VV_INR | VV_ENB; /* poll receive side for completion */ DELAY(10000); /* give it a chance */ for (waitcount = 0; waitcount < 10; waitcount++) { if (addr->vvicsr & VV_RDY) goto gotit; DELAY(1000); } failures++; /* no luck */ continue; gotit: /* we got something--is it any good? */ if ((addr->vvicsr & (VVRERR|VV_LDE)) || (addr->vvocsr & (VVXERR|VV_RFS))) { failures++; continue; } /* Purge BDP before looking at received packet */ if (vs->vs_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(vs->vs_ifuba.ifu_uba, vs->vs_ifuba.ifu_r.ifrw_bdp); m = if_rubaget(&vs->vs_ifuba, sizeof(struct vv_header), 0, &vs->vs_if); if (m != NULL) m_freem(m); v = (struct vv_header *)(vs->vs_ifuba.ifu_r.ifrw_addr); /* check message type, catch our node address */ if ((v->vh_type & 0xff) == RING_DIAGNOSTICS) { if (shost == NOHOST) { shost = v->vh_shost & 0xff; /* send to ourself now */ ((struct vv_header *) (vs->vs_ifuba.ifu_r.ifrw_addr)) ->vh_dhost = shost; } successes++; } else { failures++; } v->vh_type = 0; /* clear to check again */ } if (failures >= VVIDENTRETRY) { printf("vv%d: failed self-test after %d tries \ in %s mode\n", unit, VVIDENTRETRY, i == 0 ? "digital loopback" : (i == 1 ? "analog loopback" : "network")); printf("vv%d: icsr = %b, ocsr = %b\n", unit, 0xffff & addr->vvicsr, VV_IBITS, 0xffff & addr->vvocsr, VV_OBITS); addr->vvicsr = VV_RST; /* kill the sick board */ addr->vvocsr = VV_RST; shost = NOHOST; goto done; } } done: /* deallocate mbuf used for send packet (won't be one, anyways) */ if (vs->vs_ifuba.ifu_xtofree) { m_freem(vs->vs_ifuba.ifu_xtofree); vs->vs_ifuba.ifu_xtofree = 0; } return(shost); } /* * Start or restart output on interface. * If interface is active, this is a retransmit, so just * restuff registers and go. * If interface is not already active, get another datagram * to send off of the interface queue, and map it to the interface * before starting the output. */ vvstart(dev) dev_t dev; { register struct uba_device *ui; register struct vv_softc *vs; register struct vvreg *addr; register struct mbuf *m; register int unit, ubainfo, dest, s; unit = VVUNIT(dev); ui = vvinfo[unit]; vs = &vv_softc[unit]; if (vs->vs_oactive) goto restart; /* * Not already active: dequeue another request * and map it to the UNIBUS. If no more requests, * just return. */ s = splimp(); IF_DEQUEUE(&vs->vs_if.if_snd, m); splx(s); if (m == NULL) { vs->vs_oactive = 0; return; } dest = mtod(m, struct vv_header *)->vh_dhost; vs->vs_olen = if_wubaput(&vs->vs_ifuba, m); vs->vs_lastx = dest; restart: /* * Have request mapped to UNIBUS for transmission. * Purge any stale data from this BDP, and start the output. * * Make sure this packet will fit in the interface. */ if (vs->vs_olen > VVBUFSIZE) { printf("vv%d vs_olen: %d > VVBUFSIZE\n", unit, vs->vs_olen); panic("vvdriver vs_olen botch"); } vs->vs_if.if_timer = VVTIMEOUT; vs->vs_oactive = 1; /* ship it */ if (vs->vs_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(vs->vs_ifuba.ifu_uba, vs->vs_ifuba.ifu_w.ifrw_bdp); addr = (struct vvreg *)ui->ui_addr; ubainfo = vs->vs_ifuba.ifu_w.ifrw_info; addr->vvoba = (u_short) ubainfo; addr->vvoea = (u_short) (ubainfo >> 16); addr->vvowc = -((vs->vs_olen + 1) >> 1); addr->vvowc = -((vs->vs_olen + 1) >> 1); /* extra byte is garbage */ if (addr->vvocsr & VV_NOK) vs->vs_init++; /* count ring inits */ addr->vvocsr = VV_IEN | VV_CPB | VV_DEN | VV_INR | VV_ENB; } /* * proNET transmit interrupt * Start another output if more data to send. */ vvxint(unit) int unit; { register struct uba_device *ui; register struct vv_softc *vs; register struct vvreg *addr; register int oc; ui = vvinfo[unit]; vs = &vv_softc[unit]; vs->vs_if.if_timer = 0; addr = (struct vvreg *)ui->ui_addr; oc = 0xffff & (addr->vvocsr); if (vs->vs_oactive == 0) { vvprintf("vv%d: stray interrupt vvocsr = %b\n", unit, oc, VV_OBITS); return; } /* * we retransmit on soft error * TODO: sort retransmits to end of queue if possible! */ if (oc & (VV_OPT | VV_RFS)) { if (vs->vs_tries++ < VVRETRY) { if (oc & VV_OPT) vs->vs_otimeout++; if (oc & VV_RFS) { vs->vs_if.if_collisions++; vs->vs_refused++; } vvstart(unit); /* restart this message */ return; } } vs->vs_if.if_opackets++; vs->vs_oactive = 0; vs->vs_tries = 0; if (oc & VVXERR) { vs->vs_if.if_oerrors++; vvprintf("vv%d: error vvocsr = %b\n", unit, 0xffff & oc, VV_OBITS); } if (vs->vs_ifuba.ifu_xtofree) { m_freem(vs->vs_ifuba.ifu_xtofree); vs->vs_ifuba.ifu_xtofree = 0; } vvstart(unit); } /* * Transmit watchdog timer routine. * This routine gets called when we lose a transmit interrupt. * The best we can do is try to restart output. */ vvwatchdog(unit) int unit; { register struct vv_softc *vs; register int s; vs = &vv_softc[unit]; vvprintf("vv%d: lost a transmit interrupt.\n", unit); vs->vs_timeouts++; s = splimp(); vvstart(unit); splx(s); } /* * proNET interface receiver interrupt. * If input error just drop packet. * Otherwise purge input buffered data path and examine * packet to determine type. If can't determine length * from type, then have to drop packet. Otherwise decapsulate * packet based on type and pass to type specific higher-level * input routine. */ vvrint(unit) int unit; { register struct vv_softc *vs; register struct vvreg *addr; register struct vv_header *vv; register struct ifqueue *inq; register struct mbuf *m; int ubainfo, len, off, s; short resid; vs = &vv_softc[unit]; vs->vs_if.if_ipackets++; addr = (struct vvreg *)vvinfo[unit]->ui_addr; /* * Purge BDP */ if (vs->vs_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(vs->vs_ifuba.ifu_uba, vs->vs_ifuba.ifu_r.ifrw_bdp); /* * receive errors? */ if (addr->vvicsr & VVRERR) { vvprintf("vv%d: receive error, vvicsr = %b\n", unit, 0xffff&(addr->vvicsr), VV_IBITS); if (addr->vvicsr & VV_BDF) vs->vs_ibadf++; goto dropit; } /* * parity errors? */ if (addr->vvicsr & VV_LDE) { /* we don't have to clear it because the receive command */ /* writes 0 to parity bit */ vs->vs_parity++; /* * only on 10 megabit proNET is VV_LDE an end-to-end parity * bit. On 80 megabit, it returns to the intended use of * node-to-node parity. End-to-end parity errors on 80 megabit * give VV_BDF. */ if (vs->vs_is80 == 0) goto dropit; } /* * Get packet length from residual word count * * Compute header offset if trailer protocol * * Pull packet off interface. Off is nonzero if packet * has trailing header; if_rubaget will then force this header * information to be at the front. The vh_info field * carries the offset to the trailer data in trailer * format packets. */ vv = (struct vv_header *)(vs->vs_ifuba.ifu_r.ifrw_addr); vvtracehdr("vi", vv); resid = addr->vviwc & 01777; /* only low 10 bits valid */ if (resid) resid |= 0176000; /* high 6 bits are undefined */ len = ((VVBUFSIZE >> 1) + resid) << 1; len -= sizeof(struct vv_header); if ((addr->vvicsr & VV_DPR) || len > VVMRU || len <= 0) { vvprintf("vv%d: len too long or short, \ len = %d, vvicsr = %b\n", unit, len, 0xffff&(addr->vvicsr), VV_IBITS); goto dropit; } /* check the protocol header version */ if (vv->vh_version != RING_VERSION) { vvprintf("vv%d: bad protocol header version %d\n", unit, vv->vh_version & 0xff); goto dropit; } #define vvdataaddr(vv, off, type) ((type)(((caddr_t)((vv)+1)+(off)))) if (vv->vh_type == RING_TRAILER ) { off = ntohs((u_short)vv->vh_info); if (off > VVMTU) { vvprintf("vv%d: off > VVMTU, off = %d, vvicsr = %b\n", unit, off, 0xffff&(addr->vvicsr), VV_IBITS); goto dropit; } vv->vh_type = ntohs(*vvdataaddr(vv, off, u_short *)); resid = ntohs(*(vvdataaddr(vv, off+sizeof(u_short), u_short *))); if (off + resid > len) { vvprintf("vv%d: trailer packet too short\n", unit); vvprintf("vv%d: off = %d, resid = %d, vvicsr = %b\n", unit, off, resid, 0xffff&(addr->vvicsr), VV_IBITS); goto dropit; } len = off + resid; } else off = 0; if (len == 0) { vvprintf("vv%d: len is zero, vvicsr = %b\n", unit, 0xffff&(addr->vvicsr), VV_IBITS); goto dropit; } m = if_rubaget(&vs->vs_ifuba, len, off, &vs->vs_if); if (m == NULL) { vvprintf("vv%d: if_rubaget() failed, vvicsr = %b\n", unit, 0xffff&(addr->vvicsr), VV_IBITS); goto dropit; } if (off) { struct ifnet *ifp; ifp = *(mtod(m, struct ifnet **)); m->m_off += 2 * sizeof (u_short); m->m_len -= 2 * sizeof (u_short); *(mtod(m, struct ifnet **)) = ifp; } /* Keep track of source address of this packet */ vs->vs_lastr = vv->vh_shost; /* * Demultiplex on packet type */ switch (vv->vh_type) { #ifdef INET case RING_IP: schednetisr(NETISR_IP); inq = &ipintrq; break; #endif default: vvprintf("vv%d: unknown pkt type 0x%x\n", unit, vv->vh_type); m_freem(m); goto setup; } s = splimp(); if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); } else IF_ENQUEUE(inq, m); splx(s); /* * Reset for the next packet. */ setup: ubainfo = vs->vs_ifuba.ifu_r.ifrw_info; addr->vviba = (u_short) ubainfo; addr->vviea = (u_short) (ubainfo >> 16); addr->vviwc = -(VVBUFSIZE) >> 1; addr->vvicsr = VV_HEN | VV_IEN | VV_DEN | VV_ENB; return; /* * Drop packet on floor -- count them!! */ dropit: vs->vs_if.if_ierrors++; goto setup; } /* * proNET output routine. * Encapsulate a packet of type family for the local net. * Use trailer local net encapsulation if enough data in first * packet leaves a multiple of 512 bytes of data in remainder. */ vvoutput(ifp, m0, dst) struct ifnet *ifp; struct mbuf *m0; struct sockaddr *dst; { register struct mbuf *m; register struct vv_header *vv; register int off; register int unit; register struct vvreg *addr; register struct vv_softc *vs; register int s; int type, dest, error; m = m0; unit = ifp->if_unit; addr = (struct vvreg *)vvinfo[unit]->ui_addr; vs = &vv_softc[unit]; /* * Check to see if the input side has wedged due the UBA * vectoring through 0. * * We are lower than device ipl when we enter this routine, * so if the interface is ready with an input packet then * an input interrupt must have slipped through the cracks. * * Avoid the race with an input interrupt by watching to see * if any packets come in. */ s = vs->vs_if.if_ipackets; if (addr->vvicsr & VV_RDY && s == vs->vs_if.if_ipackets) { vvprintf("vv%d: lost a receive interrupt, icsr = %b\n", unit, 0xffff&(addr->vvicsr), VV_IBITS); s = splimp(); vvrint(unit); splx(s); } switch (dst->sa_family) { #ifdef INET case AF_INET: if (in_broadcast(((struct sockaddr_in *)dst)->sin_addr)) dest = VV_BROADCAST; else dest = in_lnaof(((struct sockaddr_in *)dst)->sin_addr); #ifdef LOOPBACK if (dest == vs->vs_host && (loif.if_flags & IFF_UP)) return (looutput(&loif, m0, dst)); #endif LOOPBACK if (dest >= 0x100) { error = EPERM; goto bad; } off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; /* * Trailerize, if the configuration allows it. * TODO: Need per host negotiation. */ if ((ifp->if_flags & IFF_NOTRAILERS) == 0) if (off > 0 && (off & 0x1ff) == 0 && m->m_off >= MMINOFF + 2 * sizeof (u_short)) { type = RING_TRAILER; m->m_off -= 2 * sizeof (u_short); m->m_len += 2 * sizeof (u_short); *mtod(m, u_short *) = htons((short)RING_IP); *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); goto gottrailertype; } type = RING_IP; off = 0; goto gottype; #endif default: printf("vv%d: can't handle af%d\n", unit, dst->sa_family); error = EAFNOSUPPORT; goto bad; } gottrailertype: /* * Packet to be sent as trailer: move first packet * (control information) to end of chain. */ while (m->m_next) m = m->m_next; m->m_next = m0; m = m0->m_next; m0->m_next = 0; m0 = m; gottype: /* * Add local net header. If no space in first mbuf, * allocate another. */ if (m->m_off > MMAXOFF || MMINOFF + sizeof (struct vv_header) > m->m_off) { m = m_get(M_DONTWAIT, MT_HEADER); if (m == NULL) { error = ENOBUFS; goto bad; } m->m_next = m0; m->m_off = MMINOFF; m->m_len = sizeof (struct vv_header); } else { m->m_off -= sizeof (struct vv_header); m->m_len += sizeof (struct vv_header); } vv = mtod(m, struct vv_header *); vv->vh_shost = vs->vs_host; vv->vh_dhost = dest; vv->vh_version = RING_VERSION; vv->vh_type = type; vv->vh_info = htons((u_short)off); vvtracehdr("vo", vv); /* * Queue message on interface, and start output if interface * not yet active. */ s = splimp(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); error = ENOBUFS; goto qfull; } IF_ENQUEUE(&ifp->if_snd, m); if (vs->vs_oactive == 0) vvstart(unit); splx(s); return (0); qfull: m0 = m; splx(s); bad: m_freem(m0); return(error); } /* * Process an ioctl request. */ vvioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { struct ifaddr *ifa = (struct ifaddr *) data; int s = splimp(), error = 0; switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; if ((ifp->if_flags & IFF_RUNNING) == 0) vvinit(ifp->if_unit); /* * Did self-test succeed? */ if ((ifp->if_flags & IFF_UP) == 0) error = ENETDOWN; /* * Attempt to check agreement of protocol address * and board address. */ switch (ifa->ifa_addr.sa_family) { case AF_INET: if (in_lnaof(IA_SIN(ifa)->sin_addr) != vv_softc[ifp->if_unit].vs_host) error = EADDRNOTAVAIL; break; } break; default: error = EINVAL; } splx(s); return (error); } /* * vvprt_hdr(s, v) print the local net header in "v" * with title is "s" */ vvprt_hdr(s, v) char *s; register struct vv_header *v; { printf("%s: dsvti: 0x%x 0x%x 0x%x 0x%x 0x%x\n", s, 0xff & (int)(v->vh_dhost), 0xff & (int)(v->vh_shost), 0xff & (int)(v->vh_version), 0xff & (int)(v->vh_type), 0xffff & (int)(v->vh_info)); } #endif NVV = %b\n", unit, oc, VV_OBITS); return; } /* * we retransmit on soft error * TODO: sort retransmits to end of queue if possible! */ if (oc & (VV_OPT | VV_RFS)) { if (vs->vs_tries++ < VVRETRY) { if (oc & VV_OPT) vs->vs_otimeout++; if (oc & VV_RFS) { vs->vs_if.if_collisions++; vs->vs_sys/vaxif/if_qe.c 444 0 12 66732 3671425204 7251 /* @(#)if_qe.c 7.1 (Berkeley) 6/5/86 */ /* from @(#)if_qe.c 1.15 (ULTRIX) 4/16/86 */ /**************************************************************** * * * Licensed from Digital Equipment Corporation * * Copyright (c) * * Digital Equipment Corporation * * Maynard, Massachusetts * * 1985, 1986 * * All rights reserved. * * * * The Information in this software is subject to change * * without notice and should not be construed as a commitment * * by Digital Equipment Corporation. Digital makes no * * representations about the suitability of this software for * * any purpose. It is supplied "As Is" without expressed or * * implied warranty. * * * * If the Regents of the University of California or its * * licensees modify the software in a manner creating * * derivative copyright rights, appropriate copyright * * legends may be placed on the derivative work in addition * * to that set forth above. * * * ****************************************************************/ /* --------------------------------------------------------------------- * Modification History * * 15-Apr-86 -- afd * Rename "unused_multi" to "qunused_multi" for extending Generic * kernel to MicroVAXen. * * 18-mar-86 -- jaw br/cvec changed to NOT use registers. * * 12 March 86 -- Jeff Chase * Modified to handle the new MCLGET macro * Changed if_qe_data.c to use more receive buffers * Added a flag to poke with adb to log qe_restarts on console * * 19 Oct 85 -- rjl * Changed the watch dog timer from 30 seconds to 3. VMS is using * less than 1 second in their's. Also turned the printf into an * mprintf. * * 09/16/85 -- Larry Cohen * Add 43bsd alpha tape changes for subnet routing * * 1 Aug 85 -- rjl * Panic on a non-existent memory interrupt and the case where a packet * was chained. The first should never happen because non-existant * memory interrupts cause a bus reset. The second should never happen * because we hang 2k input buffers on the device. * * 1 Aug 85 -- rich * Fixed the broadcast loopback code to handle Clusters without * wedging the system. * * 27 Feb. 85 -- ejf * Return default hardware address on ioctl request. * * 12 Feb. 85 -- ejf * Added internal extended loopback capability. * * 27 Dec. 84 -- rjl * Fixed bug that caused every other transmit descriptor to be used * instead of every descriptor. * * 21 Dec. 84 -- rjl * Added watchdog timer to mask hardware bug that causes device lockup. * * 18 Dec. 84 -- rjl * Reworked driver to use q-bus mapping routines. MicroVAX-I now does * copying instead of m-buf shuffleing. * A number of deficencies in the hardware/firmware were compensated * for. See comments in qestart and qerint. * * 14 Nov. 84 -- jf * Added usage counts for multicast addresses. * Updated general protocol support to allow access to the Ethernet * header. * * 04 Oct. 84 -- jf * Added support for new ioctls to add and delete multicast addresses * and set the physical address. * Add support for general protocols. * * 14 Aug. 84 -- rjl * Integrated Shannon changes. (allow arp above 1024 and ? ) * * 13 Feb. 84 -- rjl * * Initial version of driver. derived from IL driver. * * --------------------------------------------------------------------- */ #include "qe.h" #if NQE > 0 /* * Digital Q-BUS to NI Adapter */ #include "../machine/pte.h" #include "param.h" #include "systm.h" #include "mbuf.h" #include "buf.h" #include "protosw.h" #include "socket.h" #include "vmmac.h" #include "ioctl.h" #include "errno.h" #include "syslog.h" #include "time.h" #include "kernel.h" #include "../net/if.h" #include "../net/netisr.h" #include "../net/route.h" #ifdef INET #include "../netinet/in.h" #include "../netinet/in_systm.h" #include "../netinet/in_var.h" #include "../netinet/ip.h" #include "../netinet/if_ether.h" #endif #ifdef NS #include "../netns/ns.h" #include "../netns/ns_if.h" #endif #include "../vax/cpu.h" #include "../vax/mtpr.h" #include "if_qereg.h" #include "if_uba.h" #include "../vaxuba/ubareg.h" #include "../vaxuba/ubavar.h" #define NRCV 25 /* Receive descriptors */ #define NXMT 5 /* Transmit descriptors */ #define NTOT (NXMT + NRCV) /* * This constant should really be 60 because the qna adds 4 bytes of crc. * However when set to 60 our packets are ignored by deuna's , 3coms are * okay ?????????????????????????????????????????? */ #define MINDATA 64 /* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * is_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... */ struct qe_softc { struct arpcom is_ac; /* Ethernet common part */ #define is_if is_ac.ac_if /* network-visible interface */ #define is_addr is_ac.ac_enaddr /* hardware Ethernet address */ struct ifubinfo qe_uba; /* Q-bus resources */ struct ifrw qe_ifr[NRCV]; /* for receive buffers; */ struct ifxmt qe_ifw[NXMT]; /* for xmit buffers; */ int qe_flags; /* software state */ #define QEF_RUNNING 0x01 #define QEF_SETADDR 0x02 int setupaddr; /* mapping info for setup pkts */ struct qe_ring *rringaddr; /* mapping info for rings */ struct qe_ring *tringaddr; /* "" */ struct qe_ring rring[NRCV+1]; /* Receive ring descriptors */ struct qe_ring tring[NXMT+1]; /* Transmit ring descriptors */ u_char setup_pkt[16][8]; /* Setup packet */ int rindex; /* Receive index */ int tindex; /* Transmit index */ int otindex; /* Old transmit index */ int qe_intvec; /* Interrupt vector */ struct qedevice *addr; /* device addr */ int setupqueued; /* setup packet queued */ int nxmit; /* Transmits in progress */ int timeout; /* watchdog */ int qe_restarts; /* timeouts */ } qe_softc[NQE]; struct uba_device *qeinfo[NQE]; extern struct timeval time; extern timeout(); int qeprobe(), qeattach(), qeintr(), qewatch(); int qeinit(),qeoutput(),qeioctl(),qereset(),qewatch(); u_short qestd[] = { 0 }; struct uba_driver qedriver = { qeprobe, 0, qeattach, 0, qestd, "qe", qeinfo }; #define QE_TIMEO (15) #define QEUNIT(x) minor(x) static int mask = 0x3ffff; /* address mask */ int qewatchrun = 0; /* watchdog running */ /* * The deqna shouldn't receive more than ETHERMTU + sizeof(struct ether_header) * but will actually take in up to 2048 bytes. To guard against the receiver * chaining buffers (which we aren't prepared to handle) we allocate 2kb * size buffers. */ #define MAXPACKETSIZE 2048 /* Should really be ETHERMTU */ /* * Probe the QNA to see if it's there */ qeprobe(reg) caddr_t reg; { register int br, cvec; /* r11, r10 value-result */ register struct qedevice *addr = (struct qedevice *)reg; register struct qe_ring *rp; register struct qe_ring *prp; /* physical rp */ register int i, j; static int next=0; /* softc index */ register struct qe_softc *sc = &qe_softc[next++]; #ifdef lint br = 0; cvec = br; br = cvec; qeintr(0); #endif /* * Set the address mask for the particular cpu */ mask = 0x3ffff; /* * The QNA interrupts on i/o operations. To do an I/O operation * we have to setup the interface by transmitting a setup packet. */ addr->qe_csr = QE_RESET; addr->qe_vector = (uba_hd[numuba].uh_lastiv -= 4); /* * Map the communications area and the setup packet. */ sc->setupaddr = uballoc(0, (caddr_t)sc->setup_pkt, sizeof(sc->setup_pkt), 0); sc->rringaddr = (struct qe_ring *) uballoc(0, (caddr_t)sc->rring, sizeof(struct qe_ring) * (NTOT+2), 0); prp = (struct qe_ring *)((int)sc->rringaddr & mask); /* * The QNA will loop the setup packet back to the receive ring * for verification, therefore we initialize the first * receive & transmit ring descriptors and link the setup packet * to them. */ qeinitdesc(sc->tring, (caddr_t)(sc->setupaddr & mask), sizeof(sc->setup_pkt)); qeinitdesc(sc->rring, (caddr_t)(sc->setupaddr & mask), sizeof(sc->setup_pkt)); rp = (struct qe_ring *)sc->tring; rp->qe_setup = 1; rp->qe_eomsg = 1; rp->qe_flag = rp->qe_status1 = QE_NOTYET; rp->qe_valid = 1; rp = (struct qe_ring *)sc->rring; rp->qe_flag = rp->qe_status1 = QE_NOTYET; rp->qe_valid = 1; /* * Get the addr off of the interface and place it into the setup * packet. This code looks strange due to the fact that the address * is placed in the setup packet in col. major order. */ for( i = 0 ; i < 6 ; i++ ) sc->setup_pkt[i][1] = addr->qe_sta_addr[i]; qesetup( sc ); /* * Start the interface and wait for the packet. */ j = cvec; addr->qe_csr = QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT; addr->qe_rcvlist_lo = (short)prp; addr->qe_rcvlist_hi = (short)((int)prp >> 16); prp += NRCV+1; addr->qe_xmtlist_lo = (short)prp; addr->qe_xmtlist_hi = (short)((int)prp >> 16); DELAY(10000); /* * All done with the bus resources. */ ubarelse(0, &sc->setupaddr); ubarelse(0, (int *)&sc->rringaddr); if( cvec == j ) return 0; /* didn't interrupt */ return( sizeof(struct qedevice) ); } /* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */ qeattach(ui) struct uba_device *ui; { register struct qe_softc *sc = &qe_softc[ui->ui_unit]; register struct ifnet *ifp = &sc->is_if; register struct qedevice *addr = (struct qedevice *)ui->ui_addr; register int i; ifp->if_unit = ui->ui_unit; ifp->if_name = "qe"; ifp->if_mtu = ETHERMTU; ifp->if_flags = IFF_BROADCAST; /* * Read the address from the prom and save it. */ for( i=0 ; i<6 ; i++ ) sc->setup_pkt[i][1] = sc->is_addr[i] = addr->qe_sta_addr[i] & 0xff; /* * Save the vector for initialization at reset time. */ sc->qe_intvec = addr->qe_vector; ifp->if_init = qeinit; ifp->if_output = qeoutput; ifp->if_ioctl = qeioctl; ifp->if_reset = qereset; sc->qe_uba.iff_flags = UBA_CANTWAIT; if_attach(ifp); } /* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */ qereset(unit, uban) int unit, uban; { register struct uba_device *ui; if (unit >= NQE || (ui = qeinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" qe%d", unit); qe_softc[unit].is_if.if_flags &= ~IFF_RUNNING; qeinit(unit); } /* * Initialization of interface. */ qeinit(unit) int unit; { register struct qe_softc *sc = &qe_softc[unit]; register struct uba_device *ui = qeinfo[unit]; register struct qedevice *addr = (struct qedevice *)ui->ui_addr; register struct ifnet *ifp = &sc->is_if; register i; int s; /* address not known */ if (ifp->if_addrlist == (struct ifaddr *)0) return; if (sc->qe_flags & QEF_RUNNING) return; if ((ifp->if_flags & IFF_RUNNING) == 0) { /* * map the communications area onto the device */ sc->rringaddr = (struct qe_ring *) ((int) uballoc(0, (caddr_t)sc->rring, sizeof(struct qe_ring) * (NTOT+2), 0) & mask); sc->tringaddr = sc->rringaddr + NRCV + 1; sc->setupaddr = uballoc(0, (caddr_t)sc->setup_pkt, sizeof(sc->setup_pkt), 0) & mask; /* * init buffers and maps */ if (if_ubaminit(&sc->qe_uba, ui->ui_ubanum, sizeof (struct ether_header), (int)btoc(MAXPACKETSIZE), sc->qe_ifr, NRCV, sc->qe_ifw, NXMT) == 0) { printf("qe%d: can't initialize\n", unit); sc->is_if.if_flags &= ~IFF_UP; return; } } /* * Init the buffer descriptors and indexes for each of the lists and * loop them back to form a ring. */ for (i = 0; i < NRCV; i++) { qeinitdesc( &sc->rring[i], (caddr_t)(sc->qe_ifr[i].ifrw_info & mask), MAXPACKETSIZE); sc->rring[i].qe_flag = sc->rring[i].qe_status1 = QE_NOTYET; sc->rring[i].qe_valid = 1; } qeinitdesc(&sc->rring[i], (caddr_t)NULL, 0); sc->rring[i].qe_addr_lo = (short)sc->rringaddr; sc->rring[i].qe_addr_hi = (short)((int)sc->rringaddr >> 16); sc->rring[i].qe_chain = 1; sc->rring[i].qe_flag = sc->rring[i].qe_status1 = QE_NOTYET; sc->rring[i].qe_valid = 1; for( i = 0 ; i <= NXMT ; i++ ) qeinitdesc(&sc->tring[i], (caddr_t)NULL, 0); i--; sc->tring[i].qe_addr_lo = (short)sc->tringaddr; sc->tring[i].qe_addr_hi = (short)((int)sc->tringaddr >> 16); sc->tring[i].qe_chain = 1; sc->tring[i].qe_flag = sc->tring[i].qe_status1 = QE_NOTYET; sc->tring[i].qe_valid = 1; sc->nxmit = sc->otindex = sc->tindex = sc->rindex = 0; /* * Take the interface out of reset, program the vector, * enable interrupts, and tell the world we are up. */ s = splimp(); addr->qe_vector = sc->qe_intvec; sc->addr = addr; addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT | QE_ILOOP; addr->qe_rcvlist_lo = (short)sc->rringaddr; addr->qe_rcvlist_hi = (short)((int)sc->rringaddr >> 16); ifp->if_flags |= IFF_UP | IFF_RUNNING; sc->qe_flags |= QEF_RUNNING; qesetup( sc ); qestart( unit ); splx( s ); } /* * Start output on interface. * */ qestart(dev) dev_t dev; { int unit = QEUNIT(dev); struct uba_device *ui = qeinfo[unit]; register struct qe_softc *sc = &qe_softc[unit]; register struct qedevice *addr; register struct qe_ring *rp; register index; struct mbuf *m; int buf_addr, len, s; s = splimp(); addr = (struct qedevice *)ui->ui_addr; /* * The deqna doesn't look at anything but the valid bit * to determine if it should transmit this packet. If you have * a ring and fill it the device will loop indefinately on the * packet and continue to flood the net with packets until you * break the ring. For this reason we never queue more than n-1 * packets in the transmit ring. * * The microcoders should have obeyed their own defination of the * flag and status words, but instead we have to compensate. */ for( index = sc->tindex; sc->tring[index].qe_valid == 0 && sc->nxmit < (NXMT-1) ; sc->tindex = index = ++index % NXMT){ rp = &sc->tring[index]; if( sc->setupqueued ) { buf_addr = sc->setupaddr; len = 128; rp->qe_setup = 1; sc->setupqueued = 0; } else { IF_DEQUEUE(&sc->is_if.if_snd, m); if( m == 0 ){ splx(s); return; } buf_addr = sc->qe_ifw[index].ifw_info; len = if_ubaput(&sc->qe_uba, &sc->qe_ifw[index], m); } /* * Does buffer end on odd byte ? */ if( len & 1 ) { len++; rp->qe_odd_end = 1; } if( len < MINDATA ) len = MINDATA; rp->qe_buf_len = -(len/2); buf_addr &= mask; rp->qe_flag = rp->qe_status1 = QE_NOTYET; rp->qe_addr_lo = (short)buf_addr; rp->qe_addr_hi = (short)(buf_addr >> 16); rp->qe_eomsg = 1; rp->qe_flag = rp->qe_status1 = QE_NOTYET; rp->qe_valid = 1; sc->nxmit++; /* * If the watchdog time isn't running kick it. */ sc->timeout=1; if (qewatchrun == 0) { qewatchrun++; timeout(qewatch, (caddr_t)0, QE_TIMEO); } /* * See if the xmit list is invalid. */ if( addr->qe_csr & QE_XL_INVALID ) { buf_addr = (int)(sc->tringaddr+index); addr->qe_xmtlist_lo = (short)buf_addr; addr->qe_xmtlist_hi = (short)(buf_addr >> 16); } } splx( s ); } /* * Ethernet interface interrupt processor */ qeintr(unit) int unit; { register struct qe_softc *sc = &qe_softc[unit]; struct qedevice *addr = (struct qedevice *)qeinfo[unit]->ui_addr; int s, buf_addr, csr; s = splimp(); csr = addr->qe_csr; addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT | QE_ILOOP; if( csr & QE_RCV_INT ) qerint( unit ); if( csr & QE_XMIT_INT ) qetint( unit ); if( csr & QE_NEX_MEM_INT ) panic("qe: Non existant memory interrupt"); if( addr->qe_csr & QE_RL_INVALID && sc->rring[sc->rindex].qe_status1 == QE_NOTYET ) { buf_addr = (int)&sc->rringaddr[sc->rindex]; addr->qe_rcvlist_lo = (short)buf_addr; addr->qe_rcvlist_hi = (short)(buf_addr >> 16); } splx( s ); } /* * Ethernet interface transmit interrupt. */ qetint(unit) int unit; { register struct qe_softc *sc = &qe_softc[unit]; register struct qe_ring *rp; register struct ifxmt *ifxp; int status1, setupflag; short len; while( sc->otindex != sc->tindex && sc->tring[sc->otindex].qe_status1 != QE_NOTYET && sc->nxmit > 0 ) { /* * Save the status words from the descriptor so that it can * be released. */ rp = &sc->tring[sc->otindex]; status1 = rp->qe_status1; setupflag = rp->qe_setup; len = (-rp->qe_buf_len) * 2; if( rp->qe_odd_end ) len++; /* * Init the buffer descriptor */ bzero((caddr_t)rp, sizeof(struct qe_ring)); if( --sc->nxmit == 0 ) sc->timeout = 0; if( !setupflag ) { /* * Do some statistics. */ sc->is_if.if_opackets++; sc->is_if.if_collisions += ( status1 & QE_CCNT ) >> 4; if (status1 & QE_ERROR) sc->is_if.if_oerrors++; /* * If this was a broadcast packet loop it * back because the hardware can't hear its own * transmits. */ ifxp = &sc->qe_ifw[sc->otindex]; if (bcmp((caddr_t)ifxp->ifw_addr, (caddr_t)etherbroadcastaddr, sizeof(etherbroadcastaddr)) == 0) qeread(sc, &ifxp->ifrw, len); if (ifxp->ifw_xtofree) { m_freem(ifxp->ifw_xtofree); ifxp->ifw_xtofree = 0; } } sc->otindex = ++sc->otindex % NXMT; } qestart( unit ); } /* * Ethernet interface receiver interrupt. * If can't determine length from type, then have to drop packet. * Othewise decapsulate packet based on type and pass to type specific * higher-level input routine. */ qerint(unit) int unit; { register struct qe_softc *sc = &qe_softc[unit]; register struct qe_ring *rp; int len, status1, status2; int bufaddr; /* * Traverse the receive ring looking for packets to pass back. * The search is complete when we find a descriptor not in use. * * As in the transmit case the deqna doesn't honor it's own protocols * so there exists the possibility that the device can beat us around * the ring. The proper way to guard against this is to insure that * there is always at least one invalid descriptor. We chose instead * to make the ring large enough to minimize the problem. With a ring * size of 4 we haven't been able to see the problem. To be safe we * doubled that to 8. * */ for( ; sc->rring[sc->rindex].qe_status1 != QE_NOTYET ; sc->rindex = ++sc->rindex % NRCV ){ rp = &sc->rring[sc->rindex]; status1 = rp->qe_status1; status2 = rp->qe_status2; bzero((caddr_t)rp, sizeof(struct qe_ring)); if( (status1 & QE_MASK) == QE_MASK ) panic("qe: chained packet"); len = ((status1 & QE_RBL_HI) | (status2 & QE_RBL_LO)) + 60; sc->is_if.if_ipackets++; if (status1 & QE_ERROR) sc->is_if.if_ierrors++; else { /* * We don't process setup packets. */ if( !(status1 & QE_ESETUP) ) qeread(sc, &sc->qe_ifr[sc->rindex], len - sizeof(struct ether_header)); } /* * Return the buffer to the ring */ bufaddr = (int)sc->qe_ifr[sc->rindex].ifrw_info & mask; rp->qe_buf_len = -((MAXPACKETSIZE)/2); rp->qe_addr_lo = (short)bufaddr; rp->qe_addr_hi = (short)((int)bufaddr >> 16); rp->qe_flag = rp->qe_status1 = QE_NOTYET; rp->qe_valid = 1; } } /* * Ethernet output routine. * Encapsulate a packet of type family for the local net. * Use trailer local net encapsulation if enough data in first * packet leaves a multiple of 512 bytes of data in remainder. */ qeoutput(ifp, m0, dst) struct ifnet *ifp; struct mbuf *m0; struct sockaddr *dst; { int type, s, error; u_char edst[6]; struct in_addr idst; register struct qe_softc *is = &qe_softc[ifp->if_unit]; register struct mbuf *m = m0; register struct ether_header *eh; register int off; int usetrailers; if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { error = ENETDOWN; goto bad; } switch (dst->sa_family) { #ifdef INET case AF_INET: idst = ((struct sockaddr_in *)dst)->sin_addr; if (!arpresolve(&is->is_ac, m, &idst, edst, &usetrailers)) return (0); /* if not yet resolved */ off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; if (usetrailers && off > 0 && (off & 0x1ff) == 0 && m->m_off >= MMINOFF + 2 * sizeof (u_short)) { type = ETHERTYPE_TRAIL + (off>>9); m->m_off -= 2 * sizeof (u_short); m->m_len += 2 * sizeof (u_short); *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); goto gottrailertype; } type = ETHERTYPE_IP; off = 0; goto gottype; #endif #ifdef NS case AF_NS: type = ETHERTYPE_NS; bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), (caddr_t)edst, sizeof (edst)); off = 0; goto gottype; #endif case AF_UNSPEC: eh = (struct ether_header *)dst->sa_data; bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); type = eh->ether_type; goto gottype; default: printf("qe%d: can't handle af%d\n", ifp->if_unit, dst->sa_family); error = EAFNOSUPPORT; goto bad; } gottrailertype: /* * Packet to be sent as trailer: move first packet * (control information) to end of chain. */ while (m->m_next) m = m->m_next; m->m_next = m0; m = m0->m_next; m0->m_next = 0; m0 = m; gottype: /* * Add local net header. If no space in first mbuf, * allocate another. */ if (m->m_off > MMAXOFF || MMINOFF + sizeof (struct ether_header) > m->m_off) { m = m_get(M_DONTWAIT, MT_HEADER); if (m == 0) { error = ENOBUFS; goto bad; } m->m_next = m0; m->m_off = MMINOFF; m->m_len = sizeof (struct ether_header); } else { m->m_off -= sizeof (struct ether_header); m->m_len += sizeof (struct ether_header); } eh = mtod(m, struct ether_header *); eh->ether_type = htons((u_short)type); bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); bcopy((caddr_t)is->is_addr, (caddr_t)eh->ether_shost, sizeof (is->is_addr)); /* * Queue message on interface, and start output if interface * not yet active. */ s = splimp(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); splx(s); m_freem(m); return (ENOBUFS); } IF_ENQUEUE(&ifp->if_snd, m); qestart(ifp->if_unit); splx(s); return (0); bad: m_freem(m0); return (error); } /* * Process an ioctl request. */ qeioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { struct qe_softc *sc = &qe_softc[ifp->if_unit]; struct ifaddr *ifa = (struct ifaddr *)data; int s = splimp(), error = 0; switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; qeinit(ifp->if_unit); switch(ifa->ifa_addr.sa_family) { #ifdef INET case AF_INET: ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr; arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); break; #endif #ifdef NS case AF_NS: { register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); if (ns_nullhost(*ina)) ina->x_host = *(union ns_host *)(sc->is_addr); else qe_setaddr(ina->x_host.c_host, ifp->if_unit); break; } #endif } break; case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_UP) == 0 && sc->qe_flags & QEF_RUNNING) { ((struct qedevice *) (qeinfo[ifp->if_unit]->ui_addr))->qe_csr = QE_RESET; sc->qe_flags &= ~QEF_RUNNING; } else if (ifp->if_flags & IFF_UP && (sc->qe_flags & QEF_RUNNING) == 0) qerestart(sc); break; default: error = EINVAL; } splx(s); return (error); } /* * set ethernet address for unit */ qe_setaddr(physaddr, unit) u_char *physaddr; int unit; { register struct qe_softc *sc = &qe_softc[unit]; register int i; for (i = 0; i < 6; i++) sc->setup_pkt[i][1] = sc->is_addr[i] = physaddr[i]; sc->qe_flags |= QEF_SETADDR; if (sc->is_if.if_flags & IFF_RUNNING) qesetup(sc); qeinit(unit); } /* * Initialize a ring descriptor with mbuf allocation side effects */ qeinitdesc(rp, addr, len) register struct qe_ring *rp; caddr_t addr; /* mapped address */ int len; { /* * clear the entire descriptor */ bzero((caddr_t)rp, sizeof(struct qe_ring)); if( len ) { rp->qe_buf_len = -(len/2); rp->qe_addr_lo = (short)addr; rp->qe_addr_hi = (short)((int)addr >> 16); } } /* * Build a setup packet - the physical address will already be present * in first column. */ qesetup( sc ) struct qe_softc *sc; { register i, j; /* * Copy the target address to the rest of the entries in this row. */ for ( j = 0; j < 6 ; j++ ) for ( i = 2 ; i < 8 ; i++ ) sc->setup_pkt[j][i] = sc->setup_pkt[j][1]; /* * Duplicate the first half. */ bcopy((caddr_t)sc->setup_pkt[0], (caddr_t)sc->setup_pkt[8], 64); /* * Fill in the broadcast address. */ for ( i = 0; i < 6 ; i++ ) sc->setup_pkt[i][2] = 0xff; sc->setupqueued++; } /* * Pass a packet to the higher levels. * We deal with the trailer protocol here. */ qeread(sc, ifrw, len) register struct qe_softc *sc; struct ifrw *ifrw; int len; { struct ether_header *eh; struct mbuf *m; int off, resid; struct ifqueue *inq; /* * Deal with trailer protocol: if type is INET trailer * get true type from first 16-bit word past data. * Remember that type was trailer by setting off. */ eh = (struct ether_header *)ifrw->ifrw_addr; eh->ether_type = ntohs((u_short)eh->ether_type); #define qedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off)))) if (eh->ether_type >= ETHERTYPE_TRAIL && eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { off = (eh->ether_type - ETHERTYPE_TRAIL) * 512; if (off >= ETHERMTU) return; /* sanity */ eh->ether_type = ntohs(*qedataaddr(eh,off, u_short *)); resid = ntohs(*(qedataaddr(eh, off+2, u_short *))); if (off + resid > len) return; /* sanity */ len = off + resid; } else off = 0; if (len == 0) return; /* * Pull packet off interface. Off is nonzero if packet * has trailing header; qeget will then force this header * information to be at the front, but we still have to drop * the type and length which are at the front of any trailer data. */ m = if_ubaget(&sc->qe_uba, ifrw, len, off, &sc->is_if); if (m == 0) return; if (off) { struct ifnet *ifp; ifp = *(mtod(m, struct ifnet **)); m->m_off += 2 * sizeof (u_short); m->m_len -= 2 * sizeof (u_short); *(mtod(m, struct ifnet **)) = ifp; } switch (eh->ether_type) { #ifdef INET case ETHERTYPE_IP: schednetisr(NETISR_IP); inq = &ipintrq; break; case ETHERTYPE_ARP: arpinput(&sc->is_ac, m); return; #endif #ifdef NS case ETHERTYPE_NS: schednetisr(NETISR_NS); inq = &nsintrq; break; #endif default: m_freem(m); return; } if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); return; } IF_ENQUEUE(inq, m); } /* * Watchdog timer routine. There is a condition in the hardware that * causes the board to lock up under heavy load. This routine detects * the hang up and restarts the device. */ qewatch() { register struct qe_softc *sc; register int i; int inprogress=0; for (i = 0; i < NQE; i++) { sc = &qe_softc[i]; if (sc->timeout) if (++sc->timeout > 3 ) { log(LOG_ERR, "qerestart: restarted qe%d %d\n", i, ++sc->qe_restarts); qerestart(sc); } else inprogress++; } if (inprogress) { timeout(qewatch, (caddr_t)0, QE_TIMEO); qewatchrun++; } else qewatchrun=0; } /* * Restart for board lockup problem. */ qerestart(sc) register struct qe_softc *sc; { register struct ifnet *ifp = &sc->is_if; register struct qedevice *addr = sc->addr; register struct qe_ring *rp; register i; addr->qe_csr = QE_RESET; sc->timeout = 0; qesetup( sc ); for (i = 0, rp = sc->tring; i < NXMT; rp++, i++) { rp->qe_flag = rp->qe_status1 = QE_NOTYET; rp->qe_valid = 0; } sc->nxmit = sc->otindex = sc->tindex = sc->rindex = 0; addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT | QE_ILOOP; addr->qe_rcvlist_lo = (short)sc->rringaddr; addr->qe_rcvlist_hi = (short)((int)sc->rringaddr >> 16); sc->qe_flags |= QEF_RUNNING; qestart(ifp->if_unit); } #endif back. * The search is complete when sys/vaxif/if_qereg.h 444 0 12 12140 3671247777 7755 /* @(#)if_qereg.h 7.1 (Berkeley) 6/5/86 */ /* @(#)if_qereg.h 1.2 (ULTRIX) 1/3/85 */ /**************************************************************** * * * Licensed from Digital Equipment Corporation * * Copyright (c) * * Digital Equipment Corporation * * Maynard, Massachusetts * * 1985, 1986 * * All rights reserved. * * * * The Information in this software is subject to change * * without notice and should not be construed as a commitment * * by Digital Equipment Corporation. Digital makes no * * representations about the suitability of this software for * * any purpose. It is supplied "As Is" without expressed or * * implied warranty. * * * * If the Regents of the University of California or its * * licensees modify the software in a manner creating * * diriviative copyright rights, appropriate copyright * * legends may be placed on the drivative work in addition * * to that set forth above. * * * ****************************************************************/ /* --------------------------------------------------------------------- * Modification History * * 13 Feb. 84 -- rjl * * Initial version of driver. derived from IL driver. * * --------------------------------------------------------------------- */ /* * Digital Q-BUS to NI Adapter */ struct qedevice { u_short qe_sta_addr[2]; /* Station address (actually 6 */ u_short qe_rcvlist_lo; /* Receive list lo address */ u_short qe_rcvlist_hi; /* Receive list hi address */ u_short qe_xmtlist_lo; /* Transmit list lo address */ u_short qe_xmtlist_hi; /* Transmit list hi address */ u_short qe_vector; /* Interrupt vector */ u_short qe_csr; /* Command and Status Register */ }; /* * Command and status bits (csr) */ #define QE_RCV_ENABLE 0x0001 /* Receiver enable */ #define QE_RESET 0x0002 /* Software reset */ #define QE_NEX_MEM_INT 0x0004 /* Non existant mem interrupt */ #define QE_LOAD_ROM 0x0008 /* Load boot/diag from rom */ #define QE_XL_INVALID 0x0010 /* Transmit list invalid */ #define QE_RL_INVALID 0x0020 /* Receive list invalid */ #define QE_INT_ENABLE 0x0040 /* Interrupt enable */ #define QE_XMIT_INT 0x0080 /* Transmit interrupt */ #define QE_ILOOP 0x0100 /* Internal loopback */ #define QE_ELOOP 0x0200 /* External loopback */ #define QE_STIM_ENABLE 0x0400 /* Sanity timer enable */ #define QE_POWERUP 0x1000 /* Tranceiver power on */ #define QE_CARRIER 0x2000 /* Carrier detect */ #define QE_RCV_INT 0x8000 /* Receiver interrupt */ /* * Transmit and receive ring discriptor --------------------------- * * The QNA uses the flag, status1 and the valid bit as a handshake/semiphore * mechinism. * * The flag word is written on ( bits 15,15 set to 1 ) when it reads the * descriptor. If the valid bit is set it considers the address to be valid. * When it uses the buffer pointed to by the valid address it sets status word * one. */ struct qe_ring { u_short qe_flag; /* Buffer utilization flags */ u_short qe_addr_hi:6, /* Hi order bits of buffer addr */ qe_odd_begin:1, /* Odd byte begin and end (xmit)*/ qe_odd_end:1, qe_fill1:4, qe_setup:1, /* Setup packet */ qe_eomsg:1, /* End of message flag */ qe_chain:1, /* Chain address instead of buf */ qe_valid:1; /* Address field is valid */ u_short qe_addr_lo; /* Low order bits of address */ short qe_buf_len; /* Negative buffer length */ u_short qe_status1; /* Status word one */ u_short qe_status2; /* Status word two */ }; /* * Status word definations (receive) * word1 */ #define QE_OVF 0x0001 /* Receiver overflow */ #define QE_CRCERR 0x0002 /* CRC error */ #define QE_FRAME 0x0004 /* Framing alignment error */ #define QE_SHORT 0x0008 /* Packet size < 10 bytes */ #define QE_RBL_HI 0x0700 /* Hi bits of receive len */ #define QE_RUNT 0x0800 /* Runt packet */ #define QE_DISCARD 0x1000 /* Discard the packet */ #define QE_ESETUP 0x2000 /* Looped back setup or eloop */ #define QE_ERROR 0x4000 /* Receiver error */ #define QE_LASTNOT 0x8000 /* Not the last in the packet */ /* word2 */ #define QE_RBL_LO 0x00ff /* Low bits of receive len */ /* * Status word definations (transmit) * word1 */ #define QE_CCNT 0x00f0 /* Collision count this packet */ #define QE_FAIL 0x0100 /* Heart beat check failure */ #define QE_ABORT 0x0200 /* Transmission abort */ #define QE_STE16 0x0400 /* Sanity timer default on */ #define QE_NOCAR 0x0800 /* No carrier */ #define QE_LOSS 0x1000 /* Loss of carrier while xmit */ /* word2 */ #define QE_TDR 0x3fff /* Time domain reflectometry */ /* * General constant definations */ #define QEALLOC 0 /* Allocate an mbuf */ #define QENOALLOC 1 /* No mbuf allocation */ #define QEDEALLOC 2 /* Release an mbuf chain */ #define QE_NOTYET 0x8000 /* Descriptor not in use yet */ #define QE_INUSE 0x4000 /* Descriptor being used by QNA */ #define QE_MASK 0xc000 /* Lastnot/error/used mask */ truct qe_softc *sc = &qe_softc[unit]; register int i; for (i = 0; i < 6; i++) sc->setup_pkt[i][1] = sc->is_addr[i] = physaddr[i]; sc->qe_flags |= QEF_SETADDR; if (sc->is_if.if_flags & IFF_RUNNING) qesetup(sc); qeinit(unit); } /* * Initialize a ring descriptor with mbuf allocation side effects */ qeinitdesc(rp, addr, len) register struct qe_ring *rp; caddr_t addr; /* mapped address */ int lensys/QT/ 755 0 0 0 5722261067 5071 sys/QT/NETSPLFIX 664 0 0 1443 5520357160 6455 g/jsr pc,__spl0/s//clrb 177776/ g/jsr pc,__spl\([1-7]\)/s//movb $40*\1, 177776/ g/jsr pc,__splsoftclock/s//movb $40, 177776/ g/jsr pc,__splnet/s//movb $100, 177776/ g/jsr pc,__splimp/s//movb $240, 177776/ g/jsr pc,__splbio/s//movb $240, 177776/ g/jsr pc,__spltty/s//movb $240, 177776/ g/jsr pc,__splclock/s//movb $300, 177776/ g/jsr pc,__splhigh/s//movb $340, 177776/ g/jsr pc,_spl0/s//mfps r0;clrb 177776/ g/jsr pc,_spl\([1-7]\)/s//mfps r0;movb $40*\1, 177776/ g/jsr pc,_splsoftclock/s//mfps r0;movb $40, 177776/ g/jsr pc,_splnet/s//mfps r0;movb $100, 177776/ g/jsr pc,_splbio/s//mfps r0;movb $240, 177776/ g/jsr pc,_splimp/s//mfps r0;movb $240, 177776/ g/jsr pc,_spltty/s//mfps r0;movb $240, 177776/ g/jsr pc,_splclock/s//mfps r0;movb $300, 177776/ g/jsr pc,_splhigh/s//mfps r0;movb $340, 177776/ w q Interrupt enable */ #define QE_XMIT_INT 0x0080 /* Transmit interrupt */ #define QE_ILOOP 0x0100 /* Internal loopback */ #define QE_ELOOP 0x0200 /* External loopback */ #define QE_STIM_ENABLE 0x0400 /* Sanity timesys/QT/SPLFIX 664 0 0 1100 5520357250 6074 g/jsr pc,__spl\([0-7]\)/s//spl \1/ g/jsr pc,__splsoftclock/s//spl 1/ g/jsr pc,__splnet/s//spl 2/ g/jsr pc,__splbio/s//spl 5/ g/jsr pc,__splimp/s//spl 5/ g/jsr pc,__spltty/s//spl 5/ g/jsr pc,__splclock/s//spl 6/ g/jsr pc,__splhigh/s//spl 7/ g/jsr pc,_spl\([0-7]\)/s//mfps r0;spl \1/ g/jsr pc,_splsoftclock/s//mfps r0;spl 1/ g/jsr pc,_splnet/s//mfps r0;spl 2/ g/jsr pc,_splbio/s//mfps r0;spl 5/ g/jsr pc,_splimp/s//mfps r0;spl 5/ g/jsr pc,_spltty/s//mfps r0;spl 5/ g/jsr pc,_splclock/s//mfps r0;spl 6/ g/jsr pc,_splhigh/s//mfps r0;spl 7/ g/movb \(.*[^,]\),\*$-2/s//mtps \1/ w q o/s//mfps r0;mov$240, 177776/ g/jsr pc,_splimp/s//mfps r0;movb $240, 177776/ g/jsr pc,_spltty/s//mfps r0;movb $240, 177776/ g/jsr pc,_splclock/s//mfps r0;movb $300, 177776/ g/jsr pc,_splhigh/s//mfps r0;movb $340, 177776/ w q Interrupt enable */ #define QE_XMIT_INT 0x0080 /* Transmit interrupt */ #define QE_ILOOP 0x0100 /* Internal loopback */ #define QE_ELOOP 0x0200 /* External loopback */ #define QE_STIM_ENABLE 0x0400 /* Sanity timesys/QT/boot.s 640 0 0 10651 5320215175 6315 /* * SCCS id @(#)raboot.s 2.0 (2.11BSD) 4/13/91 */ #include "localopts.h" / The boot options and device are placed in the last SZFLAGS bytes / at the end of core for the bootstrap. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 / boot unit CHECKWORD= 6 .globl _doboot, hardboot, _bootcsr .text _doboot: mov 4(sp),r4 / boot options mov 2(sp),r3 / boot device #ifndef KERN_NONSEP / If running separate I/D, need to turn off memory management. / Call the routine unmap in low text, after setting up a jump / in low data where the PC will be pointing. .globl unmap mov $137,*$unmap+2 / jmp *$hardboot mov $hardboot,*$unmap+4 jmp unmap / "return" from unmap will be to hardboot in data .data #else / Reset to turn off memory management reset #endif / On power fail, hardboot is the entry point (map is already off) / and the args are in r4 (RB_POWRFAIL), r3 (rootdev) hardboot: mov r4, ENDCORE-BOOTOPTS ash $-3,r3 / shift out the partition number bic $!7,r3 / save only the drive number mov r3, ENDCORE-BOOTDEV com r4 / if CHECKWORD == ~bootopts, flags are believed mov r4, ENDCORE-CHECKWORD 1: reset / The remainder of the code is dependent on the boot device. / If you have a bootstrap ROM, just jump to the correct entry. / Otherwise, use a BOOT opcode, if available; / if necessary, read in block 0 to location 0 "by hand". / / RA bootstrap. / / Note: this is a complex boot, but then MSCP is complex!!!! / / Bootstrap for mscp disk controller tucker@gswd-vms / MSCPSIZE = 64. / One MSCP command packet is 64bytes long (need 2) RASEMAP = 140000 / RA controller owner semaphore RAERR = 100000 / error bit RASTEP1 = 04000 / step1 has started RAGO = 01 / start operation, after init RASTCON = 4 / Setup controller info RAONLIN = 11 / Put unit on line RAREAD = 41 / Read command code RAWRITE = 42 / Write command code RAEND = 200 / End command code RACMDI = 4. / Command Interrupt RARSPI = 6. / Response Interrupt RARING = 8. / Ring base RARSPL = 8. / Response Command low RARSPH = 10. / Response Command high RACMDL = 12. / Command to controller low RACMDH = 14. / Command to controller high RARSPS = 16. / Response packet length (location) RARSPREF = 20. / Response reference number RACMDS = 80. / Command packet length (location) RACMDREF = 84. / Command reference number RAUNIT = 88. / Command packet unit RAOPCODE = 92. / Command opcode offset RABYTECT = 96. / Transfer byte count RABUFL = 100. / Buffer location (16 bit addressing only) RABUFH = 102. / Buffer location high 6 bits RALBNL = 112. / Logical block number low RALBNH = 114. / Logical block number high BSIZE = 512. / Size of boot block / / Clear RA MSCP command area! / mov $ra,r0 mov $BSIZE,r1 mov r0,sp add r1,sp 1: clr (r0)+ sob r1,1b / / RA initialize controller / mov $RASTEP1,r0 mov _bootcsr,r1 / get csr of boot controller clr (r1)+ / go through controller init seq. mov $icons,r2 1: bit r0,(r1) beq 1b mov (r2)+,(r1) asl r0 bpl 1b mov $ra+RARSPREF,*$ra+RARSPL / set controller characteristics mov $ra+RACMDREF,*$ra+RACMDL mov $RASTCON,r0 jsr pc,racmd mov ENDCORE-BOOTDEV,*$ra+RAUNIT / bring boot unit online mov $RAONLIN,r0 jsr pc,racmd / / Read in block zero and jump to it / / / RA MSCP read block routine. This is very primative, so don't expect / too much from it. Note that MSCP requires large data communications / space at end of ADDROFF for command area. / / Load block zero into memory location zero. / BSIZE -> size of block to read / / Tim Tucker, Gould Electronics, August 23rd 1985 / clr *$ra+RALBNL / Put in logical block number mov $BSIZE,*$ra+RABYTECT / Put in byte to transfer clr *$ra+RABUFL / Put in disk buffer location mov $RAREAD,r0 jsr pc,racmd mov ENDCORE-BOOTDEV,r0 / put unit and mov _bootcsr,r1 / csr where bootblock expects them clr pc / and away we go / / perform MSCP command -> response poll version / racmd: movb r0,*$ra+RAOPCODE / fill in command type mov $MSCPSIZE,*$ra+RARSPS / give controller struct sizes mov $MSCPSIZE,*$ra+RACMDS mov $RASEMAP,*$ra+RARSPH / set mscp semaphores mov $RASEMAP,*$ra+RACMDH mov *_bootcsr,r0 / tap controllers shoulder mov $ra+RACMDI,r0 1: tst (r0) beq 1b / Wait till command read clr (r0)+ / Tell controller we saw it, ok. 2: tst (r0) beq 2b / Wait till response written clr (r0) / Tell controller we got it rts pc icons: RAERR ra+RARING 0 RAGO ra: 0 */ #define QE_RBL_HI 0x0700 /* Hi bits of receive len */ #define QE_RUNT 0x0800 /* Rsys/QT/ioconf.c 640 0 0 713 6002124742 6542 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ioconf.c 2.0 (2.11BSD GTE) 12/24/92 */ #include "param.h" #include "systm.h" dev_t rootdev = makedev(5,0), swapdev = makedev(5,1), pipedev = makedev(5,0); dev_t dumpdev = makedev(5,1); daddr_t dumplo = (daddr_t)512; int radump(); int (*dump)() = radump; ts.h tms.h vv.h acc.hhk.hsys/QT/param.c 640 0 0 6603 5350005610 6406 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)param.c 2.0 (2.11BSD GTE) 3/11/93 */ #include "../h/param.h" #include "../h/systm.h" #include "../h/buf.h" #include "../h/time.h" #include "../h/resource.h" #include "../h/proc.h" #include "../h/text.h" #include "../h/file.h" #include "../h/dir.h" #include "../h/inode.h" #include "../h/fs.h" #include "../h/mount.h" #include "../h/callout.h" #include "../h/map.h" #include "../h/clist.h" #include "../machine/seg.h" /* * System parameter formulae. * * This file is copied into each directory where we compile * the kernel; it should be modified there to suit local taste * if necessary. * */ #define MAXUSERS 20 #define NBUF 128 int hz = LINEHZ; struct timezone tz = { 480, 1 }; #define NPROC (10 + 7 * MAXUSERS) int nproc = NPROC; #define NTEXT (26 + MAXUSERS) int ntext = NTEXT; #define NINODE ((NPROC + 16 + MAXUSERS) + 22) int ninode = NINODE; #define NFILE ((8 * NINODE / 10) + 20) int nfile = NFILE; #define NCALL (16 + MAXUSERS) int ncallout = NCALL; int nbuf = NBUF; #define NCLIST (20 + 8 * MAXUSERS) #if NCLIST > (8192 / 32) /* 8K / sizeof(struct cblock) */ #undef NCLIST #define NCLIST (8192 / 32) #endif int nclist = NCLIST; /* * These have to be allocated somewhere; allocating * them here forces loader errors if this file is omitted * (if they've been externed everywhere else; hah!). */ struct proc *procNPROC; struct text *textNTEXT; struct inode inode[NINODE], *inodeNINODE; struct file *fileNFILE; struct callout callout[NCALL]; struct mount mount[NMOUNT]; struct buf buf[NBUF], bfreelist[BQUEUES]; struct bufhd bufhash[BUFHSZ]; #ifdef UCB_CLIST u_int clstdesc = ((((btoc(NCLIST*sizeof(struct cblock)))-1) << 8) | RW); int ucb_clist = 1; #else struct cblock cfree[NCLIST]; int ucb_clist = 0; #endif #define CMAPSIZ NPROC /* size of core allocation map */ #define SMAPSIZ ((9 * NPROC) / 10) /* size of swap allocation map */ struct mapent _coremap[CMAPSIZ]; struct map coremap[1] = { _coremap, &_coremap[CMAPSIZ], "coremap", }; struct mapent _swapmap[SMAPSIZ]; struct map swapmap[1] = { _swapmap, &_swapmap[SMAPSIZ], "swapmap", }; #ifdef QUOTA #include "../h/quota.h" struct BigQ { struct quota xquota[NQUOTA]; /* the quotas themselves */ struct dquot *ixdquot[NINODE]; /* 2.11 equiv of i_dquot */ struct dquot xdquot[NDQUOT]; /* the dquots themselves */ struct qhash xqhash[NQHASH]; struct dqhead xdqhash[NDQHASH]; }; QUOini() { extern struct qhash *qhash; extern struct dqhead *dqhead; quota = ((struct BigQ *)SEG5)->xquota; dquot = ((struct BigQ *)SEG5)->xdquot; qhash = ((struct BigQ *)SEG5)->xqhash; dqhead = ((struct BigQ *)SEG5)->xdqhash; ndquot = NDQUOT; nquota = NQUOTA; ix_dquot = ((struct BigQ *)SEG5)->ixdquot; dquotNDQUOT = &dquot[ndquot]; quotaNQUOTA = "a[nquota]; } #endif /* * Declarations of structures loaded last and allowed to reside in the * 0120000-140000 range (where buffers and clists are mapped). These * structures must be extern everywhere else, and the asm output of cc * is edited to move these structures from comm to bss (which is last) * (see the script :comm-to-bss). They are in capital letters so that * the edit script doesn't find some other occurrence. */ struct proc PROC[NPROC]; struct file FILE[NFILE]; struct text TEXT[NTEXT]; fine QEDEALLOC 2 /* Release an mbuf chain */ #define QE_NOTYET 0x8000 /* Descriptor not in use yet */ #define QE_INUSE 0sys/QT/loop.h 640 0 0 20 5320215202 6204 #define NLOOP 1 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/css.h 640 0 0 17 5320215204 6033 #define NCSS 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/de.h 640 0 0 16 5320215205 5633 #define NDE 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/dh.h 640 0 0 34 5320215205 5636 #define NDH 0 #define NDM 0  NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/dn.h 640 0 0 16 5320215206 5645 #define NDN 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/dhu.h 640 0 0 17 5320215206 6025 #define NDHU 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/dhv.h 640 0 0 17 5611406612 6034 #define NDHV 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/dmc.h 640 0 0 17 5320215207 6011 #define NDMC 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/dr.h 640 0 0 16 5320215207 5652 #define NDR 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/dz.h 640 0 0 16 5320215207 5662 #define NDZ 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/ec.h 640 0 0 16 5320215207 5634 #define NEC 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/en.h 640 0 0 16 5320215210 5641 #define NEN 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/ether.h 640 0 0 21 5320215210 6342 #define NETHER 1  .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/ht.h 640 0 0 16 5320215210 5652 #define NHT 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/hy.h 640 0 0 16 5320215210 5657 #define NHY 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/il.h 640 0 0 16 5320215211 5644 #define NIL 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/imp.h 640 0 0 17 5320215211 6026 #define NIMP 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/cn.h 640 0 0 16 5434604344 5657 #define NKL 8 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/lp.h 640 0 0 44 5320215212 5655 #define NLP 0 #define LP_MAXCOL 132 NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/pty.h 640 0 0 20 5320215212 6050 #define NPTY 12 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/qe.h 640 0 0 16 5404766746 5700 #define NQE 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/qt.h 640 0 0 16 5404766752 5714 #define NQT 1 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/ram.h 640 0 0 17 5320215213 6022 #define NRAM 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/rk.h 640 0 0 16 5320215213 5656 #define NRK 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/rx.h 640 0 0 16 5320215214 5674 #define NRX 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/sl.h 640 0 0 16 5320215214 5661 #define NSL 1 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/sri.h 640 0 0 17 5320215214 6041 #define NSRI 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/tb.h 640 0 0 16 5320215214 5650 #define NTB 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/ts.h 640 0 0 16 5404770331 5702 #define NTS 1 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/tms.h 640 0 0 40 5404770305 6055 #define NTMSCP 0 #define NTMS 0  NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/vv.h 640 0 0 16 5320215216 5700 #define NVV 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/acc.h 640 0 0 17 5320215216 5774 #define NACC 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/hk.h 640 0 0 16 5320215217 5650 #define NHK 0 . .. NETSPLFIXSPLFIXIXboot.sIXioconf.cparam.cloop.h css.h de.h dh.h dn.h dhu.h dhv.h dmc.h dr.h dz.h ec.h en.hether.h ht.h. hy.h. il.h. imp.h cn.h lp.h pty.h qe.h qt.h ram.h rk.h rx.h sl.h sri.h tb.h ts.h tms.h vv.h acc.hhk.hsys/QT/ra.h 640 0 0 60 5404770320 5653 #define NRAC 1 #define NRAD 2 #define RA_DUMP 1 si.h tm.h xp.hMakefileMake.sysMake.netMake.pdp Make.pdpmbao Make.pdpneto Make.pdpubao localopts.hoingres.h.version.vers.c.sys/QT/rl.h 640 0 0 16 5320215220 5655 #define NRL 0 ra.h rl.h br.h si.h tm.h xp.hMakefileMake.sysMake.netMake.pdp Make.pdpmbao Make.pdpneto Make.pdpubao localopts.hoingres.h.version.vers.c.sys/QT/br.h 640 0 0 16 5320215221 5644 #define NBR 0 ra.h rl.h br.h si.h tm.h xp.hMakefileMake.sysMake.netMake.pdp Make.pdpmbao Make.pdpneto Make.pdpubao localopts.hoingres.h.version.vers.c.sys/QT/si.h 640 0 0 16 5320215222 5655 #define NSI 0 ra.h rl.h br.h si.h tm.h xp.hMakefileMake.sysMake.netMake.pdp Make.pdpmbao Make.pdpneto Make.pdpubao localopts.hoingres.h.version.vers.c.sys/QT/tm.h 640 0 0 37 5320215223 5666 #define NTM 0 #define AVIVTM 1 h br.h si.h tm.h xp.hMakefileMake.sysMake.netMake.pdp Make.pdpmbao Make.pdpneto Make.pdpubao localopts.hoingres.h.version.vers.c.sys/QT/xp.h 640 0 0 36 6004072542 5701 #define NXPD 0 #define NXPC 0 .h br.h si.h tm.h xp.hMakefileMake.sysMake.netMake.pdp Make.pdpmbao Make.pdpneto Make.pdpubao localopts.hoingres.h.version.vers.c.sys/QT/Makefile 640 0 0 15443 5774714350 6646 OPTS=-DSMS -DUCB_METER -DINET -DQUOTA -DUCB_CLIST # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # %W% (Berkeley) %G% # ######################################################### # Networking, separate I/D kernel # ######################################################### H= ../h I= /usr/include M= ../machine N1= ../net N2= ../netimp N3= ../netinet N4= ../netns N6= ../pdpif S= ../sys U= ../pdpuba MB= ../pdpmba DEFS= -DKERNEL ${OPTS} -I. -I${H} CFLAGS= -O ${DEFS} CPP= /lib/cpp -P ${DEFS} AS= /bin/as -V ED= /bin/ed SUB= sys pdp pdpuba pdpmba net pdpnet # GENERAL RULES: # scb.o MUST be loaded first, param.o MUST be loaded last, # boot.o must be loaded in the base well above 0 data. # enable34.o must be in the base segment for overlaid kernels. # Don't forget the "-i" flag for split I/D, use "-n" otherwise. # # CONF Non-network assembly binaries. scb.o must be first! # boot.o should be close to the end. # NCONF Network (network space) assembly binaries. net_scb.o # doesn't have to be first. CONF= scb.o libc_bcmp.o libc_bcopy.o libc_bzero.o libc_ffs.o \ libc_insque.o libc_ldiv.o libc_lmul.o libc_lrem.o libc_remque.o \ libc_udiv.o libc_uldiv.o libc_ulsh.o \ libc_strlen.o mch_backup.o mch_click.o mch_copy.o mch_csv.o \ mch_dump.o mch_dzpdma.o mch_KScall.o mch_profile.o \ mch_start.o mch_trap.o mch_vars.o mch_xxx.o conf.o ioconf.o boot.o NCONF= libc_bcmp.o libc_bcopy.o libc_bzero.o libc_ffs.o libc_htonl.o \ libc_htons.o libc_insque.o libc_ldiv.o libc_lmul.o libc_lrem.o \ libc_uldiv.o libc_ulsh.o \ libc_remque.o libc_strlen.o libc_udiv.o net_copy.o net_csv.o \ net_mbuf.o net_scb.o net_SKcall.o net_trap.o net_xxx.o BASE= br.o cons.o dh.o dhu.o dhv.o dr.o dz.o hk.o ht.o init_sysent.o \ kern_clock.o kern_descrip.o kern_mman.o kern_proc.o kern_prot.o \ kern_subr.o kern_synch.o kern_xxx.o lp.o machdep.o ra.o ram.o \ rk.o rl.o rx.o si.o subr_rmap.o sys_inode.o sys_kern.o \ tm.o tty.o tty_conf.o tty_subr.o tty_tb.o ufs_alloc.o \ ufs_bio.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_namei.o \ vm_proc.o vm_sched.o vm_swap.o vm_text.o xp.o quota_subr.o OV1= sys_generic.o ufs_syscalls.o OV2= kern_acct.o kern_exec.o kern_exit.o kern_fork.o kern_resource.o OV3= kern_time.o sys_process.o ufs_mount.o ufs_subr.o uipc_syscalls.o OV4= dkbad.o kern_sig.o mem.o subr_xxx.o trap.o tty_pty.o tty_tty.o OV5= quota_kern.o quota_ufs.o quota_sys.o ufs_bmap.o \ sys_pipe.o # OV6 gets the (hopefully) never used routines OV6= clock.o dn.o init_main.o kern_pdp.o machdep2.o subr_prf.o syscalls.o \ subr_log.o toy.o vm_swp.o OV7= tmscp.o ts.o ufs_disksubr.o OV8= mch_fpsim.o kern_sysctl.o ingreslock.o KERNOBJ=${CONF} ${BASE} ${OV1} ${OV2} ${OV3} ${OV4} ${OV5} \ ${OV6} ${OV7} ${OV8} ${OV9} ${OV10} ${OV11} ${OV12} \ ${OV13} ${OV14} ${OV15} \ enable34.o vers.o param.o # param.o must be last! enable34.o must be in base. LD_KOBJ=${CONF} ${BASE} \ -Z ${OV1} -Z ${OV2} -Z ${OV3} -Z ${OV4} -Z ${OV5} -Z ${OV6} \ -Z ${OV7} -Z ${OV8} -Z ${OV9} -Z ${OV10} -Z ${OV11} -Z ${OV12} \ -Z ${OV13} -Z ${OV14} -Z ${OV15} -Y \ enable34.o vers.o param.o NETOBJ= ${NCONF} af.o idp_usrreq.o if.o if_acc.o if_css.o if_de.o \ if_dmc.o if_ec.o if_en.o if_ether.o if_il.o if_imp.o if_imphost.o \ if_loop.o if_qe.o if_qt.o if_sl.o if_sri.o if_uba.o if_vv.o in.o \ in_cksum.o in_pcb.o in_proto.o ip_icmp.o ip_input.o ip_output.o \ ns.o ns_error.o ns_input.o ns_ip.o ns_output.o ns_pcb.o \ ns_proto.o raw_cb.o raw_imp.o raw_ip.o \ raw_usrreq.o route.o spp_debug.o spp_usrreq.o sys_socket.o \ sys_net.o tcp_debug.o tcp_input.o tcp_output.o tcp_subr.o \ tcp_timer.o tcp_usrreq.o udp_usrreq.o uipc_domain.o uipc_mbuf.o \ uipc_proto.o uipc_socket.o uipc_socket2.o uipc_usrreq.o all: unix netnix # d.unix.o must be last object file in the dependency list! unix: ${SUB} ${KERNOBJ} d.unix.o checksys ld -X -i -o unix ${LD_KOBJ} d.unix.o size unix @echo Compacting symbol table -symcompact unix @echo Compacting strings table - this will take a few minutes -strcompact unix @echo rearranging symbols -symorder ../pdp/symbols.sort unix ./checksys unix # d.netnix.o must be the last object file in the dependency list! netnix: d.netnix.o -ld -X -i -o netnix ${NETOBJ} d.netnix.o size netnix @echo Compacting symbol table -symcompact netnix @echo Compacting strings table - this will take a few minutes -strcompact netnix @echo rearranging symbols -symorder ../pdp/symbols.sort netnix # Resolve all references between the kernel and the net. Always regenerate!!! # This was a constant source of problems during development. Should really # include ${NETOBJ} and ${KERNOBJ} on dependency line, but the pdp make doesn't # have enough table space. d.unix.o d.netnix.o: netbind FRC ld -q -r -d -X -i -o unix.o ${LD_KOBJ} ld -q -r -d -X -i -o netnix.o ${NETOBJ} ./netbind unix.o netnix.o rm unix.o netnix.o ${AS} - -o d.unix.o d.unix.s ${AS} - -o d.netnix.o d.netnix.s vers.o: FRC sh ../conf/newvers.sh ${CC} -c vers.c boot.o: boot.s ${CPP} boot.s > boot.i ${AS} -o boot.o boot.i rm -f boot.i param.o: ${CC} -S ${CFLAGS} param.c ${ED} - param.s < ../conf/:comm-to-bss ${AS} - -o param.o param.s rm -f param.s ioconf.o: ioconf.c ${CC} -c ${CFLAGS} ioconf.c checksys: ../conf/checksys.c ${CC} ${CFLAGS} -o $@ ../conf/checksys.c netbind: ../conf/netbind.c ${CC} ${CFLAGS} -o $@ ../conf/netbind.c sys pdp pdpuba pdpmba: make -f Make.$@ I=${I} H=${H} M=${M} AS="${AS}" CPP="${CPP}" \ CFLAGS="${CFLAGS}" ED="${ED}" net pdpnet: make -f Make.$@ I=${I} H=${H} M=${M} AS="${AS}" \ CPP="${CPP} -DSUPERVISOR" CFLAGS="${CFLAGS} -DSUPERVISOR" \ ED="${ED}" clean: rm -f unix core mklog *.o *.i assym.h genassym checksys rm -f netnix netbind d.unix.s d.netnix.s install: install -c -o root -g kmem -m 744 unix ${DESTDIR}/unix install -c -o root -g kmem -m 744 netnix ${DESTDIR}/netnix depend: FRC for i in ${SUB}; do \ make -f Make.$$i CFLAGS="${CFLAGS}" depend; done mkdep ${CFLAGS} param.c ioconf.c ../conf/checksys.c ../conf/netbind.c TAGSFILE= ${S}/tags TLIST= ${H} ${I} ${N1} ${N2} ${N3} ${N4} ${N5} ${N6} ${M} ${S} ${U} ${MB} ${SS} tags: FRC rm -f ${TAGSFILE} for i in ${TLIST}; do \ (cd ${S}; /usr/ucb/ctags -a -t $$i/*.[ch]); done /usr/bin/egrep "^ASENTRY|^ENTRY" ${M}/*.s | \ /bin/sed 's;\([^:]*\):\([^(]*\)(\([^)]*\));\3 \1 /^\2(\3)$$/;' \ >> ${TAGSFILE} /usr/bin/sort -o ${TAGSFILE} ${TAGSFILE} FRC: # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. RUNNING) qesetup(sc); qeinit(unit); } /* * Initialize a ring descriptor with mbuf allocation side effects */ qeinitdesc(rp, addr, len) register struct qe_ring *rp; caddr_t addr; /* mapped address */ int lensys/QT/Make.sys 664 0 0 5010 5743377446 6605 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # 2.2 (2.11BSD GTE) 1994/04/13 # S= ../sys VPATH= ../sys CFILES= ${S}/init_main.c ${S}/init_sysent.c ${S}/kern_acct.c \ ${S}/kern_clock.c ${S}/kern_descrip.c ${S}/kern_exec.c \ ${S}/kern_exit.c ${S}/kern_fork.c ${S}/kern_mman.c \ ${S}/kern_proc.c ${S}/kern_prot.c ${S}/kern_resource.c \ ${S}/kern_sig.c ${S}/kern_subr.c ${S}/kern_sysctl.c \ ${S}/kern_synch.c ${S}/kern_time.c ${S}/kern_xxx.c \ ${S}/quota_sys.c ${S}/quota_kern.c ${S}/quota_ufs.c \ ${S}/quota_subr.c ${S}/subr_log.c ${S}/subr_prf.c ${S}/subr_rmap.c \ ${S}/subr_xxx.c ${S}/sys_generic.c ${S}/sys_inode.c \ ${S}/sys_kern.c ${S}/sys_pipe.c \ ${S}/ingreslock.c \ ${S}/sys_process.c ${S}/syscalls.c ${S}/tty.c ${S}/tty_conf.c \ ${S}/tty_pty.c ${S}/tty_subr.c ${S}/tty_tb.c ${S}/tty_tty.c \ ${S}/ufs_alloc.c ${S}/ufs_bio.c ${S}/ufs_bmap.c \ ${S}/ufs_dsort.c ${S}/ufs_fio.c ${S}/ufs_inode.c \ ${S}/ufs_mount.c ${S}/ufs_namei.c ${S}/ufs_subr.c \ ${S}/ufs_disksubr.c \ ${S}/ufs_syscalls.c ${S}/uipc_syscalls.c ${S}/vm_proc.c \ ${S}/vm_sched.c ${S}/vm_swap.c ${S}/vm_swp.c ${S}/vm_text.c OBJS= init_main.o init_sysent.o kern_acct.o kern_clock.o \ kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o \ kern_proc.o kern_prot.o kern_resource.o kern_sig.o kern_sysctl.o \ kern_subr.o kern_synch.o kern_time.o kern_xxx.o quota_sys.o \ quota_kern.o quota_ufs.o quota_subr.o subr_log.o subr_prf.o subr_rmap.o \ ingreslock.o \ subr_xxx.o sys_generic.o sys_inode.o sys_kern.o \ sys_pipe.o sys_process.o syscalls.o tty.o tty_conf.o tty_pty.o \ tty_subr.o tty_tb.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o \ ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o \ ufs_subr.o ufs_syscalls.o uipc_syscalls.o vm_proc.o vm_sched.o \ ufs_disksubr.o \ vm_swap.o vm_swp.o vm_text.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s all: ${OBJS} depend: mkdep -f Make.sys ${CFLAGS} ${CFILES} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. GS} ioconf.c checksys: ../conf/checksys.c ${CC} ${CFLAGS} -o $@ ../conf/checksys.c netbind: ../conf/netbind.c ${CC} ${CFLAGS} -o $@ ../conf/netbind.c sys pdp pdpuba pdpmba: make -f Make.$@ I=${I} H=${H} M=${M} AS="${AS}" CPP="${CPP}" \ CFLAGS="${CFLAGS}" ED="${ED}" net pdpnet: make -f Make.$@ I=${I} H=${H} M=${M} AS="${AS}" \ CPP="${CPP} -DSUPERVISOR" CFLAGS="${CFLAGS} -DSUPERVISOR" \ ED="${ED}" clean: rm -f unix core mklog *.o *.i assym.h genassym checksys rm -f netnix netsys/QT/Make.net 664 0 0 5022 5266714304 6544 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # %W% (Berkeley) %G% # N1= ../net N1C= ${N1}/af.c ${N1}/if.c ${N1}/if_loop.c ${N1}/if_sl.c \ ${N1}/raw_cb.c ${N1}/raw_usrreq.c ${N1}/route.c N1O= af.o if.o if_loop.o if_sl.o raw_cb.o raw_usrreq.o route.o N2= ../netimp N2C= ${N2}/if_imp.c ${N2}/if_imphost.c ${N2}/raw_imp.c N2O= if_imp.o if_imphost.o raw_imp.o N3= ../netinet N3C= ${N3}/if_ether.c ${N3}/in.c ${N3}/in_pcb.c ${N3}/in_proto.c \ ${N3}/ip_icmp.c ${N3}/ip_input.c ${N3}/ip_output.c \ ${N3}/raw_ip.c ${N3}/tcp_debug.c ${N3}/tcp_input.c \ ${N3}/tcp_output.c ${N3}/tcp_subr.c ${N3}/tcp_timer.c \ ${N3}/tcp_usrreq.c ${N3}/udp_usrreq.c N3O= if_ether.o in.o in_pcb.o in_proto.o ip_icmp.o ip_input.o \ ip_output.o raw_ip.o tcp_debug.o tcp_input.o tcp_output.o \ tcp_subr.o tcp_timer.o tcp_usrreq.o udp_usrreq.o N5= ../netns N5C= ${N5}/ns.c ${N5}/ns_pcb.c ${N5}/ns_proto.c ${N5}/ns_error.c \ ${N5}/ns_ip.c ${N5}/ns_input.c ${N5}/ns_output.c \ ${N5}/idp_usrreq.c ${N5}/spp_usrreq.c ${N5}/spp_debug.c N5O= ns.o ns_pcb.o ns_proto.o ns_error.o ns_ip.o ns_input.o \ ns_output.o idp_usrreq.o spp_usrreq.o spp_debug.o N6= ../pdpif N6C= ${N6}/if_acc.c ${N6}/if_css.c ${N6}/if_de.c ${N6}/if_dmc.c \ ${N6}/if_ec.c ${N6}/if_en.c ${N6}/if_il.c ${N6}/if_qe.c \ ${N6}/if_qt.c ${N6}/if_sri.c ${N6}/if_uba.c ${N6}/if_vv.c N6O= if_acc.o if_css.o if_de.o if_dmc.o if_ec.o if_en.o if_il.o \ if_qe.o if_qt.o if_sri.o if_uba.o if_vv.o S= ../sys SC= ${S}/sys_socket.c ${S}/sys_net.c ${S}/uipc_domain.c \ ${S}/uipc_mbuf.c ${S}/uipc_proto.c ${S}/uipc_socket.c \ ${S}/uipc_socket2.c ${S}/uipc_usrreq.c SO= sys_socket.o sys_net.o uipc_domain.o uipc_mbuf.o uipc_proto.o \ uipc_socket.o uipc_socket2.o uipc_usrreq.o VPATH= ../net:../netimp:../netinet:../netns:../pdpif:../sys SRCS= ${N1C} ${N2C} ${N3C} ${N5C} ${N6C} ${SC} OBJS= ${N1O} ${N2O} ${N3O} ${N5O} ${N6O} ${SO} .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < NETSPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s all: ${OBJS} depend: mkdep -f Make.net ${CFLAGS} ${SRCS} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. N1C= ${N1}/af.c ${N1}/if.c ${N1}/if_loop.c ${N1}/if_sl.c \ ${N1}/raw_cb.c ${N1}/raw_usrreq.c ${N1}/route.c N1O= af.o if.o if_loop.o if_sl.o raw_cb.o raw_usrreq.o route.o N2= ../netimp N2C= ${N2}/if_imp.c ${N2}/if_imphost.c ${N2}/raw_imp.c N2O= if_imp.o if_imphost.o raw_imp.o N3= ../netinet N3C= ${N3}/if_ether.c ${N3}/in.c ${N3}/in_pcb.c ${N3}/in_proto.c \ ${N3}/ip_icmp.c ${N3}/ip_input.c ${N3}/ip_output.c \ ${N3}/raw_ip.c ${N3}/tcp_debug.c ${N3}/tcp_input.c \ ${N3}/tcp_output.c $sys/QT/Make.pdp 664 0 0 5036 5757755537 6570 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # 2.0 (2.11BSD GTE) 1995/05/21 # M= ../machine VPATH= ../machine CFILES= ${M}/clock.c ${M}/conf.c ${M}/cons.c ${M}/kern_pdp.c \ ${M}/machdep.c ${M}/machdep2.c ${M}/mem.c ${M}/ram.c ${M}/trap.c COBJS= clock.o conf.o cons.o kern_pdp.o machdep.o machdep2.o mem.o \ ram.o trap.o # We compile mch_KScall here rather than in Make.pdpnet so that it gets # compiled with the right flags. This means that it gets compiled for all # kernel, but is only included in the networking kernel. As it only takes # a few seconds to compile it, it isn't worth trashing up Make.pdpnet to # compile it there. SFILES= ${M}/libc_bcmp.s ${M}/libc_bcopy.s ${M}/libc_bzero.s \ ${M}/libc_ffs.s ${M}/libc_insque.s ${M}/libc_ldiv.s \ ${M}/libc_lmul.s ${M}/libc_lrem.s ${M}/libc_remque.s \ ${M}/libc_uldiv.s ${M}/libc_ulsh.s \ ${M}/libc_strlen.s ${M}/libc_udiv.s ${M}/mch_backup.s \ ${M}/mch_click.s ${M}/mch_copy.s ${M}/mch_csv.s ${M}/mch_dump.s \ ${M}/mch_dzpdma.s ${M}/mch_fpsim.s ${M}/mch_KScall.s \ ${M}/mch_profile.s ${M}/mch_start.s ${M}/mch_trap.s \ ${M}/mch_vars.s ${M}/mch_xxx.s ${M}/scb.s ${M}/toy.s SOBJS= libc_bcmp.o libc_bcopy.o libc_bzero.o libc_ffs.o libc_insque.o \ libc_ldiv.o libc_lmul.o libc_lrem.o libc_remque.o libc_strlen.o \ libc_uldiv.o libc_ulsh.o \ libc_udiv.o mch_backup.o mch_click.o mch_copy.o mch_csv.o \ mch_dump.o mch_dzpdma.o mch_fpsim.o mch_KScall.o mch_profile.o \ mch_start.o mch_trap.o mch_vars.o mch_xxx.o scb.o toy.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s .s.o: ${CPP} $*.s | ${AS} -u -o $*.o all: assym.h ${COBJS} ${SOBJS} ../pdp/symbols.sort assym.h: genassym ./genassym > $@ genassym: ${CC} -O ${CFLAGS} ${M}/genassym.c -o $@ # it's a tab character in the sed statement below not a space. ../pdp/symbols.sort: ../pdp/symbols.raw grep -v '^#' ../pdp/symbols.raw \ | sed 's/^ //' | sort -u > ../pdp/symbols.sort depend: assym.h mkdep -f Make.pdp ${CFLAGS} ${CFILES} ${SFILES} ${M}/genassym.c # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. : ../conf/checksys.c ${CC} ${CFLAGS} -o $@ ../conf/checksys.c netbind: ../conf/netbind.c ${CC} ${CFLAGS} -o $@ ../conf/netbind.c sys pdp pdpuba pdpmba: make -f Make.$@ I=${I} H=${H} M=${M} AS="${AS}" CPP="${CPP}" \ CFLAGS="${CFLAGS}" ED="${ED}" net pdpnet: make -f Make.$@ I=${I} H=${H} M=${M} AS="${AS}" \ CPP="${CPP} -DSUPERVISOR" CFLAGS="${CFLAGS} -DSUPERVISOR" \ ED="${ED}" clean: rm -f unix core mklog *.o *.i assym.h genassym checksys rm -f netnix netsys/QT/Make.pdpmba 664 0 0 1466 4263626577 7243 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # %W% (Berkeley) %G% # U= ../pdpmba VPATH= ../pdpmba CFILES= OBJS= .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s all: ${OBJS} depend: mkdep -f Make.pdpmba ${CFLAGS} ${CFILES} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. ke.pdpnet so that it gets # compiled with the right flags. This means that it gets compiled for all # kernel, but is only included in the networking kernel. As it only takes # a few seconds to compilesys/QT/Make.pdpnet 664 0 0 2701 5757757237 7272 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # 2.0 (2.11BSD GTE) 1995/05/21 # M= ../machine VPATH= ../machine CFILES= ${M}/enable34.c ${M}/in_cksum.c COBJS= enable34.o in_cksum.o SFILES= ${M}/libc_htonl.s ${M}/libc_htons.s ${M}/net_copy.s \ ${M}/net_csv.s ${M}/net_mbuf.s ${M}/net_scb.s ${M}/net_SKcall.s \ ${M}/net_trap.s ${M}/net_xxx.s SOBJS= libc_htonl.o libc_htons.o mch_KScall.o net_copy.o net_csv.o \ net_mbuf.o net_scb.o net_SKcall.o net_trap.o net_xxx.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < NETSPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s .s.o: ${CPP} $*.s | ${AS} -u -o $*.o all: ${COBJS} ${SOBJS} in_cksum.o: ${CC} ${CFLAGS} -S ${M}/in_cksum.c ${ED} - < ${M}/cksum-fix > /dev/null in_cksum.s ${ED} - < NETSPLFIX in_cksum.s ${AS} - -o $@ in_cksum.s rm -f in_cksum.s depend: assym.h mkdep -f Make.pdpnet ${CFLAGS} ${CFILES} ${SFILES} assym.h: make -f Make.pdp CFLAGS="${CFLAGS}" assym.h # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. KScall.s \ ${M}/mch_profile.s ${M}/mch_start.s ${M}/mch_trap.ssys/QT/Make.pdpuba 664 0 0 2200 5125225325 7216 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # %W% (Berkeley) %G% # U= ../pdpuba VPATH= ../pdpuba CFILES= ${U}/br.c ${U}/dh.c ${U}/dn.c ${U}/dhu.c ${U}/dhv.c ${U}/dkbad.c \ ${U}/dr.c ${U}/dz.c ${U}/hk.c ${U}/ht.c ${U}/lp.c ${U}/ra.c ${U}/rk.c \ ${U}/rl.c ${U}/rx.c ${U}/si.c ${U}/tm.c ${U}/tmscp.c ${U}/ts.c ${U}/xp.c OBJS= br.o dh.o dhu.o dhv.o dkbad.o dn.o dr.o dz.o hk.o ht.o lp.o ra.o rk.o \ rl.o rx.o si.o tm.o tmscp.o ts.o xp.o dn.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s all: ${OBJS} depend: mkdep -f Make.pdpuba ${CFLAGS} ${CFILES} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. dev/null in_cksum.s ${ED} - < NETSPLFIX in_cksum.s ${AS} - -o $@ in_cksum.s rm -f in_cksum.s depend: assym.h mkdep -f Make.pdpnet ${CFLAGS} ${CFILES} ${SFILES} assym.h: make -f Make.pdp CFLAGS="${CFLAGS}" assym.h # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. KScall.s \ ${M}/mch_profile.s ${M}/mch_start.s ${M}/mch_trap.ssys/QT/localopts.h 640 0 0 516 5320215231 7267 /* * This file is generated by the configuration script sys/conf/config. * * It contains a list the kernel options not prepended to the Makefile * as -Dxxxx commands to the compiler. MAXMEM was moved to param.h leaving * only LINEHZ and EXTERNALITIMES to be placed in localopts.h */ #define LINEHZ 60 #define EXTERNALITIMES 1 sys/QT/ingres.h 640 0 0 22 5756536573 6562 #define NINGRES 1 .h rl.h br.h si.h tm.h xp.hMakefileMake.sysMake.netMake.pdp Make.pdpmbao Make.pdpneto Make.pdpubao localopts.hoingres.h.version.vers.c.sys/QT/version 640 0 0 3 5611416641 6470 73  ra.h rl.h br.h si.h tm.h xp.hMakefileMake.sysMake.netMake.pdp Make.pdpmbao Make.pdpneto Make.pdpubao localopts.hoingres.h.version.vers.c.sys/QT/vers.c 640 0 0 341 5611416641 6250 char sccs[] = "@(#)2.11 BSD #73: Thu Jul 14 22:24:48 PDT 1994 (sms1@sms.iipo.gtegsc.com:/usr/src/sys/QT)\n"; char version[] = "2.11 BSD UNIX #73: Thu Jul 14 22:24:48 PDT 1994\n sms1@sms.iipo.gtegsc.com:/usr/src/sys/QT\n"; ingres.h.version.vers.c.sys/LONEX.ra/ 775 0 24 0 5774647543 6101 sys/LONEX.ra/NETSPLFIX 640 0 24 1542 5525063675 7451 g/jsr pc,__spl0/s//clrb 177776/ g/jsr pc,__spl\([1-7]\)/s//movb $40*\1, 177776/ g/jsr pc,__splsoftclock/s//movb $40, 177776/ g/jsr pc,__splnet/s//movb $100, 177776/ g/jsr pc,__splimp/s//movb $300, 177776/ g/jsr pc,__splbio/s//movb $240, 177776/ g/jsr pc,__spltty/s//movb $240, 177776/ g/jsr pc,__splclock/s//movb $300, 177776/ g/jsr pc,__splhigh/s//movb $340, 177776/ g/jsr pc,_spl0/s//movb 177776,r0;clrb 177776/ g/jsr pc,_spl\([1-7]\)/s//movb 177776,r0;movb $40*\1, 177776/ g/jsr pc,_splsoftclock/s//movb 177776,r0;movb $40, 177776/ g/jsr pc,_splnet/s//movb 177776,r0;movb $100, 177776/ g/jsr pc,_splbio/s//movb 177776,r0;movb $240, 177776/ g/jsr pc,_splimp/s//movb 177776,r0;movb $300, 177776/ g/jsr pc,_spltty/s//movb 177776,r0;movb $240, 177776/ g/jsr pc,_splclock/s//movb 177776,r0;movb $300, 177776/ g/jsr pc,_splhigh/s//movb 177776,r0;movb $340, 177776/ w q tm.o tmscp.o ts.o xp.o dn.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s all: ${OBJS} depend: mkdep -f Make.psys/LONEX.ra/SPLFIX 640 0 24 1124 5525063701 7064 g/jsr pc,__spl\([0-7]\)/s//spl \1/ g/jsr pc,__splsoftclock/s//spl 1/ g/jsr pc,__splnet/s//spl 2/ g/jsr pc,__splbio/s//spl 5/ g/jsr pc,__splimp/s//spl 6/ g/jsr pc,__spltty/s//spl 5/ g/jsr pc,__splclock/s//spl 6/ g/jsr pc,__splhigh/s//spl 7/ g/jsr pc,_spl\([0-7]\)/s//movb 177776,r0;spl \1/ g/jsr pc,_splsoftclock/s//movb 177776,r0;spl 1/ g/jsr pc,_splnet/s//movb 177776,r0;spl 2/ g/jsr pc,_splbio/s//movb 177776,r0;spl 5/ g/jsr pc,_splimp/s//movb 177776,r0;spl 6/ g/jsr pc,_spltty/s//movb 177776,r0;spl 5/ g/jsr pc,_splclock/s//movb 177776,r0;spl 6/ g/jsr pc,_splhigh/s//movb 177776,r0;spl 7/ w q c,_splbio/s//movb 177776,r0;movb $240, 177776/ g/jsr pc,_splimp/s//movb 177776,r0;movb $300, 177776/ g/jsr pc,_spltty/s//movb 177776,r0;movb $240, 177776/ g/jsr pc,_splclock/s//movb 177776,r0;movb $300, 177776/ g/jsr pc,_splhigh/s//movb 177776,r0;movb $340, 177776/ w q tm.o tmscp.o ts.o xp.o dn.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s all: ${OBJS} depend: mkdep -f Make.psys/LONEX.ra/boot.s 664 0 24 10651 5502164142 7312 /* * SCCS id @(#)raboot.s 2.0 (2.11BSD) 4/13/91 */ #include "localopts.h" / The boot options and device are placed in the last SZFLAGS bytes / at the end of core for the bootstrap. ENDCORE= 160000 / end of core, mem. management off SZFLAGS= 6 / size of boot flags BOOTOPTS= 2 / location of options, bytes below ENDCORE BOOTDEV= 4 / boot unit CHECKWORD= 6 .globl _doboot, hardboot, _bootcsr .text _doboot: mov 4(sp),r4 / boot options mov 2(sp),r3 / boot device #ifndef KERN_NONSEP / If running separate I/D, need to turn off memory management. / Call the routine unmap in low text, after setting up a jump / in low data where the PC will be pointing. .globl unmap mov $137,*$unmap+2 / jmp *$hardboot mov $hardboot,*$unmap+4 jmp unmap / "return" from unmap will be to hardboot in data .data #else / Reset to turn off memory management reset #endif / On power fail, hardboot is the entry point (map is already off) / and the args are in r4 (RB_POWRFAIL), r3 (rootdev) hardboot: mov r4, ENDCORE-BOOTOPTS ash $-3,r3 / shift out the partition number bic $!7,r3 / save only the drive number mov r3, ENDCORE-BOOTDEV com r4 / if CHECKWORD == ~bootopts, flags are believed mov r4, ENDCORE-CHECKWORD 1: reset / The remainder of the code is dependent on the boot device. / If you have a bootstrap ROM, just jump to the correct entry. / Otherwise, use a BOOT opcode, if available; / if necessary, read in block 0 to location 0 "by hand". / / RA bootstrap. / / Note: this is a complex boot, but then MSCP is complex!!!! / / Bootstrap for mscp disk controller tucker@gswd-vms / MSCPSIZE = 64. / One MSCP command packet is 64bytes long (need 2) RASEMAP = 140000 / RA controller owner semaphore RAERR = 100000 / error bit RASTEP1 = 04000 / step1 has started RAGO = 01 / start operation, after init RASTCON = 4 / Setup controller info RAONLIN = 11 / Put unit on line RAREAD = 41 / Read command code RAWRITE = 42 / Write command code RAEND = 200 / End command code RACMDI = 4. / Command Interrupt RARSPI = 6. / Response Interrupt RARING = 8. / Ring base RARSPL = 8. / Response Command low RARSPH = 10. / Response Command high RACMDL = 12. / Command to controller low RACMDH = 14. / Command to controller high RARSPS = 16. / Response packet length (location) RARSPREF = 20. / Response reference number RACMDS = 80. / Command packet length (location) RACMDREF = 84. / Command reference number RAUNIT = 88. / Command packet unit RAOPCODE = 92. / Command opcode offset RABYTECT = 96. / Transfer byte count RABUFL = 100. / Buffer location (16 bit addressing only) RABUFH = 102. / Buffer location high 6 bits RALBNL = 112. / Logical block number low RALBNH = 114. / Logical block number high BSIZE = 512. / Size of boot block / / Clear RA MSCP command area! / mov $ra,r0 mov $BSIZE,r1 mov r0,sp add r1,sp 1: clr (r0)+ sob r1,1b / / RA initialize controller / mov $RASTEP1,r0 mov _bootcsr,r1 / get csr of boot controller clr (r1)+ / go through controller init seq. mov $icons,r2 1: bit r0,(r1) beq 1b mov (r2)+,(r1) asl r0 bpl 1b mov $ra+RARSPREF,*$ra+RARSPL / set controller characteristics mov $ra+RACMDREF,*$ra+RACMDL mov $RASTCON,r0 jsr pc,racmd mov ENDCORE-BOOTDEV,*$ra+RAUNIT / bring boot unit online mov $RAONLIN,r0 jsr pc,racmd / / Read in block zero and jump to it / / / RA MSCP read block routine. This is very primative, so don't expect / too much from it. Note that MSCP requires large data communications / space at end of ADDROFF for command area. / / Load block zero into memory location zero. / BSIZE -> size of block to read / / Tim Tucker, Gould Electronics, August 23rd 1985 / clr *$ra+RALBNL / Put in logical block number mov $BSIZE,*$ra+RABYTECT / Put in byte to transfer clr *$ra+RABUFL / Put in disk buffer location mov $RAREAD,r0 jsr pc,racmd mov ENDCORE-BOOTDEV,r0 / put unit and mov _bootcsr,r1 / csr where bootblock expects them clr pc / and away we go / / perform MSCP command -> response poll version / racmd: movb r0,*$ra+RAOPCODE / fill in command type mov $MSCPSIZE,*$ra+RARSPS / give controller struct sizes mov $MSCPSIZE,*$ra+RACMDS mov $RASEMAP,*$ra+RARSPH / set mscp semaphores mov $RASEMAP,*$ra+RACMDH mov *_bootcsr,r0 / tap controllers shoulder mov $ra+RACMDI,r0 1: tst (r0) beq 1b / Wait till command read clr (r0)+ / Tell controller we saw it, ok. 2: tst (r0) beq 2b / Wait till response written clr (r0) / Tell controller we got it rts pc icons: RAERR ra+RARING 0 RAGO ra: 0 {M}/genassym.c # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTERsys/LONEX.ra/ioconf.c 664 0 24 714 5502164144 7545 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ioconf.c 2.0 (2.11BSD GTE) 12/24/92 */ #include "param.h" #include "systm.h" dev_t rootdev = makedev(5,0), swapdev = makedev(5,1), pipedev = makedev(5,0); dev_t dumpdev = makedev(5,1); daddr_t dumplo = (daddr_t)1024; int radump(); int (*dump)() = radump; ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/param.c 664 0 24 6602 5504663526 7424 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)param.c 2.0 (2.11BSD GTE) 3/11/93 */ #include "../h/param.h" #include "../h/systm.h" #include "../h/buf.h" #include "../h/time.h" #include "../h/resource.h" #include "../h/proc.h" #include "../h/text.h" #include "../h/file.h" #include "../h/dir.h" #include "../h/inode.h" #include "../h/fs.h" #include "../h/mount.h" #include "../h/callout.h" #include "../h/map.h" #include "../h/clist.h" #include "../machine/seg.h" /* * System parameter formulae. * * This file is copied into each directory where we compile * the kernel; it should be modified there to suit local taste * if necessary. * */ #define MAXUSERS 22 #define NBUF 72 int hz = LINEHZ; struct timezone tz = { 480, 1 }; #define NPROC (10 + 7 * MAXUSERS) int nproc = NPROC; #define NTEXT (26 + MAXUSERS) int ntext = NTEXT; #define NINODE ((NPROC + 16 + MAXUSERS) + 22) int ninode = NINODE; #define NFILE ((8 * NINODE / 10) + 20) int nfile = NFILE; #define NCALL (16 + MAXUSERS) int ncallout = NCALL; int nbuf = NBUF; #define NCLIST (20 + 8 * MAXUSERS) #if NCLIST > (8192 / 32) /* 8K / sizeof(struct cblock) */ #undef NCLIST #define NCLIST (8192 / 32) #endif int nclist = NCLIST; /* * These have to be allocated somewhere; allocating * them here forces loader errors if this file is omitted * (if they've been externed everywhere else; hah!). */ struct proc *procNPROC; struct text *textNTEXT; struct inode inode[NINODE], *inodeNINODE; struct file *fileNFILE; struct callout callout[NCALL]; struct mount mount[NMOUNT]; struct buf buf[NBUF], bfreelist[BQUEUES]; struct bufhd bufhash[BUFHSZ]; #ifdef UCB_CLIST u_int clstdesc = ((((btoc(NCLIST*sizeof(struct cblock)))-1) << 8) | RW); int ucb_clist = 1; #else struct cblock cfree[NCLIST]; int ucb_clist = 0; #endif #define CMAPSIZ NPROC /* size of core allocation map */ #define SMAPSIZ ((9 * NPROC) / 10) /* size of swap allocation map */ struct mapent _coremap[CMAPSIZ]; struct map coremap[1] = { _coremap, &_coremap[CMAPSIZ], "coremap", }; struct mapent _swapmap[SMAPSIZ]; struct map swapmap[1] = { _swapmap, &_swapmap[SMAPSIZ], "swapmap", }; #ifdef QUOTA #include "../h/quota.h" struct BigQ { struct quota xquota[NQUOTA]; /* the quotas themselves */ struct dquot *ixdquot[NINODE]; /* 2.11 equiv of i_dquot */ struct dquot xdquot[NDQUOT]; /* the dquots themselves */ struct qhash xqhash[NQHASH]; struct dqhead xdqhash[NDQHASH]; }; QUOini() { extern struct qhash *qhash; extern struct dqhead *dqhead; quota = ((struct BigQ *)SEG5)->xquota; dquot = ((struct BigQ *)SEG5)->xdquot; qhash = ((struct BigQ *)SEG5)->xqhash; dqhead = ((struct BigQ *)SEG5)->xdqhash; ndquot = NDQUOT; nquota = NQUOTA; ix_dquot = ((struct BigQ *)SEG5)->ixdquot; dquotNDQUOT = &dquot[ndquot]; quotaNQUOTA = "a[nquota]; } #endif /* * Declarations of structures loaded last and allowed to reside in the * 0120000-140000 range (where buffers and clists are mapped). These * structures must be extern everywhere else, and the asm output of cc * is edited to move these structures from comm to bss (which is last) * (see the script :comm-to-bss). They are in capital letters so that * the edit script doesn't find some other occurrence. */ struct proc PROC[NPROC]; struct file FILE[NFILE]; struct text TEXT[NTEXT]; } ${S} ${U} ${MB} ${SS} tags: FRC rm -f ${TAGSFILE} for i in ${TLIST}; do \ (cd ${S}; /usr/ucb/ctags -a -t $$i/*.[ch]); dsys/LONEX.ra/loop.h 664 0 24 20 5502164147 7217 #define NLOOP 1 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/css.h 664 0 24 17 5502164151 7037 #define NCSS 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/de.h 664 0 24 16 5502164152 6637 #define NDE 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/dh.h 664 0 24 34 5502164153 6643 #define NDH 3 #define NDM 3  NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/dn.h 664 0 24 16 5502164153 6651 #define NDN 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/dhu.h 664 0 24 17 5502164153 7031 #define NDHU 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/dhv.h 664 0 24 17 5502164153 7032 #define NDHV 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/dmc.h 664 0 24 17 5502164154 7015 #define NDMC 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/dr.h 664 0 24 16 5502164154 6656 #define NDR 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/dz.h 664 0 24 16 5502164154 6666 #define NDZ 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/ec.h 664 0 24 16 5502164155 6641 #define NEC 1 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/en.h 664 0 24 16 5502164155 6654 #define NEN 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/ether.h 664 0 24 21 5502164155 7355 #define NETHER 1  .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/ht.h 664 0 24 16 5502164156 6666 #define NHT 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/hy.h 664 0 24 16 5502164156 6673 #define NHY 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/il.h 664 0 24 16 5502164156 6657 #define NIL 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/imp.h 664 0 24 17 5502164157 7042 #define NIMP 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/cn.h 664 0 24 16 5502164157 6654 #define NKL 1 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/lp.h 664 0 24 44 5502164160 6662 #define NLP 2 #define LP_MAXCOL 132 NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/pty.h 664 0 24 17 5502164160 7063 #define NPTY 8 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/qe.h 664 0 24 16 5502164160 6653 #define NQE 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/qt.h 664 0 24 16 5502164161 6673 #define NQT 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/ram.h 664 0 24 17 5502164161 7027 #define NRAM 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/rk.h 664 0 24 16 5502164161 6663 #define NRK 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/rx.h 664 0 24 16 5502164162 6701 #define NRX 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/sl.h 664 0 24 16 5502164162 6666 #define NSL 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/sri.h 664 0 24 17 5502164162 7046 #define NSRI 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/tb.h 664 0 24 16 5502164163 6656 #define NTB 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/ts.h 664 0 24 16 5502164163 6677 #define NTS 2 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/tms.h 664 0 24 40 5502164163 7051 #define NTMSCP 0 #define NTMS 0  NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/vv.h 664 0 24 16 5502164164 6705 #define NVV 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/acc.h 664 0 24 17 5502164165 7002 #define NACC 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/hk.h 664 0 24 16 5502164165 6655 #define NHK 0 . .. NETSPLFIXSPLFIXaboot.saioconf.cparam.cloop.ha css.h de.h. dh.h. dn.h. dhu.h dhv.h dmc.h dr.h. dz.h. ec.h. en.h.ether.h ht.h. hy.h. il.h. imp.h cn.h. lp.h. pty.h qe.h.~ qt.h.} ram.h| rk.h.{ rx.h.z sl.h.y sri.hx tb.h.w ts.h.v tms.hu vv.h.t acc.hshk.hsys/LONEX.ra/ra.h 664 0 24 60 5502164167 6656 #define NRAC 1 #define NRAD 2 #define RA_DUMP 1 si.h.n tm.h.m xp.h.lMakefilekMake.sysjMake.neti Make.pdpnetoh Make.pdpubaogMake.pdpbf Make.pdpmbaoe localopts.hodversion.cvers.ca.bingres.h.sys/LONEX.ra/rl.h 664 0 24 16 5502164167 6672 #define NRL 2 ra.h.q rl.h.p br.h.o si.h.n tm.h.m xp.h.lMakefilekMake.sysjMake.neti Make.pdpnetoh Make.pdpubaogMake.pdpbf Make.pdpmbaoe localopts.hodversion.cvers.ca.bingres.h.sys/LONEX.ra/br.h 664 0 24 16 5504532226 6655 #define NBR 0 ra.h.q rl.h.p br.h.o si.h.n tm.h.m xp.h.lMakefilekMake.sysjMake.neti Make.pdpnetoh Make.pdpubaogMake.pdpbf Make.pdpmbaoe localopts.hodversion.cvers.ca.bingres.h.sys/LONEX.ra/si.h 664 0 24 16 5502164170 6662 #define NSI 0 ra.h.q rl.h.p br.h.o si.h.n tm.h.m xp.h.lMakefilekMake.sysjMake.neti Make.pdpnetoh Make.pdpubaogMake.pdpbf Make.pdpmbaoe localopts.hodversion.cvers.ca.bingres.h.sys/LONEX.ra/tm.h 664 0 24 37 5502164171 6673 #define NTM 0 #define AVIVTM 1 h.p br.h.o si.h.n tm.h.m xp.h.lMakefilekMake.sysjMake.neti Make.pdpnetoh Make.pdpubaogMake.pdpbf Make.pdpmbaoe localopts.hodversion.cvers.ca.bingres.h.sys/LONEX.ra/xp.h 664 0 24 36 6004072536 6702 #define NXPD 0 #define NXPC 0 .h.p br.h.o si.h.n tm.h.m xp.h.lMakefilekMake.sysjMake.neti Make.pdpnetoh Make.pdpubaogMake.pdpbf Make.pdpmbaoe localopts.hodversion.cvers.ca.bingres.h.sys/LONEX.ra/Makefile 664 0 24 15417 5774272251 7644 OPTS=-DLONEX -DUCB_METER -DINET -DQUOTA -DUCB_CLIST # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # %W% (Berkeley) %G% # ######################################################### # Networking, separate I/D kernel # ######################################################### H= ../h I= /usr/include M= ../machine N1= ../net N2= ../netimp N3= ../netinet N4= ../netns N6= ../pdpif S= ../sys U= ../pdpuba MB= ../pdpmba DEFS= -DKERNEL ${OPTS} -I. -I${H} CFLAGS= -O ${DEFS} CPP= /lib/cpp -P ${DEFS} AS= /bin/as -V ED= /bin/ed SUB= sys pdp pdpuba pdpmba net pdpnet # GENERAL RULES: # scb.o MUST be loaded first, param.o MUST be loaded last, # boot.o must be loaded in the base well above 0 data. # enable34.o must be in the base segment for overlaid kernels. # Don't forget the "-i" flag for split I/D, use "-n" otherwise. # # CONF Non-network assembly binaries. scb.o must be first! # boot.o should be close to the end. # NCONF Network (network space) assembly binaries. net_scb.o # doesn't have to be first. CONF= scb.o libc_bcmp.o libc_bcopy.o libc_bzero.o libc_ffs.o \ libc_insque.o libc_ldiv.o libc_lmul.o libc_lrem.o libc_remque.o \ libc_udiv.o libc_uldiv.o libc_ulsh.o \ libc_strlen.o mch_backup.o mch_click.o mch_copy.o mch_csv.o \ mch_dump.o mch_dzpdma.o mch_KScall.o mch_profile.o \ mch_start.o mch_trap.o mch_vars.o mch_xxx.o conf.o ioconf.o boot.o NCONF= libc_bcmp.o libc_bcopy.o libc_bzero.o libc_ffs.o libc_htonl.o \ libc_htons.o libc_insque.o libc_ldiv.o libc_lmul.o libc_lrem.o \ libc_remque.o libc_strlen.o libc_udiv.o net_copy.o net_csv.o \ net_mbuf.o net_scb.o net_SKcall.o net_trap.o net_xxx.o libc_ulsh.o BASE= br.o cons.o dh.o dhu.o dhv.o dr.o dz.o hk.o ht.o init_sysent.o \ kern_clock.o kern_descrip.o kern_mman.o kern_proc.o kern_prot.o \ kern_subr.o kern_synch.o machdep.o ram.o \ rk.o ra.o rx.o si.o subr_rmap.o sys_inode.o sys_kern.o \ tm.o tty.o tty_conf.o tty_subr.o tty_tb.o ufs_alloc.o \ ufs_bio.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_namei.o \ vm_sched.o vm_text.o xp.o quota_subr.o OV1= sys_generic.o ufs_syscalls.o OV2= kern_acct.o kern_exec.o kern_exit.o kern_fork.o kern_resource.o OV3= kern_time.o sys_process.o ufs_mount.o ufs_subr.o \ uipc_syscalls.o OV4= dkbad.o kern_sig.o mem.o subr_xxx.o trap.o tty_pty.o tty_tty.o OV5= quota_kern.o quota_ufs.o quota_sys.o ufs_bmap.o \ sys_pipe.o # OV6 gets the (hopefully) never used routines OV6= clock.o dn.o init_main.o kern_pdp.o machdep2.o subr_prf.o syscalls.o \ subr_log.o toy.o vm_swap.o OV7= tmscp.o lp.o vm_swp.o rl.o mch_fpsim.o ts.o OV8= kern_sysctl.o ingreslock.o ufs_disksubr.o kern_xxx.o vm_proc.o KERNOBJ=${CONF} ${BASE} ${OV1} ${OV2} ${OV3} ${OV4} ${OV5} \ ${OV6} ${OV7} ${OV8} ${OV9} ${OV10} ${OV11} ${OV12} \ ${OV13} ${OV14} ${OV15} \ enable34.o vers.o param.o # param.o must be last! enable34.o must be in base. LD_KOBJ=${CONF} ${BASE} \ -Z ${OV1} -Z ${OV2} -Z ${OV3} -Z ${OV4} -Z ${OV5} -Z ${OV6} \ -Z ${OV7} -Z ${OV8} -Z ${OV9} -Z ${OV10} -Z ${OV11} -Z ${OV12} \ -Z ${OV13} -Z ${OV14} -Z ${OV15} -Y \ enable34.o vers.o param.o NETOBJ= ${NCONF} af.o idp_usrreq.o if.o if_acc.o if_css.o if_de.o \ if_dmc.o if_ec.o if_en.o if_ether.o if_il.o if_imp.o if_imphost.o \ if_loop.o if_qe.o if_qt.o if_sl.o if_sri.o if_uba.o if_vv.o in.o \ in_cksum.o in_pcb.o in_proto.o ip_icmp.o ip_input.o ip_output.o \ ns.o ns_error.o ns_input.o ns_ip.o ns_output.o ns_pcb.o \ ns_proto.o raw_cb.o raw_imp.o raw_ip.o \ raw_usrreq.o route.o spp_debug.o spp_usrreq.o sys_socket.o \ sys_net.o tcp_debug.o tcp_input.o tcp_output.o tcp_subr.o \ tcp_timer.o tcp_usrreq.o udp_usrreq.o uipc_domain.o uipc_mbuf.o \ uipc_proto.o uipc_socket.o uipc_socket2.o uipc_usrreq.o all: unix netnix # d.unix.o must be last object file in the dependency list! unix: ${SUB} ${KERNOBJ} d.unix.o checksys ld -X -i -o unix ${LD_KOBJ} d.unix.o size unix @echo Compacting symbol table -symcompact unix @echo Compacting strings table - this will take a few minutes -strcompact unix @echo rearranging symbols -symorder ../pdp/symbols.sort unix ./checksys unix # d.netnix.o must be the last object file in the dependency list! netnix: d.netnix.o -ld -X -i -o netnix ${NETOBJ} d.netnix.o @echo Compacting symbol table -symcompact netnix @echo Compacting strings table - this will take a few minutes -strcompact netnix @echo rearranging symbols -symorder ../pdp/symbols.sort netnix size netnix # Resolve all references between the kernel and the net. Always regenerate!!! # This was a constant source of problems during development. Should really # include ${NETOBJ} and ${KERNOBJ} on dependency line, but the pdp make doesn't # have enough table space. d.unix.o d.netnix.o: netbind FRC ld -r -d -X -i -o unix.o ${LD_KOBJ} ld -r -d -X -o netnix.o ${NETOBJ} ./netbind unix.o netnix.o rm unix.o netnix.o ${AS} - -o d.unix.o d.unix.s ${AS} - -o d.netnix.o d.netnix.s vers.o: FRC sh ../conf/newvers.sh ${CC} -c vers.c boot.o: boot.s ${CPP} boot.s > boot.i ${AS} -o boot.o boot.i rm -f boot.i param.o: ${CC} -S ${CFLAGS} param.c ${ED} - param.s < ../conf/:comm-to-bss ${AS} - -o param.o param.s rm -f param.s ioconf.o: ioconf.c ${CC} -c ${CFLAGS} ioconf.c checksys: ../conf/checksys.c ${CC} ${CFLAGS} -o $@ ../conf/checksys.c netbind: ../conf/netbind.c ${CC} ${CFLAGS} -o $@ ../conf/netbind.c sys pdp pdpuba pdpmba: make -f Make.$@ I=${I} H=${H} M=${M} AS="${AS}" CPP="${CPP}" \ CFLAGS="${CFLAGS}" ED="${ED}" net pdpnet: make -f Make.$@ I=${I} H=${H} M=${M} AS="${AS}" \ CPP="${CPP} -DSUPERVISOR" CFLAGS="${CFLAGS} -DSUPERVISOR" \ ED="${ED}" clean: rm -f unix core mklog *.o *.i assym.h genassym checksys rm -f netnix netbind d.unix.s d.netnix.s install: install -c -o root -g kmem -m 744 unix ${DESTDIR}/unix install -c -o root -g kmem -m 744 netnix ${DESTDIR}/netnix depend: FRC for i in ${SUB}; do \ make -f Make.$$i CFLAGS="${CFLAGS}" depend; done mkdep ${CFLAGS} param.c ioconf.c ../conf/checksys.c ../conf/netbind.c TAGSFILE= ${S}/tags TLIST= ${H} ${I} ${N1} ${N2} ${N3} ${N4} ${N5} ${N6} ${M} ${S} ${U} ${MB} ${SS} tags: FRC rm -f ${TAGSFILE} for i in ${TLIST}; do \ (cd ${S}; /usr/ucb/ctags -a -t $$i/*.[ch]); done /usr/bin/egrep "^ASENTRY|^ENTRY" ${M}/*.s | \ /bin/sed 's;\([^:]*\):\([^(]*\)(\([^)]*\));\3 \1 /^\2(\3)$$/;' \ >> ${TAGSFILE} /usr/bin/sort -o ${TAGSFILE} ${TAGSFILE} FRC: # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. , IT WILL GO AWAY. RUNNING) qesetup(sc); qeinit(unit); } /* * Initialize a ring descriptor with mbuf allocation side effects */ qeinitdesc(rp, addr, len) register struct qe_ring *rp; caddr_t addr; /* mapped address */ int lensys/LONEX.ra/Make.sys 640 0 24 5010 5773670125 7560 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # 2.2 (2.11BSD GTE) 1994/04/13 # S= ../sys VPATH= ../sys CFILES= ${S}/init_main.c ${S}/init_sysent.c ${S}/kern_acct.c \ ${S}/kern_clock.c ${S}/kern_descrip.c ${S}/kern_exec.c \ ${S}/kern_exit.c ${S}/kern_fork.c ${S}/kern_mman.c \ ${S}/kern_proc.c ${S}/kern_prot.c ${S}/kern_resource.c \ ${S}/kern_sig.c ${S}/kern_subr.c ${S}/kern_sysctl.c \ ${S}/kern_synch.c ${S}/kern_time.c ${S}/kern_xxx.c \ ${S}/quota_sys.c ${S}/quota_kern.c ${S}/quota_ufs.c \ ${S}/quota_subr.c ${S}/subr_log.c ${S}/subr_prf.c ${S}/subr_rmap.c \ ${S}/subr_xxx.c ${S}/sys_generic.c ${S}/sys_inode.c \ ${S}/sys_kern.c ${S}/sys_pipe.c \ ${S}/ingreslock.c \ ${S}/sys_process.c ${S}/syscalls.c ${S}/tty.c ${S}/tty_conf.c \ ${S}/tty_pty.c ${S}/tty_subr.c ${S}/tty_tb.c ${S}/tty_tty.c \ ${S}/ufs_alloc.c ${S}/ufs_bio.c ${S}/ufs_bmap.c \ ${S}/ufs_dsort.c ${S}/ufs_fio.c ${S}/ufs_inode.c \ ${S}/ufs_mount.c ${S}/ufs_namei.c ${S}/ufs_subr.c \ ${S}/ufs_disksubr.c \ ${S}/ufs_syscalls.c ${S}/uipc_syscalls.c ${S}/vm_proc.c \ ${S}/vm_sched.c ${S}/vm_swap.c ${S}/vm_swp.c ${S}/vm_text.c OBJS= init_main.o init_sysent.o kern_acct.o kern_clock.o \ kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o \ kern_proc.o kern_prot.o kern_resource.o kern_sig.o kern_sysctl.o \ kern_subr.o kern_synch.o kern_time.o kern_xxx.o quota_sys.o \ quota_kern.o quota_ufs.o quota_subr.o subr_log.o subr_prf.o subr_rmap.o \ ingreslock.o \ subr_xxx.o sys_generic.o sys_inode.o sys_kern.o \ sys_pipe.o sys_process.o syscalls.o tty.o tty_conf.o tty_pty.o \ tty_subr.o tty_tb.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o \ ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o \ ufs_subr.o ufs_syscalls.o uipc_syscalls.o vm_proc.o vm_sched.o \ ufs_disksubr.o \ vm_swap.o vm_swp.o vm_text.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s all: ${OBJS} depend: mkdep -f Make.sys ${CFLAGS} ${CFILES} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. ys: ../conf/checksys.c ${CC} ${CFLAGS} -o $@ ../conf/checksys.c netbind: ../conf/netbind.c ${CC} ${CFLAGS} -o $@ ../conf/netbind.c sys pdp pdpuba pdpmba: make -f Make.$@ I=${I} H=${H} M=${M} AS="${AS}" CPP="${CPP}" \ CFLAGS="${CFLAGS}" ED="${ED}" net pdpnet: make -f Make.$@ I=${I} H=${H} M=${M} AS="${AS}" \ CPP="${CPP} -DSUPERVISOR" CFLAGS="${CFLAGS} -DSUPERVISOR" \ ED="${ED}" clean: rm -f unix core mklog *.o *.i assym.h genassym checksys rm -f netnix netbind d.unix.s d.netnsys/LONEX.ra/Make.net 664 0 24 5022 5502164214 7524 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # %W% (Berkeley) %G% # N1= ../net N1C= ${N1}/af.c ${N1}/if.c ${N1}/if_loop.c ${N1}/if_sl.c \ ${N1}/raw_cb.c ${N1}/raw_usrreq.c ${N1}/route.c N1O= af.o if.o if_loop.o if_sl.o raw_cb.o raw_usrreq.o route.o N2= ../netimp N2C= ${N2}/if_imp.c ${N2}/if_imphost.c ${N2}/raw_imp.c N2O= if_imp.o if_imphost.o raw_imp.o N3= ../netinet N3C= ${N3}/if_ether.c ${N3}/in.c ${N3}/in_pcb.c ${N3}/in_proto.c \ ${N3}/ip_icmp.c ${N3}/ip_input.c ${N3}/ip_output.c \ ${N3}/raw_ip.c ${N3}/tcp_debug.c ${N3}/tcp_input.c \ ${N3}/tcp_output.c ${N3}/tcp_subr.c ${N3}/tcp_timer.c \ ${N3}/tcp_usrreq.c ${N3}/udp_usrreq.c N3O= if_ether.o in.o in_pcb.o in_proto.o ip_icmp.o ip_input.o \ ip_output.o raw_ip.o tcp_debug.o tcp_input.o tcp_output.o \ tcp_subr.o tcp_timer.o tcp_usrreq.o udp_usrreq.o N5= ../netns N5C= ${N5}/ns.c ${N5}/ns_pcb.c ${N5}/ns_proto.c ${N5}/ns_error.c \ ${N5}/ns_ip.c ${N5}/ns_input.c ${N5}/ns_output.c \ ${N5}/idp_usrreq.c ${N5}/spp_usrreq.c ${N5}/spp_debug.c N5O= ns.o ns_pcb.o ns_proto.o ns_error.o ns_ip.o ns_input.o \ ns_output.o idp_usrreq.o spp_usrreq.o spp_debug.o N6= ../pdpif N6C= ${N6}/if_acc.c ${N6}/if_css.c ${N6}/if_de.c ${N6}/if_dmc.c \ ${N6}/if_ec.c ${N6}/if_en.c ${N6}/if_il.c ${N6}/if_qe.c \ ${N6}/if_qt.c ${N6}/if_sri.c ${N6}/if_uba.c ${N6}/if_vv.c N6O= if_acc.o if_css.o if_de.o if_dmc.o if_ec.o if_en.o if_il.o \ if_qe.o if_qt.o if_sri.o if_uba.o if_vv.o S= ../sys SC= ${S}/sys_socket.c ${S}/sys_net.c ${S}/uipc_domain.c \ ${S}/uipc_mbuf.c ${S}/uipc_proto.c ${S}/uipc_socket.c \ ${S}/uipc_socket2.c ${S}/uipc_usrreq.c SO= sys_socket.o sys_net.o uipc_domain.o uipc_mbuf.o uipc_proto.o \ uipc_socket.o uipc_socket2.o uipc_usrreq.o VPATH= ../net:../netimp:../netinet:../netns:../pdpif:../sys SRCS= ${N1C} ${N2C} ${N3C} ${N5C} ${N6C} ${SC} OBJS= ${N1O} ${N2O} ${N3O} ${N5O} ${N6O} ${SO} .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < NETSPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s all: ${OBJS} depend: mkdep -f Make.net ${CFLAGS} ${SRCS} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. N1C= ${N1}/af.c ${N1}/if.c ${N1}/if_loop.c ${N1}/if_sl.c \ ${N1}/raw_cb.c ${N1}/raw_usrreq.c ${N1}/route.c N1O= af.o if.o if_loop.o if_sl.o raw_cb.o raw_usrreq.o route.o N2= ../netimp N2C= ${N2}/if_imp.c ${N2}/if_imphost.c ${N2}/raw_imp.c N2O= if_imp.o if_imphost.o raw_imp.o N3= ../netinet N3C= ${N3}/if_ether.c ${N3}/in.c ${N3}/in_pcb.c ${N3}/in_proto.c \ ${N3}/ip_icmp.c ${N3}/ip_input.c ${N3}/ip_output.c \ ${N3}/raw_ip.c ${N3}/tcp_debug.c ${N3}/tcp_input.c \ ${N3}/tcp_output.c $sys/LONEX.ra/Make.pdpnet 640 0 24 2701 5773670136 10242 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # 2.0 (2.11BSD GTE) 1995/05/21 # M= ../machine VPATH= ../machine CFILES= ${M}/enable34.c ${M}/in_cksum.c COBJS= enable34.o in_cksum.o SFILES= ${M}/libc_htonl.s ${M}/libc_htons.s ${M}/net_copy.s \ ${M}/net_csv.s ${M}/net_mbuf.s ${M}/net_scb.s ${M}/net_SKcall.s \ ${M}/net_trap.s ${M}/net_xxx.s SOBJS= libc_htonl.o libc_htons.o mch_KScall.o net_copy.o net_csv.o \ net_mbuf.o net_scb.o net_SKcall.o net_trap.o net_xxx.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < NETSPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s .s.o: ${CPP} $*.s | ${AS} -u -o $*.o all: ${COBJS} ${SOBJS} in_cksum.o: ${CC} ${CFLAGS} -S ${M}/in_cksum.c ${ED} - < ${M}/cksum-fix > /dev/null in_cksum.s ${ED} - < NETSPLFIX in_cksum.s ${AS} - -o $@ in_cksum.s rm -f in_cksum.s depend: assym.h mkdep -f Make.pdpnet ${CFLAGS} ${CFILES} ${SFILES} assym.h: make -f Make.pdp CFLAGS="${CFLAGS}" assym.h # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. s.o ns_pcb.o ns_proto.o ns_error.o ns_ip.o ns_input.o \ ns_ousys/LONEX.ra/Make.pdpuba 664 0 24 2200 5502164215 10205 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # %W% (Berkeley) %G% # U= ../pdpuba VPATH= ../pdpuba CFILES= ${U}/br.c ${U}/dh.c ${U}/dn.c ${U}/dhu.c ${U}/dhv.c ${U}/dkbad.c \ ${U}/dr.c ${U}/dz.c ${U}/hk.c ${U}/ht.c ${U}/lp.c ${U}/ra.c ${U}/rk.c \ ${U}/rl.c ${U}/rx.c ${U}/si.c ${U}/tm.c ${U}/tmscp.c ${U}/ts.c ${U}/xp.c OBJS= br.o dh.o dhu.o dhv.o dkbad.o dn.o dr.o dz.o hk.o ht.o lp.o ra.o rk.o \ rl.o rx.o si.o tm.o tmscp.o ts.o xp.o dn.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s all: ${OBJS} depend: mkdep -f Make.pdpuba ${CFLAGS} ${CFILES} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. dev/null in_cksum.s ${ED} - < NETSPLFIX in_cksum.s ${AS} - -o $@ in_cksum.s rm -f in_cksum.s depend: assym.h mkdep -f Make.pdpnet ${CFLAGS} ${CFILES} ${SFILES} assym.h: make -f Make.pdp CFLAGS="${CFLAGS}" assym.h # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. s.o ns_pcb.o ns_proto.o ns_error.o ns_ip.o ns_input.o \ ns_ousys/LONEX.ra/Make.pdp 640 0 24 5036 5773670135 7536 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # 2.0 (2.11BSD GTE) 1995/05/21 # M= ../machine VPATH= ../machine CFILES= ${M}/clock.c ${M}/conf.c ${M}/cons.c ${M}/kern_pdp.c \ ${M}/machdep.c ${M}/machdep2.c ${M}/mem.c ${M}/ram.c ${M}/trap.c COBJS= clock.o conf.o cons.o kern_pdp.o machdep.o machdep2.o mem.o \ ram.o trap.o # We compile mch_KScall here rather than in Make.pdpnet so that it gets # compiled with the right flags. This means that it gets compiled for all # kernel, but is only included in the networking kernel. As it only takes # a few seconds to compile it, it isn't worth trashing up Make.pdpnet to # compile it there. SFILES= ${M}/libc_bcmp.s ${M}/libc_bcopy.s ${M}/libc_bzero.s \ ${M}/libc_ffs.s ${M}/libc_insque.s ${M}/libc_ldiv.s \ ${M}/libc_lmul.s ${M}/libc_lrem.s ${M}/libc_remque.s \ ${M}/libc_uldiv.s ${M}/libc_ulsh.s \ ${M}/libc_strlen.s ${M}/libc_udiv.s ${M}/mch_backup.s \ ${M}/mch_click.s ${M}/mch_copy.s ${M}/mch_csv.s ${M}/mch_dump.s \ ${M}/mch_dzpdma.s ${M}/mch_fpsim.s ${M}/mch_KScall.s \ ${M}/mch_profile.s ${M}/mch_start.s ${M}/mch_trap.s \ ${M}/mch_vars.s ${M}/mch_xxx.s ${M}/scb.s ${M}/toy.s SOBJS= libc_bcmp.o libc_bcopy.o libc_bzero.o libc_ffs.o libc_insque.o \ libc_ldiv.o libc_lmul.o libc_lrem.o libc_remque.o libc_strlen.o \ libc_uldiv.o libc_ulsh.o \ libc_udiv.o mch_backup.o mch_click.o mch_copy.o mch_csv.o \ mch_dump.o mch_dzpdma.o mch_fpsim.o mch_KScall.o mch_profile.o \ mch_start.o mch_trap.o mch_vars.o mch_xxx.o scb.o toy.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s .s.o: ${CPP} $*.s | ${AS} -u -o $*.o all: assym.h ${COBJS} ${SOBJS} ../pdp/symbols.sort assym.h: genassym ./genassym > $@ genassym: ${CC} -O ${CFLAGS} ${M}/genassym.c -o $@ # it's a tab character in the sed statement below not a space. ../pdp/symbols.sort: ../pdp/symbols.raw grep -v '^#' ../pdp/symbols.raw \ | sed 's/^ //' | sort -u > ../pdp/symbols.sort depend: assym.h mkdep -f Make.pdp ${CFLAGS} ${CFILES} ${SFILES} ${M}/genassym.c # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. ${CC} ${CFLAGS} -o $@ ../conf/checksys.c netbind: ../conf/netbind.c ${CC} ${CFLAGS} -o $@ ../conf/netbind.c sys pdp pdpuba pdpmba: make -f Make.$@ I=${I} H=${H} M=${M} AS="${AS}" CPP="${CPP}" \ CFLAGS="${CFLAGS}" ED="${ED}" net pdpnet: make -f Make.$@ I=${I} H=${H} M=${M} AS="${AS}" \ CPP="${CPP} -DSUPERVISOR" CFLAGS="${CFLAGS} -DSUPERVISOR" \ ED="${ED}" clean: rm -f unix core mklog *.o *.i assym.h genassym checksys rm -f netnix netbind d.unix.s d.netnsys/LONEX.ra/Make.pdpmba 664 0 24 1466 5502164215 10212 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # %W% (Berkeley) %G% # U= ../pdpmba VPATH= ../pdpmba CFILES= OBJS= .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s all: ${OBJS} depend: mkdep -f Make.pdpmba ${CFLAGS} ${CFILES} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. ke.pdpnet so that it gets # compiled with the right flags. This means that it gets compiled for all # kernel, but is only included in the networking kernel. As it only takes # a few seconds to compilesys/LONEX.ra/localopts.h 664 0 24 516 5502164216 10275 /* * This file is generated by the configuration script sys/conf/config. * * It contains a list the kernel options not prepended to the Makefile * as -Dxxxx commands to the compiler. MAXMEM was moved to param.h leaving * only LINEHZ and EXTERNALITIMES to be placed in localopts.h */ #define LINEHZ 60 #define EXTERNALITIMES 1 sys/LONEX.ra/version 640 0 24 3 5774413730 7466 25 r ra.h.q rl.h.p br.h.o si.h.n tm.h.m xp.h.lMakefilekMake.sysjMake.neti Make.pdpnetoh Make.pdpubaogMake.pdpbf Make.pdpmbaoe localopts.hodversion.cvers.ca.bingres.h.sys/LONEX.ra/vers.c 640 0 24 202 5774413730 7242 char version[] = "2.11 BSD UNIX #25: Wed Jun 28 20:02:47 PDT 1995\n schultzy0@wlonex.iipo.gtegsc.com:/usr/src/sys/LONEX.ra\n"; i Make.pdpnetoh Make.pdpubaogMake.pdpbf Make.pdpmbaoe localopts.hodversion.cvers.ca.bingres.h.sys/LONEX.ra/ingres.h 644 0 24 22 5732466615 7547 #define NINGRES 1 .h.q rl.h.p br.h.o si.h.n tm.h.m xp.h.lMakefilekMake.sysjMake.neti Make.pdpnetoh Make.pdpubaogMake.pdpbf Make.pdpmbaoe localopts.hodversion.cvers.ca.bingres.h.include/ 755 0 12 0 6001105336 5360 include/pascal/ 755 0 12 0 4627702047 6641 include/pascal/unixio.h 444 0 12 517 4013175034 10360 (* Copyright (c) 1979 Regents of the University of California *) const sccsid = '@(#)unixio.h 1.1 6/17/81'; type fileptr = record cnt :integer end; function TELL( var fptr :text) {returns} :fileptr; external; procedure SEEK( var fptr :text; var cnt :fileptr); external; procedure APPEND( var fptr :text); external; include/pascal/unixio.i 444 0 12 2016 4013175036 10377 (* Copyright (c) 1979 Regents of the University of California *) const sccsid = '@(#)unixio.i 1.1 6/17/81'; type fileptr = record cnt :integer end; function TELL( var fptr :text) {returns} :fileptr; var filesize, headsize, tailsize :integer; result :fileptr; begin tailsize := 0; while not eof(fptr) do begin get(fptr); tailsize := tailsize + 1 end; filesize := 0; reset(fptr); while not eof(fptr) do begin get(fptr); filesize := filesize + 1 end; reset(fptr); for headsize := 1 to filesize - tailsize do get(fptr); result.cnt := headsize; TELL := result end; procedure SEEK( var fptr :text; var cnt :fileptr); var i :integer; begin reset(fptr); for i := 1 to cnt.cnt do get(fptr) end; procedure APPEND( var fptr :text); var tmp :text; begin rewrite(tmp); reset(fptr); while not eof(fptr) do begin if eoln(fptr) then writeln(tmp) else write(tmp, fptr^); get(fptr) end; reset(tmp); rewrite(fptr); while not eof(tmp) do begin if eoln(tmp) then writeln(fptr) else write(fptr, tmp^); get(tmp) end end; worth trashing up Make.pdpnet to # compile it there. SFILES= ${M}/libc_bcmp.s ${M}/libc_bcopy.s ${M}/libc_bzero.s \ ${M}/libc_ffs.s ${M}/libc_insque.s ${M}/libc_ldiv.s \ ${M}/libc_lmul.s ${M}/libc_lrem.s ${M}/libc_remque.s \ ${M}/libc_uldiv.s ${M}/libc_ulsh.s \ ${M}/libc_strlen.s ${M}/libc_udiv.s ${M}/mch_backup.s \ ${M}/mch_click.s ${M}/mch_copy.s ${M}/mch_csv.s ${M}/mch_dump.s \ ${M}/mch_dzpdma.s ${M}/mch_fpsim.s ${M}/mch_KScall.s \ ${M}/mch_profile.s ${M}/mch_start.s ${M}/mch_trap.sinclude/protocols/ 755 0 12 0 4627702106 7416 include/protocols/dumprestor.h 444 0 12 1676 4622313424 12064 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dumprestor.h 5.1 (Berkeley) 12/13/86 */ #define NTREC 10 #define MLEN 16 #define MSIZ 4096 #define TS_TAPE 1 #define TS_INODE 2 #define TS_BITS 3 #define TS_ADDR 4 #define TS_END 5 #define TS_CLRI 6 #define OFS_MAGIC (int)60011 #define NFS_MAGIC (int)60012 #define MAGIC OFS_MAGIC #define CHECKSUM (int)84446 struct spcl { int c_type; time_t c_date; time_t c_ddate; int c_volume; daddr_t c_tapea; ino_t c_inumber; int c_magic; int c_checksum; struct dinode c_dinode; int c_count; char c_addr[DEV_BSIZE]; } spcl; struct idates { char id_name[16]; char id_incno; time_t id_ddate; }; #define DUMPOUTFMT "%-16s %c %s" /* for printf */ /* name, incno, ctime(date) */ #define DUMPINFMT "%16s %c %[^\n]\n" /* inverse for scanf */ f eoln(tmp) then writeln(fptr) else write(fptr, tmp^); get(tinclude/protocols/routed.h 444 0 12 3455 4066577465 11202 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)protocol.h 5.1 (Berkeley) 6/4/85 */ /* * Routing Information Protocol * * Derived from Xerox NS Routing Information Protocol * by changing 32-bit net numbers to sockaddr's and * padding stuff to 32-bit boundaries. */ #define RIPVERSION 1 struct netinfo { struct sockaddr rip_dst; /* destination net/host */ u_long rip_metric; /* cost of route */ }; struct rip { u_char rip_cmd; /* request/response */ u_char rip_vers; /* protocol version # */ u_char rip_res1[2]; /* pad to 32-bit boundary */ union { struct netinfo ru_nets[1]; /* variable length... */ char ru_tracefile[1]; /* ditto ... */ } ripun; #define rip_nets ripun.ru_nets #define rip_tracefile ripun.ru_tracefile }; /* * Packet types. */ #define RIPCMD_REQUEST 1 /* want info */ #define RIPCMD_RESPONSE 2 /* responding to request */ #define RIPCMD_TRACEON 3 /* turn tracing on */ #define RIPCMD_TRACEOFF 4 /* turn it off */ #define RIPCMD_MAX 5 #ifdef RIPCMDS char *ripcmds[RIPCMD_MAX] = { "#0", "REQUEST", "RESPONSE", "TRACEON", "TRACEOFF" }; #endif #define HOPCNT_INFINITY 16L /* per Xerox NS */ #define MAXPACKETSIZE 512 /* max broadcast size */ /* * Timer values used in managing the routing table. * Every update forces an entry's timer to be reset. After * EXPIRE_TIME without updates, the entry is marked invalid, * but held onto until GARBAGE_TIME so that others may * see it "be deleted". */ #define TIMER_RATE 30 /* alarm clocks every 30 seconds */ #define SUPPLY_INTERVAL 30 /* time to supply tables */ #define EXPIRE_TIME 180 /* time to mark entry invalid */ #define GARBAGE_TIME 240 /* time to garbage collect */ dzpdma.o mch_fpsim.o mch_KScall.o mch_profile.o \ mch_start.o mch_trap.o mch_vars.o mch_xxx.o scb.o toy.o .c.o: ${CC} ${CFLAGS} -S $*.c ${ED} - < SPLFIX $*.s ${AS} - -o $*.o $*.s rm -f $*.s .s.o: ${CPP} include/protocols/rwhod.h 444 0 12 1705 4114572740 11000 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)rwhod.h 5.1 (Berkeley) 5/28/85 */ /* * rwho protocol packet format. */ struct outmp { char out_line[8]; /* tty name */ char out_name[8]; /* user id */ long out_time; /* time on */ }; struct whod { char wd_vers; /* protocol version # */ char wd_type; /* packet type, see below */ char wd_pad[2]; long wd_sendtime; /* time stamp by sender */ long wd_recvtime; /* time stamp applied by receiver */ char wd_hostname[32]; /* hosts's name */ long wd_loadav[3]; /* load average as in uptime */ long wd_boottime; /* time system booted */ struct whoent { struct outmp we_utmp; /* active tty info */ long we_idle; /* tty idle time */ } wd_we[1024 / sizeof (struct whoent)]; }; #define WHODVERSION 1 #define WHODTYPE_STATUS 1 /* host status */ #define RIPCMD_RESPONSE 2 /* responding to request */ #deinclude/protocols/talkd.h 444 0 12 6143 4361051526 10753 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)talkd.h 5.2 (Berkeley) 3/13/86 */ #include #include /* * This describes the protocol used by the talk server and clients. * * The talk server acts a repository of invitations, responding to * requests by clients wishing to rendezvous for the purpose of * holding a conversation. In normal operation, a client, the caller, * initiates a rendezvous by sending a CTL_MSG to the server of * type LOOK_UP. This causes the server to search its invitation * tables to check if an invitation currently exists for the caller * (to speak to the callee specified in the message). If the lookup * fails, the caller then sends an ANNOUNCE message causing the server * to broadcast an announcement on the callee's login ports requesting * contact. When the callee responds, the local server uses the * recorded invitation to respond with the appropriate rendezvous * address and the caller and callee client programs establish a * stream connection through which the conversation takes place. */ /* * Client->server request message format. */ typedef struct { u_char vers; /* protocol version */ u_char type; /* request type, see below */ u_char answer; /* not used */ u_char pad; u_long id_num; /* message id */ struct sockaddr addr; struct sockaddr ctl_addr; long pid; /* caller's process id */ #define NAME_SIZE 12 char l_name[NAME_SIZE];/* caller's name */ char r_name[NAME_SIZE];/* callee's name */ #define TTY_SIZE 16 char r_tty[TTY_SIZE];/* callee's tty name */ } CTL_MSG; /* * Server->client response message format. */ typedef struct { u_char vers; /* protocol version */ u_char type; /* type of request message, see below */ u_char answer; /* respose to request message, see below */ u_char pad; u_long id_num; /* message id */ struct sockaddr addr; /* address for establishing conversation */ } CTL_RESPONSE; #define TALK_VERSION 1 /* protocol version */ /* message type values */ #define LEAVE_INVITE 0 /* leave invitation with server */ #define LOOK_UP 1 /* check for invitation by callee */ #define DELETE 2 /* delete invitation by caller */ #define ANNOUNCE 3 /* announce invitation by caller */ /* answer values */ #define SUCCESS 0 /* operation completed properly */ #define NOT_HERE 1 /* callee not logged in */ #define FAILED 2 /* operation failed for unexplained reason */ #define MACHINE_UNKNOWN 3 /* caller's machine name unknown */ #define PERMISSION_DENIED 4 /* callee's tty doesn't permit announce */ #define UNKNOWN_REQUEST 5 /* request has invalid type value */ #define BADVERSION 6 /* request has invalid protocol version */ #define BADADDR 7 /* request has invalid addr value */ #define BADCTLADDR 8 /* request has invalid ctl_addr value */ /* * Operational parameters. */ #define MAX_LIFE 60 /* max time daemon saves invitations */ /* RING_WAIT should be 10's of seconds less than MAX_LIFE */ #define RING_WAIT 30 /* time to wait before resending invitation */ -m 744 netnix ${DESTDIR}/netnix depend: FRC for i in ${SUB}; do \ make -f Make.$$i CFLAGS="${CFLAGS}" depend; done mkdep ${CFLAGS} param.c ioconf.c ../conf/checksys.c ../conf/netbind.c TAGSFILE= ${S}/tags TLIST= ${H} ${I} ${N1} ${N2} ${N3} ${N4} ${N5} ${N6} ${M} ${S} ${U} ${MB} ${SS} tags: FRC rm -f ${TAGSFILE} for i in ${TLIST}; do \ (cd ${S}; /usr/ucb/ctags -a -t $$i/*.[ch]); done /usr/bin/egrep include/protocols/timed.h 444 0 12 4400 4066577472 10767 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ /* @(#)timed.h 1.6 (Berkeley) 5/28/86 */ /* * Time Synchronization Protocol */ #define TSPVERSION 1 #define ANYADDR NULL struct tsp { u_char tsp_type; u_char tsp_vers; u_short tsp_seq; union { struct timeval tspu_time; char tspu_hopcnt; } tsp_u; char tsp_name[MAXHOSTNAMELEN]; }; #define tsp_time tsp_u.tspu_time #define tsp_hopcnt tsp_u.tspu_hopcnt /* * Command types. */ #define TSP_ANY 0 /* match any types */ #define TSP_ADJTIME 1 /* send adjtime */ #define TSP_ACK 2 /* generic acknowledgement */ #define TSP_MASTERREQ 3 /* ask for master's name */ #define TSP_MASTERACK 4 /* acknowledge master request */ #define TSP_SETTIME 5 /* send network time */ #define TSP_MASTERUP 6 /* inform slaves that master is up */ #define TSP_SLAVEUP 7 /* slave is up but not polled */ #define TSP_ELECTION 8 /* advance candidature for master */ #define TSP_ACCEPT 9 /* support candidature of master */ #define TSP_REFUSE 10 /* reject candidature of master */ #define TSP_CONFLICT 11 /* two or more masters present */ #define TSP_RESOLVE 12 /* masters' conflict resolution */ #define TSP_QUIT 13 /* reject candidature if master is up */ #define TSP_DATE 14 /* reset the time (date command) */ #define TSP_DATEREQ 15 /* remote request to reset the time */ #define TSP_DATEACK 16 /* acknowledge time setting */ #define TSP_TRACEON 17 /* turn tracing on */ #define TSP_TRACEOFF 18 /* turn tracing off */ #define TSP_MSITE 19 /* find out master's site */ #define TSP_MSITEREQ 20 /* remote master's site request */ #define TSP_TEST 21 /* for testing election algo */ #define TSP_SETDATE 22 /* New from date command */ #define TSP_SETDATEREQ 23 /* New remote for above */ #define TSP_LOOP 24 /* loop detection packet */ #define TSPTYPENUMBER 25 #ifdef TSPTYPES char *tsptype[TSPTYPENUMBER] = { "ANY", "ADJTIME", "ACK", "MASTERREQ", "MASTERACK", "SETTIME", "MASTERUP", "SLAVEUP", "ELECTION", "ACCEPT", "REFUSE", "CONFLICT", "RESOLVE", "QUIT", "DATE", "DATEREQ", "DATEACK", "TRACEON", "TRACEOFF", "MSITE", "MSITEREQ", "TEST", "SETDATE", "SETDATEREQ", "LOOP" }; #endif ame */ #define TSP_MASTERACK 4 /* acknowledge master request */ #define TSP_SETTIME 5 /* send network time */ #define TSP_MASTERUP 6 /* inform slaves that master is up */ #define TSP_SLAVEUP 7 /* slave is up but not polled */ #define TSP_ELECTION 8 /include/arpa/ 755 0 12 0 5526060277 6322 include/arpa/ftp.h 444 0 12 5045 4400442547 7345 /* * Copyright (c) 1983, 1989 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)ftp.h 5.4 (Berkeley) 2/21/89 */ /* * Definitions for FTP * See RFC-765 */ /* * Reply codes. */ #define PRELIM 1 /* positive preliminary */ #define COMPLETE 2 /* positive completion */ #define CONTINUE 3 /* positive intermediate */ #define TRANSIENT 4 /* transient negative completion */ #define ERROR 5 /* permanent negative completion */ /* * Type codes */ #define TYPE_A 1 /* ASCII */ #define TYPE_E 2 /* EBCDIC */ #define TYPE_I 3 /* image */ #define TYPE_L 4 /* local byte size */ #ifdef FTP_NAMES char *typenames[] = {"0", "ASCII", "EBCDIC", "Image", "Local" }; #endif /* * Form codes */ #define FORM_N 1 /* non-print */ #define FORM_T 2 /* telnet format effectors */ #define FORM_C 3 /* carriage control (ASA) */ #ifdef FTP_NAMES char *formnames[] = {"0", "Nonprint", "Telnet", "Carriage-control" }; #endif /* * Structure codes */ #define STRU_F 1 /* file (no record structure) */ #define STRU_R 2 /* record structure */ #define STRU_P 3 /* page structure */ #ifdef FTP_NAMES char *strunames[] = {"0", "File", "Record", "Page" }; #endif /* * Mode types */ #define MODE_S 1 /* stream */ #define MODE_B 2 /* block */ #define MODE_C 3 /* compressed */ #ifdef FTP_NAMES char *modenames[] = {"0", "Stream", "Block", "Compressed" }; #endif /* * Record Tokens */ #define REC_ESC '\377' /* Record-mode Escape */ #define REC_EOR '\001' /* Record-mode End-of-Record */ #define REC_EOF '\002' /* Record-mode End-of-File */ /* * Block Header */ #define BLK_EOR 0x80 /* Block is End-of-Record */ #define BLK_EOF 0x40 /* Block is End-of-File */ #define BLK_ERRORS 0x20 /* Block is suspected of containing errors */ #define BLK_RESTART 0x10 /* Block is Restart Marker */ #define BLK_BYTECOUNT 2 /* Bytes in this block */ caller's machine name unknown */ #define PERMISSION_DENIED 4 /* callee's tty doesn't permit announce */ #define UNKNOWN_REQUEST 5 /* request has invalid type value */ #define BADVERSION 6 /* request has invalid protocol version */ #define BADADDR 7 /* request has invalid addr value */ #define BADCTLADDR 8 /* request has invalid ctl_addr value */ /* * Operational parameters. */ #define MAX_LIFE 60 /* max time daemon saves invitations */ /* RING_WAIT should be 10's ofinclude/arpa/inet.h 444 0 12 2105 5511210405 7473 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)inet.h 5.2.2 (2.11BSD GTE) 12/31/93 */ /* * External definitions for * functions in inet(3N) */ unsigned long inet_addr(); char *inet_ntoa(); struct in_addr inet_makeaddr(); unsigned long inet_network(); unsigned long inet_netof(); unsigned long inet_lnaof(); /* transient negative completion */ #define ERROR 5 /* permanent negative completion */ /* * Type codes */ #define TYPE_A 1 /* ASCII */ #define TYPE_E 2 /* EBCDIC */ #define TYPE_I 3 /* image */ #define TYPE_L 4 /* local byte size */ #ifdef FTP_NAMES char *typenames[] = {"0", "ASCII", "EBCDIC", "Image", "Local" }; #endif /* * Form codes */ #define FORM_N 1 /* non-print */ #define FORM_T 2 /* telnet format effectors */ #defininclude/arpa/nameser.h 444 0 12 17263 5514435272 10237 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)nameser.h 5.20.1 (2.11BSD GTE) 12/31/93 */ /* * Define constants based on rfc883 */ #define PACKETSZ 512 /* maximum packet size */ #define MAXDNAME 256 /* maximum domain name */ #define MAXCDNAME 255 /* maximum compressed domain name */ #define MAXLABEL 63 /* maximum length of domain label */ /* Number of bytes of fixed size data in query structure */ #define QFIXEDSZ 4 /* number of bytes of fixed size data in resource record */ #define RRFIXEDSZ 10 /* * Internet nameserver port number */ #define NAMESERVER_PORT 53 /* * Currently defined opcodes */ #define QUERY 0x0 /* standard query */ #define IQUERY 0x1 /* inverse query */ #define STATUS 0x2 /* nameserver status query */ /*#define xxx 0x3 /* 0x3 reserved */ /* non standard */ #define UPDATEA 0x9 /* add resource record */ #define UPDATED 0xa /* delete a specific resource record */ #define UPDATEDA 0xb /* delete all nemed resource record */ #define UPDATEM 0xc /* modify a specific resource record */ #define UPDATEMA 0xd /* modify all named resource record */ #define ZONEINIT 0xe /* initial zone transfer */ #define ZONEREF 0xf /* incremental zone referesh */ /* * Currently defined response codes */ #define NOERROR 0 /* no error */ #define FORMERR 1 /* format error */ #define SERVFAIL 2 /* server failure */ #define NXDOMAIN 3 /* non existent domain */ #define NOTIMP 4 /* not implemented */ #define REFUSED 5 /* query refused */ /* non standard */ #define NOCHANGE 0xf /* update failed to change db */ /* * Type values for resources and queries */ #define T_A 1 /* host address */ #define T_NS 2 /* authoritative server */ #define T_MD 3 /* mail destination */ #define T_MF 4 /* mail forwarder */ #define T_CNAME 5 /* connonical name */ #define T_SOA 6 /* start of authority zone */ #define T_MB 7 /* mailbox domain name */ #define T_MG 8 /* mail group member */ #define T_MR 9 /* mail rename name */ #define T_NULL 10 /* null resource record */ #define T_WKS 11 /* well known service */ #define T_PTR 12 /* domain name pointer */ #define T_HINFO 13 /* host information */ #define T_MINFO 14 /* mailbox information */ #define T_MX 15 /* mail routing information */ #define T_TXT 16 /* non standard */ #define T_UINFO 100 /* user (finger) information */ #define T_UID 101 /* user ID */ #define T_GID 102 /* group ID */ #define T_UNSPEC 103 /* Unspecified format (binary data) */ /* Query type values which do not appear in resource records */ #define T_AXFR 252 /* transfer zone of authority */ #define T_MAILB 253 /* transfer mailbox records */ #define T_MAILA 254 /* transfer mail agent records */ #define T_ANY 255 /* wildcard match */ /* * Values for class field */ #define C_IN 1 /* the arpa internet */ #define C_CHAOS 3 /* for chaos net at MIT */ #define C_HS 4 /* Query class values which do not appear in resource records */ #define C_ANY 255 /* wildcard match */ /* * Status return codes for T_UNSPEC conversion routines */ #define CONV_SUCCESS 0 #define CONV_OVERFLOW -1 #define CONV_BADFMT -2 #define CONV_BADCKSUM -3 #define CONV_BADBUFLEN -4 #ifndef BYTE_ORDER #define LITTLE_ENDIAN 1234 /* least-significant byte first (vax) */ #define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */ #define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long (pdp) */ #if defined(vax) || defined(ns32000) || defined(sun386) || \ defined(BIT_ZERO_ON_RIGHT) #define BYTE_ORDER LITTLE_ENDIAN #endif #if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \ defined(is68k) || defined (tahoe) || defined (BIT_ZERO_ON_LEFT) #define BYTE_ORDER BIG_ENDIAN #endif #endif /* BYTE_ORDER */ #if defined(pdp11) #define BYTE_ORDER PDP_ENDIAN #endif #ifndef BYTE_ORDER /* you must determine what the correct bit order is for your compiler */ UNDEFINED_BIT_ORDER; #endif /* * Structure for query header, the order of the fields is machine and * compiler dependent, in our case, the bits within a byte are assignd * least significant first, while the order of transmition is most * significant first. This requires a somewhat confusing rearrangement. */ typedef struct { u_short id; /* query identification number */ #if BYTE_ORDER == BIG_ENDIAN /* fields in third byte */ u_char qr:1; /* response flag */ u_char opcode:4; /* purpose of message */ u_char aa:1; /* authoritive answer */ u_char tc:1; /* truncated message */ u_char rd:1; /* recursion desired */ /* fields in fourth byte */ u_char ra:1; /* recursion available */ u_char pr:1; /* primary server required (non standard) */ u_char unused:2; /* unused bits */ u_char rcode:4; /* response code */ #endif #if BYTE_ORDER == LITTLE_ENDIAN /* fields in third byte */ u_char rd:1; /* recursion desired */ u_char tc:1; /* truncated message */ u_char aa:1; /* authoritive answer */ u_char opcode:4; /* purpose of message */ u_char qr:1; /* response flag */ /* fields in fourth byte */ u_char rcode:4; /* response code */ u_char unused:2; /* unused bits */ u_char pr:1; /* primary server required (non standard) */ u_char ra:1; /* recursion available */ #endif #if BYTE_ORDER == PDP_ENDIAN /* Bit zero on right, compiler doesn't like u_char bit fields: PDP */ /* fields in third byte */ u_int rd:1; /* recursion desired */ u_int tc:1; /* truncated message */ u_int aa:1; /* authoritive answer */ u_int opcode:4; /* purpose of message */ u_int qr:1; /* response flag */ /* fields in fourth byte */ u_int rcode:4; /* response code */ u_int unused:2; /* unused bits */ u_int pr:1; /* primary server required (non standard) */ u_int ra:1; /* recursion available */ #endif /* remaining bytes */ u_short qdcount; /* number of question entries */ u_short ancount; /* number of answer entries */ u_short nscount; /* number of authority entries */ u_short arcount; /* number of resource entries */ } HEADER; /* * Defines for handling compressed domain names */ #define INDIR_MASK 0xc0 /* * Structure for passing resource records around. */ struct rrec { short r_zone; /* zone number */ short r_class; /* class number */ short r_type; /* type number */ u_long r_ttl; /* time to live */ int r_size; /* size of data area */ char *r_data; /* pointer to data */ }; extern u_short _getshort(); extern u_long _getlong(); /* * Inline versions of get/put short/long. * Pointer is advanced; we assume that both arguments * are lvalues and will already be in registers. * cp MUST be u_char *. */ #define GETSHORT(s, cp) { \ (s) = *(cp)++ << 8; \ (s) |= *(cp)++; \ } #define GETLONG(l, cp) { \ (l) = *(cp)++ << 8; \ (l) |= *(cp)++; (l) <<= 8; \ (l) |= *(cp)++; (l) <<= 8; \ (l) |= *(cp)++; \ } #define PUTSHORT(s, cp) { \ *(cp)++ = (s) >> 8; \ *(cp)++ = (s); \ } /* * Warning: PUTLONG destroys its first argument. */ #define PUTLONG(l, cp) { \ (cp)[3] = l; \ (cp)[2] = (l >>= 8); \ (cp)[1] = (l >>= 8); \ (cp)[0] = l >> 8; \ (cp) += sizeof(u_long); \ } f. */ eh = (struct ether_header *)ifrw->ifrw_addr; eh->ether_type = ntohs((u_short)eh->ether_type); #define qedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off)))) if (eh->ether_type >= ETHERTYPE_TRAIL && eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { off = (eh->ether_type - ETHERTYPE_TRAIL) * 512; if include/arpa/telnet.h 444 0 12 10416 4403415047 10063 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)telnet.h 5.4 (Berkeley) 2/15/89 */ /* * Definitions for the TELNET protocol. */ #define IAC 255 /* interpret as command: */ #define DONT 254 /* you are not to use option */ #define DO 253 /* please, you use option */ #define WONT 252 /* I won't use option */ #define WILL 251 /* I will use option */ #define SB 250 /* interpret as subnegotiation */ #define GA 249 /* you may reverse the line */ #define EL 248 /* erase the current line */ #define EC 247 /* erase the current character */ #define AYT 246 /* are you there */ #define AO 245 /* abort output--but let prog finish */ #define IP 244 /* interrupt process--permanently */ #define BREAK 243 /* break */ #define DM 242 /* data mark--for connect. cleaning */ #define NOP 241 /* nop */ #define SE 240 /* end sub negotiation */ #define EOR 239 /* end of record (transparent mode) */ #define SYNCH 242 /* for telfunc calls */ #ifdef TELCMDS char *telcmds[] = { "SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC", "EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", }; #endif /* telnet options */ #define TELOPT_BINARY 0 /* 8-bit data path */ #define TELOPT_ECHO 1 /* echo */ #define TELOPT_RCP 2 /* prepare to reconnect */ #define TELOPT_SGA 3 /* suppress go ahead */ #define TELOPT_NAMS 4 /* approximate message size */ #define TELOPT_STATUS 5 /* give status */ #define TELOPT_TM 6 /* timing mark */ #define TELOPT_RCTE 7 /* remote controlled transmission and echo */ #define TELOPT_NAOL 8 /* negotiate about output line width */ #define TELOPT_NAOP 9 /* negotiate about output page size */ #define TELOPT_NAOCRD 10 /* negotiate about CR disposition */ #define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */ #define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */ #define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */ #define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */ #define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */ #define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */ #define TELOPT_XASCII 17 /* extended ascic character set */ #define TELOPT_LOGOUT 18 /* force logout */ #define TELOPT_BM 19 /* byte macro */ #define TELOPT_DET 20 /* data entry terminal */ #define TELOPT_SUPDUP 21 /* supdup protocol */ #define TELOPT_SUPDUPOUTPUT 22 /* supdup output */ #define TELOPT_SNDLOC 23 /* send location */ #define TELOPT_TTYPE 24 /* terminal type */ #define TELOPT_EOR 25 /* end or record */ #define TELOPT_TUID 26 /* TACACS user identification */ #define TELOPT_OUTMRK 27 /* output marking */ #define TELOPT_TTYLOC 28 /* terminal location number */ #define TELOPT_3270REGIME 29 /* 3270 regime */ #define TELOPT_X3PAD 30 /* X.3 PAD */ #define TELOPT_NAWS 31 /* window size */ #define TELOPT_TSPEED 32 /* terminal speed */ #define TELOPT_LFLOW 33 /* remote flow control */ #define TELOPT_EXOPL 255 /* extended-options-list */ #ifdef TELOPTS #define NTELOPTS (1+TELOPT_LFLOW) char *telopts[NTELOPTS] = { "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME", "STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP", "NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS", "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO", "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT", "SEND LOCATION", "TERMINAL TYPE", "END OF RECORD", "TACACS UID", "OUTPUT MARKING", "TTYLOC", "3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW", }; #endif /* sub-option qualifiers */ #define TELQUAL_IS 0 /* option is... */ #define TELQUAL_SEND 1 /* send option */ y documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used toinclude/arpa/tftp.h 444 0 12 3557 4320757702 7542 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)tftp.h 5.2 (Berkeley) 6/27/88 */ /* * Trivial File Transfer Protocol (IEN-133) */ #define SEGSIZE 512 /* data segment size */ /* * Packet types. */ #define RRQ 01 /* read request */ #define WRQ 02 /* write request */ #define DATA 03 /* data packet */ #define ACK 04 /* acknowledgement */ #define ERROR 05 /* error code */ struct tftphdr { short th_opcode; /* packet type */ union { short tu_block; /* block # */ short tu_code; /* error code */ char tu_stuff[1]; /* request packet stuff */ } th_u; char th_data[1]; /* data or error string */ }; #define th_block th_u.tu_block #define th_code th_u.tu_code #define th_stuff th_u.tu_stuff #define th_msg th_data /* * Error codes. */ #define EUNDEF 0 /* not defined */ #define ENOTFOUND 1 /* file not found */ #define EACCESS 2 /* access violation */ #define ENOSPACE 3 /* disk full or allocation exceeded */ #define EBADOP 4 /* illegal TFTP operation */ #define EBADID 5 /* unknown transfer ID */ #define EEXISTS 6 /* file already exists */ #define ENOUSER 7 /* no such user */ * telnet options */ #define TELOPT_BINARY 0 /* 8-bit data path */ #define TELOPT_ECHO 1 /* echo */ #define TELOPT_RCP 2 /* prepare to reconnect *include/Makefile 444 3 12 5636 5461656333 7141 # # Copyright (c) 1980 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)Makefile 5.16 (2.11BSD GTE) 10/21/93 # # Doing a make install builds /usr/include # # Define SHARED to indicate whether you want # symbolic links to the system source (``symlinks''), # or a separate copy (``copies''). # (latter useful in environments where it's # not possible to keep /sys publicly readable) # # The ``rm -rf''s used below are safe because rm doesn't # follow symbolic links. # DESTDIR= TOPDIR= SUBDIRS=arpa pascal protocols OLD STD= a.out.h ar.h assert.h ctype.h curses.h disktab.h fcntl.h \ fstab.h grp.h lastlog.h math.h memory.h mp.h mtab.h ndbm.h \ netdb.h nlist.h pcc.h pwd.h ranlib.h resolv.h setjmp.h \ sgtty.h short_names.h stab.h stdio.h string.h strings.h \ struct.h syscall.h sysexits.h time.h ttyent.h tzfile.h utmp.h \ varargs.h vfont.h vmf.h LINKS= errno.h signal.h syslog.h MACHINE=pdp MACHDEP=${MACHINE} pdpif pdpuba pdpmba vaxuba NETDIRS=net netimp netinet netns netpup SYSDIRS=${NETDIRS} ${MACHDEP} SHARED= symlinks TAGSFILE=tags all: install: ${SHARED} -for i in ${STD}; do \ cmp -s $$i ${DESTDIR}/usr/include/$$i || \ install -c -m 444 $$i ${DESTDIR}/usr/include/$$i; \ done -for i in ${SUBDIRS}; do \ if [ ! -d ${DESTDIR}/usr/include/$$i ]; \ then \ mkdir ${DESTDIR}/usr/include/$$i; \ fi; \ (cd $$i; for j in *.[ih]; do \ cmp -s $$j ${DESTDIR}/usr/include/$$i/$$j || \ install -c -m 444 $$j ${DESTDIR}/usr/include/$$i/$$j; \ done); \ done -cmp -s Makefile.install ${DESTDIR}/usr/include/Makefile || \ install -c -m 444 Makefile.install ${DESTDIR}/usr/include/Makefile -for i in ${LINKS}; do \ rm -f ${DESTDIR}/usr/include/$$i; \ ln -s sys/$$i ${DESTDIR}/usr/include/$$i; \ done rm -f ${DESTDIR}/usr/include/machine ln -s ./${MACHINE} ${DESTDIR}/usr/include/machine rm -f ${DESTDIR}/usr/include/frame.h ln -s machine/frame.h ${DESTDIR}/usr/include/frame.h symlinks: -for i in ${SYSDIRS}; do \ rm -rf ${DESTDIR}/usr/include/$$i; \ if [ ! -s ${DESTDIR}/usr/include/$$i ]; \ then \ ln -s ${TOPDIR}/sys/$$i ${DESTDIR}/usr/include/$$i; \ else \ echo ${DESTDIR}/usr/include/$$i not removed; \ fi; \ done rm -rf ${DESTDIR}/usr/include/sys -if [ ! -s ${DESTDIR}/usr/include/sys ]; \ then \ ln -s ${TOPDIR}/sys/h ${DESTDIR}/usr/include/sys; \ else \ echo ${DESTDIR}/usr/include/sys not removed; \ fi copies: -for i in ${SYSDIRS}; do \ rm -rf ${DESTDIR}/usr/include/$$i; \ cd /sys; \ tar cf - $$i/*.h | (cd ${DESTDIR}/usr/include; tar xpfB -); \ done rm -rf ${DESTDIR}/usr/include/sys; mkdir ${DESTDIR}/usr/include/sys; chmod 775 ${DESTDIR}/usr/include/sys; -(cd /sys/h; tar cf - *.h | (cd ${DESTDIR}/usr/include/sys; tar xpfB -)) tags: cwd=/usr/include; \ for i in ${STD} ${LINKS}; do \ ctags -a -f ${TAGSFILE} $$cwd/$$i; \ done clean: rm -f tags LOGOUT 18 /* force logout */ #define TELOPT_BM 19 /* byte macro */ #define TELOPT_DET 20 /* data einclude/a.out.h 444 0 12 2754 5513157722 6667 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)a.out.h 2.1 (2.11BSD GTE) 1/06/94 */ #ifndef _AOUT_H_ #define _AOUT_H_ /* * Definitions of the a.out header * and magic numbers are shared with * the kernel. */ #include #define _AOUT_INCLUDE_ #include /* * Macros which take exec structures as arguments and tell whether * the file has a reasonable magic number or offset to text. */ #define N_BADMAG(x) \ (((x).a_magic)!=A_MAGIC1 && ((x).a_magic)!=A_MAGIC2 && \ ((x).a_magic)!=A_MAGIC3 && ((x).a_magic)!=A_MAGIC4 && \ ((x).a_magic)!=A_MAGIC5 && ((x).a_magic)!=A_MAGIC6) #define N_TXTOFF(x) \ ((x).a_magic==A_MAGIC5 || (x).a_magic==A_MAGIC6 ? \ sizeof(struct ovlhdr) + sizeof(struct exec) : sizeof(struct exec)) /* * The following were added as part of the new object file format. They * call functions because calculating the sums of overlay sizes was too * messy (and verbose) to do 'inline'. * * NOTE: if the magic number is that of an overlaid object the program * must pass an extended header ('xexec') as the argument. */ #include off_t n_stroff(), n_symoff(), n_datoff(), n_dreloc(), n_treloc(); #define N_STROFF(e) (n_stroff(&e)) #define N_SYMOFF(e) (n_symoff(&e)) #define N_DATOFF(e) (n_datoff(&e)) #define N_DRELOC(e) (n_dreloc(&e)) #define N_TRELOC(e) (n_treloc(&e)) #endif /* !_AOUT_H_ */ lude/$$i/$$j || \ include/ar.h 444 0 12 5034 5450741622 6233 /*- * Copyright (c) 1991 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Hugh Smith at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ar.h 5.4 (Berkeley) 4/3/91 */ #ifndef _AR_H_ #define _AR_H_ /* Pre-4BSD archives had these magic numbers in them. */ #define OARMAG1 0177555 #define OARMAG2 0177545 #define ARMAG "!\n" /* ar "magic number" */ #define SARMAG 8 /* strlen(ARMAG); */ #define AR_EFMT1 "#1/" /* extended format #1 */ struct ar_hdr { char ar_name[16]; /* name */ char ar_date[12]; /* modification time */ char ar_uid[6]; /* user id */ char ar_gid[6]; /* group id */ char ar_mode[8]; /* octal file permissions */ char ar_size[10]; /* size in bytes */ #define ARFMAG "`\n" char ar_fmag[2]; /* consistency check */ }; #endif /* !_AR_H_ */ TDIR}/usr/include/$$i/$$j; \ done); \ done -cmp -s Makefile.install ${DESTDIR}/usr/include/Makefile || \ install -c -m 444 Makefile.install ${DESTDIR}/usr/include/Makefile -for i in ${LINKS}; do \ rm -f ${DESTDIR}/usr/include/$$i; \ ln -s sys/$$i ${DESTDIR}/usr/include/$$i; \ done rm -f ${DESTDIR}/usr/include/machine ln -s ./${MACHINE} ${DESTDIR}/usr/include/machine rm -f ${DESTDIR}/usr/include/frame.h ln -s machine/frame.h ${DESTDIR}/usr/include/frame.h symliinclude/assert.h 444 0 12 400 3770654244 7110 /* assert.h 4.2 85/01/21 */ # ifndef NDEBUG # define _assert(ex) {if (!(ex)){fprintf(stderr,"Assertion failed: file \"%s\", line %d\n", __FILE__, __LINE__);exit(1);}} # define assert(ex) _assert(ex) # else # define _assert(ex) # define assert(ex) # endif grp.hB lastlog.hAmath.hh@memory.h? mp.hd>mtab.h=ndbm.h<netdb.h;nlist.h:paths.h9 pcc.h8 pwd.h7sgtty.h6ranlib.h5regexp.h4resolv.h3 vmf.h2include/ctype.h 444 0 12 1416 3770654251 6761 /* ctype.h 4.2 85/09/04 */ #define _U 01 #define _L 02 #define _N 04 #define _S 010 #define _P 020 #define _C 040 #define _X 0100 #define _B 0200 extern char _ctype_[]; #define isalpha(c) ((_ctype_+1)[c]&(_U|_L)) #define isupper(c) ((_ctype_+1)[c]&_U) #define islower(c) ((_ctype_+1)[c]&_L) #define isdigit(c) ((_ctype_+1)[c]&_N) #define isxdigit(c) ((_ctype_+1)[c]&(_N|_X)) #define isspace(c) ((_ctype_+1)[c]&_S) #define ispunct(c) ((_ctype_+1)[c]&_P) #define isalnum(c) ((_ctype_+1)[c]&(_U|_L|_N)) #define isprint(c) ((_ctype_+1)[c]&(_P|_U|_L|_N|_B)) #define isgraph(c) ((_ctype_+1)[c]&(_P|_U|_L|_N)) #define iscntrl(c) ((_ctype_+1)[c]&_C) #define isascii(c) ((unsigned)(c)<=0177) #define toupper(c) ((c)-'a'+'A') #define tolower(c) ((c)-'A'+'a') #define toascii(c) ((c)&0177) CE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ar.h 5.4 (Berkeley) 4/3/91 */ #ifndef _AR_H_ #define _AR_H_ /* Pre-4BSD archives had these magic numberinclude/curses.h 444 0 12 12013 3770654253 7156 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)curses.h 5.1 (Berkeley) 6/7/85 */ # ifndef WINDOW # include # include # define bool char # define reg register # define TRUE (1) # define FALSE (0) # define ERR (0) # define OK (1) # define _ENDLINE 001 # define _FULLWIN 002 # define _SCROLLWIN 004 # define _FLUSH 010 # define _FULLLINE 020 # define _IDLINE 040 # define _STANDOUT 0200 # define _NOCHANGE -1 # define _puts(s) tputs(s, 0, _putchar) typedef struct sgttyb SGTTY; /* * Capabilities from termcap */ extern bool AM, BS, CA, DA, DB, EO, HC, HZ, IN, MI, MS, NC, NS, OS, UL, XB, XN, XT, XS, XX; extern char *AL, *BC, *BT, *CD, *CE, *CL, *CM, *CR, *CS, *DC, *DL, *DM, *DO, *ED, *EI, *K0, *K1, *K2, *K3, *K4, *K5, *K6, *K7, *K8, *K9, *HO, *IC, *IM, *IP, *KD, *KE, *KH, *KL, *KR, *KS, *KU, *LL, *MA, *ND, *NL, *RC, *SC, *SE, *SF, *SO, *SR, *TA, *TE, *TI, *UC, *UE, *UP, *US, *VB, *VS, *VE, *AL_PARM, *DL_PARM, *UP_PARM, *DOWN_PARM, *LEFT_PARM, *RIGHT_PARM; extern char PC; /* * From the tty modes... */ extern bool GT, NONL, UPPERCASE, normtty, _pfast; struct _win_st { short _cury, _curx; short _maxy, _maxx; short _begy, _begx; short _flags; short _ch_off; bool _clear; bool _leave; bool _scroll; char **_y; short *_firstch; short *_lastch; struct _win_st *_nextp, *_orig; }; # define WINDOW struct _win_st extern bool My_term, _echoit, _rawmode, _endwin; extern char *Def_term, ttytype[]; extern int LINES, COLS, _tty_ch, _res_flg; extern SGTTY _tty; extern WINDOW *stdscr, *curscr; /* * Define VOID to stop lint from generating "null effect" * comments. */ # ifdef lint int __void__; # define VOID(x) (__void__ = (int) (x)) # else # define VOID(x) (x) # endif /* * psuedo functions for standard screen */ # define addch(ch) VOID(waddch(stdscr, ch)) # define getch() VOID(wgetch(stdscr)) # define addstr(str) VOID(waddstr(stdscr, str)) # define getstr(str) VOID(wgetstr(stdscr, str)) # define move(y, x) VOID(wmove(stdscr, y, x)) # define clear() VOID(wclear(stdscr)) # define erase() VOID(werase(stdscr)) # define clrtobot() VOID(wclrtobot(stdscr)) # define clrtoeol() VOID(wclrtoeol(stdscr)) # define insertln() VOID(winsertln(stdscr)) # define deleteln() VOID(wdeleteln(stdscr)) # define refresh() VOID(wrefresh(stdscr)) # define inch() VOID(winch(stdscr)) # define insch(c) VOID(winsch(stdscr,c)) # define delch() VOID(wdelch(stdscr)) # define standout() VOID(wstandout(stdscr)) # define standend() VOID(wstandend(stdscr)) /* * mv functions */ #define mvwaddch(win,y,x,ch) VOID(wmove(win,y,x)==ERR?ERR:waddch(win,ch)) #define mvwgetch(win,y,x) VOID(wmove(win,y,x)==ERR?ERR:wgetch(win)) #define mvwaddstr(win,y,x,str) VOID(wmove(win,y,x)==ERR?ERR:waddstr(win,str)) #define mvwgetstr(win,y,x,str) VOID(wmove(win,y,x)==ERR?ERR:wgetstr(win,str)) #define mvwinch(win,y,x) VOID(wmove(win,y,x) == ERR ? ERR : winch(win)) #define mvwdelch(win,y,x) VOID(wmove(win,y,x) == ERR ? ERR : wdelch(win)) #define mvwinsch(win,y,x,c) VOID(wmove(win,y,x) == ERR ? ERR:winsch(win,c)) #define mvaddch(y,x,ch) mvwaddch(stdscr,y,x,ch) #define mvgetch(y,x) mvwgetch(stdscr,y,x) #define mvaddstr(y,x,str) mvwaddstr(stdscr,y,x,str) #define mvgetstr(y,x,str) mvwgetstr(stdscr,y,x,str) #define mvinch(y,x) mvwinch(stdscr,y,x) #define mvdelch(y,x) mvwdelch(stdscr,y,x) #define mvinsch(y,x,c) mvwinsch(stdscr,y,x,c) /* * psuedo functions */ #define clearok(win,bf) (win->_clear = bf) #define leaveok(win,bf) (win->_leave = bf) #define scrollok(win,bf) (win->_scroll = bf) #define flushok(win,bf) (bf ? (win->_flags |= _FLUSH):(win->_flags &= ~_FLUSH)) #define getyx(win,y,x) y = win->_cury, x = win->_curx #define winch(win) (win->_y[win->_cury][win->_curx] & 0177) #define raw() (_tty.sg_flags|=RAW, _pfast=_rawmode=TRUE, stty(_tty_ch,&_tty)) #define noraw() (_tty.sg_flags&=~RAW,_rawmode=FALSE,_pfast=!(_tty.sg_flags&CRMOD),stty(_tty_ch,&_tty)) #define cbreak() (_tty.sg_flags |= CBREAK, _rawmode = TRUE, stty(_tty_ch,&_tty)) #define nocbreak() (_tty.sg_flags &= ~CBREAK,_rawmode=FALSE,stty(_tty_ch,&_tty)) #define crmode() cbreak() /* backwards compatability */ #define nocrmode() nocbreak() /* backwards compatability */ #define echo() (_tty.sg_flags |= ECHO, _echoit = TRUE, stty(_tty_ch, &_tty)) #define noecho() (_tty.sg_flags &= ~ECHO, _echoit = FALSE, stty(_tty_ch, &_tty)) #define nl() (_tty.sg_flags |= CRMOD,_pfast = _rawmode,stty(_tty_ch, &_tty)) #define nonl() (_tty.sg_flags &= ~CRMOD, _pfast = TRUE, stty(_tty_ch, &_tty)) #define savetty() ((void) gtty(_tty_ch, &_tty), _res_flg = _tty.sg_flags) #define resetty() (_tty.sg_flags = _res_flg, (void) stty(_tty_ch, &_tty)) #define erasechar() (_tty.sg_erase) #define killchar() (_tty.sg_kill) #define baudrate() (_tty.sg_ospeed) WINDOW *initscr(), *newwin(), *subwin(); char *longname(), *getcap(); /* * Used to be in unctrl.h. */ #define unctrl(c) _unctrl[(c) & 0177] extern char *_unctrl[]; # endif ight (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)curses.h 5.1 (Berkeley) 6/7/85 */ # ifndef WINDOW # include # include # define bool char # define reg register # define TRUE (1) # define FALSE (0) # define ERR (0) # define OK (1) # define _ENDLINE 001 # define _FULLWIN 002 # define _SCROLLWIN 004 # define _FLUSH 010 # define _FULLLinclude/dbm.h 444 0 12 1150 4325015643 6363 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dbm.h 5.1 (Berkeley) 3/27/86 */ #ifndef NULL /* * this is lunacy, we no longer use it (and never should have * unconditionally defined it), but, this whole file is for * backwards compatability - someone may rely on this. */ #define NULL ((char *) 0) #endif #include datum fetch(); datum firstkey(); datum nextkey(); #if 0 datum makdatum(); datum firsthash(); long calchash(); long hashinc(); #endif 0, _putchar) typedef struct sgttyb SGTTY; /* * Capabilities from termcap */ extern bool AM, BS, CA, DA, DB, EO, HC, HZ, IN, MI, MS, NC, NS, OS, UL, XB, XN, XT, XS, XX; extern char *AL, *BC, *BT, *CD, *CE, *CL, *CM, *CR, *CS, *DC, *DL, *DM, *DO, *ED, *EI, *K0, *K1, *K2, *K3, *K4, *K5, *K6, *K7, *K8, *K9, *HO, *IC, *IM, *IP, *KD, *KE, *KH, *KL, *KR, *KS, *KU, *LL, *MA, *ND, *NL, *RC, *SC, *include/OLD/ 755 0 12 0 5462124053 6005 include/OLD/dk.h 444 0 12 1455 3770654260 6654 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dk.h 5.1 (Berkeley) 12/13/86 */ /* * switch commands */ #define RAM_ON 0226 #define ROM_ON 0322 #define R_CNTL 0264 #define W_CNTL 0170 /* * library routine declarations */ extern long cmread(); extern long ocmread(); /* * call setup struct */ struct dialout { char srv; char area; char sw; char mch; char chan; char other; short check; }; struct indial { char i_lchan; char i_rhost; char i_rchan; char i_srv; char i_area; char i_sw; char i_mch; char i_chan; char i_other; short i_check; }; #define D_SH 1 #define D_FS 2 #define D_LSTNR 3 struct ring { char r_lchan; char r_srv; }; BC, *BT, *CD, *CE, *CL, *CM, *CR, *CS, *DC, *DL, *DM, *DO, *ED, *EI, *K0, *K1, *K2, *K3, *K4, *K5, *K6, *K7, *K8, *K9, *HO, *IC, *IM, *IP, *KD, *KE, *KH, *KL, *KR, *KS, *KU, *LL, *MA, *ND, *NL, *RC, *SC, *include/OLD/psout.h 644 0 12 2246 5321534636 7427 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)psout.h 5.2 (2.11BSD GTE) 1/3/93 */ /* * psout: structure output by 'ps -U'. * Mostly the pre-processed /dev directory. */ #ifndef makedev #include #endif !makedev struct psout { dev_t o_ttyd; /* u_ttyd */ int o_flag; /* p_flag */ short o_pid; /* p_pid */ char o_tty[3]; /* 1st 2 chars of tty after 'tty' */ char o_stat; /* p_stat */ short o_uid; /* p_uid */ char o_uname[UT_NAMESIZE]; /* login name of process owner */ short o_ppid; /* p_ppid */ char o_cpu; /* p_cpu */ char o_pri; /* p_pri */ char o_nice; /* p_nice */ short o_addr0; /* p_addr[0] */ short o_size; /* p_size */ caddr_t o_wchan; /* p_wchan */ time_t o_utime; /* u_utime */ time_t o_stime; /* u_stime */ time_t o_cutime; /* u_cutime */ time_t o_cstime; /* u_cstime */ short o_pgrp; /* p_pgrp */ int o_sigs; /* sum of SIGINT & SIGQUIT, if == 2 proc is ignoring both.*/ char o_comm[MAXCOMLEN+1]; /* u_comm */ char o_args[64]; /* best guess at args to process */ }; rom the tty modes... */ extern bool GT, NONL, UPPERCASE, normtty, _pfast; struct _win_st { short _cury, _curx; short _maxy, _maxx; short _begy, _begx; short _flags; short _ch_off; bool _clear; bool _leave; bool _scroll; char **_y; short *_firstch; short *_lastch; struct _win_st *_nextp, *_orig; }; # define WINDOW struinclude/errno.h 444 0 12 7423 4053130002 6740 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)errno.h 7.1 (Berkeley) 6/4/86 */ /* * Error codes */ #define EPERM 1 /* Not owner */ #define ENOENT 2 /* No such file or directory */ #define ESRCH 3 /* No such process */ #define EINTR 4 /* Interrupted system call */ #define EIO 5 /* I/O error */ #define ENXIO 6 /* No such device or address */ #define E2BIG 7 /* Arg list too long */ #define ENOEXEC 8 /* Exec format error */ #define EBADF 9 /* Bad file number */ #define ECHILD 10 /* No children */ #define EAGAIN 11 /* No more processes */ #define ENOMEM 12 /* Not enough core */ #define EACCES 13 /* Permission denied */ #define EFAULT 14 /* Bad address */ #define ENOTBLK 15 /* Block device required */ #define EBUSY 16 /* Mount device busy */ #define EEXIST 17 /* File exists */ #define EXDEV 18 /* Cross-device link */ #define ENODEV 19 /* No such device */ #define ENOTDIR 20 /* Not a directory*/ #define EISDIR 21 /* Is a directory */ #define EINVAL 22 /* Invalid argument */ #define ENFILE 23 /* File table overflow */ #define EMFILE 24 /* Too many open files */ #define ENOTTY 25 /* Not a typewriter */ #define ETXTBSY 26 /* Text file busy */ #define EFBIG 27 /* File too large */ #define ENOSPC 28 /* No space left on device */ #define ESPIPE 29 /* Illegal seek */ #define EROFS 30 /* Read-only file system */ #define EMLINK 31 /* Too many links */ #define EPIPE 32 /* Broken pipe */ /* math software */ #define EDOM 33 /* Argument too large */ #define ERANGE 34 /* Result too large */ /* non-blocking and interrupt i/o */ #define EWOULDBLOCK 35 /* Operation would block */ #define EDEADLK EWOULDBLOCK /* ditto */ #define EINPROGRESS 36 /* Operation now in progress */ #define EALREADY 37 /* Operation already in progress */ /* ipc/network software */ /* argument errors */ #define ENOTSOCK 38 /* Socket operation on non-socket */ #define EDESTADDRREQ 39 /* Destination address required */ #define EMSGSIZE 40 /* Message too long */ #define EPROTOTYPE 41 /* Protocol wrong type for socket */ #define ENOPROTOOPT 42 /* Protocol not available */ #define EPROTONOSUPPORT 43 /* Protocol not supported */ #define ESOCKTNOSUPPORT 44 /* Socket type not supported */ #define EOPNOTSUPP 45 /* Operation not supported on socket */ #define EPFNOSUPPORT 46 /* Protocol family not supported */ #define EAFNOSUPPORT 47 /* Address family not supported by protocol family */ #define EADDRINUSE 48 /* Address already in use */ #define EADDRNOTAVAIL 49 /* Can't assign requested address */ /* operational errors */ #define ENETDOWN 50 /* Network is down */ #define ENETUNREACH 51 /* Network is unreachable */ #define ENETRESET 52 /* Network dropped connection on reset */ #define ECONNABORTED 53 /* Software caused connection abort */ #define ECONNRESET 54 /* Connection reset by peer */ #define ENOBUFS 55 /* No buffer space available */ #define EISCONN 56 /* Socket is already connected */ #define ENOTCONN 57 /* Socket is not connected */ #define ESHUTDOWN 58 /* Can't send after socket shutdown */ #define ETOOMANYREFS 59 /* Too many references: can't splice */ #define ETIMEDOUT 60 /* Connection timed out */ #define ECONNREFUSED 61 /* Connection refused */ /* */ #define ELOOP 62 /* Too many levels of symbolic links */ #define ENAMETOOLONG 63 /* File name too long */ /* should be rearranged */ #define EHOSTDOWN 64 /* Host is down */ #define EHOSTUNREACH 65 /* No route to host */ #define ENOTEMPTY 66 /* Directory not empty */ /* quotas & mush */ #define EPROCLIM 67 /* Too many processes */ #define EUSERS 68 /* Too many users */ #define EDQUOT 69 /* Disc quota exceeded */ M 1 /* Not owner */ #define ENOENT 2 /* No such file or directory */ #define ESRCH 3 /* No such process */ #define EINTR 4 /* Interrupted system call */ #define EIO 5 /* I/O error */ #define ENXIO 6 /* No such device or addreinclude/fcntl.h 444 0 12 2750 3770654266 6753 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)fcntl.h 5.2 (Berkeley) 1/8/86 */ /* * Flag values accessible to open(2) and fcntl(2)-- copied from * . (The first three can only be set by open.) */ #define O_RDONLY 000 /* open for reading */ #define O_WRONLY 001 /* open for writing */ #define O_RDWR 002 /* open for read & write */ #define O_NDELAY FNDELAY /* non-blocking open */ /* really non-blocking I/O for fcntl */ #define O_APPEND FAPPEND /* append on each write */ #define O_CREAT FCREAT /* open with file create */ #define O_TRUNC FTRUNC /* open with truncation */ #define O_EXCL FEXCL /* error on create if file exists */ #ifndef F_DUPFD /* fcntl(2) requests */ #define F_DUPFD 0 /* Duplicate fildes */ #define F_GETFD 1 /* Get fildes flags */ #define F_SETFD 2 /* Set fildes flags */ #define F_GETFL 3 /* Get file flags */ #define F_SETFL 4 /* Set file flags */ #define F_GETOWN 5 /* Get owner */ #define F_SETOWN 6 /* Set owner */ /* flags for F_GETFL, F_SETFL-- copied from */ #define FNDELAY 00004 /* non-blocking reads */ #define FAPPEND 00010 /* append on each write */ #define FASYNC 00100 /* signal pgrp when data ready */ #define FCREAT 01000 /* create if nonexistant */ #define FTRUNC 02000 /* truncate to zero length */ #define FEXCL 04000 /* error if already created */ #endif 0 /* Read-only file sysinclude/frame.h 444 0 12 1044 4016525546 6722 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)frame.h 7.1 (Berkeley) 6/5/86 */ /* * Definition of the pdp call frame. */ struct frame { int fr_savr2; /* saved register 2 */ int fr_savr3; /* saved register 3 */ int fr_savr4; /* saved register 4 */ int fr_savov; /* saved overlay number */ int fr_savfp; /* saved frame pointer */ int fr_savpc; /* saved program counter */ }; pen */ /* really non-blocking I/O for ftl */ #define O_APPEND FAPPEND /* append on each write */ #define O_CREAT FCREAT /* open with file create */ #define O_TRUNC FTRUNC /* open with truncation */ #define O_EXCL FEXCL /* error on create if file exists */ #ifndef F_DUPFD /* fcntl(2) requests */ #define F_DUPFD 0 /* Duplicate fildes */ #define F_GETFD 1 /* Get fildes flags */ #define F_SETFD 2 /* Set fildes flags */ #define F_GETFL 3 /* Get file flags */ #deinclude/fstab.h 444 0 12 2411 3770654270 6731 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)fstab.h 5.1 (Berkeley) 5/30/85 */ /* * File system table, see fstab (5) * * Used by dump, mount, umount, swapon, fsck, df, ... * * The fs_spec field is the block special name. Programs * that want to use the character special name must create * that name by prepending a 'r' after the right most slash. * Quota files are always named "quotas", so if type is "rq", * then use concatenation of fs_file and "quotas" to locate * quota file. */ #define FSTAB "/etc/fstab" #define FSTAB_RW "rw" /* read/write device */ #define FSTAB_RQ "rq" /* read/write with quotas */ #define FSTAB_RO "ro" /* read-only device */ #define FSTAB_SW "sw" /* swap device */ #define FSTAB_XX "xx" /* ignore totally */ struct fstab{ char *fs_spec; /* block special device name */ char *fs_file; /* file system path prefix */ char *fs_type; /* FSTAB_* */ int fs_freq; /* dump frequency, in days */ int fs_passno; /* pass number on parallel dump */ }; struct fstab *getfsent(); struct fstab *getfsspec(); struct fstab *getfsfile(); struct fstab *getfstype(); int setfsent(); int endfsent(); / #define FASYNC 00100 /* signal pgrp when data ready */ #define FCREAT 01000 /* create if nonexistant */ #define FTRUNC 02000 /* truncate to zero length */ #define FEXCL 04000 /* error if already created */ #endif 0 /* Read-only file sysinclude/grp.h 444 0 12 266 3770654272 6412 /* grp.h 4.1 83/05/03 */ struct group { /* see getgrent(3) */ char *gr_name; char *gr_passwd; int gr_gid; char **gr_mem; }; struct group *getgrent(), *getgrgid(), *getgrnam(); OLDudGerrno.hFfcntl.hEframe.hDfstab.hC grp.hB lastlog.hAmath.hh@memory.h? mp.hd>mtab.h=ndbm.h<netdb.h;nlist.h:paths.h9 pcc.h8 pwd.h7sgtty.h6ranlib.h5regexp.h4resolv.h3 vmf.h2include/lastlog.h 444 0 12 516 3770654273 7266 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)lastlog.h 5.1 (Berkeley) 5/30/85 */ struct lastlog { time_t ll_time; char ll_line[8]; char ll_host[16]; /* same as in utmp */ }; ab.h=ndbm.h<netdb.h;nlist.h:paths.h9 pcc.h8 pwd.h7sgtty.h6ranlib.h5regexp.h4resolv.h3 vmf.h2include/math.h 444 0 12 1151 4013175015 6545 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)math.h 1.1 (2.10BSD Berkeley) 12/1/86 */ extern double fabs(), floor(), ceil(), fmod(), ldexp(); extern double sqrt(), hypot(), atof(); extern double sin(), cos(), tan(), asin(), acos(), atan(), atan2(); extern double exp(), log(), log10(), pow(); extern double sinh(), cosh(), tanh(); extern double gamma(); extern double j0(), j1(), jn(), y0(), y1(), yn(); #define HUGE 1.701411733192644270e38 #define LOGHUGE 39 uotas" to locate * quota file. */ #define FSTAB "/etc/fstab" #define FSTAB_RW "rw" /* read/write device */ #define FSTAB_RQ "rq" /* read/write with quotas */ #define FSTAB_RO "ro" /* read-only device */ #define FSTAB_SW "sw" /* swap device */ #define FSTAB_XX "xx" /* ignore totally */ struct fstab{ char *fs_spec; /* block special device name */ char *fs_file; /* file system path prefix */ char include/memory.h 444 0 12 646 4013175016 7115 /* * Copyright (c) 1985 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)memory.h 5.1 (Berkeley) 85/08/05 */ /* * Definitions of the Sys5 compat memory manipulation routines */ extern char *memccpy(); extern char *memchr(); extern int memcmp(); extern char *memcpy(); extern char *memset(); pwd.h7sgtty.h6ranlib.h5regexp.h4resolv.h3 vmf.h2include/mp.h 444 0 12 707 3770654300 6226 #define MINT struct mint MINT { int len; short *val; }; #define FREE(x) {if(x.len!=0) {free((char *)x.val); x.len=0;}} #ifndef DBG #define shfree(u) free((char *)u) #else #include "stdio.h" #define shfree(u) { if(dbg) fprintf(stderr, "free %o\n", u); free((char *)u);} extern int dbg; #endif struct half { short high; short low; }; extern MINT *itom(); extern short *xalloc(); #ifdef lint extern xv_oid; #define VOID xv_oid = #else #define VOID #endif lib.h5regexp.h4resolv.h3 vmf.h2include/mtab.h 444 0 12 654 3770654301 6537 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)mtab.h 5.1 (Berkeley) 5/30/85 */ /* * Mounted device accounting file. */ struct mtab { char m_path[32]; /* mounted on pathname */ char m_dname[32]; /* block device pathname */ char m_type[4]; /* read-only, quotas */ }; h7sgtty.h6ranlib.h5regexp.h4resolv.h3 vmf.h2include/ndbm.h 444 0 12 3262 5514435360 6552 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ndbm.h 5.1.1 (2.11BSD GTE) 12/31/93 */ /* * Hashed key data base library. */ #define PBLKSIZ 1024 #ifdef pdp11 #define DBLKSIZ 512 #else #define DBLKSIZ 4096 #endif typedef struct { int dbm_dirf; /* open directory file */ int dbm_pagf; /* open page file */ int dbm_flags; /* flags, see below */ long dbm_maxbno; /* last ``bit'' in dir file */ long dbm_bitno; /* current bit number */ long dbm_hmask; /* hash mask */ long dbm_blkptr; /* current block for dbm_nextkey */ int dbm_keyptr; /* current key for dbm_nextkey */ long dbm_blkno; /* current page to read/write */ long dbm_pagbno; /* current page in pagbuf */ char dbm_pagbuf[PBLKSIZ]; /* page file block buffer */ long dbm_dirbno; /* current block in dirbuf */ char dbm_dirbuf[DBLKSIZ]; /* directory file block buffer */ } DBM; #define _DBM_RDONLY 0x1 /* data base open read-only */ #define _DBM_IOERR 0x2 /* data base I/O error */ #define dbm_rdonly(db) ((db)->dbm_flags & _DBM_RDONLY) #define dbm_error(db) ((db)->dbm_flags & _DBM_IOERR) /* use this one at your own risk! */ #define dbm_clearerr(db) ((db)->dbm_flags &= ~_DBM_IOERR) /* for flock(2) and fstat(2) */ #define dbm_dirfno(db) ((db)->dbm_dirf) #define dbm_pagfno(db) ((db)->dbm_pagf) typedef struct { char *dptr; int dsize; } datum; /* * flags to dbm_store() */ #define DBM_INSERT 0 #define DBM_REPLACE 1 DBM *dbm_open(); void dbm_close(); datum dbm_fetch(); datum dbm_firstkey(); datum dbm_nextkey(); long dbm_forder(); int dbm_delete(); int dbm_store(); too large */ /* non-blocking and interrupt i/o */ #define EWOULDBLOCK 35 /* Operation would block */ #define EDEADLK EWOULDBLOCK /* ditto */ #define EINPROGRESS 36 /* Operation now in progress */ #define EALREADY 37 /* Operation already in progress */ /* ipc/network software */ /* argument errors */ #define ENOTSOCK 38 /* include/netdb.h 444 0 12 4517 5514435327 6735 /* * Copyright (c) 1980,1983,1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)netdb.h 5.9.1 (2.11BSD GTE) 12/31/93 */ /* * Structures returned by network * data base library. All addresses * are supplied in host order, and * returned in network order (suitable * for use in system calls). */ struct hostent { char *h_name; /* official name of host */ char **h_aliases; /* alias list */ int h_addrtype; /* host address type */ int h_length; /* length of address */ char **h_addr_list; /* list of addresses from name server */ #define h_addr h_addr_list[0] /* address, for backward compatiblity */ }; /* * Assumption here is that a network number * fits in 32 bits -- probably a poor one. */ struct netent { char *n_name; /* official name of net */ char **n_aliases; /* alias list */ int n_addrtype; /* net address type */ unsigned long n_net; /* network # */ }; struct servent { char *s_name; /* official service name */ char **s_aliases; /* alias list */ int s_port; /* port # */ char *s_proto; /* protocol to use */ }; struct protoent { char *p_name; /* official protocol name */ char **p_aliases; /* alias list */ int p_proto; /* protocol # */ }; struct hostent *gethostbyname(), *gethostbyaddr(), *gethostent(); struct netent *getnetbyname(), *getnetbyaddr(), *getnetent(); struct servent *getservbyname(), *getservbyport(), *getservent(); struct protoent *getprotobyname(), *getprotobynumber(), *getprotoent(); /* * Error return codes from gethostbyname() and gethostbyaddr() * (left in extern int h_errno). */ #define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */ #define TRY_AGAIN 2 /* Non-Authoritive Host not found, or SERVERFAIL */ #define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ #define NO_DATA 4 /* Valid name, no data record of requested type */ #define NO_ADDRESS NO_DATA /* no address, look for MX record */ unsigned long gethostid(); /* Socket type not supported */ #define EOPNOTSUPP 45 /* Operation not supported on socket */ #define EPFNOSUPPORT 46 /* Protocol family not supported */ #define EAFNOSUPPORTinclude/nlist.h 444 0 12 2555 5513160355 6765 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)nlist.h 2.2 (2.11BSD GTE) 1/06/94 */ #ifndef _NLIST_H_ #define _NLIST_H_ #include /* * Symbol table entry format. The #ifdef's are so that programs including * nlist.h can initialize nlist structures statically. */ struct oldnlist { char n_name[8]; /* symbol name */ int n_type; /* type flag */ unsigned int n_value; /* value */ }; struct nlist { #ifdef _AOUT_INCLUDE_ union { char *n_name; /* In memory address of symbol name */ off_t n_strx; /* String table offset (file) */ } n_un; #else char *n_name; /* symbol name (in memory) */ #endif u_char n_type; /* Type of symbol - see below */ char n_ovly; /* Overlay number */ u_int n_value; /* Symbol value */ }; /* * Simple values for n_type. */ #define N_UNDF 0x0 /* undefined */ #define N_ABS 0x1 /* absolute */ #define N_TEXT 0x2 /* text symbol */ #define N_DATA 0x3 /* data symbol */ #define N_BSS 0x4 /* bss symbol */ #define N_REG 0x14 /* register name */ #define N_FN 0x1f /* file name symbol */ #define N_EXT 0x20 /* external bit, or'ed in */ #define N_TYPE 0x1f /* mask for all the type bits */ /* * Format for namelist values. */ #define N_FORMAT "%06o" #endif /* _NLIST_H_ */ me */ char **s_aliases; /* alias list */ int s_port; /* port # */ char *s_proto; /* protocol to use */ }; struct protoent { char *p_name; /* include/paths.h 444 0 12 2246 5374100526 6747 /* * Copyright (c) 1989 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)pathnames.h 5.3 (2.11BSD) 5/10/93 */ #define _PATH_BSHELL "/bin/sh" #define _PATH_CSHELL "/bin/csh" #define _PATH_CP "/bin/cp" #define _PATH_RSH "/usr/ucb/rsh" #define _PATH_TTY "/dev/tty" #define _PATH_DEV "/dev" #define _PATH_LASTLOG "/usr/adm/lastlog" #define _PATH_TMP "/tmp/" #define _PATH_VARTMP "/usr/tmp/" #define _PATH_SENDMAIL "/usr/lib/sendmail" ymbol */ #define N_EXT 0x20 /* external bit, or'ed in */ #define N_TYPE 0x1f /* mask for all the type bits */ /* * Format for namelist values. */ #define N_FORMAT "%06o" #endif /* _NLIST_H_ */ me */ char **s_aliases; /* alias list */ int s_port; /* port # */ char *s_proto; /* protocol to use */ }; struct protoent { char *p_name; /* include/pcc.h 444 0 12 14304 3770654311 6417 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)pcc.h 5.1 (Berkeley) 5/30/85 */ /* * This file contains definitions for all the constants and structures * needed to use the intermediate code files generated and read by * the Portable C Compiler and related compilers. * * Rules for changing this code: * 1) All op values must be integer constants -- this permits us to run * a 'sed' script on this file to create %term declarations for yacc. * 2) Because the PCC uses fancy ASG and UNARY macros, assignment * operators must have values 1 greater than corresponding normal * operators, and unary operators must have values 2 greater ditto. * 3) Ops used only by f1 must have values >= 150 (PCCF_FORTOPS). * 4) Other language-dependent ops must have values >= 200. */ # ifndef PCC_TOKENS # define PCC_TOKENS 0 # define PCC_ERROR 1 /* an error node */ # define PCC_FREE 2 /* an unused node */ /* * Constants. */ # define PCC_STRING 3 /* a string constant */ # define PCC_ICON 4 /* an integer constant */ # define PCC_FCON 5 /* a floating point constant */ # define PCC_DCON 6 /* a double precision f.p. constant */ /* * Leaf types. */ # define PCC_NAME 7 /* an identifier */ # define PCC_REG 8 /* a register */ # define PCC_OREG 9 /* register and offset */ # define PCC_CCODES 10 /* condition codes */ # define PCC_FLD 11 /* a bit field */ /* * Arithmetic operators. */ # define PCC_PLUS 12 /* + */ # define PCC_PLUSEQ 13 /* += */ # define PCC_UPLUS 14 /* unary + (for completeness) */ # define PCC_MINUS 15 /* - */ # define PCC_MINUSEQ 16 /* -= */ # define PCC_UMINUS 17 /* unary - */ # define PCC_MUL 18 /* * */ # define PCC_MULEQ 19 /* *= */ /* Reserve a slot for 'unary *', which is PCC jargon for PCC_DEREF (yech) */ # define PCC_DIV 21 /* / */ # define PCC_DIVEQ 22 /* /= */ # define PCC_MOD 23 /* % */ # define PCC_MODEQ 24 /* %= */ # define PCC_INCR 25 /* ++ */ # define PCC_DECR 26 /* -- */ # define PCC_ASSIGN 27 /* = (these last 3 are stretching it) */ /* * Bit operators. */ # define PCC_AND 28 /* & */ # define PCC_ANDEQ 29 /* &= */ /* Reserve a slot for 'unary &', jargon for PCC_ADDROF */ # define PCC_OR 31 /* | */ # define PCC_OREQ 32 /* |= */ # define PCC_ER 33 /* ^ */ # define PCC_EREQ 34 /* ^= */ # define PCC_LS 35 /* << */ # define PCC_LSEQ 36 /* <<= */ # define PCC_RS 37 /* >> */ # define PCC_RSEQ 38 /* >>= */ # define PCC_COMPL 39 /* ~ */ /* * Booleans. */ # define PCC_EQ 40 /* == */ # define PCC_NE 41 /* != */ # define PCC_LE 42 /* <= */ # define PCC_LT 43 /* < */ # define PCC_GE 44 /* >= */ # define PCC_GT 45 /* > */ # define PCC_ULE 46 /* unsigned <= */ # define PCC_ULT 47 /* unsigned < */ # define PCC_UGE 48 /* unsigned >= */ # define PCC_UGT 49 /* unsigned > */ # define PCC_QUEST 50 /* ? (for conditional expressions) */ # define PCC_COLON 51 /* : (for conditional expressions) */ # define PCC_ANDAND 52 /* && */ # define PCC_OROR 53 /* || */ # define PCC_NOT 54 /* ! */ /* * Function calls. */ # define PCC_CALL 55 /* call by value */ /* no ASG */ # define PCC_UCALL 57 /* call with no arguments */ # define PCC_FORTCALL 58 /* call by reference? */ /* no ASG */ # define PCC_UFORTCALL 60 /* ??? */ # ifdef INLINE # define PCC_INLINE 61 /* inline function */ /* no ASG */ # define PCC_UINLINE 63 /* inline with no arguments */ # endif INLINE /* * Referencing and dereferencing. */ # define PCC_DEREF 20 /* * */ # define PCC_ADDROF 30 /* & */ /* * Special structure operators. */ # define PCC_DOT 64 /* . */ # define PCC_STREF 65 /* -> */ # define PCC_STASG 66 /* structure assignment */ # define PCC_STARG 67 /* an argument of type structure */ # define PCC_STCALL 68 /* a function of type structure */ /* no ASG */ # define PCC_USTCALL 70 /* unary structure function */ /* * Conversions. */ # define PCC_SCONV 71 /* scalar conversion */ # define PCC_PCONV 72 /* pointer conversion */ # define PCC_PMCONV 73 /* pointer multiply conversion */ # define PCC_PVCONV 74 /* pointer divide conversion */ # define PCC_CAST 75 /* redundant? */ /* * Bracket types. */ # define PCC_LB 76 /* [ */ # define PCC_RB 77 /* ] */ /* * Comma nodes. */ # define PCC_COMOP 78 /* , (in expressions) */ # define PCC_CM 79 /* , (in argument lists) */ /* * Miscellaneous. */ # define PCC_FORCE 80 /* result of last expression goes in r0 */ # define PCC_GOTO 81 /* unconditional goto */ # define PCC_CBRANCH 82 /* goto label if !test */ # define PCC_RETURN 83 /* return from function */ # define PCC_INIT 84 /* initialized data */ # define PCC_TYPE 85 /* a type */ # define PCC_CLASS 86 /* a storage class */ # define PCC_MAXOP 86 /* highest numbered PCC op */ /* * Special codes for interfacing to /lib/f1. */ # define PCCF_FORTOPS 150 # define PCCF_FTEXT 150 /* pass literal assembler text */ # define PCCF_FEXPR 151 /* a statement */ # define PCCF_FSWITCH 152 /* not implemented */ # define PCCF_FLBRAC 153 /* beginning of subroutine */ # define PCCF_FRBRAC 154 /* end of subroutine */ # define PCCF_FEOF 155 /* end of file */ # define PCCF_FARIF 156 /* not implemented */ # define PCCF_FLABEL 157 /* an f77 label */ # endif PCC_TOKENS /* * Types, as encoded in intermediate file cookies. */ # define PCCT_UNDEF 0 # define PCCT_FARG 1 /* function argument */ # define PCCT_CHAR 2 # define PCCT_SHORT 3 # define PCCT_INT 4 # define PCCT_LONG 5 # define PCCT_FLOAT 6 # define PCCT_DOUBLE 7 # define PCCT_STRTY 8 # define PCCT_UNIONTY 9 # define PCCT_ENUMTY 10 # define PCCT_MOETY 11 /* member of enum */ # define PCCT_UCHAR 12 # define PCCT_USHORT 13 # define PCCT_UNSIGNED 14 # define PCCT_ULONG 15 /* * Type modifiers. */ # define PCCTM_PTR 020 # define PCCTM_FTN 040 # define PCCTM_ARY 060 # define PCCTM_BASETYPE 017 # define PCCTM_TYPESHIFT 2 /* * Useful macros. 'PCCOM' macros apply to ops. */ # define PCCOM_ASG 1+ # define PCCOM_UNARY 2+ # define PCCOM_NOASG (-1)+ # define PCCOM_NOUNARY (-2)+ # define PCCM_TRIPLE(op, var, type) \ ((op) | ((var) << 8) | (long) (type) << 16) # define PCCM_TEXT(s) \ PCCM_TRIPLE(PCCF_FTEXT, (strlen(s) + 3) / 4, 0) # define PCCM_ADDTYPE(t, m) \ ((((t) &~ PCCTM_BASETYPE) << PCCTM_TYPESHIFT) | \ (m) | ((t) & PCCTM_BASETYPE)) of (u_short); m->m_len -= 2 * sizeof (u_short); *(mtod(m, struct ifnet **)) = ifp; } switch (eh->ether_type) { #ifdef INET case ETHERTYPE_IP: schednetisr(NETISR_IP); inq = &ipintrq; break; case ETHERTYPE_ARP: arpinput(&sc->is_ac, m); return; #endif #ifdef NS case ETHERTYPE_NS: schednetisr(NETinclude/pwd.h 444 0 12 3106 4433460540 6416 /* * Copyright (c) 1988 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)pwd.h 4.3 (Berkeley) 2/22/89 */ #define _PATH_PASSWD "/etc/passwd" #define _PATH_MASTERPASSWD "/etc/master.passwd" #define _PATH_MKPASSWD "/etc/mkpasswd" #define _PATH_PTMP "/etc/ptmp" #define _PW_KEYBYNAME '0' #define _PW_KEYBYUID '1' struct passwd { char *pw_name; /* user name */ char *pw_passwd; /* encrypted password */ int pw_uid; /* user uid */ int pw_gid; /* user gid */ long pw_change; /* password change time */ char *pw_class; /* user access class */ char *pw_gecos; /* Honeywell login info */ char *pw_dir; /* home directory */ char *pw_shell; /* default shell */ long pw_expire; /* account expiration */ }; struct passwd *getpwent(), *getpwuid(), *getpwnam(); void endpwent(), setpwfile(); int setpassent(), setpwent(); ine PCC_STRING 3 /* a string constant */ # define PCC_ICON 4 /* an integer constant */ # define PCC_FCON 5 /* a floating point constant */ # define PCC_DCON 6 /* a double precision f.p. constant */ /* * Leaf types. */ # define PCC_NAME 7 /* an identifier */ # define PCC_REG 8 /* a register */ # define PCC_OREG 9 /* register and offset */ # define PCC_CCODES 10 /* condition codes */ # define PCC_FLD 11 /* a bit field */ /* * Arithmeinclude/sgtty.h 444 0 12 112 3770654323 6757 /* sgtty.h 4.2 85/01/03 */ #ifndef _IOCTL_ #include #endif QMakefilePa.out.hO ar.hdNassert.hMctype.hLcurses.hK dbm.hJ OLDudGerrno.hFfcntl.hEframe.hDfstab.hC grp.hB lastlog.hAmath.hh@memory.h? mp.hd>mtab.h=ndbm.h<netdb.h;nlist.h:paths.h9 pcc.h8 pwd.h7sgtty.h6ranlib.h5regexp.h4resolv.h3 vmf.h2include/ranlib.h 444 0 12 4242 5355112415 7074 /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ranlib.h 5.2 (Berkeley) 4/3/91 */ #ifndef _RANLIB_H_ #define _RANLIB_H_ #define RANLIBMAG "__.SYMDEF" /* archive file name */ #define RANLIBSKEW 3 /* creation time offset */ struct ranlib { union { off_t ran_strx; /* string table index */ char *ran_name; /* in memory symbol name */ } ran_un; off_t ran_off; /* archive file offset */ }; #endif /* !_RANLIB_H_ */ efine PCC_ANDEQ 29 /* &= */ /* Reserve a slot for 'unary &', jargon for PCC_ADDROF */ # define PCC_OR 31 /* | */ # define PCC_OREQ 32 /* |= */ # define PCC_ER 33 /* ^ */ # define PCC_EREQ 34 /* ^= */ # define PCC_LS 35 /* << */ # define PCC_LSEQ 36 /* <<= */ # define PCC_RS 37 /* >> */ # define PCC_RSEQ 38 /* >>= */ # define PCC_COMPL 39 /* ~ *include/regexp.h 644 0 12 1076 4326025154 7123 /* * Definitions etc. for regexp(3) routines. * * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof], * not the System V one. */ #define NSUBEXP 10 typedef struct regexp { char *startp[NSUBEXP]; char *endp[NSUBEXP]; char regstart; /* Internal use only. */ char reganch; /* Internal use only. */ char *regmust; /* Internal use only. */ int regmlen; /* Internal use only. */ char program[1]; /* Unwarranted chumminess with compiler. */ } regexp; extern regexp *regcomp(); extern int regexec(); extern void regsub(); extern void regerror(); s provided with thdistribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific priorinclude/resolv.h 444 0 12 3355 4314377230 7145 /* * Copyright (c) 1983, 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)resolv.h 5.5 (Berkeley) 5/12/87 */ /* * Global defines and variables for resolver stub. */ #define MAXNS 3 /* max # name servers we'll track */ #define MAXDNSRCH 3 /* max # default domain levels to try */ #define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */ #define RES_TIMEOUT 4 /* seconds between retries */ struct state { int retrans; /* retransmition time interval */ int retry; /* number of times to retransmit */ long options; /* option flags - see below. */ int nscount; /* number of name servers */ struct sockaddr_in nsaddr_list[MAXNS]; /* address of name server */ #define nsaddr nsaddr_list[0] /* for backward compatibility */ u_short id; /* current packet id */ char defdname[MAXDNAME]; /* default domain */ char *dnsrch[MAXDNSRCH+1]; /* components of domain to search */ }; /* * Resolver options */ #define RES_INIT 0x0001 /* address initialized */ #define RES_DEBUG 0x0002 /* print debug messages */ #define RES_AAONLY 0x0004 /* authoritative answers only */ #define RES_USEVC 0x0008 /* use virtual circuit */ #define RES_PRIMARY 0x0010 /* query primary server only */ #define RES_IGNTC 0x0020 /* ignore trucation errors */ #define RES_RECURSE 0x0040 /* recursion desired */ #define RES_DEFNAMES 0x0080 /* use default domain name */ #define RES_STAYOPEN 0x0100 /* Keep TCP socket open */ #define RES_DNSRCH 0x0200 /* search up local domain tree */ #define RES_DEFAULT (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH) extern struct state _res; extern char *p_cdname(), *p_rr(), *p_type(), *p_class(); F ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ranlib.h 5.2 (Berkeley) 4/3/91 */ #ifndef _RANLIB_H_ #define _RANLIB_H_ #define RANLIBMAG "__.SYMDEF" /* archive file name */ #define RANLIBSKEW 3 /* creation time offset */ struct ranlib { union { off_t ran_sinclude/vmf.h 644 0 12 4074 5461646002 6424 /* Program Name: vmf.h * Author: S.M. Schultz * * ----------- Modification History ------------ * Version Date Reason For Modification * 1.0 01Jan80 1. Initial release. * 2.0 31Mar83 2. Cleanup. * 3.0 08Sep93 3. Change v_foffset to off_t instead of int. * 3.1 21Oct93 4. Create union member of structure to * make 'int' or 'char' access to data easy. * Define segment+offset and modified macros. * Place into the public domain. * -------------------------------------------------- */ #include #define MAXSEGNO 512 /* max number of segments in a space */ #define BYTESPERSEG 1024 /* must be power of two! */ #define LOG2BPS 10 /* log2(BYTESPERSEG) */ #define WORDSPERSEG (BYTESPERSEG/sizeof (int)) struct vspace { int v_fd; /* file for swapping */ off_t v_foffset; /* offset for computing file addresses */ int v_maxsegno; /* number of segments in this space */ }; struct dlink { /* general double link structure */ struct dlink *fwd; /* forward link */ struct dlink *back; /* back link */ }; struct vseg { /* structure of a segment in memory */ struct dlink s_link; /* for linking into lru list */ int s_segno; /* segment number */ struct vspace *s_vspace; /* which virtual space */ int s_lock_count; int s_flags; union { int _winfo[WORDSPERSEG]; /* the actual segment */ char _cinfo[BYTESPERSEG]; } v_un; }; #define s_winfo v_un._winfo #define s_cinfo v_un._cinfo /* masks for s_flags */ #define S_DIRTY 01 /* segment has been modified */ long nswaps; /* number of swaps */ long nmapsegs; /* number of mapseg calls */ int vminit(), vmopen(); struct vseg *vmmapseg(); void vmlock(), vmunlock(), vmclrseg(), vmmodify(); void vmflush(), vmclose(); typedef long VADDR; #define VMMODIFY(seg) (seg->s_flags |= S_DIRTY) #define VSEG(va) ((short)(va >> LOG2BPS)) #define VOFF(va) ((u_short)va % BYTESPERSEG) ry symbol name */ } ran_un; off_t ran_off; /* archive file offset */ }; #endif /* !_RANLIB_H_ */ efine PCC_ANDEQ 29 /* &= */ /* Reserve a slot for 'unary &', jargon for PCC_ADDROF */ # define PCC_OR 31 /* | */ # define PCC_OREQ 32 /* |= */ # define PCC_ER 33 /* ^ */ # define PCC_EREQ 34 /* ^= */ # define PCC_LS 35 /* << */ # define PCC_LSEQ 36 /* <<= */ # define PCC_RS 37 /* >> */ # define PCC_RSEQ 38 /* >>= */ # define PCC_COMPL 39 /* ~ *include/setjmp.h 444 0 12 66 5511222600 7057 /* setjmp.h 4.1 93/12/31 */ typedef int jmp_buf[10]; otocolsW arpadQMakefilePa.out.hO ar.hdNassert.hMctype.hLcurses.hK dbm.hJ OLDudGerrno.hFfcntl.hEframe.hDfstab.hC grp.hB lastlog.hAmath.hh@memory.h? mp.hd>mtab.h=ndbm.h<netdb.h;nlist.h:paths.h9 pcc.h8 pwd.h7sgtty.h6ranlib.h5regexp.h4resolv.h3 vmf.h2include/signal.h 444 0 12 10766 4053130003 7115 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)signal.h 1.1 (2.10BSD Berkeley) 12/1/86 */ #ifndef NSIG #define NSIG 32 #define SIGHUP 1 /* hangup */ #define SIGINT 2 /* interrupt */ #define SIGQUIT 3 /* quit */ #define SIGILL 4 /* illegal instruction (not reset when caught) */ #define ILL_RESAD_FAULT 0x0 /* reserved addressing fault */ #define ILL_PRIVIN_FAULT 0x1 /* privileged instruction fault */ #define ILL_RESOP_FAULT 0x2 /* reserved operand fault */ /* CHME, CHMS, CHMU are not yet given back to users reasonably */ #define SIGTRAP 5 /* trace trap (not reset when caught) */ #define SIGIOT 6 /* IOT instruction */ #define SIGABRT SIGIOT /* compatibility */ #define SIGEMT 7 /* EMT instruction */ #define SIGFPE 8 /* floating point exception */ #define FPE_INTOVF_TRAP 0x1 /* integer overflow */ #define FPE_INTDIV_TRAP 0x2 /* integer divide by zero */ #define FPE_FLTOVF_TRAP 0x3 /* floating overflow */ #define FPE_FLTDIV_TRAP 0x4 /* floating/decimal divide by zero */ #define FPE_FLTUND_TRAP 0x5 /* floating underflow */ #define FPE_DECOVF_TRAP 0x6 /* decimal overflow */ #define FPE_SUBRNG_TRAP 0x7 /* subscript out of range */ #define FPE_FLTOVF_FAULT 0x8 /* floating overflow fault */ #define FPE_FLTDIV_FAULT 0x9 /* divide by zero floating fault */ #define FPE_FLTUND_FAULT 0xa /* floating underflow fault */ #ifdef pdp11 #define FPE_CRAZY 0xb /* illegal return code - FPU crazy */ #define FPE_OPCODE_TRAP 0xc /* bad floating point op code */ #define FPE_OPERAND_TRAP 0xd /* bad floating point operand */ #define FPE_MAINT_TRAP 0xe /* maintenance trap */ #endif #define SIGKILL 9 /* kill (cannot be caught or ignored) */ #define SIGBUS 10 /* bus error */ #define SIGSEGV 11 /* segmentation violation */ #define SIGSYS 12 /* bad argument to system call */ #define SIGPIPE 13 /* write on a pipe with no one to read it */ #define SIGALRM 14 /* alarm clock */ #define SIGTERM 15 /* software termination signal from kill */ #define SIGURG 16 /* urgent condition on IO channel */ #define SIGSTOP 17 /* sendable stop signal not from tty */ #define SIGTSTP 18 /* stop signal from tty */ #define SIGCONT 19 /* continue a stopped process */ #define SIGCHLD 20 /* to parent on child stop or exit */ #define SIGCLD SIGCHLD /* compatibility */ #define SIGTTIN 21 /* to readers pgrp upon background tty read */ #define SIGTTOU 22 /* like TTIN for output if (tp->t_local<OSTOP) */ #define SIGIO 23 /* input/output possible signal */ #define SIGXCPU 24 /* exceeded CPU time limit */ #define SIGXFSZ 25 /* exceeded file size limit */ #define SIGVTALRM 26 /* virtual time alarm */ #define SIGPROF 27 /* profiling time alarm */ #define SIGWINCH 28 /* window size changes */ #define SIGUSR1 30 /* user defined signal 1 */ #define SIGUSR2 31 /* user defined signal 2 */ #ifndef KERNEL int (*signal())(); #endif /* * Signal vector "template" used in sigvec call. */ struct sigvec { int (*sv_handler)(); /* signal handler */ long sv_mask; /* signal mask to apply */ int sv_flags; /* see signal options below */ }; #define SV_ONSTACK 0x0001 /* take signal on signal stack */ #define SV_INTERRUPT 0x0002 /* do not restart system on signal return */ #define sv_onstack sv_flags /* isn't compatibility wonderful! */ /* * Structure used in sigstack call. */ struct sigstack { char *ss_sp; /* signal stack pointer */ int ss_onstack; /* current status */ }; /* * Information pushed on stack when a signal is delivered. * This is used by the kernel to restore state following * execution of the signal handler. It is also made available * to the handler to allow it to properly restore state if * a non-standard exit is performed. */ struct sigcontext { int sc_onstack; /* sigstack state to restore */ long sc_mask; /* signal mask to restore */ int sc_sp; /* sp to restore */ int sc_fp; /* fp to restore */ int sc_r1; /* r1 to restore */ int sc_r0; /* r0 to restore */ int sc_pc; /* pc to restore */ int sc_ps; /* psl to restore */ int sc_ovno /* overlay to restore */ }; #define BADSIG (int (*)())-1 #define SIG_DFL (int (*)())0 #define SIG_IGN (int (*)())1 #ifdef KERNEL #define SIG_CATCH (int (*)())2 #define SIG_HOLD (int (*)())3 #endif #endif /* * Macro for converting signal number to a mask suitable for * sigblock(). */ #define sigmask(m) ((long)1 << ((m)-1)) #ifndef KERNEL extern long sigblock(), sigsetmask(); #endif RETURN 83 include/stab.h 444 0 12 3475 3770654326 6600 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)stab.h 5.1 (Berkeley) 5/30/85 */ /* IF YOU ADD DEFINITIONS, ADD THEM TO nm.c as well */ /* * This file gives definitions supplementing * for permanent symbol table entries. * These must have one of the N_STAB bits on, * and are subject to relocation according to the masks in . */ /* * for symbolic debugger, sdb(1): */ #define N_GSYM 0x20 /* global symbol: name,,0,type,0 */ #define N_FNAME 0x22 /* procedure name (f77 kludge): name,,0 */ #define N_FUN 0x24 /* procedure: name,,0,linenumber,address */ #define N_STSYM 0x26 /* static symbol: name,,0,type,address */ #define N_LCSYM 0x28 /* .lcomm symbol: name,,0,type,address */ #define N_RSYM 0x40 /* register sym: name,,0,type,register */ #define N_SLINE 0x44 /* src line: 0,,0,linenumber,address */ #define N_SSYM 0x60 /* structure elt: name,,0,type,struct_offset */ #define N_SO 0x64 /* source file name: name,,0,0,address */ #define N_LSYM 0x80 /* local sym: name,,0,type,offset */ #define N_SOL 0x84 /* #included file name: name,,0,0,address */ #define N_PSYM 0xa0 /* parameter: name,,0,type,offset */ #define N_ENTRY 0xa4 /* alternate entry: name,linenumber,address */ #define N_LBRAC 0xc0 /* left bracket: 0,,0,nesting level,address */ #define N_RBRAC 0xe0 /* right bracket: 0,,0,nesting level,address */ #define N_BCOMM 0xe2 /* begin common: name,, */ #define N_ECOMM 0xe4 /* end common: name,, */ #define N_ECOML 0xe8 /* end common (local name): ,,address */ #define N_LENG 0xfe /* second stab entry with length information */ /* * for the berkeley pascal compiler, pc(1): */ #define N_PC 0x30 /* global pascal symbol: name,,0,subtype,line */ symbol: name,,0,type,address */ #define N_RSYM 0x40 /* register sym: name,,0,type,register */ #define N_SLINE 0x44 /* src line: 0,,0,linenumber,address */ #define N_SSYM 0x60 /* structure elt:include/stdio.h 444 0 12 3120 4323203741 6736 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)stdio.h 5.3 (Berkeley) 3/15/86 */ # ifndef FILE #define BUFSIZ 1024 extern struct _iobuf { int _cnt; char *_ptr; /* should be unsigned char */ char *_base; /* ditto */ int _bufsiz; short _flag; char _file; /* should be short */ } _iob[]; #define _IOREAD 01 #define _IOWRT 02 #define _IONBF 04 #define _IOMYBUF 010 #define _IOEOF 020 #define _IOERR 040 #define _IOSTRG 0100 #define _IOLBF 0200 #define _IORW 0400 #define NULL 0 #define FILE struct _iobuf #define EOF (-1) #define stdin (&_iob[0]) #define stdout (&_iob[1]) #define stderr (&_iob[2]) #ifndef lint #define getc(p) (--(p)->_cnt>=0? (int)(*(unsigned char *)(p)->_ptr++):_filbuf(p)) #endif not lint #define getchar() getc(stdin) #ifndef lint #define putc(x, p) (--(p)->_cnt >= 0 ?\ (int)(*(unsigned char *)(p)->_ptr++ = (x)) :\ (((p)->_flag & _IOLBF) && -(p)->_cnt < (p)->_bufsiz ?\ ((*(p)->_ptr = (x)) != '\n' ?\ (int)(*(unsigned char *)(p)->_ptr++) :\ _flsbuf(*(unsigned char *)(p)->_ptr, p)) :\ _flsbuf((unsigned char)(x), p))) #endif not lint #define putchar(x) putc(x,stdout) #define feof(p) (((p)->_flag&_IOEOF)!=0) #define ferror(p) (((p)->_flag&_IOERR)!=0) #define fileno(p) ((p)->_file) #define clearerr(p) ((p)->_flag &= ~(_IOERR|_IOEOF)) FILE *fopen(); FILE *fdopen(); FILE *freopen(); FILE *popen(); long ftell(); char *fgets(); char *gets(); #ifdef vax char *sprintf(); /* too painful to do right */ #endif # endif FPE_OPCODE_TRAP 0xc /* bad floating point op code */ #define FPE_OPERAND_TRAP 0xd /* bad floating point operand */ #define FPE_MAINT_TRAP 0xe /* maintenance trap */ #endif #define SIGKILL 9 /* kill (cannot be caught or ignored) */ #define SIGBUS 10 /* bus error */ #define SIGSEGV 11 /* segmentation violation */ #define SIGSYS 12 /* bad argument to system call */ #define SIGPIPE 13 /* write on a pipe with no one to rinclude/string.h 444 0 12 1140 4013175025 7121 /* * Copyright (c) 1985 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)string.h 5.1 (Berkeley) 85/08/05 */ #include /* * these next few are obsolete trash */ extern char *strcpyn(); extern char *strcatn(); extern int strcmpn(); /* * and the rest are Sys5 functions supported just so * Sys5 progs will compile easily. */ extern char *strchr(); extern char *strrchr(); extern char *strpbrk(); extern int strspn(); extern int strcspn(); extern char *strtok(); ine _IORW 0400 #define NULL 0 #define FILE struct _iobuf #define EOF (-1) #define stdin (&_iob[0]) #define stdout (&_iob[1]) #define stderr (&_iob[2]) #ifndef lint #define getc(p) (--(p)->_cnt>=0? (int)(*(unsigned char *)(p)->_ptr++):_filbuf(p)) #endif not lint #define getchar() getc(stdin) #ifndef lint #define putc(x, p) (--(p)->_cnt >= 0 ?\ (int)(*(unsigned char *)(p)->_ptr++ = (x)) :\ (((p)->_flag & _IOLBFinclude/strings.h 444 0 12 2444 4433460540 7321 /* * Copyright (c) 1988 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)strings.h 5.6 (Berkeley) 12/12/88 */ /* Routines described in string(3) */ char *strcat(), *strncat(), *strcpy(), *strncpy(), *index(), *rindex(); int strcmp(), strncmp(), strcasecmp(), strncasecmp(), strlen(); /* Routines described in memory(BA_LIB); System V compatibility */ char *memccpy(), *memchr(), *memcpy(), *memset(), *strchr(), *strdup(), *strpbrk(), *strrchr(), *strsep(), *strtok(); int memcmp(), strcspn(), strspn(); /* Routines from ANSI X3J11 */ char *strerror(); ferror(p) (((p)->_flag&_IOERR)!=0) #define fileno(p) ((p)->_file) #define clearerr(p) ((p)->_flag &= ~(_IOERR|_IOEOF)) FILE *fopen(); FILE *fdopen(); FILE *freopen(); FILE *popen(); long ftell(); char *fgets(); char *geinclude/struct.h 444 0 12 450 4013175027 7124 /* struct.h 4.1 83/05/03 */ /* * access to information relating to the fields of a structure */ #define fldoff(str, fld) ((int)&(((struct str *)0)->fld)) #define fldsiz(str, fld) (sizeof(((struct str *)0)->fld)) #define strbase(str, ptr, fld) ((struct str *)((char *)(ptr)-fldoff(str, fld))) include/syscall.h 444 0 12 7575 5555646733 7334 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)syscall.h 5.4.2 (2.11BSD GTE) 4/21/94 */ #define SYS_exit 1 #define SYS_fork 2 #define SYS_read 3 #define SYS_write 4 #define SYS_open 5 #define SYS_close 6 #define SYS_wait4 7 #define SYS_creat 8 #define SYS_link 9 #define SYS_unlink 10 #define SYS_execv 11 #define SYS_chdir 12 #define SYS_fchdir 13 #define SYS_mknod 14 #define SYS_chmod 15 #define SYS_chown 16 /* 17 is old: sbreak */ /* 18 is old: stat */ #define SYS_lseek 19 #define SYS_getpid 20 #define SYS_mount 21 #define SYS_umount 22 /* 23 is old: setuid */ #define SYS_getuid 24 /* 25 is old: stime */ #define SYS_ptrace 26 /* 27 is old: alarm */ /* 28 is old: fstat */ /* 29 is old: pause */ /* 30 is old: utime */ /* 31 is old: stty */ /* 32 is old: gtty */ #define SYS_access 33 /* 34 is old: nice */ /* 35 is old: ftime */ #define SYS_sync 36 #define SYS_kill 37 #define SYS_stat 38 /* 39 is old: setpgrp */ #define SYS_lstat 40 #define SYS_dup 41 #define SYS_pipe 42 /* 43 is old: times */ #define SYS_profil 44 /* 45 is unused */ /* 46 is old: setgid */ #define SYS_getgid 47 /* 48 is old: sigsys */ /* 49 is unused */ /* 50 is unused */ #define SYS_acct 51 #define SYS_phys 52 #define SYS_lock 53 #define SYS_ioctl 54 #define SYS_reboot 55 /* 56 is old: mpxchan */ #define SYS_symlink 57 #define SYS_readlink 58 #define SYS_execve 59 #define SYS_umask 60 #define SYS_chroot 61 #define SYS_fstat 62 /* 63 is unused */ #define SYS_getpagesize 64 #define SYS_mremap 65 #define SYS_vfork 66 /* 67 is old: vread */ /* 68 is old: vwrite */ #define SYS_sbrk 69 #define SYS_sstk 70 #define SYS_mmap 71 /* 72 is old: vadvise */ #define SYS_munmap 73 #define SYS_mprotect 74 #define SYS_madvise 75 #define SYS_vhangup 76 /* 77 is old: vlimit */ #define SYS_mincore 78 #define SYS_getgroups 79 #define SYS_setgroups 80 #define SYS_getpgrp 81 #define SYS_setpgrp 82 #define SYS_setitimer 83 /* 84 is old; wait,wait3 */ #define SYS_swapon 85 #define SYS_getitimer 86 #define SYS_gethostname 87 #define SYS_sethostname 88 #define SYS_getdtablesize 89 #define SYS_dup2 90 #define SYS_getdopt 91 #define SYS_fcntl 92 #define SYS_select 93 #define SYS_setdopt 94 #define SYS_fsync 95 #define SYS_setpriority 96 #define SYS_socket 97 #define SYS_connect 98 #define SYS_accept 99 #define SYS_getpriority 100 #define SYS_send 101 #define SYS_recv 102 #define SYS_sigreturn 103 #define SYS_bind 104 #define SYS_setsockopt 105 #define SYS_listen 106 /* 107 was vtimes */ #define SYS_sigvec 108 #define SYS_sigblock 109 #define SYS_sigsetmask 110 #define SYS_sigpause 111 #define SYS_sigstack 112 #define SYS_recvmsg 113 #define SYS_sendmsg 114 /* 115 is old vtrace */ #define SYS_gettimeofday 116 #define SYS_getrusage 117 #define SYS_getsockopt 118 /* 119 is old resuba */ #define SYS_readv 120 #define SYS_writev 121 #define SYS_settimeofday 122 #define SYS_fchown 123 #define SYS_fchmod 124 #define SYS_recvfrom 125 #define SYS_setreuid 126 #define SYS_setregid 127 #define SYS_rename 128 #define SYS_truncate 129 #define SYS_ftruncate 130 #define SYS_flock 131 /* 132 is unused */ #define SYS_sendto 133 #define SYS_shutdown 134 #define SYS_socketpair 135 #define SYS_mkdir 136 #define SYS_rmdir 137 #define SYS_utimes 138 /* 139 is unused */ #define SYS_adjtime 140 #define SYS_getpeername 141 #define SYS_gethostid 142 #define SYS_sethostid 143 #define SYS_getrlimit 144 #define SYS_setrlimit 145 #define SYS_killpg 146 /* 147 is unused */ #define SYS_setquota 148 #define SYS_quota 149 #define SYS_getsockname 150 /* * 2BSD special calls */ /* 151 is unused */ #define SYS_nostk 152 #define SYS_fetchi 153 #define SYS_ucall 154 #define SYS_fperr 155 #define SYS_gldav 156 efine SIGCLD SIGCHLD /* compatibility */ #define SIGTTIN 21 /* to readers pgrp upon background tty read */ #define SIGTTOU 22 /* liinclude/sysexits.h 444 0 12 10242 4314376572 7547 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * @(#)sysexits.h 4.4 (Berkeley) 3/24/88 */ /* ** SYSEXITS.H -- Exit status codes for system programs. ** ** This include file attempts to categorize possible error ** exit statuses for system programs, notably delivermail ** and the Berkeley network. ** ** Error numbers begin at EX__BASE to reduce the possibility of ** clashing with other exit statuses that random programs may ** already return. The meaning of the codes is approximately ** as follows: ** ** EX_USAGE -- The command was used incorrectly, e.g., with ** the wrong number of arguments, a bad flag, a bad ** syntax in a parameter, or whatever. ** EX_DATAERR -- The input data was incorrect in some way. ** This should only be used for user's data & not ** system files. ** EX_NOINPUT -- An input file (not a system file) did not ** exist or was not readable. This could also include ** errors like "No message" to a mailer (if it cared ** to catch it). ** EX_NOUSER -- The user specified did not exist. This might ** be used for mail addresses or remote logins. ** EX_NOHOST -- The host specified did not exist. This is used ** in mail addresses or network requests. ** EX_UNAVAILABLE -- A service is unavailable. This can occur ** if a support program or file does not exist. This ** can also be used as a catchall message when something ** you wanted to do doesn't work, but you don't know ** why. ** EX_SOFTWARE -- An internal software error has been detected. ** This should be limited to non-operating system related ** errors as possible. ** EX_OSERR -- An operating system error has been detected. ** This is intended to be used for such things as "cannot ** fork", "cannot create pipe", or the like. It includes ** things like getuid returning a user that does not ** exist in the passwd file. ** EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp, ** etc.) does not exist, cannot be opened, or has some ** sort of error (e.g., syntax error). ** EX_CANTCREAT -- A (user specified) output file cannot be ** created. ** EX_IOERR -- An error occurred while doing I/O on some file. ** EX_TEMPFAIL -- temporary failure, indicating something that ** is not really an error. In sendmail, this means ** that a mailer (e.g.) could not create a connection, ** and the request should be reattempted later. ** EX_PROTOCOL -- the remote system returned something that ** was "not possible" during a protocol exchange. ** EX_NOPERM -- You did not have sufficient permission to ** perform the operation. This is not intended for ** file system problems, which should use NOINPUT or ** CANTCREAT, but rather for higher level permissions. ** For example, kre uses this to restrict who students ** can send mail to. ** ** Maintained by Eric Allman (eric@berkeley, ucbvax!eric) -- ** please mail changes to me. ** ** @(#)sysexits.h 4.4 3/24/88 */ # define EX_OK 0 /* successful termination */ # define EX__BASE 64 /* base value for error messages */ # define EX_USAGE 64 /* command line usage error */ # define EX_DATAERR 65 /* data format error */ # define EX_NOINPUT 66 /* cannot open input */ # define EX_NOUSER 67 /* addressee unknown */ # define EX_NOHOST 68 /* host name unknown */ # define EX_UNAVAILABLE 69 /* service unavailable */ # define EX_SOFTWARE 70 /* internal software error */ # define EX_OSERR 71 /* system error (e.g., can't fork) */ # define EX_OSFILE 72 /* critical OS file missing */ # define EX_CANTCREAT 73 /* can't create (user) output file */ # define EX_IOERR 74 /* input/output error */ # define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */ # define EX_PROTOCOL 76 /* remote error in protocol */ # define EX_NOPERM 77 /* permission denied */ # define EX_CONFIG 78 /* configuration error */ ))-1 #define SIG_DFL (int (*)())0 #define SIG_IGN (int (*)())1 #ifdef KERNEL #define SIG_CATCH (int (*)())2 #define SIG_HOLD (int (*)())3 #endif #endif /* * Macro for converting signal number to a mask suitable for * sigblock(). */ #define sigmask(m) ((long)1 << ((m)-1)) #ifndef KERNEL extern long sigblock(), sigsetmask(); #endif RETURN 83 include/syslog.h 444 0 12 4543 4053130004 7135 /* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)syslog.h 7.1 (Berkeley) 6/4/86 */ /* * Facility codes */ #define LOG_KERN (0<<3) /* kernel messages */ #define LOG_USER (1<<3) /* random user-level messages */ #define LOG_MAIL (2<<3) /* mail system */ #define LOG_DAEMON (3<<3) /* system daemons */ #define LOG_AUTH (4<<3) /* security/authorization messages */ #define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */ #define LOG_LPR (6<<3) /* line printer subsystem */ /* other codes through 15 reserved for system use */ #define LOG_LOCAL0 (16<<3) /* reserved for local use */ #define LOG_LOCAL1 (17<<3) /* reserved for local use */ #define LOG_LOCAL2 (18<<3) /* reserved for local use */ #define LOG_LOCAL3 (19<<3) /* reserved for local use */ #define LOG_LOCAL4 (20<<3) /* reserved for local use */ #define LOG_LOCAL5 (21<<3) /* reserved for local use */ #define LOG_LOCAL6 (22<<3) /* reserved for local use */ #define LOG_LOCAL7 (23<<3) /* reserved for local use */ #define LOG_NFACILITIES 24 /* maximum number of facilities */ #define LOG_FACMASK 0x03f8 /* mask to extract facility part */ /* * Priorities (these are ordered) */ #define LOG_EMERG 0 /* system is unusable */ #define LOG_ALERT 1 /* action must be taken immediately */ #define LOG_CRIT 2 /* critical conditions */ #define LOG_ERR 3 /* error conditions */ #define LOG_WARNING 4 /* warning conditions */ #define LOG_NOTICE 5 /* normal but signification condition */ #define LOG_INFO 6 /* informational */ #define LOG_DEBUG 7 /* debug-level messages */ #define LOG_PRIMASK 0x0007 /* mask to extract priority part (internal) */ /* * arguments to setlogmask. */ #define LOG_MASK(pri) (1 << (pri)) /* mask for one priority */ #define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1) /* all priorities through pri */ /* * Option flags for openlog. * * LOG_ODELAY no longer does anything; LOG_NDELAY is the * inverse of what it used to be. */ #define LOG_PID 0x01 /* log the pid with each message */ #define LOG_CONS 0x02 /* log on the console if errors in sending */ #define LOG_ODELAY 0x04 /* delay open until syslog() is called */ #define LOG_NDELAY 0x08 /* don't delay open */ #define LOG_NOWAIT 0x10 /* if forking to log on console, don't wait() */ vel messages */ #define LOG_MAIL (2<<3) /* mail system */ #define LOG_DAEMON (3<<3) /* system daemons */ #define LOG_AUTH (4<<3) /* security/authorization meinclude/time.h 444 0 12 1063 4033621176 6562 /* * Copyright (c) 1983, 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)time.h 1.2 (Berkeley) 3/4/87 */ /* * Structure returned by gmtime and localtime calls (see ctime(3)). */ struct tm { int tm_sec; int tm_min; int tm_hour; int tm_mday; int tm_mon; int tm_year; int tm_wday; int tm_yday; int tm_isdst; long tm_gmtoff; char *tm_zone; }; extern struct tm *gmtime(), *localtime(); extern char *asctime(), *ctime(); erated internally by syslogd #define LOG_LPR (6<<3) /* line printer subsystem */ /* other codes through 15 reserved for system use */ #define LOG_LOCAL0 (16<<3) /* reserved for local use */ #define LOG_LOCAL1 (17<<3) /* reserved for local use */ #define LOG_LOCAL2 (18<<3) /* reserved for local use */ #define LOG_LOCAL3 (19<<3) /* reserved for local use */ #define LOG_LOCAL4 (20<<3) /* reserved for local use */ #define LOG_LOCAL5 (21<<3) /* reserved forinclude/ttyent.h 444 0 12 1425 3770654342 7165 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)ttyent.h 5.1 (Berkeley) 5/30/85 */ struct ttyent { /* see getttyent(3) */ char *ty_name; /* terminal device name */ char *ty_getty; /* command to execute, usually getty */ char *ty_type; /* terminal type for termcap (3X) */ int ty_status; /* status flags (see below for defines) */ char *ty_window; /* command to start up window manager */ char *ty_comment; /* usually the location of the terminal */ }; #define TTY_ON 0x1 /* enable logins (startup getty) */ #define TTY_SECURE 0x2 /* allow root to login */ extern struct ttyent *getttyent(); extern struct ttyent *getttynam(); eserved for local use */ #define LOG_LOCAL2 (18<<3) /* reserved for local use */ #define LOG_LOCAL3 (19<<3) /* reserved for local use */ #define LOG_LOCAL4 (20<<3) /* reserved for local use */ #define LOG_LOCAL5 (21<<3) /* reserved forinclude/tzfile.h 444 0 12 5037 4033621200 7112 /* * @(#)tzfile.h 5.2 tzfile.h 3/4/87 */ /* ** Information about time zone files. */ #define TZDIR "/etc/zoneinfo" /* Time zone object file directory */ #define TZDEFAULT "localtime" /* ** Each file begins with. . . */ struct tzhead { char tzh_reserved[32]; /* reserved for future use */ char tzh_timecnt[4]; /* coded number of transition times */ char tzh_typecnt[4]; /* coded number of local time types */ char tzh_charcnt[4]; /* coded number of abbr. chars */ }; /* ** . . .followed by. . . ** ** tzh_timecnt (char [4])s coded transition times a la time(2) ** tzh_timecnt (unsigned char)s types of local time starting at above ** tzh_typecnt repetitions of ** one (char [4]) coded GMT offset in seconds ** one (unsigned char) used to set tm_isdt ** one (unsigned char) that's an abbreviation list index ** tzh_charcnt (char)s '\0'-terminated zone abbreviaton strings */ /* ** In the current implementation, "tzset()" refuses to deal with files that ** exceed any of the limits below. */ /* ** The TZ_MAX_TIMES value below is enough to handle a bit more than a ** year's worth of solar time (corrected daily to the nearest second) or ** 138 years of Pacific Presidential Election time ** (where there are three time zone transitions every fourth year). */ #define TZ_MAX_TIMES 370 #define NOSOLAR /* We currently don't handle solar time */ #ifndef NOSOLAR #define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ #else /* !NOSOLAR */ #define TZ_MAX_TYPES 10 /* Maximum number of local time types */ #endif /* !NOSOLAR */ #define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ #define SECS_PER_MIN 60 #define MINS_PER_HOUR 60 #define HOURS_PER_DAY 24 #define DAYS_PER_WEEK 7 #define DAYS_PER_NYEAR 365 #define DAYS_PER_LYEAR 366 #define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR) #define SECS_PER_DAY ((long) SECS_PER_HOUR * HOURS_PER_DAY) #define MONS_PER_YEAR 12 #define TM_SUNDAY 0 #define TM_MONDAY 1 #define TM_TUESDAY 2 #define TM_WEDNESDAY 3 #define TM_THURSDAY 4 #define TM_FRIDAY 5 #define TM_SATURDAY 6 #define TM_JANUARY 0 #define TM_FEBRUARY 1 #define TM_MARCH 2 #define TM_APRIL 3 #define TM_MAY 4 #define TM_JUNE 5 #define TM_JULY 6 #define TM_AUGUST 7 #define TM_SEPTEMBER 8 #define TM_OCTOBER 9 #define TM_NOVEMBER 10 #define TM_DECEMBER 11 #define TM_SUNDAY 0 #define TM_YEAR_BASE 1900 #define EPOCH_YEAR 1970 #define EPOCH_WDAY TM_THURSDAY /* ** Accurate only for the past couple of centuries; ** that will probably do. */ #define isleap(y) (((y) % 4) == 0 && ((y) % 100) != 0 || ((y) % 400) == 0) some file. ** EX_TEMPFAIL -- temporary failure, indicating something that ** is not really an error. In sendmail, this means ** that a mailer (e.g.) could not create a connection, ** and the request should be reattempted later. ** EX_PROTOCOL -- the remote system returned something that ** was "not possible" during a protocol exchange. ** EX_NOPERM -- You did not have sufficient permission to ** perform the operation. This is not intended for ** file system problems, winclude/utmp.h 444 0 12 2133 5373311276 6615 /* * Copyright (c) 1988 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)utmp.h 5.6 (2.11BSD) 5/9/93 */ #define _PATH_UTMP "/etc/utmp" #define _PATH_WTMP "/usr/adm/wtmp" #define UT_NAMESIZE 15 #define UT_LINESIZE 8 #define UT_HOSTSIZE 16 struct utmp { char ut_line[UT_LINESIZE]; char ut_name[UT_NAMESIZE]; char ut_host[UT_HOSTSIZE]; long ut_time; }; (corrected daily to the nearest second) or ** 138 years of Pacific Presidential Election time ** (where there are three time zone transitions every fourth year). */ #define TZ_MAX_TIMES 370 #define NOSOLAR /* We currently don't handle solar time */ #ifndef NOSOLAR #define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ #else /* !NOSOLAR */ #define TZ_MAX_TYPES 10 /* Maximum number of local time include/varargs.h 444 0 12 333 3770654345 7263 /* varargs.h 4.1 83/05/03 */ typedef char *va_list; # define va_dcl int va_alist; # define va_start(list) list = (char *) &va_alist # define va_end(list) # define va_arg(list,mode) ((mode *)(list += sizeof(mode)))[-1] h$ varargs.h#vfont.hh" Makefile.installinclude/vfont.h 444 0 12 1042 4013175031 6745 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)vfont.h 5.1 (Berkeley) 5/30/85 */ /* * The structures header and dispatch define the format of a font file. * * See vfont(5) for more details. */ struct header { short magic; unsigned short size; short maxx; short maxy; short xtend; }; struct dispatch { unsigned short addr; short nbytes; char up,down,left,right; short width; }; erived * from this software without specific ior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)utmp.h 5.6 (2.11BSD) 5/9/93 */ #define _PATH_UTMP "/etc/utmp" #define _PATH_WTMP "/usr/adm/wtmp" #define UT_NAMESIZE 15 #define UT_LINESIZE 8 #define UT_HOSTSIZE 16 struct utmp { char ut_liinclude/Makefile.install 444 3 12 3037 4361165760 10574 # # Copyright (c) 1983,1986 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)Makefile.install 5.3 (Berkeley) 10/13/86 # # Makefile for /usr/include, used to convert system include subdirectories # between symbolic links and copies of kernel headers. # May also be used to update copies from kernel header files. # # The ``rm -rf''s used below are safe because rm doesn't # follow symbolic links. # DESTDIR= #ifdef vax #MACHINE=vax #MACHDEP=${MACHINE} vaxif vaxmba vaxuba #endif MACHINE=pdp MACHDEP=${MACHINE} pdpmba pdpuba stand vaxif vaxuba NETDIRS=net netimp netinet netns netpup SYSDIRS=${NETDIRS} ${MACHDEP} SYS=/sys all: @echo "\"make symlinks\", \"make copies\", or \"make update\" only" @false symlinks: for i in ${SYSDIRS}; do \ rm -rf $$i; \ ln -s ${SYS}/$$i $$i; \ done rm -rf sys ln -s ${SYS}/h sys copies: -for i in ${SYSDIRS}; do \ rm -rf $$i; \ (cd ${SYS}; tar cf - $$i/*.h) | tar xpfB -; \ done rm -rf sys; mkdir sys; chmod 775 sys; -(cd ${SYS}/h; tar cf - *.h) | (cd sys; tar xpfB -) update: -for i in ${SYSDIRS}; do \ if [ ! -d $$i ]; \ then \ mkdir $$i; \ fi; \ for j in `cd ${SYS}/$$i; echo *.[ih]`; do \ cmp -s ${SYS}/$$i/$$j $$i/$$j || \ install -c -m 444 ${SYS}/$$i/$$j $$i/$$j; \ done; \ done for j in `cd ${SYS}/h; echo *.[ih]`; do \ cmp -s ${SYS}/h/$$j sys/$$j || \ { echo "install -c -m 444 ${SYS}/h/$$j sys/$$j"; \ install -c -m 444 ${SYS}/h/$$j sys/$$j; } \ done; #define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ #define SECS_PER_MIN 60 #define MINS_PER_HOUR 60 #define HOURS_PER_DAY 24 #define DAYS_PER_WEEK 7 #define DAYS_PER_NYEAR 365 #define DAYS_PER_LYEAR 366 #define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR) #define SECS_PER_DAY ((long) SECS_PER_HOUR * HOURS_PER_DAY) #define MONS_PER_YEAR 12 #define TM_SUNDAY 0 #define TM_MONDAY 1 #define TM_TUESDAY 2 #define TM_WEDNESDAY 3 #define TM_THURSDAY 4 #define TMZ_MAX_TIMES value below is enough to handle a bit more than a ** year's worth of solar time (corrected daily to the nearest second) or ** 138 years of Pacific Presidential Election time ** (where there are three time zone transitions every fourth year). */ #define TZ_MAX_TIMES 370 #define NOSOLAR /* We currently don't handle solar time */ #ifndef NOSOLAR #define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ #else /* !NOSOLAR */ #define TZ_MAX_TYPES 10 /* Maximum number of local time types */ #endif /* !NOSOLAR */ #define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ #define SECS_PER_MIN 60 #define MINS_PER_HOUR 60 #define HOURS_PER_DAY 24 #define DAYS_PER_WEEK 7 #define DAYS_PER_NYEAR 365 #define DAYS_PER_LYEAR 366 #define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR) #define SECS_PER_DAY ((long) SECS_PER_HOUR * HOURS_PER_DAY) #define MONS_PER_YEAR 12 #define TM_SUNDAY 0 #define TM_MONDAY 1 #define TM_TUESDAY 2 #define TM_WEDNESDAY 3 #define TM_THURSDAY 4 #define TM_FRIDAY 5 #define TM_SATURDAY 6 #define TM_JANUARY 0 #define TM_FEBRUARY 1 #define TM_MARCH 2 #define TM_APRIL 3 #define TM_MAY 4 #define TM_JUNE 5 #define TM_JULY 6 #define TM_AUGUST 7 #define TM_SEPTEMBER 8 #define TM_OCTOBER 9 #define TM_NOVEMBER 10 #define TM_DECEMBER 11 #define TM_SUNDAY 0 #define TM_YEAR_BASE 1900 #define EPOCH_YEAR 1970 #define EPOCH_WDAY TM_THURSDAY /* ** Accurate only for the past couple of centuries; ** that will probably do. */ #define isleap(y) (((y) % 4) == 0 && ((y) % 100) != 0 || ((y) % 400) == 0) some file. ** EX_TEMPFAIL -- temporary failure, indicating something that ** is not really an error. In sendmail, this means ** that a mailer (e.g.) could not create a connection, ** and the request should be reattempted later. ** EX_PROTOCOL -- the remote system returned something that ** was "not possible" during a protocol exchange. ** EX_NOPERM -- You did not have sufficient permission to ** perform the operation. This is not intended for ** file system problems, winclude/utmp.h 444 0 12 2133 5373311276 6615 /* * Copyright (c) 1988 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)utmp.h 5.6 (2.11BSD) 5/9/93 */ #define _PATH_UTMP "/etc/utmp" #define _PATH_WTMP "/usr/adm/wtmp" #define UT_NAMESIZE 15 #define UT_LINESIZE 8 #define UT_HOSTSIZE 16 struct utmp { char ut_line[UT_LINESIZE]; char ut_name[UT_NAMESIZE]; char ut_host[UT_HOSTSIZE]; long ut_time; }; (corrected daily to the nearest second) or ** 138 years of Pacific Presidential Election time ** (where there are three time zone transitions every fourth year). */ #define TZ_MAX_TIMES 370 #define NOSOLAR /* We currently don't handle solar time */ #ifndef NOSOLAR #define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ #else /* !NOSOLAR */ #define TZ_MAX_TYPES 10 /* Maximum number of local time include/varargs.h 444 0 12 333 3770654345 7263 /* varargs.h 4.1 83/05/03 */ typedef char *va_list; # define va_dcl int va_alist; # define va_start(list) list = (char *) &va_alist # define va_end(list) # define va_arg(list,mode) ((mode *)(list += sizeof(mode)))[-1] h$ varargs.h#vfont.hh" Makefile.install