Annotation of researchv8dc/sys/chncp/chil.c, revision 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.