📄 ib-pcmcia.c
字号:
local->rx_nbuf = nbuf; continue; } if (local->rx_echunk < nchunk) nchunk = local->rx_echunk; ib_pcmcia_blit(modem->rx_buf + local->rx_ibuf, mem + ((rx_ichunk + irx) << 5), nchunk); local->irx += nchunk; if (2 * rx_nchunk <= local->irx) local->irx -= 2 * rx_nchunk; mem[OFFSET_PC_IRX] = local->irx; local->rx_echunk -= nchunk; local->rx_ibuf += nchunk << 5; if (local->rx_echunk == 0) ib_net_rx_parse(modem, local->rx_nbuf); } while (1) { if (local->tx_echunk == 0) { nbuf = ib_net_tx_prepare(modem); if (nbuf == 0) break; modem->stats.tx_bytes += nbuf; modem->stats.tx_packets += 1; local->tx_echunk = (nbuf + 31) >> 5; local->tx_jbuf = 0; } itx = mem[OFFSET_UT_ITX]; if (2 * tx_nchunk <= itx) goto failed; jtx = local->jtx; if (mem[OFFSET_PC_JTX] != jtx) goto failed; if (jtx < itx) nchunk = itx - jtx - tx_nchunk; else nchunk = itx - jtx + tx_nchunk; if (nchunk < 0) goto failed; if (nchunk == 0) break; if (tx_nchunk <= jtx) jtx -= tx_nchunk; if (tx_nchunk - jtx < nchunk) nchunk = tx_nchunk - jtx; if (local->tx_echunk < nchunk) nchunk = local->tx_echunk; ib_pcmcia_blit(mem + ((tx_jchunk + jtx) << 5), modem->tx_buf + local->tx_jbuf, nchunk); local->tx_echunk -= nchunk; local->tx_jbuf += nchunk << 5; local->jtx += nchunk; if (2 * tx_nchunk <= local->jtx) local->jtx -= 2 * tx_nchunk; mem[OFFSET_PC_JTX] = local->jtx; } return;failed: DEBUG(1, "ib-pcmcia: normal failed\n"); ib_pcmcia_reset(local);}/** * ib_pcmcia_wait - hardware reset wait; get hardware address. * called under ib_lock * @local: device private state. */static void ib_pcmcia_wait(struct ib_pcmcia_local_t *local){ struct ib_net_modem_t *modem = local->modem; unsigned char *mem = local->mem; if (ib_pcmcia_check(local)) return; local->feedback = mem[OFFSET_UT_SEQUENCE]; mem[OFFSET_PC_FEEDBACK] = local->feedback; local->rx_echunk = 0; local->tx_echunk = 0; mem[OFFSET_PC_IRX] = local->irx = 0; mem[OFFSET_PC_JTX] = local->jtx = 0; if (mem[OFFSET_UT_MAGIC1] != 0xac || mem[OFFSET_UT_MAGIC2] != 0x02 || mem[OFFSET_UT_FEEDBACK] != local->sequence) { DEBUG(8, "ib-pcmcia: wait %02X %02X %02X %02X\n", mem[OFFSET_UT_MAGIC1], mem[OFFSET_UT_MAGIC2], mem[OFFSET_UT_FEEDBACK], local->sequence); return; } ib_net_addr(modem, mem + OFFSET_UT_ETHERNET); local->ifstate = IFSTATE_NORMAL; ib_pcmcia_normal(local);}/** * ib_pcmcia_poll - poll hardware according to protocol. * called under ib_lock * @_local: device private state. */static void ib_pcmcia_poll(void *_local){ struct ib_pcmcia_local_t *local = _local; switch (local->ifstate) { case IFSTATE_RESET: ib_pcmcia_reset(local); break; case IFSTATE_WAIT: ib_pcmcia_wait(local); break; case IFSTATE_NORMAL: ib_pcmcia_normal(local); break; }}/** * ib_pcmcia_open - open device. * called under ib_lock * @_local: device private state. */static int ib_pcmcia_open(void *_local){ struct ib_pcmcia_local_t *local = _local; struct ib_net_modem_t *modem = local->modem; unsigned char *mem = local->mem; DEBUG(9, "ib-pcmcia: +open\n"); mem[OFFSET_PC_STATUS] = (modem->pc_status |= STATUS_READY); mem[OFFSET_PC_PACKET] = modem->stats.tx_packets & 0xff; DEBUG(9, "ib-pcmcia: -open\n"); return 0;}/** * ib_pcmcia_rx_parse - * called under ib_lock * @_local: device private state. */static void ib_pcmcia_rx_parse(void *_local){ struct ib_pcmcia_local_t *local = _local; struct ib_net_modem_t *modem = local->modem; unsigned char *mem = local->mem; ib_net_ut_status(modem, mem[OFFSET_UT_STATUS]); mem[OFFSET_PC_STATUS] = modem->pc_status; mem[OFFSET_PC_PACKET] = modem->stats.tx_packets & 0xff;}/** * ib_pcmcia_close - close device; release in a momemt. * called under ib_lock * @_local: device private state. */static int ib_pcmcia_close(void *_local){ struct ib_pcmcia_local_t *local = _local; struct ib_net_modem_t *modem = local->modem; unsigned char *mem = local->mem; if (pcmcia_dev_present(local->dev)) { mem[OFFSET_PC_STATUS] = (modem->pc_status &= ~STATUS_READY); mem[OFFSET_PC_PACKET] = modem->stats.tx_packets & 0xff; } return 0;}/** * ib_pcmcia_net_driver - PCMCIA driver callback functions. */static struct ib_net_driver_t ib_pcmcia_net_driver = { .poll = ib_pcmcia_poll, .tx_timeout = NULL, .open = ib_pcmcia_open, .rx_parse = ib_pcmcia_rx_parse, .close = ib_pcmcia_close,};/** * ib_pcmcia_config - PCMCIA config. * @link: device state. */static int ib_pcmcia_config(struct pcmcia_device *link){ struct ib_pcmcia_local_t *local = link->priv; struct net_device *netdev; struct ib_net_modem_t *modem; struct tuple_t tuple; union cisparse_t parse; unsigned char buf[64]; int version; struct config_info_t conf; struct cistpl_cftable_entry_t *cfg; struct cistpl_cftable_entry_t dflt = { 0 }; struct win_req_t req; int err; tuple.DesiredTuple = CISTPL_MANFID; tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; err = pcmcia_get_first_tuple(link, &tuple); if (err) goto failed1; err = pcmcia_get_tuple_data(link, &tuple); if (err) goto failed1; err = pcmcia_parse_tuple(&tuple, &parse); if (err) goto failed1; version = parse.manfid.card; DEBUG(1, "ib-pcmcia: card version %d\n", version); tuple.DesiredTuple = CISTPL_CONFIG; tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; err = pcmcia_get_first_tuple(link, &tuple); if (err) goto failed1; err = pcmcia_get_tuple_data(link, &tuple); if (err) goto failed1; err = pcmcia_parse_tuple(&tuple, &parse); if (err) goto failed1; link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; //err = pcmcia_get_configuration_info(link, &conf); //if (err) // goto failed1; // NTJ: quick fix to get things working with 2.6.28. // will reorg code to use pcmcia_loop_config() conf.Vcc = link->socket->socket.Vcc; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; err = pcmcia_get_first_tuple(link, &tuple); if (err) goto failed1; while (1) { if (pcmcia_get_tuple_data(link, &tuple)) goto next_entry; if (pcmcia_parse_tuple(&tuple, &parse)) goto next_entry; cfg = &parse.cftable_entry; if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; if (cfg->index == 0) goto next_entry; link->conf.ConfigIndex = cfg->index; if (cfg->flags & CISTPL_CFTABLE_AUDIO) { link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status = CCSR_AUDIO_ENA; } if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) goto next_entry; } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) goto next_entry; } if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) link->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) link->conf.Vpp = dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; break;next_entry: err = pcmcia_get_next_tuple(link, &tuple); if (err) goto failed1; } err = pcmcia_request_configuration(link, &link->conf); if (err) { DEBUG(1, "ib-pcmcia: pcmcia_request_configuration failed\n"); goto failed1; } req.AccessSpeed = 0; req.Attributes = WIN_MEMORY_TYPE_CM | WIN_DATA_WIDTH_16 | WIN_ENABLE; req.Base = 0; req.Size = version < 2 ? 0x1000 : 0x2000; link->win = NULL; err = pcmcia_request_window(&link, &req, &link->win); if (err) { DEBUG(1, "ib-pcmcia: pcmcia_request_window failed\n"); goto failed2; } local->mem = (unsigned char*) ioremap(req.Base, req.Size); if (local->mem == NULL) { DEBUG(1, "ib-pcmcia: ioremap failed\n"); err = -EIO; goto failed3; } err = ib_net_register(&netdev); if (err) goto failed4; modem = netdev->priv; strcpy(local->node.dev_name, netdev->name); ib_net_addr(modem, local->mem + OFFSET_UT_ETHERNET); modem->driver = &ib_pcmcia_net_driver; modem->pdriver = local; local->modem = modem; local->ifstate = IFSTATE_RESET; local->nreset = 0; init_timer(&local->timer); local->timer.expires = jiffies + HZ / 4; local->timer.function = ib_pcmcia_timer; local->timer.data = (unsigned long) local; add_timer(&local->timer); local->node.major = local->node.minor = 0; local->node.next = NULL; return 0;failed4: iounmap(local->mem);failed3:failed2: pcmcia_disable_device(link);failed1: DEBUG(1, "ib-pcmcia: config failed\n"); return err;}/** * ib_pcmcia_probe - probe device. * @dev: device state. */static int ib_pcmcia_probe(struct pcmcia_device *link){ struct ib_pcmcia_local_t *local; local = kmalloc(sizeof(struct ib_pcmcia_local_t), GFP_KERNEL); if (local == NULL) return -ENOMEM; local->dev = link; link->priv = local; link->conf.Attributes = 0; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Status = 0; link->conf.Vpp = 0; init_timer(&local->release); local->release.function = &ib_pcmcia_release; local->release.data = (unsigned long) local; local->modem = NULL; return ib_pcmcia_config(link);}static struct pcmcia_device_id ib_pcmcia_table[] = { PCMCIA_DEVICE_MANF_CARD(0x02e3, 0x0001), PCMCIA_DEVICE_MANF_CARD(0x02e3, 0x0002), PCMCIA_DEVICE_PROD_ID12("Kyocera Corporation", "Access Card", 0xaba79a14, 0xd66618ce), PCMCIA_DEVICE_NULL,};MODULE_DEVICE_TABLE(pcmcia, ib_pcmcia_table);/** * ib_pcmcia_driver - PCMCIA driver struct. */static struct pcmcia_driver ib_pcmcia_driver = { .owner = THIS_MODULE, .drv = { .name = ib_pcmcia_dev_info, }, .probe = ib_pcmcia_probe, .remove = ib_pcmcia_detach, .id_table = ib_pcmcia_table,};/** * ib_pcmcia_init - ib-pcmcia module init. */static int __init ib_pcmcia_init(void){ if (io16) ib_pcmcia_blit = ib_pcmcia_blit16; else ib_pcmcia_blit = ib_pcmcia_blit32; pcmcia_register_driver(&ib_pcmcia_driver); return 0;}/** * ib_pcmcia_exit - ib-pcmcia module exit. */static void __exit ib_pcmcia_exit(void){ pcmcia_unregister_driver(&ib_pcmcia_driver);}module_init(ib_pcmcia_init);module_exit(ib_pcmcia_exit);MODULE_DESCRIPTION("iBurst compatible PCMCIA driver");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -