📄 com90xx.c
字号:
continue; } /* skip this completely if an IRQ was given, because maybe * we're on a machine that locks during autoirq! */ if (!dev->irq) { /* if we do this, we're sure to get an IRQ since the * card has just reset and the NORXflag is on until * we tell it to start receiving. */ airqmask = probe_irq_on(); AINTMASK(NORXflag); udelay(1); AINTMASK(0); airq = probe_irq_off(airqmask); if (airq <= 0) { BUGMSG2(D_INIT_REASONS, "(airq=%d)\n", airq); BUGMSG(D_INIT_REASONS, "Stage 5: "); BUGLVL(D_INIT_REASONS) numprint = 0; *port = ports[numports - 1]; numports--; port--; continue; } } else { airq = dev->irq; } BUGMSG2(D_INIT, "(%d,", airq); openparen = 1; /* Everything seems okay. But which shmem, if any, puts * back its signature byte when the card is reset? * * If there are multiple cards installed, there might be * multiple shmems still in the list. */#ifdef FAST_PROBE if (numports > 1 || numshmems > 1) { ARCRESET; JIFFER(RESETtime); } else { /* just one shmem and port, assume they match */ writeb(TESTvalue, shmems[0]); }#else ARCRESET; JIFFER(RESETtime);#endif for (shmem = &shmems[0]; shmem - shmems < numshmems; shmem++) { u_long ptr; ptr = (u_long) (*shmem); if (readb(ptr) == TESTvalue) { /* found one */ int probe_more; BUGMSG2(D_INIT, "%lXh)\n", *shmem); openparen = 0; /* register the card */ if (init_once == 1 && numshmems > 1) probe_more = numshmems - 1; else probe_more = 0; retval = arc90xx_found(dev, *port, airq, *shmem, probe_more); if (retval) openparen = 0; /* remove shmem from the list */ *shmem = shmems[numshmems - 1]; numshmems--; break; } else { BUGMSG2(D_INIT_REASONS, "%Xh-", readb(ptr)); } } if (openparen) { BUGMSG2(D_INIT, "no matching shmem)\n"); BUGMSG(D_INIT_REASONS, "Stage 5: "); BUGLVL(D_INIT_REASONS) numprint = 0; } *port = ports[numports - 1]; numports--; port--; if (!retval) break; } BUGMSG(D_INIT_REASONS, "\n"); /* Now put back TESTvalue on all leftover shmems. */ for (shmem = &shmems[0]; shmem - shmems < numshmems; shmem++) writeb(TESTvalue, *shmem); if (retval) BUGMSG(D_NORMAL, "Stage 5: No ARCnet cards found.\n"); return retval;}/* Set up the struct device associated with this card. Called after * probing succeeds. */__initfunc(static int arc90xx_found(struct device *dev, int ioaddr, int airq, u_long shmem, int more)){ struct arcnet_local *lp; u_long first_mirror, last_mirror; int mirror_size; /* reserve the irq */ if (request_irq(airq, &arcnet_interrupt, 0, "arcnet (90xx)", dev)) { BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", airq); return -ENODEV; } dev->irq = airq; /* reserve the I/O region - guaranteed to work by check_region */ request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (90xx)"); dev->base_addr = ioaddr; /* find the real shared memory start/end points, including mirrors */#define BUFFER_SIZE (512)#define MIRROR_SIZE (BUFFER_SIZE*4) /* guess the actual size of one "memory mirror" - the number of * bytes between copies of the shared memory. On most cards, it's * 2k (or there are no mirrors at all) but on some, it's 4k. */ mirror_size = MIRROR_SIZE; if (readb(shmem) == TESTvalue && readb(shmem - mirror_size) != TESTvalue && readb(shmem - 2 * mirror_size) == TESTvalue) mirror_size *= 2; first_mirror = last_mirror = shmem; while (readb(first_mirror) == TESTvalue) first_mirror -= mirror_size; first_mirror += mirror_size; while (readb(last_mirror) == TESTvalue) last_mirror += mirror_size; last_mirror -= mirror_size; dev->mem_start = first_mirror; dev->mem_end = last_mirror + MIRROR_SIZE - 1; dev->rmem_start = dev->mem_start + BUFFER_SIZE * 0; dev->rmem_end = dev->mem_start + BUFFER_SIZE * 2 - 1; /* Initialize the rest of the device structure. */ dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL); if (dev->priv == NULL) { free_irq(airq, dev); release_region(ioaddr, ARCNET_TOTAL_SIZE); return -ENOMEM; } memset(dev->priv, 0, sizeof(struct arcnet_local)); lp = (struct arcnet_local *) (dev->priv); lp->card_type = ARC_90xx; lp->card_type_str = "COM 90xx"; lp->arcnet_reset = arc90xx_reset; lp->asetmask = arc90xx_setmask; lp->astatus = arc90xx_status; lp->acommand = arc90xx_command; lp->openclose_device = arc90xx_openclose; lp->prepare_tx = arc90xx_prepare_tx; lp->inthandler = arc90xx_inthandler; /* Fill in the fields of the device structure with generic * values. */ arcnet_setup(dev); /* And now fill particular fields with arcnet values */ dev->mtu = 1500; /* completely arbitrary - agrees with ether, though */ dev->hard_header_len = sizeof(struct ClientData); lp->sequence = 1; lp->recbuf = 0; BUGMSG(D_DURING, "ClientData header size is %d.\n", sizeof(struct ClientData)); BUGMSG(D_DURING, "HardHeader size is %d.\n", sizeof(struct archdr)); /* get and check the station ID from offset 1 in shmem */ lp->stationid = readb(first_mirror + 1); if (lp->stationid == 0) BUGMSG(D_NORMAL, "WARNING! Station address 00 is reserved " "for broadcasts!\n"); else if (lp->stationid == 255) BUGMSG(D_NORMAL, "WARNING! Station address FF may confuse " "DOS networking programs!\n"); dev->dev_addr[0] = lp->stationid; BUGMSG(D_NORMAL, "ARCnet COM90xx: station %02Xh found at %03lXh, IRQ %d, " "ShMem %lXh (%ld*%xh).\n", lp->stationid, dev->base_addr, dev->irq, dev->mem_start, (dev->mem_end - dev->mem_start + 1) / mirror_size, mirror_size); /* OK. We're finished. If there are probably other cards, add other * COM90xx drivers to the device chain, so they get probed later. */#ifndef MODULE while (!com90xx_explicit && more--) { if (arcnet_num_devs < MAX_ARCNET_DEVS) { arcnet_devs[arcnet_num_devs].next = dev->next; dev->next = &arcnet_devs[arcnet_num_devs]; dev = dev->next; dev->name = (char *) &arcnet_dev_names[arcnet_num_devs]; arcnet_num_devs++; } else { BUGMSG(D_NORMAL, "Too many arcnet devices - no more will be probed for.\n"); return 0; } arcnet_makename(dev->name); dev->init = arc90xx_probe; }#endif return 0;}/* Do a hardware reset on the card, and set up necessary registers. * This should be called as little as possible, because it disrupts the * token on the network (causes a RECON) and requires a significant delay. * * However, it does make sure the card is in a defined state. */int arc90xx_reset(struct device *dev, int reset_delay){ struct arcnet_local *lp = (struct arcnet_local *) dev->priv; short ioaddr = dev->base_addr; int delayval, recbuf = lp->recbuf; if (reset_delay == 3) { ARCRESET; return 0; } /* no IRQ's, please! */ lp->intmask = 0; SETMASK; BUGMSG(D_INIT, "Resetting %s (status=%Xh)\n", dev->name, ARCSTATUS); if (reset_delay) { /* reset the card */ ARCRESET; JIFFER(RESETtime); } ACOMMAND(CFLAGScmd | RESETclear); /* clear flags & end reset */ ACOMMAND(CFLAGScmd | CONFIGclear); /* verify that the ARCnet signature byte is present */ if (readb(dev->mem_start) != TESTvalue) { BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n"); return 1; } /* clear out status variables */ recbuf = lp->recbuf = 0; lp->txbuf = 2; /* enable extended (512-byte) packets */ ACOMMAND(CONFIGcmd | EXTconf);#ifndef SLOW_XMIT_COPY /* clean out all the memory to make debugging make more sense :) */ BUGLVL(D_DURING) memset_io(dev->mem_start, 0x42, 2048);#endif /* and enable receive of our first packet to the first buffer */ EnableReceiver(); /* re-enable interrupts */ lp->intmask |= NORXflag;#ifdef DETECT_RECONFIGS lp->intmask |= RECONflag;#endif SETMASK; /* done! return success. */ return 0;}static void arc90xx_openclose(int open){ if (open) MOD_INC_USE_COUNT; else MOD_DEC_USE_COUNT;}static void arc90xx_setmask(struct device *dev, u_char mask){ short ioaddr = dev->base_addr; AINTMASK(mask);}static u_char arc90xx_status(struct device *dev){ short ioaddr = dev->base_addr; return ARCSTATUS;}static void arc90xx_command(struct device *dev, u_char cmd){ short ioaddr = dev->base_addr; ACOMMAND(cmd);}/* The actual interrupt handler routine - handle various IRQ's generated * by the card. */static void arc90xx_inthandler(struct device *dev){ struct arcnet_local *lp = (struct arcnet_local *) dev->priv; int ioaddr = dev->base_addr, status, boguscount = 3, didsomething; AINTMASK(0); BUGMSG(D_DURING, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n", ARCSTATUS, lp->intmask); do { status = ARCSTATUS; didsomething = 0; /* RESET flag was enabled - card is resetting and if RX * is disabled, it's NOT because we just got a packet. */ if (status & RESETflag) { BUGMSG(D_NORMAL, "spurious reset (status=%Xh)\n", status); arc90xx_reset(dev, 0); /* all other flag values are just garbage */ break; } /* RX is inhibited - we must have received something. */ if (status & lp->intmask & NORXflag) { int recbuf = lp->recbuf = !lp->recbuf; BUGMSG(D_DURING, "receive irq (status=%Xh)\n", status); /* enable receive of our next packet */ EnableReceiver(); /* Got a packet. */ arc90xx_rx(dev, !recbuf); didsomething++; } /* it can only be an xmit-done irq if we're xmitting :) */ /*if (status&TXFREEflag && !lp->in_txhandler && lp->sending) */ if (status & lp->intmask & TXFREEflag) { struct Outgoing *out = &(lp->outgoing); int was_sending = lp->sending; lp->intmask &= ~TXFREEflag; lp->in_txhandler++; if (was_sending) lp->sending--; BUGMSG(D_DURING, "TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n", status, out->numsegs, out->segnum, out->skb); if (was_sending && !(status & TXACKflag)) { if (lp->lasttrans_dest != 0) { BUGMSG(D_EXTRA, "transmit was not acknowledged! (status=%Xh, dest=%02Xh)\n", status, lp->lasttrans_dest);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -