📄 ibmtr.c
字号:
dev->base_addr = PIOaddr; /* set the value for device */ dev->mem_start = ti->sram_base << 12; dev->mem_end = dev->mem_start + (ti->mapped_ram_size << 9) - 1; trdev_init(dev); return 0; /* Return 0 to indicate we have found a Token Ring card. */} /*ibmtr_probe1() *//*****************************************************************************//* query the adapter for the size of shared RAM *//* the function returns the RAM size in units of 512 bytes */static unsigned char __devinit 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&3)+4);}/*****************************************************************************/static int __devinit trdev_init(struct net_device *dev){ struct tok_info *ti = (struct tok_info *) dev->priv; SET_PAGE(ti->srb_page); ti->open_failure = NO ; 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; return 0;}/*****************************************************************************/static int tok_init_card(struct net_device *dev){ struct tok_info *ti; short PIOaddr; unsigned long i; PIOaddr = dev->base_addr; ti = (struct tok_info *) dev->priv; /* Special processing for first interrupt after reset */ ti->do_tok_int = FIRST_INT; /* Reset adapter */ writeb(~INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN); outb(0, PIOaddr + ADAPTRESET); schedule_timeout_uninterruptible(TR_RST_TIME); /* wait 50ms */ outb(0, PIOaddr + ADAPTRESETREL);#ifdef ENABLE_PAGING if (ti->page_mask) writeb(SRPR_ENABLE_PAGING,ti->mmio+ACA_OFFSET+ACA_RW+SRPR_EVEN);#endif writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); i = sleep_on_timeout(&ti->wait_for_reset, 4 * HZ); return i? 0 : -EAGAIN;}/*****************************************************************************/static int tok_open(struct net_device *dev){ struct tok_info *ti = (struct tok_info *) dev->priv; int i; /*the case we were left in a failure state during a previous open */ if (ti->open_failure == YES) { DPRINTK("Last time you were disconnected, how about now?\n"); printk("You can't insert with an ICS connector half-cocked.\n"); } ti->open_status = CLOSED; /* CLOSED or OPEN */ ti->sap_status = CLOSED; /* CLOSED or OPEN */ ti->open_failure = NO; /* NO or YES */ ti->open_mode = MANUAL; /* MANUAL or AUTOMATIC */ ti->sram_phys &= ~1; /* to reverse what we do in tok_close */ /* init the spinlock */ spin_lock_init(&ti->lock); init_timer(&ti->tr_timer); i = tok_init_card(dev); if (i) return i; while (1){ tok_open_adapter((unsigned long) dev); i= interruptible_sleep_on_timeout(&ti->wait_for_reset, 25 * HZ); /* sig catch: estimate opening adapter takes more than .5 sec*/ if (i>(245*HZ)/10) break; /* fancier than if (i==25*HZ) */ if (i==0) break; if (ti->open_status == OPEN && ti->sap_status==OPEN) { netif_start_queue(dev); DPRINTK("Adapter is up and running\n"); return 0; } i=schedule_timeout_interruptible(TR_RETRY_INTERVAL); /* wait 30 seconds */ if(i!=0) break; /*prob. a signal, like the i>24*HZ case above */ } outb(0, dev->base_addr + ADAPTRESET);/* kill pending interrupts*/ DPRINTK("TERMINATED via signal\n"); /*BMS useful */ return -EAGAIN;}/*****************************************************************************/#define COMMAND_OFST 0#define OPEN_OPTIONS_OFST 8#define NUM_RCV_BUF_OFST 24#define RCV_BUF_LEN_OFST 26#define DHB_LENGTH_OFST 28#define NUM_DHB_OFST 30#define DLC_MAX_SAP_OFST 32#define DLC_MAX_STA_OFST 33static void tok_open_adapter(unsigned long dev_addr){ struct net_device *dev = (struct net_device *) dev_addr; struct tok_info *ti; int i; ti = (struct tok_info *) dev->priv; SET_PAGE(ti->init_srb_page); writeb(~SRB_RESP_INT, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD); for (i = 0; i < sizeof(struct dir_open_adapter); i++) writeb(0, ti->init_srb + i); writeb(DIR_OPEN_ADAPTER, ti->init_srb + COMMAND_OFST); writew(htons(OPEN_PASS_BCON_MAC), ti->init_srb + OPEN_OPTIONS_OFST); if (ti->ring_speed == 16) { writew(htons(ti->dhb_size16mb), ti->init_srb + DHB_LENGTH_OFST); writew(htons(ti->rbuf_cnt16), ti->init_srb + NUM_RCV_BUF_OFST); writew(htons(ti->rbuf_len16), ti->init_srb + RCV_BUF_LEN_OFST); } else { writew(htons(ti->dhb_size4mb), ti->init_srb + DHB_LENGTH_OFST); writew(htons(ti->rbuf_cnt4), ti->init_srb + NUM_RCV_BUF_OFST); writew(htons(ti->rbuf_len4), ti->init_srb + RCV_BUF_LEN_OFST); } writeb(NUM_DHB, /* always 2 */ ti->init_srb + NUM_DHB_OFST); writeb(DLC_MAX_SAP, ti->init_srb + DLC_MAX_SAP_OFST); writeb(DLC_MAX_STA, ti->init_srb + DLC_MAX_STA_OFST); ti->srb = ti->init_srb; /* We use this one in the interrupt handler */ ti->srb_page = ti->init_srb_page; DPRINTK("Opening adapter: Xmit bfrs: %d X %d, Rcv bfrs: %d X %d\n", readb(ti->init_srb + NUM_DHB_OFST), ntohs(readw(ti->init_srb + DHB_LENGTH_OFST)), ntohs(readw(ti->init_srb + NUM_RCV_BUF_OFST)), ntohs(readw(ti->init_srb + RCV_BUF_LEN_OFST))); writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);}/*****************************************************************************/static void open_sap(unsigned char type, struct net_device *dev){ int i; struct tok_info *ti = (struct tok_info *) dev->priv; SET_PAGE(ti->srb_page); for (i = 0; i < sizeof(struct dlc_open_sap); i++) writeb(0, ti->srb + i);#define MAX_I_FIELD_OFST 14#define SAP_VALUE_OFST 16#define SAP_OPTIONS_OFST 17#define STATION_COUNT_OFST 18 writeb(DLC_OPEN_SAP, ti->srb + COMMAND_OFST); writew(htons(MAX_I_FIELD), ti->srb + MAX_I_FIELD_OFST); writeb(SAP_OPEN_IND_SAP | SAP_OPEN_PRIORITY, ti->srb+ SAP_OPTIONS_OFST); writeb(SAP_OPEN_STATION_CNT, ti->srb + STATION_COUNT_OFST); writeb(type, ti->srb + SAP_VALUE_OFST); writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);}/*****************************************************************************/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; /*BMS the next line is CRUCIAL or you may be sad when you */ /*BMS ifconfig tr down or hot unplug a PCMCIA card ??hownowbrowncow*/ if (/*BMSHELPdev->start == 0 ||*/ ti->open_status != OPEN) 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++) writeb(0, ti->srb + i);#define FUNCT_ADDRESS_OFST 6 writeb(DIR_SET_FUNC_ADDR, ti->srb + COMMAND_OFST); for (i = 0; i < 4; i++) writeb(address[i], ti->srb + FUNCT_ADDRESS_OFST + i); writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);#if TR_VERBOSE DPRINTK("Setting functional address: "); for (i=0;i<4;i++) printk("%02X ", address[i]); printk("\n");#endif}/*****************************************************************************/#define STATION_ID_OFST 4static int tok_send_packet(struct sk_buff *skb, struct net_device *dev){ struct tok_info *ti; unsigned long flags; ti = (struct tok_info *) dev->priv; netif_stop_queue(dev); /* lock against other CPUs */ spin_lock_irqsave(&(ti->lock), flags); /* Save skb; we'll need it when the adapter asks for the data */ ti->current_skb = skb; SET_PAGE(ti->srb_page); writeb(XMIT_UI_FRAME, ti->srb + COMMAND_OFST); writew(ti->exsap_station_id, ti->srb + STATION_ID_OFST); writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); spin_unlock_irqrestore(&(ti->lock), flags); dev->trans_start = jiffies; return 0;}/*****************************************************************************/static int tok_close(struct net_device *dev){ struct tok_info *ti = (struct tok_info *) dev->priv; /* Important for PCMCIA hot unplug, otherwise, we'll pull the card, */ /* unloading the module from memory, and then if a timer pops, ouch */ del_timer_sync(&ti->tr_timer); outb(0, dev->base_addr + ADAPTRESET); ti->sram_phys |= 1; ti->open_status = CLOSED; netif_stop_queue(dev); DPRINTK("Adapter is closed.\n"); return 0;}/*****************************************************************************/#define RETCODE_OFST 2#define OPEN_ERROR_CODE_OFST 6#define ASB_ADDRESS_OFST 8#define SRB_ADDRESS_OFST 10#define ARB_ADDRESS_OFST 12#define SSB_ADDRESS_OFST 14static char *printphase[]= {"Lobe media test","Physical insertion", "Address verification","Roll call poll","Request Parameters"};static char *printerror[]={"Function failure","Signal loss","Reserved", "Frequency error","Timeout","Ring failure","Ring beaconing", "Duplicate node address", "Parameter request-retry count exceeded","Remove received", "IMPL force received","Duplicate modifier", "No monitor detected","Monitor contention failed for RPL"};static void __iomem *map_address(struct tok_info *ti, unsigned index, __u8 *page){ if (ti->page_mask) { *page = (index >> 8) & ti->page_mask; index &= ~(ti->page_mask << 8); } return ti->sram_virt + index;}static void dir_open_adapter (struct net_device *dev){ struct tok_info *ti = (struct tok_info *) dev->priv; unsigned char ret_code; __u16 err; ti->srb = map_address(ti, ntohs(readw(ti->init_srb + SRB_ADDRESS_OFST)), &ti->srb_page); ti->ssb = map_address(ti, ntohs(readw(ti->init_srb + SSB_ADDRESS_OFST)), &ti->ssb_page); ti->arb = map_address(ti, ntohs(readw(ti->init_srb + ARB_ADDRESS_OFST)), &ti->arb_page); ti->asb = map_address(ti, ntohs(readw(ti->init_srb + ASB_ADDRESS_OFST)), &ti->asb_page); ti->current_skb = NULL; ret_code = readb(ti->init_srb + RETCODE_OFST); err = ntohs(readw(ti->init_srb + OPEN_ERROR_CODE_OFST)); if (!ret_code) { ti->open_status = OPEN; /* TR adapter is now available */ if (ti->open_mode == AUTOMATIC) { DPRINTK("Adapter reopened.\n"); } writeb(~SRB_RESP_INT, ti->mmio+ACA_OFFSET+ACA_RESET+ISRP_ODD); open_sap(EXTENDED_SAP, dev); return; } ti->open_failure = YES; if (ret_code == 7){ if (err == 0x24) { if (!ti->auto_speedsave) { DPRINTK("Open failed: Adapter speed must match " "ring speed if Automatic Ring Speed Save is " "disabled.\n"); ti->open_action = FAIL; }else DPRINTK("Retrying open to adjust to " "ring speed, "); } else if (err == 0x2d) { DPRINTK("Physical Insertion: No Monitor Detected, "); printk("retrying after %ds delay...\n", TR_RETRY_INTERVAL/HZ); } else if (err == 0x11) { DPRINTK("Lobe Media Function Failure (0x11), "); printk(" retrying after %ds delay...\n", TR_RETRY_INTERVAL/HZ); } else { char **prphase = printphase; char **prerror = printerror; DPRINTK("TR Adapter misc open failure, error code = "); printk("0x%x, Phase: %s, Error: %s\n", err, prphase[err/16 -1], prerror[err%16 -1]); printk(" retrying after %ds delay...\n", TR_RETRY_INTERVAL/HZ); } } else DPRINTK("open failed: ret_code = %02X..., ", ret_code); if (ti->open_action != FAIL) { if (ti->open_mode==AUTOMATIC){ ti->open_action = REOPEN; ibmtr_reset_timer(&(ti->tr_timer), dev); return; } wake_up(&ti->wait_for_reset); return; } DPRINTK("FAILURE, CAPUT\n");}/******************************************************************************/static irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs){ unsigned char status; /* unsigned char status_even ; */ 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 irq%d regs=%p\n", dev,irq,regs);#endif ti = (struct tok_info *) dev->priv; if (ti->sram_phys & 1) return IRQ_NONE; /* PCMCIA card extraction flag */ spin_lock(&(ti->lock));#ifdef ENABLE_PAGING save_srpr = readb(ti->mmio + ACA_OFFSET + ACA_RW + SRPR_EVEN);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -