FreeBSD/Linux Kernel Cross Reference
sys/drivers/dpeth/dp.c
1 /*
2 ** File: eth.c Version 1.00, Jan. 14, 1997
3 **
4 ** Author: Giovanni Falzoni <gfalzoni@inwind.it>
5 **
6 ** This file contains the ethernet device driver main task.
7 ** It has to be integrated with the board specific drivers.
8 ** It is a rewriting of Minix 2.0.0 ethernet driver (dp8390.c)
9 ** to remove bord specific code. It should operate (I hope)
10 ** with any board driver.
11 **
12 ** The valid messages and their parameters are:
13 **
14 ** m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR
15 ** +------------+---------+---------+--------+-------+---------+
16 ** | HARD_INT | | | | | |
17 ** +------------+---------+---------+--------+-------+---------+
18 ** | SYN_ALARM | | | | | |
19 ** +------------+---------+---------+--------+-------+---------+
20 ** | HARD_STOP | | | | | |
21 ** +------------+---------+---------+--------+-------+---------+
22 ** | FKEY_PRESSED | | | | | (99)
23 ** +------------+---------+---------+--------+-------+---------+
24 ** | DL_WRITE | port nr | proc nr | count | mode | address | (3)
25 ** +------------+---------+---------+--------+-------+---------+
26 ** | DL_WRITEV | port nr | proc nr | count | mode | address | (4)
27 ** +------------+---------+---------+--------+-------+---------+
28 ** | DL_READ | port nr | proc nr | count | | address | (5)
29 ** +------------+---------+---------+--------+-------+---------+
30 ** | DL_READV | port nr | proc nr | count | | address | (6)
31 ** +------------+---------+---------+--------+-------+---------+
32 ** | DL_INIT | port nr | proc nr | | mode | address | (7)
33 ** +------------+---------+---------+--------+-------+---------+
34 ** | DL_STOP | port_nr | | | | | (8)
35 ** +------------+---------+---------+--------+-------+---------+
36 ** | DL_GETSTAT | port nr | proc nr | | | address | (9)
37 ** +------------+---------+---------+--------+-------+---------+
38 **
39 ** The messages sent are:
40 **
41 ** m-type DL_PORT DL_PROC DL_COUNT DL_STAT DL_CLCK
42 ** +------------+---------+---------+--------+---------+---------+
43 ** |DL_TASK_REPL| port nr | proc nr |rd-count| err|stat| clock | (21)
44 ** +------------+---------+---------+--------+---------+---------+
45 **
46 ** m_type m3_i1 m3_i2 m3_ca1
47 ** +------------+---------+---------+---------------+
48 ** |DL_INIT_REPL| port nr |last port| ethernet addr | (20)
49 ** +------------+---------+---------+---------------+
50 **
51 ** $Id: dp.c,v 1.11 2005/10/21 17:09:08 philip Exp $
52 */
53
54 #include "drivers.h"
55 #include <minix/keymap.h>
56 #include <net/hton.h>
57 #include <net/gen/ether.h>
58 #include <net/gen/eth_io.h>
59
60 #include "dp.h"
61
62 /*
63 ** Local data
64 */
65 extern int errno;
66 static dpeth_t de_table[DE_PORT_NR];
67 static char *progname;
68
69 typedef struct dp_conf { /* Configuration description structure */
70 port_t dpc_port;
71 int dpc_irq;
72 phys_bytes dpc_mem;
73 char *dpc_envvar;
74 } dp_conf_t;
75
76 /* Device default configuration */
77 static dp_conf_t dp_conf[DE_PORT_NR] = {
78 /* I/O port, IRQ, Buff addr, Env. var, Buf. selector */
79 { 0x300, 5, 0xC8000, "DPETH0", },
80 { 0x280, 10, 0xCC000, "DPETH1", },
81 };
82
83 static const char CopyErrMsg[] = "unable to read/write user data";
84 static const char PortErrMsg[] = "illegal port";
85 static const char RecvErrMsg[] = "receive failed";
86 static const char SendErrMsg[] = "send failed";
87 static const char SizeErrMsg[] = "illegal packet size";
88 static const char TypeErrMsg[] = "illegal message type";
89 static const char DevName[] = "eth#?";
90
91 static void do_getname(message *mp);
92
93 /*
94 ** Name: void reply(dpeth_t *dep, int err)
95 ** Function: Fills a DL_TASK_REPLY reply message and sends it.
96 */
97 static void reply(dpeth_t * dep, int err)
98 {
99 message reply;
100 int status = FALSE;
101
102 if (dep->de_flags & DEF_ACK_SEND) status |= DL_PACK_SEND;
103 if (dep->de_flags & DEF_ACK_RECV) status |= DL_PACK_RECV;
104
105 reply.m_type = DL_TASK_REPLY;
106 reply.DL_PORT = dep - de_table;
107 reply.DL_PROC = dep->de_client;
108 reply.DL_STAT = status /* | ((u32_t) err << 16) */;
109 reply.DL_COUNT = dep->de_read_s;
110 getuptime(&reply.DL_CLCK);
111
112 DEBUG(printf("\t reply %d (%ld)\n", reply.m_type, reply.DL_STAT));
113
114 if ((status = send(dep->de_client, &reply)) == OK) {
115 dep->de_read_s = 0;
116 dep->de_flags &= NOT(DEF_ACK_SEND | DEF_ACK_RECV);
117
118 } else if (status != ELOCKED || err == OK)
119 panic(dep->de_name, SendErrMsg, status);
120
121 return;
122 }
123
124 /*
125 ** Name: void dp_confaddr(dpeth_t *dep)
126 ** Function: Checks environment for a User defined ethernet address.
127 */
128 static void dp_confaddr(dpeth_t * dep)
129 {
130 static char ea_fmt[] = "x:x:x:x:x:x";
131 char ea_key[16];
132 int ix;
133 long val;
134
135 strcpy(ea_key, dp_conf[dep - de_table].dpc_envvar);
136 strcat(ea_key, "_EA");
137
138 for (ix = 0; ix < SA_ADDR_LEN; ix++) {
139 val = dep->de_address.ea_addr[ix];
140 if (env_parse(ea_key, ea_fmt, ix, &val, 0x00L, 0xFFL) != EP_SET)
141 break;
142 dep->de_address.ea_addr[ix] = val;
143 }
144
145 if (ix != 0 && ix != SA_ADDR_LEN)
146 /* It's all or nothing, force a panic */
147 env_parse(ea_key, "?", 0, &val, 0L, 0L);
148 return;
149 }
150
151 /*
152 ** Name: void update_conf(dpeth_t *dep, dp_conf_t *dcp)
153 ** Function: Gets the default settings from 'dp_conf' table and
154 ** modifies them from the environment.
155 */
156 static void update_conf(dpeth_t * dep, dp_conf_t * dcp)
157 {
158 static char dpc_fmt[] = "x:d:x";
159 long val;
160
161 dep->de_mode = DEM_SINK;
162 val = dcp->dpc_port; /* Get I/O port address */
163 switch (env_parse(dcp->dpc_envvar, dpc_fmt, 0, &val, 0x000L, 0x3FFL)) {
164 case EP_OFF: dep->de_mode = DEM_DISABLED; break;
165 case EP_ON:
166 case EP_SET: dep->de_mode = DEM_ENABLED; break;
167 }
168 dep->de_base_port = val;
169
170 val = dcp->dpc_irq | DEI_DEFAULT; /* Get Interrupt line (IRQ) */
171 env_parse(dcp->dpc_envvar, dpc_fmt, 1, &val, 0L, (long) NR_IRQ_VECTORS - 1);
172 dep->de_irq = val;
173
174 val = dcp->dpc_mem; /* Get shared memory address */
175 env_parse(dcp->dpc_envvar, dpc_fmt, 2, &val, 0L, LONG_MAX);
176 dep->de_linmem = val;
177
178 return;
179 }
180
181 /*
182 ** Name: void do_dump(message *mp)
183 ** Function: Displays statistics on screen (SFx key from console)
184 */
185 static void do_dump(message *mp)
186 {
187 dpeth_t *dep;
188 int port;
189
190 printf("\n\n");
191 for (port = 0, dep = de_table; port < DE_PORT_NR; port += 1, dep += 1) {
192
193 if (dep->de_mode == DEM_DISABLED) continue;
194
195 printf("%s statistics:\t\t", dep->de_name);
196
197 /* Network interface status */
198 printf("Status: 0x%04x (%d)\n\n", dep->de_flags, dep->de_int_pending);
199
200 (*dep->de_dumpstatsf) (dep);
201
202 /* Transmitted/received bytes */
203 printf("Tx bytes:%10ld\t", dep->bytes_Tx);
204 printf("Rx bytes:%10ld\n", dep->bytes_Rx);
205
206 /* Transmitted/received packets */
207 printf("Tx OK: %8ld\t", dep->de_stat.ets_packetT);
208 printf("Rx OK: %8ld\n", dep->de_stat.ets_packetR);
209
210 /* Transmit/receive errors */
211 printf("Tx Err: %8ld\t", dep->de_stat.ets_sendErr);
212 printf("Rx Err: %8ld\n", dep->de_stat.ets_recvErr);
213
214 /* Transmit unnerruns/receive overrruns */
215 printf("Tx Und: %8ld\t", dep->de_stat.ets_fifoUnder);
216 printf("Rx Ovr: %8ld\n", dep->de_stat.ets_fifoOver);
217
218 /* Transmit collisions/receive CRC errors */
219 printf("Tx Coll: %8ld\t", dep->de_stat.ets_collision);
220 printf("Rx CRC: %8ld\n", dep->de_stat.ets_CRCerr);
221 }
222 return;
223 }
224
225 /*
226 ** Name: void get_userdata(int user_proc, vir_bytes user_addr, int count, void *loc_addr)
227 ** Function: Copies data from user area.
228 */
229 static void get_userdata(int user_proc, vir_bytes user_addr, int count, void *loc_addr)
230 {
231 int rc;
232 vir_bytes len;
233
234 len = (count > IOVEC_NR ? IOVEC_NR : count) * sizeof(iovec_t);
235 if ((rc = sys_datacopy(user_proc, user_addr, SELF, (vir_bytes)loc_addr, len)) != OK)
236 panic(DevName, CopyErrMsg, rc);
237 return;
238 }
239
240 /*
241 ** Name: void do_first_init(dpeth_t *dep, dp_conf_t *dcp);
242 ** Function: Init action to setup task
243 */
244 static void do_first_init(dpeth_t *dep, dp_conf_t *dcp)
245 {
246
247 if (dep->de_linmem != 0) {
248 dep->de_memsegm = BIOS_SEG;
249 /* phys2seg(&dep->de_memsegm, &dep->de_memoffs, dep->de_linmem); */
250 } else
251 dep->de_linmem = 0xFFFF0000;
252
253 /* Make sure statisics are cleared */
254 memset((void *) &(dep->de_stat), 0, sizeof(eth_stat_t));
255
256 /* Device specific initialization */
257 (*dep->de_initf) (dep);
258
259 /* Set the interrupt handler policy. Request interrupts not to be reenabled
260 * automatically. Return the IRQ line number when an interrupt occurs.
261 */
262 dep->de_hook = dep->de_irq;
263 sys_irqsetpolicy(dep->de_irq, 0 /*IRQ_REENABLE*/, &dep->de_hook);
264 dep->de_int_pending = FALSE;
265 sys_irqenable(&dep->de_hook);
266
267 return;
268 }
269
270 /*
271 ** Name: void do_init(message *mp)
272 ** Function: Checks for hardware presence.
273 ** Provides initialization of hardware and data structures
274 */
275 static void do_init(message * mp)
276 {
277 int port;
278 dpeth_t *dep;
279 dp_conf_t *dcp;
280 message reply_mess;
281
282 port = mp->DL_PORT;
283 if (port >= 0 && port < DE_PORT_NR) {
284
285 dep = &de_table[port];
286 dcp = &dp_conf[port];
287 strcpy(dep->de_name, DevName);
288 dep->de_name[4] = '' + port;
289
290 if (dep->de_mode == DEM_DISABLED) {
291
292 update_conf(dep, dcp); /* First time thru */
293 if (dep->de_mode == DEM_ENABLED &&
294 !el1_probe(dep) && /* Probe for 3c501 */
295 !wdeth_probe(dep) && /* Probe for WD80x3 */
296 !ne_probe(dep) && /* Probe for NEx000 */
297 !el2_probe(dep) && /* Probe for 3c503 */
298 !el3_probe(dep)) { /* Probe for 3c509 */
299 printf("%s: warning no ethernet card found at 0x%04X\n",
300 dep->de_name, dep->de_base_port);
301 dep->de_mode = DEM_DISABLED;
302 }
303 }
304
305 /* 'de_mode' may change if probe routines fail, test again */
306 switch (dep->de_mode) {
307
308 case DEM_DISABLED:
309 /* Device is configured OFF or hardware probe failed */
310 port = ENXIO;
311 break;
312
313 case DEM_ENABLED:
314 /* Device is present and probed */
315 if (dep->de_flags == DEF_EMPTY) {
316 /* These actions only the first time */
317 do_first_init(dep, dcp);
318 dep->de_flags |= DEF_ENABLED;
319 }
320 dep->de_flags &= NOT(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
321 if (mp->DL_MODE & DL_PROMISC_REQ)
322 dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
323 if (mp->DL_MODE & DL_MULTI_REQ) dep->de_flags |= DEF_MULTI;
324 if (mp->DL_MODE & DL_BROAD_REQ) dep->de_flags |= DEF_BROAD;
325 (*dep->de_flagsf) (dep);
326 dep->de_client = mp->m_source;
327 break;
328
329 case DEM_SINK:
330 /* Device not present (sink mode) */
331 memset(dep->de_address.ea_addr, 0, sizeof(ether_addr_t));
332 dp_confaddr(dep); /* Station address from env. */
333 break;
334
335 default: break;
336 }
337 *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
338
339 } else /* Port number is out of range */
340 port = ENXIO;
341
342 reply_mess.m_type = DL_INIT_REPLY;
343 reply_mess.m3_i1 = port;
344 reply_mess.m3_i2 = DE_PORT_NR;
345 DEBUG(printf("\t reply %d\n", reply_mess.m_type));
346 if (send(mp->m_source, &reply_mess) != OK) /* Can't send */
347 panic(dep->de_name, SendErrMsg, mp->m_source);
348
349 return;
350 }
351
352 /*
353 ** Name: void dp_next_iovec(iovec_dat_t *iovp)
354 ** Function: Retrieves data from next iovec element.
355 */
356 PUBLIC void dp_next_iovec(iovec_dat_t * iovp)
357 {
358
359 iovp->iod_iovec_s -= IOVEC_NR;
360 iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
361 get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr,
362 iovp->iod_iovec_s, iovp->iod_iovec);
363 return;
364 }
365
366 /*
367 ** Name: int calc_iovec_size(iovec_dat_t *iovp)
368 ** Function: Compute the size of a request.
369 */
370 static int calc_iovec_size(iovec_dat_t * iovp)
371 {
372 int size, ix;
373
374 size = ix = 0;
375 do {
376 size += iovp->iod_iovec[ix].iov_size;
377 if (++ix >= IOVEC_NR) {
378 dp_next_iovec(iovp);
379 ix = 0;
380 }
381
382 /* Till all vectors added */
383 } while (ix < iovp->iod_iovec_s);
384 return size;
385 }
386
387 /*
388 ** Name: void do_vwrite(message *mp, int vectored)
389 ** Function:
390 */
391 static void do_vwrite(message * mp, int vectored)
392 {
393 int port, size;
394 dpeth_t *dep;
395
396 port = mp->DL_PORT;
397 if (port < 0 || port >= DE_PORT_NR) /* Check for illegal port number */
398 panic(dep->de_name, PortErrMsg, port);
399
400 dep = &de_table[port];
401 dep->de_client = mp->DL_PROC;
402
403 if (dep->de_mode == DEM_ENABLED) {
404
405 if (dep->de_flags & DEF_SENDING) /* Is sending in progress? */
406 panic(dep->de_name, "send already in progress ", NO_NUM);
407
408 dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
409 if (vectored) {
410 get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
411 mp->DL_COUNT, dep->de_write_iovec.iod_iovec);
412 dep->de_write_iovec.iod_iovec_s = mp->DL_COUNT;
413 dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
414 size = calc_iovec_size(&dep->de_write_iovec);
415 } else {
416 dep->de_write_iovec.iod_iovec[0].iov_addr = (vir_bytes) mp->DL_ADDR;
417 dep->de_write_iovec.iod_iovec[0].iov_size = size = mp->DL_COUNT;
418 dep->de_write_iovec.iod_iovec_s = 1;
419 dep->de_write_iovec.iod_iovec_addr = 0;
420 }
421 if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE)
422 panic(dep->de_name, SizeErrMsg, size);
423
424 dep->de_flags |= DEF_SENDING;
425 (*dep->de_sendf) (dep, FALSE, size);
426
427 } else if (dep->de_mode == DEM_SINK)
428 dep->de_flags |= DEF_ACK_SEND;
429
430 reply(dep, OK);
431 return;
432 }
433
434 /*
435 ** Name: void do_vread(message *mp, int vectored)
436 ** Function:
437 */
438 static void do_vread(message * mp, int vectored)
439 {
440 int port, size;
441 dpeth_t *dep;
442
443 port = mp->DL_PORT;
444 if (port < 0 || port >= DE_PORT_NR) /* Check for illegal port number */
445 panic(dep->de_name, PortErrMsg, port);
446
447 dep = &de_table[port];
448 dep->de_client = mp->DL_PROC;
449
450 if (dep->de_mode == DEM_ENABLED) {
451
452 if (dep->de_flags & DEF_READING) /* Reading in progress */
453 panic(dep->de_name, "read already in progress", NO_NUM);
454
455 dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
456 if (vectored) {
457 get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
458 mp->DL_COUNT, dep->de_read_iovec.iod_iovec);
459 dep->de_read_iovec.iod_iovec_s = mp->DL_COUNT;
460 dep->de_read_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
461 size = calc_iovec_size(&dep->de_read_iovec);
462 } else {
463 dep->de_read_iovec.iod_iovec[0].iov_addr = (vir_bytes) mp->DL_ADDR;
464 dep->de_read_iovec.iod_iovec[0].iov_size = size = mp->DL_COUNT;
465 dep->de_read_iovec.iod_iovec_s = 1;
466 dep->de_read_iovec.iod_iovec_addr = 0;
467 }
468 if (size < ETH_MAX_PACK_SIZE) panic(dep->de_name, SizeErrMsg, size);
469
470 dep->de_flags |= DEF_READING;
471 (*dep->de_recvf) (dep, FALSE, size);
472 #if 0
473 if ((dep->de_flags & (DEF_READING | DEF_STOPPED)) == (DEF_READING | DEF_STOPPED))
474 /* The chip is stopped, and all arrived packets delivered */
475 (*dep->de_resetf) (dep);
476 dep->de_flags &= NOT(DEF_STOPPED);
477 #endif
478 }
479 reply(dep, OK);
480 return;
481 }
482
483 /*
484 ** Name: void do_getstat(message *mp)
485 ** Function: Reports device statistics.
486 */
487 static void do_getstat(message * mp)
488 {
489 int port, rc;
490 dpeth_t *dep;
491
492 port = mp->DL_PORT;
493 if (port < 0 || port >= DE_PORT_NR) /* Check for illegal port number */
494 panic(dep->de_name, PortErrMsg, port);
495
496 dep = &de_table[port];
497 dep->de_client = mp->DL_PROC;
498
499 if (dep->de_mode == DEM_ENABLED) (*dep->de_getstatsf) (dep);
500 if ((rc = sys_datacopy(SELF, (vir_bytes)&dep->de_stat,
501 mp->DL_PROC, (vir_bytes)mp->DL_ADDR,
502 (vir_bytes) sizeof(dep->de_stat))) != OK)
503 panic(DevName, CopyErrMsg, rc);
504 reply(dep, OK);
505 return;
506 }
507
508 static void do_getname(mp)
509 message *mp;
510 {
511 int r;
512
513 strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
514 mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';
515 mp->m_type= DL_NAME_REPLY;
516 r= send(mp->m_source, mp);
517 if (r != OK)
518 panic("dpeth", "do_getname: send failed: %d\n", r);
519 }
520
521 /*
522 ** Name: void do_stop(message *mp)
523 ** Function: Stops network interface.
524 */
525 static void do_stop(message * mp)
526 {
527 int port;
528 dpeth_t *dep;
529
530 port = mp->DL_PORT;
531 if (port < 0 || port >= DE_PORT_NR) /* Check for illegal port number */
532 panic(dep->de_name, PortErrMsg, port);
533
534 dep = &de_table[port];
535 if (dep->de_mode == DEM_ENABLED && (dep->de_flags & DEF_ENABLED)) {
536
537 /* Stop device */
538 (dep->de_stopf) (dep);
539 dep->de_flags = DEF_EMPTY;
540 dep->de_mode = DEM_DISABLED;
541 }
542 return;
543 }
544
545 static void do_watchdog(void *message)
546 {
547
548 DEBUG(printf("\t no reply"));
549 return;
550 }
551
552 /*
553 ** Name: int dpeth_task(void)
554 ** Function: Main entry for dp task
555 */
556 PUBLIC int main(int argc, char **argv)
557 {
558 message m;
559 dpeth_t *dep;
560 int rc, fkeys, sfkeys, tasknr;
561
562 (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
563
564 env_setargs(argc, argv);
565
566 /* Request function key for debug dumps */
567 fkeys = sfkeys = 0; bit_set(sfkeys, 8);
568 if ((fkey_map(&fkeys, &sfkeys)) != OK)
569 printf("%s: couldn't program Shift+F8 key (%d)\n", DevName, errno);
570
571 #ifdef ETH_IGN_PROTO
572 {
573 static u16_t eth_ign_proto = 0;
574 long val;
575 val = 0xFFFF;
576 env_parse("ETH_IGN_PROTO", "x", 0, &val, 0x0000L, 0xFFFFL);
577 eth_ign_proto = htons((u16_t) val);
578 }
579 #endif
580
581 /* Try to notify inet that we are present (again) */
582 rc = findproc("inet", &tasknr);
583 if (rc == OK)
584 notify(tasknr);
585
586 while (TRUE) {
587 if ((rc = receive(ANY, &m)) != OK) panic(dep->de_name, RecvErrMsg, rc);
588
589 DEBUG(printf("eth: got message %d, ", m.m_type));
590
591 switch (m.m_type) {
592 case DEV_PING: /* Status request from RS */
593 notify(m.m_source);
594 continue;
595 case DL_WRITE: /* Write message to device */
596 do_vwrite(&m, FALSE);
597 break;
598 case DL_WRITEV: /* Write message to device */
599 do_vwrite(&m, TRUE);
600 break;
601 case DL_READ: /* Read message from device */
602 do_vread(&m, FALSE);
603 break;
604 case DL_READV: /* Read message from device */
605 do_vread(&m, TRUE);
606 break;
607 case DL_INIT: /* Initialize device */
608 do_init(&m);
609 break;
610 case DL_GETSTAT: /* Get device statistics */
611 do_getstat(&m);
612 break;
613 case DL_GETNAME:
614 do_getname(&m);
615 break;
616 case SYN_ALARM: /* to be defined */
617 do_watchdog(&m);
618 break;
619 case DL_STOP: /* Stop device */
620 do_stop(&m);
621 break;
622 case SYS_SIG: {
623 sigset_t sigset = m.NOTIFY_ARG;
624 if (sigismember(&sigset, SIGKSTOP)) { /* Shut down */
625 for (rc = 0; rc < DE_PORT_NR; rc += 1) {
626 if (de_table[rc].de_mode == DEM_ENABLED) {
627 m.m_type = DL_STOP;
628 m.DL_PORT = rc;
629 do_stop(&m);
630 }
631 }
632 }
633 break;
634 }
635 case HARD_INT: /* Interrupt from device */
636 for (dep = de_table; dep < &de_table[DE_PORT_NR]; dep += 1) {
637 /* If device is enabled and interrupt pending */
638 if (dep->de_mode == DEM_ENABLED) {
639 dep->de_int_pending = TRUE;
640 (*dep->de_interruptf) (dep);
641 if (dep->de_flags & (DEF_ACK_SEND | DEF_ACK_RECV))
642 reply(dep, !OK);
643 dep->de_int_pending = FALSE;
644 sys_irqenable(&dep->de_hook);
645 }
646 }
647 break;
648 case FKEY_PRESSED: /* Function key pressed */
649 do_dump(&m);
650 break;
651 default: /* Invalid message type */
652 panic(DevName, TypeErrMsg, m.m_type);
653 break;
654 }
655 }
656 return OK; /* Never reached, but keeps compiler happy */
657 }
658
659 /** dp.c **/
Cache object: 77b91efbfca22239020e6a4baa00cef2
|