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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 66b628a was 66b628a, checked in by martin@…>, 15 years ago

further code simplification

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