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

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