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

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

more cleanup

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