- Fixes to OS wrappers to allow extra mask parameter for PCCard status
[AROS.git] / workbench / devs / networks / etherlink3 / unit.c
blob7f78bfb4ddc3e3e28cb52c16a874d7bc69e21bb0
1 /*
3 Copyright (C) 2001-2011 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.
23 #include <exec/memory.h>
24 #include <exec/execbase.h>
25 #include <exec/errors.h>
27 #include <proto/exec.h>
28 #ifndef __amigaos4__
29 #include <proto/alib.h>
30 #else
31 #include <clib/alib_protos.h>
32 #endif
33 #include <proto/utility.h>
34 #include <proto/timer.h>
36 #include "device.h"
37 #include "etherlink3.h"
38 #include "mii.h"
40 #include "unit_protos.h"
41 #include "request_protos.h"
44 #define TASK_PRIORITY 0
45 #define STACK_SIZE 4096
46 #define INT_MASK \
47 (EL3INTF_UPDATESTATS | EL3INTF_RXCOMPLETE | EL3INTF_TXAVAIL \
48 | EL3INTF_TXCOMPLETE)
49 #define DMA_INT_MASK \
50 (EL3INTF_UPDONE | EL3INTF_DOWNDONE | EL3INTF_UPDATESTATS \
51 | EL3INTF_TXCOMPLETE)
52 #define PORT_COUNT 6
55 #ifndef AbsExecBase
56 #define AbsExecBase (*(struct ExecBase **)4)
57 #endif
58 #ifdef __amigaos4__
59 #undef AddTask
60 #define AddTask(task, initial_pc, final_pc) \
61 IExec->AddTask(task, initial_pc, final_pc, NULL)
62 #endif
64 VOID SelectMedium(struct DevUnit *unit, UWORD transceiver,
65 struct DevBase *base);
66 static struct AddressRange *FindMulticastRange(struct DevUnit *unit,
67 ULONG lower_bound_left, UWORD lower_bound_right, ULONG upper_bound_left,
68 UWORD upper_bound_right, struct DevBase *base);
69 static VOID RXInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code));
70 static VOID CopyPacket(struct DevUnit *unit, struct IOSana2Req *request,
71 UWORD packet_size, UWORD packet_type, UBYTE *buffer, BOOL all_read,
72 struct DevBase *base);
73 static BOOL AddressFilter(struct DevUnit *unit, UBYTE *address,
74 struct DevBase *base);
75 static VOID TXInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code));
76 static VOID TxError(struct DevUnit *unit, struct DevBase *base);
77 static VOID DMARXInt(REG(a1, struct DevUnit *unit),
78 REG(a5, APTR int_code));
79 static VOID DMATXInt(REG(a1, struct DevUnit *unit),
80 REG(a5, APTR int_code));
81 static VOID DMATXEndInt(REG(a1, struct DevUnit *unit),
82 REG(a5, APTR int_code));
83 static VOID ReportEvents(struct DevUnit *unit, ULONG events,
84 struct DevBase *base);
85 static VOID UnitTask();
86 static UWORD ReadEEPROM(struct DevUnit *unit, UWORD index,
87 struct DevBase *base);
88 static BOOL ReadMII(struct DevUnit *unit, UWORD phy_no, UWORD reg_no,
89 UWORD *value, struct DevBase *base);
90 #if 0
91 static VOID WriteMII(struct DevUnit *unit, UWORD phy_no, UWORD reg_no,
92 UWORD value, struct DevBase *base);
93 #endif
94 static ULONG ReadMIIBits(struct DevUnit *unit, UBYTE count,
95 struct DevBase *base);
96 static VOID WriteMIIBits(struct DevUnit *unit, ULONG value, UBYTE count,
97 struct DevBase *base);
98 static BOOL ReadMIIBit(struct DevUnit *unit, struct DevBase *base);
99 static VOID WriteMIIBit(struct DevUnit *unit, BOOL is_one,
100 struct DevBase *base);
101 #if 0
102 static VOID DoMIIZCycle(struct DevUnit *unit, struct DevBase *base);
103 #endif
104 static VOID BusyMicroDelay(ULONG micros, struct DevBase *base);
107 static const UBYTE port_choices[] =
109 /* EL3XCVR_AUTONEG,*/
110 EL3XCVR_100BASETX,
111 EL3XCVR_10BASET,
112 EL3XCVR_MII,
113 EL3XCVR_100BASEFX,
114 EL3XCVR_10BASE2,
115 EL3XCVR_AUI
118 static const UBYTE port_masks[] =
120 EL3REG_MEDIAOPTIONSF_10BASET,
121 EL3REG_MEDIAOPTIONSF_AUI,
123 EL3REG_MEDIAOPTIONSF_10BASE2,
124 EL3REG_MEDIAOPTIONSF_100BASETX,
125 EL3REG_MEDIAOPTIONSF_100BASEFX,
126 EL3REG_MEDIAOPTIONSF_MII,
128 EL3REG_MEDIAOPTIONSF_100BASETX | EL3REG_MEDIAOPTIONSF_10BASET
132 /****i* etherlink3.device/CreateUnit ***************************************
134 * NAME
135 * CreateUnit -- Create a unit.
137 * SYNOPSIS
138 * unit = CreateUnit(index, card, io_tags, generation,
139 * bus)
141 * struct DevUnit *CreateUnit(ULONG, APTR, struct TagItem *, UWORD,
142 * UWORD);
144 * FUNCTION
145 * Creates a new unit.
147 ****************************************************************************
151 struct DevUnit *CreateUnit(ULONG index, APTR card,
152 const struct TagItem *io_tags, UWORD generation, UWORD bus,
153 struct DevBase *base)
155 BOOL success = TRUE;
156 struct DevUnit *unit;
157 struct Task *task;
158 struct MsgPort *port;
159 UBYTE i, *buffer;
160 APTR stack;
161 ULONG *upd, *next_upd, *fragment, dma_size;
162 APTR rx_int_function, tx_int_function;
164 unit = AllocMem(sizeof(struct DevUnit), MEMF_CLEAR | MEMF_PUBLIC);
165 if(unit == NULL)
166 success = FALSE;
168 if(success)
170 InitSemaphore(&unit->access_lock);
171 NewList((APTR)&unit->openers);
172 NewList((APTR)&unit->type_trackers);
173 NewList((APTR)&unit->multicast_ranges);
175 unit->index = index;
176 unit->device = base;
177 unit->card = card;
178 unit->generation = generation;
179 unit->bus = bus;
180 unit->ByteIn =
181 (APTR)GetTagData(IOTAG_ByteIn, (UPINT)NULL, io_tags);
182 unit->LongIn =
183 (APTR)GetTagData(IOTAG_LongIn, (UPINT)NULL, io_tags);
184 unit->ByteOut =
185 (APTR)GetTagData(IOTAG_ByteOut, (UPINT)NULL, io_tags);
186 unit->WordOut =
187 (APTR)GetTagData(IOTAG_WordOut, (UPINT)NULL, io_tags);
188 unit->LongOut =
189 (APTR)GetTagData(IOTAG_LongOut, (UPINT)NULL, io_tags);
190 unit->LongsIn =
191 (APTR)GetTagData(IOTAG_LongsIn, (UPINT)NULL, io_tags);
192 unit->LongsOut =
193 (APTR)GetTagData(IOTAG_LongsOut, (UPINT)NULL, io_tags);
194 unit->BEWordOut =
195 (APTR)GetTagData(IOTAG_BEWordOut, (UPINT)NULL, io_tags);
196 unit->LEWordIn =
197 (APTR)GetTagData(IOTAG_LEWordIn, (UPINT)NULL, io_tags);
198 unit->LELongIn =
199 (APTR)GetTagData(IOTAG_LELongIn, (UPINT)NULL, io_tags);
200 unit->LEWordOut =
201 (APTR)GetTagData(IOTAG_LEWordOut, (UPINT)NULL, io_tags);
202 unit->LELongOut =
203 (APTR)GetTagData(IOTAG_LELongOut, (UPINT)NULL, io_tags);
204 unit->AllocDMAMem =
205 (APTR)GetTagData(IOTAG_AllocDMAMem, (UPINT)NULL, io_tags);
206 unit->FreeDMAMem =
207 (APTR)GetTagData(IOTAG_FreeDMAMem, (UPINT)NULL, io_tags);
208 if(unit->ByteIn == NULL || unit->LongIn == NULL
209 || unit->ByteOut == NULL
210 || unit->WordOut == NULL || unit->LongOut == NULL
211 || unit->LongsIn == NULL || unit->LongsOut == NULL
212 || unit->BEWordOut == NULL || unit->LEWordIn == NULL
213 || unit->LELongIn == NULL || unit->LEWordOut == NULL
214 || unit->LELongOut == NULL
215 || generation >= BOOMERANG_GEN
216 && (unit->AllocDMAMem == NULL || unit->FreeDMAMem == NULL))
217 success = FALSE;
220 if(success)
222 if(unit->generation >= VORTEX_GEN)
223 unit->size_shift = 2;
225 InitialiseAdapter(unit, FALSE, base);
226 unit->flags |= UNITF_HAVEADAPTER;
228 /* Set up packet filter command */
230 unit->rx_filter_cmd = EL3CMD_SETRXFILTER | EL3CMD_SETRXFILTERF_BCAST
231 | EL3CMD_SETRXFILTERF_UCAST;
233 /* Set up interrupt mask */
235 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
236 unit->int_mask = DMA_INT_MASK;
237 else
238 unit->int_mask = INT_MASK;
240 /* Disable statistics interrupts for PCMCIA because they can't be
241 cleared on A1200 */
243 if(bus == PCCARD_BUS)
244 unit->int_mask &= ~EL3INTF_UPDATESTATS;
246 /* Store location of registers that were originally in window 1 */
248 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
249 unit->window1_offset += EL3_WINDOWSIZE;
251 /* Create the message ports for queuing requests */
253 for(i = 0; i < REQUEST_QUEUE_COUNT; i++)
255 unit->request_ports[i] = port = AllocMem(sizeof(struct MsgPort),
256 MEMF_PUBLIC | MEMF_CLEAR);
257 if(port == NULL)
258 success = FALSE;
260 if(success)
262 NewList(&port->mp_MsgList);
263 port->mp_Flags = PA_IGNORE;
264 port->mp_SigTask = &unit->tx_int;
268 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
270 unit->rx_buffer = unit->AllocDMAMem(unit->card,
271 ETH_MAXPACKETSIZE * RX_SLOT_COUNT, 1);
272 unit->tx_buffer =
273 unit->AllocDMAMem(unit->card, ETH_MAXPACKETSIZE, 1);
275 else
277 unit->rx_buffer =
278 AllocVec((ETH_MAXPACKETSIZE + 3) & ~3, MEMF_PUBLIC);
279 unit->tx_buffer = AllocVec(ETH_MAXPACKETSIZE, MEMF_PUBLIC);
282 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
284 unit->tx_requests = AllocVec(sizeof(APTR) * TX_SLOT_COUNT,
285 MEMF_PUBLIC);
286 unit->headers = unit->AllocDMAMem(unit->card,
287 ETH_HEADERSIZE * TX_SLOT_COUNT, 1);
288 unit->dpds =
289 unit->AllocDMAMem(unit->card, DPD_SIZE * TX_SLOT_COUNT, 8);
290 next_upd = unit->upds =
291 unit->AllocDMAMem(unit->card, UPD_SIZE * RX_SLOT_COUNT, 8);
292 if(unit->tx_requests == NULL || unit->headers == NULL
293 || unit->dpds == NULL || next_upd == NULL)
294 success = FALSE;
297 if(unit->rx_buffer == NULL || unit->tx_buffer == NULL)
298 success = FALSE;
301 if(success)
303 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
305 /* Construct RX ring */
307 buffer = unit->rx_buffer;
308 for(i = 0; i < RX_SLOT_COUNT; i++)
310 upd = next_upd;
311 next_upd = upd + UPD_SIZE / sizeof(ULONG);
312 upd[EL3UPD_NEXT] = MakeLELong((ULONG)(UPINT)next_upd);
313 upd[EL3UPD_STATUS] = 0;
314 fragment = upd + EL3UPD_FIRSTFRAG;
315 fragment[EL3FRAG_ADDR] = MakeLELong((ULONG)(UPINT)buffer);
316 fragment[EL3FRAG_LEN] =
317 MakeLELong(EL3FRAG_LENF_LAST | ETH_MAXPACKETSIZE);
318 buffer += ETH_MAXPACKETSIZE;
320 upd[EL3UPD_NEXT] = MakeLELong((ULONG)(UPINT)unit->upds);
321 unit->next_upd = unit->upds;
323 dma_size = UPD_SIZE * RX_SLOT_COUNT;
324 CachePreDMA(unit->upds, &dma_size, 0);
325 dma_size = ETH_MAXPACKETSIZE * RX_SLOT_COUNT;
326 CachePreDMA(unit->rx_buffer, &dma_size, 0);
329 /* Record maximum speed in BPS */
331 if((unit->capabilities & EL3ROM_CAPABILITIESF_100MBPS) != 0)
332 unit->speed = 100000000;
333 else
334 unit->speed = 10000000;
336 /* Initialise status, transmit and receive interrupts */
338 unit->status_int.is_Node.ln_Name =
339 base->device.dd_Library.lib_Node.ln_Name;
340 unit->status_int.is_Code = (APTR)StatusInt;
341 unit->status_int.is_Data = unit;
343 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
344 rx_int_function = DMARXInt;
345 else
346 rx_int_function = RXInt;
347 unit->rx_int.is_Node.ln_Name =
348 base->device.dd_Library.lib_Node.ln_Name;
349 unit->rx_int.is_Code = rx_int_function;
350 unit->rx_int.is_Data = unit;
352 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
353 tx_int_function = DMATXInt;
354 else
355 tx_int_function = TXInt;
356 unit->tx_int.is_Node.ln_Name =
357 base->device.dd_Library.lib_Node.ln_Name;
358 unit->tx_int.is_Code = tx_int_function;
359 unit->tx_int.is_Data = unit;
361 unit->tx_end_int.is_Node.ln_Name =
362 base->device.dd_Library.lib_Node.ln_Name;
363 unit->tx_end_int.is_Code = DMATXEndInt;
364 unit->tx_end_int.is_Data = unit;
366 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
369 if(success)
371 /* Create a new task */
373 unit->task = task =
374 AllocMem(sizeof(struct Task), MEMF_PUBLIC | MEMF_CLEAR);
375 if(task == NULL)
376 success = FALSE;
379 if(success)
381 stack = AllocMem(STACK_SIZE, MEMF_PUBLIC);
382 if(stack == NULL)
383 success = FALSE;
386 if(success)
388 /* Initialise and start task */
390 task->tc_Node.ln_Type = NT_TASK;
391 task->tc_Node.ln_Pri = TASK_PRIORITY;
392 task->tc_Node.ln_Name =
393 base->device.dd_Library.lib_Node.ln_Name;
394 task->tc_SPUpper = stack + STACK_SIZE;
395 task->tc_SPLower = stack;
396 task->tc_SPReg = stack + STACK_SIZE;
397 NewList(&task->tc_MemEntry);
399 if(AddTask(task, UnitTask, NULL) == NULL)
400 success = FALSE;
403 /* Send the unit to the new task */
405 if(success)
406 task->tc_UserData = unit;
408 if(!success)
410 DeleteUnit(unit, base);
411 unit = NULL;
414 return unit;
419 /****i* etherlink3.device/DeleteUnit ***************************************
421 * NAME
422 * DeleteUnit -- Delete a unit.
424 * SYNOPSIS
425 * DeleteUnit(unit)
427 * VOID DeleteUnit(struct DevUnit *);
429 * FUNCTION
430 * Deletes a unit.
432 * INPUTS
433 * unit - Device unit (can be NULL).
435 * RESULT
436 * None.
438 * EXAMPLE
440 * NOTES
442 * BUGS
444 * SEE ALSO
446 ****************************************************************************
450 VOID DeleteUnit(struct DevUnit *unit, struct DevBase *base)
452 UBYTE i;
453 struct Task *task;
455 if(unit != NULL)
457 task = unit->task;
458 if(task != NULL)
460 if(task->tc_UserData != NULL)
462 RemTask(task);
463 FreeMem(task->tc_SPLower, STACK_SIZE);
465 FreeMem(task, sizeof(struct Task));
468 for(i = 0; i < REQUEST_QUEUE_COUNT; i++)
470 if(unit->request_ports[i] != NULL)
471 FreeMem(unit->request_ports[i], sizeof(struct MsgPort));
474 if((unit->flags & UNITF_HAVEADAPTER) != 0) /* Needed! */
475 GoOffline(unit, base);
477 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
479 unit->FreeDMAMem(unit->card, unit->upds);
480 unit->FreeDMAMem(unit->card, unit->dpds);
481 unit->FreeDMAMem(unit->card, unit->headers);
482 FreeVec(unit->tx_requests);
485 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
487 unit->FreeDMAMem(unit->card, unit->tx_buffer);
488 unit->FreeDMAMem(unit->card, unit->rx_buffer);
490 else
492 FreeVec(unit->tx_buffer);
493 FreeVec(unit->rx_buffer);
496 FreeMem(unit, sizeof(struct DevUnit));
499 return;
504 /****i* etherlink3.device/InitialiseAdapter ********************************
506 * NAME
507 * InitialiseAdapter -- .
509 * SYNOPSIS
510 * InitialiseAdapter(unit, reinsertion)
512 * BOOL InitialiseAdapter(struct DevUnit *, BOOL);
514 * FUNCTION
516 * INPUTS
517 * unit
518 * reinsertion
520 * RESULT
521 * None.
523 * EXAMPLE
525 * NOTES
527 * BUGS
529 * SEE ALSO
531 ****************************************************************************
535 BOOL InitialiseAdapter(struct DevUnit *unit, BOOL reinsertion,
536 struct DevBase *base)
538 UBYTE *p, i;
539 UWORD address_part, links = 0, ports, new_ports, tp_ports,
540 media_status, transceiver, status, advert, ability, modes;
541 ULONG config;
542 BOOL autoselect;
544 /* Reset card. We avoid resetting the receive logic because it stops the
545 link status working in the MII Status register */
547 unit->LEWordOut(unit->card, EL3REG_COMMAND,
548 EL3CMD_RXRESET | EL3CMD_RXRESETF_SKIPNETWORK);
549 while((unit->LEWordIn(unit->card, EL3REG_STATUS) &
550 EL3REG_STATUSF_CMDINPROGRESS) != 0);
551 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_TXRESET);
552 while((unit->LEWordIn(unit->card, EL3REG_STATUS) &
553 EL3REG_STATUSF_CMDINPROGRESS) != 0);
555 /* Select IO addresses and interrupt for PCCard */
557 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 0);
558 if(unit->bus == PCCARD_BUS)
559 unit->LEWordOut(unit->card, EL3REG_RESCONFIG, 0x3f00);
560 if(unit->bus == ISA_BUS)
561 unit->LEWordOut(unit->card, EL3REG_RESCONFIG, (10 << 12) | 0xf00);
563 /* Fully enable an ISA card */
565 if(unit->bus == ISA_BUS)
566 unit->LEWordOut(unit->card, EL3REG_CONFIG, EL3REG_CONFIGF_ENABLE);
568 /* Get card capabilities */
570 unit->capabilities = ReadEEPROM(unit, EL3ROM_CAPABILITIES, base);
572 /* Get default MAC address */
574 p = unit->default_address;
576 for(i = 0; i < ETH_ADDRESSSIZE / 2; i++)
578 address_part = ReadEEPROM(unit, EL3ROM_ALTADDRESS0 + i, base);
579 *p++ = address_part >> 8;
580 *p++ = address_part & 0xff;
583 /* Get available transceivers */
585 if(unit->bus == PCCARD_BUS || unit->bus == ISA_BUS)
587 config = unit->LEWordIn(unit->card, EL3REG_CONFIG);
588 ports = (config >> 8) &
589 (EL3REG_MEDIAOPTIONSF_AUI | EL3REG_MEDIAOPTIONSF_10BASE2);
590 if((config & EL3REG_CONFIGF_10BASET) != 0)
591 ports |= EL3REG_MEDIAOPTIONSF_10BASET;
593 else
595 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 3);
596 ports = unit->LEWordIn(unit->card, EL3REG_MEDIAOPTIONS);
597 #if 0
598 if(ports == 0)
599 ports = EL3REG_MEDIAOPTIONSF_MII; /* fix for 3c916? */
600 #endif
603 /* Get transceiver choice from EEPROM */
605 if(unit->bus == PCI_BUS)
607 config = unit->LELongIn(unit->card, EL3REG_INTERNALCONFIG);
608 transceiver =
609 (config & EL3REG_INTERNALCONFIGF_XCVR)
610 >> EL3REG_INTERNALCONFIGB_XCVR;
611 autoselect = (config & EL3REG_INTERNALCONFIGF_AUTOXCVR) != 0;
613 else
615 config = ReadEEPROM(unit, EL3ROM_ADDRCONFIG, base);
616 transceiver =
617 (config & EL3REG_ADDRCONFIGF_XCVR) >> EL3REG_ADDRCONFIGB_XCVR;
618 autoselect = (config & EL3REG_ADDRCONFIGF_AUTOSELECT) != 0;
621 if(!autoselect)
623 /* Check if chosen medium is available */
625 new_ports = ports & port_masks[transceiver];
626 if(new_ports != 0)
627 ports = new_ports;
628 else
629 autoselect = TRUE;
632 /* Auto-select media type */
634 if(autoselect)
636 /* Get transceivers with an active link */
638 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 4);
640 if(unit->generation < CYCLONE_GEN)
642 tp_ports =
643 ports &
644 (EL3REG_MEDIAOPTIONSF_10BASET | EL3REG_MEDIAOPTIONSF_100BASETX);
645 if(tp_ports != 0)
647 SelectMedium(unit, EL3XCVR_10BASET, base);
648 media_status = unit->LEWordIn(unit->card, EL3REG_MEDIA);
649 if((media_status & EL3REG_MEDIAF_BEAT) != 0)
650 links |= tp_ports;
654 if((ports & EL3REG_MEDIAOPTIONSF_MII) != 0
655 || unit->generation >= CYCLONE_GEN)
657 for(i = 0; i < 32; i++)
659 if(ReadMII(unit, i, MII_STATUS, &status, base))
661 ReadMII(unit, i, MII_STATUS, &status, base);
662 /* Yes, status reg must be read twice */
663 if((status & MII_STATUSF_LINK) != 0)
665 if(i == 24) /* Built-in transceiver */
667 if(((status & MII_STATUSF_AUTONEGDONE) != 0)
668 && ((status & MII_STATUSF_EXTREGSET) != 0))
670 ReadMII(unit, i, MII_AUTONEGADVERT, &advert, base);
671 ReadMII(unit, i, MII_AUTONEGABILITY, &ability,
672 base);
673 modes = advert & ability;
675 if((modes & MII_AUTONEGF_100BASETX) != 0)
676 links |= EL3REG_MEDIAOPTIONSF_100BASETX;
677 #if 0
678 if((modes & MII_AUTONEGF_100BASET4) != 0)
679 links |= EL3REG_MEDIAOPTIONSF_100BASET4;
680 #endif
681 if((modes & MII_AUTONEGF_10BASET) != 0)
682 links |= EL3REG_MEDIAOPTIONSF_10BASET;
684 else
686 modes = MII_AUTONEGF_10BASET;
687 links |= EL3REG_MEDIAOPTIONSF_10BASET;
689 unit->autoneg_modes = modes;
691 else
693 links |= EL3REG_MEDIAOPTIONSF_MII;
694 unit->mii_phy_no = i;
701 #if 0
702 if((ports & EL3REG_MEDIAOPTIONSF_10BASE2) != 0)
704 SelectMedium(unit, EL3XCVR_10BASE2, base);
705 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STARTCOAX);
707 if(LoopbackTest(base))
708 links |= EL3REG_MEDIAOPTIONSF_10BASE2;
710 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STOPCOAX);
712 #endif
714 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 0);
716 new_ports = ports & links;
717 if((new_ports) != 0)
718 ports = new_ports;
721 /* Prioritised choice from remaining transceivers */
723 for(i = 0; i < PORT_COUNT; i++)
725 transceiver = port_choices[i];
726 if((ports & port_masks[transceiver]) != 0)
728 unit->transceiver = transceiver;
729 i = PORT_COUNT;
733 /* Find out whether to use full duplex */
735 if((transceiver == EL3XCVR_10BASET || transceiver == EL3XCVR_100BASETX)
736 && unit->generation >= CYCLONE_GEN)
738 modes = unit->autoneg_modes;
741 (modes & MII_AUTONEGF_100BASETXFD) != 0
744 modes
747 MII_AUTONEGF_100BASETX
749 MII_AUTONEGF_10BASETFD
753 MII_AUTONEGF_10BASETFD
755 unit->flags |= UNITF_FULLDUPLEX;
758 /* Return */
760 return TRUE;
765 /****i* etherlink3.device/ConfigureAdapter *********************************
767 * NAME
768 * ConfigureAdapter -- .
770 * SYNOPSIS
771 * ConfigureAdapter(unit)
773 * VOID ConfigureAdapter(struct DevUnit *);
775 * FUNCTION
777 * INPUTS
778 * unit
780 * RESULT
781 * None.
783 * EXAMPLE
785 * NOTES
787 * BUGS
789 * SEE ALSO
791 ****************************************************************************
795 VOID ConfigureAdapter(struct DevUnit *unit, struct DevBase *base)
797 UBYTE i;
799 /* Set MAC address */
801 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 2);
803 for(i = 0; i < ETH_ADDRESSSIZE; i++)
804 unit->ByteOut(unit->card, EL3REG_ADDRESS0 + i, unit->address[i]);
806 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
808 for(i = 0; i < ETH_ADDRESSSIZE; i++)
809 unit->ByteOut(unit->card, EL3REG_MASK0 + i, 0);
812 /* Enable wider statistics counters */
814 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 4);
815 if(unit->generation >= BOOMERANG_GEN)
816 unit->LEWordOut(unit->card, EL3REG_NETDIAG,
817 EL3REG_NETDIAGF_WIDESTATS);
819 /* Decide on promiscuous mode */
821 if((unit->flags & UNITF_PROM) != 0)
822 unit->rx_filter_cmd |= EL3CMD_SETRXFILTERF_PROM;
824 /* Select chosen transceiver */
826 SelectMedium(unit, unit->transceiver, base);
828 /* Go online */
830 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
831 unit->LELongOut(unit->card, EL3REG_UPLIST, (ULONG)(UPINT)unit->upds);
832 GoOnline(unit, base);
834 /* Return */
836 return;
841 /****i* etherlink3.device/SelectMedium *************************************
843 * NAME
844 * SelectMedium -- .
846 * SYNOPSIS
847 * SelectMedium(unit, transceiver)
849 * VOID SelectMedium(struct DevUnit *, UWORD);
851 * FUNCTION
853 * INPUTS
854 * unit
855 * transceiver
857 * RESULT
858 * None.
860 * EXAMPLE
862 * NOTES
864 * BUGS
866 * SEE ALSO
868 ****************************************************************************
872 VOID SelectMedium(struct DevUnit *unit, UWORD transceiver,
873 struct DevBase *base)
875 ULONG config;
876 UWORD old_window;
878 if((transceiver == EL3XCVR_10BASET || transceiver == EL3XCVR_100BASETX)
879 && unit->generation >= CYCLONE_GEN)
880 transceiver = EL3XCVR_AUTONEG;
882 /* Select transceiver */
884 old_window =
885 unit->LEWordIn(unit->card, EL3REG_STATUS) >> EL3REG_STATUSB_WINDOW;
886 if(unit->bus == PCI_BUS)
888 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 3);
889 config = unit->LELongIn(unit->card, EL3REG_INTERNALCONFIG);
890 config &= ~EL3REG_INTERNALCONFIGF_XCVR;
891 config |= transceiver << EL3REG_INTERNALCONFIGB_XCVR;
892 unit->LELongOut(unit->card, EL3REG_INTERNALCONFIG, config);
894 else
896 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 0);
897 config = unit->LEWordIn(unit->card, EL3REG_ADDRCONFIG);
898 config &= ~EL3REG_ADDRCONFIGF_XCVR;
899 config |= transceiver << EL3REG_ADDRCONFIGB_XCVR;
900 unit->LEWordOut(unit->card, EL3REG_ADDRCONFIG, config);
902 unit->LEWordOut(unit->card, EL3REG_COMMAND,
903 EL3CMD_SELECTWINDOW | old_window);
905 return;
910 /****i* etherlink3.device/GoOnline *****************************************
912 * NAME
913 * GoOnline -- .
915 * SYNOPSIS
916 * GoOnline(unit)
918 * VOID GoOnline(struct DevUnit *);
920 ****************************************************************************
924 VOID GoOnline(struct DevUnit *unit, struct DevBase *base)
926 UWORD transceiver;
928 /* Choose interrupts */
930 unit->flags |= UNITF_ONLINE;
931 unit->LEWordOut(unit->card, EL3REG_COMMAND,
932 EL3CMD_SETINTMASK | unit->int_mask);
933 unit->LEWordOut(unit->card, EL3REG_COMMAND,
934 EL3CMD_SETZEROMASK | unit->int_mask);
936 /* Enable the transceiver */
938 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
939 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_UPUNSTALL);
940 /* needed? */
941 transceiver = unit->transceiver;
943 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 4);
944 if(transceiver == EL3XCVR_100BASETX)
946 unit->LEWordOut(unit->card, EL3REG_MEDIA, EL3REG_MEDIAF_BEATCHECK);
948 else if(transceiver == EL3XCVR_10BASET)
950 unit->LEWordOut(unit->card, EL3REG_MEDIA,
951 EL3REG_MEDIAF_BEATCHECK | EL3REG_MEDIAF_JABBERCHECK);
953 else if(transceiver == EL3XCVR_10BASE2)
954 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STARTCOAX | 0);
956 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 3);
957 if((unit->flags & UNITF_FULLDUPLEX) != 0)
958 unit->LEWordOut(unit->card, EL3REG_MACCONTROL,
959 EL3REG_MACCONTROLF_FULLDUPLEX);
961 unit->LEWordOut(unit->card, EL3REG_COMMAND, unit->rx_filter_cmd);
962 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_RXENABLE);
963 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_TXENABLE);
964 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 1);
966 /* Enable statistics collection */
968 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STATSENABLE);
970 /* Record start time and report Online event */
972 GetSysTime(&unit->stats.LastStart);
973 ReportEvents(unit, S2EVENT_ONLINE, base);
975 return;
980 /****i* etherlink3.device/GoOffline ****************************************
982 * NAME
983 * GoOffline -- .
985 * SYNOPSIS
986 * GoOffline(unit)
988 * VOID GoOffline(struct DevUnit *);
990 ****************************************************************************
994 VOID GoOffline(struct DevUnit *unit, struct DevBase *base)
996 unit->flags &= ~UNITF_ONLINE;
998 if((unit->flags & UNITF_HAVEADAPTER) != 0)
1000 /* Stop interrupts */
1002 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SETINTMASK | 0);
1003 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1004 EL3CMD_ACKINT | EL3INTF_ANY);
1006 /* Stop transmission and reception */
1008 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_RXDISABLE);
1009 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_TXDISABLE);
1011 if((unit->capabilities & EL3ROM_CAPABILITIESF_FULLMASTER) != 0)
1013 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_UPSTALL);
1014 while((unit->LEWordIn(unit->card, EL3REG_STATUS) &
1015 EL3REG_STATUSF_CMDINPROGRESS) != 0);
1016 unit->LELongOut(unit->card, EL3REG_UPLIST, (ULONG)0);
1017 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_DOWNSTALL);
1018 while((unit->LEWordIn(unit->card, EL3REG_STATUS)
1019 & EL3REG_STATUSF_CMDINPROGRESS) != 0);
1020 unit->LELongOut(unit->card, EL3REG_DOWNLIST, (ULONG)0);
1023 /* Turn off media functions */
1025 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 4);
1026 unit->LEWordOut(unit->card, EL3REG_MEDIA, 0);
1027 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 1);
1028 #if 0
1029 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STOPCOAX | 0);
1030 #endif
1032 /* Update then disable statistics */
1034 UpdateStats(unit, base);
1035 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STATSDISABLE);
1038 /* Flush pending read and write requests */
1040 FlushUnit(unit, WRITE_QUEUE, S2ERR_OUTOFSERVICE, base);
1042 /* Report Offline event and return */
1044 ReportEvents(unit, S2EVENT_OFFLINE, base);
1045 return;
1050 /****i* etherlink3.device/AddMulticastRange ********************************
1052 * NAME
1053 * AddMulticastRange -- .
1055 * SYNOPSIS
1056 * success = AddMulticastRange(unit, lower_bound, upper_bound)
1058 * BOOL AddMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1060 ****************************************************************************
1064 BOOL AddMulticastRange(struct DevUnit *unit, const UBYTE *lower_bound,
1065 const UBYTE *upper_bound, struct DevBase *base)
1067 struct AddressRange *range;
1068 ULONG lower_bound_left, upper_bound_left;
1069 UWORD lower_bound_right, upper_bound_right;
1071 lower_bound_left = BELong(*((ULONG *)lower_bound));
1072 lower_bound_right = BEWord(*((UWORD *)(lower_bound + 4)));
1073 upper_bound_left = BELong(*((ULONG *)upper_bound));
1074 upper_bound_right = BEWord(*((UWORD *)(upper_bound + 4)));
1076 range = FindMulticastRange(unit, lower_bound_left, lower_bound_right,
1077 upper_bound_left, upper_bound_right, base);
1079 if(range != NULL)
1080 range->add_count++;
1081 else
1083 range = AllocMem(sizeof(struct AddressRange), MEMF_PUBLIC);
1084 if(range != NULL)
1086 range->lower_bound_left = lower_bound_left;
1087 range->lower_bound_right = lower_bound_right;
1088 range->upper_bound_left = upper_bound_left;
1089 range->upper_bound_right = upper_bound_right;
1090 range->add_count = 1;
1092 Disable();
1093 AddTail((APTR)&unit->multicast_ranges, (APTR)range);
1094 Enable();
1096 if(unit->range_count++ == 0)
1098 unit->rx_filter_cmd |= EL3CMD_SETRXFILTERF_MCAST;
1099 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1100 unit->rx_filter_cmd);
1105 return range != NULL;
1110 /****i* etherlink3.device/RemMulticastRange ********************************
1112 * NAME
1113 * RemMulticastRange -- .
1115 * SYNOPSIS
1116 * found = RemMulticastRange(unit, lower_bound, upper_bound)
1118 * BOOL RemMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1120 ****************************************************************************
1124 BOOL RemMulticastRange(struct DevUnit *unit, const UBYTE *lower_bound,
1125 const UBYTE *upper_bound, struct DevBase *base)
1127 struct AddressRange *range;
1128 ULONG lower_bound_left, upper_bound_left;
1129 UWORD lower_bound_right, upper_bound_right;
1131 lower_bound_left = BELong(*((ULONG *)lower_bound));
1132 lower_bound_right = BEWord(*((UWORD *)(lower_bound + 4)));
1133 upper_bound_left = BELong(*((ULONG *)upper_bound));
1134 upper_bound_right = BEWord(*((UWORD *)(upper_bound + 4)));
1136 range = FindMulticastRange(unit, lower_bound_left, lower_bound_right,
1137 upper_bound_left, upper_bound_right, base);
1139 if(range != NULL)
1141 if(--range->add_count == 0)
1143 Disable();
1144 Remove((APTR)range);
1145 Enable();
1146 FreeMem(range, sizeof(struct AddressRange));
1148 if(--unit->range_count == 0)
1150 unit->rx_filter_cmd &= ~EL3CMD_SETRXFILTERF_MCAST;
1151 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1152 unit->rx_filter_cmd);
1157 return range != NULL;
1162 /****i* etherlink3.device/FindMulticastRange *******************************
1164 * NAME
1165 * FindMulticastRange -- .
1167 * SYNOPSIS
1168 * range = FindMulticastRange(unit, lower_bound_left,
1169 * lower_bound_right, upper_bound_left, upper_bound_right)
1171 * struct AddressRange *FindMulticastRange(struct DevUnit *, ULONG,
1172 * UWORD, ULONG, UWORD);
1174 ****************************************************************************
1178 static struct AddressRange *FindMulticastRange(struct DevUnit *unit,
1179 ULONG lower_bound_left, UWORD lower_bound_right, ULONG upper_bound_left,
1180 UWORD upper_bound_right, struct DevBase *base)
1182 struct AddressRange *range, *tail;
1183 BOOL found = FALSE;
1185 range = (APTR)unit->multicast_ranges.mlh_Head;
1186 tail = (APTR)&unit->multicast_ranges.mlh_Tail;
1188 while((range != tail) && !found)
1190 if((lower_bound_left == range->lower_bound_left) &&
1191 (lower_bound_right == range->lower_bound_right) &&
1192 (upper_bound_left == range->upper_bound_left) &&
1193 (upper_bound_right == range->upper_bound_right))
1194 found = TRUE;
1195 else
1196 range = (APTR)range->node.mln_Succ;
1199 if(!found)
1200 range = NULL;
1202 return range;
1207 /****i* etherlink3.device/FindTypeStats ************************************
1209 * NAME
1210 * FindTypeStats -- .
1212 * SYNOPSIS
1213 * stats = FindTypeStats(unit, list,
1214 * packet_type)
1216 * struct TypeStats *FindTypeStats(struct DevUnit *, struct MinList *,
1217 * ULONG);
1219 ****************************************************************************
1223 struct TypeStats *FindTypeStats(struct DevUnit *unit, struct MinList *list,
1224 ULONG packet_type, struct DevBase *base)
1226 struct TypeStats *stats, *tail;
1227 BOOL found = FALSE;
1229 stats = (APTR)list->mlh_Head;
1230 tail = (APTR)&list->mlh_Tail;
1232 while(stats != tail && !found)
1234 if(stats->packet_type == packet_type)
1235 found = TRUE;
1236 else
1237 stats = (APTR)stats->node.mln_Succ;
1240 if(!found)
1241 stats = NULL;
1243 return stats;
1248 /****i* etherlink3.device/FlushUnit ****************************************
1250 * NAME
1251 * FlushUnit -- .
1253 * SYNOPSIS
1254 * FlushUnit(unit, last_queue, error)
1256 * VOID FlushUnit(struct DevUnit *, UBYTE, BYTE);
1258 ****************************************************************************
1260 * Includes alternative implementations because of ambiguities in SANA-II
1261 * documentation.
1265 VOID FlushUnit(struct DevUnit *unit, UBYTE last_queue, BYTE error,
1266 struct DevBase *base)
1268 struct IORequest *request;
1269 UBYTE i;
1270 struct Opener *opener, *tail;
1272 /* Abort queued requests */
1274 for(i = 0; i <= last_queue; i++)
1276 while((request = (APTR)GetMsg(unit->request_ports[i])) != NULL)
1278 request->io_Error = IOERR_ABORTED;
1279 ReplyMsg((APTR)request);
1283 #if 1
1284 opener = (APTR)unit->openers.mlh_Head;
1285 tail = (APTR)&unit->openers.mlh_Tail;
1287 /* Flush every opener's read queue */
1289 while(opener != tail)
1291 while((request = (APTR)GetMsg(&opener->read_port)) != NULL)
1293 request->io_Error = error;
1294 ReplyMsg((APTR)request);
1296 opener = (APTR)opener->node.mln_Succ;
1299 #else
1300 opener = request->ios2_BufferManagement;
1301 while((request = (APTR)GetMsg(&opener->read_port)) != NULL)
1303 request->io_Error = IOERR_ABORTED;
1304 ReplyMsg((APTR)request);
1306 #endif
1308 /* Return */
1310 return;
1315 /****i* etherlink3.device/StatusInt ****************************************
1317 * NAME
1318 * StatusInt
1320 * SYNOPSIS
1321 * finished = StatusInt(unit, int_code)
1323 * BOOL StatusInt(struct DevUnit *, APTR);
1325 ****************************************************************************
1327 * int_code is really in A5, but GCC 2.95.3 doesn't seem able to handle that.
1328 * Since we don't use this parameter, we can lie.
1332 BOOL StatusInt(REG(a1, struct DevUnit *unit), REG(a6, APTR int_code))
1334 struct DevBase *base;
1335 UWORD ints;
1337 base = unit->device;
1338 ints = unit->LEWordIn(unit->card, EL3REG_STATUS);
1340 if((ints & EL3INTF_ANY) != 0)
1342 /* Handle interrupts */
1344 if((ints & EL3INTF_UPDONE) != 0)
1346 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1347 EL3CMD_ACKINT | EL3INTF_UPDONE);
1348 Cause(&unit->rx_int);
1350 if((ints & EL3INTF_DOWNDONE) != 0)
1352 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1353 EL3CMD_ACKINT | EL3INTF_DOWNDONE);
1354 Cause(&unit->tx_end_int);
1356 if((ints & EL3INTF_UPDATESTATS) != 0)
1357 UpdateStats(unit, base);
1358 if((ints & EL3INTF_RXCOMPLETE) != 0)
1360 #ifndef __MORPHOS__
1361 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1362 EL3CMD_SETINTMASK | (unit->int_mask & ~EL3INTF_RXCOMPLETE));
1363 #endif
1364 Cause(&unit->rx_int);
1366 if((ints & EL3INTF_TXAVAIL) != 0)
1368 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1369 EL3CMD_ACKINT | EL3INTF_TXAVAIL);
1370 Cause(&unit->tx_int);
1372 if((ints & EL3INTF_TXCOMPLETE) != 0)
1373 TxError(unit, base);
1375 /* Acknowledge interrupt request */
1377 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1378 EL3CMD_ACKINT | EL3INTF_ANY);
1381 return FALSE;
1386 /****i* etherlink3.device/RXInt ********************************************
1388 * NAME
1389 * RXInt
1391 * SYNOPSIS
1392 * RXInt(unit, int_code)
1394 * VOID RXInt(struct DevUnit *, APTR);
1396 ****************************************************************************
1400 static VOID RXInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code))
1402 UWORD rx_status, packet_size;
1403 struct DevBase *base;
1404 BOOL is_orphan, accepted;
1405 ULONG packet_type;
1406 UBYTE *buffer;
1407 struct IOSana2Req *request, *request_tail;
1408 struct Opener *opener, *opener_tail;
1409 struct TypeStats *tracker;
1411 base = unit->device;
1412 buffer = unit->rx_buffer;
1414 while(((rx_status = unit->LEWordIn(unit->card, EL3REG_RXSTATUS))
1415 & EL3REG_RXSTATUSF_INCOMPLETE) == 0)
1417 if((rx_status & EL3REG_RXSTATUSF_ERROR) == 0)
1419 /* Read packet header */
1421 is_orphan = TRUE;
1422 packet_size = rx_status & EL3REG_RXSTATUS_SIZEMASK;
1423 unit->LongsIn(unit->card, EL3REG_DATA0, (ULONG *)buffer,
1424 ETH_HEADERSIZE + 3 >> 2);
1426 if(AddressFilter(unit, buffer + ETH_PACKET_DEST, base))
1428 packet_type = BEWord(*((UWORD *)(buffer + ETH_PACKET_TYPE)));
1430 opener = (APTR)unit->openers.mlh_Head;
1431 opener_tail = (APTR)&unit->openers.mlh_Tail;
1433 /* Offer packet to every opener */
1435 while(opener != opener_tail)
1437 request = (APTR)opener->read_port.mp_MsgList.lh_Head;
1438 request_tail = (APTR)&opener->read_port.mp_MsgList.lh_Tail;
1439 accepted = FALSE;
1441 /* Offer packet to each request until it's accepted */
1443 while((request != request_tail) && !accepted)
1445 if(request->ios2_PacketType == packet_type
1446 || request->ios2_PacketType <= ETH_MTU
1447 && packet_type <= ETH_MTU)
1449 CopyPacket(unit, request, packet_size, packet_type,
1450 buffer, !is_orphan, base);
1451 accepted = TRUE;
1453 request =
1454 (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
1457 if(accepted)
1458 is_orphan = FALSE;
1459 opener = (APTR)opener->node.mln_Succ;
1462 /* If packet was unwanted, give it to S2_READORPHAN request */
1464 if(is_orphan)
1466 unit->stats.UnknownTypesReceived++;
1467 if(!IsMsgPortEmpty(unit->request_ports[ADOPT_QUEUE]))
1469 CopyPacket(unit,
1470 (APTR)unit->request_ports[ADOPT_QUEUE]->
1471 mp_MsgList.lh_Head, packet_size, packet_type, buffer,
1472 FALSE, base);
1476 /* Update remaining statistics */
1478 tracker =
1479 FindTypeStats(unit, &unit->type_trackers, packet_type, base);
1480 if(tracker != NULL)
1482 tracker->stats.PacketsReceived++;
1483 tracker->stats.BytesReceived += packet_size;
1487 else
1489 unit->stats.BadData++;
1490 ReportEvents(unit, S2EVENT_ERROR | S2EVENT_HARDWARE | S2EVENT_RX,
1491 base);
1494 /* Discard packet */
1496 Disable(); /* Needed? */
1497 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_RXDISCARD);
1498 while((unit->LEWordIn(unit->card, EL3REG_STATUS) &
1499 EL3REG_STATUSF_CMDINPROGRESS) != 0);
1500 Enable();
1503 /* Return */
1505 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1506 EL3CMD_SETINTMASK | unit->int_mask);
1507 return;
1512 /****i* etherlink3.device/CopyPacket ***************************************
1514 * NAME
1515 * CopyPacket
1517 * SYNOPSIS
1518 * CopyPacket(unit, request, packet_size, packet_type,
1519 * buffer, all_read)
1521 * VOID CopyPacket(struct DevUnit *, struct IOSana2Req *, UWORD, UWORD,
1522 * UBYTE *, BOOL);
1524 ****************************************************************************
1528 static VOID CopyPacket(struct DevUnit *unit, struct IOSana2Req *request,
1529 UWORD packet_size, UWORD packet_type, UBYTE *buffer, BOOL all_read,
1530 struct DevBase *base)
1532 struct Opener *opener;
1533 BOOL filtered = FALSE;
1535 /* Set multicast and broadcast flags */
1537 request->ios2_Req.io_Flags &= ~(SANA2IOF_BCAST | SANA2IOF_MCAST);
1538 if((*((ULONG *)(buffer + ETH_PACKET_DEST)) == 0xffffffff) &&
1539 (*((UWORD *)(buffer + ETH_PACKET_DEST + 4)) == 0xffff))
1540 request->ios2_Req.io_Flags |= SANA2IOF_BCAST;
1541 else if((buffer[ETH_PACKET_DEST] & 0x1) != 0)
1542 request->ios2_Req.io_Flags |= SANA2IOF_MCAST;
1544 /* Set source and destination addresses and packet type */
1546 CopyMem(buffer + ETH_PACKET_SOURCE, request->ios2_SrcAddr,
1547 ETH_ADDRESSSIZE);
1548 CopyMem(buffer + ETH_PACKET_DEST, request->ios2_DstAddr,
1549 ETH_ADDRESSSIZE);
1550 request->ios2_PacketType = packet_type;
1552 /* Read rest of packet (PIO mode only) */
1554 if(!all_read)
1556 unit->LongsIn(unit->card, EL3REG_DATA0,
1557 (ULONG *)(buffer + ((ETH_PACKET_DATA + 3) & ~0x3)),
1558 (packet_size - ETH_PACKET_DATA + 1) >> 2);
1561 /* Adjust for cooked packet request */
1563 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1565 packet_size -= ETH_PACKET_DATA;
1566 buffer += ETH_PACKET_DATA;
1568 #ifdef USE_HACKS
1569 else
1570 packet_size += 4; /* Needed for Shapeshifter & Fusion */
1571 #endif
1572 request->ios2_DataLength = packet_size;
1574 /* Filter packet */
1576 opener = request->ios2_BufferManagement;
1577 if((request->ios2_Req.io_Command == CMD_READ) &&
1578 (opener->filter_hook != NULL))
1579 if(!CallHookPkt(opener->filter_hook, request, buffer))
1580 filtered = TRUE;
1582 if(!filtered)
1584 /* Copy packet into opener's buffer and reply packet */
1586 if(!opener->rx_function(request->ios2_Data, buffer, packet_size))
1588 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
1589 request->ios2_WireError = S2WERR_BUFF_ERROR;
1590 ReportEvents(unit,
1591 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF | S2EVENT_RX,
1592 base);
1594 Remove((APTR)request);
1595 ReplyMsg((APTR)request);
1598 return;
1603 /****i* etherlink3.device/AddressFilter ************************************
1605 * NAME
1606 * AddressFilter
1608 * SYNOPSIS
1609 * accept = AddressFilter(unit, address)
1611 * BOOL AddressFilter(struct DevUnit *, UBYTE *);
1613 ****************************************************************************
1617 static BOOL AddressFilter(struct DevUnit *unit, UBYTE *address,
1618 struct DevBase *base)
1620 struct AddressRange *range, *tail;
1621 BOOL accept = TRUE;
1622 ULONG address_left;
1623 UWORD address_right;
1625 /* Check whether address is unicast/broadcast or multicast */
1627 address_left = BELong(*((ULONG *)address));
1628 address_right = BEWord(*((UWORD *)(address + 4)));
1630 if((address_left & 0x01000000) != 0 &&
1631 !(address_left == 0xffffffff && address_right == 0xffff))
1633 /* Check if this multicast address is wanted */
1635 range = (APTR)unit->multicast_ranges.mlh_Head;
1636 tail = (APTR)&unit->multicast_ranges.mlh_Tail;
1637 accept = FALSE;
1639 while((range != tail) && !accept)
1641 if((address_left > range->lower_bound_left ||
1642 address_left == range->lower_bound_left &&
1643 address_right >= range->lower_bound_right) &&
1644 (address_left < range->upper_bound_left ||
1645 address_left == range->upper_bound_left &&
1646 address_right <= range->upper_bound_right))
1647 accept = TRUE;
1648 range = (APTR)range->node.mln_Succ;
1651 if(!accept)
1652 unit->special_stats[S2SS_ETHERNET_BADMULTICAST & 0xffff]++;
1655 return accept;
1660 /****i* etherlink3.device/TXInt ********************************************
1662 * NAME
1663 * TXInt
1665 * SYNOPSIS
1666 * TXInt(unit)
1668 * VOID TXInt(struct DevUnit *);
1670 ****************************************************************************
1674 static VOID TXInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code))
1676 UWORD packet_size, data_size, send_size;
1677 struct DevBase *base;
1678 struct IOSana2Req *request;
1679 BOOL proceed = TRUE;
1680 struct Opener *opener;
1681 ULONG *buffer, wire_error;
1682 UBYTE *(*dma_tx_function)(REG(a0, APTR));
1683 BYTE error;
1684 struct MsgPort *port;
1685 struct TypeStats *tracker;
1687 base = unit->device;
1688 port = unit->request_ports[WRITE_QUEUE];
1690 while(proceed && (!IsMsgPortEmpty(port)))
1692 error = 0;
1694 request = (APTR)port->mp_MsgList.lh_Head;
1695 data_size = packet_size = request->ios2_DataLength;
1697 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1698 packet_size += ETH_PACKET_DATA;
1700 if(unit->LEWordIn(unit->card, EL3REG_TXSPACE)
1701 > EL3_PREAMBLESIZE + packet_size)
1703 /* Write packet preamble */
1705 unit->LELongOut(unit->card, EL3REG_DATA0, packet_size);
1707 /* Write packet header */
1709 send_size = (packet_size + 3) & ~0x3;
1710 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1712 unit->LongOut(unit->card, EL3REG_DATA0,
1713 *((ULONG *)request->ios2_DstAddr));
1714 unit->WordOut(unit->card, EL3REG_DATA0,
1715 *((UWORD *)(request->ios2_DstAddr + 4)));
1716 unit->WordOut(unit->card, EL3REG_DATA0,
1717 *((UWORD *)unit->address));
1718 unit->LongOut(unit->card, EL3REG_DATA0,
1719 *((ULONG *)(unit->address + 2)));
1720 unit->BEWordOut(unit->card, EL3REG_DATA0,
1721 request->ios2_PacketType);
1722 send_size -= ETH_HEADERSIZE;
1725 /* Get packet data */
1727 opener = (APTR)request->ios2_BufferManagement;
1728 dma_tx_function = opener->dma_tx_function;
1729 if(dma_tx_function != NULL)
1730 buffer = (ULONG *)dma_tx_function(request->ios2_Data);
1731 else
1732 buffer = NULL;
1734 if(buffer == NULL)
1736 buffer = (ULONG *)unit->tx_buffer;
1737 if(!opener->tx_function(buffer, request->ios2_Data, data_size))
1739 error = S2ERR_NO_RESOURCES;
1740 wire_error = S2WERR_BUFF_ERROR;
1741 ReportEvents(unit,
1742 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF
1743 | S2EVENT_TX, base);
1747 /* Write packet data */
1749 if(error == 0)
1751 unit->LongsOut(unit->card, EL3REG_DATA0, buffer,
1752 send_size >> 2);
1753 buffer += (send_size >> 2);
1754 if((send_size & 0x3) != 0)
1755 unit->WordOut(unit->card, EL3REG_DATA0, *((UWORD *)buffer));
1758 /* Reply packet */
1760 request->ios2_Req.io_Error = error;
1761 request->ios2_WireError = wire_error;
1762 Remove((APTR)request);
1763 ReplyMsg((APTR)request);
1765 /* Update statistics */
1767 if(error == 0)
1769 tracker = FindTypeStats(unit, &unit->type_trackers,
1770 request->ios2_PacketType, base);
1771 if(tracker != NULL)
1773 tracker->stats.PacketsSent++;
1774 tracker->stats.BytesSent += packet_size;
1778 else
1779 proceed = FALSE;
1782 if(proceed)
1783 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
1784 else
1786 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SETTXTHRESH
1787 | ((EL3_PREAMBLESIZE + packet_size) >> unit->size_shift));
1788 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_IGNORE;
1791 return;
1796 /****i* etherlink3.device/TxError ******************************************
1798 * NAME
1799 * TxError
1801 * SYNOPSIS
1802 * TxError(unit)
1804 * VOID TxError(struct DevUnit *);
1806 ****************************************************************************
1810 static VOID TxError(struct DevUnit *unit, struct DevBase *base)
1812 UPINT window1_offset;
1813 UBYTE tx_status, flags = 0;
1815 window1_offset = unit->window1_offset;
1817 /* Gather all errors */
1819 while(((tx_status =
1820 unit->ByteIn(unit->card, window1_offset + EL3REG_TXSTATUS))
1821 & EL3REG_TXSTATUSF_COMPLETE) != 0)
1823 flags |= tx_status;
1824 unit->ByteOut(unit->card, window1_offset + EL3REG_TXSTATUS, 0);
1827 /* Restart transmitter if necessary */
1829 if((flags & EL3REG_TXSTATUSF_JABBER) != 0)
1831 Disable();
1832 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_TXRESET);
1833 while((unit->LEWordIn(unit->card, EL3REG_STATUS) &
1834 EL3REG_STATUSF_CMDINPROGRESS) != 0);
1835 Enable();
1838 if((flags & (EL3REG_TXSTATUSF_JABBER | EL3REG_TXSTATUSF_OVERFLOW
1839 | EL3REG_TXSTATUSF_RECLAIMERROR)) != 0)
1840 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_TXENABLE);
1842 /* Report the error(s) */
1844 ReportEvents(unit, S2EVENT_ERROR | S2EVENT_HARDWARE | S2EVENT_TX, base);
1846 return;
1851 /****i* etherlink3.device/UpdateStats **************************************
1853 * NAME
1854 * UpdateStats
1856 * SYNOPSIS
1857 * UpdateStats(unit)
1859 * VOID UpdateStats(struct DevUnit *);
1861 ****************************************************************************
1865 VOID UpdateStats(struct DevUnit *unit, struct DevBase *base)
1867 UBYTE frame_counts_upper;
1868 UWORD generation, old_window;
1870 generation = unit->generation;
1872 old_window =
1873 unit->LEWordIn(unit->card, EL3REG_STATUS) >> EL3REG_STATUSB_WINDOW;
1874 if(generation < VORTEX_GEN)
1875 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STATSDISABLE);
1877 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 6);
1878 unit->ByteIn(unit->card, EL3REG_CARRIERLOST);
1879 unit->ByteIn(unit->card, EL3REG_SQEERRORS);
1880 unit->ByteIn(unit->card, EL3REG_MULTIPLECOLLISIONS);
1881 unit->ByteIn(unit->card, EL3REG_SINGLECOLLISIONS);
1882 unit->ByteIn(unit->card, EL3REG_LATECOLLISIONS);
1883 unit->stats.Overruns += unit->ByteIn(unit->card, EL3REG_RXOVERRUNS);
1884 unit->stats.PacketsSent += unit->ByteIn(unit->card, EL3REG_TXFRAMESOK);
1885 unit->stats.PacketsReceived +=
1886 unit->ByteIn(unit->card, EL3REG_RXFRAMESOK);
1887 unit->special_stats[S2SS_ETHERNET_RETRIES & 0xffff] +=
1888 unit->ByteIn(unit->card, EL3REG_FRAMESDEFERRED);
1889 unit->LEWordIn(unit->card, EL3REG_RXBYTESOK);
1890 unit->LEWordIn(unit->card, EL3REG_TXBYTESOK);
1891 if(generation >= VORTEX_GEN)
1893 frame_counts_upper = unit->ByteIn(unit->card, EL3REG_FRAMESOKUPPER);
1894 unit->stats.PacketsReceived += (frame_counts_upper & 0x3) << 8;
1895 unit->stats.PacketsSent += (frame_counts_upper & 0x30) << 4;
1896 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_SELECTWINDOW | 4);
1897 unit->ByteIn(unit->card, EL3REG_BADSSD);
1898 if(generation >= BOOMERANG_GEN)
1899 unit->ByteIn(unit->card, EL3REG_BYTESOKUPPER);
1902 if(generation < VORTEX_GEN)
1903 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_STATSENABLE);
1904 unit->LEWordOut(unit->card, EL3REG_COMMAND,
1905 EL3CMD_SELECTWINDOW | old_window);
1906 return;
1911 /****i* etherlink3.device/DMARXInt *****************************************
1913 * NAME
1914 * DMARXInt
1916 * SYNOPSIS
1917 * DMARXInt(unit, int_code)
1919 * VOID DMARXInt(struct DevUnit *, APTR);
1921 ****************************************************************************
1925 static VOID DMARXInt(REG(a1, struct DevUnit *unit),
1926 REG(a5, APTR int_code))
1928 UWORD packet_size;
1929 struct DevBase *base;
1930 BOOL is_orphan, accepted;
1931 ULONG rx_status, packet_type, *upd, *fragment, dma_size;
1932 UBYTE *buffer;
1933 struct IOSana2Req *request, *request_tail;
1934 struct Opener *opener, *opener_tail;
1935 struct TypeStats *tracker;
1937 base = unit->device;
1938 upd = unit->next_upd;
1940 dma_size = UPD_SIZE * RX_SLOT_COUNT;
1941 CachePostDMA(unit->upds, &dma_size, 0);
1943 while(((rx_status = LELong(upd[EL3UPD_STATUS]))
1944 & EL3UPD_STATUSF_COMPLETE) != 0)
1946 fragment = upd + EL3UPD_FIRSTFRAG;
1947 buffer = (UBYTE *)(UPINT)LELong(fragment[EL3FRAG_ADDR]);
1949 dma_size = ETH_MAXPACKETSIZE;
1950 CachePostDMA(buffer, &dma_size, 0);
1952 if((rx_status & EL3UPD_STATUSF_ERROR) == 0)
1954 is_orphan = TRUE;
1955 packet_size = rx_status & EL3UPD_STATUSF_SIZE;
1957 if(AddressFilter(unit, buffer + ETH_PACKET_DEST, base))
1959 packet_type = BEWord(*((UWORD *)(buffer + ETH_PACKET_TYPE)));
1961 opener = (APTR)unit->openers.mlh_Head;
1962 opener_tail = (APTR)&unit->openers.mlh_Tail;
1964 /* Offer packet to every opener */
1966 while(opener != opener_tail)
1968 request = (APTR)opener->read_port.mp_MsgList.lh_Head;
1969 request_tail = (APTR)&opener->read_port.mp_MsgList.lh_Tail;
1970 accepted = FALSE;
1972 /* Offer packet to each request until it's accepted */
1974 while((request != request_tail) && !accepted)
1976 if(request->ios2_PacketType == packet_type
1977 || request->ios2_PacketType <= ETH_MTU
1978 && packet_type <= ETH_MTU)
1980 CopyPacket(unit, request, packet_size, packet_type,
1981 buffer, TRUE, base);
1982 accepted = TRUE;
1984 request =
1985 (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
1988 if(accepted)
1989 is_orphan = FALSE;
1990 opener = (APTR)opener->node.mln_Succ;
1993 /* If packet was unwanted, give it to S2_READORPHAN request */
1995 if(is_orphan)
1997 unit->stats.UnknownTypesReceived++;
1998 if(!IsMsgPortEmpty(unit->request_ports[ADOPT_QUEUE]))
2000 CopyPacket(unit,
2001 (APTR)unit->request_ports[ADOPT_QUEUE]->
2002 mp_MsgList.lh_Head, packet_size, packet_type, buffer,
2003 TRUE, base);
2007 /* Update remaining statistics */
2009 tracker =
2010 FindTypeStats(unit, &unit->type_trackers, packet_type, base);
2011 if(tracker != NULL)
2013 tracker->stats.PacketsReceived++;
2014 tracker->stats.BytesReceived += packet_size;
2018 else
2020 unit->stats.BadData++;
2021 ReportEvents(unit, S2EVENT_ERROR | S2EVENT_HARDWARE | S2EVENT_RX,
2022 base);
2025 upd[EL3UPD_STATUS] = 0;
2027 dma_size = ETH_MAXPACKETSIZE;
2028 CachePreDMA(buffer, &dma_size, 0);
2030 upd = (ULONG *)(UPINT)LELong(upd[EL3UPD_NEXT]);
2033 dma_size = UPD_SIZE * RX_SLOT_COUNT;
2034 CachePreDMA(unit->upds, &dma_size, 0);
2036 /* Return */
2038 unit->next_upd = upd;
2039 unit->LEWordOut(unit->card, EL3REG_COMMAND, EL3CMD_UPUNSTALL);
2040 #if 1 /* ??? */
2041 unit->LEWordOut(unit->card, EL3REG_COMMAND,
2042 EL3CMD_SETINTMASK | unit->int_mask);
2043 #endif
2044 return;
2049 /****i* etherlink3.device/DMATXInt *****************************************
2051 * NAME
2052 * DMATXInt
2054 * SYNOPSIS
2055 * DMATXInt(unit, int_code)
2057 * VOID DMATXInt(struct DevUnit *, APTR);
2059 ****************************************************************************
2063 static VOID DMATXInt(REG(a1, struct DevUnit *unit),
2064 REG(a5, APTR int_code))
2066 UWORD packet_size, data_size, slot, new_slot, *p, *q, i;
2067 struct DevBase *base;
2068 struct IOSana2Req *request;
2069 BOOL proceed = TRUE;
2070 struct Opener *opener;
2071 ULONG wire_error, *dpd, *last_dpd, *next_dpd, *fragment, dma_size;
2072 UBYTE *(*dma_tx_function)(REG(a0, APTR));
2073 BYTE error;
2074 UBYTE *buffer;
2075 struct MsgPort *port;
2077 base = unit->device;
2078 port = unit->request_ports[WRITE_QUEUE];
2080 while(proceed && (!IsMsgPortEmpty(port)))
2082 slot = unit->tx_in_slot;
2083 new_slot = (slot + 1) % TX_SLOT_COUNT;
2085 if(new_slot != unit->tx_out_slot
2086 && (unit->flags & UNITF_TXBUFFERINUSE) == 0)
2088 error = 0;
2090 request = (APTR)port->mp_MsgList.lh_Head;
2091 data_size = packet_size = request->ios2_DataLength;
2093 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
2094 packet_size += ETH_HEADERSIZE;
2095 dpd = unit->dpds + ((DPD_SIZE / sizeof(ULONG)) * slot);
2097 /* Write packet preamble */
2099 Remove((APTR)request);
2100 unit->tx_requests[slot] = request;
2101 dpd[EL3DPD_NEXT] = (ULONG)0;
2102 dpd[EL3DPD_HEADER] =
2103 MakeLELong(EL3DPD_HEADERF_DLINT | packet_size);
2104 fragment = dpd + EL3DPD_FIRSTFRAG;
2106 /* Write packet header */
2108 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
2110 buffer = unit->headers + ETH_HEADERSIZE * slot;
2111 fragment[EL3FRAG_ADDR] = MakeLELong((ULONG)(UPINT)buffer);
2112 fragment[EL3FRAG_LEN] = MakeLELong(ETH_HEADERSIZE);
2114 p = (UWORD *)buffer;
2115 for(i = 0, q = (UWORD *)request->ios2_DstAddr;
2116 i < ETH_ADDRESSSIZE / 2; i++)
2117 *p++ = *q++;
2118 for(i = 0, q = (UWORD *)unit->address;
2119 i < ETH_ADDRESSSIZE / 2; i++)
2120 *p++ = *q++;
2121 *p++ = MakeBEWord(request->ios2_PacketType);
2122 buffer = (UBYTE *)p;
2124 dma_size = ETH_HEADERSIZE;
2125 CachePreDMA(buffer, &dma_size, DMA_ReadFromRAM);
2126 fragment += EL3_FRAGLEN;
2129 /* Get packet data */
2131 opener = (APTR)request->ios2_BufferManagement;
2132 dma_tx_function = opener->dma_tx_function;
2133 if(dma_tx_function != NULL)
2134 buffer = dma_tx_function(request->ios2_Data);
2135 else
2136 buffer = NULL;
2138 if(buffer == NULL)
2140 buffer = unit->tx_buffer;
2141 if(opener->tx_function(buffer, request->ios2_Data, data_size))
2142 unit->flags |= UNITF_TXBUFFERINUSE;
2143 else
2145 error = S2ERR_NO_RESOURCES;
2146 wire_error = S2WERR_BUFF_ERROR;
2147 ReportEvents(unit,
2148 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF
2149 | S2EVENT_TX, base);
2153 /* Fill in rest of descriptor for packet transmission */
2155 if(error == 0)
2157 fragment[EL3FRAG_ADDR] = MakeLELong((ULONG)(UPINT)buffer);
2158 fragment[EL3FRAG_LEN] =
2159 MakeLELong(EL3FRAG_LENF_LAST | data_size);
2161 /* Pass packet to adapter */
2163 dma_size = data_size;
2164 CachePreDMA(buffer, &dma_size, DMA_ReadFromRAM);
2166 last_dpd = (ULONG *)(UPINT)
2167 unit->LELongIn(unit->card, EL3REG_DOWNLIST);
2168 if(last_dpd != NULL)
2170 unit->LEWordOut(unit->card, EL3REG_COMMAND,
2171 EL3CMD_DOWNSTALL);
2172 while((unit->LEWordIn(unit->card, EL3REG_STATUS)
2173 & EL3REG_STATUSF_CMDINPROGRESS) != 0);
2174 while((next_dpd =
2175 (ULONG *)(UPINT)LELong(last_dpd[EL3DPD_NEXT])) != NULL)
2176 last_dpd = next_dpd;
2177 last_dpd[EL3DPD_NEXT] = MakeLELong((ULONG)(UPINT)dpd);
2178 dma_size = DPD_SIZE * TX_SLOT_COUNT;
2179 CachePreDMA(unit->dpds, &dma_size, 0);
2180 unit->LEWordOut(unit->card, EL3REG_COMMAND,
2181 EL3CMD_DOWNUNSTALL);
2183 else
2185 dma_size = DPD_SIZE * TX_SLOT_COUNT;
2186 CachePreDMA(unit->dpds, &dma_size, 0);
2187 unit->LELongOut(unit->card, EL3REG_DOWNLIST,
2188 (ULONG)(UPINT)dpd);
2191 unit->tx_in_slot = new_slot;
2193 else
2195 /* Reply failed request */
2197 request->ios2_Req.io_Error = error;
2198 request->ios2_WireError = wire_error;
2199 ReplyMsg((APTR)request);
2202 else
2203 proceed = FALSE;
2206 if(proceed)
2207 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
2208 else
2209 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_IGNORE;
2211 return;
2216 /****i* etherlink3.device/DMATXEndInt **************************************
2218 * NAME
2219 * DMATXEndInt
2221 * SYNOPSIS
2222 * DMATXEndInt(unit, int_code)
2224 * VOID DMATXEndInt(struct DevUnit *, APTR);
2226 * NOTES
2227 * I think it's safe to assume that there will always be at least one
2228 * completed packet whenever this interrupt is called.
2230 ****************************************************************************
2234 static VOID DMATXEndInt(REG(a1, struct DevUnit *unit),
2235 REG(a5, APTR int_code))
2237 UWORD data_size, packet_size, new_out_slot, i;
2238 UBYTE *buffer;
2239 struct DevBase *base;
2240 struct IOSana2Req *request;
2241 ULONG *dpd, *fragment, dma_size;
2242 struct TypeStats *tracker;
2244 /* Find out which packets have completed */
2246 base = unit->device;
2247 dpd = (ULONG *)(UPINT)unit->LELongIn(unit->card, EL3REG_DOWNLIST);
2248 if(dpd != NULL)
2249 new_out_slot = (dpd - unit->dpds) / (sizeof(ULONG) * DPD_SIZE);
2250 else
2251 new_out_slot = unit->tx_in_slot;
2253 /* Retire sent packets */
2255 for(i = unit->tx_out_slot; i != new_out_slot;
2256 i = (i + 1) % TX_SLOT_COUNT)
2258 /* Mark end of DMA */
2260 request = unit->tx_requests[i];
2261 data_size = packet_size = request->ios2_DataLength;
2262 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
2263 packet_size += ETH_HEADERSIZE;
2265 dpd = unit->dpds + ((DPD_SIZE / sizeof(ULONG)) * i);
2266 fragment = dpd + EL3DPD_FIRSTFRAG;
2267 dma_size = DPD_SIZE * TX_SLOT_COUNT;
2268 CachePostDMA(unit->dpds, &dma_size, 0);
2270 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
2272 buffer = (APTR)(UPINT)LELong(fragment[EL3FRAG_ADDR]);
2273 dma_size = ETH_HEADERSIZE;
2274 CachePostDMA(buffer, &dma_size, DMA_ReadFromRAM);
2275 fragment += EL3_FRAGLEN;
2278 buffer = (APTR)(UPINT)LELong(fragment[EL3FRAG_ADDR]);
2279 dma_size = data_size;
2280 CachePostDMA(buffer, &dma_size, DMA_ReadFromRAM);
2282 /* Check if unit's TX buffer is now free */
2284 if(buffer == unit->tx_buffer)
2285 unit->flags &= ~UNITF_TXBUFFERINUSE;
2287 /* Update statistics */
2289 tracker = FindTypeStats(unit, &unit->type_trackers,
2290 request->ios2_PacketType, base);
2291 if(tracker != NULL)
2293 tracker->stats.PacketsSent++;
2294 tracker->stats.BytesSent += packet_size;
2297 /* Reply request */
2299 request->ios2_Req.io_Error = 0;
2300 ReplyMsg((APTR)request);
2303 unit->tx_out_slot = new_out_slot;
2305 /* Restart downloads if they had stopped */
2307 if(unit->request_ports[WRITE_QUEUE]->mp_Flags == PA_IGNORE)
2308 Cause(&unit->tx_int);
2310 return;
2315 /****i* etherlink3.device/ReportEvents *************************************
2317 * NAME
2318 * ReportEvents -- .
2320 * SYNOPSIS
2321 * ReportEvents(unit, events)
2323 * VOID ReportEvents(struct DevUnit *, ULONG);
2325 * INPUTS
2326 * unit - A unit of this device.
2327 * events - A mask of events to report.
2329 * RESULT
2330 * None.
2332 ****************************************************************************
2336 static VOID ReportEvents(struct DevUnit *unit, ULONG events,
2337 struct DevBase *base)
2339 struct IOSana2Req *request, *tail, *next_request;
2340 struct List *list;
2342 list = &unit->request_ports[EVENT_QUEUE]->mp_MsgList;
2343 next_request = (APTR)list->lh_Head;
2344 tail = (APTR)&list->lh_Tail;
2346 Disable();
2347 while(next_request != tail)
2349 request = next_request;
2350 next_request = (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
2352 if((request->ios2_WireError & events) != 0)
2354 request->ios2_WireError = events;
2355 Remove((APTR)request);
2356 ReplyMsg((APTR)request);
2359 Enable();
2361 return;
2366 /****i* etherlink3.device/UnitTask *****************************************
2368 * NAME
2369 * UnitTask
2371 * SYNOPSIS
2372 * UnitTask()
2374 * VOID UnitTask();
2376 * FUNCTION
2378 * INPUTS
2380 * RESULT
2382 * EXAMPLE
2384 * NOTES
2386 * BUGS
2388 * SEE ALSO
2390 ****************************************************************************
2394 static VOID UnitTask()
2396 struct Task *task;
2397 struct IORequest *request;
2398 struct DevUnit *unit;
2399 struct DevBase *base;
2400 struct MsgPort *general_port;
2401 ULONG signals, wait_signals, card_removed_signal, card_inserted_signal,
2402 general_port_signal;
2404 /* Get parameters */
2406 task = AbsExecBase->ThisTask;
2407 unit = task->tc_UserData;
2408 base = unit->device;
2410 /* Activate general request port */
2412 general_port = unit->request_ports[GENERAL_QUEUE];
2413 general_port->mp_SigTask = task;
2414 general_port->mp_SigBit = AllocSignal(-1);
2415 general_port_signal = 1 << general_port->mp_SigBit;
2416 general_port->mp_Flags = PA_SIGNAL;
2418 /* Allocate a signal for notification of card removal */
2420 card_removed_signal = unit->card_removed_signal = 1 << AllocSignal(-1);
2421 card_inserted_signal = unit->card_inserted_signal = 1 << AllocSignal(-1);
2422 wait_signals = (1 << general_port->mp_SigBit) | card_removed_signal
2423 | card_inserted_signal;
2425 /* Tell ourselves to check port for old messages */
2427 Signal(task, general_port_signal);
2429 /* Infinite loop to service requests and signals */
2431 while(TRUE)
2433 signals = Wait(wait_signals);
2435 if((signals & card_inserted_signal) != 0)
2437 if(unit->insertion_function(unit->card, base))
2439 unit->flags |= UNITF_HAVEADAPTER;
2440 if((unit->flags & UNITF_CONFIGURED) != 0)
2441 ConfigureAdapter(unit, base);
2445 if((signals & card_removed_signal) != 0)
2447 unit->removal_function(unit->card, base);
2448 GoOffline(unit, base);
2451 if((signals & general_port_signal) != 0)
2453 while((request = (APTR)GetMsg(general_port)) != NULL)
2455 /* Service the request as soon as the unit is free */
2457 ObtainSemaphore(&unit->access_lock);
2458 ServiceRequest((APTR)request, base);
2466 /****i* etherlink3.device/ReadEEPROM ***************************************
2468 * NAME
2469 * ReadEEPROM -- Read a location on card's EEPROM.
2471 * SYNOPSIS
2472 * value = ReadEEPROM(unit, index)
2474 * UWORD ReadEEPROM(struct DevUnit *, UWORD);
2476 * INPUTS
2477 * unit - Device unit.
2478 * index - Offset within EEPROM.
2480 * RESULT
2481 * value - Contents of specified EEPROM location.
2483 ****************************************************************************
2487 static UWORD ReadEEPROM(struct DevUnit *unit, UWORD index,
2488 struct DevBase *base)
2490 unit->LEWordOut(unit->card, EL3REG_EEPROMCMD, EL3ECMD_READ | index);
2491 while((unit->LEWordIn(unit->card, EL3REG_EEPROMCMD) &
2492 EL3REG_EEPROMCMDF_BUSY) != 0);
2494 return unit->LEWordIn(unit->card, EL3REG_EEPROMDATA);
2499 /****i* etherlink3.device/ReadMII ******************************************
2501 * NAME
2502 * ReadMII -- Read a register on an MII PHY.
2504 * SYNOPSIS
2505 * success = ReadMII(unit, phy_no, reg_no, value)
2507 * BOOL ReadMII(struct DevUnit *, UWORD, UWORD, UWORD *);
2509 * FUNCTION
2510 * Reads a register on an MII PHY. Window 4 must be selected before
2511 * calling this function.
2513 * INPUTS
2514 * unit - Device unit.
2515 * phy_no - .
2516 * reg_no - .
2517 * value - Pointer to location to store value read from MII register.
2519 * RESULT
2520 * success - Success indicator.
2522 ****************************************************************************
2526 static BOOL ReadMII(struct DevUnit *unit, UWORD phy_no, UWORD reg_no,
2527 UWORD *value, struct DevBase *base)
2529 BOOL success = TRUE;
2531 WriteMIIBits(unit, 0xffffffff, 32, base);
2532 WriteMIIBits(unit, 0x6, 4, base);
2533 WriteMIIBits(unit, phy_no, 5, base);
2534 WriteMIIBits(unit, reg_no, 5, base);
2535 ReadMIIBit(unit, base);
2536 if(ReadMIIBit(unit, base))
2537 success = FALSE;
2538 *value = ReadMIIBits(unit, 16, base);
2539 ReadMIIBit(unit, base);
2541 return success;
2546 /****i* etherlink3.device/WriteMII *****************************************
2548 * NAME
2549 * WriteMII -- Write to a register on an MII PHY.
2551 * SYNOPSIS
2552 * WriteMII(unit, phy_no, reg_no, value)
2554 * VOID WriteMII(struct DevUnit *, UWORD, UWORD, UWORD);
2556 * INPUTS
2557 * unit - Device unit.
2558 * phy_no - .
2559 * reg_no - .
2560 * value - value to write to MII register.
2562 * RESULT
2563 * None.
2565 ****************************************************************************
2569 #if 0
2570 static VOID WriteMII(struct DevUnit *unit, UWORD phy_no, UWORD reg_no,
2571 UWORD value, struct DevBase *base)
2573 WriteMIIBits(unit, 0xffffffff, 32, base);
2574 WriteMIIBits(unit, 0x5, 4, base);
2575 WriteMIIBits(unit, phy_no, 5, base);
2576 WriteMIIBits(unit, reg_no, 5, base);
2577 WriteMIIBit(unit, TRUE, base);
2578 WriteMIIBits(unit, value, 16, base);
2579 DoMIIZCycle(unit, base);
2581 return;
2583 #endif
2587 /****i* etherlink3.device/ReadMIIBits **************************************
2589 * NAME
2590 * ReadMIIBits
2592 * SYNOPSIS
2593 * value = ReadMIIBits(unit, count)
2595 * ULONG ReadMIIBits(struct DevUnit *, UBYTE);
2597 ****************************************************************************
2601 static ULONG ReadMIIBits(struct DevUnit *unit, UBYTE count,
2602 struct DevBase *base)
2604 UBYTE i;
2605 ULONG value = 0;
2607 /* LEWordOut(io_addr, LEWordIn(reg) & ~EL3REG_PHYMGMTF_WRITE);*/
2608 for(i = 0; i < count; i++)
2610 value <<= 1;
2611 if(ReadMIIBit(unit, base))
2612 value |= 1;
2613 unit->LEWordIn(unit->card, EL3REG_PHYMGMT);
2615 /* ReadMIIBit(unit, base)? value |= 1;*/
2617 return value;
2621 /****i* etherlink3.device/WriteMIIBits *************************************
2623 * NAME
2624 * WriteMIIBits
2626 * SYNOPSIS
2627 * WriteMIIBits(unit, value, count)
2629 * VOID WriteMIIBits(struct DevUnit *, ULONG, UBYTE);
2631 ****************************************************************************
2635 static VOID WriteMIIBits(struct DevUnit *unit, ULONG value, UBYTE count,
2636 struct DevBase *base)
2638 ULONG mask;
2640 for(mask = 1 << (count - 1); mask != 0; mask >>= 1)
2641 WriteMIIBit(unit, (value & mask) != 0, base);
2643 return;
2648 /****i* etherlink3.device/ReadMIIBit ***************************************
2650 * NAME
2651 * ReadMIIBit
2653 * SYNOPSIS
2654 * is_one = ReadMIIBit(unit)
2656 * BOOL ReadMIIBit(struct DevUnit *);
2658 ****************************************************************************
2662 static BOOL ReadMIIBit(struct DevUnit *unit, struct DevBase *base)
2664 BOOL is_one;
2666 unit->LEWordOut(unit->card, EL3REG_PHYMGMT, 0);
2667 BusyMicroDelay(1, base);
2668 unit->LEWordOut(unit->card, EL3REG_PHYMGMT, EL3REG_PHYMGMTF_CLK);
2669 BusyMicroDelay(1, base);
2670 is_one =
2671 (unit->LEWordIn(unit->card, EL3REG_PHYMGMT) & EL3REG_PHYMGMTF_DATA)
2672 != 0;
2673 BusyMicroDelay(1, base);
2675 return is_one;
2680 /****i* etherlink3.device/WriteMIIBit **************************************
2682 * NAME
2683 * WriteMIIBit
2685 * SYNOPSIS
2686 * WriteMIIBit(unit, is_one)
2688 * VOID WriteMIIBit(struct DevUnit *, BOOL);
2690 ****************************************************************************
2694 static VOID WriteMIIBit(struct DevUnit *unit, BOOL is_one,
2695 struct DevBase *base)
2697 unit->LEWordOut(unit->card, EL3REG_PHYMGMT, EL3REG_PHYMGMTF_WRITE);
2698 BusyMicroDelay(1, base);
2699 if(is_one)
2700 unit->LEWordOut(unit->card, EL3REG_PHYMGMT,
2701 EL3REG_PHYMGMTF_WRITE | EL3REG_PHYMGMTF_CLK |
2702 EL3REG_PHYMGMTF_DATA);
2703 else
2704 unit->LEWordOut(unit->card, EL3REG_PHYMGMT,
2705 EL3REG_PHYMGMTF_WRITE | EL3REG_PHYMGMTF_CLK);
2706 BusyMicroDelay(1, base);
2708 return;
2713 /****i* etherlink3.device/DoMIIZCycle **************************************
2715 * NAME
2716 * DoMIIZCycle
2718 * SYNOPSIS
2719 * DoMIIZCycle(unit)
2721 * VOID DoMIIZCycle(struct DevUnit *);
2723 ****************************************************************************
2727 #if 0
2728 static VOID DoMIIZCycle(struct DevUnit *unit, struct DevBase *base)
2730 unit->LEWordOut(unit->card, EL3REG_PHYMGMT,
2731 unit->LEWordIn(unit->card, EL3REG_PHYMGMT) & ~EL3REG_PHYMGMTF_CLK);
2732 BusyMicroDelay(1, base);
2733 unit->LEWordOut(unit->card, EL3REG_PHYMGMT, EL3REG_PHYMGMTF_CLK);
2734 BusyMicroDelay(1, base);
2736 return;
2738 #endif
2742 #if 0
2743 static VOID BusyMicroDelay(ULONG micros, struct DevBase *base)
2745 struct timeval time, end_time;
2747 GetSysTime(&end_time);
2748 time.tv_secs = 0;
2749 time.tv_micro = micros;
2750 AddTime(&end_time, &time);
2752 while(CmpTime(&end_time, &time) < 0)
2753 GetSysTime(&time);
2755 return;
2759 #else
2760 static VOID BusyMicroDelay(ULONG micros, struct DevBase *base)
2762 struct EClockVal time, end_time;
2763 ULONG rate;
2765 rate = ReadEClock(&time);
2766 end_time.ev_hi = time.ev_hi;
2767 end_time.ev_lo = time.ev_lo + (micros * rate + 1) / 1000000;
2768 if(end_time.ev_lo < time.ev_lo)
2769 end_time.ev_hi++;
2771 while(time.ev_lo < end_time.ev_lo || time.ev_hi < end_time.ev_hi)
2772 ReadEClock(&time);
2774 return;
2776 #endif