Annotation of researchv8dc/sys/dev/il.c, revision 1.1.1.1

1.1       root        1: #include "il.h"
                      2: 
                      3: #if NIL > 0
                      4: 
                      5: #include "../h/param.h"
                      6: #include "../h/systm.h"
                      7: #include "../h/dir.h"
                      8: #include "../h/user.h"
                      9: #include "../h/map.h"
                     10: #include "../h/pte.h"
                     11: #include "../h/buf.h"
                     12: #include "../h/ubareg.h"
                     13: #include "../h/ubavar.h"
                     14: #include "../h/proc.h"
                     15: #include "../h/tty.h"
                     16: /*#include "../h/queue.h"*/
                     17: #include "../h/ilreg.h"
                     18: #include "../h/conf.h"
                     19: 
                     20: #define PRINET 26 /* sleep priority: interruptible */
                     21: 
                     22: struct ilcb ilcb[NIL];
                     23: extern int ilprobe(), ilattach(), ilrint(), ilcint();
                     24: struct uba_device *ildinfo[NIL];
                     25: u_short        ilstd[] = {0164040};
                     26: struct uba_driver ildriver =
                     27:      { ilprobe, 0, ilattach, 0, ilstd, "il", ildinfo };
                     28: 
                     29: 
                     30: /*++*
                     31:  * Macro:      NM10command
                     32:  * Abstract:   pass the NM10 board an inline command
                     33:  * Parameters: 
                     34:  *     command:        command to process
                     35:  *     size:           size of data buffer
                     36:  *     buf:            data buffer
                     37:  *     addr:           NM10 device addr
                     38:  * Returns:    nothing
                     39:  * Affects:    nothing
                     40:  * Errors:     none
                     41:  * Design:     trivial
                     42:  *
                     43:  *--*/
                     44: #define NM10command(command, size, buf)                                \
                     45: {                                                              \
                     46:     register unsigned int map = ((unsigned int) buf);          \
                     47:     reg->bcr = size;                                           \
                     48:     reg->bar = map & 0xffff;                                   \
                     49:     reg->csr = ((map & 0x30000)  >> 2) | command;              \
                     50:     while ((reg->csr & IL_CMD_DONE) == 0);                     \
                     51: }
                     52: 
                     53: 
                     54: /*++*
                     55:  * Routine:    ilinit
                     56:  * Abstract:   Initialize the Interlan ethernet driver.
                     57:  * Parameters: 
                     58:  *     dev:    number device to initialize;
                     59:  * Returns:    nothing
                     60:  * Affects:    nothing
                     61:  * Errors:     
                     62:  * Design:     trivial
                     63:  *
                     64:  *--*/
                     65:  ilinit (dev)
                     66:  {
                     67:      register struct ilcb *ib = &ilcb[dev];
                     68:      register struct uba_device *ui = ildinfo[dev];
                     69:      register struct ilreg *reg = (struct ilreg *)ui->ui_addr;
                     70: 
                     71:      if (ib->avail)
                     72:      {
                     73:         u.u_error = EBUSY;
                     74:         return;
                     75:      }
                     76: 
                     77:      ib->in_map  = uballoc(ui->ui_ubanum, (caddr_t) 0x80000000,
                     78:                           ILUBASIZE, UBA_NEEDBDP|UBA_CANTWAIT);
                     79:      ib->cmd_map = uballoc(ui->ui_ubanum, (caddr_t) 0x80000000,
                     80:                           ILUBASIZE, UBA_NEEDBDP|UBA_CANTWAIT);
                     81: 
                     82:      if ((ib->in_map == 0) || (ib->cmd_map == 0))
                     83:      {
                     84:         if (ib->in_map)
                     85:            ubarelse (ui->ui_ubanum, &ib->in_map);
                     86:         if (ib->cmd_map)
                     87:            ubarelse (ui->ui_ubanum, &ib->cmd_map);
                     88:         u.u_error = ENOMEM;
                     89:         return;
                     90:      }
                     91: 
                     92:    /*++*
                     93:     * initialize cummulative statistics
                     94:     *
                     95:     *--*/
                     96:     {
                     97:         struct ilstats stats;
                     98:         register unsigned short *st = (unsigned short *) &stats.rframes;
                     99:         register unsigned int   *in = (unsigned int *)   &ib->info.rframes;
                    100: 
                    101:        NM10command (IL_RPT_STATS, 66,
                    102:                     ubaremap(ui->ui_ubanum, ib->in_map, stats));
                    103: 
                    104:        /* we do this remap to cause a ubapurge */
                    105:        ubaremap(ui->ui_ubanum, ib->in_map, stats);
                    106: 
                    107:        while (st > (unsigned short *) &stats.modid)
                    108:             *in++  = *st++;
                    109: 
                    110:         ib->info.iladdr = stats.iladdr;
                    111:         ib->info.modid  = stats.modid;
                    112:         ib->info.firmid = stats.firmid;
                    113:     }
                    114: 
                    115:     ib->in_ptr     = 0;
                    116:     ib->in_packet  = NULL;
                    117:     ib->cmd_packet = NULL;
                    118:     ib->in_next           = NULL;
                    119: 
                    120:     initqueue((struct Queue *)&ib->cmd_q);
                    121: 
                    122:     ilrstart (ui);
                    123:     NM10command (IL_ON_LINE, 0, 0);
                    124:  }
                    125: 
                    126: ilopen (dev, flag)
                    127: {
                    128:      register struct ilcb *ib = &ilcb[dev];
                    129: 
                    130:      if (ib > &ilcb[NIL] || !ib->attached)
                    131:      {
                    132:         u.u_error = ENXIO;
                    133:         return;
                    134:      }
                    135: 
                    136: }
                    137:      
                    138: ilclose (dev)
                    139: {
                    140:     return;
                    141: }
                    142: 
                    143: 
                    144: /*++*
                    145:  * Procedure: ilcommand
                    146:  * Abstract:
                    147:  *      send command to net.
                    148:  * Parameters:
                    149:  *      dev =  device number   
                    150:  *      p =    pointer to packet that is to be given to Interland device.
                    151:  * Design:
                    152:  *
                    153:  *--*/
                    154: ilcommand(dev, p)
                    155: register struct ilpacket *p;
                    156: {
                    157:     register struct uba_device *ui = ildinfo [dev];
                    158:     register struct ilcb *ib = &ilcb [dev];
                    159:     int ipl;
                    160:     extern ilcmdstart();
                    161: 
                    162:     ipl = spl6();
                    163: 
                    164:     if (ib->cmd_packet == NULL)
                    165:     {
                    166:        ib->cmd_packet = p;
                    167:        ilcmdstart (ui);
                    168:     }
                    169:     else enqueue (&ib->cmd_q, p);
                    170: 
                    171:     splx(ipl);
                    172: }
                    173: 
                    174: 
                    175: 
                    176: ilioctl (dev, cmd, arg) int *arg;
                    177: {
                    178:     switch (cmd)
                    179:     {
                    180:        case IL_INIT:
                    181:        {
                    182:            if (suser())
                    183:                ilinit (dev);
                    184:            else
                    185:            {
                    186:                u.u_error = EPERM;
                    187:                return;
                    188:            }
                    189:        }
                    190:        break;
                    191: 
                    192:        case IL_DISABLE:
                    193:        {
                    194: /*         ildisable (dev); */
                    195:        }
                    196:        break;
                    197: 
                    198:        case IL_STATS:
                    199:        {
                    200:            register struct ilcb *ib = &ilcb[dev];
                    201:             unsigned short buf[ILPHEAD + 66];
                    202:            register struct ilpacket *p = (struct ilpacket *)buf;
                    203:            extern ilstats ();
                    204: 
                    205:            p->command = IL_RPT_STATS;
                    206:            p->function = ilstats;
                    207:            p->count = 66;
                    208:            ilcommand (dev, p);
                    209: 
                    210:            while (p->command == IL_RPT_STATS)
                    211:                 sleep((caddr_t) p, PRINET);
                    212:             copyout(&ib->info, arg, sizeof ib->info);
                    213:        }
                    214:        break;
                    215: 
                    216:        default:
                    217:        {
                    218:            u.u_error = EINVAL;
                    219:        }
                    220:        break;
                    221:     }
                    222: }
                    223:            
                    224: 
                    225: /*++*
                    226:  * Routine:    ilfind
                    227:  * Abstract:   find a type filter that matched a specified type.
                    228:  * Parameters: 
                    229:  *     ib   =  pointer to the ethernet device ilcb.
                    230:  *     type =  type that filter will match.
                    231:  * Returns:    
                    232:  *     SUCCESS:        a descriptor with the matched type.
                    233:  *     FAILURE:        NULL
                    234:  * Affects:    nothing
                    235:  * Errors:     none
                    236:  * Design:     trivial
                    237:  *
                    238:  *--*/
                    239: struct iltype *ilfind(ib, type) register unsigned short type;
                    240:                                register struct ilcb *ib;
                    241: {
                    242:     register struct iltype *d;
                    243:     for (  d  = (struct iltype *)ib->type_q.F;
                    244:           d != (struct iltype *)&ib->type_q;
                    245:           d  = (struct iltype *) d->head.F  )
                    246:        if (d->type == type)
                    247:           return (d);
                    248:     return (NULL);
                    249: }
                    250: 
                    251: 
                    252: /*++*
                    253:  * Routine:    ilconnect
                    254:  * Abstract:   create and ethernet type filter entry
                    255:  * Parameters: 
                    256:  *     unit =  ethernet device unit number.
                    257:  *     type =  ethernet type
                    258:  *     funct = function to call if we find a match
                    259:  * Returns:    
                    260:  *     SUCCESS:        1
                    261:  *     FAILURE:        0
                    262:  * Affects:    
                    263:  *     ilcb[unit].type_q:              entry placed in queue
                    264:  *     ilcb[unit].free_q:              entry removed from queue
                    265:  * Errors:     none
                    266:  * Design:     ...
                    267:  *
                    268:  *--*/
                    269: ilconnect (unit, type, function) register funct *function;
                    270: {
                    271:     register struct iltype *d;
                    272:     register struct ilcb *ib = &ilcb[unit];
                    273:     register int ipl;
                    274: 
                    275:     ipl = spl6();
                    276:     if (ilfind (ib, type) == NULL)
                    277:        if (d = (struct iltype *) dequeue (&ib->free_q))
                    278:        {
                    279:           ib->num_free--;
                    280:           d->type = type;
                    281:           d->funct = function;
                    282:           enqueue (&ib->type_q, d);
                    283:           ib->num_types++;
                    284:           splx (ipl);
                    285:           return (1);
                    286:        }
                    287:     splx (ipl);
                    288:     return (0);
                    289: }
                    290: 
                    291: 
                    292: 
                    293: /*++*
                    294:  * Routine:    ildisconnect
                    295:  * Abstract:   remove an ethernet type filter match entry
                    296:  * Parameters: 
                    297:  *     unit =  ethernet device unit number
                    298:  *     type =  ethernet type
                    299:  * Returns:    
                    300:  *     SUCCESS:        1
                    301:  *     FAILURE:        0
                    302:  * Affects:    
                    303:  *     ilcb[unit].type_q:              entry removed
                    304:  *     ilcb[unit].free_q:              entry entered
                    305:  * Errors:     none
                    306:  * Design:     ...
                    307:  *
                    308:  *--*/
                    309: ildisconnect (unit, type) register int type;
                    310: {
                    311:     struct iltype *d;
                    312:     register struct ilcb *ib = &ilcb[unit];
                    313:     register int ipl;
                    314: 
                    315:     if (d = ilfind (ib, type))
                    316:     {
                    317:        ipl = spl6 ();
                    318:        enqueue (&ib->free_q, dequeue (&d));
                    319:        ib->num_types--;
                    320:        ib->num_free++;
                    321:        splx(ipl);
                    322:     }
                    323: }
                    324: 
                    325: 
                    326: 
                    327: /*++*
                    328:  * Routine:    iladdress
                    329:  * Abstract:   return (by reference) the device net address
                    330:  * Parameters: 
                    331:  *     addr = the network address.
                    332:  * Returns:    nothing
                    333:  * Affects:    nothing
                    334:  * Errors:     none
                    335:  * Design:     trivial
                    336:  *
                    337:  *--*/
                    338: iladdress (dev, addr) register struct iladdr *addr;
                    339: {
                    340:     register struct ilcb *ib = &ilcb[dev];
                    341:     *addr = ib->info.iladdr;
                    342: }
                    343: 
                    344: 
                    345: /*++*
                    346:  * Procedure: ilrstart
                    347:  * Abstract: Start read operation on net.
                    348:  * Parameters:
                    349:  *      'ui'   type "uba_device *": pointer to ethernet device to be started.
                    350:  *
                    351:  *--*/
                    352: 
                    353: ilrstart(ui)
                    354: register struct uba_device *ui;
                    355: {
                    356:     register struct ilreg *reg = (struct ilreg *)ui->ui_addr;
                    357:     register struct ilcb *ib = &ilcb[ui->ui_unit];
                    358:     register struct ilpacket *p;
                    359:     int ipl;
                    360: 
                    361:     if (ib->in_packet == NULL)
                    362:     {
                    363:        ipl = spl6();
                    364:        ib->in_packet = &ib->in_pool[ib->in_ptr];
                    365:        ib->in_ptr ^= 1;
                    366:        ib->in_next = ubaremap (ui->ui_ubanum, ib->in_map,
                    367:                                ib->in_packet->data);
                    368:        if (ib->cmd_packet == NULL)
                    369:        {
                    370:            NM10command (IL_RCVR_BUFFER | IL_RCV_INTR,
                    371:                         ILPACKETSIZE,
                    372:                         ib->in_next);
                    373:            ib->in_next = NULL;
                    374:        }
                    375:        splx (ipl);
                    376:     }
                    377: }
                    378: 
                    379: 
                    380: 
                    381: /*++*
                    382:  * Procedure: ilcmdstart
                    383:  * Abstract: Start packet transmission on net.
                    384:  * Parameters:
                    385:  *      ui     pointer to ethernet device structure.
                    386:  * Design:
                    387:  *     We give the Interland device the correct command
                    388:  *
                    389:  *     The UNIBUS address is derived by calculating the offset of the
                    390:  *     packet from the packet pool buffer base address and adding it to the
                    391:  *     allocated unibus buffer base address.
                    392:  *
                    393:  *     We must do a purge to make sure the uba device has no data words
                    394:  *     lying around that might get sent on the next DMA.
                    395:  *
                    396:  *--*/
                    397: ilcmdstart(ui)
                    398: register struct uba_device *ui;
                    399: {
                    400: 
                    401:     register struct ilcb *ib = &ilcb[ui->ui_unit];
                    402:     register struct ilreg *ilreg = (struct ilreg *)ui->ui_addr;
                    403:     register struct ilpacket *p;
                    404:     register unsigned int buffer;
                    405: 
                    406:      if (ib->cmd_packet == NULL)
                    407:         if ((ib->cmd_packet = (struct ilpacket *)dequeue(&ib->cmd_q)) == NULL)
                    408:           return;
                    409:     
                    410:     /* we dont use NM10command here since we are not interested
                    411:        in waiting for the command to complete synchronously */
                    412: 
                    413:     p = ib->cmd_packet;
                    414:     buffer = (unsigned int) ubaremap (ui->ui_ubanum, ib->cmd_map,
                    415:                                      p->data);
                    416:     ilreg->bcr = p->count;
                    417:     ilreg->bar = buffer & 0xffff;
                    418:     ilreg->csr =  ((buffer & 0x30000)  >> 2)
                    419:                         | p->command | IL_CMD_INTR | IL_RCV_INTR;
                    420: 
                    421: }
                    422: 
                    423: 
                    424: /*++*
                    425:  * Procedure: ilrint
                    426:  * Abstract: Net read interrupt handler.
                    427:  * Parameters:
                    428:  *      dev =  number of ethernet device.
                    429:  *
                    430:  *--*/
                    431: ilrint(dev)
                    432: {
                    433: 
                    434:     register struct ilcb *ib = &ilcb[dev];
                    435:     register struct uba_device *ui = ildinfo[dev];
                    436:     register struct il_rheader *l;
                    437:     register struct iltype *d;
                    438: 
                    439:     l = (struct il_rheader *)ib->in_packet;
                    440:     ilrstart(ui);
                    441:     if (l->status & IL_RCV_STATUS)
                    442:        printf ("il%d: received bad packet; status %x\n", dev, l);
                    443:     else if (d = ilfind(ib, l->type))
                    444:         (*d->funct)(dev, l);
                    445: }
                    446: 
                    447: 
                    448: /*++*
                    449:  * Procedure: ilcint
                    450:  * Abstract: Net transmit interrupt handler.
                    451:  * Parameters:
                    452:  *      'en'   number of device we interrupted on.
                    453:  *
                    454:  *--*/
                    455: 
                    456: ilcint(dev)
                    457: {
                    458:     register struct ilcb *ib = &ilcb[dev];
                    459:     register struct uba_device *ui = ildinfo[dev];
                    460:     register unsigned short status;
                    461:     register struct ilpacket *p = ib->cmd_packet;
                    462:     register struct ilreg *reg = (struct ilreg *) ui->ui_addr;
                    463: 
                    464:     if (p == NULL)
                    465:     {
                    466:        printf ("il%d: spurious transmit interrupt\n", dev);
                    467:        return;
                    468:     }
                    469: 
                    470:     status = reg->csr & IL_CMD_STATUS;
                    471:     if (p->command == IL_XMIT_SEND)
                    472:     {
                    473:          if ((status) > 1)
                    474:            printf ("il%d: dropped xmit packet\n", dev);
                    475:     }
                    476:     else if (status)
                    477:          printf ("il%d: command %x bad status packet: %x\n",
                    478:                  dev, p->command, p);
                    479: 
                    480:     if (p->function != NULL)
                    481:         (*(p->function)) (p, dev);
                    482: 
                    483:      if (ib->in_next)
                    484:      {
                    485:         NM10command (IL_RCVR_BUFFER | IL_RCV_INTR,
                    486:                      ILPACKETSIZE,
                    487:                      ib->in_next);
                    488:      }
                    489:         
                    490:     ib->in_next = NULL;
                    491:     ib->cmd_packet = NULL;
                    492:     ilcmdstart (ui);
                    493: }
                    494: 
                    495: 
                    496: /*++*
                    497:  * Procedure: ilstats
                    498:  * Abstract:
                    499:  *     Merge currently collected data into the device statistics
                    500:  *     table. This routine assumes HIGH PRIORITY.
                    501:  *
                    502:  *--*/
                    503:  ilstats (p, dev) struct ilpacket *p;
                    504:  {
                    505:     register struct ilcb *ib = &ilcb[dev];
                    506:     register struct ilstats *stats = (struct ilstats *)p->data;
                    507:     register unsigned int   *in = (unsigned int *)   &ib->info.rframes;
                    508:     register unsigned short *st = (unsigned short *) &stats->rframes;
                    509: 
                    510:     while (st < (unsigned short *) stats)
                    511:        *in++  += *st++;
                    512:     ib->info.rfifo = stats->rfifo;
                    513:     p->command = IL_NULL_CMD;
                    514:     wakeup((caddr_t) p);
                    515:  }
                    516: 
                    517: 
                    518: 
                    519: /*++*
                    520:  * Procedure: ilattach
                    521:  * Abstract: 
                    522:  *      This routine is called at system startup and initializes
                    523:  *      the device information structures.
                    524:  * Parameters:
                    525:  *      'ui'   type "uba_device *": pointer to the device information
                    526:  *             structure.
                    527:  *--*/
                    528: ilattach(ui)
                    529: register struct uba_device *ui;
                    530: {
                    531:     register struct ilreg *reg = (struct ilreg *) ui->ui_addr;
                    532:     register struct ilcb  *ib  = &ilcb[ui->ui_unit];
                    533:     register unsigned short status;
                    534:     register int i;
                    535: 
                    536:     if (&ilcb[ui->ui_unit] > &ilcb[NIL])
                    537:     {
                    538:        printf ("il%d: unit number to large. Max = %d\n",
                    539:                 ui->ui_unit, NIL);
                    540:        return;
                    541:     }
                    542: 
                    543:     if (status = (reg->csr & IL_CMD_STATUS))
                    544:     {
                    545:        printf ("il%d: bad reset status %x\n");
                    546:        return;
                    547:     }
                    548: 
                    549:     ib->attached = 1;
                    550: 
                    551:     initqueue((struct Queue *)&ib->type_q);
                    552:     initqueue((struct Queue *)&ib->free_q);
                    553:     ib->num_types = 0;
                    554:     ib->num_free = ILMAXTYPES;
                    555: 
                    556:     for (i = 0; i < ILMAXTYPES; i++)
                    557:         enqueue (&ib->free_q, ib->type[i]);
                    558: 
                    559: #ifdef TCP_IP
                    560: #if NBBNNET > 0
                    561:     il_attach();
                    562: #endif NBBNNET
                    563: #endif TCP_IP
                    564: }
                    565: 
                    566: 
                    567: 
                    568: /*++*
                    569:  * Procedure: ilprobe
                    570:  * Abstract:
                    571:  *      This routine is called by the system auto configurer
                    572:  *      at boot time. It locates the interrupt vectors of the device
                    573:  *      by doing FM (f___ing Magic). Cvec is used as a global register
                    574:  *      in which the interrupt routine places the interrupt vector
                    575:  *      that it found when the device interrupted.
                    576:  *      We can use this routine to do some boot time testing if
                    577:  *      we want.
                    578:  * Parameters:
                    579:  *      'reg'  the base address of the ethernet device.
                    580:  *
                    581:  *--*/
                    582: ilprobe(reg)
                    583: struct ilreg *reg;
                    584: {
                    585:        register int br,cvec;
                    586:        
                    587: #ifdef lint
                    588:        br = 0; cvec = br; br = cvec;
                    589: #endif
                    590:        
                    591:        reg->bcr = 0;
                    592:        reg->bar = 0;
                    593:        reg->csr = IL_OFF_LINE | IL_CMD_INTR;
                    594:        DELAY(10000);
                    595: 
                    596:         br = reg->csr;  /* clear off status from il board */
                    597:        cvec &= ~0xf;   /* make sure we have the first intr vector */
                    598:        return(1);
                    599: }
                    600: 
                    601: 
                    602: 
                    603: 
                    604: /*++*
                    605:  * Procedure: ilreset
                    606:  * Abstract:
                    607:  *      reset the interlan ethernet device
                    608:  *      Called on UBA reset to restart pending I/O.
                    609:  *      Just prints the device name and restarts the receiver and
                    610:  *      transmitter.  No other state that we care about is lost by
                    611:  *      the reset.
                    612:  * Parameters:
                    613:  *      'uban' number of the uba that was reset.
                    614:  *
                    615:  *--*/
                    616: ilreset(uban)
                    617: {
                    618: 
                    619:     register int dev;
                    620:     register struct uba_device *ui;
                    621:     register struct ilreg *reg = (struct ilreg *) ui->ui_addr;
                    622:     register struct ilcb *ib;
                    623: 
                    624:     for (dev = 0; dev < NIL; dev++)
                    625:     {
                    626:        if ((ui = ildinfo[dev]) ||
                    627:             ui->ui_alive == 0 ||
                    628:             ui->ui_ubanum != uban)
                    629:                continue;
                    630: 
                    631: 
                    632:          ib = &ilcb[dev];
                    633:         /*++*
                    634:           * do a reset command so we are sure of the state
                    635:           *
                    636:          *--*/
                    637:         NM10command (IL_RESET, 0, 0);
                    638:         printf("[reset] ");
                    639: 
                    640:        /*++*
                    641:         * put us back on line if we are active
                    642:         * and start the command and receive processes.
                    643:         *
                    644:         *--*/
                    645:         if (ib->avail)
                    646:          {
                    647:             NM10command (IL_ON_LINE, 0, 0);
                    648:             printf ("[on line]");
                    649:         }
                    650:         else printf ("[off line]");
                    651:     }
                    652: 
                    653:     if (ib->cmd_packet)
                    654:        (*ib->cmd_packet->function) (ib->cmd_packet, dev);
                    655: 
                    656:     ib->in_ptr     = 0;
                    657:     ib->in_packet  = NULL;
                    658:     ib->in_next    = NULL;
                    659:     ib->cmd_packet = NULL;
                    660:     ilcmdstart(ui);
                    661:     ilrstart (ui);
                    662: }
                    663: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.