FreeBSD/Linux Kernel Cross Reference
sys/i386ps2/if_en.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1993 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26
27 /*
28 * HISTORY
29 * $Log: if_en.c,v $
30 * Revision 2.2 93/11/17 16:53:33 dbg
31 * Changed start() to return void.
32 * [93/09/13 dbg]
33 *
34 * Created, used if_pc586 as a reference.
35 * [93/09/09 zon]
36 *
37 */
38
39 /* default: no debug messages */
40 #undef EN_DEBUG
41
42 /* default: thick ethernet */
43 #define EN_THIN_ETHERNET 0
44
45 /* default: no loopback */
46 #define EN_LOOPBACK 0
47
48 #include <mach_ttd.h>
49 #include <kern/time_out.h>
50 #include <device/device_types.h>
51 #include <device/errno.h>
52 #include <device/io_req.h>
53 #include <device/if_hdr.h>
54 #include <device/if_ether.h>
55 #include <device/net_status.h>
56 #include <device/net_io.h>
57
58 #include <i386/ipl.h>
59 #include <mach/vm_param.h>
60 #include <vm/vm_kern.h>
61
62 #if MACH_TTD
63 #include <ttd/ttd_stub.h>
64 #endif
65
66 #include <i386ps2/bus.h>
67
68 #include <en.h>
69
70 #ifdef EN_DEBUG
71 /* if non-zero, print debugging information */
72 /* if > 1, print more information */
73 /* if > 2, print even more information */
74 int en_debug = EN_DEBUG;
75 #endif
76
77 /* if non-zero, configure for THIN ethernet, otherwise for THICK ethernet */
78 int en_thin_ethernet = EN_THIN_ETHERNET;
79
80 /* if non-zero, enable hardware loopback */
81 int en_loopback = EN_LOOPBACK;
82
83 /*****************************************************************************/
84
85 /*
86 * LOCAL MEMORY MAP
87 *
88 * SCP FFF6 -- FFFF, 10 BYTES
89 * ISCP FFEE -- FFF5, 8 BYTES
90 * SCB FFDE -- FFED, 16 BYTES
91 * CU FFCC -- FFDD, 18 BYTES
92 * TBD FFC4 -- FFCB, 8 BYTES
93 * TBUF F80E -- FFC3, 1974 BYTES
94 * RBUF C320 -- F80D, 13550 BYTES (25 X 542)
95 * RBD C226 -- C31F, 250 BYTES (25 X 10)
96 * FD C000 -- C225, 550 BYTES (25 X 22)
97 */
98
99 #define RBUF_SIZE 542 /* size of a receive buffer */
100
101 #define TBUF_SIZE 1974 /* size of transmit buffer */
102
103 #define MAX_FD 25 /* FD chain has 25 units */
104 #define MAX_RBD 25 /* RBD chain has 25 units */
105
106 #define ETHER_SIZE 6 /* size of ethernet address */
107
108 #define SCP 0xFFF6 /* local address of SCP */
109 #define ISCP 0xFFEE /* local address of ISCP */
110 #define SCB 0xFFDE /* local address of SCB */
111 #define CU 0xFFCC /* local address of CU */
112 #define TBD 0xFFC4 /* local address of TBD */
113 #define TBUF 0xF80E /* local address of TBUF */
114
115 /* local address of RBUF[i] */
116 #define RBUF(i) (0xC320 + ((i) * RBUF_SIZE))
117
118 /* local address of RBD[i] */
119 #define RBD(i) (0xC226 + ((i) * sizeof(struct rbd)))
120
121 /* local address of FD[i] */
122 #define FD(i) (0xC000 + ((i) * sizeof(struct fd)))
123 #define FD_INDEX(f) (((f) - FD(0)) / sizeof(struct fd))
124
125 typedef struct scp {
126 unsigned short sysbus;
127 unsigned short unused[2];
128 unsigned short iscp;
129 unsigned short iscp_base;
130 } *scp_t;
131
132 typedef struct iscp {
133 unsigned short busy;
134 unsigned short scb_offset;
135 unsigned short scb;
136 unsigned short scb_base;
137 } *iscp_t;
138
139 typedef struct scb {
140 unsigned short status;
141 unsigned short command;
142 unsigned short cbl_offset;
143 unsigned short rfa_offset;
144 unsigned short crcerrs;
145 unsigned short alnerrs;
146 unsigned short rscerrs;
147 unsigned short ovrnerrs;
148 } *scb_t;
149
150 typedef struct transmit {
151 unsigned short tbd_offset;
152 unsigned char dest_addr[ETHER_SIZE];
153 unsigned short length;
154 } *transmit_t;
155
156 typedef struct configure {
157 unsigned short fifolim_bytecnt;
158 unsigned short addrlen_mode;
159 unsigned short linprio_interframe;
160 unsigned short slot_time;
161 unsigned short hardware;
162 unsigned short min_frame_len;
163 } *configure_t;
164
165 /* standard configuration parameters */
166 #define FIFOLIM_BYTECNT 0x080C
167 #define ADDRLEN_MODE 0x2600
168 #define LINPRIO_INTERFRAME 0x6000
169 #define SLOT_TIME 0xF200
170 #define HARDWARE 0x0000
171 #define MIN_FRAME_LEN 0x0040
172
173 typedef struct ac {
174 unsigned short status;
175 unsigned short command;
176 unsigned short link_offset;
177 union {
178 struct transmit transmit;
179 struct configure configure;
180 unsigned char iasetup[ETHER_SIZE];
181 } cmd;
182 } *ac_t;
183
184 typedef struct tbd {
185 unsigned short act_count;
186 unsigned short next_tbd_offset;
187 unsigned short buffer_addr;
188 unsigned short buffer_base;
189 } *tbd_t;
190
191 typedef struct fd {
192 unsigned short status;
193 unsigned short command;
194 unsigned short link_offset;
195 unsigned short rbd_offset;
196 unsigned char destination[ETHER_SIZE];
197 unsigned char source[ETHER_SIZE];
198 unsigned short length;
199 } *fd_t;
200
201 typedef struct rbd {
202 unsigned short status;
203 unsigned short next_rbd_offset;
204 unsigned short buffer_addr;
205 unsigned short buffer_base;
206 unsigned short size;
207 } *rbd_t;
208
209 #define SCB_SW_INT 0xF000
210 #define SCB_SW_CX 0x8000
211 #define SCB_SW_FR 0x4000
212 #define SCB_SW_CNA 0x2000
213 #define SCB_SW_RNR 0x1000
214
215 #define SCB_IDLE 0x0700
216 #define SCB_CUS_IDLE 0x0000
217 #define SCB_CUS_SUSPND 0x0100
218 #define SCB_CUS_ACTV 0x0200
219
220 #define SCB_RUS_IDLE 0x0000
221 #define SCB_RUS_SUSPND 0x0010
222 #define SCB_RUS_NORESRC 0x0020
223 #define SCB_RUS_READY 0x0040
224
225 #define SCB_ACK_CX 0x8000
226 #define SCB_ACK_FR 0x4000
227 #define SCB_ACK_CNA 0x2000
228 #define SCB_ACK_RNR 0x1000
229
230 #define SCB_CU_STRT 0x0100
231 #define SCB_CU_RSUM 0x0200
232 #define SCB_CU_SUSPND 0x0300
233 #define SCB_CU_ABRT 0x0400
234
235 #define SCB_RESET 0x0080
236
237 #define SCB_RU_STRT 0x0010
238 #define SCB_RU_RSUM 0x0020
239 #define SCB_RU_SUSPND 0x0030
240 #define SCB_RU_ABRT 0x0040
241
242 #define AC_NOP 0x00
243 #define AC_IASETUP 0x01
244 #define AC_CONFIGURE 0x02
245 #define AC_MCSETUP 0x03
246 #define AC_TRANSMIT 0x04
247 #define AC_TDR 0x05
248 #define AC_DUMP 0x06
249 #define AC_DIAGNOSE 0x07
250
251 #define AC_SW_C 0x8000
252 #define AC_SW_B 0x4000
253 #define AC_SW_OK 0x2000
254 #define AC_SW_A 0x1000
255 #define AC_SW_FAIL 0x0800
256
257 #define AC_CW_EL 0x8000
258 #define AC_CW_S 0x4000
259 #define AC_CW_I 0x2000
260
261 #define TC_CARRIER 0x0400
262 #define TC_CLS 0x0200
263 #define TC_DMA 0x0100
264 #define TC_DEFER 0x0080
265 #define TC_SQE 0x0040
266 #define TC_COLLISION 0x0020
267
268 #define TBD_SW_EOF 0x8000
269 #define TBD_SW_COUNT 0x3FFF
270
271 #define RBD_SW_EOF 0x8000
272 #define RBD_SW_COUNT 0x3FFF
273 #define RBD_EL 0x8000
274 #define RFD_DONE 0x8000
275 #define RFD_BUSY 0x4000
276 #define RFD_OK 0x2000
277 #define RFD_CRC 0x0800
278 #define RFD_ALN 0x0400
279 #define RFD_RSC 0x0200
280 #define RFD_DMA 0x0100
281 #define RFD_SHORT 0x0080
282 #define RFD_EOF 0x0040
283 #define RFD_EL 0x8000
284 #define RFD_SUSP 0x4000
285
286 /*****************************************************************************/
287
288 static int probe();
289 static int attach();
290 static int interrupt();
291
292 #if MACH_TTD
293 int en_get_packet();
294 int en_send_packet();
295 #endif
296
297 static struct i386_dev *info[NEN];
298
299 struct i386_driver endriver = { probe, 0, attach, "en", info, 0, 0 };
300
301 int (*enintrs[])() = { interrupt, 0 };
302
303 /* spl for network interrupts */
304 #define SPLNET spl6
305
306 /* POS identification for ethernet board */
307 #define EN_POS_ID 0x6042
308
309 /* do automatic reset if no interrupts for 10 seconds */
310 #define AUTOMATIC_RESET 10000
311
312 /* maximum local address (local address is 16 bits) */
313 #define MAX_ADDRESS 0x00010000
314
315 /* window to local memory is 16K bytes */
316 #define WINDOW_SIZE round_page(16 * 1024)
317
318 /* information from ethernet POS registers */
319 typedef struct pos {
320 int card_enabled; /* if non-zero, the card is enabled */
321 int thin_ethernet_enabled; /* if non-zero, thin ethernet is enabled */
322 unsigned short io_base; /* ethernet I/O register base */
323 unsigned long ram_base; /* local memory window base */
324 int interrupt_level; /* ethernet interrupt level (IRQ) */
325 int revision_level; /* ethernet adapter revision level */
326 unsigned short register6; /* address of "register 6" */
327 } *pos_t;
328
329 /* ethernet device per-unit state information */
330 typedef struct en {
331 int unit; /* unit number, index to en[] */
332 struct pos pos; /* POS information */
333 unsigned char bank; /* current local memory bank */
334 unsigned short minimum_address; /* minimum local memory address */
335 unsigned char *window; /* window to local memory */
336 char network_address[ETHER_SIZE]; /* ethernet address */
337 int attached; /* if non-zero, unit is attached */
338 #if MACH_TTD
339 int ttd_enabled; /* if non-zero, TTD polled mode */
340 #endif
341 int busy; /* if non-zero, output is busy */
342 int interrupt_count; /* automatic_reset() counter */
343 unsigned short fd; /* (local) address of current fd */
344 unsigned short end_fd; /* (local) address of end fd */
345 unsigned short end_rbd; /* (local) address of end rbd */
346 volatile scp_t scp; /* pointer to SCP in bank #3 */
347 volatile iscp_t iscp; /* pointer to ISCP in bank #3 */
348 volatile scb_t scb; /* pointer to SCB in bank #3 */
349 volatile ac_t cb; /* pointer to CB in bank #3 */
350 volatile tbd_t tbd; /* pointer to TBD in bank #3 */
351 struct ifnet ifnet; /* IFNET structure */
352 } *en_t;
353
354 /* ethernet device per-unit state information */
355 static struct en en[NEN];
356
357 /*****************************************************************************/
358
359 /* print an ethernet address */
360 static print_ethernet_address(unsigned char *address)
361 {
362 printf("%02X:%02X:%02X:%02X:%02X:%02X",
363 address[0],
364 address[1],
365 address[2],
366 address[3],
367 address[4],
368 address[5]);
369 }
370
371 /*****************************************************************************/
372
373 #define MAX_POS_SLOT 0x0008
374 #define POS_SELECT_PORT 0x0096
375 #define POS_SELECT_BASE 0x0008
376 #define POS_REGISTER_BASE 0x0100
377
378 /* read a POS register */
379 static unsigned char POS_read(int slot, int n)
380 {
381 unsigned char value;
382
383 outb(POS_SELECT_PORT, POS_SELECT_BASE + slot);
384 value = inb(POS_REGISTER_BASE + n);
385 outb(POS_SELECT_PORT, 0);
386
387 return value;
388
389 }
390
391 /* write a POS register */
392 static void POS_write(int slot, int n, unsigned char value)
393 {
394
395 outb(POS_SELECT_PORT, POS_SELECT_BASE + slot);
396 outb(POS_REGISTER_BASE + n, value);
397 outb(POS_SELECT_PORT, 0);
398
399 }
400
401 /* read POS identification in the adapter at the specified slot */
402 static unsigned short POS_read_slot_id(int slot)
403 {
404 union {
405 unsigned short word;
406 unsigned char byte[2];
407 } x;
408
409 x.byte[0] = POS_read(slot, 0);
410 x.byte[1] = POS_read(slot, 1);
411
412 return x.word;
413
414 }
415
416 /* read POS register 'n' in the adapter at the specified slot */
417 static unsigned char POS_read_slot_data(int slot, int n)
418 {
419
420 return POS_read(slot, n + 2);
421
422 }
423
424 /* write POS register 'n' in the adaptor at the specified slot */
425 static void POS_write_slot_data(int slot, int n, unsigned char value)
426 {
427
428 POS_write(slot, n + 2, value);
429
430 }
431
432 /*****************************************************************************/
433
434 /* reset the ethernet adaptor, disable interrupt generation */
435 static void
436 channel_reset(register en_t x)
437 {
438 register volatile unsigned char *w = x->window;
439 register volatile unsigned char ww;
440
441 #ifdef EN_DEBUG
442 if (en_debug > 2)
443 printf("EN%d CHANNEL RESET\n", x->unit);
444 #endif
445
446 outb(x->pos.register6, 0x03);
447 ww = *w;
448 ww = *w;
449 ww = *w;
450 ww = *w;
451 outb(x->pos.register6, 0x83);
452
453 x->bank = 3;
454
455 }
456
457 /* enable the ethernet adaptor to generate interrupts */
458 /* interrupt generation is disabled after a channel_reset() */
459 static void
460 enable_interrupts(register en_t x)
461 {
462
463 outb(x->pos.register6, inb(x->pos.register6) | 0x04);
464
465 }
466
467 /* strobe the ethernet adaptor's channel attention */
468 static void
469 channel_attention(register en_t x)
470 {
471 register unsigned char register6 = inb(x->pos.register6);
472 register volatile unsigned char *w = x->window;
473 register volatile unsigned char ww;
474
475 #ifdef EN_DEBUG
476 if (en_debug > 2)
477 printf("EN%d CHANNEL ATTENTION\n", x->unit);
478 #endif
479
480 outb(x->pos.register6, register6 | 0x40);
481 ww = *w;
482 ww = *w;
483 outb(x->pos.register6, register6);
484
485 }
486
487 /* return an access pointer to local memory */
488 /*** this may move the window to a different bank ***/
489 /* NOTE: all interesting structures are in bank #3 (0xC000 - 0xFFFF) */
490 static unsigned char *
491 window(register en_t x, register unsigned short address)
492 {
493 register unsigned char bank = ((address) >> 14) & 3;
494
495 if (address < x->minimum_address)
496 panic("EN%d WINDOW ADDRESS 0x%04X < 0x%04X\n",
497 x->unit,
498 address,
499 x->minimum_address);
500
501 if (bank != x->bank) {
502 outb(x->pos.register6,
503 (inb(x->pos.register6) & 0xFC) | bank);
504 x->bank = bank;
505 }
506
507 return &x->window[address & 0x3FFF];
508
509 }
510
511 /* check a bank of local memory, return zero if OK */
512 /* return address+1 if local memory error */
513 static int bank_check(register en_t x, unsigned short base)
514 {
515 int i;
516 int bank = (base >> 14) & 3;
517 unsigned char *w = window(x, base);
518
519 for (i = 0; i < 0x4000; i++)
520 *window(x, base + i) = (i + bank) & 0xFF;
521
522 for (i = 0; i < 0x4000; i++)
523 if (*window(x, base + i) != ((i + bank) & 0xFF))
524 return base + i + 1;
525
526 return 0;
527
528 }
529
530 /*****************************************************************************/
531
532 /* probe for an ethernet device, return non-zero if one is found */
533 /* this routine reads all POS register information for the adaptor */
534 static int probe(addr, iod)
535 register caddr_t addr;
536 register struct i386_dev *iod;
537 {
538 register en_t x = &en[iod->dev_unit];
539 unsigned char register0;
540 unsigned char register1;
541 int slot;
542 int unit;
543
544 /* search for an adaptor for the specified device unit */
545 unit = 0;
546 for (slot = 0; slot < MAX_POS_SLOT; slot++) {
547 if ((POS_read_slot_id(slot) == EN_POS_ID) &&
548 (unit++ == iod->dev_unit))
549 break;
550 }
551 if (slot == MAX_POS_SLOT)
552 return 0;
553
554 /* set device unit (index to en[]) */
555 x->unit = iod->dev_unit;
556
557 /* read POS register #0 */
558 register0 = POS_read_slot_data(slot, 0);
559
560 /* read CARD_ENABLED bit */
561 x->pos.card_enabled = register0 & 0x01;
562
563 /* read/set THIN_ETHERNET_ENABLED bit */
564 if (x->pos.thin_ethernet_enabled = !(register0 & 0x20)) {
565 if (!en_thin_ethernet) {
566 register0 |= 0x20;
567 POS_write_slot_data(slot, 0, register0);
568 }
569 }
570 else {
571 if (en_thin_ethernet) {
572 register0 &= ~0x20;
573 POS_write_slot_data(slot, 0, register0);
574 }
575 }
576
577 /* read IO_BASE */
578 switch (register0 & 0x06) {
579 case 0x00:
580 x->pos.io_base = 0x0300;
581 break;
582 case 0x02:
583 x->pos.io_base = 0x1300;
584 break;
585 case 0x04:
586 x->pos.io_base = 0x2300;
587 break;
588 case 0x06:
589 x->pos.io_base = 0x3300;
590 break;
591 }
592
593 /* read RAM_BASE */
594 switch (register0 & 0x18) {
595 case 0x00:
596 x->pos.ram_base = 0x000C0000;
597 break;
598 case 0x08:
599 x->pos.ram_base = 0x000C8000;
600 break;
601 case 0x10:
602 x->pos.ram_base = 0x000D0000;
603 break;
604 case 0x18:
605 x->pos.ram_base = 0x000D8000;
606 break;
607 }
608
609 /* read INTERRUPT_LEVEL */
610 switch (register0 & 0xC0) {
611 case 0x00:
612 x->pos.interrupt_level = 12;
613 break;
614 case 0x40:
615 x->pos.interrupt_level = 7;
616 break;
617 case 0x80:
618 x->pos.interrupt_level = 3;
619 break;
620 case 0xC0:
621 x->pos.interrupt_level = 9;
622 break;
623 }
624
625 /* write INTERRUPT_LEVEL to cover POST routine bug */
626 register1 = POS_read_slot_data(slot, 1);
627 register1 &= 0xF0;
628 switch (x->pos.interrupt_level) {
629 case 12:
630 register1 |= 0x01;
631 break;
632 case 7:
633 register1 |= 0x02;
634 break;
635 case 3:
636 register1 |= 0x04;
637 break;
638 case 9:
639 register1 |= 0x08;
640 break;
641 }
642 POS_write_slot_data(slot, 1, register1);
643
644 #ifdef EN_DEBUG
645 if (en_debug > 2) {
646 printf("ENPROBE: EN%d\n", x->unit);
647 printf(" BOARD IS %s\n",
648 x->pos.card_enabled ? "ENABLED" : "DISABLED");
649 printf(" THIN ETHERNET IS %s\n",
650 x->pos.thin_ethernet_enabled ? "ENABLED" : "DISABLED");
651 printf(" IO BASE IS 0x%04X\n",
652 x->pos.io_base);
653 printf(" RAM BASE IS 0x%08X\n",
654 x->pos.ram_base);
655 printf(" INTERRUPT LEVEL IS %d\n",
656 x->pos.interrupt_level);
657 }
658 #endif
659
660 /* complain if the adaptor is not enabled */
661 if (!x->pos.card_enabled)
662 printf("EN%d: ETHERNET ADAPTOR IS NOT ENABLED.\n", x->unit);
663
664 /* return non-zero if enabled ethernet adaptor has been found */
665 return x->pos.card_enabled;
666
667 }
668
669 /* attach an ethernet device, return non-zero if success */
670 /* this routine sets up the device per-unit state information */
671 static int attach(iod)
672 register struct i386_dev *iod;
673 {
674 register en_t x = &en[iod->dev_unit];
675 register int i;
676 int memory_size;
677
678 /* cache the I/O address of adaptor register #6 */
679 x->pos.register6 = x->pos.io_base + 6;
680
681 /* get a pointer to the local memory window */
682 x->window = (void *)phystokv(x->pos.ram_base);
683
684 /* reset the ethernet adaptor */
685 channel_reset(x);
686
687 /* read the ethernet address */
688 for (i = 0; i < ETHER_SIZE; i++)
689 x->network_address[i] = inb(x->pos.io_base + i);
690
691 /* display the ethernet address */
692 #ifdef EN_DEBUG
693 if (en_debug > 2)
694 printf("ENATTACH: EN%d\n"
695 " ETHERNET ADDRESS ",
696 x->unit);
697 else
698 #endif
699 printf("EN%d: ", x->unit);
700 print_ethernet_address(x->network_address);
701 printf("\n");
702
703 /* read the revision level from adaptor register #7 */
704 x->pos.revision_level = inb(x->pos.io_base + 7) & 0x0F;
705
706 #ifdef EN_DEBUG
707 if (en_debug > 2)
708 printf(" REVISION LEVEL IS '%X'\n",
709 x->pos.revision_level);
710 #endif
711
712 /* error if incorrect revision level */
713 switch (x->pos.revision_level) {
714 case 0x0F:
715 case 0x0E:
716 break;
717 default:
718 printf("EN%d: INCORRECT REVISION LEVEL '%X'\n",
719 x->unit,
720 x->pos.revision_level);
721 return 0;
722 }
723
724 /* check local memory, determine size of local memory */
725 /* error if can not access at least 16K of local memory */
726 x->minimum_address = 0x0000;
727 if (i = bank_check(x, 0xC000)) {
728 printf("EN%d: CAN NOT ACCESS LOCAL MEMORY AT 0x%04x\n",
729 x->unit,
730 i - 1);
731 return 0;
732 }
733 else if (bank_check(x, 0x8000)) {
734 memory_size = 16;
735 x->minimum_address = 0xC000;
736 }
737 else if (bank_check(x, 0x4000)) {
738 memory_size = 32;
739 x->minimum_address = 0x8000;
740 }
741 else if (bank_check(x, 0x0000)) {
742 memory_size = 48;
743 x->minimum_address = 0x4000;
744 }
745 else {
746 memory_size = 64;
747 x->minimum_address = 0x0000;
748 }
749
750 #ifdef EN_DEBUG
751 if (en_debug > 2)
752 printf(" THERE ARE %dK BYTES OF LOCAL MEMORY\n",
753 memory_size);
754 #endif
755
756 /* set up IFNET structure for this device unit */
757 x->ifnet.if_unit = x->unit;
758 x->ifnet.if_mtu = ETHERMTU;
759 x->ifnet.if_flags = IFF_BROADCAST;
760 x->ifnet.if_header_size = sizeof(struct ether_header);
761 x->ifnet.if_header_format = HDR_ETHERNET;
762 x->ifnet.if_address_size = 6;
763 x->ifnet.if_address = x->network_address;
764 if_init_queues(&x->ifnet);
765
766 /* connect interrupt handler to the adaptor's IRQ */
767 iod->dev_pic = x->pos.interrupt_level;
768 iod->dev_spl = SPL4;
769 take_dev_irq(iod);
770
771 /* this ethernet device unit has been attached OK */
772 x->attached = 1;
773
774 #if MACH_TTD
775 if (!ttd_get_packet) {
776 ttd_device_unit = x->unit;
777 ttd_get_packet = en_get_packet;
778 ttd_send_packet = en_send_packet;
779 memcpy(ttd_host_ether_id.array,
780 x->network_address,
781 ETHER_SIZE);
782 }
783 #endif
784
785 #ifdef EN_DEBUG
786 if (en_debug > 2)
787 printf("EN%d ATTACH: OK\n", x->unit);
788 #endif
789
790 /* return non-zero if attached OK */
791 return !x->attached;
792
793 }
794
795 /*****************************************************************************/
796
797 #ifdef EN_DEBUG
798
799 static void print_scp(en_t x, unsigned short scp_offset)
800 {
801 scp_t scp = (scp_t)window(x, scp_offset);
802
803 printf("SCP 0x%04X: SYSBUS=0x%04X ISCP=0x%04X ISCP_BASE=0x%04X\n",
804 scp_offset,
805 scp->sysbus,
806 scp->iscp,
807 scp->iscp_base);
808
809 }
810
811 static void print_iscp(en_t x, unsigned short iscp_offset)
812 {
813 iscp_t iscp = (iscp_t)window(x, iscp_offset);
814
815 printf("ISCP 0x%04X: BUSY=0x%04X SCB_OFFSET=0x%04X "
816 "SCB=0x%04X SCB_BASE=0x%04X\n",
817 iscp_offset,
818 iscp->busy,
819 iscp->scb_offset,
820 iscp->scb,
821 iscp->scb_base);
822
823 }
824
825 static void print_scb(en_t x, unsigned short scb_offset)
826 {
827 scb_t scb = (scb_t)window(x, scb_offset);
828
829 printf("SCB 0x%04X: STATUS=0x%04X COMMAND=0x%04X\n",
830 scb_offset,
831 scb->status,
832 scb->command);
833 printf(" CBL_OFFSET=0x%04X RFA_OFFSET=0x%04X\n",
834 scb->cbl_offset,
835 scb->rfa_offset);
836 printf(" ERRS 0x%04X 0x%04X 0x%04X 0x%04X\n",
837 scb->crcerrs,
838 scb->alnerrs,
839 scb->rscerrs,
840 scb->ovrnerrs);
841
842 }
843
844 static void print_ac(en_t x, unsigned short cb_offset)
845 {
846 ac_t cb = (ac_t)window(x, cb_offset);
847
848 printf("CB 0x%04X: STATUS=0x%04X COMMAND=0x%04X LINK_OFFSET=0x%04X\n",
849 cb_offset,
850 cb->status,
851 cb->command,
852 cb->link_offset);
853 switch (cb->command & 0x0007) {
854 case AC_NOP:
855 printf("NOP\n");
856 break;
857 case AC_IASETUP:
858 printf("IASETUP: ");
859 print_ethernet_address(cb->cmd.iasetup);
860 printf("\n");
861 break;
862 case AC_CONFIGURE:
863 printf("CONFIGURE: %d %d %d %d %d %d\n",
864 cb->cmd.configure.fifolim_bytecnt,
865 cb->cmd.configure.addrlen_mode,
866 cb->cmd.configure.linprio_interframe,
867 cb->cmd.configure.slot_time,
868 cb->cmd.configure.hardware,
869 cb->cmd.configure.min_frame_len);
870 break;
871 case AC_MCSETUP:
872 printf("MCSETUP\n");
873 break;
874 case AC_TRANSMIT:
875 printf("TRANSMIT: 0x%04X ",
876 cb->cmd.transmit.tbd_offset);
877 print_ethernet_address(cb->cmd.transmit.dest_addr);
878 printf(" %d\n", cb->cmd.transmit.length);
879 break;
880 case AC_TDR:
881 printf("TDR\n");
882 break;
883 case AC_DUMP:
884 printf("DUMP\n");
885 break;
886 case AC_DIAGNOSE:
887 printf("DIAGNOSE\n");
888 break;
889 }
890 }
891
892 static void print_fd(en_t x, unsigned short fd_offset)
893 {
894 fd_t fd = (fd_t)window(x, fd_offset);
895
896 printf("FD 0x%04X: STATUS=0x%04X COMMAND=0x%04X\n",
897 fd_offset,
898 fd->status,
899 fd->command);
900 printf(" LINK=0x%04X RBD=0x%04X\n",
901 fd->link_offset,
902 fd->rbd_offset);
903 printf(" DEST=");
904 print_ethernet_address(fd->destination);
905 printf("\n");
906 printf(" SOURCE=");
907 print_ethernet_address(fd->source);
908 printf("\n");
909 printf(" LENGTH=%d\n", fd->length);
910
911 }
912
913 #endif
914
915 /*****************************************************************************/
916
917 /* acknowledge any completed commands, return non-zero if error */
918 static int acknowledge(register en_t x, char *where)
919 {
920 register int i;
921
922 if (x->scb->command = (x->scb->status & SCB_SW_INT)) {
923
924 #ifdef EN_DEBUG
925 if (en_debug > 2)
926 printf("EN%d %s: ACKNOWLEDGE 0x%04X\n",
927 x->unit,
928 where,
929 x->scb->status & SCB_SW_INT);
930 #endif
931
932 channel_attention(x);
933 for (i = 0; i < 1000000; i++)
934 if (!x->scb->command)
935 break;
936 if (x->scb->command) {
937 printf("EN%d %s: 0x%04X NOT ACKNOWLEDGED\n",
938 x->unit,
939 where,
940 x->scb->command);
941 return -1;
942 }
943
944 }
945
946 return 0;
947
948 }
949
950 /* run a command, return non-zero if error */
951 static int
952 run_command(register en_t x,
953 char *where,
954 char *what,
955 register int interrupt)
956 {
957 int i;
958
959 x->cb->status = 0;
960 x->cb->command |= AC_CW_EL;
961 x->cb->link_offset = CU;
962
963 if (interrupt)
964 x->cb->command |= AC_CW_I;
965
966 #ifdef EN_DEBUG
967 if (en_debug > 2)
968 print_ac(x, CU);
969 #endif
970
971 if (interrupt)
972 while (x->scb->command);
973
974 x->scb->command = SCB_CU_STRT;
975
976 channel_attention(x);
977
978 if (interrupt)
979 return 0;
980
981 for(i = 0; i < 10000000; i++)
982 if (x->cb->status & AC_SW_C)
983 break;
984
985 x->cb->command = AC_CW_EL;
986
987 if (x->cb->status & AC_SW_B) {
988 printf("EN%d %s: %s TIMEOUT\n", x->unit, where, what);
989 return -1;
990 }
991
992 if (!(x->cb->status & AC_SW_C) ||
993 !(x->cb->status & AC_SW_OK)) {
994 printf("EN%d %s: %s FAILED (0x%04X)\n",
995 x->unit,
996 where,
997 what,
998 x->cb->status);
999 return -1;
1000 }
1001
1002 if (acknowledge(x, where))
1003 return -1;
1004
1005 return 0;
1006
1007 }
1008
1009 /* do a NOP command, return non-zero if error */
1010 static int ac_nop(register en_t x, char *where)
1011 {
1012
1013 x->cb->command = AC_NOP;
1014
1015 return run_command(x, where, "NOP", 0);
1016
1017 }
1018
1019 /* do a DIAGNOSE command, return non-zero if error */
1020 static int ac_diagnose(register en_t x, char *where)
1021 {
1022
1023 x->cb->command = AC_DIAGNOSE;
1024
1025 return run_command(x, where, "DIAGNOSE", 0);
1026
1027 }
1028
1029 /* do a CONFIGURE command, return non-zero if error */
1030 static int
1031 ac_configure(register en_t x,
1032 char *where,
1033 unsigned short fifolim_bytecnt,
1034 unsigned short addrlen_mode,
1035 unsigned short linprio_interframe,
1036 unsigned short slot_time,
1037 unsigned short hardware,
1038 unsigned short min_frame_len)
1039 {
1040
1041 x->cb->command = AC_CONFIGURE;
1042 x->cb->cmd.configure.fifolim_bytecnt = fifolim_bytecnt;
1043 x->cb->cmd.configure.addrlen_mode = addrlen_mode;
1044 x->cb->cmd.configure.linprio_interframe = linprio_interframe;
1045 x->cb->cmd.configure.slot_time = slot_time;
1046 x->cb->cmd.configure.hardware = hardware;
1047 x->cb->cmd.configure.min_frame_len = min_frame_len;
1048
1049 return run_command(x, where, "CONFIGURE", 0);
1050
1051 }
1052
1053 /* do an IASETUP command, return non-zero if error */
1054 static int
1055 ac_iasetup(register en_t x,
1056 char *where,
1057 unsigned char *network_address)
1058 {
1059
1060 x->cb->command = AC_IASETUP;
1061
1062 memcpy(x->cb->cmd.iasetup, x->network_address, ETHER_SIZE);
1063
1064 return run_command(x, where, "IASETUP", 0);
1065
1066 }
1067
1068 /*****************************************************************************/
1069
1070 /* build the FD chain */
1071 static void build_fd_chain(register en_t x)
1072 {
1073 register int i;
1074
1075 for (i = 0; i < MAX_FD; i++) {
1076 register fd_t fd = (fd_t)window(x, FD(i));
1077 fd->status = 0;
1078 fd->command = 0;
1079 fd->rbd_offset = i ? 0xFFFF : RBD(0);
1080 if ((i + 1) < MAX_FD) {
1081 fd->link_offset = FD(i + 1);
1082 }
1083 else {
1084 fd->command |= AC_CW_EL;
1085 fd->link_offset = 0xFFFF;
1086 }
1087 }
1088
1089 /* the first FD in the chain is the "current" one */
1090 x->fd = FD(0);
1091
1092 /* the last FD in the chain is for recycle() */
1093 x->end_fd = FD(MAX_FD - 1);
1094
1095 }
1096
1097 /* build the RBD chain */
1098 static void build_rbd_chain(register en_t x)
1099 {
1100 register int i;
1101
1102 for (i = 0; i < MAX_RBD; i++) {
1103 register rbd_t rbd = (rbd_t)window(x, RBD(i));
1104 rbd->status = 0;
1105 rbd->buffer_addr = RBUF(i);
1106 rbd->buffer_base = 0;
1107 rbd->size = RBUF_SIZE;
1108 if ((i + 1) < MAX_RBD)
1109 rbd->next_rbd_offset = RBD(i + 1);
1110 else {
1111 rbd->size |= AC_CW_EL;
1112 rbd->next_rbd_offset = 0xFFFF;
1113 }
1114 }
1115
1116 /* the last RBD in the chain is for recycle() */
1117 x->end_rbd = RBD(MAX_RBD - 1);
1118
1119 }
1120
1121 /* start up the RECEIVE UNIT */
1122 static void start_receive_unit(register en_t x)
1123 {
1124
1125 if ((x->scb->status & SCB_RUS_READY) == SCB_RUS_READY) {
1126 #ifdef EN_DEBUG
1127 if (en_debug)
1128 printf("EN%d START_RECEIVE_UNIT: READY FD 0x%04X\n",
1129 x->unit,
1130 x->fd);
1131 #endif
1132 return;
1133 }
1134
1135 build_fd_chain(x);
1136
1137 build_rbd_chain(x);
1138
1139 #ifdef EN_DEBUG
1140 if (en_debug)
1141 printf("EN%d START_RECEIVE_UNIT: FD 0x%04X\n",
1142 x->unit,
1143 x->fd);
1144 #endif
1145
1146 x->scb->rfa_offset = x->fd;
1147 x->scb->command = SCB_RU_STRT;
1148
1149 channel_attention(x);
1150
1151 }
1152
1153 /* transmit a packet frame */
1154 static void transmit(register en_t x, char *data, int count)
1155 {
1156 unsigned char *tbuf;
1157 struct ether_header *eh = (struct ether_header *)data;
1158
1159 if ((x->ifnet.if_flags & (IFF_UP | IFF_RUNNING)) !=
1160 (IFF_UP | IFF_RUNNING))
1161 panic("EN%d TRANSMIT: NOT UP AND RUNNING", x->unit);
1162
1163 #ifdef EN_DEBUG
1164 if (en_debug) {
1165 printf("EN%d TRANSMIT: DHOST ", x->unit);
1166 print_ethernet_address(eh->ether_dhost);
1167 printf("\n");
1168 }
1169 #endif
1170
1171 count -= sizeof(struct ether_header);
1172
1173 tbuf = window(x, TBUF);
1174 memcpy(tbuf, data + sizeof(struct ether_header), count);
1175 if (count < ETHERMIN)
1176 bzero(&tbuf[count], ETHERMIN - count);
1177
1178 /* move window back to bank #3 */
1179 (void)window(x, 0xFFFF);
1180
1181 /* set up TBD */
1182 x->tbd->act_count = (count < ETHERMIN) ? ETHERMIN : count;
1183 x->tbd->next_tbd_offset = 0xFFFF;
1184 x->tbd->buffer_addr = TBUF;
1185 x->tbd->buffer_base = 0;
1186 x->tbd->act_count |= TBD_SW_EOF;
1187
1188 /* set up CB with TRANSMIT command */
1189 x->cb->command = AC_TRANSMIT;
1190 x->cb->cmd.transmit.tbd_offset = TBD;
1191 x->cb->cmd.transmit.length = (unsigned short)eh->ether_type;
1192 memcpy(x->cb->cmd.transmit.dest_addr,
1193 eh->ether_dhost,
1194 ETHER_SIZE);
1195
1196 /* run TRANSMIT command, interrupt when complete */
1197 run_command(x, "TRANSMIT", "TRANSMIT", 1);
1198
1199 }
1200
1201 /* start output */
1202 static void start(int unit)
1203 {
1204 register en_t x = &en[unit];
1205 io_req_t m;
1206
1207 /* error if ethernet device is not UP and RUNNING */
1208 if ((x->ifnet.if_flags & (IFF_UP | IFF_RUNNING)) !=
1209 (IFF_UP | IFF_RUNNING)) {
1210 printf("EN%d START: NOT UP AND RUNNING\n", unit);
1211
1212 IF_DEQUEUE(&x->ifnet.if_snd, m);
1213
1214 if (m)
1215 iodone(m);
1216
1217 return;
1218 }
1219
1220 /* if currently busy with output, do nothing */
1221 if (x->busy && (x->scb->status & SCB_IDLE)) {
1222 #ifdef EN_DEBUG
1223 if (en_debug)
1224 printf("EN%d START: BUSY\n", x->unit);
1225 #endif
1226 return;
1227 }
1228 x->busy = 0;
1229
1230 /* take the I/O request out of the queue */
1231 IF_DEQUEUE(&x->ifnet.if_snd, m);
1232
1233 /* if there is an I/O request, transmit the packet */
1234 if (m) {
1235 #ifdef EN_DEBUG
1236 if (en_debug)
1237 printf("EN%d START: OK\n", unit);
1238 #endif
1239 x->busy++;
1240 transmit(x, m->io_data, m->io_count);
1241 iodone(m);
1242 }
1243 #ifdef EN_DEBUG
1244 else if (en_debug)
1245 printf("EN%d START: EMPTY\n", x->unit);
1246 #endif
1247
1248 return;
1249 }
1250
1251 /* forward declaration of reset() */
1252 static void reset(register en_t x, char *where);
1253
1254 /* automatic reset if there is no interrupt activity */
1255 static automatic_reset(x)
1256 en_t x;
1257 {
1258 spl_t s;
1259
1260 /* if ethernet device is no UP and RUNNING, do nothing */
1261 if ((x->ifnet.if_flags & (IFF_UP | IFF_RUNNING)) !=
1262 (IFF_UP | IFF_RUNNING))
1263 return;
1264
1265 /* if there has been no interrupt activity, reset() */
1266 if (!x->interrupt_count) {
1267 s = SPLNET();
1268 reset(x, "AUTOMATIC_RESET");
1269 splx(s);
1270 }
1271 /* otherwise, clear the counter and set up the timeout() */
1272 else {
1273 x->interrupt_count = 0;
1274 (void)untimeout(automatic_reset, x);
1275 timeout(automatic_reset, x, AUTOMATIC_RESET);
1276 }
1277
1278 }
1279
1280 /* reset the ethernet device, set UP and RUNNING if success */
1281 static void reset(register en_t x, char *where)
1282 {
1283 int i;
1284
1285 #ifdef EN_DEBUG
1286 if (en_debug)
1287 printf("EN%d RESET (%s)\n", x->unit, where);
1288 #endif
1289
1290 /* do hardware reset */
1291 channel_reset(x);
1292
1293 /* enable hardware loopback if required */
1294 if (en_loopback)
1295 outb(x->pos.register6, inb(x->pos.register6) | 0x20);
1296
1297 /* clear all local memory */
1298 for (i = x->minimum_address; i < MAX_ADDRESS; i += 0x4000)
1299 bzero(window(x, i), 0x4000);
1300
1301 /* set up SCP */
1302 x->scp = (scp_t)window(x, SCP);
1303 x->scp->sysbus = 0;
1304 x->scp->iscp = ISCP;
1305 x->scp->iscp_base = 0;
1306 #ifdef EN_DEBUG
1307 if (en_debug > 2)
1308 print_scp(x, SCP);
1309 #endif
1310
1311 /* set up ISCP */
1312 x->iscp = (iscp_t)window(x, ISCP);
1313 x->iscp->busy = 1;
1314 x->iscp->scb_offset = SCB;
1315 x->iscp->scb = 0;
1316 x->iscp->scb_base = 0;
1317 #ifdef EN_DEBUG
1318 if (en_debug > 2)
1319 print_iscp(x, ISCP);
1320 #endif
1321
1322 /* set up SCB */
1323 x->scb = (scb_t)window(x, SCB);
1324 x->scb->status = 0;
1325 x->scb->command = 0;
1326 x->scb->cbl_offset = CU;
1327 x->scb->rfa_offset = FD(0);
1328 x->scb->crcerrs = 0;
1329 x->scb->alnerrs = 0;
1330 x->scb->rscerrs = 0;
1331 x->scb->ovrnerrs = 0;
1332 #ifdef EN_DEBUG
1333 if (en_debug > 2)
1334 print_scb(x, SCB);
1335 #endif
1336
1337 /* set up CB pointer */
1338 x->cb = (ac_t)window(x, CU);
1339
1340 /* set up TBD pointer */
1341 x->tbd = (tbd_t)window(x, TBD);
1342
1343 /* issue SCB_RESET */
1344 x->scb->command = SCB_RESET;
1345 channel_attention(x);
1346
1347 /* error if SCB_RESET timeout */
1348 for (i = 0; i < 1000000; i++)
1349 if (!x->iscp->busy)
1350 break;
1351 if (x->iscp->busy) {
1352 printf("EN%d RESET: SCB_RESET TIMEOUT\n", x->unit);
1353 goto error;
1354 }
1355
1356 /* error if not ready after SCB_RESET */
1357 for (i = 0; i < 1000000; i++)
1358 if (x->scb->status == (SCB_SW_CX | SCB_SW_CNA))
1359 break;
1360 if (x->scb->status != (SCB_SW_CX | SCB_SW_CNA)) {
1361 printf("EN%d RESET: SCB_RESET NOT READY\n", x->unit);
1362 goto error;
1363 }
1364
1365 /* acknowledge the SCB_RESET */
1366 (void)acknowledge(x, "RESET");
1367
1368 /* do a NOP, error if error */
1369 if (ac_nop(x, "RESET"))
1370 goto error;
1371
1372 /* do a DIAGNOSE, error if error */
1373 if (ac_diagnose(x, "RESET"))
1374 goto error;
1375
1376 /* do a CONFIGURE, error if error */
1377 if (ac_configure(x,
1378 "RESET",
1379 FIFOLIM_BYTECNT,
1380 ADDRLEN_MODE,
1381 LINPRIO_INTERFRAME,
1382 SLOT_TIME,
1383 HARDWARE,
1384 MIN_FRAME_LEN))
1385 goto error;
1386
1387 /* do an IASETUP, error if error */
1388 if (ac_iasetup(x, "RESET", x->network_address))
1389 goto error;
1390
1391 /* ethernet device is UP and RUNNING */
1392 x->ifnet.if_flags |= IFF_UP | IFF_RUNNING;
1393
1394 /* clear start() busy flag */
1395 x->busy = 0;
1396
1397 /* set automatic reset timer */
1398 x->interrupt_count = 1;
1399 automatic_reset(x);
1400
1401 /* allow the adaptor to generate interrupts */
1402 #if EN_TTD
1403 if (!kttd_active)
1404 #endif
1405 enable_interrupts(x);
1406
1407 /* start up the RECEIVE UNIT */
1408 start_receive_unit(x);
1409
1410 /* start up the transmitter */
1411 start(x->unit);
1412
1413 /* all done */
1414 return;
1415
1416 /* reset has failed */
1417 error:
1418
1419 /* do a channel_reset() to turn off the adaptor */
1420 channel_reset(x);
1421
1422 /* ethernet device is not UP and RUNNING */
1423 x->ifnet.if_flags &= ~IFF_RUNNING;
1424 x->ifnet.if_flags &= ~IFF_UP;
1425
1426 /* complain that the reset failed */
1427 printf("EN%d %s: RESET FAILED\n", x->unit, where);
1428
1429 }
1430
1431 /* recycle the current receive frame descriptor and its receive buffers */
1432 /* return a pointer to the current FD, return zero if error */
1433 static fd_t recycle(register en_t x, unsigned short end_rbd)
1434 {
1435 fd_t fd;
1436 unsigned short next_fd;
1437 volatile rbd_t rbd;
1438
1439 #ifdef EN_DEBUG
1440 if (en_debug > 1)
1441 printf("EN%d RECYCLE: FD[%d]\n", x->unit, FD_INDEX(x->fd));
1442 #endif
1443
1444 /* get a pointer to the current frame descriptor */
1445 fd = (fd_t)window(x, x->fd);
1446
1447 /* if there are receive buffers to recycle... */
1448 if (fd->rbd_offset != 0xFFFF) {
1449
1450 /* get a pointer to the new end of the free list */
1451 if (end_rbd == 0xFFFF)
1452 end_rbd = fd->rbd_offset;
1453 for (;;) {
1454 rbd = (rbd_t)window(x, end_rbd);
1455 if (rbd->status & RBD_SW_EOF)
1456 break;
1457 if ((end_rbd = rbd->next_rbd_offset) == 0xFFFF) {
1458 printf("EN%d RECYCLE: FD[%d] BAD RBD CHAIN\n",
1459 x->unit,
1460 FD_INDEX(x->fd));
1461 return 0;
1462 }
1463 }
1464
1465 /* terminate the new end of the free list */
1466 rbd->status = 0;
1467 rbd->next_rbd_offset = 0xFFFF;
1468 rbd->size |= RBD_EL;
1469
1470 /* connect to the end of the free list */
1471 rbd = (rbd_t)window(x, x->end_rbd);
1472 rbd->next_rbd_offset = fd->rbd_offset;
1473 rbd->size &= ~RBD_EL;
1474
1475 /* note the new end of the free list */
1476 x->end_rbd = end_rbd;
1477
1478 }
1479
1480 /* get a pointer to the current frame descriptor */
1481 fd = (fd_t)window(x, x->fd);
1482
1483 /* error if FD chain is broken */
1484 if ((next_fd = fd->link_offset) == 0xFFFF) {
1485 printf("EN%d RECYCLE: FD[%d] BAD FD CHAIN\n",
1486 x->unit,
1487 FD_INDEX(x->fd));
1488 return 0;
1489 }
1490
1491 /* clear the fields for this FD structure */
1492 fd->status = 0;
1493 fd->command = AC_CW_EL;
1494 fd->link_offset = 0xFFFF;
1495 fd->rbd_offset = 0xFFFF;
1496
1497 /* attach to the end of the free list */
1498 fd = (fd_t)window(x, x->end_fd);
1499 fd->link_offset = x->fd;
1500 fd->command = 0;
1501 x->end_fd = x->fd;
1502
1503 /* make the next FD the current FD */
1504 return (fd_t)window(x, x->fd = next_fd);
1505
1506 }
1507
1508 /* receive a packet, return zero if no packet received */
1509 static ipc_kmsg_t receive(register en_t x, ipc_kmsg_t m)
1510 {
1511 volatile fd_t fd;
1512 volatile rbd_t rbd;
1513 ipc_kmsg_t allocated;
1514 struct ether_header *e;
1515 struct packet_header *p;
1516 char *d;
1517 unsigned short n;
1518 unsigned short rbd_address;
1519
1520 if ((x->ifnet.if_flags & (IFF_UP | IFF_RUNNING)) !=
1521 (IFF_UP | IFF_RUNNING))
1522 panic("EN%d RECEIVE: NOT UP AND RUNNING", x->unit);
1523
1524 /* get a pointer to the current frame descriptor */
1525 fd = (fd_t)window(x, x->fd);
1526
1527 /* while there is a completed frame to process... */
1528 while (fd->status & RFD_DONE) {
1529
1530 /* if the frame is not OK, complain and drop the packet */
1531 if (!(fd->status & RFD_OK)) {
1532 printf("EN%d RECEIVE: FD[%d] STATUS 0x%04X\n",
1533 x->unit,
1534 FD_INDEX(x->fd),
1535 fd->status & 0x0FFF);
1536 x->ifnet.if_ierrors++;
1537 if (!(fd = recycle(x, 0xFFFF)))
1538 goto error;
1539 continue;
1540 }
1541
1542 /* if can't get a message buffer, complain and drop packet */
1543 allocated = 0;
1544 if (!m && ((allocated = m = net_kmsg_get()) == IKM_NULL)) {
1545 #ifdef EN_DEBUG
1546 if (en_debug)
1547 printf("EN%d RECEIVE: "
1548 "FD[%d] NET_KMSG_GET FAILED\n",
1549 x->unit,
1550 FD_INDEX(x->fd));
1551 #endif
1552 x->ifnet.if_rcvdrops++;
1553 if (!(fd = recycle(x, 0xFFFF)))
1554 goto error;
1555 continue;
1556 }
1557
1558 #ifdef EN_DEBUG
1559 if (en_debug) {
1560 printf("EN%d RECEIVE: FD[%d] ",
1561 x->unit,
1562 FD_INDEX(x->fd));
1563 print_ethernet_address(fd->source);
1564 printf(" => ", x->unit);
1565 print_ethernet_address(fd->destination);
1566 printf("\n");
1567 }
1568 #endif
1569
1570 /* get pointers to the ethernet header and packet data */
1571 e = (struct ether_header *)(&net_kmsg(m)->header[0]);
1572 p = (struct packet_header *)(&net_kmsg(m)->packet[0]);
1573 d = (char *)(p + 1);
1574 p->type = e->ether_type = fd->length;
1575 p->length = sizeof(struct packet_header);
1576
1577 /* set ether_type, ether_shost and ether_dhost */
1578 memcpy(e->ether_shost, fd->source, ETHER_SIZE);
1579 memcpy(e->ether_dhost, fd->destination, ETHER_SIZE);
1580
1581 /* error if there is no receive buffer */
1582 if ((rbd_address = fd->rbd_offset) == 0xFFFF) {
1583 printf("EN%d RECEIVE: FD[%d] MISSING RBD\n",
1584 x->unit,
1585 FD_INDEX(x->fd));
1586 x->ifnet.if_rcvdrops++;
1587 goto error;
1588 }
1589
1590 /* copy each receive buffer into the message buffer... */
1591 for (;;) {
1592
1593 /* get pointer to receive buffer descriptor */
1594 rbd = (rbd_t)window(x, rbd_address);
1595
1596 /* copy receive buffer to message buffer */
1597 n = rbd->status & RBD_SW_COUNT;
1598 memcpy(d, window(x, rbd->buffer_addr), n);
1599 d += n;
1600
1601 /* accumulate packet length */
1602 p->length += n;
1603
1604 /* get pointer to receive buffer descriptor */
1605 rbd = (rbd_t)window(x, rbd_address);
1606
1607 /* all done if end of receive buffer chain */
1608 if (rbd->status & RBD_SW_EOF)
1609 break;
1610
1611 /* go to the next buffer, error if chain is broken */
1612 if ((rbd_address = rbd->next_rbd_offset) == 0xFFFF) {
1613 printf("EN%d RECEIVE: FD[%d] BAD RBD CHAIN\n",
1614 x->unit,
1615 FD_INDEX(x->fd));
1616 x->ifnet.if_rcvdrops++;
1617 goto error;
1618 }
1619
1620 }
1621
1622 /* all done, recycle this frame descriptor and its buffers */
1623 if (!(fd = recycle(x, rbd_address)))
1624 goto error;
1625
1626 /* all done, no error, return message */
1627 return m;
1628
1629 }
1630
1631 /* all done, there is no message to return */
1632 return 0;
1633
1634 error:
1635
1636 /* if a message buffer was allocated, put it back */
1637 if (allocated)
1638 net_kmsg_put(allocated);
1639
1640 /* reset */
1641 reset(x, "RECEIVE");
1642
1643 /* failed, return zero */
1644 return 0;
1645
1646 }
1647
1648 /*****************************************************************************/
1649
1650 /* handle an ethernet adaptor interrupt */
1651 static int interrupt(unit)
1652 int unit;
1653 {
1654 register volatile en_t x = &en[unit];
1655 unsigned short type;
1656 ipc_kmsg_t m;
1657 struct packet_header *p;
1658
1659 #ifdef EN_DEBUG
1660 if (en_debug)
1661 printf("EN%d INTERRUPT 0x%04X\n",
1662 x->unit,
1663 x->scb->status & SCB_SW_INT);
1664 #endif
1665
1666 /* if not UP and RUNNING, complain then do nothing */
1667 if ((x->ifnet.if_flags & (IFF_UP | IFF_RUNNING)) !=
1668 (IFF_UP | IFF_RUNNING)) {
1669 printf("EN%d INTERRUPT: NOT UP AND RUNNING\n", unit);
1670 return -1;
1671 }
1672
1673 /* count this interrupt for automatic_reset() */
1674 x->interrupt_count++;
1675
1676 /* while there are interrupts to process... */
1677 while (type = (x->scb->status & SCB_SW_INT)) {
1678
1679 /* acknowledge the interrupting command(s) */
1680 acknowledge(x, "INTERRUPT");
1681
1682 /* if a frame has been received, process it (them) */
1683 if (type & SCB_SW_FR)
1684 while (m = receive(x, 0)) {
1685 p = (struct packet_header *)
1686 (&net_kmsg(m)->packet[0]);
1687 net_packet(&x->ifnet,
1688 m,
1689 p->length,
1690 ethernet_priority(m));
1691 }
1692
1693 /* if the RECEIVE UNIT went off-line, restart it */
1694 if (type & SCB_SW_RNR)
1695 start_receive_unit(x);
1696
1697 /* if a packet has been transmitted, try for another */
1698 if (type & SCB_SW_CX) {
1699 x->busy = 0;
1700 start(unit);
1701 }
1702
1703 }
1704
1705 /* return zero, nothing looks at this return value anyway... */
1706 return 0;
1707
1708 }
1709
1710 /*****************************************************************************/
1711
1712 #if MACH_TTD
1713
1714 int en_get_packet(unit)
1715 int unit;
1716 {
1717 en_t x = &en[unit];
1718 spl_t s;
1719
1720 /* crash if TTD not active */
1721 if (!kttd_active)
1722 panic("EN%d EN_GET_PACKET: KTTD NOT ACTIVE\n");
1723
1724 s = SPLNET();
1725
1726 /* if not UP and RUNNING, do a reset() */
1727 if ((x->ifnet.if_flags & (IFF_UP | IFF_RUNNING)) !=
1728 (IFF_UP | IFF_RUNNING))
1729 reset(x, "EN_GET_PACKET");
1730
1731 /* loop until a packet is received */
1732 while (!receive(x, (ipc_kmsg_t)ttd_request_msg));
1733
1734 /* acknowledge any completed commands */
1735 (void)acknowledge(x, "EN_GET_PACKET");
1736
1737 splx(s);
1738
1739 return 0;
1740
1741 }
1742
1743 int en_send_packet(unit, packet, len)
1744 int unit;
1745 char *packet;
1746 int len;
1747 {
1748 en_t x = &en[unit];
1749 spl_t s;
1750
1751 /* crash if TTD not active */
1752 if (!kttd_active)
1753 panic("EN%d EN_SEND_PACKET: KTTD NOT ACTIVE\n");
1754
1755 s = SPLNET();
1756
1757 /* transmit the packet */
1758 transmit(x, packet, len);
1759
1760 /* acknowledge any completed commands */
1761 (void)acknowledge(x, "EN_SEND_PACKET");
1762
1763 splx(s);
1764
1765 return 0;
1766
1767 }
1768
1769 #endif
1770
1771 /*****************************************************************************/
1772
1773 /* return en structure pointer for specified ethernet device */
1774 /* return zero if bad unit number or device not UP */
1775 static en_t dev_to_en(register dev_t dev, char *name)
1776 {
1777 register unsigned int unit = minor(dev);
1778 register en_t x;
1779
1780 #ifdef EN_DEBUG
1781 if (en_debug)
1782 printf("EN%d %s\n", unit, name);
1783 #endif
1784
1785 if ((unit < NEN) && ((x = &en[unit])->ifnet.if_flags & IFF_UP))
1786 return x;
1787
1788 return 0;
1789
1790 }
1791
1792 /* open an ethernet device */
1793 io_return_t
1794 enopen(dev_t dev, dev_mode_t mode, io_req_t ior)
1795 {
1796 unsigned int unit = minor(dev);
1797 register en_t x;
1798 spl_t s;
1799
1800 #ifdef EN_DEBUG
1801 if (en_debug)
1802 printf("EN%d OPEN\n", unit);
1803 #endif
1804
1805 /* error if bad unit number or device not attached */
1806 if ((unit >NEN) || !(x = &en[unit])->attached)
1807 return D_NO_SUCH_DEVICE;
1808
1809 #ifdef EN_DEBUG
1810 if (en_debug > 2) {
1811 int i, base;
1812 unsigned char c;
1813 printf(" BOARD IS %s\n",
1814 x->pos.card_enabled ? "ENABLED" : "DISABLED");
1815 printf(" THIN ETHERNET IS %s\n",
1816 x->pos.thin_ethernet_enabled ? "ENABLED" : "DISABLED");
1817 printf(" IO BASE IS 0x%04X\n",
1818 x->pos.io_base);
1819 printf(" RAM BASE IS 0x%08X\n",
1820 x->pos.ram_base);
1821 printf(" INTERRUPT LEVEL IS %d\n",
1822 x->pos.interrupt_level);
1823 printf(" ETHERNET ADDRESS ");
1824 print_ethernet_address(x->network_address);
1825 printf("\n");
1826 printf(" ETHERNET BOARD REVISION LEVEL IS '%X'\n",
1827 x->pos.revision_level);
1828 printf(" THE MINIMUM ADDRESS IS 0x%04X\n",
1829 x->minimum_address);
1830 for (base = x->minimum_address;
1831 base < MAX_ADDRESS;
1832 base += 0x4000)
1833 if (i = bank_check(x, base))
1834 break;
1835 if (i)
1836 printf(" CAN NOT ACCESS BYTE AT 0x%04X\n", i - 1);
1837 else
1838 printf(" RAM ACCESS OK\n");
1839 }
1840 #endif
1841
1842 /* reset the ethernet device */
1843 s = SPLNET();
1844 reset(x, "ENOPEN");
1845 splx(s);
1846
1847 /* success if the device is UP and RUNNING */
1848 if (x->ifnet.if_flags & IFF_RUNNING)
1849 return D_SUCCESS;
1850
1851 /* error if the reset() failed */
1852 return D_IO_ERROR;
1853
1854 }
1855
1856 /* output to an ethernet device */
1857 io_return_t
1858 enoutput(dev_t dev, io_req_t ior)
1859 {
1860 register en_t x = dev_to_en(dev, "ENOUTPUT");
1861
1862 /* error if no such device */
1863 if (!x)
1864 return D_NO_SUCH_DEVICE;
1865
1866 /* use the generic net_write() */
1867 return net_write(&x->ifnet, start, ior);
1868
1869 }
1870
1871 /* set the input filter for an ethernet device */
1872 io_return_t
1873 ensetinput(dev_t dev,
1874 mach_port_t receive_port,
1875 int priority,
1876 filter_t *filter,
1877 unsigned int filter_count)
1878 {
1879 register en_t x = dev_to_en(dev, "ENSETINPUT");
1880
1881 /* error if no such device */
1882 if (!x)
1883 return D_NO_SUCH_DEVICE;
1884
1885 /* use the generic net_set_filter() */
1886 return net_set_filter(&x->ifnet,
1887 receive_port,
1888 priority,
1889 filter,
1890 filter_count);
1891
1892 }
1893
1894 /* get status for an ethernet device */
1895 io_return_t
1896 engetstat(dev_t dev,
1897 int flavor,
1898 dev_status_t status,
1899 unsigned int *count)
1900 {
1901 register en_t x = dev_to_en(dev, "ENGETSTAT");
1902
1903 /* error if no such device */
1904 if (!x)
1905 return D_NO_SUCH_DEVICE;
1906
1907 /* use the generic net_getstat() */
1908 return net_getstat(&x->ifnet, flavor, status, count);
1909
1910 }
1911
1912 /* set status for an ethernet device */
1913 io_return_t
1914 ensetstat(dev_t dev,
1915 int flavor,
1916 dev_status_t status,
1917 unsigned int count)
1918 {
1919 register en_t x = dev_to_en(dev, "ENSETSTAT");
1920 register struct net_status *ns = (struct net_status *)status;
1921 spl_t s;
1922
1923 /* error if no such device */
1924 if (!x)
1925 return D_NO_SUCH_DEVICE;
1926
1927 /* do the right thing... */
1928 switch (flavor) {
1929 case NET_STATUS:
1930 if (count != NET_STATUS_COUNT)
1931 return D_INVALID_OPERATION;
1932 #ifdef EN_DEBUG
1933 if (en_debug)
1934 printf("EN%d SETSTAT: NET_STATUS 0x%08X\n",
1935 x->unit,
1936 ns->flags);
1937 #endif
1938 s = SPLNET();
1939 reset(x, "ENSETSTAT");
1940 splx(s);
1941 break;
1942 default:
1943 return D_INVALID_OPERATION;
1944 }
1945
1946 return D_SUCCESS;
1947
1948 }
Cache object: b3f8f5cd64c28a2b27ac445542f1ca01
|