📄 rtl8139.c
字号:
{ prom9346_decode_command(eeprom, eeprom->input & 0xff); } break; case Chip9346_data_read: eeprom->eedo = (eeprom->output & 0x8000)?1:0; eeprom->output <<= 1; if (eeprom->tick == 16) { ++eeprom->address; eeprom->address &= EEPROM_9346_ADDR_MASK; eeprom->output = eeprom->contents[eeprom->address]; eeprom->tick = 0;#if defined(DEBUG_RTL8139) printf("eeprom: +++ read next address 0x%02x data=0x%04x\n", eeprom->address, eeprom->output);#endif } break; case Chip9346_data_write: eeprom->input = (eeprom->input << 1) | (bit & 1); if (eeprom->tick == 16) {#if defined(DEBUG_RTL8139) printf("RTL8139: eeprom write to address 0x%02x data=0x%04x\n", eeprom->address, eeprom->input);#endif eeprom->contents[eeprom->address] = eeprom->input; eeprom->mode = Chip9346_none; /* waiting for next command after CS cycle */ eeprom->tick = 0; eeprom->input = 0; } break; case Chip9346_data_write_all: eeprom->input = (eeprom->input << 1) | (bit & 1); if (eeprom->tick == 16) { int i; for (i = 0; i < EEPROM_9346_SIZE; i++) { eeprom->contents[i] = eeprom->input; }#if defined(DEBUG_RTL8139) printf("RTL8139: eeprom filled with data=0x%04x\n", eeprom->input);#endif eeprom->mode = Chip9346_enter_command_mode; eeprom->tick = 0; eeprom->input = 0; } break; default: break; }}int prom9346_get_wire(RTL8139State *s){ EEprom9346 *eeprom = &s->eeprom; if (!eeprom->eecs) return 0; return eeprom->eedo;}void prom9346_set_wire(RTL8139State *s, int eecs, int eesk, int eedi){ EEprom9346 *eeprom = &s->eeprom; uint8_t old_eecs = eeprom->eecs; uint8_t old_eesk = eeprom->eesk; eeprom->eecs = eecs; eeprom->eesk = eesk; eeprom->eedi = eedi;#if defined(DEBUG_RTL8139) printf("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n", eeprom->eecs, eeprom->eesk, eeprom->eedi, eeprom->eedo);#endif if (!old_eecs && eecs) { /* Synchronize start */ eeprom->tick = 0; eeprom->input = 0; eeprom->output = 0; eeprom->mode = Chip9346_enter_command_mode;#if defined(DEBUG_RTL8139) printf("=== eeprom: begin access, enter command mode\n");#endif } if (!eecs) {#if defined(DEBUG_RTL8139) printf("=== eeprom: end access\n");#endif return; } if (!old_eesk && eesk) { /* SK front rules */ prom9346_shift_clock(eeprom); }}static void rtl8139_update_irq(RTL8139State *s){ int isr; isr = (s->IntrStatus & s->IntrMask) & 0xffff;#if defined(DEBUG_RTL8139) printf("RTL8139: Set IRQ line %d to %d (%04x %04x)\n", s->irq, isr ? 1 : 0, s->IntrStatus, s->IntrMask);#endif if (s->irq == 16) { /* PCI irq */ pci_set_irq(s->pci_dev, 0, (isr != 0)); } else { /* ISA irq */ pic_set_irq(s->irq, (isr != 0)); }}#define POLYNOMIAL 0x04c11db6/* From FreeBSD *//* XXX: optimize */static int compute_mcast_idx(const uint8_t *ep){ uint32_t crc; int carry, i, j; uint8_t b; crc = 0xffffffff; for (i = 0; i < 6; i++) { b = *ep++; for (j = 0; j < 8; j++) { carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); crc <<= 1; b >>= 1; if (carry) crc = ((crc ^ POLYNOMIAL) | carry); } } return (crc >> 26);}static int rtl8139_RxWrap(RTL8139State *s){ /* wrapping enabled; assume 1.5k more buffer space if size < 65536 */ return (s->RxConfig & (1 << 7));}static int rtl8139_receiver_enabled(RTL8139State *s){ return s->bChipCmdState & CmdRxEnb;}static int rtl8139_transmitter_enabled(RTL8139State *s){ return s->bChipCmdState & CmdTxEnb;}static int rtl8139_cp_receiver_enabled(RTL8139State *s){ return s->CpCmd & CPlusRxEnb;}static int rtl8139_cp_transmitter_enabled(RTL8139State *s){ return s->CpCmd & CPlusTxEnb;}static void rtl8139_write_buffer(RTL8139State *s, const void *buf, int size){ if (s->RxBufAddr + size > s->RxBufferSize) { int wrapped = MOD2(s->RxBufAddr + size, s->RxBufferSize); /* write packet data */ if (wrapped && s->RxBufferSize < 65536 && !rtl8139_RxWrap(s)) { #if defined(DEBUG_RTL8139) printf(">>> RTL8139: rx packet wrapped in buffer at %d\n", size-wrapped); #endif if (size > wrapped) { cpu_physical_memory_write( s->RxBuf + s->RxBufAddr, buf, size-wrapped ); } /* reset buffer pointer */ s->RxBufAddr = 0; cpu_physical_memory_write( s->RxBuf + s->RxBufAddr, buf + (size-wrapped), wrapped ); s->RxBufAddr = wrapped; return; } } /* non-wrapping path or overwrapping enabled */ cpu_physical_memory_write( s->RxBuf + s->RxBufAddr, buf, size ); s->RxBufAddr += size;}#define MIN_BUF_SIZE 60static inline target_phys_addr_t rtl8139_addr64(uint32_t low, uint32_t high){#if TARGET_PHYS_ADDR_BITS > 32 return low | ((target_phys_addr_t)high << 32);#else return low;#endif}static int rtl8139_can_receive(void *opaque){ RTL8139State *s = opaque; int avail; /* Recieve (drop) packets if card is disabled. */ if (!s->clock_enabled) return 1; if (!rtl8139_receiver_enabled(s)) return 1; if (rtl8139_cp_receiver_enabled(s)) { /* ??? Flow control not implemented in c+ mode. This is a hack to work around slirp deficiencies anyway. */ return 1; } else { avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, s->RxBufferSize); return (avail == 0 || avail >= 1514); }}static void rtl8139_receive(void *opaque, const uint8_t *buf, int size){ RTL8139State *s = opaque; uint32_t packet_header = 0; uint8_t buf1[60]; static const uint8_t broadcast_macaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };#if defined(DEBUG_RTL8139) printf(">>> RTL8139: received len=%d\n", size);#endif /* test if board clock is stopped */ if (!s->clock_enabled) {#if defined(DEBUG_RTL8139) printf("RTL8139: stopped ==========================\n");#endif return; } /* first check if receiver is enabled */ if (!rtl8139_receiver_enabled(s)) {#if defined(DEBUG_RTL8139) printf("RTL8139: receiver disabled ================\n");#endif return; } /* XXX: check this */ if (s->RxConfig & AcceptAllPhys) { /* promiscuous: receive all */#if defined(DEBUG_RTL8139) printf(">>> RTL8139: packet received in promiscuous mode\n");#endif } else { if (!memcmp(buf, broadcast_macaddr, 6)) { /* broadcast address */ if (!(s->RxConfig & AcceptBroadcast)) {#if defined(DEBUG_RTL8139) printf(">>> RTL8139: broadcast packet rejected\n");#endif return; } packet_header |= RxBroadcast;#if defined(DEBUG_RTL8139) printf(">>> RTL8139: broadcast packet received\n");#endif } else if (buf[0] & 0x01) { /* multicast */ if (!(s->RxConfig & AcceptMulticast)) {#if defined(DEBUG_RTL8139) printf(">>> RTL8139: multicast packet rejected\n");#endif return; } int mcast_idx = compute_mcast_idx(buf); if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))) {#if defined(DEBUG_RTL8139) printf(">>> RTL8139: multicast address mismatch\n");#endif return; } packet_header |= RxMulticast;#if defined(DEBUG_RTL8139) printf(">>> RTL8139: multicast packet received\n");#endif } else if (s->phys[0] == buf[0] && s->phys[1] == buf[1] && s->phys[2] == buf[2] && s->phys[3] == buf[3] && s->phys[4] == buf[4] && s->phys[5] == buf[5]) { /* match */ if (!(s->RxConfig & AcceptMyPhys)) {#if defined(DEBUG_RTL8139) printf(">>> RTL8139: rejecting physical address matching packet\n");#endif return; } packet_header |= RxPhysical;#if defined(DEBUG_RTL8139) printf(">>> RTL8139: physical address matching packet received\n");#endif } else {#if defined(DEBUG_RTL8139) printf(">>> RTL8139: unknown packet\n");#endif return; } } /* if too small buffer, then expand it */ if (size < MIN_BUF_SIZE) { memcpy(buf1, buf, size); memset(buf1 + size, 0, MIN_BUF_SIZE - size); buf = buf1; size = MIN_BUF_SIZE; } if (rtl8139_cp_receiver_enabled(s)) {#if defined(DEBUG_RTL8139) printf("RTL8139: in C+ Rx mode ================\n");#endif /* begin C+ receiver mode *//* w0 ownership flag */#define CP_RX_OWN (1<<31)/* w0 end of ring flag */#define CP_RX_EOR (1<<30)/* w0 bits 0...12 : buffer size */#define CP_RX_BUFFER_SIZE_MASK ((1<<13) - 1)/* w1 tag available flag */#define CP_RX_TAVA (1<<16)/* w1 bits 0...15 : VLAN tag */#define CP_RX_VLAN_TAG_MASK ((1<<16) - 1)/* w2 low 32bit of Rx buffer ptr *//* w3 high 32bit of Rx buffer ptr */ int descriptor = s->currCPlusRxDesc; target_phys_addr_t cplus_rx_ring_desc; cplus_rx_ring_desc = rtl8139_addr64(s->RxRingAddrLO, s->RxRingAddrHI); cplus_rx_ring_desc += 16 * descriptor;#ifdef DEBUG_RTL8139 printf("RTL8139: +++ C+ mode reading RX descriptor %d from host memory at %08x %08x = 0x%8lx\n", descriptor, s->RxRingAddrHI, s->RxRingAddrLO, cplus_rx_ring_desc);#endif uint32_t val, rxdw0,rxdw1,rxbufLO,rxbufHI; cpu_physical_memory_read(cplus_rx_ring_desc, (uint8_t *)&val, 4); rxdw0 = le32_to_cpu(val); cpu_physical_memory_read(cplus_rx_ring_desc+4, (uint8_t *)&val, 4); rxdw1 = le32_to_cpu(val); cpu_physical_memory_read(cplus_rx_ring_desc+8, (uint8_t *)&val, 4); rxbufLO = le32_to_cpu(val); cpu_physical_memory_read(cplus_rx_ring_desc+12, (uint8_t *)&val, 4); rxbufHI = le32_to_cpu(val);#ifdef DEBUG_RTL8139 printf("RTL8139: +++ C+ mode RX descriptor %d %08x %08x %08x %08x\n", descriptor, rxdw0, rxdw1, rxbufLO, rxbufHI);#endif if (!(rxdw0 & CP_RX_OWN)) {#if defined(DEBUG_RTL8139) printf("RTL8139: C+ Rx mode : descriptor %d is owned by host\n", descriptor);#endif s->IntrStatus |= RxOverflow; ++s->RxMissed; rtl8139_update_irq(s); return; } uint32_t rx_space = rxdw0 & CP_RX_BUFFER_SIZE_MASK; if (size+4 > rx_space) {#if defined(DEBUG_RTL8139) printf("RTL8139: C+ Rx mode : descriptor %d size %d received %d + 4\n", descriptor, rx_space, size);#endif s->IntrStatus |= RxOverflow; ++s->RxMissed; rtl8139_update_irq(s); return; } target_phys_addr_t rx_addr = rtl8139_addr64(rxbufLO, rxbufHI); /* receive/copy to target memory */ cpu_physical_memory_write( rx_addr, buf, size ); /* write checksum */#if defined (RTL8139_CALCULATE_RXCRC) val = cpu_to_le32(crc32(~0, buf, size));#else val = 0;#endif cpu_physical_memory_write( rx_addr+size, (uint8_t *)&val, 4);/* first segment of received packet flag */#define CP_RX_STATUS_FS (1<<29)/* last segment of received packet flag */#define CP_RX_STATUS_LS (1<<28)/* multicast packet flag */#define CP_RX_STATUS_MAR (1<<26)/* physical-matching packet flag */#define CP_RX_STATUS_PAM (1<<25)/* broadcast packet flag */#define CP_RX_STATUS_BAR (1<<24)/* runt packet flag */#define CP_RX_STATUS_RUNT (1<<19)/* crc error flag */#define CP_RX_STATUS_CRC (1<<18)/* IP checksum error flag */#define CP_RX_STATUS_IPF (1<<15)/* UDP checksum error flag */#define CP_RX_STATUS_UDPF (1<<14)/* TCP checksum error flag */#define CP_RX_STATUS_TCPF (1<<13) /* transfer ownership to target */ rxdw0 &= ~CP_RX_OWN; /* set first segment bit */ rxdw0 |= CP_RX_STATUS_FS; /* set last segment bit */ rxdw0 |= CP_RX_STATUS_LS; /* set received packet type flags */ if (packet_header & RxBroadcast) rxdw0 |= CP_RX_STATUS_BAR; if (packet_header & RxMulticast) rxdw0 |= CP_RX_STATUS_MAR; if (packet_header & RxPhysical) rxdw0 |= CP_RX_STATUS_PAM; /* set received size */ rxdw0 &= ~CP_RX_BUFFER_SIZE_MASK; rxdw0 |= (size+4); /* reset VLAN tag flag */ rxdw1 &= ~CP_RX_TAVA; /* update ring data */ val = cpu_to_le32(rxdw0); cpu_physical_memory_write(cplus_rx_ring_desc, (uint8_t *)&val, 4); val = cpu_to_le32(rxdw1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -