revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / networks / rhine / unit.c
blob7eb917aae1997f60b3f3434ec202239a607fe9c7
1 /*
3 Copyright (C) 2001-2017 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>
26 #include <exec/tasks.h>
28 #include <proto/exec.h>
29 #include <proto/alib.h>
30 #include <proto/utility.h>
31 #include <proto/timer.h>
33 #include "device.h"
34 #include "task.h"
35 #include "rhine.h"
37 #include "unit_protos.h"
38 #include "request_protos.h"
39 #include "timer_protos.h"
42 #define TASK_PRIORITY 0
43 #define STACK_SIZE 4096
44 #define INT_MASK 0xffff
45 #define TX_DESC_SIZE (RH_DESCSIZE * 2 + ETH_HEADERSIZE + 2)
47 VOID DeinitialiseAdapter(struct DevUnit *unit, struct DevBase *base);
48 static struct AddressRange *FindMulticastRange(struct DevUnit *unit,
49 ULONG lower_bound_left, UWORD lower_bound_right, ULONG upper_bound_left,
50 UWORD upper_bound_right, struct DevBase *base);
51 static VOID SetMulticast(struct DevUnit *unit, struct DevBase *base);
52 static BOOL StatusInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code));
53 static VOID RXInt(REG(a1, struct DevUnit *unit), REG(a6, APTR int_code));
54 static VOID DistributeRXPacket(struct DevUnit *unit, const UBYTE *packet,
55 UWORD packet_size, struct DevBase *base);
56 static VOID CopyPacket(struct DevUnit *unit, struct IOSana2Req *request,
57 UWORD packet_size, UWORD packet_type, const UBYTE *buffer,
58 struct DevBase *base);
59 static BOOL AddressFilter(struct DevUnit *unit, UBYTE *address,
60 struct DevBase *base);
61 static VOID TXInt(REG(a1, struct DevUnit *unit), REG(a6, APTR int_code));
62 static VOID TXEndInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code));
63 static VOID RetireTXSlot(struct DevUnit *unit, UWORD slot,
64 struct DevBase *base);
65 static VOID ResetHandler(REG(a1, struct DevUnit *unit),
66 REG(a6, APTR int_code));
67 static VOID ReportEvents(struct DevUnit *unit, ULONG events,
68 struct DevBase *base);
69 static VOID UnitTask(struct DevUnit *unit);
70 UWORD ReadMII(struct DevUnit *unit, UWORD phy_no, UWORD reg_no,
71 struct DevBase *base);
75 /****i* rhine.device/CreateUnit ********************************************
77 * NAME
78 * CreateUnit -- Create a unit.
80 * SYNOPSIS
81 * unit = CreateUnit(index, io_base, id, card,
82 * io_tags, bus)
84 * struct DevUnit *CreateUnit(ULONG, APTR, UWORD, APTR,
85 * struct TagItem *, UWORD);
87 * FUNCTION
88 * Creates a new unit.
90 ****************************************************************************
94 struct DevUnit *CreateUnit(ULONG index, APTR card,
95 const struct TagItem *io_tags, UWORD bus, struct DevBase *base)
97 BOOL success = TRUE;
98 struct DevUnit *unit;
99 struct Task *task;
100 struct MsgPort *port;
101 UWORD i;
102 ULONG *desc, desc_p, buffer_p, dma_size;
103 APTR stack;
105 unit = AllocMem(sizeof(struct DevUnit), MEMF_CLEAR | MEMF_PUBLIC);
106 if(unit == NULL)
107 success = FALSE;
109 if(success)
111 /* Initialise lists etc. */
113 NewList((APTR)&unit->openers);
114 NewList((APTR)&unit->type_trackers);
115 NewList((APTR)&unit->multicast_ranges);
117 unit->index = index;
118 unit->device = base;
119 unit->card = card;
120 unit->bus = bus;
122 /* Store I/O hooks */
124 unit->ByteIn =
125 (APTR)GetTagData(IOTAG_ByteIn, (UPINT)NULL, io_tags);
126 unit->ByteOut =
127 (APTR)GetTagData(IOTAG_ByteOut, (UPINT)NULL, io_tags);
128 unit->LEWordIn =
129 (APTR)GetTagData(IOTAG_LEWordIn, (UPINT)NULL, io_tags);
130 unit->LELongIn =
131 (APTR)GetTagData(IOTAG_LELongIn, (UPINT)NULL, io_tags);
132 unit->LEWordOut =
133 (APTR)GetTagData(IOTAG_LEWordOut, (UPINT)NULL, io_tags);
134 unit->LELongOut =
135 (APTR)GetTagData(IOTAG_LELongOut, (UPINT)NULL, io_tags);
136 unit->AllocDMAMem =
137 (APTR)GetTagData(IOTAG_AllocDMAMem, (UPINT)NULL, io_tags);
138 unit->FreeDMAMem =
139 (APTR)GetTagData(IOTAG_FreeDMAMem, (UPINT)NULL, io_tags);
140 if(unit->ByteIn == NULL
141 || unit->ByteOut == NULL
142 || unit->LEWordIn == NULL
143 || unit->LELongIn == NULL
144 || unit->LEWordOut == NULL
145 || unit->LELongOut == NULL
146 || unit->AllocDMAMem == NULL
147 || unit->FreeDMAMem == NULL)
148 success = FALSE;
151 if(success)
153 InitSemaphore(&unit->access_lock);
155 /* Create the message ports for queuing requests */
157 for(i = 0; i < REQUEST_QUEUE_COUNT; i++)
159 unit->request_ports[i] = port = AllocMem(sizeof(struct MsgPort),
160 MEMF_PUBLIC | MEMF_CLEAR);
161 if(port == NULL)
162 success = FALSE;
164 if(success)
166 NewList(&port->mp_MsgList);
167 port->mp_Flags = PA_IGNORE;
170 if(success)
171 unit->request_ports[WRITE_QUEUE]->mp_SigTask = &unit->tx_int;
174 if(success)
176 /* Allocate TX descriptors */
178 desc = unit->AllocDMAMem(unit->card, TX_DESC_SIZE * TX_SLOT_COUNT, 16);
179 if(desc == NULL)
180 success = FALSE;
183 if(success)
185 /* Fill arrays of virtual and physical addresses of TX descriptors */
187 dma_size = TX_DESC_SIZE * TX_SLOT_COUNT;
188 desc_p = (ULONG)(UPINT)CachePreDMA(desc, &dma_size, 0);
189 if(dma_size != TX_DESC_SIZE * TX_SLOT_COUNT)
190 success = FALSE;
191 CachePostDMA(desc, &dma_size, 0);
193 for(i = 0; i < TX_SLOT_COUNT; i++)
195 unit->tx_descs[i] = desc;
196 desc += TX_DESC_SIZE / sizeof(ULONG);
197 unit->tx_descs_p[i] = desc_p;
198 desc_p += TX_DESC_SIZE;
202 if(success)
204 /* Allocate RX descriptors */
206 desc = unit->AllocDMAMem(unit->card, RH_DESCSIZE * RX_SLOT_COUNT, 16);
207 if(desc == NULL)
208 success = FALSE;
211 if(success)
213 /* Fill arrays of virtual and physical addresses of TX descriptors */
215 dma_size = RH_DESCSIZE * RX_SLOT_COUNT;
216 desc_p = (ULONG)(UPINT)CachePreDMA(desc, &dma_size, 0);
217 if(dma_size != RH_DESCSIZE * RX_SLOT_COUNT)
218 success = FALSE;
219 CachePostDMA(desc, &dma_size, 0);
221 for(i = 0; i < RX_SLOT_COUNT; i++)
223 unit->rx_descs[i] = desc;
224 desc += RH_DESCSIZE / sizeof(ULONG);
225 unit->rx_descs_p[i] = desc_p;
226 desc_p += RH_DESCSIZE;
229 /* Allocate packet buffers */
231 unit->tx_buffer = unit->AllocDMAMem(unit->card, FRAME_BUFFER_SIZE, 4);
232 if(unit->tx_buffer == NULL)
233 success = FALSE;
235 for(i = 0; i < RX_SLOT_COUNT; i++)
237 unit->rx_buffers[i] = unit->AllocDMAMem(unit->card,
238 FRAME_BUFFER_SIZE, 4);
239 if(unit->rx_buffers[i] == NULL)
240 success = FALSE;
243 unit->tx_requests = AllocVec(sizeof(APTR) * TX_SLOT_COUNT,
244 MEMF_PUBLIC);
245 if(unit->tx_requests == NULL)
246 success = FALSE;
249 if(success)
251 /* Construct RX ring */
253 for(i = 0; i < RX_SLOT_COUNT; i++)
255 desc = unit->rx_descs[i];
256 desc[RH_DESC_RXSTATUS] = MakeLELong(RH_DESC_RXSTATUSF_INUSE);
257 desc[RH_DESC_RXCONTROL] = MakeLELong(FRAME_BUFFER_SIZE);
258 dma_size = FRAME_BUFFER_SIZE;
259 buffer_p =
260 (ULONG)(UPINT)CachePreDMA(unit->rx_buffers[i], &dma_size, 0);
261 if(dma_size != FRAME_BUFFER_SIZE)
262 success = FALSE;
263 desc[RH_DESC_DATA] = MakeLELong(buffer_p);
264 desc[RH_DESC_NEXT] =
265 MakeLELong(unit->rx_descs_p[(i + 1) % RX_SLOT_COUNT]);
266 desc += RH_DESCSIZE / sizeof(ULONG);
268 dma_size = RH_DESCSIZE * RX_SLOT_COUNT;
269 CachePreDMA(unit->rx_descs, &dma_size, 0);
272 if(success)
274 /* Initialise network adapter hardware */
276 success = InitialiseAdapter(unit, FALSE, base);
277 unit->flags |= UNITF_HAVEADAPTER;
280 if(success)
282 /* Record maximum speed in BPS */
284 unit->speed = 100000000;
286 /* Initialise interrupts */
288 unit->status_int.is_Code = (APTR)StatusInt;
289 unit->status_int.is_Data = unit;
291 unit->rx_int.is_Node.ln_Name =
292 base->device.dd_Library.lib_Node.ln_Name;
293 unit->rx_int.is_Code = (APTR)RXInt;
294 unit->rx_int.is_Data = unit;
296 unit->tx_int.is_Node.ln_Name =
297 base->device.dd_Library.lib_Node.ln_Name;
298 unit->tx_int.is_Code = (APTR)TXInt;
299 unit->tx_int.is_Data = unit;
301 unit->tx_end_int.is_Node.ln_Name =
302 base->device.dd_Library.lib_Node.ln_Name;
303 unit->tx_end_int.is_Code = (APTR)TXEndInt;
304 unit->tx_end_int.is_Data = unit;
306 unit->reset_handler.is_Node.ln_Name =
307 base->device.dd_Library.lib_Node.ln_Name;
308 unit->reset_handler.is_Code = (APTR)ResetHandler;
309 unit->reset_handler.is_Data = unit;
311 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
313 /* Create a new task */
315 unit->task = task =
316 AllocMem(sizeof(struct Task), MEMF_PUBLIC | MEMF_CLEAR);
317 if(task == NULL)
318 success = FALSE;
321 if(success)
323 stack = AllocMem(STACK_SIZE, MEMF_PUBLIC);
324 if(stack == NULL)
325 success = FALSE;
328 if(success)
330 /* Initialise and start task */
332 task->tc_Node.ln_Type = NT_TASK;
333 task->tc_Node.ln_Pri = TASK_PRIORITY;
334 task->tc_Node.ln_Name = base->device.dd_Library.lib_Node.ln_Name;
335 task->tc_SPUpper = stack + STACK_SIZE;
336 task->tc_SPLower = stack;
337 task->tc_SPReg = task->tc_SPUpper;
338 NewList(&task->tc_MemEntry);
340 if(AddUnitTask(task, UnitTask, unit) != NULL)
341 unit->flags |= UNITF_TASKADDED;
342 else
343 success = FALSE;
346 if(!success)
348 DeleteUnit(unit, base);
349 unit = NULL;
352 return unit;
357 /****i* rhine.device/DeleteUnit ********************************************
359 * NAME
360 * DeleteUnit -- Delete a unit.
362 * SYNOPSIS
363 * DeleteUnit(unit)
365 * VOID DeleteUnit(struct DevUnit *);
367 * FUNCTION
368 * Deletes a unit.
370 * INPUTS
371 * unit - Device unit (may be NULL).
373 * RESULT
374 * None.
376 ****************************************************************************
380 VOID DeleteUnit(struct DevUnit *unit, struct DevBase *base)
382 UBYTE i;
383 struct Task *task;
385 if(unit != NULL)
387 task = unit->task;
388 if(task != NULL)
390 if((unit->flags & UNITF_TASKADDED) != 0)
391 RemTask(task);
392 FreeMem(task->tc_SPLower, STACK_SIZE);
393 FreeMem(task, sizeof(struct Task));
396 for(i = 0; i < REQUEST_QUEUE_COUNT; i++)
398 if(unit->request_ports[i] != NULL)
399 FreeMem(unit->request_ports[i], sizeof(struct MsgPort));
402 if((unit->flags & UNITF_ONLINE) != 0) /* Needed! */
403 GoOffline(unit, base);
405 if((unit->flags & UNITF_HAVEADAPTER) != 0)
406 DeinitialiseAdapter(unit, base);
408 for(i = 0; i < RX_SLOT_COUNT; i++)
409 unit->FreeDMAMem(unit->card, unit->rx_buffers[i]);
410 unit->FreeDMAMem(unit->card, unit->tx_buffer);
411 unit->FreeDMAMem(unit->card, unit->rx_descs[0]);
412 unit->FreeDMAMem(unit->card, unit->tx_descs[0]);
414 FreeVec(unit->tx_requests);
416 FreeMem(unit, sizeof(struct DevUnit));
419 return;
424 /****i* rhine.device/InitialiseAdapter *************************************
426 * NAME
427 * InitialiseAdapter
429 * SYNOPSIS
430 * success = InitialiseAdapter(unit, reinsertion)
432 * BOOL InitialiseAdapter(struct DevUnit *, BOOL);
434 * FUNCTION
436 * INPUTS
437 * unit
438 * reinsertion
440 * RESULT
441 * success - Success indicator.
443 ****************************************************************************
447 BOOL InitialiseAdapter(struct DevUnit *unit, BOOL reinsertion,
448 struct DevBase *base)
450 BOOL success = TRUE;
451 UBYTE *p, eeprom_reg;
452 UWORD i;
454 /* Reload data from EEPROM */
456 eeprom_reg = unit->ByteIn(unit->card, RH_REG_EEPROM);
457 unit->ByteOut(unit->card, RH_REG_EEPROM,
458 eeprom_reg | RH_REG_EEPROMF_LOAD);
460 BusyMicroDelay(1, base);
461 while((unit->ByteIn(unit->card, RH_REG_EEPROM) & RH_REG_EEPROMF_LOAD)
462 != 0);
464 /* Get default MAC address */
466 p = unit->default_address;
467 for(i = 0; i < ETH_ADDRESSSIZE; i++)
468 *p++ = unit->ByteIn(unit->card, RH_REG_ADDRESS + i);
470 /* Send reset command */
472 unit->ByteOut(unit->card, RH_REG_CONTROL + 1, RH_REG_CONTROL1F_RESET);
473 BusyMicroDelay(110, base);
474 while((unit->ByteIn(unit->card, RH_REG_CONTROL + 1)
475 & RH_REG_CONTROL1F_RESET) != 0);
477 /* Disable interrupts */
479 unit->LEWordOut(unit->card, RH_REG_INTSTATUS, INT_MASK);
480 unit->LEWordOut(unit->card, RH_REG_INTMASK, 0);
481 if(TRUE)
482 unit->LEWordOut(unit->card, RH_REG_MIIINTMASK, 0);
484 /* Configure MII */
486 unit->ByteOut(unit->card, RH_REG_MIICTRL,
487 unit->ByteIn(unit->card, RH_REG_MIICTRL) | RH_REG_MIICTRLF_AUTOPOLL);
489 if(TRUE)
490 unit->mii_phy_no = unit->ByteIn(unit->card, RH_REG_MIICONFIG)
491 & RH_REG_MIICONFIGF_PHYADDR;
492 else
493 unit->mii_phy_no = 1;
495 /* Return */
497 return success;
502 /****i* rhine.device/DeinitialiseAdapter ***********************************
504 * NAME
505 * DeinitialiseAdapter
507 * SYNOPSIS
508 * DeinitialiseAdapter(unit)
510 * VOID DeinitialiseAdapter(struct DevUnit *);
512 * FUNCTION
514 * INPUTS
515 * unit
517 * RESULT
518 * None.
520 ****************************************************************************
524 VOID DeinitialiseAdapter(struct DevUnit *unit, struct DevBase *base)
526 return;
531 /****i* rhine.device/ConfigureAdapter **************************************
533 * NAME
534 * ConfigureAdapter -- Set up card for transmission/reception.
536 * SYNOPSIS
537 * ConfigureAdapter(unit)
539 * VOID ConfigureAdapter(struct DevUnit *);
541 ****************************************************************************
545 VOID ConfigureAdapter(struct DevUnit *unit, struct DevBase *base)
547 const UBYTE *p;
548 UWORD i;
550 /* Set MAC address */
552 p = unit->address;
553 for(i = 0; i < ETH_ADDRESSSIZE; i++)
554 unit->ByteOut(unit->card, RH_REG_ADDRESS + i, *p++);
556 /* Set DMA rings */
558 unit->LELongOut(unit->card, RH_REG_TXLIST, unit->tx_descs_p[0]);
559 unit->LELongOut(unit->card, RH_REG_RXLIST, unit->rx_descs_p[0]);
561 /* Choose packet types to receive */
563 unit->LEWordOut(unit->card, RH_REG_PCIBUSCONFIG, 6);
564 unit->ByteOut(unit->card, RH_REG_RXCONFIG,
565 RH_REG_RXCONFIGF_BCAST | RH_REG_RXCONFIGF_MCAST);
567 /* Return */
569 return;
574 /****i* rhine.device/GoOnline **********************************************
576 * NAME
577 * GoOnline -- Enable transmission/reception.
579 * SYNOPSIS
580 * GoOnline(unit)
582 * VOID GoOnline(struct DevUnit *);
584 ****************************************************************************
588 VOID GoOnline(struct DevUnit *unit, struct DevBase *base)
590 /* Enable interrupts */
592 unit->flags |= UNITF_ONLINE;
593 unit->LEWordOut(unit->card, RH_REG_INTMASK, INT_MASK);
595 /* Enable frame transmission and reception */
597 unit->LEWordOut(unit->card, RH_REG_CONTROL, RH_REG_CONTROLF_TXENABLE
598 | RH_REG_CONTROLF_RXENABLE | RH_REG_CONTROLF_START);
600 /* Record start time and report Online event */
602 GetSysTime(&unit->stats.LastStart);
603 ReportEvents(unit, S2EVENT_ONLINE, base);
605 return;
610 /****i* rhine.device/GoOffline *********************************************
612 * NAME
613 * GoOffline -- Disable transmission/reception.
615 * SYNOPSIS
616 * GoOffline(unit)
618 * VOID GoOffline(struct DevUnit *);
620 * FUNCTION
622 * INPUTS
623 * unit
625 * RESULT
626 * None.
628 ****************************************************************************
632 VOID GoOffline(struct DevUnit *unit, struct DevBase *base)
634 unit->flags &= ~UNITF_ONLINE;
636 /* Flush pending read and write requests */
638 FlushUnit(unit, MGMT_QUEUE, S2ERR_OUTOFSERVICE, base);
640 /* Report Offline event and return */
642 ReportEvents(unit, S2EVENT_OFFLINE, base);
643 return;
648 /****i* rhine.device/AddMulticastRange *************************************
650 * NAME
651 * AddMulticastRange
653 * SYNOPSIS
654 * success = AddMulticastRange(unit, lower_bound, upper_bound)
656 * BOOL AddMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
658 ****************************************************************************
662 BOOL AddMulticastRange(struct DevUnit *unit, const UBYTE *lower_bound,
663 const UBYTE *upper_bound, struct DevBase *base)
665 struct AddressRange *range;
666 ULONG lower_bound_left, upper_bound_left;
667 UWORD lower_bound_right, upper_bound_right;
669 lower_bound_left = BELong(*((ULONG *)lower_bound));
670 lower_bound_right = BEWord(*((UWORD *)(lower_bound + 4)));
671 upper_bound_left = BELong(*((ULONG *)upper_bound));
672 upper_bound_right = BEWord(*((UWORD *)(upper_bound + 4)));
674 range = FindMulticastRange(unit, lower_bound_left, lower_bound_right,
675 upper_bound_left, upper_bound_right, base);
677 if(range != NULL)
678 range->add_count++;
679 else
681 range = AllocMem(sizeof(struct AddressRange), MEMF_PUBLIC);
682 if(range != NULL)
684 range->lower_bound_left = lower_bound_left;
685 range->lower_bound_right = lower_bound_right;
686 range->upper_bound_left = upper_bound_left;
687 range->upper_bound_right = upper_bound_right;
688 range->add_count = 1;
690 Disable();
691 AddTail((APTR)&unit->multicast_ranges, (APTR)range);
692 unit->range_count++;
693 SetMulticast(unit, base);
694 Enable();
698 return range != NULL;
703 /****i* rhine.device/RemMulticastRange *************************************
705 * NAME
706 * RemMulticastRange
708 * SYNOPSIS
709 * found = RemMulticastRange(unit, lower_bound, upper_bound)
711 * BOOL RemMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
713 ****************************************************************************
717 BOOL RemMulticastRange(struct DevUnit *unit, const UBYTE *lower_bound,
718 const UBYTE *upper_bound, struct DevBase *base)
720 struct AddressRange *range;
721 ULONG lower_bound_left, upper_bound_left;
722 UWORD lower_bound_right, upper_bound_right;
724 lower_bound_left = BELong(*((ULONG *)lower_bound));
725 lower_bound_right = BEWord(*((UWORD *)(lower_bound + 4)));
726 upper_bound_left = BELong(*((ULONG *)upper_bound));
727 upper_bound_right = BEWord(*((UWORD *)(upper_bound + 4)));
729 range = FindMulticastRange(unit, lower_bound_left, lower_bound_right,
730 upper_bound_left, upper_bound_right, base);
732 if(range != NULL)
734 if(--range->add_count == 0)
736 Disable();
737 Remove((APTR)range);
738 unit->range_count--;
739 SetMulticast(unit, base);
740 Enable();
741 FreeMem(range, sizeof(struct AddressRange));
745 return range != NULL;
750 /****i* rhine.device/FindMulticastRange ************************************
752 * NAME
753 * FindMulticastRange
755 * SYNOPSIS
756 * range = FindMulticastRange(unit, lower_bound_left,
757 * lower_bound_right, upper_bound_left, upper_bound_right)
759 * struct AddressRange *FindMulticastRange(struct DevUnit *, ULONG,
760 * UWORD, ULONG, UWORD);
762 ****************************************************************************
766 static struct AddressRange *FindMulticastRange(struct DevUnit *unit,
767 ULONG lower_bound_left, UWORD lower_bound_right, ULONG upper_bound_left,
768 UWORD upper_bound_right, struct DevBase *base)
770 struct AddressRange *range, *tail;
771 BOOL found = FALSE;
773 range = (APTR)unit->multicast_ranges.mlh_Head;
774 tail = (APTR)&unit->multicast_ranges.mlh_Tail;
776 while(range != tail && !found)
778 if(lower_bound_left == range->lower_bound_left &&
779 lower_bound_right == range->lower_bound_right &&
780 upper_bound_left == range->upper_bound_left &&
781 upper_bound_right == range->upper_bound_right)
782 found = TRUE;
783 else
784 range = (APTR)range->node.mln_Succ;
787 if(!found)
788 range = NULL;
790 return range;
795 /****i* rhine.device/SetMulticast ******************************************
797 * NAME
798 * SetMulticast
800 * SYNOPSIS
801 * SetMulticast(unit)
803 * VOID SetMulticast(struct DevUnit *);
805 ****************************************************************************
809 static VOID SetMulticast(struct DevUnit *unit, struct DevBase *base)
811 if(!IsListEmpty(&unit->multicast_ranges))
813 unit->LELongOut(unit->card, RH_REG_MCASTFILTER, 0xffffffff);
814 unit->LELongOut(unit->card, RH_REG_MCASTFILTER + 4, 0xffffffff);
816 else
818 unit->LELongOut(unit->card, RH_REG_MCASTFILTER, 0);
819 unit->LELongOut(unit->card, RH_REG_MCASTFILTER + 4, 0);
822 return;
827 /****i* rhine.device/FindTypeStats *****************************************
829 * NAME
830 * FindTypeStats
832 * SYNOPSIS
833 * stats = FindTypeStats(unit, list,
834 * packet_type)
836 * struct TypeStats *FindTypeStats(struct DevUnit *, struct MinList *,
837 * ULONG);
839 ****************************************************************************
843 struct TypeStats *FindTypeStats(struct DevUnit *unit, struct MinList *list,
844 ULONG packet_type, struct DevBase *base)
846 struct TypeStats *stats, *tail;
847 BOOL found = FALSE;
849 stats = (APTR)list->mlh_Head;
850 tail = (APTR)&list->mlh_Tail;
852 while(stats != tail && !found)
854 if(stats->packet_type == packet_type)
855 found = TRUE;
856 else
857 stats = (APTR)stats->node.mln_Succ;
860 if(!found)
861 stats = NULL;
863 return stats;
868 /****i* rhine.device/FlushUnit *********************************************
870 * NAME
871 * FlushUnit
873 * SYNOPSIS
874 * FlushUnit(unit, last_queue, error)
876 * VOID FlushUnit(struct DevUnit *, UBYTE, BYTE);
878 ****************************************************************************
882 VOID FlushUnit(struct DevUnit *unit, UBYTE last_queue, BYTE error,
883 struct DevBase *base)
885 struct IORequest *request;
886 UBYTE i;
887 struct Opener *opener, *tail;
889 /* Abort queued requests */
891 for(i = 0; i <= last_queue; i++)
893 while((request = (APTR)GetMsg(unit->request_ports[i])) != NULL)
895 request->io_Error = IOERR_ABORTED;
896 ReplyMsg((APTR)request);
900 #if 1
901 opener = (APTR)unit->openers.mlh_Head;
902 tail = (APTR)&unit->openers.mlh_Tail;
904 /* Flush every opener's read queues */
906 while(opener != tail)
908 while((request = (APTR)GetMsg(&opener->read_port)) != NULL)
910 request->io_Error = error;
911 ReplyMsg((APTR)request);
913 while((request = (APTR)GetMsg(&opener->mgmt_port)) != NULL)
915 request->io_Error = error;
916 ReplyMsg((APTR)request);
918 opener = (APTR)opener->node.mln_Succ;
921 #else
922 opener = request->ios2_BufferManagement;
923 while((request = (APTR)GetMsg(&opener->read_port)) != NULL)
925 request->io_Error = IOERR_ABORTED;
926 ReplyMsg((APTR)request);
928 while((request = (APTR)GetMsg(&opener->mgmt_port)) != NULL)
930 request->io_Error = IOERR_ABORTED;
931 ReplyMsg((APTR)request);
933 #endif
935 /* Return */
937 return;
942 /****i* rhine.device/StatusInt *********************************************
944 * NAME
945 * StatusInt
947 * SYNOPSIS
948 * finished = StatusInt(unit)
950 * BOOL StatusInt(struct DevUnit *);
952 * INPUTS
953 * unit - A unit of this device.
955 * RESULT
956 * finished - Always FALSE.
958 ****************************************************************************
962 static BOOL StatusInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code))
964 struct DevBase *base;
965 UWORD ints;
967 base = unit->device;
968 ints = unit->LEWordIn(unit->card, RH_REG_INTSTATUS);
970 if(ints != 0)
972 /* Acknowledge interrupts */
974 unit->LEWordOut(unit->card, RH_REG_INTSTATUS, ints);
976 /* FIXME: Need IO-sync here for PPC etc.? */
978 /* Handle interrupts */
980 if((ints & (RH_INTF_TXERR | RH_INTF_TXOK)) != 0)
981 Cause(&unit->tx_end_int);
982 if((ints & (RH_INTF_RXERR | RH_INTF_RXOK)) != 0)
983 Cause(&unit->rx_int);
986 return FALSE;
991 /****i* rhine.device/RXInt *************************************************
993 * NAME
994 * RXInt -- Soft interrupt for packet reception.
996 * SYNOPSIS
997 * RXInt(unit)
999 * VOID RXInt(struct DevUnit *);
1001 * FUNCTION
1003 * INPUTS
1004 * unit - A unit of this device.
1006 * RESULT
1007 * None.
1009 ****************************************************************************
1013 static VOID RXInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code))
1015 UWORD slot, packet_size;
1016 struct DevBase *base;
1017 ULONG rx_status, *desc, dma_size;
1018 UBYTE *buffer;
1020 base = unit->device;
1021 slot = unit->rx_slot;
1022 desc = unit->rx_descs[slot];
1024 dma_size = TX_DESC_SIZE;
1025 CachePostDMA(unit->rx_descs, &dma_size, 0);
1026 while(((rx_status = LELong(desc[RH_DESC_RXSTATUS]))
1027 & RH_DESC_RXSTATUSF_INUSE) == 0)
1029 if((rx_status & RH_DESC_RXSTATUSF_OK) != 0)
1031 packet_size = ((rx_status & RH_DESC_RXSTATUSF_LENGTH)
1032 >> RH_DESC_RXSTATUSB_LENGTH) - ETH_CRCSIZE;
1033 buffer = unit->rx_buffers[slot];
1035 if(AddressFilter(unit, buffer + ETH_PACKET_DEST, base))
1037 unit->stats.PacketsReceived++;
1038 DistributeRXPacket(unit, buffer, packet_size, base);
1041 else
1043 unit->stats.BadData++;
1044 ReportEvents(unit, S2EVENT_ERROR | S2EVENT_HARDWARE | S2EVENT_RX,
1045 base);
1048 /* Mark descriptor as free for next time */
1050 desc[RH_DESC_RXSTATUS] = MakeLELong(RH_DESC_RXSTATUSF_INUSE);
1052 /* Get next descriptor */
1054 slot = (slot + 1) % RX_SLOT_COUNT;
1055 desc = unit->rx_descs[slot];
1058 /* Return */
1060 unit->rx_slot = slot;
1061 return;
1066 /****i* rhine.device/DistributeRXPacket ************************************
1068 * NAME
1069 * DistributeRXPacket -- Send a packet to all appropriate destinations.
1071 * SYNOPSIS
1072 * DistributeRXPacket(unit, frame)
1074 * VOID DistributeRXPacket(struct DevUnit *, UBYTE *);
1076 ****************************************************************************
1080 static VOID DistributeRXPacket(struct DevUnit *unit, const UBYTE *packet,
1081 UWORD packet_size, struct DevBase *base)
1083 BOOL is_orphan = TRUE, accepted;
1084 ULONG packet_type;
1085 struct IOSana2Req *request, *request_tail;
1086 struct Opener *opener, *opener_tail;
1087 struct TypeStats *tracker;
1089 /* Offer packet to every opener */
1091 opener = (APTR)unit->openers.mlh_Head;
1092 opener_tail = (APTR)&unit->openers.mlh_Tail;
1093 packet_type = BEWord(*((UWORD *)(packet + ETH_PACKET_TYPE)));
1095 while(opener != opener_tail)
1097 request = (APTR)opener->read_port.mp_MsgList.lh_Head;
1098 request_tail = (APTR)&opener->read_port.mp_MsgList.lh_Tail;
1099 accepted = FALSE;
1101 /* Offer packet to each request until it's accepted */
1103 while(request != request_tail && !accepted)
1105 if(request->ios2_PacketType == packet_type)
1107 CopyPacket(unit, request, packet_size, packet_type,
1108 packet, base);
1109 accepted = TRUE;
1111 request =
1112 (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
1115 if(accepted)
1116 is_orphan = FALSE;
1117 opener = (APTR)opener->node.mln_Succ;
1120 /* If packet was unwanted, give it to S2_READORPHAN request */
1122 if(is_orphan)
1124 unit->stats.UnknownTypesReceived++;
1125 if(!IsMsgPortEmpty(unit->request_ports[ADOPT_QUEUE]))
1127 CopyPacket(unit,
1128 (APTR)unit->request_ports[ADOPT_QUEUE]->mp_MsgList.lh_Head,
1129 packet_size, packet_type, packet, base);
1133 /* Update remaining statistics */
1135 if(packet_type <= ETH_MTU)
1136 packet_type = ETH_MTU;
1137 tracker =
1138 FindTypeStats(unit, &unit->type_trackers, packet_type, base);
1139 if(tracker != NULL)
1141 tracker->stats.PacketsReceived++;
1142 tracker->stats.BytesReceived += packet_size;
1145 return;
1150 /****i* rhine.device/CopyPacket ********************************************
1152 * NAME
1153 * CopyPacket -- Copy packet to client's buffer.
1155 * SYNOPSIS
1156 * CopyPacket(unit, request, packet_size, packet_type,
1157 * buffer)
1159 * VOID CopyPacket(struct DevUnit *, struct IOSana2Req *, UWORD, UWORD,
1160 * UBYTE *);
1162 ****************************************************************************
1166 static VOID CopyPacket(struct DevUnit *unit, struct IOSana2Req *request,
1167 UWORD packet_size, UWORD packet_type, const UBYTE *buffer,
1168 struct DevBase *base)
1170 struct Opener *opener;
1171 BOOL filtered = FALSE;
1173 /* Set multicast and broadcast flags */
1175 request->ios2_Req.io_Flags &= ~(SANA2IOF_BCAST | SANA2IOF_MCAST);
1176 if((*((ULONG *)(buffer + ETH_PACKET_DEST)) == 0xffffffff) &&
1177 (*((UWORD *)(buffer + ETH_PACKET_DEST + 4)) == 0xffff))
1178 request->ios2_Req.io_Flags |= SANA2IOF_BCAST;
1179 else if((buffer[ETH_PACKET_DEST] & 0x1) != 0)
1180 request->ios2_Req.io_Flags |= SANA2IOF_MCAST;
1182 /* Set source and destination addresses and packet type */
1184 CopyMem(buffer + ETH_PACKET_SOURCE, request->ios2_SrcAddr,
1185 ETH_ADDRESSSIZE);
1186 CopyMem(buffer + ETH_PACKET_DEST, request->ios2_DstAddr,
1187 ETH_ADDRESSSIZE);
1188 request->ios2_PacketType = packet_type;
1190 /* Adjust for cooked packet request */
1192 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1194 packet_size -= ETH_PACKET_DATA;
1195 buffer += ETH_PACKET_DATA;
1197 #ifdef USE_HACKS
1198 else
1199 packet_size += 4; /* Needed for Shapeshifter & Fusion */
1200 #endif
1201 request->ios2_DataLength = packet_size;
1203 /* Filter packet */
1205 opener = request->ios2_BufferManagement;
1206 if(request->ios2_Req.io_Command == CMD_READ &&
1207 opener->filter_hook != NULL)
1208 if(!CallHookPkt(opener->filter_hook, request, (APTR)buffer))
1209 filtered = TRUE;
1211 if(!filtered)
1213 /* Copy packet into opener's buffer and reply packet */
1215 if(!opener->rx_function(request->ios2_Data, (APTR)buffer,
1216 packet_size))
1218 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
1219 request->ios2_WireError = S2WERR_BUFF_ERROR;
1220 ReportEvents(unit,
1221 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF | S2EVENT_RX,
1222 base);
1224 Remove((APTR)request);
1225 ReplyMsg((APTR)request);
1228 return;
1233 /****i* rhine.device/AddressFilter *****************************************
1235 * NAME
1236 * AddressFilter -- Determine if an RX packet should be accepted.
1238 * SYNOPSIS
1239 * accept = AddressFilter(unit, address)
1241 * BOOL AddressFilter(struct DevUnit *, UBYTE *);
1243 ****************************************************************************
1247 static BOOL AddressFilter(struct DevUnit *unit, UBYTE *address,
1248 struct DevBase *base)
1250 struct AddressRange *range, *tail;
1251 BOOL accept = TRUE;
1252 ULONG address_left;
1253 UWORD address_right;
1255 /* Check whether address is unicast/broadcast or multicast */
1257 address_left = BELong(*((ULONG *)address));
1258 address_right = BEWord(*((UWORD *)(address + 4)));
1260 if(((address_left & 0x01000000) != 0) &&
1261 !((address_left == 0xffffffff) && (address_right == 0xffff)))
1263 /* Check if this multicast address is wanted */
1265 range = (APTR)unit->multicast_ranges.mlh_Head;
1266 tail = (APTR)&unit->multicast_ranges.mlh_Tail;
1267 accept = FALSE;
1269 while((range != tail) && !accept)
1271 if((address_left > range->lower_bound_left ||
1272 address_left == range->lower_bound_left &&
1273 address_right >= range->lower_bound_right) &&
1274 (address_left < range->upper_bound_left ||
1275 address_left == range->upper_bound_left &&
1276 address_right <= range->upper_bound_right))
1277 accept = TRUE;
1278 range = (APTR)range->node.mln_Succ;
1281 if(!accept)
1282 unit->special_stats[S2SS_ETHERNET_BADMULTICAST & 0xffff]++;
1285 return accept;
1290 /****i* rhine.device/TXInt *************************************************
1292 * NAME
1293 * TXInt -- Soft interrupt for packet transmission.
1295 * SYNOPSIS
1296 * TXInt(unit)
1298 * VOID TXInt(struct DevUnit *);
1300 * FUNCTION
1302 * INPUTS
1303 * unit - A unit of this device.
1305 * RESULT
1306 * None.
1308 ****************************************************************************
1312 static VOID TXInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code))
1314 struct DevBase *base;
1315 UWORD packet_size, data_size, slot, new_slot, *p, *q, i;
1316 struct IOSana2Req *request;
1317 BOOL proceed = TRUE;
1318 struct Opener *opener;
1319 ULONG wire_error, *desc, dma_size, desc_p, buffer_p, txcontrol_value;
1320 UBYTE *(*dma_tx_function)(REG(a0, APTR));
1321 BYTE error;
1322 UBYTE *buffer;
1323 struct MsgPort *port;
1325 base = unit->device;
1326 port = unit->request_ports[WRITE_QUEUE];
1328 while(proceed && !IsMsgPortEmpty(port))
1330 slot = unit->tx_in_slot;
1331 new_slot = (slot + 1) % TX_SLOT_COUNT;
1333 if(new_slot != unit->tx_out_slot
1334 && (unit->flags & UNITF_TXBUFFERINUSE) == 0)
1336 error = 0;
1338 /* Get request and DMA frame descriptor */
1340 request = (APTR)port->mp_MsgList.lh_Head;
1342 Remove((APTR)request);
1343 unit->tx_requests[slot] = request;
1344 desc = unit->tx_descs[slot];
1345 desc_p = unit->tx_descs_p[slot];
1347 data_size = packet_size = request->ios2_DataLength;
1348 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1349 packet_size += ETH_HEADERSIZE;
1350 if(packet_size < ETH_MINSIZE)
1351 packet_size = ETH_MINSIZE;
1353 /* Decide if one or two descriptors are needed, and generate
1354 Ethernet header if necessary */
1356 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1358 /* Use first descriptor for Ethernet header */
1360 buffer = (UBYTE *)desc + 2 * RH_DESCSIZE;
1361 buffer_p = desc_p + 2 * RH_DESCSIZE;
1363 desc[RH_DESC_TXCONTROL] =
1364 MakeLELong(RH_DESC_TXCONTROLF_FIRSTFRAG
1365 | RH_DESC_TXCONTROLF_CHAIN | ETH_HEADERSIZE);
1366 desc[RH_DESC_DATA] = MakeLELong(buffer_p);
1367 desc[RH_DESC_NEXT] = MakeLELong(desc_p + RH_DESCSIZE);
1369 /* Write Ethernet header */
1371 p = (UWORD *)buffer;
1372 for(i = 0, q = (UWORD *)request->ios2_DstAddr;
1373 i < ETH_ADDRESSSIZE / 2; i++)
1374 *p++ = *q++;
1375 for(i = 0, q = (UWORD *)unit->address;
1376 i < ETH_ADDRESSSIZE / 2; i++)
1377 *p++ = *q++;
1378 *p++ = MakeBEWord(request->ios2_PacketType);
1380 /* Use spare second descriptor for frame data */
1382 desc += RH_DESCSIZE / 4;
1383 desc_p += RH_DESCSIZE;
1385 txcontrol_value = RH_DESC_TXCONTROLF_INT
1386 | RH_DESC_TXCONTROLF_LASTFRAG
1387 | RH_DESC_TXCONTROLF_CHAIN
1388 | packet_size - ETH_HEADERSIZE;
1390 else
1392 txcontrol_value = RH_DESC_TXCONTROLF_INT
1393 | RH_DESC_TXCONTROLF_FIRSTFRAG | RH_DESC_TXCONTROLF_LASTFRAG
1394 | RH_DESC_TXCONTROLF_CHAIN
1395 | packet_size;
1398 /* Get packet data */
1400 opener = (APTR)request->ios2_BufferManagement;
1401 dma_tx_function = opener->dma_tx_function;
1402 if(dma_tx_function != NULL)
1403 buffer = dma_tx_function(request->ios2_Data);
1404 else
1405 buffer = NULL;
1407 if(buffer == NULL)
1409 buffer = unit->tx_buffer;
1410 if(opener->tx_function(buffer, request->ios2_Data,
1411 data_size))
1413 unit->flags |= UNITF_TXBUFFERINUSE;
1415 else
1417 error = S2ERR_NO_RESOURCES;
1418 wire_error = S2WERR_BUFF_ERROR;
1419 ReportEvents(unit,
1420 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF
1421 | S2EVENT_TX, base);
1424 unit->tx_buffers[slot] = buffer;
1426 /* Fill in descriptor for frame data */
1428 if(error == 0)
1430 dma_size = data_size;
1431 buffer_p = (ULONG)(UPINT)CachePreDMA(buffer, &dma_size,
1432 DMA_ReadFromRAM);
1433 desc[RH_DESC_TXCONTROL] = MakeLELong(txcontrol_value);
1434 desc[RH_DESC_DATA] = MakeLELong(buffer_p);
1435 desc[RH_DESC_NEXT] = MakeLELong(unit->tx_descs_p[new_slot]);
1437 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1438 desc -= RH_DESCSIZE / 4;
1440 desc[RH_DESC_TXSTATUS] = MakeLELong(RH_DESC_TXSTATUSF_INUSE);
1443 if(error == 0)
1445 /* Restart transmission if it had stopped */
1447 dma_size = TX_DESC_SIZE * TX_SLOT_COUNT;
1448 CachePreDMA(unit->tx_descs, &dma_size, 0);
1449 unit->ByteOut(unit->card, RH_REG_CONTROL,
1450 unit->ByteIn(unit->card, RH_REG_CONTROL)
1451 | RH_REG_CONTROLF_TXPOLL);
1453 /* FIXME: Need IO-sync here for PPC etc.? */
1455 unit->tx_in_slot = new_slot;
1457 else
1459 /* Return failed request */
1461 request->ios2_Req.io_Error = error;
1462 request->ios2_WireError = wire_error;
1463 ReplyMsg((APTR)request);
1466 else
1467 proceed = FALSE;
1470 if(proceed)
1471 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
1472 else
1473 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_IGNORE;
1475 return;
1480 /****i* rhine.device/TXEndInt **********************************************
1482 * NAME
1483 * TXEndInt -- Clean up after a frame has been sent.
1485 * SYNOPSIS
1486 * TXEndInt(unit, int_code)
1488 * VOID TXEndInt(struct DevUnit *, APTR);
1490 * INPUTS
1491 * unit - A unit of this device.
1492 * int_code - Unused.
1494 * RESULT
1495 * None.
1497 ****************************************************************************
1499 * It appears to be safe to assume that there will always be at least one
1500 * completed packet whenever this interrupt is called.
1504 static VOID TXEndInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code))
1506 UWORD data_size, i = 0;
1507 UBYTE *buffer;
1508 struct DevBase *base;
1509 ULONG *desc, dma_size;
1510 BOOL proceed = TRUE;
1512 /* Retire sent packets */
1514 base = unit->device;
1515 dma_size = TX_DESC_SIZE * TX_SLOT_COUNT;
1516 CachePostDMA(unit->tx_descs, &dma_size, 0);
1518 i = unit->tx_out_slot;
1519 while(proceed)
1521 /* Skip to "spare" descriptor if valid */
1523 desc = unit->tx_descs[i];
1524 if((desc[RH_DESC_TXCONTROL] & RH_DESC_TXCONTROLF_LASTFRAG) == 0)
1525 desc += 4;
1527 /* Check that descriptor is not in use */
1529 if((desc[RH_DESC_TXSTATUS] & MakeLELong(RH_DESC_TXSTATUSF_INUSE))
1530 == 0 && i != unit->tx_in_slot)
1532 buffer = unit->tx_buffers[i];
1533 dma_size = data_size;
1534 CachePostDMA(buffer, &dma_size, DMA_ReadFromRAM);
1536 /* Check if unit's buffer is now free */
1538 if(buffer == unit->tx_buffer)
1539 unit->flags &= ~UNITF_TXBUFFERINUSE;
1541 RetireTXSlot(unit, i, base);
1543 i = (i + 1) % TX_SLOT_COUNT;
1545 else
1546 proceed = FALSE;
1549 unit->tx_out_slot = i;
1551 dma_size = TX_DESC_SIZE * TX_SLOT_COUNT;
1552 CachePreDMA(unit->tx_descs, &dma_size, 0);
1554 /* Restart downloads if they had stopped */
1556 if(unit->request_ports[WRITE_QUEUE]->mp_Flags == PA_IGNORE)
1557 Cause(&unit->tx_int);
1559 return;
1564 /****i* rhine.device/RetireTXSlot ******************************************
1566 * NAME
1567 * RetireTXSlot -- Reply finished TX request.
1569 * SYNOPSIS
1570 * RetireTXSlot(unit, slot)
1572 * VOID RetireTXSlot(struct DevUnit *, UWORD);
1574 ****************************************************************************
1578 static VOID RetireTXSlot(struct DevUnit *unit, UWORD slot,
1579 struct DevBase *base)
1581 UWORD frame_size;
1582 struct IOSana2Req *request;
1583 struct TypeStats *tracker;
1585 /* Update statistics */
1587 slot = unit->tx_out_slot;
1588 request = unit->tx_requests[slot];
1589 frame_size = request->ios2_DataLength;
1590 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1591 frame_size += ETH_HEADERSIZE;
1593 unit->stats.PacketsSent++;
1595 tracker = FindTypeStats(unit, &unit->type_trackers,
1596 request->ios2_PacketType, base);
1597 if(tracker != NULL)
1599 tracker->stats.PacketsSent++;
1600 tracker->stats.BytesSent += frame_size;
1603 /* Reply request */
1605 request->ios2_Req.io_Error = 0;
1606 ReplyMsg((APTR)request);
1608 return;
1613 /****i* rhine.device/ResetHandler ******************************************
1615 * NAME
1616 * ResetHandler -- Disable hardware before a reboot.
1618 * SYNOPSIS
1619 * ResetHandler(unit, int_code)
1621 * VOID ResetHandler(struct DevUnit *, APTR);
1623 ****************************************************************************
1627 static VOID ResetHandler(REG(a1, struct DevUnit *unit),
1628 REG(a6, APTR int_code))
1630 if((unit->flags & UNITF_HAVEADAPTER) != 0)
1632 /* Disable frame transmission and reception */
1634 unit->LEWordOut(unit->card, RH_REG_CONTROL, RH_REG_CONTROLF_STOP);
1636 /* Stop interrupts */
1638 unit->LEWordOut(unit->card, RH_REG_INTMASK, 0);
1642 return;
1647 /****i* rhine.device/ReportEvents ******************************************
1649 * NAME
1650 * ReportEvents
1652 * SYNOPSIS
1653 * ReportEvents(unit, events)
1655 * VOID ReportEvents(struct DevUnit *, ULONG);
1657 * FUNCTION
1659 * INPUTS
1660 * unit - A unit of this device.
1661 * events - A mask of events to report.
1663 * RESULT
1664 * None.
1666 ****************************************************************************
1670 static VOID ReportEvents(struct DevUnit *unit, ULONG events,
1671 struct DevBase *base)
1673 struct IOSana2Req *request, *tail, *next_request;
1674 struct List *list;
1676 list = &unit->request_ports[EVENT_QUEUE]->mp_MsgList;
1677 next_request = (APTR)list->lh_Head;
1678 tail = (APTR)&list->lh_Tail;
1680 Disable();
1681 while(next_request != tail)
1683 request = next_request;
1684 next_request = (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
1686 if((request->ios2_WireError & events) != 0)
1688 request->ios2_WireError = events;
1689 Remove((APTR)request);
1690 ReplyMsg((APTR)request);
1693 Enable();
1695 return;
1700 /****i* rhine.device/UnitTask **********************************************
1702 * NAME
1703 * UnitTask
1705 * SYNOPSIS
1706 * UnitTask(unit)
1708 * VOID UnitTask(struct DevUnit *);
1710 * FUNCTION
1711 * Completes deferred requests, and handles card insertion and removal
1712 * in conjunction with the relevant interrupts.
1714 ****************************************************************************
1718 static VOID UnitTask(struct DevUnit *unit)
1720 struct DevBase *base;
1721 struct IORequest *request;
1722 struct MsgPort *general_port;
1723 ULONG signals = 0, wait_signals, card_removed_signal,
1724 card_inserted_signal, general_port_signal;
1726 base = unit->device;
1728 /* Activate general request port */
1730 general_port = unit->request_ports[GENERAL_QUEUE];
1731 general_port->mp_SigTask = unit->task;
1732 general_port->mp_SigBit = AllocSignal(-1);
1733 general_port_signal = 1 << general_port->mp_SigBit;
1734 general_port->mp_Flags = PA_SIGNAL;
1736 /* Allocate signals for notification of card removal and insertion */
1738 card_removed_signal = unit->card_removed_signal = 1 << AllocSignal(-1);
1739 card_inserted_signal = unit->card_inserted_signal = 1 << AllocSignal(-1);
1740 wait_signals = (1 << general_port->mp_SigBit) | card_removed_signal
1741 | card_inserted_signal | SIGBREAKF_CTRL_C;
1743 /* Tell ourselves to check port for old messages */
1745 Signal(unit->task, general_port_signal);
1747 /* Infinite loop to service requests and signals */
1749 while(TRUE)
1751 signals = Wait(wait_signals);
1753 if((signals & card_inserted_signal) != 0)
1755 if(unit->insertion_function(unit->card, base))
1757 unit->flags |= UNITF_HAVEADAPTER;
1758 if((unit->flags & UNITF_CONFIGURED) != 0)
1759 ConfigureAdapter(unit, base);
1760 if((unit->flags & UNITF_WASONLINE) != 0)
1762 GoOnline(unit, base);
1763 unit->flags &= ~UNITF_WASONLINE;
1768 if((signals & card_removed_signal) != 0)
1770 unit->removal_function(unit->card, base);
1771 if((unit->flags & UNITF_WASONLINE) != 0)
1772 GoOffline(unit, base);
1775 if((signals & general_port_signal) != 0)
1777 while((request = (APTR)GetMsg(general_port)) != NULL)
1779 /* Service the request as soon as the unit is free */
1781 ObtainSemaphore(&unit->access_lock);
1782 ServiceRequest((APTR)request, base);
1790 /****i* rhine.device/ReadMII ***********************************************
1792 * NAME
1793 * ReadMII -- Read a register in an MII PHY.
1795 * SYNOPSIS
1796 * value = ReadMII(unit, phy_no, reg_no)
1798 * UWORD ReadMII(struct DevUnit *, UWORD, UWORD);
1800 * INPUTS
1801 * unit - A unit of this device.
1802 * phy_no - Index of PHY to use.
1803 * reg_no - MII register to read.
1805 * RESULT
1806 * value - Value read from MII register.
1808 ****************************************************************************
1812 UWORD ReadMII(struct DevUnit *unit, UWORD phy_no, UWORD reg_no,
1813 struct DevBase *base)
1815 while((unit->ByteIn(unit->card, RH_REG_MIICTRL)
1816 & (RH_REG_MIICTRLF_READ | RH_REG_MIICTRLF_WRITE)) != 0);
1818 unit->ByteOut(unit->card, RH_REG_MIICTRL, 0);
1819 unit->ByteOut(unit->card, RH_REG_MIICONFIG, phy_no);
1820 unit->ByteOut(unit->card, RH_REG_MIIREGNO, reg_no);
1821 unit->ByteOut(unit->card, RH_REG_MIICTRL, RH_REG_MIICTRLF_READ);
1822 while((unit->ByteIn(unit->card, RH_REG_MIICTRL)
1823 & (RH_REG_MIICTRLF_READ | RH_REG_MIICTRLF_WRITE)) != 0);
1825 return unit->LEWordIn(unit->card, RH_REG_MIIDATA);