📄 fmvj18x_cs.c
字号:
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); link->conf.ConfigIndex = parse.cftable_entry.index; tuple.DesiredTuple = CISTPL_MANFID; if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); else buf[0] = 0xffff; switch (le16_to_cpu(buf[0])) { case MANFID_TDK: cardtype = TDK; if (le16_to_cpu(buf[1]) == PRODID_TDK_CF010) { cs_status_t status; pcmcia_get_status(handle, &status); if (status.CardState & CS_EVENT_3VCARD) link->conf.Vcc = 33; /* inserted in 3.3V slot */ } else if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410) { /* MultiFunction Card */ link->conf.ConfigBase = 0x800; link->conf.ConfigIndex = 0x47; link->io.NumPorts2 = 8; } break; case MANFID_CONTEC: cardtype = CONTEC; break; case MANFID_FUJITSU: if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10302) /* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302), but these are MBH10304 based card. */ cardtype = MBH10304; 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 (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); else buf[0] = 0xffff; switch (le16_to_cpu(buf[0])) { case MANFID_FUJITSU: if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10304) { cardtype = XXX10304; /* MBH10304 with buggy CIS */ link->conf.ConfigIndex = 0x20; } else { cardtype = MBH10302; /* NextCom NC5310, etc. */ link->conf.ConfigIndex = 1; } break; case MANFID_UNGERMANN: cardtype = UNGERMANN; break; default: cardtype = MBH10302; link->conf.ConfigIndex = 1; } } if (link->io.NumPorts2 != 0) { link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED|IRQ_HANDLE_PRESENT; ret = mfc_try_io_port(link); if (ret != CS_SUCCESS) goto cs_failed; } else if (cardtype == UNGERMANN) { ret = ungermann_try_io_port(link); if (ret != CS_SUCCESS) goto cs_failed; } else { CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io)); } CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; if (link->io.BasePort2 != 0) fmvj18x_setup_mfc(link); ioaddr = dev->base_addr; /* Reset controller */ if (sram_config == 0) outb(CONFIG0_RST, ioaddr + CONFIG_0); else outb(CONFIG0_RST_1, ioaddr + CONFIG_0); /* Power On chip and select bank 0 */ if (cardtype == MBH10302) outb(BANK_0, ioaddr + CONFIG_1); else outb(BANK_0U, ioaddr + CONFIG_1); /* Set hardware address */ switch (cardtype) { case MBH10304: case TDK: case LA501: case CONTEC: tuple.DesiredTuple = CISTPL_FUNCE; tuple.TupleOffset = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); tuple.TupleOffset = 0; CS_CHECK(GetTupleData, pcmcia_get_tuple_data(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, pcmcia_get_next_tuple(handle, &tuple)); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(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 XXX10304: /* Read MACID from Buggy CIS */ if (fmvj18x_get_hwinfo(link, tuple.TupleData) == -1) { printk(KERN_NOTICE "fmvj18x_cs: unable to read hardware net address.\n"); goto failed; } for (i = 0 ; i < 6; i++) { dev->dev_addr[i] = tuple.TupleData[i]; } card_name = "FMV-J182"; 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; } lp->cardtype = cardtype; link->dev = &lp->node; link->state &= ~DEV_CONFIG_PENDING; if (register_netdev(dev) != 0) { printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n"); link->dev = NULL; goto failed; } strcpy(lp->node.dev_name, dev->name); /* 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(link); link->state &= ~DEV_CONFIG_PENDING;} /* fmvj18x_config *//*====================================================================*/static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id){ win_req_t req; memreq_t mem; u_char *base; int i, j; /* Allocate a small memory window */ req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; req.Base = 0; req.Size = 0; req.AccessSpeed = 0; i = pcmcia_request_window(&link->handle, &req, &link->win); if (i != CS_SUCCESS) { cs_error(link->handle, RequestWindow, i); return -1; } base = ioremap(req.Base, req.Size); mem.Page = 0; mem.CardOffset = 0; pcmcia_map_mem_page(link->win, &mem); /* * MBH10304 CISTPL_FUNCE_LAN_NODE_ID format * 22 0d xx xx xx 04 06 yy yy yy yy yy yy ff * 'xx' is garbage. * 'yy' is MAC address. */ for (i = 0; i < 0x200; i++) { if (readb(base+i*2) == 0x22) { if (readb(base+(i-1)*2) == 0xff && readb(base+(i+5)*2) == 0x04 && readb(base+(i+6)*2) == 0x06 && readb(base+(i+13)*2) == 0xff) break; } } if (i != 0x200) { for (j = 0 ; j < 6; j++,i++) { node_id[j] = readb(base+(i+7)*2); } } iounmap(base); j = pcmcia_release_window(link->win); if (j != CS_SUCCESS) cs_error(link->handle, ReleaseWindow, j); return (i != 0x200) ? 0 : -1;} /* fmvj18x_get_hwinfo *//*====================================================================*/static int fmvj18x_setup_mfc(dev_link_t *link){ win_req_t req; memreq_t mem; u_char *base; int i, j; struct net_device *dev = link->priv; ioaddr_t ioaddr; /* Allocate a small memory window */ req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; req.Base = 0; req.Size = 0; req.AccessSpeed = 0; i = pcmcia_request_window(&link->handle, &req, &link->win); if (i != CS_SUCCESS) { cs_error(link->handle, RequestWindow, i); return -1; } base = ioremap(req.Base, req.Size); mem.Page = 0; mem.CardOffset = 0; pcmcia_map_mem_page(link->win, &mem); ioaddr = dev->base_addr; writeb(0x47, base+0x800); /* Config Option Register of LAN */ writeb(0x0, base+0x802); /* Config and Status Register */ writeb(ioaddr & 0xff, base+0x80a); /* I/O Base(Low) of LAN */ writeb((ioaddr >> 8) & 0xff, base+0x80c); /* I/O Base(High) of LAN */ writeb(0x45, base+0x820); /* Config Option Register of Modem */ writeb(0x8, base+0x822); /* Config and Status Register */ iounmap(base); j = pcmcia_release_window(link->win); if (j != CS_SUCCESS) cs_error(link->handle, ReleaseWindow, j); return 0;}/*====================================================================*/static void fmvj18x_release(dev_link_t *link){ DEBUG(0, "fmvj18x_release(0x%p)\n", link); /* Don't bother checking to see if these succeed or not */ pcmcia_release_window(link->win); pcmcia_release_configuration(link->handle); pcmcia_release_io(link->handle, &link->io); pcmcia_release_irq(link->handle, &link->irq); link->state &= ~DEV_CONFIG;}/*====================================================================*/static int fmvj18x_event(event_t event, int priority, event_callback_args_t *args){ dev_link_t *link = args->client_data; struct net_device *dev = link->priv; 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); 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); pcmcia_release_configuration(link->handle); } break; case CS_EVENT_PM_RESUME: link->state &= ~DEV_SUSPEND; /* Fall through... */ case CS_EVENT_CARD_RESET: if (link->state & DEV_CONFIG) { pcmcia_request_configuration(link->handle, &link->conf); if (link->open) { fjn_reset(dev); netif_device_attach(dev); } } break; } return 0;} /* fmvj18x_event */static struct pcmcia_driver fmvj18x_cs_driver = { .owner = THIS_MODULE, .drv = { .name = "fmvj18x_cs", }, .attach = fmvj18x_attach, .detach = fmvj18x_detach,};static int __init init_fmvj18x_cs(void){ return pcmcia_register_driver(&fmvj18x_cs_driver);}static void __exit exit_fmvj18x_cs(void){ pcmcia_unregister_driver(&fmvj18x_cs_driver); while (dev_list != NULL) fmvj18x_detach(dev_list);}module_init(init_fmvj18x_cs);module_exit(exit_fmvj18x_cs);/*====================================================================*/static irqreturn_t fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs){ struct net_device *dev = dev_id; local_info_t *lp = netdev_priv(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 IRQ_NONE; } 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); return IRQ_HANDLED;} /* fjn_interrupt *//*====================================================================*/static void fjn_tx_timeout(struct net_device *dev){ struct local_info_t *lp = netdev_priv(dev);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -