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

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

declutter

  • Property mode set to 100644
File size: 26.7 KB
RevLine 
[21580dd]1/** @addtogroup dp8390
2 * @{
3 */
4
5/** @file
6 * DP8390 network interface core implementation.
7 */
8
9#include <assert.h>
[2687bdb]10#include <byteorder.h>
[21580dd]11#include <errno.h>
[14f1db0]12#include <netif_local.h>
[c69d327]13#include <net/packet.h>
[0a866eeb]14#include <packet_client.h>
[21580dd]15#include "dp8390_drv.h"
16#include "dp8390_port.h"
17#include "dp8390.h"
[2a6e4ac2]18#include "ne2000.h"
[21580dd]19
20/** Queues the outgoing packet.
21 * @param[in] dep The network interface structure.
22 * @param[in] packet The outgoing packet.
[1bfd3d3]23 * @return EOK on success.
[95ff5c4]24 * @return EINVAL
[21580dd]25 */
[46d4d9f]26int queue_packet(dpeth_t * dep, packet_t *packet);
[21580dd]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 */
[aadf01e]33static void outsb(port_t port, void * buf, size_t size);
[21580dd]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 */
[aadf01e]40static void outsw(port_t port, void * buf, size_t size);
[21580dd]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 */
[95ff5c4]46#define CR_EXTRA CR_STA
[21580dd]47
[74864ac]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);
[d3a0af7]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);
[74864ac]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);
[21580dd]65
[95ff5c4]66int do_probe(dpeth_t *dep)
67{
[21580dd]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. */
[95ff5c4]72 return EXDEV;
73
[21580dd]74 if (dep->de_mode == DEM_ENABLED)
75 dp_init(dep);
[95ff5c4]76
[21580dd]77 return EOK;
78}
79
[95ff5c4]80int do_init(dpeth_t *dep, int mode)
81{
[21580dd]82 if (dep->de_mode == DEM_DISABLED)
83 // might call do_probe()
84 return EXDEV;
[95ff5c4]85
86 if (dep->de_mode == DEM_SINK) {
[21580dd]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 }
[95ff5c4]97
[21580dd]98 assert(dep->de_mode == DEM_ENABLED);
[95ff5c4]99 assert(dep->de_flags & DEF_ENABLED);
100
[21580dd]101 dep->de_flags &= ~(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
[95ff5c4]102
[aadf01e]103 if (mode &DL_PROMISC_REQ)
[21580dd]104 dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
[95ff5c4]105
[aadf01e]106 if (mode &DL_MULTI_REQ)
[21580dd]107 dep->de_flags |= DEF_MULTI;
[95ff5c4]108
[aadf01e]109 if (mode &DL_BROAD_REQ)
[21580dd]110 dep->de_flags |= DEF_BROAD;
[95ff5c4]111
[21580dd]112// dep->de_client = mp->m_source;
113 dp_reinit(dep);
[95ff5c4]114
[21580dd]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;
[95ff5c4]119
[21580dd]120// mess_reply(mp, &reply_mess);
121 return EOK;
122}
123
[95ff5c4]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)) {
[aadf01e]129 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
130 (dep->de_stopf)(dep);
[21580dd]131 dep->de_flags = DEF_EMPTY;
132 }
133}
134
[95ff5c4]135int queue_packet(dpeth_t *dep, packet_t *packet)
136{
[46d4d9f]137 packet_t *tmp;
[95ff5c4]138
139 if (dep->packet_count >= MAX_PACKETS) {
[aadf01e]140 netif_pq_release(packet_get_id(packet));
[21580dd]141 return ELIMIT;
142 }
[95ff5c4]143
[21580dd]144 tmp = dep->packet_queue;
[95ff5c4]145 while (pq_next(tmp))
[aadf01e]146 tmp = pq_next(tmp);
[95ff5c4]147
148 if (pq_add(&tmp, packet, 0, 0) != EOK)
[21580dd]149 return EINVAL;
[95ff5c4]150
151 if (!dep->packet_count)
[21580dd]152 dep->packet_queue = packet;
[95ff5c4]153
154 ++dep->packet_count;
[21580dd]155 return EBUSY;
156}
157
[95ff5c4]158int do_pwrite(dpeth_t *dep, packet_t *packet, int from_int)
[21580dd]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)
[74864ac]168 fprintf(stderr, "dp8390: illegal port\n");
[21580dd]169 dep= &de_table[port];
170 dep->de_client= mp->DL_PROC;
171*/
[95ff5c4]172 if (dep->de_mode == DEM_SINK) {
[21580dd]173 assert(!from_int);
174// dep->de_flags |= DEF_PACK_SEND;
[74864ac]175 reply(dep, EOK, false);
[21580dd]176// return;
177 return EOK;
178 }
[95ff5c4]179
[21580dd]180 assert(dep->de_mode == DEM_ENABLED);
[aadf01e]181 assert(dep->de_flags &DEF_ENABLED);
[95ff5c4]182
183 if ((dep->packet_queue) && (!from_int)) {
[aadf01e]184// if (dep->de_flags &DEF_SEND_AVAIL){
[74864ac]185// fprintf(stderr, "dp8390: send already in progress\n");
[aadf01e]186 return queue_packet(dep, packet);
[21580dd]187 }
[95ff5c4]188
[21580dd]189 sendq_head= dep->de_sendq_head;
[95ff5c4]190// if (dep->de_sendq[sendq_head].sq_filled) {
[21580dd]191// if (from_int)
[74864ac]192// fprintf(stderr, "dp8390: should not be sending\n");
[21580dd]193// dep->de_sendmsg= *mp;
194// dep->de_flags |= DEF_SEND_AVAIL;
[74864ac]195// reply(dep, EOK, false);
[21580dd]196// return;
[aadf01e]197// return queue_packet(dep, packet);
[21580dd]198// }
[aadf01e]199// assert(!(dep->de_flags &DEF_PACK_SEND));
[95ff5c4]200
201/* if (vectored) {
[21580dd]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;
[95ff5c4]207
[21580dd]208 dep->de_tmp_iovec = dep->de_write_iovec;
209 size = calc_iovec_size(&dep->de_tmp_iovec);
[95ff5c4]210 } else {
[21580dd]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*/
[aadf01e]220 size = packet_get_data_length(packet);
[d3a0af7]221 dep->de_write_iovec.iod_iovec[0].iov_addr = (void *) packet_get_data(packet);
[21580dd]222 dep->de_write_iovec.iod_iovec[0].iov_size = size;
223 dep->de_write_iovec.iod_iovec_s = 1;
[d3a0af7]224 dep->de_write_iovec.iod_iovec_addr = NULL;
[95ff5c4]225
226 if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED) {
[74864ac]227 fprintf(stderr, "dp8390: invalid packet size\n");
[21580dd]228 return EINVAL;
229 }
[95ff5c4]230
[21580dd]231 (dep->de_user2nicf)(dep, &dep->de_write_iovec, 0,
[95ff5c4]232 dep->de_sendq[sendq_head].sq_sendpage * DP_PAGESIZE,
233 size);
[74864ac]234 dep->de_sendq[sendq_head].sq_filled= true;
[95ff5c4]235 if (dep->de_sendq_tail == sendq_head) {
[21580dd]236 outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);
237 outb_reg0(dep, DP_TBCR1, size >> 8);
[95ff5c4]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;
[21580dd]242
243 if (++sendq_head == dep->de_sendq_nr)
244 sendq_head= 0;
[95ff5c4]245
[21580dd]246 assert(sendq_head < SENDQ_NR);
[95ff5c4]247 dep->de_sendq_head = sendq_head;
248
[21580dd]249// dep->de_flags |= DEF_PACK_SEND;
[95ff5c4]250
251 /*
252 * If the interrupt handler called, don't send a reply. The reply
[21580dd]253 * will be sent after all interrupts are handled.
254 */
255 if (from_int)
256 return EOK;
[95ff5c4]257
[74864ac]258 reply(dep, EOK, false);
[95ff5c4]259
[21580dd]260 assert(dep->de_mode == DEM_ENABLED);
[95ff5c4]261 assert(dep->de_flags & DEF_ENABLED);
262
[21580dd]263 return EOK;
264}
265
[95ff5c4]266void dp_init(dpeth_t *dep)
[21580dd]267{
268 int dp_rcr_reg;
[d3c9b60]269 int i;
[95ff5c4]270
[21580dd]271 /* General initialization */
272 dep->de_flags = DEF_EMPTY;
273 (*dep->de_initf)(dep);
[95ff5c4]274
[506a805]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');
[d3c9b60]278
279 /*
280 * Initialization of the dp8390 following the mandatory procedure
[21580dd]281 * in reference manual ("DP8390D/NS32490D NIC Network Interface
282 * Controller", National Semiconductor, July 1995, Page 29).
283 */
[d3c9b60]284
[21580dd]285 /* Step 1: */
286 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
[d3c9b60]287
[21580dd]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);
[d3c9b60]293
[21580dd]294 /* Step 3: */
295 outb_reg0(dep, DP_RBCR0, 0);
296 outb_reg0(dep, DP_RBCR1, 0);
[d3c9b60]297
[21580dd]298 /* Step 4: */
299 dp_rcr_reg = 0;
[d3c9b60]300
301 if (dep->de_flags & DEF_PROMISC)
[21580dd]302 dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
[d3c9b60]303
304 if (dep->de_flags & DEF_BROAD)
[21580dd]305 dp_rcr_reg |= RCR_AB;
[d3c9b60]306
307 if (dep->de_flags & DEF_MULTI)
[21580dd]308 dp_rcr_reg |= RCR_AM;
[d3c9b60]309
[21580dd]310 outb_reg0(dep, DP_RCR, dp_rcr_reg);
[d3c9b60]311
[21580dd]312 /* Step 5: */
313 outb_reg0(dep, DP_TCR, TCR_INTERNAL);
[d3c9b60]314
[21580dd]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);
[d3c9b60]319
[21580dd]320 /* Step 7: */
321 outb_reg0(dep, DP_ISR, 0xFF);
[d3c9b60]322
[21580dd]323 /* Step 8: */
324 outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
[d3c9b60]325 IMR_OVWE | IMR_CNTE);
326
[21580dd]327 /* Step 9: */
328 outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
[d3c9b60]329
[21580dd]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]);
[d3c9b60]336
[21580dd]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);
[d3c9b60]345
[21580dd]346 outb_reg1(dep, DP_CURR, dep->de_startpage + 1);
[d3c9b60]347
[21580dd]348 /* Step 10: */
349 outb_reg0(dep, DP_CR, CR_DM_ABORT | CR_STA);
[d3c9b60]350
[21580dd]351 /* Step 11: */
352 outb_reg0(dep, DP_TCR, TCR_NORMAL);
[d3c9b60]353
354 inb_reg0(dep, DP_CNTR0); /* Reset counters by reading */
[21580dd]355 inb_reg0(dep, DP_CNTR1);
356 inb_reg0(dep, DP_CNTR2);
[d3c9b60]357
[21580dd]358 /* Finish the initialization. */
359 dep->de_flags |= DEF_ENABLED;
[d3c9b60]360 for (i = 0; i < dep->de_sendq_nr; i++)
[21580dd]361 dep->de_sendq[i].sq_filled= 0;
[d3c9b60]362
363 dep->de_sendq_head = 0;
364 dep->de_sendq_tail = 0;
365
366 if (dep->de_16bit) {
[21580dd]367 dep->de_user2nicf= dp_pio16_user2nic;
368 dep->de_nic2userf= dp_pio16_nic2user;
369 dep->de_getblockf= dp_pio16_getblock;
[d3c9b60]370 } else {
[21580dd]371 dep->de_user2nicf= dp_pio8_user2nic;
372 dep->de_nic2userf= dp_pio8_nic2user;
373 dep->de_getblockf= dp_pio8_getblock;
374 }
375}
376
[b590c21]377static void dp_reinit(dpeth_t *dep)
[21580dd]378{
379 int dp_rcr_reg;
[b590c21]380
[21580dd]381 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
[b590c21]382
[21580dd]383 dp_rcr_reg = 0;
[b590c21]384
385 if (dep->de_flags & DEF_PROMISC)
[21580dd]386 dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
[b590c21]387
388 if (dep->de_flags & DEF_BROAD)
[21580dd]389 dp_rcr_reg |= RCR_AB;
[b590c21]390
391 if (dep->de_flags & DEF_MULTI)
[21580dd]392 dp_rcr_reg |= RCR_AM;
[b590c21]393
[21580dd]394 outb_reg0(dep, DP_RCR, dp_rcr_reg);
395}
396
[b590c21]397static void dp_reset(dpeth_t *dep)
[21580dd]398{
399 int i;
[b590c21]400
[21580dd]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);
[b590c21]405
406 for (i = 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
[21580dd]407 ; /* Do nothing */
[b590c21]408
409 outb_reg0(dep, DP_TCR, TCR_1EXTERNAL | TCR_OFST);
410 outb_reg0(dep, DP_CR, CR_STA | CR_DM_ABORT);
[21580dd]411 outb_reg0(dep, DP_TCR, TCR_NORMAL);
[b590c21]412
413 /* Acknowledge the ISR_RDC (remote DMA) interrupt. */
414 for (i = 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) &ISR_RDC) == 0); i++)
[21580dd]415 ; /* Do nothing */
[b590c21]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
[21580dd]421 * pretend that the packet is processed. Higher layers will
422 * retransmit if the packet wasn't actually sent.
423 */
[b590c21]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
[21580dd]430 dp_send(dep);
431 dep->de_flags &= ~DEF_STOPPED;
432}
433
[6fc0edd]434void dp_check_ints(dpeth_t *dep, int isr)
[21580dd]435{
[6fc0edd]436 int tsr;
[21580dd]437 int size, sendq_tail;
[0777f4c5]438
439 if (!(dep->de_flags & DEF_ENABLED))
[74864ac]440 fprintf(stderr, "dp8390: got premature interrupt\n");
[0777f4c5]441
[6fc0edd]442 for (; isr; isr = inb_reg0(dep, DP_ISR)) {
[21580dd]443 outb_reg0(dep, DP_ISR, isr);
[0777f4c5]444
445 if (isr & (ISR_PTX | ISR_TXE)) {
446 if (isr & ISR_TXE)
[21580dd]447 dep->de_stat.ets_sendErr++;
[0777f4c5]448 else {
[21580dd]449 tsr = inb_reg0(dep, DP_TSR);
[0777f4c5]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++;
[21580dd]471 }
[0777f4c5]472
473 sendq_tail = dep->de_sendq_tail;
474
475 if (!(dep->de_sendq[sendq_tail].sq_filled)) {
[21580dd]476 /* Or hardware bug? */
[0777f4c5]477 printf("%s: transmit interrupt, but not sending\n", dep->de_name);
[21580dd]478 continue;
479 }
[0777f4c5]480
481 dep->de_sendq[sendq_tail].sq_filled = 0;
482
[21580dd]483 if (++sendq_tail == dep->de_sendq_nr)
[0777f4c5]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;
[21580dd]490 outb_reg0(dep, DP_TPSR,
[0777f4c5]491 dep->de_sendq[sendq_tail].sq_sendpage);
[21580dd]492 outb_reg0(dep, DP_TBCR1, size >> 8);
[0777f4c5]493 outb_reg0(dep, DP_TBCR0, size & 0xff);
[21580dd]494 outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);
495 }
[0777f4c5]496
[aadf01e]497// if (dep->de_flags &DEF_SEND_AVAIL)
[21580dd]498 dp_send(dep);
499 }
[0777f4c5]500
501 if (isr & ISR_PRX) {
[21580dd]502 /* Only call dp_recv if there is a read request */
[aadf01e]503// if (dep->de_flags) &DEF_READING)
[21580dd]504 dp_recv(dep);
505 }
506
[0777f4c5]507 if (isr & ISR_RXE)
508 dep->de_stat.ets_recvErr++;
509
510 if (isr & ISR_CNT) {
[21580dd]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 }
[0777f4c5]515
516 if (isr & ISR_OVW) {
[21580dd]517 dep->de_stat.ets_OVW++;
[0777f4c5]518/* if (dep->de_flags & DEF_READING) {
519 printf("dp_check_ints: strange: overwrite warning and pending read request\n");
[21580dd]520 dp_recv(dep);
521 }
522*/ }
[0777f4c5]523
524 if (isr & ISR_RDC) {
[21580dd]525 /* Nothing to do */
526 }
[0777f4c5]527
528 if (isr & ISR_RST) {
529 /*
530 * This means we got an interrupt but the ethernet
[21580dd]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 }
[0777f4c5]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.
[21580dd]545 */
546 dp_reset(dep);
547 }
548}
549
[6fc0edd]550static void dp_recv(dpeth_t *dep)
[21580dd]551{
552 dp_rcvhdr_t header;
[04729b1]553 //unsigned pageno, curr, next;
554 int pageno, curr, next;
[d3a0af7]555 size_t length;
[21580dd]556 int packet_processed, r;
[74864ac]557 uint16_t eth_type;
[b590c21]558
[74864ac]559 packet_processed = false;
[21580dd]560 pageno = inb_reg0(dep, DP_BNRY) + 1;
[b590c21]561 if (pageno == dep->de_stoppage)
562 pageno = dep->de_startpage;
563
564 do {
[21580dd]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);
[b590c21]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);
[21580dd]576 next = header.dr_next;
[b590c21]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);
[21580dd]579 next= curr;
[b590c21]580 } else if ((next < dep->de_startpage) || (next >= dep->de_stoppage)) {
[21580dd]581 printf("%s: strange next page\n", dep->de_name);
582 next= curr;
[b590c21]583 } else if (header.dr_status & RSR_FO) {
584 /*
585 * This is very serious, so we issue a warning and
586 * reset the buffers
[21580dd]587 */
[b590c21]588 printf("%s: fifo overrun, resetting receive buffer\n", dep->de_name);
[21580dd]589 dep->de_stat.ets_fifoOver++;
590 next = curr;
[b590c21]591 } else if ((header.dr_status & RSR_PRX) && (dep->de_flags & DEF_ENABLED)) {
592 r = dp_pkt2user(dep, pageno, length);
[fc23ef6]593 if (r != EOK)
[21580dd]594 return;
[b590c21]595
[74864ac]596 packet_processed = true;
[21580dd]597 dep->de_stat.ets_packetR++;
598 }
[b590c21]599
[21580dd]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);
[b590c21]604
[21580dd]605 pageno = next;
[b590c21]606 } while (!packet_processed);
[21580dd]607}
608
[b590c21]609static void dp_send(dpeth_t *dep)
[21580dd]610{
[46d4d9f]611 packet_t *packet;
[b590c21]612
[aadf01e]613// if (!(dep->de_flags &DEF_SEND_AVAIL))
[21580dd]614// return;
[b590c21]615
616 if (dep->packet_queue) {
[21580dd]617 packet = dep->packet_queue;
[aadf01e]618 dep->packet_queue = pq_detach(packet);
[74864ac]619 do_pwrite(dep, packet, true);
[aadf01e]620 netif_pq_release(packet_get_id(packet));
[b590c21]621 --dep->packet_count;
[21580dd]622 }
[b590c21]623
624// if (!dep->packet_queue)
[21580dd]625// dep->de_flags &= ~DEF_SEND_AVAIL;
[b590c21]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;
[21580dd]637 default:
[74864ac]638 fprintf(stderr, "dp8390: wrong type\n");
[21580dd]639 break;
640 }
641*/
642}
643
[b590c21]644static void dp_pio8_getblock(dpeth_t *dep, int page, size_t offset, size_t size, void *dst)
[21580dd]645{
646 offset = page * DP_PAGESIZE + offset;
[aadf01e]647 outb_reg0(dep, DP_RBCR0, size &0xFF);
[21580dd]648 outb_reg0(dep, DP_RBCR1, size >> 8);
[aadf01e]649 outb_reg0(dep, DP_RSAR0, offset &0xFF);
[21580dd]650 outb_reg0(dep, DP_RSAR1, offset >> 8);
651 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
[b590c21]652
[21580dd]653 insb(dep->de_data_port, dst, size);
654}
655
[b590c21]656static void dp_pio16_getblock(dpeth_t *dep, int page, size_t offset, size_t size, void *dst)
[21580dd]657{
658 offset = page * DP_PAGESIZE + offset;
[aadf01e]659 outb_reg0(dep, DP_RBCR0, size &0xFF);
[21580dd]660 outb_reg0(dep, DP_RBCR1, size >> 8);
[aadf01e]661 outb_reg0(dep, DP_RSAR0, offset &0xFF);
[21580dd]662 outb_reg0(dep, DP_RSAR1, offset >> 8);
663 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
[b590c21]664
665 assert(!(size & 1));
666
[21580dd]667 insw(dep->de_data_port, dst, size);
668}
669
[b590c21]670static int dp_pkt2user(dpeth_t *dep, int page, int length)
[21580dd]671{
672 int last, count;
[46d4d9f]673 packet_t *packet;
[b590c21]674
675// if (!(dep->de_flags & DEF_READING))
[21580dd]676// return EGENERIC;
[b590c21]677
[aadf01e]678 packet = netif_packet_get_1(length);
[b590c21]679 if (!packet)
[aadf01e]680 return ENOMEM;
[b590c21]681
[d3a0af7]682 dep->de_read_iovec.iod_iovec[0].iov_addr = (void *) packet_suffix(packet, length);
[21580dd]683 dep->de_read_iovec.iod_iovec[0].iov_size = length;
684 dep->de_read_iovec.iod_iovec_s = 1;
[d3a0af7]685 dep->de_read_iovec.iod_iovec_addr = NULL;
[b590c21]686
[21580dd]687 last = page + (length - 1) / DP_PAGESIZE;
[b590c21]688 if (last >= dep->de_stoppage) {
689 count = (dep->de_stoppage - page) * DP_PAGESIZE - sizeof(dp_rcvhdr_t);
690
[21580dd]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 +
[b590c21]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 {
[21580dd]698 (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
[b590c21]699 sizeof(dp_rcvhdr_t), &dep->de_read_iovec, 0, length);
[21580dd]700 }
[b590c21]701
[21580dd]702 dep->de_read_s = length;
703 dep->de_flags |= DEF_PACK_RECV;
704// dep->de_flags &= ~DEF_READING;
[b590c21]705
706 if (dep->received_count >= MAX_PACKETS) {
[aadf01e]707 netif_pq_release(packet_get_id(packet));
[21580dd]708 return ELIMIT;
[b590c21]709 } else {
710 if (pq_add(&dep->received_queue, packet, 0, 0) == EOK)
711 ++dep->received_count;
712 else
[aadf01e]713 netif_pq_release(packet_get_id(packet));
[21580dd]714 }
[b590c21]715
[fc23ef6]716 return EOK;
[21580dd]717}
718
[d3a0af7]719static void dp_pio8_user2nic(dpeth_t *dep, iovec_dat_t *iovp, size_t offset, int nic_addr, size_t count)
[21580dd]720{
721// phys_bytes phys_user;
[04729b1]722 int i;
[d3a0af7]723 size_t bytes;
724
[21580dd]725 outb_reg0(dep, DP_ISR, ISR_RDC);
[d3a0af7]726
727 outb_reg0(dep, DP_RBCR0, count & 0xFF);
[21580dd]728 outb_reg0(dep, DP_RBCR1, count >> 8);
[d3a0af7]729 outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
[21580dd]730 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
731 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
[d3a0af7]732
733 i = 0;
734 while (count > 0) {
735 if (i >= IOVEC_NR) {
[21580dd]736 dp_next_iovec(iovp);
[d3a0af7]737 i = 0;
[21580dd]738 continue;
739 }
[d3a0af7]740
[21580dd]741 assert(i < iovp->iod_iovec_s);
[d3a0af7]742
743 if (offset >= iovp->iod_iovec[i].iov_size) {
[21580dd]744 offset -= iovp->iod_iovec[i].iov_size;
745 i++;
746 continue;
747 }
[d3a0af7]748
[21580dd]749 bytes = iovp->iod_iovec[i].iov_size - offset;
750 if (bytes > count)
751 bytes = count;
[d3a0af7]752
753 do_vir_outsb(dep->de_data_port, iovp->iod_iovec[i].iov_addr + offset, bytes);
[21580dd]754 count -= bytes;
755 offset += bytes;
756 }
[d3a0af7]757
[21580dd]758 assert(count == 0);
[d3a0af7]759
760 for (i = 0; i < 100; i++) {
761 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
[21580dd]762 break;
763 }
[d3a0af7]764
[21580dd]765 if (i == 100)
[74864ac]766 fprintf(stderr, "dp8390: remote dma failed to complete\n");
[21580dd]767}
768
[d3a0af7]769static void dp_pio16_user2nic(dpeth_t *dep, iovec_dat_t *iovp, size_t offset, int nic_addr, size_t count)
[21580dd]770{
[d3a0af7]771 void *vir_user;
772 size_t ecount;
773 int i, r;
774 size_t bytes;
[74864ac]775 //uint8_t two_bytes[2];
776 uint16_t two_bytes;
[21580dd]777 int odd_byte;
[d3a0af7]778
779 ecount = (count + 1) & ~1;
780 odd_byte = 0;
781
[21580dd]782 outb_reg0(dep, DP_ISR, ISR_RDC);
[d3a0af7]783 outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
[21580dd]784 outb_reg0(dep, DP_RBCR1, ecount >> 8);
[d3a0af7]785 outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
[21580dd]786 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
787 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
[d3a0af7]788
789 i = 0;
790 while (count > 0) {
791 if (i >= IOVEC_NR) {
[21580dd]792 dp_next_iovec(iovp);
[d3a0af7]793 i = 0;
[21580dd]794 continue;
795 }
[d3a0af7]796
[21580dd]797 assert(i < iovp->iod_iovec_s);
[d3a0af7]798
799 if (offset >= iovp->iod_iovec[i].iov_size) {
[21580dd]800 offset -= iovp->iod_iovec[i].iov_size;
801 i++;
802 continue;
803 }
[d3a0af7]804
[21580dd]805 bytes = iovp->iod_iovec[i].iov_size - offset;
806 if (bytes > count)
807 bytes = count;
[d3a0af7]808
809 vir_user = iovp->iod_iovec[i].iov_addr + offset;
810
811 if (odd_byte) {
812 r = sys_vircopy(user_proc, D, vir_user,
813 // SELF, D, (vir_bytes) &two_bytes[1], 1);
814 SELF, D, &(((uint8_t *) &two_bytes)[1]), 1);
815
[fc23ef6]816 if (r != EOK)
[74864ac]817 fprintf(stderr, "DP8390: dp_pio16_user2nic: sys_vircopy failed\n");
818
[d3a0af7]819 //outw(dep->de_data_port, *(uint16_t *) two_bytes);
[04729b1]820 outw(dep->de_data_port, two_bytes);
[21580dd]821 count--;
822 offset++;
823 bytes--;
824 vir_user++;
825 odd_byte= 0;
[d3a0af7]826
[21580dd]827 if (!bytes)
828 continue;
829 }
[d3a0af7]830
831 ecount= bytes & ~1;
832 if (ecount != 0) {
833 do_vir_outsw(dep->de_data_port, vir_user, ecount);
[21580dd]834 count -= ecount;
835 offset += ecount;
836 bytes -= ecount;
837 vir_user += ecount;
838 }
[d3a0af7]839
840 if (bytes) {
[21580dd]841 assert(bytes == 1);
[d3a0af7]842
843 r = sys_vircopy(user_proc, D, vir_user,
844 // SELF, D, (vir_bytes) &two_bytes[0], 1);
845 SELF, D, &(((uint8_t *) &two_bytes)[0]), 1);
846
[fc23ef6]847 if (r != EOK)
[74864ac]848 fprintf(stderr, "DP8390: dp_pio16_user2nic: sys_vircopy failed\n");
849
[21580dd]850 count--;
851 offset++;
852 bytes--;
853 vir_user++;
854 odd_byte= 1;
855 }
856 }
[d3a0af7]857
[21580dd]858 assert(count == 0);
[d3a0af7]859
[21580dd]860 if (odd_byte)
[d3a0af7]861 //outw(dep->de_data_port, *(uint16_t *) two_bytes);
[04729b1]862 outw(dep->de_data_port, two_bytes);
[d3a0af7]863
864 for (i = 0; i < 100; i++) {
[aadf01e]865 if (inb_reg0(dep, DP_ISR) &ISR_RDC)
[21580dd]866 break;
867 }
[d3a0af7]868
[21580dd]869 if (i == 100)
[74864ac]870 fprintf(stderr, "dp8390: remote dma failed to complete\n");
[21580dd]871}
872
[d3a0af7]873static void dp_pio8_nic2user(dpeth_t *dep, int nic_addr, iovec_dat_t *iovp, size_t offset, size_t count)
[21580dd]874{
875// phys_bytes phys_user;
[04729b1]876 int i;
[d3a0af7]877 size_t bytes;
878
879 outb_reg0(dep, DP_RBCR0, count & 0xFF);
[21580dd]880 outb_reg0(dep, DP_RBCR1, count >> 8);
[d3a0af7]881 outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
[21580dd]882 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
883 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
[d3a0af7]884
885 i = 0;
886 while (count > 0) {
887 if (i >= IOVEC_NR) {
[21580dd]888 dp_next_iovec(iovp);
889 i= 0;
890 continue;
891 }
[d3a0af7]892
[21580dd]893 assert(i < iovp->iod_iovec_s);
[d3a0af7]894
895 if (offset >= iovp->iod_iovec[i].iov_size) {
[21580dd]896 offset -= iovp->iod_iovec[i].iov_size;
897 i++;
898 continue;
899 }
[d3a0af7]900
[21580dd]901 bytes = iovp->iod_iovec[i].iov_size - offset;
902 if (bytes > count)
903 bytes = count;
[d3a0af7]904
905 do_vir_insb(dep->de_data_port, iovp->iod_iovec[i].iov_addr + offset, bytes);
[21580dd]906 count -= bytes;
907 offset += bytes;
908 }
[d3a0af7]909
[21580dd]910 assert(count == 0);
911}
912
[d3a0af7]913static void dp_pio16_nic2user(dpeth_t *dep, int nic_addr, iovec_dat_t *iovp, size_t offset, size_t count)
[21580dd]914{
[d3a0af7]915 void *vir_user;
916 size_t ecount;
917 int i, r;
918 size_t bytes;
[74864ac]919 //uint8_t two_bytes[2];
920 uint16_t two_bytes;
[21580dd]921 int odd_byte;
[d3a0af7]922
923 ecount = (count + 1) & ~1;
924 odd_byte = 0;
925
926 outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
[21580dd]927 outb_reg0(dep, DP_RBCR1, ecount >> 8);
[d3a0af7]928 outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
[21580dd]929 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
930 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
[d3a0af7]931
932 i = 0;
933 while (count > 0) {
934 if (i >= IOVEC_NR) {
[21580dd]935 dp_next_iovec(iovp);
[d3a0af7]936 i = 0;
[21580dd]937 continue;
938 }
[d3a0af7]939
[21580dd]940 assert(i < iovp->iod_iovec_s);
[d3a0af7]941
942 if (offset >= iovp->iod_iovec[i].iov_size) {
[21580dd]943 offset -= iovp->iod_iovec[i].iov_size;
944 i++;
945 continue;
946 }
[d3a0af7]947
[21580dd]948 bytes = iovp->iod_iovec[i].iov_size - offset;
949 if (bytes > count)
950 bytes = count;
[d3a0af7]951
952 vir_user = iovp->iod_iovec[i].iov_addr + offset;
953
954 if (odd_byte) {
[04729b1]955 //r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[1],
[d3a0af7]956 r= sys_vircopy(SELF, D, &(((uint8_t *) &two_bytes)[1]),
957 user_proc, D, vir_user, 1);
[fc23ef6]958 if (r != EOK)
[74864ac]959 fprintf(stderr, "DP8390: dp_pio16_nic2user: sys_vircopy failed\n");
960
[21580dd]961 count--;
962 offset++;
963 bytes--;
964 vir_user++;
965 odd_byte= 0;
[d3a0af7]966
[21580dd]967 if (!bytes)
968 continue;
969 }
[d3a0af7]970
971 ecount= bytes & ~1;
972 if (ecount != 0) {
973 do_vir_insw(dep->de_data_port, vir_user, ecount);
[21580dd]974 count -= ecount;
975 offset += ecount;
976 bytes -= ecount;
977 vir_user += ecount;
978 }
[d3a0af7]979
980 if (bytes) {
[21580dd]981 assert(bytes == 1);
[d3a0af7]982
983 //*(uint16_t *) two_bytes= inw(dep->de_data_port);
984 two_bytes = inw(dep->de_data_port);
985 //r= sys_vircopy(SELF, D, (vir_bytes) &two_bytes[0],
986 r = sys_vircopy(SELF, D, &(((uint8_t *) &two_bytes)[0]),
987 user_proc, D, vir_user, 1);
[fc23ef6]988 if (r != EOK)
[74864ac]989 fprintf(stderr, "DP8390: dp_pio16_nic2user: sys_vircopy failed\n");
990
[21580dd]991 count--;
992 offset++;
993 bytes--;
994 vir_user++;
995 odd_byte= 1;
996 }
997 }
[d3a0af7]998
[21580dd]999 assert(count == 0);
1000}
1001
[d3a0af7]1002static void dp_next_iovec(iovec_dat_t *iovp)
[21580dd]1003{
1004 assert(iovp->iod_iovec_s > IOVEC_NR);
[d3a0af7]1005
[21580dd]1006 iovp->iod_iovec_s -= IOVEC_NR;
1007 iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
[d3a0af7]1008
1009 memcpy(iovp->iod_iovec, iovp->iod_iovec_addr,
1010 (iovp->iod_iovec_s > IOVEC_NR ? IOVEC_NR : iovp->iod_iovec_s) *
1011 sizeof(iovec_t));
[21580dd]1012}
1013
[d3a0af7]1014static void conf_hw(dpeth_t *dep)
[21580dd]1015{
[aadf01e]1016// static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 /* ,... */};
[d3a0af7]1017
[21580dd]1018// int ifnr;
1019// dp_conf_t *dcp;
[d3a0af7]1020
[21580dd]1021// dep->de_mode= DEM_DISABLED; /* Superfluous */
1022// ifnr= dep-de_table;
[d3a0af7]1023
[21580dd]1024// dcp= &dp_conf[ifnr];
1025// update_conf(dep, dcp);
1026// if (dep->de_mode != DEM_ENABLED)
1027// return;
[d3a0af7]1028
[8f5e2527]1029 if (!ne_probe(dep)) {
[7e752b2]1030 printf("%s: No ethernet card found at %#lx\n",
1031 dep->de_name, dep->de_base_port);
[21580dd]1032 dep->de_mode= DEM_DISABLED;
1033 return;
1034 }
[d3a0af7]1035
[21580dd]1036 dep->de_mode = DEM_ENABLED;
1037 dep->de_flags = DEF_EMPTY;
1038// dep->de_stat = empty_stat;
1039}
1040
[d3a0af7]1041static void reply(dpeth_t *dep, int err, int may_block)
[21580dd]1042{
1043/* message reply;
1044 int status;
1045 int r;
[d3a0af7]1046
[21580dd]1047 status = 0;
[aadf01e]1048 if (dep->de_flags &DEF_PACK_SEND)
[21580dd]1049 status |= DL_PACK_SEND;
[d3a0af7]1050
[aadf01e]1051 if (dep->de_flags &DEF_PACK_RECV)
[21580dd]1052 status |= DL_PACK_RECV;
[d3a0af7]1053
[21580dd]1054 reply.m_type = DL_TASK_REPLY;
1055 reply.DL_PORT = dep - de_table;
1056 reply.DL_PROC = dep->de_client;
1057 reply.DL_STAT = status | ((u32_t) err << 16);
1058 reply.DL_COUNT = dep->de_read_s;
[d3a0af7]1059 reply.DL_CLCK = 0; *//* Don't know */
1060
1061/* r = send(dep->de_client, &reply);
1062 if (r == ELOCKED && may_block) {
[21580dd]1063 printf("send locked\n");
1064 return;
1065 }
[d3a0af7]1066
[21580dd]1067 if (r < 0)
[74864ac]1068 fprintf(stderr, "dp8390: send failed\n");
[21580dd]1069
1070*/ dep->de_read_s = 0;
1071// dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV);
1072}
1073
1074static void insb(port_t port, void *buf, size_t size)
1075{
1076 size_t i;
[d3a0af7]1077
1078 for (i = 0; i < size; i++)
[aadf01e]1079 *((uint8_t *) buf + i) = inb(port);
[21580dd]1080}
1081
1082static void insw(port_t port, void *buf, size_t size)
1083{
1084 size_t i;
[d3a0af7]1085
1086 for (i = 0; i * 2 < size; i++)
[aadf01e]1087 *((uint16_t *) buf + i) = inw(port);
[21580dd]1088}
1089
1090static void outsb(port_t port, void *buf, size_t size)
1091{
1092 size_t i;
[d3a0af7]1093
1094 for (i = 0; i < size; i++)
[aadf01e]1095 outb(port, *((uint8_t *) buf + i));
[21580dd]1096}
1097
1098static void outsw(port_t port, void *buf, size_t size)
1099{
1100 size_t i;
[d3a0af7]1101
1102 for (i = 0; i * 2 < size; i++)
[aadf01e]1103 outw(port, *((uint16_t *) buf + i));
[21580dd]1104}
1105
1106/** @}
1107 */
Note: See TracBrowser for help on using the repository browser.