rtl8139.c (8301B)
1 /* 2 * core/rtl8139.c 3 * 4 * Copyright (C) 2010 stateless 5 */ 6 7 #include <rtl8139.h> 8 #include <pci.h> 9 #include <x86.h> 10 #include <idt.h> 11 #include <heap.h> 12 #include <rtc.h> 13 #include <string.h> 14 #include <errno.h> 15 16 #define INTMASK (RTL_INT_PCIERR | RTL_INT_RX_ERR \ 17 | RTL_INT_RX_OK | RTL_INT_TX_ERR \ 18 | RTL_INT_TX_OK | RTL_INT_RXBUF_OVERFLOW) 19 20 enum { 21 RTL_VENDOR_ID = 0x10ec, 22 RTL_DEVICE_ID = 0x8139, 23 RTL_RESET_TIMEOUT = 20 /* 200 ms */ 24 }; 25 26 /* NOTE: register naming comes from NetBSD-DC sources. */ 27 enum rtl_registers { 28 RTL_IDR0 = 0x00, /* Mac address */ 29 RTL_MAR0 = 0x08, /* Multicast filter */ 30 RTL_TXSTATUS0 = 0x10, /* Transmit status (4 32bit regs) */ 31 RTL_TXSTATUS1 = 0x14, /* Transmit status (4 32bit regs) */ 32 RTL_TXSTATUS2 = 0x18, /* Transmit status (4 32bit regs) */ 33 RTL_TXSTATUS3 = 0x1c, /* Transmit status (4 32bit regs) */ 34 RTL_TXADDR0 = 0x20, /* Tx descriptors (also 4 32bit) */ 35 RTL_TXADDR1 = 0x24, /* Tx descriptors (also 4 32bit) */ 36 RTL_TXADDR2 = 0x28, /* Tx descriptors (also 4 32bit) */ 37 RTL_TXADDR3 = 0x2c, /* Tx descriptors (also 4 32bit) */ 38 RTL_RXBUF = 0x30, /* Receive buffer start address */ 39 RTL_RXEARLYCNT = 0x34, /* Early Rx byte count */ 40 RTL_RXEARLYSTATUS = 0x36, /* Early Rx status */ 41 RTL_CHIPCMD = 0x37, /* Command register */ 42 RTL_RXBUFTAIL = 0x38, /* Current address of packet read (queue tail) */ 43 RTL_RXBUFHEAD = 0x3A, /* Current buffer address (queue head) */ 44 RTL_INTRMASK = 0x3C, /* Interrupt mask */ 45 RTL_INTRSTATUS = 0x3E, /* Interrupt status */ 46 RTL_TXCONFIG = 0x40, /* Tx config */ 47 RTL_RXCONFIG = 0x44, /* Rx config */ 48 RTL_TIMER = 0x48, /* A general purpose counter */ 49 RTL_RXMISSED = 0x4C, /* 24 bits valid, write clears */ 50 RTL_CFG9346 = 0x50, /* 93C46 command register */ 51 RTL_CONFIG0 = 0x51, /* Configuration reg 0 */ 52 RTL_CONFIG1 = 0x52, /* Configuration reg 1 */ 53 RTL_TIMERINT = 0x54, /* Timer interrupt register (32 bits) */ 54 RTL_MEDIASTATUS = 0x58, /* Media status register */ 55 RTL_CONFIG3 = 0x59, /* Config register 3 */ 56 RTL_CONFIG4 = 0x5A, /* Config register 4 */ 57 RTL_MULTIINTR = 0x5C, /* Multiple interrupt select */ 58 RTL_MII_TSAD = 0x60, /* Transmit status of all descriptors (16 bits) */ 59 RTL_MII_BMCR = 0x62, /* Basic Mode Control Register (16 bits) */ 60 RTL_MII_BMSR = 0x64, /* Basic Mode Status Register (16 bits) */ 61 RTL_AS_ADVERT = 0x66, /* Auto-negotiation advertisement reg (16 bits) */ 62 RTL_AS_LPAR = 0x68, /* Auto-negotiation link partner reg (16 bits) */ 63 RTL_AS_EXPANSION = 0x6A /* Auto-negotiation expansion reg (16 bits) */ 64 }; 65 66 enum rtl_command_bits { 67 RTL_CMD_RESET = 0x10, 68 RTL_CMD_RX_ENABLE = 0x08, 69 RTL_CMD_TX_ENABLE = 0x04, 70 RTL_CMD_RX_BUF_EMPTY = 0x01 71 }; 72 73 enum rtl_int_status { 74 RTL_INT_PCIERR = 0x8000, /* PCI Bus error */ 75 RTL_INT_TIMEOUT = 0x4000, /* Set when TCTR reaches TimerInt value */ 76 RTL_INT_RXFIFO_OVERFLOW = 0x0040, /* Rx FIFO overflow */ 77 RTL_INT_RXFIFO_UNDERRUN = 0x0020, /* Packet underrun / link change */ 78 RTL_INT_RXBUF_OVERFLOW = 0x0010, /* Rx BUFFER overflow */ 79 RTL_INT_TX_ERR = 0x0008, 80 RTL_INT_TX_OK = 0x0004, 81 RTL_INT_RX_ERR = 0x0002, 82 RTL_INT_RX_OK = 0x0001 83 }; 84 85 enum rtl_tx_status { 86 RTL_TX_CARRIER_LOST = 0x80000000, /* Carrier sense lost */ 87 RTL_TX_ABORTED = 0x40000000, /* Transmission aborted */ 88 RTL_TX_OUT_OF_WINDOW = 0x20000000, /* Out of window collision */ 89 RTL_TX_STATUS_OK = 0x00008000, /* Status ok: a good packet was transmitted */ 90 RTL_TX_UNDERRUN = 0x00004000, /* Transmit FIFO underrun */ 91 RTL_TX_HOST_OWNS = 0x00002000, /* Set to 1 when DMA operation is completed */ 92 RTL_TX_SIZE_MASK = 0x00001fff /* Descriptor size mask */ 93 }; 94 95 enum rtl_rx_status { 96 RTL_RX_MULTICAST = 0x00008000, /* Multicast packet */ 97 RTL_RX_PAM = 0x00004000, /* Physical address matched */ 98 RTL_RX_BROADCAST = 0x00002000, /* Broadcast address matched */ 99 RTL_RX_BAD_SYMBOL = 0x00000020, /* Invalid symbol in 100TX packet */ 100 RTL_RX_RUNT = 0x00000010, /* Packet size is <64 bytes */ 101 RTL_RX_TOO_LONG = 0x00000008, /* Packet size is >4K bytes */ 102 RTL_RX_CRC_ERR = 0x00000004, /* CRC error */ 103 RTL_RX_FRAME_ALIGN = 0x00000002, /* Frame alignment error */ 104 RTL_RX_STATUS_OK = 0x00000001 /* Status ok: a good packet was received */ 105 }; 106 107 struct rtl8139_t { 108 char rx_buffer[8192 + 16]; 109 uint8_t mac_addr[6]; 110 spinlock_t iolock; 111 uint32_t io_base; 112 } *rtl = NULL; 113 114 void 115 rtl8139_int(__attribute__ ((unused)) struct trapframe_t *regs) 116 { 117 panic("yoohoo!"); 118 } 119 120 static void 121 rtl_write8(uint16_t offset, uint8_t val) 122 { 123 acquire(&rtl->iolock); 124 outb(rtl->io_base + offset, val); 125 release(&rtl->iolock); 126 } 127 128 static void 129 rtl_write32(uint16_t offset, uint32_t val) 130 { 131 acquire(&rtl->iolock); 132 outl(rtl->io_base + offset, val); 133 release(&rtl->iolock); 134 } 135 136 static void 137 rtl_write16(uint16_t offset, uint16_t val) 138 { 139 acquire(&rtl->iolock); 140 outw(rtl->io_base + offset, val); 141 release(&rtl->iolock); 142 } 143 144 static uint8_t 145 rtl_read8(uint16_t offset) 146 { 147 uint8_t r; 148 149 acquire(&rtl->iolock); 150 r = inb(rtl->io_base + offset); 151 release(&rtl->iolock); 152 return r; 153 } 154 155 static uint32_t 156 rtl_read32(uint16_t offset) 157 { 158 uint32_t r; 159 160 acquire(&rtl->iolock); 161 r = inl(rtl->io_base + offset); 162 release(&rtl->iolock); 163 return r; 164 } 165 166 int 167 rtl8139_init(void) 168 { 169 struct pci_dev_t *dev; 170 uint32_t i, timeout = 0; 171 172 /* enumerate the PCI bus looking for an rtl8139 */ 173 dev = get_pci_dev(RTL_VENDOR_ID, RTL_DEVICE_ID); 174 if (!dev) 175 return -ENODEV; 176 177 rtl = kmalloc(sizeof(*rtl)); 178 if (IS_ERR(rtl)) 179 return PTR_ERR(rtl); 180 181 memset(rtl, 0, sizeof(*rtl)); 182 initspinlock(&rtl->iolock); 183 184 /* grab the io port base for all subsequence i/o operations */ 185 rtl->io_base = dev->cspace->type0.bar0 & 0xfffffffc; 186 187 /* reset the device */ 188 rtl_write8(RTL_CHIPCMD, RTL_CMD_RESET); 189 do { 190 if (timeout++ == RTL_RESET_TIMEOUT) 191 goto err; 192 msleep(1); /* sleep for ~10ms */ 193 } while (rtl_read8(RTL_CHIPCMD) & RTL_CMD_RESET); 194 195 register_isr_handler(0x20 + dev->cspace->type0.irq, rtl8139_int); 196 197 /* grab the mac-address */ 198 for (i = 0; i < 6; ++i) 199 rtl->mac_addr[i] = rtl_read8(i); 200 201 /* put the device in config mode to enable writing to the config registers */ 202 rtl_write8(RTL_CFG9346, 0xc0); 203 /* reset config 1 */ 204 rtl_write8(RTL_CONFIG1, 0); 205 /* go back to normal mode */ 206 rtl_write8(RTL_CFG9346, 0); 207 208 /* set the receive buffer address */ 209 rtl_write32(RTL_RXBUF, (uint32_t)rtl->rx_buffer); 210 /* TODO: setup the tx descriptors */ 211 212 #if 0 213 /* accept 214 * physical address packets, 215 * physical match packets, 216 * multicast packets, 217 * and broadcast packets 218 * enable wrap mode 219 */ 220 rtl_write32(RTL_RXCONFIG, 0xf | (1 << 7)); 221 /* make sure IRQs will fire */ 222 rtl_write32(RTL_INTRMASK, RTL_INT_TX_OK | RTL_INT_RX_OK); 223 #else 224 rtl_write32(RTL_RXMISSED, 0); 225 rtl_write32(RTL_RXCONFIG, rtl_read32(RTL_RXCONFIG) | 0x0000000f); 226 rtl_write32(RTL_MAR0, 0); 227 rtl_write32(RTL_MAR0 + 4, 0); 228 rtl_write16(RTL_MULTIINTR, 0); 229 rtl_write16(RTL_INTRMASK, INTMASK); 230 #endif 231 232 /* enable the receiver and the transmitter */ 233 rtl_write32(RTL_CHIPCMD, RTL_CMD_RX_ENABLE | RTL_CMD_TX_ENABLE); 234 /* just to be on the safe side */ 235 rtl_write8(RTL_CFG9346, 0); 236 return 0; 237 err: 238 kfree(rtl); 239 return -EBUSY; 240 } 241 242 const uint8_t * 243 get_mac_addr(void) 244 { 245 if (!rtl) 246 return NULL; 247 return rtl->mac_addr; 248 } 249