📄 aironet4500_card.c
字号:
int isa_ioaddr = 0;// int p; int card = 0; int i=0; if (! io[0] || ! irq[0]){ // printk(" Both irq and io params must be supplied for ISA mode !!!\n"); return -ENODEV; } printk(KERN_WARNING " Aironet ISA Card in non-PNP(ISA) mode sometimes feels bad on interrupt \n"); printk(KERN_WARNING " Use aironet4500_pnp if any problems(i.e. card malfunctioning). \n"); printk(KERN_WARNING " Note that this isa probe is not friendly... must give exact parameters \n"); while (irq[card] !=0){ isa_ioaddr = io[card]; isa_irq_line = irq[card]; request_region(isa_ioaddr, AIRONET4X00_IO_SIZE, "aironet4x00 ioaddr"); if (!dev) { dev = init_etherdev(dev, 0 ); } dev->priv = kmalloc(sizeof(struct awc_private),GFP_KERNEL ); memset(dev->priv,0,sizeof(struct awc_private)); if (!dev->priv) { printk(KERN_CRIT "aironet4x00: could not allocate device private, some unstability may follow\n"); return -1; }; // ether_setup(dev); // dev->tx_queue_len = tx_queue_len; dev->hard_start_xmit = &awc_start_xmit; // dev->set_config = &awc_config_misiganes,aga mitte awc_config; dev->get_stats = &awc_get_stats; // dev->set_multicast_list = &awc_set_multicast_list; dev->change_mtu = awc_change_mtu; dev->init = &awc_init; dev->open = &awc_open; dev->stop = &awc_close; dev->base_addr = isa_ioaddr; dev->irq = isa_irq_line; dev->tx_timeout = &awc_tx_timeout; dev->watchdog_timeo = AWC_TX_TIMEOUT; request_irq(dev->irq,awc_interrupt ,SA_INTERRUPT ,"Aironet 4X00",dev); awc_private_init( dev); if ( awc_init(dev) ){ printk("card not found at irq %x mem %x\n",irq[card],io[card]); if (card==0) return -1; break; } i=0; while (aironet4500_devices[i] && i < MAX_AWCS-1) i++; if (!aironet4500_devices[i]){ aironet4500_devices[i]=dev; ((struct awc_private *) aironet4500_devices[i]->priv)->card_type = AIRONET4500_ISA; if (awc_proc_set_fun) awc_proc_set_fun(i); } card++; } if (card == 0 ) { return -ENODEV; }; return 0;}#ifdef MODULEstatic void awc_isa_release(void) {// long flags; int i=0; DEBUG(0, "awc_detach \n"); i=0; while ( i < MAX_AWCS) { if (!aironet4500_devices[i]) {i++; continue;} if (((struct awc_private *)aironet4500_devices[i]->priv)->card_type != AIRONET4500_ISA) {i++; continue;} if (awc_proc_unset_fun) awc_proc_unset_fun(i); release_region(aironet4500_devices[i]->base_addr, AIRONET4X00_IO_SIZE);// release_region(isa_cisaddr, AIRONET4X00_CIS_SIZE, "aironet4x00 cis");// release_region(isa_memaddr, AIRONET4X00_MEM_SIZE, "aironet4x00 mem"); unregister_netdev(aironet4500_devices[i]); free_irq(aironet4500_devices[i]->irq,aironet4500_devices[i]); kfree(aironet4500_devices[i]->priv); kfree(aironet4500_devices[i]); aironet4500_devices[i]=0; i++; } } #endif //MODULE #endif /* CONFIG_AIRONET4500_ISA */#ifdef CONFIG_AIRONET4500_365 #define port_range 0x40int awc_i365_offset_ports[] = {0x3e0,0x3e0,0x3e2,0x3e2};int awc_i365_data_ports [] = {0x3e1,0x3e1,0x3e3,0x3e3};int awc_i365_irq[] = {5,5,11,12};int awc_i365_io[] = {0x140,0x100,0x400,0x440};int awc_i365_sockets = 0;struct i365_socket { int offset_port ; int data_port; int socket; int irq; int io; int manufacturer; int product;}; inline u8 i365_in (struct i365_socket * s, int offset) { outb(offset + (s->socket % 2)* 0x40, s->offset_port); return inb(s->data_port); };inline void i365_out (struct i365_socket * s, int offset,int data){ outb(offset + (s->socket % 2)* 0x40 ,s->offset_port); outb((data & 0xff),s->data_port) ; };void awc_i365_card_release(struct i365_socket * s){ i365_out(s, 0x5, 0); // clearing ints i365_out(s, 0x6, 0x20); // mem 16 bits i365_out(s, 0x7, 0); // clear IO i365_out(s, 0x3, 0); // gen ctrl reset + mem mode i365_out(s, 0x2, 0); // reset power i365_out(s, 0x2, i365_in(s, 0x2) & 0x7f ); // cardenable off i365_out(s, 0x2, 0); // remove power };int awc_i365_probe_once(struct i365_socket * s ){ int caps=i365_in(s, 0); int ret; unsigned long jiff;// short rev = 0x3000; unsigned char cis [0x3e3]; unsigned char * mem = phys_to_virt(0xd000); int i; int port ; DEBUG(1," i365 control ID %x \n", caps); if (caps & 0xC){ return 1; }; ret = i365_in(s, 0x1); if ((ret & 0xC0) != 0xC0){ printk("card in socket %d port %x not in known state, %x \n", s->socket, s->offset_port, ret ); return -1; }; awc_i365_card_release(s); udelay(100000); i365_out(s, 0x2, 0x10 ); // power enable udelay(200000); i365_out(s, 0x2, 0x10 | 0x01 | 0x04 | 0x80); //power enable udelay(250000); if (!s->irq) s->irq = 11; i365_out(s, 0x3, 0x40 | 0x20 | s->irq); jiff = jiffies; while (jiffies-jiff < HZ ) if (i365_in(s,0x1) & 0x20) break; if (! (i365_in(s,0x1) & 0x20) ){ printk("irq enable timeout on socket %x \n", s->socket); return -1; }; i365_out(s,0x10,0xd0); i365_out(s,0x11,0x0); i365_out(s,0x12,0xd0); i365_out(s,0x13,0x0); i365_out(s,0x14,0x30 ); i365_out(s,0x15,0x3f | 0x40); // enab mem reg bit i365_out(s,0x06,0x01); // enab mem udelay(10000); cis[0] = 0x45; // memcpy_toio( 0xd3e0, &(cis[0]),0x1);// mem[0x3e0] = 0x0;// mem[0] = 0x45; mem[0x3e0] = 0x45; udelay(10000); memcpy_fromio(cis,0xD000, 0x3e0); for (i = 0; i <= 0x3e2; i++) printk("%02x", mem[i]); for (i = 0; i <= 0x3e2; i++) printk("%c", mem[i]); i=0; while (i < 0x3e0){ if (cis[i] == 0xff) break; if (cis[i] != 0x20 ){ i = i + 2 + cis[i+1]; continue; }else { s->manufacturer = cis[i+2] | (cis[i+3]<<8); s->product = cis[i+4] | (cis[i+5]<<8); break; }; i++; }; DEBUG(1,"socket %x manufacturer %x product %x \n", s->socket, s->manufacturer,s->product); i365_out(s,0x07, 0x1 | 0x2); // enable io 16bit udelay(1000); port = s->io; i365_out(s,0x08, port & 0xff); i365_out(s,0x09, (port & 0xff00)/ 0x100); i365_out(s,0x0A, (port+port_range) & 0xff); i365_out(s,0x0B, ((port+port_range) & 0xff00) /0x100); i365_out(s,0x06, 0x40); // enable io window udelay(1000); i365_out(s,0x3e0,0x45); outw(0x10, s->io); jiff = jiffies; while (!(inw(s->io + 0x30) & 0x10)){ if (jiffies - jiff > HZ ){ printk("timed out waitin for command ack \n"); break; } }; outw(0x10, s->io + 0x34); udelay(10000); return 0; };static int awc_i365_init(struct i365_socket * s) { struct net_device * dev; int i; dev = init_etherdev(0, sizeof(struct awc_private) );// dev->tx_queue_len = tx_queue_len; ether_setup(dev); dev->hard_start_xmit = &awc_start_xmit;// dev->set_config = &awc_config_misiganes,aga mitte awc_config; dev->get_stats = &awc_get_stats; dev->set_multicast_list = &awc_set_multicast_list; dev->init = &awc_init; dev->open = &awc_open; dev->stop = &awc_close; dev->irq = s->irq; dev->base_addr = s->io; dev->tx_timeout = &awc_tx_timeout; dev->watchdog_timeo = AWC_TX_TIMEOUT; awc_private_init( dev); i=0; while (aironet4500_devices[i] && i < MAX_AWCS-1) i++; if (!aironet4500_devices[i]){ aironet4500_devices[i]=dev; ((struct awc_private *) aironet4500_devices[i]->priv)->card_type = AIRONET4500_365; if (awc_proc_set_fun) awc_proc_set_fun(i); } if (register_netdev(dev) != 0) { printk(KERN_NOTICE "awc_cs: register_netdev() failed\n"); goto failed; } return 0; failed: return -1;}static void awc_i365_release(void) {// long flags; int i=0; DEBUG(0, "awc_detach \n"); i=0; while ( i < MAX_AWCS) { if (!aironet4500_devices[i]) {i++; continue;} if (((struct awc_private *)aironet4500_devices[i]->priv)->card_type != AIRONET4500_365) {i++; continue;} if (awc_proc_unset_fun) awc_proc_unset_fun(i); unregister_netdev(aironet4500_devices[i]); //kfree(aironet4500_devices[i]->priv); kfree(aironet4500_devices[i]); aironet4500_devices[i]=0; i++; } } int awc_i365_probe(void) { int i = 1; int k = 0; int ret = 0; int found=0; struct i365_socket s; /* Always emit the version, before any failure. */ if (!awc_i365_sockets) { printk(" awc i82635 4x00: use bitfiel opts awc_i365_sockets=0x3 <- (1|2) to probe sockets 0 and 1\n"); return -1; }; while (k < 4){ if (i & awc_i365_sockets){ s.offset_port = awc_i365_offset_ports[k]; s.data_port = awc_i365_data_ports[k]; s.socket = k; s.manufacturer = 0; s.product = 0; s.irq = awc_i365_irq[k]; s.io = awc_i365_io[k]; ret = awc_i365_probe_once(&s); if (!ret){ if (awc_i365_init(&s)) goto failed; else found++; } else if (ret == -1) goto failed; }; k++; i *=2; }; if (!found){ printk("no aironet 4x00 cards found\n"); return -1; } return 0;failed: awc_i365_release(); return -1; }#endif /* CONFIG_AIRONET4500_365 */#ifdef MODULE int init_module(void){ int found = 0; printk("%s\n ", awc_version); #ifdef CONFIG_AIRONET4500_PCI if (awc4500_pci_probe(NULL) == -ENODEV){// printk("PCI 4X00 aironet cards not found\n"); } else { found++;// printk("PCI 4X00 found some cards \n"); }#endif#ifdef CONFIG_AIRONET4500_PNP if (awc4500_pnp_probe(NULL) == -ENODEV){// printk("PNP 4X00 aironet cards not found\n"); } else { found++;// printk("PNP 4X00 found some cards \n"); }#endif#ifdef CONFIG_AIRONET4500_365 if ( awc_i365_probe() == -1) {// printk("PCMCIA 4X00 aironet cards not found for i365(without card services) initialization\n"); } else { found++ ;// printk("PCMCIA 4X00 found some cards, take care, this code is not supposed to work yet \n"); }#endif#ifdef CONFIG_AIRONET4500_ISA if (awc4500_isa_probe(NULL) == -ENODEV){// printk("ISA 4X00 aironet ISA-bus non-PNP-mode cards not found\n"); } else { found++;// printk("ISA 4X00 found some cards \n"); }#endif if (!found) { printk(KERN_ERR "No Aironet 4X00 cards were found. Note that for ISA \n cards you should use either automatic PNP mode or \n ISA mode with both io and irq param \n Aironet is also afraid of: being second PNP controller(by slot), having anything(brandname bios weirdnesses) in range 0x100-0x180 and maybe around 0xd0000\n If you PNP type card does not get found, try non-PNP switch before complainig. \n"); return -1; } return 0; }void cleanup_module(void){ DEBUG(0, "awc_cs: unloading %c ",'\n');#ifdef CONFIG_AIRONET4500_PCI awc_pci_release();#endif#ifdef CONFIG_AIRONET4500_PNP awc_pnp_release();#endif#ifdef CONFIG_AIRONET4500_365 awc_i365_release();#endif#ifdef CONFIG_AIRONET4500_ISA awc_isa_release();#endif}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -