3 Prometheus NE2000 driver.
5 Copyright (C) 2001-2004 Matay
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation.
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
23 /// includes and defines
28 #include <aros/asmcall.h>
29 #include <aros/libcall.h>
31 #define AROS_LIBFUNC_INIT
32 #define AROS_LIBFUNC_EXIT
33 #define AROS_INTFUNC_INIT
34 #define AROS_INTFUNC_EXIT
37 #include <proto/exec.h>
38 #include <proto/expansion.h>
39 #include <proto/utility.h>
40 #include <proto/dos.h>
41 #include <proto/prometheus.h>
42 #include <proto/timer.h>
43 #include <exec/libraries.h>
44 #include <exec/resident.h>
45 #include <exec/memory.h>
46 #include <exec/interrupts.h>
47 #include <exec/errors.h>
48 #include <devices/sana2.h>
49 #include <hardware/intbits.h>
50 #include <dos/dostags.h>
61 #define TX_BUFFER 0x40
62 #define RX_BUFFER 0x46
63 #define BUFFER_END 0x80
64 #define INTMASK (INT_RXPACKET | INT_TXPACKET | INT_TXERROR)
68 #define PCI_VENDOR_REALTEK 0x10EC
69 #define PCI_DEVICE_RTL8029 0x8029
73 #define UF_CONFIGURED 0x01
74 #define UF_ONLINE 0x02
75 #define UF_PROMISCUOUS 0x04
77 // Macro for registerized parameters (used in some OS functions).
80 #if defined(__mc68000) && !defined(__AROS__)
81 #define _REG(A, B) B __asm(#A)
82 #define REG(A, B) _REG(A, B)
88 // Macro for declaring local libraries bases.
90 #define USE(a) struct Library * a = dd->dd_##a;
91 #define USE_U(a) struct Library * a = ud->ud_##a;
93 // Debug on/off switch (debug off if commented).
97 // Macros for debug messages.
100 #define USE_D(a) struct Library *##a = dd->dd_##a;
101 #define USE_UD(a) struct Library *##a = ud->ud_##a;
102 #define DBG(a) FPrintf(dd->debug, a "\n")
103 #define DBG_U(a) FPrintf(ud->debug, a "\n")
104 #define DBG_T(a) FPrintf(ud->tdebug, a "\n")
105 #define DBG1(a,b) FPrintf(dd->debug, a "\n",(LONG)b)
106 #define DBG1_U(a,b) FPrintf(ud->debug, a "\n",(LONG)b)
107 #define DBG1_T(a,b) FPrintf(ud->tdebug, a "\n",(LONG)b)
108 #define DBG2(a,b,c) FPrintf(dd->debug, a "\n",(LONG)b,(LONG)c)
109 #define DBG2_U(a,b,c) FPrintf(ud->debug, a "\n",(LONG)b,(LONG)c)
110 #define DBG2_T(a,b,c) FPrintf(ud->tdebug, a "\n",(LONG)b,(LONG)c)
121 #define DBG2_U(a,b,c)
122 #define DBG2_T(a,b,c)
125 // New Style Device support
127 #define NSCMD_DEVICEQUERY 0x4000
129 struct NSDeviceQueryResult
131 ULONG DevQueryFormat
; /* this is type 0 */
132 ULONG SizeAvailable
; /* bytes available */
133 UWORD DeviceType
; /* what the device does */
134 UWORD DeviceSubType
; /* depends on the main type */
135 UWORD
*SupportedCommands
; /* 0 terminated list of cmd's */
138 #define NSDEVTYPE_SANA2 7 /* A >=SANA2R2 networking device */
141 /// device structures
145 struct Library dd_Lib
;
147 struct Library
*dd_SysBase
;
148 struct Library
*dd_PrometheusBase
;
149 struct Library
*dd_UtilityBase
;
150 struct Library
*dd_DOSBase
;
151 struct Library
*dd_TimerBase
;
152 struct UnitData
*dd_Units
[4];
153 struct timerequest dd_Treq
;
164 struct Message ud_Message
;
166 struct Library
*ud_SysBase
;
167 struct Library
*ud_PrometheusBase
;
168 struct Library
*ud_DOSBase
;
169 struct Library
*ud_TimerBase
;
170 struct Interrupt
*ud_Interrupt
;
171 struct Task
*ud_Task
;
172 struct MsgPort
*ud_TaskPort
;
173 struct MsgPort
*ud_LifeTime
;
174 struct MinList ud_RxQueue
;
175 struct MinList ud_TxQueue
;
176 struct IOSana2Req
*ud_PendingWrite
;
179 ULONG ud_GoWriteMask
;
180 UWORD ud_RxBuffer
[768];
182 UBYTE ud_EtherAddress
[6];
183 UBYTE ud_SoftAddress
[6];
184 struct Sana2DeviceStats ud_DevStats
;
197 BOOL (*bf_CopyTo
)(REG(a0
, APTR
), REG(a1
, APTR
), REG(d0
, ULONG
));
198 BOOL (*bf_CopyFrom
)(REG(a0
, APTR
), REG(a1
, APTR
), REG(d0
, ULONG
));
205 AROS_UFP3(struct DevData
*, DevInit
,
206 AROS_UFPA(IPTR
, num
, D0
),
207 AROS_UFPA(APTR
, seglist
, A0
),
208 AROS_UFPA(struct Library
*, sysb
, A6
));
209 AROS_LD3(LONG
, DevOpen
,
210 AROS_LDA(struct IOSana2Req
*, req
, A1
),
211 AROS_LDA(LONG
, unit
, D0
),
212 AROS_LDA(ULONG
, flags
, D1
),
213 struct DevData
*, dd
, 1, S2
);
214 AROS_LD1(APTR
, DevClose
,
215 AROS_LDA(struct IOSana2Req
*, req
, A1
),
216 struct DevData
*, dd
, 2, S2
);
217 AROS_LD0(APTR
, DevExpunge
,
218 struct DevData
*, dd
, 3, S2
);
219 AROS_LD0(APTR
, DevReserved
,
220 struct DevData
*, dd
, 4, S2
);
221 AROS_LD1(VOID
, DevBeginIO
,
222 AROS_LDA(struct IOSana2Req
*, req
, A1
),
223 struct DevData
*, dd
, 5, S2
);
224 AROS_LD1(ULONG
, DevAbortIO
,
225 AROS_LDA(struct IOSana2Req
*, req
, A1
),
226 struct DevData
*, dd
, 6, S2
);
228 LONG
DevOpen(REG(a1
, struct IOSana2Req
*req
), REG(d0
, LONG unit
),
229 REG(d1
, LONG flags
), REG(a6
, struct DevData
*dd
));
230 APTR
DevClose(REG(a1
, struct IOSana2Req
*req
), REG(a6
, struct DevData
*dd
));
231 APTR
DevExpunge(REG(a6
, struct DevData
*dd
));
232 LONG
DevReserved(void);
233 void DevBeginIO(REG(a1
, struct IOSana2Req
*req
),
234 REG(a6
, struct DevData
*dd
));
235 ULONG
DevAbortIO(REG(a1
, struct IOSana2Req
*req
),
236 REG(a6
, struct DevData
*dd
));
239 void IoDone(struct UnitData
*ud
, struct IOSana2Req
*req
, LONG err
, LONG werr
);
240 LONG
OpenDeviceLibraries(struct DevData
*dd
);
241 void CloseDeviceLibraries(struct DevData
*dd
);
242 LONG
PrepareCookie(struct IOSana2Req
*req
, struct DevData
*dd
);
243 LONG
RunTask(struct DevData
*dd
, struct UnitData
*ud
);
244 void ClearGlobalStats(struct UnitData
*ud
);
245 struct UnitData
*OpenUnit(struct DevData
*dd
, LONG unit
, LONG flags
);
246 struct UnitData
*InitializeUnit(struct DevData
*dd
, LONG unit
);
247 void CloseUnit(struct DevData
*dd
, struct UnitData
*ud
);
248 void ExpungeUnit(struct DevData
*dd
, struct UnitData
*ud
);
250 void CmdNSDQuery(struct UnitData
*ud
, struct IOStdReq
*req
);
251 void S2DeviceQuery(struct UnitData
*ud
, struct IOSana2Req
*req
);
252 void S2GetStationAddress(struct UnitData
*ud
, struct IOSana2Req
*req
);
253 void S2ConfigInterface(struct UnitData
*ud
, struct IOSana2Req
*req
);
254 void S2Online(struct UnitData
*ud
, struct IOSana2Req
*req
);
255 void S2Offline(struct UnitData
*ud
, struct IOSana2Req
*req
);
256 void S2GetGlobalStats(struct UnitData
*ud
, struct IOSana2Req
*req
);
258 void HardwareReset(struct UnitData
*ud
);
259 void HardwareInit (struct UnitData
*ud
);
260 IPTR
FindHardware(struct DevData
*dd
, WORD unit
, struct UnitData
*ud
);
261 void GoOnline (struct UnitData
*ud
);
262 void GoOffline(struct UnitData
*ud
);
263 void GetHwAddress(struct UnitData
*ud
);
264 void WriteHwAddress(struct UnitData
*ud
);
265 LONG
PacketReceived(struct UnitData
*ud
);
266 LONG
RingBufferNotEmpty(struct UnitData
*ud
);
268 struct IOSana2Req
*SearchReadRequest(struct UnitData
*ud
,
269 struct MinList
*queue
, ULONG type
);
273 struct Library
*sys_base
;
277 /// tables and constants
279 extern struct Resident romtag
;
280 const UBYTE IdString
[] = DEV_IDSTRING
;
282 const void *FuncTable
[] =
285 AROS_SLIB_ENTRY(DevOpen
, S2
, 1),
286 AROS_SLIB_ENTRY(DevClose
, S2
, 2),
287 AROS_SLIB_ENTRY(DevExpunge
, S2
, 3),
288 AROS_SLIB_ENTRY(DevReserved
, S2
, 4),
289 AROS_SLIB_ENTRY(DevBeginIO
, S2
, 5),
290 AROS_SLIB_ENTRY(DevAbortIO
, S2
, 6),
302 UWORD NSDSupported
[] =
308 S2_GETSTATIONADDRESS
,
321 // Called when the device is loaded into memory. Makes system library, initializes Library structure, opens
322 // libraries used by the device. Returns device base or NULL if init failed.
325 AROS_UFH3(struct DevData
*, DevInit
,
326 AROS_UFHA(IPTR
, num
, D0
),
327 AROS_UFHA(APTR
, seglist
, A0
),
328 AROS_UFHA(struct Library
*, sysb
, A6
))
330 struct DevData
*DevInit(REG(d0
, ULONG num
), REG(a0
, void *seglist
),
331 REG(a6
, struct Library
*sysb
))
337 struct Library
*SysBase
= sysb
;
339 if (dd
= (struct DevData
*)MakeLibrary(FuncTable
, NULL
, NULL
,
340 sizeof(struct DevData
), 0))
342 dd
->dd_Lib
.lib_Node
.ln_Type
= NT_DEVICE
;
343 dd
->dd_Lib
.lib_Node
.ln_Name
= (TEXT
*)romtag
.rt_Name
;
344 dd
->dd_Lib
.lib_Flags
= LIBF_CHANGED
| LIBF_SUMUSED
;
345 dd
->dd_Lib
.lib_Version
= DEV_VERSION
;
346 dd
->dd_Lib
.lib_Revision
= DEV_REVISION
;
347 dd
->dd_Lib
.lib_IdString
= (TEXT
*)romtag
.rt_IdString
;
348 dd
->dd_Lib
.lib_OpenCnt
= 0;
349 dd
->dd_SegList
= seglist
;
350 dd
->dd_SysBase
= SysBase
;
351 if (OpenDeviceLibraries(dd
))
356 for (i
= 0; i
< 4; i
++) dd
->dd_Units
[i
] = NULL
;
363 strcpy(dd
->dpath
, "KCON:0/17/400/300/prm-rtl8029.device (main)/AUTO/CLOSE/WAIT");
364 GetVar("PrometheusDebug", dd
->dpath
, 128, 0);
365 dd
->debug
= Open(dd
->dpath
, MODE_NEWFILE
);
368 DBG1("Device initialized, base at $%08lx.", dd
);
369 AddDevice((struct Device
*)dd
);
372 CloseDeviceLibraries(dd
);
383 AROS_LH3(LONG
, DevOpen
,
384 AROS_LHA(struct IOSana2Req
*, req
, A1
),
385 AROS_LHA(LONG
, unit
, D0
),
386 AROS_LHA(ULONG
, flags
, D1
),
387 struct DevData
*, dd
, 1, S2
)
389 LONG
DevOpen(REG(a1
, struct IOSana2Req
*req
), REG(d0
, LONG unit
),
390 REG(d1
, LONG flags
), REG(a6
, struct DevData
*dd
))
398 DBG("DevOpen() called.");
399 dd
->dd_Lib
.lib_OpenCnt
++; // expunge protection
401 if ((unit
>= 0) && (unit
<= 3))
403 if (ud
= OpenUnit(dd
, unit
, flags
))
405 req
->ios2_Req
.io_Error
= 0;
406 req
->ios2_Req
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
407 req
->ios2_Req
.io_Device
= (struct Device
*)dd
;
408 req
->ios2_Req
.io_Unit
= (struct Unit
*)ud
;
409 if (PrepareCookie(req
, dd
))
411 dd
->dd_Lib
.lib_Flags
&= ~LIBF_DELEXP
;
412 DBG("DevOpen(): device opened successfully.");
415 DBG("PrepareCookie() failed.");
419 req
->ios2_Req
.io_Error
= IOERR_OPENFAIL
;
420 req
->ios2_Req
.io_Device
= (struct Device
*)-1;
421 req
->ios2_Req
.io_Unit
= (struct Unit
*)-1;
422 dd
->dd_Lib
.lib_OpenCnt
--; /* end of expunge protection */
423 return IOERR_OPENFAIL
;
432 AROS_LH1(APTR
, DevClose
,
433 AROS_LHA(struct IOSana2Req
*, req
, A1
),
434 struct DevData
*, dd
, 2, S2
)
436 APTR
DevClose(REG(a1
, struct IOSana2Req
*req
), REG(a6
, struct DevData
*dd
))
444 CloseUnit(dd
, (struct UnitData
*)req
->ios2_Req
.io_Unit
);
446 if (req
->ios2_BufferManagement
) FreeMem(req
->ios2_BufferManagement
,
447 sizeof(struct BuffFunctions
));
449 if (--dd
->dd_Lib
.lib_OpenCnt
== 0)
451 DBG("DevClose(): open counter reached 0.");
452 if (dd
->dd_Lib
.lib_Flags
& LIBF_DELEXP
)
454 return AROS_LVO_CALL0(APTR
, struct DevData
*, dd
, 2, );
456 return (DevExpunge(dd
));
468 AROS_LH0(APTR
, DevExpunge
,
469 struct DevData
*, dd
, 3, S2
)
471 APTR
DevExpunge(REG(a6
, struct DevData
*dd
))
480 if (dd
->dd_Lib
.lib_OpenCnt
)
482 dd
->dd_Lib
.lib_Flags
|= LIBF_DELEXP
;
485 Remove((struct Node
*)dd
);
486 CloseDeviceLibraries(dd
);
487 seglist
= dd
->dd_SegList
;
488 FreeMem((APTR
)dd
- dd
->dd_Lib
.lib_NegSize
,
489 (IPTR
)dd
->dd_Lib
.lib_PosSize
+ (IPTR
)dd
->dd_Lib
.lib_NegSize
);
490 DBG("DevExpunge(): expunged.");
500 AROS_LH0(APTR
, DevReserved
,
501 struct DevData
*, dd
, 4, S2
)
503 LONG
DevReserved (void)
517 AROS_LH1(VOID
, DevBeginIO
,
518 AROS_LHA(struct IOSana2Req
*, req
, A1
),
519 struct DevData
*, dd
, 5, S2
)
521 void DevBeginIO(REG(a1
, struct IOSana2Req
*req
),
522 REG(a6
, struct DevData
*dd
))
529 struct UnitData
*ud
= (struct UnitData
*)req
->ios2_Req
.io_Unit
;
532 switch(req
->ios2_Req
.io_Command
)
534 case NSCMD_DEVICEQUERY
: CmdNSDQuery(ud
, (struct IOStdReq
*)req
); break;
535 case S2_DEVICEQUERY
: S2DeviceQuery(ud
, req
); break;
536 case S2_GETSTATIONADDRESS
: S2GetStationAddress(ud
, req
); break;
537 case S2_CONFIGINTERFACE
: S2ConfigInterface(ud
, req
); break;
538 case S2_ONLINE
: S2Online(ud
, req
); break;
539 case S2_OFFLINE
: S2Offline(ud
, req
); break;
540 case S2_GETGLOBALSTATS
: S2GetGlobalStats(ud
, req
); break;
543 DBG1("CMD_READ [$%08lx].", (LONG
)req
);
544 req
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
545 PutMsg(ud
->ud_TaskPort
, &req
->ios2_Req
.io_Message
);
549 for (i
= 0; i
< 6; i
++) req
->ios2_DstAddr
[i
] = 0xFF;
551 DBG1("CMD_WRITE [$%08lx].", (LONG
)req
);
552 req
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
553 PutMsg(ud
->ud_TaskPort
, &req
->ios2_Req
.io_Message
);
557 DBG1("CMD_FLUSH [$%08lx].", (LONG
)req
);
558 req
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
559 PutMsg(ud
->ud_TaskPort
, &req
->ios2_Req
.io_Message
);
563 DBG1("DevBeginIo(): unknown command code %ld.", req
->ios2_Req
.io_Command
);
564 IoDone(ud
, req
, IOERR_NOCMD
, S2WERR_GENERIC_ERROR
);
576 AROS_LH1(ULONG
, DevAbortIO
,
577 AROS_LHA(struct IOSana2Req
*, req
, A1
),
578 struct DevData
*, dd
, 6, S2
)
580 ULONG
DevAbortIO(REG(a1
, struct IOSana2Req
*req
),
581 REG(a6
, struct DevData
*dd
))
589 struct UnitData
*ud
= (struct UnitData
*)req
->ios2_Req
.io_Unit
;
590 struct MinList
*list
;
591 struct MinNode
*node
;
593 DBG1("DevAbortIo: aborting $%08lx.", req
);
594 switch (req
->ios2_Req
.io_Command
)
597 list
= &ud
->ud_RxQueue
;
602 list
= &ud
->ud_TxQueue
;
611 for (node
= list
->mlh_Head
; node
->mln_Succ
; node
= node
->mln_Succ
)
613 if (node
== (struct MinNode
*)req
)
615 if (((struct Message
*)node
)->mn_Node
.ln_Type
!= NT_REPLYMSG
)
617 Remove((struct Node
*)node
);
618 req
->ios2_Req
.io_Error
= IOERR_ABORTED
;
619 ReplyMsg((struct Message
*)node
);
626 else ret
= IOERR_NOCMD
;
634 // AUXILIARY FUNCTIONS
636 /// IoDone(struct UnitData *ud, struct IOSana2Req *req, LONG err, LONG werr)
637 // Function ends IORequest with given error codes. Requests with IOF_QUICK cleared will be ReplyMsg()-ed.
639 void IoDone(struct UnitData
*ud
, struct IOSana2Req
*req
, LONG err
, LONG werr
)
643 req
->ios2_Req
.io_Error
= err
;
644 req
->ios2_WireError
= werr
;
645 if (!(req
->ios2_Req
.io_Flags
& IOF_QUICK
))
646 ReplyMsg(&req
->ios2_Req
.io_Message
);
651 /// OpenDeviceLibraries(struct DevData *dd)
653 LONG
OpenDeviceLibraries(struct DevData
*dd
)
657 if (!(dd
->dd_UtilityBase
= OpenLibrary("utility.library", 39))) return FALSE
;
658 if (!(dd
->dd_PrometheusBase
= OpenLibrary("prometheus.library", 2))) return FALSE
;
659 if (!(dd
->dd_DOSBase
= OpenLibrary("dos.library", 38))) return FALSE
;
660 if (OpenDevice ("timer.device", UNIT_VBLANK
, (struct IORequest
*)&dd
->dd_Treq
, 0) == 0)
662 dd
->dd_TimerBase
= (struct Library
*)dd
->dd_Treq
.tr_node
.io_Device
;
669 /// CloseDeviceLibraries(struct DevData *dd)
671 void CloseDeviceLibraries(struct DevData
*dd
)
675 if (dd
->dd_DOSBase
) CloseLibrary(dd
->dd_DOSBase
);
676 if (dd
->dd_PrometheusBase
) CloseLibrary(dd
->dd_PrometheusBase
);
677 if (dd
->dd_UtilityBase
) CloseLibrary(dd
->dd_UtilityBase
);
678 if (dd
->dd_TimerBase
) CloseDevice ((struct IORequest
*)&dd
->dd_Treq
);
682 /// PrepareCookie(struct IOSana2Req *req, struct DevData *dd)
684 LONG
PrepareCookie(struct IOSana2Req
*req
, struct DevData
*dd
)
690 if (req
->ios2_BufferManagement
)
692 struct BuffFunctions
*bfun
;
694 if (bfun
= AllocMem(sizeof(struct BuffFunctions
), MEMF_ANY
))
696 bfun
->bf_CopyFrom
= (APTR
)GetTagData(S2_CopyFromBuff
, (IPTR
)NULL
,
697 (struct TagItem
*)req
->ios2_BufferManagement
);
698 bfun
->bf_CopyTo
= (APTR
)GetTagData(S2_CopyToBuff
, (IPTR
)NULL
,
699 (struct TagItem
*)req
->ios2_BufferManagement
);
701 if (bfun
->bf_CopyFrom
&& bfun
->bf_CopyTo
)
703 DBG1("CopyFrom [$%08lx].", bfun
->bf_CopyFrom
);
704 req
->ios2_BufferManagement
= bfun
;
707 else FreeMem(bfun
, sizeof(struct BuffFunctions
));
714 /// RunTask(struct DevData *dd, struct UnitData *ud)
716 LONG
RunTask(struct DevData
*dd
, struct UnitData
*ud
)
720 const struct TagItem task_tags
[] =
722 {NP_Entry
, (IPTR
)UnitTask
},
723 {NP_Name
, (IPTR
)ud
->ud_Name
},
728 DBG("RunTask() called.");
730 if(ud
->ud_LifeTime
= CreateMsgPort())
732 if (ud
->ud_Task
= (struct Task
*)CreateNewProc(task_tags
))
736 DBG1("Task [$%08lx] started.", ud
->ud_Task
);
737 for (i
= 0; i
< 50; i
++)
739 if (!(ud
->ud_TaskPort
= FindPort(ud
->ud_Name
))) Delay(1);
742 DBG("Task port detected.");
743 ud
->ud_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
744 ud
->ud_Message
.mn_Length
= sizeof(struct UnitData
);
745 ud
->ud_Message
.mn_ReplyPort
= ud
->ud_LifeTime
;
746 PutMsg(ud
->ud_TaskPort
, &ud
->ud_Message
);
756 /// KillTask(struct DevData *dd, struct UnitData *ud)
758 void KillTask(struct DevData
*dd
, struct UnitData
*ud
)
763 Signal(ud
->ud_Task
, SIGBREAKF_CTRL_C
);
764 WaitPort(ud
->ud_LifeTime
);
765 GetMsg(ud
->ud_LifeTime
);
766 DeleteMsgPort(ud
->ud_LifeTime
);
772 /// ClearGlobalStats()
774 void ClearGlobalStats(struct UnitData
*ud
)
778 ud
->ud_DevStats
.PacketsReceived
= 0;
779 ud
->ud_DevStats
.PacketsSent
= 0;
780 GetSysTime(&ud
->ud_DevStats
.LastStart
);
787 struct UnitData
*OpenUnit(struct DevData
*dd
, LONG unit
, LONG flags
)
790 struct UnitData
*ud
= dd
->dd_Units
[unit
];
792 DBG("OpenUnit() called.");
794 /* Eliminate 'promiscuous without exclusive' flag combination. */
796 if ((flags
& SANA2OPF_PROM
) && !(flags
& SANA2OPF_MINE
)) return NULL
;
798 /* Initialize unit if opened first time. */
802 if (!(ud
= InitializeUnit(dd
, unit
))) return NULL
;
805 /* Check exclusive flag - reject if already opened by someone else. */
807 if ((flags
& SANA2OPF_MINE
) && ud
->ud_OpenCnt
) return NULL
;
809 /* Set promiscuous flag if requested - we konw here MINE was requested too, and noone else has opened */
810 /* the unit. So we can just set it if requested. */
812 if (flags
& SANA2OPF_PROM
) ud
->ud_Flags
|= UF_PROMISCUOUS
;
814 /* OK, increment open counter and exit with success. */
817 DBG2("%s opened [%ld].", ud
->ud_Name
, ud
->ud_OpenCnt
);
824 void CloseUnit(struct DevData
*dd
, struct UnitData
*ud
)
828 DBG1("%s closed.", ud
->ud_Name
);
829 if (!(--ud
->ud_OpenCnt
)) ExpungeUnit(dd
, ud
);
836 struct UnitData
*InitializeUnit(struct DevData
*dd
, LONG unit
)
845 DBG("InitializeUnit() called.");
846 if (ud
= AllocMem(sizeof(struct UnitData
), MEMF_PUBLIC
| MEMF_CLEAR
))
848 if (ud
->ud_Hardware
= FindHardware(dd
, unit
, ud
))
851 ud
->debug
= dd
->debug
;
854 for (i
= 5; i
>= 0; i
--)
856 ud
->ud_SoftAddress
[i
] = 0x00;
857 ud
->ud_EtherAddress
[i
] = 0x00;
859 ud
->ud_SysBase
= dd
->dd_SysBase
;
860 ud
->ud_PrometheusBase
= dd
->dd_PrometheusBase
;
861 ud
->ud_DOSBase
= dd
->dd_DOSBase
;
862 ud
->ud_TimerBase
= dd
->dd_TimerBase
;
863 strcpy(ud
->ud_Name
, "prm-rtl8029.device (x)");
864 ud
->ud_Name
[20] = '0' + unit
;
865 ud
->ud_RxQueue
.mlh_Head
= (struct MinNode
*)&ud
->ud_RxQueue
.mlh_Tail
;
866 ud
->ud_RxQueue
.mlh_Tail
= NULL
;
867 ud
->ud_RxQueue
.mlh_TailPred
= (struct MinNode
*)&ud
->ud_RxQueue
.mlh_Head
;
868 ud
->ud_TxQueue
.mlh_Head
= (struct MinNode
*)&ud
->ud_TxQueue
.mlh_Tail
;
869 ud
->ud_TxQueue
.mlh_Tail
= NULL
;
870 ud
->ud_TxQueue
.mlh_TailPred
= (struct MinNode
*)&ud
->ud_TxQueue
.mlh_Head
;
871 ud
->ud_NextPage
= RX_BUFFER
;
877 dd
->dd_Units
[unit
] = ud
;
878 DBG1("%s initialized.", (LONG
)ud
->ud_Name
);
890 void ExpungeUnit(struct DevData
*dd
, struct UnitData
*ud
)
898 unit
= ud
->ud_Name
[20] - '0';
899 if (ud
->ud_Flags
& UF_ONLINE
) GoOffline(ud
);
900 if (ud
->ud_Task
) KillTask(dd
, ud
);
901 FreeMem(ud
, sizeof(struct UnitData
));
902 dd
->dd_Units
[unit
] = NULL
;
903 DBG1("%s expunged.", ud
->ud_Name
);
910 // IMMEDIATE DEVICE COMMANDS
914 void S2DeviceQuery(struct UnitData
*ud
, struct IOSana2Req
*req
)
917 struct Sana2DeviceQuery
*query
= req
->ios2_StatData
;
919 DBG_U("S2_DEVICEQUERY.");
922 if (query
->SizeAvailable
>= sizeof(struct Sana2DeviceQuery
))
924 query
->SizeSupplied
= sizeof(struct Sana2DeviceQuery
);
925 query
->DevQueryFormat
= 0;
926 query
->DeviceLevel
= 0;
927 query
->AddrFieldSize
= 48;
929 query
->BPS
= 10000000;
930 query
->HardwareType
= S2WireType_Ethernet
;
931 IoDone(ud
, req
, OK
, OK
);
933 else IoDone(ud
, req
, S2ERR_BAD_ARGUMENT
, S2WERR_GENERIC_ERROR
);
935 else IoDone(ud
, req
, S2ERR_BAD_ARGUMENT
, S2WERR_NULL_POINTER
);
940 /// S2GetStationAddress()
942 void S2GetStationAddress(struct UnitData
*ud
, struct IOSana2Req
*req
)
947 DBG_U("S2_GETSTATIONADDRESS.");
948 CopyMem(ud
->ud_SoftAddress
, req
->ios2_SrcAddr
, 6);
949 CopyMem(ud
->ud_EtherAddress
, req
->ios2_DstAddr
, 6);
950 IoDone(ud
, req
, OK
, OK
);
957 void S2Online(struct UnitData
*ud
, struct IOSana2Req
*req
)
962 ClearGlobalStats(ud
);
963 if (!(ud
->ud_Flags
& UF_ONLINE
))
966 ud
->ud_Flags
|= UF_ONLINE
;
967 IoDone(ud
, req
, OK
, OK
);
969 else IoDone(ud
, req
, S2ERR_BAD_STATE
, S2WERR_UNIT_ONLINE
);
974 /// S2ConfigInterface()
976 BOOL
address_has_all(UBYTE
*addr
, UBYTE num
)
980 for (i
= 5; i
>= 0; i
--)
982 if (addr
[i
] != num
) return FALSE
;
988 void S2ConfigInterface(struct UnitData
*ud
, struct IOSana2Req
*req
)
993 DBG_U("S2_CONFIGINTERFACE.");
994 ClearGlobalStats(ud
);
995 if (ud
->ud_Flags
& UF_CONFIGURED
)
997 IoDone(ud
, req
, S2ERR_BAD_STATE
, S2WERR_IS_CONFIGURED
);
999 else if (address_has_all(req
->ios2_SrcAddr
, 0x00) ||
1000 address_has_all(req
->ios2_SrcAddr
, 0xFF))
1002 IoDone(ud
, req
, S2ERR_BAD_ADDRESS
, S2WERR_SRC_ADDRESS
);
1007 CopyMem(req
->ios2_SrcAddr
, ud
->ud_SoftAddress
, 6);
1009 if (!(ud
->ud_Flags
& UF_ONLINE
))
1012 ud
->ud_Flags
|= UF_ONLINE
;
1014 ud
->ud_Flags
|= UF_CONFIGURED
;
1015 IoDone(ud
, req
, OK
, OK
);
1023 void S2Offline(struct UnitData
*ud
, struct IOSana2Req
*req
)
1027 DBG_U("S2_OFFLINE.");
1028 if (ud
->ud_Flags
& UF_ONLINE
)
1031 ud
->ud_Flags
&= ~UF_ONLINE
;
1032 IoDone(ud
, req
, OK
, OK
);
1034 else IoDone(ud
, req
, S2ERR_BAD_STATE
, S2WERR_UNIT_OFFLINE
);
1039 /// S2GetGlobalStats()
1041 void S2GetGlobalStats(struct UnitData
*ud
, struct IOSana2Req
*req
)
1045 if (req
->ios2_StatData
)
1047 CopyMem(&ud
->ud_DevStats
, req
->ios2_StatData
, sizeof(struct Sana2DeviceStats
));
1048 IoDone(ud
, req
, OK
, OK
);
1050 else IoDone(ud
, req
, S2ERR_BAD_ARGUMENT
, S2WERR_NULL_POINTER
);
1056 void CmdNSDQuery(struct UnitData
*ud
, struct IOStdReq
*req
)
1060 struct NSDeviceQueryResult
*qdata
;
1063 DBG_U("NSCMD_DEVICEQUERY.");
1064 if (req
->io_Length
>= sizeof(struct NSDeviceQueryResult
))
1066 if (qdata
= (struct NSDeviceQueryResult
*)req
->io_Data
)
1068 if ((qdata
->DevQueryFormat
== 0) && (qdata
->SizeAvailable
== 0))
1070 qdata
->SizeAvailable
= sizeof(struct NSDeviceQueryResult
);
1071 qdata
->DeviceType
= NSDEVTYPE_SANA2
;
1072 qdata
->DeviceSubType
= 0;
1073 qdata
->SupportedCommands
= NSDSupported
;
1074 req
->io_Actual
= sizeof(struct NSDeviceQueryResult
);
1076 else error
= IOERR_BADLENGTH
;
1078 else error
= IOERR_BADADDRESS
;
1080 else error
= IOERR_BADLENGTH
;
1082 /* I don't use IoDone() here, because it writes to ios2_WireError */
1083 /* but this request can be simple IOStdReq one. */
1085 req
->io_Error
= error
;
1086 if (!(req
->io_Flags
& IOF_QUICK
)) ReplyMsg(&req
->io_Message
);
1092 // HARDWARE ACCESS FUNCTIONS
1097 AROS_INTH1(IntCode
, struct UnitData
*, ud
)
1099 LONG
IntCode(REG(a1
, struct UnitData
*ud
))
1106 struct IOSana2Req
*req
;
1109 while (intstatus
= (BYTEIN(ud
->ud_Hardware
+ NE2000_INT_STATUS
)
1112 if (intstatus
& INT_TXERROR
)
1114 BYTEOUT(ud
->ud_Hardware
+ NE2000_INT_STATUS
, INT_TXERROR
);
1115 req
= ud
->ud_PendingWrite
;
1116 IoDone(ud
, req
, S2ERR_TX_FAILURE
, S2WERR_TOO_MANY_RETIRES
);
1117 Signal(ud
->ud_Task
, ud
->ud_GoWriteMask
);
1121 if (intstatus
& INT_TXPACKET
)
1123 BYTEOUT(ud
->ud_Hardware
+ NE2000_INT_STATUS
, INT_TXPACKET
);
1124 req
= ud
->ud_PendingWrite
;
1125 ud
->ud_DevStats
.PacketsSent
++;
1126 IoDone(ud
, req
, OK
, OK
);
1127 Signal(ud
->ud_Task
, ud
->ud_GoWriteMask
);
1131 if (intstatus
& INT_RXPACKET
)
1134 UWORD mask
= 0xFFFF;
1137 while (RingBufferNotEmpty(ud
))
1139 BYTEOUT(ud
->ud_Hardware
+ NE2000_INT_STATUS
, INT_RXPACKET
);
1140 len
= PacketReceived(ud
);
1141 if (req
= SearchReadRequest(ud
, &ud
->ud_RxQueue
,
1142 BEWord(ud
->ud_RxBuffer
[6])))
1144 if (req
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) offset
= 0;
1147 AROS_UFC3(BOOL
, ((struct BuffFunctions
*)
1148 req
->ios2_BufferManagement
)->bf_CopyTo
,
1149 AROS_UFCA(APTR
, req
->ios2_Data
, A0
),
1150 AROS_UFCA(APTR
, &ud
->ud_RxBuffer
[offset
], A1
),
1151 AROS_UFCA(ULONG
, len
- (offset
<< 1), D0
));
1153 ((struct BuffFunctions
*)req
->ios2_BufferManagement
)->
1154 bf_CopyTo(req
->ios2_Data
, &ud
->ud_RxBuffer
[offset
],
1155 len
- (offset
<< 1));
1157 CopyMem(&ud
->ud_RxBuffer
[0], req
->ios2_DstAddr
, 6);
1158 CopyMem(&ud
->ud_RxBuffer
[3], req
->ios2_SrcAddr
, 6);
1159 req
->ios2_DataLength
= len
- (offset
<< 1);
1160 for (i
= 2; i
>= 0; i
--) mask
&= ud
->ud_RxBuffer
[i
];
1162 req
->ios2_Req
.io_Flags
|= SANA2IOF_BCAST
;
1163 ud
->ud_DevStats
.PacketsReceived
++;
1164 IoDone(ud
, req
, OK
, OK
);
1176 /// InstallInterrupt()
1178 LONG
InstallInterrupt(struct UnitData
*ud
)
1181 USE_U(PrometheusBase
)
1182 struct Interrupt
*intr
;
1184 if (intr
= AllocMem(sizeof(struct Interrupt
), MEMF_PUBLIC
| MEMF_CLEAR
))
1186 intr
->is_Node
.ln_Type
= NT_INTERRUPT
;
1187 intr
->is_Node
.ln_Name
= ud
->ud_Name
;
1189 intr
->is_Code
= (APTR
)IntCode
;
1190 Prm_AddIntServer(ud
->ud_Board
, intr
);
1191 ud
->ud_Interrupt
= intr
;
1198 /// RemoveInterrupt()
1200 void RemoveInterrupt(struct UnitData
*ud
)
1203 USE_U(PrometheusBase
)
1205 Prm_RemIntServer(ud
->ud_Board
, ud
->ud_Interrupt
);
1206 FreeMem(ud
->ud_Interrupt
, sizeof(struct Interrupt
));
1213 IPTR
FindHardware(struct DevData
*dd
, WORD unit
, struct UnitData
*ud
)
1222 board
= Prm_FindBoardTags(board
,
1223 PRM_Vendor
, PCI_VENDOR_REALTEK
,
1224 PRM_Device
, PCI_DEVICE_RTL8029
,
1231 ud
->ud_Board
= board
;
1232 Prm_GetBoardAttrsTags(board
,
1233 PRM_MemoryAddr0
, (IPTR
)&hwbase
,
1235 Prm_SetBoardAttrsTags(board
,
1236 PRM_BoardOwner
, (IPTR
)dd
,
1246 void HardwareInit (struct UnitData
*ud
)
1248 IPTR hw
= ud
->ud_Hardware
;
1250 BYTEOUT(hw
+ NE2000_COMMAND
, 0x21);
1251 BYTEOUT(hw
+ NE2000_DATA_CONFIG
,
1252 DTCFG_FIFO_8
| DTCFG_WIDE
| DTCFG_LOOPSEL
);
1253 BYTEOUT(hw
+ NE2000_DMA_COUNTER0
, 0);
1254 BYTEOUT(hw
+ NE2000_DMA_COUNTER1
, 0);
1255 BYTEOUT(hw
+ NE2000_TX_CONFIG
, 0x02);
1256 BYTEOUT(hw
+ NE2000_PAGE_START
, RX_BUFFER
);
1257 BYTEOUT(hw
+ NE2000_PAGE_STOP
, BUFFER_END
);
1258 BYTEOUT(hw
+ NE2000_BOUNDARY
, BUFFER_END
- 1);
1259 BYTEOUT(hw
+ NE2000_INT_STATUS
, 0xFF);
1260 BYTEOUT(hw
+ NE2000_INT_MASK
, 0x00);
1261 BYTEOUT(hw
+ NE2000_COMMAND
, 0x61);
1262 BYTEOUT(hw
+ NE2000_CURRENT_PAGE
, RX_BUFFER
);
1263 BYTEOUT(hw
+ NE2000_COMMAND
, 0x21);
1270 void HardwareReset (struct UnitData
*ud
)
1273 IPTR hw
= ud
->ud_Hardware
;
1276 WORDOUT(hw
+ NE2000_RESET_PORT
, trash
);
1278 trash
= WORDIN(hw
+ NE2000_RESET_PORT
);
1286 void GoOnline (struct UnitData
*ud
)
1288 IPTR hw
= ud
->ud_Hardware
;
1292 InstallInterrupt(ud
);
1293 BYTEOUT(hw
+ NE2000_COMMAND
, 0x22);
1294 BYTEOUT(hw
+ NE2000_TX_CONFIG
, 0x00);
1295 BYTEOUT(hw
+ NE2000_RX_CONFIG
, RXCFG_BCAST
| RXCFG_MCAST
|
1296 ((ud
->ud_Flags
& UF_PROMISCUOUS
) ? RXCFG_PROM
: 0));
1297 BYTEOUT(hw
+ NE2000_INT_STATUS
, 0xFF);
1298 BYTEOUT(hw
+ NE2000_INT_MASK
, INTMASK
);
1306 void GoOffline(struct UnitData
*ud
)
1308 IPTR hw
= ud
->ud_Hardware
;
1310 BYTEOUT(hw
+ NE2000_COMMAND
, 0x21);
1311 BYTEOUT(hw
+ NE2000_TX_CONFIG
, 0x02);
1312 BYTEOUT(hw
+ NE2000_RX_CONFIG
, 0x20);
1313 BYTEOUT(hw
+ NE2000_INT_STATUS
, 0xFF);
1314 BYTEOUT(hw
+ NE2000_INT_MASK
, 0);
1315 RemoveInterrupt(ud
);
1322 void BoardShutdown(struct UnitData
*ud
)
1324 IPTR hw
= ud
->ud_Hardware
;
1327 BYTEOUT(hw
+ NE2000_INT_MASK
, 0);
1328 BYTEOUT(hw
+ NE2000_INT_STATUS
, 0xFF);
1333 /// GetPacketHeader()
1335 ULONG
GetPacketHeader(IPTR ne
, UBYTE page
)
1339 BYTEOUT(ne
+ NE2000_DMA_COUNTER0
, 4);
1340 BYTEOUT(ne
+ NE2000_DMA_COUNTER1
, 0);
1341 BYTEOUT(ne
+ NE2000_DMA_START_ADDR0
, 0);
1342 BYTEOUT(ne
+ NE2000_DMA_START_ADDR1
, page
);
1343 BYTEOUT(ne
+ NE2000_COMMAND
,
1344 COMMAND_PAGE0
| COMMAND_START
| COMMAND_READ
);
1345 hdr
= LEWORDIN(ne
+ NE2000_DMA_PORT
);
1346 hdr
|= LEWORDIN(ne
+ NE2000_DMA_PORT
) << 16;
1353 /*GetPacket(volatile struct Ne2000 *ne, UBYTE startpage, UWORD len, UWORD *buffer)*/
1354 VOID
GetPacket(IPTR ne
, UBYTE startpage
, UWORD len
, UWORD
*buffer
)
1358 BYTEOUT(ne
+ NE2000_DMA_COUNTER0
, len
& 0xFF);
1359 BYTEOUT(ne
+ NE2000_DMA_COUNTER1
, len
>> 8);
1360 BYTEOUT(ne
+ NE2000_DMA_START_ADDR0
, 4);
1361 BYTEOUT(ne
+ NE2000_DMA_START_ADDR1
, startpage
);
1362 BYTEOUT(ne
+ NE2000_COMMAND
, COMMAND_PAGE0
| COMMAND_START
| COMMAND_READ
);
1364 for (count
= (len
+ 1) >> 1; count
; count
--)
1366 *buffer
++ = WORDIN(ne
+ NE2000_DMA_PORT
);
1372 /// PacketReceived()
1374 LONG
PacketReceived(struct UnitData
*ud
)
1378 header
= GetPacketHeader(ud
->ud_Hardware
, ud
->ud_NextPage
);
1380 GetPacket(ud
->ud_Hardware
, ud
->ud_NextPage
, len
, (UWORD
*)ud
->ud_RxBuffer
);
1381 BYTEOUT(ud
->ud_Hardware
+ NE2000_BOUNDARY
, ud
->ud_NextPage
);
1382 ud
->ud_NextPage
= (header
>> 8) & 0xFF;
1383 BYTEOUT(ud
->ud_Hardware
+ NE2000_INT_STATUS
, INT_RXPACKET
);
1388 /// BufferOverflow()
1390 void BufferOverflow(struct UnitData
*ud
)
1392 struct Library
*DOSBase
= ud
->ud_DOSBase
;
1393 IPTR hw
= ud
->ud_Hardware
;
1394 UBYTE txp
, resent
= FALSE
, intstatus
;
1396 txp
= BYTEIN(hw
+ NE2000_COMMAND
) & COMMAND_TXP
;
1397 BYTEOUT(hw
+ NE2000_COMMAND
, COMMAND_PAGE0
| COMMAND_ABORT
| COMMAND_STOP
);
1399 BYTEOUT(hw
+ NE2000_DMA_COUNTER0
, 0);
1400 BYTEOUT(hw
+ NE2000_DMA_COUNTER1
, 0);
1404 intstatus
= BYTEIN(hw
+ NE2000_INT_STATUS
);
1405 if (!(intstatus
& (INT_TXPACKET
| INT_TXERROR
))) resent
= TRUE
;
1408 BYTEOUT(hw
+ NE2000_TX_CONFIG
, TXCFG_LOOP_INT
);
1409 BYTEOUT(hw
+ NE2000_COMMAND
,
1410 COMMAND_PAGE1
| COMMAND_ABORT
| COMMAND_START
);
1411 BYTEOUT(hw
+ NE2000_CURRENT_PAGE
, RX_BUFFER
);
1412 BYTEOUT(hw
+ NE2000_COMMAND
,
1413 COMMAND_PAGE0
| COMMAND_ABORT
| COMMAND_START
);
1414 BYTEOUT(hw
+ NE2000_BOUNDARY
, BUFFER_END
- 1);
1415 ud
->ud_NextPage
= RX_BUFFER
;
1417 BYTEOUT(hw
+ NE2000_TX_CONFIG
, TXCFG_LOOP_NONE
);
1418 if (resent
) BYTEOUT(hw
+ NE2000_COMMAND
, COMMAND_PAGE0
| COMMAND_START
|
1419 COMMAND_ABORT
| COMMAND_TXP
);
1420 BYTEOUT(hw
+ NE2000_INT_STATUS
, INT_OVERFLOW
);
1428 void SendPacket(struct UnitData
*ud
, struct IOSana2Req
*req
)
1432 IPTR hw
= ud
->ud_Hardware
;
1433 UBYTE ethbuffer
[1536], *datapointer
;
1434 UWORD
*ethdata
= (UWORD
*)ethbuffer
;
1435 ULONG data_len
= req
->ios2_DataLength
;
1438 /* If not raw packets, fill in Dst, Src and Type fields of Ethernet frame. 'datapointer' is a variable */
1439 /* holding address of data to copy from network stack. If packet is raw, datapointer points to start */
1440 /* of ethbuffer, otherwise points to ef_Data field (first byte after Ethernet header. */
1442 if (!(req
->ios2_Req
.io_Flags
& SANA2IOF_RAW
))
1444 struct EthFrame
*ef
= (struct EthFrame
*)ethbuffer
;
1446 CopyMem(req
->ios2_DstAddr
, ef
->ef_DestAddr
, 6);
1447 CopyMem(ud
->ud_EtherAddress
, ef
->ef_SrcAddr
, 6);
1448 ef
->ef_Type
= MakeBEWord(req
->ios2_PacketType
);
1449 datapointer
= ef
->ef_Data
;
1451 else datapointer
= ethbuffer
;
1453 /* Copy data from network stack using supplied CopyFrom() function. */
1456 AROS_UFC3(BOOL
, ((struct BuffFunctions
*)
1457 req
->ios2_BufferManagement
)->bf_CopyFrom
,
1458 AROS_UFCA(APTR
, datapointer
, A0
),
1459 AROS_UFCA(APTR
, req
->ios2_Data
, A1
),
1460 AROS_UFCA(ULONG
, data_len
, D0
));
1462 ((struct BuffFunctions
*)req
->ios2_BufferManagement
)->bf_CopyFrom(
1463 datapointer
, req
->ios2_Data
, data_len
);
1466 /* Now we need length of data to send to hardware. IORequest ios2_DataLength does not include header */
1467 /* length if packet is not RAW. So we should add it. */
1469 if (!(req
->ios2_Req
.io_Flags
& SANA2IOF_RAW
)) data_len
+= 14;
1471 /* Packet sent to Ethernet hardware should be at least 60 bytes long (4 bytes of CRC will be appended */
1472 /* by hardware giving 64 bytes). If our packet is shorter we should extend it with spaces. */
1474 while (data_len
< 60) ethbuffer
[data_len
++] = ' ';
1476 /* Now the packet is ready to send it to NIC buffer. It is done by Remote Write DMA command. Firstly */
1477 /* write address and counter should be initialized, then command register. */
1480 BYTEOUT(hw
+ NE2000_DMA_COUNTER0
, data_len
& 0xFF);
1481 BYTEOUT(hw
+ NE2000_DMA_COUNTER1
, data_len
>> 8);
1482 BYTEOUT(hw
+ NE2000_DMA_START_ADDR0
, 0);
1483 BYTEOUT(hw
+ NE2000_DMA_START_ADDR1
, TX_BUFFER
);
1484 BYTEOUT(hw
+ NE2000_COMMAND
,
1485 COMMAND_PAGE0
| COMMAND_START
| COMMAND_WRITE
);
1487 /* Now we can send packet data to DMAPort word by word. */
1489 for (cycles
= (data_len
+ 1) >> 1; cycles
; cycles
--)
1490 WORDOUT(hw
+ NE2000_DMA_PORT
, *ethdata
++);
1492 /* Send packet to the wire. Register setup first. */
1494 BYTEOUT(hw
+ NE2000_TX_PAGE_START
, TX_BUFFER
);
1495 BYTEOUT(hw
+ NE2000_TX_COUNTER0
, data_len
& 0xFF);
1496 BYTEOUT(hw
+ NE2000_TX_COUNTER1
, data_len
>> 8);
1498 /* Three, two, one, go! */
1500 BYTEOUT(hw
+ NE2000_COMMAND
,
1501 COMMAND_PAGE0
| COMMAND_START
| COMMAND_ABORT
| COMMAND_TXP
);
1504 /* OK. Packet was sent (successfully or not). Hardware will respond with TXPACKET or TXERROR interrupt */
1505 /* then we will be able to reply IORequest in the interrupt server. */
1507 DBG_T("Packet sent.");
1514 void GetHwAddress(struct UnitData
*ud
)
1517 IPTR hw
= ud
->ud_Hardware
;
1520 BYTEOUT(hw
+ NE2000_DMA_COUNTER0
, 6);
1521 BYTEOUT(hw
+ NE2000_DMA_COUNTER1
, 0);
1522 BYTEOUT(hw
+ NE2000_DMA_START_ADDR0
, 0);
1523 BYTEOUT(hw
+ NE2000_DMA_START_ADDR1
, 0);
1524 BYTEOUT(hw
+ NE2000_COMMAND
, COMMAND_READ
);
1525 for (i
= 0; i
< 6; i
++)
1526 ud
->ud_EtherAddress
[i
] = WORDIN(hw
+ NE2000_DMA_PORT
);
1529 DBG_U("\thardware address (read):");
1530 for (i
= 0; i
< 6; i
++) DBG1_U("\t%02lx", ud
->ud_EtherAddress
[i
]);
1537 /// WriteHwAddress()
1539 void WriteHwAddress(struct UnitData
*ud
)
1542 IPTR hw
= ud
->ud_Hardware
;
1546 DBG_U("\thardware address (write):");
1547 for (i
= 0; i
< 6; i
++) DBG1_U("\t%02lx", ud
->ud_SoftAddress
[i
]);
1550 BYTEOUT(hw
+ NE2000_COMMAND
,
1551 COMMAND_PAGE1
| COMMAND_ABORT
| COMMAND_STOP
);
1552 for (i
= 0; i
< 6; i
++)
1554 BYTEOUT(hw
+ NE2000_PHYSICAL_ADDR0
+ i
, ud
->ud_SoftAddress
[i
]);
1556 BYTEOUT(hw
+ NE2000_COMMAND
,
1557 COMMAND_PAGE0
| COMMAND_ABORT
| COMMAND_STOP
);
1562 /// RingBufferNotEmpty()
1564 LONG
RingBufferNotEmpty(struct UnitData
*ud
)
1567 IPTR hw
= ud
->ud_Hardware
;
1569 BYTEOUT(hw
+ NE2000_COMMAND
,
1570 COMMAND_PAGE1
| COMMAND_ABORT
| COMMAND_START
);
1571 current
= BYTEIN(hw
+ NE2000_CURRENT_PAGE
);
1572 BYTEOUT(hw
+ NE2000_COMMAND
,
1573 COMMAND_PAGE0
| COMMAND_ABORT
| COMMAND_START
);
1575 if (ud
->ud_NextPage
== current
) return FALSE
;
1583 /// SearchReadRequest()
1585 struct IOSana2Req
*SearchReadRequest(struct UnitData
*ud
,
1586 struct MinList
*queue
, ULONG type
)
1588 struct Library
*SysBase
= ud
->ud_SysBase
;
1589 struct IOSana2Req
*req
, *found
= NULL
/*, *x*/ ;
1591 for (req
= (struct IOSana2Req
*)queue
->mlh_Head
;
1592 req
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
1593 req
= (struct IOSana2Req
*)req
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
)
1595 if (req
->ios2_PacketType
== type
)
1597 Remove((struct Node
*)req
);
1608 void FlushQueues(struct UnitData
*ud
)
1612 struct IOSana2Req
*xreq
;
1617 xreq
= (struct IOSana2Req
*)RemHead((struct List
*)&ud
->ud_RxQueue
);
1620 DBG1_T("<- READ [$08%lx] [F].", xreq
);
1621 IoDone(ud
, xreq
, IOERR_ABORTED
, S2WERR_GENERIC_ERROR
);
1627 xreq
= (struct IOSana2Req
*)RemHead((struct List
*)&ud
->ud_TxQueue
);
1630 DBG1_T("<- WRITE [$08%lx] [F].", xreq
);
1631 IoDone(ud
, xreq
, IOERR_ABORTED
, S2WERR_GENERIC_ERROR
);
1639 void MainLoop(struct UnitData
*ud
, struct MsgPort
*port
)
1643 ULONG signals
, sigmask
;
1644 struct IOSana2Req
*req
;
1647 UBYTE wname
[60], *ptr
;
1649 ptr
= strcpy(wname
, "CON:400/17/400/300/");
1650 ptr
= strcpy(ptr
, ud
->ud_Name
);
1651 strcpy(ptr
,"/AUTO/CLOSE/WAIT");
1652 ud
->tdebug
= Open(wname
, MODE_NEWFILE
);
1655 sigmask
= 1 << port
->mp_SigBit
;
1658 DBG_T("Waiting...");
1659 signals
= Wait(SIGBREAKF_CTRL_C
| sigmask
| ud
->ud_GoWriteMask
);
1661 if (signals
& ud
->ud_GoWriteMask
)
1665 req
= (struct IOSana2Req
*)RemHead((struct List
*)&ud
->ud_TxQueue
);
1667 ud
->ud_PendingWrite
= req
;
1668 if (req
) SendPacket(ud
, req
);
1671 if (signals
& SIGBREAKF_CTRL_C
)
1673 DBG1_T("TASK: %s task killed.", ud
->ud_Name
);
1677 if (signals
& sigmask
)
1679 struct IOSana2Req
*req
;
1682 while (req
= (struct IOSana2Req
*)GetMsg(port
))
1684 switch (req
->ios2_Req
.io_Command
)
1687 DBG1_T("-> READ [$%08lx].", req
);
1689 AddTail((struct List
*)&ud
->ud_RxQueue
, (struct Node
*)req
);
1695 DBG1_T("-> WRITE [$%08lx].", req
);
1696 if (ud
->ud_PendingWrite
)
1699 AddTail((struct List
*)&ud
->ud_TxQueue
, (struct Node
*)req
);
1704 ud
->ud_PendingWrite
= req
;
1705 SendPacket(ud
, req
);
1706 DBG_T("Packet sent 2.");
1711 DBG1_T("-> FLUSH [$%08lx].", req
);
1713 DBG1_T("<- FLUSH [$%08lx].", req
);
1714 IoDone(ud
, req
, OK
, OK
);
1718 DBG2_T("-> Unknown ($%lx) [$%08lx].", req
->ios2_Req
.io_Command
, req
);
1730 struct Library
*SysBase
;
1732 struct MsgPort
*port
;
1733 struct UnitData
*ud
;
1736 struct Library
*DOSBase
;
1742 SysBase
= *(struct Library
**)4;
1744 task
= FindTask(NULL
);
1745 if (port
= CreateMsgPort())
1747 port
->mp_Node
.ln_Name
= task
->tc_Node
.ln_Name
;
1748 port
->mp_Node
.ln_Pri
= 20;
1752 ud
= (struct UnitData
*)GetMsg(port
);
1753 if ((ud
->ud_GoWriteBit
= AllocSignal(-1)) != -1)
1755 ud
->ud_GoWriteMask
= 1 << ud
->ud_GoWriteBit
;
1757 FreeSignal(ud
->ud_GoWriteBit
);
1759 DeleteMsgPort(port
);
1761 ReplyMsg(&ud
->ud_Message
);