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

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

more declutter

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