📄 ibmtr.c
字号:
if (time_after(jiffies, timeout)) { DPRINTK("Hardware timeout during initialization.\n"); kfree_s(ti, sizeof(struct tok_info)); return -ENODEV; } ti->sram=((__u32)readb(ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN)<<12); ti->global_int_enable=PIOaddr+ADAPTINTREL; ti->adapter_int_enable=PIOaddr+ADAPTINTREL; break; } if (ibmtr_debug_trace & TRC_INIT) { /* just report int */ DPRINTK("irq=%d",irq); if (ibmtr_debug_trace & TRC_INITV) { /* full chat in verbose only */ DPRINTK(", ti->mmio=%08X",ti->mmio); printk(", segment=%02X",segment); } printk(".\n"); } /* Get hw address of token ring card */#if !TR_NEWFORMAT DPRINTK("hw address: ");#endif j=0; for (i=0; i<0x18; i=i+2) { /* technical reference states to do this */ temp = 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 = readb(ti->mmio + AIPADAPTYPE); /* get Data Rate: F=4Mb, E=16Mb, D=4Mb & 16Mb ?? */ ti->data_rate = readb(ti->mmio + AIPDATARATE); /* Get Early Token Release support?: F=no, E=4Mb, D=16Mb, C=4&16Mb */ ti->token_release = readb(ti->mmio + AIPEARLYTOKEN); /* How much shared RAM is on adapter ? */ ti->avail_shared_ram = get_sram_size(ti); /* 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 = readb(ti->mmio + AIPSHRAMPAGE); /* Available DHB 4Mb size: F=2048, E=4096, D=4464 */ switch (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 (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<<((((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;#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: ti->page_mask=(ti->mapped_ram_size==32) ? 0xc0 : 0; ti->page_mask=(ti->mapped_ram_size==64) ? 0x80 : 0; DPRINTK("Dual size shared RAM page (code=0xC), don't support it!\n"); /* nb/dwm: I did this because RRR (3,2) bits are documented as R/O and I can't find how to select which page size Also, the above conditional statement sequence is invalid as page_mask will always be set by the second stmt */ kfree_s(ti, sizeof(struct tok_info)); return -ENODEV; break; default: DPRINTK("Unknown shared ram paging info %01X\n",ti->shared_ram_paging); kfree_s(ti, sizeof(struct tok_info)); return -ENODEV; break; } 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, ti->mapped_ram_size); ti->page_mask = 0; /* reset paging */ } else { ti->mapped_ram_size=ti->avail_shared_ram; DPRINTK("Shared RAM paging enabled. Page size : %uK\n", ((ti->page_mask^ 0xff)+1)>>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 = ((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_s(ti, sizeof(struct tok_info)); 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 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_s(ti, sizeof(struct tok_info)); return -ENODEV; } /*?? Now, allocate some of the PIO PORTs for this driver.. */ request_region(PIOaddr,IBMTR_IO_EXTENT,"ibmtr"); /* record PIOaddr range as busy */#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]);#endif /* Calculate the maximum DHB we can use */ switch (ti->mapped_ram_size) { 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, 4464); ti->rbuf_len4 = 520; ti->rbuf_cnt4 = 9; ti->dhb_size16mb = MIN(ti->dhb_size16mb, 4096); ti->rbuf_len16 = 1032; /* 1024 usable */ ti->rbuf_cnt16 = 4; break; case 64 : /* 32KB shared RAM */ ti->dhb_size4mb = MIN(ti->dhb_size4mb, 4464); ti->rbuf_len4 = 1032; ti->rbuf_cnt4 = 6; ti->dhb_size16mb = MIN(ti->dhb_size16mb, 10240); ti->rbuf_len16 = 1032; ti->rbuf_cnt16 = 10; break; case 127 : /* 63KB shared RAM */ ti->dhb_size4mb = MIN(ti->dhb_size4mb, 4464); ti->rbuf_len4 = 1032; ti->rbuf_cnt4 = 6; ti->dhb_size16mb = MIN(ti->dhb_size16mb, 16384); ti->rbuf_len16 = 1032; ti->rbuf_cnt16 = 16; break; case 128 : /* 64KB shared RAM */ ti->dhb_size4mb = MIN(ti->dhb_size4mb, 4464); ti->rbuf_len4 = 1032; ti->rbuf_cnt4 = 6; ti->dhb_size16mb = MIN(ti->dhb_size16mb, 17960); 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 */__initfunc(static unsigned char 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-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<<((readb(adapt_info->mmio+ ACA_OFFSET + ACA_RW + RRR_ODD)>>2)+4);}__initfunc(static int trdev_init(struct device *dev)){ struct tok_info *ti=(struct tok_info *)dev->priv; 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 = NULL; dev->change_mtu = ibmtr_change_mtu;#ifndef MODULE tr_setup(dev);#endif return 0;}static int tok_open(struct device *dev){ struct tok_info *ti=(struct tok_info *)dev->priv; /* init the spinlock */ ti->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; 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) { dev->tbusy=0; dev->interrupt=0; dev->start=1; /* NEED to see smem size *AND* reset high 512 bytes if needed */ MOD_INC_USE_COUNT; return 0; } else return -EAGAIN;}static int tok_close(struct device *dev){ struct tok_info *ti=(struct tok_info *) dev->priv; writeb(DIR_CLOSE_ADAPTER, ti->srb + offsetof(struct srb_close_adapter, command)); writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); ti->open_status=CLOSED; sleep_on(&ti->wait_for_tok_int); if (readb(ti->srb + offsetof(struct srb_close_adapter, ret_code))) DPRINTK("close adapter failed: %02X\n", (int)readb(ti->srb + offsetof(struct srb_close_adapter, ret_code))); dev->start = 0; 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 device *dev; 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)); /* Disable interrupts till processing is finished */ dev->interrupt=1; 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=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"); spin_unlock(&(ti->lock)); dev->interrupt = 0; return; } /* Check ISRP EVEN too. */ if ( readb (ti->mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN) == 0xFF) { DPRINTK("PCMCIA card removed.\n"); spin_unlock(&(ti->lock)); dev->interrupt = 0; return; }#endif if (status & ADAP_CHK_INT) { int i; __u32 check_reason; check_reason=ti->mmio + ntohs(readw(ti->sram + ACA_OFFSET + ACA_RW +WWCR_EVEN)); DPRINTK("Adapter check interrupt\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -