Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / networks / rhine / unit.c
blob707e24924959813098327e51159975c9911e87cc
1 /*
3 Copyright (C) 2001-2012 Neil Cafferkey
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 MA 02111-1307, USA.
23 #include <exec/memory.h>
24 #include <exec/execbase.h>
25 #include <exec/errors.h>
27 #include <proto/exec.h>
28 #include <proto/alib.h>
29 #include <proto/utility.h>
30 #include <proto/timer.h>
32 #include "device.h"
33 #include "rhine.h"
35 #include "unit_protos.h"
36 #include "request_protos.h"
37 #include "timer_protos.h"
40 #define TASK_PRIORITY 0
41 #define STACK_SIZE 4096
42 #define INT_MASK 0xffff
43 #define TX_DESC_SIZE (RH_DESCSIZE * 2 + ETH_HEADERSIZE + 2)
45 #ifndef AbsExecBase
46 #define AbsExecBase sys_base
47 #endif
49 VOID DeinitialiseAdapter(struct DevUnit *unit, struct DevBase *base);
50 static struct AddressRange *FindMulticastRange(struct DevUnit *unit,
51 ULONG lower_bound_left, UWORD lower_bound_right, ULONG upper_bound_left,
52 UWORD upper_bound_right, struct DevBase *base);
53 static VOID SetMulticast(struct DevUnit *unit, struct DevBase *base);
54 static BOOL StatusInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code));
55 static VOID RXInt(REG(a1, struct DevUnit *unit), REG(a6, APTR int_code));
56 static VOID DistributeRXPacket(struct DevUnit *unit, const UBYTE *packet,
57 UWORD packet_size, struct DevBase *base);
58 static VOID CopyPacket(struct DevUnit *unit, struct IOSana2Req *request,
59 UWORD packet_size, UWORD packet_type, const UBYTE *buffer,
60 struct DevBase *base);
61 static BOOL AddressFilter(struct DevUnit *unit, UBYTE *address,
62 struct DevBase *base);
63 static VOID TXInt(REG(a1, struct DevUnit *unit), REG(a6, APTR int_code));
64 static VOID TXEndInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code));
65 static VOID RetireTXSlot(struct DevUnit *unit, UWORD slot,
66 struct DevBase *base);
67 static VOID ResetHandler(REG(a1, struct DevUnit *unit),
68 REG(a6, APTR int_code));
69 static VOID ReportEvents(struct DevUnit *unit, ULONG events,
70 struct DevBase *base);
71 static VOID UnitTask(struct ExecBase *sys_base);
72 UWORD ReadMII(struct DevUnit *unit, UWORD phy_no, UWORD reg_no,
73 struct DevBase *base);
75 #if !defined(__AROS__)
76 static const UBYTE broadcast_address[] =
77 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
78 #endif
80 #ifdef __AROS__
81 #undef AddTask
82 #define AddTask(task, initial_pc, final_pc) \
83 ({ \
84 struct TagItem _task_tags[] = \
85 {{TASKTAG_ARG1, (IPTR)SysBase}, {TAG_END, 0}}; \
86 NewAddTask(task, initial_pc, final_pc, _task_tags); \
88 #endif
92 /****i* rhine.device/CreateUnit ********************************************
94 * NAME
95 * CreateUnit -- Create a unit.
97 * SYNOPSIS
98 * unit = CreateUnit(index, io_base, id, card,
99 * io_tags, bus)
101 * struct DevUnit *CreateUnit(ULONG, APTR, UWORD, APTR,
102 * struct TagItem *, UWORD);
104 * FUNCTION
105 * Creates a new unit.
107 ****************************************************************************
111 struct DevUnit *CreateUnit(ULONG index, APTR card,
112 struct TagItem *io_tags, UWORD bus, struct DevBase *base)
114 BOOL success = TRUE;
115 struct DevUnit *unit;
116 struct Task *task;
117 struct MsgPort *port;
118 UWORD i;
119 ULONG *desc, desc_p, buffer_p, dma_size;
120 APTR stack;
122 unit = AllocMem(sizeof(struct DevUnit), MEMF_CLEAR | MEMF_PUBLIC);
123 if(unit == NULL)
124 success = FALSE;
126 if(success)
128 /* Initialise lists etc. */
130 NewList((APTR)&unit->openers);
131 NewList((APTR)&unit->type_trackers);
132 NewList((APTR)&unit->multicast_ranges);
134 unit->index = index;
135 unit->device = base;
136 unit->card = card;
137 unit->bus = bus;
139 /* Store I/O hooks */
141 unit->ByteIn =
142 (APTR)GetTagData(IOTAG_ByteIn, (UPINT)NULL, io_tags);
143 unit->ByteOut =
144 (APTR)GetTagData(IOTAG_ByteOut, (UPINT)NULL, io_tags);
145 unit->LEWordIn =
146 (APTR)GetTagData(IOTAG_LEWordIn, (UPINT)NULL, io_tags);
147 unit->LELongIn =
148 (APTR)GetTagData(IOTAG_LELongIn, (UPINT)NULL, io_tags);
149 unit->LEWordOut =
150 (APTR)GetTagData(IOTAG_LEWordOut, (UPINT)NULL, io_tags);
151 unit->LELongOut =
152 (APTR)GetTagData(IOTAG_LELongOut, (UPINT)NULL, io_tags);
153 unit->AllocDMAMem =
154 (APTR)GetTagData(IOTAG_AllocDMAMem, (UPINT)NULL, io_tags);
155 unit->FreeDMAMem =
156 (APTR)GetTagData(IOTAG_FreeDMAMem, (UPINT)NULL, io_tags);
157 if(unit->ByteIn == NULL
158 || unit->ByteOut == NULL
159 || unit->LEWordIn == NULL
160 || unit->LELongIn == NULL
161 || unit->LEWordOut == NULL
162 || unit->LELongOut == NULL
163 || unit->AllocDMAMem == NULL
164 || unit->FreeDMAMem == NULL)
165 success = FALSE;
168 if(success)
170 InitSemaphore(&unit->access_lock);
172 /* Create the message ports for queuing requests */
174 for(i = 0; i < REQUEST_QUEUE_COUNT; i++)
176 unit->request_ports[i] = port = AllocMem(sizeof(struct MsgPort),
177 MEMF_PUBLIC | MEMF_CLEAR);
178 if(port == NULL)
179 success = FALSE;
181 if(success)
183 NewList(&port->mp_MsgList);
184 port->mp_Flags = PA_IGNORE;
187 if(success)
188 unit->request_ports[WRITE_QUEUE]->mp_SigTask = &unit->tx_int;
191 if(success)
193 /* Allocate TX descriptors */
195 desc = unit->AllocDMAMem(unit->card, TX_DESC_SIZE * TX_SLOT_COUNT, 16);
196 if(desc == NULL)
197 success = FALSE;
200 if(success)
202 /* Fill arrays of virtual and physical addresses of TX descriptors */
204 dma_size = TX_DESC_SIZE * TX_SLOT_COUNT;
205 desc_p = (ULONG)(UPINT)CachePreDMA(desc, &dma_size, 0);
206 if(dma_size != TX_DESC_SIZE * TX_SLOT_COUNT)
207 success = FALSE;
208 CachePostDMA(desc, &dma_size, 0);
210 for(i = 0; i < TX_SLOT_COUNT; i++)
212 unit->tx_descs[i] = desc;
213 desc += TX_DESC_SIZE / sizeof(ULONG);
214 unit->tx_descs_p[i] = desc_p;
215 desc_p += TX_DESC_SIZE;
219 if(success)
221 /* Allocate RX descriptors */
223 desc = unit->AllocDMAMem(unit->card, RH_DESCSIZE * RX_SLOT_COUNT, 16);
224 if(desc == NULL)
225 success = FALSE;
228 if(success)
230 /* Fill arrays of virtual and physical addresses of TX descriptors */
232 dma_size = RH_DESCSIZE * RX_SLOT_COUNT;
233 desc_p = (ULONG)(UPINT)CachePreDMA(desc, &dma_size, 0);
234 if(dma_size != RH_DESCSIZE * RX_SLOT_COUNT)
235 success = FALSE;
236 CachePostDMA(desc, &dma_size, 0);
238 for(i = 0; i < RX_SLOT_COUNT; i++)
240 unit->rx_descs[i] = desc;
241 desc += RH_DESCSIZE / sizeof(ULONG);
242 unit->rx_descs_p[i] = desc_p;
243 desc_p += RH_DESCSIZE;
246 /* Allocate packet buffers */
248 unit->tx_buffer = unit->AllocDMAMem(unit->card, FRAME_BUFFER_SIZE, 4);
249 if(unit->tx_buffer == NULL)
250 success = FALSE;
252 for(i = 0; i < RX_SLOT_COUNT; i++)
254 unit->rx_buffers[i] = unit->AllocDMAMem(unit->card,
255 FRAME_BUFFER_SIZE, 4);
256 if(unit->rx_buffers[i] == NULL)
257 success = FALSE;
260 unit->tx_requests = AllocVec(sizeof(APTR) * TX_SLOT_COUNT,
261 MEMF_PUBLIC);
262 if(unit->tx_requests == NULL)
263 success = FALSE;
266 if(success)
268 /* Construct RX ring */
270 for(i = 0; i < RX_SLOT_COUNT; i++)
272 desc = unit->rx_descs[i];
273 desc[RH_DESC_RXSTATUS] = MakeLELong(RH_DESC_RXSTATUSF_INUSE);
274 desc[RH_DESC_RXCONTROL] = MakeLELong(FRAME_BUFFER_SIZE);
275 dma_size = FRAME_BUFFER_SIZE;
276 buffer_p =
277 (ULONG)(UPINT)CachePreDMA(unit->rx_buffers[i], &dma_size, 0);
278 if(dma_size != FRAME_BUFFER_SIZE)
279 success = FALSE;
280 desc[RH_DESC_DATA] = MakeLELong(buffer_p);
281 desc[RH_DESC_NEXT] =
282 MakeLELong(unit->rx_descs_p[(i + 1) % RX_SLOT_COUNT]);
283 desc += RH_DESCSIZE / sizeof(ULONG);
285 dma_size = RH_DESCSIZE * RX_SLOT_COUNT;
286 CachePreDMA(unit->rx_descs, &dma_size, 0);
289 if(success)
291 /* Initialise network adapter hardware */
293 success = InitialiseAdapter(unit, FALSE, base);
294 unit->flags |= UNITF_HAVEADAPTER;
297 if(success)
299 /* Record maximum speed in BPS */
301 unit->speed = 100000000;
303 /* Initialise interrupts */
305 unit->status_int.is_Code = (APTR)StatusInt;
306 unit->status_int.is_Data = unit;
308 unit->rx_int.is_Node.ln_Name =
309 base->device.dd_Library.lib_Node.ln_Name;
310 unit->rx_int.is_Code = (APTR)RXInt;
311 unit->rx_int.is_Data = unit;
313 unit->tx_int.is_Node.ln_Name =
314 base->device.dd_Library.lib_Node.ln_Name;
315 unit->tx_int.is_Code = (APTR)TXInt;
316 unit->tx_int.is_Data = unit;
318 unit->tx_end_int.is_Node.ln_Name =
319 base->device.dd_Library.lib_Node.ln_Name;
320 unit->tx_end_int.is_Code = (APTR)TXEndInt;
321 unit->tx_end_int.is_Data = unit;
323 unit->reset_handler.is_Node.ln_Name =
324 base->device.dd_Library.lib_Node.ln_Name;
325 unit->reset_handler.is_Code = (APTR)ResetHandler;
326 unit->reset_handler.is_Data = unit;
328 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
330 /* Create a new task */
332 unit->task = task =
333 AllocMem(sizeof(struct Task), MEMF_PUBLIC | MEMF_CLEAR);
334 if(task == NULL)
335 success = FALSE;
338 if(success)
340 stack = AllocMem(STACK_SIZE, MEMF_PUBLIC);
341 if(stack == NULL)
342 success = FALSE;
345 if(success)
347 /* Initialise and start task */
349 task->tc_Node.ln_Type = NT_TASK;
350 task->tc_Node.ln_Pri = TASK_PRIORITY;
351 task->tc_Node.ln_Name = base->device.dd_Library.lib_Node.ln_Name;
352 task->tc_SPUpper = stack + STACK_SIZE;
353 task->tc_SPLower = stack;
354 task->tc_SPReg = stack + STACK_SIZE;
355 NewList(&task->tc_MemEntry);
357 if(AddTask(task, UnitTask, NULL) == NULL)
358 success = FALSE;
361 if(success)
363 /* Send the unit to the new task */
365 task->tc_UserData = unit;
368 if(!success)
370 DeleteUnit(unit, base);
371 unit = NULL;
374 return unit;
379 /****i* rhine.device/DeleteUnit ********************************************
381 * NAME
382 * DeleteUnit -- Delete a unit.
384 * SYNOPSIS
385 * DeleteUnit(unit)
387 * VOID DeleteUnit(struct DevUnit *);
389 * FUNCTION
390 * Deletes a unit.
392 * INPUTS
393 * unit - Device unit (may be NULL).
395 * RESULT
396 * None.
398 ****************************************************************************
402 VOID DeleteUnit(struct DevUnit *unit, struct DevBase *base)
404 UBYTE i;
405 struct Task *task;
407 if(unit != NULL)
409 task = unit->task;
410 if(task != NULL)
412 if(task->tc_UserData != NULL)
414 RemTask(task);
415 FreeMem(task->tc_SPLower, STACK_SIZE);
417 FreeMem(task, sizeof(struct Task));
420 for(i = 0; i < REQUEST_QUEUE_COUNT; i++)
422 if(unit->request_ports[i] != NULL)
423 FreeMem(unit->request_ports[i], sizeof(struct MsgPort));
426 if((unit->flags & UNITF_ONLINE) != 0) /* Needed! */
427 GoOffline(unit, base);
429 if((unit->flags & UNITF_HAVEADAPTER) != 0)
430 DeinitialiseAdapter(unit, base);
432 for(i = 0; i < RX_SLOT_COUNT; i++)
433 unit->FreeDMAMem(unit->card, unit->rx_buffers[i]);
434 unit->FreeDMAMem(unit->card, unit->tx_buffer);
435 unit->FreeDMAMem(unit->card, unit->rx_descs[0]);
436 unit->FreeDMAMem(unit->card, unit->tx_descs[0]);
438 FreeVec(unit->tx_requests);
440 FreeMem(unit, sizeof(struct DevUnit));
443 return;
448 /****i* rhine.device/InitialiseAdapter *************************************
450 * NAME
451 * InitialiseAdapter
453 * SYNOPSIS
454 * success = InitialiseAdapter(unit, reinsertion)
456 * BOOL InitialiseAdapter(struct DevUnit *, BOOL);
458 * FUNCTION
460 * INPUTS
461 * unit
462 * reinsertion
464 * RESULT
465 * success - Success indicator.
467 ****************************************************************************
471 BOOL InitialiseAdapter(struct DevUnit *unit, BOOL reinsertion,
472 struct DevBase *base)
474 BOOL success = TRUE;
475 UBYTE *p, eeprom_reg;
476 UWORD i;
478 /* Reload data from EEPROM */
480 eeprom_reg = unit->ByteIn(unit->card, RH_REG_EEPROM);
481 unit->ByteOut(unit->card, RH_REG_EEPROM,
482 eeprom_reg | RH_REG_EEPROMF_LOAD);
484 BusyMicroDelay(1, base);
485 while((unit->ByteIn(unit->card, RH_REG_EEPROM) & RH_REG_EEPROMF_LOAD)
486 != 0);
488 /* Get default MAC address */
490 p = unit->default_address;
491 for(i = 0; i < ETH_ADDRESSSIZE; i++)
492 *p++ = unit->ByteIn(unit->card, RH_REG_ADDRESS + i);
494 /* Send reset command */
496 unit->ByteOut(unit->card, RH_REG_CONTROL + 1, RH_REG_CONTROL1F_RESET);
497 BusyMicroDelay(110, base);
498 while((unit->ByteIn(unit->card, RH_REG_CONTROL + 1)
499 & RH_REG_CONTROL1F_RESET) != 0);
501 /* Disable interrupts */
503 unit->LEWordOut(unit->card, RH_REG_INTSTATUS, INT_MASK);
504 unit->LEWordOut(unit->card, RH_REG_INTMASK, 0);
505 if(TRUE)
506 unit->LEWordOut(unit->card, RH_REG_MIIINTMASK, 0);
508 /* Configure MII */
510 unit->ByteOut(unit->card, RH_REG_MIICTRL,
511 unit->ByteIn(unit->card, RH_REG_MIICTRL) | RH_REG_MIICTRLF_AUTOPOLL);
513 if(TRUE)
514 unit->mii_phy_no = unit->ByteIn(unit->card, RH_REG_MIICONFIG)
515 & RH_REG_MIICONFIGF_PHYADDR;
516 else
517 unit->mii_phy_no = 1;
519 /* Return */
521 return success;
526 /****i* rhine.device/DeinitialiseAdapter ***********************************
528 * NAME
529 * DeinitialiseAdapter
531 * SYNOPSIS
532 * DeinitialiseAdapter(unit)
534 * VOID DeinitialiseAdapter(struct DevUnit *);
536 * FUNCTION
538 * INPUTS
539 * unit
541 * RESULT
542 * None.
544 ****************************************************************************
548 VOID DeinitialiseAdapter(struct DevUnit *unit, struct DevBase *base)
550 return;
555 /****i* rhine.device/ConfigureAdapter **************************************
557 * NAME
558 * ConfigureAdapter -- Set up card for transmission/reception.
560 * SYNOPSIS
561 * ConfigureAdapter(unit)
563 * VOID ConfigureAdapter(struct DevUnit *);
565 ****************************************************************************
569 VOID ConfigureAdapter(struct DevUnit *unit, struct DevBase *base)
571 const UBYTE *p;
572 UWORD i;
574 /* Set MAC address */
576 p = unit->address;
577 for(i = 0; i < ETH_ADDRESSSIZE; i++)
578 unit->ByteOut(unit->card, RH_REG_ADDRESS + i, *p++);
580 /* Set DMA rings */
582 unit->LELongOut(unit->card, RH_REG_TXLIST, unit->tx_descs_p[0]);
583 unit->LELongOut(unit->card, RH_REG_RXLIST, unit->rx_descs_p[0]);
585 /* Choose packet types to receive */
587 unit->LEWordOut(unit->card, RH_REG_PCIBUSCONFIG, 6);
588 unit->ByteOut(unit->card, RH_REG_RXCONFIG,
589 RH_REG_RXCONFIGF_BCAST | RH_REG_RXCONFIGF_MCAST);
591 /* Return */
593 return;
598 /****i* rhine.device/GoOnline **********************************************
600 * NAME
601 * GoOnline -- Enable transmission/reception.
603 * SYNOPSIS
604 * GoOnline(unit)
606 * VOID GoOnline(struct DevUnit *);
608 ****************************************************************************
612 VOID GoOnline(struct DevUnit *unit, struct DevBase *base)
614 /* Enable interrupts */
616 unit->flags |= UNITF_ONLINE;
617 unit->LEWordOut(unit->card, RH_REG_INTMASK, INT_MASK);
619 /* Enable frame transmission and reception */
621 unit->LEWordOut(unit->card, RH_REG_CONTROL, RH_REG_CONTROLF_TXENABLE
622 | RH_REG_CONTROLF_RXENABLE | RH_REG_CONTROLF_START);
624 /* Record start time and report Online event */
626 GetSysTime(&unit->stats.LastStart);
627 ReportEvents(unit, S2EVENT_ONLINE, base);
629 return;
634 /****i* rhine.device/GoOffline *********************************************
636 * NAME
637 * GoOffline -- Disable transmission/reception.
639 * SYNOPSIS
640 * GoOffline(unit)
642 * VOID GoOffline(struct DevUnit *);
644 * FUNCTION
646 * INPUTS
647 * unit
649 * RESULT
650 * None.
652 ****************************************************************************
656 VOID GoOffline(struct DevUnit *unit, struct DevBase *base)
658 unit->flags &= ~UNITF_ONLINE;
660 /* Flush pending read and write requests */
662 FlushUnit(unit, MGMT_QUEUE, S2ERR_OUTOFSERVICE, base);
664 /* Report Offline event and return */
666 ReportEvents(unit, S2EVENT_OFFLINE, base);
667 return;
672 /****i* rhine.device/AddMulticastRange *************************************
674 * NAME
675 * AddMulticastRange
677 * SYNOPSIS
678 * success = AddMulticastRange(unit, lower_bound, upper_bound)
680 * BOOL AddMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
682 ****************************************************************************
686 BOOL AddMulticastRange(struct DevUnit *unit, const UBYTE *lower_bound,
687 const UBYTE *upper_bound, struct DevBase *base)
689 struct AddressRange *range;
690 ULONG lower_bound_left, upper_bound_left;
691 UWORD lower_bound_right, upper_bound_right;
693 lower_bound_left = BELong(*((ULONG *)lower_bound));
694 lower_bound_right = BEWord(*((UWORD *)(lower_bound + 4)));
695 upper_bound_left = BELong(*((ULONG *)upper_bound));
696 upper_bound_right = BEWord(*((UWORD *)(upper_bound + 4)));
698 range = FindMulticastRange(unit, lower_bound_left, lower_bound_right,
699 upper_bound_left, upper_bound_right, base);
701 if(range != NULL)
702 range->add_count++;
703 else
705 range = AllocMem(sizeof(struct AddressRange), MEMF_PUBLIC);
706 if(range != NULL)
708 range->lower_bound_left = lower_bound_left;
709 range->lower_bound_right = lower_bound_right;
710 range->upper_bound_left = upper_bound_left;
711 range->upper_bound_right = upper_bound_right;
712 range->add_count = 1;
714 Disable();
715 AddTail((APTR)&unit->multicast_ranges, (APTR)range);
716 unit->range_count++;
717 SetMulticast(unit, base);
718 Enable();
722 return range != NULL;
727 /****i* rhine.device/RemMulticastRange *************************************
729 * NAME
730 * RemMulticastRange
732 * SYNOPSIS
733 * found = RemMulticastRange(unit, lower_bound, upper_bound)
735 * BOOL RemMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
737 ****************************************************************************
741 BOOL RemMulticastRange(struct DevUnit *unit, const UBYTE *lower_bound,
742 const UBYTE *upper_bound, struct DevBase *base)
744 struct AddressRange *range;
745 ULONG lower_bound_left, upper_bound_left;
746 UWORD lower_bound_right, upper_bound_right;
748 lower_bound_left = BELong(*((ULONG *)lower_bound));
749 lower_bound_right = BEWord(*((UWORD *)(lower_bound + 4)));
750 upper_bound_left = BELong(*((ULONG *)upper_bound));
751 upper_bound_right = BEWord(*((UWORD *)(upper_bound + 4)));
753 range = FindMulticastRange(unit, lower_bound_left, lower_bound_right,
754 upper_bound_left, upper_bound_right, base);
756 if(range != NULL)
758 if(--range->add_count == 0)
760 Disable();
761 Remove((APTR)range);
762 unit->range_count--;
763 SetMulticast(unit, base);
764 Enable();
765 FreeMem(range, sizeof(struct AddressRange));
769 return range != NULL;
774 /****i* rhine.device/FindMulticastRange ************************************
776 * NAME
777 * FindMulticastRange
779 * SYNOPSIS
780 * range = FindMulticastRange(unit, lower_bound_left,
781 * lower_bound_right, upper_bound_left, upper_bound_right)
783 * struct AddressRange *FindMulticastRange(struct DevUnit *, ULONG,
784 * UWORD, ULONG, UWORD);
786 ****************************************************************************
790 static struct AddressRange *FindMulticastRange(struct DevUnit *unit,
791 ULONG lower_bound_left, UWORD lower_bound_right, ULONG upper_bound_left,
792 UWORD upper_bound_right, struct DevBase *base)
794 struct AddressRange *range, *tail;
795 BOOL found = FALSE;
797 range = (APTR)unit->multicast_ranges.mlh_Head;
798 tail = (APTR)&unit->multicast_ranges.mlh_Tail;
800 while(range != tail && !found)
802 if(lower_bound_left == range->lower_bound_left &&
803 lower_bound_right == range->lower_bound_right &&
804 upper_bound_left == range->upper_bound_left &&
805 upper_bound_right == range->upper_bound_right)
806 found = TRUE;
807 else
808 range = (APTR)range->node.mln_Succ;
811 if(!found)
812 range = NULL;
814 return range;
819 /****i* rhine.device/SetMulticast ******************************************
821 * NAME
822 * SetMulticast
824 * SYNOPSIS
825 * SetMulticast(unit)
827 * VOID SetMulticast(struct DevUnit *);
829 ****************************************************************************
833 static VOID SetMulticast(struct DevUnit *unit, struct DevBase *base)
835 if(!IsListEmpty(&unit->multicast_ranges))
837 unit->LELongOut(unit->card, RH_REG_MCASTFILTER, 0xffffffff);
838 unit->LELongOut(unit->card, RH_REG_MCASTFILTER + 4, 0xffffffff);
840 else
842 unit->LELongOut(unit->card, RH_REG_MCASTFILTER, 0);
843 unit->LELongOut(unit->card, RH_REG_MCASTFILTER + 4, 0);
846 return;
851 /****i* rhine.device/FindTypeStats *****************************************
853 * NAME
854 * FindTypeStats
856 * SYNOPSIS
857 * stats = FindTypeStats(unit, list,
858 * packet_type)
860 * struct TypeStats *FindTypeStats(struct DevUnit *, struct MinList *,
861 * ULONG);
863 ****************************************************************************
867 struct TypeStats *FindTypeStats(struct DevUnit *unit, struct MinList *list,
868 ULONG packet_type, struct DevBase *base)
870 struct TypeStats *stats, *tail;
871 BOOL found = FALSE;
873 stats = (APTR)list->mlh_Head;
874 tail = (APTR)&list->mlh_Tail;
876 while(stats != tail && !found)
878 if(stats->packet_type == packet_type)
879 found = TRUE;
880 else
881 stats = (APTR)stats->node.mln_Succ;
884 if(!found)
885 stats = NULL;
887 return stats;
892 /****i* rhine.device/FlushUnit *********************************************
894 * NAME
895 * FlushUnit
897 * SYNOPSIS
898 * FlushUnit(unit, last_queue, error)
900 * VOID FlushUnit(struct DevUnit *, UBYTE, BYTE);
902 ****************************************************************************
906 VOID FlushUnit(struct DevUnit *unit, UBYTE last_queue, BYTE error,
907 struct DevBase *base)
909 struct IORequest *request;
910 UBYTE i;
911 struct Opener *opener, *tail;
913 /* Abort queued requests */
915 for(i = 0; i <= last_queue; i++)
917 while((request = (APTR)GetMsg(unit->request_ports[i])) != NULL)
919 request->io_Error = IOERR_ABORTED;
920 ReplyMsg((APTR)request);
924 #if 1
925 opener = (APTR)unit->openers.mlh_Head;
926 tail = (APTR)&unit->openers.mlh_Tail;
928 /* Flush every opener's read queues */
930 while(opener != tail)
932 while((request = (APTR)GetMsg(&opener->read_port)) != NULL)
934 request->io_Error = error;
935 ReplyMsg((APTR)request);
937 while((request = (APTR)GetMsg(&opener->mgmt_port)) != NULL)
939 request->io_Error = error;
940 ReplyMsg((APTR)request);
942 opener = (APTR)opener->node.mln_Succ;
945 #else
946 opener = request->ios2_BufferManagement;
947 while((request = (APTR)GetMsg(&opener->read_port)) != NULL)
949 request->io_Error = IOERR_ABORTED;
950 ReplyMsg((APTR)request);
952 while((request = (APTR)GetMsg(&opener->mgmt_port)) != NULL)
954 request->io_Error = IOERR_ABORTED;
955 ReplyMsg((APTR)request);
957 #endif
959 /* Return */
961 return;
966 /****i* rhine.device/StatusInt *********************************************
968 * NAME
969 * StatusInt
971 * SYNOPSIS
972 * finished = StatusInt(unit)
974 * BOOL StatusInt(struct DevUnit *);
976 * INPUTS
977 * unit - A unit of this device.
979 * RESULT
980 * finished - Always FALSE.
982 ****************************************************************************
986 static BOOL StatusInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code))
988 struct DevBase *base;
989 UWORD ints;
991 base = unit->device;
992 ints = unit->LEWordIn(unit->card, RH_REG_INTSTATUS);
994 if(ints != 0)
996 /* Acknowledge interrupts */
998 unit->LEWordOut(unit->card, RH_REG_INTSTATUS, ints);
1000 /* FIXME: Need IO-sync here for PPC etc.? */
1002 /* Handle interrupts */
1004 if((ints & (RH_INTF_TXERR | RH_INTF_TXOK)) != 0)
1005 Cause(&unit->tx_end_int);
1006 if((ints & (RH_INTF_RXERR | RH_INTF_RXOK)) != 0)
1007 Cause(&unit->rx_int);
1010 return FALSE;
1015 /****i* rhine.device/RXInt *************************************************
1017 * NAME
1018 * RXInt -- Soft interrupt for packet reception.
1020 * SYNOPSIS
1021 * RXInt(unit)
1023 * VOID RXInt(struct DevUnit *);
1025 * FUNCTION
1027 * INPUTS
1028 * unit - A unit of this device.
1030 * RESULT
1031 * None.
1033 ****************************************************************************
1037 static VOID RXInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code))
1039 UWORD slot, packet_size;
1040 struct DevBase *base;
1041 ULONG rx_status, *desc, dma_size;
1042 UBYTE *buffer;
1044 base = unit->device;
1045 slot = unit->rx_slot;
1046 desc = unit->rx_descs[slot];
1048 dma_size = TX_DESC_SIZE;
1049 CachePostDMA(unit->rx_descs, &dma_size, 0);
1050 while(((rx_status = LELong(desc[RH_DESC_RXSTATUS]))
1051 & RH_DESC_RXSTATUSF_INUSE) == 0)
1053 if((rx_status & RH_DESC_RXSTATUSF_OK) != 0)
1055 packet_size = ((rx_status & RH_DESC_RXSTATUSF_LENGTH)
1056 >> RH_DESC_RXSTATUSB_LENGTH) - ETH_CRCSIZE;
1057 buffer = unit->rx_buffers[slot];
1059 if(AddressFilter(unit, buffer + ETH_PACKET_DEST, base))
1061 unit->stats.PacketsReceived++;
1062 DistributeRXPacket(unit, buffer, packet_size, base);
1065 else
1067 unit->stats.BadData++;
1068 ReportEvents(unit, S2EVENT_ERROR | S2EVENT_HARDWARE | S2EVENT_RX,
1069 base);
1072 /* Mark descriptor as free for next time */
1074 desc[RH_DESC_RXSTATUS] = MakeLELong(RH_DESC_RXSTATUSF_INUSE);
1076 /* Get next descriptor */
1078 slot = (slot + 1) % RX_SLOT_COUNT;
1079 desc = unit->rx_descs[slot];
1082 /* Return */
1084 unit->rx_slot = slot;
1085 return;
1090 /****i* rhine.device/DistributeRXPacket ************************************
1092 * NAME
1093 * DistributeRXPacket -- Send a packet to all appropriate destinations.
1095 * SYNOPSIS
1096 * DistributeRXPacket(unit, frame)
1098 * VOID DistributeRXPacket(struct DevUnit *, UBYTE *);
1100 ****************************************************************************
1104 static VOID DistributeRXPacket(struct DevUnit *unit, const UBYTE *packet,
1105 UWORD packet_size, struct DevBase *base)
1107 BOOL is_orphan = TRUE, accepted;
1108 ULONG packet_type;
1109 struct IOSana2Req *request, *request_tail;
1110 struct Opener *opener, *opener_tail;
1111 struct TypeStats *tracker;
1113 /* Offer packet to every opener */
1115 opener = (APTR)unit->openers.mlh_Head;
1116 opener_tail = (APTR)&unit->openers.mlh_Tail;
1117 packet_type = BEWord(*((UWORD *)(packet + ETH_PACKET_TYPE)));
1119 while(opener != opener_tail)
1121 request = (APTR)opener->read_port.mp_MsgList.lh_Head;
1122 request_tail = (APTR)&opener->read_port.mp_MsgList.lh_Tail;
1123 accepted = FALSE;
1125 /* Offer packet to each request until it's accepted */
1127 while(request != request_tail && !accepted)
1129 if(request->ios2_PacketType == packet_type)
1131 CopyPacket(unit, request, packet_size, packet_type,
1132 packet, base);
1133 accepted = TRUE;
1135 request =
1136 (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
1139 if(accepted)
1140 is_orphan = FALSE;
1141 opener = (APTR)opener->node.mln_Succ;
1144 /* If packet was unwanted, give it to S2_READORPHAN request */
1146 if(is_orphan)
1148 unit->stats.UnknownTypesReceived++;
1149 if(!IsMsgPortEmpty(unit->request_ports[ADOPT_QUEUE]))
1151 CopyPacket(unit,
1152 (APTR)unit->request_ports[ADOPT_QUEUE]->mp_MsgList.lh_Head,
1153 packet_size, packet_type, packet, base);
1157 /* Update remaining statistics */
1159 if(packet_type <= ETH_MTU)
1160 packet_type = ETH_MTU;
1161 tracker =
1162 FindTypeStats(unit, &unit->type_trackers, packet_type, base);
1163 if(tracker != NULL)
1165 tracker->stats.PacketsReceived++;
1166 tracker->stats.BytesReceived += packet_size;
1169 return;
1174 /****i* rhine.device/CopyPacket ********************************************
1176 * NAME
1177 * CopyPacket -- Copy packet to client's buffer.
1179 * SYNOPSIS
1180 * CopyPacket(unit, request, packet_size, packet_type,
1181 * buffer)
1183 * VOID CopyPacket(struct DevUnit *, struct IOSana2Req *, UWORD, UWORD,
1184 * UBYTE *);
1186 ****************************************************************************
1190 static VOID CopyPacket(struct DevUnit *unit, struct IOSana2Req *request,
1191 UWORD packet_size, UWORD packet_type, const UBYTE *buffer,
1192 struct DevBase *base)
1194 struct Opener *opener;
1195 BOOL filtered = FALSE;
1197 /* Set multicast and broadcast flags */
1199 request->ios2_Req.io_Flags &= ~(SANA2IOF_BCAST | SANA2IOF_MCAST);
1200 if((*((ULONG *)(buffer + ETH_PACKET_DEST)) == 0xffffffff) &&
1201 (*((UWORD *)(buffer + ETH_PACKET_DEST + 4)) == 0xffff))
1202 request->ios2_Req.io_Flags |= SANA2IOF_BCAST;
1203 else if((buffer[ETH_PACKET_DEST] & 0x1) != 0)
1204 request->ios2_Req.io_Flags |= SANA2IOF_MCAST;
1206 /* Set source and destination addresses and packet type */
1208 CopyMem(buffer + ETH_PACKET_SOURCE, request->ios2_SrcAddr,
1209 ETH_ADDRESSSIZE);
1210 CopyMem(buffer + ETH_PACKET_DEST, request->ios2_DstAddr,
1211 ETH_ADDRESSSIZE);
1212 request->ios2_PacketType = packet_type;
1214 /* Adjust for cooked packet request */
1216 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1218 packet_size -= ETH_PACKET_DATA;
1219 buffer += ETH_PACKET_DATA;
1221 #ifdef USE_HACKS
1222 else
1223 packet_size += 4; /* Needed for Shapeshifter & Fusion */
1224 #endif
1225 request->ios2_DataLength = packet_size;
1227 /* Filter packet */
1229 opener = request->ios2_BufferManagement;
1230 if(request->ios2_Req.io_Command == CMD_READ &&
1231 opener->filter_hook != NULL)
1232 if(!CallHookPkt(opener->filter_hook, request, (APTR)buffer))
1233 filtered = TRUE;
1235 if(!filtered)
1237 /* Copy packet into opener's buffer and reply packet */
1239 if(!opener->rx_function(request->ios2_Data, (APTR)buffer,
1240 packet_size))
1242 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
1243 request->ios2_WireError = S2WERR_BUFF_ERROR;
1244 ReportEvents(unit,
1245 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF | S2EVENT_RX,
1246 base);
1248 Remove((APTR)request);
1249 ReplyMsg((APTR)request);
1252 return;
1257 /****i* rhine.device/AddressFilter *****************************************
1259 * NAME
1260 * AddressFilter -- Determine if an RX packet should be accepted.
1262 * SYNOPSIS
1263 * accept = AddressFilter(unit, address)
1265 * BOOL AddressFilter(struct DevUnit *, UBYTE *);
1267 ****************************************************************************
1271 static BOOL AddressFilter(struct DevUnit *unit, UBYTE *address,
1272 struct DevBase *base)
1274 struct AddressRange *range, *tail;
1275 BOOL accept = TRUE;
1276 ULONG address_left;
1277 UWORD address_right;
1279 /* Check whether address is unicast/broadcast or multicast */
1281 address_left = BELong(*((ULONG *)address));
1282 address_right = BEWord(*((UWORD *)(address + 4)));
1284 if(((address_left & 0x01000000) != 0) &&
1285 !((address_left == 0xffffffff) && (address_right == 0xffff)))
1287 /* Check if this multicast address is wanted */
1289 range = (APTR)unit->multicast_ranges.mlh_Head;
1290 tail = (APTR)&unit->multicast_ranges.mlh_Tail;
1291 accept = FALSE;
1293 while((range != tail) && !accept)
1295 if((address_left > range->lower_bound_left ||
1296 address_left == range->lower_bound_left &&
1297 address_right >= range->lower_bound_right) &&
1298 (address_left < range->upper_bound_left ||
1299 address_left == range->upper_bound_left &&
1300 address_right <= range->upper_bound_right))
1301 accept = TRUE;
1302 range = (APTR)range->node.mln_Succ;
1305 if(!accept)
1306 unit->special_stats[S2SS_ETHERNET_BADMULTICAST & 0xffff]++;
1309 return accept;
1314 /****i* rhine.device/TXInt *************************************************
1316 * NAME
1317 * TXInt -- Soft interrupt for packet transmission.
1319 * SYNOPSIS
1320 * TXInt(unit)
1322 * VOID TXInt(struct DevUnit *);
1324 * FUNCTION
1326 * INPUTS
1327 * unit - A unit of this device.
1329 * RESULT
1330 * None.
1332 ****************************************************************************
1336 static VOID TXInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code))
1338 struct DevBase *base;
1339 UWORD packet_size, data_size, slot, new_slot, *p, *q, i;
1340 struct IOSana2Req *request;
1341 BOOL proceed = TRUE;
1342 struct Opener *opener;
1343 ULONG wire_error, *desc, dma_size, desc_p, buffer_p, txcontrol_value;
1344 UBYTE *(*dma_tx_function)(REG(a0, APTR));
1345 BYTE error;
1346 UBYTE *buffer;
1347 struct MsgPort *port;
1349 base = unit->device;
1350 port = unit->request_ports[WRITE_QUEUE];
1352 while(proceed && !IsMsgPortEmpty(port))
1354 slot = unit->tx_in_slot;
1355 new_slot = (slot + 1) % TX_SLOT_COUNT;
1357 if(new_slot != unit->tx_out_slot
1358 && (unit->flags & UNITF_TXBUFFERINUSE) == 0)
1360 error = 0;
1362 /* Get request and DMA frame descriptor */
1364 request = (APTR)port->mp_MsgList.lh_Head;
1366 Remove((APTR)request);
1367 unit->tx_requests[slot] = request;
1368 desc = unit->tx_descs[slot];
1369 desc_p = unit->tx_descs_p[slot];
1371 data_size = packet_size = request->ios2_DataLength;
1372 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1373 packet_size += ETH_HEADERSIZE;
1374 if(packet_size < ETH_MINSIZE)
1375 packet_size = ETH_MINSIZE;
1377 /* Decide if one or two descriptors are needed, and generate
1378 Ethernet header if necessary */
1380 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1382 /* Use first descriptor for Ethernet header */
1384 buffer = (UBYTE *)desc + 2 * RH_DESCSIZE;
1385 buffer_p = desc_p + 2 * RH_DESCSIZE;
1387 desc[RH_DESC_TXCONTROL] =
1388 MakeLELong(RH_DESC_TXCONTROLF_FIRSTFRAG
1389 | RH_DESC_TXCONTROLF_CHAIN | ETH_HEADERSIZE);
1390 desc[RH_DESC_DATA] = MakeLELong(buffer_p);
1391 desc[RH_DESC_NEXT] = MakeLELong(desc_p + RH_DESCSIZE);
1393 /* Write Ethernet header */
1395 p = (UWORD *)buffer;
1396 for(i = 0, q = (UWORD *)request->ios2_DstAddr;
1397 i < ETH_ADDRESSSIZE / 2; i++)
1398 *p++ = *q++;
1399 for(i = 0, q = (UWORD *)unit->address;
1400 i < ETH_ADDRESSSIZE / 2; i++)
1401 *p++ = *q++;
1402 *p++ = MakeBEWord(request->ios2_PacketType);
1404 /* Use spare second descriptor for frame data */
1406 desc += RH_DESCSIZE / 4;
1407 desc_p += RH_DESCSIZE;
1409 txcontrol_value = RH_DESC_TXCONTROLF_INT
1410 | RH_DESC_TXCONTROLF_LASTFRAG
1411 | RH_DESC_TXCONTROLF_CHAIN
1412 | packet_size - ETH_HEADERSIZE;
1414 else
1416 txcontrol_value = RH_DESC_TXCONTROLF_INT
1417 | RH_DESC_TXCONTROLF_FIRSTFRAG | RH_DESC_TXCONTROLF_LASTFRAG
1418 | RH_DESC_TXCONTROLF_CHAIN
1419 | packet_size;
1422 /* Get packet data */
1424 opener = (APTR)request->ios2_BufferManagement;
1425 dma_tx_function = opener->dma_tx_function;
1426 if(dma_tx_function != NULL)
1427 buffer = dma_tx_function(request->ios2_Data);
1428 else
1429 buffer = NULL;
1431 if(buffer == NULL)
1433 buffer = unit->tx_buffer;
1434 if(opener->tx_function(buffer, request->ios2_Data,
1435 data_size))
1437 unit->flags |= UNITF_TXBUFFERINUSE;
1439 else
1441 error = S2ERR_NO_RESOURCES;
1442 wire_error = S2WERR_BUFF_ERROR;
1443 ReportEvents(unit,
1444 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF
1445 | S2EVENT_TX, base);
1448 unit->tx_buffers[slot] = buffer;
1450 /* Fill in descriptor for frame data */
1452 if(error == 0)
1454 dma_size = data_size;
1455 buffer_p = (ULONG)(UPINT)CachePreDMA(buffer, &dma_size,
1456 DMA_ReadFromRAM);
1457 desc[RH_DESC_TXCONTROL] = MakeLELong(txcontrol_value);
1458 desc[RH_DESC_DATA] = MakeLELong(buffer_p);
1459 desc[RH_DESC_NEXT] = MakeLELong(unit->tx_descs_p[new_slot]);
1461 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1462 desc -= RH_DESCSIZE / 4;
1464 desc[RH_DESC_TXSTATUS] = MakeLELong(RH_DESC_TXSTATUSF_INUSE);
1467 if(error == 0)
1469 /* Restart transmission if it had stopped */
1471 dma_size = TX_DESC_SIZE * TX_SLOT_COUNT;
1472 CachePreDMA(unit->tx_descs, &dma_size, 0);
1473 unit->ByteOut(unit->card, RH_REG_CONTROL,
1474 unit->ByteIn(unit->card, RH_REG_CONTROL)
1475 | RH_REG_CONTROLF_TXPOLL);
1477 /* FIXME: Need IO-sync here for PPC etc.? */
1479 unit->tx_in_slot = new_slot;
1481 else
1483 /* Return failed request */
1485 request->ios2_Req.io_Error = error;
1486 request->ios2_WireError = wire_error;
1487 ReplyMsg((APTR)request);
1490 else
1491 proceed = FALSE;
1494 if(proceed)
1495 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
1496 else
1497 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_IGNORE;
1499 return;
1504 /****i* rhine.device/TXEndInt **********************************************
1506 * NAME
1507 * TXEndInt -- Clean up after a frame has been sent.
1509 * SYNOPSIS
1510 * TXEndInt(unit, int_code)
1512 * VOID TXEndInt(struct DevUnit *, APTR);
1514 * INPUTS
1515 * unit - A unit of this device.
1516 * int_code - Unused.
1518 * RESULT
1519 * None.
1521 ****************************************************************************
1523 * It appears to be safe to assume that there will always be at least one
1524 * completed packet whenever this interrupt is called.
1528 static VOID TXEndInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code))
1530 UWORD data_size, i = 0;
1531 UBYTE *buffer;
1532 struct DevBase *base;
1533 ULONG *desc, dma_size;
1534 BOOL proceed = TRUE;
1536 /* Retire sent packets */
1538 base = unit->device;
1539 dma_size = TX_DESC_SIZE * TX_SLOT_COUNT;
1540 CachePostDMA(unit->tx_descs, &dma_size, 0);
1542 i = unit->tx_out_slot;
1543 while(proceed)
1545 /* Skip to "spare" descriptor if valid */
1547 desc = unit->tx_descs[i];
1548 if((desc[RH_DESC_TXCONTROL] & RH_DESC_TXCONTROLF_LASTFRAG) == 0)
1549 desc += 4;
1551 /* Check that descriptor is not in use */
1553 if((desc[RH_DESC_TXSTATUS] & MakeLELong(RH_DESC_TXSTATUSF_INUSE))
1554 == 0 && i != unit->tx_in_slot)
1556 buffer = unit->tx_buffers[i];
1557 dma_size = data_size;
1558 CachePostDMA(buffer, &dma_size, DMA_ReadFromRAM);
1560 /* Check if unit's buffer is now free */
1562 if(buffer == unit->tx_buffer)
1563 unit->flags &= ~UNITF_TXBUFFERINUSE;
1565 RetireTXSlot(unit, i, base);
1567 i = (i + 1) % TX_SLOT_COUNT;
1569 else
1570 proceed = FALSE;
1573 unit->tx_out_slot = i;
1575 dma_size = TX_DESC_SIZE * TX_SLOT_COUNT;
1576 CachePreDMA(unit->tx_descs, &dma_size, 0);
1578 /* Restart downloads if they had stopped */
1580 if(unit->request_ports[WRITE_QUEUE]->mp_Flags == PA_IGNORE)
1581 Cause(&unit->tx_int);
1583 return;
1588 /****i* rhine.device/RetireTXSlot ******************************************
1590 * NAME
1591 * RetireTXSlot -- Reply finished TX request.
1593 * SYNOPSIS
1594 * RetireTXSlot(unit, slot)
1596 * VOID RetireTXSlot(struct DevUnit *, UWORD);
1598 ****************************************************************************
1602 static VOID RetireTXSlot(struct DevUnit *unit, UWORD slot,
1603 struct DevBase *base)
1605 UWORD frame_size;
1606 struct IOSana2Req *request;
1607 struct TypeStats *tracker;
1609 /* Update statistics */
1611 slot = unit->tx_out_slot;
1612 request = unit->tx_requests[slot];
1613 frame_size = request->ios2_DataLength;
1614 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1615 frame_size += ETH_HEADERSIZE;
1617 unit->stats.PacketsSent++;
1619 tracker = FindTypeStats(unit, &unit->type_trackers,
1620 request->ios2_PacketType, base);
1621 if(tracker != NULL)
1623 tracker->stats.PacketsSent++;
1624 tracker->stats.BytesSent += frame_size;
1627 /* Reply request */
1629 request->ios2_Req.io_Error = 0;
1630 ReplyMsg((APTR)request);
1632 return;
1637 /****i* rhine.device/ResetHandler ******************************************
1639 * NAME
1640 * ResetHandler -- Disable hardware before a reboot.
1642 * SYNOPSIS
1643 * ResetHandler(unit, int_code)
1645 * VOID ResetHandler(struct DevUnit *, APTR);
1647 ****************************************************************************
1651 static VOID ResetHandler(REG(a1, struct DevUnit *unit),
1652 REG(a6, APTR int_code))
1654 if((unit->flags & UNITF_HAVEADAPTER) != 0)
1656 /* Disable frame transmission and reception */
1658 unit->LEWordOut(unit->card, RH_REG_CONTROL, RH_REG_CONTROLF_STOP);
1660 /* Stop interrupts */
1662 unit->LEWordOut(unit->card, RH_REG_INTMASK, 0);
1666 return;
1671 /****i* rhine.device/ReportEvents ******************************************
1673 * NAME
1674 * ReportEvents
1676 * SYNOPSIS
1677 * ReportEvents(unit, events)
1679 * VOID ReportEvents(struct DevUnit *, ULONG);
1681 * FUNCTION
1683 * INPUTS
1684 * unit - A unit of this device.
1685 * events - A mask of events to report.
1687 * RESULT
1688 * None.
1690 ****************************************************************************
1694 static VOID ReportEvents(struct DevUnit *unit, ULONG events,
1695 struct DevBase *base)
1697 struct IOSana2Req *request, *tail, *next_request;
1698 struct List *list;
1700 list = &unit->request_ports[EVENT_QUEUE]->mp_MsgList;
1701 next_request = (APTR)list->lh_Head;
1702 tail = (APTR)&list->lh_Tail;
1704 Disable();
1705 while(next_request != tail)
1707 request = next_request;
1708 next_request = (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
1710 if((request->ios2_WireError & events) != 0)
1712 request->ios2_WireError = events;
1713 Remove((APTR)request);
1714 ReplyMsg((APTR)request);
1717 Enable();
1719 return;
1724 /****i* rhine.device/UnitTask **********************************************
1726 * NAME
1727 * UnitTask
1729 * SYNOPSIS
1730 * UnitTask()
1732 * VOID UnitTask();
1734 * FUNCTION
1735 * Completes deferred requests, and handles card insertion and removal
1736 * in conjunction with the relevant interrupts.
1738 ****************************************************************************
1742 static VOID UnitTask(struct ExecBase *sys_base)
1744 struct Task *task;
1745 struct IORequest *request;
1746 struct DevUnit *unit;
1747 struct DevBase *base;
1748 struct MsgPort *general_port;
1749 ULONG signals = 0, wait_signals, card_removed_signal,
1750 card_inserted_signal, general_port_signal;
1752 /* Get parameters */
1754 task = AbsExecBase->ThisTask;
1755 unit = task->tc_UserData;
1756 base = unit->device;
1758 /* Activate general request port */
1760 general_port = unit->request_ports[GENERAL_QUEUE];
1761 general_port->mp_SigTask = task;
1762 general_port->mp_SigBit = AllocSignal(-1);
1763 general_port_signal = 1 << general_port->mp_SigBit;
1764 general_port->mp_Flags = PA_SIGNAL;
1766 /* Allocate signals for notification of card removal and insertion */
1768 card_removed_signal = unit->card_removed_signal = 1 << AllocSignal(-1);
1769 card_inserted_signal = unit->card_inserted_signal = 1 << AllocSignal(-1);
1770 wait_signals = (1 << general_port->mp_SigBit) | card_removed_signal
1771 | card_inserted_signal | SIGBREAKF_CTRL_C;
1773 /* Tell ourselves to check port for old messages */
1775 Signal(task, general_port_signal);
1777 /* Infinite loop to service requests and signals */
1779 while(TRUE)
1781 signals = Wait(wait_signals);
1783 if((signals & card_inserted_signal) != 0)
1785 if(unit->insertion_function(unit->card, base))
1787 unit->flags |= UNITF_HAVEADAPTER;
1788 if((unit->flags & UNITF_CONFIGURED) != 0)
1789 ConfigureAdapter(unit, base);
1790 if((unit->flags & UNITF_WASONLINE) != 0)
1792 GoOnline(unit, base);
1793 unit->flags &= ~UNITF_WASONLINE;
1798 if((signals & card_removed_signal) != 0)
1800 unit->removal_function(unit->card, base);
1801 if((unit->flags & UNITF_WASONLINE) != 0)
1802 GoOffline(unit, base);
1805 if((signals & general_port_signal) != 0)
1807 while((request = (APTR)GetMsg(general_port)) != NULL)
1809 /* Service the request as soon as the unit is free */
1811 ObtainSemaphore(&unit->access_lock);
1812 ServiceRequest((APTR)request, base);
1820 /****i* rhine.device/ReadMII ***********************************************
1822 * NAME
1823 * ReadMII -- Read a register in an MII PHY.
1825 * SYNOPSIS
1826 * value = ReadMII(unit, phy_no, reg_no)
1828 * UWORD ReadMII(struct DevUnit *, UWORD, UWORD);
1830 * INPUTS
1831 * unit - A unit of this device.
1832 * phy_no - Index of PHY to use.
1833 * reg_no - MII register to read.
1835 * RESULT
1836 * value - Value read from MII register.
1838 ****************************************************************************
1842 UWORD ReadMII(struct DevUnit *unit, UWORD phy_no, UWORD reg_no,
1843 struct DevBase *base)
1845 while((unit->ByteIn(unit->card, RH_REG_MIICTRL)
1846 & (RH_REG_MIICTRLF_READ | RH_REG_MIICTRLF_WRITE)) != 0);
1848 unit->ByteOut(unit->card, RH_REG_MIICTRL, 0);
1849 unit->ByteOut(unit->card, RH_REG_MIICONFIG, phy_no);
1850 unit->ByteOut(unit->card, RH_REG_MIIREGNO, reg_no);
1851 unit->ByteOut(unit->card, RH_REG_MIICTRL, RH_REG_MIICTRLF_READ);
1852 while((unit->ByteIn(unit->card, RH_REG_MIICTRL)
1853 & (RH_REG_MIICTRLF_READ | RH_REG_MIICTRLF_WRITE)) != 0);
1855 return unit->LEWordIn(unit->card, RH_REG_MIIDATA);