📄 e100.c
字号:
struct { uint16_t data; // Data uint8_t regaddr:5; // PHY register address uint8_t phyaddr:5; // PHY address uint8_t opcode:2; // Opcode uint8_t r:1; // Ready uint8_t ie:1; // Interrup enable uint8_t rs1:2; // Reserved }u; } mdi_ctrl; /* Receive byte counter register */ uint32_t rx_byte_counter; /* Early receive interrupt register */ uint8_t early_interrupt; /* Flow control register */ union { uint16_t val; }flow_ctrl; /* Power management driver register */ union { uint8_t val; struct { uint8_t pme_s:1; // PME status uint8_t tco_r:1; // TCO request uint8_t f_tco_i:1; // Force TCO indication uint8_t tco_re:1; // TCO ready uint8_t rs1:1; // Reserved uint8_t isp:1; // Intersting packet uint8_t mg:1; // Magic packet uint8_t lsci:1; // Link status change indication }u; }pm_reg; /* General control register */ uint8_t gen_ctrl; /* General status register */ uint8_t gen_status; /* These are reserved or we don't support register */ uint8_t others[30];} __attribute__ ((packed)) csr_t;typedef struct{ uint8_t byte_count; uint8_t rx_fifo_limit:4; uint8_t tx_fifo_limit:4; uint8_t adpt_inf_spacing; uint8_t rs1; uint8_t rx_dma_max_bytes; uint8_t tx_dma_max_bytes:7; uint8_t dmbc_en:1; uint8_t late_scb:1, rs2:1, tno_intr:1, ci_intr:1, rs3:1, rs4:1, dis_overrun_rx:1, save_bad_frame:1; uint8_t dis_short_rx:1, underrun_retry:2, rs5:5; uint8_t mii:1, rs6:7; uint8_t rs7; uint8_t rs8:3, nsai:1, preamble_len:2, loopback:2; uint8_t linear_prio:3, rs9:5; uint8_t pri_mode:1, rs10:3, interframe_spacing:4; uint16_t rs11; uint8_t promiscuous:1, broadcast_dis:1, rs12:5, crs_cdt:1; uint16_t rs13; uint8_t strip:1, padding:1, rx_crc:1, rs14:5; uint8_t rs15:6, force_fdx:1, fdx_en:1; uint8_t rs16:6, mul_ia:2; uint8_t rs17:3, mul_all:1, rs18:4;} __attribute__ ((packed)) i82557_cfg_t;typedef struct { VLANClientState *vc; PCIDevice *pci_dev; int mmio_index; uint8_t scb_stat; /* SCB stat/ack byte */ uint32_t region_base_addr[REGION_NUM]; /* PCI region addresses */ uint8_t macaddr[6]; uint16_t mdimem[32]; eeprom_t eeprom; uint32_t device; /* device variant */ uint8_t mult_list[8]; /* Multicast address list */ int is_multcast_enable; /* (cu_base + cu_offset) address the next command block in the command block list. */ uint32_t cu_base; /* CU base address */ uint32_t cu_offset; /* CU address offset */ uint32_t cu_next; /* Point to next command when CU go to suspend */ /* (ru_base + ru_offset) address the RFD in the Receive Frame Area. */ uint32_t ru_base; /* RU base address */ uint32_t ru_offset; /* RU address offset */ uint32_t statsaddr; /* pointer to e100_stats_t */ e100_stats_t statistics; /* statistical counters */ /* Configuration bytes. */ i82557_cfg_t config; /* FIFO buffer of card. The packet that need to be sent buffered in it */ uint8_t pkt_buf[MAX_ETH_FRAME_SIZE+4]; /* Data length in FIFO buffer */ int pkt_buf_len; /* Data in mem is always in the byte order of the controller (le). */ union { csr_t csr; uint8_t mem[PCI_MEM_SIZE]; }pci_mem;} E100State;/* CB structure, filled by device driver * This is a common structure of CB. In some * special case such as TRANSMIT command, the * reserved field will be used. */struct control_block{ uint16_t rs1:13; /* reserved */ uint8_t ok:1; /* 1:command executed without error, otherwise 0 */ uint8_t rs2:1; uint8_t c:1; /* execution status. set by device, clean by software */ uint8_t cmd:3; /* command */ uint16_t rs3:10; /* most time equal to 0 */ uint8_t i:1; /* whether trigger interrupt after execution. 1:yes; 0:no */ uint8_t s:1; /* suspend */ uint8_t el:1; /* end flag */ uint32_t link_addr;} __attribute__ ((packed));typedef struct{ uint32_t tx_desc_addr; /* transmit buffer decsriptor array address. */ uint16_t tcb_bytes:14; /* transmit command block byte count (in lower 14 bits)*/ uint8_t rs1:1; uint8_t eof:1; uint8_t tx_threshold; /* transmit threshold */ uint8_t tbd_num; /* TBD number */} __attribute__ ((packed)) tbd_t;/* Receive frame descriptore structure */typedef struct{ uint16_t status:13; // Result of receive opration uint8_t ok:1; // 1:receive without error, otherwise 0 uint8_t rs1:1; uint8_t c:1; // 1:receive complete uint8_t rs2:3; uint8_t sf:1; // 0:simplified mode uint8_t h:1; // 1:header RFD uint16_t rs3:9; uint8_t s:1; // 1:go to suspend uint8_t el:1; // 1:last RFD uint32_t link_addr; // Add on RU base point to next RFD uint32_t rs4; uint16_t count:14; // Number of bytes written into data area uint8_t f:1; // Set by device when count field update uint8_t eof:1; // Set by device when placing data into data area complete uint16_t size:14; // Buffer size (even number) uint8_t rs5:2;} __attribute__ ((packed)) rfd_t;enum{ RX_COLLISION = BIT(0), // 1:Receive collision detected RX_IA_MATCH = BIT(1), // 0:Receive frame match individual address RX_NO_MATCH = BIT(2), // 1:Receive frame match no address RX_ERR = BIT(4), // 1:Receive frame error RX_TYPE = BIT(5), // 1:Receive frame is a type frame RX_SHORT = BIT(7), // 1:Receive frame is too short RX_DMA_ERR = BIT(8), RX_LARGE = BIT(9), // 1:Receive frame is too large RX_CRC_ERR = BIT(10),} RFD_STATUS;typedef struct PCIE100State { PCIDevice dev; E100State e100;} PCIE100State;/* Default values for MDI (PHY) registers */static const uint16_t e100_mdi_default[] = { /* MDI Registers 0 - 6, 7 */ 0x3000, 0x780d, 0x02a8, 0x0154, 0x05e1, 0x0000, 0x0000, 0x0000, /* MDI Registers 8 - 15 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* MDI Registers 16 - 31 */ 0x0003, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,};static const uint8_t broadcast_macaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };/* Debugging codes */#ifdef DEBUG_E100static void e100_dump(char *comment, uint8_t *info, int len){ int i; if ( !comment || !info ) return; fprintf(stderr, "EE100\t%-24s%s", __func__, comment); for ( i=0; i<len; i++ ) fprintf(stderr, "%x ", info[i]); fprintf(stderr, "\n");}static const char *regname[] ={ [0] = "SCB Status", [1] = "SCB Ack", [2] = "SCB Cmd", [3] = "SCB Interrupt Mask", [4] = "SCB Pointer", [8] = "SCB Port", [0xc] = "SCB Flash", [0xe] = "SCB Eeprom", [0x10] = "SCB Ctrl MDI", [0x14] = "SCB Early RX",};#define SCBNAME(x) \ ( (x) < (sizeof(regname) / sizeof(regname[0])) ? regname[(x)] : "Unknown SCB Register" )static const char *cb_cmd_name[] ={ [CBL_NOP] = "NOP", [CBL_IASETUP] = "Individual address setup", [CBL_CONFIGURE] = "Configure", [CBL_MULTCAST_ADDR_SETUP] = "Set Multcast address list", [CBL_TRANSMIT] = "Transmit", [CBL_LOAD_MICROCODE] = "Load microcode", [CBL_DUMP] = "Dump", [CBL_DIAGNOSE] = "Diagnose",};#define CB_CMD_NAME(x) \ ( (x) < (sizeof(cb_cmd_name) / sizeof(cb_cmd_name[0])) ? cb_cmd_name[(x)] : "Unknown CB command" )static const char *eeprom_opcode_name[] ={ [0] = "Unknow", [EEPROM_WRITE] = "Write", [EEPROM_READ] = "Read", [EEPROM_ERASE] = "Erase",};#define EEPROM_OPCODE_NAME(x) \ ( (x) < (sizeof(eeprom_opcode_name) / sizeof(eeprom_opcode_name[0])) ? \ eeprom_opcode_name[(x)] : "Unknown" )static struct eeprom_trace_data{ uint8_t eedo[256]; uint8_t di[256]; int op; int i; uint32_t data;}etd = {.op = NOP};static void eeprom_trace(int eedo, int di, int dir, int next_op, int clr){ int i; if ( clr ) { char *opname = NULL; switch ( etd.op ) { case NOP: break; case OPCODE: opname = "opcode"; break; case ADDR: opname = "address"; break; case DATA: opname = "data transfer"; break; default: opname = "Unknown"; } if ( opname ) { logout("EEPROM trace:\n"); fprintf(stderr, "\toperation: %s\n", opname); fprintf(stderr, "\tDI track:"); for ( i=0; i<etd.i; i++ ) fprintf(stderr, "%x ", etd.di[i]); fprintf(stderr, "\n\tDO track:"); for ( i=0; i<etd.i; i++ ) fprintf(stderr, "%x ", etd.eedo[i]); fprintf(stderr, "\n\tData:%#x\n", etd.data); } memset(&etd, 0x0, sizeof(etd)); etd.op = next_op; return; } etd.eedo[etd.i] = eedo; etd.di[etd.i] = di; etd.i ++; if ( dir == EEPROM_READ && etd.op == DATA ) etd.data = (etd.data << 1) | eedo; else etd.data = (etd.data << 1) | di;}#define INT_NAME(x) \ ({ \ char *name = NULL; \ switch (x) \ { \ case INT_FCP: \ name = "FCP"; \ break; \ case INT_SWI: \ name = "SWI"; \ break; \ case INT_MDI: \ name = "MDI"; \ break; \ case INT_RNR: \ name = "RNR"; \ break; \ case INT_CNA: \ name = "CNA"; \ break; \ case INT_FR: \ name = "FR"; \ break; \ case INT_CX_TNO: \ name ="CX/TNO"; \ break; \ default: \ name ="Unknown"; \ } \ name; \ })#elsestatic void e100_dump(char *comment, uint8_t *info, int len) {}static void eeprom_trace(int eedo, int di, int dir, int next_op, int clr) {}#endifstatic void pci_reset(E100State * s){ uint8_t *pci_conf = s->pci_dev->config; memcpy(pci_conf, &e100_pci_configure[0], sizeof(e100_pci_configure)); logout("%p\n", s); /* I82557 */ PCI_CONFIG_8(E100_PCI_REVISION_ID, 0x01); PCI_CONFIG_8(0x3c, 0x0);}static void e100_selective_reset(E100State * s){ memset(s->pci_mem.mem, 0x0, sizeof(s->pci_mem.mem)); // Set RU/CU to idle, maintain the register mentioned in spec, SET_CU_STATE(CU_IDLE); SET_RU_STATE(RU_IDLE); logout("CU and RU go to idle\n"); s->ru_offset = 0; s->cu_offset = 0; s->cu_next = 0; // For 82557, special interrupt bits are all 1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -