3 Copyright (C) 2012-2017 The AROS Dev Team
4 Copyright (C) 2001-2012 Neil Cafferkey
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
24 #include <exec/memory.h>
25 #include <exec/execbase.h>
26 #include <exec/errors.h>
28 #include <proto/exec.h>
29 #include <proto/alib.h>
30 #include <proto/utility.h>
31 #include <proto/timer.h>
36 #include "unit_protos.h"
37 #include "request_protos.h"
38 #include "timer_protos.h"
41 #define TASK_PRIORITY 0
42 #define STACK_SIZE 4096
43 #define INT_MASK 0xffff
44 #define TX_DESC_SIZE (RH_DESCSIZE * 2 + ETH_HEADERSIZE + 2)
47 #define AbsExecBase sys_base
50 VOID
DeinitialiseAdapter(struct DevUnit
*unit
, struct DevBase
*base
);
51 static struct AddressRange
*FindMulticastRange(struct DevUnit
*unit
,
52 ULONG lower_bound_left
, UWORD lower_bound_right
, ULONG upper_bound_left
,
53 UWORD upper_bound_right
, struct DevBase
*base
);
54 static VOID
SetMulticast(struct DevUnit
*unit
, struct DevBase
*base
);
55 static BOOL
StatusInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
));
56 static VOID
RXInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
));
57 static VOID
DistributeRXPacket(struct DevUnit
*unit
, const UBYTE
*packet
,
58 UWORD packet_size
, struct DevBase
*base
);
59 static VOID
CopyPacket(struct DevUnit
*unit
, struct IOSana2Req
*request
,
60 UWORD packet_size
, UWORD packet_type
, const UBYTE
*buffer
,
61 struct DevBase
*base
);
62 static BOOL
AddressFilter(struct DevUnit
*unit
, UBYTE
*address
,
63 struct DevBase
*base
);
64 static VOID
TXInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
));
65 static VOID
TXEndInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
));
66 static VOID
RetireTXSlot(struct DevUnit
*unit
, UWORD slot
,
67 struct DevBase
*base
);
68 static VOID
ResetHandler(REG(a1
, struct DevUnit
*unit
),
69 REG(a6
, APTR int_code
));
70 static VOID
ReportEvents(struct DevUnit
*unit
, ULONG events
,
71 struct DevBase
*base
);
72 static VOID
UnitTask(struct ExecBase
*sys_base
);
73 UWORD
ReadMII(struct DevUnit
*unit
, UWORD phy_no
, UWORD reg_no
,
74 struct DevBase
*base
);
76 #if !defined(__AROS__)
77 static const UBYTE broadcast_address
[] =
78 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
83 #define AddTask(task, initial_pc, final_pc) \
85 struct TagItem _task_tags[] = \
86 {{TASKTAG_ARG1, (IPTR)SysBase}, {TAG_END, 0}}; \
87 NewAddTask(task, initial_pc, final_pc, _task_tags); \
93 /****i* rhine.device/CreateUnit ********************************************
96 * CreateUnit -- Create a unit.
99 * unit = CreateUnit(index, io_base, id, card,
102 * struct DevUnit *CreateUnit(ULONG, APTR, UWORD, APTR,
103 * struct TagItem *, UWORD);
106 * Creates a new unit.
108 ****************************************************************************
112 struct DevUnit
*CreateUnit(ULONG index
, APTR card
,
113 const struct TagItem
*io_tags
, UWORD bus
, struct DevBase
*base
)
116 struct DevUnit
*unit
;
118 struct MsgPort
*port
;
120 ULONG
*desc
, desc_p
, buffer_p
, dma_size
;
123 unit
= AllocMem(sizeof(struct DevUnit
), MEMF_CLEAR
| MEMF_PUBLIC
);
129 /* Initialise lists etc. */
131 NewList((APTR
)&unit
->openers
);
132 NewList((APTR
)&unit
->type_trackers
);
133 NewList((APTR
)&unit
->multicast_ranges
);
140 /* Store I/O hooks */
143 (APTR
)GetTagData(IOTAG_ByteIn
, (UPINT
)NULL
, io_tags
);
145 (APTR
)GetTagData(IOTAG_ByteOut
, (UPINT
)NULL
, io_tags
);
147 (APTR
)GetTagData(IOTAG_LEWordIn
, (UPINT
)NULL
, io_tags
);
149 (APTR
)GetTagData(IOTAG_LELongIn
, (UPINT
)NULL
, io_tags
);
151 (APTR
)GetTagData(IOTAG_LEWordOut
, (UPINT
)NULL
, io_tags
);
153 (APTR
)GetTagData(IOTAG_LELongOut
, (UPINT
)NULL
, io_tags
);
155 (APTR
)GetTagData(IOTAG_AllocDMAMem
, (UPINT
)NULL
, io_tags
);
157 (APTR
)GetTagData(IOTAG_FreeDMAMem
, (UPINT
)NULL
, io_tags
);
158 if(unit
->ByteIn
== NULL
159 || unit
->ByteOut
== NULL
160 || unit
->LEWordIn
== NULL
161 || unit
->LELongIn
== NULL
162 || unit
->LEWordOut
== NULL
163 || unit
->LELongOut
== NULL
164 || unit
->AllocDMAMem
== NULL
165 || unit
->FreeDMAMem
== NULL
)
171 InitSemaphore(&unit
->access_lock
);
173 /* Create the message ports for queuing requests */
175 for(i
= 0; i
< REQUEST_QUEUE_COUNT
; i
++)
177 unit
->request_ports
[i
] = port
= AllocMem(sizeof(struct MsgPort
),
178 MEMF_PUBLIC
| MEMF_CLEAR
);
184 NewList(&port
->mp_MsgList
);
185 port
->mp_Flags
= PA_IGNORE
;
189 unit
->request_ports
[WRITE_QUEUE
]->mp_SigTask
= &unit
->tx_int
;
194 /* Allocate TX descriptors */
196 desc
= unit
->AllocDMAMem(unit
->card
, TX_DESC_SIZE
* TX_SLOT_COUNT
, 16);
203 /* Fill arrays of virtual and physical addresses of TX descriptors */
205 dma_size
= TX_DESC_SIZE
* TX_SLOT_COUNT
;
206 desc_p
= (ULONG
)(UPINT
)CachePreDMA(desc
, &dma_size
, 0);
207 if(dma_size
!= TX_DESC_SIZE
* TX_SLOT_COUNT
)
209 CachePostDMA(desc
, &dma_size
, 0);
211 for(i
= 0; i
< TX_SLOT_COUNT
; i
++)
213 unit
->tx_descs
[i
] = desc
;
214 desc
+= TX_DESC_SIZE
/ sizeof(ULONG
);
215 unit
->tx_descs_p
[i
] = desc_p
;
216 desc_p
+= TX_DESC_SIZE
;
222 /* Allocate RX descriptors */
224 desc
= unit
->AllocDMAMem(unit
->card
, RH_DESCSIZE
* RX_SLOT_COUNT
, 16);
231 /* Fill arrays of virtual and physical addresses of TX descriptors */
233 dma_size
= RH_DESCSIZE
* RX_SLOT_COUNT
;
234 desc_p
= (ULONG
)(UPINT
)CachePreDMA(desc
, &dma_size
, 0);
235 if(dma_size
!= RH_DESCSIZE
* RX_SLOT_COUNT
)
237 CachePostDMA(desc
, &dma_size
, 0);
239 for(i
= 0; i
< RX_SLOT_COUNT
; i
++)
241 unit
->rx_descs
[i
] = desc
;
242 desc
+= RH_DESCSIZE
/ sizeof(ULONG
);
243 unit
->rx_descs_p
[i
] = desc_p
;
244 desc_p
+= RH_DESCSIZE
;
247 /* Allocate packet buffers */
249 unit
->tx_buffer
= unit
->AllocDMAMem(unit
->card
, FRAME_BUFFER_SIZE
, 4);
250 if(unit
->tx_buffer
== NULL
)
253 for(i
= 0; i
< RX_SLOT_COUNT
; i
++)
255 unit
->rx_buffers
[i
] = unit
->AllocDMAMem(unit
->card
,
256 FRAME_BUFFER_SIZE
, 4);
257 if(unit
->rx_buffers
[i
] == NULL
)
261 unit
->tx_requests
= AllocVec(sizeof(APTR
) * TX_SLOT_COUNT
,
263 if(unit
->tx_requests
== NULL
)
269 /* Construct RX ring */
271 for(i
= 0; i
< RX_SLOT_COUNT
; i
++)
273 desc
= unit
->rx_descs
[i
];
274 desc
[RH_DESC_RXSTATUS
] = MakeLELong(RH_DESC_RXSTATUSF_INUSE
);
275 desc
[RH_DESC_RXCONTROL
] = MakeLELong(FRAME_BUFFER_SIZE
);
276 dma_size
= FRAME_BUFFER_SIZE
;
278 (ULONG
)(UPINT
)CachePreDMA(unit
->rx_buffers
[i
], &dma_size
, 0);
279 if(dma_size
!= FRAME_BUFFER_SIZE
)
281 desc
[RH_DESC_DATA
] = MakeLELong(buffer_p
);
283 MakeLELong(unit
->rx_descs_p
[(i
+ 1) % RX_SLOT_COUNT
]);
284 desc
+= RH_DESCSIZE
/ sizeof(ULONG
);
286 dma_size
= RH_DESCSIZE
* RX_SLOT_COUNT
;
287 CachePreDMA(unit
->rx_descs
, &dma_size
, 0);
292 /* Initialise network adapter hardware */
294 success
= InitialiseAdapter(unit
, FALSE
, base
);
295 unit
->flags
|= UNITF_HAVEADAPTER
;
300 /* Record maximum speed in BPS */
302 unit
->speed
= 100000000;
304 /* Initialise interrupts */
306 unit
->status_int
.is_Code
= (APTR
)StatusInt
;
307 unit
->status_int
.is_Data
= unit
;
309 unit
->rx_int
.is_Node
.ln_Name
=
310 base
->device
.dd_Library
.lib_Node
.ln_Name
;
311 unit
->rx_int
.is_Code
= (APTR
)RXInt
;
312 unit
->rx_int
.is_Data
= unit
;
314 unit
->tx_int
.is_Node
.ln_Name
=
315 base
->device
.dd_Library
.lib_Node
.ln_Name
;
316 unit
->tx_int
.is_Code
= (APTR
)TXInt
;
317 unit
->tx_int
.is_Data
= unit
;
319 unit
->tx_end_int
.is_Node
.ln_Name
=
320 base
->device
.dd_Library
.lib_Node
.ln_Name
;
321 unit
->tx_end_int
.is_Code
= (APTR
)TXEndInt
;
322 unit
->tx_end_int
.is_Data
= unit
;
324 unit
->reset_handler
.is_Node
.ln_Name
=
325 base
->device
.dd_Library
.lib_Node
.ln_Name
;
326 unit
->reset_handler
.is_Code
= (APTR
)ResetHandler
;
327 unit
->reset_handler
.is_Data
= unit
;
329 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
331 /* Create a new task */
334 AllocMem(sizeof(struct Task
), MEMF_PUBLIC
| MEMF_CLEAR
);
341 stack
= AllocMem(STACK_SIZE
, MEMF_PUBLIC
);
348 /* Initialise and start task */
350 task
->tc_Node
.ln_Type
= NT_TASK
;
351 task
->tc_Node
.ln_Pri
= TASK_PRIORITY
;
352 task
->tc_Node
.ln_Name
= base
->device
.dd_Library
.lib_Node
.ln_Name
;
353 task
->tc_SPUpper
= stack
+ STACK_SIZE
;
354 task
->tc_SPLower
= stack
;
355 task
->tc_SPReg
= stack
+ STACK_SIZE
;
356 NewList(&task
->tc_MemEntry
);
358 if(AddTask(task
, UnitTask
, NULL
) == NULL
)
364 /* Send the unit to the new task */
366 task
->tc_UserData
= unit
;
371 DeleteUnit(unit
, base
);
380 /****i* rhine.device/DeleteUnit ********************************************
383 * DeleteUnit -- Delete a unit.
388 * VOID DeleteUnit(struct DevUnit *);
394 * unit - Device unit (may be NULL).
399 ****************************************************************************
403 VOID
DeleteUnit(struct DevUnit
*unit
, struct DevBase
*base
)
413 if(task
->tc_UserData
!= NULL
)
416 FreeMem(task
->tc_SPLower
, STACK_SIZE
);
418 FreeMem(task
, sizeof(struct Task
));
421 for(i
= 0; i
< REQUEST_QUEUE_COUNT
; i
++)
423 if(unit
->request_ports
[i
] != NULL
)
424 FreeMem(unit
->request_ports
[i
], sizeof(struct MsgPort
));
427 if((unit
->flags
& UNITF_ONLINE
) != 0) /* Needed! */
428 GoOffline(unit
, base
);
430 if((unit
->flags
& UNITF_HAVEADAPTER
) != 0)
431 DeinitialiseAdapter(unit
, base
);
433 for(i
= 0; i
< RX_SLOT_COUNT
; i
++)
434 unit
->FreeDMAMem(unit
->card
, unit
->rx_buffers
[i
]);
435 unit
->FreeDMAMem(unit
->card
, unit
->tx_buffer
);
436 unit
->FreeDMAMem(unit
->card
, unit
->rx_descs
[0]);
437 unit
->FreeDMAMem(unit
->card
, unit
->tx_descs
[0]);
439 FreeVec(unit
->tx_requests
);
441 FreeMem(unit
, sizeof(struct DevUnit
));
449 /****i* rhine.device/InitialiseAdapter *************************************
455 * success = InitialiseAdapter(unit, reinsertion)
457 * BOOL InitialiseAdapter(struct DevUnit *, BOOL);
466 * success - Success indicator.
468 ****************************************************************************
472 BOOL
InitialiseAdapter(struct DevUnit
*unit
, BOOL reinsertion
,
473 struct DevBase
*base
)
476 UBYTE
*p
, eeprom_reg
;
479 /* Reload data from EEPROM */
481 eeprom_reg
= unit
->ByteIn(unit
->card
, RH_REG_EEPROM
);
482 unit
->ByteOut(unit
->card
, RH_REG_EEPROM
,
483 eeprom_reg
| RH_REG_EEPROMF_LOAD
);
485 BusyMicroDelay(1, base
);
486 while((unit
->ByteIn(unit
->card
, RH_REG_EEPROM
) & RH_REG_EEPROMF_LOAD
)
489 /* Get default MAC address */
491 p
= unit
->default_address
;
492 for(i
= 0; i
< ETH_ADDRESSSIZE
; i
++)
493 *p
++ = unit
->ByteIn(unit
->card
, RH_REG_ADDRESS
+ i
);
495 /* Send reset command */
497 unit
->ByteOut(unit
->card
, RH_REG_CONTROL
+ 1, RH_REG_CONTROL1F_RESET
);
498 BusyMicroDelay(110, base
);
499 while((unit
->ByteIn(unit
->card
, RH_REG_CONTROL
+ 1)
500 & RH_REG_CONTROL1F_RESET
) != 0);
502 /* Disable interrupts */
504 unit
->LEWordOut(unit
->card
, RH_REG_INTSTATUS
, INT_MASK
);
505 unit
->LEWordOut(unit
->card
, RH_REG_INTMASK
, 0);
507 unit
->LEWordOut(unit
->card
, RH_REG_MIIINTMASK
, 0);
511 unit
->ByteOut(unit
->card
, RH_REG_MIICTRL
,
512 unit
->ByteIn(unit
->card
, RH_REG_MIICTRL
) | RH_REG_MIICTRLF_AUTOPOLL
);
515 unit
->mii_phy_no
= unit
->ByteIn(unit
->card
, RH_REG_MIICONFIG
)
516 & RH_REG_MIICONFIGF_PHYADDR
;
518 unit
->mii_phy_no
= 1;
527 /****i* rhine.device/DeinitialiseAdapter ***********************************
530 * DeinitialiseAdapter
533 * DeinitialiseAdapter(unit)
535 * VOID DeinitialiseAdapter(struct DevUnit *);
545 ****************************************************************************
549 VOID
DeinitialiseAdapter(struct DevUnit
*unit
, struct DevBase
*base
)
556 /****i* rhine.device/ConfigureAdapter **************************************
559 * ConfigureAdapter -- Set up card for transmission/reception.
562 * ConfigureAdapter(unit)
564 * VOID ConfigureAdapter(struct DevUnit *);
566 ****************************************************************************
570 VOID
ConfigureAdapter(struct DevUnit
*unit
, struct DevBase
*base
)
575 /* Set MAC address */
578 for(i
= 0; i
< ETH_ADDRESSSIZE
; i
++)
579 unit
->ByteOut(unit
->card
, RH_REG_ADDRESS
+ i
, *p
++);
583 unit
->LELongOut(unit
->card
, RH_REG_TXLIST
, unit
->tx_descs_p
[0]);
584 unit
->LELongOut(unit
->card
, RH_REG_RXLIST
, unit
->rx_descs_p
[0]);
586 /* Choose packet types to receive */
588 unit
->LEWordOut(unit
->card
, RH_REG_PCIBUSCONFIG
, 6);
589 unit
->ByteOut(unit
->card
, RH_REG_RXCONFIG
,
590 RH_REG_RXCONFIGF_BCAST
| RH_REG_RXCONFIGF_MCAST
);
599 /****i* rhine.device/GoOnline **********************************************
602 * GoOnline -- Enable transmission/reception.
607 * VOID GoOnline(struct DevUnit *);
609 ****************************************************************************
613 VOID
GoOnline(struct DevUnit
*unit
, struct DevBase
*base
)
615 /* Enable interrupts */
617 unit
->flags
|= UNITF_ONLINE
;
618 unit
->LEWordOut(unit
->card
, RH_REG_INTMASK
, INT_MASK
);
620 /* Enable frame transmission and reception */
622 unit
->LEWordOut(unit
->card
, RH_REG_CONTROL
, RH_REG_CONTROLF_TXENABLE
623 | RH_REG_CONTROLF_RXENABLE
| RH_REG_CONTROLF_START
);
625 /* Record start time and report Online event */
627 GetSysTime(&unit
->stats
.LastStart
);
628 ReportEvents(unit
, S2EVENT_ONLINE
, base
);
635 /****i* rhine.device/GoOffline *********************************************
638 * GoOffline -- Disable transmission/reception.
643 * VOID GoOffline(struct DevUnit *);
653 ****************************************************************************
657 VOID
GoOffline(struct DevUnit
*unit
, struct DevBase
*base
)
659 unit
->flags
&= ~UNITF_ONLINE
;
661 /* Flush pending read and write requests */
663 FlushUnit(unit
, MGMT_QUEUE
, S2ERR_OUTOFSERVICE
, base
);
665 /* Report Offline event and return */
667 ReportEvents(unit
, S2EVENT_OFFLINE
, base
);
673 /****i* rhine.device/AddMulticastRange *************************************
679 * success = AddMulticastRange(unit, lower_bound, upper_bound)
681 * BOOL AddMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
683 ****************************************************************************
687 BOOL
AddMulticastRange(struct DevUnit
*unit
, const UBYTE
*lower_bound
,
688 const UBYTE
*upper_bound
, struct DevBase
*base
)
690 struct AddressRange
*range
;
691 ULONG lower_bound_left
, upper_bound_left
;
692 UWORD lower_bound_right
, upper_bound_right
;
694 lower_bound_left
= BELong(*((ULONG
*)lower_bound
));
695 lower_bound_right
= BEWord(*((UWORD
*)(lower_bound
+ 4)));
696 upper_bound_left
= BELong(*((ULONG
*)upper_bound
));
697 upper_bound_right
= BEWord(*((UWORD
*)(upper_bound
+ 4)));
699 range
= FindMulticastRange(unit
, lower_bound_left
, lower_bound_right
,
700 upper_bound_left
, upper_bound_right
, base
);
706 range
= AllocMem(sizeof(struct AddressRange
), MEMF_PUBLIC
);
709 range
->lower_bound_left
= lower_bound_left
;
710 range
->lower_bound_right
= lower_bound_right
;
711 range
->upper_bound_left
= upper_bound_left
;
712 range
->upper_bound_right
= upper_bound_right
;
713 range
->add_count
= 1;
716 AddTail((APTR
)&unit
->multicast_ranges
, (APTR
)range
);
718 SetMulticast(unit
, base
);
723 return range
!= NULL
;
728 /****i* rhine.device/RemMulticastRange *************************************
734 * found = RemMulticastRange(unit, lower_bound, upper_bound)
736 * BOOL RemMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
738 ****************************************************************************
742 BOOL
RemMulticastRange(struct DevUnit
*unit
, const UBYTE
*lower_bound
,
743 const UBYTE
*upper_bound
, struct DevBase
*base
)
745 struct AddressRange
*range
;
746 ULONG lower_bound_left
, upper_bound_left
;
747 UWORD lower_bound_right
, upper_bound_right
;
749 lower_bound_left
= BELong(*((ULONG
*)lower_bound
));
750 lower_bound_right
= BEWord(*((UWORD
*)(lower_bound
+ 4)));
751 upper_bound_left
= BELong(*((ULONG
*)upper_bound
));
752 upper_bound_right
= BEWord(*((UWORD
*)(upper_bound
+ 4)));
754 range
= FindMulticastRange(unit
, lower_bound_left
, lower_bound_right
,
755 upper_bound_left
, upper_bound_right
, base
);
759 if(--range
->add_count
== 0)
764 SetMulticast(unit
, base
);
766 FreeMem(range
, sizeof(struct AddressRange
));
770 return range
!= NULL
;
775 /****i* rhine.device/FindMulticastRange ************************************
781 * range = FindMulticastRange(unit, lower_bound_left,
782 * lower_bound_right, upper_bound_left, upper_bound_right)
784 * struct AddressRange *FindMulticastRange(struct DevUnit *, ULONG,
785 * UWORD, ULONG, UWORD);
787 ****************************************************************************
791 static struct AddressRange
*FindMulticastRange(struct DevUnit
*unit
,
792 ULONG lower_bound_left
, UWORD lower_bound_right
, ULONG upper_bound_left
,
793 UWORD upper_bound_right
, struct DevBase
*base
)
795 struct AddressRange
*range
, *tail
;
798 range
= (APTR
)unit
->multicast_ranges
.mlh_Head
;
799 tail
= (APTR
)&unit
->multicast_ranges
.mlh_Tail
;
801 while(range
!= tail
&& !found
)
803 if(lower_bound_left
== range
->lower_bound_left
&&
804 lower_bound_right
== range
->lower_bound_right
&&
805 upper_bound_left
== range
->upper_bound_left
&&
806 upper_bound_right
== range
->upper_bound_right
)
809 range
= (APTR
)range
->node
.mln_Succ
;
820 /****i* rhine.device/SetMulticast ******************************************
828 * VOID SetMulticast(struct DevUnit *);
830 ****************************************************************************
834 static VOID
SetMulticast(struct DevUnit
*unit
, struct DevBase
*base
)
836 if(!IsListEmpty(&unit
->multicast_ranges
))
838 unit
->LELongOut(unit
->card
, RH_REG_MCASTFILTER
, 0xffffffff);
839 unit
->LELongOut(unit
->card
, RH_REG_MCASTFILTER
+ 4, 0xffffffff);
843 unit
->LELongOut(unit
->card
, RH_REG_MCASTFILTER
, 0);
844 unit
->LELongOut(unit
->card
, RH_REG_MCASTFILTER
+ 4, 0);
852 /****i* rhine.device/FindTypeStats *****************************************
858 * stats = FindTypeStats(unit, list,
861 * struct TypeStats *FindTypeStats(struct DevUnit *, struct MinList *,
864 ****************************************************************************
868 struct TypeStats
*FindTypeStats(struct DevUnit
*unit
, struct MinList
*list
,
869 ULONG packet_type
, struct DevBase
*base
)
871 struct TypeStats
*stats
, *tail
;
874 stats
= (APTR
)list
->mlh_Head
;
875 tail
= (APTR
)&list
->mlh_Tail
;
877 while(stats
!= tail
&& !found
)
879 if(stats
->packet_type
== packet_type
)
882 stats
= (APTR
)stats
->node
.mln_Succ
;
893 /****i* rhine.device/FlushUnit *********************************************
899 * FlushUnit(unit, last_queue, error)
901 * VOID FlushUnit(struct DevUnit *, UBYTE, BYTE);
903 ****************************************************************************
907 VOID
FlushUnit(struct DevUnit
*unit
, UBYTE last_queue
, BYTE error
,
908 struct DevBase
*base
)
910 struct IORequest
*request
;
912 struct Opener
*opener
, *tail
;
914 /* Abort queued requests */
916 for(i
= 0; i
<= last_queue
; i
++)
918 while((request
= (APTR
)GetMsg(unit
->request_ports
[i
])) != NULL
)
920 request
->io_Error
= IOERR_ABORTED
;
921 ReplyMsg((APTR
)request
);
926 opener
= (APTR
)unit
->openers
.mlh_Head
;
927 tail
= (APTR
)&unit
->openers
.mlh_Tail
;
929 /* Flush every opener's read queues */
931 while(opener
!= tail
)
933 while((request
= (APTR
)GetMsg(&opener
->read_port
)) != NULL
)
935 request
->io_Error
= error
;
936 ReplyMsg((APTR
)request
);
938 while((request
= (APTR
)GetMsg(&opener
->mgmt_port
)) != NULL
)
940 request
->io_Error
= error
;
941 ReplyMsg((APTR
)request
);
943 opener
= (APTR
)opener
->node
.mln_Succ
;
947 opener
= request
->ios2_BufferManagement
;
948 while((request
= (APTR
)GetMsg(&opener
->read_port
)) != NULL
)
950 request
->io_Error
= IOERR_ABORTED
;
951 ReplyMsg((APTR
)request
);
953 while((request
= (APTR
)GetMsg(&opener
->mgmt_port
)) != NULL
)
955 request
->io_Error
= IOERR_ABORTED
;
956 ReplyMsg((APTR
)request
);
967 /****i* rhine.device/StatusInt *********************************************
973 * finished = StatusInt(unit)
975 * BOOL StatusInt(struct DevUnit *);
978 * unit - A unit of this device.
981 * finished - Always FALSE.
983 ****************************************************************************
987 static BOOL
StatusInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
))
989 struct DevBase
*base
;
993 ints
= unit
->LEWordIn(unit
->card
, RH_REG_INTSTATUS
);
997 /* Acknowledge interrupts */
999 unit
->LEWordOut(unit
->card
, RH_REG_INTSTATUS
, ints
);
1001 /* FIXME: Need IO-sync here for PPC etc.? */
1003 /* Handle interrupts */
1005 if((ints
& (RH_INTF_TXERR
| RH_INTF_TXOK
)) != 0)
1006 Cause(&unit
->tx_end_int
);
1007 if((ints
& (RH_INTF_RXERR
| RH_INTF_RXOK
)) != 0)
1008 Cause(&unit
->rx_int
);
1016 /****i* rhine.device/RXInt *************************************************
1019 * RXInt -- Soft interrupt for packet reception.
1024 * VOID RXInt(struct DevUnit *);
1029 * unit - A unit of this device.
1034 ****************************************************************************
1038 static VOID
RXInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
))
1040 UWORD slot
, packet_size
;
1041 struct DevBase
*base
;
1042 ULONG rx_status
, *desc
, dma_size
;
1045 base
= unit
->device
;
1046 slot
= unit
->rx_slot
;
1047 desc
= unit
->rx_descs
[slot
];
1049 dma_size
= TX_DESC_SIZE
;
1050 CachePostDMA(unit
->rx_descs
, &dma_size
, 0);
1051 while(((rx_status
= LELong(desc
[RH_DESC_RXSTATUS
]))
1052 & RH_DESC_RXSTATUSF_INUSE
) == 0)
1054 if((rx_status
& RH_DESC_RXSTATUSF_OK
) != 0)
1056 packet_size
= ((rx_status
& RH_DESC_RXSTATUSF_LENGTH
)
1057 >> RH_DESC_RXSTATUSB_LENGTH
) - ETH_CRCSIZE
;
1058 buffer
= unit
->rx_buffers
[slot
];
1060 if(AddressFilter(unit
, buffer
+ ETH_PACKET_DEST
, base
))
1062 unit
->stats
.PacketsReceived
++;
1063 DistributeRXPacket(unit
, buffer
, packet_size
, base
);
1068 unit
->stats
.BadData
++;
1069 ReportEvents(unit
, S2EVENT_ERROR
| S2EVENT_HARDWARE
| S2EVENT_RX
,
1073 /* Mark descriptor as free for next time */
1075 desc
[RH_DESC_RXSTATUS
] = MakeLELong(RH_DESC_RXSTATUSF_INUSE
);
1077 /* Get next descriptor */
1079 slot
= (slot
+ 1) % RX_SLOT_COUNT
;
1080 desc
= unit
->rx_descs
[slot
];
1085 unit
->rx_slot
= slot
;
1091 /****i* rhine.device/DistributeRXPacket ************************************
1094 * DistributeRXPacket -- Send a packet to all appropriate destinations.
1097 * DistributeRXPacket(unit, frame)
1099 * VOID DistributeRXPacket(struct DevUnit *, UBYTE *);
1101 ****************************************************************************
1105 static VOID
DistributeRXPacket(struct DevUnit
*unit
, const UBYTE
*packet
,
1106 UWORD packet_size
, struct DevBase
*base
)
1108 BOOL is_orphan
= TRUE
, accepted
;
1110 struct IOSana2Req
*request
, *request_tail
;
1111 struct Opener
*opener
, *opener_tail
;
1112 struct TypeStats
*tracker
;
1114 /* Offer packet to every opener */
1116 opener
= (APTR
)unit
->openers
.mlh_Head
;
1117 opener_tail
= (APTR
)&unit
->openers
.mlh_Tail
;
1118 packet_type
= BEWord(*((UWORD
*)(packet
+ ETH_PACKET_TYPE
)));
1120 while(opener
!= opener_tail
)
1122 request
= (APTR
)opener
->read_port
.mp_MsgList
.lh_Head
;
1123 request_tail
= (APTR
)&opener
->read_port
.mp_MsgList
.lh_Tail
;
1126 /* Offer packet to each request until it's accepted */
1128 while(request
!= request_tail
&& !accepted
)
1130 if(request
->ios2_PacketType
== packet_type
)
1132 CopyPacket(unit
, request
, packet_size
, packet_type
,
1137 (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
1142 opener
= (APTR
)opener
->node
.mln_Succ
;
1145 /* If packet was unwanted, give it to S2_READORPHAN request */
1149 unit
->stats
.UnknownTypesReceived
++;
1150 if(!IsMsgPortEmpty(unit
->request_ports
[ADOPT_QUEUE
]))
1153 (APTR
)unit
->request_ports
[ADOPT_QUEUE
]->mp_MsgList
.lh_Head
,
1154 packet_size
, packet_type
, packet
, base
);
1158 /* Update remaining statistics */
1160 if(packet_type
<= ETH_MTU
)
1161 packet_type
= ETH_MTU
;
1163 FindTypeStats(unit
, &unit
->type_trackers
, packet_type
, base
);
1166 tracker
->stats
.PacketsReceived
++;
1167 tracker
->stats
.BytesReceived
+= packet_size
;
1175 /****i* rhine.device/CopyPacket ********************************************
1178 * CopyPacket -- Copy packet to client's buffer.
1181 * CopyPacket(unit, request, packet_size, packet_type,
1184 * VOID CopyPacket(struct DevUnit *, struct IOSana2Req *, UWORD, UWORD,
1187 ****************************************************************************
1191 static VOID
CopyPacket(struct DevUnit
*unit
, struct IOSana2Req
*request
,
1192 UWORD packet_size
, UWORD packet_type
, const UBYTE
*buffer
,
1193 struct DevBase
*base
)
1195 struct Opener
*opener
;
1196 BOOL filtered
= FALSE
;
1198 /* Set multicast and broadcast flags */
1200 request
->ios2_Req
.io_Flags
&= ~(SANA2IOF_BCAST
| SANA2IOF_MCAST
);
1201 if((*((ULONG
*)(buffer
+ ETH_PACKET_DEST
)) == 0xffffffff) &&
1202 (*((UWORD
*)(buffer
+ ETH_PACKET_DEST
+ 4)) == 0xffff))
1203 request
->ios2_Req
.io_Flags
|= SANA2IOF_BCAST
;
1204 else if((buffer
[ETH_PACKET_DEST
] & 0x1) != 0)
1205 request
->ios2_Req
.io_Flags
|= SANA2IOF_MCAST
;
1207 /* Set source and destination addresses and packet type */
1209 CopyMem(buffer
+ ETH_PACKET_SOURCE
, request
->ios2_SrcAddr
,
1211 CopyMem(buffer
+ ETH_PACKET_DEST
, request
->ios2_DstAddr
,
1213 request
->ios2_PacketType
= packet_type
;
1215 /* Adjust for cooked packet request */
1217 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
1219 packet_size
-= ETH_PACKET_DATA
;
1220 buffer
+= ETH_PACKET_DATA
;
1224 packet_size
+= 4; /* Needed for Shapeshifter & Fusion */
1226 request
->ios2_DataLength
= packet_size
;
1230 opener
= request
->ios2_BufferManagement
;
1231 if(request
->ios2_Req
.io_Command
== CMD_READ
&&
1232 opener
->filter_hook
!= NULL
)
1233 if(!CallHookPkt(opener
->filter_hook
, request
, (APTR
)buffer
))
1238 /* Copy packet into opener's buffer and reply packet */
1240 if(!opener
->rx_function(request
->ios2_Data
, (APTR
)buffer
,
1243 request
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
1244 request
->ios2_WireError
= S2WERR_BUFF_ERROR
;
1246 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
| S2EVENT_RX
,
1249 Remove((APTR
)request
);
1250 ReplyMsg((APTR
)request
);
1258 /****i* rhine.device/AddressFilter *****************************************
1261 * AddressFilter -- Determine if an RX packet should be accepted.
1264 * accept = AddressFilter(unit, address)
1266 * BOOL AddressFilter(struct DevUnit *, UBYTE *);
1268 ****************************************************************************
1272 static BOOL
AddressFilter(struct DevUnit
*unit
, UBYTE
*address
,
1273 struct DevBase
*base
)
1275 struct AddressRange
*range
, *tail
;
1278 UWORD address_right
;
1280 /* Check whether address is unicast/broadcast or multicast */
1282 address_left
= BELong(*((ULONG
*)address
));
1283 address_right
= BEWord(*((UWORD
*)(address
+ 4)));
1285 if(((address_left
& 0x01000000) != 0) &&
1286 !((address_left
== 0xffffffff) && (address_right
== 0xffff)))
1288 /* Check if this multicast address is wanted */
1290 range
= (APTR
)unit
->multicast_ranges
.mlh_Head
;
1291 tail
= (APTR
)&unit
->multicast_ranges
.mlh_Tail
;
1294 while((range
!= tail
) && !accept
)
1296 if((address_left
> range
->lower_bound_left
||
1297 address_left
== range
->lower_bound_left
&&
1298 address_right
>= range
->lower_bound_right
) &&
1299 (address_left
< range
->upper_bound_left
||
1300 address_left
== range
->upper_bound_left
&&
1301 address_right
<= range
->upper_bound_right
))
1303 range
= (APTR
)range
->node
.mln_Succ
;
1307 unit
->special_stats
[S2SS_ETHERNET_BADMULTICAST
& 0xffff]++;
1315 /****i* rhine.device/TXInt *************************************************
1318 * TXInt -- Soft interrupt for packet transmission.
1323 * VOID TXInt(struct DevUnit *);
1328 * unit - A unit of this device.
1333 ****************************************************************************
1337 static VOID
TXInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
))
1339 struct DevBase
*base
;
1340 UWORD packet_size
, data_size
, slot
, new_slot
, *p
, *q
, i
;
1341 struct IOSana2Req
*request
;
1342 BOOL proceed
= TRUE
;
1343 struct Opener
*opener
;
1344 ULONG wire_error
, *desc
, dma_size
, desc_p
, buffer_p
, txcontrol_value
;
1345 UBYTE
*(*dma_tx_function
)(REG(a0
, APTR
));
1348 struct MsgPort
*port
;
1350 base
= unit
->device
;
1351 port
= unit
->request_ports
[WRITE_QUEUE
];
1353 while(proceed
&& !IsMsgPortEmpty(port
))
1355 slot
= unit
->tx_in_slot
;
1356 new_slot
= (slot
+ 1) % TX_SLOT_COUNT
;
1358 if(new_slot
!= unit
->tx_out_slot
1359 && (unit
->flags
& UNITF_TXBUFFERINUSE
) == 0)
1363 /* Get request and DMA frame descriptor */
1365 request
= (APTR
)port
->mp_MsgList
.lh_Head
;
1367 Remove((APTR
)request
);
1368 unit
->tx_requests
[slot
] = request
;
1369 desc
= unit
->tx_descs
[slot
];
1370 desc_p
= unit
->tx_descs_p
[slot
];
1372 data_size
= packet_size
= request
->ios2_DataLength
;
1373 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
1374 packet_size
+= ETH_HEADERSIZE
;
1375 if(packet_size
< ETH_MINSIZE
)
1376 packet_size
= ETH_MINSIZE
;
1378 /* Decide if one or two descriptors are needed, and generate
1379 Ethernet header if necessary */
1381 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
1383 /* Use first descriptor for Ethernet header */
1385 buffer
= (UBYTE
*)desc
+ 2 * RH_DESCSIZE
;
1386 buffer_p
= desc_p
+ 2 * RH_DESCSIZE
;
1388 desc
[RH_DESC_TXCONTROL
] =
1389 MakeLELong(RH_DESC_TXCONTROLF_FIRSTFRAG
1390 | RH_DESC_TXCONTROLF_CHAIN
| ETH_HEADERSIZE
);
1391 desc
[RH_DESC_DATA
] = MakeLELong(buffer_p
);
1392 desc
[RH_DESC_NEXT
] = MakeLELong(desc_p
+ RH_DESCSIZE
);
1394 /* Write Ethernet header */
1396 p
= (UWORD
*)buffer
;
1397 for(i
= 0, q
= (UWORD
*)request
->ios2_DstAddr
;
1398 i
< ETH_ADDRESSSIZE
/ 2; i
++)
1400 for(i
= 0, q
= (UWORD
*)unit
->address
;
1401 i
< ETH_ADDRESSSIZE
/ 2; i
++)
1403 *p
++ = MakeBEWord(request
->ios2_PacketType
);
1405 /* Use spare second descriptor for frame data */
1407 desc
+= RH_DESCSIZE
/ 4;
1408 desc_p
+= RH_DESCSIZE
;
1410 txcontrol_value
= RH_DESC_TXCONTROLF_INT
1411 | RH_DESC_TXCONTROLF_LASTFRAG
1412 | RH_DESC_TXCONTROLF_CHAIN
1413 | packet_size
- ETH_HEADERSIZE
;
1417 txcontrol_value
= RH_DESC_TXCONTROLF_INT
1418 | RH_DESC_TXCONTROLF_FIRSTFRAG
| RH_DESC_TXCONTROLF_LASTFRAG
1419 | RH_DESC_TXCONTROLF_CHAIN
1423 /* Get packet data */
1425 opener
= (APTR
)request
->ios2_BufferManagement
;
1426 dma_tx_function
= opener
->dma_tx_function
;
1427 if(dma_tx_function
!= NULL
)
1428 buffer
= dma_tx_function(request
->ios2_Data
);
1434 buffer
= unit
->tx_buffer
;
1435 if(opener
->tx_function(buffer
, request
->ios2_Data
,
1438 unit
->flags
|= UNITF_TXBUFFERINUSE
;
1442 error
= S2ERR_NO_RESOURCES
;
1443 wire_error
= S2WERR_BUFF_ERROR
;
1445 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
1446 | S2EVENT_TX
, base
);
1449 unit
->tx_buffers
[slot
] = buffer
;
1451 /* Fill in descriptor for frame data */
1455 dma_size
= data_size
;
1456 buffer_p
= (ULONG
)(UPINT
)CachePreDMA(buffer
, &dma_size
,
1458 desc
[RH_DESC_TXCONTROL
] = MakeLELong(txcontrol_value
);
1459 desc
[RH_DESC_DATA
] = MakeLELong(buffer_p
);
1460 desc
[RH_DESC_NEXT
] = MakeLELong(unit
->tx_descs_p
[new_slot
]);
1462 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
1463 desc
-= RH_DESCSIZE
/ 4;
1465 desc
[RH_DESC_TXSTATUS
] = MakeLELong(RH_DESC_TXSTATUSF_INUSE
);
1470 /* Restart transmission if it had stopped */
1472 dma_size
= TX_DESC_SIZE
* TX_SLOT_COUNT
;
1473 CachePreDMA(unit
->tx_descs
, &dma_size
, 0);
1474 unit
->ByteOut(unit
->card
, RH_REG_CONTROL
,
1475 unit
->ByteIn(unit
->card
, RH_REG_CONTROL
)
1476 | RH_REG_CONTROLF_TXPOLL
);
1478 /* FIXME: Need IO-sync here for PPC etc.? */
1480 unit
->tx_in_slot
= new_slot
;
1484 /* Return failed request */
1486 request
->ios2_Req
.io_Error
= error
;
1487 request
->ios2_WireError
= wire_error
;
1488 ReplyMsg((APTR
)request
);
1496 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
1498 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_IGNORE
;
1505 /****i* rhine.device/TXEndInt **********************************************
1508 * TXEndInt -- Clean up after a frame has been sent.
1511 * TXEndInt(unit, int_code)
1513 * VOID TXEndInt(struct DevUnit *, APTR);
1516 * unit - A unit of this device.
1517 * int_code - Unused.
1522 ****************************************************************************
1524 * It appears to be safe to assume that there will always be at least one
1525 * completed packet whenever this interrupt is called.
1529 static VOID
TXEndInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
))
1531 UWORD data_size
, i
= 0;
1533 struct DevBase
*base
;
1534 ULONG
*desc
, dma_size
;
1535 BOOL proceed
= TRUE
;
1537 /* Retire sent packets */
1539 base
= unit
->device
;
1540 dma_size
= TX_DESC_SIZE
* TX_SLOT_COUNT
;
1541 CachePostDMA(unit
->tx_descs
, &dma_size
, 0);
1543 i
= unit
->tx_out_slot
;
1546 /* Skip to "spare" descriptor if valid */
1548 desc
= unit
->tx_descs
[i
];
1549 if((desc
[RH_DESC_TXCONTROL
] & RH_DESC_TXCONTROLF_LASTFRAG
) == 0)
1552 /* Check that descriptor is not in use */
1554 if((desc
[RH_DESC_TXSTATUS
] & MakeLELong(RH_DESC_TXSTATUSF_INUSE
))
1555 == 0 && i
!= unit
->tx_in_slot
)
1557 buffer
= unit
->tx_buffers
[i
];
1558 dma_size
= data_size
;
1559 CachePostDMA(buffer
, &dma_size
, DMA_ReadFromRAM
);
1561 /* Check if unit's buffer is now free */
1563 if(buffer
== unit
->tx_buffer
)
1564 unit
->flags
&= ~UNITF_TXBUFFERINUSE
;
1566 RetireTXSlot(unit
, i
, base
);
1568 i
= (i
+ 1) % TX_SLOT_COUNT
;
1574 unit
->tx_out_slot
= i
;
1576 dma_size
= TX_DESC_SIZE
* TX_SLOT_COUNT
;
1577 CachePreDMA(unit
->tx_descs
, &dma_size
, 0);
1579 /* Restart downloads if they had stopped */
1581 if(unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
== PA_IGNORE
)
1582 Cause(&unit
->tx_int
);
1589 /****i* rhine.device/RetireTXSlot ******************************************
1592 * RetireTXSlot -- Reply finished TX request.
1595 * RetireTXSlot(unit, slot)
1597 * VOID RetireTXSlot(struct DevUnit *, UWORD);
1599 ****************************************************************************
1603 static VOID
RetireTXSlot(struct DevUnit
*unit
, UWORD slot
,
1604 struct DevBase
*base
)
1607 struct IOSana2Req
*request
;
1608 struct TypeStats
*tracker
;
1610 /* Update statistics */
1612 slot
= unit
->tx_out_slot
;
1613 request
= unit
->tx_requests
[slot
];
1614 frame_size
= request
->ios2_DataLength
;
1615 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
1616 frame_size
+= ETH_HEADERSIZE
;
1618 unit
->stats
.PacketsSent
++;
1620 tracker
= FindTypeStats(unit
, &unit
->type_trackers
,
1621 request
->ios2_PacketType
, base
);
1624 tracker
->stats
.PacketsSent
++;
1625 tracker
->stats
.BytesSent
+= frame_size
;
1630 request
->ios2_Req
.io_Error
= 0;
1631 ReplyMsg((APTR
)request
);
1638 /****i* rhine.device/ResetHandler ******************************************
1641 * ResetHandler -- Disable hardware before a reboot.
1644 * ResetHandler(unit, int_code)
1646 * VOID ResetHandler(struct DevUnit *, APTR);
1648 ****************************************************************************
1652 static VOID
ResetHandler(REG(a1
, struct DevUnit
*unit
),
1653 REG(a6
, APTR int_code
))
1655 if((unit
->flags
& UNITF_HAVEADAPTER
) != 0)
1657 /* Disable frame transmission and reception */
1659 unit
->LEWordOut(unit
->card
, RH_REG_CONTROL
, RH_REG_CONTROLF_STOP
);
1661 /* Stop interrupts */
1663 unit
->LEWordOut(unit
->card
, RH_REG_INTMASK
, 0);
1672 /****i* rhine.device/ReportEvents ******************************************
1678 * ReportEvents(unit, events)
1680 * VOID ReportEvents(struct DevUnit *, ULONG);
1685 * unit - A unit of this device.
1686 * events - A mask of events to report.
1691 ****************************************************************************
1695 static VOID
ReportEvents(struct DevUnit
*unit
, ULONG events
,
1696 struct DevBase
*base
)
1698 struct IOSana2Req
*request
, *tail
, *next_request
;
1701 list
= &unit
->request_ports
[EVENT_QUEUE
]->mp_MsgList
;
1702 next_request
= (APTR
)list
->lh_Head
;
1703 tail
= (APTR
)&list
->lh_Tail
;
1706 while(next_request
!= tail
)
1708 request
= next_request
;
1709 next_request
= (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
1711 if((request
->ios2_WireError
& events
) != 0)
1713 request
->ios2_WireError
= events
;
1714 Remove((APTR
)request
);
1715 ReplyMsg((APTR
)request
);
1725 /****i* rhine.device/UnitTask **********************************************
1736 * Completes deferred requests, and handles card insertion and removal
1737 * in conjunction with the relevant interrupts.
1739 ****************************************************************************
1743 static VOID
UnitTask(struct ExecBase
*sys_base
)
1746 struct IORequest
*request
;
1747 struct DevUnit
*unit
;
1748 struct DevBase
*base
;
1749 struct MsgPort
*general_port
;
1750 ULONG signals
= 0, wait_signals
, card_removed_signal
,
1751 card_inserted_signal
, general_port_signal
;
1753 /* Get parameters */
1755 task
= FindTask(NULL
);
1756 unit
= task
->tc_UserData
;
1757 base
= unit
->device
;
1759 /* Activate general request port */
1761 general_port
= unit
->request_ports
[GENERAL_QUEUE
];
1762 general_port
->mp_SigTask
= task
;
1763 general_port
->mp_SigBit
= AllocSignal(-1);
1764 general_port_signal
= 1 << general_port
->mp_SigBit
;
1765 general_port
->mp_Flags
= PA_SIGNAL
;
1767 /* Allocate signals for notification of card removal and insertion */
1769 card_removed_signal
= unit
->card_removed_signal
= 1 << AllocSignal(-1);
1770 card_inserted_signal
= unit
->card_inserted_signal
= 1 << AllocSignal(-1);
1771 wait_signals
= (1 << general_port
->mp_SigBit
) | card_removed_signal
1772 | card_inserted_signal
| SIGBREAKF_CTRL_C
;
1774 /* Tell ourselves to check port for old messages */
1776 Signal(task
, general_port_signal
);
1778 /* Infinite loop to service requests and signals */
1782 signals
= Wait(wait_signals
);
1784 if((signals
& card_inserted_signal
) != 0)
1786 if(unit
->insertion_function(unit
->card
, base
))
1788 unit
->flags
|= UNITF_HAVEADAPTER
;
1789 if((unit
->flags
& UNITF_CONFIGURED
) != 0)
1790 ConfigureAdapter(unit
, base
);
1791 if((unit
->flags
& UNITF_WASONLINE
) != 0)
1793 GoOnline(unit
, base
);
1794 unit
->flags
&= ~UNITF_WASONLINE
;
1799 if((signals
& card_removed_signal
) != 0)
1801 unit
->removal_function(unit
->card
, base
);
1802 if((unit
->flags
& UNITF_WASONLINE
) != 0)
1803 GoOffline(unit
, base
);
1806 if((signals
& general_port_signal
) != 0)
1808 while((request
= (APTR
)GetMsg(general_port
)) != NULL
)
1810 /* Service the request as soon as the unit is free */
1812 ObtainSemaphore(&unit
->access_lock
);
1813 ServiceRequest((APTR
)request
, base
);
1821 /****i* rhine.device/ReadMII ***********************************************
1824 * ReadMII -- Read a register in an MII PHY.
1827 * value = ReadMII(unit, phy_no, reg_no)
1829 * UWORD ReadMII(struct DevUnit *, UWORD, UWORD);
1832 * unit - A unit of this device.
1833 * phy_no - Index of PHY to use.
1834 * reg_no - MII register to read.
1837 * value - Value read from MII register.
1839 ****************************************************************************
1843 UWORD
ReadMII(struct DevUnit
*unit
, UWORD phy_no
, UWORD reg_no
,
1844 struct DevBase
*base
)
1846 while((unit
->ByteIn(unit
->card
, RH_REG_MIICTRL
)
1847 & (RH_REG_MIICTRLF_READ
| RH_REG_MIICTRLF_WRITE
)) != 0);
1849 unit
->ByteOut(unit
->card
, RH_REG_MIICTRL
, 0);
1850 unit
->ByteOut(unit
->card
, RH_REG_MIICONFIG
, phy_no
);
1851 unit
->ByteOut(unit
->card
, RH_REG_MIIREGNO
, reg_no
);
1852 unit
->ByteOut(unit
->card
, RH_REG_MIICTRL
, RH_REG_MIICTRLF_READ
);
1853 while((unit
->ByteIn(unit
->card
, RH_REG_MIICTRL
)
1854 & (RH_REG_MIICTRLF_READ
| RH_REG_MIICTRLF_WRITE
)) != 0);
1856 return unit
->LEWordIn(unit
->card
, RH_REG_MIIDATA
);