revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / networks / intelpro100 / unit.c
blob68bb674a37274314876b1e3c2b8974a99aadb8f5
1 /*
3 Copyright (C) 2001-2017 Neil Cafferkey
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 MA 02111-1307, USA.
23 #include <exec/memory.h>
24 #include <exec/execbase.h>
25 #include <exec/errors.h>
26 #include <exec/tasks.h>
28 #include <proto/exec.h>
29 #ifndef __amigaos4__
30 #include <proto/alib.h>
31 #else
32 #include <clib/alib_protos.h>
33 #endif
34 #include <proto/utility.h>
35 #include <proto/timer.h>
37 #include "device.h"
38 #include "task.h"
39 #include "intelpro100.h"
40 #include "mii.h"
41 #include "dp83840.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
50 #define STAT_COUNT 16
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,
102 0x053f
106 /****i* intelpro100.device/CreateUnit **************************************
108 * NAME
109 * CreateUnit -- Create a unit.
111 * SYNOPSIS
112 * unit = CreateUnit(index, card, io_tags, bus)
114 * struct DevUnit *CreateUnit(ULONG, APTR, struct TagItem *, UWORD);
116 * FUNCTION
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)
126 BOOL success = TRUE;
127 struct DevUnit *unit;
128 struct Task *task;
129 struct MsgPort *port;
130 UBYTE i;
131 APTR stack;
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);
136 if(unit == NULL)
137 success = FALSE;
139 if(success)
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);
149 unit->index = index;
150 unit->device = base;
151 unit->card = card;
152 unit->bus = bus;
154 /* Store I/O hooks */
156 unit->ByteIn =
157 (APTR)GetTagData(IOTAG_ByteIn, (UPINT)NULL, io_tags);
158 unit->ByteOut =
159 (APTR)GetTagData(IOTAG_ByteOut, (UPINT)NULL, io_tags);
160 unit->LEWordIn =
161 (APTR)GetTagData(IOTAG_LEWordIn, (UPINT)NULL, io_tags);
162 unit->LELongIn =
163 (APTR)GetTagData(IOTAG_LELongIn, (UPINT)NULL, io_tags);
164 unit->LEWordOut =
165 (APTR)GetTagData(IOTAG_LEWordOut, (UPINT)NULL, io_tags);
166 unit->LELongOut =
167 (APTR)GetTagData(IOTAG_LELongOut, (UPINT)NULL, io_tags);
168 unit->AllocDMAMem =
169 (APTR)GetTagData(IOTAG_AllocDMAMem, (UPINT)NULL, io_tags);
170 unit->FreeDMAMem =
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)
178 success = FALSE;
180 /* Allocate buffer for adapter to writes statistics to */
182 unit->stats_buffer =
183 AllocVec(sizeof(ULONG) * (STAT_COUNT + 1), MEMF_PUBLIC);
184 if(unit->stats_buffer == NULL)
185 success = FALSE;
188 if(success)
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);
201 if(port == NULL)
202 success = FALSE;
204 if(success)
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)
225 success = FALSE;
228 if(success)
230 /* Construct TX ring */
232 for(i = 0; i < TX_SLOT_COUNT; i++)
234 tcb = next_tcb;
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++)
245 rcb = next_rcb;
246 next_rcb = rcb + RCB_SIZE / sizeof(ULONG);
247 rcb[PROCB_NEXT] = MakeLELong((ULONG)(UPINT)next_rcb);
248 rcb[PROCB_RXINFO] =
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;
287 if(success)
289 /* Create a new task */
291 unit->task = task =
292 AllocMem(sizeof(struct Task), MEMF_PUBLIC | MEMF_CLEAR);
293 if(task == NULL)
294 success = FALSE;
297 if(success)
299 /* Allocate stack */
301 stack = AllocMem(STACK_SIZE, MEMF_PUBLIC);
302 if(stack == NULL)
303 success = FALSE;
306 if(success)
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;
321 else
322 success = FALSE;
325 if(!success)
327 DeleteUnit(unit, base);
328 unit = NULL;
331 return unit;
336 /****i* intelpro100.device/DeleteUnit **************************************
338 * NAME
339 * DeleteUnit -- Delete a unit.
341 * SYNOPSIS
342 * DeleteUnit(unit)
344 * VOID DeleteUnit(struct DevUnit *);
346 * FUNCTION
347 * Deletes a unit.
349 * INPUTS
350 * unit - Device unit (can be NULL).
352 * RESULT
353 * None.
355 ****************************************************************************
359 VOID DeleteUnit(struct DevUnit *unit, struct DevBase *base)
361 UBYTE i;
362 struct Task *task;
364 if(unit != NULL)
366 task = unit->task;
367 if(task != NULL)
369 if((unit->flags & UNITF_TASKADDED) != 0)
370 RemTask(task);
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);
385 FreeVec(unit->rcbs);
386 FreeVec(unit->tcbs);
387 FreeVec(unit->tx_buffer);
388 FreeVec(unit->stats_buffer);
390 FreeMem(unit, sizeof(struct DevUnit));
393 return;
398 /****i* intelpro100.device/InitialiseAdapter *******************************
400 * NAME
401 * InitialiseAdapter -- Initialise network adapter hardware.
403 * SYNOPSIS
404 * InitialiseAdapter(unit)
406 * VOID InitialiseAdapter(struct DevUnit *);
408 * INPUTS
409 * unit
411 * RESULT
412 * None.
414 ****************************************************************************
418 static VOID InitialiseAdapter(struct DevUnit *unit, struct DevBase *base)
420 UBYTE *p, i;
421 UWORD address_part;
423 /* Reset card */
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);
446 /* Return */
448 return;
453 /****i* intelpro100.device/ConfigureAdapter ********************************
455 * NAME
456 * ConfigureAdapter -- Put adapter online for the first time.
458 * SYNOPSIS
459 * ConfigureAdapter(unit)
461 * VOID ConfigureAdapter(struct DevUnit *);
463 * INPUTS
464 * unit
466 * RESULT
467 * None.
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]);
487 tcb[PROCB_CONTROL] =
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);
507 /* Go online */
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);
514 /* Return */
516 return;
521 /****i* intelpro100.device/FillConfigData **********************************
523 * NAME
524 * FillConfigData -- Fill in the data for a configuration command.
526 * SYNOPSIS
527 * FillConfigData(unit, tcb)
529 * VOID FillConfigData(struct DevUnit *, ULONG *);
531 * INPUTS
532 * unit - A unit of this device.
533 * tcb - The configuration command block.
535 * RESULT
536 * None.
538 ****************************************************************************
542 static VOID FillConfigData(struct DevUnit *unit, ULONG *tcb,
543 struct DevBase *base)
545 UBYTE i;
546 const ULONG *p;
547 ULONG *q;
549 /* Copy constant parameters from template */
551 for(p = config_data, q = tcb + PROCB_CF0, i = 0; i < CONFIG_DATA_LEN;
552 i++)
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);
561 /* AUI or MII? */
563 if((unit->phy_info & PROROM_PHYINFO0F_AUI) != 0)
564 tcb[PROCB_CF3] |= MakeLELong(PROCB_CF3F_CDT);
565 else
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);
575 /* Return */
577 return;
582 /****i* intelpro100.device/GoOnline ****************************************
584 * NAME
585 * GoOnline -- Put the adapter online.
587 * SYNOPSIS
588 * GoOnline(unit)
590 * VOID GoOnline(struct DevUnit *);
592 * INPUTS
593 * unit - A unit of this device.
595 * RESULT
596 * None.
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);
618 return;
623 /****i* intelpro100.device/GoOffline ***************************************
625 * NAME
626 * GoOffline -- Put the adpater offline.
628 * SYNOPSIS
629 * GoOffline(unit)
631 * VOID GoOffline(struct DevUnit *);
633 * INPUTS
634 * unit - A unit of this device.
636 * RESULT
637 * None.
639 ****************************************************************************
643 VOID GoOffline(struct DevUnit *unit, struct DevBase *base)
645 unit->flags &= ~UNITF_ONLINE;
647 if((unit->flags & UNITF_HAVEADAPTER) != 0)
649 /* Stop reception */
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);
665 return;
670 /****i* intelpro100.device/AddMulticastRange *******************************
672 * NAME
673 * AddMulticastRange
675 * SYNOPSIS
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);
699 if(range != NULL)
700 range->add_count++;
701 else
703 range = AllocMem(sizeof(struct AddressRange), MEMF_PUBLIC);
704 if(range != NULL)
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;
712 Disable();
713 AddTail((APTR)&unit->multicast_ranges, (APTR)range);
714 Enable();
718 return range != NULL;
723 /****i* intelpro100.device/RemMulticastRange *******************************
725 * NAME
726 * RemMulticastRange
728 * SYNOPSIS
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);
752 if(range != NULL)
754 if(--range->add_count == 0)
756 Disable();
757 Remove((APTR)range);
758 Enable();
759 FreeMem(range, sizeof(struct AddressRange));
763 return range != NULL;
768 /****i* intelpro100.device/FindMulticastRange ******************************
770 * NAME
771 * FindMulticastRange
773 * SYNOPSIS
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;
789 BOOL found = FALSE;
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))
800 found = TRUE;
801 else
802 range = (APTR)range->node.mln_Succ;
805 if(!found)
806 range = NULL;
808 return range;
813 /****i* intelpro100.device/SetMulticast ************************************
815 * NAME
816 * SetMulticast
818 * SYNOPSIS
819 * SetMulticast(unit)
821 * VOID SetMulticast(struct DevUnit *);
823 * FUNCTION
824 * Fills in the unit's multicast list TCB, but does not send it to the
825 * device.
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;
836 BOOL range_ended;
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);
847 p++;
848 while(range != tail && i < MAX_MCAST_ENTRIES)
850 address_left = range->lower_bound_left;
851 address_right = range->lower_bound_right;
852 range_ended = FALSE;
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)
863 range_ended = TRUE;
865 if(++address_right == 0)
866 address_left++;
869 if(range_ended)
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 */
877 if(range != tail)
878 unit->flags |= UNITF_ALLMCAST;
879 else
880 unit->flags &= ~UNITF_ALLMCAST;
883 return;
888 /****i* intelpro100.device/FindTypeStats ***********************************
890 * NAME
891 * FindTypeStats
893 * SYNOPSIS
894 * stats = FindTypeStats(unit, list,
895 * packet_type)
897 * struct TypeStats *FindTypeStats(struct DevUnit *, struct MinList *,
898 * ULONG);
900 ****************************************************************************
904 struct TypeStats *FindTypeStats(struct DevUnit *unit, struct MinList *list,
905 ULONG packet_type, struct DevBase *base)
907 struct TypeStats *stats, *tail;
908 BOOL found = FALSE;
910 stats = (APTR)list->mlh_Head;
911 tail = (APTR)&list->mlh_Tail;
913 while((stats != tail) && !found)
915 if(stats->packet_type == packet_type)
916 found = TRUE;
917 else
918 stats = (APTR)stats->node.mln_Succ;
921 if(!found)
922 stats = NULL;
924 return stats;
929 /****i* intelpro100.device/FlushUnit ***************************************
931 * NAME
932 * FlushUnit
934 * SYNOPSIS
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;
947 UBYTE i;
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);
961 #if 1
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;
977 #else
978 opener = request->ios2_BufferManagement;
979 while((request = (APTR)GetMsg(&opener->read_port)) != NULL)
981 request->io_Error = IOERR_ABORTED;
982 ReplyMsg((APTR)request);
984 #endif
986 /* Return */
988 return;
993 /****i* intelpro100.device/StatusInt ***************************************
995 * NAME
996 * StatusInt
998 * SYNOPSIS
999 * finished = StatusInt(unit)
1001 * BOOL StatusInt(struct DevUnit *);
1003 * INPUTS
1004 * unit - A unit of this device.
1006 * RESULT
1007 * finished - Always FALSE.
1009 ****************************************************************************
1013 static BOOL StatusInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code))
1015 struct DevBase *base;
1016 UWORD ints;
1018 base = unit->device;
1019 ints = unit->ByteIn(unit->card, PROREG_INTSTATUS);
1021 if(ints != 0)
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);
1035 return FALSE;
1040 /****i* intelpro100.device/RXInt *******************************************
1042 * NAME
1043 * RXInt
1045 * SYNOPSIS
1046 * RXInt(unit)
1048 * VOID RXInt(struct DevUnit *);
1050 * INPUTS
1051 * unit - A unit of this device.
1052 * int_code - Unused.
1054 * RESULT
1055 * None.
1057 ****************************************************************************
1061 static VOID RXInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code))
1063 UWORD packet_size;
1064 struct DevBase *base;
1065 BOOL is_orphan, accepted;
1066 ULONG rx_status_le, rx_info, packet_type, *rcb, *last_rcb, dma_size;
1067 UBYTE *buffer;
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)
1083 is_orphan = TRUE;
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;
1101 accepted = FALSE;
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,
1110 buffer, base);
1111 accepted = TRUE;
1113 request =
1114 (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
1117 if(accepted)
1118 is_orphan = FALSE;
1119 opener = (APTR)opener->node.mln_Succ;
1122 /* If packet was unwanted, give it to S2_READORPHAN request */
1124 if(is_orphan)
1126 unit->stats.UnknownTypesReceived++;
1127 if(!IsMsgPortEmpty(unit->request_ports[ADOPT_QUEUE]))
1129 CopyPacket(unit,
1130 (APTR)unit->request_ports[ADOPT_QUEUE]->
1131 mp_MsgList.lh_Head, packet_size, packet_type, buffer,
1132 base);
1136 /* Update remaining statistics */
1138 tracker =
1139 FindTypeStats(unit, &unit->type_trackers, packet_type, base);
1140 if(tracker != NULL)
1142 tracker->stats.PacketsReceived++;
1143 tracker->stats.BytesReceived += packet_size;
1147 else
1149 unit->stats.BadData++;
1150 ReportEvents(unit, S2EVENT_ERROR | S2EVENT_HARDWARE | S2EVENT_RX,
1151 base);
1154 rcb[PROCB_CONTROL] = MakeLELong(PROCB_CONTROLF_SUSPEND);
1155 rcb[PROCB_RXINFO] =
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);
1164 if(TRUE)
1165 unit->LEWordOut(unit->card, PROREG_COMMAND, PRO_RUCMD_RESUME);
1167 last_rcb = rcb;
1168 rcb = (ULONG *)(UPINT)LELong(rcb[PROCB_NEXT]);
1171 /* Return */
1173 unit->last_rcb = last_rcb;
1174 return;
1179 /****i* intelpro100.device/CopyPacket **************************************
1181 * NAME
1182 * CopyPacket
1184 * SYNOPSIS
1185 * CopyPacket(unit, request, packet_size, packet_type,
1186 * buffer)
1188 * VOID CopyPacket(struct DevUnit *, struct IOSana2Req *, UWORD, UWORD,
1189 * UBYTE *);
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,
1214 ETH_ADDRESSSIZE);
1215 CopyMem(buffer + ETH_PACKET_DEST, request->ios2_DstAddr,
1216 ETH_ADDRESSSIZE);
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;
1226 #ifdef USE_HACKS
1227 else
1228 packet_size += 4; /* Needed for Shapeshifter & Fusion */
1229 #endif
1230 request->ios2_DataLength = packet_size;
1232 /* Filter packet */
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))
1238 filtered = TRUE;
1240 if(!filtered)
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;
1248 ReportEvents(unit,
1249 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF | S2EVENT_RX,
1250 base);
1252 Remove((APTR)request);
1253 ReplyMsg((APTR)request);
1256 return;
1261 /****i* intelpro100.device/AddressFilter ***********************************
1263 * NAME
1264 * AddressFilter
1266 * SYNOPSIS
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;
1279 BOOL accept = TRUE;
1280 ULONG address_left;
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;
1295 accept = FALSE;
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)))
1305 accept = TRUE;
1306 range = (APTR)range->node.mln_Succ;
1309 if(!accept)
1310 unit->special_stats[S2SS_ETHERNET_BADMULTICAST & 0xffff]++;
1313 return accept;
1318 /****i* intelpro100.device/TXInt *******************************************
1320 * NAME
1321 * TXInt
1323 * SYNOPSIS
1324 * TXInt(unit)
1326 * VOID TXInt(struct DevUnit *);
1328 * INPUTS
1329 * unit - A unit of this device.
1330 * int_code - Unused.
1332 * RESULT
1333 * None.
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,
1353 action;
1354 UBYTE *(*dma_tx_function)(REG(a0, APTR));
1355 BYTE error;
1356 UBYTE *buffer;
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))
1374 == 0)
1376 error = 0;
1377 request = (APTR)GetMsg(port);
1378 request->ios2_Req.io_Message.mn_Node.ln_Type = NT_FREEMSG;
1380 switch(request->ios2_Req.io_Command)
1382 case CMD_WRITE:
1383 case S2_MULTICAST:
1384 case S2_BROADCAST:
1385 action = PROACT_TX;
1386 break;
1387 default:
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);
1413 tcb[PROCB_TXINFO] =
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++)
1423 *p++ = *q++;
1424 for(i = 0, q = (UWORD *)unit->address;
1425 i < ETH_ADDRESSSIZE / 2; i++)
1426 *p++ = *q++;
1427 *p++ = MakeBEWord(request->ios2_PacketType);
1428 buffer = (UBYTE *)p;
1430 fragment += PRO_FRAGLEN;
1432 else
1434 tcb[PROCB_TXINFO] =
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);
1446 else
1447 buffer = NULL;
1449 if(buffer == NULL)
1451 buffer = unit->tx_buffer;
1452 if(opener->tx_function(buffer, request->ios2_Data,
1453 data_size))
1455 unit->flags |= UNITF_TXBUFFERINUSE;
1457 else
1459 error = S2ERR_NO_RESOURCES;
1460 wire_error = S2WERR_BUFF_ERROR;
1461 ReportEvents(unit,
1462 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF
1463 | S2EVENT_TX, base);
1467 /* Put pointer to packet data into descriptor */
1469 if(error == 0)
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);
1477 else
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;
1496 else
1498 tcb[PROCB_CONTROL] = MakeLELong(PROACT_CONFIGURE
1499 | PROCB_CONTROLF_SUSPEND | PROCB_CONTROLF_INT);
1500 FillConfigData(unit, tcb, base);
1504 if(error == 0)
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,
1521 PRO_CUCMD_RESUME);
1524 AddTail((APTR)&unit->tx_requests, (APTR)request);
1525 unit->last_tcb = tcb;
1527 else
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;
1537 else
1538 proceed = FALSE;
1541 if(proceed)
1542 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
1543 else
1544 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_IGNORE;
1546 return;
1551 /****i* intelpro100.device/TXEndInt ****************************************
1553 * NAME
1554 * TXEndInt
1556 * SYNOPSIS
1557 * TXEndInt(unit)
1559 * VOID TXEndInt(struct DevUnit *);
1561 * INPUTS
1562 * unit - A unit of this device.
1563 * int_code - Unused.
1565 * RESULT
1566 * None.
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;
1578 UBYTE *buffer;
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);
1630 if(tracker != NULL)
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;
1648 /* Reply request */
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);
1669 return;
1674 /****i* intelpro100.device/UpdateStats *************************************
1676 * NAME
1677 * UpdateStats
1679 * SYNOPSIS
1680 * UpdateStats(unit)
1682 * VOID UpdateStats(struct DevUnit *);
1684 * INPUTS
1685 * unit - A unit of this device.
1687 * RESULT
1688 * None.
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]);
1717 return;
1722 /****i* intelpro100.device/ReportEvents ************************************
1724 * NAME
1725 * ReportEvents
1727 * SYNOPSIS
1728 * ReportEvents(unit, events)
1730 * VOID ReportEvents(struct DevUnit *, ULONG);
1732 * INPUTS
1733 * unit - A unit of this device.
1734 * events - A mask of events to report.
1736 * RESULT
1737 * None.
1739 ****************************************************************************
1743 static VOID ReportEvents(struct DevUnit *unit, ULONG events,
1744 struct DevBase *base)
1746 struct IOSana2Req *request, *tail, *next_request;
1747 struct List *list;
1749 list = &unit->request_ports[EVENT_QUEUE]->mp_MsgList;
1750 next_request = (APTR)list->lh_Head;
1751 tail = (APTR)&list->lh_Tail;
1753 Disable();
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);
1766 Enable();
1768 return;
1773 /****i* intelpro100.device/UnitTask ****************************************
1775 * NAME
1776 * UnitTask
1778 * SYNOPSIS
1779 * UnitTask(unit)
1781 * VOID UnitTask(struct DevUnit *);
1783 * FUNCTION
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 */
1817 while(TRUE)
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 ****************************
1838 * NAME
1839 * GetEEPROMAddressSize
1841 * SYNOPSIS
1842 * size = GetEEPROMAddressSize(unit)
1844 * UWORD GetEEPROMAddressSize(struct DevUnit *);
1846 * INPUTS
1847 * unit - A unit of this device.
1849 * RESULT
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)
1862 UWORD size;
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);
1871 return size;
1876 /****i* intelpro100.device/ReadEEPROM **************************************
1878 * NAME
1879 * ReadEEPROM -- Read an EEPROM location.
1881 * SYNOPSIS
1882 * value = ReadEEPROM(unit, index)
1884 * UWORD ReadEEPROM(struct DevUnit *, UWORD);
1886 * INPUTS
1887 * unit - A unit of this device.
1888 * index - Offset within EEPROM.
1890 * RESULT
1891 * value - Contents of specified EEPROM location.
1893 ****************************************************************************
1897 static UWORD ReadEEPROM(struct DevUnit *unit, UWORD index,
1898 struct DevBase *base)
1900 UWORD value;
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);
1909 return value;
1914 /****i* intelpro100.device/ReadEEPROMBits **********************************
1916 * NAME
1917 * ReadEEPROMBits -- Read a stream of bits from the EEPROM.
1919 * SYNOPSIS
1920 * value = ReadEEPROMBits(unit, count)
1922 * ULONG ReadEEPROMBits(struct DevUnit *, UBYTE);
1924 * INPUTS
1925 * unit - A unit of this device.
1926 * count - Number of bits to be read.
1928 * RESULT
1929 * value - The bits read from the EEPROM, right-justified.
1931 ****************************************************************************
1935 static ULONG ReadEEPROMBits(struct DevUnit *unit, UBYTE count,
1936 struct DevBase *base)
1938 UBYTE i;
1939 ULONG value = 0;
1941 for(i = 0; i < count; i++)
1943 value <<= 1;
1944 if(ReadEEPROMBit(unit, base))
1945 value |= 0x1;
1948 return value;
1952 /****i* intelpro100.device/WriteEEPROMBits *********************************
1954 * NAME
1955 * WriteEEPROMBits -- Write a stream of bits to the EEPROM.
1957 * SYNOPSIS
1958 * WriteEEPROMBits(unit, value, count)
1960 * VOID WriteEEPROMBits(struct DevUnit *, ULONG, UBYTE);
1962 * INPUTS
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.
1967 * RESULT
1968 * None.
1970 ****************************************************************************
1974 static VOID WriteEEPROMBits(struct DevUnit *unit, ULONG value, UBYTE count,
1975 struct DevBase *base)
1977 ULONG mask;
1979 for(mask = 1 << (count - 1); mask != 0; mask >>= 1)
1980 WriteEEPROMBit(unit, (value & mask) != 0, base);
1982 return;
1987 /****i* intelpro100.device/ReadEEPROMBit ***********************************
1989 * NAME
1990 * ReadEEPROMBit -- Read a bit from the EEPROM.
1992 * SYNOPSIS
1993 * value = ReadEEPROMBit(unit)
1995 * BOOL ReadEEPROMBit(struct DevUnit *);
1997 * INPUTS
1998 * unit - A unit of this device.
2000 * RESULT
2001 * value - True for one, false for zero.
2003 ****************************************************************************
2007 static BOOL ReadEEPROMBit(struct DevUnit *unit, struct DevBase *base)
2009 BOOL is_one;
2011 unit->LEWordOut(unit->card, PROREG_EEPROM,
2012 PROREG_EEPROMF_SELECT | PROREG_EEPROMF_CLK);
2013 BusyMicroDelay(2, base);
2014 is_one =
2015 (unit->LEWordIn(unit->card, PROREG_EEPROM) & PROREG_EEPROMF_DATAIN)
2016 != 0;
2017 unit->LEWordOut(unit->card, PROREG_EEPROM, PROREG_EEPROMF_SELECT);
2018 BusyMicroDelay(2, base);
2020 return is_one;
2025 /****i* intelpro100.device/WriteEEPROMBit **********************************
2027 * NAME
2028 * WriteEEPROMBit -- Write a bit to the EEPROM.
2030 * SYNOPSIS
2031 * data_in = WriteEEPROMBit(unit, is_one)
2033 * BOOL WriteEEPROMBit(struct DevUnit *, BOOL);
2035 * INPUTS
2036 * unit - A unit of this device.
2037 * is_one - True if a set bit should be written.
2039 * RESULT
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)
2049 UWORD data_out;
2051 if(is_one)
2052 data_out = PROREG_EEPROMF_DATAOUT;
2053 else
2054 data_out = 0;
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);
2065 return
2066 (unit->LEWordIn(unit->card, PROREG_EEPROM) & PROREG_EEPROMF_DATAIN)
2067 != 0;
2072 /****i* intelpro100.device/ReadMII *****************************************
2074 * NAME
2075 * ReadMII -- Read a register in an MII PHY.
2077 * SYNOPSIS
2078 * value = ReadMII(unit, phy_no, reg_no)
2080 * UWORD ReadMII(struct DevUnit *, UWORD, UWORD);
2082 * INPUTS
2083 * unit - A unit of this device.
2084 * phy_no - Index of PHY to use.
2085 * reg_no - MII register to read.
2087 * RESULT
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)
2097 ULONG value;
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 ****************************************
2114 * NAME
2115 * WriteMII -- Write to a register in an MII PHY.
2117 * SYNOPSIS
2118 * WriteMII(unit, phy_no, reg_no, value)
2120 * VOID WriteMII(struct DevUnit *, UWORD, UWORD, UWORD);
2122 * INPUTS
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.
2128 * RESULT
2129 * None.
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
2142 | value);
2143 while
2146 unit->LELongIn(unit->card, PROREG_MIICONTROL)
2147 & PROREG_MIICONTROLF_READY
2149 == 0
2152 return;
2157 /****i* intelpro100.device/BusyMicroDelay **********************************
2159 * NAME
2160 * BusyMilliDelay - Busy-wait for specified number of microseconds.
2162 * SYNOPSIS
2163 * BusyMilliDelay(micros)
2165 * VOID BusyMilliDelay(ULONG);
2167 ****************************************************************************
2171 #if 1
2172 static VOID BusyMicroDelay(ULONG micros, struct DevBase *base)
2174 struct timeval time, end_time;
2176 GetSysTime(&end_time);
2177 time.tv_secs = 0;
2178 time.tv_micro = micros;
2179 AddTime(&end_time, &time);
2181 while(CmpTime(&end_time, &time) < 0)
2182 GetSysTime(&time);
2184 return;
2188 #else
2189 static VOID BusyMicroDelay(ULONG micros, struct DevBase *base)
2191 struct EClockVal time, end_time;
2192 ULONG rate;
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)
2198 end_time.ev_hi++;
2200 while(time.ev_lo < end_time.ev_lo || time.ev_hi < end_time.ev_hi)
2201 ReadEClock(&time);
2203 return;
2205 #endif