Serenity Operating System
at hosted 398 lines 14 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <Kernel/Net/RTL8139NetworkAdapter.h> 28#include <LibBareMetal/IO.h> 29 30//#define RTL8139_DEBUG 31 32namespace Kernel { 33 34#define REG_MAC 0x00 35#define REG_MAR0 0x08 36#define REG_MAR4 0x12 37#define REG_TXSTATUS0 0x10 38#define REG_TXADDR0 0x20 39#define REG_RXBUF 0x30 40#define REG_COMMAND 0x37 41#define REG_CAPR 0x38 42#define REG_IMR 0x3C 43#define REG_ISR 0x3E 44#define REG_TXCFG 0x40 45#define REG_RXCFG 0x44 46#define REG_MPC 0x4C 47#define REG_CFG9346 0x50 48#define REG_CONFIG1 0x52 49#define REG_MSR 0x58 50#define REG_BMCR 0x62 51 52#define TX_STATUS_OWN 0x2000 53#define TX_STATUS_THRESHOLD_MAX 0x3F0000 54 55#define COMMAND_RX_EMPTY 0x01 56#define COMMAND_TX_ENABLE 0x04 57#define COMMAND_RX_ENABLE 0x08 58#define COMMAND_RESET 0x10 59 60#define INT_RXOK 0x01 61#define INT_RXERR 0x02 62#define INT_TXOK 0x04 63#define INT_TXERR 0x08 64#define INT_RX_BUFFER_OVERFLOW 0x10 65#define INT_LINK_CHANGE 0x20 66#define INT_RX_FIFO_OVERFLOW 0x40 67#define INT_LENGTH_CHANGE 0x2000 68#define INT_SYSTEM_ERROR 0x8000 69 70#define CFG9346_NONE 0x00 71#define CFG9346_EEM0 0x40 72#define CFG9346_EEM1 0x80 73 74#define TXCFG_TXRR_ZERO 0x00 75#define TXCFG_MAX_DMA_16B 0x000 76#define TXCFG_MAX_DMA_32B 0x100 77#define TXCFG_MAX_DMA_64B 0x200 78#define TXCFG_MAX_DMA_128B 0x300 79#define TXCFG_MAX_DMA_256B 0x400 80#define TXCFG_MAX_DMA_512B 0x500 81#define TXCFG_MAX_DMA_1K 0x600 82#define TXCFG_MAX_DMA_2K 0x700 83#define TXCFG_IFG11 0x3000000 84 85#define RXCFG_AAP 0x01 86#define RXCFG_APM 0x02 87#define RXCFG_AM 0x04 88#define RXCFG_AB 0x08 89#define RXCFG_AR 0x10 90#define RXCFG_WRAP_INHIBIT 0x80 91#define RXCFG_MAX_DMA_16B 0x000 92#define RXCFG_MAX_DMA_32B 0x100 93#define RXCFG_MAX_DMA_64B 0x200 94#define RXCFG_MAX_DMA_128B 0x300 95#define RXCFG_MAX_DMA_256B 0x400 96#define RXCFG_MAX_DMA_512B 0x500 97#define RXCFG_MAX_DMA_1K 0x600 98#define RXCFG_MAX_DMA_UNLIMITED 0x0700 99#define RXCFG_RBLN_8K 0x0000 100#define RXCFG_RBLN_16K 0x0800 101#define RXCFG_RBLN_32K 0x1000 102#define RXCFG_RBLN_64K 0x1800 103#define RXCFG_FTH_NONE 0xE000 104 105#define MSR_LINKB 0x02 106#define MSR_RX_FLOW_CONTROL_ENABLE 0x40 107 108#define BMCR_SPEED 0x2000 109#define BMCR_AUTO_NEGOTIATE 0x1000 110#define BMCR_DUPLEX 0x0100 111 112#define RX_MULTICAST 0x8000 113#define RX_PHYSICAL_MATCH 0x4000 114#define RX_BROADCAST 0x2000 115#define RX_INVALID_SYMBOL_ERROR 0x20 116#define RX_RUNT 0x10 117#define RX_LONG 0x08 118#define RX_CRC_ERROR 0x04 119#define RX_FRAME_ALIGNMENT_ERROR 0x02 120#define RX_OK 0x01 121 122#define PACKET_SIZE_MAX 0x600 123#define PACKET_SIZE_MIN 0x16 124 125#define RX_BUFFER_SIZE 32768 126#define TX_BUFFER_SIZE PACKET_SIZE_MAX 127 128void RTL8139NetworkAdapter::detect(const PCI::Address& address) 129{ 130 if (address.is_null()) 131 return; 132 static const PCI::ID rtl8139_id = { 0x10EC, 0x8139 }; 133 PCI::ID id = PCI::get_id(address); 134 if (id != rtl8139_id) 135 return; 136 u8 irq = PCI::get_interrupt_line(address); 137 (void)adopt(*new RTL8139NetworkAdapter(address, irq)).leak_ref(); 138} 139 140RTL8139NetworkAdapter::RTL8139NetworkAdapter(PCI::Address address, u8 irq) 141 : PCI::Device(address, irq) 142 , m_io_base(PCI::get_BAR0(pci_address()) & ~1) 143 , m_rx_buffer(MM.allocate_contiguous_kernel_region(PAGE_ROUND_UP(RX_BUFFER_SIZE + PACKET_SIZE_MAX), "RTL8139 RX", Region::Access::Read | Region::Access::Write)) 144 , m_packet_buffer(MM.allocate_contiguous_kernel_region(PAGE_ROUND_UP(PACKET_SIZE_MAX), "RTL8139 Packet buffer", Region::Access::Read | Region::Access::Write)) 145{ 146 m_tx_buffers.ensure_capacity(RTL8139_TX_BUFFER_COUNT); 147 set_interface_name("rtl8139"); 148 149 klog() << "RTL8139: Found @ " << pci_address(); 150 151 enable_bus_mastering(pci_address()); 152 153 m_interrupt_line = PCI::get_interrupt_line(pci_address()); 154 klog() << "RTL8139: port base: " << m_io_base; 155 klog() << "RTL8139: Interrupt line: " << m_interrupt_line; 156 157 // we add space to account for overhang from the last packet - the rtl8139 158 // can optionally guarantee that packets will be contiguous by 159 // purposefully overrunning the rx buffer 160 klog() << "RTL8139: RX buffer: " << m_rx_buffer->vmobject().physical_pages()[0]->paddr(); 161 162 for (int i = 0; i < RTL8139_TX_BUFFER_COUNT; i++) { 163 m_tx_buffers.append(MM.allocate_contiguous_kernel_region(PAGE_ROUND_UP(TX_BUFFER_SIZE), "RTL8139 TX", Region::Access::Write | Region::Access::Read)); 164 klog() << "RTL8139: TX buffer " << i << ": " << m_tx_buffers[i]->vmobject().physical_pages()[0]->paddr(); 165 } 166 167 reset(); 168 169 read_mac_address(); 170 const auto& mac = mac_address(); 171 klog() << "RTL8139: MAC address: " << mac.to_string().characters(); 172 173 enable_irq(); 174} 175 176RTL8139NetworkAdapter::~RTL8139NetworkAdapter() 177{ 178} 179 180void RTL8139NetworkAdapter::handle_irq(const RegisterState&) 181{ 182 for (;;) { 183 int status = in16(REG_ISR); 184 out16(REG_ISR, status); 185 186#ifdef RTL8139_DEBUG 187 klog() << "RTL8139NetworkAdapter::handle_irq status=0x" << String::format("%x", status); 188#endif 189 190 if ((status & (INT_RXOK | INT_RXERR | INT_TXOK | INT_TXERR | INT_RX_BUFFER_OVERFLOW | INT_LINK_CHANGE | INT_RX_FIFO_OVERFLOW | INT_LENGTH_CHANGE | INT_SYSTEM_ERROR)) == 0) 191 break; 192 193 if (status & INT_RXOK) { 194#ifdef RTL8139_DEBUG 195 klog() << "RTL8139NetworkAdapter: rx ready"; 196#endif 197 receive(); 198 } 199 if (status & INT_RXERR) { 200 klog() << "RTL8139NetworkAdapter: rx error - resetting device"; 201 reset(); 202 } 203 if (status & INT_TXOK) { 204#ifdef RTL8139_DEBUG 205 klog() << "RTL8139NetworkAdapter: tx complete"; 206#endif 207 } 208 if (status & INT_TXERR) { 209 klog() << "RTL8139NetworkAdapter: tx error - resetting device"; 210 reset(); 211 } 212 if (status & INT_RX_BUFFER_OVERFLOW) { 213 klog() << "RTL8139NetworkAdapter: rx buffer overflow"; 214 } 215 if (status & INT_LINK_CHANGE) { 216 m_link_up = (in8(REG_MSR) & MSR_LINKB) == 0; 217 klog() << "RTL8139NetworkAdapter: link status changed up=" << m_link_up; 218 } 219 if (status & INT_RX_FIFO_OVERFLOW) { 220 klog() << "RTL8139NetworkAdapter: rx fifo overflow"; 221 } 222 if (status & INT_LENGTH_CHANGE) { 223 klog() << "RTL8139NetworkAdapter: cable length change"; 224 } 225 if (status & INT_SYSTEM_ERROR) { 226 klog() << "RTL8139NetworkAdapter: system error - resetting device"; 227 reset(); 228 } 229 } 230} 231 232void RTL8139NetworkAdapter::reset() 233{ 234 m_rx_buffer_offset = 0; 235 m_tx_next_buffer = 0; 236 237 // reset the device to clear out all the buffers and config 238 out8(REG_COMMAND, COMMAND_RESET); 239 while ((in8(REG_COMMAND) & COMMAND_RESET) != 0) 240 ; 241 242 // unlock config registers 243 out8(REG_CFG9346, CFG9346_EEM0 | CFG9346_EEM1); 244 // turn on multicast 245 out32(REG_MAR0, 0xffffffff); 246 out32(REG_MAR4, 0xffffffff); 247 // enable rx/tx 248 out8(REG_COMMAND, COMMAND_RX_ENABLE | COMMAND_TX_ENABLE); 249 // device might be in sleep mode, this will take it out 250 out8(REG_CONFIG1, 0); 251 // set up rx buffer 252 out32(REG_RXBUF, m_rx_buffer->vmobject().physical_pages()[0]->paddr().get()); 253 // reset missed packet counter 254 out8(REG_MPC, 0); 255 // "basic mode control register" options - 100mbit, full duplex, auto 256 // negotiation 257 out16(REG_BMCR, BMCR_SPEED | BMCR_AUTO_NEGOTIATE | BMCR_DUPLEX); 258 // enable flow control 259 out8(REG_MSR, MSR_RX_FLOW_CONTROL_ENABLE); 260 // configure rx: accept physical (MAC) match, multicast, and broadcast, 261 // use the optional contiguous packet feature, the maximum dma transfer 262 // size, a 32k buffer, and no fifo threshold 263 out32(REG_RXCFG, RXCFG_APM | RXCFG_AM | RXCFG_AB | RXCFG_WRAP_INHIBIT | RXCFG_MAX_DMA_UNLIMITED | RXCFG_RBLN_32K | RXCFG_FTH_NONE); 264 // configure tx: default retry count (16), max DMA burst size of 1024 265 // bytes, interframe gap time of the only allowable value. the DMA burst 266 // size is important - silent failures have been observed with 2048 bytes. 267 out32(REG_TXCFG, TXCFG_TXRR_ZERO | TXCFG_MAX_DMA_1K | TXCFG_IFG11); 268 // tell the chip where we want it to DMA from for outgoing packets. 269 for (int i = 0; i < 4; i++) 270 out32(REG_TXADDR0 + (i * 4), m_tx_buffers[i]->vmobject().physical_pages()[0]->paddr().get()); 271 // re-lock config registers 272 out8(REG_CFG9346, CFG9346_NONE); 273 // enable rx/tx again in case they got turned off (apparently some cards 274 // do this?) 275 out8(REG_COMMAND, COMMAND_RX_ENABLE | COMMAND_TX_ENABLE); 276 277 // choose irqs, then clear any pending 278 out16(REG_IMR, INT_RXOK | INT_RXERR | INT_TXOK | INT_TXERR | INT_RX_BUFFER_OVERFLOW | INT_LINK_CHANGE | INT_RX_FIFO_OVERFLOW | INT_LENGTH_CHANGE | INT_SYSTEM_ERROR); 279 out16(REG_ISR, 0xffff); 280} 281 282void RTL8139NetworkAdapter::read_mac_address() 283{ 284 u8 mac[6]; 285 for (int i = 0; i < 6; i++) 286 mac[i] = in8(REG_MAC + i); 287 set_mac_address(mac); 288} 289 290void RTL8139NetworkAdapter::send_raw(const u8* data, size_t length) 291{ 292#ifdef RTL8139_DEBUG 293 klog() << "RTL8139NetworkAdapter::send_raw length=" << length; 294#endif 295 296 if (length > PACKET_SIZE_MAX) { 297 klog() << "RTL8139NetworkAdapter: packet was too big; discarding"; 298 return; 299 } 300 301 int hw_buffer = -1; 302 for (int i = 0; i < RTL8139_TX_BUFFER_COUNT; i++) { 303 int potential_buffer = (m_tx_next_buffer + i) % 4; 304 305 auto status = in32(REG_TXSTATUS0 + (potential_buffer * 4)); 306 if (status & TX_STATUS_OWN) { 307 hw_buffer = potential_buffer; 308 break; 309 } 310 } 311 312 if (hw_buffer == -1) { 313 klog() << "RTL8139NetworkAdapter: hardware buffers full; discarding packet"; 314 return; 315 } else { 316#ifdef RTL8139_DEBUG 317 klog() << "RTL8139NetworkAdapter: chose buffer " << hw_buffer << " @ " << PhysicalAddress(m_tx_buffer_addr[hw_buffer]); 318#endif 319 m_tx_next_buffer = (hw_buffer + 1) % 4; 320 } 321 322 memcpy(m_tx_buffers[hw_buffer]->vaddr().as_ptr(), data, length); 323 memset(m_tx_buffers[hw_buffer]->vaddr().as_ptr() + length, 0, TX_BUFFER_SIZE - length); 324 325 // the rtl8139 will not actually emit packets onto the network if they're 326 // smaller than 64 bytes. the rtl8139 adds a checksum to the end of each 327 // packet, and that checksum is four bytes long, so we pad the packet to 328 // 60 bytes if necessary to make sure the whole thing is large enough. 329 if (length < 60) { 330#ifdef RTL8139_DEBUG 331 klog() << "RTL8139NetworkAdapter: adjusting payload size from " << length << " to 60"; 332#endif 333 length = 60; 334 } 335 336 out32(REG_TXSTATUS0 + (hw_buffer * 4), length); 337} 338 339void RTL8139NetworkAdapter::receive() 340{ 341 auto* start_of_packet = m_rx_buffer->vaddr().as_ptr() + m_rx_buffer_offset; 342 343 u16 status = *(const u16*)(start_of_packet + 0); 344 u16 length = *(const u16*)(start_of_packet + 2); 345 346#ifdef RTL8139_DEBUG 347 klog() << "RTL8139NetworkAdapter::receive status=0x" << String::format("%x", status) << " length=" << length << " offset=" << m_rx_buffer_offset; 348#endif 349 350 if (!(status & RX_OK) || (status & (RX_INVALID_SYMBOL_ERROR | RX_CRC_ERROR | RX_FRAME_ALIGNMENT_ERROR)) || (length >= PACKET_SIZE_MAX) || (length < PACKET_SIZE_MIN)) { 351 klog() << "RTL8139NetworkAdapter::receive got bad packet status=0x" << String::format("%x", status) << " length=" << length; 352 reset(); 353 return; 354 } 355 356 // we never have to worry about the packet wrapping around the buffer, 357 // since we set RXCFG_WRAP_INHIBIT, which allows the rtl8139 to write data 358 // past the end of the alloted space. 359 memcpy(m_packet_buffer->vaddr().as_ptr(), (const u8*)(start_of_packet + 4), length - 4); 360 // let the card know that we've read this data 361 m_rx_buffer_offset = ((m_rx_buffer_offset + length + 4 + 3) & ~3) % RX_BUFFER_SIZE; 362 out16(REG_CAPR, m_rx_buffer_offset - 0x10); 363 m_rx_buffer_offset %= RX_BUFFER_SIZE; 364 365 did_receive(m_packet_buffer->vaddr().as_ptr(), length - 4); 366} 367 368void RTL8139NetworkAdapter::out8(u16 address, u8 data) 369{ 370 m_io_base.offset(address).out(data); 371} 372 373void RTL8139NetworkAdapter::out16(u16 address, u16 data) 374{ 375 m_io_base.offset(address).out(data); 376} 377 378void RTL8139NetworkAdapter::out32(u16 address, u32 data) 379{ 380 m_io_base.offset(address).out(data); 381} 382 383u8 RTL8139NetworkAdapter::in8(u16 address) 384{ 385 return m_io_base.offset(address).in<u8>(); 386} 387 388u16 RTL8139NetworkAdapter::in16(u16 address) 389{ 390 return m_io_base.offset(address).in<u16>(); 391} 392 393u32 RTL8139NetworkAdapter::in32(u16 address) 394{ 395 return m_io_base.offset(address).in<u32>(); 396} 397 398}