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

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

cleanup

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