📄 rtl8139.c
字号:
#if DEAD_CODE src_phys= rep->re_rx_buf + d_start; cps = sys_physcopy( NONE, PHYS_SEG, src_phys, SELF, D, (vir_bytes) &rxstat, sizeof(rxstat)); if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);#endif if (rep->re_clear_rx) {#if 0 printf("rl_readv: late buffer overflow\n");#endif goto suspend; /* Buffer overflow */ } /* Should convert from little endian to host byte order */ if (!(rxstat & RL_RXS_ROK)) { printf("rxstat = 0x%08lx\n", rxstat); printf("d_start: 0x%x, d_end: 0x%x, rxstat: 0x%lx\n", d_start, d_end, rxstat); panic("rtl8139","received packet not OK", NO_NUM); } totlen= (rxstat >> RL_RXS_LEN_S); if (totlen < 8 || totlen > 2*ETH_MAX_PACK_SIZE) { /* Someting went wrong */ printf( "rl_readv: bad length (%u) in status 0x%08lx at offset 0x%x\n", totlen, rxstat, d_start); printf( "d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%lx\n", d_start, d_end, totlen, rxstat); panic(NULL, NULL, NO_NUM); }#if 0 printf("d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%x\n", d_start, d_end, totlen, rxstat);#endif if (totlen+4 > amount) { printf("rl_readv: packet not yet ready\n"); goto suspend; } /* Should subtract the CRC */ packlen= totlen - ETH_CRC_SIZE; if (vectored) { int iov_offset = 0;#if 0 if ((cps = sys_umap(re_client, D, (vir_bytes) mp->DL_ADDR, count * sizeof(rep->re_iovec[0]), &iov_src)) != OK) printf("sys_umap failed: %d\n", cps);#endif size= 0; o= d_start+4; src_phys= rep->re_rx_buf; for (i= 0; i<count; i += IOVEC_NR, iov_src += IOVEC_NR * sizeof(rep->re_iovec[0]), iov_offset += IOVEC_NR * sizeof(rep->re_iovec[0])) { n= IOVEC_NR; if (i+n > count) n= count-i;#if 0 cps = sys_physcopy(NONE, PHYS_SEG, iov_src, SELF, D, (vir_bytes) rep->re_iovec, n * sizeof(rep->re_iovec[0])); if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);#else cps = sys_vircopy(re_client, D, (vir_bytes) mp->DL_ADDR + iov_offset, SELF, D, (vir_bytes) rep->re_iovec, n * sizeof(rep->re_iovec[0])); if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);#endif for (j= 0, iovp= rep->re_iovec; j<n; j++, iovp++) { s= iovp->iov_size; if (size + s > packlen) { assert(packlen > size); s= packlen-size; }#if 0 if (sys_umap(re_client, D, iovp->iov_addr, s, &dst_phys) != OK) panic("rtl8139","umap_local failed\n", NO_NUM);#endif if (o >= RX_BUFSIZE) { o -= RX_BUFSIZE; assert(o < RX_BUFSIZE); } if (o+s > RX_BUFSIZE) { assert(o<RX_BUFSIZE); s1= RX_BUFSIZE-o;#if 0 cps = sys_abscopy(src_phys+o, dst_phys, s1); if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps); cps = sys_abscopy(src_phys, dst_phys+s1, s-s1); if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);#else cps = sys_vircopy(SELF, D, (vir_bytes) rep->v_re_rx_buf+o, re_client, D, iovp->iov_addr, s1); if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__); cps = sys_vircopy(SELF, D, (vir_bytes) rep->v_re_rx_buf, re_client, D, iovp->iov_addr+s1, s-s1); if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);#endif } else {#if 0 cps = sys_abscopy(src_phys+o, dst_phys, s); if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);#else cps = sys_vircopy(SELF, D, (vir_bytes) rep->v_re_rx_buf+o, re_client, D, iovp->iov_addr, s); if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);#endif } size += s; if (size == packlen) break; o += s; } if (size == packlen) break; } if (size < packlen) { assert(0); } } else { assert(0);#if 0 size= mp->DL_COUNT; if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED) panic("rtl8139","invalid packet size", size); if (OK != sys_umap(re_client, D, (vir_bytes)mp->DL_ADDR, size, &phys_user)) panic("rtl8139","umap_local failed", NO_NUM); p= rep->re_tx[tx_head].ret_buf; cps = sys_abscopy(phys_user, p, size); if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);#endif } if (rep->re_clear_rx) { /* For some reason the receiver FIFO is not stopped when * the buffer is full. */ #if 0 printf("rl_readv: later buffer overflow\n"); #endif goto suspend; /* Buffer overflow */ } rep->re_stat.ets_packetR++; rep->re_read_s= packlen; rep->re_flags= (rep->re_flags & ~REF_READING) | REF_PACK_RECV; /* Avoid overflow in 16-bit computations */ l= d_start; l += totlen+4; l= (l+3) & ~3; /* align */ if (l >= RX_BUFSIZE) { l -= RX_BUFSIZE; assert(l < RX_BUFSIZE); } rl_outw(port, RL_CAPR, l-RL_CAPR_DATA_OFF); if (!from_int) reply(rep, OK, FALSE); return; suspend: if (from_int) { assert(rep->re_flags & REF_READING); /* No need to store any state */ return; } rep->re_rx_mess= *mp; assert(!(rep->re_flags & REF_READING)); rep->re_flags |= REF_READING; reply(rep, OK, FALSE); } /*===========================================================================* * rl_writev * *===========================================================================*/ static void rl_writev(mp, from_int, vectored) message *mp; int from_int; int vectored; { phys_bytes p, iov_src, phys_user; int i, j, n, s, port, count, size; int tx_head, re_client; re_t *rep; iovec_t *iovp; char *ret; int cps; port = mp->DL_PORT; count = mp->DL_COUNT; if (port < 0 || port >= RE_PORT_NR) panic("rtl8139","illegal port", port); rep= &re_table[port]; re_client= mp->DL_PROC; rep->re_client= re_client; assert(rep->re_mode == REM_ENABLED); assert(rep->re_flags & REF_ENABLED); if (from_int) { assert(rep->re_flags & REF_SEND_AVAIL); rep->re_flags &= ~REF_SEND_AVAIL; rep->re_send_int= FALSE; rep->re_tx_alive= TRUE; } tx_head= rep->re_tx_head; if (rep->re_tx[tx_head].ret_busy) { assert(!(rep->re_flags & REF_SEND_AVAIL)); rep->re_flags |= REF_SEND_AVAIL; if (rep->re_tx[tx_head].ret_busy) goto suspend; /* Race condition, the interrupt handler may clear re_busy * before we got a chance to set REF_SEND_AVAIL. Checking * ret_busy twice should be sufficient. */ #if 0 printf("rl_writev: race detected\n"); #endif rep->re_flags &= ~REF_SEND_AVAIL; rep->re_send_int= FALSE; } assert(!(rep->re_flags & REF_SEND_AVAIL)); assert(!(rep->re_flags & REF_PACK_SENT)); if (vectored) { int iov_offset = 0;#if 0 if (OK != sys_umap(re_client, D, (vir_bytes)mp->DL_ADDR, count * sizeof(rep->re_iovec[0]), &iov_src)) panic("rtl8139","umap_local failed", NO_NUM);#endif size= 0;#if 0 p= rep->re_tx[tx_head].ret_buf;#else ret = rep->re_tx[tx_head].v_ret_buf;#endif for (i= 0; i<count; i += IOVEC_NR, iov_src += IOVEC_NR * sizeof(rep->re_iovec[0]), iov_offset += IOVEC_NR * sizeof(rep->re_iovec[0])) { n= IOVEC_NR; if (i+n > count) n= count-i;#if 0 cps = sys_physcopy(NONE, PHYS_SEG, iov_src, SELF, D, (vir_bytes) rep->re_iovec, n * sizeof(rep->re_iovec[0])); if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);#else cps = sys_vircopy(re_client, D, ((vir_bytes) mp->DL_ADDR) + iov_offset, SELF, D, (vir_bytes) rep->re_iovec, n * sizeof(rep->re_iovec[0])); if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps);#endif for (j= 0, iovp= rep->re_iovec; j<n; j++, iovp++) { s= iovp->iov_size; if (size + s > ETH_MAX_PACK_SIZE_TAGGED) { panic("rtl8139","invalid packet size", NO_NUM); } if (OK != sys_umap(re_client, D, iovp->iov_addr, s, &phys_user)) panic("rtl8139","umap_local failed\n", NO_NUM);#if 0 cps = sys_abscopy(phys_user, p, s); if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);#else cps = sys_vircopy(re_client, D, iovp->iov_addr, SELF, D, (vir_bytes) ret, s); if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps);#endif size += s;#if 0 p += s;#endif ret += s; } } if (size < ETH_MIN_PACK_SIZE) panic("rtl8139","invalid packet size", size); } else { size= mp->DL_COUNT; if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED) panic("rtl8139","invalid packet size", size);#if 0 if (OK != sys_umap(re_client, D, (vir_bytes)mp->DL_ADDR, size, &phys_user)) panic("rtl8139","umap_local failed\n", NO_NUM); p= rep->re_tx[tx_head].ret_buf; cps = sys_abscopy(phys_user, p, size); if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);#else ret = rep->re_tx[tx_head].v_ret_buf; cps = sys_vircopy(re_client, D, (vir_bytes)mp->DL_ADDR, SELF, D, (vir_bytes) ret, size); if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);#endif } rl_outl(rep->re_base_port, RL_TSD0+tx_head*4, rep->re_ertxth | size); rep->re_tx[tx_head].ret_busy= TRUE; if (++tx_head == N_TX_BUF) tx_head= 0; assert(tx_head < RL_N_TX); rep->re_tx_head= tx_head; rep->re_flags |= REF_PACK_SENT; /* If the interrupt handler called, don't send a reply. The reply * will be sent after all interrupts are handled. */ if (from_int) return; reply(rep, OK, FALSE); return;suspend:#if 0 printf("rl_writev: head %d, tail %d, busy: %d %d %d %d\n", tx_head, rep->re_tx_tail, rep->re_tx[0].ret_busy, rep->re_tx[1].ret_busy, rep->re_tx[2].ret_busy, rep->re_tx[3].ret_busy); printf("rl_writev: TSD: 0x%x, 0x%x, 0x%x, 0x%x\n", rl_inl(rep->re_base_port, RL_TSD0+0*4), rl_inl(rep->re_base_port, RL_TSD0+1*4), rl_inl(rep->re_base_port, RL_TSD0+2*4), rl_inl(rep->re_base_port, RL_TSD0+3*4));#endif if (from_int) panic("rtl8139","should not be sending\n", NO_NUM); rep->re_tx_mess= *mp; reply(rep, OK, FALSE);}/*===========================================================================* * rl_check_ints * *===========================================================================*/static void rl_check_ints(rep)re_t *rep;{#if 010-1f R/W TSD[0-3] Transmit Status of Descriptor [0-3] 31 R CRS Carrier Sense Lost 30 R TABT Transmit Abort 29 R OWC Out of Window Collision 27-24 R NCC[3-0] Number of Collision Count 23-22 reserved 21-16 R/W ERTXH[5-0] Early Tx Threshold 15 R TOK Transmit OK 14 R TUN Transmit FIFO Underrun 13 R/W OWN OWN 12-0 R/W SIZE Descriptor Size3e-3f R/W ISR Interrupt Status Register 6 R/W FOVW Fx FIFO Overflow Interrupt 5 R/W PUN/LinkChg Packet Underrun / Link Change Interrupt 3 R/W TER Transmit Error Interrupt 2 R/W TOK Transmit OK Interrupt3e-3f R/W ISR Interrupt Status Register 15 R/W SERR System Error Interrupt 14 R/W TimeOut Time Out Interrupt 13 R/W LenChg Cable Length Change Interrupt3e-3f R/W ISR Interrupt Status Register 4 R/W RXOVW Rx Buffer Overflow Interrupt 1 R/W RER Receive Error Interrupt 0 R/W ROK Receive OK Interrupt4c-4f R/W MPC Missed Packet Counter60-61 R TSAD Transmit Status of All Descriptors 15-12 R TOK[3-0] TOK bit of Descriptor [3-0] 11-8 R TUN[3-0] TUN bit of Descriptor [3-0] 7-4 R TABT[3-0] TABT bit of Descriptor [3-0] 3-0 R OWN[3-0] OWN bit of Descriptor [3-0]6c-6d R DIS Disconnect Counter 15-0 R DCNT Disconnect Counter6e-6f R FCSC False Carrier Sense Counter 15-0 R FCSCNT False Carrier event counter72-73 R REC RX_ER Counter 15-0 R RXERCNT Received packet counter#endif int re_flags; re_flags= rep->re_flags; if ((re_flags & REF_READING) && !(rl_inb(rep->re_base_port, RL_CR) & RL_CR_BUFE)) { if (rep->re_rx_mess.m_type == DL_READV) { rl_readv(&rep->re_rx_mess, TRUE /* from int */, TRUE /* vectored */); } else { assert(rep->re_rx_mess.m_type == DL_READ); rl_readv(&rep->re_rx_mess, TRUE /* from int */, FALSE /* !vectored */); } } if (rep->re_clear_rx) rl_clear_rx(rep); if (rep->re_need_reset) rl_do_reset(rep); if (rep->re_send_int) { if (rep->re_tx_mess.m_type == DL_WRITEV) { rl_writev(&rep->re_tx_mess, TRUE /* from int */, TRUE /* vectored */); } else { assert(rep->re_tx_mess.m_type == DL_WRITE); rl_writev(&rep->re_tx_mess, TRUE /* from int */, FALSE /* !vectored */); } } if (rep->re_report_link) rl_report_link(rep); if (rep->re_flags & (REF_PACK_SENT | REF_PACK_RECV)) reply(rep, OK, TRUE);}/*===========================================================================* * rl_report_link * *===========================================================================*/static void rl_report_link(rep)re_t *rep;{ port_t port; u16_t mii_ctrl, mii_status, mii_ana, mii_anlpa, mii_ane, mii_extstat; u8_t msr; int f, link_up; rep->re_report_link= FALSE; port= rep->re_base_port; msr= rl_inb(port, RL_MSR); link_up= !(msr & RL_MSR_LINKB); rep->re_link_up= link_up; if (!link_up) { printf("%s: link down\n", rep->re_name); return; } mii_ctrl= rl_inw(port, RL_BMCR); mii_status= rl_inw(port, RL_BMSR); mii_ana= rl_inw(port, RL_ANAR); mii_anlpa= rl_inw(port, RL_ANLPAR); mii_ane= rl_inw(port, RL_ANER); mii_extstat= 0; if (mii_ctrl & (MII_CTRL_LB|MII_CTRL_PD|MII_CTRL_ISO)) { printf("%s: PHY: ", rep->re_name); f= 1; if (mii_ctrl & MII_CTRL_LB) { printf("loopback mode"); f= 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -