📄 ibmtr.c
字号:
DPRINTK("hw address: ");#endif j=0; for (i=0; i<0x18; i=i+2) { /* technical reference states to do this */ temp = isa_readb(ti->mmio + AIP + i) & 0x0f;#if !TR_NEWFORMAT printk("%1X",ti->hw_address[j]=temp);#else ti->hw_address[j]=temp;#endif if(j&1) dev->dev_addr[(j/2)]=ti->hw_address[j]+(ti->hw_address[j-1]<<4); ++j; }#ifndef TR_NEWFORMAT printk("\n");#endif /* get Adapter type: 'F' = Adapter/A, 'E' = 16/4 Adapter II,...*/ ti->adapter_type = isa_readb(ti->mmio + AIPADAPTYPE); /* get Data Rate: F=4Mb, E=16Mb, D=4Mb & 16Mb ?? */ ti->data_rate = isa_readb(ti->mmio + AIPDATARATE); /* Get Early Token Release support?: F=no, E=4Mb, D=16Mb, C=4&16Mb */ ti->token_release = isa_readb(ti->mmio + AIPEARLYTOKEN); /* How much shared RAM is on adapter ? */#ifdef PCMCIA ti->avail_shared_ram = pcmcia_reality_check(get_sram_size(ti)); ibmtr_mem_base = ti->sram_base << 12 ; #else ti->avail_shared_ram = get_sram_size(ti);#endif /* We need to set or do a bunch of work here based on previous results.. */ /* Support paging? What sizes?: F=no, E=16k, D=32k, C=16 & 32k */ ti->shared_ram_paging = isa_readb(ti->mmio + AIPSHRAMPAGE); /* Available DHB 4Mb size: F=2048, E=4096, D=4464 */ switch (isa_readb(ti->mmio + AIP4MBDHB)) { case 0xe : ti->dhb_size4mb = 4096; break; case 0xd : ti->dhb_size4mb = 4464; break; default : ti->dhb_size4mb = 2048; break; } /* Available DHB 16Mb size: F=2048, E=4096, D=8192, C=16384, B=17960 */ switch (isa_readb(ti->mmio + AIP16MBDHB)) { case 0xe : ti->dhb_size16mb = 4096; break; case 0xd : ti->dhb_size16mb = 8192; break; case 0xc : ti->dhb_size16mb = 16384; break; case 0xb : ti->dhb_size16mb = 17960; break; default : ti->dhb_size16mb = 2048; break; }#if !TR_NEWFORMAT DPRINTK("atype=%x, drate=%x, trel=%x, asram=%dK, srp=%x, " "dhb(4mb=%x, 16mb=%x)\n",ti->adapter_type, ti->data_rate, ti->token_release, ti->avail_shared_ram/2, ti->shared_ram_paging, ti->dhb_size4mb, ti->dhb_size16mb);#endif /* We must figure out how much shared memory space this adapter * will occupy so that if there are two adapters we can fit both * in. Given a choice, we will limit this adapter to 32K. The * maximum space will will use for two adapters is 64K so if the * adapter we are working on demands 64K (it also doesn't support * paging), then only one adapter can be supported. */ /* * determine how much of total RAM is mapped into PC space */ ti->mapped_ram_size=1<<((((isa_readb(ti->mmio+ ACA_OFFSET + ACA_RW + RRR_ODD)) >>2) & 0x03) + 4); ti->page_mask=0; if (ti->shared_ram_paging == 0xf) { /* No paging in adapter */ ti->mapped_ram_size = ti->avail_shared_ram; } else {#ifdef ENABLE_PAGING unsigned char pg_size=0;#endif#if !TR_NEWFORMAT DPRINTK("shared ram page size: %dK\n",ti->mapped_ram_size/2);#endif#ifdef ENABLE_PAGING switch(ti->shared_ram_paging) { case 0xf: break; case 0xe: ti->page_mask=(ti->mapped_ram_size==32) ? 0xc0 : 0; pg_size=32; /* 16KB page size */ break; case 0xd: ti->page_mask=(ti->mapped_ram_size==64) ? 0x80 : 0; pg_size=64; /* 32KB page size */ break; case 0xc: switch (ti->mapped_ram_size) { case 32: ti->page_mask=0xc0; pg_size=32; break; case 64: ti->page_mask=0x80; pg_size=64; break; } break; default: DPRINTK("Unknown shared ram paging info %01X\n",ti->shared_ram_paging); kfree(ti); return -ENODEV; break; } if (ibmtr_debug_trace & TRC_INIT) DPRINTK("Shared RAM paging code: " "%02X mapped RAM size: %dK shared RAM size: %dK page mask: %0xX\n:", ti->shared_ram_paging, ti->mapped_ram_size/2, ti->avail_shared_ram/2, ti->page_mask); if (ti->page_mask) { if (pg_size > ti->mapped_ram_size) { DPRINTK("Page size (%d) > mapped ram window (%d), can't page.\n", pg_size/2, ti->mapped_ram_size/2); ti->page_mask = 0; /* reset paging */ } } else if (pg_size > ti->mapped_ram_size) { DPRINTK("Page size (%d) > mapped ram window (%d), can't page.\n", pg_size/2, ti->mapped_ram_size/2); }#endif } /* finish figuring the shared RAM address */ if (cardpresent==TR_ISA) { static __u32 ram_bndry_mask[]={0xffffe000, 0xffffc000, 0xffff8000, 0xffff0000}; __u32 new_base, rrr_32, chk_base, rbm; rrr_32 = ((isa_readb(ti->mmio+ ACA_OFFSET + ACA_RW + RRR_ODD))>>2) & 0x00000003; rbm = ram_bndry_mask[rrr_32]; new_base = (ibmtr_mem_base + (~rbm)) & rbm; /* up to boundary */ chk_base = new_base + (ti->mapped_ram_size<<9); if (chk_base > (ibmtr_mem_base + IBMTR_SHARED_RAM_SIZE)) { DPRINTK("Shared RAM for this adapter (%05x) exceeds driver" " limit (%05x), adapter not started.\n", chk_base, ibmtr_mem_base + IBMTR_SHARED_RAM_SIZE); kfree(ti); return -ENODEV; } else { /* seems cool, record what we have figured out */ ti->sram_base = new_base >> 12; ibmtr_mem_base = chk_base; } }#if !TR_NEWFORMAT DPRINTK("Using %dK shared RAM\n",ti->mapped_ram_size/2);#endif /* The PCMCIA has already got the interrupt line and the io port, so no chance of anybody else getting it - MLP */#ifndef PCMCIA if (request_irq (dev->irq = irq, &tok_interrupt,0,"ibmtr", dev) != 0) { DPRINTK("Could not grab irq %d. Halting Token Ring driver.\n",irq); kfree(ti); return -ENODEV; } /*?? Now, allocate some of the PIO PORTs for this driver.. */ request_region(PIOaddr,IBMTR_IO_EXTENT,"ibmtr"); /* record PIOaddr range as busy */#endif#if !TR_NEWFORMAT DPRINTK("%s",version); /* As we have passed card identification, let the world know we're here! */#else if (version) { printk("%s",version); version = NULL; } DPRINTK("%s %s found\n", channel_def[cardpresent-1], adapter_def(ti->adapter_type)); DPRINTK("using irq %d, PIOaddr %hx, %dK shared RAM.\n", irq, PIOaddr, ti->mapped_ram_size/2); DPRINTK("Hardware address : %02X:%02X:%02X:%02X:%02X:%02X\n", dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); if (ti->page_mask) DPRINTK("Shared RAM paging enabled. Page size: %uK Shared Ram size %dK\n", ((ti->page_mask ^ 0xff)+1)>>2,ti->avail_shared_ram/2); else DPRINTK("Shared RAM paging disabled. ti->page_mask %x\n",ti->page_mask);#endif /* Calculate the maximum DHB we can use */ if (!ti->page_mask) { ti->avail_shared_ram=ti->mapped_ram_size; } switch (ti->avail_shared_ram) { case 16 : /* 8KB shared RAM */ ti->dhb_size4mb = MIN(ti->dhb_size4mb, 2048); ti->rbuf_len4 = 1032; ti->rbuf_cnt4 = 2; ti->dhb_size16mb = MIN(ti->dhb_size16mb, 2048); ti->rbuf_len16 = 1032; ti->rbuf_cnt16 = 2; break; case 32 : /* 16KB shared RAM */ ti->dhb_size4mb = MIN(ti->dhb_size4mb, 2048); ti->rbuf_len4 = 520; ti->rbuf_cnt4 = 9; ti->dhb_size16mb = MIN(ti->dhb_size16mb, 2048); ti->rbuf_len16 = 1032; /* 1024 usable */ ti->rbuf_cnt16 = 4; break; case 64 : /* 32KB shared RAM */ ti->dhb_size4mb = MIN(ti->dhb_size4mb, 2048); ti->rbuf_len4 = 1032; ti->rbuf_cnt4 = 6; ti->dhb_size16mb = MIN(ti->dhb_size16mb, 2048); ti->rbuf_len16 = 1032; ti->rbuf_cnt16 = 10; break; case 127 : /* 63KB shared RAM */ ti->dhb_size4mb = MIN(ti->dhb_size4mb, 2048); ti->rbuf_len4 = 1032; ti->rbuf_cnt4 = 6; ti->dhb_size16mb = MIN(ti->dhb_size16mb, 2048); ti->rbuf_len16 = 1032; ti->rbuf_cnt16 = 16; break; case 128 : /* 64KB shared RAM */ ti->dhb_size4mb = MIN(ti->dhb_size4mb, 2048); ti->rbuf_len4 = 1032; ti->rbuf_cnt4 = 6; ti->dhb_size16mb = MIN(ti->dhb_size16mb, 2048); ti->rbuf_len16 = 1032; ti->rbuf_cnt16 = 18; break; default : ti->dhb_size4mb = 2048; ti->rbuf_len4 = 1032; ti->rbuf_cnt4 = 2; ti->dhb_size16mb = 2048; ti->rbuf_len16 = 1032; ti->rbuf_cnt16 = 2; break; } ti->maxmtu16 = (ti->rbuf_len16*ti->rbuf_cnt16)-((ti->rbuf_cnt16)<<3)-TR_HLEN; ti->maxmtu4 = (ti->rbuf_len4*ti->rbuf_cnt4)-((ti->rbuf_cnt4)<<3)-TR_HLEN; DPRINTK("Maximum MTU 16Mbps: %d, 4Mbps: %d\n", ti->maxmtu16, ti->maxmtu4); dev->base_addr=PIOaddr; /* set the value for device */ trdev_init(dev); tok_init_card(dev); return 0; /* Return 0 to indicate we have found a Token Ring card. */}/* query the adapter for the size of shared RAM */static unsigned char __init get_sram_size(struct tok_info *adapt_info){ unsigned char avail_sram_code; static unsigned char size_code[]={ 0,16,32,64,127,128 }; /* Adapter gives 'F' -- use RRR bits 3,2 'E' -- 8kb 'D' -- 16kb 'C' -- 32kb 'A' -- 64KB 'B' - 64KB less 512 bytes at top (WARNING ... must zero top bytes in INIT */ avail_sram_code=0xf-isa_readb(adapt_info->mmio + AIPAVAILSHRAM); if (avail_sram_code) return size_code[avail_sram_code]; else /* for code 'F', must compute size from RRR(3,2) bits */ return 1<<((isa_readb(adapt_info->mmio+ ACA_OFFSET + ACA_RW + RRR_ODD)>>2)+4);}static int __init trdev_init(struct net_device *dev){ struct tok_info *ti=(struct tok_info *)dev->priv; /* init the spinlock */ spin_lock_init(&ti->lock); SET_PAGE(ti->srb_page); ti->open_status = CLOSED; dev->init = tok_init_card; dev->open = tok_open; dev->stop = tok_close; dev->hard_start_xmit = tok_send_packet; dev->get_stats = tok_get_stats; dev->set_multicast_list = tok_set_multicast_list; dev->change_mtu = ibmtr_change_mtu;#ifndef MODULE#ifndef PCMCIA tr_setup(dev);#endif#endif return 0;}static void tok_set_multicast_list(struct net_device *dev){ struct tok_info *ti=(struct tok_info *)dev->priv; struct dev_mc_list *mclist; unsigned char address[4]; int i; if(ti->open_status==CLOSED) return; address[0] = address[1] = address[2] = address[3] = 0; mclist = dev->mc_list; for (i=0; i< dev->mc_count; i++) { address[0] |= mclist->dmi_addr[2]; address[1] |= mclist->dmi_addr[3]; address[2] |= mclist->dmi_addr[4]; address[3] |= mclist->dmi_addr[5]; mclist = mclist->next; } SET_PAGE(ti->srb_page); for (i=0; i<sizeof(struct srb_set_funct_addr); i++) isa_writeb(0, ti->srb+i); isa_writeb(DIR_SET_FUNC_ADDR, ti->srb + offsetof(struct srb_set_funct_addr, command)); DPRINTK("Setting functional address: "); for (i=0; i<4; i++) { isa_writeb(address[i], ti->srb + offsetof(struct srb_set_funct_addr, funct_address)+i); printk("%02X ", address[i]); } isa_writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); printk("\n");}static int tok_open(struct net_device *dev){ struct tok_info *ti=(struct tok_info *)dev->priv; if (ti->open_status==CLOSED) tok_init_card(dev); if (ti->open_status==IN_PROGRESS) sleep_on(&ti->wait_for_reset); if (ti->open_status==SUCCESS) { /* NEED to see smem size *AND* reset high 512 bytes if needed */ netif_start_queue(dev); MOD_INC_USE_COUNT; return 0; } else return -EAGAIN;}static int tok_close(struct net_device *dev){ struct tok_info *ti=(struct tok_info *) dev->priv; if(ti->open_status!=CLOSED) { netif_stop_queue(dev); SET_PAGE(ti->srb_page); isa_writeb(DIR_CLOSE_ADAPTER, ti->srb + offsetof(struct srb_close_adapter, command)); isa_writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); ti->open_status=CLOSED; sleep_on(&ti->wait_for_tok_int); SET_PAGE(ti->srb_page); if (isa_readb(ti->srb + offsetof(struct srb_close_adapter, ret_code))) DPRINTK("close adapter failed: %02X\n", (int)isa_readb(ti->srb + offsetof(struct srb_close_adapter, ret_code)));#ifdef PCMCIA ti->sram = 0 ;#endif DPRINTK("Adapter closed.\n"); MOD_DEC_USE_COUNT; } return 0;}void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs){ unsigned char status; struct tok_info *ti; struct net_device *dev;#ifdef ENABLE_PAGING unsigned char save_srpr;#endif dev = dev_id;#if TR_VERBOSE DPRINTK("Int from tok_driver, dev : %p\n",dev);#endif ti = (struct tok_info *) dev->priv; spin_lock(&(ti->lock));#ifdef ENABLE_PAGING save_srpr=isa_readb(ti->mmio+ACA_OFFSET+ACA_RW+SRPR_EVEN);#endif /* Disable interrupts till processing is finished */ isa_writeb((~INT_ENABLE), ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN); /* Reset interrupt for ISA boards */ if (ti->adapter_int_enable) outb(0,ti->adapter_int_enable); else outb(0,ti->global_int_enable); switch (ti->do_tok_int) { case NOT_FIRST: /* Begin the regular interrupt handler HERE inline to avoid the extra levels of logic and call depth for the original solution. */ status=isa_readb(ti->mmio + ACA_OFFSET + ACA_RW + ISRP_ODD);#ifdef PCMCIA /* Check if the PCMCIA card was pulled. */ if (status == 0xFF) { DPRINTK("PCMCIA card removed.\n"); ti->open_status=CLOSED; goto return_point ; } /* Check ISRP EVEN too. */ if ( isa_readb (ti->mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN) == 0xFF) { DPRINTK("PCMCIA card removed.\n"); ti->open_status=CLOSED; goto return_point ; }#endif if (status & ADAP_CHK_INT) { int i; __u32 check_reason; __u8 check_reason_page=0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -