Changes in uspace/srv/hw/netif/dp8390/dp8390.c [3c106e88:7922dea] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hw/netif/dp8390/dp8390.c
r3c106e88 r7922dea 38 38 */ 39 39 40 /** @addtogroup ne200040 /** @addtogroup dp8390 41 41 * @{ 42 42 */ 43 43 44 44 /** @file 45 * 46 * NE2000 (based on DP8390) network interface core implementation. 47 * Only the basic NE2000 PIO (ISA) interface is supported, remote 48 * DMA is completely absent from this code for simplicity. 49 * 45 * DP8390 network interface core implementation. 50 46 */ 51 47 … … 53 49 #include <byteorder.h> 54 50 #include <errno.h> 55 #include <libarch/ddi.h> 56 #include <netif_skel.h> 51 #include <netif_local.h> 57 52 #include <net/packet.h> 58 53 #include <nil_interface.h> 59 54 #include <packet_client.h> 55 #include "dp8390_drv.h" 56 #include "dp8390_port.h" 60 57 #include "dp8390.h" 61 62 /** Page size */ 63 #define DP_PAGE 256 64 65 /** 6 * DP_PAGE >= 1514 bytes */ 66 #define SQ_PAGES 6 67 68 /* NE2000 implementation. */ 69 70 /** NE2000 Data Register */ 71 #define NE2K_DATA 0x0010 72 73 /** NE2000 Reset register */ 74 #define NE2K_RESET 0x001f 75 76 /** NE2000 data start */ 77 #define NE2K_START 0x4000 78 79 /** NE2000 data size */ 80 #define NE2K_SIZE 0x4000 81 82 /** NE2000 retry count */ 83 #define NE2K_RETRY 100 84 85 /** NE2000 error messages rate limiting */ 86 #define NE2K_ERL 10 87 88 /** Minimum Ethernet packet size in bytes */ 89 #define ETH_MIN_PACK_SIZE 60 90 91 /** Maximum Ethernet packet size in bytes */ 92 #define ETH_MAX_PACK_SIZE_TAGGED 1518 93 94 /** Type definition of the receive header 95 * 96 */ 97 typedef struct { 98 /** Copy of RSR */ 99 uint8_t status; 100 101 /** Pointer to next packet */ 102 uint8_t next; 103 104 /** Receive Byte Count Low */ 105 uint8_t rbcl; 106 107 /** Receive Byte Count High */ 108 uint8_t rbch; 109 } recv_header_t; 58 #include "ne2000.h" 59 60 /** Read a memory block byte by byte. 61 * 62 * @param[in] port The source address. 63 * @param[out] buf The destination buffer. 64 * @param[in] size The memory block size in bytes. 65 * 66 */ 67 static void outsb(port_t port, void * buf, size_t size); 110 68 111 69 /** Read a memory block word by word. 112 70 * 113 * @param[in] port Source address. 114 * @param[out] buf Destination buffer. 115 * @param[in] size Memory block size in bytes. 116 * 117 */ 118 static void pio_read_buf_16(void *port, void *buf, size_t size) 119 { 120 size_t i; 121 122 for (i = 0; (i << 1) < size; i++) 123 *((uint16_t *) buf + i) = pio_read_16((ioport16_t *) (port)); 124 } 125 126 /** Write a memory block word by word. 127 * 128 * @param[in] port Destination address. 129 * @param[in] buf Source buffer. 130 * @param[in] size Memory block size in bytes. 131 * 132 */ 133 static void pio_write_buf_16(void *port, void *buf, size_t size) 134 { 135 size_t i; 136 137 for (i = 0; (i << 1) < size; i++) 138 pio_write_16((ioport16_t *) port, *((uint16_t *) buf + i)); 139 } 140 141 static void ne2k_download(ne2k_t *ne2k, void *buf, size_t addr, size_t size) 142 { 143 size_t esize = size & ~1; 144 145 pio_write_8(ne2k->port + DP_RBCR0, esize & 0xff); 146 pio_write_8(ne2k->port + DP_RBCR1, (esize >> 8) & 0xff); 147 pio_write_8(ne2k->port + DP_RSAR0, addr & 0xff); 148 pio_write_8(ne2k->port + DP_RSAR1, (addr >> 8) & 0xff); 149 pio_write_8(ne2k->port + DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA); 150 151 if (esize != 0) { 152 pio_read_buf_16(ne2k->data_port, buf, esize); 153 size -= esize; 154 buf += esize; 155 } 156 157 if (size) { 158 assert(size == 1); 159 160 uint16_t word = pio_read_16(ne2k->data_port); 161 memcpy(buf, &word, 1); 162 } 163 } 164 165 static void ne2k_upload(ne2k_t *ne2k, void *buf, size_t addr, size_t size) 166 { 167 size_t esize = size & ~1; 168 169 pio_write_8(ne2k->port + DP_RBCR0, esize & 0xff); 170 pio_write_8(ne2k->port + DP_RBCR1, (esize >> 8) & 0xff); 171 pio_write_8(ne2k->port + DP_RSAR0, addr & 0xff); 172 pio_write_8(ne2k->port + DP_RSAR1, (addr >> 8) & 0xff); 173 pio_write_8(ne2k->port + DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA); 174 175 if (esize != 0) { 176 pio_write_buf_16(ne2k->data_port, buf, esize); 177 size -= esize; 178 buf += esize; 179 } 180 181 if (size) { 182 assert(size == 1); 183 184 uint16_t word = 0; 185 186 memcpy(&word, buf, 1); 187 pio_write_16(ne2k->data_port, word); 188 } 189 } 190 191 /** Probe and initialize the network interface. 192 * 193 * @param[in,out] ne2k Network interface structure. 194 * @param[in] port Device address. 195 * @param[in] irq Device interrupt vector. 196 * 197 * @return EOK on success. 198 * @return EXDEV if the network interface was not recognized. 199 * 200 */ 201 int ne2k_probe(ne2k_t *ne2k, void *port, int irq) 202 { 71 * @param[in] port The source address. 72 * @param[out] buf The destination buffer. 73 * @param[in] size The memory block size in bytes. 74 * 75 */ 76 static void outsw(port_t port, void * buf, size_t size); 77 78 /* 79 * Some clones of the dp8390 and the PC emulator 'Bochs' require the CR_STA 80 * on writes to the CR register. Additional CR_STAs do not appear to hurt 81 * genuine dp8390s. 82 */ 83 #define CR_EXTRA CR_STA 84 85 static void dp_init(dpeth_t *dep); 86 static void dp_reinit(dpeth_t *dep); 87 static void dp_reset(dpeth_t *dep); 88 static void dp_recv(int nil_phone, device_id_t device_id, dpeth_t *dep); 89 static int dp_pkt2user(int nil_phone, device_id_t device_id, dpeth_t *dep, int page, int length); 90 static void conf_hw(dpeth_t *dep); 91 static void insb(port_t port, void *buf, size_t size); 92 static void insw(port_t port, void *buf, size_t size); 93 94 int do_probe(dpeth_t *dep) 95 { 96 /* This is the default, try to (re)locate the device. */ 97 conf_hw(dep); 98 if (!dep->up) 99 /* Probe failed, or the device is configured off. */ 100 return EXDEV; 101 102 if (dep->up) 103 dp_init(dep); 104 105 return EOK; 106 } 107 108 /** Initialize and/or start the network interface. 109 * 110 * @param[in,out] dep The network interface structure. 111 * 112 * @return EOK on success. 113 * @return EXDEV if the network interface is disabled. 114 * 115 */ 116 int do_init(dpeth_t *dep) 117 { 118 if (!dep->up) 119 /* FIXME: Perhaps call do_probe()? */ 120 return EXDEV; 121 122 assert(dep->up); 123 assert(dep->enabled); 124 125 dp_reinit(dep); 126 return EOK; 127 } 128 129 void do_stop(dpeth_t *dep) 130 { 131 if ((dep->up) && (dep->enabled)) { 132 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT); 133 ne_stop(dep); 134 135 dep->enabled = false; 136 dep->stopped = false; 137 dep->sending = false; 138 dep->send_avail = false; 139 } 140 } 141 142 static void dp_user2nic(dpeth_t *dep, void *buf, size_t offset, int nic_addr, size_t size) 143 { 144 size_t ecount = size & ~1; 145 146 outb_reg0(dep, DP_ISR, ISR_RDC); 147 148 if (dep->de_16bit) { 149 outb_reg0(dep, DP_RBCR0, ecount & 0xff); 150 outb_reg0(dep, DP_RBCR1, ecount >> 8); 151 } else { 152 outb_reg0(dep, DP_RBCR0, size & 0xff); 153 outb_reg0(dep, DP_RBCR1, size >> 8); 154 } 155 156 outb_reg0(dep, DP_RSAR0, nic_addr & 0xff); 157 outb_reg0(dep, DP_RSAR1, nic_addr >> 8); 158 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA); 159 160 if (dep->de_16bit) { 161 void *ptr = buf + offset; 162 163 if (ecount != 0) { 164 outsw(dep->de_data_port, ptr, ecount); 165 size -= ecount; 166 offset += ecount; 167 ptr += ecount; 168 } 169 170 if (size) { 171 assert(size == 1); 172 173 uint16_t two_bytes; 174 175 memcpy(&(((uint8_t *) &two_bytes)[0]), ptr, 1); 176 outw(dep->de_data_port, two_bytes); 177 } 178 } else 179 outsb(dep->de_data_port, buf + offset, size); 180 203 181 unsigned int i; 182 for (i = 0; i < 100; i++) { 183 if (inb_reg0(dep, DP_ISR) & ISR_RDC) 184 break; 185 } 186 187 if (i == 100) 188 fprintf(stderr, "Remote DMA failed to complete\n"); 189 } 190 191 int do_pwrite(dpeth_t *dep, packet_t *packet, int from_int) 192 { 193 int size; 194 int sendq_head; 195 196 assert(dep->up); 197 assert(dep->enabled); 198 199 if (dep->send_avail) { 200 fprintf(stderr, "Send already in progress\n"); 201 return EBUSY; 202 } 203 204 sendq_head = dep->de_sendq_head; 205 if (dep->de_sendq[sendq_head].sq_filled) { 206 if (from_int) 207 fprintf(stderr, "dp8390: should not be sending\n"); 208 dep->send_avail = true; 209 dep->sending = false; 210 211 return EBUSY; 212 } 213 214 assert(!dep->sending); 215 216 void *buf = packet_get_data(packet); 217 size = packet_get_data_length(packet); 218 219 if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED) { 220 fprintf(stderr, "dp8390: invalid packet size\n"); 221 return EINVAL; 222 } 223 224 dp_user2nic(dep, buf, 0, dep->de_sendq[sendq_head].sq_sendpage 225 * DP_PAGESIZE, size); 226 dep->de_sendq[sendq_head].sq_filled = true; 227 228 if (dep->de_sendq_tail == sendq_head) { 229 outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage); 230 outb_reg0(dep, DP_TBCR1, size >> 8); 231 outb_reg0(dep, DP_TBCR0, size & 0xff); 232 outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA); /* there it goes .. */ 233 } else 234 dep->de_sendq[sendq_head].sq_size = size; 235 236 if (++sendq_head == dep->de_sendq_nr) 237 sendq_head = 0; 238 239 assert(sendq_head < SENDQ_NR); 240 dep->de_sendq_head = sendq_head; 241 dep->sending = true; 242 243 if (from_int) 244 return EOK; 245 246 dep->sending = false; 247 248 return EOK; 249 } 250 251 void dp_init(dpeth_t *dep) 252 { 253 int dp_rcr_reg; 254 int i; 204 255 205 256 /* General initialization */ 206 ne2k->port = port; 207 ne2k->data_port = ne2k->port + NE2K_DATA; 208 ne2k->irq = irq; 209 ne2k->probed = false; 210 ne2k->up = false; 211 212 /* Reset the ethernet card */ 213 uint8_t val = pio_read_8(ne2k->port + NE2K_RESET); 214 usleep(2000); 215 pio_write_8(ne2k->port + NE2K_RESET, val); 216 usleep(2000); 217 218 /* Reset the DP8390 */ 219 pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT); 220 for (i = 0; i < 0x1000; i++) { 221 if (pio_read_8(ne2k->port + DP_ISR) != 0) 222 break; 223 } 224 225 /* Check if the DP8390 is really there */ 226 val = pio_read_8(ne2k->port + DP_CR); 227 if ((val & (CR_STP | CR_DM_ABORT)) != (CR_STP | CR_DM_ABORT)) 228 return EXDEV; 229 230 /* Disable the receiver and init TCR and DCR */ 231 pio_write_8(ne2k->port + DP_RCR, RCR_MON); 232 pio_write_8(ne2k->port + DP_TCR, TCR_NORMAL); 233 pio_write_8(ne2k->port + DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS); 234 235 /* Setup a transfer to get the MAC address */ 236 pio_write_8(ne2k->port + DP_RBCR0, ETH_ADDR << 1); 237 pio_write_8(ne2k->port + DP_RBCR1, 0); 238 pio_write_8(ne2k->port + DP_RSAR0, 0); 239 pio_write_8(ne2k->port + DP_RSAR1, 0); 240 pio_write_8(ne2k->port + DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA); 241 242 for (i = 0; i < ETH_ADDR; i++) 243 ne2k->mac[i] = pio_read_16(ne2k->data_port); 257 dep->enabled = false; 258 dep->stopped = false; 259 dep->sending = false; 260 dep->send_avail = false; 261 ne_init(dep); 262 263 printf("Ethernet address "); 264 for (i = 0; i < 6; i++) 265 printf("%x%c", dep->de_address.ea_addr[i], i < 5 ? ':' : '\n'); 244 266 245 267 /* 246 * Setup send queue. Use the first 247 * SQ_PAGES of NE2000 memory for the send 248 * buffer. 249 */ 250 ne2k->sq.dirty = false; 251 ne2k->sq.page = NE2K_START / DP_PAGE; 252 fibril_mutex_initialize(&ne2k->sq_mutex); 253 fibril_condvar_initialize(&ne2k->sq_cv); 254 255 /* 256 * Setup receive ring buffer. Use all the rest 257 * of the NE2000 memory (except the first SQ_PAGES 258 * reserved for the send buffer) for the receive 259 * ring buffer. 260 */ 261 ne2k->start_page = ne2k->sq.page + SQ_PAGES; 262 ne2k->stop_page = ne2k->sq.page + NE2K_SIZE / DP_PAGE; 263 264 /* 265 * Initialization of the DP8390 following the mandatory procedure 268 * Initialization of the dp8390 following the mandatory procedure 266 269 * in reference manual ("DP8390D/NS32490D NIC Network Interface 267 270 * Controller", National Semiconductor, July 1995, Page 29). … … 269 272 270 273 /* Step 1: */ 271 pio_write_8(ne2k->port +DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);274 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT); 272 275 273 276 /* Step 2: */ 274 pio_write_8(ne2k->port + DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS); 277 if (dep->de_16bit) 278 outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS); 279 else 280 outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS); 275 281 276 282 /* Step 3: */ 277 pio_write_8(ne2k->port +DP_RBCR0, 0);278 pio_write_8(ne2k->port +DP_RBCR1, 0);283 outb_reg0(dep, DP_RBCR0, 0); 284 outb_reg0(dep, DP_RBCR1, 0); 279 285 280 286 /* Step 4: */ 281 pio_write_8(ne2k->port + DP_RCR, RCR_AB); 287 dp_rcr_reg = RCR_AB; /* Enable broadcasts */ 288 289 outb_reg0(dep, DP_RCR, dp_rcr_reg); 282 290 283 291 /* Step 5: */ 284 pio_write_8(ne2k->port +DP_TCR, TCR_INTERNAL);292 outb_reg0(dep, DP_TCR, TCR_INTERNAL); 285 293 286 294 /* Step 6: */ 287 pio_write_8(ne2k->port + DP_BNRY, ne2k->start_page);288 pio_write_8(ne2k->port + DP_PSTART, ne2k->start_page);289 pio_write_8(ne2k->port + DP_PSTOP, ne2k->stop_page);295 outb_reg0(dep, DP_BNRY, dep->de_startpage); 296 outb_reg0(dep, DP_PSTART, dep->de_startpage); 297 outb_reg0(dep, DP_PSTOP, dep->de_stoppage); 290 298 291 299 /* Step 7: */ 292 pio_write_8(ne2k->port + DP_ISR, 0xff);300 outb_reg0(dep, DP_ISR, 0xFF); 293 301 294 302 /* Step 8: */ 295 pio_write_8(ne2k->port + DP_IMR,296 IMR_ PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE);303 outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | 304 IMR_OVWE | IMR_CNTE); 297 305 298 306 /* Step 9: */ 299 pio_write_8(ne2k->port +DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);300 301 pio_write_8(ne2k->port + DP_PAR0, ne2k->mac[0]);302 pio_write_8(ne2k->port + DP_PAR1, ne2k->mac[1]);303 pio_write_8(ne2k->port + DP_PAR2, ne2k->mac[2]);304 pio_write_8(ne2k->port + DP_PAR3, ne2k->mac[3]);305 pio_write_8(ne2k->port + DP_PAR4, ne2k->mac[4]);306 pio_write_8(ne2k->port + DP_PAR5, ne2k->mac[5]);307 308 pio_write_8(ne2k->port +DP_MAR0, 0xff);309 pio_write_8(ne2k->port +DP_MAR1, 0xff);310 pio_write_8(ne2k->port +DP_MAR2, 0xff);311 pio_write_8(ne2k->port +DP_MAR3, 0xff);312 pio_write_8(ne2k->port +DP_MAR4, 0xff);313 pio_write_8(ne2k->port +DP_MAR5, 0xff);314 pio_write_8(ne2k->port +DP_MAR6, 0xff);315 pio_write_8(ne2k->port +DP_MAR7, 0xff);316 317 pio_write_8(ne2k->port + DP_CURR, ne2k->start_page + 1);307 outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP); 308 309 outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]); 310 outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]); 311 outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]); 312 outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]); 313 outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]); 314 outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]); 315 316 outb_reg1(dep, DP_MAR0, 0xff); 317 outb_reg1(dep, DP_MAR1, 0xff); 318 outb_reg1(dep, DP_MAR2, 0xff); 319 outb_reg1(dep, DP_MAR3, 0xff); 320 outb_reg1(dep, DP_MAR4, 0xff); 321 outb_reg1(dep, DP_MAR5, 0xff); 322 outb_reg1(dep, DP_MAR6, 0xff); 323 outb_reg1(dep, DP_MAR7, 0xff); 324 325 outb_reg1(dep, DP_CURR, dep->de_startpage + 1); 318 326 319 327 /* Step 10: */ 320 pio_write_8(ne2k->port +DP_CR, CR_DM_ABORT | CR_STA);328 outb_reg0(dep, DP_CR, CR_DM_ABORT | CR_STA); 321 329 322 330 /* Step 11: */ 323 pio_write_8(ne2k->port + DP_TCR, TCR_NORMAL); 324 325 /* Reset counters by reading */ 326 pio_read_8(ne2k->port + DP_CNTR0); 327 pio_read_8(ne2k->port + DP_CNTR1); 328 pio_read_8(ne2k->port + DP_CNTR2); 329 330 /* Finish the initialization */ 331 ne2k->probed = true; 332 return EOK; 333 } 334 335 /** Start the network interface. 336 * 337 * @param[in,out] ne2k Network interface structure. 338 * 339 * @return EOK on success. 340 * @return EXDEV if the network interface is disabled. 341 * 342 */ 343 int ne2k_up(ne2k_t *ne2k) 344 { 345 if (!ne2k->probed) 346 return EXDEV; 347 348 pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_STA); 349 pio_write_8(ne2k->port + DP_RCR, RCR_AB); 350 351 ne2k->up = true; 352 return EOK; 353 } 354 355 /** Stop the network interface. 356 * 357 * @param[in,out] ne2k Network interface structure. 358 * 359 */ 360 void ne2k_down(ne2k_t *ne2k) 361 { 362 if ((ne2k->probed) && (ne2k->up)) { 363 pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT); 364 365 /* Reset the ethernet card */ 366 uint8_t val = pio_read_8(ne2k->port + NE2K_RESET); 367 usleep(2000); 368 pio_write_8(ne2k->port + NE2K_RESET, val); 369 370 ne2k->up = false; 371 } 372 } 373 374 /** Send a frame. 375 * 376 * @param[in,out] ne2k Network interface structure. 377 * @param[in] packet Frame to be sent. 378 * 379 */ 380 void ne2k_send(ne2k_t *ne2k, packet_t *packet) 381 { 382 assert(ne2k->probed); 383 assert(ne2k->up); 384 385 fibril_mutex_lock(&ne2k->sq_mutex); 386 387 while (ne2k->sq.dirty) 388 fibril_condvar_wait(&ne2k->sq_cv, &ne2k->sq_mutex); 389 390 void *buf = packet_get_data(packet); 391 size_t size = packet_get_data_length(packet); 392 393 if ((size < ETH_MIN_PACK_SIZE) || (size > ETH_MAX_PACK_SIZE_TAGGED)) { 394 fprintf(stderr, "%s: Frame dropped (invalid size %zu bytes)\n", 395 NAME, size); 396 return; 397 } 398 399 /* Upload the frame to the ethernet card */ 400 ne2k_upload(ne2k, buf, ne2k->sq.page * DP_PAGE, size); 401 ne2k->sq.dirty = true; 402 ne2k->sq.size = size; 403 404 /* Initialize the transfer */ 405 pio_write_8(ne2k->port + DP_TPSR, ne2k->sq.page); 406 pio_write_8(ne2k->port + DP_TBCR0, size & 0xff); 407 pio_write_8(ne2k->port + DP_TBCR1, (size >> 8) & 0xff); 408 pio_write_8(ne2k->port + DP_CR, CR_TXP | CR_STA); 409 410 fibril_mutex_unlock(&ne2k->sq_mutex); 411 } 412 413 static void ne2k_reset(ne2k_t *ne2k) 414 { 415 unsigned int i; 416 417 /* Stop the chip */ 418 pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT); 419 pio_write_8(ne2k->port + DP_RBCR0, 0); 420 pio_write_8(ne2k->port + DP_RBCR1, 0); 421 422 for (i = 0; i < 0x1000; i++) { 423 if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RST) != 0) 424 break; 425 } 426 427 pio_write_8(ne2k->port + DP_TCR, TCR_1EXTERNAL | TCR_OFST); 428 pio_write_8(ne2k->port + DP_CR, CR_STA | CR_DM_ABORT); 429 pio_write_8(ne2k->port + DP_TCR, TCR_NORMAL); 430 431 /* Acknowledge the ISR_RDC (remote DMA) interrupt */ 432 for (i = 0; i < 0x1000; i++) { 433 if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RDC) != 0) 434 break; 435 } 436 437 uint8_t val = pio_read_8(ne2k->port + DP_ISR); 438 pio_write_8(ne2k->port + DP_ISR, val & ~ISR_RDC); 331 outb_reg0(dep, DP_TCR, TCR_NORMAL); 332 333 inb_reg0(dep, DP_CNTR0); /* Reset counters by reading */ 334 inb_reg0(dep, DP_CNTR1); 335 inb_reg0(dep, DP_CNTR2); 336 337 /* Finish the initialization. */ 338 dep->enabled = true; 339 for (i = 0; i < dep->de_sendq_nr; i++) 340 dep->de_sendq[i].sq_filled= 0; 341 342 dep->de_sendq_head = 0; 343 dep->de_sendq_tail = 0; 344 } 345 346 static void dp_reinit(dpeth_t *dep) 347 { 348 int dp_rcr_reg; 349 350 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA); 351 352 /* Enable broadcasts */ 353 dp_rcr_reg = RCR_AB; 354 355 outb_reg0(dep, DP_RCR, dp_rcr_reg); 356 } 357 358 static void dp_reset(dpeth_t *dep) 359 { 360 int i; 361 362 /* Stop chip */ 363 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT); 364 outb_reg0(dep, DP_RBCR0, 0); 365 outb_reg0(dep, DP_RBCR1, 0); 366 367 for (i = 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++) 368 ; /* Do nothing */ 369 370 outb_reg0(dep, DP_TCR, TCR_1EXTERNAL | TCR_OFST); 371 outb_reg0(dep, DP_CR, CR_STA | CR_DM_ABORT); 372 outb_reg0(dep, DP_TCR, TCR_NORMAL); 373 374 /* Acknowledge the ISR_RDC (remote DMA) interrupt. */ 375 for (i = 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) &ISR_RDC) == 0); i++) 376 ; /* Do nothing */ 377 378 outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & ~ISR_RDC); 439 379 440 380 /* 441 * Reset the transmit ring. If we were transmitting a frame,442 * wepretend that the packet is processed. Higher layers will381 * Reset the transmit ring. If we were transmitting a packet, we 382 * pretend that the packet is processed. Higher layers will 443 383 * retransmit if the packet wasn't actually sent. 444 384 */ 445 fibril_mutex_lock(&ne2k->sq_mutex); 446 ne2k->sq.dirty = false; 447 fibril_mutex_unlock(&ne2k->sq_mutex); 448 } 449 450 static uint8_t ne2k_isr_ack(ne2k_t *ne2k) 451 { 452 uint8_t isr = pio_read_8(ne2k->port + DP_ISR); 385 dep->de_sendq_head = 0; 386 dep->de_sendq_tail = 0; 387 388 for (i = 0; i < dep->de_sendq_nr; i++) 389 dep->de_sendq[i].sq_filled = 0; 390 391 dep->send_avail = false; 392 dep->stopped = false; 393 } 394 395 static uint8_t isr_acknowledge(dpeth_t *dep) 396 { 397 uint8_t isr = inb_reg0(dep, DP_ISR); 453 398 if (isr != 0) 454 pio_write_8(ne2k->port +DP_ISR, isr);399 outb_reg0(dep, DP_ISR, isr); 455 400 456 401 return isr; 457 402 } 458 403 459 static void ne2k_receive_frame(ne2k_t *ne2k, uint8_t page, size_t length, 460 int nil_phone, device_id_t device_id) 461 { 462 packet_t *packet = netif_packet_get_1(length); 463 if (!packet) 464 return; 465 466 void *buf = packet_suffix(packet, length); 467 bzero(buf, length); 468 uint8_t last = page + length / DP_PAGE; 469 470 if (last >= ne2k->stop_page) { 471 size_t left = (ne2k->stop_page - page) * DP_PAGE 472 - sizeof(recv_header_t); 473 474 ne2k_download(ne2k, buf, page * DP_PAGE + sizeof(recv_header_t), 475 left); 476 ne2k_download(ne2k, buf + left, ne2k->start_page * DP_PAGE, 477 length - left); 478 } else 479 ne2k_download(ne2k, buf, page * DP_PAGE + sizeof(recv_header_t), 480 length); 481 482 ne2k->stats.receive_packets++; 483 nil_received_msg(nil_phone, device_id, packet, SERVICE_NONE); 484 } 485 486 static void ne2k_receive(ne2k_t *ne2k, int nil_phone, device_id_t device_id) 487 { 488 while (true) { 489 uint8_t boundary = pio_read_8(ne2k->port + DP_BNRY) + 1; 490 491 if (boundary == ne2k->stop_page) 492 boundary = ne2k->start_page; 493 494 pio_write_8(ne2k->port + DP_CR, CR_PS_P1 | CR_STA); 495 uint8_t current = pio_read_8(ne2k->port + DP_CURR); 496 pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_STA); 497 498 if (current == boundary) 499 /* No more frames to process */ 500 break; 501 502 recv_header_t header; 503 size_t size = sizeof(header); 504 size_t offset = boundary * DP_PAGE; 505 506 /* Get the frame header */ 507 pio_write_8(ne2k->port + DP_RBCR0, size & 0xff); 508 pio_write_8(ne2k->port + DP_RBCR1, (size >> 8) & 0xff); 509 pio_write_8(ne2k->port + DP_RSAR0, offset & 0xff); 510 pio_write_8(ne2k->port + DP_RSAR1, (offset >> 8) & 0xff); 511 pio_write_8(ne2k->port + DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA); 512 513 pio_read_buf_16(ne2k->data_port, (void *) &header, size); 514 515 size_t length = 516 (((size_t) header.rbcl) | (((size_t) header.rbch) << 8)) - size; 517 uint8_t next = header.next; 518 519 if ((length < ETH_MIN_PACK_SIZE) 520 || (length > ETH_MAX_PACK_SIZE_TAGGED)) { 521 fprintf(stderr, "%s: Rant frame (%zu bytes)\n", NAME, length); 522 next = current; 523 } else if ((header.next < ne2k->start_page) 524 || (header.next > ne2k->stop_page)) { 525 fprintf(stderr, "%s: Malformed next frame %u\n", NAME, 526 header.next); 527 next = current; 528 } else if (header.status & RSR_FO) { 529 /* 530 * This is very serious, so we issue a warning and 531 * reset the buffers. 532 */ 533 fprintf(stderr, "%s: FIFO overrun\n", NAME); 534 ne2k->overruns++; 535 next = current; 536 } else if ((header.status & RSR_PRX) && (ne2k->up)) 537 ne2k_receive_frame(ne2k, boundary, length, nil_phone, device_id); 538 539 /* 540 * Update the boundary pointer 541 * to the value of the page 542 * prior to the next packet to 543 * be processed. 544 */ 545 if (next == ne2k->start_page) 546 next = ne2k->stop_page - 1; 547 else 548 next--; 549 550 pio_write_8(ne2k->port + DP_BNRY, next); 551 } 552 } 553 554 void ne2k_interrupt(ne2k_t *ne2k, uint8_t isr, int nil_phone, device_id_t device_id) 555 { 556 bool signal = false; 557 bool stopped = false; 558 559 for (; (isr & 0x7f) != 0; isr = ne2k_isr_ack(ne2k)) { 404 void dp_check_ints(int nil_phone, device_id_t device_id, dpeth_t *dep, uint8_t isr) 405 { 406 int tsr; 407 int size, sendq_tail; 408 409 for (; (isr & 0x7f) != 0; isr = isr_acknowledge(dep)) { 560 410 if (isr & (ISR_PTX | ISR_TXE)) { 561 411 if (isr & ISR_TXE) 562 ne2k->stats.send_errors++;412 dep->de_stat.ets_sendErr++; 563 413 else { 564 uint8_t tsr = pio_read_8(ne2k->port +DP_TSR);414 tsr = inb_reg0(dep, DP_TSR); 565 415 566 416 if (tsr & TSR_PTX) 567 ne2k->stats.send_packets++;417 dep->de_stat.ets_packetT++; 568 418 569 419 if (tsr & TSR_COL) 570 ne2k->stats.collisions++;420 dep->de_stat.ets_collision++; 571 421 572 422 if (tsr & TSR_ABT) 573 ne2k->stats.send_aborted_errors++;423 dep->de_stat.ets_transAb++; 574 424 575 425 if (tsr & TSR_CRS) 576 ne2k->stats.send_carrier_errors++;426 dep->de_stat.ets_carrSense++; 577 427 578 if (tsr & TSR_FU) { 579 ne2k->underruns++; 580 if (ne2k->underruns < NE2K_ERL) 581 fprintf(stderr, "%s: FIFO underrun\n", NAME); 582 } 428 if ((tsr & TSR_FU) && (++dep->de_stat.ets_fifoUnder <= 10)) 429 printf("FIFO underrun\n"); 583 430 584 if (tsr & TSR_CDH) { 585 ne2k->stats.send_heartbeat_errors++; 586 if (ne2k->stats.send_heartbeat_errors < NE2K_ERL) 587 fprintf(stderr, "%s: CD heartbeat failure\n", NAME); 588 } 431 if ((tsr & TSR_CDH) && (++dep->de_stat.ets_CDheartbeat <= 10)) 432 printf("CD heart beat failure\n"); 589 433 590 434 if (tsr & TSR_OWC) 591 ne2k->stats.send_window_errors++;435 dep->de_stat.ets_OWC++; 592 436 } 593 437 594 fibril_mutex_lock(&ne2k->sq_mutex); 595 596 if (ne2k->sq.dirty) { 597 /* Prepare the buffer for next packet */ 598 ne2k->sq.dirty = false; 599 ne2k->sq.size = 0; 600 signal = true; 601 } else { 602 ne2k->misses++; 603 if (ne2k->misses < NE2K_ERL) 604 fprintf(stderr, "%s: Spurious PTX interrupt\n", NAME); 438 sendq_tail = dep->de_sendq_tail; 439 440 if (!(dep->de_sendq[sendq_tail].sq_filled)) { 441 printf("PTX interrupt, but no frame to send\n"); 442 continue; 605 443 } 606 444 607 fibril_mutex_unlock(&ne2k->sq_mutex); 445 dep->de_sendq[sendq_tail].sq_filled = false; 446 447 if (++sendq_tail == dep->de_sendq_nr) 448 sendq_tail = 0; 449 450 dep->de_sendq_tail = sendq_tail; 451 452 if (dep->de_sendq[sendq_tail].sq_filled) { 453 size = dep->de_sendq[sendq_tail].sq_size; 454 outb_reg0(dep, DP_TPSR, 455 dep->de_sendq[sendq_tail].sq_sendpage); 456 outb_reg0(dep, DP_TBCR1, size >> 8); 457 outb_reg0(dep, DP_TBCR0, size & 0xff); 458 outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA); 459 } 460 461 dep->send_avail = false; 608 462 } 609 463 610 464 if (isr & ISR_PRX) 611 ne2k_receive(ne2k, nil_phone, device_id);465 dp_recv(nil_phone, device_id, dep); 612 466 613 467 if (isr & ISR_RXE) 614 ne2k->stats.receive_errors++;468 dep->de_stat.ets_recvErr++; 615 469 616 470 if (isr & ISR_CNT) { 617 ne2k->stats.receive_crc_errors += 618 pio_read_8(ne2k->port + DP_CNTR0); 619 ne2k->stats.receive_frame_errors += 620 pio_read_8(ne2k->port + DP_CNTR1); 621 ne2k->stats.receive_missed_errors += 622 pio_read_8(ne2k->port + DP_CNTR2); 471 dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0); 472 dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1); 473 dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2); 474 } 475 476 if (isr & ISR_OVW) 477 dep->de_stat.ets_OVW++; 478 479 if (isr & ISR_RDC) { 480 /* Nothing to do */ 623 481 } 624 482 … … 628 486 * chip is shutdown. We set the flag 'stopped' 629 487 * and continue processing arrived packets. When the 630 * receive buffer is empty, we reset the DP8390.488 * receive buffer is empty, we reset the dp8390. 631 489 */ 632 stopped = true; 633 } 634 } 635 636 if (stopped) { 490 dep->stopped = true; 491 break; 492 } 493 } 494 495 if (dep->stopped) { 637 496 /* 638 497 * The chip is stopped, and all arrived 639 498 * frames are delivered. 640 499 */ 641 ne2k_reset(ne2k); 642 } 643 644 /* Signal a next frame to be sent */ 645 if (signal) 646 fibril_condvar_broadcast(&ne2k->sq_cv); 500 dp_reset(dep); 501 } 502 503 dep->sending = false; 504 } 505 506 static void dp_getblock(dpeth_t *dep, int page, size_t offset, size_t size, void *dst) 507 { 508 offset = page * DP_PAGESIZE + offset; 509 510 outb_reg0(dep, DP_RBCR0, size & 0xff); 511 outb_reg0(dep, DP_RBCR1, size >> 8); 512 outb_reg0(dep, DP_RSAR0, offset & 0xff); 513 outb_reg0(dep, DP_RSAR1, offset >> 8); 514 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA); 515 516 if (dep->de_16bit) { 517 assert((size % 2) == 0); 518 insw(dep->de_data_port, dst, size); 519 } else 520 insb(dep->de_data_port, dst, size); 521 } 522 523 static void dp_recv(int nil_phone, device_id_t device_id, dpeth_t *dep) 524 { 525 dp_rcvhdr_t header; 526 int pageno, curr, next; 527 size_t length; 528 int packet_processed, r; 529 uint16_t eth_type; 530 531 packet_processed = false; 532 pageno = inb_reg0(dep, DP_BNRY) + 1; 533 if (pageno == dep->de_stoppage) 534 pageno = dep->de_startpage; 535 536 do { 537 outb_reg0(dep, DP_CR, CR_PS_P1 | CR_EXTRA); 538 curr = inb_reg1(dep, DP_CURR); 539 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA); 540 541 if (curr == pageno) 542 break; 543 544 dp_getblock(dep, pageno, (size_t) 0, sizeof(header), &header); 545 dp_getblock(dep, pageno, sizeof(header) + 546 2 * sizeof(ether_addr_t), sizeof(eth_type), ð_type); 547 548 length = (header.dr_rbcl | (header.dr_rbch << 8)) - sizeof(dp_rcvhdr_t); 549 next = header.dr_next; 550 if ((length < ETH_MIN_PACK_SIZE) || (length > ETH_MAX_PACK_SIZE_TAGGED)) { 551 printf("Packet with strange length arrived: %zu\n", length); 552 next= curr; 553 } else if ((next < dep->de_startpage) || (next >= dep->de_stoppage)) { 554 printf("Strange next page\n"); 555 next= curr; 556 } else if (header.dr_status & RSR_FO) { 557 /* 558 * This is very serious, so we issue a warning and 559 * reset the buffers 560 */ 561 printf("FIFO overrun, resetting receive buffer\n"); 562 dep->de_stat.ets_fifoOver++; 563 next = curr; 564 } else if ((header.dr_status & RSR_PRX) && (dep->enabled)) { 565 r = dp_pkt2user(nil_phone, device_id, dep, pageno, length); 566 if (r != EOK) 567 return; 568 569 packet_processed = true; 570 dep->de_stat.ets_packetR++; 571 } 572 573 if (next == dep->de_startpage) 574 outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1); 575 else 576 outb_reg0(dep, DP_BNRY, next - 1); 577 578 pageno = next; 579 } while (!packet_processed); 580 } 581 582 static void dp_nic2user(dpeth_t *dep, int nic_addr, void *buf, size_t offset, size_t size) 583 { 584 size_t ecount = size & ~1; 585 586 if (dep->de_16bit) { 587 outb_reg0(dep, DP_RBCR0, ecount & 0xFF); 588 outb_reg0(dep, DP_RBCR1, ecount >> 8); 589 } else { 590 outb_reg0(dep, DP_RBCR0, size & 0xff); 591 outb_reg0(dep, DP_RBCR1, size >> 8); 592 } 593 594 outb_reg0(dep, DP_RSAR0, nic_addr & 0xff); 595 outb_reg0(dep, DP_RSAR1, nic_addr >> 8); 596 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA); 597 598 if (dep->de_16bit) { 599 void *ptr = buf + offset; 600 601 if (ecount != 0) { 602 insw(dep->de_data_port, ptr, ecount); 603 size -= ecount; 604 offset += ecount; 605 ptr += ecount; 606 } 607 608 if (size) { 609 assert(size == 1); 610 611 uint16_t two_bytes = inw(dep->de_data_port); 612 memcpy(ptr, &(((uint8_t *) &two_bytes)[0]), 1); 613 } 614 } else 615 insb(dep->de_data_port, buf + offset, size); 616 } 617 618 static int dp_pkt2user(int nil_phone, device_id_t device_id, dpeth_t *dep, int page, int length) 619 { 620 int last, count; 621 packet_t *packet; 622 623 packet = netif_packet_get_1(length); 624 if (!packet) 625 return ENOMEM; 626 627 void *buf = packet_suffix(packet, length); 628 629 last = page + (length - 1) / DP_PAGESIZE; 630 if (last >= dep->de_stoppage) { 631 count = (dep->de_stoppage - page) * DP_PAGESIZE - sizeof(dp_rcvhdr_t); 632 633 dp_nic2user(dep, page * DP_PAGESIZE + sizeof(dp_rcvhdr_t), 634 buf, 0, count); 635 dp_nic2user(dep, dep->de_startpage * DP_PAGESIZE, 636 buf, count, length - count); 637 } else { 638 dp_nic2user(dep, page * DP_PAGESIZE + sizeof(dp_rcvhdr_t), 639 buf, 0, length); 640 } 641 642 nil_received_msg(nil_phone, device_id, packet, SERVICE_NONE); 643 644 return EOK; 645 } 646 647 static void conf_hw(dpeth_t *dep) 648 { 649 if (!ne_probe(dep)) { 650 printf("No ethernet card found at %#lx\n", dep->de_base_port); 651 dep->up = false; 652 return; 653 } 654 655 dep->up = true; 656 dep->enabled = false; 657 dep->stopped = false; 658 dep->sending = false; 659 dep->send_avail = false; 660 } 661 662 static void insb(port_t port, void *buf, size_t size) 663 { 664 size_t i; 665 666 for (i = 0; i < size; i++) 667 *((uint8_t *) buf + i) = inb(port); 668 } 669 670 static void insw(port_t port, void *buf, size_t size) 671 { 672 size_t i; 673 674 for (i = 0; i * 2 < size; i++) 675 *((uint16_t *) buf + i) = inw(port); 676 } 677 678 static void outsb(port_t port, void *buf, size_t size) 679 { 680 size_t i; 681 682 for (i = 0; i < size; i++) 683 outb(port, *((uint8_t *) buf + i)); 684 } 685 686 static void outsw(port_t port, void *buf, size_t size) 687 { 688 size_t i; 689 690 for (i = 0; i * 2 < size; i++) 691 outw(port, *((uint16_t *) buf + i)); 647 692 } 648 693
Note:
See TracChangeset
for help on using the changeset viewer.