📄 fmvj18x_cs.c
字号:
if (le16_to_cpu(buf[1]) == PRODID_TDK_CF010) { cs_status_t status; CardServices(GetStatus, handle, &status); if (status.CardState & CS_EVENT_3VCARD) link->conf.Vcc = 33; /* inserted in 3.3V slot */ } 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 (CardServices(GetFirstTuple, handle, &tuple) == CS_SUCCESS) CS_CHECK(GetTupleData, 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; /* 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; /* 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 == UNGERMANN) outb(BANK_0U, ioaddr + CONFIG_1); else outb(BANK_0, 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, 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 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."); unregister_netdev(dev); 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; } 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 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; link->win = (window_handle_t)link->handle; i = CardServices(RequestWindow, &link->win, &req); if (i != CS_SUCCESS) { cs_error(link->handle, RequestWindow, i); return -1; } base = ioremap(req.Base, req.Size); mem.Page = 0; mem.CardOffset = 0; CardServices(MapMemPage, 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 = CardServices(ReleaseWindow, link->win); if (j != CS_SUCCESS) cs_error(link->handle, ReleaseWindow, j); return (i != 0x200) ? 0 : -1;} /* fmvj18x_get_hwinfo *//*====================================================================*/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_wake_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; netif_stop_queue(dev); { short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; unsigned char *buf = skb->data; if (length > ETH_FRAME_LEN) { printk(KERN_NOTICE "%s: Attempting to send a large packet" " (%d bytes).\n", dev->name, length); return 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -