Annotation of researchv8dc/sys/chncp/chil.c, revision 1.1.1.1

1.1       root        1: #include "../chunix/chsys.h"
                      2: #include "../chunix/chconf.h"
                      3: #include "../chaos/chaos.h"
                      4: #include "../chaos/address-res.h"
                      5: 
                      6: #ifdef VMUNIX
                      7: #include "../h/buf.h"
                      8: #include "../h/ubavar.h"
                      9: #include "../h/pte.h"
                     10: #include "../h/ubareg.h"
                     11: #endif VMUNIX
                     12: 
                     13: /*
                     14:  * Chaos device driver for the interlan ethernet interface.
                     15:  *
                     16:  * This driver depends heavily on the fact that the device will
                     17:  * interrupt exactly once per receive buffer and once per command
                     18:  * regardless of how many times the CSR is read (and thus the
                     19:  * DONE bits cleared).
                     20:  * Until a lot of this chaos code is rewritten, it is too painful to DMA
                     21:  * directly into a packet buffer since the buffers must be > 512 bytes, even
                     22:  * for the smallest packet.  Thus we just have fixed buffers, and copy the data out.
                     23:  * For transmission, we do indeed DMA directly from packets.
                     24:  * Note that for the VAX we permanently allocate a buffered data path for transmit,
                     25:  * unless NOHOG is defined, in which case we allocate as needed.
                     26:  * For receive, we use a direct data path and a permanently-mapped buffer.
                     27:  *
                     28:  * NOTE!!! The size of this structure must not be an even multiple of 8 !!!
                     29:  * If it is then "buffer chaining" will occur!
                     30:  */
                     31: union chilpkt {
                     32:        struct il_stat                                  ilp_stat;
                     33:        struct {
                     34:                struct il_rheader                       ilp_Rhdr;
                     35:                union {
                     36:                        struct ar_packet                ilp_Arpkt;
                     37:                        struct {
                     38:                                struct pkt_header       ilp_Chhead;
                     39:                                char            ilp_Chdata[CHMAXDATA];
                     40:                        }                               ilp_Chpkt;
                     41:                }                                       ilp_data;
                     42:                char                                    ilp_crc[4];
                     43:        }                                               ilp_edata;
                     44: };
                     45: #define ilp_arpkt      ilp_edata.ilp_data.ilp_Arpkt
                     46: #define ilp_chhead     ilp_edata.ilp_data.ilp_Chpkt.ilp_Chhead
                     47: #define ilp_chdata     ilp_edata.ilp_data.ilp_Chpkt.ilp_Chdata
                     48: #define ilp_chpkt      ilp_edata.ilp_data.ilp_Chpkt
                     49: #define ilp_rhdr       ilp_edata.ilp_Rhdr
                     50: int chilstart(), chilreset();
                     51: 
                     52: /*
                     53: #define        DEBUG
                     54: */
                     55: 
                     56: #ifdef DEBUG
                     57: #define IF_DEBUG(x)    (x)
                     58: #else
                     59: #define IF_DEBUG(x)
                     60: #endif
                     61: 
                     62: #define NOHOG      /* Don't hog buffered data path (for xmit) */
                     63: 
                     64: #define splIL()                spl5()
                     65: 
                     66: /*
                     67:  * Address resolution data:
                     68:  * This should move to an "address resolution" file when more than one
                     69:  * Ethernet device is supported.
                     70:  */
                     71: #define ETHER_BROADCAST {-1, -1, -1, -1, -1, -1}
                     72: u_char ether_broadcast[6] = ETHER_BROADCAST;
                     73: #define NPAIRS 20      /* how many addresses should we remember */
                     74: struct ar_pair {
                     75:        chaddr  arp_chaos;
                     76:        u_char  arp_ether[6];
                     77:        long    arp_time;
                     78: };
                     79: long   arptime;        /* LRU clock for ar_pair slots */
                     80: 
                     81: /*
                     82:  * Canned request packet we send out when we don't have the ethernet address
                     83:  * of an outgoing packet.
                     84:  */
                     85: struct chilapkt        {
                     86:        struct il_xheader       ar_xhdr;
                     87:        struct ar_packet        ar_pkt;
                     88: };
                     89: /*
                     90:  * Software state per interface.
                     91:  */
                     92: struct chilsoft {
                     93:        char    il_unit;
                     94: #ifdef VMUNIX
                     95:        char    il_ubanum;
                     96:        char    il_rbdp;
                     97:        char    il_xbdp;
                     98:        int     il_ruba;
                     99:        int     il_xuba;
                    100: #endif
                    101:        short   il_oactive;     /* is output active? */
                    102:        short   il_startrcv;    /* hang receive next chance */
                    103:        short   il_scsr;
                    104:        u_char  il_enaddr[6];   /* board's ethernet address */
                    105:        short   il_doreply;     /* Reply buffer full */
                    106:        short   il_replying;    /* Reply buffer being transmitted */
                    107:        struct ildevice         *il_devaddr;
                    108:        struct chxcvr           il_xcvr;
                    109:        struct ar_pair          il_pairs[NPAIRS];
                    110:        struct ar_pair          *il_epairs;
                    111:        struct il_xheader       il_savex;       /* Yick. */
                    112:        union chilpkt           il_rpkt;        /* DMA input buffer */
                    113:        struct chilapkt         il_arrequest;   /* Address request buffer */
                    114:        struct chilapkt         il_arreply;     /* Address reply buffer */
                    115: } chilsoft[NCHIL];
                    116: 
                    117: /*
                    118:  * Error codes
                    119:  */
                    120: char *ilerrs[] = {
                    121:        "success",                      /* 0 */
                    122:        "success with retries",         /* 01 */
                    123:        "illegal command",              /* 02 */
                    124:        "inappropriate command",        /* 03 */
                    125:        "failure",                      /* 04 */
                    126:        "buffer size exceeded",         /* 05 */
                    127:        "frame too small",              /* 06 */
                    128:        0,                              /* 07 */
                    129:        "excessive collisions",         /* 010 */
                    130:        0,                              /* 011 */
                    131:        "buffer alignment error",       /* 012 */
                    132:        0,                              /* 013 */
                    133:        0,                              /* 014 */
                    134:        0,                              /* 015 */
                    135:        0,                              /* 016 */
                    136:        "non-existent memory"           /* 017 */
                    137: };
                    138: 
                    139: char *ildiag[] = {
                    140:        "success",                      /* 0 */
                    141:        "checksum error",               /* 1 */
                    142:        "NM10 dma error",               /* 2 */
                    143:        "transmitter error",            /* 3 */
                    144:        "receiver error",               /* 4 */
                    145:        "loopback failure",             /* 5 */
                    146: };
                    147: long chillost;
                    148: long chilarrp;
                    149: long chilarls;
                    150: long chilxstat;
                    151: long chilrst;
                    152: long chilrin;
                    153: long chilcin;
                    154: long chilar;
                    155: long chilxrq;
                    156: long chilxrp;
                    157: 
                    158: #ifdef VMUNIX
                    159: 
                    160: /*
                    161:  * This stuff should be elsewhere, but isn't right now.
                    162:  */
                    163: 
                    164: #ifdef VAX780
                    165: #define UBAPURGEBITS UBADPR_BNE
                    166: #else
                    167: #define UBAPURGEBITS (UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE)
                    168: #endif VAX780
                    169: 
                    170: #define PURGEBDP(ubanum, bdpnum) \
                    171:        uba_hd[ubanum].uh_uba->uba_dpr[bdpnum] |= UBAPURGEBITS
                    172: 
                    173: /*
                    174:  * Autoconfiguration support for VMUNIX
                    175:  */
                    176: int chilprobe(), chilattach(), chilrint(), chilcint();
                    177: struct uba_device *chilinfo[NCHIL];
                    178: unsigned short chilstd[] = { 0 };
                    179: struct uba_driver childriver = { chilprobe, 0, chilattach, 0, chilstd, "chil", chilinfo };
                    180: 
                    181: /*
                    182:  * Do an OFFLINE command to cause an interrupt for the
                    183:  * autoconfigure stuff.
                    184:  */
                    185: chilprobe(reg)
                    186:        caddr_t reg;
                    187: {
                    188:        register int br, cvec;          /* r11, r10 */
                    189:        register struct ildevice *addr = (struct ildevice *)reg;
                    190:        register int i;
                    191: 
                    192: #ifdef lint
                    193:        {
                    194:                int j = 0;
                    195: 
                    196:                br = 0; cvec = br; br = cvec;
                    197:                i = j; j = i;
                    198:                chilrint(0); chilcint(0);
                    199:        }
                    200: #endif
                    201:        addr->il_csr = ILC_OFFLINE|IL_CIE;
                    202:        DELAY(100000);
                    203:        i = addr->il_csr;               /* clear CDONE */
                    204:        if (cvec > 0 && cvec != 0x200)
                    205:                cvec -= 4;
                    206: 
                    207:        return (1);
                    208: }
                    209: 
                    210: /*
                    211:  * Attach interface
                    212:  */
                    213: chilattach(ui)
                    214:        register struct uba_device *ui;
                    215: {
                    216:        chilsoft[ui->ui_unit].il_ubanum = ui->ui_ubanum;
                    217:        chilsetup(ui->ui_unit, (struct ildevice *)ui->ui_addr);
                    218: }
                    219: #else VMUNIX
                    220: int chilndev = NCHIL;
                    221: int chiladdr[NCHIL] = { CHIL_ADDR };
                    222: #endif VMUNIX
                    223: 
                    224: /*
                    225:  * Do the run-time initialization of the given transceiver.
                    226:  * Reception is not enabled.
                    227:  */
                    228: chilsetup(unit, addr)
                    229: int unit;
                    230: register struct ildevice *addr;
                    231: {
                    232:        register struct chilsoft *sp = &chilsoft[unit];
                    233:        int s;
                    234: 
                    235:        sp->il_xcvr.xc_devaddr = (unsigned *)addr;      /* This indicates attachment! */
                    236:        sp->il_xcvr.xc_addr = 0;        /* We don't know chaos addr yet */
                    237:        sp->il_xcvr.xc_start = chilstart;
                    238:        sp->il_xcvr.xc_reset = chilreset;
                    239:        sp->il_xcvr.xc_ilinfo.il_soft = sp;
                    240:        sp->il_epairs = &sp->il_pairs[NPAIRS];
                    241:        sp->il_devaddr = addr;
                    242:        sp->il_unit = unit;
                    243: 
                    244: #ifdef VMUNIX
                    245: 
                    246: #ifndef NOHOG
                    247:        sp->il_xuba = uballoc(sp->il_ubanum, (caddr_t)&sp->il_rpkt,
                    248:                                sizeof(union chilpkt), UBA_CANTWAIT|UBA_NEEDBDP);
                    249:        sp->il_xbdp = (sp->il_xuba >> 28) & 0x0f;
                    250: #endif not NOHOG
                    251: 
                    252:        sp->il_ruba = uballoc(sp->il_ubanum, (caddr_t)&sp->il_rpkt,
                    253:                                sizeof(union chilpkt), UBA_CANTWAIT);
                    254:        sp->il_rbdp = (sp->il_ruba >> 28) & 0x0f;
                    255: #endif VMUNIX
                    256: 
                    257:        s = splIL();
                    258:        ilbusywait(sp, ILC_RESET, 0);           /* Initialize interface */
                    259:        addr->il_bar = sp->il_ruba & 0xffff;
                    260:        addr->il_bcr = sizeof(struct il_stat);
                    261:        ilbusywait(sp, ILC_STAT, (sp->il_ruba >> 2) & IL_EUA);
                    262:        if (sp->il_rbdp)
                    263:                PURGEBDP(sp->il_ubanum, sp->il_rbdp);
                    264:        splx(s);
                    265:        bcopy(sp->il_rpkt.ilp_stat.ils_addr, sp->il_enaddr, 6);
                    266:        bcopy(ether_broadcast, sp->il_arrequest.ar_xhdr.ilx_dhost, 6);
                    267:        sp->il_arrequest.ar_xhdr.ilx_type = ILADDR_TYPE;
                    268:        sp->il_arrequest.ar_pkt.ar_hardware = AR_ETHERNET;
                    269:        sp->il_arrequest.ar_pkt.ar_protocol = ILCHAOS_TYPE;
                    270:        sp->il_arrequest.ar_pkt.ar_hlength = 6;
                    271:        sp->il_arrequest.ar_pkt.ar_plength = 2;
                    272:        sp->il_arrequest.ar_pkt.ar_opcode = AR_REQUEST;
                    273:        bcopy(sp->il_enaddr, sp->il_arrequest.ar_pkt.ar_esender, 6);
                    274:        bcopy((u_char *)&sp->il_arrequest, (u_char *)&sp->il_arreply,
                    275:              sizeof(struct chilapkt));
                    276:        sp->il_arreply.ar_pkt.ar_opcode = AR_REPLY;
                    277: 
                    278:        printf("chil%d: ether addr %x %x %x %x %x %x module %s firmware %s\n",
                    279:                unit,
                    280:                sp->il_enaddr[0]&0xff, sp->il_enaddr[1]&0xff,
                    281:                sp->il_enaddr[2]&0xff, sp->il_enaddr[3]&0xff,
                    282:                sp->il_enaddr[4]&0xff, sp->il_enaddr[5]&0xff,
                    283:                sp->il_rpkt.ilp_stat.ils_module,
                    284:                sp->il_rpkt.ilp_stat.ils_firmware);
                    285: }
                    286: 
                    287: /*
                    288:  * chaos interlan initialization. Also does initialization to the static xcvr
                    289:  * structure since initialized unions don't work anyway.
                    290:  */
                    291: chilinit()
                    292: {
                    293:        int unit;
                    294: 
                    295:        for (unit = 0; unit < NCHIL; unit++) {
                    296: 
                    297: #ifndef VMUNIX
                    298:                chilsetup(unit, (struct ildevice *)chiladdr[unit]);
                    299: #endif not VMUNIX
                    300: 
                    301:                chilreset(&chilsoft[unit].il_xcvr);
                    302:        }
                    303: }
                    304: /*
                    305:  * Receive our chaosnet address
                    306:  */
                    307: chilseta(dev, addr)
                    308: unsigned dev;
                    309: unsigned short addr;
                    310: {
                    311:        register struct chilsoft *sp;
                    312:        register struct chroute *r;
                    313:                
                    314:        if (dev >= NCHIL)
                    315:                return 1;
                    316:        else {
                    317:                sp = &chilsoft[dev];
                    318:                if (sp->il_xcvr.xc_devaddr == 0)
                    319:                        return 1;
                    320:                if (sp->il_xcvr.xc_addr != 0) {  /* If we were already connected */
                    321:                        r = &Chroutetab[sp->il_xcvr.xc_subnet];
                    322:                        r->rt_type = 0;
                    323:                        r->rt_cost = CHHCOST;
                    324:                }
                    325:                sp->il_xcvr.xc_addr = addr;
                    326:                if (sp->il_xcvr.xc_subnet >= CHNSUBNET)
                    327:                        return 1;
                    328:                sp->il_arrequest.ar_pkt.ar_csender.ch_addr = addr;
                    329:                sp->il_arreply.ar_pkt.ar_csender.ch_addr = addr;
                    330:                r = &Chroutetab[sp->il_xcvr.xc_subnet];
                    331:                r->rt_type = CHDIRECT;
                    332:                r->rt_cost = CHHCOST/2;
                    333:                r->rt_xcvr = &sp->il_xcvr;
                    334:                return 0;
                    335:        }
                    336: }
                    337: /*
                    338:  * Reset interface after UNIBUS reset.
                    339:  */
                    340: chilreset(xp)
                    341: struct chxcvr *xp;
                    342: {
                    343:        register struct chilsoft *sp = xp->xc_ilinfo.il_soft;
                    344:        register int s;
                    345: 
                    346:        if (sp == 0)
                    347:                return;
                    348:        s = splIL();
                    349:        ilbusywait(sp, ILC_RESET, 0);
                    350:        ilbusywait(sp, ILC_CLPBAK, 0);
                    351:        ilbusywait(sp, ILC_CLPRMSC, 0);
                    352:        ilbusywait(sp, ILC_CRCVERR, 0);
                    353:        ilbusywait(sp, ILC_FLUSH, 0);
                    354:        ilbusywait(sp, ILC_ONLINE, 0);
                    355:        chilrstart(sp);
                    356:        splx(s);
                    357: }
                    358: 
                    359: /*
                    360:  * Start output on an idle line
                    361:  */
                    362: chilstart(xp)
                    363: struct chxcvr *xp;
                    364: {
                    365:        register struct chilsoft *sp = xp->xc_ilinfo.il_soft;
                    366: 
                    367: /*     IF_DEBUG(printf("chilstart (unit %d)\n", sp->il_unit)); */
                    368:        if (sp->il_xcvr.xc_tpkt != NOPKT)
                    369:                panic("chilstart: already busy");
                    370:        if (sp->il_oactive == 0)
                    371:                chilcint(sp->il_unit);
                    372: }
                    373: /*
                    374:  * Command (usually transmit) done interrupt.
                    375:  */
                    376: chilcint(dev)
                    377: {
                    378:        register struct ildevice *addr;
                    379:        register struct il_xheader *epkt;
                    380:        register struct chilsoft *sp = &chilsoft[dev];
                    381:        register struct packet *pkt;
                    382:        int elength;
                    383: 
                    384:        chilcin++;
                    385:        LOCK;
                    386:        addr = (struct ildevice *)sp->il_xcvr.xc_devaddr;
                    387:        IF_DEBUG(printf("chilcint: unit %d  oactive %d  xbdp %d\n",
                    388:                minor(dev), sp->il_oactive, (sp->il_xuba >> 28) & 0x0f));
                    389: 
                    390: #ifdef VMUNIX
                    391: #ifdef NOHOG
                    392:        if (sp->il_oactive)
                    393:                ubarelse(sp->il_ubanum, &sp->il_xuba);
                    394: #else
                    395:        if (sp->il_xbdp)
                    396:                PURGEBDP(sp->il_ubanum, sp->il_xbdp);
                    397: #endif NOHOG
                    398: #endif VMUNIX
                    399: 
                    400:        sp->il_oactive = 0;
                    401:        sp->il_scsr = addr->il_csr;
                    402:        if (sp->il_replying) {
                    403:                sp->il_replying = 0;
                    404:                sp->il_doreply = 0;
                    405:        } else if ((pkt = sp->il_xcvr.xc_tpkt) != NOPKT) {
                    406:                if ((sp->il_scsr & IL_STATUS) > 1) {
                    407:                        chilxstat = sp->il_scsr;
                    408:                        sp->il_xcvr.xc_abrt++;
                    409:                } else {
                    410:                        if (sp->il_scsr & IL_STATUS)
                    411:                                sp->il_xcvr.xc_abrt++;
                    412:                        sp->il_xcvr.xc_xmtd++;
                    413:                }
                    414:                bcopy(&sp->il_savex,
                    415:                      (char *)&pkt->pk_phead - sizeof(struct il_xheader),
                    416:                      sizeof(struct il_xheader));
                    417:                IF_DEBUG(printf("chil: pkt %d (op %o didx %x) done\n",
                    418:                                pkt->pk_pkn, pkt->pk_op, pkt->pk_didx & 0xffff));
                    419:                xmitdone(pkt);
                    420:        }
                    421:        /*
                    422:         * If the last receive interrupt happened while a command was
                    423:         * in progress, it couldn't prime the receive buffer then, so it
                    424:         * set the flag telling us to do it here.
                    425:         */
                    426:        if (sp->il_startrcv)
                    427:                chilrstart(sp);
                    428:        /*
                    429:         * If last receive interrupt created an address resolution reply
                    430:         * to send, send it rather than another data packet.
                    431:         */
                    432:        if (sp->il_doreply) {
                    433:                sp->il_replying = 1;
                    434:                epkt = (struct il_xheader *)&sp->il_arreply;
                    435:                elength = sizeof(struct chilapkt);
                    436:                chilxrp++;
                    437:        } else if ((pkt = xmitnext(&sp->il_xcvr)) == NOPKT)
                    438:                return;
                    439:        else {
                    440:                IF_DEBUG(printf("chil: pkt %d (op %o didx %x) started\n",
                    441:                                pkt->pk_pkn, pkt->pk_op, pkt->pk_didx & 0xffff));
                    442:                epkt = (struct il_xheader *)
                    443:                        ((char *)&pkt->pk_phead - sizeof(struct il_xheader));
                    444:                elength = sizeof(struct il_xheader) +
                    445:                          sizeof(struct pkt_header) +
                    446:                          pkt->pk_len;
                    447:                bcopy((char *)epkt, (char *)&sp->il_savex,
                    448:                      sizeof(struct il_xheader));
                    449:                if (pkt->pk_xdest == 0) {
                    450:                        epkt->ilx_type = ILCHAOS_TYPE;
                    451:                        bcopy(ether_broadcast, epkt->ilx_dhost, 6);
                    452:                } else {
                    453:                        register struct ar_pair *app;
                    454: 
                    455:                        for (app = sp->il_pairs;
                    456:                             app < sp->il_epairs && app->arp_chaos.ch_addr;
                    457:                             app++)
                    458:                                if (pkt->pk_xdest == app->arp_chaos.ch_addr) {
                    459:                                        app->arp_time = ++arptime;
                    460:                                        epkt->ilx_type = ILCHAOS_TYPE;
                    461:                                        bcopy(app->arp_ether, epkt->ilx_dhost,
                    462:                                              6);
                    463:                                        app = 0;
                    464:                                        break;
                    465:                                }
                    466:                        if (app) {
                    467:                                chilxrq++;
                    468:                                /*
                    469:                                 * We have no cached address translation -
                    470:                                 * we must ask for one.
                    471:                                 */
                    472:                                epkt = (struct il_xheader *)&sp->il_arrequest;
                    473:                                sp->il_arrequest.ar_pkt.ar_ctarget.ch_addr =
                    474:                                        pkt->pk_xdest;
                    475:                                elength = sizeof(struct chilapkt);
                    476:                        }
                    477:                }
                    478:        }
                    479: 
                    480: #ifdef NOHOG
                    481:        sp->il_xuba = uballoc(sp->il_ubanum, (caddr_t)epkt, elength, UBA_WANTBDP);
                    482: #else
                    483:        sp->il_xuba = ubaremap(sp->il_ubanum, sp->il_xuba, (caddr_t)epkt);
                    484: #endif NOHOG
                    485: 
                    486:        IF_DEBUG(printf("  new uba map: xbdp %d  addr %x\n",
                    487:                (sp->il_xuba >> 28) & 0x0f, sp->il_xuba & 0xfff));
                    488: 
                    489:        addr->il_bar = sp->il_xuba & 0xffff;
                    490:        addr->il_bcr = (elength + 1) & ~1;
                    491:        addr->il_csr = ((sp->il_xuba >> 2) & IL_EUA) |
                    492:                        ILC_XMIT|IL_CIE|IL_RIE;
                    493:        sp->il_oactive++;
                    494: }
                    495: /*
                    496:  * Receiver interrupt
                    497:  */
                    498: chilrint(dev)
                    499: {
                    500:        register struct chilsoft *sp = &chilsoft[dev];
                    501:        register struct packet *pkt;    /* shouldn't be reg on pdp11 */
                    502:        int elength;
                    503: 
                    504:        chilrin++;
                    505:        if (sp->il_rbdp)
                    506:                PURGEBDP(sp->il_ubanum, sp->il_rbdp);
                    507:        if (sp->il_rpkt.ilp_rhdr.ilr_status == 0377) {
                    508:                printf("chil%d: Receive interrupt with no packet!\n");
                    509:                return;
                    510:        }
                    511:        if (sp->il_rpkt.ilp_rhdr.ilr_status & 4) {
                    512:                sp->il_xcvr.xc_rej++;
                    513:                chillost++;
                    514:        }
                    515:        /*
                    516:         * Data length is chaos packet size plus header (minus
                    517:         * frame status and length == 4 plus 4 for the crc == 0!)
                    518:         */
                    519:        elength = sp->il_rpkt.ilp_rhdr.ilr_length - sizeof(struct il_rheader);
                    520:        if (sp->il_rpkt.ilp_rhdr.ilr_status & 3)
                    521:                printf("chil%d: Received erroneous frame. Status: %d\n",
                    522:                        dev, sp->il_rpkt.ilp_rhdr.ilr_status);
                    523:        else if (sp->il_rpkt.ilp_rhdr.ilr_type == ILADDR_TYPE)
                    524:                chilrar(sp, &sp->il_rpkt.ilp_arpkt, elength);
                    525:        else if (sp->il_rpkt.ilp_rhdr.ilr_type == ILCHAOS_TYPE)
                    526:                if (elength < sizeof(struct pkt_header) ||
                    527:                    elength < sizeof(struct pkt_header) + sp->il_rpkt.ilp_chhead.ph_len)
                    528:                        sp->il_xcvr.xc_leng++;
                    529:                else  {
                    530:                        register struct chroute *r;
                    531:                        
                    532:                        r = &Chroutetab[sp->il_xcvr.xc_subnet];
                    533:                        r->rt_type = CHDIRECT;
                    534:                        r->rt_cost = CHCCOST;
                    535:                        r->rt_xcvr = &sp->il_xcvr;
                    536:                        if ((pkt = pkalloc((int)sp->il_rpkt.ilp_chhead.ph_len,
                    537:                                           1)) == NOPKT)
                    538:                                sp->il_xcvr.xc_rej++;
                    539:                        else {
                    540:                                bcopy((u_char *)&sp->il_rpkt.ilp_chpkt,
                    541:                                      (u_char *)&pkt->pk_phead,
                    542:                                      sizeof(struct pkt_header) +
                    543:                                      sp->il_rpkt.ilp_chhead.ph_len);
                    544:                                sp->il_xcvr.xc_rcvd++;
                    545:                                LOCK;
                    546:                                if (pkt->pk_daddr == sp->il_xcvr.xc_addr &&
                    547:                                    Chmyaddr != -1)
                    548:                                    pkt->pk_daddr = Chmyaddr;
                    549:                                rcvpkt(pkt);
                    550:                        }
                    551:                }
                    552:        if (sp->il_oactive)
                    553:                sp->il_startrcv = 1;
                    554:        else
                    555:                chilrstart(sp);
                    556: }
                    557: chilrstart(sp)
                    558: register struct chilsoft *sp;
                    559: {
                    560:        register struct ildevice *addr = sp->il_devaddr;
                    561: 
                    562:        chilrst++;
                    563:        sp->il_rpkt.ilp_rhdr.ilr_status = 0177777;
                    564:        addr->il_bar = sp->il_ruba & 0xffff;
                    565:        addr->il_bcr = sizeof(union chilpkt);
                    566:        addr->il_csr = (sp->il_ruba >> 2) & IL_EUA |
                    567:                        ILC_RCV|IL_RIE;
                    568:        while (!((sp->il_scsr = addr->il_csr) & IL_CDONE))
                    569:                /* Busy wait */;
                    570:        if (sp->il_scsr & IL_STATUS)
                    571:                printf("il%d: receive buffer error: %d\n",
                    572:                        sp->il_unit, sp->il_scsr & IL_STATUS);
                    573:        sp->il_startrcv = 0;
                    574: }
                    575: /*
                    576:  * Receive an address resolution packet.
                    577:  */
                    578: chilrar(sp, arp, length)
                    579: register struct chilsoft *sp;
                    580: register struct ar_packet *arp;
                    581: {
                    582:        register struct ar_pair *app;
                    583:        register struct ar_pair *nap;
                    584: 
                    585:        u_char *eaddr;
                    586: 
                    587:        chilar++;
                    588:        if (length < sizeof(struct ar_packet) ||
                    589:            arp->ar_hardware != AR_ETHERNET ||
                    590:            arp->ar_protocol != ILCHAOS_TYPE ||
                    591:            arp->ar_plength != sizeof(chaddr) ||
                    592:            arp->ar_csender.ch_addr == 0)
                    593:                return;
                    594:        eaddr = 0;
                    595:        nap = sp->il_pairs;
                    596:        for (app = nap; app < sp->il_epairs && app->arp_chaos.ch_addr; app++)
                    597:                if (arp->ar_csender.ch_addr == app->arp_chaos.ch_addr) {
                    598:                        eaddr = app->arp_ether;
                    599:                        break;
                    600:                } else if (app->arp_time < nap->arp_time)
                    601:                        nap = app;
                    602:        /*
                    603:         * If we are already cacheing the senders addresses,
                    604:         * update our cache with possibly new information.
                    605:         */
                    606:        if (eaddr)
                    607:                bcopy(arp->ar_esender, app->arp_ether, 6);
                    608:        if (arp->ar_ctarget.ch_addr != sp->il_xcvr.xc_addr)
                    609:                return;
                    610:        /*
                    611:         * If we have never heard of this host before, find
                    612:         * a slot and remember him.
                    613:         * Note that we leave the time alone since we haven't used the entry.
                    614:         * This is to prevent other hosts from flushing our cache
                    615:         */
                    616:        if (eaddr == 0) {
                    617:                bcopy(arp->ar_esender, nap->arp_ether, 6);
                    618:                nap->arp_chaos.ch_addr = arp->ar_csender.ch_addr;
                    619:        }
                    620:        if (arp->ar_opcode == AR_REQUEST)
                    621:                if (sp->il_doreply)
                    622:                        chilarls++;
                    623:                else {
                    624:                        chilarrp++;
                    625:                        IF_DEBUG(printf("chilrar: sending arp (unit %d)\n",
                    626:                                        sp->il_unit));
                    627:                        sp->il_arreply.ar_pkt.ar_ctarget.ch_addr = arp->ar_csender.ch_addr;
                    628:                        bcopy(arp->ar_esender, sp->il_arreply.ar_pkt.ar_etarget, 6);
                    629:                        bcopy(arp->ar_esender, sp->il_arreply.ar_xhdr.ilx_dhost, 6);
                    630:                        sp->il_doreply = 1;
                    631:                        if (sp->il_oactive == 0)
                    632:                                chilcint(sp->il_unit);
                    633:                }
                    634: }                      
                    635: #define MAXWAIT        1000000         /* on the order of 10 seconds */
                    636: /*
                    637:  * Perform a command and busy-wait for the interrupt.
                    638:  * Used when it's not safe to sleep.
                    639:  * This should never be called to receive a packet.
                    640:  */
                    641: ilbusywait(sp, command, bits)
                    642: register struct chilsoft *sp;
                    643: int command, bits;
                    644: {
                    645:        register struct ildevice *addr = sp->il_devaddr;
                    646:        register int csr, i;
                    647: 
                    648:        csr = addr->il_csr;
                    649:        IF_DEBUG(printf("il%d: busy wait %x csr %x bcr %x bar %x bits %x",
                    650: sp->il_unit, command, csr&0xffff, addr->il_bcr&0xffff, addr->il_bar&0xffff, bits));
                    651:        addr->il_csr = bits|command;
                    652:        for (i = 0; !((csr = addr->il_csr) & IL_CDONE); i++)
                    653:                if (i >= MAXWAIT) {
                    654:                        printf("il%d: lost CDONE\n", sp->il_unit);
                    655:                        return;
                    656:                }
                    657:        IF_DEBUG((csr & IL_STATUS) ? printf("%s\n",
                    658:                (command == ILC_DIAG || command == ILC_RESET ?
                    659:                ildiag : ilerrs)[csr & IL_STATUS])
                    660:                        : printf("done\n"));
                    661: }

unix.superglobalmegacorp.com

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