revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / networks / etherlink3 / unit.c
blobea0a371a68aee210cf1aab3537cf1c01ab9e38d7
1 /*
3 Copyright (C) 2012-2017 The AROS Dev team
4 Copyright (C) 2001-2012 Neil Cafferkey
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19 MA 02111-1307, USA.
23 #include <string.h>
25 #include <exec/memory.h>
26 #include <exec/execbase.h>
27 #include <exec/errors.h>
29 #include <proto/exec.h>
30 #ifndef __amigaos4__
31 #include <proto/alib.h>
32 #else
33 #include <clib/alib_protos.h>
34 #endif
35 #include <proto/utility.h>
36 #include <proto/timer.h>
38 #include "device.h"
39 #include "etherlink3.h"
40 #include "mii.h"
42 #include "unit_protos.h"
43 #include "request_protos.h"
46 #define TASK_PRIORITY 0
47 #define STACK_SIZE 4096
48 #define INT_MASK \
49 (EL3INTF_UPDATESTATS | EL3INTF_RXCOMPLETE | EL3INTF_TXAVAIL \
50 | EL3INTF_TXCOMPLETE)
51 #define DMA_INT_MASK \
52 (EL3INTF_UPDONE | EL3INTF_DOWNDONE | EL3INTF_UPDATESTATS \
53 | EL3INTF_TXCOMPLETE)
54 #define PORT_COUNT 6
57 #ifndef AbsExecBase
58 #define AbsExecBase sys_base
59 #endif
60 #ifdef __amigaos4__
61 #undef AddTask
62 #define AddTask(task, initial_pc, final_pc) \
63 IExec->AddTask(task, initial_pc, final_pc, NULL)
64 #endif
65 #ifdef __AROS__
66 #undef AddTask
67 #define AddTask(task, initial_pc, final_pc) \
68 ({ \
69 struct TagItem _task_tags[] = \
70 {{TASKTAG_ARG1, (IPTR)SysBase}, {TAG_END, 0}}; \
71 NewAddTask(task, initial_pc, final_pc, _task_tags); \
73 #endif
75 VOID SelectMedium(struct DevUnit *unit, UWORD transceiver,
76 struct DevBase *base);
77 static struct AddressRange *FindMulticastRange(struct DevUnit *unit,
78 ULONG lower_bound_left, UWORD lower_bound_right, ULONG upper_bound_left,
79 UWORD upper_bound_right, struct DevBase *base);
80 static VOID RXInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code));
81 static VOID CopyPacket(struct DevUnit *unit, struct IOSana2Req *request,
82 UWORD packet_size, UWORD packet_type, UBYTE *buffer, BOOL all_read,
83 struct DevBase *base);
84 static BOOL AddressFilter(struct DevUnit *unit, UBYTE *address,
85 struct DevBase *base);
86 static VOID TXInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code));
87 static VOID TxError(struct DevUnit *unit, struct DevBase *base);
88 static VOID DMARXInt(REG(a1, struct DevUnit *unit),
89 REG(a5, APTR int_code));
90 static VOID DMATXInt(REG(a1, struct DevUnit *unit),
91 REG(a5, APTR int_code));
92 static VOID DMATXEndInt(REG(a1, struct DevUnit *unit),
93 REG(a5, APTR int_code));
94 static VOID ReportEvents(struct DevUnit *unit, ULONG events,
95 struct DevBase *base);
96 static VOID UnitTask(struct ExecBase *sys_base);
97 static UWORD ReadEEPROM(struct DevUnit *unit, UWORD index,
98 struct DevBase *base);
99 static BOOL ReadMII(struct DevUnit *unit, UWORD phy_no, UWORD reg_no,
100 UWORD *value, struct DevBase *base);
101 #if 0
102 static VOID WriteMII(struct DevUnit *unit, UWORD phy_no, UWORD reg_no,
103 UWORD value, struct DevBase *base);
104 #endif
105 static ULONG ReadMIIBits(struct DevUnit *unit, UBYTE count,
106 struct DevBase *base);
107 static VOID WriteMIIBits(struct DevUnit *unit, ULONG value, UBYTE count,
108 struct DevBase *base);
109 static BOOL ReadMIIBit(struct DevUnit *unit, struct DevBase *base);
110 static VOID WriteMIIBit(struct DevUnit *unit, BOOL is_one,
111 struct DevBase *base);
112 #if 0
113 static VOID DoMIIZCycle(struct DevUnit *unit, struct DevBase *base);
114 #endif
115 static VOID BusyMicroDelay(ULONG micros, struct DevBase *base);
118 static const UBYTE port_choices[] =
120 /* EL3XCVR_AUTONEG,*/
121 EL3XCVR_100BASETX,
122 EL3XCVR_10BASET,
123 EL3XCVR_MII,
124 EL3XCVR_100BASEFX,
125 EL3XCVR_10BASE2,
126 EL3XCVR_AUI
129 static const UBYTE port_masks[] =
131 EL3REG_MEDIAOPTIONSF_10BASET,
132 EL3REG_MEDIAOPTIONSF_AUI,
134 EL3REG_MEDIAOPTIONSF_10BASE2,
135 EL3REG_MEDIAOPTIONSF_100BASETX,
136 EL3REG_MEDIAOPTIONSF_100BASEFX,
137 EL3REG_MEDIAOPTIONSF_MII,
139 EL3REG_MEDIAOPTIONSF_100BASETX | EL3REG_MEDIAOPTIONSF_10BASET
143 /****i* etherlink3.device/CreateUnit ***************************************
145 * NAME
146 * CreateUnit -- Create a unit.
148 * SYNOPSIS
149 * unit = CreateUnit(index, card, io_tags, generation,
150 * bus)
152 * struct DevUnit *CreateUnit(ULONG, APTR, struct TagItem *, UWORD,
153 * UWORD);
155 * FUNCTION
156 * Creates a new unit.
158 ****************************************************************************
162 struct DevUnit *CreateUnit(ULONG index, APTR card,
163 const struct TagItem *io_tags, UWORD generation, UWORD bus,
164 struct DevBase *base)
166 BOOL success = TRUE;
167 struct DevUnit *unit;
168 struct Task *task;
169 struct MsgPort *port;
170 UBYTE i, *buffer;
171 APTR stack;
172 ULONG *upd, *next_upd, *fragment, dma_size;
173 APTR rx_int_function, tx_int_function;
175 unit = AllocMem(sizeof(struct DevUnit), MEMF_CLEAR | MEMF_PUBLIC);
176 if(unit == NULL)
177 success = FALSE;
179 if(success)
181 InitSemaphore(&unit->access_lock);
182 NewList((APTR)&unit->openers);
183 NewList((APTR)&unit->type_trackers);
184 NewList((APTR)&unit->multicast_ranges);
186 unit->index = index;
187 unit->device = base;
188 unit->card = card;
189 unit->generation = generation;
190 unit->bus = bus;
191 unit->ByteIn =
192 (APTR)GetTagData(IOTAG_ByteIn, (UPINT)NULL, io_tags);
193 unit->LongIn =
194 (APTR)GetTagData(IOTAG_LongIn, (UPINT)NULL, io_tags);
195 unit->ByteOut =
196 (APTR)GetTagData(IOTAG_ByteOut, (UPINT)NULL, io_tags);
197 unit->WordOut =
198 (APTR)GetTagData(IOTAG_WordOut, (UPINT)NULL, io_tags);
199 unit->LongOut =
200 (APTR)GetTagData(IOTAG_LongOut, (UPINT)NULL, io_tags);
201 unit->LongsIn =
202 (APTR)GetTagData(IOTAG_LongsIn, (UPINT)NULL, io_tags);
203 unit->LongsOut =
204 (APTR)GetTagData(IOTAG_LongsOut, (UPINT)NULL, io_tags);
205 unit->BEWordOut =
206 (APTR)GetTagData(IOTAG_BEWordOut, (UPINT)NULL, io_tags);
207 unit->LEWordIn =
208 (APTR)GetTagData(IOTAG_LEWordIn, (UPINT)NULL, io_tags);
209 unit->LELongIn =
210 (APTR)GetTagData(IOTAG_LELongIn, (UPINT)NULL, io_tags);
211 unit->LEWordOut =
212 (APTR)GetTagData(IOTAG_LEWordOut, (UPINT)NULL, io_tags);
213 unit->LELongOut =
214 (APTR)GetTagData(IOTAG_LELongOut, (UPINT)NULL, io_tags);
215 unit->AllocDMAMem =
216 (APTR)GetTagData(IOTAG_AllocDMAMem, (UPINT)NULL, io_tags);
217 unit->FreeDMAMem =
218 (APTR)GetTagData(IOTAG_FreeDMAMem, (UPINT)NULL, io_tags);
219 if(unit->ByteIn == NULL || unit->LongIn == NULL
220 || unit->ByteOut == NULL
221 || unit->WordOut == NULL || unit->LongOut == NULL
222 || unit->LongsIn == NULL || unit->LongsOut == NULL
223 || unit->BEWordOut == NULL || unit->LEWordIn == NULL
224 || unit->LELongIn == NULL || unit->LEWordOut == NULL
225 || unit->LELongOut == NULL
226 || generation >= BOOMERANG_GEN
227 && (unit->AllocDMAMem == NULL || unit->FreeDMAMem == NULL))
228 success = FALSE;
231 if(success)
233 if(unit->generation >= VORTEX_GEN)
234 unit->size_shift = 2;
236 InitialiseAdapter(unit, FALSE, base);
237 unit->flags |= UNITF_HAVEADAPTER;
239 /* Set up packet filter command */
241 unit->rx_filter_cmd = EL3CMD_SETRXFILTER | EL3CMD_SETRXFILTERF_BCAST
242 | EL3CMD_SETRXFILTERF_UCAST;
244 /* Set up interrupt mask */
246 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
247 unit->int_mask = DMA_INT_MASK;
248 else
249 unit->int_mask = INT_MASK;
251 /* Disable statistics interrupts for PCMCIA because they can't be
252 cleared on A1200 */
254 if(bus == PCCARD_BUS)
255 unit->int_mask &= ~EL3INTF_UPDATESTATS;
257 /* Store location of registers that were originally in window 1 */
259 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
260 unit->window1_offset += EL3_WINDOWSIZE;
262 /* Create the message ports for queuing requests */
264 for(i = 0; i < REQUEST_QUEUE_COUNT; i++)
266 unit->request_ports[i] = port = AllocMem(sizeof(struct MsgPort),
267 MEMF_PUBLIC | MEMF_CLEAR);
268 if(port == NULL)
269 success = FALSE;
271 if(success)
273 NewList(&port->mp_MsgList);
274 port->mp_Flags = PA_IGNORE;
275 port->mp_SigTask = &unit->tx_int;
279 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
281 unit->rx_buffer = unit->AllocDMAMem(unit->card,
282 ETH_MAXPACKETSIZE * RX_SLOT_COUNT, 1);
283 unit->tx_buffer =
284 unit->AllocDMAMem(unit->card, ETH_MAXPACKETSIZE, 1);
286 else
288 unit->rx_buffer =
289 AllocVec((ETH_MAXPACKETSIZE + 3) & ~3, MEMF_PUBLIC);
290 unit->tx_buffer = AllocVec(ETH_MAXPACKETSIZE, MEMF_PUBLIC);
293 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
295 unit->tx_requests = AllocVec(sizeof(APTR) * TX_SLOT_COUNT,
296 MEMF_PUBLIC);
297 unit->headers = unit->AllocDMAMem(unit->card,
298 ETH_HEADERSIZE * TX_SLOT_COUNT, 1);
299 unit->dpds =
300 unit->AllocDMAMem(unit->card, DPD_SIZE * TX_SLOT_COUNT, 8);
301 next_upd = unit->upds =
302 unit->AllocDMAMem(unit->card, UPD_SIZE * RX_SLOT_COUNT, 8);
303 if(unit->tx_requests == NULL || unit->headers == NULL
304 || unit->dpds == NULL || next_upd == NULL)
305 success = FALSE;
308 if(unit->rx_buffer == NULL || unit->tx_buffer == NULL)
309 success = FALSE;
312 if(success)
314 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
316 /* Construct RX ring */
318 buffer = unit->rx_buffer;
319 for(i = 0; i < RX_SLOT_COUNT; i++)
321 upd = next_upd;
322 next_upd = upd + UPD_SIZE / sizeof(ULONG);
323 upd[EL3UPD_NEXT] = MakeLELong((ULONG)(UPINT)next_upd);
324 upd[EL3UPD_STATUS] = 0;
325 fragment = upd + EL3UPD_FIRSTFRAG;
326 fragment[EL3FRAG_ADDR] = MakeLELong((ULONG)(UPINT)buffer);
327 fragment[EL3FRAG_LEN] =
328 MakeLELong(EL3FRAG_LENF_LAST | ETH_MAXPACKETSIZE);
329 buffer += ETH_MAXPACKETSIZE;
331 upd[EL3UPD_NEXT] = MakeLELong((ULONG)(UPINT)unit->upds);
332 unit->next_upd = unit->upds;
334 dma_size = UPD_SIZE * RX_SLOT_COUNT;
335 CachePreDMA(unit->upds, &dma_size, 0);
336 dma_size = ETH_MAXPACKETSIZE * RX_SLOT_COUNT;
337 CachePreDMA(unit->rx_buffer, &dma_size, 0);
340 /* Record maximum speed in BPS */
342 if((unit->capabilities & EL3ROM_CAPABILITIESF_100MBPS) != 0)
343 unit->speed = 100000000;
344 else
345 unit->speed = 10000000;
347 /* Initialise status, transmit and receive interrupts */
349 unit->status_int.is_Node.ln_Name =
350 base->device.dd_Library.lib_Node.ln_Name;
351 unit->status_int.is_Code = (APTR)StatusInt;
352 unit->status_int.is_Data = unit;
354 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
355 rx_int_function = DMARXInt;
356 else
357 rx_int_function = RXInt;
358 unit->rx_int.is_Node.ln_Name =
359 base->device.dd_Library.lib_Node.ln_Name;
360 unit->rx_int.is_Code = rx_int_function;
361 unit->rx_int.is_Data = unit;
363 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
364 tx_int_function = DMATXInt;
365 else
366 tx_int_function = TXInt;
367 unit->tx_int.is_Node.ln_Name =
368 base->device.dd_Library.lib_Node.ln_Name;
369 unit->tx_int.is_Code = tx_int_function;
370 unit->tx_int.is_Data = unit;
372 unit->tx_end_int.is_Node.ln_Name =
373 base->device.dd_Library.lib_Node.ln_Name;
374 unit->tx_end_int.is_Code = DMATXEndInt;
375 unit->tx_end_int.is_Data = unit;
377 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
380 if(success)
382 /* Create a new task */
384 unit->task = task =
385 AllocMem(sizeof(struct Task), MEMF_PUBLIC | MEMF_CLEAR);
386 if(task == NULL)
387 success = FALSE;
390 if(success)
392 stack = AllocMem(STACK_SIZE, MEMF_PUBLIC);
393 if(stack == NULL)
394 success = FALSE;
397 if(success)
399 /* Initialise and start task */
401 task->tc_Node.ln_Type = NT_TASK;
402 task->tc_Node.ln_Pri = TASK_PRIORITY;
403 task->tc_Node.ln_Name =
404 base->device.dd_Library.lib_Node.ln_Name;
405 task->tc_SPUpper = stack + STACK_SIZE;
406 task->tc_SPLower = stack;
407 task->tc_SPReg = stack + STACK_SIZE;
408 NewList(&task->tc_MemEntry);
410 if(AddTask(task, UnitTask, NULL) == NULL)
411 success = FALSE;
414 /* Send the unit to the new task */
416 if(success)
417 task->tc_UserData = unit;
419 if(!success)
421 DeleteUnit(unit, base);
422 unit = NULL;
425 return unit;
430 /****i* etherlink3.device/DeleteUnit ***************************************
432 * NAME
433 * DeleteUnit -- Delete a unit.
435 * SYNOPSIS
436 * DeleteUnit(unit)
438 * VOID DeleteUnit(struct DevUnit *);
440 * FUNCTION
441 * Deletes a unit.
443 * INPUTS
444 * unit - Device unit (can be NULL).
446 * RESULT
447 * None.
449 * EXAMPLE
451 * NOTES
453 * BUGS
455 * SEE ALSO
457 ****************************************************************************
461 VOID DeleteUnit(struct DevUnit *unit, struct DevBase *base)
463 UBYTE i;
464 struct Task *task;
466 if(unit != NULL)
468 task = unit->task;
469 if(task != NULL)
471 if(task->tc_UserData != NULL)
473 RemTask(task);
474 FreeMem(task->tc_SPLower, STACK_SIZE);
476 FreeMem(task, sizeof(struct Task));
479 for(i = 0; i < REQUEST_QUEUE_COUNT; i++)
481 if(unit->request_ports[i] != NULL)
482 FreeMem(unit->request_ports[i], sizeof(struct MsgPort));
485 if((unit->flags & UNITF_HAVEADAPTER) != 0) /* Needed! */
486 GoOffline(unit, base);
488 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
490 unit->FreeDMAMem(unit->card, unit->upds);
491 unit->FreeDMAMem(unit->card, unit->dpds);
492 unit->FreeDMAMem(unit->card, unit->headers);
493 FreeVec(unit->tx_requests);
496 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
498 unit->FreeDMAMem(unit->card, unit->tx_buffer);
499 unit->FreeDMAMem(unit->card, unit->rx_buffer);
501 else
503 FreeVec(unit->tx_buffer);
504 FreeVec(unit->rx_buffer);
507 FreeMem(unit, sizeof(struct DevUnit));
510 return;
515 /****i* etherlink3.device/InitialiseAdapter ********************************
517 * NAME
518 * InitialiseAdapter -- .
520 * SYNOPSIS
521 * InitialiseAdapter(unit, reinsertion)
523 * BOOL InitialiseAdapter(struct DevUnit *, BOOL);
525 * FUNCTION
527 * INPUTS
528 * unit
529 * reinsertion
531 * RESULT
532 * None.
534 * EXAMPLE
536 * NOTES
538 * BUGS
540 * SEE ALSO
542 ****************************************************************************
546 BOOL InitialiseAdapter(struct DevUnit *unit, BOOL reinsertion,
547 struct DevBase *base)
549 UBYTE *p, i;
550 UWORD address_part, links = 0, ports, new_ports, tp_ports,
551 media_status, transceiver, status, advert, ability, modes;
552 ULONG config;
553 BOOL autoselect;
555 /* Reset card. We avoid resetting the receive logic because it stops the
556 link status working in the MII Status register */
558 unit->LEWordOut(unit->card, EL3REG_COMMAND,
559 EL3CMD_RXRESET | EL3CMD_RXRESETF_SKIPNETWORK);
560 while((unit->LEWordIn(unit->card, EL3REG_STATUS) &
561 EL3REG_STATUSF_CMDINPROGRESS) != 0);
562 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_TXRESET);
563 while((unit->LEWordIn(unit->card, EL3REG_STATUS) &
564 EL3REG_STATUSF_CMDINPROGRESS) != 0);
566 /* Select IO addresses and interrupt for PCCard */
568 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 0);
569 if(unit->bus == PCCARD_BUS)
570 unit->LEWordOut(unit->card, EL3REG_RESCONFIG, 0x3f00);
571 if(unit->bus == ISA_BUS)
572 unit->LEWordOut(unit->card, EL3REG_RESCONFIG, (10 << 12) | 0xf00);
574 /* Fully enable an ISA card */
576 if(unit->bus == ISA_BUS)
577 unit->LEWordOut(unit->card, EL3REG_CONFIG, EL3REG_CONFIGF_ENABLE);
579 /* Get card capabilities */
581 unit->capabilities = ReadEEPROM(unit, EL3ROM_CAPABILITIES, base);
583 /* Get default MAC address */
585 p = unit->default_address;
587 for(i = 0; i < ETH_ADDRESSSIZE / 2; i++)
589 address_part = ReadEEPROM(unit, EL3ROM_ALTADDRESS0 + i, base);
590 *p++ = address_part >> 8;
591 *p++ = address_part & 0xff;
594 /* Get available transceivers */
596 if(unit->bus == PCCARD_BUS || unit->bus == ISA_BUS)
598 config = unit->LEWordIn(unit->card, EL3REG_CONFIG);
599 ports = (config >> 8) &
600 (EL3REG_MEDIAOPTIONSF_AUI | EL3REG_MEDIAOPTIONSF_10BASE2);
601 if((config & EL3REG_CONFIGF_10BASET) != 0)
602 ports |= EL3REG_MEDIAOPTIONSF_10BASET;
604 else
606 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 3);
607 ports = unit->LEWordIn(unit->card, EL3REG_MEDIAOPTIONS);
608 #if 0
609 if(ports == 0)
610 ports = EL3REG_MEDIAOPTIONSF_MII; /* fix for 3c916? */
611 #endif
614 /* Get transceiver choice from EEPROM */
616 if(unit->bus == PCI_BUS)
618 config = unit->LELongIn(unit->card, EL3REG_INTERNALCONFIG);
619 transceiver =
620 (config & EL3REG_INTERNALCONFIGF_XCVR)
621 >> EL3REG_INTERNALCONFIGB_XCVR;
622 autoselect = (config & EL3REG_INTERNALCONFIGF_AUTOXCVR) != 0;
624 else
626 config = ReadEEPROM(unit, EL3ROM_ADDRCONFIG, base);
627 transceiver =
628 (config & EL3REG_ADDRCONFIGF_XCVR) >> EL3REG_ADDRCONFIGB_XCVR;
629 autoselect = (config & EL3REG_ADDRCONFIGF_AUTOSELECT) != 0;
632 if(!autoselect)
634 /* Check if chosen medium is available */
636 new_ports = ports & port_masks[transceiver];
637 if(new_ports != 0)
638 ports = new_ports;
639 else
640 autoselect = TRUE;
643 /* Auto-select media type */
645 if(autoselect)
647 /* Get transceivers with an active link */
649 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 4);
651 if(unit->generation < CYCLONE_GEN)
653 tp_ports =
654 ports &
655 (EL3REG_MEDIAOPTIONSF_10BASET | EL3REG_MEDIAOPTIONSF_100BASETX);
656 if(tp_ports != 0)
658 SelectMedium(unit, EL3XCVR_10BASET, base);
659 media_status = unit->LEWordIn(unit->card, EL3REG_MEDIA);
660 if((media_status & EL3REG_MEDIAF_BEAT) != 0)
661 links |= tp_ports;
665 if((ports & EL3REG_MEDIAOPTIONSF_MII) != 0
666 || unit->generation >= CYCLONE_GEN)
668 for(i = 0; i < 32; i++)
670 if(ReadMII(unit, i, MII_STATUS, &status, base))
672 ReadMII(unit, i, MII_STATUS, &status, base);
673 /* Yes, status reg must be read twice */
674 if((status & MII_STATUSF_LINK) != 0)
676 if(i == 24) /* Built-in transceiver */
678 if(((status & MII_STATUSF_AUTONEGDONE) != 0)
679 && ((status & MII_STATUSF_EXTREGSET) != 0))
681 ReadMII(unit, i, MII_AUTONEGADVERT, &advert, base);
682 ReadMII(unit, i, MII_AUTONEGABILITY, &ability,
683 base);
684 modes = advert & ability;
686 if((modes & MII_AUTONEGF_100BASETX) != 0)
687 links |= EL3REG_MEDIAOPTIONSF_100BASETX;
688 #if 0
689 if((modes & MII_AUTONEGF_100BASET4) != 0)
690 links |= EL3REG_MEDIAOPTIONSF_100BASET4;
691 #endif
692 if((modes & MII_AUTONEGF_10BASET) != 0)
693 links |= EL3REG_MEDIAOPTIONSF_10BASET;
695 else
697 modes = MII_AUTONEGF_10BASET;
698 links |= EL3REG_MEDIAOPTIONSF_10BASET;
700 unit->autoneg_modes = modes;
702 else
704 links |= EL3REG_MEDIAOPTIONSF_MII;
705 unit->mii_phy_no = i;
712 #if 0
713 if((ports & EL3REG_MEDIAOPTIONSF_10BASE2) != 0)
715 SelectMedium(unit, EL3XCVR_10BASE2, base);
716 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STARTCOAX);
718 if(LoopbackTest(base))
719 links |= EL3REG_MEDIAOPTIONSF_10BASE2;
721 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STOPCOAX);
723 #endif
725 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 0);
727 new_ports = ports & links;
728 if((new_ports) != 0)
729 ports = new_ports;
732 /* Prioritised choice from remaining transceivers */
734 for(i = 0; i < PORT_COUNT; i++)
736 transceiver = port_choices[i];
737 if((ports & port_masks[transceiver]) != 0)
739 unit->transceiver = transceiver;
740 i = PORT_COUNT;
744 /* Find out whether to use full duplex */
746 if((transceiver == EL3XCVR_10BASET || transceiver == EL3XCVR_100BASETX)
747 && unit->generation >= CYCLONE_GEN)
749 modes = unit->autoneg_modes;
752 (modes & MII_AUTONEGF_100BASETXFD) != 0
755 modes
758 MII_AUTONEGF_100BASETX
760 MII_AUTONEGF_10BASETFD
764 MII_AUTONEGF_10BASETFD
766 unit->flags |= UNITF_FULLDUPLEX;
769 /* Return */
771 return TRUE;
776 /****i* etherlink3.device/ConfigureAdapter *********************************
778 * NAME
779 * ConfigureAdapter -- .
781 * SYNOPSIS
782 * ConfigureAdapter(unit)
784 * VOID ConfigureAdapter(struct DevUnit *);
786 * FUNCTION
788 * INPUTS
789 * unit
791 * RESULT
792 * None.
794 * EXAMPLE
796 * NOTES
798 * BUGS
800 * SEE ALSO
802 ****************************************************************************
806 VOID ConfigureAdapter(struct DevUnit *unit, struct DevBase *base)
808 UBYTE i;
810 /* Set MAC address */
812 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 2);
814 for(i = 0; i < ETH_ADDRESSSIZE; i++)
815 unit->ByteOut(unit->card, EL3REG_ADDRESS0 + i, unit->address[i]);
817 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
819 for(i = 0; i < ETH_ADDRESSSIZE; i++)
820 unit->ByteOut(unit->card, EL3REG_MASK0 + i, 0);
823 /* Enable wider statistics counters */
825 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 4);
826 if(unit->generation >= BOOMERANG_GEN)
827 unit->LEWordOut(unit->card, EL3REG_NETDIAG,
828 EL3REG_NETDIAGF_WIDESTATS);
830 /* Decide on promiscuous mode */
832 if((unit->flags & UNITF_PROM) != 0)
833 unit->rx_filter_cmd |= EL3CMD_SETRXFILTERF_PROM;
835 /* Select chosen transceiver */
837 SelectMedium(unit, unit->transceiver, base);
839 /* Go online */
841 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
842 unit->LELongOut(unit->card, EL3REG_UPLIST, (ULONG)(UPINT)unit->upds);
843 GoOnline(unit, base);
845 /* Return */
847 return;
852 /****i* etherlink3.device/SelectMedium *************************************
854 * NAME
855 * SelectMedium -- .
857 * SYNOPSIS
858 * SelectMedium(unit, transceiver)
860 * VOID SelectMedium(struct DevUnit *, UWORD);
862 * FUNCTION
864 * INPUTS
865 * unit
866 * transceiver
868 * RESULT
869 * None.
871 * EXAMPLE
873 * NOTES
875 * BUGS
877 * SEE ALSO
879 ****************************************************************************
883 VOID SelectMedium(struct DevUnit *unit, UWORD transceiver,
884 struct DevBase *base)
886 ULONG config;
887 UWORD old_window;
889 if((transceiver == EL3XCVR_10BASET || transceiver == EL3XCVR_100BASETX)
890 && unit->generation >= CYCLONE_GEN)
891 transceiver = EL3XCVR_AUTONEG;
893 /* Select transceiver */
895 old_window =
896 unit->LEWordIn(unit->card, EL3REG_STATUS) >> EL3REG_STATUSB_WINDOW;
897 if(unit->bus == PCI_BUS)
899 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 3);
900 config = unit->LELongIn(unit->card, EL3REG_INTERNALCONFIG);
901 config &= ~EL3REG_INTERNALCONFIGF_XCVR;
902 config |= transceiver << EL3REG_INTERNALCONFIGB_XCVR;
903 unit->LELongOut(unit->card, EL3REG_INTERNALCONFIG, config);
905 else
907 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 0);
908 config = unit->LEWordIn(unit->card, EL3REG_ADDRCONFIG);
909 config &= ~EL3REG_ADDRCONFIGF_XCVR;
910 config |= transceiver << EL3REG_ADDRCONFIGB_XCVR;
911 unit->LEWordOut(unit->card, EL3REG_ADDRCONFIG, config);
913 unit->LEWordOut(unit->card, EL3REG_COMMAND,
914 EL3CMD_SELECTWINDOW | old_window);
916 return;
921 /****i* etherlink3.device/GoOnline *****************************************
923 * NAME
924 * GoOnline -- .
926 * SYNOPSIS
927 * GoOnline(unit)
929 * VOID GoOnline(struct DevUnit *);
931 ****************************************************************************
935 VOID GoOnline(struct DevUnit *unit, struct DevBase *base)
937 UWORD transceiver;
939 /* Choose interrupts */
941 unit->flags |= UNITF_ONLINE;
942 unit->LEWordOut(unit->card, EL3REG_COMMAND,
943 EL3CMD_SETINTMASK | unit->int_mask);
944 unit->LEWordOut(unit->card, EL3REG_COMMAND,
945 EL3CMD_SETZEROMASK | unit->int_mask);
947 /* Enable the transceiver */
949 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
950 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_UPUNSTALL);
951 /* needed? */
952 transceiver = unit->transceiver;
954 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 4);
955 if(transceiver == EL3XCVR_100BASETX)
957 unit->LEWordOut(unit->card, EL3REG_MEDIA, EL3REG_MEDIAF_BEATCHECK);
959 else if(transceiver == EL3XCVR_10BASET)
961 unit->LEWordOut(unit->card, EL3REG_MEDIA,
962 EL3REG_MEDIAF_BEATCHECK | EL3REG_MEDIAF_JABBERCHECK);
964 else if(transceiver == EL3XCVR_10BASE2)
965 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STARTCOAX | 0);
967 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 3);
968 if((unit->flags & UNITF_FULLDUPLEX) != 0)
969 unit->LEWordOut(unit->card, EL3REG_MACCONTROL,
970 EL3REG_MACCONTROLF_FULLDUPLEX);
972 unit->LEWordOut(unit->card, EL3REG_COMMAND, unit->rx_filter_cmd);
973 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_RXENABLE);
974 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_TXENABLE);
975 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 1);
977 /* Enable statistics collection */
979 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STATSENABLE);
981 /* Record start time and report Online event */
983 GetSysTime(&unit->stats.LastStart);
984 ReportEvents(unit, S2EVENT_ONLINE, base);
986 return;
991 /****i* etherlink3.device/GoOffline ****************************************
993 * NAME
994 * GoOffline -- .
996 * SYNOPSIS
997 * GoOffline(unit)
999 * VOID GoOffline(struct DevUnit *);
1001 ****************************************************************************
1005 VOID GoOffline(struct DevUnit *unit, struct DevBase *base)
1007 unit->flags &= ~UNITF_ONLINE;
1009 if((unit->flags & UNITF_HAVEADAPTER) != 0)
1011 /* Stop interrupts */
1013 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SETINTMASK | 0);
1014 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1015 EL3CMD_ACKINT | EL3INTF_ANY);
1017 /* Stop transmission and reception */
1019 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_RXDISABLE);
1020 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_TXDISABLE);
1022 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
1024 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_UPSTALL);
1025 while((unit->LEWordIn(unit->card, EL3REG_STATUS) &
1026 EL3REG_STATUSF_CMDINPROGRESS) != 0);
1027 unit->LELongOut(unit->card, EL3REG_UPLIST, (ULONG)0);
1028 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_DOWNSTALL);
1029 while((unit->LEWordIn(unit->card, EL3REG_STATUS)
1030 & EL3REG_STATUSF_CMDINPROGRESS) != 0);
1031 unit->LELongOut(unit->card, EL3REG_DOWNLIST, (ULONG)0);
1034 /* Turn off media functions */
1036 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 4);
1037 unit->LEWordOut(unit->card, EL3REG_MEDIA, 0);
1038 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 1);
1039 #if 0
1040 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STOPCOAX | 0);
1041 #endif
1043 /* Update then disable statistics */
1045 UpdateStats(unit, base);
1046 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STATSDISABLE);
1049 /* Flush pending read and write requests */
1051 FlushUnit(unit, WRITE_QUEUE, S2ERR_OUTOFSERVICE, base);
1053 /* Report Offline event and return */
1055 ReportEvents(unit, S2EVENT_OFFLINE, base);
1056 return;
1061 /****i* etherlink3.device/AddMulticastRange ********************************
1063 * NAME
1064 * AddMulticastRange -- .
1066 * SYNOPSIS
1067 * success = AddMulticastRange(unit, lower_bound, upper_bound)
1069 * BOOL AddMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1071 ****************************************************************************
1075 BOOL AddMulticastRange(struct DevUnit *unit, const UBYTE *lower_bound,
1076 const UBYTE *upper_bound, struct DevBase *base)
1078 struct AddressRange *range;
1079 ULONG lower_bound_left, upper_bound_left;
1080 UWORD lower_bound_right, upper_bound_right;
1082 lower_bound_left = BELong(*((ULONG *)lower_bound));
1083 lower_bound_right = BEWord(*((UWORD *)(lower_bound + 4)));
1084 upper_bound_left = BELong(*((ULONG *)upper_bound));
1085 upper_bound_right = BEWord(*((UWORD *)(upper_bound + 4)));
1087 range = FindMulticastRange(unit, lower_bound_left, lower_bound_right,
1088 upper_bound_left, upper_bound_right, base);
1090 if(range != NULL)
1091 range->add_count++;
1092 else
1094 range = AllocMem(sizeof(struct AddressRange), MEMF_PUBLIC);
1095 if(range != NULL)
1097 range->lower_bound_left = lower_bound_left;
1098 range->lower_bound_right = lower_bound_right;
1099 range->upper_bound_left = upper_bound_left;
1100 range->upper_bound_right = upper_bound_right;
1101 range->add_count = 1;
1103 Disable();
1104 AddTail((APTR)&unit->multicast_ranges, (APTR)range);
1105 Enable();
1107 if(unit->range_count++ == 0)
1109 unit->rx_filter_cmd |= EL3CMD_SETRXFILTERF_MCAST;
1110 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1111 unit->rx_filter_cmd);
1116 return range != NULL;
1121 /****i* etherlink3.device/RemMulticastRange ********************************
1123 * NAME
1124 * RemMulticastRange -- .
1126 * SYNOPSIS
1127 * found = RemMulticastRange(unit, lower_bound, upper_bound)
1129 * BOOL RemMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1131 ****************************************************************************
1135 BOOL RemMulticastRange(struct DevUnit *unit, const UBYTE *lower_bound,
1136 const UBYTE *upper_bound, struct DevBase *base)
1138 struct AddressRange *range;
1139 ULONG lower_bound_left, upper_bound_left;
1140 UWORD lower_bound_right, upper_bound_right;
1142 lower_bound_left = BELong(*((ULONG *)lower_bound));
1143 lower_bound_right = BEWord(*((UWORD *)(lower_bound + 4)));
1144 upper_bound_left = BELong(*((ULONG *)upper_bound));
1145 upper_bound_right = BEWord(*((UWORD *)(upper_bound + 4)));
1147 range = FindMulticastRange(unit, lower_bound_left, lower_bound_right,
1148 upper_bound_left, upper_bound_right, base);
1150 if(range != NULL)
1152 if(--range->add_count == 0)
1154 Disable();
1155 Remove((APTR)range);
1156 Enable();
1157 FreeMem(range, sizeof(struct AddressRange));
1159 if(--unit->range_count == 0)
1161 unit->rx_filter_cmd &= ~EL3CMD_SETRXFILTERF_MCAST;
1162 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1163 unit->rx_filter_cmd);
1168 return range != NULL;
1173 /****i* etherlink3.device/FindMulticastRange *******************************
1175 * NAME
1176 * FindMulticastRange -- .
1178 * SYNOPSIS
1179 * range = FindMulticastRange(unit, lower_bound_left,
1180 * lower_bound_right, upper_bound_left, upper_bound_right)
1182 * struct AddressRange *FindMulticastRange(struct DevUnit *, ULONG,
1183 * UWORD, ULONG, UWORD);
1185 ****************************************************************************
1189 static struct AddressRange *FindMulticastRange(struct DevUnit *unit,
1190 ULONG lower_bound_left, UWORD lower_bound_right, ULONG upper_bound_left,
1191 UWORD upper_bound_right, struct DevBase *base)
1193 struct AddressRange *range, *tail;
1194 BOOL found = FALSE;
1196 range = (APTR)unit->multicast_ranges.mlh_Head;
1197 tail = (APTR)&unit->multicast_ranges.mlh_Tail;
1199 while((range != tail) && !found)
1201 if((lower_bound_left == range->lower_bound_left) &&
1202 (lower_bound_right == range->lower_bound_right) &&
1203 (upper_bound_left == range->upper_bound_left) &&
1204 (upper_bound_right == range->upper_bound_right))
1205 found = TRUE;
1206 else
1207 range = (APTR)range->node.mln_Succ;
1210 if(!found)
1211 range = NULL;
1213 return range;
1218 /****i* etherlink3.device/FindTypeStats ************************************
1220 * NAME
1221 * FindTypeStats -- .
1223 * SYNOPSIS
1224 * stats = FindTypeStats(unit, list,
1225 * packet_type)
1227 * struct TypeStats *FindTypeStats(struct DevUnit *, struct MinList *,
1228 * ULONG);
1230 ****************************************************************************
1234 struct TypeStats *FindTypeStats(struct DevUnit *unit, struct MinList *list,
1235 ULONG packet_type, struct DevBase *base)
1237 struct TypeStats *stats, *tail;
1238 BOOL found = FALSE;
1240 stats = (APTR)list->mlh_Head;
1241 tail = (APTR)&list->mlh_Tail;
1243 while(stats != tail && !found)
1245 if(stats->packet_type == packet_type)
1246 found = TRUE;
1247 else
1248 stats = (APTR)stats->node.mln_Succ;
1251 if(!found)
1252 stats = NULL;
1254 return stats;
1259 /****i* etherlink3.device/FlushUnit ****************************************
1261 * NAME
1262 * FlushUnit -- .
1264 * SYNOPSIS
1265 * FlushUnit(unit, last_queue, error)
1267 * VOID FlushUnit(struct DevUnit *, UBYTE, BYTE);
1269 ****************************************************************************
1271 * Includes alternative implementations because of ambiguities in SANA-II
1272 * documentation.
1276 VOID FlushUnit(struct DevUnit *unit, UBYTE last_queue, BYTE error,
1277 struct DevBase *base)
1279 struct IORequest *request;
1280 UBYTE i;
1281 struct Opener *opener, *tail;
1283 /* Abort queued requests */
1285 for(i = 0; i <= last_queue; i++)
1287 while((request = (APTR)GetMsg(unit->request_ports[i])) != NULL)
1289 request->io_Error = IOERR_ABORTED;
1290 ReplyMsg((APTR)request);
1294 #if 1
1295 opener = (APTR)unit->openers.mlh_Head;
1296 tail = (APTR)&unit->openers.mlh_Tail;
1298 /* Flush every opener's read queue */
1300 while(opener != tail)
1302 while((request = (APTR)GetMsg(&opener->read_port)) != NULL)
1304 request->io_Error = error;
1305 ReplyMsg((APTR)request);
1307 opener = (APTR)opener->node.mln_Succ;
1310 #else
1311 opener = request->ios2_BufferManagement;
1312 while((request = (APTR)GetMsg(&opener->read_port)) != NULL)
1314 request->io_Error = IOERR_ABORTED;
1315 ReplyMsg((APTR)request);
1317 #endif
1319 /* Return */
1321 return;
1326 /****i* etherlink3.device/StatusInt ****************************************
1328 * NAME
1329 * StatusInt
1331 * SYNOPSIS
1332 * finished = StatusInt(unit, int_code)
1334 * BOOL StatusInt(struct DevUnit *, APTR);
1336 ****************************************************************************
1338 * int_code is really in A5, but GCC 2.95.3 doesn't seem able to handle that.
1339 * Since we don't use this parameter, we can lie.
1343 BOOL StatusInt(REG(a1, struct DevUnit *unit), REG(a6, APTR int_code))
1345 struct DevBase *base;
1346 UWORD ints;
1348 base = unit->device;
1349 ints = unit->LEWordIn(unit->card, EL3REG_STATUS);
1351 if((ints & EL3INTF_ANY) != 0)
1353 /* Handle interrupts */
1355 if((ints & EL3INTF_UPDONE) != 0)
1357 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1358 EL3CMD_ACKINT | EL3INTF_UPDONE);
1359 Cause(&unit->rx_int);
1361 if((ints & EL3INTF_DOWNDONE) != 0)
1363 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1364 EL3CMD_ACKINT | EL3INTF_DOWNDONE);
1365 Cause(&unit->tx_end_int);
1367 if((ints & EL3INTF_UPDATESTATS) != 0)
1368 UpdateStats(unit, base);
1369 if((ints & EL3INTF_RXCOMPLETE) != 0)
1371 #ifndef __MORPHOS__
1372 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1373 EL3CMD_SETINTMASK | (unit->int_mask & ~EL3INTF_RXCOMPLETE));
1374 #endif
1375 Cause(&unit->rx_int);
1377 if((ints & EL3INTF_TXAVAIL) != 0)
1379 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1380 EL3CMD_ACKINT | EL3INTF_TXAVAIL);
1381 Cause(&unit->tx_int);
1383 if((ints & EL3INTF_TXCOMPLETE) != 0)
1384 TxError(unit, base);
1386 /* Acknowledge interrupt request */
1388 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1389 EL3CMD_ACKINT | EL3INTF_ANY);
1392 return FALSE;
1397 /****i* etherlink3.device/RXInt ********************************************
1399 * NAME
1400 * RXInt
1402 * SYNOPSIS
1403 * RXInt(unit, int_code)
1405 * VOID RXInt(struct DevUnit *, APTR);
1407 ****************************************************************************
1411 static VOID RXInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code))
1413 UWORD rx_status, packet_size;
1414 struct DevBase *base;
1415 BOOL is_orphan, accepted;
1416 ULONG packet_type;
1417 UBYTE *buffer;
1418 struct IOSana2Req *request, *request_tail;
1419 struct Opener *opener, *opener_tail;
1420 struct TypeStats *tracker;
1422 base = unit->device;
1423 buffer = unit->rx_buffer;
1425 while(((rx_status = unit->LEWordIn(unit->card, EL3REG_RXSTATUS))
1426 & EL3REG_RXSTATUSF_INCOMPLETE) == 0)
1428 if((rx_status & EL3REG_RXSTATUSF_ERROR) == 0)
1430 /* Read packet header */
1432 is_orphan = TRUE;
1433 packet_size = rx_status & EL3REG_RXSTATUS_SIZEMASK;
1434 unit->LongsIn(unit->card, EL3REG_DATA0, (ULONG *)buffer,
1435 ETH_HEADERSIZE + 3 >> 2);
1437 if(AddressFilter(unit, buffer + ETH_PACKET_DEST, base))
1439 packet_type = BEWord(*((UWORD *)(buffer + ETH_PACKET_TYPE)));
1441 opener = (APTR)unit->openers.mlh_Head;
1442 opener_tail = (APTR)&unit->openers.mlh_Tail;
1444 /* Offer packet to every opener */
1446 while(opener != opener_tail)
1448 request = (APTR)opener->read_port.mp_MsgList.lh_Head;
1449 request_tail = (APTR)&opener->read_port.mp_MsgList.lh_Tail;
1450 accepted = FALSE;
1452 /* Offer packet to each request until it's accepted */
1454 while((request != request_tail) && !accepted)
1456 if(request->ios2_PacketType == packet_type
1457 || request->ios2_PacketType <= ETH_MTU
1458 && packet_type <= ETH_MTU)
1460 CopyPacket(unit, request, packet_size, packet_type,
1461 buffer, !is_orphan, base);
1462 accepted = TRUE;
1464 request =
1465 (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
1468 if(accepted)
1469 is_orphan = FALSE;
1470 opener = (APTR)opener->node.mln_Succ;
1473 /* If packet was unwanted, give it to S2_READORPHAN request */
1475 if(is_orphan)
1477 unit->stats.UnknownTypesReceived++;
1478 if(!IsMsgPortEmpty(unit->request_ports[ADOPT_QUEUE]))
1480 CopyPacket(unit,
1481 (APTR)unit->request_ports[ADOPT_QUEUE]->
1482 mp_MsgList.lh_Head, packet_size, packet_type, buffer,
1483 FALSE, base);
1487 /* Update remaining statistics */
1489 tracker =
1490 FindTypeStats(unit, &unit->type_trackers, packet_type, base);
1491 if(tracker != NULL)
1493 tracker->stats.PacketsReceived++;
1494 tracker->stats.BytesReceived += packet_size;
1498 else
1500 unit->stats.BadData++;
1501 ReportEvents(unit, S2EVENT_ERROR | S2EVENT_HARDWARE | S2EVENT_RX,
1502 base);
1505 /* Discard packet */
1507 Disable(); /* Needed? */
1508 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_RXDISCARD);
1509 while((unit->LEWordIn(unit->card, EL3REG_STATUS) &
1510 EL3REG_STATUSF_CMDINPROGRESS) != 0);
1511 Enable();
1514 /* Return */
1516 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1517 EL3CMD_SETINTMASK | unit->int_mask);
1518 return;
1523 /****i* etherlink3.device/CopyPacket ***************************************
1525 * NAME
1526 * CopyPacket
1528 * SYNOPSIS
1529 * CopyPacket(unit, request, packet_size, packet_type,
1530 * buffer, all_read)
1532 * VOID CopyPacket(struct DevUnit *, struct IOSana2Req *, UWORD, UWORD,
1533 * UBYTE *, BOOL);
1535 ****************************************************************************
1539 static VOID CopyPacket(struct DevUnit *unit, struct IOSana2Req *request,
1540 UWORD packet_size, UWORD packet_type, UBYTE *buffer, BOOL all_read,
1541 struct DevBase *base)
1543 struct Opener *opener;
1544 BOOL filtered = FALSE;
1546 /* Set multicast and broadcast flags */
1548 request->ios2_Req.io_Flags &= ~(SANA2IOF_BCAST | SANA2IOF_MCAST);
1549 if((*((ULONG *)(buffer + ETH_PACKET_DEST)) == 0xffffffff) &&
1550 (*((UWORD *)(buffer + ETH_PACKET_DEST + 4)) == 0xffff))
1551 request->ios2_Req.io_Flags |= SANA2IOF_BCAST;
1552 else if((buffer[ETH_PACKET_DEST] & 0x1) != 0)
1553 request->ios2_Req.io_Flags |= SANA2IOF_MCAST;
1555 /* Set source and destination addresses and packet type */
1557 CopyMem(buffer + ETH_PACKET_SOURCE, request->ios2_SrcAddr,
1558 ETH_ADDRESSSIZE);
1559 CopyMem(buffer + ETH_PACKET_DEST, request->ios2_DstAddr,
1560 ETH_ADDRESSSIZE);
1561 request->ios2_PacketType = packet_type;
1563 /* Read rest of packet (PIO mode only) */
1565 if(!all_read)
1567 unit->LongsIn(unit->card, EL3REG_DATA0,
1568 (ULONG *)(buffer + ((ETH_PACKET_DATA + 3) & ~0x3)),
1569 (packet_size - ETH_PACKET_DATA + 1) >> 2);
1572 /* Adjust for cooked packet request */
1574 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1576 packet_size -= ETH_PACKET_DATA;
1577 buffer += ETH_PACKET_DATA;
1579 #ifdef USE_HACKS
1580 else
1581 packet_size += 4; /* Needed for Shapeshifter & Fusion */
1582 #endif
1583 request->ios2_DataLength = packet_size;
1585 /* Filter packet */
1587 opener = request->ios2_BufferManagement;
1588 if((request->ios2_Req.io_Command == CMD_READ) &&
1589 (opener->filter_hook != NULL))
1590 if(!CallHookPkt(opener->filter_hook, request, buffer))
1591 filtered = TRUE;
1593 if(!filtered)
1595 /* Copy packet into opener's buffer and reply packet */
1597 if(!opener->rx_function(request->ios2_Data, buffer, packet_size))
1599 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
1600 request->ios2_WireError = S2WERR_BUFF_ERROR;
1601 ReportEvents(unit,
1602 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF | S2EVENT_RX,
1603 base);
1605 Remove((APTR)request);
1606 ReplyMsg((APTR)request);
1609 return;
1614 /****i* etherlink3.device/AddressFilter ************************************
1616 * NAME
1617 * AddressFilter
1619 * SYNOPSIS
1620 * accept = AddressFilter(unit, address)
1622 * BOOL AddressFilter(struct DevUnit *, UBYTE *);
1624 ****************************************************************************
1628 static BOOL AddressFilter(struct DevUnit *unit, UBYTE *address,
1629 struct DevBase *base)
1631 struct AddressRange *range, *tail;
1632 BOOL accept = TRUE;
1633 ULONG address_left;
1634 UWORD address_right;
1636 /* Check whether address is unicast/broadcast or multicast */
1638 address_left = BELong(*((ULONG *)address));
1639 address_right = BEWord(*((UWORD *)(address + 4)));
1641 if((address_left & 0x01000000) != 0 &&
1642 !(address_left == 0xffffffff && address_right == 0xffff))
1644 /* Check if this multicast address is wanted */
1646 range = (APTR)unit->multicast_ranges.mlh_Head;
1647 tail = (APTR)&unit->multicast_ranges.mlh_Tail;
1648 accept = FALSE;
1650 while((range != tail) && !accept)
1652 if((address_left > range->lower_bound_left ||
1653 address_left == range->lower_bound_left &&
1654 address_right >= range->lower_bound_right) &&
1655 (address_left < range->upper_bound_left ||
1656 address_left == range->upper_bound_left &&
1657 address_right <= range->upper_bound_right))
1658 accept = TRUE;
1659 range = (APTR)range->node.mln_Succ;
1662 if(!accept)
1663 unit->special_stats[S2SS_ETHERNET_BADMULTICAST & 0xffff]++;
1666 return accept;
1671 /****i* etherlink3.device/TXInt ********************************************
1673 * NAME
1674 * TXInt
1676 * SYNOPSIS
1677 * TXInt(unit)
1679 * VOID TXInt(struct DevUnit *);
1681 ****************************************************************************
1685 static VOID TXInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code))
1687 UWORD packet_size, data_size, send_size;
1688 struct DevBase *base;
1689 struct IOSana2Req *request;
1690 BOOL proceed = TRUE;
1691 struct Opener *opener;
1692 ULONG *buffer, wire_error;
1693 UBYTE *(*dma_tx_function)(REG(a0, APTR));
1694 BYTE error;
1695 struct MsgPort *port;
1696 struct TypeStats *tracker;
1698 base = unit->device;
1699 port = unit->request_ports[WRITE_QUEUE];
1701 while(proceed && (!IsMsgPortEmpty(port)))
1703 error = 0;
1705 request = (APTR)port->mp_MsgList.lh_Head;
1706 data_size = packet_size = request->ios2_DataLength;
1708 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1709 packet_size += ETH_PACKET_DATA;
1711 if(unit->LEWordIn(unit->card, EL3REG_TXSPACE)
1712 > EL3_PREAMBLESIZE + packet_size)
1714 /* Write packet preamble */
1716 unit->LELongOut(unit->card, EL3REG_DATA0, packet_size);
1718 /* Write packet header */
1720 send_size = (packet_size + 3) & ~0x3;
1721 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1723 union {
1724 UBYTE bytes[12];
1725 ULONG ulong[3];
1726 } header;
1727 memcpy(&header.bytes[0], request->ios2_DstAddr, 6);
1728 memcpy(&header.bytes[6], unit->address, 6);
1729 unit->LongOut(unit->card, EL3REG_DATA0, header.ulong[0]);
1730 unit->LongOut(unit->card, EL3REG_DATA0, header.ulong[1]);
1731 unit->LongOut(unit->card, EL3REG_DATA0, header.ulong[2]);
1732 unit->BEWordOut(unit->card, EL3REG_DATA0,
1733 request->ios2_PacketType);
1734 send_size -= ETH_HEADERSIZE;
1737 /* Get packet data */
1739 opener = (APTR)request->ios2_BufferManagement;
1740 dma_tx_function = opener->dma_tx_function;
1741 if(dma_tx_function != NULL)
1742 buffer = (ULONG *)dma_tx_function(request->ios2_Data);
1743 else
1744 buffer = NULL;
1746 if(buffer == NULL)
1748 buffer = (ULONG *)unit->tx_buffer;
1749 if(!opener->tx_function(buffer, request->ios2_Data, data_size))
1751 error = S2ERR_NO_RESOURCES;
1752 wire_error = S2WERR_BUFF_ERROR;
1753 ReportEvents(unit,
1754 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF
1755 | S2EVENT_TX, base);
1759 /* Write packet data */
1761 if(error == 0)
1763 unit->LongsOut(unit->card, EL3REG_DATA0, buffer,
1764 send_size >> 2);
1765 buffer += (send_size >> 2);
1766 if((send_size & 0x3) != 0)
1767 unit->WordOut(unit->card, EL3REG_DATA0, *((UWORD *)buffer));
1770 /* Reply packet */
1772 request->ios2_Req.io_Error = error;
1773 request->ios2_WireError = wire_error;
1774 Remove((APTR)request);
1775 ReplyMsg((APTR)request);
1777 /* Update statistics */
1779 if(error == 0)
1781 tracker = FindTypeStats(unit, &unit->type_trackers,
1782 request->ios2_PacketType, base);
1783 if(tracker != NULL)
1785 tracker->stats.PacketsSent++;
1786 tracker->stats.BytesSent += packet_size;
1790 else
1791 proceed = FALSE;
1794 if(proceed)
1795 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
1796 else
1798 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SETTXTHRESH
1799 | ((EL3_PREAMBLESIZE + packet_size) >> unit->size_shift));
1800 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_IGNORE;
1803 return;
1808 /****i* etherlink3.device/TxError ******************************************
1810 * NAME
1811 * TxError
1813 * SYNOPSIS
1814 * TxError(unit)
1816 * VOID TxError(struct DevUnit *);
1818 ****************************************************************************
1822 static VOID TxError(struct DevUnit *unit, struct DevBase *base)
1824 UPINT window1_offset;
1825 UBYTE tx_status, flags = 0;
1827 window1_offset = unit->window1_offset;
1829 /* Gather all errors */
1831 while(((tx_status =
1832 unit->ByteIn(unit->card, window1_offset + EL3REG_TXSTATUS))
1833 & EL3REG_TXSTATUSF_COMPLETE) != 0)
1835 flags |= tx_status;
1836 unit->ByteOut(unit->card, window1_offset + EL3REG_TXSTATUS, 0);
1839 /* Restart transmitter if necessary */
1841 if((flags & EL3REG_TXSTATUSF_JABBER) != 0)
1843 Disable();
1844 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_TXRESET);
1845 while((unit->LEWordIn(unit->card, EL3REG_STATUS) &
1846 EL3REG_STATUSF_CMDINPROGRESS) != 0);
1847 Enable();
1850 if((flags & (EL3REG_TXSTATUSF_JABBER | EL3REG_TXSTATUSF_OVERFLOW
1851 | EL3REG_TXSTATUSF_RECLAIMERROR)) != 0)
1852 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_TXENABLE);
1854 /* Report the error(s) */
1856 ReportEvents(unit, S2EVENT_ERROR | S2EVENT_HARDWARE | S2EVENT_TX, base);
1858 return;
1863 /****i* etherlink3.device/UpdateStats **************************************
1865 * NAME
1866 * UpdateStats
1868 * SYNOPSIS
1869 * UpdateStats(unit)
1871 * VOID UpdateStats(struct DevUnit *);
1873 ****************************************************************************
1877 VOID UpdateStats(struct DevUnit *unit, struct DevBase *base)
1879 UBYTE frame_counts_upper;
1880 UWORD generation, old_window;
1882 generation = unit->generation;
1884 old_window =
1885 unit->LEWordIn(unit->card, EL3REG_STATUS) >> EL3REG_STATUSB_WINDOW;
1886 if(generation < VORTEX_GEN)
1887 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STATSDISABLE);
1889 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 6);
1890 unit->ByteIn(unit->card, EL3REG_CARRIERLOST);
1891 unit->ByteIn(unit->card, EL3REG_SQEERRORS);
1892 unit->ByteIn(unit->card, EL3REG_MULTIPLECOLLISIONS);
1893 unit->ByteIn(unit->card, EL3REG_SINGLECOLLISIONS);
1894 unit->ByteIn(unit->card, EL3REG_LATECOLLISIONS);
1895 unit->stats.Overruns += unit->ByteIn(unit->card, EL3REG_RXOVERRUNS);
1896 unit->stats.PacketsSent += unit->ByteIn(unit->card, EL3REG_TXFRAMESOK);
1897 unit->stats.PacketsReceived +=
1898 unit->ByteIn(unit->card, EL3REG_RXFRAMESOK);
1899 unit->special_stats[S2SS_ETHERNET_RETRIES & 0xffff] +=
1900 unit->ByteIn(unit->card, EL3REG_FRAMESDEFERRED);
1901 unit->LEWordIn(unit->card, EL3REG_RXBYTESOK);
1902 unit->LEWordIn(unit->card, EL3REG_TXBYTESOK);
1903 if(generation >= VORTEX_GEN)
1905 frame_counts_upper = unit->ByteIn(unit->card, EL3REG_FRAMESOKUPPER);
1906 unit->stats.PacketsReceived += (frame_counts_upper & 0x3) << 8;
1907 unit->stats.PacketsSent += (frame_counts_upper & 0x30) << 4;
1908 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 4);
1909 unit->ByteIn(unit->card, EL3REG_BADSSD);
1910 if(generation >= BOOMERANG_GEN)
1911 unit->ByteIn(unit->card, EL3REG_BYTESOKUPPER);
1914 if(generation < VORTEX_GEN)
1915 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STATSENABLE);
1916 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1917 EL3CMD_SELECTWINDOW | old_window);
1918 return;
1923 /****i* etherlink3.device/DMARXInt *****************************************
1925 * NAME
1926 * DMARXInt
1928 * SYNOPSIS
1929 * DMARXInt(unit, int_code)
1931 * VOID DMARXInt(struct DevUnit *, APTR);
1933 ****************************************************************************
1937 static VOID DMARXInt(REG(a1, struct DevUnit *unit),
1938 REG(a5, APTR int_code))
1940 UWORD packet_size;
1941 struct DevBase *base;
1942 BOOL is_orphan, accepted;
1943 ULONG rx_status, packet_type, *upd, *fragment, dma_size;
1944 UBYTE *buffer;
1945 struct IOSana2Req *request, *request_tail;
1946 struct Opener *opener, *opener_tail;
1947 struct TypeStats *tracker;
1949 base = unit->device;
1950 upd = unit->next_upd;
1952 dma_size = UPD_SIZE * RX_SLOT_COUNT;
1953 CachePostDMA(unit->upds, &dma_size, 0);
1955 while(((rx_status = LELong(upd[EL3UPD_STATUS]))
1956 & EL3UPD_STATUSF_COMPLETE) != 0)
1958 fragment = upd + EL3UPD_FIRSTFRAG;
1959 buffer = (UBYTE *)(UPINT)LELong(fragment[EL3FRAG_ADDR]);
1961 dma_size = ETH_MAXPACKETSIZE;
1962 CachePostDMA(buffer, &dma_size, 0);
1964 if((rx_status & EL3UPD_STATUSF_ERROR) == 0)
1966 is_orphan = TRUE;
1967 packet_size = rx_status & EL3UPD_STATUSF_SIZE;
1969 if(AddressFilter(unit, buffer + ETH_PACKET_DEST, base))
1971 packet_type = BEWord(*((UWORD *)(buffer + ETH_PACKET_TYPE)));
1973 opener = (APTR)unit->openers.mlh_Head;
1974 opener_tail = (APTR)&unit->openers.mlh_Tail;
1976 /* Offer packet to every opener */
1978 while(opener != opener_tail)
1980 request = (APTR)opener->read_port.mp_MsgList.lh_Head;
1981 request_tail = (APTR)&opener->read_port.mp_MsgList.lh_Tail;
1982 accepted = FALSE;
1984 /* Offer packet to each request until it's accepted */
1986 while((request != request_tail) && !accepted)
1988 if(request->ios2_PacketType == packet_type
1989 || request->ios2_PacketType <= ETH_MTU
1990 && packet_type <= ETH_MTU)
1992 CopyPacket(unit, request, packet_size, packet_type,
1993 buffer, TRUE, base);
1994 accepted = TRUE;
1996 request =
1997 (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
2000 if(accepted)
2001 is_orphan = FALSE;
2002 opener = (APTR)opener->node.mln_Succ;
2005 /* If packet was unwanted, give it to S2_READORPHAN request */
2007 if(is_orphan)
2009 unit->stats.UnknownTypesReceived++;
2010 if(!IsMsgPortEmpty(unit->request_ports[ADOPT_QUEUE]))
2012 CopyPacket(unit,
2013 (APTR)unit->request_ports[ADOPT_QUEUE]->
2014 mp_MsgList.lh_Head, packet_size, packet_type, buffer,
2015 TRUE, base);
2019 /* Update remaining statistics */
2021 tracker =
2022 FindTypeStats(unit, &unit->type_trackers, packet_type, base);
2023 if(tracker != NULL)
2025 tracker->stats.PacketsReceived++;
2026 tracker->stats.BytesReceived += packet_size;
2030 else
2032 unit->stats.BadData++;
2033 ReportEvents(unit, S2EVENT_ERROR | S2EVENT_HARDWARE | S2EVENT_RX,
2034 base);
2037 upd[EL3UPD_STATUS] = 0;
2039 dma_size = ETH_MAXPACKETSIZE;
2040 CachePreDMA(buffer, &dma_size, 0);
2042 upd = (ULONG *)(UPINT)LELong(upd[EL3UPD_NEXT]);
2045 dma_size = UPD_SIZE * RX_SLOT_COUNT;
2046 CachePreDMA(unit->upds, &dma_size, 0);
2048 /* Return */
2050 unit->next_upd = upd;
2051 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_UPUNSTALL);
2052 #if 1 /* ??? */
2053 unit->LEWordOut(unit->card, EL3REG_COMMAND,
2054 EL3CMD_SETINTMASK | unit->int_mask);
2055 #endif
2056 return;
2061 /****i* etherlink3.device/DMATXInt *****************************************
2063 * NAME
2064 * DMATXInt
2066 * SYNOPSIS
2067 * DMATXInt(unit, int_code)
2069 * VOID DMATXInt(struct DevUnit *, APTR);
2071 ****************************************************************************
2075 static VOID DMATXInt(REG(a1, struct DevUnit *unit),
2076 REG(a5, APTR int_code))
2078 UWORD packet_size, data_size, slot, new_slot, *p, *q, i;
2079 struct DevBase *base;
2080 struct IOSana2Req *request;
2081 BOOL proceed = TRUE;
2082 struct Opener *opener;
2083 ULONG wire_error, *dpd, *last_dpd, *next_dpd, *fragment, dma_size;
2084 UBYTE *(*dma_tx_function)(REG(a0, APTR));
2085 BYTE error;
2086 UBYTE *buffer;
2087 struct MsgPort *port;
2089 base = unit->device;
2090 port = unit->request_ports[WRITE_QUEUE];
2092 while(proceed && (!IsMsgPortEmpty(port)))
2094 slot = unit->tx_in_slot;
2095 new_slot = (slot + 1) % TX_SLOT_COUNT;
2097 if(new_slot != unit->tx_out_slot
2098 && (unit->flags & UNITF_TXBUFFERINUSE) == 0)
2100 error = 0;
2102 request = (APTR)port->mp_MsgList.lh_Head;
2103 data_size = packet_size = request->ios2_DataLength;
2105 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
2106 packet_size += ETH_HEADERSIZE;
2107 dpd = unit->dpds + ((DPD_SIZE / sizeof(ULONG)) * slot);
2109 /* Write packet preamble */
2111 Remove((APTR)request);
2112 unit->tx_requests[slot] = request;
2113 dpd[EL3DPD_NEXT] = (ULONG)0;
2114 dpd[EL3DPD_HEADER] =
2115 MakeLELong(EL3DPD_HEADERF_DLINT | packet_size);
2116 fragment = dpd + EL3DPD_FIRSTFRAG;
2118 /* Write packet header */
2120 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
2122 buffer = unit->headers + ETH_HEADERSIZE * slot;
2123 fragment[EL3FRAG_ADDR] = MakeLELong((ULONG)(UPINT)buffer);
2124 fragment[EL3FRAG_LEN] = MakeLELong(ETH_HEADERSIZE);
2126 p = (UWORD *)buffer;
2127 for(i = 0, q = (UWORD *)request->ios2_DstAddr;
2128 i < ETH_ADDRESSSIZE / 2; i++)
2129 *p++ = *q++;
2130 for(i = 0, q = (UWORD *)unit->address;
2131 i < ETH_ADDRESSSIZE / 2; i++)
2132 *p++ = *q++;
2133 *p++ = MakeBEWord(request->ios2_PacketType);
2134 buffer = (UBYTE *)p;
2136 dma_size = ETH_HEADERSIZE;
2137 CachePreDMA(buffer, &dma_size, DMA_ReadFromRAM);
2138 fragment += EL3_FRAGLEN;
2141 /* Get packet data */
2143 opener = (APTR)request->ios2_BufferManagement;
2144 dma_tx_function = opener->dma_tx_function;
2145 if(dma_tx_function != NULL)
2146 buffer = dma_tx_function(request->ios2_Data);
2147 else
2148 buffer = NULL;
2150 if(buffer == NULL)
2152 buffer = unit->tx_buffer;
2153 if(opener->tx_function(buffer, request->ios2_Data, data_size))
2154 unit->flags |= UNITF_TXBUFFERINUSE;
2155 else
2157 error = S2ERR_NO_RESOURCES;
2158 wire_error = S2WERR_BUFF_ERROR;
2159 ReportEvents(unit,
2160 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF
2161 | S2EVENT_TX, base);
2165 /* Fill in rest of descriptor for packet transmission */
2167 if(error == 0)
2169 fragment[EL3FRAG_ADDR] = MakeLELong((ULONG)(UPINT)buffer);
2170 fragment[EL3FRAG_LEN] =
2171 MakeLELong(EL3FRAG_LENF_LAST | data_size);
2173 /* Pass packet to adapter */
2175 dma_size = data_size;
2176 CachePreDMA(buffer, &dma_size, DMA_ReadFromRAM);
2178 last_dpd = (ULONG *)(UPINT)
2179 unit->LELongIn(unit->card, EL3REG_DOWNLIST);
2180 if(last_dpd != NULL)
2182 unit->LEWordOut(unit->card, EL3REG_COMMAND,
2183 EL3CMD_DOWNSTALL);
2184 while((unit->LEWordIn(unit->card, EL3REG_STATUS)
2185 & EL3REG_STATUSF_CMDINPROGRESS) != 0);
2186 while((next_dpd =
2187 (ULONG *)(UPINT)LELong(last_dpd[EL3DPD_NEXT])) != NULL)
2188 last_dpd = next_dpd;
2189 last_dpd[EL3DPD_NEXT] = MakeLELong((ULONG)(UPINT)dpd);
2190 dma_size = DPD_SIZE * TX_SLOT_COUNT;
2191 CachePreDMA(unit->dpds, &dma_size, 0);
2192 unit->LEWordOut(unit->card, EL3REG_COMMAND,
2193 EL3CMD_DOWNUNSTALL);
2195 else
2197 dma_size = DPD_SIZE * TX_SLOT_COUNT;
2198 CachePreDMA(unit->dpds, &dma_size, 0);
2199 unit->LELongOut(unit->card, EL3REG_DOWNLIST,
2200 (ULONG)(UPINT)dpd);
2203 unit->tx_in_slot = new_slot;
2205 else
2207 /* Reply failed request */
2209 request->ios2_Req.io_Error = error;
2210 request->ios2_WireError = wire_error;
2211 ReplyMsg((APTR)request);
2214 else
2215 proceed = FALSE;
2218 if(proceed)
2219 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
2220 else
2221 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_IGNORE;
2223 return;
2228 /****i* etherlink3.device/DMATXEndInt **************************************
2230 * NAME
2231 * DMATXEndInt
2233 * SYNOPSIS
2234 * DMATXEndInt(unit, int_code)
2236 * VOID DMATXEndInt(struct DevUnit *, APTR);
2238 * NOTES
2239 * I think it's safe to assume that there will always be at least one
2240 * completed packet whenever this interrupt is called.
2242 ****************************************************************************
2246 static VOID DMATXEndInt(REG(a1, struct DevUnit *unit),
2247 REG(a5, APTR int_code))
2249 UWORD data_size, packet_size, new_out_slot, i;
2250 UBYTE *buffer;
2251 struct DevBase *base;
2252 struct IOSana2Req *request;
2253 ULONG *dpd, *fragment, dma_size;
2254 struct TypeStats *tracker;
2256 /* Find out which packets have completed */
2258 base = unit->device;
2259 dpd = (ULONG *)(UPINT)unit->LELongIn(unit->card, EL3REG_DOWNLIST);
2260 if(dpd != NULL)
2261 new_out_slot = (dpd - unit->dpds) / (sizeof(ULONG) * DPD_SIZE);
2262 else
2263 new_out_slot = unit->tx_in_slot;
2265 /* Retire sent packets */
2267 for(i = unit->tx_out_slot; i != new_out_slot;
2268 i = (i + 1) % TX_SLOT_COUNT)
2270 /* Mark end of DMA */
2272 request = unit->tx_requests[i];
2273 data_size = packet_size = request->ios2_DataLength;
2274 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
2275 packet_size += ETH_HEADERSIZE;
2277 dpd = unit->dpds + ((DPD_SIZE / sizeof(ULONG)) * i);
2278 fragment = dpd + EL3DPD_FIRSTFRAG;
2279 dma_size = DPD_SIZE * TX_SLOT_COUNT;
2280 CachePostDMA(unit->dpds, &dma_size, 0);
2282 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
2284 buffer = (APTR)(UPINT)LELong(fragment[EL3FRAG_ADDR]);
2285 dma_size = ETH_HEADERSIZE;
2286 CachePostDMA(buffer, &dma_size, DMA_ReadFromRAM);
2287 fragment += EL3_FRAGLEN;
2290 buffer = (APTR)(UPINT)LELong(fragment[EL3FRAG_ADDR]);
2291 dma_size = data_size;
2292 CachePostDMA(buffer, &dma_size, DMA_ReadFromRAM);
2294 /* Check if unit's TX buffer is now free */
2296 if(buffer == unit->tx_buffer)
2297 unit->flags &= ~UNITF_TXBUFFERINUSE;
2299 /* Update statistics */
2301 tracker = FindTypeStats(unit, &unit->type_trackers,
2302 request->ios2_PacketType, base);
2303 if(tracker != NULL)
2305 tracker->stats.PacketsSent++;
2306 tracker->stats.BytesSent += packet_size;
2309 /* Reply request */
2311 request->ios2_Req.io_Error = 0;
2312 ReplyMsg((APTR)request);
2315 unit->tx_out_slot = new_out_slot;
2317 /* Restart downloads if they had stopped */
2319 if(unit->request_ports[WRITE_QUEUE]->mp_Flags == PA_IGNORE)
2320 Cause(&unit->tx_int);
2322 return;
2327 /****i* etherlink3.device/ReportEvents *************************************
2329 * NAME
2330 * ReportEvents -- .
2332 * SYNOPSIS
2333 * ReportEvents(unit, events)
2335 * VOID ReportEvents(struct DevUnit *, ULONG);
2337 * INPUTS
2338 * unit - A unit of this device.
2339 * events - A mask of events to report.
2341 * RESULT
2342 * None.
2344 ****************************************************************************
2348 static VOID ReportEvents(struct DevUnit *unit, ULONG events,
2349 struct DevBase *base)
2351 struct IOSana2Req *request, *tail, *next_request;
2352 struct List *list;
2354 list = &unit->request_ports[EVENT_QUEUE]->mp_MsgList;
2355 next_request = (APTR)list->lh_Head;
2356 tail = (APTR)&list->lh_Tail;
2358 Disable();
2359 while(next_request != tail)
2361 request = next_request;
2362 next_request = (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
2364 if((request->ios2_WireError & events) != 0)
2366 request->ios2_WireError = events;
2367 Remove((APTR)request);
2368 ReplyMsg((APTR)request);
2371 Enable();
2373 return;
2378 /****i* etherlink3.device/UnitTask *****************************************
2380 * NAME
2381 * UnitTask
2383 * SYNOPSIS
2384 * UnitTask()
2386 * VOID UnitTask();
2388 * FUNCTION
2390 * INPUTS
2392 * RESULT
2394 * EXAMPLE
2396 * NOTES
2398 * BUGS
2400 * SEE ALSO
2402 ****************************************************************************
2406 static VOID UnitTask(struct ExecBase *sys_base)
2408 struct Task *task;
2409 struct IORequest *request;
2410 struct DevUnit *unit;
2411 struct DevBase *base;
2412 struct MsgPort *general_port;
2413 ULONG signals, wait_signals, card_removed_signal, card_inserted_signal,
2414 general_port_signal;
2416 /* Get parameters */
2418 task = FindTask(NULL);
2419 unit = task->tc_UserData;
2420 base = unit->device;
2422 /* Activate general request port */
2424 general_port = unit->request_ports[GENERAL_QUEUE];
2425 general_port->mp_SigTask = task;
2426 general_port->mp_SigBit = AllocSignal(-1);
2427 general_port_signal = 1 << general_port->mp_SigBit;
2428 general_port->mp_Flags = PA_SIGNAL;
2430 /* Allocate a signal for notification of card removal */
2432 card_removed_signal = unit->card_removed_signal = 1 << AllocSignal(-1);
2433 card_inserted_signal = unit->card_inserted_signal = 1 << AllocSignal(-1);
2434 wait_signals = (1 << general_port->mp_SigBit) | card_removed_signal
2435 | card_inserted_signal;
2437 /* Tell ourselves to check port for old messages */
2439 Signal(task, general_port_signal);
2441 /* Infinite loop to service requests and signals */
2443 while(TRUE)
2445 signals = Wait(wait_signals);
2447 if((signals & card_inserted_signal) != 0)
2449 if(unit->insertion_function(unit->card, base))
2451 unit->flags |= UNITF_HAVEADAPTER;
2452 if((unit->flags & UNITF_CONFIGURED) != 0)
2453 ConfigureAdapter(unit, base);
2457 if((signals & card_removed_signal) != 0)
2459 unit->removal_function(unit->card, base);
2460 GoOffline(unit, base);
2463 if((signals & general_port_signal) != 0)
2465 while((request = (APTR)GetMsg(general_port)) != NULL)
2467 /* Service the request as soon as the unit is free */
2469 ObtainSemaphore(&unit->access_lock);
2470 ServiceRequest((APTR)request, base);
2478 /****i* etherlink3.device/ReadEEPROM ***************************************
2480 * NAME
2481 * ReadEEPROM -- Read a location on card's EEPROM.
2483 * SYNOPSIS
2484 * value = ReadEEPROM(unit, index)
2486 * UWORD ReadEEPROM(struct DevUnit *, UWORD);
2488 * INPUTS
2489 * unit - Device unit.
2490 * index - Offset within EEPROM.
2492 * RESULT
2493 * value - Contents of specified EEPROM location.
2495 ****************************************************************************
2499 static UWORD ReadEEPROM(struct DevUnit *unit, UWORD index,
2500 struct DevBase *base)
2502 unit->LEWordOut(unit->card, EL3REG_EEPROMCMD, EL3ECMD_READ | index);
2503 while((unit->LEWordIn(unit->card, EL3REG_EEPROMCMD) &
2504 EL3REG_EEPROMCMDF_BUSY) != 0);
2506 return unit->LEWordIn(unit->card, EL3REG_EEPROMDATA);
2511 /****i* etherlink3.device/ReadMII ******************************************
2513 * NAME
2514 * ReadMII -- Read a register on an MII PHY.
2516 * SYNOPSIS
2517 * success = ReadMII(unit, phy_no, reg_no, value)
2519 * BOOL ReadMII(struct DevUnit *, UWORD, UWORD, UWORD *);
2521 * FUNCTION
2522 * Reads a register on an MII PHY. Window 4 must be selected before
2523 * calling this function.
2525 * INPUTS
2526 * unit - Device unit.
2527 * phy_no - .
2528 * reg_no - .
2529 * value - Pointer to location to store value read from MII register.
2531 * RESULT
2532 * success - Success indicator.
2534 ****************************************************************************
2538 static BOOL ReadMII(struct DevUnit *unit, UWORD phy_no, UWORD reg_no,
2539 UWORD *value, struct DevBase *base)
2541 BOOL success = TRUE;
2543 WriteMIIBits(unit, 0xffffffff, 32, base);
2544 WriteMIIBits(unit, 0x6, 4, base);
2545 WriteMIIBits(unit, phy_no, 5, base);
2546 WriteMIIBits(unit, reg_no, 5, base);
2547 ReadMIIBit(unit, base);
2548 if(ReadMIIBit(unit, base))
2549 success = FALSE;
2550 *value = ReadMIIBits(unit, 16, base);
2551 ReadMIIBit(unit, base);
2553 return success;
2558 /****i* etherlink3.device/WriteMII *****************************************
2560 * NAME
2561 * WriteMII -- Write to a register on an MII PHY.
2563 * SYNOPSIS
2564 * WriteMII(unit, phy_no, reg_no, value)
2566 * VOID WriteMII(struct DevUnit *, UWORD, UWORD, UWORD);
2568 * INPUTS
2569 * unit - Device unit.
2570 * phy_no - .
2571 * reg_no - .
2572 * value - value to write to MII register.
2574 * RESULT
2575 * None.
2577 ****************************************************************************
2581 #if 0
2582 static VOID WriteMII(struct DevUnit *unit, UWORD phy_no, UWORD reg_no,
2583 UWORD value, struct DevBase *base)
2585 WriteMIIBits(unit, 0xffffffff, 32, base);
2586 WriteMIIBits(unit, 0x5, 4, base);
2587 WriteMIIBits(unit, phy_no, 5, base);
2588 WriteMIIBits(unit, reg_no, 5, base);
2589 WriteMIIBit(unit, TRUE, base);
2590 WriteMIIBits(unit, value, 16, base);
2591 DoMIIZCycle(unit, base);
2593 return;
2595 #endif
2599 /****i* etherlink3.device/ReadMIIBits **************************************
2601 * NAME
2602 * ReadMIIBits
2604 * SYNOPSIS
2605 * value = ReadMIIBits(unit, count)
2607 * ULONG ReadMIIBits(struct DevUnit *, UBYTE);
2609 ****************************************************************************
2613 static ULONG ReadMIIBits(struct DevUnit *unit, UBYTE count,
2614 struct DevBase *base)
2616 UBYTE i;
2617 ULONG value = 0;
2619 /* LEWordOut(io_addr, LEWordIn(reg) & ~EL3REG_PHYMGMTF_WRITE);*/
2620 for(i = 0; i < count; i++)
2622 value <<= 1;
2623 if(ReadMIIBit(unit, base))
2624 value |= 1;
2625 unit->LEWordIn(unit->card, EL3REG_PHYMGMT);
2627 /* ReadMIIBit(unit, base)? value |= 1;*/
2629 return value;
2633 /****i* etherlink3.device/WriteMIIBits *************************************
2635 * NAME
2636 * WriteMIIBits
2638 * SYNOPSIS
2639 * WriteMIIBits(unit, value, count)
2641 * VOID WriteMIIBits(struct DevUnit *, ULONG, UBYTE);
2643 ****************************************************************************
2647 static VOID WriteMIIBits(struct DevUnit *unit, ULONG value, UBYTE count,
2648 struct DevBase *base)
2650 ULONG mask;
2652 for(mask = 1 << (count - 1); mask != 0; mask >>= 1)
2653 WriteMIIBit(unit, (value & mask) != 0, base);
2655 return;
2660 /****i* etherlink3.device/ReadMIIBit ***************************************
2662 * NAME
2663 * ReadMIIBit
2665 * SYNOPSIS
2666 * is_one = ReadMIIBit(unit)
2668 * BOOL ReadMIIBit(struct DevUnit *);
2670 ****************************************************************************
2674 static BOOL ReadMIIBit(struct DevUnit *unit, struct DevBase *base)
2676 BOOL is_one;
2678 unit->LEWordOut(unit->card, EL3REG_PHYMGMT, 0);
2679 BusyMicroDelay(1, base);
2680 unit->LEWordOut(unit->card, EL3REG_PHYMGMT, EL3REG_PHYMGMTF_CLK);
2681 BusyMicroDelay(1, base);
2682 is_one =
2683 (unit->LEWordIn(unit->card, EL3REG_PHYMGMT) & EL3REG_PHYMGMTF_DATA)
2684 != 0;
2685 BusyMicroDelay(1, base);
2687 return is_one;
2692 /****i* etherlink3.device/WriteMIIBit **************************************
2694 * NAME
2695 * WriteMIIBit
2697 * SYNOPSIS
2698 * WriteMIIBit(unit, is_one)
2700 * VOID WriteMIIBit(struct DevUnit *, BOOL);
2702 ****************************************************************************
2706 static VOID WriteMIIBit(struct DevUnit *unit, BOOL is_one,
2707 struct DevBase *base)
2709 unit->LEWordOut(unit->card, EL3REG_PHYMGMT, EL3REG_PHYMGMTF_WRITE);
2710 BusyMicroDelay(1, base);
2711 if(is_one)
2712 unit->LEWordOut(unit->card, EL3REG_PHYMGMT,
2713 EL3REG_PHYMGMTF_WRITE | EL3REG_PHYMGMTF_CLK |
2714 EL3REG_PHYMGMTF_DATA);
2715 else
2716 unit->LEWordOut(unit->card, EL3REG_PHYMGMT,
2717 EL3REG_PHYMGMTF_WRITE | EL3REG_PHYMGMTF_CLK);
2718 BusyMicroDelay(1, base);
2720 return;
2725 /****i* etherlink3.device/DoMIIZCycle **************************************
2727 * NAME
2728 * DoMIIZCycle
2730 * SYNOPSIS
2731 * DoMIIZCycle(unit)
2733 * VOID DoMIIZCycle(struct DevUnit *);
2735 ****************************************************************************
2739 #if 0
2740 static VOID DoMIIZCycle(struct DevUnit *unit, struct DevBase *base)
2742 unit->LEWordOut(unit->card, EL3REG_PHYMGMT,
2743 unit->LEWordIn(unit->card, EL3REG_PHYMGMT) & ~EL3REG_PHYMGMTF_CLK);
2744 BusyMicroDelay(1, base);
2745 unit->LEWordOut(unit->card, EL3REG_PHYMGMT, EL3REG_PHYMGMTF_CLK);
2746 BusyMicroDelay(1, base);
2748 return;
2750 #endif
2754 #if 0
2755 static VOID BusyMicroDelay(ULONG micros, struct DevBase *base)
2757 struct timeval time, end_time;
2759 GetSysTime(&end_time);
2760 time.tv_secs = 0;
2761 time.tv_micro = micros;
2762 AddTime(&end_time, &time);
2764 while(CmpTime(&end_time, &time) < 0)
2765 GetSysTime(&time);
2767 return;
2771 #else
2772 static VOID BusyMicroDelay(ULONG micros, struct DevBase *base)
2774 struct EClockVal time, end_time;
2775 ULONG rate;
2777 rate = ReadEClock(&time);
2778 end_time.ev_hi = time.ev_hi;
2779 end_time.ev_lo = time.ev_lo + (micros * rate + 1) / 1000000;
2780 if(end_time.ev_lo < time.ev_lo)
2781 end_time.ev_hi++;
2783 while(time.ev_lo < end_time.ev_lo || time.ev_hi < end_time.ev_hi)
2784 ReadEClock(&time);
2786 return;
2788 #endif