📄 ibmtr.c
字号:
DPRINTK("8 reason bytes follow: "); for(i=0; i<8; i++, check_reason++) printk("%02X ", (int)readb(check_reason)); printk("\n"); writeb((~ADAP_CHK_INT), ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD); writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); dev->interrupt=0; } else if (readb(ti->mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN) & (TCR_INT | ERR_INT | ACCESS_INT)) { DPRINTK("adapter error: ISRP_EVEN : %02x\n", (int)readb(ti->mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN)); writeb(~(TCR_INT | ERR_INT | ACCESS_INT), ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN); writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); dev->interrupt=0; } else if (status & (SRB_RESP_INT | ASB_FREE_INT | ARB_CMD_INT | SSB_RESP_INT)) { /* SRB, ASB, ARB or SSB response */ if (status & SRB_RESP_INT) { /* SRB response */ switch(readb(ti->srb)) { /* SRB command check */ case XMIT_DIR_FRAME: { unsigned char xmit_ret_code; xmit_ret_code=readb(ti->srb + offsetof(struct srb_xmit, ret_code)); if (xmit_ret_code != 0xff) { DPRINTK("error on xmit_dir_frame request: %02X\n", xmit_ret_code); if (ti->current_skb) { dev_kfree_skb(ti->current_skb); ti->current_skb=NULL; } dev->tbusy=0; if (ti->readlog_pending) ibmtr_readlog(dev); } } break; case XMIT_UI_FRAME: { unsigned char xmit_ret_code; xmit_ret_code=readb(ti->srb + offsetof(struct srb_xmit, ret_code)); if (xmit_ret_code != 0xff) { DPRINTK("error on xmit_ui_frame request: %02X\n", xmit_ret_code); if (ti->current_skb) { dev_kfree_skb(ti->current_skb); ti->current_skb=NULL; } dev->tbusy=0; if (ti->readlog_pending) ibmtr_readlog(dev); } } break; case DIR_OPEN_ADAPTER: { unsigned char open_ret_code; __u16 open_error_code; ti->srb=ti->sram+ntohs(readw(ti->init_srb +offsetof(struct srb_open_response, srb_addr))); ti->ssb=ti->sram+ntohs(readw(ti->init_srb +offsetof(struct srb_open_response, ssb_addr))); ti->arb=ti->sram+ntohs(readw(ti->init_srb +offsetof(struct srb_open_response, arb_addr))); ti->asb=ti->sram+ntohs(readw(ti->init_srb +offsetof(struct srb_open_response, asb_addr))); ti->current_skb=NULL; open_ret_code = readb(ti->init_srb +offsetof(struct srb_open_response, ret_code)); open_error_code = ntohs(readw(ti->init_srb +offsetof(struct srb_open_response, error_code))); if (open_ret_code==7) { if (!ti->auto_ringspeedsave && (open_error_code==0x24)) { DPRINTK("Open failed: Adapter speed must match ring " "speed if Automatic Ring Speed Save is disabled.\n"); ti->open_status=FAILURE; wake_up(&ti->wait_for_reset); } else if (open_error_code==0x24) DPRINTK("Retrying open to adjust to ring speed.\n"); else if ((open_error_code==0x2d) && ti->auto_ringspeedsave) DPRINTK("No signal detected for Auto Speed Detection.\n"); else if (open_error_code==0x11) { if (ti->retry_count--) DPRINTK("Ring broken/disconnected, retrying...\n"); else { DPRINTK("Ring broken/disconnected, open failed.\n"); ti->open_status = FAILURE; } } else DPRINTK("Unrecoverable error: error code = %04x.\n", open_error_code); } else if (!open_ret_code) {#if !TR_NEWFORMAT DPRINTK("board opened...\n");#else DPRINTK("Adapter initialized and opened.\n");#endif writeb(~(SRB_RESP_INT), ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD); writeb(~(CMD_IN_SRB), ti->mmio + ACA_OFFSET + ACA_RESET + ISRA_ODD); open_sap(EXTENDED_SAP,dev); /* YdW probably hates me */ goto skip_reset; } else DPRINTK("open failed: ret_code = %02X, retrying\n", open_ret_code); if (ti->open_status != FAILURE) { ibmtr_reset_timer(&(ti->tr_timer), dev); } } break; case DIR_CLOSE_ADAPTER: wake_up(&ti->wait_for_tok_int); break; case DLC_OPEN_SAP: if (readb(ti->srb+offsetof(struct dlc_open_sap, ret_code))) { DPRINTK("open_sap failed: ret_code = %02X,retrying\n", (int)readb(ti->srb+offsetof(struct dlc_open_sap, ret_code))); ibmtr_reset_timer(&(ti->tr_timer), dev); } else { ti->exsap_station_id= readw(ti->srb+offsetof(struct dlc_open_sap, station_id)); ti->open_status=SUCCESS; /* TR adapter is now available */ wake_up(&ti->wait_for_reset); } break; case DIR_INTERRUPT: case DIR_MOD_OPEN_PARAMS: case DIR_SET_GRP_ADDR: case DIR_SET_FUNC_ADDR: case DLC_CLOSE_SAP: if (readb(ti->srb+offsetof(struct srb_interrupt, ret_code))) DPRINTK("error on %02X: %02X\n", (int)readb(ti->srb+offsetof(struct srb_interrupt, command)), (int)readb(ti->srb+offsetof(struct srb_interrupt, ret_code))); break; case DIR_READ_LOG: if (readb(ti->srb+offsetof(struct srb_read_log, ret_code))) DPRINTK("error on dir_read_log: %02X\n", (int)readb(ti->srb+offsetof(struct srb_read_log, ret_code))); else if (IBMTR_DEBUG_MESSAGES) { DPRINTK( "Line errors %02X, Internal errors %02X, Burst errors %02X\n" "A/C errors %02X, Abort delimiters %02X, Lost frames %02X\n" "Receive congestion count %02X, Frame copied errors %02X\n" "Frequency errors %02X, Token errors %02X\n", (int)readb(ti->srb+offsetof(struct srb_read_log, line_errors)), (int)readb(ti->srb+offsetof(struct srb_read_log, internal_errors)), (int)readb(ti->srb+offsetof(struct srb_read_log, burst_errors)), (int)readb(ti->srb+offsetof(struct srb_read_log, A_C_errors)), (int)readb(ti->srb+offsetof(struct srb_read_log, abort_delimiters)), (int)readb(ti->srb+offsetof(struct srb_read_log, lost_frames)), (int)readb(ti->srb+offsetof(struct srb_read_log, recv_congest_count)), (int)readb(ti->srb+offsetof(struct srb_read_log, frame_copied_errors)), (int)readb(ti->srb+offsetof(struct srb_read_log, frequency_errors)), (int)readb(ti->srb+offsetof(struct srb_read_log, token_errors))); } dev->tbusy=0; break; default: DPRINTK("Unknown command %02X encountered\n", (int)readb(ti->srb)); } /* SRB command check */ writeb(~CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_RESET + ISRA_ODD); writeb(~SRB_RESP_INT, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD); skip_reset: } /* SRB response */ if (status & ASB_FREE_INT) { /* ASB response */ switch(readb(ti->asb)) { /* ASB command check */ case REC_DATA: case XMIT_UI_FRAME: case XMIT_DIR_FRAME: break; default: DPRINTK("unknown command in asb %02X\n", (int)readb(ti->asb)); } /* ASB command check */ if (readb(ti->asb+2)!=0xff) /* checks ret_code */ DPRINTK("ASB error %02X in cmd %02X\n", (int)readb(ti->asb+2),(int)readb(ti->asb)); writeb(~ASB_FREE_INT, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD); } /* ASB response */ if (status & ARB_CMD_INT) { /* ARB response */ switch (readb(ti->arb)) { /* ARB command check */ case DLC_STATUS: DPRINTK("DLC_STATUS new status: %02X on station %02X\n", ntohs(readw(ti->arb + offsetof(struct arb_dlc_status, status))), ntohs(readw(ti->arb +offsetof(struct arb_dlc_status, station_id)))); break; case REC_DATA: tr_rx(dev); break; case RING_STAT_CHANGE: { unsigned short ring_status; ring_status=ntohs(readw(ti->arb +offsetof(struct arb_ring_stat_change, ring_status))); if (ring_status & (SIGNAL_LOSS | LOBE_FAULT)) { DPRINTK("Signal loss/Lobe fault\n"); DPRINTK("We try to reopen the adapter.\n"); ibmtr_reset_timer(&(ti->tr_timer), dev); } else if (ring_status & (HARD_ERROR | XMIT_BEACON | AUTO_REMOVAL | REMOVE_RECV | RING_RECOVER)) DPRINTK("New ring status: %02X\n", ring_status); if (ring_status & LOG_OVERFLOW) { if (dev->tbusy) ti->readlog_pending = 1; else ibmtr_readlog(dev); } } break; case XMIT_DATA_REQ: tr_tx(dev); break; default: DPRINTK("Unknown command %02X in arb\n", (int)readb(ti->arb)); break; } /* ARB command check */ writeb(~ARB_CMD_INT, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD); writeb(ARB_FREE, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); } /* ARB response */ if (status & SSB_RESP_INT) { /* SSB response */ unsigned char retcode; switch (readb(ti->ssb)) { /* SSB command check */ case XMIT_DIR_FRAME: case XMIT_UI_FRAME: retcode = readb(ti->ssb+2); if (retcode && (retcode != 0x22)) /* checks ret_code */ DPRINTK("xmit ret_code: %02X xmit error code: %02X\n", (int)retcode, (int)readb(ti->ssb+6)); else ti->tr_stats.tx_packets++; break; case XMIT_XID_CMD: DPRINTK("xmit xid ret_code: %02X\n", (int)readb(ti->ssb+2)); default: DPRINTK("Unknown command %02X in ssb\n", (int)readb(ti->ssb)); } /* SSB command check */ writeb(~SSB_RESP_INT, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD); writeb(SSB_FREE, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); } /* SSB response */ } /* SRB, ARB, ASB or SSB response */ dev->interrupt=0; writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); break; case FIRST_INT: initial_tok_int(dev); break; default: DPRINTK("Unexpected interrupt from tr adapter\n"); } spin_unlock(&(ti->lock));}static void initial_tok_int(struct device *dev){ __u32 encoded_addr; __u32 hw_encoded_addr; struct tok_info *ti; ti=(struct tok_info *) dev->priv; ti->do_tok_int=NOT_FIRST;#ifndef TR_NEWFORMAT DPRINTK("Initial tok int received\n");#endif /* we assign the shared-ram address for ISA devices */ if(!ti->sram) { writeb(ti->sram_base, ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN); ti->sram=((__u32)ti->sram_base << 12); } ti->init_srb=ti->sram +ntohs((unsigned short)readw(ti->mmio+ ACA_OFFSET + WRBR_EVEN)); SET_PAGE(ntohs((unsigned short)readw(ti->mmio+ACA_OFFSET + WRBR_EVEN))); dev->mem_start = ti->sram; dev->mem_end = ti->sram + (ti->mapped_ram_size<<9) - 1;#if TR_VERBOSE { int i; DPRINTK("init_srb(%p):", ti->init_srb); for (i=0;i<17;i++) printk("%02X ", (int)readb(ti->init_srb+i)); printk("\n"); }#endif hw_encoded_addr = readw(ti->init_srb + offsetof(struct srb_init_response, encoded_address));#if !TR_NEWFORMAT DPRINTK("srb_init_response->encoded_address: %04X\n", hw_encoded_addr); DPRINTK("ntohs(srb_init_response->encoded_address): %04X\n", ntohs(hw_encoded_addr));#endif encoded_addr=(ti->sram + ntohs(hw_encoded_addr)); ti->ring_speed = readb(ti->init_srb+offsetof(struct srb_init_response, init_status)) & 0x01 ? 16 : 4;#if !TR_NEWFORMAT DPRINTK("encoded addr (%04X,%04X,%08X): ", hw_encoded_addr, ntohs(hw_encoded_addr), encoded_addr);#else DPRINTK("Initial interrupt : %d Mbps, shared RAM base %08x.\n", ti->ring_speed, ti->sram);#endif ti->auto_ringspeedsave=readb(ti->init_srb +offsetof(struct srb_init_response, init_status_2)) & 0x4 ? TRUE : FALSE;#if !TR_NEWFORMAT for(i=0;i<TR_ALEN;i++) { dev->dev_addr[i]=readb(encoded_addr + i); printk("%02X%s", dev->dev_addr[i], (i==TR_ALEN-1) ? "" : ":" ); } printk("\n");#endif tok_open_adapter((unsigned long)dev);}static int tok_init_card(struct 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 */ dev->tbusy=1; /* nothing can be done before reset and open completed */#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_RESET + ISRP_EVEN);#if !TR_NEWFORMAT DPRINTK("resetting card\n");#endif outb(0, PIOaddr+ADAPTRESET); for (i=jiffies+TR_RESET_INTERVAL; time_before_eq(jiffies, i);); /* wait 50ms */ outb(0,PIOaddr+ADAPTRESETREL);#if !TR_NEWFORMAT DPRINTK("card reset\n");#endif ti->open_status=IN_PROGRESS; writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); return 0;}static void open_sap(unsigned char type,struct device *dev){ int i; struct tok_info *ti=(struct tok_info *) dev->priv; SET_PAGE(ti->srb); for (i=0; i<sizeof(struct dlc_open_sap); i++) writeb(0, ti->srb+i); writeb(DLC_OPEN_SAP, ti->srb + offsetof(struct dlc_open_sap, command));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -