3 Copyright (C) 2001-2012 Neil Cafferkey
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
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 sys_base
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(struct ExecBase
*sys_base
);
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 #define AddTask(task, initial_pc, final_pc) \
126 struct TagItem _task_tags[] = \
127 {{TASKTAG_ARG1, (IPTR)SysBase}, {TAG_END, 0}}; \
128 NewAddTask(task, initial_pc, final_pc, _task_tags); \
133 /****i* intelpro100.device/CreateUnit **************************************
136 * CreateUnit -- Create a unit.
139 * unit = CreateUnit(index, card, io_tags, bus)
141 * struct DevUnit *CreateUnit(ULONG, APTR, struct TagItem *, UWORD);
144 * Creates a new unit.
146 ****************************************************************************
150 struct DevUnit
*CreateUnit(ULONG index
, APTR card
,
151 struct TagItem
*io_tags
, UWORD bus
, struct DevBase
*base
)
154 struct DevUnit
*unit
;
156 struct MsgPort
*port
;
159 ULONG
*tcb
, *next_tcb
, *rcb
, *next_rcb
, dma_size
;
160 APTR rx_int_function
, tx_int_function
;
162 unit
= AllocMem(sizeof(struct DevUnit
), MEMF_CLEAR
| MEMF_PUBLIC
);
168 /* Initialise lists etc. */
170 InitSemaphore(&unit
->access_lock
);
171 NewList((APTR
)&unit
->openers
);
172 NewList((APTR
)&unit
->type_trackers
);
173 NewList((APTR
)&unit
->multicast_ranges
);
174 NewList((APTR
)&unit
->tx_requests
);
181 /* Store I/O hooks */
184 (APTR
)GetTagData(IOTAG_ByteIn
, (UPINT
)NULL
, io_tags
);
186 (APTR
)GetTagData(IOTAG_ByteOut
, (UPINT
)NULL
, io_tags
);
188 (APTR
)GetTagData(IOTAG_LEWordIn
, (UPINT
)NULL
, io_tags
);
190 (APTR
)GetTagData(IOTAG_LELongIn
, (UPINT
)NULL
, io_tags
);
192 (APTR
)GetTagData(IOTAG_LEWordOut
, (UPINT
)NULL
, io_tags
);
194 (APTR
)GetTagData(IOTAG_LELongOut
, (UPINT
)NULL
, io_tags
);
196 (APTR
)GetTagData(IOTAG_AllocDMAMem
, (UPINT
)NULL
, io_tags
);
198 (APTR
)GetTagData(IOTAG_FreeDMAMem
, (UPINT
)NULL
, io_tags
);
199 if(unit
->ByteIn
== NULL
200 || unit
->ByteOut
== NULL
201 || unit
->LEWordIn
== NULL
202 || unit
->LEWordOut
== NULL
|| unit
->LELongIn
== NULL
203 || unit
->LELongOut
== NULL
204 || unit
->AllocDMAMem
== NULL
|| unit
->FreeDMAMem
== NULL
)
207 /* Allocate buffer for adapter to writes statistics to */
210 AllocVec(sizeof(ULONG
) * (STAT_COUNT
+ 1), MEMF_PUBLIC
);
211 if(unit
->stats_buffer
== NULL
)
217 /* Initialise network adapter hardware */
219 InitialiseAdapter(unit
, base
);
220 unit
->flags
|= UNITF_HAVEADAPTER
;
222 /* Create the message ports for queuing requests */
224 for(i
= 0; i
< REQUEST_QUEUE_COUNT
; i
++)
226 unit
->request_ports
[i
] = port
= AllocMem(sizeof(struct MsgPort
),
227 MEMF_PUBLIC
| MEMF_CLEAR
);
233 NewList(&port
->mp_MsgList
);
234 port
->mp_Flags
= PA_IGNORE
;
235 port
->mp_SigTask
= &unit
->tx_int
;
239 /* Allocate and initialise packet/command descriptors */
241 unit
->tx_buffer
= AllocVec(ETH_MAXPACKETSIZE
, MEMF_PUBLIC
);
242 next_tcb
= unit
->first_tcb
= unit
->tcbs
=
243 AllocVec(TCB_SIZE
* TX_SLOT_COUNT
, MEMF_PUBLIC
| MEMF_CLEAR
);
244 next_rcb
= unit
->rcbs
=
245 AllocVec(RCB_SIZE
* RX_SLOT_COUNT
, MEMF_PUBLIC
| MEMF_CLEAR
);
246 unit
->multicast_cb
= AllocVec(PROCB_COUNT
* sizeof(ULONG
)
247 + sizeof(UWORD
) + ETH_ADDRESSSIZE
* MAX_MCAST_ENTRIES
,
248 MEMF_PUBLIC
| MEMF_CLEAR
);
250 if(next_tcb
== NULL
|| next_rcb
== NULL
|| unit
->tx_buffer
== NULL
251 || unit
->multicast_cb
== NULL
)
257 /* Construct TX ring */
259 for(i
= 0; i
< TX_SLOT_COUNT
; i
++)
262 next_tcb
= tcb
+ TCB_SIZE
/ sizeof(ULONG
);
263 tcb
[PROCB_NEXT
] = MakeLELong((ULONG
)(IPTR
)next_tcb
);
265 tcb
[PROCB_NEXT
] = MakeLELong((ULONG
)(IPTR
)unit
->tcbs
);
266 unit
->last_tcb
= tcb
;
268 /* Construct RX ring */
270 for(i
= 0; i
< RX_SLOT_COUNT
; i
++)
273 next_rcb
= rcb
+ RCB_SIZE
/ sizeof(ULONG
);
274 rcb
[PROCB_NEXT
] = MakeLELong((ULONG
)(IPTR
)next_rcb
);
276 MakeLELong(ETH_MAXPACKETSIZE
<< PROCB_RXINFOB_BUFFERSIZE
);
278 rcb
[PROCB_CONTROL
] = MakeLELong(PROCB_CONTROLF_SUSPEND
);
279 rcb
[PROCB_NEXT
] = MakeLELong((ULONG
)(IPTR
)unit
->rcbs
);
280 unit
->last_rcb
= rcb
;
281 dma_size
= RCB_SIZE
* RX_SLOT_COUNT
;
282 CachePreDMA(unit
->rcbs
, &dma_size
, 0);
284 /* Record maximum speed in BPS */
286 unit
->speed
= 100000000;
288 /* Initialise status, transmit and receive interrupts */
290 unit
->status_int
.is_Code
= (APTR
)StatusInt
;
291 unit
->status_int
.is_Data
= unit
;
293 rx_int_function
= RXInt
;
294 unit
->rx_int
.is_Node
.ln_Name
=
295 base
->device
.dd_Library
.lib_Node
.ln_Name
;
296 unit
->rx_int
.is_Node
.ln_Pri
= 16;
297 unit
->rx_int
.is_Code
= rx_int_function
;
298 unit
->rx_int
.is_Data
= unit
;
300 tx_int_function
= TXInt
;
301 unit
->tx_int
.is_Node
.ln_Name
=
302 base
->device
.dd_Library
.lib_Node
.ln_Name
;
303 unit
->tx_int
.is_Code
= tx_int_function
;
304 unit
->tx_int
.is_Data
= unit
;
306 unit
->tx_end_int
.is_Node
.ln_Name
=
307 base
->device
.dd_Library
.lib_Node
.ln_Name
;
308 unit
->tx_end_int
.is_Code
= TXEndInt
;
309 unit
->tx_end_int
.is_Data
= unit
;
311 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
316 /* Create a new task */
319 AllocMem(sizeof(struct Task
), MEMF_PUBLIC
| MEMF_CLEAR
);
328 stack
= AllocMem(STACK_SIZE
, MEMF_PUBLIC
);
335 /* Initialise and start task */
337 task
->tc_Node
.ln_Type
= NT_TASK
;
338 task
->tc_Node
.ln_Pri
= TASK_PRIORITY
;
339 task
->tc_Node
.ln_Name
=
340 base
->device
.dd_Library
.lib_Node
.ln_Name
;
341 task
->tc_SPUpper
= stack
+ STACK_SIZE
;
342 task
->tc_SPLower
= stack
;
343 task
->tc_SPReg
= stack
+ STACK_SIZE
;
344 NewList(&task
->tc_MemEntry
);
346 if(AddTask(task
, UnitTask
, NULL
) == NULL
)
350 /* Send the unit to the new task */
353 task
->tc_UserData
= unit
;
357 DeleteUnit(unit
, base
);
366 /****i* intelpro100.device/DeleteUnit **************************************
369 * DeleteUnit -- Delete a unit.
374 * VOID DeleteUnit(struct DevUnit *);
380 * unit - Device unit (can be NULL).
385 ****************************************************************************
389 VOID
DeleteUnit(struct DevUnit
*unit
, struct DevBase
*base
)
399 if(task
->tc_UserData
!= NULL
)
401 if(task
->tc_SPLower
!= NULL
)
402 FreeMem(task
->tc_SPLower
, STACK_SIZE
);
403 FreeMem(task
, sizeof(struct Task
));
406 for(i
= 0; i
< REQUEST_QUEUE_COUNT
; i
++)
408 if(unit
->request_ports
[i
] != NULL
)
409 FreeMem(unit
->request_ports
[i
], sizeof(struct MsgPort
));
412 if((unit
->flags
& UNITF_ONLINE
) != 0) /* Needed! */
413 GoOffline(unit
, base
);
415 FreeVec(unit
->multicast_cb
);
418 FreeVec(unit
->tx_buffer
);
419 FreeVec(unit
->stats_buffer
);
421 FreeMem(unit
, sizeof(struct DevUnit
));
429 /****i* intelpro100.device/InitialiseAdapter *******************************
432 * InitialiseAdapter -- Initialise network adapter hardware.
435 * InitialiseAdapter(unit)
437 * VOID InitialiseAdapter(struct DevUnit *);
445 ****************************************************************************
449 static VOID
InitialiseAdapter(struct DevUnit
*unit
, struct DevBase
*base
)
456 unit
->LELongOut(unit
->card
, PROREG_PORT
, 0);
457 BusyMicroDelay(10, base
);
459 /* Get default MAC address */
461 unit
->eeprom_addr_size
= GetEEPROMAddressSize(unit
, base
);
462 p
= unit
->default_address
;
464 for(i
= 0; i
< ETH_ADDRESSSIZE
/ sizeof(UWORD
); i
++)
466 address_part
= ReadEEPROM(unit
, PROROM_ADDRESS0
+ i
, base
);
467 *p
++ = address_part
& 0xff;
468 *p
++ = address_part
>> 8;
471 /* Set up statistics dump area */
473 unit
->LELongOut(unit
->card
, PROREG_GENPTR
, (ULONG
)(IPTR
)unit
->stats_buffer
);
474 unit
->LEWordOut(unit
->card
, PROREG_COMMAND
, PRO_CUCMD_SETSTATSBUFFER
);
475 while(unit
->LEWordIn(unit
->card
, PROREG_COMMAND
) != 0);
484 /****i* intelpro100.device/ConfigureAdapter ********************************
487 * ConfigureAdapter -- Put adapter online for the first time.
490 * ConfigureAdapter(unit)
492 * VOID ConfigureAdapter(struct DevUnit *);
500 ****************************************************************************
504 VOID
ConfigureAdapter(struct DevUnit
*unit
, struct DevBase
*base
)
506 ULONG
*tcb
, dma_size
;
507 UWORD phy_type
, phy_no
, config
;
509 /* Set MAC address */
511 tcb
= (ULONG
*)(IPTR
)LELong(unit
->last_tcb
[PROCB_NEXT
]);
512 tcb
[PROCB_CONTROL
] = MakeLELong(PROACT_SETADDRESS
);
513 CopyMem(&unit
->address
, tcb
+ PROCB_ADDRESS
, ETH_ADDRESSSIZE
);
515 /* Set other parameters */
517 tcb
= (ULONG
*)(IPTR
)LELong(tcb
[PROCB_NEXT
]);
519 MakeLELong(PROACT_CONFIGURE
| PROCB_CONTROLF_SUSPEND
);
520 unit
->phy_info
= ReadEEPROM(unit
, PROROM_PHYINFO0
, base
);
521 FillConfigData(unit
, tcb
, base
);
522 unit
->last_tcb
= tcb
;
524 dma_size
= TCB_SIZE
* TX_SLOT_COUNT
;
525 CachePreDMA(unit
->tcbs
, &dma_size
, 0);
527 /* DP83840-specific configuration */
529 phy_type
= unit
->phy_info
& PROROM_PHYINFO0F_TYPE
;
530 if(phy_type
== PRO_PHY_DP83840
|| phy_type
== PRO_PHY_DP83840A
)
532 phy_no
= unit
->phy_info
& PROROM_PHYINFO0F_ADDR
;
533 config
= ReadMII(unit
, phy_no
, MII_PCR
, base
);
534 config
|= 0x400 | MII_PCRF_NOLINKMON
| MII_PCRF_LED4DUPLEX
;
535 WriteMII(unit
, phy_no
, MII_PCR
, config
, base
);
540 unit
->LELongOut(unit
->card
, PROREG_GENPTR
, (ULONG
)(IPTR
)unit
->tcbs
);
541 unit
->LEWordOut(unit
->card
, PROREG_COMMAND
, PRO_CUCMD_START
);
542 while(unit
->LEWordIn(unit
->card
, PROREG_COMMAND
) != 0);
543 GoOnline(unit
, base
);
552 /****i* intelpro100.device/FillConfigData **********************************
555 * FillConfigData -- Fill in the data for a configuration command.
558 * FillConfigData(unit, tcb)
560 * VOID FillConfigData(struct DevUnit *, ULONG *);
563 * unit - A unit of this device.
564 * tcb - The configuration command block.
569 ****************************************************************************
573 static VOID
FillConfigData(struct DevUnit
*unit
, ULONG
*tcb
,
574 struct DevBase
*base
)
580 /* Copy constant parameters from template */
582 for(p
= config_data
, q
= tcb
+ PROCB_CF0
, i
= 0; i
< CONFIG_DATA_LEN
;
584 *q
++ = MakeLELong(*p
++);
585 unit
->last_tcb
= tcb
;
587 /* Decide on promiscuous mode */
589 if((unit
->flags
& UNITF_PROM
) != 0)
590 tcb
[PROCB_CF3
] |= MakeLELong(PROCB_CF3F_PROM
);
594 if((unit
->phy_info
& PROROM_PHYINFO0F_AUI
) != 0)
595 tcb
[PROCB_CF3
] |= MakeLELong(PROCB_CF3F_CDT
);
597 tcb
[PROCB_CF2
] |= MakeLELong(PROCB_CF2F_MIIMODE
);
599 /* Accept all multicasts? */
601 if((unit
->flags
& UNITF_ALLMCAST
) != 0)
603 tcb
[PROCB_CF5
] |= MakeLELong(PROCB_CF5F_ALLMCAST
);
613 /****i* intelpro100.device/GoOnline ****************************************
616 * GoOnline -- Put the adapter online.
621 * VOID GoOnline(struct DevUnit *);
624 * unit - A unit of this device.
629 ****************************************************************************
633 VOID
GoOnline(struct DevUnit
*unit
, struct DevBase
*base
)
635 /* Enable the transceiver */
637 unit
->flags
|= UNITF_ONLINE
;
639 unit
->LELongOut(unit
->card
, PROREG_GENPTR
,
640 LELong(unit
->last_rcb
[PROCB_NEXT
]));
641 unit
->LEWordOut(unit
->card
, PROREG_COMMAND
, PRO_RUCMD_START
);
642 while(unit
->LEWordIn(unit
->card
, PROREG_COMMAND
) != 0);
644 /* Record start time and report Online event */
646 GetSysTime(&unit
->stats
.LastStart
);
647 ReportEvents(unit
, S2EVENT_ONLINE
, base
);
654 /****i* intelpro100.device/GoOffline ***************************************
657 * GoOffline -- Put the adpater offline.
662 * VOID GoOffline(struct DevUnit *);
665 * unit - A unit of this device.
670 ****************************************************************************
674 VOID
GoOffline(struct DevUnit
*unit
, struct DevBase
*base
)
676 unit
->flags
&= ~UNITF_ONLINE
;
678 if((unit
->flags
& UNITF_HAVEADAPTER
) != 0)
682 unit
->LEWordOut(unit
->card
, PROREG_COMMAND
, PRO_RUCMD_ABORT
);
684 /* Update statistics */
686 UpdateStats(unit
, base
);
689 /* Flush pending read and write requests */
691 FlushUnit(unit
, WRITE_QUEUE
, S2ERR_OUTOFSERVICE
, base
);
693 /* Report Offline event and return */
695 ReportEvents(unit
, S2EVENT_OFFLINE
, base
);
701 /****i* intelpro100.device/AddMulticastRange *******************************
707 * success = AddMulticastRange(unit, lower_bound, upper_bound)
709 * BOOL AddMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
711 ****************************************************************************
715 BOOL
AddMulticastRange(struct DevUnit
*unit
, const UBYTE
*lower_bound
,
716 const UBYTE
*upper_bound
, struct DevBase
*base
)
718 struct AddressRange
*range
;
719 ULONG lower_bound_left
, upper_bound_left
;
720 UWORD lower_bound_right
, upper_bound_right
;
722 lower_bound_left
= BELong(*((ULONG
*)lower_bound
));
723 lower_bound_right
= BEWord(*((UWORD
*)(lower_bound
+ 4)));
724 upper_bound_left
= BELong(*((ULONG
*)upper_bound
));
725 upper_bound_right
= BEWord(*((UWORD
*)(upper_bound
+ 4)));
727 range
= FindMulticastRange(unit
, lower_bound_left
, lower_bound_right
,
728 upper_bound_left
, upper_bound_right
, base
);
734 range
= AllocMem(sizeof(struct AddressRange
), MEMF_PUBLIC
);
737 range
->lower_bound_left
= lower_bound_left
;
738 range
->lower_bound_right
= lower_bound_right
;
739 range
->upper_bound_left
= upper_bound_left
;
740 range
->upper_bound_right
= upper_bound_right
;
741 range
->add_count
= 1;
744 AddTail((APTR
)&unit
->multicast_ranges
, (APTR
)range
);
749 return range
!= NULL
;
754 /****i* intelpro100.device/RemMulticastRange *******************************
760 * found = RemMulticastRange(unit, lower_bound, upper_bound)
762 * BOOL RemMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
764 ****************************************************************************
768 BOOL
RemMulticastRange(struct DevUnit
*unit
, const UBYTE
*lower_bound
,
769 const UBYTE
*upper_bound
, struct DevBase
*base
)
771 struct AddressRange
*range
;
772 ULONG lower_bound_left
, upper_bound_left
;
773 UWORD lower_bound_right
, upper_bound_right
;
775 lower_bound_left
= BELong(*((ULONG
*)lower_bound
));
776 lower_bound_right
= BEWord(*((UWORD
*)(lower_bound
+ 4)));
777 upper_bound_left
= BELong(*((ULONG
*)upper_bound
));
778 upper_bound_right
= BEWord(*((UWORD
*)(upper_bound
+ 4)));
780 range
= FindMulticastRange(unit
, lower_bound_left
, lower_bound_right
,
781 upper_bound_left
, upper_bound_right
, base
);
785 if(--range
->add_count
== 0)
790 FreeMem(range
, sizeof(struct AddressRange
));
794 return range
!= NULL
;
799 /****i* intelpro100.device/FindMulticastRange ******************************
805 * range = FindMulticastRange(unit, lower_bound_left,
806 * lower_bound_right, upper_bound_left, upper_bound_right)
808 * struct AddressRange *FindMulticastRange(struct DevUnit *, ULONG,
809 * UWORD, ULONG, UWORD);
811 ****************************************************************************
815 static struct AddressRange
*FindMulticastRange(struct DevUnit
*unit
,
816 ULONG lower_bound_left
, UWORD lower_bound_right
, ULONG upper_bound_left
,
817 UWORD upper_bound_right
, struct DevBase
*base
)
819 struct AddressRange
*range
, *tail
;
822 range
= (APTR
)unit
->multicast_ranges
.mlh_Head
;
823 tail
= (APTR
)&unit
->multicast_ranges
.mlh_Tail
;
825 while((range
!= tail
) && !found
)
827 if((lower_bound_left
== range
->lower_bound_left
) &&
828 (lower_bound_right
== range
->lower_bound_right
) &&
829 (upper_bound_left
== range
->upper_bound_left
) &&
830 (upper_bound_right
== range
->upper_bound_right
))
833 range
= (APTR
)range
->node
.mln_Succ
;
844 /****i* intelpro100.device/SetMulticast ************************************
852 * VOID SetMulticast(struct DevUnit *);
855 * Fills in the unit's multicast list TCB, but does not send it to the
858 ****************************************************************************
862 static VOID
SetMulticast(struct DevUnit
*unit
, struct DevBase
*base
)
864 ULONG
*tcb
, address_left
;
865 UWORD address_right
, i
= 0, *p
;
866 struct AddressRange
*range
, *tail
;
869 tcb
= unit
->multicast_cb
;
871 if((unit
->flags
& UNITF_PROM
) == 0)
873 /* Fill in multicast list */
875 range
= (APTR
)unit
->multicast_ranges
.mlh_Head
;
876 tail
= (APTR
)&unit
->multicast_ranges
.mlh_Tail
;
877 p
= (UWORD
*)(tcb
+ PROCB_COUNT
);
879 while(range
!= tail
&& i
< MAX_MCAST_ENTRIES
)
881 address_left
= range
->lower_bound_left
;
882 address_right
= range
->lower_bound_right
;
885 while(!range_ended
&& i
++ < MAX_MCAST_ENTRIES
)
887 *p
++ = MakeBEWord((UWORD
)(address_left
>> 16));
888 *p
++ = MakeBEWord((UWORD
)(address_left
));
889 *p
++ = MakeBEWord((UWORD
)(address_right
));
891 if(address_left
== range
->upper_bound_left
&&
892 address_right
== range
->upper_bound_right
)
896 if(++address_right
== 0)
901 range
= (APTR
)range
->node
.mln_Succ
;
903 p
= (UWORD
*)(tcb
+ PROCB_COUNT
);
904 *p
= MakeLEWord(ETH_ADDRESSSIZE
* i
);
906 /* Accept all multicasts if there are too many addresses */
909 unit
->flags
|= UNITF_ALLMCAST
;
911 unit
->flags
&= ~UNITF_ALLMCAST
;
919 /****i* intelpro100.device/FindTypeStats ***********************************
925 * stats = FindTypeStats(unit, list,
928 * struct TypeStats *FindTypeStats(struct DevUnit *, struct MinList *,
931 ****************************************************************************
935 struct TypeStats
*FindTypeStats(struct DevUnit
*unit
, struct MinList
*list
,
936 ULONG packet_type
, struct DevBase
*base
)
938 struct TypeStats
*stats
, *tail
;
941 stats
= (APTR
)list
->mlh_Head
;
942 tail
= (APTR
)&list
->mlh_Tail
;
944 while((stats
!= tail
) && !found
)
946 if(stats
->packet_type
== packet_type
)
949 stats
= (APTR
)stats
->node
.mln_Succ
;
960 /****i* intelpro100.device/FlushUnit ***************************************
966 * FlushUnit(unit, last_queue, error)
968 * VOID FlushUnit(struct DevUnit *, UBYTE, BYTE);
970 ****************************************************************************
974 VOID
FlushUnit(struct DevUnit
*unit
, UBYTE last_queue
, BYTE error
,
975 struct DevBase
*base
)
977 struct IORequest
*request
;
979 struct Opener
*opener
, *tail
;
981 /* Abort queued requests */
983 for(i
= 0; i
<= last_queue
; i
++)
985 while((request
= (APTR
)GetMsg(unit
->request_ports
[i
])) != NULL
)
987 request
->io_Error
= IOERR_ABORTED
;
988 ReplyMsg((APTR
)request
);
993 opener
= (APTR
)unit
->openers
.mlh_Head
;
994 tail
= (APTR
)&unit
->openers
.mlh_Tail
;
996 /* Flush every opener's read queue */
998 while(opener
!= tail
)
1000 while((request
= (APTR
)GetMsg(&opener
->read_port
)) != NULL
)
1002 request
->io_Error
= error
;
1003 ReplyMsg((APTR
)request
);
1005 opener
= (APTR
)opener
->node
.mln_Succ
;
1009 opener
= request
->ios2_BufferManagement
;
1010 while((request
= (APTR
)GetMsg(&opener
->read_port
)) != NULL
)
1012 request
->io_Error
= IOERR_ABORTED
;
1013 ReplyMsg((APTR
)request
);
1024 /****i* intelpro100.device/StatusInt ***************************************
1030 * finished = StatusInt(unit)
1032 * BOOL StatusInt(struct DevUnit *);
1035 * unit - A unit of this device.
1038 * finished - Always FALSE.
1040 ****************************************************************************
1044 static BOOL
StatusInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
))
1046 struct DevBase
*base
;
1049 base
= unit
->device
;
1050 ints
= unit
->ByteIn(unit
->card
, PROREG_INTSTATUS
);
1054 /* Handle interrupts */
1056 if((ints
& PROINTF_GENERAL
) != 0)
1057 Cause(&unit
->tx_end_int
);
1058 if((ints
& PROINTF_RXDONE
) != 0)
1059 Cause(&unit
->rx_int
);
1061 /* Acknowledge interrupts */
1063 unit
->ByteOut(unit
->card
, PROREG_INTSTATUS
, ints
);
1071 /****i* intelpro100.device/RXInt *******************************************
1079 * VOID RXInt(struct DevUnit *);
1082 * unit - A unit of this device.
1083 * int_code - Unused.
1088 ****************************************************************************
1092 static VOID
RXInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
))
1095 struct DevBase
*base
;
1096 BOOL is_orphan
, accepted
;
1097 ULONG rx_status_le
, rx_info
, packet_type
, *rcb
, *last_rcb
, dma_size
;
1099 struct IOSana2Req
*request
, *request_tail
;
1100 struct Opener
*opener
, *opener_tail
;
1101 struct TypeStats
*tracker
;
1103 base
= unit
->device
;
1104 last_rcb
= unit
->last_rcb
;
1105 rcb
= (ULONG
*)(IPTR
)LELong(last_rcb
[PROCB_NEXT
]);
1107 dma_size
= RCB_SIZE
;
1108 CachePostDMA(rcb
, &dma_size
, 0);
1109 while(((rx_status_le
= rcb
[PROCB_CONTROL
])
1110 & MakeLELong(PROCB_CONTROLF_DONE
)) != 0)
1112 if((rx_status_le
& MakeLELong(PROCB_CONTROLF_OK
)) != 0)
1115 rx_info
= LELong(rcb
[PROCB_RXINFO
]);
1116 packet_size
= rx_info
& PROCB_RXINFOF_FRAMESIZE
;
1117 buffer
= (UBYTE
*)(rcb
+ PROCB_BUFFER
);
1119 if(AddressFilter(unit
, buffer
+ ETH_PACKET_DEST
, base
))
1121 packet_type
= BEWord(*((UWORD
*)(buffer
+ ETH_PACKET_TYPE
)));
1123 opener
= (APTR
)unit
->openers
.mlh_Head
;
1124 opener_tail
= (APTR
)&unit
->openers
.mlh_Tail
;
1126 /* Offer packet to every opener */
1128 while(opener
!= opener_tail
)
1130 request
= (APTR
)opener
->read_port
.mp_MsgList
.lh_Head
;
1131 request_tail
= (APTR
)&opener
->read_port
.mp_MsgList
.lh_Tail
;
1134 /* Offer packet to each request until it's accepted */
1136 while((request
!= request_tail
) && !accepted
)
1138 if(request
->ios2_PacketType
== packet_type
)
1140 CopyPacket(unit
, request
, packet_size
, packet_type
,
1145 (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
1150 opener
= (APTR
)opener
->node
.mln_Succ
;
1153 /* If packet was unwanted, give it to S2_READORPHAN request */
1157 unit
->stats
.UnknownTypesReceived
++;
1158 if(!IsMsgPortEmpty(unit
->request_ports
[ADOPT_QUEUE
]))
1161 (APTR
)unit
->request_ports
[ADOPT_QUEUE
]->
1162 mp_MsgList
.lh_Head
, packet_size
, packet_type
, buffer
,
1167 /* Update remaining statistics */
1170 FindTypeStats(unit
, &unit
->type_trackers
, packet_type
, base
);
1173 tracker
->stats
.PacketsReceived
++;
1174 tracker
->stats
.BytesReceived
+= packet_size
;
1180 unit
->stats
.BadData
++;
1181 ReportEvents(unit
, S2EVENT_ERROR
| S2EVENT_HARDWARE
| S2EVENT_RX
,
1185 rcb
[PROCB_CONTROL
] = MakeLELong(PROCB_CONTROLF_SUSPEND
);
1187 MakeLELong(ETH_MAXPACKETSIZE
<< PROCB_RXINFOB_BUFFERSIZE
);
1189 /* Clear suspend flag from previous CB without touching bits that
1190 adapter may be writing to; and resume execution */
1192 *(((UBYTE
*)last_rcb
+ PROCB_CONTROL
) + 3) = 0;
1193 dma_size
= RCB_SIZE
;
1194 CachePreDMA(last_rcb
, &dma_size
, 0);
1196 unit
->LEWordOut(unit
->card
, PROREG_COMMAND
, PRO_RUCMD_RESUME
);
1199 rcb
= (ULONG
*)(IPTR
)LELong(rcb
[PROCB_NEXT
]);
1204 unit
->last_rcb
= last_rcb
;
1210 /****i* intelpro100.device/CopyPacket **************************************
1216 * CopyPacket(unit, request, packet_size, packet_type,
1219 * VOID CopyPacket(struct DevUnit *, struct IOSana2Req *, UWORD, UWORD,
1222 ****************************************************************************
1226 static VOID
CopyPacket(struct DevUnit
*unit
, struct IOSana2Req
*request
,
1227 UWORD packet_size
, UWORD packet_type
, UBYTE
*buffer
,
1228 struct DevBase
*base
)
1230 struct Opener
*opener
;
1231 BOOL filtered
= FALSE
;
1233 /* Set multicast and broadcast flags */
1235 request
->ios2_Req
.io_Flags
&= ~(SANA2IOF_BCAST
| SANA2IOF_MCAST
);
1236 if((*((ULONG
*)(buffer
+ ETH_PACKET_DEST
)) == 0xffffffff) &&
1237 (*((UWORD
*)(buffer
+ ETH_PACKET_DEST
+ 4)) == 0xffff))
1238 request
->ios2_Req
.io_Flags
|= SANA2IOF_BCAST
;
1239 else if((buffer
[ETH_PACKET_DEST
] & 0x1) != 0)
1240 request
->ios2_Req
.io_Flags
|= SANA2IOF_MCAST
;
1242 /* Set source and destination addresses and packet type */
1244 CopyMem(buffer
+ ETH_PACKET_SOURCE
, request
->ios2_SrcAddr
,
1246 CopyMem(buffer
+ ETH_PACKET_DEST
, request
->ios2_DstAddr
,
1248 request
->ios2_PacketType
= packet_type
;
1250 /* Adjust for cooked packet request */
1252 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
1254 packet_size
-= ETH_PACKET_DATA
;
1255 buffer
+= ETH_PACKET_DATA
;
1259 packet_size
+= 4; /* Needed for Shapeshifter & Fusion */
1261 request
->ios2_DataLength
= packet_size
;
1265 opener
= request
->ios2_BufferManagement
;
1266 if((request
->ios2_Req
.io_Command
== CMD_READ
) &&
1267 (opener
->filter_hook
!= NULL
))
1268 if(!CallHookPkt(opener
->filter_hook
, request
, buffer
))
1273 /* Copy packet into opener's buffer and reply packet */
1275 if(!opener
->rx_function(request
->ios2_Data
, buffer
, packet_size
))
1277 request
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
1278 request
->ios2_WireError
= S2WERR_BUFF_ERROR
;
1280 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
| S2EVENT_RX
,
1283 Remove((APTR
)request
);
1284 ReplyMsg((APTR
)request
);
1292 /****i* intelpro100.device/AddressFilter ***********************************
1298 * accept = AddressFilter(unit, address)
1300 * BOOL AddressFilter(struct DevUnit *, UBYTE *);
1302 ****************************************************************************
1306 static BOOL
AddressFilter(struct DevUnit
*unit
, UBYTE
*address
,
1307 struct DevBase
*base
)
1309 struct AddressRange
*range
, *tail
;
1312 UWORD address_right
;
1314 /* Check whether address is unicast/broadcast or multicast */
1316 address_left
= BELong(*((ULONG
*)address
));
1317 address_right
= BEWord(*((UWORD
*)(address
+ 4)));
1319 if((address_left
& 0x01000000) != 0 &&
1320 !(address_left
== 0xffffffff && address_right
== 0xffff))
1322 /* Check if this multicast address is wanted */
1324 range
= (APTR
)unit
->multicast_ranges
.mlh_Head
;
1325 tail
= (APTR
)&unit
->multicast_ranges
.mlh_Tail
;
1328 while((range
!= tail
) && !accept
)
1330 if(((address_left
> range
->lower_bound_left
) ||
1331 (address_left
== range
->lower_bound_left
) &&
1332 (address_right
>= range
->lower_bound_right
)) &&
1333 ((address_left
< range
->upper_bound_left
) ||
1334 (address_left
== range
->upper_bound_left
) &&
1335 (address_right
<= range
->upper_bound_right
)))
1337 range
= (APTR
)range
->node
.mln_Succ
;
1341 unit
->special_stats
[S2SS_ETHERNET_BADMULTICAST
& 0xffff]++;
1349 /****i* intelpro100.device/TXInt *******************************************
1357 * VOID TXInt(struct DevUnit *);
1360 * unit - A unit of this device.
1361 * int_code - Unused.
1366 ****************************************************************************
1368 * Note that when the CU is resumed, the adapter examines the suspend flag
1369 * again in the command that caused the suspension. If the flag is set, the
1370 * CU will be suspended without executing any new commands. This means that
1371 * all TCBs can't be in use at the same time, and the dynamically inserted
1372 * multicast list command can't have its suspend flag set.
1376 static VOID
TXInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
))
1378 struct DevBase
*base
;
1379 UWORD packet_size
, data_size
, *p
, *q
, i
;
1380 struct IOSana2Req
*request
;
1381 BOOL proceed
= TRUE
;
1382 struct Opener
*opener
;
1383 ULONG wire_error
, *tcb
, *last_tcb
, *mcast_cb
, *fragment
, dma_size
,
1385 UBYTE
*(*dma_tx_function
)(REG(a0
, APTR
));
1388 struct MsgPort
*port
;
1390 base
= unit
->device
;
1391 port
= unit
->request_ports
[WRITE_QUEUE
];
1393 while(proceed
&& !IsMsgPortEmpty(port
))
1395 last_tcb
= unit
->last_tcb
;
1396 tcb
= (ULONG
*)(IPTR
)LELong(last_tcb
[PROCB_NEXT
]);
1398 /* Ensure there are at least two free CBs available (two are needed
1399 for setting the multicast filter) and that neither the TX nor the
1400 multicast buffer is currently in use */
1402 if((ULONG
*)(IPTR
)LELong(((ULONG
*)(IPTR
)LELong(tcb
[PROCB_NEXT
]))[PROCB_NEXT
])
1404 && (unit
->flags
& (UNITF_TXBUFFERINUSE
| UNITF_MCASTBUFFERINUSE
))
1408 request
= (APTR
)GetMsg(port
);
1409 request
->ios2_Req
.io_Message
.mn_Node
.ln_Type
= NT_FREEMSG
;
1411 switch(request
->ios2_Req
.io_Command
)
1419 action
= PROACT_CONFIGURE
;
1422 if(action
== PROACT_TX
)
1424 /* Handle TX request */
1426 data_size
= packet_size
= request
->ios2_DataLength
;
1428 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
1429 packet_size
+= ETH_HEADERSIZE
;
1431 /* Write packet preamble */
1433 tcb
[PROCB_CONTROL
] =
1434 MakeLELong(PROACT_TX
| PROCB_CONTROLF_SUSPEND
1435 | PROCB_CONTROLF_INT
| PROCB_CONTROLF_FLEXIBLE
);
1436 fragment
= tcb
+ PROCB_EXTFRAGS
;
1437 tcb
[PROCB_FRAGMENTS
] = MakeLELong((ULONG
)(IPTR
)fragment
);
1439 /* Write packet header */
1441 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
1443 buffer
= (UBYTE
*)(tcb
+ PROCB_EXTBUFFER
);
1445 MakeLELong(2 << PROCB_TXINFOB_FRAGCOUNT
1446 | 1 << PROCB_TXINFOB_THRESHOLD
1447 | PROCB_TXINFOF_EOF
);
1448 fragment
[PROFRAG_ADDR
] = MakeLELong((ULONG
)(IPTR
)buffer
);
1449 fragment
[PROFRAG_LEN
] = MakeLELong(ETH_HEADERSIZE
);
1451 p
= (UWORD
*)buffer
;
1452 for(i
= 0, q
= (UWORD
*)request
->ios2_DstAddr
;
1453 i
< ETH_ADDRESSSIZE
/ 2; i
++)
1455 for(i
= 0, q
= (UWORD
*)unit
->address
;
1456 i
< ETH_ADDRESSSIZE
/ 2; i
++)
1458 *p
++ = MakeBEWord(request
->ios2_PacketType
);
1459 buffer
= (UBYTE
*)p
;
1461 fragment
+= PRO_FRAGLEN
;
1466 MakeLELong(1 << PROCB_TXINFOB_FRAGCOUNT
1467 | 1 << PROCB_TXINFOB_THRESHOLD
1468 | PROCB_TXINFOF_EOF
);
1471 /* Get packet data */
1473 opener
= (APTR
)request
->ios2_BufferManagement
;
1474 dma_tx_function
= opener
->dma_tx_function
;
1475 if(dma_tx_function
!= NULL
)
1476 buffer
= dma_tx_function(request
->ios2_Data
);
1482 buffer
= unit
->tx_buffer
;
1483 if(opener
->tx_function(buffer
, request
->ios2_Data
,
1486 unit
->flags
|= UNITF_TXBUFFERINUSE
;
1490 error
= S2ERR_NO_RESOURCES
;
1491 wire_error
= S2WERR_BUFF_ERROR
;
1493 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
1494 | S2EVENT_TX
, base
);
1498 /* Put pointer to packet data into descriptor */
1502 dma_size
= data_size
;
1503 CachePreDMA(buffer
, &dma_size
, DMA_ReadFromRAM
);
1504 fragment
[PROFRAG_ADDR
] = MakeLELong((ULONG
)(IPTR
)buffer
);
1505 fragment
[PROFRAG_LEN
] = MakeLELong(data_size
);
1510 /* Update multicast reception filter */
1512 SetMulticast(unit
, base
);
1513 if((unit
->flags
& UNITF_ALLMCAST
) == 0)
1515 tcb
[PROCB_CONTROL
] = MakeLELong(PROACT_NOP
);
1516 mcast_cb
= unit
->multicast_cb
;
1517 mcast_cb
[PROCB_CONTROL
] = MakeLELong(PROACT_SETMCAST
);
1518 mcast_cb
[PROCB_NEXT
] = tcb
[PROCB_NEXT
];
1519 tcb
[PROCB_NEXT
] = MakeLELong((ULONG
)(IPTR
)mcast_cb
);
1520 unit
->link_cb
= tcb
;
1521 tcb
= (ULONG
*)(IPTR
)LELong(mcast_cb
[PROCB_NEXT
]);
1522 tcb
[PROCB_CONTROL
] = MakeLELong(PROACT_CONFIGURE
1523 | PROCB_CONTROLF_SUSPEND
| PROCB_CONTROLF_INT
);
1524 FillConfigData(unit
, tcb
, base
);
1525 unit
->flags
|= UNITF_MCASTBUFFERINUSE
;
1529 tcb
[PROCB_CONTROL
] = MakeLELong(PROACT_CONFIGURE
1530 | PROCB_CONTROLF_SUSPEND
| PROCB_CONTROLF_INT
);
1531 FillConfigData(unit
, tcb
, base
);
1537 /* Clear suspend flag from previous CB without touching bits
1538 that adapter may be writing to; and resume execution */
1540 if(last_tcb
[PROCB_CONTROL
] != 0)
1541 *(((UBYTE
*)last_tcb
+ PROCB_CONTROL
) + 3) =
1542 PROCB_CONTROLF_INT
>> 24;
1543 dma_size
= TCB_SIZE
* TX_SLOT_COUNT
;
1544 CachePreDMA(unit
->tcbs
, &dma_size
, 0);
1545 dma_size
= MCAST_CB_SIZE
;
1546 CachePreDMA(unit
->multicast_cb
, &dma_size
, 0);
1547 if((unit
->ByteIn(unit
->card
, PROREG_STATUS
)
1548 & PROREG_STATUSF_CUSTATE
)
1549 == (PRO_CUSTATE_SUSPENDED
<< PROREG_STATUSB_CUSTATE
))
1551 unit
->LEWordOut(unit
->card
, PROREG_COMMAND
,
1555 AddTail((APTR
)&unit
->tx_requests
, (APTR
)request
);
1556 unit
->last_tcb
= tcb
;
1560 /* Return failed request */
1562 request
->ios2_Req
.io_Error
= error
;
1563 request
->ios2_WireError
= wire_error
;
1564 ReplyMsg((APTR
)request
);
1565 tcb
[PROCB_CONTROL
] = 0;
1573 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
1575 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_IGNORE
;
1582 /****i* intelpro100.device/TXEndInt ****************************************
1590 * VOID TXEndInt(struct DevUnit *);
1593 * unit - A unit of this device.
1594 * int_code - Unused.
1599 ****************************************************************************
1601 * It appears to be safe to assume that there will always be at least one
1602 * completed packet whenever this interrupt is called.
1606 static VOID
TXEndInt(REG(a1
, struct DevUnit
*unit
), REG(a5
, APTR int_code
))
1608 UWORD data_size
, packet_size
;
1610 struct DevBase
*base
;
1611 struct IOSana2Req
*request
;
1612 ULONG
*tcb
, *fragment
, dma_size
, action
;
1613 struct TypeStats
*tracker
;
1615 /* Retire sent packets and configuration commands */
1617 base
= unit
->device
;
1618 dma_size
= TCB_SIZE
* TX_SLOT_COUNT
;
1619 CachePostDMA(unit
->tcbs
, &dma_size
, 0);
1620 dma_size
= MCAST_CB_SIZE
;
1621 CachePostDMA(unit
->multicast_cb
, &dma_size
, 0);
1623 for(tcb
= unit
->first_tcb
;
1624 (tcb
[PROCB_CONTROL
] & MakeLELong(PROCB_CONTROLF_DONE
)) != 0;
1625 tcb
= (ULONG
*)(IPTR
)LELong(tcb
[PROCB_NEXT
]))
1627 action
= LELong(tcb
[PROCB_CONTROL
]) & PROCB_CONTROLF_ACTION
;
1629 if(action
== PROACT_TX
|| action
== PROACT_CONFIGURE
1630 && (unit
->link_cb
!= NULL
1631 || (tcb
[PROCB_CF5
] & PROCB_CF5F_ALLMCAST
) != 0))
1633 request
= (APTR
)RemHead((APTR
)&unit
->tx_requests
);
1635 if(action
== PROACT_TX
)
1637 /* Mark end of DMA */
1639 data_size
= packet_size
= request
->ios2_DataLength
;
1640 fragment
= (ULONG
*)(IPTR
)LELong(tcb
[PROCB_FRAGMENTS
]);
1642 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
1644 packet_size
+= ETH_HEADERSIZE
;
1645 fragment
+= PRO_FRAGLEN
;
1648 buffer
= (UBYTE
*)(IPTR
)LELong(fragment
[PROFRAG_ADDR
]);
1649 dma_size
= data_size
;
1650 CachePostDMA(buffer
, &dma_size
, DMA_ReadFromRAM
);
1652 /* Check if unit's buffer is now free */
1654 if(buffer
== unit
->tx_buffer
)
1655 unit
->flags
&= ~UNITF_TXBUFFERINUSE
;
1657 /* Update statistics */
1659 tracker
= FindTypeStats(unit
, &unit
->type_trackers
,
1660 request
->ios2_PacketType
, base
);
1663 tracker
->stats
.PacketsSent
++;
1664 tracker
->stats
.BytesSent
+= packet_size
;
1667 else if(action
== PROACT_CONFIGURE
)
1669 /* Mark end of multicast update */
1671 if(unit
->link_cb
!= NULL
)
1673 unit
->link_cb
[PROCB_NEXT
] = MakeLELong((ULONG
)(IPTR
)tcb
);
1674 unit
->flags
&= ~UNITF_MCASTBUFFERINUSE
;
1675 unit
->link_cb
= NULL
;
1681 request
->ios2_Req
.io_Error
= 0;
1682 ReplyMsg((APTR
)request
);
1685 /* Mark CB as unused/clear suspend flag */
1687 tcb
[PROCB_CONTROL
] = 0;
1690 dma_size
= TCB_SIZE
* TX_SLOT_COUNT
;
1691 CachePreDMA(unit
->tcbs
, &dma_size
, 0);
1693 unit
->first_tcb
= tcb
;
1695 /* Restart downloads if they had stopped */
1697 if(unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
== PA_IGNORE
)
1698 Cause(&unit
->tx_int
);
1705 /****i* intelpro100.device/UpdateStats *************************************
1713 * VOID UpdateStats(struct DevUnit *);
1716 * unit - A unit of this device.
1721 ****************************************************************************
1725 VOID
UpdateStats(struct DevUnit
*unit
, struct DevBase
*base
)
1727 ULONG dma_size
, *buffer
;
1729 buffer
= unit
->stats_buffer
;
1730 buffer
[STAT_COUNT
] = 0;
1731 dma_size
= sizeof(ULONG
) * STAT_COUNT
;
1732 CachePreDMA(unit
->stats_buffer
, &dma_size
, 0);
1733 unit
->ByteOut(unit
->card
, PROREG_COMMAND
, PRO_CUCMD_DUMPRESETSTATS
);
1734 while(buffer
[STAT_COUNT
] != MakeLELong(0xa007))
1736 dma_size
= sizeof(ULONG
) * STAT_COUNT
;
1737 CachePostDMA(unit
->stats_buffer
, &dma_size
, 0);
1740 unit
->stats
.Overruns
+= LELong(buffer
[PROSTAT_RXOVERRUNS
]);
1741 unit
->stats
.PacketsSent
+= LELong(buffer
[PROSTAT_TXFRAMESOK
]);
1742 unit
->stats
.PacketsReceived
+= LELong(buffer
[PROSTAT_RXFRAMESOK
]);
1743 unit
->special_stats
[S2SS_ETHERNET_RETRIES
& 0xffff] +=
1744 LELong(buffer
[PROSTAT_FRAMESDEFERRED
]);
1745 unit
->special_stats
[S2SS_ETHERNET_FIFO_UNDERRUNS
& 0xffff] +=
1746 LELong(buffer
[PROSTAT_TXUNDERRUNS
]);
1753 /****i* intelpro100.device/ReportEvents ************************************
1759 * ReportEvents(unit, events)
1761 * VOID ReportEvents(struct DevUnit *, ULONG);
1764 * unit - A unit of this device.
1765 * events - A mask of events to report.
1770 ****************************************************************************
1774 static VOID
ReportEvents(struct DevUnit
*unit
, ULONG events
,
1775 struct DevBase
*base
)
1777 struct IOSana2Req
*request
, *tail
, *next_request
;
1780 list
= &unit
->request_ports
[EVENT_QUEUE
]->mp_MsgList
;
1781 next_request
= (APTR
)list
->lh_Head
;
1782 tail
= (APTR
)&list
->lh_Tail
;
1785 while(next_request
!= tail
)
1787 request
= next_request
;
1788 next_request
= (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
1790 if((request
->ios2_WireError
& events
) != 0)
1792 request
->ios2_WireError
= events
;
1793 Remove((APTR
)request
);
1794 ReplyMsg((APTR
)request
);
1804 /****i* intelpro100.device/UnitTask ****************************************
1815 * Completes deferred requests.
1817 ****************************************************************************
1825 static VOID
UnitTask(struct ExecBase
*sys_base
)
1828 struct IORequest
*request
;
1829 struct DevUnit
*unit
;
1830 struct DevBase
*base
;
1831 struct MsgPort
*general_port
;
1832 ULONG signals
, wait_signals
, general_port_signal
;
1834 /* Get parameters */
1836 task
= AbsExecBase
->ThisTask
;
1837 unit
= task
->tc_UserData
;
1838 base
= unit
->device
;
1840 /* Activate general request port */
1842 general_port
= unit
->request_ports
[GENERAL_QUEUE
];
1843 general_port
->mp_SigTask
= task
;
1844 general_port
->mp_SigBit
= AllocSignal(-1);
1845 general_port_signal
= 1 << general_port
->mp_SigBit
;
1846 general_port
->mp_Flags
= PA_SIGNAL
;
1848 /* Allocate a signal for notification of card removal */
1850 wait_signals
= (1 << general_port
->mp_SigBit
);
1852 /* Tell ourselves to check port for old messages */
1854 Signal(task
, general_port_signal
);
1856 /* Infinite loop to service requests and signals */
1860 signals
= Wait(wait_signals
);
1862 if((signals
& general_port_signal
) != 0)
1864 while((request
= (APTR
)GetMsg(general_port
)) != NULL
)
1866 /* Service the request as soon as the unit is free */
1868 ObtainSemaphore(&unit
->access_lock
);
1869 ServiceRequest((APTR
)request
, base
);
1877 /****i* intelpro100.device/GetEEPROMAddressSize ****************************
1880 * GetEEPROMAddressSize
1883 * size = GetEEPROMAddressSize(unit)
1885 * UWORD GetEEPROMAddressSize(struct DevUnit *);
1888 * unit - A unit of this device.
1891 * size - Width of EEPROM addresses.
1893 ****************************************************************************
1895 * Although the manual doesn't make it explicit, chip select must be asserted
1896 * before setting any other bits, at least on the i82557.
1900 static UWORD
GetEEPROMAddressSize(struct DevUnit
*unit
,
1901 struct DevBase
*base
)
1905 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
, PROREG_EEPROMF_SELECT
);
1906 WriteEEPROMBits(unit
, 0x6, 3, base
);
1907 for(size
= 1; WriteEEPROMBit(unit
, FALSE
, base
); size
++);
1908 ReadEEPROMBits(unit
, 16, base
);
1909 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
, 0);
1910 BusyMicroDelay(1, base
);
1917 /****i* intelpro100.device/ReadEEPROM **************************************
1920 * ReadEEPROM -- Read an EEPROM location.
1923 * value = ReadEEPROM(unit, index)
1925 * UWORD ReadEEPROM(struct DevUnit *, UWORD);
1928 * unit - A unit of this device.
1929 * index - Offset within EEPROM.
1932 * value - Contents of specified EEPROM location.
1934 ****************************************************************************
1938 static UWORD
ReadEEPROM(struct DevUnit
*unit
, UWORD index
,
1939 struct DevBase
*base
)
1943 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
, PROREG_EEPROMF_SELECT
);
1944 WriteEEPROMBits(unit
, 0x6, 3, base
);
1945 WriteEEPROMBits(unit
, index
, unit
->eeprom_addr_size
, base
);
1946 value
= ReadEEPROMBits(unit
, 16, base
);
1947 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
, 0);
1948 BusyMicroDelay(1, base
);
1955 /****i* intelpro100.device/ReadEEPROMBits **********************************
1958 * ReadEEPROMBits -- Read a stream of bits from the EEPROM.
1961 * value = ReadEEPROMBits(unit, count)
1963 * ULONG ReadEEPROMBits(struct DevUnit *, UBYTE);
1966 * unit - A unit of this device.
1967 * count - Number of bits to be read.
1970 * value - The bits read from the EEPROM, right-justified.
1972 ****************************************************************************
1976 static ULONG
ReadEEPROMBits(struct DevUnit
*unit
, UBYTE count
,
1977 struct DevBase
*base
)
1982 for(i
= 0; i
< count
; i
++)
1985 if(ReadEEPROMBit(unit
, base
))
1993 /****i* intelpro100.device/WriteEEPROMBits *********************************
1996 * WriteEEPROMBits -- Write a stream of bits to the EEPROM.
1999 * WriteEEPROMBits(unit, value, count)
2001 * VOID WriteEEPROMBits(struct DevUnit *, ULONG, UBYTE);
2004 * unit - A unit of this device.
2005 * value - The bits to write to the EEPROM, right-justified.
2006 * count - Number of bits to be Write.
2011 ****************************************************************************
2015 static VOID
WriteEEPROMBits(struct DevUnit
*unit
, ULONG value
, UBYTE count
,
2016 struct DevBase
*base
)
2020 for(mask
= 1 << (count
- 1); mask
!= 0; mask
>>= 1)
2021 WriteEEPROMBit(unit
, (value
& mask
) != 0, base
);
2028 /****i* intelpro100.device/ReadEEPROMBit ***********************************
2031 * ReadEEPROMBit -- Read a bit from the EEPROM.
2034 * value = ReadEEPROMBit(unit)
2036 * BOOL ReadEEPROMBit(struct DevUnit *);
2039 * unit - A unit of this device.
2042 * value - True for one, false for zero.
2044 ****************************************************************************
2048 static BOOL
ReadEEPROMBit(struct DevUnit
*unit
, struct DevBase
*base
)
2052 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
,
2053 PROREG_EEPROMF_SELECT
| PROREG_EEPROMF_CLK
);
2054 BusyMicroDelay(2, base
);
2056 (unit
->LEWordIn(unit
->card
, PROREG_EEPROM
) & PROREG_EEPROMF_DATAIN
)
2058 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
, PROREG_EEPROMF_SELECT
);
2059 BusyMicroDelay(2, base
);
2066 /****i* intelpro100.device/WriteEEPROMBit **********************************
2069 * WriteEEPROMBit -- Write a bit to the EEPROM.
2072 * data_in = WriteEEPROMBit(unit, is_one)
2074 * BOOL WriteEEPROMBit(struct DevUnit *, BOOL);
2077 * unit - A unit of this device.
2078 * is_one - True if a set bit should be written.
2081 * data_in - True if data-in bit is set.
2083 ****************************************************************************
2087 static BOOL
WriteEEPROMBit(struct DevUnit
*unit
, BOOL is_one
,
2088 struct DevBase
*base
)
2093 data_out
= PROREG_EEPROMF_DATAOUT
;
2097 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
,
2098 PROREG_EEPROMF_SELECT
| data_out
);
2099 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
,
2100 PROREG_EEPROMF_SELECT
| PROREG_EEPROMF_CLK
| data_out
);
2101 BusyMicroDelay(2, base
);
2102 unit
->LEWordOut(unit
->card
, PROREG_EEPROM
,
2103 PROREG_EEPROMF_SELECT
| data_out
);
2104 BusyMicroDelay(2, base
);
2107 (unit
->LEWordIn(unit
->card
, PROREG_EEPROM
) & PROREG_EEPROMF_DATAIN
)
2113 /****i* intelpro100.device/ReadMII *****************************************
2116 * ReadMII -- Read a register in an MII PHY.
2119 * value = ReadMII(unit, phy_no, reg_no)
2121 * UWORD ReadMII(struct DevUnit *, UWORD, UWORD);
2124 * unit - A unit of this device.
2125 * phy_no - Index of PHY to use.
2126 * reg_no - MII register to read.
2129 * value - Value read from MII register.
2131 ****************************************************************************
2135 static UWORD
ReadMII(struct DevUnit
*unit
, UWORD phy_no
, UWORD reg_no
,
2136 struct DevBase
*base
)
2140 unit
->LELongOut(unit
->card
, PROREG_MIICONTROL
,
2141 2 << PROREG_MIICONTROLB_CMD
2142 | phy_no
<< PROREG_MIICONTROLB_PHYNO
2143 | reg_no
<< PROREG_MIICONTROLB_REGNO
);
2145 value
= unit
->LELongIn(unit
->card
, PROREG_MIICONTROL
);
2146 while((value
& PROREG_MIICONTROLF_READY
) == 0);
2148 return value
& PROREG_MIICONTROLF_DATA
;
2153 /****i* intelpro100.device/WriteMII ****************************************
2156 * WriteMII -- Write to a register in an MII PHY.
2159 * WriteMII(unit, phy_no, reg_no, value)
2161 * VOID WriteMII(struct DevUnit *, UWORD, UWORD, UWORD);
2164 * unit - A unit of this device.
2165 * phy_no - Index of PHY to use.
2166 * reg_no - MII register to write to.
2167 * value - Value to write to MII register.
2172 ****************************************************************************
2176 static VOID
WriteMII(struct DevUnit
*unit
, UWORD phy_no
, UWORD reg_no
,
2177 UWORD value
, struct DevBase
*base
)
2179 unit
->LELongOut(unit
->card
, PROREG_MIICONTROL
,
2180 1 << PROREG_MIICONTROLB_CMD
2181 | phy_no
<< PROREG_MIICONTROLB_PHYNO
2182 | reg_no
<< PROREG_MIICONTROLB_REGNO
2187 unit
->LELongIn(unit
->card
, PROREG_MIICONTROL
)
2188 & PROREG_MIICONTROLF_READY
2198 /****i* intelpro100.device/BusyMicroDelay **********************************
2201 * BusyMilliDelay - Busy-wait for specified number of microseconds.
2204 * BusyMilliDelay(micros)
2206 * VOID BusyMilliDelay(ULONG);
2208 ****************************************************************************
2213 static VOID
BusyMicroDelay(ULONG micros
, struct DevBase
*base
)
2215 struct timeval time
, end_time
;
2217 GetSysTime(&end_time
);
2219 time
.tv_micro
= micros
;
2220 AddTime(&end_time
, &time
);
2222 while(CmpTime(&end_time
, &time
) < 0)
2230 static VOID
BusyMicroDelay(ULONG micros
, struct DevBase
*base
)
2232 struct EClockVal time
, end_time
;
2235 rate
= ReadEClock(&time
);
2236 end_time
.ev_hi
= time
.ev_hi
;
2237 end_time
.ev_lo
= time
.ev_lo
+ (micros
* rate
+ 1) / 1000000;
2238 if(end_time
.ev_lo
< time
.ev_lo
)
2241 while(time
.ev_lo
< end_time
.ev_lo
|| time
.ev_hi
< end_time
.ev_hi
)