3 Copyright (C) 2001-2005 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,
23 #include <exec/memory.h>
24 #include <exec/execbase.h>
25 #include <exec/errors.h>
27 #include <proto/exec.h>
29 #include <proto/alib.h>
31 #include <clib/alib_protos.h>
33 #include <proto/utility.h>
34 #include <proto/timer.h>
37 #include "intelpro100.h"
41 #include "unit_protos.h"
42 #include "request_protos.h"
45 #define TASK_PRIORITY 0
46 #define STACK_SIZE 4096
47 #define CONFIG_DATA_LEN 6
49 #define MAX_MCAST_ENTRIES 100
50 #define MCAST_CB_SIZE (PROCB_COUNT * sizeof(ULONG) + sizeof(UWORD) \
51 + ETH_ADDRESSSIZE * MAX_MCAST_ENTRIES)
54 #define AbsExecBase (*(struct ExecBase **)4)
57 static VOID
InitialiseAdapter(struct DevUnit
*unit
, struct DevBase
*base
);
58 static VOID
FillConfigData(struct DevUnit
*unit
, ULONG
*tcb
,
59 struct DevBase
*base
);
60 static struct AddressRange
*FindMulticastRange(struct DevUnit
*unit
,
61 ULONG lower_bound_left
, UWORD lower_bound_right
, ULONG upper_bound_left
,
62 UWORD upper_bound_right
, struct DevBase
*base
);
63 static VOID
SetMulticast(struct DevUnit
*unit
, struct DevBase
*base
);
64 static BOOL
StatusInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
));
65 static VOID
RXInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
));
66 static VOID
CopyPacket(struct DevUnit
*unit
, struct IOSana2Req
*request
,
67 UWORD packet_size
, UWORD packet_type
, UBYTE
*buffer
,
68 struct DevBase
*base
);
69 static BOOL
AddressFilter(struct DevUnit
*unit
, UBYTE
*address
,
70 struct DevBase
*base
);
71 static VOID
TXInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
));
72 static VOID
TXEndInt(REG(a1
, struct DevUnit
*unit
),
73 REG(a5
, APTR int_code
));
74 static VOID
ReportEvents(struct DevUnit
*unit
, ULONG events
,
75 struct DevBase
*base
);
76 static VOID
UnitTask();
77 static UWORD
GetEEPROMAddressSize(struct DevUnit
*unit
,
78 struct DevBase
*base
);
79 static UWORD
ReadEEPROM(struct DevUnit
*unit
, UWORD index
,
80 struct DevBase
*base
);
81 static ULONG
ReadEEPROMBits(struct DevUnit
*unit
, UBYTE count
,
82 struct DevBase
*base
);
83 static VOID
WriteEEPROMBits(struct DevUnit
*unit
, ULONG value
, UBYTE count
,
84 struct DevBase
*base
);
85 static BOOL
ReadEEPROMBit(struct DevUnit
*unit
, struct DevBase
*base
);
86 static BOOL
WriteEEPROMBit(struct DevUnit
*unit
, BOOL is_one
,
87 struct DevBase
*base
);
88 static UWORD
ReadMII(struct DevUnit
*unit
, UWORD phy_no
, UWORD reg_no
,
89 struct DevBase
*base
);
90 static VOID
WriteMII(struct DevUnit
*unit
, UWORD phy_no
, UWORD reg_no
,
91 UWORD value
, struct DevBase
*base
);
92 static VOID
BusyMicroDelay(ULONG micros
, struct DevBase
*base
);
96 static const ULONG config_data
[] =
98 8 << PROCB_CF0B_RXFIFOLIM
| 22 << PROCB_CF0B_SIZE
,
99 1 << PROCB_CF1B_UNDERRUNRETRIES
| PROCB_CF1F_DISCARDRUNTS
100 | PROCB_CF1F_STDSTATS
| PROCB_CF1F_STDTXBLOCK
| 0x00020000,
101 2 << PROCB_CF2B_PREAMBLETYPE
| PROCB_CF2F_NOSOURCEINSERT
| 0x00060001,
102 0xf200 << PROCB_CF3B_ARPFILTER
| 6 << PROCB_CF3B_IFS
| 0x48000000,
103 PROCB_CF4F_USEFDPIN
| PROCB_CF4F_PADDING
| 0x00f04000,
110 #define AddTask(task, initial_pc, final_pc) \
111 IExec->AddTask(task, initial_pc, final_pc, NULL)
114 static const struct EmulLibEntry mos_task_trap
=
120 #define UnitTask &mos_task_trap
124 /****i* intelpro100.device/CreateUnit **************************************
127 * CreateUnit -- Create a unit.
130 * unit = CreateUnit(index, card, io_tags, bus)
132 * struct DevUnit *CreateUnit(ULONG, APTR, struct TagItem *, UWORD);
135 * Creates a new unit.
137 ****************************************************************************
141 struct DevUnit
*CreateUnit(ULONG index
, APTR card
,
142 const struct TagItem
*io_tags
, UWORD bus
, struct DevBase
*base
)
145 struct DevUnit
*unit
;
147 struct MsgPort
*port
;
150 ULONG
*tcb
, *next_tcb
, *rcb
, *next_rcb
, dma_size
;
151 APTR rx_int_function
, tx_int_function
;
153 unit
= AllocMem(sizeof(struct DevUnit
), MEMF_CLEAR
| MEMF_PUBLIC
);
159 /* Initialise lists etc. */
161 InitSemaphore(&unit
->access_lock
);
162 NewList((APTR
)&unit
->openers
);
163 NewList((APTR
)&unit
->type_trackers
);
164 NewList((APTR
)&unit
->multicast_ranges
);
165 NewList((APTR
)&unit
->tx_requests
);
172 /* Store I/O hooks */
175 (APTR
)GetTagData(IOTAG_ByteIn
, (UPINT
)NULL
, io_tags
);
177 (APTR
)GetTagData(IOTAG_ByteOut
, (UPINT
)NULL
, io_tags
);
179 (APTR
)GetTagData(IOTAG_LEWordIn
, (UPINT
)NULL
, io_tags
);
181 (APTR
)GetTagData(IOTAG_LELongIn
, (UPINT
)NULL
, io_tags
);
183 (APTR
)GetTagData(IOTAG_LEWordOut
, (UPINT
)NULL
, io_tags
);
185 (APTR
)GetTagData(IOTAG_LELongOut
, (UPINT
)NULL
, io_tags
);
187 (APTR
)GetTagData(IOTAG_AllocDMAMem
, (UPINT
)NULL
, io_tags
);
189 (APTR
)GetTagData(IOTAG_FreeDMAMem
, (UPINT
)NULL
, io_tags
);
190 if(unit
->ByteIn
== NULL
191 || unit
->ByteOut
== NULL
192 || unit
->LEWordIn
== NULL
193 || unit
->LEWordOut
== NULL
|| unit
->LELongIn
== NULL
194 || unit
->LELongOut
== NULL
195 || unit
->AllocDMAMem
== NULL
|| unit
->FreeDMAMem
== NULL
)
198 /* Allocate buffer for adapter to writes statistics to */
201 AllocVec(sizeof(ULONG
) * (STAT_COUNT
+ 1), MEMF_PUBLIC
);
202 if(unit
->stats_buffer
== NULL
)
208 /* Initialise network adapter hardware */
210 InitialiseAdapter(unit
, base
);
211 unit
->flags
|= UNITF_HAVEADAPTER
;
213 /* Create the message ports for queuing requests */
215 for(i
= 0; i
< REQUEST_QUEUE_COUNT
; i
++)
217 unit
->request_ports
[i
] = port
= AllocMem(sizeof(struct MsgPort
),
218 MEMF_PUBLIC
| MEMF_CLEAR
);
224 NewList(&port
->mp_MsgList
);
225 port
->mp_Flags
= PA_IGNORE
;
226 port
->mp_SigTask
= &unit
->tx_int
;
230 /* Allocate and initialise packet/command descriptors */
232 unit
->tx_buffer
= AllocVec(ETH_MAXPACKETSIZE
, MEMF_PUBLIC
);
233 next_tcb
= unit
->first_tcb
= unit
->tcbs
=
234 AllocVec(TCB_SIZE
* TX_SLOT_COUNT
, MEMF_PUBLIC
| MEMF_CLEAR
);
235 next_rcb
= unit
->rcbs
=
236 AllocVec(RCB_SIZE
* RX_SLOT_COUNT
, MEMF_PUBLIC
| MEMF_CLEAR
);
237 unit
->multicast_cb
= AllocVec(PROCB_COUNT
* sizeof(ULONG
)
238 + sizeof(UWORD
) + ETH_ADDRESSSIZE
* MAX_MCAST_ENTRIES
,
239 MEMF_PUBLIC
| MEMF_CLEAR
);
241 if(next_tcb
== NULL
|| next_rcb
== NULL
|| unit
->tx_buffer
== NULL
242 || unit
->multicast_cb
== NULL
)
248 /* Construct TX ring */
250 for(i
= 0; i
< TX_SLOT_COUNT
; i
++)
253 next_tcb
= tcb
+ TCB_SIZE
/ sizeof(ULONG
);
254 tcb
[PROCB_NEXT
] = MakeLELong((ULONG
)next_tcb
);
256 tcb
[PROCB_NEXT
] = MakeLELong((ULONG
)unit
->tcbs
);
257 unit
->last_tcb
= tcb
;
259 /* Construct RX ring */
261 for(i
= 0; i
< RX_SLOT_COUNT
; i
++)
264 next_rcb
= rcb
+ RCB_SIZE
/ sizeof(ULONG
);
265 rcb
[PROCB_NEXT
] = MakeLELong((ULONG
)next_rcb
);
267 MakeLELong(ETH_MAXPACKETSIZE
<< PROCB_RXINFOB_BUFFERSIZE
);
269 rcb
[PROCB_CONTROL
] = MakeLELong(PROCB_CONTROLF_SUSPEND
);
270 rcb
[PROCB_NEXT
] = MakeLELong((ULONG
)unit
->rcbs
);
271 unit
->last_rcb
= rcb
;
272 dma_size
= RCB_SIZE
* RX_SLOT_COUNT
;
273 CachePreDMA(unit
->rcbs
, &dma_size
, 0);
275 /* Record maximum speed in BPS */
277 unit
->speed
= 100000000;
279 /* Initialise status, transmit and receive interrupts */
281 unit
->status_int
.is_Code
= (APTR
)StatusInt
;
282 unit
->status_int
.is_Data
= unit
;
284 rx_int_function
= RXInt
;
285 unit
->rx_int
.is_Node
.ln_Name
= (TEXT
*)device_name
;
286 unit
->rx_int
.is_Node
.ln_Pri
= 16;
287 unit
->rx_int
.is_Code
= rx_int_function
;
288 unit
->rx_int
.is_Data
= unit
;
290 tx_int_function
= TXInt
;
291 unit
->tx_int
.is_Node
.ln_Name
= (TEXT
*)device_name
;
292 unit
->tx_int
.is_Code
= tx_int_function
;
293 unit
->tx_int
.is_Data
= unit
;
295 unit
->tx_end_int
.is_Node
.ln_Name
= (TEXT
*)device_name
;
296 unit
->tx_end_int
.is_Code
= TXEndInt
;
297 unit
->tx_end_int
.is_Data
= unit
;
299 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
304 /* Create a new task */
307 AllocMem(sizeof(struct Task
), MEMF_PUBLIC
| MEMF_CLEAR
);
316 stack
= AllocMem(STACK_SIZE
, MEMF_PUBLIC
);
323 /* Initialise and start task */
325 task
->tc_Node
.ln_Type
= NT_TASK
;
326 task
->tc_Node
.ln_Pri
= TASK_PRIORITY
;
327 task
->tc_Node
.ln_Name
= (APTR
)device_name
;
328 task
->tc_SPUpper
= stack
+ STACK_SIZE
;
329 task
->tc_SPLower
= stack
;
330 task
->tc_SPReg
= stack
+ STACK_SIZE
;
331 NewList(&task
->tc_MemEntry
);
333 if(AddTask(task
, UnitTask
, NULL
) == NULL
)
337 /* Send the unit to the new task */
340 task
->tc_UserData
= unit
;
344 DeleteUnit(unit
, base
);
353 /****i* intelpro100.device/DeleteUnit **************************************
356 * DeleteUnit -- Delete a unit.
361 * VOID DeleteUnit(struct DevUnit *);
367 * unit - Device unit (can be NULL).
372 ****************************************************************************
376 VOID
DeleteUnit(struct DevUnit
*unit
, struct DevBase
*base
)
386 if(task
->tc_UserData
!= NULL
)
388 if(task
->tc_SPLower
!= NULL
)
389 FreeMem(task
->tc_SPLower
, STACK_SIZE
);
390 FreeMem(task
, sizeof(struct Task
));
393 for(i
= 0; i
< REQUEST_QUEUE_COUNT
; i
++)
395 if(unit
->request_ports
[i
] != NULL
)
396 FreeMem(unit
->request_ports
[i
], sizeof(struct MsgPort
));
399 if((unit
->flags
& UNITF_ONLINE
) != 0) /* Needed! */
400 GoOffline(unit
, base
);
402 FreeVec(unit
->multicast_cb
);
405 FreeVec(unit
->tx_buffer
);
406 FreeVec(unit
->stats_buffer
);
408 FreeMem(unit
, sizeof(struct DevUnit
));
416 /****i* intelpro100.device/InitialiseAdapter *******************************
419 * InitialiseAdapter -- Initialise network adapter hardware.
422 * InitialiseAdapter(unit)
424 * VOID InitialiseAdapter(struct DevUnit *);
432 ****************************************************************************
436 static VOID
InitialiseAdapter(struct DevUnit
*unit
, struct DevBase
*base
)
443 unit
->LELongOut(unit
->card
, PROREG_PORT
, 0);
444 BusyMicroDelay(10, base
);
446 /* Get default MAC address */
448 unit
->eeprom_addr_size
= GetEEPROMAddressSize(unit
, base
);
449 p
= unit
->default_address
;
451 for(i
= 0; i
< ETH_ADDRESSSIZE
/ sizeof(UWORD
); i
++)
453 address_part
= ReadEEPROM(unit
, PROROM_ADDRESS0
+ i
, base
);
454 *p
++ = address_part
& 0xff;
455 *p
++ = address_part
>> 8;
458 /* Set up statistics dump area */
460 unit
->LELongOut(unit
->card
, PROREG_GENPTR
, (ULONG
)unit
->stats_buffer
);
461 unit
->LEWordOut(unit
->card
, PROREG_COMMAND
, PRO_CUCMD_SETSTATSBUFFER
);
462 while(unit
->LEWordIn(unit
->card
, PROREG_COMMAND
) != 0);
471 /****i* intelpro100.device/ConfigureAdapter ********************************
474 * ConfigureAdapter -- Put adapter online for the first time.
477 * ConfigureAdapter(unit)
479 * VOID ConfigureAdapter(struct DevUnit *);
487 ****************************************************************************
491 VOID
ConfigureAdapter(struct DevUnit
*unit
, struct DevBase
*base
)
493 ULONG
*tcb
, dma_size
;
494 UWORD phy_type
, phy_no
, config
;
496 /* Set MAC address */
498 tcb
= (ULONG
*)LELong(unit
->last_tcb
[PROCB_NEXT
]);
499 tcb
[PROCB_CONTROL
] = MakeLELong(PROACT_SETADDRESS
);
500 CopyMem(&unit
->address
, tcb
+ PROCB_ADDRESS
, ETH_ADDRESSSIZE
);
502 /* Set other parameters */
504 tcb
= (ULONG
*)LELong(tcb
[PROCB_NEXT
]);
506 MakeLELong(PROACT_CONFIGURE
| PROCB_CONTROLF_SUSPEND
);
507 unit
->phy_info
= ReadEEPROM(unit
, PROROM_PHYINFO0
, base
);
508 FillConfigData(unit
, tcb
, base
);
509 unit
->last_tcb
= tcb
;
511 dma_size
= TCB_SIZE
* TX_SLOT_COUNT
;
512 CachePreDMA(unit
->tcbs
, &dma_size
, 0);
514 /* DP83840-specific configuration */
516 phy_type
= unit
->phy_info
& PROROM_PHYINFO0F_TYPE
;
517 if(phy_type
== PRO_PHY_DP83840
|| phy_type
== PRO_PHY_DP83840A
)
519 phy_no
= unit
->phy_info
& PROROM_PHYINFO0F_ADDR
;
520 config
= ReadMII(unit
, phy_no
, MII_PCR
, base
);
521 config
|= 0x400 | MII_PCRF_NOLINKMON
| MII_PCRF_LED4DUPLEX
;
522 WriteMII(unit
, phy_no
, MII_PCR
, config
, base
);
527 unit
->LELongOut(unit
->card
, PROREG_GENPTR
, (ULONG
)unit
->tcbs
);
528 unit
->LEWordOut(unit
->card
, PROREG_COMMAND
, PRO_CUCMD_START
);
529 while(unit
->LEWordIn(unit
->card
, PROREG_COMMAND
) != 0);
530 GoOnline(unit
, base
);
539 /****i* intelpro100.device/FillConfigData **********************************
542 * FillConfigData -- Fill in the data for a configuration command.
545 * FillConfigData(unit, tcb)
547 * VOID FillConfigData(struct DevUnit *, ULONG *);
550 * unit - A unit of this device.
551 * tcb - The configuration command block.
556 ****************************************************************************
560 static VOID
FillConfigData(struct DevUnit
*unit
, ULONG
*tcb
,
561 struct DevBase
*base
)
567 /* Copy constant parameters from template */
569 for(p
= config_data
, q
= tcb
+ PROCB_CF0
, i
= 0; i
< CONFIG_DATA_LEN
;
571 *q
++ = MakeLELong(*p
++);
572 unit
->last_tcb
= tcb
;
574 /* Decide on promiscuous mode */
576 if((unit
->flags
& UNITF_PROM
) != 0)
577 tcb
[PROCB_CF3
] |= MakeLELong(PROCB_CF3F_PROM
);
581 if((unit
->phy_info
& PROROM_PHYINFO0F_AUI
) != 0)
582 tcb
[PROCB_CF3
] |= MakeLELong(PROCB_CF3F_CDT
);
584 tcb
[PROCB_CF2
] |= MakeLELong(PROCB_CF2F_MIIMODE
);
586 /* Accept all multicasts? */
588 if((unit
->flags
& UNITF_ALLMCAST
) != 0)
590 tcb
[PROCB_CF5
] |= MakeLELong(PROCB_CF5F_ALLMCAST
);
600 /****i* intelpro100.device/GoOnline ****************************************
603 * GoOnline -- Put the adapter online.
608 * VOID GoOnline(struct DevUnit *);
611 * unit - A unit of this device.
616 ****************************************************************************
620 VOID
GoOnline(struct DevUnit
*unit
, struct DevBase
*base
)
622 /* Enable the transceiver */
624 unit
->flags
|= UNITF_ONLINE
;
626 unit
->LELongOut(unit
->card
, PROREG_GENPTR
,
627 LELong(unit
->last_rcb
[PROCB_NEXT
]));
628 unit
->LEWordOut(unit
->card
, PROREG_COMMAND
, PRO_RUCMD_START
);
629 while(unit
->LEWordIn(unit
->card
, PROREG_COMMAND
) != 0);
631 /* Record start time and report Online event */
633 GetSysTime(&unit
->stats
.LastStart
);
634 ReportEvents(unit
, S2EVENT_ONLINE
, base
);
641 /****i* intelpro100.device/GoOffline ***************************************
644 * GoOffline -- Put the adpater offline.
649 * VOID GoOffline(struct DevUnit *);
652 * unit - A unit of this device.
657 ****************************************************************************
661 VOID
GoOffline(struct DevUnit
*unit
, struct DevBase
*base
)
663 unit
->flags
&= ~UNITF_ONLINE
;
665 if((unit
->flags
& UNITF_HAVEADAPTER
) != 0)
669 unit
->LEWordOut(unit
->card
, PROREG_COMMAND
, PRO_RUCMD_ABORT
);
671 /* Update statistics */
673 UpdateStats(unit
, base
);
676 /* Flush pending read and write requests */
678 FlushUnit(unit
, WRITE_QUEUE
, S2ERR_OUTOFSERVICE
, base
);
680 /* Report Offline event and return */
682 ReportEvents(unit
, S2EVENT_OFFLINE
, base
);
688 /****i* intelpro100.device/AddMulticastRange *******************************
694 * success = AddMulticastRange(unit, lower_bound, upper_bound)
696 * BOOL AddMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
698 ****************************************************************************
702 BOOL
AddMulticastRange(struct DevUnit
*unit
, const UBYTE
*lower_bound
,
703 const UBYTE
*upper_bound
, struct DevBase
*base
)
705 struct AddressRange
*range
;
706 ULONG lower_bound_left
, upper_bound_left
;
707 UWORD lower_bound_right
, upper_bound_right
;
709 lower_bound_left
= BELong(*((ULONG
*)lower_bound
));
710 lower_bound_right
= BEWord(*((UWORD
*)(lower_bound
+ 4)));
711 upper_bound_left
= BELong(*((ULONG
*)upper_bound
));
712 upper_bound_right
= BEWord(*((UWORD
*)(upper_bound
+ 4)));
714 range
= FindMulticastRange(unit
, lower_bound_left
, lower_bound_right
,
715 upper_bound_left
, upper_bound_right
, base
);
721 range
= AllocMem(sizeof(struct AddressRange
), MEMF_PUBLIC
);
724 range
->lower_bound_left
= lower_bound_left
;
725 range
->lower_bound_right
= lower_bound_right
;
726 range
->upper_bound_left
= upper_bound_left
;
727 range
->upper_bound_right
= upper_bound_right
;
728 range
->add_count
= 1;
731 AddTail((APTR
)&unit
->multicast_ranges
, (APTR
)range
);
736 return range
!= NULL
;
741 /****i* intelpro100.device/RemMulticastRange *******************************
747 * found = RemMulticastRange(unit, lower_bound, upper_bound)
749 * BOOL RemMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
751 ****************************************************************************
755 BOOL
RemMulticastRange(struct DevUnit
*unit
, const UBYTE
*lower_bound
,
756 const UBYTE
*upper_bound
, struct DevBase
*base
)
758 struct AddressRange
*range
;
759 ULONG lower_bound_left
, upper_bound_left
;
760 UWORD lower_bound_right
, upper_bound_right
;
762 lower_bound_left
= BELong(*((ULONG
*)lower_bound
));
763 lower_bound_right
= BEWord(*((UWORD
*)(lower_bound
+ 4)));
764 upper_bound_left
= BELong(*((ULONG
*)upper_bound
));
765 upper_bound_right
= BEWord(*((UWORD
*)(upper_bound
+ 4)));
767 range
= FindMulticastRange(unit
, lower_bound_left
, lower_bound_right
,
768 upper_bound_left
, upper_bound_right
, base
);
772 if(--range
->add_count
== 0)
777 FreeMem(range
, sizeof(struct AddressRange
));
781 return range
!= NULL
;
786 /****i* intelpro100.device/FindMulticastRange ******************************
792 * range = FindMulticastRange(unit, lower_bound_left,
793 * lower_bound_right, upper_bound_left, upper_bound_right)
795 * struct AddressRange *FindMulticastRange(struct DevUnit *, ULONG,
796 * UWORD, ULONG, UWORD);
798 ****************************************************************************
802 static struct AddressRange
*FindMulticastRange(struct DevUnit
*unit
,
803 ULONG lower_bound_left
, UWORD lower_bound_right
, ULONG upper_bound_left
,
804 UWORD upper_bound_right
, struct DevBase
*base
)
806 struct AddressRange
*range
, *tail
;
809 range
= (APTR
)unit
->multicast_ranges
.mlh_Head
;
810 tail
= (APTR
)&unit
->multicast_ranges
.mlh_Tail
;
812 while((range
!= tail
) && !found
)
814 if((lower_bound_left
== range
->lower_bound_left
) &&
815 (lower_bound_right
== range
->lower_bound_right
) &&
816 (upper_bound_left
== range
->upper_bound_left
) &&
817 (upper_bound_right
== range
->upper_bound_right
))
820 range
= (APTR
)range
->node
.mln_Succ
;
831 /****i* intelpro100.device/SetMulticast ************************************
839 * VOID SetMulticast(struct DevUnit *);
842 * Fills in the unit's multicast list TCB, but does not send it to the
845 ****************************************************************************
849 static VOID
SetMulticast(struct DevUnit
*unit
, struct DevBase
*base
)
851 ULONG
*tcb
, address_left
;
852 UWORD address_right
, i
= 0, *p
;
853 struct AddressRange
*range
, *tail
;
856 tcb
= unit
->multicast_cb
;
858 if((unit
->flags
& UNITF_PROM
) == 0)
860 /* Fill in multicast list */
862 range
= (APTR
)unit
->multicast_ranges
.mlh_Head
;
863 tail
= (APTR
)&unit
->multicast_ranges
.mlh_Tail
;
864 p
= (UWORD
*)(tcb
+ PROCB_COUNT
);
866 while(range
!= tail
&& i
< MAX_MCAST_ENTRIES
)
868 address_left
= range
->lower_bound_left
;
869 address_right
= range
->lower_bound_right
;
872 while(!range_ended
&& i
++ < MAX_MCAST_ENTRIES
)
874 *p
++ = MakeBEWord((UWORD
)(address_left
>> 16));
875 *p
++ = MakeBEWord((UWORD
)(address_left
));
876 *p
++ = MakeBEWord((UWORD
)(address_right
));
878 if(address_left
== range
->upper_bound_left
&&
879 address_right
== range
->upper_bound_right
)
883 if(++address_right
== 0)
888 range
= (APTR
)range
->node
.mln_Succ
;
890 p
= (UWORD
*)(tcb
+ PROCB_COUNT
);
891 *p
= MakeLEWord(ETH_ADDRESSSIZE
* i
);
893 /* Accept all multicasts if there are too many addresses */
896 unit
->flags
|= UNITF_ALLMCAST
;
898 unit
->flags
&= ~UNITF_ALLMCAST
;
906 /****i* intelpro100.device/FindTypeStats ***********************************
912 * stats = FindTypeStats(unit, list,
915 * struct TypeStats *FindTypeStats(struct DevUnit *, struct MinList *,
918 ****************************************************************************
922 struct TypeStats
*FindTypeStats(struct DevUnit
*unit
, struct MinList
*list
,
923 ULONG packet_type
, struct DevBase
*base
)
925 struct TypeStats
*stats
, *tail
;
928 stats
= (APTR
)list
->mlh_Head
;
929 tail
= (APTR
)&list
->mlh_Tail
;
931 while((stats
!= tail
) && !found
)
933 if(stats
->packet_type
== packet_type
)
936 stats
= (APTR
)stats
->node
.mln_Succ
;
947 /****i* intelpro100.device/FlushUnit ***************************************
953 * FlushUnit(unit, last_queue, error)
955 * VOID FlushUnit(struct DevUnit *, UBYTE, BYTE);
957 ****************************************************************************
961 VOID
FlushUnit(struct DevUnit
*unit
, UBYTE last_queue
, BYTE error
,
962 struct DevBase
*base
)
964 struct IORequest
*request
;
966 struct Opener
*opener
, *tail
;
968 /* Abort queued requests */
970 for(i
= 0; i
<= last_queue
; i
++)
972 while((request
= (APTR
)GetMsg(unit
->request_ports
[i
])) != NULL
)
974 request
->io_Error
= IOERR_ABORTED
;
975 ReplyMsg((APTR
)request
);
980 opener
= (APTR
)unit
->openers
.mlh_Head
;
981 tail
= (APTR
)&unit
->openers
.mlh_Tail
;
983 /* Flush every opener's read queue */
985 while(opener
!= tail
)
987 while((request
= (APTR
)GetMsg(&opener
->read_port
)) != NULL
)
989 request
->io_Error
= error
;
990 ReplyMsg((APTR
)request
);
992 opener
= (APTR
)opener
->node
.mln_Succ
;
996 opener
= request
->ios2_BufferManagement
;
997 while((request
= (APTR
)GetMsg(&opener
->read_port
)) != NULL
)
999 request
->io_Error
= IOERR_ABORTED
;
1000 ReplyMsg((APTR
)request
);
1011 /****i* intelpro100.device/StatusInt ***************************************
1017 * finished = StatusInt(unit)
1019 * BOOL StatusInt(struct DevUnit *);
1022 * unit - A unit of this device.
1025 * finished - Always FALSE.
1027 ****************************************************************************
1031 static BOOL
StatusInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
))
1033 struct DevBase
*base
;
1036 base
= unit
->device
;
1037 ints
= unit
->ByteIn(unit
->card
, PROREG_INTSTATUS
);
1041 /* Handle interrupts */
1043 if((ints
& PROINTF_GENERAL
) != 0)
1044 Cause(&unit
->tx_end_int
);
1045 if((ints
& PROINTF_RXDONE
) != 0)
1046 Cause(&unit
->rx_int
);
1048 /* Acknowledge all interrupts */
1050 unit
->ByteOut(unit
->card
, PROREG_INTSTATUS
, 0xff);
1058 /****i* intelpro100.device/RXInt *******************************************
1066 * VOID RXInt(struct DevUnit *);
1069 * unit - A unit of this device.
1070 * int_code - Unused.
1075 ****************************************************************************
1079 static VOID
RXInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
))
1082 struct DevBase
*base
;
1083 BOOL is_orphan
, accepted
;
1084 ULONG rx_status_le
, rx_info
, packet_type
, *rcb
, *last_rcb
, dma_size
;
1086 struct IOSana2Req
*request
, *request_tail
;
1087 struct Opener
*opener
, *opener_tail
;
1088 struct TypeStats
*tracker
;
1090 base
= unit
->device
;
1091 last_rcb
= unit
->last_rcb
;
1092 rcb
= (ULONG
*)LELong(last_rcb
[PROCB_NEXT
]);
1094 dma_size
= RCB_SIZE
;
1095 CachePostDMA(rcb
, &dma_size
, 0);
1096 while(((rx_status_le
= rcb
[PROCB_CONTROL
])
1097 & MakeLELong(PROCB_CONTROLF_DONE
)) != 0)
1099 if((rx_status_le
& MakeLELong(PROCB_CONTROLF_OK
)) != 0)
1102 rx_info
= LELong(rcb
[PROCB_RXINFO
]);
1103 packet_size
= rx_info
& PROCB_RXINFOF_FRAMESIZE
;
1104 buffer
= (UBYTE
*)(rcb
+ PROCB_BUFFER
);
1106 if(AddressFilter(unit
, buffer
+ ETH_PACKET_DEST
, base
))
1108 packet_type
= BEWord(*((UWORD
*)(buffer
+ ETH_PACKET_TYPE
)));
1110 opener
= (APTR
)unit
->openers
.mlh_Head
;
1111 opener_tail
= (APTR
)&unit
->openers
.mlh_Tail
;
1113 /* Offer packet to every opener */
1115 while(opener
!= opener_tail
)
1117 request
= (APTR
)opener
->read_port
.mp_MsgList
.lh_Head
;
1118 request_tail
= (APTR
)&opener
->read_port
.mp_MsgList
.lh_Tail
;
1121 /* Offer packet to each request until it's accepted */
1123 while((request
!= request_tail
) && !accepted
)
1125 if(request
->ios2_PacketType
== packet_type
)
1127 CopyPacket(unit
, request
, packet_size
, packet_type
,
1132 (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
1137 opener
= (APTR
)opener
->node
.mln_Succ
;
1140 /* If packet was unwanted, give it to S2_READORPHAN request */
1144 unit
->stats
.UnknownTypesReceived
++;
1145 if(!IsMsgPortEmpty(unit
->request_ports
[ADOPT_QUEUE
]))
1148 (APTR
)unit
->request_ports
[ADOPT_QUEUE
]->
1149 mp_MsgList
.lh_Head
, packet_size
, packet_type
, buffer
,
1154 /* Update remaining statistics */
1157 FindTypeStats(unit
, &unit
->type_trackers
, packet_type
, base
);
1160 tracker
->stats
.PacketsReceived
++;
1161 tracker
->stats
.BytesReceived
+= packet_size
;
1167 unit
->stats
.BadData
++;
1168 ReportEvents(unit
, S2EVENT_ERROR
| S2EVENT_HARDWARE
| S2EVENT_RX
,
1172 rcb
[PROCB_CONTROL
] = MakeLELong(PROCB_CONTROLF_SUSPEND
);
1174 MakeLELong(ETH_MAXPACKETSIZE
<< PROCB_RXINFOB_BUFFERSIZE
);
1176 /* Clear suspend flag from previous CB without touching bits that
1177 adapter may be writing to; and resume execution */
1179 *(((UBYTE
*)last_rcb
+ PROCB_CONTROL
) + 3) = 0;
1180 dma_size
= RCB_SIZE
;
1181 CachePreDMA(last_rcb
, &dma_size
, 0);
1183 unit
->LEWordOut(unit
->card
, PROREG_COMMAND
, PRO_RUCMD_RESUME
);
1186 rcb
= (ULONG
*)LELong(rcb
[PROCB_NEXT
]);
1191 unit
->last_rcb
= last_rcb
;
1197 /****i* intelpro100.device/CopyPacket **************************************
1203 * CopyPacket(unit, request, packet_size, packet_type,
1206 * VOID CopyPacket(struct DevUnit *, struct IOSana2Req *, UWORD, UWORD,
1209 ****************************************************************************
1213 static VOID
CopyPacket(struct DevUnit
*unit
, struct IOSana2Req
*request
,
1214 UWORD packet_size
, UWORD packet_type
, UBYTE
*buffer
,
1215 struct DevBase
*base
)
1217 struct Opener
*opener
;
1218 BOOL filtered
= FALSE
;
1220 /* Set multicast and broadcast flags */
1222 request
->ios2_Req
.io_Flags
&= ~(SANA2IOF_BCAST
| SANA2IOF_MCAST
);
1223 if((*((ULONG
*)(buffer
+ ETH_PACKET_DEST
)) == 0xffffffff) &&
1224 (*((UWORD
*)(buffer
+ ETH_PACKET_DEST
+ 4)) == 0xffff))
1225 request
->ios2_Req
.io_Flags
|= SANA2IOF_BCAST
;
1226 else if((buffer
[ETH_PACKET_DEST
] & 0x1) != 0)
1227 request
->ios2_Req
.io_Flags
|= SANA2IOF_MCAST
;
1229 /* Set source and destination addresses and packet type */
1231 CopyMem(buffer
+ ETH_PACKET_SOURCE
, request
->ios2_SrcAddr
,
1233 CopyMem(buffer
+ ETH_PACKET_DEST
, request
->ios2_DstAddr
,
1235 request
->ios2_PacketType
= packet_type
;
1237 /* Adjust for cooked packet request */
1239 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
1241 packet_size
-= ETH_PACKET_DATA
;
1242 buffer
+= ETH_PACKET_DATA
;
1246 packet_size
+= 4; /* Needed for Shapeshifter & Fusion */
1248 request
->ios2_DataLength
= packet_size
;
1252 opener
= request
->ios2_BufferManagement
;
1253 if((request
->ios2_Req
.io_Command
== CMD_READ
) &&
1254 (opener
->filter_hook
!= NULL
))
1255 if(!CallHookPkt(opener
->filter_hook
, request
, buffer
))
1260 /* Copy packet into opener's buffer and reply packet */
1262 if(!opener
->rx_function(request
->ios2_Data
, buffer
, packet_size
))
1264 request
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
1265 request
->ios2_WireError
= S2WERR_BUFF_ERROR
;
1267 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
| S2EVENT_RX
,
1270 Remove((APTR
)request
);
1271 ReplyMsg((APTR
)request
);
1279 /****i* intelpro100.device/AddressFilter ***********************************
1285 * accept = AddressFilter(unit, address)
1287 * BOOL AddressFilter(struct DevUnit *, UBYTE *);
1289 ****************************************************************************
1293 static BOOL
AddressFilter(struct DevUnit
*unit
, UBYTE
*address
,
1294 struct DevBase
*base
)
1296 struct AddressRange
*range
, *tail
;
1299 UWORD address_right
;
1301 /* Check whether address is unicast/broadcast or multicast */
1303 address_left
= BELong(*((ULONG
*)address
));
1304 address_right
= BEWord(*((UWORD
*)(address
+ 4)));
1306 if((address_left
& 0x01000000) != 0 &&
1307 !(address_left
== 0xffffffff && address_right
== 0xffff))
1309 /* Check if this multicast address is wanted */
1311 range
= (APTR
)unit
->multicast_ranges
.mlh_Head
;
1312 tail
= (APTR
)&unit
->multicast_ranges
.mlh_Tail
;
1315 while((range
!= tail
) && !accept
)
1317 if(((address_left
> range
->lower_bound_left
) ||
1318 (address_left
== range
->lower_bound_left
) &&
1319 (address_right
>= range
->lower_bound_right
)) &&
1320 ((address_left
< range
->upper_bound_left
) ||
1321 (address_left
== range
->upper_bound_left
) &&
1322 (address_right
<= range
->upper_bound_right
)))
1324 range
= (APTR
)range
->node
.mln_Succ
;
1328 unit
->special_stats
[S2SS_ETHERNET_BADMULTICAST
& 0xffff]++;
1336 /****i* intelpro100.device/TXInt *******************************************
1344 * VOID TXInt(struct DevUnit *);
1347 * unit - A unit of this device.
1348 * int_code - Unused.
1353 ****************************************************************************
1355 * Note that when the CU is resumed, the adapter examines the suspend flag
1356 * again in the command that caused the suspension. If the flag is set, the
1357 * CU will be suspended without executing any new commands. This means that
1358 * all TCBs can't be in use at the same time, and the dynamically inserted
1359 * multicast list command can't have its suspend flag set.
1363 static VOID
TXInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
))
1365 struct DevBase
*base
;
1366 UWORD packet_size
, data_size
, *p
, *q
, i
;
1367 struct IOSana2Req
*request
;
1368 BOOL proceed
= TRUE
;
1369 struct Opener
*opener
;
1370 ULONG wire_error
, *tcb
, *last_tcb
, *mcast_cb
, *fragment
, dma_size
,
1372 UBYTE
*(*dma_tx_function
)(REG(a0
, APTR
));
1375 struct MsgPort
*port
;
1377 base
= unit
->device
;
1378 port
= unit
->request_ports
[WRITE_QUEUE
];
1380 while(proceed
&& !IsMsgPortEmpty(port
))
1382 last_tcb
= unit
->last_tcb
;
1383 tcb
= (ULONG
*)LELong(last_tcb
[PROCB_NEXT
]);
1385 /* Ensure there are at least two free CBs available (two are needed
1386 for setting the multicast filter) and that neither the TX nor the
1387 multicast buffer is currently in use */
1389 if((ULONG
*)LELong(((ULONG
*)LELong(tcb
[PROCB_NEXT
]))[PROCB_NEXT
])
1391 && (unit
->flags
& (UNITF_TXBUFFERINUSE
| UNITF_MCASTBUFFERINUSE
))
1395 request
= (APTR
)GetMsg(port
);
1396 request
->ios2_Req
.io_Message
.mn_Node
.ln_Type
= NT_FREEMSG
;
1398 switch(request
->ios2_Req
.io_Command
)
1406 action
= PROACT_CONFIGURE
;
1409 if(action
== PROACT_TX
)
1411 /* Handle TX request */
1413 data_size
= packet_size
= request
->ios2_DataLength
;
1415 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
1416 packet_size
+= ETH_HEADERSIZE
;
1418 /* Write packet preamble */
1420 tcb
[PROCB_CONTROL
] =
1421 MakeLELong(PROACT_TX
| PROCB_CONTROLF_SUSPEND
1422 | PROCB_CONTROLF_INT
| PROCB_CONTROLF_FLEXIBLE
);
1423 fragment
= tcb
+ PROCB_EXTFRAGS
;
1424 tcb
[PROCB_FRAGMENTS
] = MakeLELong((ULONG
)fragment
);
1426 /* Write packet header */
1428 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
1430 buffer
= (UBYTE
*)(tcb
+ PROCB_EXTBUFFER
);
1432 MakeLELong(2 << PROCB_TXINFOB_FRAGCOUNT
1433 | 1 << PROCB_TXINFOB_THRESHOLD
1434 | PROCB_TXINFOF_EOF
);
1435 fragment
[PROFRAG_ADDR
] = MakeLELong((ULONG
)buffer
);
1436 fragment
[PROFRAG_LEN
] = MakeLELong(ETH_HEADERSIZE
);
1438 p
= (UWORD
*)buffer
;
1439 for(i
= 0, q
= (UWORD
*)request
->ios2_DstAddr
;
1440 i
< ETH_ADDRESSSIZE
/ 2; i
++)
1442 for(i
= 0, q
= (UWORD
*)unit
->address
;
1443 i
< ETH_ADDRESSSIZE
/ 2; i
++)
1445 *p
++ = MakeBEWord(request
->ios2_PacketType
);
1446 buffer
= (UBYTE
*)p
;
1448 fragment
+= PRO_FRAGLEN
;
1453 MakeLELong(1 << PROCB_TXINFOB_FRAGCOUNT
1454 | 1 << PROCB_TXINFOB_THRESHOLD
1455 | PROCB_TXINFOF_EOF
);
1458 /* Get packet data */
1460 opener
= (APTR
)request
->ios2_BufferManagement
;
1461 dma_tx_function
= opener
->dma_tx_function
;
1462 if(dma_tx_function
!= NULL
)
1463 buffer
= dma_tx_function(request
->ios2_Data
);
1469 buffer
= unit
->tx_buffer
;
1470 if(opener
->tx_function(buffer
, request
->ios2_Data
,
1473 unit
->flags
|= UNITF_TXBUFFERINUSE
;
1477 error
= S2ERR_NO_RESOURCES
;
1478 wire_error
= S2WERR_BUFF_ERROR
;
1480 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
1481 | S2EVENT_TX
, base
);
1485 /* Put pointer to packet data into descriptor */
1489 dma_size
= data_size
;
1490 CachePreDMA(buffer
, &dma_size
, DMA_ReadFromRAM
);
1491 fragment
[PROFRAG_ADDR
] = MakeLELong((ULONG
)buffer
);
1492 fragment
[PROFRAG_LEN
] = MakeLELong(data_size
);
1497 /* Update multicast reception filter */
1499 SetMulticast(unit
, base
);
1500 if((unit
->flags
& UNITF_ALLMCAST
) == 0)
1502 tcb
[PROCB_CONTROL
] = MakeLELong(PROACT_NOP
);
1503 mcast_cb
= unit
->multicast_cb
;
1504 mcast_cb
[PROCB_CONTROL
] = MakeLELong(PROACT_SETMCAST
);
1505 mcast_cb
[PROCB_NEXT
] = tcb
[PROCB_NEXT
];
1506 tcb
[PROCB_NEXT
] = MakeLELong((ULONG
)mcast_cb
);
1507 unit
->link_cb
= tcb
;
1508 tcb
= (ULONG
*)LELong(mcast_cb
[PROCB_NEXT
]);
1509 tcb
[PROCB_CONTROL
] = MakeLELong(PROACT_CONFIGURE
1510 | PROCB_CONTROLF_SUSPEND
| PROCB_CONTROLF_INT
);
1511 FillConfigData(unit
, tcb
, base
);
1512 unit
->flags
|= UNITF_MCASTBUFFERINUSE
;
1516 tcb
[PROCB_CONTROL
] = MakeLELong(PROACT_CONFIGURE
1517 | PROCB_CONTROLF_SUSPEND
| PROCB_CONTROLF_INT
);
1518 FillConfigData(unit
, tcb
, base
);
1524 /* Clear suspend flag from previous CB without touching bits
1525 that adapter may be writing to; and resume execution */
1527 if(last_tcb
[PROCB_CONTROL
] != 0)
1528 *(((UBYTE
*)last_tcb
+ PROCB_CONTROL
) + 3) =
1529 PROCB_CONTROLF_INT
>> 24;
1530 dma_size
= TCB_SIZE
* TX_SLOT_COUNT
;
1531 CachePreDMA(unit
->tcbs
, &dma_size
, 0);
1532 dma_size
= MCAST_CB_SIZE
;
1533 CachePreDMA(unit
->multicast_cb
, &dma_size
, 0);
1534 if((unit
->ByteIn(unit
->card
, PROREG_STATUS
)
1535 & PROREG_STATUSF_CUSTATE
)
1536 == (PRO_CUSTATE_SUSPENDED
<< PROREG_STATUSB_CUSTATE
))
1538 unit
->LEWordOut(unit
->card
, PROREG_COMMAND
,
1542 AddTail((APTR
)&unit
->tx_requests
, (APTR
)request
);
1543 unit
->last_tcb
= tcb
;
1547 /* Return failed request */
1549 request
->ios2_Req
.io_Error
= error
;
1550 request
->ios2_WireError
= wire_error
;
1551 ReplyMsg((APTR
)request
);
1552 tcb
[PROCB_CONTROL
] = 0;
1560 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
1562 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_IGNORE
;
1569 /****i* intelpro100.device/TXEndInt ****************************************
1577 * VOID TXEndInt(struct DevUnit *);
1580 * unit - A unit of this device.
1581 * int_code - Unused.
1586 ****************************************************************************
1588 * It appears to be safe to assume that there will always be at least one
1589 * completed packet whenever this interrupt is called.
1593 static VOID
TXEndInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
))
1595 UWORD data_size
, packet_size
;
1597 struct DevBase
*base
;
1598 struct IOSana2Req
*request
;
1599 ULONG
*tcb
, *fragment
, dma_size
, action
;
1600 struct TypeStats
*tracker
;
1602 /* Retire sent packets and configuration commands */
1604 base
= unit
->device
;
1605 dma_size
= TCB_SIZE
* TX_SLOT_COUNT
;
1606 CachePostDMA(unit
->tcbs
, &dma_size
, 0);
1607 dma_size
= MCAST_CB_SIZE
;
1608 CachePostDMA(unit
->multicast_cb
, &dma_size
, 0);
1610 for(tcb
= unit
->first_tcb
;
1611 (tcb
[PROCB_CONTROL
] & MakeLELong(PROCB_CONTROLF_DONE
)) != 0;
1612 tcb
= (ULONG
*)LELong(tcb
[PROCB_NEXT
]))
1614 action
= LELong(tcb
[PROCB_CONTROL
]) & PROCB_CONTROLF_ACTION
;
1616 if(action
== PROACT_TX
|| action
== PROACT_CONFIGURE
1617 && (unit
->link_cb
!= NULL
1618 || (tcb
[PROCB_CF5
] & PROCB_CF5F_ALLMCAST
) != 0))
1620 request
= (APTR
)RemHead((APTR
)&unit
->tx_requests
);
1622 if(action
== PROACT_TX
)
1624 /* Mark end of DMA */
1626 data_size
= packet_size
= request
->ios2_DataLength
;
1627 fragment
= (ULONG
*)LELong(tcb
[PROCB_FRAGMENTS
]);
1629 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
1631 packet_size
+= ETH_HEADERSIZE
;
1632 fragment
+= PRO_FRAGLEN
;
1635 buffer
= (UBYTE
*)LELong(fragment
[PROFRAG_ADDR
]);
1636 dma_size
= data_size
;
1637 CachePostDMA(buffer
, &dma_size
, DMA_ReadFromRAM
);
1639 /* Check if unit's buffer is now free */
1641 if(buffer
== unit
->tx_buffer
)
1642 unit
->flags
&= ~UNITF_TXBUFFERINUSE
;
1644 /* Update statistics */
1646 tracker
= FindTypeStats(unit
, &unit
->type_trackers
,
1647 request
->ios2_PacketType
, base
);
1650 tracker
->stats
.PacketsSent
++;
1651 tracker
->stats
.BytesSent
+= packet_size
;
1654 else if(action
== PROACT_CONFIGURE
)
1656 /* Mark end of multicast update */
1658 if(unit
->link_cb
!= NULL
)
1660 unit
->link_cb
[PROCB_NEXT
] = MakeLELong((ULONG
)tcb
);
1661 unit
->flags
&= ~UNITF_MCASTBUFFERINUSE
;
1662 unit
->link_cb
= NULL
;
1668 request
->ios2_Req
.io_Error
= 0;
1669 ReplyMsg((APTR
)request
);
1672 /* Mark CB as unused/clear suspend flag */
1674 tcb
[PROCB_CONTROL
] = 0;
1677 dma_size
= TCB_SIZE
* TX_SLOT_COUNT
;
1678 CachePreDMA(unit
->tcbs
, &dma_size
, 0);
1680 unit
->first_tcb
= tcb
;
1682 /* Restart downloads if they had stopped */
1684 if(unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
== PA_IGNORE
)
1685 Cause(&unit
->tx_int
);
1692 /****i* intelpro100.device/UpdateStats *************************************
1700 * VOID UpdateStats(struct DevUnit *);
1703 * unit - A unit of this device.
1708 ****************************************************************************
1712 VOID
UpdateStats(struct DevUnit
*unit
, struct DevBase
*base
)
1714 ULONG dma_size
, *buffer
;
1716 buffer
= unit
->stats_buffer
;
1717 buffer
[STAT_COUNT
] = 0;
1718 dma_size
= sizeof(ULONG
) * STAT_COUNT
;
1719 CachePreDMA(unit
->stats_buffer
, &dma_size
, 0);
1720 unit
->ByteOut(unit
->card
, PROREG_COMMAND
, PRO_CUCMD_DUMPRESETSTATS
);
1721 while(buffer
[STAT_COUNT
] != MakeLELong(0xa007))
1723 dma_size
= sizeof(ULONG
) * STAT_COUNT
;
1724 CachePostDMA(unit
->stats_buffer
, &dma_size
, 0);
1727 unit
->stats
.Overruns
+= LELong(buffer
[PROSTAT_RXOVERRUNS
]);
1728 unit
->stats
.PacketsSent
+= LELong(buffer
[PROSTAT_TXFRAMESOK
]);
1729 unit
->stats
.PacketsReceived
+= LELong(buffer
[PROSTAT_RXFRAMESOK
]);
1730 unit
->special_stats
[S2SS_ETHERNET_RETRIES
& 0xffff] +=
1731 LELong(buffer
[PROSTAT_FRAMESDEFERRED
]);
1732 unit
->special_stats
[S2SS_ETHERNET_FIFO_UNDERRUNS
& 0xffff] +=
1733 LELong(buffer
[PROSTAT_TXUNDERRUNS
]);
1740 /****i* intelpro100.device/ReportEvents ************************************
1746 * ReportEvents(unit, events)
1748 * VOID ReportEvents(struct DevUnit *, ULONG);
1751 * unit - A unit of this device.
1752 * events - A mask of events to report.
1757 ****************************************************************************
1761 static VOID
ReportEvents(struct DevUnit
*unit
, ULONG events
,
1762 struct DevBase
*base
)
1764 struct IOSana2Req
*request
, *tail
, *next_request
;
1767 list
= &unit
->request_ports
[EVENT_QUEUE
]->mp_MsgList
;
1768 next_request
= (APTR
)list
->lh_Head
;
1769 tail
= (APTR
)&list
->lh_Tail
;
1772 while(next_request
!= tail
)
1774 request
= next_request
;
1775 next_request
= (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
1777 if((request
->ios2_WireError
& events
) != 0)
1779 request
->ios2_WireError
= events
;
1780 Remove((APTR
)request
);
1781 ReplyMsg((APTR
)request
);
1791 /****i* intelpro100.device/UnitTask ****************************************
1802 * Completes deferred requests.
1804 ****************************************************************************
1812 static VOID
UnitTask()
1815 struct IORequest
*request
;
1816 struct DevUnit
*unit
;
1817 struct DevBase
*base
;
1818 struct MsgPort
*general_port
;
1819 ULONG signals
, wait_signals
, general_port_signal
;
1821 /* Get parameters */
1823 task
= AbsExecBase
->ThisTask
;
1824 unit
= task
->tc_UserData
;
1825 base
= unit
->device
;
1827 /* Activate general request port */
1829 general_port
= unit
->request_ports
[GENERAL_QUEUE
];
1830 general_port
->mp_SigTask
= task
;
1831 general_port
->mp_SigBit
= AllocSignal(-1);
1832 general_port_signal
= 1 << general_port
->mp_SigBit
;
1833 general_port
->mp_Flags
= PA_SIGNAL
;
1835 /* Allocate a signal for notification of card removal */
1837 wait_signals
= (1 << general_port
->mp_SigBit
);
1839 /* Tell ourselves to check port for old messages */
1841 Signal(task
, general_port_signal
);
1843 /* Infinite loop to service requests and signals */
1847 signals
= Wait(wait_signals
);
1849 if((signals
& general_port_signal
) != 0)
1851 while((request
= (APTR
)GetMsg(general_port
)) != NULL
)
1853 /* Service the request as soon as the unit is free */
1855 ObtainSemaphore(&unit
->access_lock
);
1856 ServiceRequest((APTR
)request
, base
);
1864 /****i* intelpro100.device/GetEEPROMAddressSize ****************************
1867 * GetEEPROMAddressSize
1870 * size = GetEEPROMAddressSize(unit)
1872 * UWORD GetEEPROMAddressSize(struct DevUnit *);
1875 * unit - A unit of this device.
1878 * size - Width of EEPROM addresses.
1880 ****************************************************************************
1882 * Although the manual doesn't make it explicit, chip select must be asserted
1883 * before setting any other bits, at least on the i82557.
1887 static UWORD
GetEEPROMAddressSize(struct DevUnit
*unit
,
1888 struct DevBase
*base
)
1892 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
, PROREG_EEPROMF_SELECT
);
1893 WriteEEPROMBits(unit
, 0x6, 3, base
);
1894 for(size
= 1; WriteEEPROMBit(unit
, FALSE
, base
); size
++);
1895 ReadEEPROMBits(unit
, 16, base
);
1896 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
, 0);
1897 BusyMicroDelay(1, base
);
1904 /****i* intelpro100.device/ReadEEPROM **************************************
1907 * ReadEEPROM -- Read an EEPROM location.
1910 * value = ReadEEPROM(unit, index)
1912 * UWORD ReadEEPROM(struct DevUnit *, UWORD);
1915 * unit - A unit of this device.
1916 * index - Offset within EEPROM.
1919 * value - Contents of specified EEPROM location.
1921 ****************************************************************************
1925 static UWORD
ReadEEPROM(struct DevUnit
*unit
, UWORD index
,
1926 struct DevBase
*base
)
1930 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
, PROREG_EEPROMF_SELECT
);
1931 WriteEEPROMBits(unit
, 0x6, 3, base
);
1932 WriteEEPROMBits(unit
, index
, unit
->eeprom_addr_size
, base
);
1933 value
= ReadEEPROMBits(unit
, 16, base
);
1934 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
, 0);
1935 BusyMicroDelay(1, base
);
1942 /****i* intelpro100.device/ReadEEPROMBits **********************************
1945 * ReadEEPROMBits -- Read a stream of bits from the EEPROM.
1948 * value = ReadEEPROMBits(unit, count)
1950 * ULONG ReadEEPROMBits(struct DevUnit *, UBYTE);
1953 * unit - A unit of this device.
1954 * count - Number of bits to be read.
1957 * value - The bits read from the EEPROM, right-justified.
1959 ****************************************************************************
1963 static ULONG
ReadEEPROMBits(struct DevUnit
*unit
, UBYTE count
,
1964 struct DevBase
*base
)
1969 for(i
= 0; i
< count
; i
++)
1972 if(ReadEEPROMBit(unit
, base
))
1980 /****i* intelpro100.device/WriteEEPROMBits *********************************
1983 * WriteEEPROMBits -- Write a stream of bits to the EEPROM.
1986 * WriteEEPROMBits(unit, value, count)
1988 * VOID WriteEEPROMBits(struct DevUnit *, ULONG, UBYTE);
1991 * unit - A unit of this device.
1992 * value - The bits to write to the EEPROM, right-justified.
1993 * count - Number of bits to be Write.
1998 ****************************************************************************
2002 static VOID
WriteEEPROMBits(struct DevUnit
*unit
, ULONG value
, UBYTE count
,
2003 struct DevBase
*base
)
2007 for(mask
= 1 << (count
- 1); mask
!= 0; mask
>>= 1)
2008 WriteEEPROMBit(unit
, (value
& mask
) != 0, base
);
2015 /****i* intelpro100.device/ReadEEPROMBit ***********************************
2018 * ReadEEPROMBit -- Read a bit from the EEPROM.
2021 * value = ReadEEPROMBit(unit)
2023 * BOOL ReadEEPROMBit(struct DevUnit *);
2026 * unit - A unit of this device.
2029 * value - True for one, false for zero.
2031 ****************************************************************************
2035 static BOOL
ReadEEPROMBit(struct DevUnit
*unit
, struct DevBase
*base
)
2039 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
,
2040 PROREG_EEPROMF_SELECT
| PROREG_EEPROMF_CLK
);
2041 BusyMicroDelay(2, base
);
2043 (unit
->LEWordIn(unit
->card
, PROREG_EEPROM
) & PROREG_EEPROMF_DATAIN
)
2045 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
, PROREG_EEPROMF_SELECT
);
2046 BusyMicroDelay(2, base
);
2053 /****i* intelpro100.device/WriteEEPROMBit **********************************
2056 * WriteEEPROMBit -- Write a bit to the EEPROM.
2059 * data_in = WriteEEPROMBit(unit, is_one)
2061 * BOOL WriteEEPROMBit(struct DevUnit *, BOOL);
2064 * unit - A unit of this device.
2065 * is_one - True if a set bit should be written.
2068 * data_in - True if data-in bit is set.
2070 ****************************************************************************
2074 static BOOL
WriteEEPROMBit(struct DevUnit
*unit
, BOOL is_one
,
2075 struct DevBase
*base
)
2080 data_out
= PROREG_EEPROMF_DATAOUT
;
2084 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
,
2085 PROREG_EEPROMF_SELECT
| data_out
);
2086 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
,
2087 PROREG_EEPROMF_SELECT
| PROREG_EEPROMF_CLK
| data_out
);
2088 BusyMicroDelay(2, base
);
2089 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
,
2090 PROREG_EEPROMF_SELECT
| data_out
);
2091 BusyMicroDelay(2, base
);
2094 (unit
->LEWordIn(unit
->card
, PROREG_EEPROM
) & PROREG_EEPROMF_DATAIN
)
2100 /****i* intelpro100.device/ReadMII *****************************************
2103 * ReadMII -- Read a register in an MII PHY.
2106 * value = ReadMII(unit, phy_no, reg_no)
2108 * UWORD ReadMII(struct DevUnit *, UWORD, UWORD);
2111 * unit - A unit of this device.
2112 * phy_no - Index of PHY to use.
2113 * reg_no - MII register to read.
2116 * value - Value read from MII register.
2118 ****************************************************************************
2122 static UWORD
ReadMII(struct DevUnit
*unit
, UWORD phy_no
, UWORD reg_no
,
2123 struct DevBase
*base
)
2127 unit
->LELongOut(unit
->card
, PROREG_MIICONTROL
,
2128 2 << PROREG_MIICONTROLB_CMD
2129 | phy_no
<< PROREG_MIICONTROLB_PHYNO
2130 | reg_no
<< PROREG_MIICONTROLB_REGNO
);
2132 value
= unit
->LELongIn(unit
->card
, PROREG_MIICONTROL
);
2133 while((value
& PROREG_MIICONTROLF_READY
) == 0);
2135 return value
& PROREG_MIICONTROLF_DATA
;
2140 /****i* intelpro100.device/WriteMII ****************************************
2143 * WriteMII -- Write to a register in an MII PHY.
2146 * WriteMII(unit, phy_no, reg_no, value)
2148 * VOID WriteMII(struct DevUnit *, UWORD, UWORD, UWORD);
2151 * unit - A unit of this device.
2152 * phy_no - Index of PHY to use.
2153 * reg_no - MII register to write to.
2154 * value - Value to write to MII register.
2159 ****************************************************************************
2163 static VOID
WriteMII(struct DevUnit
*unit
, UWORD phy_no
, UWORD reg_no
,
2164 UWORD value
, struct DevBase
*base
)
2166 unit
->LELongOut(unit
->card
, PROREG_MIICONTROL
,
2167 1 << PROREG_MIICONTROLB_CMD
2168 | phy_no
<< PROREG_MIICONTROLB_PHYNO
2169 | reg_no
<< PROREG_MIICONTROLB_REGNO
2174 unit
->LELongIn(unit
->card
, PROREG_MIICONTROL
)
2175 & PROREG_MIICONTROLF_READY
2185 /****i* prism2.device/BusyMicroDelay ***************************************
2188 * BusyMilliDelay - Busy-wait for specified number of microseconds.
2191 * BusyMilliDelay(micros)
2193 * VOID BusyMilliDelay(ULONG);
2195 ****************************************************************************
2200 static VOID
BusyMicroDelay(ULONG micros
, struct DevBase
*base
)
2202 struct timeval time
, end_time
;
2204 GetSysTime(&end_time
);
2206 time
.tv_micro
= micros
;
2207 AddTime(&end_time
, &time
);
2209 while(CmpTime(&end_time
, &time
) < 0)
2217 static VOID
BusyMicroDelay(ULONG micros
, struct DevBase
*base
)
2219 struct EClockVal time
, end_time
;
2222 rate
= ReadEClock(&time
);
2223 end_time
.ev_hi
= time
.ev_hi
;
2224 end_time
.ev_lo
= time
.ev_lo
+ (micros
* rate
+ 1) / 1000000;
2225 if(end_time
.ev_lo
< time
.ev_lo
)
2228 while(time
.ev_lo
< end_time
.ev_lo
|| time
.ev_hi
< end_time
.ev_hi
)