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,
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>
30 #include <proto/alib.h>
32 #include <clib/alib_protos.h>
34 #include <proto/utility.h>
35 #include <proto/timer.h>
39 #include "intelpro100.h"
43 #include "unit_protos.h"
44 #include "request_protos.h"
47 #define TASK_PRIORITY 0
48 #define STACK_SIZE 4096
49 #define CONFIG_DATA_LEN 6
51 #define MAX_MCAST_ENTRIES 100
52 #define MCAST_CB_SIZE (PROCB_COUNT * sizeof(ULONG) + sizeof(UWORD) \
53 + ETH_ADDRESSSIZE * MAX_MCAST_ENTRIES)
55 static VOID
InitialiseAdapter(struct DevUnit
*unit
, struct DevBase
*base
);
56 static VOID
FillConfigData(struct DevUnit
*unit
, ULONG
*tcb
,
57 struct DevBase
*base
);
58 static struct AddressRange
*FindMulticastRange(struct DevUnit
*unit
,
59 ULONG lower_bound_left
, UWORD lower_bound_right
, ULONG upper_bound_left
,
60 UWORD upper_bound_right
, struct DevBase
*base
);
61 static VOID
SetMulticast(struct DevUnit
*unit
, struct DevBase
*base
);
62 static BOOL
StatusInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
));
63 static VOID
RXInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
));
64 static VOID
CopyPacket(struct DevUnit
*unit
, struct IOSana2Req
*request
,
65 UWORD packet_size
, UWORD packet_type
, UBYTE
*buffer
,
66 struct DevBase
*base
);
67 static BOOL
AddressFilter(struct DevUnit
*unit
, UBYTE
*address
,
68 struct DevBase
*base
);
69 static VOID
TXInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
));
70 static VOID
TXEndInt(REG(a1
, struct DevUnit
*unit
),
71 REG(a5
, APTR int_code
));
72 static VOID
ReportEvents(struct DevUnit
*unit
, ULONG events
,
73 struct DevBase
*base
);
74 static VOID
UnitTask(struct DevUnit
*);
75 static UWORD
GetEEPROMAddressSize(struct DevUnit
*unit
,
76 struct DevBase
*base
);
77 static UWORD
ReadEEPROM(struct DevUnit
*unit
, UWORD index
,
78 struct DevBase
*base
);
79 static ULONG
ReadEEPROMBits(struct DevUnit
*unit
, UBYTE count
,
80 struct DevBase
*base
);
81 static VOID
WriteEEPROMBits(struct DevUnit
*unit
, ULONG value
, UBYTE count
,
82 struct DevBase
*base
);
83 static BOOL
ReadEEPROMBit(struct DevUnit
*unit
, struct DevBase
*base
);
84 static BOOL
WriteEEPROMBit(struct DevUnit
*unit
, BOOL is_one
,
85 struct DevBase
*base
);
86 static UWORD
ReadMII(struct DevUnit
*unit
, UWORD phy_no
, UWORD reg_no
,
87 struct DevBase
*base
);
88 static VOID
WriteMII(struct DevUnit
*unit
, UWORD phy_no
, UWORD reg_no
,
89 UWORD value
, struct DevBase
*base
);
90 static VOID
BusyMicroDelay(ULONG micros
, struct DevBase
*base
);
94 static const ULONG config_data
[] =
96 8 << PROCB_CF0B_RXFIFOLIM
| 22 << PROCB_CF0B_SIZE
,
97 1 << PROCB_CF1B_UNDERRUNRETRIES
| PROCB_CF1F_DISCARDRUNTS
98 | PROCB_CF1F_STDSTATS
| PROCB_CF1F_STDTXBLOCK
| 0x00020000,
99 2 << PROCB_CF2B_PREAMBLETYPE
| PROCB_CF2F_NOSOURCEINSERT
| 0x00060001,
100 0xf200 << PROCB_CF3B_ARPFILTER
| 6 << PROCB_CF3B_IFS
| 0x48000000,
101 PROCB_CF4F_USEFDPIN
| PROCB_CF4F_PADDING
| 0x00f04000,
106 /****i* intelpro100.device/CreateUnit **************************************
109 * CreateUnit -- Create a unit.
112 * unit = CreateUnit(index, card, io_tags, bus)
114 * struct DevUnit *CreateUnit(ULONG, APTR, struct TagItem *, UWORD);
117 * Creates a new unit.
119 ****************************************************************************
123 struct DevUnit
*CreateUnit(ULONG index
, APTR card
,
124 const struct TagItem
*io_tags
, UWORD bus
, struct DevBase
*base
)
127 struct DevUnit
*unit
;
129 struct MsgPort
*port
;
132 ULONG
*tcb
, *next_tcb
, *rcb
, *next_rcb
, dma_size
;
133 APTR rx_int_function
, tx_int_function
;
135 unit
= AllocMem(sizeof(struct DevUnit
), MEMF_CLEAR
| MEMF_PUBLIC
);
141 /* Initialise lists etc. */
143 InitSemaphore(&unit
->access_lock
);
144 NewList((APTR
)&unit
->openers
);
145 NewList((APTR
)&unit
->type_trackers
);
146 NewList((APTR
)&unit
->multicast_ranges
);
147 NewList((APTR
)&unit
->tx_requests
);
154 /* Store I/O hooks */
157 (APTR
)GetTagData(IOTAG_ByteIn
, (UPINT
)NULL
, io_tags
);
159 (APTR
)GetTagData(IOTAG_ByteOut
, (UPINT
)NULL
, io_tags
);
161 (APTR
)GetTagData(IOTAG_LEWordIn
, (UPINT
)NULL
, io_tags
);
163 (APTR
)GetTagData(IOTAG_LELongIn
, (UPINT
)NULL
, io_tags
);
165 (APTR
)GetTagData(IOTAG_LEWordOut
, (UPINT
)NULL
, io_tags
);
167 (APTR
)GetTagData(IOTAG_LELongOut
, (UPINT
)NULL
, io_tags
);
169 (APTR
)GetTagData(IOTAG_AllocDMAMem
, (UPINT
)NULL
, io_tags
);
171 (APTR
)GetTagData(IOTAG_FreeDMAMem
, (UPINT
)NULL
, io_tags
);
172 if(unit
->ByteIn
== NULL
173 || unit
->ByteOut
== NULL
174 || unit
->LEWordIn
== NULL
175 || unit
->LEWordOut
== NULL
|| unit
->LELongIn
== NULL
176 || unit
->LELongOut
== NULL
177 || unit
->AllocDMAMem
== NULL
|| unit
->FreeDMAMem
== NULL
)
180 /* Allocate buffer for adapter to writes statistics to */
183 AllocVec(sizeof(ULONG
) * (STAT_COUNT
+ 1), MEMF_PUBLIC
);
184 if(unit
->stats_buffer
== NULL
)
190 /* Initialise network adapter hardware */
192 InitialiseAdapter(unit
, base
);
193 unit
->flags
|= UNITF_HAVEADAPTER
;
195 /* Create the message ports for queuing requests */
197 for(i
= 0; i
< REQUEST_QUEUE_COUNT
; i
++)
199 unit
->request_ports
[i
] = port
= AllocMem(sizeof(struct MsgPort
),
200 MEMF_PUBLIC
| MEMF_CLEAR
);
206 NewList(&port
->mp_MsgList
);
207 port
->mp_Flags
= PA_IGNORE
;
208 port
->mp_SigTask
= &unit
->tx_int
;
212 /* Allocate and initialise packet/command descriptors */
214 unit
->tx_buffer
= AllocVec(ETH_MAXPACKETSIZE
, MEMF_PUBLIC
);
215 next_tcb
= unit
->first_tcb
= unit
->tcbs
=
216 AllocVec(TCB_SIZE
* TX_SLOT_COUNT
, MEMF_PUBLIC
| MEMF_CLEAR
);
217 next_rcb
= unit
->rcbs
=
218 AllocVec(RCB_SIZE
* RX_SLOT_COUNT
, MEMF_PUBLIC
| MEMF_CLEAR
);
219 unit
->multicast_cb
= AllocVec(PROCB_COUNT
* sizeof(ULONG
)
220 + sizeof(UWORD
) + ETH_ADDRESSSIZE
* MAX_MCAST_ENTRIES
,
221 MEMF_PUBLIC
| MEMF_CLEAR
);
223 if(next_tcb
== NULL
|| next_rcb
== NULL
|| unit
->tx_buffer
== NULL
224 || unit
->multicast_cb
== NULL
)
230 /* Construct TX ring */
232 for(i
= 0; i
< TX_SLOT_COUNT
; i
++)
235 next_tcb
= tcb
+ TCB_SIZE
/ sizeof(ULONG
);
236 tcb
[PROCB_NEXT
] = MakeLELong((ULONG
)(UPINT
)next_tcb
);
238 tcb
[PROCB_NEXT
] = MakeLELong((ULONG
)(UPINT
)unit
->tcbs
);
239 unit
->last_tcb
= tcb
;
241 /* Construct RX ring */
243 for(i
= 0; i
< RX_SLOT_COUNT
; i
++)
246 next_rcb
= rcb
+ RCB_SIZE
/ sizeof(ULONG
);
247 rcb
[PROCB_NEXT
] = MakeLELong((ULONG
)(UPINT
)next_rcb
);
249 MakeLELong(ETH_MAXPACKETSIZE
<< PROCB_RXINFOB_BUFFERSIZE
);
251 rcb
[PROCB_CONTROL
] = MakeLELong(PROCB_CONTROLF_SUSPEND
);
252 rcb
[PROCB_NEXT
] = MakeLELong((ULONG
)(UPINT
)unit
->rcbs
);
253 unit
->last_rcb
= rcb
;
254 dma_size
= RCB_SIZE
* RX_SLOT_COUNT
;
255 CachePreDMA(unit
->rcbs
, &dma_size
, 0);
257 /* Record maximum speed in BPS */
259 unit
->speed
= 100000000;
261 /* Initialise status, transmit and receive interrupts */
263 unit
->status_int
.is_Code
= (APTR
)StatusInt
;
264 unit
->status_int
.is_Data
= unit
;
266 rx_int_function
= RXInt
;
267 unit
->rx_int
.is_Node
.ln_Name
=
268 base
->device
.dd_Library
.lib_Node
.ln_Name
;
269 unit
->rx_int
.is_Node
.ln_Pri
= 16;
270 unit
->rx_int
.is_Code
= rx_int_function
;
271 unit
->rx_int
.is_Data
= unit
;
273 tx_int_function
= TXInt
;
274 unit
->tx_int
.is_Node
.ln_Name
=
275 base
->device
.dd_Library
.lib_Node
.ln_Name
;
276 unit
->tx_int
.is_Code
= tx_int_function
;
277 unit
->tx_int
.is_Data
= unit
;
279 unit
->tx_end_int
.is_Node
.ln_Name
=
280 base
->device
.dd_Library
.lib_Node
.ln_Name
;
281 unit
->tx_end_int
.is_Code
= TXEndInt
;
282 unit
->tx_end_int
.is_Data
= unit
;
284 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
289 /* Create a new task */
292 AllocMem(sizeof(struct Task
), MEMF_PUBLIC
| MEMF_CLEAR
);
301 stack
= AllocMem(STACK_SIZE
, MEMF_PUBLIC
);
308 /* Initialise and start task */
310 task
->tc_Node
.ln_Type
= NT_TASK
;
311 task
->tc_Node
.ln_Pri
= TASK_PRIORITY
;
312 task
->tc_Node
.ln_Name
=
313 base
->device
.dd_Library
.lib_Node
.ln_Name
;
314 task
->tc_SPUpper
= stack
+ STACK_SIZE
;
315 task
->tc_SPLower
= stack
;
316 task
->tc_SPReg
= task
->tc_SPUpper
;
317 NewList(&task
->tc_MemEntry
);
319 if(AddUnitTask(task
, UnitTask
, unit
) != NULL
)
320 unit
->flags
|= UNITF_TASKADDED
;
327 DeleteUnit(unit
, base
);
336 /****i* intelpro100.device/DeleteUnit **************************************
339 * DeleteUnit -- Delete a unit.
344 * VOID DeleteUnit(struct DevUnit *);
350 * unit - Device unit (can be NULL).
355 ****************************************************************************
359 VOID
DeleteUnit(struct DevUnit
*unit
, struct DevBase
*base
)
369 if((unit
->flags
& UNITF_TASKADDED
) != 0)
371 FreeMem(task
->tc_SPLower
, STACK_SIZE
);
372 FreeMem(task
, sizeof(struct Task
));
375 for(i
= 0; i
< REQUEST_QUEUE_COUNT
; i
++)
377 if(unit
->request_ports
[i
] != NULL
)
378 FreeMem(unit
->request_ports
[i
], sizeof(struct MsgPort
));
381 if((unit
->flags
& UNITF_ONLINE
) != 0) /* Needed! */
382 GoOffline(unit
, base
);
384 FreeVec(unit
->multicast_cb
);
387 FreeVec(unit
->tx_buffer
);
388 FreeVec(unit
->stats_buffer
);
390 FreeMem(unit
, sizeof(struct DevUnit
));
398 /****i* intelpro100.device/InitialiseAdapter *******************************
401 * InitialiseAdapter -- Initialise network adapter hardware.
404 * InitialiseAdapter(unit)
406 * VOID InitialiseAdapter(struct DevUnit *);
414 ****************************************************************************
418 static VOID
InitialiseAdapter(struct DevUnit
*unit
, struct DevBase
*base
)
425 unit
->LELongOut(unit
->card
, PROREG_PORT
, 0);
426 BusyMicroDelay(10, base
);
428 /* Get default MAC address */
430 unit
->eeprom_addr_size
= GetEEPROMAddressSize(unit
, base
);
431 p
= unit
->default_address
;
433 for(i
= 0; i
< ETH_ADDRESSSIZE
/ sizeof(UWORD
); i
++)
435 address_part
= ReadEEPROM(unit
, PROROM_ADDRESS0
+ i
, base
);
436 *p
++ = address_part
& 0xff;
437 *p
++ = address_part
>> 8;
440 /* Set up statistics dump area */
442 unit
->LELongOut(unit
->card
, PROREG_GENPTR
, (ULONG
)(UPINT
)unit
->stats_buffer
);
443 unit
->LEWordOut(unit
->card
, PROREG_COMMAND
, PRO_CUCMD_SETSTATSBUFFER
);
444 while(unit
->LEWordIn(unit
->card
, PROREG_COMMAND
) != 0);
453 /****i* intelpro100.device/ConfigureAdapter ********************************
456 * ConfigureAdapter -- Put adapter online for the first time.
459 * ConfigureAdapter(unit)
461 * VOID ConfigureAdapter(struct DevUnit *);
469 ****************************************************************************
473 VOID
ConfigureAdapter(struct DevUnit
*unit
, struct DevBase
*base
)
475 ULONG
*tcb
, dma_size
;
476 UWORD phy_type
, phy_no
, config
;
478 /* Set MAC address */
480 tcb
= (ULONG
*)(UPINT
)LELong(unit
->last_tcb
[PROCB_NEXT
]);
481 tcb
[PROCB_CONTROL
] = MakeLELong(PROACT_SETADDRESS
);
482 CopyMem(&unit
->address
, tcb
+ PROCB_ADDRESS
, ETH_ADDRESSSIZE
);
484 /* Set other parameters */
486 tcb
= (ULONG
*)(UPINT
)LELong(tcb
[PROCB_NEXT
]);
488 MakeLELong(PROACT_CONFIGURE
| PROCB_CONTROLF_SUSPEND
);
489 unit
->phy_info
= ReadEEPROM(unit
, PROROM_PHYINFO0
, base
);
490 FillConfigData(unit
, tcb
, base
);
491 unit
->last_tcb
= tcb
;
493 dma_size
= TCB_SIZE
* TX_SLOT_COUNT
;
494 CachePreDMA(unit
->tcbs
, &dma_size
, 0);
496 /* DP83840-specific configuration */
498 phy_type
= unit
->phy_info
& PROROM_PHYINFO0F_TYPE
;
499 if(phy_type
== PRO_PHY_DP83840
|| phy_type
== PRO_PHY_DP83840A
)
501 phy_no
= unit
->phy_info
& PROROM_PHYINFO0F_ADDR
;
502 config
= ReadMII(unit
, phy_no
, MII_PCR
, base
);
503 config
|= 0x400 | MII_PCRF_NOLINKMON
| MII_PCRF_LED4DUPLEX
;
504 WriteMII(unit
, phy_no
, MII_PCR
, config
, base
);
509 unit
->LELongOut(unit
->card
, PROREG_GENPTR
, (ULONG
)(UPINT
)unit
->tcbs
);
510 unit
->LEWordOut(unit
->card
, PROREG_COMMAND
, PRO_CUCMD_START
);
511 while(unit
->LEWordIn(unit
->card
, PROREG_COMMAND
) != 0);
512 GoOnline(unit
, base
);
521 /****i* intelpro100.device/FillConfigData **********************************
524 * FillConfigData -- Fill in the data for a configuration command.
527 * FillConfigData(unit, tcb)
529 * VOID FillConfigData(struct DevUnit *, ULONG *);
532 * unit - A unit of this device.
533 * tcb - The configuration command block.
538 ****************************************************************************
542 static VOID
FillConfigData(struct DevUnit
*unit
, ULONG
*tcb
,
543 struct DevBase
*base
)
549 /* Copy constant parameters from template */
551 for(p
= config_data
, q
= tcb
+ PROCB_CF0
, i
= 0; i
< CONFIG_DATA_LEN
;
553 *q
++ = MakeLELong(*p
++);
554 unit
->last_tcb
= tcb
;
556 /* Decide on promiscuous mode */
558 if((unit
->flags
& UNITF_PROM
) != 0)
559 tcb
[PROCB_CF3
] |= MakeLELong(PROCB_CF3F_PROM
);
563 if((unit
->phy_info
& PROROM_PHYINFO0F_AUI
) != 0)
564 tcb
[PROCB_CF3
] |= MakeLELong(PROCB_CF3F_CDT
);
566 tcb
[PROCB_CF2
] |= MakeLELong(PROCB_CF2F_MIIMODE
);
568 /* Accept all multicasts? */
570 if((unit
->flags
& UNITF_ALLMCAST
) != 0)
572 tcb
[PROCB_CF5
] |= MakeLELong(PROCB_CF5F_ALLMCAST
);
582 /****i* intelpro100.device/GoOnline ****************************************
585 * GoOnline -- Put the adapter online.
590 * VOID GoOnline(struct DevUnit *);
593 * unit - A unit of this device.
598 ****************************************************************************
602 VOID
GoOnline(struct DevUnit
*unit
, struct DevBase
*base
)
604 /* Enable the transceiver */
606 unit
->flags
|= UNITF_ONLINE
;
608 unit
->LELongOut(unit
->card
, PROREG_GENPTR
,
609 LELong(unit
->last_rcb
[PROCB_NEXT
]));
610 unit
->LEWordOut(unit
->card
, PROREG_COMMAND
, PRO_RUCMD_START
);
611 while(unit
->LEWordIn(unit
->card
, PROREG_COMMAND
) != 0);
613 /* Record start time and report Online event */
615 GetSysTime(&unit
->stats
.LastStart
);
616 ReportEvents(unit
, S2EVENT_ONLINE
, base
);
623 /****i* intelpro100.device/GoOffline ***************************************
626 * GoOffline -- Put the adpater offline.
631 * VOID GoOffline(struct DevUnit *);
634 * unit - A unit of this device.
639 ****************************************************************************
643 VOID
GoOffline(struct DevUnit
*unit
, struct DevBase
*base
)
645 unit
->flags
&= ~UNITF_ONLINE
;
647 if((unit
->flags
& UNITF_HAVEADAPTER
) != 0)
651 unit
->LEWordOut(unit
->card
, PROREG_COMMAND
, PRO_RUCMD_ABORT
);
653 /* Update statistics */
655 UpdateStats(unit
, base
);
658 /* Flush pending read and write requests */
660 FlushUnit(unit
, WRITE_QUEUE
, S2ERR_OUTOFSERVICE
, base
);
662 /* Report Offline event and return */
664 ReportEvents(unit
, S2EVENT_OFFLINE
, base
);
670 /****i* intelpro100.device/AddMulticastRange *******************************
676 * success = AddMulticastRange(unit, lower_bound, upper_bound)
678 * BOOL AddMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
680 ****************************************************************************
684 BOOL
AddMulticastRange(struct DevUnit
*unit
, const UBYTE
*lower_bound
,
685 const UBYTE
*upper_bound
, struct DevBase
*base
)
687 struct AddressRange
*range
;
688 ULONG lower_bound_left
, upper_bound_left
;
689 UWORD lower_bound_right
, upper_bound_right
;
691 lower_bound_left
= BELong(*((ULONG
*)lower_bound
));
692 lower_bound_right
= BEWord(*((UWORD
*)(lower_bound
+ 4)));
693 upper_bound_left
= BELong(*((ULONG
*)upper_bound
));
694 upper_bound_right
= BEWord(*((UWORD
*)(upper_bound
+ 4)));
696 range
= FindMulticastRange(unit
, lower_bound_left
, lower_bound_right
,
697 upper_bound_left
, upper_bound_right
, base
);
703 range
= AllocMem(sizeof(struct AddressRange
), MEMF_PUBLIC
);
706 range
->lower_bound_left
= lower_bound_left
;
707 range
->lower_bound_right
= lower_bound_right
;
708 range
->upper_bound_left
= upper_bound_left
;
709 range
->upper_bound_right
= upper_bound_right
;
710 range
->add_count
= 1;
713 AddTail((APTR
)&unit
->multicast_ranges
, (APTR
)range
);
718 return range
!= NULL
;
723 /****i* intelpro100.device/RemMulticastRange *******************************
729 * found = RemMulticastRange(unit, lower_bound, upper_bound)
731 * BOOL RemMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
733 ****************************************************************************
737 BOOL
RemMulticastRange(struct DevUnit
*unit
, const UBYTE
*lower_bound
,
738 const UBYTE
*upper_bound
, struct DevBase
*base
)
740 struct AddressRange
*range
;
741 ULONG lower_bound_left
, upper_bound_left
;
742 UWORD lower_bound_right
, upper_bound_right
;
744 lower_bound_left
= BELong(*((ULONG
*)lower_bound
));
745 lower_bound_right
= BEWord(*((UWORD
*)(lower_bound
+ 4)));
746 upper_bound_left
= BELong(*((ULONG
*)upper_bound
));
747 upper_bound_right
= BEWord(*((UWORD
*)(upper_bound
+ 4)));
749 range
= FindMulticastRange(unit
, lower_bound_left
, lower_bound_right
,
750 upper_bound_left
, upper_bound_right
, base
);
754 if(--range
->add_count
== 0)
759 FreeMem(range
, sizeof(struct AddressRange
));
763 return range
!= NULL
;
768 /****i* intelpro100.device/FindMulticastRange ******************************
774 * range = FindMulticastRange(unit, lower_bound_left,
775 * lower_bound_right, upper_bound_left, upper_bound_right)
777 * struct AddressRange *FindMulticastRange(struct DevUnit *, ULONG,
778 * UWORD, ULONG, UWORD);
780 ****************************************************************************
784 static struct AddressRange
*FindMulticastRange(struct DevUnit
*unit
,
785 ULONG lower_bound_left
, UWORD lower_bound_right
, ULONG upper_bound_left
,
786 UWORD upper_bound_right
, struct DevBase
*base
)
788 struct AddressRange
*range
, *tail
;
791 range
= (APTR
)unit
->multicast_ranges
.mlh_Head
;
792 tail
= (APTR
)&unit
->multicast_ranges
.mlh_Tail
;
794 while((range
!= tail
) && !found
)
796 if((lower_bound_left
== range
->lower_bound_left
) &&
797 (lower_bound_right
== range
->lower_bound_right
) &&
798 (upper_bound_left
== range
->upper_bound_left
) &&
799 (upper_bound_right
== range
->upper_bound_right
))
802 range
= (APTR
)range
->node
.mln_Succ
;
813 /****i* intelpro100.device/SetMulticast ************************************
821 * VOID SetMulticast(struct DevUnit *);
824 * Fills in the unit's multicast list TCB, but does not send it to the
827 ****************************************************************************
831 static VOID
SetMulticast(struct DevUnit
*unit
, struct DevBase
*base
)
833 ULONG
*tcb
, address_left
;
834 UWORD address_right
, i
= 0, *p
;
835 struct AddressRange
*range
, *tail
;
838 tcb
= unit
->multicast_cb
;
840 if((unit
->flags
& UNITF_PROM
) == 0)
842 /* Fill in multicast list */
844 range
= (APTR
)unit
->multicast_ranges
.mlh_Head
;
845 tail
= (APTR
)&unit
->multicast_ranges
.mlh_Tail
;
846 p
= (UWORD
*)(tcb
+ PROCB_COUNT
);
848 while(range
!= tail
&& i
< MAX_MCAST_ENTRIES
)
850 address_left
= range
->lower_bound_left
;
851 address_right
= range
->lower_bound_right
;
854 while(!range_ended
&& i
++ < MAX_MCAST_ENTRIES
)
856 *p
++ = MakeBEWord((UWORD
)(address_left
>> 16));
857 *p
++ = MakeBEWord((UWORD
)(address_left
));
858 *p
++ = MakeBEWord((UWORD
)(address_right
));
860 if(address_left
== range
->upper_bound_left
&&
861 address_right
== range
->upper_bound_right
)
865 if(++address_right
== 0)
870 range
= (APTR
)range
->node
.mln_Succ
;
872 p
= (UWORD
*)(tcb
+ PROCB_COUNT
);
873 *p
= MakeLEWord(ETH_ADDRESSSIZE
* i
);
875 /* Accept all multicasts if there are too many addresses */
878 unit
->flags
|= UNITF_ALLMCAST
;
880 unit
->flags
&= ~UNITF_ALLMCAST
;
888 /****i* intelpro100.device/FindTypeStats ***********************************
894 * stats = FindTypeStats(unit, list,
897 * struct TypeStats *FindTypeStats(struct DevUnit *, struct MinList *,
900 ****************************************************************************
904 struct TypeStats
*FindTypeStats(struct DevUnit
*unit
, struct MinList
*list
,
905 ULONG packet_type
, struct DevBase
*base
)
907 struct TypeStats
*stats
, *tail
;
910 stats
= (APTR
)list
->mlh_Head
;
911 tail
= (APTR
)&list
->mlh_Tail
;
913 while((stats
!= tail
) && !found
)
915 if(stats
->packet_type
== packet_type
)
918 stats
= (APTR
)stats
->node
.mln_Succ
;
929 /****i* intelpro100.device/FlushUnit ***************************************
935 * FlushUnit(unit, last_queue, error)
937 * VOID FlushUnit(struct DevUnit *, UBYTE, BYTE);
939 ****************************************************************************
943 VOID
FlushUnit(struct DevUnit
*unit
, UBYTE last_queue
, BYTE error
,
944 struct DevBase
*base
)
946 struct IORequest
*request
;
948 struct Opener
*opener
, *tail
;
950 /* Abort queued requests */
952 for(i
= 0; i
<= last_queue
; i
++)
954 while((request
= (APTR
)GetMsg(unit
->request_ports
[i
])) != NULL
)
956 request
->io_Error
= IOERR_ABORTED
;
957 ReplyMsg((APTR
)request
);
962 opener
= (APTR
)unit
->openers
.mlh_Head
;
963 tail
= (APTR
)&unit
->openers
.mlh_Tail
;
965 /* Flush every opener's read queue */
967 while(opener
!= tail
)
969 while((request
= (APTR
)GetMsg(&opener
->read_port
)) != NULL
)
971 request
->io_Error
= error
;
972 ReplyMsg((APTR
)request
);
974 opener
= (APTR
)opener
->node
.mln_Succ
;
978 opener
= request
->ios2_BufferManagement
;
979 while((request
= (APTR
)GetMsg(&opener
->read_port
)) != NULL
)
981 request
->io_Error
= IOERR_ABORTED
;
982 ReplyMsg((APTR
)request
);
993 /****i* intelpro100.device/StatusInt ***************************************
999 * finished = StatusInt(unit)
1001 * BOOL StatusInt(struct DevUnit *);
1004 * unit - A unit of this device.
1007 * finished - Always FALSE.
1009 ****************************************************************************
1013 static BOOL
StatusInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
))
1015 struct DevBase
*base
;
1018 base
= unit
->device
;
1019 ints
= unit
->ByteIn(unit
->card
, PROREG_INTSTATUS
);
1023 /* Handle interrupts */
1025 if((ints
& PROINTF_GENERAL
) != 0)
1026 Cause(&unit
->tx_end_int
);
1027 if((ints
& PROINTF_RXDONE
) != 0)
1028 Cause(&unit
->rx_int
);
1030 /* Acknowledge interrupts */
1032 unit
->ByteOut(unit
->card
, PROREG_INTSTATUS
, ints
);
1040 /****i* intelpro100.device/RXInt *******************************************
1048 * VOID RXInt(struct DevUnit *);
1051 * unit - A unit of this device.
1052 * int_code - Unused.
1057 ****************************************************************************
1061 static VOID
RXInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
))
1064 struct DevBase
*base
;
1065 BOOL is_orphan
, accepted
;
1066 ULONG rx_status_le
, rx_info
, packet_type
, *rcb
, *last_rcb
, dma_size
;
1068 struct IOSana2Req
*request
, *request_tail
;
1069 struct Opener
*opener
, *opener_tail
;
1070 struct TypeStats
*tracker
;
1072 base
= unit
->device
;
1073 last_rcb
= unit
->last_rcb
;
1074 rcb
= (ULONG
*)(UPINT
)LELong(last_rcb
[PROCB_NEXT
]);
1076 dma_size
= RCB_SIZE
;
1077 CachePostDMA(rcb
, &dma_size
, 0);
1078 while(((rx_status_le
= rcb
[PROCB_CONTROL
])
1079 & MakeLELong(PROCB_CONTROLF_DONE
)) != 0)
1081 if((rx_status_le
& MakeLELong(PROCB_CONTROLF_OK
)) != 0)
1084 rx_info
= LELong(rcb
[PROCB_RXINFO
]);
1085 packet_size
= rx_info
& PROCB_RXINFOF_FRAMESIZE
;
1086 buffer
= (UBYTE
*)(rcb
+ PROCB_BUFFER
);
1088 if(AddressFilter(unit
, buffer
+ ETH_PACKET_DEST
, base
))
1090 packet_type
= BEWord(*((UWORD
*)(buffer
+ ETH_PACKET_TYPE
)));
1092 opener
= (APTR
)unit
->openers
.mlh_Head
;
1093 opener_tail
= (APTR
)&unit
->openers
.mlh_Tail
;
1095 /* Offer packet to every opener */
1097 while(opener
!= opener_tail
)
1099 request
= (APTR
)opener
->read_port
.mp_MsgList
.lh_Head
;
1100 request_tail
= (APTR
)&opener
->read_port
.mp_MsgList
.lh_Tail
;
1103 /* Offer packet to each request until it's accepted */
1105 while((request
!= request_tail
) && !accepted
)
1107 if(request
->ios2_PacketType
== packet_type
)
1109 CopyPacket(unit
, request
, packet_size
, packet_type
,
1114 (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
1119 opener
= (APTR
)opener
->node
.mln_Succ
;
1122 /* If packet was unwanted, give it to S2_READORPHAN request */
1126 unit
->stats
.UnknownTypesReceived
++;
1127 if(!IsMsgPortEmpty(unit
->request_ports
[ADOPT_QUEUE
]))
1130 (APTR
)unit
->request_ports
[ADOPT_QUEUE
]->
1131 mp_MsgList
.lh_Head
, packet_size
, packet_type
, buffer
,
1136 /* Update remaining statistics */
1139 FindTypeStats(unit
, &unit
->type_trackers
, packet_type
, base
);
1142 tracker
->stats
.PacketsReceived
++;
1143 tracker
->stats
.BytesReceived
+= packet_size
;
1149 unit
->stats
.BadData
++;
1150 ReportEvents(unit
, S2EVENT_ERROR
| S2EVENT_HARDWARE
| S2EVENT_RX
,
1154 rcb
[PROCB_CONTROL
] = MakeLELong(PROCB_CONTROLF_SUSPEND
);
1156 MakeLELong(ETH_MAXPACKETSIZE
<< PROCB_RXINFOB_BUFFERSIZE
);
1158 /* Clear suspend flag from previous CB without touching bits that
1159 adapter may be writing to; and resume execution */
1161 *(((UBYTE
*)last_rcb
+ PROCB_CONTROL
) + 3) = 0;
1162 dma_size
= RCB_SIZE
;
1163 CachePreDMA(last_rcb
, &dma_size
, 0);
1165 unit
->LEWordOut(unit
->card
, PROREG_COMMAND
, PRO_RUCMD_RESUME
);
1168 rcb
= (ULONG
*)(UPINT
)LELong(rcb
[PROCB_NEXT
]);
1173 unit
->last_rcb
= last_rcb
;
1179 /****i* intelpro100.device/CopyPacket **************************************
1185 * CopyPacket(unit, request, packet_size, packet_type,
1188 * VOID CopyPacket(struct DevUnit *, struct IOSana2Req *, UWORD, UWORD,
1191 ****************************************************************************
1195 static VOID
CopyPacket(struct DevUnit
*unit
, struct IOSana2Req
*request
,
1196 UWORD packet_size
, UWORD packet_type
, UBYTE
*buffer
,
1197 struct DevBase
*base
)
1199 struct Opener
*opener
;
1200 BOOL filtered
= FALSE
;
1202 /* Set multicast and broadcast flags */
1204 request
->ios2_Req
.io_Flags
&= ~(SANA2IOF_BCAST
| SANA2IOF_MCAST
);
1205 if((*((ULONG
*)(buffer
+ ETH_PACKET_DEST
)) == 0xffffffff) &&
1206 (*((UWORD
*)(buffer
+ ETH_PACKET_DEST
+ 4)) == 0xffff))
1207 request
->ios2_Req
.io_Flags
|= SANA2IOF_BCAST
;
1208 else if((buffer
[ETH_PACKET_DEST
] & 0x1) != 0)
1209 request
->ios2_Req
.io_Flags
|= SANA2IOF_MCAST
;
1211 /* Set source and destination addresses and packet type */
1213 CopyMem(buffer
+ ETH_PACKET_SOURCE
, request
->ios2_SrcAddr
,
1215 CopyMem(buffer
+ ETH_PACKET_DEST
, request
->ios2_DstAddr
,
1217 request
->ios2_PacketType
= packet_type
;
1219 /* Adjust for cooked packet request */
1221 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
1223 packet_size
-= ETH_PACKET_DATA
;
1224 buffer
+= ETH_PACKET_DATA
;
1228 packet_size
+= 4; /* Needed for Shapeshifter & Fusion */
1230 request
->ios2_DataLength
= packet_size
;
1234 opener
= request
->ios2_BufferManagement
;
1235 if((request
->ios2_Req
.io_Command
== CMD_READ
) &&
1236 (opener
->filter_hook
!= NULL
))
1237 if(!CallHookPkt(opener
->filter_hook
, request
, buffer
))
1242 /* Copy packet into opener's buffer and reply packet */
1244 if(!opener
->rx_function(request
->ios2_Data
, buffer
, packet_size
))
1246 request
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
1247 request
->ios2_WireError
= S2WERR_BUFF_ERROR
;
1249 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
| S2EVENT_RX
,
1252 Remove((APTR
)request
);
1253 ReplyMsg((APTR
)request
);
1261 /****i* intelpro100.device/AddressFilter ***********************************
1267 * accept = AddressFilter(unit, address)
1269 * BOOL AddressFilter(struct DevUnit *, UBYTE *);
1271 ****************************************************************************
1275 static BOOL
AddressFilter(struct DevUnit
*unit
, UBYTE
*address
,
1276 struct DevBase
*base
)
1278 struct AddressRange
*range
, *tail
;
1281 UWORD address_right
;
1283 /* Check whether address is unicast/broadcast or multicast */
1285 address_left
= BELong(*((ULONG
*)address
));
1286 address_right
= BEWord(*((UWORD
*)(address
+ 4)));
1288 if((address_left
& 0x01000000) != 0 &&
1289 !(address_left
== 0xffffffff && address_right
== 0xffff))
1291 /* Check if this multicast address is wanted */
1293 range
= (APTR
)unit
->multicast_ranges
.mlh_Head
;
1294 tail
= (APTR
)&unit
->multicast_ranges
.mlh_Tail
;
1297 while((range
!= tail
) && !accept
)
1299 if(((address_left
> range
->lower_bound_left
) ||
1300 (address_left
== range
->lower_bound_left
) &&
1301 (address_right
>= range
->lower_bound_right
)) &&
1302 ((address_left
< range
->upper_bound_left
) ||
1303 (address_left
== range
->upper_bound_left
) &&
1304 (address_right
<= range
->upper_bound_right
)))
1306 range
= (APTR
)range
->node
.mln_Succ
;
1310 unit
->special_stats
[S2SS_ETHERNET_BADMULTICAST
& 0xffff]++;
1318 /****i* intelpro100.device/TXInt *******************************************
1326 * VOID TXInt(struct DevUnit *);
1329 * unit - A unit of this device.
1330 * int_code - Unused.
1335 ****************************************************************************
1337 * Note that when the CU is resumed, the adapter examines the suspend flag
1338 * again in the command that caused the suspension. If the flag is set, the
1339 * CU will be suspended without executing any new commands. This means that
1340 * all TCBs can't be in use at the same time, and the dynamically inserted
1341 * multicast list command can't have its suspend flag set.
1345 static VOID
TXInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
))
1347 struct DevBase
*base
;
1348 UWORD packet_size
, data_size
, *p
, *q
, i
;
1349 struct IOSana2Req
*request
;
1350 BOOL proceed
= TRUE
;
1351 struct Opener
*opener
;
1352 ULONG wire_error
, *tcb
, *last_tcb
, *mcast_cb
, *fragment
, dma_size
,
1354 UBYTE
*(*dma_tx_function
)(REG(a0
, APTR
));
1357 struct MsgPort
*port
;
1359 base
= unit
->device
;
1360 port
= unit
->request_ports
[WRITE_QUEUE
];
1362 while(proceed
&& !IsMsgPortEmpty(port
))
1364 last_tcb
= unit
->last_tcb
;
1365 tcb
= (ULONG
*)(UPINT
)LELong(last_tcb
[PROCB_NEXT
]);
1367 /* Ensure there are at least two free CBs available (two are needed
1368 for setting the multicast filter) and that neither the TX nor the
1369 multicast buffer is currently in use */
1371 if((UPINT
)LELong(((ULONG
*)(UPINT
)LELong(tcb
[PROCB_NEXT
]))[PROCB_NEXT
])
1372 != (UPINT
)unit
->first_tcb
1373 && (unit
->flags
& (UNITF_TXBUFFERINUSE
| UNITF_MCASTBUFFERINUSE
))
1377 request
= (APTR
)GetMsg(port
);
1378 request
->ios2_Req
.io_Message
.mn_Node
.ln_Type
= NT_FREEMSG
;
1380 switch(request
->ios2_Req
.io_Command
)
1388 action
= PROACT_CONFIGURE
;
1391 if(action
== PROACT_TX
)
1393 /* Handle TX request */
1395 data_size
= packet_size
= request
->ios2_DataLength
;
1397 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
1398 packet_size
+= ETH_HEADERSIZE
;
1400 /* Write packet preamble */
1402 tcb
[PROCB_CONTROL
] =
1403 MakeLELong(PROACT_TX
| PROCB_CONTROLF_SUSPEND
1404 | PROCB_CONTROLF_INT
| PROCB_CONTROLF_FLEXIBLE
);
1405 fragment
= tcb
+ PROCB_EXTFRAGS
;
1406 tcb
[PROCB_FRAGMENTS
] = MakeLELong((ULONG
)(UPINT
)fragment
);
1408 /* Write packet header */
1410 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
1412 buffer
= (UBYTE
*)(tcb
+ PROCB_EXTBUFFER
);
1414 MakeLELong(2 << PROCB_TXINFOB_FRAGCOUNT
1415 | 1 << PROCB_TXINFOB_THRESHOLD
1416 | PROCB_TXINFOF_EOF
);
1417 fragment
[PROFRAG_ADDR
] = MakeLELong((ULONG
)(UPINT
)buffer
);
1418 fragment
[PROFRAG_LEN
] = MakeLELong(ETH_HEADERSIZE
);
1420 p
= (UWORD
*)buffer
;
1421 for(i
= 0, q
= (UWORD
*)request
->ios2_DstAddr
;
1422 i
< ETH_ADDRESSSIZE
/ 2; i
++)
1424 for(i
= 0, q
= (UWORD
*)unit
->address
;
1425 i
< ETH_ADDRESSSIZE
/ 2; i
++)
1427 *p
++ = MakeBEWord(request
->ios2_PacketType
);
1428 buffer
= (UBYTE
*)p
;
1430 fragment
+= PRO_FRAGLEN
;
1435 MakeLELong(1 << PROCB_TXINFOB_FRAGCOUNT
1436 | 1 << PROCB_TXINFOB_THRESHOLD
1437 | PROCB_TXINFOF_EOF
);
1440 /* Get packet data */
1442 opener
= (APTR
)request
->ios2_BufferManagement
;
1443 dma_tx_function
= opener
->dma_tx_function
;
1444 if(dma_tx_function
!= NULL
)
1445 buffer
= dma_tx_function(request
->ios2_Data
);
1451 buffer
= unit
->tx_buffer
;
1452 if(opener
->tx_function(buffer
, request
->ios2_Data
,
1455 unit
->flags
|= UNITF_TXBUFFERINUSE
;
1459 error
= S2ERR_NO_RESOURCES
;
1460 wire_error
= S2WERR_BUFF_ERROR
;
1462 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
1463 | S2EVENT_TX
, base
);
1467 /* Put pointer to packet data into descriptor */
1471 dma_size
= data_size
;
1472 CachePreDMA(buffer
, &dma_size
, DMA_ReadFromRAM
);
1473 fragment
[PROFRAG_ADDR
] = MakeLELong((ULONG
)(UPINT
)buffer
);
1474 fragment
[PROFRAG_LEN
] = MakeLELong(data_size
);
1479 /* Update multicast reception filter */
1481 SetMulticast(unit
, base
);
1482 if((unit
->flags
& UNITF_ALLMCAST
) == 0)
1484 tcb
[PROCB_CONTROL
] = MakeLELong(PROACT_NOP
);
1485 mcast_cb
= unit
->multicast_cb
;
1486 mcast_cb
[PROCB_CONTROL
] = MakeLELong(PROACT_SETMCAST
);
1487 mcast_cb
[PROCB_NEXT
] = tcb
[PROCB_NEXT
];
1488 tcb
[PROCB_NEXT
] = MakeLELong((ULONG
)(UPINT
)mcast_cb
);
1489 unit
->link_cb
= tcb
;
1490 tcb
= (ULONG
*)(UPINT
)LELong(mcast_cb
[PROCB_NEXT
]);
1491 tcb
[PROCB_CONTROL
] = MakeLELong(PROACT_CONFIGURE
1492 | PROCB_CONTROLF_SUSPEND
| PROCB_CONTROLF_INT
);
1493 FillConfigData(unit
, tcb
, base
);
1494 unit
->flags
|= UNITF_MCASTBUFFERINUSE
;
1498 tcb
[PROCB_CONTROL
] = MakeLELong(PROACT_CONFIGURE
1499 | PROCB_CONTROLF_SUSPEND
| PROCB_CONTROLF_INT
);
1500 FillConfigData(unit
, tcb
, base
);
1506 /* Clear suspend flag from previous CB without touching bits
1507 that adapter may be writing to; and resume execution */
1509 if(last_tcb
[PROCB_CONTROL
] != 0)
1510 *(((UBYTE
*)last_tcb
+ PROCB_CONTROL
) + 3) =
1511 PROCB_CONTROLF_INT
>> 24;
1512 dma_size
= TCB_SIZE
* TX_SLOT_COUNT
;
1513 CachePreDMA(unit
->tcbs
, &dma_size
, 0);
1514 dma_size
= MCAST_CB_SIZE
;
1515 CachePreDMA(unit
->multicast_cb
, &dma_size
, 0);
1516 if((unit
->ByteIn(unit
->card
, PROREG_STATUS
)
1517 & PROREG_STATUSF_CUSTATE
)
1518 == (PRO_CUSTATE_SUSPENDED
<< PROREG_STATUSB_CUSTATE
))
1520 unit
->LEWordOut(unit
->card
, PROREG_COMMAND
,
1524 AddTail((APTR
)&unit
->tx_requests
, (APTR
)request
);
1525 unit
->last_tcb
= tcb
;
1529 /* Return failed request */
1531 request
->ios2_Req
.io_Error
= error
;
1532 request
->ios2_WireError
= wire_error
;
1533 ReplyMsg((APTR
)request
);
1534 tcb
[PROCB_CONTROL
] = 0;
1542 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
1544 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_IGNORE
;
1551 /****i* intelpro100.device/TXEndInt ****************************************
1559 * VOID TXEndInt(struct DevUnit *);
1562 * unit - A unit of this device.
1563 * int_code - Unused.
1568 ****************************************************************************
1570 * It appears to be safe to assume that there will always be at least one
1571 * completed packet whenever this interrupt is called.
1575 static VOID
TXEndInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
))
1577 UWORD data_size
, packet_size
;
1579 struct DevBase
*base
;
1580 struct IOSana2Req
*request
;
1581 ULONG
*tcb
, *fragment
, dma_size
, action
;
1582 struct TypeStats
*tracker
;
1584 /* Retire sent packets and configuration commands */
1586 base
= unit
->device
;
1587 dma_size
= TCB_SIZE
* TX_SLOT_COUNT
;
1588 CachePostDMA(unit
->tcbs
, &dma_size
, 0);
1589 dma_size
= MCAST_CB_SIZE
;
1590 CachePostDMA(unit
->multicast_cb
, &dma_size
, 0);
1592 for(tcb
= unit
->first_tcb
;
1593 (tcb
[PROCB_CONTROL
] & MakeLELong(PROCB_CONTROLF_DONE
)) != 0;
1594 tcb
= (ULONG
*)(UPINT
)LELong(tcb
[PROCB_NEXT
]))
1596 action
= LELong(tcb
[PROCB_CONTROL
]) & PROCB_CONTROLF_ACTION
;
1598 if(action
== PROACT_TX
|| action
== PROACT_CONFIGURE
1599 && (unit
->link_cb
!= NULL
1600 || (tcb
[PROCB_CF5
] & PROCB_CF5F_ALLMCAST
) != 0))
1602 request
= (APTR
)RemHead((APTR
)&unit
->tx_requests
);
1604 if(action
== PROACT_TX
)
1606 /* Mark end of DMA */
1608 data_size
= packet_size
= request
->ios2_DataLength
;
1609 fragment
= (ULONG
*)(UPINT
)LELong(tcb
[PROCB_FRAGMENTS
]);
1611 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
1613 packet_size
+= ETH_HEADERSIZE
;
1614 fragment
+= PRO_FRAGLEN
;
1617 buffer
= (UBYTE
*)(UPINT
)LELong(fragment
[PROFRAG_ADDR
]);
1618 dma_size
= data_size
;
1619 CachePostDMA(buffer
, &dma_size
, DMA_ReadFromRAM
);
1621 /* Check if unit's buffer is now free */
1623 if(buffer
== unit
->tx_buffer
)
1624 unit
->flags
&= ~UNITF_TXBUFFERINUSE
;
1626 /* Update statistics */
1628 tracker
= FindTypeStats(unit
, &unit
->type_trackers
,
1629 request
->ios2_PacketType
, base
);
1632 tracker
->stats
.PacketsSent
++;
1633 tracker
->stats
.BytesSent
+= packet_size
;
1636 else if(action
== PROACT_CONFIGURE
)
1638 /* Mark end of multicast update */
1640 if(unit
->link_cb
!= NULL
)
1642 unit
->link_cb
[PROCB_NEXT
] = MakeLELong((ULONG
)(UPINT
)tcb
);
1643 unit
->flags
&= ~UNITF_MCASTBUFFERINUSE
;
1644 unit
->link_cb
= NULL
;
1650 request
->ios2_Req
.io_Error
= 0;
1651 ReplyMsg((APTR
)request
);
1654 /* Mark CB as unused/clear suspend flag */
1656 tcb
[PROCB_CONTROL
] = 0;
1659 dma_size
= TCB_SIZE
* TX_SLOT_COUNT
;
1660 CachePreDMA(unit
->tcbs
, &dma_size
, 0);
1662 unit
->first_tcb
= tcb
;
1664 /* Restart downloads if they had stopped */
1666 if(unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
== PA_IGNORE
)
1667 Cause(&unit
->tx_int
);
1674 /****i* intelpro100.device/UpdateStats *************************************
1682 * VOID UpdateStats(struct DevUnit *);
1685 * unit - A unit of this device.
1690 ****************************************************************************
1694 VOID
UpdateStats(struct DevUnit
*unit
, struct DevBase
*base
)
1696 ULONG dma_size
, *buffer
;
1698 buffer
= unit
->stats_buffer
;
1699 buffer
[STAT_COUNT
] = 0;
1700 dma_size
= sizeof(ULONG
) * STAT_COUNT
;
1701 CachePreDMA(unit
->stats_buffer
, &dma_size
, 0);
1702 unit
->ByteOut(unit
->card
, PROREG_COMMAND
, PRO_CUCMD_DUMPRESETSTATS
);
1703 while(buffer
[STAT_COUNT
] != MakeLELong(0xa007))
1705 dma_size
= sizeof(ULONG
) * STAT_COUNT
;
1706 CachePostDMA(unit
->stats_buffer
, &dma_size
, 0);
1709 unit
->stats
.Overruns
+= LELong(buffer
[PROSTAT_RXOVERRUNS
]);
1710 unit
->stats
.PacketsSent
+= LELong(buffer
[PROSTAT_TXFRAMESOK
]);
1711 unit
->stats
.PacketsReceived
+= LELong(buffer
[PROSTAT_RXFRAMESOK
]);
1712 unit
->special_stats
[S2SS_ETHERNET_RETRIES
& 0xffff] +=
1713 LELong(buffer
[PROSTAT_FRAMESDEFERRED
]);
1714 unit
->special_stats
[S2SS_ETHERNET_FIFO_UNDERRUNS
& 0xffff] +=
1715 LELong(buffer
[PROSTAT_TXUNDERRUNS
]);
1722 /****i* intelpro100.device/ReportEvents ************************************
1728 * ReportEvents(unit, events)
1730 * VOID ReportEvents(struct DevUnit *, ULONG);
1733 * unit - A unit of this device.
1734 * events - A mask of events to report.
1739 ****************************************************************************
1743 static VOID
ReportEvents(struct DevUnit
*unit
, ULONG events
,
1744 struct DevBase
*base
)
1746 struct IOSana2Req
*request
, *tail
, *next_request
;
1749 list
= &unit
->request_ports
[EVENT_QUEUE
]->mp_MsgList
;
1750 next_request
= (APTR
)list
->lh_Head
;
1751 tail
= (APTR
)&list
->lh_Tail
;
1754 while(next_request
!= tail
)
1756 request
= next_request
;
1757 next_request
= (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
1759 if((request
->ios2_WireError
& events
) != 0)
1761 request
->ios2_WireError
= events
;
1762 Remove((APTR
)request
);
1763 ReplyMsg((APTR
)request
);
1773 /****i* intelpro100.device/UnitTask ****************************************
1781 * VOID UnitTask(struct DevUnit *);
1784 * Completes deferred requests.
1786 ****************************************************************************
1790 static VOID
UnitTask(struct DevUnit
*unit
)
1792 struct DevBase
*base
;
1793 struct IORequest
*request
;
1794 struct MsgPort
*general_port
;
1795 ULONG signals
, wait_signals
, general_port_signal
;
1797 base
= unit
->device
;
1799 /* Activate general request port */
1801 general_port
= unit
->request_ports
[GENERAL_QUEUE
];
1802 general_port
->mp_SigTask
= unit
->task
;
1803 general_port
->mp_SigBit
= AllocSignal(-1);
1804 general_port_signal
= 1 << general_port
->mp_SigBit
;
1805 general_port
->mp_Flags
= PA_SIGNAL
;
1807 /* Allocate a signal for notification of card removal */
1809 wait_signals
= (1 << general_port
->mp_SigBit
);
1811 /* Tell ourselves to check port for old messages */
1813 Signal(unit
->task
, general_port_signal
);
1815 /* Infinite loop to service requests and signals */
1819 signals
= Wait(wait_signals
);
1821 if((signals
& general_port_signal
) != 0)
1823 while((request
= (APTR
)GetMsg(general_port
)) != NULL
)
1825 /* Service the request as soon as the unit is free */
1827 ObtainSemaphore(&unit
->access_lock
);
1828 ServiceRequest((APTR
)request
, base
);
1836 /****i* intelpro100.device/GetEEPROMAddressSize ****************************
1839 * GetEEPROMAddressSize
1842 * size = GetEEPROMAddressSize(unit)
1844 * UWORD GetEEPROMAddressSize(struct DevUnit *);
1847 * unit - A unit of this device.
1850 * size - Width of EEPROM addresses.
1852 ****************************************************************************
1854 * Although the manual doesn't make it explicit, chip select must be asserted
1855 * before setting any other bits, at least on the i82557.
1859 static UWORD
GetEEPROMAddressSize(struct DevUnit
*unit
,
1860 struct DevBase
*base
)
1864 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
, PROREG_EEPROMF_SELECT
);
1865 WriteEEPROMBits(unit
, 0x6, 3, base
);
1866 for(size
= 1; WriteEEPROMBit(unit
, FALSE
, base
); size
++);
1867 ReadEEPROMBits(unit
, 16, base
);
1868 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
, 0);
1869 BusyMicroDelay(1, base
);
1876 /****i* intelpro100.device/ReadEEPROM **************************************
1879 * ReadEEPROM -- Read an EEPROM location.
1882 * value = ReadEEPROM(unit, index)
1884 * UWORD ReadEEPROM(struct DevUnit *, UWORD);
1887 * unit - A unit of this device.
1888 * index - Offset within EEPROM.
1891 * value - Contents of specified EEPROM location.
1893 ****************************************************************************
1897 static UWORD
ReadEEPROM(struct DevUnit
*unit
, UWORD index
,
1898 struct DevBase
*base
)
1902 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
, PROREG_EEPROMF_SELECT
);
1903 WriteEEPROMBits(unit
, 0x6, 3, base
);
1904 WriteEEPROMBits(unit
, index
, unit
->eeprom_addr_size
, base
);
1905 value
= ReadEEPROMBits(unit
, 16, base
);
1906 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
, 0);
1907 BusyMicroDelay(1, base
);
1914 /****i* intelpro100.device/ReadEEPROMBits **********************************
1917 * ReadEEPROMBits -- Read a stream of bits from the EEPROM.
1920 * value = ReadEEPROMBits(unit, count)
1922 * ULONG ReadEEPROMBits(struct DevUnit *, UBYTE);
1925 * unit - A unit of this device.
1926 * count - Number of bits to be read.
1929 * value - The bits read from the EEPROM, right-justified.
1931 ****************************************************************************
1935 static ULONG
ReadEEPROMBits(struct DevUnit
*unit
, UBYTE count
,
1936 struct DevBase
*base
)
1941 for(i
= 0; i
< count
; i
++)
1944 if(ReadEEPROMBit(unit
, base
))
1952 /****i* intelpro100.device/WriteEEPROMBits *********************************
1955 * WriteEEPROMBits -- Write a stream of bits to the EEPROM.
1958 * WriteEEPROMBits(unit, value, count)
1960 * VOID WriteEEPROMBits(struct DevUnit *, ULONG, UBYTE);
1963 * unit - A unit of this device.
1964 * value - The bits to write to the EEPROM, right-justified.
1965 * count - Number of bits to be Write.
1970 ****************************************************************************
1974 static VOID
WriteEEPROMBits(struct DevUnit
*unit
, ULONG value
, UBYTE count
,
1975 struct DevBase
*base
)
1979 for(mask
= 1 << (count
- 1); mask
!= 0; mask
>>= 1)
1980 WriteEEPROMBit(unit
, (value
& mask
) != 0, base
);
1987 /****i* intelpro100.device/ReadEEPROMBit ***********************************
1990 * ReadEEPROMBit -- Read a bit from the EEPROM.
1993 * value = ReadEEPROMBit(unit)
1995 * BOOL ReadEEPROMBit(struct DevUnit *);
1998 * unit - A unit of this device.
2001 * value - True for one, false for zero.
2003 ****************************************************************************
2007 static BOOL
ReadEEPROMBit(struct DevUnit
*unit
, struct DevBase
*base
)
2011 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
,
2012 PROREG_EEPROMF_SELECT
| PROREG_EEPROMF_CLK
);
2013 BusyMicroDelay(2, base
);
2015 (unit
->LEWordIn(unit
->card
, PROREG_EEPROM
) & PROREG_EEPROMF_DATAIN
)
2017 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
, PROREG_EEPROMF_SELECT
);
2018 BusyMicroDelay(2, base
);
2025 /****i* intelpro100.device/WriteEEPROMBit **********************************
2028 * WriteEEPROMBit -- Write a bit to the EEPROM.
2031 * data_in = WriteEEPROMBit(unit, is_one)
2033 * BOOL WriteEEPROMBit(struct DevUnit *, BOOL);
2036 * unit - A unit of this device.
2037 * is_one - True if a set bit should be written.
2040 * data_in - True if data-in bit is set.
2042 ****************************************************************************
2046 static BOOL
WriteEEPROMBit(struct DevUnit
*unit
, BOOL is_one
,
2047 struct DevBase
*base
)
2052 data_out
= PROREG_EEPROMF_DATAOUT
;
2056 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
,
2057 PROREG_EEPROMF_SELECT
| data_out
);
2058 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
,
2059 PROREG_EEPROMF_SELECT
| PROREG_EEPROMF_CLK
| data_out
);
2060 BusyMicroDelay(2, base
);
2061 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
,
2062 PROREG_EEPROMF_SELECT
| data_out
);
2063 BusyMicroDelay(2, base
);
2066 (unit
->LEWordIn(unit
->card
, PROREG_EEPROM
) & PROREG_EEPROMF_DATAIN
)
2072 /****i* intelpro100.device/ReadMII *****************************************
2075 * ReadMII -- Read a register in an MII PHY.
2078 * value = ReadMII(unit, phy_no, reg_no)
2080 * UWORD ReadMII(struct DevUnit *, UWORD, UWORD);
2083 * unit - A unit of this device.
2084 * phy_no - Index of PHY to use.
2085 * reg_no - MII register to read.
2088 * value - Value read from MII register.
2090 ****************************************************************************
2094 static UWORD
ReadMII(struct DevUnit
*unit
, UWORD phy_no
, UWORD reg_no
,
2095 struct DevBase
*base
)
2099 unit
->LELongOut(unit
->card
, PROREG_MIICONTROL
,
2100 2 << PROREG_MIICONTROLB_CMD
2101 | phy_no
<< PROREG_MIICONTROLB_PHYNO
2102 | reg_no
<< PROREG_MIICONTROLB_REGNO
);
2104 value
= unit
->LELongIn(unit
->card
, PROREG_MIICONTROL
);
2105 while((value
& PROREG_MIICONTROLF_READY
) == 0);
2107 return value
& PROREG_MIICONTROLF_DATA
;
2112 /****i* intelpro100.device/WriteMII ****************************************
2115 * WriteMII -- Write to a register in an MII PHY.
2118 * WriteMII(unit, phy_no, reg_no, value)
2120 * VOID WriteMII(struct DevUnit *, UWORD, UWORD, UWORD);
2123 * unit - A unit of this device.
2124 * phy_no - Index of PHY to use.
2125 * reg_no - MII register to write to.
2126 * value - Value to write to MII register.
2131 ****************************************************************************
2135 static VOID
WriteMII(struct DevUnit
*unit
, UWORD phy_no
, UWORD reg_no
,
2136 UWORD value
, struct DevBase
*base
)
2138 unit
->LELongOut(unit
->card
, PROREG_MIICONTROL
,
2139 1 << PROREG_MIICONTROLB_CMD
2140 | phy_no
<< PROREG_MIICONTROLB_PHYNO
2141 | reg_no
<< PROREG_MIICONTROLB_REGNO
2146 unit
->LELongIn(unit
->card
, PROREG_MIICONTROL
)
2147 & PROREG_MIICONTROLF_READY
2157 /****i* intelpro100.device/BusyMicroDelay **********************************
2160 * BusyMilliDelay - Busy-wait for specified number of microseconds.
2163 * BusyMilliDelay(micros)
2165 * VOID BusyMilliDelay(ULONG);
2167 ****************************************************************************
2172 static VOID
BusyMicroDelay(ULONG micros
, struct DevBase
*base
)
2174 struct timeval time
, end_time
;
2176 GetSysTime(&end_time
);
2178 time
.tv_micro
= micros
;
2179 AddTime(&end_time
, &time
);
2181 while(CmpTime(&end_time
, &time
) < 0)
2189 static VOID
BusyMicroDelay(ULONG micros
, struct DevBase
*base
)
2191 struct EClockVal time
, end_time
;
2194 rate
= ReadEClock(&time
);
2195 end_time
.ev_hi
= time
.ev_hi
;
2196 end_time
.ev_lo
= time
.ev_lo
+ (micros
* rate
+ 1) / 1000000;
2197 if(end_time
.ev_lo
< time
.ev_lo
)
2200 while(time
.ev_lo
< end_time
.ev_lo
|| time
.ev_hi
< end_time
.ev_hi
)