📄 fmvj18x_cs.c
字号:
local_info_t *lp = link->priv; struct net_device *dev = &lp->dev; tuple_t tuple; cisparse_t parse; u_short buf[32]; int i, last_fn, last_ret, ret; ioaddr_t ioaddr; cardtype_t cardtype; char *card_name = "unknown"; u_char *node_id; DEBUG(0, "fmvj18x_config(0x%p)\n", link); /* This reads the card's CONFIG tuple to find its configuration registers. */ tuple.DesiredTuple = CISTPL_CONFIG; CS_CHECK(GetFirstTuple, handle, &tuple); tuple.TupleData = (u_char *)buf; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; CS_CHECK(GetTupleData, handle, &tuple); CS_CHECK(ParseTuple, handle, &tuple, &parse); /* Configure card */ link->state |= DEV_CONFIG; link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; tuple.DesiredTuple = CISTPL_FUNCE; tuple.TupleOffset = 0; if (CardServices(GetFirstTuple, handle, &tuple) == CS_SUCCESS) { /* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; CS_CHECK(GetFirstTuple, handle, &tuple); CS_CHECK(GetTupleData, handle, &tuple); CS_CHECK(ParseTuple, handle, &tuple, &parse); link->conf.ConfigIndex = parse.cftable_entry.index; tuple.DesiredTuple = CISTPL_MANFID; if (CardServices(GetFirstTuple, handle, &tuple) == CS_SUCCESS) CS_CHECK(GetTupleData, handle, &tuple); else buf[0] = 0xffff; switch (le16_to_cpu(buf[0])) { case MANFID_TDK: cardtype = TDK; break; case MANFID_CONTEC: cardtype = CONTEC; break; case MANFID_FUJITSU: if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10302) cardtype = MBH10302; else if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10304) cardtype = MBH10304; else cardtype = LA501; break; default: cardtype = MBH10304; } } else { /* old type card */ tuple.DesiredTuple = CISTPL_MANFID; if (CardServices(GetFirstTuple, handle, &tuple) == CS_SUCCESS) CS_CHECK(GetTupleData, handle, &tuple); else buf[0] = 0xffff; switch (le16_to_cpu(buf[0])) { case MANFID_UNGERMANN: cardtype = UNGERMANN; /* Ungermann-Bass Access/CARD accepts 0x300,0x320,0x340,0x360 0x380,0x3c0 only for ioport. */ for (link->io.BasePort1 = 0x300; link->io.BasePort1 < 0x3e0; link->io.BasePort1 += 0x20) { ret = CardServices(RequestIO, link->handle, &link->io); if (ret == CS_SUCCESS) { /* calculate ConfigIndex value */ link->conf.ConfigIndex = ((link->io.BasePort1 & 0x0f0) >> 3) | 0x22; goto req_irq; } } /* if ioport allocation is failed, goto failed */ printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n"); goto failed; default: cardtype = MBH10302; link->conf.ConfigIndex = 1; } } CS_CHECK(RequestIO, link->handle, &link->io);req_irq: CS_CHECK(RequestIRQ, link->handle, &link->irq); CS_CHECK(RequestConfiguration, link->handle, &link->conf); dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; if (register_netdev(dev) != 0) { printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n"); goto failed; } ioaddr = dev->base_addr; /* Power On chip and select bank 0 */ if(cardtype == UNGERMANN) outb(BANK_0U, ioaddr + CONFIG_1); else outb(BANK_0, ioaddr + CONFIG_1); /* Reset controler */ if( sram_config == 0 ) outb(CONFIG0_RST, ioaddr + CONFIG_0); else outb(CONFIG0_RST_1, ioaddr + CONFIG_0); /* Set hardware address */ switch (cardtype) { case MBH10304: case TDK: case LA501: case CONTEC: tuple.DesiredTuple = CISTPL_FUNCE; tuple.TupleOffset = 0; CS_CHECK(GetFirstTuple, handle, &tuple); tuple.TupleOffset = 0; CS_CHECK(GetTupleData, handle, &tuple); if (cardtype == MBH10304) { /* MBH10304's CIS_FUNCE is corrupted */ node_id = &(tuple.TupleData[5]); card_name = "FMV-J182"; } else { while (tuple.TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID ) { CS_CHECK(GetNextTuple, handle, &tuple) ; CS_CHECK(GetTupleData, handle, &tuple) ; } node_id = &(tuple.TupleData[2]); if( cardtype == TDK ) { card_name = "TDK LAK-CD021"; } else if( cardtype == LA501 ) { card_name = "LA501"; } else { card_name = "C-NET(PC)C"; } } /* Read MACID from CIS */ for (i = 0; i < 6; i++) dev->dev_addr[i] = node_id[i]; break; case UNGERMANN: /* Read MACID from register */ for (i = 0; i < 6; i++) dev->dev_addr[i] = inb(ioaddr + UNGERMANN_MAC_ID + i); card_name = "Access/CARD"; break; case MBH10302: default: /* Read MACID from register */ for (i = 0; i < 6; i++) dev->dev_addr[i] = inb(ioaddr + MAC_ID + i); card_name = "FMV-J181"; break; } strcpy(lp->node.dev_name, dev->name); link->dev = &lp->node; link->state &= ~DEV_CONFIG_PENDING; lp->cardtype = cardtype; /* print current configuration */ printk(KERN_INFO "%s: %s, sram %s, port %#3lx, irq %d, hw_addr ", dev->name, card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2", dev->base_addr, dev->irq); for (i = 0; i < 6; i++) printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); return; cs_failed: /* All Card Services errors end up here */ cs_error(link->handle, last_fn, last_ret);failed: fmvj18x_release((u_long)link);} /* fmvj18x_config */ /*====================================================================*/static void fmvj18x_release(u_long arg){ dev_link_t *link = (dev_link_t *)arg; DEBUG(0, "fmvj18x_release(0x%p)\n", link); /* If the device is currently in use, we won't release until it is actually closed. */ if (link->open) { DEBUG(1, "fmvj18x_cs: release postponed, '%s' " "still open\n", link->dev->dev_name); link->state |= DEV_STALE_CONFIG; return; } /* Don't bother checking to see if these succeed or not */ CardServices(ReleaseWindow, link->win); CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIRQ, link->handle, &link->irq); link->state &= ~DEV_CONFIG; } /* fmvj18x_release *//*====================================================================*/static int fmvj18x_event(event_t event, int priority, event_callback_args_t *args){ dev_link_t *link = args->client_data; local_info_t *lp = link->priv; struct net_device *dev = &lp->dev; DEBUG(1, "fmvj18x_event(0x%06x)\n", event); switch (event) { case CS_EVENT_CARD_REMOVAL: link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG) { netif_device_detach(dev); mod_timer(&link->release, jiffies + HZ/20); } break; case CS_EVENT_CARD_INSERTION: link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; fmvj18x_config(link); break; case CS_EVENT_PM_SUSPEND: link->state |= DEV_SUSPEND; /* Fall through... */ case CS_EVENT_RESET_PHYSICAL: if (link->state & DEV_CONFIG) { if (link->open) netif_device_detach(dev); CardServices(ReleaseConfiguration, link->handle); } break; case CS_EVENT_PM_RESUME: link->state &= ~DEV_SUSPEND; /* Fall through... */ case CS_EVENT_CARD_RESET: if (link->state & DEV_CONFIG) { CardServices(RequestConfiguration, link->handle, &link->conf); if (link->open) { fjn_reset(dev); netif_device_attach(dev); } } break; } return 0;} /* fmvj18x_event *//*====================================================================*/static int __init init_fmvj18x_cs(void){ servinfo_t serv; DEBUG(0, "%s\n", version); CardServices(GetCardServicesInfo, &serv); if (serv.Revision != CS_RELEASE_CODE) { printk(KERN_NOTICE "fmvj18x: Card Services release " "does not match!\n"); return -1; } register_pccard_driver(&dev_info, &fmvj18x_attach, &fmvj18x_detach); return 0;}static void __exit exit_fmvj18x_cs(void){ DEBUG(0, "fmvj18x_cs: unloading\n"); unregister_pccard_driver(&dev_info); while (dev_list != NULL) fmvj18x_detach(dev_list);}module_init(init_fmvj18x_cs);module_exit(exit_fmvj18x_cs);/*====================================================================*/static void fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs){ local_info_t *lp = dev_id; struct net_device *dev = &lp->dev; ioaddr_t ioaddr; unsigned short tx_stat, rx_stat; if (lp == NULL) { printk(KERN_NOTICE "fjn_interrupt(): irq %d for " "unknown device.\n", irq); return; } ioaddr = dev->base_addr; /* avoid multiple interrupts */ outw(0x0000, ioaddr + TX_INTR); /* wait for a while */ udelay(1); /* get status */ tx_stat = inb(ioaddr + TX_STATUS); rx_stat = inb(ioaddr + RX_STATUS); /* clear status */ outb(tx_stat, ioaddr + TX_STATUS); outb(rx_stat, ioaddr + RX_STATUS); DEBUG(4, "%s: interrupt, rx_status %02x.\n", dev->name, rx_stat); DEBUG(4, " tx_status %02x.\n", tx_stat); if (rx_stat || (inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) { /* there is packet(s) in rx buffer */ fjn_rx(dev); } if (tx_stat & F_TMT_RDY) { lp->stats.tx_packets += lp->sent ; lp->sent = 0 ; if (lp->tx_queue) { outb(DO_TX | lp->tx_queue, ioaddr + TX_START); lp->sent = lp->tx_queue ; lp->tx_queue = 0; lp->tx_queue_len = 0; dev->trans_start = jiffies; } else { lp->tx_started = 0; } netif_wake_queue(dev); } DEBUG(4, "%s: exiting interrupt,\n", dev->name); DEBUG(4, " tx_status %02x, rx_status %02x.\n", tx_stat, rx_stat); outb(D_TX_INTR, ioaddr + TX_INTR); outb(D_RX_INTR, ioaddr + RX_INTR);} /* fjn_interrupt *//*====================================================================*/static void fjn_tx_timeout(struct net_device *dev){ struct local_info_t *lp = (struct local_info_t *)dev->priv; ioaddr_t ioaddr = dev->base_addr; printk(KERN_NOTICE "%s: transmit timed out with status %04x, %s?\n", dev->name, htons(inw(ioaddr + TX_STATUS)), inb(ioaddr + TX_STATUS) & F_TMT_RDY ? "IRQ conflict" : "network cable problem"); printk(KERN_NOTICE "%s: timeout registers: %04x %04x %04x " "%04x %04x %04x %04x %04x.\n", dev->name, htons(inw(ioaddr + 0)), htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)), htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)), htons(inw(ioaddr +10)), htons(inw(ioaddr +12)), htons(inw(ioaddr +14))); lp->stats.tx_errors++; /* ToDo: We should try to restart the adaptor... */ cli(); fjn_reset(dev); lp->tx_started = 0; lp->tx_queue = 0; lp->tx_queue_len = 0; lp->sent = 0; lp->open_time = jiffies; sti(); netif_start_queue(dev);}static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev){ struct local_info_t *lp = (struct local_info_t *)dev->priv; ioaddr_t ioaddr = dev->base_addr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -