Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / networks / etherlink3 / unit.c
blob5206dad0d942df95d6fed62ae46b2c2984b9662d
1 /*
3 Copyright (C) 2001-2012 Neil Cafferkey
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 MA 02111-1307, USA.
22 #include <string.h>
24 #include <exec/memory.h>
25 #include <exec/execbase.h>
26 #include <exec/errors.h>
28 #include <proto/exec.h>
29 #ifndef __amigaos4__
30 #include <proto/alib.h>
31 #else
32 #include <clib/alib_protos.h>
33 #endif
34 #include <proto/utility.h>
35 #include <proto/timer.h>
37 #include "device.h"
38 #include "etherlink3.h"
39 #include "mii.h"
41 #include "unit_protos.h"
42 #include "request_protos.h"
45 #define TASK_PRIORITY 0
46 #define STACK_SIZE 4096
47 #define INT_MASK \
48 (EL3INTF_UPDATESTATS | EL3INTF_RXCOMPLETE | EL3INTF_TXAVAIL \
49 | EL3INTF_TXCOMPLETE)
50 #define DMA_INT_MASK \
51 (EL3INTF_UPDONE | EL3INTF_DOWNDONE | EL3INTF_UPDATESTATS \
52 | EL3INTF_TXCOMPLETE)
53 #define PORT_COUNT 6
56 #ifndef AbsExecBase
57 #define AbsExecBase sys_base
58 #endif
59 #ifdef __amigaos4__
60 #undef AddTask
61 #define AddTask(task, initial_pc, final_pc) \
62 IExec->AddTask(task, initial_pc, final_pc, NULL)
63 #endif
64 #ifdef __AROS__
65 #undef AddTask
66 #define AddTask(task, initial_pc, final_pc) \
67 ({ \
68 struct TagItem _task_tags[] = \
69 {{TASKTAG_ARG1, (IPTR)SysBase}, {TAG_END, 0}}; \
70 NewAddTask(task, initial_pc, final_pc, _task_tags); \
72 #endif
74 VOID SelectMedium(struct DevUnit *unit, UWORD transceiver,
75 struct DevBase *base);
76 static struct AddressRange *FindMulticastRange(struct DevUnit *unit,
77 ULONG lower_bound_left, UWORD lower_bound_right, ULONG upper_bound_left,
78 UWORD upper_bound_right, struct DevBase *base);
79 static VOID RXInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code));
80 static VOID CopyPacket(struct DevUnit *unit, struct IOSana2Req *request,
81 UWORD packet_size, UWORD packet_type, UBYTE *buffer, BOOL all_read,
82 struct DevBase *base);
83 static BOOL AddressFilter(struct DevUnit *unit, UBYTE *address,
84 struct DevBase *base);
85 static VOID TXInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code));
86 static VOID TxError(struct DevUnit *unit, struct DevBase *base);
87 static VOID DMARXInt(REG(a1, struct DevUnit *unit),
88 REG(a5, APTR int_code));
89 static VOID DMATXInt(REG(a1, struct DevUnit *unit),
90 REG(a5, APTR int_code));
91 static VOID DMATXEndInt(REG(a1, struct DevUnit *unit),
92 REG(a5, APTR int_code));
93 static VOID ReportEvents(struct DevUnit *unit, ULONG events,
94 struct DevBase *base);
95 static VOID UnitTask(struct ExecBase *sys_base);
96 static UWORD ReadEEPROM(struct DevUnit *unit, UWORD index,
97 struct DevBase *base);
98 static BOOL ReadMII(struct DevUnit *unit, UWORD phy_no, UWORD reg_no,
99 UWORD *value, struct DevBase *base);
100 #if 0
101 static VOID WriteMII(struct DevUnit *unit, UWORD phy_no, UWORD reg_no,
102 UWORD value, struct DevBase *base);
103 #endif
104 static ULONG ReadMIIBits(struct DevUnit *unit, UBYTE count,
105 struct DevBase *base);
106 static VOID WriteMIIBits(struct DevUnit *unit, ULONG value, UBYTE count,
107 struct DevBase *base);
108 static BOOL ReadMIIBit(struct DevUnit *unit, struct DevBase *base);
109 static VOID WriteMIIBit(struct DevUnit *unit, BOOL is_one,
110 struct DevBase *base);
111 #if 0
112 static VOID DoMIIZCycle(struct DevUnit *unit, struct DevBase *base);
113 #endif
114 static VOID BusyMicroDelay(ULONG micros, struct DevBase *base);
117 static const UBYTE port_choices[] =
119 /* EL3XCVR_AUTONEG,*/
120 EL3XCVR_100BASETX,
121 EL3XCVR_10BASET,
122 EL3XCVR_MII,
123 EL3XCVR_100BASEFX,
124 EL3XCVR_10BASE2,
125 EL3XCVR_AUI
128 static const UBYTE port_masks[] =
130 EL3REG_MEDIAOPTIONSF_10BASET,
131 EL3REG_MEDIAOPTIONSF_AUI,
133 EL3REG_MEDIAOPTIONSF_10BASE2,
134 EL3REG_MEDIAOPTIONSF_100BASETX,
135 EL3REG_MEDIAOPTIONSF_100BASEFX,
136 EL3REG_MEDIAOPTIONSF_MII,
138 EL3REG_MEDIAOPTIONSF_100BASETX | EL3REG_MEDIAOPTIONSF_10BASET
142 /****i* etherlink3.device/CreateUnit ***************************************
144 * NAME
145 * CreateUnit -- Create a unit.
147 * SYNOPSIS
148 * unit = CreateUnit(index, card, io_tags, generation,
149 * bus)
151 * struct DevUnit *CreateUnit(ULONG, APTR, struct TagItem *, UWORD,
152 * UWORD);
154 * FUNCTION
155 * Creates a new unit.
157 ****************************************************************************
161 struct DevUnit *CreateUnit(ULONG index, APTR card,
162 struct TagItem *io_tags, UWORD generation, UWORD bus,
163 struct DevBase *base)
165 BOOL success = TRUE;
166 struct DevUnit *unit;
167 struct Task *task;
168 struct MsgPort *port;
169 UBYTE i, *buffer;
170 APTR stack;
171 ULONG *upd, *next_upd, *fragment, dma_size;
172 APTR rx_int_function, tx_int_function;
174 unit = AllocMem(sizeof(struct DevUnit), MEMF_CLEAR | MEMF_PUBLIC);
175 if(unit == NULL)
176 success = FALSE;
178 if(success)
180 InitSemaphore(&unit->access_lock);
181 NewList((APTR)&unit->openers);
182 NewList((APTR)&unit->type_trackers);
183 NewList((APTR)&unit->multicast_ranges);
185 unit->index = index;
186 unit->device = base;
187 unit->card = card;
188 unit->generation = generation;
189 unit->bus = bus;
190 unit->ByteIn =
191 (APTR)GetTagData(IOTAG_ByteIn, (UPINT)NULL, io_tags);
192 unit->LongIn =
193 (APTR)GetTagData(IOTAG_LongIn, (UPINT)NULL, io_tags);
194 unit->ByteOut =
195 (APTR)GetTagData(IOTAG_ByteOut, (UPINT)NULL, io_tags);
196 unit->WordOut =
197 (APTR)GetTagData(IOTAG_WordOut, (UPINT)NULL, io_tags);
198 unit->LongOut =
199 (APTR)GetTagData(IOTAG_LongOut, (UPINT)NULL, io_tags);
200 unit->LongsIn =
201 (APTR)GetTagData(IOTAG_LongsIn, (UPINT)NULL, io_tags);
202 unit->LongsOut =
203 (APTR)GetTagData(IOTAG_LongsOut, (UPINT)NULL, io_tags);
204 unit->BEWordOut =
205 (APTR)GetTagData(IOTAG_BEWordOut, (UPINT)NULL, io_tags);
206 unit->LEWordIn =
207 (APTR)GetTagData(IOTAG_LEWordIn, (UPINT)NULL, io_tags);
208 unit->LELongIn =
209 (APTR)GetTagData(IOTAG_LELongIn, (UPINT)NULL, io_tags);
210 unit->LEWordOut =
211 (APTR)GetTagData(IOTAG_LEWordOut, (UPINT)NULL, io_tags);
212 unit->LELongOut =
213 (APTR)GetTagData(IOTAG_LELongOut, (UPINT)NULL, io_tags);
214 unit->AllocDMAMem =
215 (APTR)GetTagData(IOTAG_AllocDMAMem, (UPINT)NULL, io_tags);
216 unit->FreeDMAMem =
217 (APTR)GetTagData(IOTAG_FreeDMAMem, (UPINT)NULL, io_tags);
218 if(unit->ByteIn == NULL || unit->LongIn == NULL
219 || unit->ByteOut == NULL
220 || unit->WordOut == NULL || unit->LongOut == NULL
221 || unit->LongsIn == NULL || unit->LongsOut == NULL
222 || unit->BEWordOut == NULL || unit->LEWordIn == NULL
223 || unit->LELongIn == NULL || unit->LEWordOut == NULL
224 || unit->LELongOut == NULL
225 || generation >= BOOMERANG_GEN
226 && (unit->AllocDMAMem == NULL || unit->FreeDMAMem == NULL))
227 success = FALSE;
230 if(success)
232 if(unit->generation >= VORTEX_GEN)
233 unit->size_shift = 2;
235 InitialiseAdapter(unit, FALSE, base);
236 unit->flags |= UNITF_HAVEADAPTER;
238 /* Set up packet filter command */
240 unit->rx_filter_cmd = EL3CMD_SETRXFILTER | EL3CMD_SETRXFILTERF_BCAST
241 | EL3CMD_SETRXFILTERF_UCAST;
243 /* Set up interrupt mask */
245 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
246 unit->int_mask = DMA_INT_MASK;
247 else
248 unit->int_mask = INT_MASK;
250 /* Disable statistics interrupts for PCMCIA because they can't be
251 cleared on A1200 */
253 if(bus == PCCARD_BUS)
254 unit->int_mask &= ~EL3INTF_UPDATESTATS;
256 /* Store location of registers that were originally in window 1 */
258 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
259 unit->window1_offset += EL3_WINDOWSIZE;
261 /* Create the message ports for queuing requests */
263 for(i = 0; i < REQUEST_QUEUE_COUNT; i++)
265 unit->request_ports[i] = port = AllocMem(sizeof(struct MsgPort),
266 MEMF_PUBLIC | MEMF_CLEAR);
267 if(port == NULL)
268 success = FALSE;
270 if(success)
272 NewList(&port->mp_MsgList);
273 port->mp_Flags = PA_IGNORE;
274 port->mp_SigTask = &unit->tx_int;
278 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
280 unit->rx_buffer = unit->AllocDMAMem(unit->card,
281 ETH_MAXPACKETSIZE * RX_SLOT_COUNT, 1);
282 unit->tx_buffer =
283 unit->AllocDMAMem(unit->card, ETH_MAXPACKETSIZE, 1);
285 else
287 unit->rx_buffer =
288 AllocVec((ETH_MAXPACKETSIZE + 3) & ~3, MEMF_PUBLIC);
289 unit->tx_buffer = AllocVec(ETH_MAXPACKETSIZE, MEMF_PUBLIC);
292 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
294 unit->tx_requests = AllocVec(sizeof(APTR) * TX_SLOT_COUNT,
295 MEMF_PUBLIC);
296 unit->headers = unit->AllocDMAMem(unit->card,
297 ETH_HEADERSIZE * TX_SLOT_COUNT, 1);
298 unit->dpds =
299 unit->AllocDMAMem(unit->card, DPD_SIZE * TX_SLOT_COUNT, 8);
300 next_upd = unit->upds =
301 unit->AllocDMAMem(unit->card, UPD_SIZE * RX_SLOT_COUNT, 8);
302 if(unit->tx_requests == NULL || unit->headers == NULL
303 || unit->dpds == NULL || next_upd == NULL)
304 success = FALSE;
307 if(unit->rx_buffer == NULL || unit->tx_buffer == NULL)
308 success = FALSE;
311 if(success)
313 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
315 /* Construct RX ring */
317 buffer = unit->rx_buffer;
318 for(i = 0; i < RX_SLOT_COUNT; i++)
320 upd = next_upd;
321 next_upd = upd + UPD_SIZE / sizeof(ULONG);
322 upd[EL3UPD_NEXT] = MakeLELong((ULONG)(UPINT)next_upd);
323 upd[EL3UPD_STATUS] = 0;
324 fragment = upd + EL3UPD_FIRSTFRAG;
325 fragment[EL3FRAG_ADDR] = MakeLELong((ULONG)(UPINT)buffer);
326 fragment[EL3FRAG_LEN] =
327 MakeLELong(EL3FRAG_LENF_LAST | ETH_MAXPACKETSIZE);
328 buffer += ETH_MAXPACKETSIZE;
330 upd[EL3UPD_NEXT] = MakeLELong((ULONG)(UPINT)unit->upds);
331 unit->next_upd = unit->upds;
333 dma_size = UPD_SIZE * RX_SLOT_COUNT;
334 CachePreDMA(unit->upds, &dma_size, 0);
335 dma_size = ETH_MAXPACKETSIZE * RX_SLOT_COUNT;
336 CachePreDMA(unit->rx_buffer, &dma_size, 0);
339 /* Record maximum speed in BPS */
341 if((unit->capabilities & EL3ROM_CAPABILITIESF_100MBPS) != 0)
342 unit->speed = 100000000;
343 else
344 unit->speed = 10000000;
346 /* Initialise status, transmit and receive interrupts */
348 unit->status_int.is_Node.ln_Name =
349 base->device.dd_Library.lib_Node.ln_Name;
350 unit->status_int.is_Code = (APTR)StatusInt;
351 unit->status_int.is_Data = unit;
353 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
354 rx_int_function = DMARXInt;
355 else
356 rx_int_function = RXInt;
357 unit->rx_int.is_Node.ln_Name =
358 base->device.dd_Library.lib_Node.ln_Name;
359 unit->rx_int.is_Code = rx_int_function;
360 unit->rx_int.is_Data = unit;
362 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
363 tx_int_function = DMATXInt;
364 else
365 tx_int_function = TXInt;
366 unit->tx_int.is_Node.ln_Name =
367 base->device.dd_Library.lib_Node.ln_Name;
368 unit->tx_int.is_Code = tx_int_function;
369 unit->tx_int.is_Data = unit;
371 unit->tx_end_int.is_Node.ln_Name =
372 base->device.dd_Library.lib_Node.ln_Name;
373 unit->tx_end_int.is_Code = DMATXEndInt;
374 unit->tx_end_int.is_Data = unit;
376 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
379 if(success)
381 /* Create a new task */
383 unit->task = task =
384 AllocMem(sizeof(struct Task), MEMF_PUBLIC | MEMF_CLEAR);
385 if(task == NULL)
386 success = FALSE;
389 if(success)
391 stack = AllocMem(STACK_SIZE, MEMF_PUBLIC);
392 if(stack == NULL)
393 success = FALSE;
396 if(success)
398 /* Initialise and start task */
400 task->tc_Node.ln_Type = NT_TASK;
401 task->tc_Node.ln_Pri = TASK_PRIORITY;
402 task->tc_Node.ln_Name =
403 base->device.dd_Library.lib_Node.ln_Name;
404 task->tc_SPUpper = stack + STACK_SIZE;
405 task->tc_SPLower = stack;
406 task->tc_SPReg = stack + STACK_SIZE;
407 NewList(&task->tc_MemEntry);
409 if(AddTask(task, UnitTask, NULL) == NULL)
410 success = FALSE;
413 /* Send the unit to the new task */
415 if(success)
416 task->tc_UserData = unit;
418 if(!success)
420 DeleteUnit(unit, base);
421 unit = NULL;
424 return unit;
429 /****i* etherlink3.device/DeleteUnit ***************************************
431 * NAME
432 * DeleteUnit -- Delete a unit.
434 * SYNOPSIS
435 * DeleteUnit(unit)
437 * VOID DeleteUnit(struct DevUnit *);
439 * FUNCTION
440 * Deletes a unit.
442 * INPUTS
443 * unit - Device unit (can be NULL).
445 * RESULT
446 * None.
448 * EXAMPLE
450 * NOTES
452 * BUGS
454 * SEE ALSO
456 ****************************************************************************
460 VOID DeleteUnit(struct DevUnit *unit, struct DevBase *base)
462 UBYTE i;
463 struct Task *task;
465 if(unit != NULL)
467 task = unit->task;
468 if(task != NULL)
470 if(task->tc_UserData != NULL)
472 RemTask(task);
473 FreeMem(task->tc_SPLower, STACK_SIZE);
475 FreeMem(task, sizeof(struct Task));
478 for(i = 0; i < REQUEST_QUEUE_COUNT; i++)
480 if(unit->request_ports[i] != NULL)
481 FreeMem(unit->request_ports[i], sizeof(struct MsgPort));
484 if((unit->flags & UNITF_HAVEADAPTER) != 0) /* Needed! */
485 GoOffline(unit, base);
487 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
489 unit->FreeDMAMem(unit->card, unit->upds);
490 unit->FreeDMAMem(unit->card, unit->dpds);
491 unit->FreeDMAMem(unit->card, unit->headers);
492 FreeVec(unit->tx_requests);
495 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
497 unit->FreeDMAMem(unit->card, unit->tx_buffer);
498 unit->FreeDMAMem(unit->card, unit->rx_buffer);
500 else
502 FreeVec(unit->tx_buffer);
503 FreeVec(unit->rx_buffer);
506 FreeMem(unit, sizeof(struct DevUnit));
509 return;
514 /****i* etherlink3.device/InitialiseAdapter ********************************
516 * NAME
517 * InitialiseAdapter -- .
519 * SYNOPSIS
520 * InitialiseAdapter(unit, reinsertion)
522 * BOOL InitialiseAdapter(struct DevUnit *, BOOL);
524 * FUNCTION
526 * INPUTS
527 * unit
528 * reinsertion
530 * RESULT
531 * None.
533 * EXAMPLE
535 * NOTES
537 * BUGS
539 * SEE ALSO
541 ****************************************************************************
545 BOOL InitialiseAdapter(struct DevUnit *unit, BOOL reinsertion,
546 struct DevBase *base)
548 UBYTE *p, i;
549 UWORD address_part, links = 0, ports, new_ports, tp_ports,
550 media_status, transceiver, status, advert, ability, modes;
551 ULONG config;
552 BOOL autoselect;
554 /* Reset card. We avoid resetting the receive logic because it stops the
555 link status working in the MII Status register */
557 unit->LEWordOut(unit->card, EL3REG_COMMAND,
558 EL3CMD_RXRESET | EL3CMD_RXRESETF_SKIPNETWORK);
559 while((unit->LEWordIn(unit->card, EL3REG_STATUS) &
560 EL3REG_STATUSF_CMDINPROGRESS) != 0);
561 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_TXRESET);
562 while((unit->LEWordIn(unit->card, EL3REG_STATUS) &
563 EL3REG_STATUSF_CMDINPROGRESS) != 0);
565 /* Select IO addresses and interrupt for PCCard */
567 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 0);
568 if(unit->bus == PCCARD_BUS)
569 unit->LEWordOut(unit->card, EL3REG_RESCONFIG, 0x3f00);
570 if(unit->bus == ISA_BUS)
571 unit->LEWordOut(unit->card, EL3REG_RESCONFIG, (10 << 12) | 0xf00);
573 /* Fully enable an ISA card */
575 if(unit->bus == ISA_BUS)
576 unit->LEWordOut(unit->card, EL3REG_CONFIG, EL3REG_CONFIGF_ENABLE);
578 /* Get card capabilities */
580 unit->capabilities = ReadEEPROM(unit, EL3ROM_CAPABILITIES, base);
582 /* Get default MAC address */
584 p = unit->default_address;
586 for(i = 0; i < ETH_ADDRESSSIZE / 2; i++)
588 address_part = ReadEEPROM(unit, EL3ROM_ALTADDRESS0 + i, base);
589 *p++ = address_part >> 8;
590 *p++ = address_part & 0xff;
593 /* Get available transceivers */
595 if(unit->bus == PCCARD_BUS || unit->bus == ISA_BUS)
597 config = unit->LEWordIn(unit->card, EL3REG_CONFIG);
598 ports = (config >> 8) &
599 (EL3REG_MEDIAOPTIONSF_AUI | EL3REG_MEDIAOPTIONSF_10BASE2);
600 if((config & EL3REG_CONFIGF_10BASET) != 0)
601 ports |= EL3REG_MEDIAOPTIONSF_10BASET;
603 else
605 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 3);
606 ports = unit->LEWordIn(unit->card, EL3REG_MEDIAOPTIONS);
607 #if 0
608 if(ports == 0)
609 ports = EL3REG_MEDIAOPTIONSF_MII; /* fix for 3c916? */
610 #endif
613 /* Get transceiver choice from EEPROM */
615 if(unit->bus == PCI_BUS)
617 config = unit->LELongIn(unit->card, EL3REG_INTERNALCONFIG);
618 transceiver =
619 (config & EL3REG_INTERNALCONFIGF_XCVR)
620 >> EL3REG_INTERNALCONFIGB_XCVR;
621 autoselect = (config & EL3REG_INTERNALCONFIGF_AUTOXCVR) != 0;
623 else
625 config = ReadEEPROM(unit, EL3ROM_ADDRCONFIG, base);
626 transceiver =
627 (config & EL3REG_ADDRCONFIGF_XCVR) >> EL3REG_ADDRCONFIGB_XCVR;
628 autoselect = (config & EL3REG_ADDRCONFIGF_AUTOSELECT) != 0;
631 if(!autoselect)
633 /* Check if chosen medium is available */
635 new_ports = ports & port_masks[transceiver];
636 if(new_ports != 0)
637 ports = new_ports;
638 else
639 autoselect = TRUE;
642 /* Auto-select media type */
644 if(autoselect)
646 /* Get transceivers with an active link */
648 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 4);
650 if(unit->generation < CYCLONE_GEN)
652 tp_ports =
653 ports &
654 (EL3REG_MEDIAOPTIONSF_10BASET | EL3REG_MEDIAOPTIONSF_100BASETX);
655 if(tp_ports != 0)
657 SelectMedium(unit, EL3XCVR_10BASET, base);
658 media_status = unit->LEWordIn(unit->card, EL3REG_MEDIA);
659 if((media_status & EL3REG_MEDIAF_BEAT) != 0)
660 links |= tp_ports;
664 if((ports & EL3REG_MEDIAOPTIONSF_MII) != 0
665 || unit->generation >= CYCLONE_GEN)
667 for(i = 0; i < 32; i++)
669 if(ReadMII(unit, i, MII_STATUS, &status, base))
671 ReadMII(unit, i, MII_STATUS, &status, base);
672 /* Yes, status reg must be read twice */
673 if((status & MII_STATUSF_LINK) != 0)
675 if(i == 24) /* Built-in transceiver */
677 if(((status & MII_STATUSF_AUTONEGDONE) != 0)
678 && ((status & MII_STATUSF_EXTREGSET) != 0))
680 ReadMII(unit, i, MII_AUTONEGADVERT, &advert, base);
681 ReadMII(unit, i, MII_AUTONEGABILITY, &ability,
682 base);
683 modes = advert & ability;
685 if((modes & MII_AUTONEGF_100BASETX) != 0)
686 links |= EL3REG_MEDIAOPTIONSF_100BASETX;
687 #if 0
688 if((modes & MII_AUTONEGF_100BASET4) != 0)
689 links |= EL3REG_MEDIAOPTIONSF_100BASET4;
690 #endif
691 if((modes & MII_AUTONEGF_10BASET) != 0)
692 links |= EL3REG_MEDIAOPTIONSF_10BASET;
694 else
696 modes = MII_AUTONEGF_10BASET;
697 links |= EL3REG_MEDIAOPTIONSF_10BASET;
699 unit->autoneg_modes = modes;
701 else
703 links |= EL3REG_MEDIAOPTIONSF_MII;
704 unit->mii_phy_no = i;
711 #if 0
712 if((ports & EL3REG_MEDIAOPTIONSF_10BASE2) != 0)
714 SelectMedium(unit, EL3XCVR_10BASE2, base);
715 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STARTCOAX);
717 if(LoopbackTest(base))
718 links |= EL3REG_MEDIAOPTIONSF_10BASE2;
720 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STOPCOAX);
722 #endif
724 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 0);
726 new_ports = ports & links;
727 if((new_ports) != 0)
728 ports = new_ports;
731 /* Prioritised choice from remaining transceivers */
733 for(i = 0; i < PORT_COUNT; i++)
735 transceiver = port_choices[i];
736 if((ports & port_masks[transceiver]) != 0)
738 unit->transceiver = transceiver;
739 i = PORT_COUNT;
743 /* Find out whether to use full duplex */
745 if((transceiver == EL3XCVR_10BASET || transceiver == EL3XCVR_100BASETX)
746 && unit->generation >= CYCLONE_GEN)
748 modes = unit->autoneg_modes;
751 (modes & MII_AUTONEGF_100BASETXFD) != 0
754 modes
757 MII_AUTONEGF_100BASETX
759 MII_AUTONEGF_10BASETFD
763 MII_AUTONEGF_10BASETFD
765 unit->flags |= UNITF_FULLDUPLEX;
768 /* Return */
770 return TRUE;
775 /****i* etherlink3.device/ConfigureAdapter *********************************
777 * NAME
778 * ConfigureAdapter -- .
780 * SYNOPSIS
781 * ConfigureAdapter(unit)
783 * VOID ConfigureAdapter(struct DevUnit *);
785 * FUNCTION
787 * INPUTS
788 * unit
790 * RESULT
791 * None.
793 * EXAMPLE
795 * NOTES
797 * BUGS
799 * SEE ALSO
801 ****************************************************************************
805 VOID ConfigureAdapter(struct DevUnit *unit, struct DevBase *base)
807 UBYTE i;
809 /* Set MAC address */
811 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 2);
813 for(i = 0; i < ETH_ADDRESSSIZE; i++)
814 unit->ByteOut(unit->card, EL3REG_ADDRESS0 + i, unit->address[i]);
816 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
818 for(i = 0; i < ETH_ADDRESSSIZE; i++)
819 unit->ByteOut(unit->card, EL3REG_MASK0 + i, 0);
822 /* Enable wider statistics counters */
824 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 4);
825 if(unit->generation >= BOOMERANG_GEN)
826 unit->LEWordOut(unit->card, EL3REG_NETDIAG,
827 EL3REG_NETDIAGF_WIDESTATS);
829 /* Decide on promiscuous mode */
831 if((unit->flags & UNITF_PROM) != 0)
832 unit->rx_filter_cmd |= EL3CMD_SETRXFILTERF_PROM;
834 /* Select chosen transceiver */
836 SelectMedium(unit, unit->transceiver, base);
838 /* Go online */
840 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
841 unit->LELongOut(unit->card, EL3REG_UPLIST, (ULONG)(UPINT)unit->upds);
842 GoOnline(unit, base);
844 /* Return */
846 return;
851 /****i* etherlink3.device/SelectMedium *************************************
853 * NAME
854 * SelectMedium -- .
856 * SYNOPSIS
857 * SelectMedium(unit, transceiver)
859 * VOID SelectMedium(struct DevUnit *, UWORD);
861 * FUNCTION
863 * INPUTS
864 * unit
865 * transceiver
867 * RESULT
868 * None.
870 * EXAMPLE
872 * NOTES
874 * BUGS
876 * SEE ALSO
878 ****************************************************************************
882 VOID SelectMedium(struct DevUnit *unit, UWORD transceiver,
883 struct DevBase *base)
885 ULONG config;
886 UWORD old_window;
888 if((transceiver == EL3XCVR_10BASET || transceiver == EL3XCVR_100BASETX)
889 && unit->generation >= CYCLONE_GEN)
890 transceiver = EL3XCVR_AUTONEG;
892 /* Select transceiver */
894 old_window =
895 unit->LEWordIn(unit->card, EL3REG_STATUS) >> EL3REG_STATUSB_WINDOW;
896 if(unit->bus == PCI_BUS)
898 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 3);
899 config = unit->LELongIn(unit->card, EL3REG_INTERNALCONFIG);
900 config &= ~EL3REG_INTERNALCONFIGF_XCVR;
901 config |= transceiver << EL3REG_INTERNALCONFIGB_XCVR;
902 unit->LELongOut(unit->card, EL3REG_INTERNALCONFIG, config);
904 else
906 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 0);
907 config = unit->LEWordIn(unit->card, EL3REG_ADDRCONFIG);
908 config &= ~EL3REG_ADDRCONFIGF_XCVR;
909 config |= transceiver << EL3REG_ADDRCONFIGB_XCVR;
910 unit->LEWordOut(unit->card, EL3REG_ADDRCONFIG, config);
912 unit->LEWordOut(unit->card, EL3REG_COMMAND,
913 EL3CMD_SELECTWINDOW | old_window);
915 return;
920 /****i* etherlink3.device/GoOnline *****************************************
922 * NAME
923 * GoOnline -- .
925 * SYNOPSIS
926 * GoOnline(unit)
928 * VOID GoOnline(struct DevUnit *);
930 ****************************************************************************
934 VOID GoOnline(struct DevUnit *unit, struct DevBase *base)
936 UWORD transceiver;
938 /* Choose interrupts */
940 unit->flags |= UNITF_ONLINE;
941 unit->LEWordOut(unit->card, EL3REG_COMMAND,
942 EL3CMD_SETINTMASK | unit->int_mask);
943 unit->LEWordOut(unit->card, EL3REG_COMMAND,
944 EL3CMD_SETZEROMASK | unit->int_mask);
946 /* Enable the transceiver */
948 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
949 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_UPUNSTALL);
950 /* needed? */
951 transceiver = unit->transceiver;
953 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 4);
954 if(transceiver == EL3XCVR_100BASETX)
956 unit->LEWordOut(unit->card, EL3REG_MEDIA, EL3REG_MEDIAF_BEATCHECK);
958 else if(transceiver == EL3XCVR_10BASET)
960 unit->LEWordOut(unit->card, EL3REG_MEDIA,
961 EL3REG_MEDIAF_BEATCHECK | EL3REG_MEDIAF_JABBERCHECK);
963 else if(transceiver == EL3XCVR_10BASE2)
964 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STARTCOAX | 0);
966 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 3);
967 if((unit->flags & UNITF_FULLDUPLEX) != 0)
968 unit->LEWordOut(unit->card, EL3REG_MACCONTROL,
969 EL3REG_MACCONTROLF_FULLDUPLEX);
971 unit->LEWordOut(unit->card, EL3REG_COMMAND, unit->rx_filter_cmd);
972 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_RXENABLE);
973 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_TXENABLE);
974 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 1);
976 /* Enable statistics collection */
978 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STATSENABLE);
980 /* Record start time and report Online event */
982 GetSysTime(&unit->stats.LastStart);
983 ReportEvents(unit, S2EVENT_ONLINE, base);
985 return;
990 /****i* etherlink3.device/GoOffline ****************************************
992 * NAME
993 * GoOffline -- .
995 * SYNOPSIS
996 * GoOffline(unit)
998 * VOID GoOffline(struct DevUnit *);
1000 ****************************************************************************
1004 VOID GoOffline(struct DevUnit *unit, struct DevBase *base)
1006 unit->flags &= ~UNITF_ONLINE;
1008 if((unit->flags & UNITF_HAVEADAPTER) != 0)
1010 /* Stop interrupts */
1012 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SETINTMASK | 0);
1013 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1014 EL3CMD_ACKINT | EL3INTF_ANY);
1016 /* Stop transmission and reception */
1018 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_RXDISABLE);
1019 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_TXDISABLE);
1021 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
1023 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_UPSTALL);
1024 while((unit->LEWordIn(unit->card, EL3REG_STATUS) &
1025 EL3REG_STATUSF_CMDINPROGRESS) != 0);
1026 unit->LELongOut(unit->card, EL3REG_UPLIST, (ULONG)0);
1027 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_DOWNSTALL);
1028 while((unit->LEWordIn(unit->card, EL3REG_STATUS)
1029 & EL3REG_STATUSF_CMDINPROGRESS) != 0);
1030 unit->LELongOut(unit->card, EL3REG_DOWNLIST, (ULONG)0);
1033 /* Turn off media functions */
1035 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 4);
1036 unit->LEWordOut(unit->card, EL3REG_MEDIA, 0);
1037 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 1);
1038 #if 0
1039 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STOPCOAX | 0);
1040 #endif
1042 /* Update then disable statistics */
1044 UpdateStats(unit, base);
1045 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STATSDISABLE);
1048 /* Flush pending read and write requests */
1050 FlushUnit(unit, WRITE_QUEUE, S2ERR_OUTOFSERVICE, base);
1052 /* Report Offline event and return */
1054 ReportEvents(unit, S2EVENT_OFFLINE, base);
1055 return;
1060 /****i* etherlink3.device/AddMulticastRange ********************************
1062 * NAME
1063 * AddMulticastRange -- .
1065 * SYNOPSIS
1066 * success = AddMulticastRange(unit, lower_bound, upper_bound)
1068 * BOOL AddMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1070 ****************************************************************************
1074 BOOL AddMulticastRange(struct DevUnit *unit, const UBYTE *lower_bound,
1075 const UBYTE *upper_bound, struct DevBase *base)
1077 struct AddressRange *range;
1078 ULONG lower_bound_left, upper_bound_left;
1079 UWORD lower_bound_right, upper_bound_right;
1081 lower_bound_left = BELong(*((ULONG *)lower_bound));
1082 lower_bound_right = BEWord(*((UWORD *)(lower_bound + 4)));
1083 upper_bound_left = BELong(*((ULONG *)upper_bound));
1084 upper_bound_right = BEWord(*((UWORD *)(upper_bound + 4)));
1086 range = FindMulticastRange(unit, lower_bound_left, lower_bound_right,
1087 upper_bound_left, upper_bound_right, base);
1089 if(range != NULL)
1090 range->add_count++;
1091 else
1093 range = AllocMem(sizeof(struct AddressRange), MEMF_PUBLIC);
1094 if(range != NULL)
1096 range->lower_bound_left = lower_bound_left;
1097 range->lower_bound_right = lower_bound_right;
1098 range->upper_bound_left = upper_bound_left;
1099 range->upper_bound_right = upper_bound_right;
1100 range->add_count = 1;
1102 Disable();
1103 AddTail((APTR)&unit->multicast_ranges, (APTR)range);
1104 Enable();
1106 if(unit->range_count++ == 0)
1108 unit->rx_filter_cmd |= EL3CMD_SETRXFILTERF_MCAST;
1109 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1110 unit->rx_filter_cmd);
1115 return range != NULL;
1120 /****i* etherlink3.device/RemMulticastRange ********************************
1122 * NAME
1123 * RemMulticastRange -- .
1125 * SYNOPSIS
1126 * found = RemMulticastRange(unit, lower_bound, upper_bound)
1128 * BOOL RemMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1130 ****************************************************************************
1134 BOOL RemMulticastRange(struct DevUnit *unit, const UBYTE *lower_bound,
1135 const UBYTE *upper_bound, struct DevBase *base)
1137 struct AddressRange *range;
1138 ULONG lower_bound_left, upper_bound_left;
1139 UWORD lower_bound_right, upper_bound_right;
1141 lower_bound_left = BELong(*((ULONG *)lower_bound));
1142 lower_bound_right = BEWord(*((UWORD *)(lower_bound + 4)));
1143 upper_bound_left = BELong(*((ULONG *)upper_bound));
1144 upper_bound_right = BEWord(*((UWORD *)(upper_bound + 4)));
1146 range = FindMulticastRange(unit, lower_bound_left, lower_bound_right,
1147 upper_bound_left, upper_bound_right, base);
1149 if(range != NULL)
1151 if(--range->add_count == 0)
1153 Disable();
1154 Remove((APTR)range);
1155 Enable();
1156 FreeMem(range, sizeof(struct AddressRange));
1158 if(--unit->range_count == 0)
1160 unit->rx_filter_cmd &= ~EL3CMD_SETRXFILTERF_MCAST;
1161 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1162 unit->rx_filter_cmd);
1167 return range != NULL;
1172 /****i* etherlink3.device/FindMulticastRange *******************************
1174 * NAME
1175 * FindMulticastRange -- .
1177 * SYNOPSIS
1178 * range = FindMulticastRange(unit, lower_bound_left,
1179 * lower_bound_right, upper_bound_left, upper_bound_right)
1181 * struct AddressRange *FindMulticastRange(struct DevUnit *, ULONG,
1182 * UWORD, ULONG, UWORD);
1184 ****************************************************************************
1188 static struct AddressRange *FindMulticastRange(struct DevUnit *unit,
1189 ULONG lower_bound_left, UWORD lower_bound_right, ULONG upper_bound_left,
1190 UWORD upper_bound_right, struct DevBase *base)
1192 struct AddressRange *range, *tail;
1193 BOOL found = FALSE;
1195 range = (APTR)unit->multicast_ranges.mlh_Head;
1196 tail = (APTR)&unit->multicast_ranges.mlh_Tail;
1198 while((range != tail) && !found)
1200 if((lower_bound_left == range->lower_bound_left) &&
1201 (lower_bound_right == range->lower_bound_right) &&
1202 (upper_bound_left == range->upper_bound_left) &&
1203 (upper_bound_right == range->upper_bound_right))
1204 found = TRUE;
1205 else
1206 range = (APTR)range->node.mln_Succ;
1209 if(!found)
1210 range = NULL;
1212 return range;
1217 /****i* etherlink3.device/FindTypeStats ************************************
1219 * NAME
1220 * FindTypeStats -- .
1222 * SYNOPSIS
1223 * stats = FindTypeStats(unit, list,
1224 * packet_type)
1226 * struct TypeStats *FindTypeStats(struct DevUnit *, struct MinList *,
1227 * ULONG);
1229 ****************************************************************************
1233 struct TypeStats *FindTypeStats(struct DevUnit *unit, struct MinList *list,
1234 ULONG packet_type, struct DevBase *base)
1236 struct TypeStats *stats, *tail;
1237 BOOL found = FALSE;
1239 stats = (APTR)list->mlh_Head;
1240 tail = (APTR)&list->mlh_Tail;
1242 while(stats != tail && !found)
1244 if(stats->packet_type == packet_type)
1245 found = TRUE;
1246 else
1247 stats = (APTR)stats->node.mln_Succ;
1250 if(!found)
1251 stats = NULL;
1253 return stats;
1258 /****i* etherlink3.device/FlushUnit ****************************************
1260 * NAME
1261 * FlushUnit -- .
1263 * SYNOPSIS
1264 * FlushUnit(unit, last_queue, error)
1266 * VOID FlushUnit(struct DevUnit *, UBYTE, BYTE);
1268 ****************************************************************************
1270 * Includes alternative implementations because of ambiguities in SANA-II
1271 * documentation.
1275 VOID FlushUnit(struct DevUnit *unit, UBYTE last_queue, BYTE error,
1276 struct DevBase *base)
1278 struct IORequest *request;
1279 UBYTE i;
1280 struct Opener *opener, *tail;
1282 /* Abort queued requests */
1284 for(i = 0; i <= last_queue; i++)
1286 while((request = (APTR)GetMsg(unit->request_ports[i])) != NULL)
1288 request->io_Error = IOERR_ABORTED;
1289 ReplyMsg((APTR)request);
1293 #if 1
1294 opener = (APTR)unit->openers.mlh_Head;
1295 tail = (APTR)&unit->openers.mlh_Tail;
1297 /* Flush every opener's read queue */
1299 while(opener != tail)
1301 while((request = (APTR)GetMsg(&opener->read_port)) != NULL)
1303 request->io_Error = error;
1304 ReplyMsg((APTR)request);
1306 opener = (APTR)opener->node.mln_Succ;
1309 #else
1310 opener = request->ios2_BufferManagement;
1311 while((request = (APTR)GetMsg(&opener->read_port)) != NULL)
1313 request->io_Error = IOERR_ABORTED;
1314 ReplyMsg((APTR)request);
1316 #endif
1318 /* Return */
1320 return;
1325 /****i* etherlink3.device/StatusInt ****************************************
1327 * NAME
1328 * StatusInt
1330 * SYNOPSIS
1331 * finished = StatusInt(unit, int_code)
1333 * BOOL StatusInt(struct DevUnit *, APTR);
1335 ****************************************************************************
1337 * int_code is really in A5, but GCC 2.95.3 doesn't seem able to handle that.
1338 * Since we don't use this parameter, we can lie.
1342 BOOL StatusInt(REG(a1, struct DevUnit *unit), REG(a6, APTR int_code))
1344 struct DevBase *base;
1345 UWORD ints;
1347 base = unit->device;
1348 ints = unit->LEWordIn(unit->card, EL3REG_STATUS);
1350 if((ints & EL3INTF_ANY) != 0)
1352 /* Handle interrupts */
1354 if((ints & EL3INTF_UPDONE) != 0)
1356 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1357 EL3CMD_ACKINT | EL3INTF_UPDONE);
1358 Cause(&unit->rx_int);
1360 if((ints & EL3INTF_DOWNDONE) != 0)
1362 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1363 EL3CMD_ACKINT | EL3INTF_DOWNDONE);
1364 Cause(&unit->tx_end_int);
1366 if((ints & EL3INTF_UPDATESTATS) != 0)
1367 UpdateStats(unit, base);
1368 if((ints & EL3INTF_RXCOMPLETE) != 0)
1370 #ifndef __MORPHOS__
1371 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1372 EL3CMD_SETINTMASK | (unit->int_mask & ~EL3INTF_RXCOMPLETE));
1373 #endif
1374 Cause(&unit->rx_int);
1376 if((ints & EL3INTF_TXAVAIL) != 0)
1378 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1379 EL3CMD_ACKINT | EL3INTF_TXAVAIL);
1380 Cause(&unit->tx_int);
1382 if((ints & EL3INTF_TXCOMPLETE) != 0)
1383 TxError(unit, base);
1385 /* Acknowledge interrupt request */
1387 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1388 EL3CMD_ACKINT | EL3INTF_ANY);
1391 return FALSE;
1396 /****i* etherlink3.device/RXInt ********************************************
1398 * NAME
1399 * RXInt
1401 * SYNOPSIS
1402 * RXInt(unit, int_code)
1404 * VOID RXInt(struct DevUnit *, APTR);
1406 ****************************************************************************
1410 static VOID RXInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code))
1412 UWORD rx_status, packet_size;
1413 struct DevBase *base;
1414 BOOL is_orphan, accepted;
1415 ULONG packet_type;
1416 UBYTE *buffer;
1417 struct IOSana2Req *request, *request_tail;
1418 struct Opener *opener, *opener_tail;
1419 struct TypeStats *tracker;
1421 base = unit->device;
1422 buffer = unit->rx_buffer;
1424 while(((rx_status = unit->LEWordIn(unit->card, EL3REG_RXSTATUS))
1425 & EL3REG_RXSTATUSF_INCOMPLETE) == 0)
1427 if((rx_status & EL3REG_RXSTATUSF_ERROR) == 0)
1429 /* Read packet header */
1431 is_orphan = TRUE;
1432 packet_size = rx_status & EL3REG_RXSTATUS_SIZEMASK;
1433 unit->LongsIn(unit->card, EL3REG_DATA0, (ULONG *)buffer,
1434 ETH_HEADERSIZE + 3 >> 2);
1436 if(AddressFilter(unit, buffer + ETH_PACKET_DEST, base))
1438 packet_type = BEWord(*((UWORD *)(buffer + ETH_PACKET_TYPE)));
1440 opener = (APTR)unit->openers.mlh_Head;
1441 opener_tail = (APTR)&unit->openers.mlh_Tail;
1443 /* Offer packet to every opener */
1445 while(opener != opener_tail)
1447 request = (APTR)opener->read_port.mp_MsgList.lh_Head;
1448 request_tail = (APTR)&opener->read_port.mp_MsgList.lh_Tail;
1449 accepted = FALSE;
1451 /* Offer packet to each request until it's accepted */
1453 while((request != request_tail) && !accepted)
1455 if(request->ios2_PacketType == packet_type
1456 || request->ios2_PacketType <= ETH_MTU
1457 && packet_type <= ETH_MTU)
1459 CopyPacket(unit, request, packet_size, packet_type,
1460 buffer, !is_orphan, base);
1461 accepted = TRUE;
1463 request =
1464 (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
1467 if(accepted)
1468 is_orphan = FALSE;
1469 opener = (APTR)opener->node.mln_Succ;
1472 /* If packet was unwanted, give it to S2_READORPHAN request */
1474 if(is_orphan)
1476 unit->stats.UnknownTypesReceived++;
1477 if(!IsMsgPortEmpty(unit->request_ports[ADOPT_QUEUE]))
1479 CopyPacket(unit,
1480 (APTR)unit->request_ports[ADOPT_QUEUE]->
1481 mp_MsgList.lh_Head, packet_size, packet_type, buffer,
1482 FALSE, base);
1486 /* Update remaining statistics */
1488 tracker =
1489 FindTypeStats(unit, &unit->type_trackers, packet_type, base);
1490 if(tracker != NULL)
1492 tracker->stats.PacketsReceived++;
1493 tracker->stats.BytesReceived += packet_size;
1497 else
1499 unit->stats.BadData++;
1500 ReportEvents(unit, S2EVENT_ERROR | S2EVENT_HARDWARE | S2EVENT_RX,
1501 base);
1504 /* Discard packet */
1506 Disable(); /* Needed? */
1507 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_RXDISCARD);
1508 while((unit->LEWordIn(unit->card, EL3REG_STATUS) &
1509 EL3REG_STATUSF_CMDINPROGRESS) != 0);
1510 Enable();
1513 /* Return */
1515 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1516 EL3CMD_SETINTMASK | unit->int_mask);
1517 return;
1522 /****i* etherlink3.device/CopyPacket ***************************************
1524 * NAME
1525 * CopyPacket
1527 * SYNOPSIS
1528 * CopyPacket(unit, request, packet_size, packet_type,
1529 * buffer, all_read)
1531 * VOID CopyPacket(struct DevUnit *, struct IOSana2Req *, UWORD, UWORD,
1532 * UBYTE *, BOOL);
1534 ****************************************************************************
1538 static VOID CopyPacket(struct DevUnit *unit, struct IOSana2Req *request,
1539 UWORD packet_size, UWORD packet_type, UBYTE *buffer, BOOL all_read,
1540 struct DevBase *base)
1542 struct Opener *opener;
1543 BOOL filtered = FALSE;
1545 /* Set multicast and broadcast flags */
1547 request->ios2_Req.io_Flags &= ~(SANA2IOF_BCAST | SANA2IOF_MCAST);
1548 if((*((ULONG *)(buffer + ETH_PACKET_DEST)) == 0xffffffff) &&
1549 (*((UWORD *)(buffer + ETH_PACKET_DEST + 4)) == 0xffff))
1550 request->ios2_Req.io_Flags |= SANA2IOF_BCAST;
1551 else if((buffer[ETH_PACKET_DEST] & 0x1) != 0)
1552 request->ios2_Req.io_Flags |= SANA2IOF_MCAST;
1554 /* Set source and destination addresses and packet type */
1556 CopyMem(buffer + ETH_PACKET_SOURCE, request->ios2_SrcAddr,
1557 ETH_ADDRESSSIZE);
1558 CopyMem(buffer + ETH_PACKET_DEST, request->ios2_DstAddr,
1559 ETH_ADDRESSSIZE);
1560 request->ios2_PacketType = packet_type;
1562 /* Read rest of packet (PIO mode only) */
1564 if(!all_read)
1566 unit->LongsIn(unit->card, EL3REG_DATA0,
1567 (ULONG *)(buffer + ((ETH_PACKET_DATA + 3) & ~0x3)),
1568 (packet_size - ETH_PACKET_DATA + 1) >> 2);
1571 /* Adjust for cooked packet request */
1573 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1575 packet_size -= ETH_PACKET_DATA;
1576 buffer += ETH_PACKET_DATA;
1578 #ifdef USE_HACKS
1579 else
1580 packet_size += 4; /* Needed for Shapeshifter & Fusion */
1581 #endif
1582 request->ios2_DataLength = packet_size;
1584 /* Filter packet */
1586 opener = request->ios2_BufferManagement;
1587 if((request->ios2_Req.io_Command == CMD_READ) &&
1588 (opener->filter_hook != NULL))
1589 if(!CallHookPkt(opener->filter_hook, request, buffer))
1590 filtered = TRUE;
1592 if(!filtered)
1594 /* Copy packet into opener's buffer and reply packet */
1596 if(!opener->rx_function(request->ios2_Data, buffer, packet_size))
1598 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
1599 request->ios2_WireError = S2WERR_BUFF_ERROR;
1600 ReportEvents(unit,
1601 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF | S2EVENT_RX,
1602 base);
1604 Remove((APTR)request);
1605 ReplyMsg((APTR)request);
1608 return;
1613 /****i* etherlink3.device/AddressFilter ************************************
1615 * NAME
1616 * AddressFilter
1618 * SYNOPSIS
1619 * accept = AddressFilter(unit, address)
1621 * BOOL AddressFilter(struct DevUnit *, UBYTE *);
1623 ****************************************************************************
1627 static BOOL AddressFilter(struct DevUnit *unit, UBYTE *address,
1628 struct DevBase *base)
1630 struct AddressRange *range, *tail;
1631 BOOL accept = TRUE;
1632 ULONG address_left;
1633 UWORD address_right;
1635 /* Check whether address is unicast/broadcast or multicast */
1637 address_left = BELong(*((ULONG *)address));
1638 address_right = BEWord(*((UWORD *)(address + 4)));
1640 if((address_left & 0x01000000) != 0 &&
1641 !(address_left == 0xffffffff && address_right == 0xffff))
1643 /* Check if this multicast address is wanted */
1645 range = (APTR)unit->multicast_ranges.mlh_Head;
1646 tail = (APTR)&unit->multicast_ranges.mlh_Tail;
1647 accept = FALSE;
1649 while((range != tail) && !accept)
1651 if((address_left > range->lower_bound_left ||
1652 address_left == range->lower_bound_left &&
1653 address_right >= range->lower_bound_right) &&
1654 (address_left < range->upper_bound_left ||
1655 address_left == range->upper_bound_left &&
1656 address_right <= range->upper_bound_right))
1657 accept = TRUE;
1658 range = (APTR)range->node.mln_Succ;
1661 if(!accept)
1662 unit->special_stats[S2SS_ETHERNET_BADMULTICAST & 0xffff]++;
1665 return accept;
1670 /****i* etherlink3.device/TXInt ********************************************
1672 * NAME
1673 * TXInt
1675 * SYNOPSIS
1676 * TXInt(unit)
1678 * VOID TXInt(struct DevUnit *);
1680 ****************************************************************************
1684 static VOID TXInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code))
1686 UWORD packet_size, data_size, send_size;
1687 struct DevBase *base;
1688 struct IOSana2Req *request;
1689 BOOL proceed = TRUE;
1690 struct Opener *opener;
1691 ULONG *buffer, wire_error;
1692 UBYTE *(*dma_tx_function)(REG(a0, APTR));
1693 BYTE error;
1694 struct MsgPort *port;
1695 struct TypeStats *tracker;
1697 base = unit->device;
1698 port = unit->request_ports[WRITE_QUEUE];
1700 while(proceed && (!IsMsgPortEmpty(port)))
1702 error = 0;
1704 request = (APTR)port->mp_MsgList.lh_Head;
1705 data_size = packet_size = request->ios2_DataLength;
1707 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1708 packet_size += ETH_PACKET_DATA;
1710 if(unit->LEWordIn(unit->card, EL3REG_TXSPACE)
1711 > EL3_PREAMBLESIZE + packet_size)
1713 /* Write packet preamble */
1715 unit->LELongOut(unit->card, EL3REG_DATA0, packet_size);
1717 /* Write packet header */
1719 send_size = (packet_size + 3) & ~0x3;
1720 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1722 union {
1723 UBYTE bytes[12];
1724 ULONG ulong[3];
1725 } header;
1726 memcpy(&header.bytes[0], request->ios2_DstAddr, 6);
1727 memcpy(&header.bytes[6], unit->address, 6);
1728 unit->LongOut(unit->card, EL3REG_DATA0, header.ulong[0]);
1729 unit->LongOut(unit->card, EL3REG_DATA0, header.ulong[1]);
1730 unit->LongOut(unit->card, EL3REG_DATA0, header.ulong[2]);
1731 unit->BEWordOut(unit->card, EL3REG_DATA0,
1732 request->ios2_PacketType);
1733 send_size -= ETH_HEADERSIZE;
1736 /* Get packet data */
1738 opener = (APTR)request->ios2_BufferManagement;
1739 dma_tx_function = opener->dma_tx_function;
1740 if(dma_tx_function != NULL)
1741 buffer = (ULONG *)dma_tx_function(request->ios2_Data);
1742 else
1743 buffer = NULL;
1745 if(buffer == NULL)
1747 buffer = (ULONG *)unit->tx_buffer;
1748 if(!opener->tx_function(buffer, request->ios2_Data, data_size))
1750 error = S2ERR_NO_RESOURCES;
1751 wire_error = S2WERR_BUFF_ERROR;
1752 ReportEvents(unit,
1753 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF
1754 | S2EVENT_TX, base);
1758 /* Write packet data */
1760 if(error == 0)
1762 unit->LongsOut(unit->card, EL3REG_DATA0, buffer,
1763 send_size >> 2);
1764 buffer += (send_size >> 2);
1765 if((send_size & 0x3) != 0)
1766 unit->WordOut(unit->card, EL3REG_DATA0, *((UWORD *)buffer));
1769 /* Reply packet */
1771 request->ios2_Req.io_Error = error;
1772 request->ios2_WireError = wire_error;
1773 Remove((APTR)request);
1774 ReplyMsg((APTR)request);
1776 /* Update statistics */
1778 if(error == 0)
1780 tracker = FindTypeStats(unit, &unit->type_trackers,
1781 request->ios2_PacketType, base);
1782 if(tracker != NULL)
1784 tracker->stats.PacketsSent++;
1785 tracker->stats.BytesSent += packet_size;
1789 else
1790 proceed = FALSE;
1793 if(proceed)
1794 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
1795 else
1797 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SETTXTHRESH
1798 | ((EL3_PREAMBLESIZE + packet_size) >> unit->size_shift));
1799 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_IGNORE;
1802 return;
1807 /****i* etherlink3.device/TxError ******************************************
1809 * NAME
1810 * TxError
1812 * SYNOPSIS
1813 * TxError(unit)
1815 * VOID TxError(struct DevUnit *);
1817 ****************************************************************************
1821 static VOID TxError(struct DevUnit *unit, struct DevBase *base)
1823 UPINT window1_offset;
1824 UBYTE tx_status, flags = 0;
1826 window1_offset = unit->window1_offset;
1828 /* Gather all errors */
1830 while(((tx_status =
1831 unit->ByteIn(unit->card, window1_offset + EL3REG_TXSTATUS))
1832 & EL3REG_TXSTATUSF_COMPLETE) != 0)
1834 flags |= tx_status;
1835 unit->ByteOut(unit->card, window1_offset + EL3REG_TXSTATUS, 0);
1838 /* Restart transmitter if necessary */
1840 if((flags & EL3REG_TXSTATUSF_JABBER) != 0)
1842 Disable();
1843 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_TXRESET);
1844 while((unit->LEWordIn(unit->card, EL3REG_STATUS) &
1845 EL3REG_STATUSF_CMDINPROGRESS) != 0);
1846 Enable();
1849 if((flags & (EL3REG_TXSTATUSF_JABBER | EL3REG_TXSTATUSF_OVERFLOW
1850 | EL3REG_TXSTATUSF_RECLAIMERROR)) != 0)
1851 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_TXENABLE);
1853 /* Report the error(s) */
1855 ReportEvents(unit, S2EVENT_ERROR | S2EVENT_HARDWARE | S2EVENT_TX, base);
1857 return;
1862 /****i* etherlink3.device/UpdateStats **************************************
1864 * NAME
1865 * UpdateStats
1867 * SYNOPSIS
1868 * UpdateStats(unit)
1870 * VOID UpdateStats(struct DevUnit *);
1872 ****************************************************************************
1876 VOID UpdateStats(struct DevUnit *unit, struct DevBase *base)
1878 UBYTE frame_counts_upper;
1879 UWORD generation, old_window;
1881 generation = unit->generation;
1883 old_window =
1884 unit->LEWordIn(unit->card, EL3REG_STATUS) >> EL3REG_STATUSB_WINDOW;
1885 if(generation < VORTEX_GEN)
1886 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STATSDISABLE);
1888 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 6);
1889 unit->ByteIn(unit->card, EL3REG_CARRIERLOST);
1890 unit->ByteIn(unit->card, EL3REG_SQEERRORS);
1891 unit->ByteIn(unit->card, EL3REG_MULTIPLECOLLISIONS);
1892 unit->ByteIn(unit->card, EL3REG_SINGLECOLLISIONS);
1893 unit->ByteIn(unit->card, EL3REG_LATECOLLISIONS);
1894 unit->stats.Overruns += unit->ByteIn(unit->card, EL3REG_RXOVERRUNS);
1895 unit->stats.PacketsSent += unit->ByteIn(unit->card, EL3REG_TXFRAMESOK);
1896 unit->stats.PacketsReceived +=
1897 unit->ByteIn(unit->card, EL3REG_RXFRAMESOK);
1898 unit->special_stats[S2SS_ETHERNET_RETRIES & 0xffff] +=
1899 unit->ByteIn(unit->card, EL3REG_FRAMESDEFERRED);
1900 unit->LEWordIn(unit->card, EL3REG_RXBYTESOK);
1901 unit->LEWordIn(unit->card, EL3REG_TXBYTESOK);
1902 if(generation >= VORTEX_GEN)
1904 frame_counts_upper = unit->ByteIn(unit->card, EL3REG_FRAMESOKUPPER);
1905 unit->stats.PacketsReceived += (frame_counts_upper & 0x3) << 8;
1906 unit->stats.PacketsSent += (frame_counts_upper & 0x30) << 4;
1907 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 4);
1908 unit->ByteIn(unit->card, EL3REG_BADSSD);
1909 if(generation >= BOOMERANG_GEN)
1910 unit->ByteIn(unit->card, EL3REG_BYTESOKUPPER);
1913 if(generation < VORTEX_GEN)
1914 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STATSENABLE);
1915 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1916 EL3CMD_SELECTWINDOW | old_window);
1917 return;
1922 /****i* etherlink3.device/DMARXInt *****************************************
1924 * NAME
1925 * DMARXInt
1927 * SYNOPSIS
1928 * DMARXInt(unit, int_code)
1930 * VOID DMARXInt(struct DevUnit *, APTR);
1932 ****************************************************************************
1936 static VOID DMARXInt(REG(a1, struct DevUnit *unit),
1937 REG(a5, APTR int_code))
1939 UWORD packet_size;
1940 struct DevBase *base;
1941 BOOL is_orphan, accepted;
1942 ULONG rx_status, packet_type, *upd, *fragment, dma_size;
1943 UBYTE *buffer;
1944 struct IOSana2Req *request, *request_tail;
1945 struct Opener *opener, *opener_tail;
1946 struct TypeStats *tracker;
1948 base = unit->device;
1949 upd = unit->next_upd;
1951 dma_size = UPD_SIZE * RX_SLOT_COUNT;
1952 CachePostDMA(unit->upds, &dma_size, 0);
1954 while(((rx_status = LELong(upd[EL3UPD_STATUS]))
1955 & EL3UPD_STATUSF_COMPLETE) != 0)
1957 fragment = upd + EL3UPD_FIRSTFRAG;
1958 buffer = (UBYTE *)(UPINT)LELong(fragment[EL3FRAG_ADDR]);
1960 dma_size = ETH_MAXPACKETSIZE;
1961 CachePostDMA(buffer, &dma_size, 0);
1963 if((rx_status & EL3UPD_STATUSF_ERROR) == 0)
1965 is_orphan = TRUE;
1966 packet_size = rx_status & EL3UPD_STATUSF_SIZE;
1968 if(AddressFilter(unit, buffer + ETH_PACKET_DEST, base))
1970 packet_type = BEWord(*((UWORD *)(buffer + ETH_PACKET_TYPE)));
1972 opener = (APTR)unit->openers.mlh_Head;
1973 opener_tail = (APTR)&unit->openers.mlh_Tail;
1975 /* Offer packet to every opener */
1977 while(opener != opener_tail)
1979 request = (APTR)opener->read_port.mp_MsgList.lh_Head;
1980 request_tail = (APTR)&opener->read_port.mp_MsgList.lh_Tail;
1981 accepted = FALSE;
1983 /* Offer packet to each request until it's accepted */
1985 while((request != request_tail) && !accepted)
1987 if(request->ios2_PacketType == packet_type
1988 || request->ios2_PacketType <= ETH_MTU
1989 && packet_type <= ETH_MTU)
1991 CopyPacket(unit, request, packet_size, packet_type,
1992 buffer, TRUE, base);
1993 accepted = TRUE;
1995 request =
1996 (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
1999 if(accepted)
2000 is_orphan = FALSE;
2001 opener = (APTR)opener->node.mln_Succ;
2004 /* If packet was unwanted, give it to S2_READORPHAN request */
2006 if(is_orphan)
2008 unit->stats.UnknownTypesReceived++;
2009 if(!IsMsgPortEmpty(unit->request_ports[ADOPT_QUEUE]))
2011 CopyPacket(unit,
2012 (APTR)unit->request_ports[ADOPT_QUEUE]->
2013 mp_MsgList.lh_Head, packet_size, packet_type, buffer,
2014 TRUE, base);
2018 /* Update remaining statistics */
2020 tracker =
2021 FindTypeStats(unit, &unit->type_trackers, packet_type, base);
2022 if(tracker != NULL)
2024 tracker->stats.PacketsReceived++;
2025 tracker->stats.BytesReceived += packet_size;
2029 else
2031 unit->stats.BadData++;
2032 ReportEvents(unit, S2EVENT_ERROR | S2EVENT_HARDWARE | S2EVENT_RX,
2033 base);
2036 upd[EL3UPD_STATUS] = 0;
2038 dma_size = ETH_MAXPACKETSIZE;
2039 CachePreDMA(buffer, &dma_size, 0);
2041 upd = (ULONG *)(UPINT)LELong(upd[EL3UPD_NEXT]);
2044 dma_size = UPD_SIZE * RX_SLOT_COUNT;
2045 CachePreDMA(unit->upds, &dma_size, 0);
2047 /* Return */
2049 unit->next_upd = upd;
2050 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_UPUNSTALL);
2051 #if 1 /* ??? */
2052 unit->LEWordOut(unit->card, EL3REG_COMMAND,
2053 EL3CMD_SETINTMASK | unit->int_mask);
2054 #endif
2055 return;
2060 /****i* etherlink3.device/DMATXInt *****************************************
2062 * NAME
2063 * DMATXInt
2065 * SYNOPSIS
2066 * DMATXInt(unit, int_code)
2068 * VOID DMATXInt(struct DevUnit *, APTR);
2070 ****************************************************************************
2074 static VOID DMATXInt(REG(a1, struct DevUnit *unit),
2075 REG(a5, APTR int_code))
2077 UWORD packet_size, data_size, slot, new_slot, *p, *q, i;
2078 struct DevBase *base;
2079 struct IOSana2Req *request;
2080 BOOL proceed = TRUE;
2081 struct Opener *opener;
2082 ULONG wire_error, *dpd, *last_dpd, *next_dpd, *fragment, dma_size;
2083 UBYTE *(*dma_tx_function)(REG(a0, APTR));
2084 BYTE error;
2085 UBYTE *buffer;
2086 struct MsgPort *port;
2088 base = unit->device;
2089 port = unit->request_ports[WRITE_QUEUE];
2091 while(proceed && (!IsMsgPortEmpty(port)))
2093 slot = unit->tx_in_slot;
2094 new_slot = (slot + 1) % TX_SLOT_COUNT;
2096 if(new_slot != unit->tx_out_slot
2097 && (unit->flags & UNITF_TXBUFFERINUSE) == 0)
2099 error = 0;
2101 request = (APTR)port->mp_MsgList.lh_Head;
2102 data_size = packet_size = request->ios2_DataLength;
2104 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
2105 packet_size += ETH_HEADERSIZE;
2106 dpd = unit->dpds + ((DPD_SIZE / sizeof(ULONG)) * slot);
2108 /* Write packet preamble */
2110 Remove((APTR)request);
2111 unit->tx_requests[slot] = request;
2112 dpd[EL3DPD_NEXT] = (ULONG)0;
2113 dpd[EL3DPD_HEADER] =
2114 MakeLELong(EL3DPD_HEADERF_DLINT | packet_size);
2115 fragment = dpd + EL3DPD_FIRSTFRAG;
2117 /* Write packet header */
2119 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
2121 buffer = unit->headers + ETH_HEADERSIZE * slot;
2122 fragment[EL3FRAG_ADDR] = MakeLELong((ULONG)(UPINT)buffer);
2123 fragment[EL3FRAG_LEN] = MakeLELong(ETH_HEADERSIZE);
2125 p = (UWORD *)buffer;
2126 for(i = 0, q = (UWORD *)request->ios2_DstAddr;
2127 i < ETH_ADDRESSSIZE / 2; i++)
2128 *p++ = *q++;
2129 for(i = 0, q = (UWORD *)unit->address;
2130 i < ETH_ADDRESSSIZE / 2; i++)
2131 *p++ = *q++;
2132 *p++ = MakeBEWord(request->ios2_PacketType);
2133 buffer = (UBYTE *)p;
2135 dma_size = ETH_HEADERSIZE;
2136 CachePreDMA(buffer, &dma_size, DMA_ReadFromRAM);
2137 fragment += EL3_FRAGLEN;
2140 /* Get packet data */
2142 opener = (APTR)request->ios2_BufferManagement;
2143 dma_tx_function = opener->dma_tx_function;
2144 if(dma_tx_function != NULL)
2145 buffer = dma_tx_function(request->ios2_Data);
2146 else
2147 buffer = NULL;
2149 if(buffer == NULL)
2151 buffer = unit->tx_buffer;
2152 if(opener->tx_function(buffer, request->ios2_Data, data_size))
2153 unit->flags |= UNITF_TXBUFFERINUSE;
2154 else
2156 error = S2ERR_NO_RESOURCES;
2157 wire_error = S2WERR_BUFF_ERROR;
2158 ReportEvents(unit,
2159 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF
2160 | S2EVENT_TX, base);
2164 /* Fill in rest of descriptor for packet transmission */
2166 if(error == 0)
2168 fragment[EL3FRAG_ADDR] = MakeLELong((ULONG)(UPINT)buffer);
2169 fragment[EL3FRAG_LEN] =
2170 MakeLELong(EL3FRAG_LENF_LAST | data_size);
2172 /* Pass packet to adapter */
2174 dma_size = data_size;
2175 CachePreDMA(buffer, &dma_size, DMA_ReadFromRAM);
2177 last_dpd = (ULONG *)(UPINT)
2178 unit->LELongIn(unit->card, EL3REG_DOWNLIST);
2179 if(last_dpd != NULL)
2181 unit->LEWordOut(unit->card, EL3REG_COMMAND,
2182 EL3CMD_DOWNSTALL);
2183 while((unit->LEWordIn(unit->card, EL3REG_STATUS)
2184 & EL3REG_STATUSF_CMDINPROGRESS) != 0);
2185 while((next_dpd =
2186 (ULONG *)(UPINT)LELong(last_dpd[EL3DPD_NEXT])) != NULL)
2187 last_dpd = next_dpd;
2188 last_dpd[EL3DPD_NEXT] = MakeLELong((ULONG)(UPINT)dpd);
2189 dma_size = DPD_SIZE * TX_SLOT_COUNT;
2190 CachePreDMA(unit->dpds, &dma_size, 0);
2191 unit->LEWordOut(unit->card, EL3REG_COMMAND,
2192 EL3CMD_DOWNUNSTALL);
2194 else
2196 dma_size = DPD_SIZE * TX_SLOT_COUNT;
2197 CachePreDMA(unit->dpds, &dma_size, 0);
2198 unit->LELongOut(unit->card, EL3REG_DOWNLIST,
2199 (ULONG)(UPINT)dpd);
2202 unit->tx_in_slot = new_slot;
2204 else
2206 /* Reply failed request */
2208 request->ios2_Req.io_Error = error;
2209 request->ios2_WireError = wire_error;
2210 ReplyMsg((APTR)request);
2213 else
2214 proceed = FALSE;
2217 if(proceed)
2218 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
2219 else
2220 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_IGNORE;
2222 return;
2227 /****i* etherlink3.device/DMATXEndInt **************************************
2229 * NAME
2230 * DMATXEndInt
2232 * SYNOPSIS
2233 * DMATXEndInt(unit, int_code)
2235 * VOID DMATXEndInt(struct DevUnit *, APTR);
2237 * NOTES
2238 * I think it's safe to assume that there will always be at least one
2239 * completed packet whenever this interrupt is called.
2241 ****************************************************************************
2245 static VOID DMATXEndInt(REG(a1, struct DevUnit *unit),
2246 REG(a5, APTR int_code))
2248 UWORD data_size, packet_size, new_out_slot, i;
2249 UBYTE *buffer;
2250 struct DevBase *base;
2251 struct IOSana2Req *request;
2252 ULONG *dpd, *fragment, dma_size;
2253 struct TypeStats *tracker;
2255 /* Find out which packets have completed */
2257 base = unit->device;
2258 dpd = (ULONG *)(UPINT)unit->LELongIn(unit->card, EL3REG_DOWNLIST);
2259 if(dpd != NULL)
2260 new_out_slot = (dpd - unit->dpds) / (sizeof(ULONG) * DPD_SIZE);
2261 else
2262 new_out_slot = unit->tx_in_slot;
2264 /* Retire sent packets */
2266 for(i = unit->tx_out_slot; i != new_out_slot;
2267 i = (i + 1) % TX_SLOT_COUNT)
2269 /* Mark end of DMA */
2271 request = unit->tx_requests[i];
2272 data_size = packet_size = request->ios2_DataLength;
2273 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
2274 packet_size += ETH_HEADERSIZE;
2276 dpd = unit->dpds + ((DPD_SIZE / sizeof(ULONG)) * i);
2277 fragment = dpd + EL3DPD_FIRSTFRAG;
2278 dma_size = DPD_SIZE * TX_SLOT_COUNT;
2279 CachePostDMA(unit->dpds, &dma_size, 0);
2281 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
2283 buffer = (APTR)(UPINT)LELong(fragment[EL3FRAG_ADDR]);
2284 dma_size = ETH_HEADERSIZE;
2285 CachePostDMA(buffer, &dma_size, DMA_ReadFromRAM);
2286 fragment += EL3_FRAGLEN;
2289 buffer = (APTR)(UPINT)LELong(fragment[EL3FRAG_ADDR]);
2290 dma_size = data_size;
2291 CachePostDMA(buffer, &dma_size, DMA_ReadFromRAM);
2293 /* Check if unit's TX buffer is now free */
2295 if(buffer == unit->tx_buffer)
2296 unit->flags &= ~UNITF_TXBUFFERINUSE;
2298 /* Update statistics */
2300 tracker = FindTypeStats(unit, &unit->type_trackers,
2301 request->ios2_PacketType, base);
2302 if(tracker != NULL)
2304 tracker->stats.PacketsSent++;
2305 tracker->stats.BytesSent += packet_size;
2308 /* Reply request */
2310 request->ios2_Req.io_Error = 0;
2311 ReplyMsg((APTR)request);
2314 unit->tx_out_slot = new_out_slot;
2316 /* Restart downloads if they had stopped */
2318 if(unit->request_ports[WRITE_QUEUE]->mp_Flags == PA_IGNORE)
2319 Cause(&unit->tx_int);
2321 return;
2326 /****i* etherlink3.device/ReportEvents *************************************
2328 * NAME
2329 * ReportEvents -- .
2331 * SYNOPSIS
2332 * ReportEvents(unit, events)
2334 * VOID ReportEvents(struct DevUnit *, ULONG);
2336 * INPUTS
2337 * unit - A unit of this device.
2338 * events - A mask of events to report.
2340 * RESULT
2341 * None.
2343 ****************************************************************************
2347 static VOID ReportEvents(struct DevUnit *unit, ULONG events,
2348 struct DevBase *base)
2350 struct IOSana2Req *request, *tail, *next_request;
2351 struct List *list;
2353 list = &unit->request_ports[EVENT_QUEUE]->mp_MsgList;
2354 next_request = (APTR)list->lh_Head;
2355 tail = (APTR)&list->lh_Tail;
2357 Disable();
2358 while(next_request != tail)
2360 request = next_request;
2361 next_request = (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
2363 if((request->ios2_WireError & events) != 0)
2365 request->ios2_WireError = events;
2366 Remove((APTR)request);
2367 ReplyMsg((APTR)request);
2370 Enable();
2372 return;
2377 /****i* etherlink3.device/UnitTask *****************************************
2379 * NAME
2380 * UnitTask
2382 * SYNOPSIS
2383 * UnitTask()
2385 * VOID UnitTask();
2387 * FUNCTION
2389 * INPUTS
2391 * RESULT
2393 * EXAMPLE
2395 * NOTES
2397 * BUGS
2399 * SEE ALSO
2401 ****************************************************************************
2405 static VOID UnitTask(struct ExecBase *sys_base)
2407 struct Task *task;
2408 struct IORequest *request;
2409 struct DevUnit *unit;
2410 struct DevBase *base;
2411 struct MsgPort *general_port;
2412 ULONG signals, wait_signals, card_removed_signal, card_inserted_signal,
2413 general_port_signal;
2415 /* Get parameters */
2417 task = AbsExecBase->ThisTask;
2418 unit = task->tc_UserData;
2419 base = unit->device;
2421 /* Activate general request port */
2423 general_port = unit->request_ports[GENERAL_QUEUE];
2424 general_port->mp_SigTask = task;
2425 general_port->mp_SigBit = AllocSignal(-1);
2426 general_port_signal = 1 << general_port->mp_SigBit;
2427 general_port->mp_Flags = PA_SIGNAL;
2429 /* Allocate a signal for notification of card removal */
2431 card_removed_signal = unit->card_removed_signal = 1 << AllocSignal(-1);
2432 card_inserted_signal = unit->card_inserted_signal = 1 << AllocSignal(-1);
2433 wait_signals = (1 << general_port->mp_SigBit) | card_removed_signal
2434 | card_inserted_signal;
2436 /* Tell ourselves to check port for old messages */
2438 Signal(task, general_port_signal);
2440 /* Infinite loop to service requests and signals */
2442 while(TRUE)
2444 signals = Wait(wait_signals);
2446 if((signals & card_inserted_signal) != 0)
2448 if(unit->insertion_function(unit->card, base))
2450 unit->flags |= UNITF_HAVEADAPTER;
2451 if((unit->flags & UNITF_CONFIGURED) != 0)
2452 ConfigureAdapter(unit, base);
2456 if((signals & card_removed_signal) != 0)
2458 unit->removal_function(unit->card, base);
2459 GoOffline(unit, base);
2462 if((signals & general_port_signal) != 0)
2464 while((request = (APTR)GetMsg(general_port)) != NULL)
2466 /* Service the request as soon as the unit is free */
2468 ObtainSemaphore(&unit->access_lock);
2469 ServiceRequest((APTR)request, base);
2477 /****i* etherlink3.device/ReadEEPROM ***************************************
2479 * NAME
2480 * ReadEEPROM -- Read a location on card's EEPROM.
2482 * SYNOPSIS
2483 * value = ReadEEPROM(unit, index)
2485 * UWORD ReadEEPROM(struct DevUnit *, UWORD);
2487 * INPUTS
2488 * unit - Device unit.
2489 * index - Offset within EEPROM.
2491 * RESULT
2492 * value - Contents of specified EEPROM location.
2494 ****************************************************************************
2498 static UWORD ReadEEPROM(struct DevUnit *unit, UWORD index,
2499 struct DevBase *base)
2501 unit->LEWordOut(unit->card, EL3REG_EEPROMCMD, EL3ECMD_READ | index);
2502 while((unit->LEWordIn(unit->card, EL3REG_EEPROMCMD) &
2503 EL3REG_EEPROMCMDF_BUSY) != 0);
2505 return unit->LEWordIn(unit->card, EL3REG_EEPROMDATA);
2510 /****i* etherlink3.device/ReadMII ******************************************
2512 * NAME
2513 * ReadMII -- Read a register on an MII PHY.
2515 * SYNOPSIS
2516 * success = ReadMII(unit, phy_no, reg_no, value)
2518 * BOOL ReadMII(struct DevUnit *, UWORD, UWORD, UWORD *);
2520 * FUNCTION
2521 * Reads a register on an MII PHY. Window 4 must be selected before
2522 * calling this function.
2524 * INPUTS
2525 * unit - Device unit.
2526 * phy_no - .
2527 * reg_no - .
2528 * value - Pointer to location to store value read from MII register.
2530 * RESULT
2531 * success - Success indicator.
2533 ****************************************************************************
2537 static BOOL ReadMII(struct DevUnit *unit, UWORD phy_no, UWORD reg_no,
2538 UWORD *value, struct DevBase *base)
2540 BOOL success = TRUE;
2542 WriteMIIBits(unit, 0xffffffff, 32, base);
2543 WriteMIIBits(unit, 0x6, 4, base);
2544 WriteMIIBits(unit, phy_no, 5, base);
2545 WriteMIIBits(unit, reg_no, 5, base);
2546 ReadMIIBit(unit, base);
2547 if(ReadMIIBit(unit, base))
2548 success = FALSE;
2549 *value = ReadMIIBits(unit, 16, base);
2550 ReadMIIBit(unit, base);
2552 return success;
2557 /****i* etherlink3.device/WriteMII *****************************************
2559 * NAME
2560 * WriteMII -- Write to a register on an MII PHY.
2562 * SYNOPSIS
2563 * WriteMII(unit, phy_no, reg_no, value)
2565 * VOID WriteMII(struct DevUnit *, UWORD, UWORD, UWORD);
2567 * INPUTS
2568 * unit - Device unit.
2569 * phy_no - .
2570 * reg_no - .
2571 * value - value to write to MII register.
2573 * RESULT
2574 * None.
2576 ****************************************************************************
2580 #if 0
2581 static VOID WriteMII(struct DevUnit *unit, UWORD phy_no, UWORD reg_no,
2582 UWORD value, struct DevBase *base)
2584 WriteMIIBits(unit, 0xffffffff, 32, base);
2585 WriteMIIBits(unit, 0x5, 4, base);
2586 WriteMIIBits(unit, phy_no, 5, base);
2587 WriteMIIBits(unit, reg_no, 5, base);
2588 WriteMIIBit(unit, TRUE, base);
2589 WriteMIIBits(unit, value, 16, base);
2590 DoMIIZCycle(unit, base);
2592 return;
2594 #endif
2598 /****i* etherlink3.device/ReadMIIBits **************************************
2600 * NAME
2601 * ReadMIIBits
2603 * SYNOPSIS
2604 * value = ReadMIIBits(unit, count)
2606 * ULONG ReadMIIBits(struct DevUnit *, UBYTE);
2608 ****************************************************************************
2612 static ULONG ReadMIIBits(struct DevUnit *unit, UBYTE count,
2613 struct DevBase *base)
2615 UBYTE i;
2616 ULONG value = 0;
2618 /* LEWordOut(io_addr, LEWordIn(reg) & ~EL3REG_PHYMGMTF_WRITE);*/
2619 for(i = 0; i < count; i++)
2621 value <<= 1;
2622 if(ReadMIIBit(unit, base))
2623 value |= 1;
2624 unit->LEWordIn(unit->card, EL3REG_PHYMGMT);
2626 /* ReadMIIBit(unit, base)? value |= 1;*/
2628 return value;
2632 /****i* etherlink3.device/WriteMIIBits *************************************
2634 * NAME
2635 * WriteMIIBits
2637 * SYNOPSIS
2638 * WriteMIIBits(unit, value, count)
2640 * VOID WriteMIIBits(struct DevUnit *, ULONG, UBYTE);
2642 ****************************************************************************
2646 static VOID WriteMIIBits(struct DevUnit *unit, ULONG value, UBYTE count,
2647 struct DevBase *base)
2649 ULONG mask;
2651 for(mask = 1 << (count - 1); mask != 0; mask >>= 1)
2652 WriteMIIBit(unit, (value & mask) != 0, base);
2654 return;
2659 /****i* etherlink3.device/ReadMIIBit ***************************************
2661 * NAME
2662 * ReadMIIBit
2664 * SYNOPSIS
2665 * is_one = ReadMIIBit(unit)
2667 * BOOL ReadMIIBit(struct DevUnit *);
2669 ****************************************************************************
2673 static BOOL ReadMIIBit(struct DevUnit *unit, struct DevBase *base)
2675 BOOL is_one;
2677 unit->LEWordOut(unit->card, EL3REG_PHYMGMT, 0);
2678 BusyMicroDelay(1, base);
2679 unit->LEWordOut(unit->card, EL3REG_PHYMGMT, EL3REG_PHYMGMTF_CLK);
2680 BusyMicroDelay(1, base);
2681 is_one =
2682 (unit->LEWordIn(unit->card, EL3REG_PHYMGMT) & EL3REG_PHYMGMTF_DATA)
2683 != 0;
2684 BusyMicroDelay(1, base);
2686 return is_one;
2691 /****i* etherlink3.device/WriteMIIBit **************************************
2693 * NAME
2694 * WriteMIIBit
2696 * SYNOPSIS
2697 * WriteMIIBit(unit, is_one)
2699 * VOID WriteMIIBit(struct DevUnit *, BOOL);
2701 ****************************************************************************
2705 static VOID WriteMIIBit(struct DevUnit *unit, BOOL is_one,
2706 struct DevBase *base)
2708 unit->LEWordOut(unit->card, EL3REG_PHYMGMT, EL3REG_PHYMGMTF_WRITE);
2709 BusyMicroDelay(1, base);
2710 if(is_one)
2711 unit->LEWordOut(unit->card, EL3REG_PHYMGMT,
2712 EL3REG_PHYMGMTF_WRITE | EL3REG_PHYMGMTF_CLK |
2713 EL3REG_PHYMGMTF_DATA);
2714 else
2715 unit->LEWordOut(unit->card, EL3REG_PHYMGMT,
2716 EL3REG_PHYMGMTF_WRITE | EL3REG_PHYMGMTF_CLK);
2717 BusyMicroDelay(1, base);
2719 return;
2724 /****i* etherlink3.device/DoMIIZCycle **************************************
2726 * NAME
2727 * DoMIIZCycle
2729 * SYNOPSIS
2730 * DoMIIZCycle(unit)
2732 * VOID DoMIIZCycle(struct DevUnit *);
2734 ****************************************************************************
2738 #if 0
2739 static VOID DoMIIZCycle(struct DevUnit *unit, struct DevBase *base)
2741 unit->LEWordOut(unit->card, EL3REG_PHYMGMT,
2742 unit->LEWordIn(unit->card, EL3REG_PHYMGMT) & ~EL3REG_PHYMGMTF_CLK);
2743 BusyMicroDelay(1, base);
2744 unit->LEWordOut(unit->card, EL3REG_PHYMGMT, EL3REG_PHYMGMTF_CLK);
2745 BusyMicroDelay(1, base);
2747 return;
2749 #endif
2753 #if 0
2754 static VOID BusyMicroDelay(ULONG micros, struct DevBase *base)
2756 struct timeval time, end_time;
2758 GetSysTime(&end_time);
2759 time.tv_secs = 0;
2760 time.tv_micro = micros;
2761 AddTime(&end_time, &time);
2763 while(CmpTime(&end_time, &time) < 0)
2764 GetSysTime(&time);
2766 return;
2770 #else
2771 static VOID BusyMicroDelay(ULONG micros, struct DevBase *base)
2773 struct EClockVal time, end_time;
2774 ULONG rate;
2776 rate = ReadEClock(&time);
2777 end_time.ev_hi = time.ev_hi;
2778 end_time.ev_lo = time.ev_lo + (micros * rate + 1) / 1000000;
2779 if(end_time.ev_lo < time.ev_lo)
2780 end_time.ev_hi++;
2782 while(time.ev_lo < end_time.ev_lo || time.ev_hi < end_time.ev_hi)
2783 ReadEClock(&time);
2785 return;
2787 #endif