Updated PCI IDs to latest snapshot.
[tangerine.git] / workbench / devs / networks / intelpro100 / unit.c
blob1f74f20cfbadb3751d27f1f2b147f1938eaef1c1
1 /*
3 Copyright (C) 2001-2005 Neil Cafferkey
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 MA 02111-1307, USA.
23 #include <exec/memory.h>
24 #include <exec/execbase.h>
25 #include <exec/errors.h>
27 #include <proto/exec.h>
28 #ifndef __amigaos4__
29 #include <proto/alib.h>
30 #else
31 #include <clib/alib_protos.h>
32 #endif
33 #include <proto/utility.h>
34 #include <proto/timer.h>
36 #include "device.h"
37 #include "intelpro100.h"
38 #include "mii.h"
39 #include "dp83840.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
48 #define STAT_COUNT 16
49 #define MAX_MCAST_ENTRIES 100
50 #define MCAST_CB_SIZE (PROCB_COUNT * sizeof(ULONG) + sizeof(UWORD) \
51 + ETH_ADDRESSSIZE * MAX_MCAST_ENTRIES)
53 #ifndef AbsExecBase
54 #define AbsExecBase (*(struct ExecBase **)4)
55 #endif
57 static VOID InitialiseAdapter(struct DevUnit *unit, struct DevBase *base);
58 static VOID FillConfigData(struct DevUnit *unit, ULONG *tcb,
59 struct DevBase *base);
60 static struct AddressRange *FindMulticastRange(struct DevUnit *unit,
61 ULONG lower_bound_left, UWORD lower_bound_right, ULONG upper_bound_left,
62 UWORD upper_bound_right, struct DevBase *base);
63 static VOID SetMulticast(struct DevUnit *unit, struct DevBase *base);
64 static BOOL StatusInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code));
65 static VOID RXInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code));
66 static VOID CopyPacket(struct DevUnit *unit, struct IOSana2Req *request,
67 UWORD packet_size, UWORD packet_type, UBYTE *buffer,
68 struct DevBase *base);
69 static BOOL AddressFilter(struct DevUnit *unit, UBYTE *address,
70 struct DevBase *base);
71 static VOID TXInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code));
72 static VOID TXEndInt(REG(a1, struct DevUnit *unit),
73 REG(a5, APTR int_code));
74 static VOID ReportEvents(struct DevUnit *unit, ULONG events,
75 struct DevBase *base);
76 static VOID UnitTask();
77 static UWORD GetEEPROMAddressSize(struct DevUnit *unit,
78 struct DevBase *base);
79 static UWORD ReadEEPROM(struct DevUnit *unit, UWORD index,
80 struct DevBase *base);
81 static ULONG ReadEEPROMBits(struct DevUnit *unit, UBYTE count,
82 struct DevBase *base);
83 static VOID WriteEEPROMBits(struct DevUnit *unit, ULONG value, UBYTE count,
84 struct DevBase *base);
85 static BOOL ReadEEPROMBit(struct DevUnit *unit, struct DevBase *base);
86 static BOOL WriteEEPROMBit(struct DevUnit *unit, BOOL is_one,
87 struct DevBase *base);
88 static UWORD ReadMII(struct DevUnit *unit, UWORD phy_no, UWORD reg_no,
89 struct DevBase *base);
90 static VOID WriteMII(struct DevUnit *unit, UWORD phy_no, UWORD reg_no,
91 UWORD value, struct DevBase *base);
92 static VOID BusyMicroDelay(ULONG micros, struct DevBase *base);
96 static const ULONG config_data[] =
98 8 << PROCB_CF0B_RXFIFOLIM | 22 << PROCB_CF0B_SIZE,
99 1 << PROCB_CF1B_UNDERRUNRETRIES | PROCB_CF1F_DISCARDRUNTS
100 | PROCB_CF1F_STDSTATS | PROCB_CF1F_STDTXBLOCK | 0x00020000,
101 2 << PROCB_CF2B_PREAMBLETYPE | PROCB_CF2F_NOSOURCEINSERT | 0x00060001,
102 0xf200 << PROCB_CF3B_ARPFILTER | 6 << PROCB_CF3B_IFS | 0x48000000,
103 PROCB_CF4F_USEFDPIN | PROCB_CF4F_PADDING | 0x00f04000,
104 0x053f
108 #ifdef __amigaos4__
109 #undef AddTask
110 #define AddTask(task, initial_pc, final_pc) \
111 IExec->AddTask(task, initial_pc, final_pc, NULL)
112 #endif
113 #ifdef __MORPHOS__
114 static const struct EmulLibEntry mos_task_trap =
116 TRAP_LIB,
118 (APTR)UnitTask
120 #define UnitTask &mos_task_trap
121 #endif
124 /****i* intelpro100.device/CreateUnit **************************************
126 * NAME
127 * CreateUnit -- Create a unit.
129 * SYNOPSIS
130 * unit = CreateUnit(index, card, io_tags, bus)
132 * struct DevUnit *CreateUnit(ULONG, APTR, struct TagItem *, UWORD);
134 * FUNCTION
135 * Creates a new unit.
137 ****************************************************************************
141 struct DevUnit *CreateUnit(ULONG index, APTR card,
142 const struct TagItem *io_tags, UWORD bus, struct DevBase *base)
144 BOOL success = TRUE;
145 struct DevUnit *unit;
146 struct Task *task;
147 struct MsgPort *port;
148 UBYTE i;
149 APTR stack;
150 ULONG *tcb, *next_tcb, *rcb, *next_rcb, dma_size;
151 APTR rx_int_function, tx_int_function;
153 unit = AllocMem(sizeof(struct DevUnit), MEMF_CLEAR | MEMF_PUBLIC);
154 if(unit == NULL)
155 success = FALSE;
157 if(success)
159 /* Initialise lists etc. */
161 InitSemaphore(&unit->access_lock);
162 NewList((APTR)&unit->openers);
163 NewList((APTR)&unit->type_trackers);
164 NewList((APTR)&unit->multicast_ranges);
165 NewList((APTR)&unit->tx_requests);
167 unit->index = index;
168 unit->device = base;
169 unit->card = card;
170 unit->bus = bus;
172 /* Store I/O hooks */
174 unit->ByteIn =
175 (APTR)GetTagData(IOTAG_ByteIn, (UPINT)NULL, io_tags);
176 unit->ByteOut =
177 (APTR)GetTagData(IOTAG_ByteOut, (UPINT)NULL, io_tags);
178 unit->LEWordIn =
179 (APTR)GetTagData(IOTAG_LEWordIn, (UPINT)NULL, io_tags);
180 unit->LELongIn =
181 (APTR)GetTagData(IOTAG_LELongIn, (UPINT)NULL, io_tags);
182 unit->LEWordOut =
183 (APTR)GetTagData(IOTAG_LEWordOut, (UPINT)NULL, io_tags);
184 unit->LELongOut =
185 (APTR)GetTagData(IOTAG_LELongOut, (UPINT)NULL, io_tags);
186 unit->AllocDMAMem =
187 (APTR)GetTagData(IOTAG_AllocDMAMem, (UPINT)NULL, io_tags);
188 unit->FreeDMAMem =
189 (APTR)GetTagData(IOTAG_FreeDMAMem, (UPINT)NULL, io_tags);
190 if(unit->ByteIn == NULL
191 || unit->ByteOut == NULL
192 || unit->LEWordIn == NULL
193 || unit->LEWordOut == NULL || unit->LELongIn == NULL
194 || unit->LELongOut == NULL
195 || unit->AllocDMAMem == NULL || unit->FreeDMAMem == NULL)
196 success = FALSE;
198 /* Allocate buffer for adapter to writes statistics to */
200 unit->stats_buffer =
201 AllocVec(sizeof(ULONG) * (STAT_COUNT + 1), MEMF_PUBLIC);
202 if(unit->stats_buffer == NULL)
203 success = FALSE;
206 if(success)
208 /* Initialise network adapter hardware */
210 InitialiseAdapter(unit, base);
211 unit->flags |= UNITF_HAVEADAPTER;
213 /* Create the message ports for queuing requests */
215 for(i = 0; i < REQUEST_QUEUE_COUNT; i++)
217 unit->request_ports[i] = port = AllocMem(sizeof(struct MsgPort),
218 MEMF_PUBLIC | MEMF_CLEAR);
219 if(port == NULL)
220 success = FALSE;
222 if(success)
224 NewList(&port->mp_MsgList);
225 port->mp_Flags = PA_IGNORE;
226 port->mp_SigTask = &unit->tx_int;
230 /* Allocate and initialise packet/command descriptors */
232 unit->tx_buffer = AllocVec(ETH_MAXPACKETSIZE, MEMF_PUBLIC);
233 next_tcb = unit->first_tcb = unit->tcbs =
234 AllocVec(TCB_SIZE * TX_SLOT_COUNT, MEMF_PUBLIC | MEMF_CLEAR);
235 next_rcb = unit->rcbs =
236 AllocVec(RCB_SIZE * RX_SLOT_COUNT, MEMF_PUBLIC | MEMF_CLEAR);
237 unit->multicast_cb = AllocVec(PROCB_COUNT * sizeof(ULONG)
238 + sizeof(UWORD) + ETH_ADDRESSSIZE * MAX_MCAST_ENTRIES,
239 MEMF_PUBLIC | MEMF_CLEAR);
241 if(next_tcb == NULL || next_rcb == NULL || unit->tx_buffer == NULL
242 || unit->multicast_cb == NULL)
243 success = FALSE;
246 if(success)
248 /* Construct TX ring */
250 for(i = 0; i < TX_SLOT_COUNT; i++)
252 tcb = next_tcb;
253 next_tcb = tcb + TCB_SIZE / sizeof(ULONG);
254 tcb[PROCB_NEXT] = MakeLELong((ULONG)next_tcb);
256 tcb[PROCB_NEXT] = MakeLELong((ULONG)unit->tcbs);
257 unit->last_tcb = tcb;
259 /* Construct RX ring */
261 for(i = 0; i < RX_SLOT_COUNT; i++)
263 rcb = next_rcb;
264 next_rcb = rcb + RCB_SIZE / sizeof(ULONG);
265 rcb[PROCB_NEXT] = MakeLELong((ULONG)next_rcb);
266 rcb[PROCB_RXINFO] =
267 MakeLELong(ETH_MAXPACKETSIZE << PROCB_RXINFOB_BUFFERSIZE);
269 rcb[PROCB_CONTROL] = MakeLELong(PROCB_CONTROLF_SUSPEND);
270 rcb[PROCB_NEXT] = MakeLELong((ULONG)unit->rcbs);
271 unit->last_rcb = rcb;
272 dma_size = RCB_SIZE * RX_SLOT_COUNT;
273 CachePreDMA(unit->rcbs, &dma_size, 0);
275 /* Record maximum speed in BPS */
277 unit->speed = 100000000;
279 /* Initialise status, transmit and receive interrupts */
281 unit->status_int.is_Code = (APTR)StatusInt;
282 unit->status_int.is_Data = unit;
284 rx_int_function = RXInt;
285 unit->rx_int.is_Node.ln_Name = (TEXT *)device_name;
286 unit->rx_int.is_Node.ln_Pri = 16;
287 unit->rx_int.is_Code = rx_int_function;
288 unit->rx_int.is_Data = unit;
290 tx_int_function = TXInt;
291 unit->tx_int.is_Node.ln_Name = (TEXT *)device_name;
292 unit->tx_int.is_Code = tx_int_function;
293 unit->tx_int.is_Data = unit;
295 unit->tx_end_int.is_Node.ln_Name = (TEXT *)device_name;
296 unit->tx_end_int.is_Code = TXEndInt;
297 unit->tx_end_int.is_Data = unit;
299 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
302 if(success)
304 /* Create a new task */
306 unit->task = task =
307 AllocMem(sizeof(struct Task), MEMF_PUBLIC | MEMF_CLEAR);
308 if(task == NULL)
309 success = FALSE;
312 if(success)
314 /* Allocate stack */
316 stack = AllocMem(STACK_SIZE, MEMF_PUBLIC);
317 if(stack == NULL)
318 success = FALSE;
321 if(success)
323 /* Initialise and start task */
325 task->tc_Node.ln_Type = NT_TASK;
326 task->tc_Node.ln_Pri = TASK_PRIORITY;
327 task->tc_Node.ln_Name = (APTR)device_name;
328 task->tc_SPUpper = stack + STACK_SIZE;
329 task->tc_SPLower = stack;
330 task->tc_SPReg = stack + STACK_SIZE;
331 NewList(&task->tc_MemEntry);
333 if(AddTask(task, UnitTask, NULL) == NULL)
334 success = FALSE;
337 /* Send the unit to the new task */
339 if(success)
340 task->tc_UserData = unit;
342 if(!success)
344 DeleteUnit(unit, base);
345 unit = NULL;
348 return unit;
353 /****i* intelpro100.device/DeleteUnit **************************************
355 * NAME
356 * DeleteUnit -- Delete a unit.
358 * SYNOPSIS
359 * DeleteUnit(unit)
361 * VOID DeleteUnit(struct DevUnit *);
363 * FUNCTION
364 * Deletes a unit.
366 * INPUTS
367 * unit - Device unit (can be NULL).
369 * RESULT
370 * None.
372 ****************************************************************************
376 VOID DeleteUnit(struct DevUnit *unit, struct DevBase *base)
378 UBYTE i;
379 struct Task *task;
381 if(unit != NULL)
383 task = unit->task;
384 if(task != NULL)
386 if(task->tc_UserData != NULL)
387 RemTask(task);
388 if(task->tc_SPLower != NULL)
389 FreeMem(task->tc_SPLower, STACK_SIZE);
390 FreeMem(task, sizeof(struct Task));
393 for(i = 0; i < REQUEST_QUEUE_COUNT; i++)
395 if(unit->request_ports[i] != NULL)
396 FreeMem(unit->request_ports[i], sizeof(struct MsgPort));
399 if((unit->flags & UNITF_ONLINE) != 0) /* Needed! */
400 GoOffline(unit, base);
402 FreeVec(unit->multicast_cb);
403 FreeVec(unit->rcbs);
404 FreeVec(unit->tcbs);
405 FreeVec(unit->tx_buffer);
406 FreeVec(unit->stats_buffer);
408 FreeMem(unit, sizeof(struct DevUnit));
411 return;
416 /****i* intelpro100.device/InitialiseAdapter *******************************
418 * NAME
419 * InitialiseAdapter -- Initialise network adapter hardware.
421 * SYNOPSIS
422 * InitialiseAdapter(unit)
424 * VOID InitialiseAdapter(struct DevUnit *);
426 * INPUTS
427 * unit
429 * RESULT
430 * None.
432 ****************************************************************************
436 static VOID InitialiseAdapter(struct DevUnit *unit, struct DevBase *base)
438 UBYTE *p, i;
439 UWORD address_part;
441 /* Reset card */
443 unit->LELongOut(unit->card, PROREG_PORT, 0);
444 BusyMicroDelay(10, base);
446 /* Get default MAC address */
448 unit->eeprom_addr_size = GetEEPROMAddressSize(unit, base);
449 p = unit->default_address;
451 for(i = 0; i < ETH_ADDRESSSIZE / sizeof(UWORD); i++)
453 address_part = ReadEEPROM(unit, PROROM_ADDRESS0 + i, base);
454 *p++ = address_part & 0xff;
455 *p++ = address_part >> 8;
458 /* Set up statistics dump area */
460 unit->LELongOut(unit->card, PROREG_GENPTR, (ULONG)unit->stats_buffer);
461 unit->LEWordOut(unit->card, PROREG_COMMAND, PRO_CUCMD_SETSTATSBUFFER);
462 while(unit->LEWordIn(unit->card, PROREG_COMMAND) != 0);
464 /* Return */
466 return;
471 /****i* intelpro100.device/ConfigureAdapter ********************************
473 * NAME
474 * ConfigureAdapter -- Put adapter online for the first time.
476 * SYNOPSIS
477 * ConfigureAdapter(unit)
479 * VOID ConfigureAdapter(struct DevUnit *);
481 * INPUTS
482 * unit
484 * RESULT
485 * None.
487 ****************************************************************************
491 VOID ConfigureAdapter(struct DevUnit *unit, struct DevBase *base)
493 ULONG *tcb, dma_size;
494 UWORD phy_type, phy_no, config;
496 /* Set MAC address */
498 tcb = (ULONG *)LELong(unit->last_tcb[PROCB_NEXT]);
499 tcb[PROCB_CONTROL] = MakeLELong(PROACT_SETADDRESS);
500 CopyMem(&unit->address, tcb + PROCB_ADDRESS, ETH_ADDRESSSIZE);
502 /* Set other parameters */
504 tcb = (ULONG *)LELong(tcb[PROCB_NEXT]);
505 tcb[PROCB_CONTROL] =
506 MakeLELong(PROACT_CONFIGURE | PROCB_CONTROLF_SUSPEND);
507 unit->phy_info = ReadEEPROM(unit, PROROM_PHYINFO0, base);
508 FillConfigData(unit, tcb, base);
509 unit->last_tcb = tcb;
511 dma_size = TCB_SIZE * TX_SLOT_COUNT;
512 CachePreDMA(unit->tcbs, &dma_size, 0);
514 /* DP83840-specific configuration */
516 phy_type = unit->phy_info & PROROM_PHYINFO0F_TYPE;
517 if(phy_type == PRO_PHY_DP83840 || phy_type == PRO_PHY_DP83840A)
519 phy_no = unit->phy_info & PROROM_PHYINFO0F_ADDR;
520 config = ReadMII(unit, phy_no, MII_PCR, base);
521 config |= 0x400 | MII_PCRF_NOLINKMON | MII_PCRF_LED4DUPLEX;
522 WriteMII(unit, phy_no, MII_PCR, config, base);
525 /* Go online */
527 unit->LELongOut(unit->card, PROREG_GENPTR, (ULONG)unit->tcbs);
528 unit->LEWordOut(unit->card, PROREG_COMMAND, PRO_CUCMD_START);
529 while(unit->LEWordIn(unit->card, PROREG_COMMAND) != 0);
530 GoOnline(unit, base);
532 /* Return */
534 return;
539 /****i* intelpro100.device/FillConfigData **********************************
541 * NAME
542 * FillConfigData -- Fill in the data for a configuration command.
544 * SYNOPSIS
545 * FillConfigData(unit, tcb)
547 * VOID FillConfigData(struct DevUnit *, ULONG *);
549 * INPUTS
550 * unit - A unit of this device.
551 * tcb - The configuration command block.
553 * RESULT
554 * None.
556 ****************************************************************************
560 static VOID FillConfigData(struct DevUnit *unit, ULONG *tcb,
561 struct DevBase *base)
563 UBYTE i;
564 const ULONG *p;
565 ULONG *q;
567 /* Copy constant parameters from template */
569 for(p = config_data, q = tcb + PROCB_CF0, i = 0; i < CONFIG_DATA_LEN;
570 i++)
571 *q++ = MakeLELong(*p++);
572 unit->last_tcb = tcb;
574 /* Decide on promiscuous mode */
576 if((unit->flags & UNITF_PROM) != 0)
577 tcb[PROCB_CF3] |= MakeLELong(PROCB_CF3F_PROM);
579 /* AUI or MII? */
581 if((unit->phy_info & PROROM_PHYINFO0F_AUI) != 0)
582 tcb[PROCB_CF3] |= MakeLELong(PROCB_CF3F_CDT);
583 else
584 tcb[PROCB_CF2] |= MakeLELong(PROCB_CF2F_MIIMODE);
586 /* Accept all multicasts? */
588 if((unit->flags & UNITF_ALLMCAST ) != 0)
590 tcb[PROCB_CF5] |= MakeLELong(PROCB_CF5F_ALLMCAST);
593 /* Return */
595 return;
600 /****i* intelpro100.device/GoOnline ****************************************
602 * NAME
603 * GoOnline -- Put the adapter online.
605 * SYNOPSIS
606 * GoOnline(unit)
608 * VOID GoOnline(struct DevUnit *);
610 * INPUTS
611 * unit - A unit of this device.
613 * RESULT
614 * None.
616 ****************************************************************************
620 VOID GoOnline(struct DevUnit *unit, struct DevBase *base)
622 /* Enable the transceiver */
624 unit->flags |= UNITF_ONLINE;
626 unit->LELongOut(unit->card, PROREG_GENPTR,
627 LELong(unit->last_rcb[PROCB_NEXT]));
628 unit->LEWordOut(unit->card, PROREG_COMMAND, PRO_RUCMD_START);
629 while(unit->LEWordIn(unit->card, PROREG_COMMAND) != 0);
631 /* Record start time and report Online event */
633 GetSysTime(&unit->stats.LastStart);
634 ReportEvents(unit, S2EVENT_ONLINE, base);
636 return;
641 /****i* intelpro100.device/GoOffline ***************************************
643 * NAME
644 * GoOffline -- Put the adpater offline.
646 * SYNOPSIS
647 * GoOffline(unit)
649 * VOID GoOffline(struct DevUnit *);
651 * INPUTS
652 * unit - A unit of this device.
654 * RESULT
655 * None.
657 ****************************************************************************
661 VOID GoOffline(struct DevUnit *unit, struct DevBase *base)
663 unit->flags &= ~UNITF_ONLINE;
665 if((unit->flags & UNITF_HAVEADAPTER) != 0)
667 /* Stop reception */
669 unit->LEWordOut(unit->card, PROREG_COMMAND, PRO_RUCMD_ABORT);
671 /* Update statistics */
673 UpdateStats(unit, base);
676 /* Flush pending read and write requests */
678 FlushUnit(unit, WRITE_QUEUE, S2ERR_OUTOFSERVICE, base);
680 /* Report Offline event and return */
682 ReportEvents(unit, S2EVENT_OFFLINE, base);
683 return;
688 /****i* intelpro100.device/AddMulticastRange *******************************
690 * NAME
691 * AddMulticastRange
693 * SYNOPSIS
694 * success = AddMulticastRange(unit, lower_bound, upper_bound)
696 * BOOL AddMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
698 ****************************************************************************
702 BOOL AddMulticastRange(struct DevUnit *unit, const UBYTE *lower_bound,
703 const UBYTE *upper_bound, struct DevBase *base)
705 struct AddressRange *range;
706 ULONG lower_bound_left, upper_bound_left;
707 UWORD lower_bound_right, upper_bound_right;
709 lower_bound_left = BELong(*((ULONG *)lower_bound));
710 lower_bound_right = BEWord(*((UWORD *)(lower_bound + 4)));
711 upper_bound_left = BELong(*((ULONG *)upper_bound));
712 upper_bound_right = BEWord(*((UWORD *)(upper_bound + 4)));
714 range = FindMulticastRange(unit, lower_bound_left, lower_bound_right,
715 upper_bound_left, upper_bound_right, base);
717 if(range != NULL)
718 range->add_count++;
719 else
721 range = AllocMem(sizeof(struct AddressRange), MEMF_PUBLIC);
722 if(range != NULL)
724 range->lower_bound_left = lower_bound_left;
725 range->lower_bound_right = lower_bound_right;
726 range->upper_bound_left = upper_bound_left;
727 range->upper_bound_right = upper_bound_right;
728 range->add_count = 1;
730 Disable();
731 AddTail((APTR)&unit->multicast_ranges, (APTR)range);
732 Enable();
736 return range != NULL;
741 /****i* intelpro100.device/RemMulticastRange *******************************
743 * NAME
744 * RemMulticastRange
746 * SYNOPSIS
747 * found = RemMulticastRange(unit, lower_bound, upper_bound)
749 * BOOL RemMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
751 ****************************************************************************
755 BOOL RemMulticastRange(struct DevUnit *unit, const UBYTE *lower_bound,
756 const UBYTE *upper_bound, struct DevBase *base)
758 struct AddressRange *range;
759 ULONG lower_bound_left, upper_bound_left;
760 UWORD lower_bound_right, upper_bound_right;
762 lower_bound_left = BELong(*((ULONG *)lower_bound));
763 lower_bound_right = BEWord(*((UWORD *)(lower_bound + 4)));
764 upper_bound_left = BELong(*((ULONG *)upper_bound));
765 upper_bound_right = BEWord(*((UWORD *)(upper_bound + 4)));
767 range = FindMulticastRange(unit, lower_bound_left, lower_bound_right,
768 upper_bound_left, upper_bound_right, base);
770 if(range != NULL)
772 if(--range->add_count == 0)
774 Disable();
775 Remove((APTR)range);
776 Enable();
777 FreeMem(range, sizeof(struct AddressRange));
781 return range != NULL;
786 /****i* intelpro100.device/FindMulticastRange ******************************
788 * NAME
789 * FindMulticastRange
791 * SYNOPSIS
792 * range = FindMulticastRange(unit, lower_bound_left,
793 * lower_bound_right, upper_bound_left, upper_bound_right)
795 * struct AddressRange *FindMulticastRange(struct DevUnit *, ULONG,
796 * UWORD, ULONG, UWORD);
798 ****************************************************************************
802 static struct AddressRange *FindMulticastRange(struct DevUnit *unit,
803 ULONG lower_bound_left, UWORD lower_bound_right, ULONG upper_bound_left,
804 UWORD upper_bound_right, struct DevBase *base)
806 struct AddressRange *range, *tail;
807 BOOL found = FALSE;
809 range = (APTR)unit->multicast_ranges.mlh_Head;
810 tail = (APTR)&unit->multicast_ranges.mlh_Tail;
812 while((range != tail) && !found)
814 if((lower_bound_left == range->lower_bound_left) &&
815 (lower_bound_right == range->lower_bound_right) &&
816 (upper_bound_left == range->upper_bound_left) &&
817 (upper_bound_right == range->upper_bound_right))
818 found = TRUE;
819 else
820 range = (APTR)range->node.mln_Succ;
823 if(!found)
824 range = NULL;
826 return range;
831 /****i* intelpro100.device/SetMulticast ************************************
833 * NAME
834 * SetMulticast
836 * SYNOPSIS
837 * SetMulticast(unit)
839 * VOID SetMulticast(struct DevUnit *);
841 * FUNCTION
842 * Fills in the unit's multicast list TCB, but does not send it to the
843 * device.
845 ****************************************************************************
849 static VOID SetMulticast(struct DevUnit *unit, struct DevBase *base)
851 ULONG *tcb, address_left;
852 UWORD address_right, i = 0, *p;
853 struct AddressRange *range, *tail;
854 BOOL range_ended;
856 tcb = unit->multicast_cb;
858 if((unit->flags & UNITF_PROM) == 0)
860 /* Fill in multicast list */
862 range = (APTR)unit->multicast_ranges.mlh_Head;
863 tail = (APTR)&unit->multicast_ranges.mlh_Tail;
864 p = (UWORD *)(tcb + PROCB_COUNT);
865 p++;
866 while(range != tail && i < MAX_MCAST_ENTRIES)
868 address_left = range->lower_bound_left;
869 address_right = range->lower_bound_right;
870 range_ended = FALSE;
872 while(!range_ended && i++ < MAX_MCAST_ENTRIES)
874 *p++ = MakeBEWord((UWORD)(address_left >> 16));
875 *p++ = MakeBEWord((UWORD)(address_left));
876 *p++ = MakeBEWord((UWORD)(address_right));
878 if(address_left == range->upper_bound_left &&
879 address_right == range->upper_bound_right)
881 range_ended = TRUE;
883 if(++address_right == 0)
884 address_left++;
887 if(range_ended)
888 range = (APTR)range->node.mln_Succ;
890 p = (UWORD *)(tcb + PROCB_COUNT);
891 *p = MakeLEWord(ETH_ADDRESSSIZE * i);
893 /* Accept all multicasts if there are too many addresses */
895 if(range != tail)
896 unit->flags |= UNITF_ALLMCAST;
897 else
898 unit->flags &= ~UNITF_ALLMCAST;
901 return;
906 /****i* intelpro100.device/FindTypeStats ***********************************
908 * NAME
909 * FindTypeStats
911 * SYNOPSIS
912 * stats = FindTypeStats(unit, list,
913 * packet_type)
915 * struct TypeStats *FindTypeStats(struct DevUnit *, struct MinList *,
916 * ULONG);
918 ****************************************************************************
922 struct TypeStats *FindTypeStats(struct DevUnit *unit, struct MinList *list,
923 ULONG packet_type, struct DevBase *base)
925 struct TypeStats *stats, *tail;
926 BOOL found = FALSE;
928 stats = (APTR)list->mlh_Head;
929 tail = (APTR)&list->mlh_Tail;
931 while((stats != tail) && !found)
933 if(stats->packet_type == packet_type)
934 found = TRUE;
935 else
936 stats = (APTR)stats->node.mln_Succ;
939 if(!found)
940 stats = NULL;
942 return stats;
947 /****i* intelpro100.device/FlushUnit ***************************************
949 * NAME
950 * FlushUnit
952 * SYNOPSIS
953 * FlushUnit(unit, last_queue, error)
955 * VOID FlushUnit(struct DevUnit *, UBYTE, BYTE);
957 ****************************************************************************
961 VOID FlushUnit(struct DevUnit *unit, UBYTE last_queue, BYTE error,
962 struct DevBase *base)
964 struct IORequest *request;
965 UBYTE i;
966 struct Opener *opener, *tail;
968 /* Abort queued requests */
970 for(i = 0; i <= last_queue; i++)
972 while((request = (APTR)GetMsg(unit->request_ports[i])) != NULL)
974 request->io_Error = IOERR_ABORTED;
975 ReplyMsg((APTR)request);
979 #if 1
980 opener = (APTR)unit->openers.mlh_Head;
981 tail = (APTR)&unit->openers.mlh_Tail;
983 /* Flush every opener's read queue */
985 while(opener != tail)
987 while((request = (APTR)GetMsg(&opener->read_port)) != NULL)
989 request->io_Error = error;
990 ReplyMsg((APTR)request);
992 opener = (APTR)opener->node.mln_Succ;
995 #else
996 opener = request->ios2_BufferManagement;
997 while((request = (APTR)GetMsg(&opener->read_port)) != NULL)
999 request->io_Error = IOERR_ABORTED;
1000 ReplyMsg((APTR)request);
1002 #endif
1004 /* Return */
1006 return;
1011 /****i* intelpro100.device/StatusInt ***************************************
1013 * NAME
1014 * StatusInt
1016 * SYNOPSIS
1017 * finished = StatusInt(unit)
1019 * BOOL StatusInt(struct DevUnit *);
1021 * INPUTS
1022 * unit - A unit of this device.
1024 * RESULT
1025 * finished - Always FALSE.
1027 ****************************************************************************
1031 static BOOL StatusInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code))
1033 struct DevBase *base;
1034 UWORD ints;
1036 base = unit->device;
1037 ints = unit->ByteIn(unit->card, PROREG_INTSTATUS);
1039 if(ints != 0)
1041 /* Handle interrupts */
1043 if((ints & PROINTF_GENERAL) != 0)
1044 Cause(&unit->tx_end_int);
1045 if((ints & PROINTF_RXDONE) != 0)
1046 Cause(&unit->rx_int);
1048 /* Acknowledge all interrupts */
1050 unit->ByteOut(unit->card, PROREG_INTSTATUS, 0xff);
1053 return FALSE;
1058 /****i* intelpro100.device/RXInt *******************************************
1060 * NAME
1061 * RXInt
1063 * SYNOPSIS
1064 * RXInt(unit)
1066 * VOID RXInt(struct DevUnit *);
1068 * INPUTS
1069 * unit - A unit of this device.
1070 * int_code - Unused.
1072 * RESULT
1073 * None.
1075 ****************************************************************************
1079 static VOID RXInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code))
1081 UWORD packet_size;
1082 struct DevBase *base;
1083 BOOL is_orphan, accepted;
1084 ULONG rx_status_le, rx_info, packet_type, *rcb, *last_rcb, dma_size;
1085 UBYTE *buffer;
1086 struct IOSana2Req *request, *request_tail;
1087 struct Opener *opener, *opener_tail;
1088 struct TypeStats *tracker;
1090 base = unit->device;
1091 last_rcb = unit->last_rcb;
1092 rcb = (ULONG *)LELong(last_rcb[PROCB_NEXT]);
1094 dma_size = RCB_SIZE;
1095 CachePostDMA(rcb, &dma_size, 0);
1096 while(((rx_status_le = rcb[PROCB_CONTROL])
1097 & MakeLELong(PROCB_CONTROLF_DONE)) != 0)
1099 if((rx_status_le & MakeLELong(PROCB_CONTROLF_OK)) != 0)
1101 is_orphan = TRUE;
1102 rx_info = LELong(rcb[PROCB_RXINFO]);
1103 packet_size = rx_info & PROCB_RXINFOF_FRAMESIZE;
1104 buffer = (UBYTE *)(rcb + PROCB_BUFFER);
1106 if(AddressFilter(unit, buffer + ETH_PACKET_DEST, base))
1108 packet_type = BEWord(*((UWORD *)(buffer + ETH_PACKET_TYPE)));
1110 opener = (APTR)unit->openers.mlh_Head;
1111 opener_tail = (APTR)&unit->openers.mlh_Tail;
1113 /* Offer packet to every opener */
1115 while(opener != opener_tail)
1117 request = (APTR)opener->read_port.mp_MsgList.lh_Head;
1118 request_tail = (APTR)&opener->read_port.mp_MsgList.lh_Tail;
1119 accepted = FALSE;
1121 /* Offer packet to each request until it's accepted */
1123 while((request != request_tail) && !accepted)
1125 if(request->ios2_PacketType == packet_type)
1127 CopyPacket(unit, request, packet_size, packet_type,
1128 buffer, base);
1129 accepted = TRUE;
1131 request =
1132 (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
1135 if(accepted)
1136 is_orphan = FALSE;
1137 opener = (APTR)opener->node.mln_Succ;
1140 /* If packet was unwanted, give it to S2_READORPHAN request */
1142 if(is_orphan)
1144 unit->stats.UnknownTypesReceived++;
1145 if(!IsMsgPortEmpty(unit->request_ports[ADOPT_QUEUE]))
1147 CopyPacket(unit,
1148 (APTR)unit->request_ports[ADOPT_QUEUE]->
1149 mp_MsgList.lh_Head, packet_size, packet_type, buffer,
1150 base);
1154 /* Update remaining statistics */
1156 tracker =
1157 FindTypeStats(unit, &unit->type_trackers, packet_type, base);
1158 if(tracker != NULL)
1160 tracker->stats.PacketsReceived++;
1161 tracker->stats.BytesReceived += packet_size;
1165 else
1167 unit->stats.BadData++;
1168 ReportEvents(unit, S2EVENT_ERROR | S2EVENT_HARDWARE | S2EVENT_RX,
1169 base);
1172 rcb[PROCB_CONTROL] = MakeLELong(PROCB_CONTROLF_SUSPEND);
1173 rcb[PROCB_RXINFO] =
1174 MakeLELong(ETH_MAXPACKETSIZE << PROCB_RXINFOB_BUFFERSIZE);
1176 /* Clear suspend flag from previous CB without touching bits that
1177 adapter may be writing to; and resume execution */
1179 *(((UBYTE *)last_rcb + PROCB_CONTROL) + 3) = 0;
1180 dma_size = RCB_SIZE;
1181 CachePreDMA(last_rcb, &dma_size, 0);
1182 if(TRUE)
1183 unit->LEWordOut(unit->card, PROREG_COMMAND, PRO_RUCMD_RESUME);
1185 last_rcb = rcb;
1186 rcb = (ULONG *)LELong(rcb[PROCB_NEXT]);
1189 /* Return */
1191 unit->last_rcb = last_rcb;
1192 return;
1197 /****i* intelpro100.device/CopyPacket **************************************
1199 * NAME
1200 * CopyPacket
1202 * SYNOPSIS
1203 * CopyPacket(unit, request, packet_size, packet_type,
1204 * buffer)
1206 * VOID CopyPacket(struct DevUnit *, struct IOSana2Req *, UWORD, UWORD,
1207 * UBYTE *);
1209 ****************************************************************************
1213 static VOID CopyPacket(struct DevUnit *unit, struct IOSana2Req *request,
1214 UWORD packet_size, UWORD packet_type, UBYTE *buffer,
1215 struct DevBase *base)
1217 struct Opener *opener;
1218 BOOL filtered = FALSE;
1220 /* Set multicast and broadcast flags */
1222 request->ios2_Req.io_Flags &= ~(SANA2IOF_BCAST | SANA2IOF_MCAST);
1223 if((*((ULONG *)(buffer + ETH_PACKET_DEST)) == 0xffffffff) &&
1224 (*((UWORD *)(buffer + ETH_PACKET_DEST + 4)) == 0xffff))
1225 request->ios2_Req.io_Flags |= SANA2IOF_BCAST;
1226 else if((buffer[ETH_PACKET_DEST] & 0x1) != 0)
1227 request->ios2_Req.io_Flags |= SANA2IOF_MCAST;
1229 /* Set source and destination addresses and packet type */
1231 CopyMem(buffer + ETH_PACKET_SOURCE, request->ios2_SrcAddr,
1232 ETH_ADDRESSSIZE);
1233 CopyMem(buffer + ETH_PACKET_DEST, request->ios2_DstAddr,
1234 ETH_ADDRESSSIZE);
1235 request->ios2_PacketType = packet_type;
1237 /* Adjust for cooked packet request */
1239 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1241 packet_size -= ETH_PACKET_DATA;
1242 buffer += ETH_PACKET_DATA;
1244 #ifdef USE_HACKS
1245 else
1246 packet_size += 4; /* Needed for Shapeshifter & Fusion */
1247 #endif
1248 request->ios2_DataLength = packet_size;
1250 /* Filter packet */
1252 opener = request->ios2_BufferManagement;
1253 if((request->ios2_Req.io_Command == CMD_READ) &&
1254 (opener->filter_hook != NULL))
1255 if(!CallHookPkt(opener->filter_hook, request, buffer))
1256 filtered = TRUE;
1258 if(!filtered)
1260 /* Copy packet into opener's buffer and reply packet */
1262 if(!opener->rx_function(request->ios2_Data, buffer, packet_size))
1264 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
1265 request->ios2_WireError = S2WERR_BUFF_ERROR;
1266 ReportEvents(unit,
1267 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF | S2EVENT_RX,
1268 base);
1270 Remove((APTR)request);
1271 ReplyMsg((APTR)request);
1274 return;
1279 /****i* intelpro100.device/AddressFilter ***********************************
1281 * NAME
1282 * AddressFilter
1284 * SYNOPSIS
1285 * accept = AddressFilter(unit, address)
1287 * BOOL AddressFilter(struct DevUnit *, UBYTE *);
1289 ****************************************************************************
1293 static BOOL AddressFilter(struct DevUnit *unit, UBYTE *address,
1294 struct DevBase *base)
1296 struct AddressRange *range, *tail;
1297 BOOL accept = TRUE;
1298 ULONG address_left;
1299 UWORD address_right;
1301 /* Check whether address is unicast/broadcast or multicast */
1303 address_left = BELong(*((ULONG *)address));
1304 address_right = BEWord(*((UWORD *)(address + 4)));
1306 if((address_left & 0x01000000) != 0 &&
1307 !(address_left == 0xffffffff && address_right == 0xffff))
1309 /* Check if this multicast address is wanted */
1311 range = (APTR)unit->multicast_ranges.mlh_Head;
1312 tail = (APTR)&unit->multicast_ranges.mlh_Tail;
1313 accept = FALSE;
1315 while((range != tail) && !accept)
1317 if(((address_left > range->lower_bound_left) ||
1318 (address_left == range->lower_bound_left) &&
1319 (address_right >= range->lower_bound_right)) &&
1320 ((address_left < range->upper_bound_left) ||
1321 (address_left == range->upper_bound_left) &&
1322 (address_right <= range->upper_bound_right)))
1323 accept = TRUE;
1324 range = (APTR)range->node.mln_Succ;
1327 if(!accept)
1328 unit->special_stats[S2SS_ETHERNET_BADMULTICAST & 0xffff]++;
1331 return accept;
1336 /****i* intelpro100.device/TXInt *******************************************
1338 * NAME
1339 * TXInt
1341 * SYNOPSIS
1342 * TXInt(unit)
1344 * VOID TXInt(struct DevUnit *);
1346 * INPUTS
1347 * unit - A unit of this device.
1348 * int_code - Unused.
1350 * RESULT
1351 * None.
1353 ****************************************************************************
1355 * Note that when the CU is resumed, the adapter examines the suspend flag
1356 * again in the command that caused the suspension. If the flag is set, the
1357 * CU will be suspended without executing any new commands. This means that
1358 * all TCBs can't be in use at the same time, and the dynamically inserted
1359 * multicast list command can't have its suspend flag set.
1363 static VOID TXInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code))
1365 struct DevBase *base;
1366 UWORD packet_size, data_size, *p, *q, i;
1367 struct IOSana2Req *request;
1368 BOOL proceed = TRUE;
1369 struct Opener *opener;
1370 ULONG wire_error, *tcb, *last_tcb, *mcast_cb, *fragment, dma_size,
1371 action;
1372 UBYTE *(*dma_tx_function)(REG(a0, APTR));
1373 BYTE error;
1374 UBYTE *buffer;
1375 struct MsgPort *port;
1377 base = unit->device;
1378 port = unit->request_ports[WRITE_QUEUE];
1380 while(proceed && !IsMsgPortEmpty(port))
1382 last_tcb = unit->last_tcb;
1383 tcb = (ULONG *)LELong(last_tcb[PROCB_NEXT]);
1385 /* Ensure there are at least two free CBs available (two are needed
1386 for setting the multicast filter) and that neither the TX nor the
1387 multicast buffer is currently in use */
1389 if((ULONG *)LELong(((ULONG *)LELong(tcb[PROCB_NEXT]))[PROCB_NEXT])
1390 != unit->first_tcb
1391 && (unit->flags & (UNITF_TXBUFFERINUSE | UNITF_MCASTBUFFERINUSE))
1392 == 0)
1394 error = 0;
1395 request = (APTR)GetMsg(port);
1396 request->ios2_Req.io_Message.mn_Node.ln_Type = NT_FREEMSG;
1398 switch(request->ios2_Req.io_Command)
1400 case CMD_WRITE:
1401 case S2_MULTICAST:
1402 case S2_BROADCAST:
1403 action = PROACT_TX;
1404 break;
1405 default:
1406 action = PROACT_CONFIGURE;
1409 if(action == PROACT_TX)
1411 /* Handle TX request */
1413 data_size = packet_size = request->ios2_DataLength;
1415 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1416 packet_size += ETH_HEADERSIZE;
1418 /* Write packet preamble */
1420 tcb[PROCB_CONTROL] =
1421 MakeLELong(PROACT_TX | PROCB_CONTROLF_SUSPEND
1422 | PROCB_CONTROLF_INT | PROCB_CONTROLF_FLEXIBLE);
1423 fragment = tcb + PROCB_EXTFRAGS;
1424 tcb[PROCB_FRAGMENTS] = MakeLELong((ULONG)fragment);
1426 /* Write packet header */
1428 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1430 buffer = (UBYTE *)(tcb + PROCB_EXTBUFFER);
1431 tcb[PROCB_TXINFO] =
1432 MakeLELong(2 << PROCB_TXINFOB_FRAGCOUNT
1433 | 1 << PROCB_TXINFOB_THRESHOLD
1434 | PROCB_TXINFOF_EOF);
1435 fragment[PROFRAG_ADDR] = MakeLELong((ULONG)buffer);
1436 fragment[PROFRAG_LEN] = MakeLELong(ETH_HEADERSIZE);
1438 p = (UWORD *)buffer;
1439 for(i = 0, q = (UWORD *)request->ios2_DstAddr;
1440 i < ETH_ADDRESSSIZE / 2; i++)
1441 *p++ = *q++;
1442 for(i = 0, q = (UWORD *)unit->address;
1443 i < ETH_ADDRESSSIZE / 2; i++)
1444 *p++ = *q++;
1445 *p++ = MakeBEWord(request->ios2_PacketType);
1446 buffer = (UBYTE *)p;
1448 fragment += PRO_FRAGLEN;
1450 else
1452 tcb[PROCB_TXINFO] =
1453 MakeLELong(1 << PROCB_TXINFOB_FRAGCOUNT
1454 | 1 << PROCB_TXINFOB_THRESHOLD
1455 | PROCB_TXINFOF_EOF);
1458 /* Get packet data */
1460 opener = (APTR)request->ios2_BufferManagement;
1461 dma_tx_function = opener->dma_tx_function;
1462 if(dma_tx_function != NULL)
1463 buffer = dma_tx_function(request->ios2_Data);
1464 else
1465 buffer = NULL;
1467 if(buffer == NULL)
1469 buffer = unit->tx_buffer;
1470 if(opener->tx_function(buffer, request->ios2_Data,
1471 data_size))
1473 unit->flags |= UNITF_TXBUFFERINUSE;
1475 else
1477 error = S2ERR_NO_RESOURCES;
1478 wire_error = S2WERR_BUFF_ERROR;
1479 ReportEvents(unit,
1480 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF
1481 | S2EVENT_TX, base);
1485 /* Put pointer to packet data into descriptor */
1487 if(error == 0)
1489 dma_size = data_size;
1490 CachePreDMA(buffer, &dma_size, DMA_ReadFromRAM);
1491 fragment[PROFRAG_ADDR] = MakeLELong((ULONG)buffer);
1492 fragment[PROFRAG_LEN] = MakeLELong(data_size);
1495 else
1497 /* Update multicast reception filter */
1499 SetMulticast(unit, base);
1500 if((unit->flags & UNITF_ALLMCAST) == 0)
1502 tcb[PROCB_CONTROL] = MakeLELong(PROACT_NOP);
1503 mcast_cb = unit->multicast_cb;
1504 mcast_cb[PROCB_CONTROL] = MakeLELong(PROACT_SETMCAST);
1505 mcast_cb[PROCB_NEXT] = tcb[PROCB_NEXT];
1506 tcb[PROCB_NEXT] = MakeLELong((ULONG)mcast_cb);
1507 unit->link_cb = tcb;
1508 tcb = (ULONG *)LELong(mcast_cb[PROCB_NEXT]);
1509 tcb[PROCB_CONTROL] = MakeLELong(PROACT_CONFIGURE
1510 | PROCB_CONTROLF_SUSPEND | PROCB_CONTROLF_INT);
1511 FillConfigData(unit, tcb, base);
1512 unit->flags |= UNITF_MCASTBUFFERINUSE;
1514 else
1516 tcb[PROCB_CONTROL] = MakeLELong(PROACT_CONFIGURE
1517 | PROCB_CONTROLF_SUSPEND | PROCB_CONTROLF_INT);
1518 FillConfigData(unit, tcb, base);
1522 if(error == 0)
1524 /* Clear suspend flag from previous CB without touching bits
1525 that adapter may be writing to; and resume execution */
1527 if(last_tcb[PROCB_CONTROL] != 0)
1528 *(((UBYTE *)last_tcb + PROCB_CONTROL) + 3) =
1529 PROCB_CONTROLF_INT >> 24;
1530 dma_size = TCB_SIZE * TX_SLOT_COUNT;
1531 CachePreDMA(unit->tcbs, &dma_size, 0);
1532 dma_size = MCAST_CB_SIZE;
1533 CachePreDMA(unit->multicast_cb, &dma_size, 0);
1534 if((unit->ByteIn(unit->card, PROREG_STATUS)
1535 & PROREG_STATUSF_CUSTATE)
1536 == (PRO_CUSTATE_SUSPENDED << PROREG_STATUSB_CUSTATE))
1538 unit->LEWordOut(unit->card, PROREG_COMMAND,
1539 PRO_CUCMD_RESUME);
1542 AddTail((APTR)&unit->tx_requests, (APTR)request);
1543 unit->last_tcb = tcb;
1545 else
1547 /* Return failed request */
1549 request->ios2_Req.io_Error = error;
1550 request->ios2_WireError = wire_error;
1551 ReplyMsg((APTR)request);
1552 tcb[PROCB_CONTROL] = 0;
1555 else
1556 proceed = FALSE;
1559 if(proceed)
1560 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
1561 else
1562 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_IGNORE;
1564 return;
1569 /****i* intelpro100.device/TXEndInt ****************************************
1571 * NAME
1572 * TXEndInt
1574 * SYNOPSIS
1575 * TXEndInt(unit)
1577 * VOID TXEndInt(struct DevUnit *);
1579 * INPUTS
1580 * unit - A unit of this device.
1581 * int_code - Unused.
1583 * RESULT
1584 * None.
1586 ****************************************************************************
1588 * It appears to be safe to assume that there will always be at least one
1589 * completed packet whenever this interrupt is called.
1593 static VOID TXEndInt(REG(a1, struct DevUnit *unit), REG(a5, APTR int_code))
1595 UWORD data_size, packet_size;
1596 UBYTE *buffer;
1597 struct DevBase *base;
1598 struct IOSana2Req *request;
1599 ULONG *tcb, *fragment, dma_size, action;
1600 struct TypeStats *tracker;
1602 /* Retire sent packets and configuration commands */
1604 base = unit->device;
1605 dma_size = TCB_SIZE * TX_SLOT_COUNT;
1606 CachePostDMA(unit->tcbs, &dma_size, 0);
1607 dma_size = MCAST_CB_SIZE;
1608 CachePostDMA(unit->multicast_cb, &dma_size, 0);
1610 for(tcb = unit->first_tcb;
1611 (tcb[PROCB_CONTROL] & MakeLELong(PROCB_CONTROLF_DONE)) != 0;
1612 tcb = (ULONG *)LELong(tcb[PROCB_NEXT]))
1614 action = LELong(tcb[PROCB_CONTROL]) & PROCB_CONTROLF_ACTION;
1616 if(action == PROACT_TX || action == PROACT_CONFIGURE
1617 && (unit->link_cb != NULL
1618 || (tcb[PROCB_CF5] & PROCB_CF5F_ALLMCAST) != 0))
1620 request = (APTR)RemHead((APTR)&unit->tx_requests);
1622 if(action == PROACT_TX)
1624 /* Mark end of DMA */
1626 data_size = packet_size = request->ios2_DataLength;
1627 fragment = (ULONG *)LELong(tcb[PROCB_FRAGMENTS]);
1629 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1631 packet_size += ETH_HEADERSIZE;
1632 fragment += PRO_FRAGLEN;
1635 buffer = (UBYTE *)LELong(fragment[PROFRAG_ADDR]);
1636 dma_size = data_size;
1637 CachePostDMA(buffer, &dma_size, DMA_ReadFromRAM);
1639 /* Check if unit's buffer is now free */
1641 if(buffer == unit->tx_buffer)
1642 unit->flags &= ~UNITF_TXBUFFERINUSE;
1644 /* Update statistics */
1646 tracker = FindTypeStats(unit, &unit->type_trackers,
1647 request->ios2_PacketType, base);
1648 if(tracker != NULL)
1650 tracker->stats.PacketsSent++;
1651 tracker->stats.BytesSent += packet_size;
1654 else if(action == PROACT_CONFIGURE)
1656 /* Mark end of multicast update */
1658 if(unit->link_cb != NULL)
1660 unit->link_cb[PROCB_NEXT] = MakeLELong((ULONG)tcb);
1661 unit->flags &= ~UNITF_MCASTBUFFERINUSE;
1662 unit->link_cb = NULL;
1666 /* Reply request */
1668 request->ios2_Req.io_Error = 0;
1669 ReplyMsg((APTR)request);
1672 /* Mark CB as unused/clear suspend flag */
1674 tcb[PROCB_CONTROL] = 0;
1677 dma_size = TCB_SIZE * TX_SLOT_COUNT;
1678 CachePreDMA(unit->tcbs, &dma_size, 0);
1680 unit->first_tcb = tcb;
1682 /* Restart downloads if they had stopped */
1684 if(unit->request_ports[WRITE_QUEUE]->mp_Flags == PA_IGNORE)
1685 Cause(&unit->tx_int);
1687 return;
1692 /****i* intelpro100.device/UpdateStats *************************************
1694 * NAME
1695 * UpdateStats
1697 * SYNOPSIS
1698 * UpdateStats(unit)
1700 * VOID UpdateStats(struct DevUnit *);
1702 * INPUTS
1703 * unit - A unit of this device.
1705 * RESULT
1706 * None.
1708 ****************************************************************************
1712 VOID UpdateStats(struct DevUnit *unit, struct DevBase *base)
1714 ULONG dma_size, *buffer;
1716 buffer = unit->stats_buffer;
1717 buffer[STAT_COUNT] = 0;
1718 dma_size = sizeof(ULONG) * STAT_COUNT;
1719 CachePreDMA(unit->stats_buffer, &dma_size, 0);
1720 unit->ByteOut(unit->card, PROREG_COMMAND, PRO_CUCMD_DUMPRESETSTATS);
1721 while(buffer[STAT_COUNT] != MakeLELong(0xa007))
1723 dma_size = sizeof(ULONG) * STAT_COUNT;
1724 CachePostDMA(unit->stats_buffer, &dma_size, 0);
1727 unit->stats.Overruns += LELong(buffer[PROSTAT_RXOVERRUNS]);
1728 unit->stats.PacketsSent += LELong(buffer[PROSTAT_TXFRAMESOK]);
1729 unit->stats.PacketsReceived += LELong(buffer[PROSTAT_RXFRAMESOK]);
1730 unit->special_stats[S2SS_ETHERNET_RETRIES & 0xffff] +=
1731 LELong(buffer[PROSTAT_FRAMESDEFERRED]);
1732 unit->special_stats[S2SS_ETHERNET_FIFO_UNDERRUNS & 0xffff] +=
1733 LELong(buffer[PROSTAT_TXUNDERRUNS]);
1735 return;
1740 /****i* intelpro100.device/ReportEvents ************************************
1742 * NAME
1743 * ReportEvents
1745 * SYNOPSIS
1746 * ReportEvents(unit, events)
1748 * VOID ReportEvents(struct DevUnit *, ULONG);
1750 * INPUTS
1751 * unit - A unit of this device.
1752 * events - A mask of events to report.
1754 * RESULT
1755 * None.
1757 ****************************************************************************
1761 static VOID ReportEvents(struct DevUnit *unit, ULONG events,
1762 struct DevBase *base)
1764 struct IOSana2Req *request, *tail, *next_request;
1765 struct List *list;
1767 list = &unit->request_ports[EVENT_QUEUE]->mp_MsgList;
1768 next_request = (APTR)list->lh_Head;
1769 tail = (APTR)&list->lh_Tail;
1771 Disable();
1772 while(next_request != tail)
1774 request = next_request;
1775 next_request = (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
1777 if((request->ios2_WireError & events) != 0)
1779 request->ios2_WireError = events;
1780 Remove((APTR)request);
1781 ReplyMsg((APTR)request);
1784 Enable();
1786 return;
1791 /****i* intelpro100.device/UnitTask ****************************************
1793 * NAME
1794 * UnitTask
1796 * SYNOPSIS
1797 * UnitTask()
1799 * VOID UnitTask();
1801 * FUNCTION
1802 * Completes deferred requests.
1804 ****************************************************************************
1808 #ifdef __MORPHOS__
1809 #undef UnitTask
1810 #endif
1812 static VOID UnitTask()
1814 struct Task *task;
1815 struct IORequest *request;
1816 struct DevUnit *unit;
1817 struct DevBase *base;
1818 struct MsgPort *general_port;
1819 ULONG signals, wait_signals, general_port_signal;
1821 /* Get parameters */
1823 task = AbsExecBase->ThisTask;
1824 unit = task->tc_UserData;
1825 base = unit->device;
1827 /* Activate general request port */
1829 general_port = unit->request_ports[GENERAL_QUEUE];
1830 general_port->mp_SigTask = task;
1831 general_port->mp_SigBit = AllocSignal(-1);
1832 general_port_signal = 1 << general_port->mp_SigBit;
1833 general_port->mp_Flags = PA_SIGNAL;
1835 /* Allocate a signal for notification of card removal */
1837 wait_signals = (1 << general_port->mp_SigBit);
1839 /* Tell ourselves to check port for old messages */
1841 Signal(task, general_port_signal);
1843 /* Infinite loop to service requests and signals */
1845 while(TRUE)
1847 signals = Wait(wait_signals);
1849 if((signals & general_port_signal) != 0)
1851 while((request = (APTR)GetMsg(general_port)) != NULL)
1853 /* Service the request as soon as the unit is free */
1855 ObtainSemaphore(&unit->access_lock);
1856 ServiceRequest((APTR)request, base);
1864 /****i* intelpro100.device/GetEEPROMAddressSize ****************************
1866 * NAME
1867 * GetEEPROMAddressSize
1869 * SYNOPSIS
1870 * size = GetEEPROMAddressSize(unit)
1872 * UWORD GetEEPROMAddressSize(struct DevUnit *);
1874 * INPUTS
1875 * unit - A unit of this device.
1877 * RESULT
1878 * size - Width of EEPROM addresses.
1880 ****************************************************************************
1882 * Although the manual doesn't make it explicit, chip select must be asserted
1883 * before setting any other bits, at least on the i82557.
1887 static UWORD GetEEPROMAddressSize(struct DevUnit *unit,
1888 struct DevBase *base)
1890 UWORD size;
1892 unit->LEWordOut(unit->card, PROREG_EEPROM, PROREG_EEPROMF_SELECT);
1893 WriteEEPROMBits(unit, 0x6, 3, base);
1894 for(size = 1; WriteEEPROMBit(unit, FALSE, base); size++);
1895 ReadEEPROMBits(unit, 16, base);
1896 unit->LEWordOut(unit->card, PROREG_EEPROM, 0);
1897 BusyMicroDelay(1, base);
1899 return size;
1904 /****i* intelpro100.device/ReadEEPROM **************************************
1906 * NAME
1907 * ReadEEPROM -- Read an EEPROM location.
1909 * SYNOPSIS
1910 * value = ReadEEPROM(unit, index)
1912 * UWORD ReadEEPROM(struct DevUnit *, UWORD);
1914 * INPUTS
1915 * unit - A unit of this device.
1916 * index - Offset within EEPROM.
1918 * RESULT
1919 * value - Contents of specified EEPROM location.
1921 ****************************************************************************
1925 static UWORD ReadEEPROM(struct DevUnit *unit, UWORD index,
1926 struct DevBase *base)
1928 UWORD value;
1930 unit->LEWordOut(unit->card, PROREG_EEPROM, PROREG_EEPROMF_SELECT);
1931 WriteEEPROMBits(unit, 0x6, 3, base);
1932 WriteEEPROMBits(unit, index, unit->eeprom_addr_size, base);
1933 value = ReadEEPROMBits(unit, 16, base);
1934 unit->LEWordOut(unit->card, PROREG_EEPROM, 0);
1935 BusyMicroDelay(1, base);
1937 return value;
1942 /****i* intelpro100.device/ReadEEPROMBits **********************************
1944 * NAME
1945 * ReadEEPROMBits -- Read a stream of bits from the EEPROM.
1947 * SYNOPSIS
1948 * value = ReadEEPROMBits(unit, count)
1950 * ULONG ReadEEPROMBits(struct DevUnit *, UBYTE);
1952 * INPUTS
1953 * unit - A unit of this device.
1954 * count - Number of bits to be read.
1956 * RESULT
1957 * value - The bits read from the EEPROM, right-justified.
1959 ****************************************************************************
1963 static ULONG ReadEEPROMBits(struct DevUnit *unit, UBYTE count,
1964 struct DevBase *base)
1966 UBYTE i;
1967 ULONG value = 0;
1969 for(i = 0; i < count; i++)
1971 value <<= 1;
1972 if(ReadEEPROMBit(unit, base))
1973 value |= 0x1;
1976 return value;
1980 /****i* intelpro100.device/WriteEEPROMBits *********************************
1982 * NAME
1983 * WriteEEPROMBits -- Write a stream of bits to the EEPROM.
1985 * SYNOPSIS
1986 * WriteEEPROMBits(unit, value, count)
1988 * VOID WriteEEPROMBits(struct DevUnit *, ULONG, UBYTE);
1990 * INPUTS
1991 * unit - A unit of this device.
1992 * value - The bits to write to the EEPROM, right-justified.
1993 * count - Number of bits to be Write.
1995 * RESULT
1996 * None.
1998 ****************************************************************************
2002 static VOID WriteEEPROMBits(struct DevUnit *unit, ULONG value, UBYTE count,
2003 struct DevBase *base)
2005 ULONG mask;
2007 for(mask = 1 << (count - 1); mask != 0; mask >>= 1)
2008 WriteEEPROMBit(unit, (value & mask) != 0, base);
2010 return;
2015 /****i* intelpro100.device/ReadEEPROMBit ***********************************
2017 * NAME
2018 * ReadEEPROMBit -- Read a bit from the EEPROM.
2020 * SYNOPSIS
2021 * value = ReadEEPROMBit(unit)
2023 * BOOL ReadEEPROMBit(struct DevUnit *);
2025 * INPUTS
2026 * unit - A unit of this device.
2028 * RESULT
2029 * value - True for one, false for zero.
2031 ****************************************************************************
2035 static BOOL ReadEEPROMBit(struct DevUnit *unit, struct DevBase *base)
2037 BOOL is_one;
2039 unit->LEWordOut(unit->card, PROREG_EEPROM,
2040 PROREG_EEPROMF_SELECT | PROREG_EEPROMF_CLK);
2041 BusyMicroDelay(2, base);
2042 is_one =
2043 (unit->LEWordIn(unit->card, PROREG_EEPROM) & PROREG_EEPROMF_DATAIN)
2044 != 0;
2045 unit->LEWordOut(unit->card, PROREG_EEPROM, PROREG_EEPROMF_SELECT);
2046 BusyMicroDelay(2, base);
2048 return is_one;
2053 /****i* intelpro100.device/WriteEEPROMBit **********************************
2055 * NAME
2056 * WriteEEPROMBit -- Write a bit to the EEPROM.
2058 * SYNOPSIS
2059 * data_in = WriteEEPROMBit(unit, is_one)
2061 * BOOL WriteEEPROMBit(struct DevUnit *, BOOL);
2063 * INPUTS
2064 * unit - A unit of this device.
2065 * is_one - True if a set bit should be written.
2067 * RESULT
2068 * data_in - True if data-in bit is set.
2070 ****************************************************************************
2074 static BOOL WriteEEPROMBit(struct DevUnit *unit, BOOL is_one,
2075 struct DevBase *base)
2077 UWORD data_out;
2079 if(is_one)
2080 data_out = PROREG_EEPROMF_DATAOUT;
2081 else
2082 data_out = 0;
2084 unit->LEWordOut(unit->card, PROREG_EEPROM,
2085 PROREG_EEPROMF_SELECT | data_out);
2086 unit->LEWordOut(unit->card, PROREG_EEPROM,
2087 PROREG_EEPROMF_SELECT | PROREG_EEPROMF_CLK | data_out);
2088 BusyMicroDelay(2, base);
2089 unit->LEWordOut(unit->card, PROREG_EEPROM,
2090 PROREG_EEPROMF_SELECT | data_out);
2091 BusyMicroDelay(2, base);
2093 return
2094 (unit->LEWordIn(unit->card, PROREG_EEPROM) & PROREG_EEPROMF_DATAIN)
2095 != 0;
2100 /****i* intelpro100.device/ReadMII *****************************************
2102 * NAME
2103 * ReadMII -- Read a register in an MII PHY.
2105 * SYNOPSIS
2106 * value = ReadMII(unit, phy_no, reg_no)
2108 * UWORD ReadMII(struct DevUnit *, UWORD, UWORD);
2110 * INPUTS
2111 * unit - A unit of this device.
2112 * phy_no - Index of PHY to use.
2113 * reg_no - MII register to read.
2115 * RESULT
2116 * value - Value read from MII register.
2118 ****************************************************************************
2122 static UWORD ReadMII(struct DevUnit *unit, UWORD phy_no, UWORD reg_no,
2123 struct DevBase *base)
2125 ULONG value;
2127 unit->LELongOut(unit->card, PROREG_MIICONTROL,
2128 2 << PROREG_MIICONTROLB_CMD
2129 | phy_no << PROREG_MIICONTROLB_PHYNO
2130 | reg_no << PROREG_MIICONTROLB_REGNO);
2132 value = unit->LELongIn(unit->card, PROREG_MIICONTROL);
2133 while((value & PROREG_MIICONTROLF_READY) == 0);
2135 return value & PROREG_MIICONTROLF_DATA;
2140 /****i* intelpro100.device/WriteMII ****************************************
2142 * NAME
2143 * WriteMII -- Write to a register in an MII PHY.
2145 * SYNOPSIS
2146 * WriteMII(unit, phy_no, reg_no, value)
2148 * VOID WriteMII(struct DevUnit *, UWORD, UWORD, UWORD);
2150 * INPUTS
2151 * unit - A unit of this device.
2152 * phy_no - Index of PHY to use.
2153 * reg_no - MII register to write to.
2154 * value - Value to write to MII register.
2156 * RESULT
2157 * None.
2159 ****************************************************************************
2163 static VOID WriteMII(struct DevUnit *unit, UWORD phy_no, UWORD reg_no,
2164 UWORD value, struct DevBase *base)
2166 unit->LELongOut(unit->card, PROREG_MIICONTROL,
2167 1 << PROREG_MIICONTROLB_CMD
2168 | phy_no << PROREG_MIICONTROLB_PHYNO
2169 | reg_no << PROREG_MIICONTROLB_REGNO
2170 | value);
2171 while
2174 unit->LELongIn(unit->card, PROREG_MIICONTROL)
2175 & PROREG_MIICONTROLF_READY
2177 == 0
2180 return;
2185 /****i* prism2.device/BusyMicroDelay ***************************************
2187 * NAME
2188 * BusyMilliDelay - Busy-wait for specified number of microseconds.
2190 * SYNOPSIS
2191 * BusyMilliDelay(micros)
2193 * VOID BusyMilliDelay(ULONG);
2195 ****************************************************************************
2199 #if 1
2200 static VOID BusyMicroDelay(ULONG micros, struct DevBase *base)
2202 struct timeval time, end_time;
2204 GetSysTime(&end_time);
2205 time.tv_secs = 0;
2206 time.tv_micro = micros;
2207 AddTime(&end_time, &time);
2209 while(CmpTime(&end_time, &time) < 0)
2210 GetSysTime(&time);
2212 return;
2216 #else
2217 static VOID BusyMicroDelay(ULONG micros, struct DevBase *base)
2219 struct EClockVal time, end_time;
2220 ULONG rate;
2222 rate = ReadEClock(&time);
2223 end_time.ev_hi = time.ev_hi;
2224 end_time.ev_lo = time.ev_lo + (micros * rate + 1) / 1000000;
2225 if(end_time.ev_lo < time.ev_lo)
2226 end_time.ev_hi++;
2228 while(time.ev_lo < end_time.ev_lo || time.ev_hi < end_time.ev_hi)
2229 ReadEClock(&time);
2231 return;
2233 #endif