source: mainline/uspace/srv/hw/netif/dp8390/dp8390.c@ aa1e202

lfn serial ticket/834-toolchain-update topic/fix-logger-deadlock topic/msim-upgrade topic/simplify-dev-export
Last change on this file since aa1e202 was aa1e202, checked in by Martin Decky <martin@…>, 16 years ago

cleanup

  • Property mode set to 100644
File size: 17.7 KB
Line 
1/** @addtogroup dp8390
2 * @{
3 */
4
5/** @file
6 * DP8390 network interface core implementation.
7 */
8
9#include <assert.h>
10#include <byteorder.h>
11#include <errno.h>
12#include <netif_local.h>
13#include <net/packet.h>
14#include <nil_interface.h>
15#include <packet_client.h>
16#include "dp8390_drv.h"
17#include "dp8390_port.h"
18#include "dp8390.h"
19#include "ne2000.h"
20
21/** Read a memory block byte by byte.
22 *
23 * @param[in] port The source address.
24 * @param[out] buf The destination buffer.
25 * @param[in] size The memory block size in bytes.
26 *
27 */
28static void outsb(port_t port, void * buf, size_t size);
29
30/** Read a memory block word by word.
31 *
32 * @param[in] port The source address.
33 * @param[out] buf The destination buffer.
34 * @param[in] size The memory block size in bytes.
35 *
36 */
37static void outsw(port_t port, void * buf, size_t size);
38
39/*
40 * Some clones of the dp8390 and the PC emulator 'Bochs' require the CR_STA
41 * on writes to the CR register. Additional CR_STAs do not appear to hurt
42 * genuine dp8390s.
43 */
44#define CR_EXTRA CR_STA
45
46static void dp_init(dpeth_t *dep);
47static void dp_reinit(dpeth_t *dep);
48static void dp_reset(dpeth_t *dep);
49static void dp_recv(int nil_phone, device_id_t device_id, dpeth_t *dep);
50static void dp_pio8_getblock(dpeth_t *dep, int page, size_t offset, size_t size, void *dst);
51static void dp_pio16_getblock(dpeth_t *dep, int page, size_t offset, size_t size, void *dst);
52static int dp_pkt2user(int nil_phone, device_id_t device_id, dpeth_t *dep, int page, int length);
53static void dp_pio8_user2nic(dpeth_t *dep, void *buf, size_t offset, int nic_addr, size_t size);
54static void dp_pio16_user2nic(dpeth_t *dep, void *buf, size_t offset, int nic_addr, size_t size);
55static void dp_pio8_nic2user(dpeth_t *dep, int nic_addr, void *buf, size_t offset, size_t size);
56static void dp_pio16_nic2user(dpeth_t *dep, int nic_addr, void *buf, size_t offset, size_t size);
57static void conf_hw(dpeth_t *dep);
58static void insb(port_t port, void *buf, size_t size);
59static void insw(port_t port, void *buf, size_t size);
60
61int do_probe(dpeth_t *dep)
62{
63 /* This is the default, try to (re)locate the device. */
64 conf_hw(dep);
65 if (dep->de_mode == DEM_DISABLED)
66 /* Probe failed, or the device is configured off. */
67 return EXDEV;
68
69 if (dep->de_mode == DEM_ENABLED)
70 dp_init(dep);
71
72 return EOK;
73}
74
75int do_init(dpeth_t *dep, int mode)
76{
77 if (dep->de_mode == DEM_DISABLED)
78 /* FIXME: Perhaps call do_probe()? */
79 return EXDEV;
80
81 assert(dep->de_mode == DEM_ENABLED);
82 assert(dep->de_flags & DEF_ENABLED);
83
84 dep->de_flags &= ~(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
85
86 if (mode &DL_PROMISC_REQ)
87 dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
88
89 if (mode &DL_MULTI_REQ)
90 dep->de_flags |= DEF_MULTI;
91
92 if (mode &DL_BROAD_REQ)
93 dep->de_flags |= DEF_BROAD;
94
95 dp_reinit(dep);
96 return EOK;
97}
98
99void do_stop(dpeth_t *dep)
100{
101 if ((dep->de_mode == DEM_ENABLED)
102 && (dep->de_flags & DEF_ENABLED)) {
103 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
104 (dep->de_stopf)(dep);
105 dep->de_flags = DEF_EMPTY;
106 }
107}
108
109int do_pwrite(dpeth_t *dep, packet_t *packet, int from_int)
110{
111 int size;
112 int sendq_head;
113
114 assert(dep->de_mode == DEM_ENABLED);
115 assert(dep->de_flags & DEF_ENABLED);
116
117 if (dep->de_flags & DEF_SEND_AVAIL) {
118 fprintf(stderr, "dp8390: send already in progress\n");
119 return EBUSY;
120 }
121
122 sendq_head = dep->de_sendq_head;
123 if (dep->de_sendq[sendq_head].sq_filled) {
124 if (from_int)
125 fprintf(stderr, "dp8390: should not be sending\n");
126 dep->de_flags |= DEF_SEND_AVAIL;
127 dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV);
128
129 return EBUSY;
130 }
131
132 assert(!(dep->de_flags & DEF_PACK_SEND));
133
134 void *buf = packet_get_data(packet);
135 size = packet_get_data_length(packet);
136
137 if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED) {
138 fprintf(stderr, "dp8390: invalid packet size\n");
139 return EINVAL;
140 }
141
142 (dep->de_user2nicf)(dep, buf, 0,
143 dep->de_sendq[sendq_head].sq_sendpage * DP_PAGESIZE, size);
144 dep->de_sendq[sendq_head].sq_filled = true;
145
146 if (dep->de_sendq_tail == sendq_head) {
147 outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);
148 outb_reg0(dep, DP_TBCR1, size >> 8);
149 outb_reg0(dep, DP_TBCR0, size & 0xff);
150 outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA); /* there it goes .. */
151 } else
152 dep->de_sendq[sendq_head].sq_size = size;
153
154 if (++sendq_head == dep->de_sendq_nr)
155 sendq_head = 0;
156
157 assert(sendq_head < SENDQ_NR);
158 dep->de_sendq_head = sendq_head;
159
160 dep->de_flags |= DEF_PACK_SEND;
161
162 if (from_int)
163 return EOK;
164
165 dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV);
166
167 return EOK;
168}
169
170void dp_init(dpeth_t *dep)
171{
172 int dp_rcr_reg;
173 int i;
174
175 /* General initialization */
176 dep->de_flags = DEF_EMPTY;
177 (*dep->de_initf)(dep);
178
179 printf("%s: Ethernet address ", dep->de_name);
180 for (i = 0; i < 6; i++)
181 printf("%x%c", dep->de_address.ea_addr[i], i < 5 ? ':' : '\n');
182
183 /*
184 * Initialization of the dp8390 following the mandatory procedure
185 * in reference manual ("DP8390D/NS32490D NIC Network Interface
186 * Controller", National Semiconductor, July 1995, Page 29).
187 */
188
189 /* Step 1: */
190 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
191
192 /* Step 2: */
193 if (dep->de_16bit)
194 outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
195 else
196 outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS);
197
198 /* Step 3: */
199 outb_reg0(dep, DP_RBCR0, 0);
200 outb_reg0(dep, DP_RBCR1, 0);
201
202 /* Step 4: */
203 dp_rcr_reg = 0;
204
205 if (dep->de_flags & DEF_PROMISC)
206 dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
207
208 if (dep->de_flags & DEF_BROAD)
209 dp_rcr_reg |= RCR_AB;
210
211 if (dep->de_flags & DEF_MULTI)
212 dp_rcr_reg |= RCR_AM;
213
214 outb_reg0(dep, DP_RCR, dp_rcr_reg);
215
216 /* Step 5: */
217 outb_reg0(dep, DP_TCR, TCR_INTERNAL);
218
219 /* Step 6: */
220 outb_reg0(dep, DP_BNRY, dep->de_startpage);
221 outb_reg0(dep, DP_PSTART, dep->de_startpage);
222 outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
223
224 /* Step 7: */
225 outb_reg0(dep, DP_ISR, 0xFF);
226
227 /* Step 8: */
228 outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
229 IMR_OVWE | IMR_CNTE);
230
231 /* Step 9: */
232 outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
233
234 outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]);
235 outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]);
236 outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]);
237 outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]);
238 outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]);
239 outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]);
240
241 outb_reg1(dep, DP_MAR0, 0xff);
242 outb_reg1(dep, DP_MAR1, 0xff);
243 outb_reg1(dep, DP_MAR2, 0xff);
244 outb_reg1(dep, DP_MAR3, 0xff);
245 outb_reg1(dep, DP_MAR4, 0xff);
246 outb_reg1(dep, DP_MAR5, 0xff);
247 outb_reg1(dep, DP_MAR6, 0xff);
248 outb_reg1(dep, DP_MAR7, 0xff);
249
250 outb_reg1(dep, DP_CURR, dep->de_startpage + 1);
251
252 /* Step 10: */
253 outb_reg0(dep, DP_CR, CR_DM_ABORT | CR_STA);
254
255 /* Step 11: */
256 outb_reg0(dep, DP_TCR, TCR_NORMAL);
257
258 inb_reg0(dep, DP_CNTR0); /* Reset counters by reading */
259 inb_reg0(dep, DP_CNTR1);
260 inb_reg0(dep, DP_CNTR2);
261
262 /* Finish the initialization. */
263 dep->de_flags |= DEF_ENABLED;
264 for (i = 0; i < dep->de_sendq_nr; i++)
265 dep->de_sendq[i].sq_filled= 0;
266
267 dep->de_sendq_head = 0;
268 dep->de_sendq_tail = 0;
269
270 if (dep->de_16bit) {
271 dep->de_user2nicf= dp_pio16_user2nic;
272 dep->de_nic2userf= dp_pio16_nic2user;
273 dep->de_getblockf= dp_pio16_getblock;
274 } else {
275 dep->de_user2nicf= dp_pio8_user2nic;
276 dep->de_nic2userf= dp_pio8_nic2user;
277 dep->de_getblockf= dp_pio8_getblock;
278 }
279}
280
281static void dp_reinit(dpeth_t *dep)
282{
283 int dp_rcr_reg;
284
285 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
286
287 dp_rcr_reg = 0;
288
289 if (dep->de_flags & DEF_PROMISC)
290 dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
291
292 if (dep->de_flags & DEF_BROAD)
293 dp_rcr_reg |= RCR_AB;
294
295 if (dep->de_flags & DEF_MULTI)
296 dp_rcr_reg |= RCR_AM;
297
298 outb_reg0(dep, DP_RCR, dp_rcr_reg);
299}
300
301static void dp_reset(dpeth_t *dep)
302{
303 int i;
304
305 /* Stop chip */
306 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
307 outb_reg0(dep, DP_RBCR0, 0);
308 outb_reg0(dep, DP_RBCR1, 0);
309
310 for (i = 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
311 ; /* Do nothing */
312
313 outb_reg0(dep, DP_TCR, TCR_1EXTERNAL | TCR_OFST);
314 outb_reg0(dep, DP_CR, CR_STA | CR_DM_ABORT);
315 outb_reg0(dep, DP_TCR, TCR_NORMAL);
316
317 /* Acknowledge the ISR_RDC (remote DMA) interrupt. */
318 for (i = 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) &ISR_RDC) == 0); i++)
319 ; /* Do nothing */
320
321 outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & ~ISR_RDC);
322
323 /*
324 * Reset the transmit ring. If we were transmitting a packet, we
325 * pretend that the packet is processed. Higher layers will
326 * retransmit if the packet wasn't actually sent.
327 */
328 dep->de_sendq_head = 0;
329 dep->de_sendq_tail = 0;
330
331 for (i = 0; i < dep->de_sendq_nr; i++)
332 dep->de_sendq[i].sq_filled = 0;
333
334 dep->de_flags &= ~DEF_SEND_AVAIL;
335 dep->de_flags &= ~DEF_STOPPED;
336}
337
338void dp_check_ints(int nil_phone, device_id_t device_id, dpeth_t *dep, int isr)
339{
340 int tsr;
341 int size, sendq_tail;
342
343 if (!(dep->de_flags & DEF_ENABLED))
344 fprintf(stderr, "dp8390: got premature interrupt\n");
345
346 for (; isr; isr = inb_reg0(dep, DP_ISR)) {
347 outb_reg0(dep, DP_ISR, isr);
348
349 if (isr & (ISR_PTX | ISR_TXE)) {
350 if (isr & ISR_TXE)
351 dep->de_stat.ets_sendErr++;
352 else {
353 tsr = inb_reg0(dep, DP_TSR);
354
355 if (tsr & TSR_PTX)
356 dep->de_stat.ets_packetT++;
357
358 if (tsr & TSR_COL)
359 dep->de_stat.ets_collision++;
360
361 if (tsr & TSR_ABT)
362 dep->de_stat.ets_transAb++;
363
364 if (tsr & TSR_CRS)
365 dep->de_stat.ets_carrSense++;
366
367 if ((tsr & TSR_FU) && (++dep->de_stat.ets_fifoUnder <= 10))
368 printf("%s: fifo underrun\n", dep->de_name);
369
370 if ((tsr & TSR_CDH) && (++dep->de_stat.ets_CDheartbeat <= 10))
371 printf("%s: CD heart beat failure\n", dep->de_name);
372
373 if (tsr & TSR_OWC)
374 dep->de_stat.ets_OWC++;
375 }
376
377 sendq_tail = dep->de_sendq_tail;
378
379 if (!(dep->de_sendq[sendq_tail].sq_filled)) {
380 /* Or hardware bug? */
381 printf("%s: transmit interrupt, but not sending\n", dep->de_name);
382 continue;
383 }
384
385 dep->de_sendq[sendq_tail].sq_filled = 0;
386
387 if (++sendq_tail == dep->de_sendq_nr)
388 sendq_tail = 0;
389
390 dep->de_sendq_tail = sendq_tail;
391
392 if (dep->de_sendq[sendq_tail].sq_filled) {
393 size = dep->de_sendq[sendq_tail].sq_size;
394 outb_reg0(dep, DP_TPSR,
395 dep->de_sendq[sendq_tail].sq_sendpage);
396 outb_reg0(dep, DP_TBCR1, size >> 8);
397 outb_reg0(dep, DP_TBCR0, size & 0xff);
398 outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);
399 }
400
401 dep->de_flags &= ~DEF_SEND_AVAIL;
402 }
403
404 if (isr & ISR_PRX)
405 dp_recv(nil_phone, device_id, dep);
406
407 if (isr & ISR_RXE)
408 dep->de_stat.ets_recvErr++;
409
410 if (isr & ISR_CNT) {
411 dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
412 dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
413 dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
414 }
415
416 if (isr & ISR_OVW)
417 dep->de_stat.ets_OVW++;
418
419 if (isr & ISR_RDC) {
420 /* Nothing to do */
421 }
422
423 if (isr & ISR_RST) {
424 /*
425 * This means we got an interrupt but the ethernet
426 * chip is shutdown. We set the flag DEF_STOPPED,
427 * and continue processing arrived packets. When the
428 * receive buffer is empty, we reset the dp8390.
429 */
430 dep->de_flags |= DEF_STOPPED;
431 break;
432 }
433 }
434
435 if ((dep->de_flags & DEF_STOPPED) == DEF_STOPPED) {
436 /*
437 * The chip is stopped, and all arrived packets
438 * are delivered.
439 */
440 dp_reset(dep);
441 }
442
443 dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV);
444}
445
446static void dp_recv(int nil_phone, device_id_t device_id, dpeth_t *dep)
447{
448 dp_rcvhdr_t header;
449 int pageno, curr, next;
450 size_t length;
451 int packet_processed, r;
452 uint16_t eth_type;
453
454 packet_processed = false;
455 pageno = inb_reg0(dep, DP_BNRY) + 1;
456 if (pageno == dep->de_stoppage)
457 pageno = dep->de_startpage;
458
459 do {
460 outb_reg0(dep, DP_CR, CR_PS_P1 | CR_EXTRA);
461 curr = inb_reg1(dep, DP_CURR);
462 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
463
464 if (curr == pageno)
465 break;
466
467 (dep->de_getblockf)(dep, pageno, (size_t) 0, sizeof(header), &header);
468 (dep->de_getblockf)(dep, pageno, sizeof(header) + 2 * sizeof(ether_addr_t), sizeof(eth_type), &eth_type);
469
470 length = (header.dr_rbcl | (header.dr_rbch << 8)) - sizeof(dp_rcvhdr_t);
471 next = header.dr_next;
472 if ((length < ETH_MIN_PACK_SIZE) || (length > ETH_MAX_PACK_SIZE_TAGGED)) {
473 printf("%s: packet with strange length arrived: %d\n", dep->de_name, (int) length);
474 next= curr;
475 } else if ((next < dep->de_startpage) || (next >= dep->de_stoppage)) {
476 printf("%s: strange next page\n", dep->de_name);
477 next= curr;
478 } else if (header.dr_status & RSR_FO) {
479 /*
480 * This is very serious, so we issue a warning and
481 * reset the buffers
482 */
483 printf("%s: fifo overrun, resetting receive buffer\n", dep->de_name);
484 dep->de_stat.ets_fifoOver++;
485 next = curr;
486 } else if ((header.dr_status & RSR_PRX) && (dep->de_flags & DEF_ENABLED)) {
487 r = dp_pkt2user(nil_phone, device_id, dep, pageno, length);
488 if (r != EOK)
489 return;
490
491 packet_processed = true;
492 dep->de_stat.ets_packetR++;
493 }
494
495 if (next == dep->de_startpage)
496 outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
497 else
498 outb_reg0(dep, DP_BNRY, next - 1);
499
500 pageno = next;
501 } while (!packet_processed);
502}
503
504static void dp_pio8_getblock(dpeth_t *dep, int page, size_t offset, size_t size, void *dst)
505{
506 offset = page * DP_PAGESIZE + offset;
507 outb_reg0(dep, DP_RBCR0, size &0xFF);
508 outb_reg0(dep, DP_RBCR1, size >> 8);
509 outb_reg0(dep, DP_RSAR0, offset &0xFF);
510 outb_reg0(dep, DP_RSAR1, offset >> 8);
511 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
512
513 insb(dep->de_data_port, dst, size);
514}
515
516static void dp_pio16_getblock(dpeth_t *dep, int page, size_t offset, size_t size, void *dst)
517{
518 offset = page * DP_PAGESIZE + offset;
519 outb_reg0(dep, DP_RBCR0, size &0xFF);
520 outb_reg0(dep, DP_RBCR1, size >> 8);
521 outb_reg0(dep, DP_RSAR0, offset &0xFF);
522 outb_reg0(dep, DP_RSAR1, offset >> 8);
523 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
524
525 assert(!(size & 1));
526
527 insw(dep->de_data_port, dst, size);
528}
529
530static int dp_pkt2user(int nil_phone, device_id_t device_id, dpeth_t *dep, int page, int length)
531{
532 int last, count;
533 packet_t *packet;
534
535 packet = netif_packet_get_1(length);
536 if (!packet)
537 return ENOMEM;
538
539 void *buf = packet_suffix(packet, length);
540
541 last = page + (length - 1) / DP_PAGESIZE;
542 if (last >= dep->de_stoppage) {
543 count = (dep->de_stoppage - page) * DP_PAGESIZE - sizeof(dp_rcvhdr_t);
544
545 (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
546 sizeof(dp_rcvhdr_t), buf, 0, count);
547 (dep->de_nic2userf)(dep, dep->de_startpage * DP_PAGESIZE,
548 buf, count, length - count);
549 } else {
550 (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
551 sizeof(dp_rcvhdr_t), buf, 0, length);
552 }
553
554 dep->de_flags |= DEF_PACK_RECV;
555
556 nil_received_msg(nil_phone, device_id, packet, SERVICE_NONE);
557
558 return EOK;
559}
560
561static void dp_pio8_user2nic(dpeth_t *dep, void *buf, size_t offset, int nic_addr, size_t size)
562{
563 outb_reg0(dep, DP_ISR, ISR_RDC);
564
565 outb_reg0(dep, DP_RBCR0, size & 0xFF);
566 outb_reg0(dep, DP_RBCR1, size >> 8);
567 outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
568 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
569 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
570
571 outsb(dep->de_data_port, buf + offset, size);
572
573 unsigned int i;
574 for (i = 0; i < 100; i++) {
575 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
576 break;
577 }
578
579 if (i == 100)
580 fprintf(stderr, "dp8390: remote DMA failed to complete\n");
581}
582
583static void dp_pio16_user2nic(dpeth_t *dep, void *buf, size_t offset, int nic_addr, size_t size)
584{
585 void *vir_user;
586 size_t ecount;
587 uint16_t two_bytes;
588
589 ecount = size & ~1;
590
591 outb_reg0(dep, DP_ISR, ISR_RDC);
592 outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
593 outb_reg0(dep, DP_RBCR1, ecount >> 8);
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_RW | CR_PS_P0 | CR_STA);
597
598 vir_user = buf + offset;
599 if (ecount != 0) {
600 outsw(dep->de_data_port, vir_user, ecount);
601 size -= ecount;
602 offset += ecount;
603 vir_user += ecount;
604 }
605
606 if (size) {
607 assert(size == 1);
608
609 memcpy(&(((uint8_t *) &two_bytes)[0]), vir_user, 1);
610 outw(dep->de_data_port, two_bytes);
611 }
612
613 unsigned int i;
614 for (i = 0; i < 100; i++) {
615 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
616 break;
617 }
618
619 if (i == 100)
620 fprintf(stderr, "dp8390: remote dma failed to complete\n");
621}
622
623static void dp_pio8_nic2user(dpeth_t *dep, int nic_addr, void *buf, size_t offset, size_t size)
624{
625 outb_reg0(dep, DP_RBCR0, size & 0xFF);
626 outb_reg0(dep, DP_RBCR1, size >> 8);
627 outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
628 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
629 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
630
631 insb(dep->de_data_port, buf + offset, size);
632}
633
634static void dp_pio16_nic2user(dpeth_t *dep, int nic_addr, void *buf, size_t offset, size_t size)
635{
636 void *vir_user;
637 size_t ecount;
638 uint16_t two_bytes;
639
640 ecount = size & ~1;
641
642 outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
643 outb_reg0(dep, DP_RBCR1, ecount >> 8);
644 outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
645 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
646 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
647
648 vir_user = buf + offset;
649 if (ecount != 0) {
650 insw(dep->de_data_port, vir_user, ecount);
651 size -= ecount;
652 offset += ecount;
653 vir_user += ecount;
654 }
655
656 if (size) {
657 assert(size == 1);
658
659 two_bytes = inw(dep->de_data_port);
660 memcpy(vir_user, &(((uint8_t *) &two_bytes)[0]), 1);
661 }
662}
663
664static void conf_hw(dpeth_t *dep)
665{
666 if (!ne_probe(dep)) {
667 printf("%s: No ethernet card found at %#lx\n",
668 dep->de_name, dep->de_base_port);
669 dep->de_mode= DEM_DISABLED;
670 return;
671 }
672
673 dep->de_mode = DEM_ENABLED;
674 dep->de_flags = DEF_EMPTY;
675}
676
677static void insb(port_t port, void *buf, size_t size)
678{
679 size_t i;
680
681 for (i = 0; i < size; i++)
682 *((uint8_t *) buf + i) = inb(port);
683}
684
685static void insw(port_t port, void *buf, size_t size)
686{
687 size_t i;
688
689 for (i = 0; i * 2 < size; i++)
690 *((uint16_t *) buf + i) = inw(port);
691}
692
693static void outsb(port_t port, void *buf, size_t size)
694{
695 size_t i;
696
697 for (i = 0; i < size; i++)
698 outb(port, *((uint8_t *) buf + i));
699}
700
701static void outsw(port_t port, void *buf, size_t size)
702{
703 size_t i;
704
705 for (i = 0; i * 2 < size; i++)
706 outw(port, *((uint16_t *) buf + i));
707}
708
709/** @}
710 */
Note: See TracBrowser for help on using the repository browser.