📄 xirc2ps_cs.c
字号:
switch(parse.manfid.manf) { case MANFID_XIRCOM: local->manf_str = "Xircom"; break; case MANFID_ACCTON: local->manf_str = "Accton"; break; case MANFID_COMPAQ: case MANFID_COMPAQ2: local->manf_str = "Compaq"; break; case MANFID_INTEL: local->manf_str = "Intel"; break; case MANFID_TOSHIBA: local->manf_str = "Toshiba"; break; default: printk(KNOT_XIRC "Unknown Card Manufacturer ID: 0x%04x\n", (unsigned)parse.manfid.manf); goto failure; } DEBUG(0, "found %s card\n", local->manf_str); if (!set_card_type(link, buf)) { printk(KNOT_XIRC "this card is not supported\n"); goto failure; } /* get configuration stuff */ tuple.DesiredTuple = CISTPL_CONFIG; if ((err=first_tuple(handle, &tuple, &parse))) goto cis_error; link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; /* get the ethernet address from the CIS */ tuple.DesiredTuple = CISTPL_FUNCE; for (err = first_tuple(handle, &tuple, &parse); !err; err = next_tuple(handle, &tuple, &parse)) { /* Once I saw two CISTPL_FUNCE_LAN_NODE_ID entries: * the first one with a length of zero the second correct - * so I skip all entries with length 0 */ if (parse.funce.type == CISTPL_FUNCE_LAN_NODE_ID && ((cistpl_lan_node_id_t *)parse.funce.data)->nb) break; } if (err) { /* not found: try to get the node-id from tuple 0x89 */ tuple.DesiredTuple = 0x89; /* data layout looks like tuple 0x22 */ if ((err = pcmcia_get_first_tuple(handle, &tuple)) == 0 && (err = pcmcia_get_tuple_data(handle, &tuple)) == 0) { if (tuple.TupleDataLen == 8 && *buf == CISTPL_FUNCE_LAN_NODE_ID) memcpy(&parse, buf, 8); else err = -1; } } if (err) { /* another try (James Lehmer's CE2 version 4.1)*/ tuple.DesiredTuple = CISTPL_FUNCE; for (err = first_tuple(handle, &tuple, &parse); !err; err = next_tuple(handle, &tuple, &parse)) { if (parse.funce.type == 0x02 && parse.funce.data[0] == 1 && parse.funce.data[1] == 6 && tuple.TupleDataLen == 13) { buf[1] = 4; memcpy(&parse, buf+1, 8); break; } } } if (err) { printk(KNOT_XIRC "node-id not found in CIS\n"); goto failure; } node_id = (cistpl_lan_node_id_t *)parse.funce.data; if (node_id->nb != 6) { printk(KNOT_XIRC "malformed node-id in CIS\n"); goto failure; } for (i=0; i < 6; i++) dev->dev_addr[i] = node_id->id[i]; /* Configure card */ link->state |= DEV_CONFIG; link->io.IOAddrLines =10; link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; link->irq.Attributes = IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_LEVEL_ID; if (local->modem) { int pass; if (do_sound) { link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status |= CCSR_AUDIO_ENA; } link->irq.Attributes |= IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED ; link->io.NumPorts2 = 8; link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; if (local->dingo) { /* Take the Modem IO port from the CIS and scan for a free * Ethernet port */ link->io.NumPorts1 = 16; /* no Mako stuff anymore */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; for (err = first_tuple(handle, &tuple, &parse); !err; err = next_tuple(handle, &tuple, &parse)) { if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) { for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { link->conf.ConfigIndex = cf->index ; link->io.BasePort2 = cf->io.win[0].base; link->io.BasePort1 = ioaddr; if (!(err=pcmcia_request_io(link->handle, &link->io))) goto port_found; } } } } else { link->io.NumPorts1 = 18; /* We do 2 passes here: The first one uses the regular mapping and * the second tries again, thereby considering that the 32 ports are * mirrored every 32 bytes. Actually we use a mirrored port for * the Mako if (on the first pass) the COR bit 5 is set. */ for (pass=0; pass < 2; pass++) { tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; for (err = first_tuple(handle, &tuple, &parse); !err; err = next_tuple(handle, &tuple, &parse)){ if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8){ link->conf.ConfigIndex = cf->index ; link->io.BasePort2 = cf->io.win[0].base; link->io.BasePort1 = link->io.BasePort2 + (pass ? (cf->index & 0x20 ? -24:8) : (cf->index & 0x20 ? 8:-24)); if (!(err=pcmcia_request_io(link->handle, &link->io))) goto port_found; } } } /* if special option: * try to configure as Ethernet only. * .... */ } printk(KNOT_XIRC "no ports available\n"); } else { link->irq.Attributes |= IRQ_TYPE_EXCLUSIVE; link->io.NumPorts1 = 16; for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { link->io.BasePort1 = ioaddr; if (!(err=pcmcia_request_io(link->handle, &link->io))) goto port_found; } link->io.BasePort1 = 0; /* let CS decide */ if ((err=pcmcia_request_io(link->handle, &link->io))) { cs_error(link->handle, RequestIO, err); goto config_error; } } port_found: if (err) goto config_error; /**************** * Now allocate an interrupt line. Note that this does not * actually assign a handler to the interrupt. */ if ((err=pcmcia_request_irq(link->handle, &link->irq))) { cs_error(link->handle, RequestIRQ, err); goto config_error; } /**************** * This actually configures the PCMCIA socket -- setting up * the I/O windows and the interrupt mapping. */ if ((err=pcmcia_request_configuration(link->handle, &link->conf))) { cs_error(link->handle, RequestConfiguration, err); goto config_error; } if (local->dingo) { conf_reg_t reg; win_req_t req; memreq_t mem; /* Reset the modem's BAR to the correct value * This is necessary because in the RequestConfiguration call, * the base address of the ethernet port (BasePort1) is written * to the BAR registers of the modem. */ reg.Action = CS_WRITE; reg.Offset = CISREG_IOBASE_0; reg.Value = link->io.BasePort2 & 0xff; if ((err = pcmcia_access_configuration_register(link->handle, ®))) { cs_error(link->handle, AccessConfigurationRegister, err); goto config_error; } reg.Action = CS_WRITE; reg.Offset = CISREG_IOBASE_1; reg.Value = (link->io.BasePort2 >> 8) & 0xff; if ((err = pcmcia_access_configuration_register(link->handle, ®))) { cs_error(link->handle, AccessConfigurationRegister, err); goto config_error; } /* There is no config entry for the Ethernet part which * is at 0x0800. So we allocate a window into the attribute * memory and write direct to the CIS registers */ req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; req.Base = req.Size = 0; req.AccessSpeed = 0; if ((err = pcmcia_request_window(&link->handle, &req, &link->win))) { cs_error(link->handle, RequestWindow, err); goto config_error; } local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800; mem.CardOffset = 0x0; mem.Page = 0; if ((err = pcmcia_map_mem_page(link->win, &mem))) { cs_error(link->handle, MapMemPage, err); goto config_error; } /* Setup the CCRs; there are no infos in the CIS about the Ethernet * part. */ writeb(0x47, local->dingo_ccr + CISREG_COR); ioaddr = link->io.BasePort1; writeb(ioaddr & 0xff , local->dingo_ccr + CISREG_IOBASE_0); writeb((ioaddr >> 8)&0xff , local->dingo_ccr + CISREG_IOBASE_1); #if 0 { u_char tmp; printk(KERN_INFO "ECOR:"); for (i=0; i < 7; i++) { tmp = readb(local->dingo_ccr + i*2); printk(" %02x", tmp); } printk("\n"); printk(KERN_INFO "DCOR:"); for (i=0; i < 4; i++) { tmp = readb(local->dingo_ccr + 0x20 + i*2); printk(" %02x", tmp); } printk("\n"); printk(KERN_INFO "SCOR:"); for (i=0; i < 10; i++) { tmp = readb(local->dingo_ccr + 0x40 + i*2); printk(" %02x", tmp); } printk("\n"); } #endif writeb(0x01, local->dingo_ccr + 0x20); writeb(0x0c, local->dingo_ccr + 0x22); writeb(0x00, local->dingo_ccr + 0x24); writeb(0x00, local->dingo_ccr + 0x26); writeb(0x00, local->dingo_ccr + 0x28); } /* The if_port symbol can be set when the module is loaded */ local->probe_port=0; if (!if_port) { local->probe_port = dev->if_port = 1; } else if ((if_port >= 1 && if_port <= 2) || (local->mohawk && if_port==4)) dev->if_port = if_port; else printk(KNOT_XIRC "invalid if_port requested\n"); /* we can now register the device with the net subsystem */ dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; if (local->dingo) do_reset(dev, 1); /* a kludge to make the cem56 work */ link->dev = &local->node; link->state &= ~DEV_CONFIG_PENDING; SET_NETDEV_DEV(dev, &handle_to_dev(handle)); if ((err=register_netdev(dev))) { printk(KNOT_XIRC "register_netdev() failed\n"); link->dev = NULL; goto config_error; } strcpy(local->node.dev_name, dev->name); /* give some infos about the hardware */ printk(KERN_INFO "%s: %s: port %#3lx, irq %d, hwaddr", dev->name, local->manf_str,(u_long)dev->base_addr, (int)dev->irq); for (i = 0; i < 6; i++) printk("%c%02X", i?':':' ', dev->dev_addr[i]); printk("\n"); return; config_error: link->state &= ~DEV_CONFIG_PENDING; xirc2ps_release(link); return; cis_error: printk(KNOT_XIRC "unable to parse CIS\n"); failure: link->state &= ~DEV_CONFIG_PENDING;} /* xirc2ps_config *//**************** * After a card is removed, xirc2ps_release() will unregister the net * device, and release the PCMCIA configuration. If the device is * still open, this will be postponed until it is closed. */static voidxirc2ps_release(dev_link_t *link){ DEBUG(0, "release(0x%p)\n", link); if (link->win) { struct net_device *dev = link->priv; local_info_t *local = netdev_priv(dev); if (local->dingo) iounmap(local->dingo_ccr - 0x0800); 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;} /* xirc2ps_release *//*====================================================================*//**************** * The card status event handler. Mostly, this schedules other * stuff to run after an event is received. A CARD_REMOVAL event * also sets some flags to discourage the net drivers from trying * to talk to the card any more. * * When a CARD_REMOVAL event is received, we immediately set a flag * to block future accesses to this device. All the functions that * actually access the device should check this flag to make sure * the card is still present. */static intxirc2ps_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(0, "event(%d)\n", (int)event); switch (event) { case CS_EVENT_REGISTRATION_COMPLETE: DEBUG(0, "registration complete\n"); break; 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; xirc2ps_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); do_powerdown(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) { do_reset(dev,1); netif_device_attach(dev); } } break; } return 0;} /* xirc2ps_event *//*====================================================================*//**************** * This is the Interrupt service route. */static irqreturn_txirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs){ struct net_device *dev = (struct net_device *)dev_id; local_info_t *lp = netdev_priv(dev); kio_addr_t ioaddr; u_char saved_page;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -