# 2.11BSD#431 - /usr/src/sys/pdpif/if_qt.c

##### Functions

    qbaini            X
    qt_ns             X
    qtattach          X
    qtinit            X
    qtintr            X
    qtioctl           X
    qtoutput          X
    qtread            X
    qtrestart         X
    qtrint            X
    qtsrr             X
    qtstart           X
    qttint            X
    qtturbo           X

##### Variables

    qt_softc          X
    qtdriver          X
    qtinfo            X
    qtstd             X

##### Macros

    BBLMIS            X
    MAXPACKETSIZE     X
    MINPACKETSIZE     X
    NRCV              X
    NXMT              X
    QTF_RUNNING       X
    QTF_STARTUP       X
    is_addr           X
    is_if             X

##### struct's

    qt_softc          X
    qt_uba            X

       1: /*	@(#)if_qt.c	1.2 (2.11BSD) 2/20/93
       2:  *
       3:  * Modification History
       4:  * 23-Feb-92 -- sms
       5:  *	Rewrite the buffer handling so that fewer than the maximum number of
       6:  *	buffers may be used (32 receive and 12 transmit buffers consume 66+kb
       7:  *	of main system memory in addition to the internal structures in the
       8:  *	networking code).  A freelist of available buffers is maintained now.
       9:  *	When I/O operations complete the associated buffer is placed on the
      10:  *	freelist (a single linked list for simplicity) and when an I/O is
      11:  *	started a buffer is pulled off the list.
      12:  *
      13:  * 20-Feb-92 -- sms
      14:  *	It works!  Darned board couldn't handle "short" rings - those rings
      15:  *	where only half the entries were made available to the board (the
      16:  *	ring descriptors were the full size, merely half the entries were
      17:  * 	flagged as belonging always to the driver).  Grrrr.  Would have thought
      18:  *	the board could skip over those entries reserved by the driver.
      19:  *	Now to find a way not to have to allocated 32+12 times 1.5kb worth of
      20:  *	buffers...
      21:  *
      22:  * 03-Feb-92 -- sms
      23:  *	Released but still not working.  The driver now responds to arp and
      24:  *	ping requests.  The board is apparently not returning ring descriptors
      25:  *	to the driver so eventually we run out of buffers.  Back to the
      26:  *	drawing board.
      27:  *
      28:  * 28-Dec-92 -- sms
      29:  *	Still not released.  Hiatus in finding free time and thin-netting
      30:  *	the systems (many thanks Terry!).
      31:  *	Added logic to dynamically allocate a vector and initialize it.
      32:  *
      33:  * 23-Oct-92 -- sms
      34:  *	The INIT block must (apparently) be quadword aligned [no thanks to
      35:  *	the manual for not mentioning that fact].  The necessary alignment
      36:  *	is achieved by allocating the INIT block from main memory ('malloc'
      37:  *	guarantees click alignment) and mapping it as needed (which is _very_
      38:  *	infrequently).  A check for quadword alignment of the ring descriptors
      39:  *	was added - at present the descriptors are properly aligned, if this
      40:  *	should change then something will have to be done (like do it "right").
      41:  *	Darned alignment restrictions!
      42:  *
      43:  *	A couple of typos were corrected (missing parentheses, reversed
      44:  *	arguments to printf calls, etc).
      45:  *
      46:  * 13-Oct-92 -- sms@wlv.iipo.gtegsc.com
      47:  *	Created based on the DELQA-PLUS addendum to DELQA User's Guide.
      48:  *	This driver ('qt') is selected at system configuration time.  If the
      49:  *	board *	is not a DELQA-YM an error message will be printed and the
      50:  *	interface will not be attached.
      51: */
      52:
      53: #include "qt.h"
      54: #if NQT > 0
      55:
      56: #include "param.h"
      57: #include "pdp/psl.h"
      58: #include "pdp/seg.h"
      59: #include "map.h"
      60: #include "systm.h"
      61: #include "mbuf.h"
      62: #include "buf.h"
      63: #include "protosw.h"
      64: #include "socket.h"
      65: #include "ioctl.h"
      66: #include "errno.h"
      67: #include "syslog.h"
      68: #include "time.h"
      69: #include "kernel.h"
      70:
      71: #include "../net/if.h"
      72: #include "../net/netisr.h"
      73: #include "../net/route.h"
      74:
      75: #ifdef INET
      76: #include "domain.h"
      77: #include "../netinet/in.h"
      78: #include "../netinet/in_systm.h"
      79: #include "../netinet/in_var.h"
      80: #include "../netinet/ip.h"
      81: #include "../netinet/if_ether.h"
      82: #endif
      83:
      84: #ifdef NS
      85: #include "../netns/ns.h"
      86: #include "../netns/ns_if.h"
      87: #endif
      88:
      89: #include "if_qtreg.h"
      90: #include "if_uba.h"
      91: #include "../pdpuba/ubavar.h"
      92:
      93: #define NRCV    16      /* Receive descriptors (must be <= 32) */
      94: #define NXMT    6       /* Transmit descriptors	(must be <= 12) */
      95: #if NRCV > 32 || NXMT > 12
      96:     generate an error
      97: #endif
      98:
      99:     struct  qt_uba
     100:         {
     101:         struct  qt_uba  *next;  /* link to next buffer in list or
     102: 					 * NULL if the last buffer
     103: 					*/
     104:         struct  ifuba   ubabuf; /* buffer descriptor */
     105:         };
     106:
     107: struct  qt_softc {
     108:     struct  arpcom is_ac;       /* common part - must be first  */
     109: #define is_if   is_ac.ac_if     /* network-visible interface 	*/
     110: #define is_addr is_ac.ac_enaddr     /* hardware Ethernet address 	*/
     111:     struct  qt_uba  *freelist;  /* list of available buffers	*/
     112:     struct  qt_uba  ifrw[NRCV + NXMT];
     113:     u_short initclick;      /* click addr of the INIT block */
     114:     struct  qt_rring *rring;    /* Receive ring address 	*/
     115:     struct  qt_tring *tring;    /* Transmit ring address 	*/
     116:     char    r_align[QT_MAX_RCV * sizeof (struct qt_rring) + 8];
     117:     char    t_align[QT_MAX_XMT * sizeof (struct qt_tring) + 8];
     118:     short   qt_flags;       /* software state		*/
     119: #define QTF_RUNNING 0x1
     120: #define QTF_STARTUP 0x2     /* Waiting for start interrupt  */
     121:     char    rindex;         /* Receive Completed Index	*/
     122:     char    nxtrcv;         /* Next Receive Index		*/
     123:     char    nrcv;           /* Number of Receives active	*/
     124:     char    tindex;         /* Transmit index		*/
     125:     char    otindex;        /* Old transmit index		*/
     126:     char    nxmit;          /* # of xmits in progress	*/
     127:     struct  qtdevice *addr;     /* device CSR addr		*/
     128: } qt_softc[NQT];
     129:
     130: struct  uba_device *qtinfo[NQT];
     131:
     132: int qtattach(), qtintr(), qtinit(), qtoutput(), qtioctl();
     133:
     134: extern  struct ifnet loif;
     135:
     136: u_short qtstd[] = { 0 };
     137:
     138: struct  uba_driver qtdriver =
     139:     { 0, 0, qtattach, 0, qtstd, "qe", qtinfo };
     140:
     141: /*
     142:  * Maximum packet size needs to include 4 bytes for the CRC
     143:  * on received packets.
     144: */
     145: #define MAXPACKETSIZE (ETHERMTU + sizeof (struct ether_header) + 4)
     146: #define MINPACKETSIZE 64
     147:
     148: /*
     149:  * The C compiler's propensity for prepending '_'s to names is the reason
     150:  * for the hack below.  We need the "handler" address (the code which
     151:  * sets up the interrupt stack frame) in order to initialize the vector.
     152: */
     153:
     154: static int qtfoo()
     155:     {
     156:     asm("mov $qtintr, r0");     /* return value is in r0 */
     157:     }
     158:
     159: /*
     160:  * Interface exists.  More accurately, something exists at the CSR (see
     161:  * sys/sys_net.c) -- there's no guarantee it's a DELQA-YM.
     162:  *
     163:  * The ring descriptors are initialized, the buffers allocated using first the
     164:  * DMA region allocated at network load time and then later main memory.  The
     165:  * INIT block is filled in and the device is poked/probed to see if it really
     166:  * is a DELQA-YM.  If the device is not a -YM then a message is printed and
     167:  * the 'if_attach' call is skipped.  For a -YM the START command is issued,
     168:  * but the device is not marked as running|up - that happens at interrupt level
     169:  * when the device interrupts to say it has started.
     170: */
     171:
     172: qtattach(ui)
     173:     struct uba_device *ui;
     174:     {
     175:     register struct qt_softc *sc = &qt_softc[ui->ui_unit];
     176:     register struct ifnet *ifp = &sc->is_if;
     177:     register struct qt_init *iniblk = (struct qt_init *)SEG5;
     178:     segm    seg5;
     179:     long    bufaddr;
     180:     extern int nextiv();
     181:
     182:     ifp->if_unit = ui->ui_unit;
     183:     ifp->if_name = "qe";
     184:     ifp->if_mtu = ETHERMTU;
     185:     ifp->if_flags = IFF_BROADCAST;
     186:
     187: /*
     188:  * Fill in most of the INIT block: vector, options (interrupt enable), ring
     189:  * locations.  The physical address is copied from the ROMs as part of the
     190:  * -YM testing proceedure.  The CSR is saved here rather than in qtinit()
     191:  * because the qtturbo() routine needs it.
     192:  *
     193:  * The INIT block must be quadword aligned.  Using malloc() guarantees click
     194:  * (64 byte) alignment.  Since the only time the INIT block is referenced is
     195:  * at 'startup' or 'reset' time there is really no time penalty (and a modest
     196:  * D space savings) involved.
     197: */
     198:     sc->addr = (struct qtdevice *)ui->ui_addr;
     199:     sc->initclick = MALLOC(coremap, btoc(sizeof (struct qt_init)));
     200:     saveseg5(seg5);
     201:     mapseg5(sc->initclick, 077406);
     202:     bzero(iniblk, sizeof (struct qt_init));
     203:     sc->rring = (struct qt_rring *)(((int)sc->r_align + 7) & ~7);
     204:     sc->tring = (struct qt_tring *)(((int)sc->t_align + 7) & ~7);
     205:
     206: /*
     207:  * Fetch the next available interrupt vector.  The routine is in the kernel
     208:  * (for several reasons) so use SKcall.  Then initialize the vector with
     209:  * the address of our 'handler' and PSW of supervisor, priority 4 and unit
     210: */
     211:     iniblk->vector = SKcall(nextiv, 0);
     212:     mtkd(iniblk->vector, qtfoo());
     213:     mtkd(iniblk->vector + 2, PSL_CURSUP | PSL_BR4 | ifp->if_unit);
     214:
     215:     iniblk->options = INIT_OPTIONS_INT;
     216:     bufaddr = startnet + (long)sc->rring;
     217:     iniblk->rx_lo = loint(bufaddr);
     218:     iniblk->rx_hi = hiint(bufaddr);
     219:     bufaddr = startnet + (long)sc->tring;
     220:     iniblk->tx_lo = loint(bufaddr);
     221:     iniblk->tx_hi = hiint(bufaddr);
     222:     restorseg5(seg5);
     223:
     224: /*
     225:  * Now allocate the buffers and initialize the buffers.  This should _never_
     226:  * fail because main memory is allocated after the DMA pool is used up.
     227: */
     228:
     229:     if  (!qbaini(sc, NRCV + NXMT))
     230:         return;     /* XXX */
     231:
     232:     ifp->if_init = qtinit;
     233:     ifp->if_output = qtoutput;
     234:     ifp->if_ioctl = qtioctl;
     235:     ifp->if_reset = 0;
     236:     if  (qtturbo(sc))
     237:         if_attach(ifp);
     238:     }
     239:
     240: qtturbo(sc)
     241:     register struct qt_softc *sc;
     242:     {
     243:     register int i;
     244:     register struct qtdevice *addr = sc->addr;
     245:     struct  qt_init *iniblk = (struct qt_init *)SEG5;
     246:     segm    seg5;
     247:
     248: /*
     249:  * Issue the software reset.  Delay 150us.  The board should now be in
     250:  * DELQA-Normal mode.  Set ITB and DEQTA select.  If both bits do not
     251:  * stay turned on then the board is not a DELQA-YM.
     252: */
     253:     addr->arqr = ARQR_SR;
     254:     addr->arqr = 0;
     255:     delay(150L);
     256:
     257:     addr->srr = 0x8001;     /* MS | ITB */
     258:     i = addr->srr;
     259:     addr->srr = 0x8000;     /* Turn off ITB, set DELQA select */
     260:     if  (i != 0x8001)
     261:         {
     262:         printf("qt@%o !-YM\n", addr);
     263:         return(0);
     264:         }
     265: /*
     266:  * Board is a DELQA-YM.  Send the commands to enable Turbo mode.  Delay
     267:  * 1 second, testing the SRR register every millisecond to see if the
     268:  * board has shifted to Turbo mode.
     269: */
     270:     addr->xcr0 = 0x0baf;
     271:     addr->xcr1 = 0xff00;
     272:     for (i = 0; i < 1000; i++)
     273:         {
     274:         if  ((addr->srr & SRR_RESP) == 1)
     275:             break;
     276:         delay(1000L);
     277:         }
     278:     if  (i >= 1000)
     279:         {
     280:         printf("qt@%o !Turbo\n", addr);
     281:         return(0);
     282:         }
     283: /*
     284:  * Board has entered Turbo mode.  Now copy the physical address from the
     285:  * ROMs to the INIT block.  Fill in the address in the part of the structure
     286:  * "visible" to the rest of the system.
     287: */
     288:     saveseg5(seg5);
     289:     mapseg5(sc->initclick, 077406);
     290:     sc->is_addr[0] = addr->sarom[0];
     291:     sc->is_addr[1] = addr->sarom[2];
     292:     sc->is_addr[2] = addr->sarom[4];
     293:     sc->is_addr[3] = addr->sarom[6];
     294:     sc->is_addr[4] = addr->sarom[8];
     295:     sc->is_addr[5] = addr->sarom[10];
     296:     bcopy(sc->is_addr, iniblk->paddr, 6);
     297:     restorseg5(seg5);
     298:     return(1);
     299:     }
     300:
     301: qtinit(unit)
     302:     int unit;
     303:     {
     304:     int s;
     305:     register struct qt_softc *sc = &qt_softc[unit];
     306:     struct qtdevice *addr = sc->addr;
     307:     struct  ifnet *ifp = &sc->is_if;
     308:     struct  qt_rring *rp;
     309:     struct  qt_tring *tp;
     310:     register struct qt_uba  *xp;
     311:     register int i;
     312:     long    buf_adr;
     313:
     314:     if  (!ifp->if_addrlist)     /* oops! */
     315:         return;
     316: /*
     317:  * Now initialize the receive ring descriptors.  Because this routine can be
     318:  * called with outstanding I/O operations we check the ring descriptors for
     319:  * a non-zero 'rhost0' (or 'thost0') word and place those buffers back on
     320:  * the free list.
     321: */
     322:     for (i = 0, rp = sc->rring; i < QT_MAX_RCV; i++, rp++)
     323:         {
     324:         rp->rmd3 = RMD3_OWN;
     325:         if  (xp = rp->rhost0)
     326:             {
     327:             rp->rhost0 = 0;
     328:             xp->next = sc->freelist;
     329:             sc->freelist = xp;
     330:             }
     331:         }
     332:     for (i = 0, tp = sc->tring ; i < QT_MAX_XMT; i++, tp++)
     333:         {
     334:         sc->tring[i].tmd3 = TMD3_OWN;
     335:         if  (xp = tp->thost0)
     336:             {
     337:             tp->thost0 = 0;
     338:             xp->next = sc->freelist;
     339:             sc->freelist = xp;
     340:             }
     341:         }
     342:
     343:     sc->nxmit = 0;
     344:     sc->otindex = 0;
     345:     sc->tindex = 0;
     346:     sc->rindex = 0;
     347:     sc->nxtrcv = 0;
     348:     sc->nrcv = 0;
     349:
     350:     s = splimp();
     351: /*
     352:  * Now we tell the device the address of the INIT block.  The device
     353:  * _must_ be in the Turbo mode at this time.  The "START" command is
     354:  * then issued to the device.  A 1 second timeout is then started.
     355:  * When the interrupt occurs the IFF_UP|IFF_RUNNING state is entered and
     356:  * full operations will proceed.  If the timeout expires without an interrupt
     357:  * being received an error is printed, the flags cleared and the device left
     358:  * marked down.
     359: */
     360:     buf_adr = ctob((long)sc->initclick);
     361:     addr->ibal = loint(buf_adr);
     362:     addr->ibah = hiint(buf_adr);
     363:     addr->srqr = 2;
     364: /*
     365:  * set internal state to 'startup' and start a one second timer.  the interrupt
     366:  * service routine will be entered either 1) when the device posts the 'start'
     367:  * interrupt or 2) when the timer expires.  The interrupt routine will fill
     368:  * the receive rings, etc.
     369: */
     370:     sc->qt_flags = QTF_STARTUP;
     371:     TIMEOUT(qtintr, unit, 60);
     372:     splx(s);
     373:     }
     374:
     375: /*
     376:  * Start output on interface.
     377:  */
     378:
     379: qtstart(unit)
     380:     int unit;
     381:     {
     382:     int     len, s;
     383:     register struct qt_softc *sc = &qt_softc[unit];
     384:     register struct qt_tring *rp;
     385:     struct  mbuf *m;
     386:     long    buf_addr;
     387:     register struct qt_uba *xp;
     388:
     389:     s = splimp();
     390:     while   (sc->nxmit < NXMT)
     391:         {
     392:         IF_DEQUEUE(&sc->is_if.if_snd, m);
     393:         if  (m == 0)
     394:             break;
     395:         rp = &sc->tring[sc->tindex];
     396: #ifdef  QTDEBUG
     397:         if  ((rp->tmd3 & TMD3_OWN) == 0)
     398:             printf("qt xmit in progress\n");
     399: #endif
     400: /*
     401:  * Now pull a buffer off of the freelist.  Guaranteed to be a buffer
     402:  * because both the receive and transmit sides limit themselves to
     403:  * NRCV and NXMT buffers respectively.
     404: */
     405:         xp = sc->freelist;
     406:         sc->freelist = xp->next;
     407:
     408:         buf_addr = xp->ubabuf.ifu_w.ifrw_info;
     409:         len = if_wubaput(&xp->ubabuf, m);
     410:         if  (len < MINPACKETSIZE)
     411:             len = MINPACKETSIZE;
     412:         rp->tmd4 = loint(buf_addr);
     413:         rp->tmd5 = hiint(buf_addr) & TMD5_HADR;
     414:         rp->tmd3 = len & TMD3_BCT;  /* set length,clear ownership */
     415:         rp->thost0 = xp;        /* set entry active */
     416:         sc->addr->arqr = ARQR_TRQ;  /* tell device it has buffer */
     417:         sc->nxmit++;
     418:         if  (++sc->tindex >= QT_MAX_XMT)
     419:             sc->tindex = 0;
     420:         }
     421:     splx(s);
     422:     }
     423:
     424: /*
     425:  * General interrupt service routine.  Receive, transmit, device start
     426:  * interrupts and timeouts come here.  Check for hard device errors and print a
     427:  * message if any errors are found.  If we are waiting for the device to
     428:  * START then check if the device is now running.
     429: */
     430:
     431: qtintr(unit)
     432:     int unit;
     433:     {
     434:     register struct qt_softc *sc = &qt_softc[unit];
     435:     register int status;
     436:     int s;
     437:
     438:     status = sc->addr->srr;
     439:     if  (status < 0)
     440:         /* should we reset the device after a bunch of these errs? */
     441:         qtsrr(unit, status);
     442:     if  (sc->qt_flags == QTF_STARTUP)
     443:         {
     444:         if  ((status & SRR_RESP) == 2)
     445:             {
     446:             sc->qt_flags = QTF_RUNNING;
     447:             sc->is_if.if_flags |= (IFF_UP | IFF_RUNNING);
     448:             }
     449:         else
     450:             printf("qt%d !start\n", unit);
     451:         }
     452:     s = splimp();
     453:     qtrint(unit);
     454:     if  (sc->nxmit)
     455:         qttint(unit);
     456:     qtstart(unit);
     457:     splx(s);
     458:     }
     459:
     460: /*
     461:  * Transmit interrupt service.  Only called if there are outstanding transmit
     462:  * requests which could have completed.  The DELQA-YM doesn't provide the
     463:  * status bits telling the kind (receive, transmit) of interrupt.
     464: */
     465:
     466: #define BBLMIS (TMD2_BBL|TMD2_MIS)
     467:
     468: qttint(unit)
     469:     int unit;
     470:     {
     471:     register struct qt_softc *sc = &qt_softc[unit];
     472:     register struct qt_tring *rp;
     473:     register struct qt_uba *xp;
     474:
     475:     while   (sc->nxmit > 0)
     476:         {
     477:         rp = &sc->tring[sc->otindex];
     478:         if  ((rp->tmd3 & TMD3_OWN) == 0)
     479:             break;
     480: /*
     481:  * Now check the buffer address (the first word in the ring descriptor
     482:  * available for the host's use).  If it is NULL then we have already seen
     483:  * and processed (or never presented to the board in the first place) this
     484:  * entry and the ring descriptor should not be counted.
     485: */
     486:         xp = rp->thost0;
     487:         if  (xp == 0)
     488:             break;
     489: /*
     490:  * Clear the buffer address from the ring descriptor and put the
     491:  * buffer back on the freelist for future use.
     492: */
     493:         rp->thost0 = 0;
     494:         xp->next = sc->freelist;
     495:         sc->freelist = xp;
     496:
     497:         sc->nxmit--;
     498:         sc->is_if.if_opackets++;
     499: /*
     500:  * Collisions don't count as output errors, but babbling and missing packets
     501:  * do count as output errors.
     502: */
     503:         if  (rp->tmd2 & TMD2_CER)
     504:             sc->is_if.if_collisions++;
     505:         if  ((rp->tmd0 & TMD0_ERR1) ||
     506:              ((rp->tmd2 & TMD2_ERR2) && (rp->tmd2 & BBLMIS)))
     507:             {
     508: #ifdef QTDEBUG
     509:             printf("qt%d tmd2 %b\n", unit, rp->tmd2, TMD2_BITS);
     510: #endif
     511:             sc->is_if.if_oerrors++;
     512:             }
     513:         if  (++sc->otindex >= QT_MAX_XMT)
     514:             sc->otindex = 0;
     515:         }
     516:     }
     517:
     518: /*
     519:  * Receive interrupt service.  Pull packet off the interface and put into
     520:  * a mbuf chain for processing later.
     521: */
     522:
     523: qtrint(unit)
     524:     int unit;
     525:     {
     526:     register struct qt_softc *sc = &qt_softc[unit];
     527:     register struct qt_rring *rp;
     528:     register struct qt_uba *xp;
     529:     int len;
     530:     long    bufaddr;
     531:
     532:     while   (sc->rring[sc->rindex].rmd3 & RMD3_OWN)
     533:         {
     534:         rp = &sc->rring[sc->rindex];
     535: /*
     536:  * If the host word is 0 then this is a buffer either already seen or not
     537:  * presented to the device in the first place.
     538: */
     539:         xp = rp->rhost0;
     540:         if  (xp == 0)
     541:             break;
     542:
     543:         if     ((rp->rmd0 & (RMD0_STP|RMD0_ENP)) != (RMD0_STP|RMD0_ENP))
     544:             {
     545:             printf("qt%d chained packet\n", unit);
     546:             sc->is_if.if_ierrors++;
     547:             goto rnext;
     548:             }
     549:         len = (rp->rmd1 & RMD1_MCNT) - 4;   /* -4 for CRC */
     550:         sc->is_if.if_ipackets++;
     551:
     552:         if  ((rp->rmd0 & RMD0_ERR3) || (rp->rmd2 & RMD2_ERR4))
     553:             {
     554:             sc->is_if.if_ierrors++;
     555: #ifdef QTDEBUG
     556:             printf("qt%d rmd0 %b\n", unit, rp->rmd0, RMD0_BITS);
     557:             printf("qt%d rmd2 %b\n", unit, rp->rmd2, RMD2_BITS);
     558: #endif
     559:             }
     560:         else
     561:             qtread(sc, &xp->ubabuf,
     562:                 len - sizeof (struct ether_header));
     563: rnext:
     564:         --sc->nrcv;
     565:         if  (++sc->rindex >= QT_MAX_RCV)
     566:             sc->rindex = 0;
     567: /*
     568:  * put the buffer back on the free list and clear the first host word
     569:  * in the ring descriptor so we don't process this one again.
     570: */
     571:         xp->next = sc->freelist;
     572:         sc->freelist = xp;
     573:         rp->rhost0 = 0;
     574:         }
     575:     while   (sc->nrcv < NRCV)
     576:         {
     577:         rp = &sc->rring[sc->nxtrcv];
     578: #ifdef  QTDEBUG
     579:         if  ((rp->rmd3 & RMD3_OWN) == 0)
     580:             printf("qtrint: !OWN\n");
     581: #endif
     582:         xp = sc->freelist;
     583:         sc->freelist = xp->next;
     584:         bufaddr = xp->ubabuf.ifu_r.ifrw_info;
     585:         rp->rmd1 = MAXPACKETSIZE;
     586:         rp->rmd4 = loint(bufaddr);
     587:         rp->rmd5 = hiint(bufaddr);
     588:         rp->rhost0 = xp;
     589:         rp->rmd3 = 0;           /* clear RMD3_OWN */
     590:         ++sc->nrcv;
     591:         sc->addr->arqr = ARQR_RRQ;  /* tell device it has buffer */
     592:         if  (++sc->nxtrcv >= QT_MAX_RCV)
     593:             sc->nxtrcv = 0;
     594:         }
     595:     }
     596:
     597: /*
     598:  * Place data on the appropriate queue and call the start routine to
     599:  * send the data to the device.
     600: */
     601:
     602: qtoutput(ifp, m0, dst)
     603:     struct  ifnet *ifp;
     604:     struct  mbuf *m0;
     605:     struct  sockaddr *dst;
     606:     {
     607:     int type, s, trail;
     608:     u_char  edst[6];
     609:     struct  in_addr idst;
     610:     register struct ether_header *eh;
     611:     register struct qt_softc *is = &qt_softc[ifp->if_unit];
     612:     register struct mbuf *m = m0;
     613:     struct  mbuf *mcopy = (struct mbuf *)0;
     614:
     615:     if  ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
     616:         {
     617:         m_freem(m0);
     618:         return(ENETDOWN);
     619:         }
     620:     switch  (dst->sa_family)
     621:         {
     622: #ifdef INET
     623:         case    AF_INET:
     624:             idst = ((struct sockaddr_in *)dst)->sin_addr;
     625:             if  (!arpresolve(&is->is_ac, m, &idst, edst,&trail))
     626:                 return(0);  /* wait for arp to finish */
     627:             if  (!bcmp(edst, etherbroadcastaddr,sizeof (edst)))
     628:                 mcopy = m_copy(m, 0, (int)M_COPYALL);
     629:             type = ETHERTYPE_IP;
     630:             break;
     631: #endif
     632: #ifdef NS
     633:         case    AF_NS:
     634:             type = ETHERTYPE_NS;
     635:             bcopy(&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
     636:                     edst, sizeof (edst));
     637:             if  (!bcmp(edst, &ns_broadcast, sizeof (edst)))
     638:                 return(looutput(&loif, m, dst));
     639:             break;
     640: #endif
     641:         case    AF_UNSPEC:
     642:             eh = (struct ether_header *)dst->sa_data;
     643:             bcopy(eh->ether_dhost, (caddr_t)edst, sizeof (edst));
     644:             type = eh->ether_type;
     645:             break;
     646:         default:
     647:             printf("qt%d can't handle af%d\n", ifp->if_unit,
     648:                 dst->sa_family);
     649:             m_freem(m);
     650:             return(EAFNOSUPPORT);
     651:         }
     652: /*
     653:  * Add local net header.  If no space in first mbuf, allocate another.
     654: */
     655:     if  (m->m_off > MMAXOFF ||
     656:             MMINOFF + sizeof (struct ether_header) > m->m_off)
     657:         {
     658:         m = m_get(M_DONTWAIT, MT_HEADER);
     659:         if  (m == 0)
     660:             {
     661:             m_freem(m0);
     662: nobufs:         if  (mcopy)
     663:                 m_freem(mcopy);
     664:             return(ENOBUFS);
     665:             }
     666:         m->m_next = m0;
     667:         m->m_off = MMINOFF;
     668:         m->m_len = sizeof (struct ether_header);
     669:         }
     670:     else
     671:         {
     672:         m->m_off -= sizeof (struct ether_header);
     673:         m->m_len += sizeof (struct ether_header);
     674:         }
     675:     eh = mtod(m, struct ether_header *);
     676:     eh->ether_type = htons((u_short)type);
     677:     bcopy(edst, (caddr_t)eh->ether_dhost, sizeof (edst));
     678:     bcopy(is->is_addr, (caddr_t)eh->ether_shost, sizeof (is->is_addr));
     679:
     680:     s = splimp();
     681:     if  (IF_QFULL(&ifp->if_snd))
     682:         {
     683:         IF_DROP(&ifp->if_snd);
     684:         m_freem(m);
     685:         splx(s);
     686:         goto nobufs;
     687:         }
     688:     IF_ENQUEUE(&ifp->if_snd, m);
     689:     qtstart(ifp->if_unit);
     690:     splx(s);
     691:     return(mcopy ? looutput(&loif, mcopy, dst) : 0);
     692:     }
     693:
     694: qtioctl(ifp, cmd, data)
     695:     register struct ifnet *ifp;
     696:     int cmd;
     697:     caddr_t data;
     698:     {
     699:     struct qt_softc *sc = &qt_softc[ifp->if_unit];
     700:     struct ifaddr *ifa = (struct ifaddr *)data;
     701:     int s = splimp(), error = 0;
     702: #ifdef  NS
     703:     register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
     704: #endif
     705:
     706:     switch  (cmd)
     707:         {
     708:         case    SIOCSIFADDR:
     709: /*
     710:  * Resetting the board is probably overkill, but then again this is only
     711:  * done when the system comes up or possibly when a reset is needed after a
     712:  * major network fault (open wire, etc).
     713: */
     714:             qtrestart(sc);
     715:             switch  (ifa->ifa_addr.sa_family)
     716:                 {
     717: #ifdef INET
     718:                 case    AF_INET:
     719:                     ((struct arpcom *)ifp)->ac_ipaddr =
     720:                         IA_SIN(ifa)->sin_addr;
     721:                     arpwhohas(ifp, &IA_SIN(ifa)->sin_addr);
     722:                     break;
     723: #endif
     724: #ifdef NS
     725:                 case    AF_NS:
     726:                     if  (ns_nullhost(*ina))
     727:                         ina->x_host =
     728:                         *(union ns_host *)(sc->is_addr);
     729:                     else
     730:                         {
     731:                         qt_ns(ina->x_host.c_host);
     732:                         qtrestart(sc);
     733:                         }
     734:                     break;
     735: #endif
     736:                 }
     737:             break;
     738:         case    SIOCSIFFLAGS:
     739:             if  ((ifp->if_flags & IFF_UP) == 0 &&
     740:                     sc->qt_flags & QTF_RUNNING)
     741:                 {
     742: /*
     743:  * We've been asked to stop the board and leave it that way.  qtturbo()
     744:  * does this with the side effect of placing the device back in Turbo mode.
     745: */
     746:                 qtturbo(sc);
     747:                 sc->qt_flags &= ~QTF_RUNNING;
     748:                 }
     749:             else if (ifp->if_flags & IFF_UP &&
     750:                     !(sc->qt_flags & QTF_RUNNING))
     751:                 qtrestart(sc);
     752:             break;
     753:         default:
     754:             error = EINVAL;
     755:         }
     756:     splx(s);
     757:     return(error);
     758:     }
     759:
     760: #ifdef  NS
     761: qt_ns(cp)
     762:     register char *cp;
     763:     {
     764:     segm    seg5;
     765:     register struct qt_init *iniblk = (struct qt_init *)SEG5;
     766:
     767:     saveseg5(seg5);
     768:     mapseg5(sc->initclick, 077406);
     769:     bcopy(cp, sc->is_addr, 6);
     770:     bcopy(cp, iniblk->paddr, 6);
     771:     restorseg5(seg5);
     772:     }
     773: #endif
     774:
     775: /*
     776:  * Pull the data off of the board and pass back to the upper layers of
     777:  * the networking code.  Trailers are counted as errors and the packet
     778:  * dropped.  SEG5 is saved and restored (used to peek at the packet type).
     779: */
     780:
     781: qtread(sc, ifuba, len)
     782:     register struct qt_softc *sc;
     783:     struct  ifuba *ifuba;
     784:     int len;
     785:     {
     786:     struct  ether_header *eh;
     787:         register struct mbuf *m;
     788:     struct  ifqueue *inq;
     789:     int type;
     790:     segm    seg5;
     791:
     792:     saveseg5(seg5);
     793:     mapseg5(ifuba->ifu_r.ifrw_click, 077406);
     794:     eh = (struct ether_header *)SEG5;
     795:     eh->ether_type = ntohs((u_short)eh->ether_type);
     796:     type = eh->ether_type;
     797:     restorseg5(seg5);
     798:     if  (len == 0 || type >= ETHERTYPE_TRAIL &&
     799:             type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER)
     800:         {
     801:         sc->is_if.if_ierrors++;
     802:         return;
     803:         }
     804:
     805:     m = if_rubaget(ifuba, len, 0, &sc->is_if);
     806:     if  (m == 0)
     807:         return;
     808:
     809:     switch  (type)
     810:         {
     811: #ifdef INET
     812:         case    ETHERTYPE_IP:
     813:             schednetisr(NETISR_IP);
     814:             inq = &ipintrq;
     815:             break;
     816:         case    ETHERTYPE_ARP:
     817:             arpinput(&sc->is_ac, m);
     818:             return;
     819: #endif
     820: #ifdef NS
     821:         case    ETHERTYPE_NS:
     822:             schednetisr(NETISR_NS);
     823:             inq = &nsintrq;
     824:             break;
     825: #endif
     826:         default:
     827:             m_freem(m);
     828:             return;
     829:         }
     830:
     831:     if  (IF_QFULL(inq))
     832:         {
     833:         IF_DROP(inq);
     834:         m_freem(m);
     835:         return;
     836:         }
     837:     IF_ENQUEUE(inq, m);
     838:     }
     839:
     840:
     841: qtsrr(unit, srrbits)
     842:     int unit, srrbits;
     843:     {
     844:     printf("qt%d srr=%b\n", unit, srrbits, SRR_BITS);
     845:     }
     846:
     847: /*
     848:  * Reset the device.  This moves it from DELQA-T mode to DELQA-Normal mode.
     849:  * After the reset put the device back in -T mode.  Then call qtinit() to
     850:  * reinitialize the ring structures and issue the 'timeout' for the "device
     851:  * started interrupt".
     852: */
     853:
     854: qtrestart(sc)
     855:     register struct qt_softc *sc;
     856:     {
     857:
     858:     qtturbo(sc);
     859:     qtinit(sc - qt_softc);
     860:     }
     861:
     862: qbaini(sc, num)
     863:     struct  qt_softc *sc;
     864:     int num;
     865:     {
     866:     register int i;
     867:     register memaddr click;
     868:     struct  qt_uba  *xp;
     869:     register struct ifuba   *ifuba;
     870:
     871:     for (i = 0; i < num; i++)
     872:         {
     873:         xp = &sc->ifrw[i];
     874:         ifuba = &xp->ubabuf;
     875:         click = m_ioget(MAXPACKETSIZE);
     876:         if  (click == 0)
     877:             {
     878:             click = MALLOC(coremap, btoc(MAXPACKETSIZE));
     879:             if  (click == 0)
     880:                 return(0);  /* _can't_ happen */
     881:             }
     882:         ifuba->ifu_hlen = sizeof (struct ether_header);
     883:         ifuba->ifu_w.ifrw_click = ifuba->ifu_r.ifrw_click = click;
     884:         ifuba->ifu_w.ifrw_info = ifuba->ifu_r.ifrw_info =
     885:             ctob((long)click);
     886:         xp->next = sc->freelist;
     887:         sc->freelist = xp;
     888:         }
     889:     return(1);
     890:     }
     891: #endif

#### Defined functions

qbaini defined in line 862; used 1 times

- in line 229

qt_ns defined in line 761; used 1 times

- in line 731

qtattach defined in line 172; used 2 times

- in line 132, 139

qtfoo defined in line 154; used 1 times

- in line 212

qtinit defined in line 301; used 3 times

- in line 132, 232, 859

qtintr defined in line 431; used 2 times

- in line 132, 371

qtioctl defined in line 694; used 2 times

- in line 132, 234

qtoutput defined in line 602; used 2 times

- in line 132, 233

qtread defined in line 781; used 1 times

- in line 561

qtrestart defined in line 854; used 3 times

- in line 714, 732, 751

qtrint defined in line 523; used 1 times

- in line 453

qtsrr defined in line 841; used 1 times

- in line 441

qtstart defined in line 379; used 2 times

- in line 456, 689

qttint defined in line 468; used 1 times

- in line 455

qtturbo defined in line 240; used 3 times

- in line 236, 746, 858

#### Defined variables

qt_softc defined in line 128; used 9 times

- in line 175, 305, 383, 434, 471, 526, 611, 699, 859

qtdriver defined in line 138; never used
qtinfo defined in line 130; used 1 times

- in line 139

qtstd defined in line 136; used 1 times

- in line 139

#### Defined struct's

qt_softc defined in line 107; used 24 times

- in line 175(2), 241(2), 305(2), 383(2), 434(2), 471(2), 526(2), 611(2), 699(2), 782(2), 855(2), 863(2)

qt_uba defined in line 99; used 16 times

- in line 101(2), 111-112(4), 310(2), 387(2), 473(2), 528(2), 868(2)

#### Defined macros

BBLMIS defined in line 466; used 1 times

- in line 506

MAXPACKETSIZE defined in line 145; used 3 times

- in line 585, 875-878(2)

MINPACKETSIZE defined in line 146; used 2 times

- in line 410-411(2)

NRCV defined in line 93; used 4 times

- in line 95, 112, 229, 575

NXMT defined in line 94; used 4 times

- in line 95, 112, 229, 390

QTF_RUNNING defined in line 119; used 4 times

- in line 446, 740, 747-750(2)

QTF_STARTUP defined in line 120; used 2 times

- in line 370, 442

is_addr defined in line 110; used 11 times

- in line 290-296(7), 678(2), 728, 769

is_if defined in line 109; used 12 times

- in line 176, 307, 392, 447, 498, 504, 511, 546-554(3), 801-805(2)

Last modified: 1993-02-28 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1910 |