void e1000_turn_on(struct e1000_dev *dev) { int tx_control, rx_control; uint32_t ims = 0; // turn on the controller's receive engine rx_control = e1000_inl(dev, E1000_RCTL); rx_control |= (1<<1); e1000_outl(dev, E1000_RCTL, rx_control); // turn on the controller's transmit engine tx_control = e1000_inl(dev, E1000_TCTL); tx_control |= (1<<1); e1000_outl(dev, E1000_TCTL, tx_control); // enable the controller's interrupts e1000_outl(dev, E1000_ICR, 0xFFFFFFFF); e1000_outl(dev, E1000_IMC, 0xFFFFFFFF); ims |= 1<<0; // TXDW ims |= 1<<1; // TXQE ims |= 1<<2; // LSC ims |= 1<<4; // RXDMT0 ims |= 1<<7; // RXT0 e1000_outl(dev, E1000_IMS, ims); }
void e1000_turn_on(struct e1000_dev *dev) { int tx_control; int rx_control; uint32_t ims = 0; /* turn on the controller's receive engine */ rx_control = e1000_inl(dev, E1000_RCTL); rx_control |= (1 << 1); e1000_outl(dev, E1000_RCTL, rx_control); /* turn on the controller's transmit engine */ tx_control = e1000_inl(dev, E1000_TCTL); tx_control |= (1 << 1); e1000_outl(dev, E1000_TCTL, tx_control); /* enable the controller's interrupts */ e1000_outl(dev, E1000_ICR, 0xFFFFFFFF); e1000_outl(dev, E1000_IMC, 0xFFFFFFFF); ims |= 1 << 0; /* TXDW */ ims |= 1 << 1; /* TXQE */ ims |= 1 << 2; /* LSC */ ims |= 1 << 4; /* RXDMT0 */ ims |= 1 << 7; /* RXT0 */ e1000_outl(dev, E1000_IMS, ims); }
static irqreturn_t e1000_interrupt_handler(int irq, void *dev_id) { struct e1000_dev *e1000 = (struct e1000_dev *)dev_id; /* Get and clear interrupt status bits */ int intr_cause = e1000_inl(e1000, E1000_ICR); e1000_outl(e1000, E1000_ICR, intr_cause); // not for me if (intr_cause == 0) return IRQ_NONE; /* Handle interrupts according to status bit settings */ // Link status change if (intr_cause & (1<<2)) { if (e1000_inl(e1000, E1000_STATUS) & 2) e1000->bifup = true; else e1000->bifup = false; } /* Check if we received an incoming packet, if so, call skel_receive() */ // Rx-descriptor Timer expired if (intr_cause & (1<<7)) e1000_receive(e1000); // Tx queue empty if (intr_cause & (1<<1)) wd_cancel(e1000->txtimeout); /* Check is a packet transmission just completed. If so, call skel_txdone. * This may disable further Tx interrupts if there are no pending * tansmissions. */ // Tx-descriptor Written back if (intr_cause & (1<<0)) uip_poll(&e1000->uip_dev, e1000_uiptxpoll); // Rx-Descriptors Low if (intr_cause & (1<<4)) { int tail; tail = e1000->rx_ring.tail + e1000->rx_ring.free; tail %= CONFIG_E1000_N_RX_DESC; e1000->rx_ring.tail = tail; e1000->rx_ring.free = 0; e1000_outl(e1000, E1000_RDT, tail); } return IRQ_HANDLED; }
void e1000_turn_off(struct e1000_dev *dev) { int tx_control, rx_control; // turn off the controller's receive engine rx_control = e1000_inl(dev, E1000_RCTL); rx_control &= ~(1<<1); e1000_outl(dev, E1000_RCTL, rx_control); // turn off the controller's transmit engine tx_control = e1000_inl(dev, E1000_TCTL); tx_control &= ~(1<<1); e1000_outl(dev, E1000_TCTL, tx_control); // turn off the controller's interrupts e1000_outl(dev, E1000_IMC, 0xFFFFFFFF); }
struct network_dev *e1000_init() { struct network_dev *device = kcalloc(sizeof(*device), 1); struct e1000 *e = (struct e1000 *)kmalloc(sizeof(*e)); e1000_global = e; device->device = e; e->dev = device; e->pci = pci_get_device(INTEL_VEND, E1000_DEV); if(e->pci == NULL) { e->pci = pci_get_device(INTEL_VEND, 0x109a); } if(e->pci == NULL) { e->pci = pci_get_device(INTEL_VEND, 0x100f); } if(e->pci != NULL) { e->pci_hdr = e->pci->header; printf("Intel Pro/1000 Ethernet adapter Rev %i found at ", e->pci_hdr->rev); e->io_base = pci_get_bar(e->pci, PCI_BAR_IO) & ~1; printf("I/O base address %x\n",e->io_base); //e->mem_base = (uint8_t *)(pci_get_bar(e->pci, PCI_BAR_MEM) & ~3); //printf("mem base %x\n",e->mem_base); printf("IRQ %i PIN %i\n",e->pci_hdr->int_line, e->pci_hdr->int_pin); e1000_eeprom_gettype(e); e1000_getmac(e, (char *)device->mac); print_mac((char *)&device->mac); // for(int i = 0; i < 6; i++) // e1000_outb(e,0x5400 + i, device->mac[i]); pci_register_irq(e->pci, &e1000_handler, e); e1000_start(e); device->send = e1000_send; // device->receive = e1000_receive; uint32_t flags = e1000_inl(e, REG_RCTRL); e1000_outl(e, REG_RCTRL, flags | RCTRL_EN);//RCTRL_8192 | RCTRL_MPE | RCTRL_UPE |RCTRL_EN); } else { kfree(e); kfree(device); e = NULL; device = NULL; } return device; }
size_t e1000_send(struct network_dev *dev, uint8_t *_buf, size_t length) { struct e1000 *e = dev->device; e->tx_descs[e->tx_cur]->addr = (uint64_t)(uintptr_t)V2P(_buf); e->tx_descs[e->tx_cur]->length = length; e->tx_descs[e->tx_cur]->cmd = ((1 << 3) | 3); uint8_t old_cur = e->tx_cur; e->tx_cur = (e->tx_cur + 1) % NUM_TX_DESC; e1000_outl(e, REG_TXDESCTAIL, e->tx_cur); while(!(e->tx_descs[old_cur]->status & 0xff)); return 0; }
void e1000_reset(struct e1000_dev *dev) { uint32_t dev_control; // Reset the network controller hardware dev_control = 0; dev_control |= (1<<0); // FD-bit (Full Duplex) dev_control |= (0<<2); // GIOMD-bit (GIO Master Disable) dev_control |= (1<<3); // LRST-bit (Link Reset) dev_control |= (1<<6); // SLU-bit (Set Link Up) dev_control |= (2<<8); // SPEED=2 (1000Mbps) dev_control |= (0<<11); // FRCSPD-bit (Force Speed) dev_control |= (0<<12); // FRCDPLX-bit (Force Duplex) dev_control |= (0<<20); // ADVD3WUC-bit (Advertise D3 Wake Up Cap) dev_control |= (1<<26); // RST-bit (Device Reset) dev_control |= (1<<27); // RFCE-bit (Receive Flow Control Enable) dev_control |= (1<<28); // TFCE-bit (Transmit Flow Control Enable) dev_control |= (0<<30); // VME-bit (VLAN Mode Enable) dev_control |= (0<<31); // PHY_RST-bit (PHY Reset) e1000_outl(dev, E1000_IMC, 0xFFFFFFFF); e1000_outl(dev, E1000_STATUS, 0x00000000); e1000_outl(dev, E1000_CTRL, dev_control); dev_control &= ~(1<<26); // clear RST-bit (Device Reset) e1000_outl(dev, E1000_CTRL, dev_control); up_mdelay(10); e1000_outl(dev, E1000_CTRL_EXT, 0x001401C0); e1000_outl(dev, E1000_IMC, 0xFFFFFFFF); }
void e1000_txinit(struct e1000 *e) { uintptr_t ptr; struct e1000_tx_desc *descs; ptr = (uintptr_t)(kmalloc(sizeof(struct e1000_tx_desc)*NUM_TX_DESC + 16)); e->tx_free = (uint8_t *)ptr; if(ptr % 16 != 0) ptr = (ptr + 16) - (ptr % 16); descs = (struct e1000_tx_desc *)ptr; for(int i = 0; i < NUM_TX_DESC; i++) { e->tx_descs[i] = (struct e1000_tx_desc *)((uintptr_t)descs + i*16); e->tx_descs[i]->addr = 0; e->tx_descs[i]->cmd = 0; } //give the card the pointer to the descriptors e1000_outl(e, REG_TXDESCLO, V2P(ptr)); e1000_outl(e, REG_TXDESCHI, 0); //now setup total length of descriptors e1000_outl(e, REG_TXDESCLEN, NUM_TX_DESC * 16); //setup numbers e1000_outl(e, REG_TXDESCHEAD, 0); e1000_outl(e, REG_TXDESCTAIL, NUM_TX_DESC); e->tx_cur = 0; e1000_outl(e, REG_TCTRL, (1 << 1) | (1 << 3)); }
void e1000_rxinit(struct e1000 *e) { uintptr_t ptr; struct e1000_rx_desc *descs; ptr = (uintptr_t)(kmalloc(sizeof(struct e1000_rx_desc)*NUM_RX_DESC + 16)); e->rx_free = (uint8_t *)ptr; if(ptr % 16 != 0) ptr = (ptr + 16) - (ptr % 16); descs = (struct e1000_rx_desc *)ptr; for(int i = 0; i < NUM_RX_DESC; i++) { e->rx_descs[i] = (struct e1000_rx_desc *)((uintptr_t)descs + i*16); e->rx_descs[i]->addr = (uint64_t)(uintptr_t)V2P(kmalloc(8192 + 16)); e->rx_descs[i]->status = 0; } //give the card the pointer to the descriptors e1000_outl(e, REG_RXDESCLO, V2P(ptr)); e1000_outl(e, REG_RXDESCHI, 0); //now setup total length of descriptors e1000_outl(e, REG_RXDESCLEN, NUM_RX_DESC * 16); //setup numbers e1000_outl(e, REG_RXDESCHEAD, 0); e1000_outl(e, REG_RXDESCTAIL, NUM_RX_DESC); e->rx_cur = 0; //enable receiving //uint32_t flags = (2 << 16) | (1 << 25) | (1 << 26) | (1 << 15) | (1 << 5) | (0 << 8) | (1 << 4) | (1 << 3) | ( 1 << 2); uint32_t flags = (2 << 16) | (1 << 25) | (1 << 26) | (1 << 15) | (1 << 5) | (0 << 8) | (0 << 4) | (0 << 3) | ( 1 << 2); // uint32_t flags = (2 << 16) | (1 << 25) | (1 << 26) | (1 << 15) | (1 << 5) | (0 << 8) | (1 << 4) | ( 1 << 2); // e1000_outl(e, REG_RCTRL, RCTRL_8192 | RCTRL_MPE); e1000_outl(e, REG_RCTRL, flags);//RCTRL_8192 | RCTRL_MPE | RCTRL_UPE |RCTRL_EN); }
void e1000_start(struct e1000 *e) { //set link up e1000_linkup(e); //have to clear out the multicast filter, otherwise shit breaks for(int i = 0; i < 0x80; i++) e1000_outl(e, 0x5200 + i*4, 0); e1000_interrupt_enable(e); e1000_rxinit(e); e1000_txinit(e); }
void e1000_eeprom_gettype(struct e1000 *e) { uint32_t val = 0; e1000_outl(e, REG_EEPROM, 0x1); for(int i = 0; i < 1000; i++)///while( val & 0x2 || val & 0x10) { val = e1000_inl(e, REG_EEPROM); if(val & 0x10) e->is_e = 0; else e->is_e = 1; } }
void e1000_received(struct e1000 *e) { struct sockbuf *sb; uint16_t old_cur; while((e->rx_descs[e->rx_cur]->status & 0x1)) { uint8_t *buf = (void *)(uintptr_t)P2V(e->rx_descs[e->rx_cur]->addr); uint16_t len = e->rx_descs[e->rx_cur]->length; sb = sockbuf_alloc(e->dev, len); kmemcpy(sb->data, buf, len); network_received(sb); e->rx_descs[e->rx_cur]->status = 0; old_cur = e->rx_cur; e->rx_cur = (e->rx_cur + 1) % NUM_RX_DESC; e1000_outl(e, REG_RXDESCTAIL, old_cur ) ; } }
uint32_t e1000_eeprom_read(struct e1000 *e, uint8_t addr) { uint32_t val = 0; uint32_t test; if(e->is_e == 0) test = addr << 8; else test = addr << 2; e1000_outl(e, REG_EEPROM, test | 0x1); if(e->is_e == 0) while(!((val = e1000_inl(e, REG_EEPROM)) & (1<<4))) ;// printf("is %i val %x\n",e->is_e,val); else while(!((val = e1000_inl(e, REG_EEPROM)) & (1<<1))) ;// printf("is %i val %x\n",e->is_e,val); val >>= 16; return val; }
static int e1000_transmit(struct e1000_dev *e1000) { int tail = e1000->tx_ring.tail; unsigned char *cp = (unsigned char *) (e1000->tx_ring.buf + tail * CONFIG_E1000_BUFF_SIZE); int count = e1000->netdev.d_len; /* Verify that the hardware is ready to send another packet. If we get * here, then we are committed to sending a packet; Higher level logic * must have assured that there is not transmission in progress. */ if (!e1000->tx_ring.desc[tail].desc_status) { return -1; } /* Increment statistics */ /* Send the packet: address=skel->sk_dev.d_buf, length=skel->sk_dev.d_len */ memcpy(cp, e1000->netdev.d_buf, e1000->netdev.d_len); /* prepare the transmit-descriptor */ e1000->tx_ring.desc[tail].packet_length = count < 60 ? 60 : count; e1000->tx_ring.desc[tail].desc_status = 0; /* give ownership of this descriptor to the network controller */ tail = (tail + 1) % CONFIG_E1000_N_TX_DESC; e1000->tx_ring.tail = tail; e1000_outl(e1000, E1000_TDT, tail); /* Enable Tx interrupts */ /* Setup the TX timeout watchdog (perhaps restarting the timer) */ wd_start(e1000->txtimeout, E1000_TXTIMEOUT, e1000_txtimeout, 1, (uint32_t)e1000); return OK; }
void e1000_linkup(struct e1000 *e) { uint32_t val; val = e1000_inl(e,REG_CTRL); e1000_outl(e, REG_CTRL, val | ECTRL_SLU); }
void e1000_init(struct e1000_dev *dev) { uint32_t rxd_phys, txd_phys, kmem_phys; uint32_t rx_control, tx_control; uint32_t pba; int i; e1000_reset(dev); // configure the controller's 'receive' engine rx_control = 0; rx_control |= (0<<1); // EN-bit (Enable) rx_control |= (0<<2); // SPB-bit (Store Bad Packets) rx_control |= (0<<3); // UPE-bit (Unicast Promiscuous Mode) rx_control |= (1<<4); // MPE-bit (Multicast Promiscuous Mode) rx_control |= (0<<5); // LPE-bit (Long Packet Enable) rx_control |= (0<<6); // LBM=0 (Loop-Back Mode) rx_control |= (0<<8); // RDMTS=0 (Rx Descriptor Min Threshold Size) rx_control |= (0<<10); // DTYPE=0 (Descriptor Type) rx_control |= (0<<12); // MO=0 (Multicast Offset) rx_control |= (1<<15); // BAM-bit (Broadcast Address Mode) rx_control |= (0<<16); // BSIZE=0 (Buffer Size = 2048) rx_control |= (0<<18); // VLE-bit (VLAN filter Enable) rx_control |= (0<<19); // CFIEN-bit (Canonical Form Indicator Enable) rx_control |= (0<<20); // CFI-bit (Canonical Form Indicator) rx_control |= (1<<22); // DPF-bit (Discard Pause Frames) rx_control |= (0<<23); // PMCF-bit (Pass MAC Control Frames) rx_control |= (0<<25); // BSEX=0 (Buffer Size EXtension) rx_control |= (1<<26); // SECRC-bit (Strip Ethernet CRC) rx_control |= (0<<27); // FLEXBUF=0 (Flexible Buffer size) e1000_outl(dev, E1000_RCTL, rx_control); // configure the controller's 'transmit' engine tx_control = 0; tx_control |= (0<<1); // EN-bit (Enable) tx_control |= (1<<3); // PSP-bit (Pad Short Packets) tx_control |= (15<<4); // CT=15 (Collision Threshold) tx_control |= (63<<12); // COLD=63 (Collision Distance) tx_control |= (0<<22); // SWXOFF-bit (Software XOFF) tx_control |= (1<<24); // RTLC-bit (Re-Transmit on Late Collision) tx_control |= (0<<25); // UNORTX-bit (Underrun No Re-Transmit) tx_control |= (0<<26); // TXCSCMT=0 (TxDesc Mininum Threshold) tx_control |= (0<<28); // MULR-bit (Multiple Request Support) e1000_outl(dev, E1000_TCTL, tx_control); // hardware flow control pba = e1000_inl(dev, E1000_PBA); // get receive FIFO size pba = (pba & 0x000000ff)<<10; e1000_outl(dev, E1000_FCAL, 0x00C28001); e1000_outl(dev, E1000_FCAH, 0x00000100); e1000_outl(dev, E1000_FCT, 0x00008808); e1000_outl(dev, E1000_FCTTV, 0x00000680); e1000_outl(dev, E1000_FCRTL, (pba*8/10)|0x80000000); e1000_outl(dev, E1000_FCRTH, pba*9/10); // setup tx rings txd_phys = PADDR((uintptr_t)dev->tx_ring.desc); kmem_phys = PADDR((uintptr_t)dev->tx_ring.buf); for (i=0; i<CONFIG_E1000_N_TX_DESC; i++,kmem_phys+=CONFIG_E1000_BUFF_SIZE) { dev->tx_ring.desc[i].base_address = kmem_phys; dev->tx_ring.desc[i].packet_length = 0; dev->tx_ring.desc[i].cksum_offset = 0; dev->tx_ring.desc[i].cksum_origin = 0; dev->tx_ring.desc[i].desc_status = 1; dev->tx_ring.desc[i].desc_command = (1<<0)|(1<<1)|(1<<3); dev->tx_ring.desc[i].special_info = 0; } dev->tx_ring.tail = 0; e1000_outl(dev, E1000_TDT, 0); e1000_outl(dev, E1000_TDH, 0); // tell controller the location, size, and fetch-policy for Tx queue e1000_outl(dev, E1000_TDBAL, txd_phys); e1000_outl(dev, E1000_TDBAH, 0x00000000); e1000_outl(dev, E1000_TDLEN, CONFIG_E1000_N_TX_DESC*16); e1000_outl(dev, E1000_TXDCTL, 0x01010000); // setup rx rings rxd_phys = PADDR((uintptr_t)dev->rx_ring.desc); kmem_phys = PADDR((uintptr_t)dev->rx_ring.buf); for (i=0; i<CONFIG_E1000_N_RX_DESC; i++,kmem_phys+=CONFIG_E1000_BUFF_SIZE) { dev->rx_ring.desc[i].base_address = kmem_phys; dev->rx_ring.desc[i].packet_length = 0; dev->rx_ring.desc[i].packet_cksum = 0; dev->rx_ring.desc[i].desc_status = 0; dev->rx_ring.desc[i].desc_errors = 0; dev->rx_ring.desc[i].vlan_tag = 0; } dev->rx_ring.head = 0; dev->rx_ring.tail = CONFIG_E1000_N_RX_DESC-1; dev->rx_ring.free = 0; // give the controller ownership of all receive descriptors e1000_outl(dev, E1000_RDH, 0); e1000_outl(dev, E1000_RDT, CONFIG_E1000_N_RX_DESC-1); // tell controller the location, size, and fetch-policy for RX queue e1000_outl(dev, E1000_RDBAL, rxd_phys); e1000_outl(dev, E1000_RDBAH, 0x00000000); e1000_outl(dev, E1000_RDLEN, CONFIG_E1000_N_RX_DESC*16); e1000_outl(dev, E1000_RXDCTL, 0x01010000); e1000_turn_on(dev); }
void e1000_interrupt_enable(struct e1000 *e) { e1000_outl(e,REG_IMASK ,0x1F6DC); e1000_outl(e,REG_IMASK ,0xff & ~4); e1000_inl(e,0xc0); }