From e68c1ec8c68f79c49454328a0035fd1c26d65b4d Mon Sep 17 00:00:00 2001 From: Marcin Bzdulski Date: Mon, 2 Nov 2026 13:12:04 +0100 Subject: [PATCH] fresh commit --- Devs/networks/3c589.device | Bin 0 -> 9292 bytes GPL | 340 ++++++ Install | 43 + Install.info | Bin 0 -> 2583 bytes Libs/pccard.library | Bin 0 -> 5420 bytes Manual | 234 ++++ Manual.info | Bin 0 -> 2433 bytes Read Me | 20 + Read Me.info | Bin 0 -> 1783 bytes Source.info | Bin 0 -> 2762 bytes Source/Makefile | 31 + Source/Notes | 27 + Source/device.c | 651 +++++++++++ Source/device.h | 257 +++++ Source/etherlink3.h | 320 ++++++ Source/initializers.h | 105 ++ Source/request.c | 1523 +++++++++++++++++++++++++ Source/request_protos.h | 36 + Source/unit.c | 2166 ++++++++++++++++++++++++++++++++++++ Source/unit_protos.h | 49 + 20 files changed, 5802 insertions(+) create mode 100644 Devs/networks/3c589.device create mode 100644 GPL create mode 100644 Install create mode 100644 Install.info create mode 100644 Libs/pccard.library create mode 100644 Manual create mode 100644 Manual.info create mode 100644 Read Me create mode 100644 Read Me.info create mode 100644 Source.info create mode 100644 Source/Makefile create mode 100644 Source/Notes create mode 100644 Source/device.c create mode 100644 Source/device.h create mode 100644 Source/etherlink3.h create mode 100644 Source/initializers.h create mode 100644 Source/request.c create mode 100644 Source/request_protos.h create mode 100644 Source/unit.c create mode 100644 Source/unit_protos.h diff --git a/Devs/networks/3c589.device b/Devs/networks/3c589.device new file mode 100644 index 0000000000000000000000000000000000000000..091dc4a6899d9d3e7984a4a457a6c7d333989364 GIT binary patch literal 9292 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 PfYV<;Qv#k>VeWqe+R3?h literal 0 HcmV?d00001 diff --git a/GPL b/GPL new file mode 100644 index 0000000..60549be --- /dev/null +++ b/GPL @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Install b/Install new file mode 100644 index 0000000..ad597c9 --- /dev/null +++ b/Install @@ -0,0 +1,43 @@ +; Installer for 3c589.device. +; Copyright © 2003 Neil Cafferkey. +; $VER: "Install 3c589.device" 1.2 (25.2.2004) + + +; Set constants + +(set #kick-too-low-msg "Kickstart 2.05 or greater is required.") + +(set #dev-name "3c589.device") +(set #devs-source "Devs/networks") +(set @default-dest "DEVS:networks") +(set #pccard-name "pccard.library") +(set #libs-source "Libs") +(set #libs-dest "LIBS:") + + +; Check Kickstart version + +(if (< (/ (getversion) 65536) 37) + (abort #kick-too-low-msg) +) + + +; Install pccard.library + +(copylib + (source (tackon #libs-source #pccard-name)) + (dest #libs-dest) +; (newname #dev-name) + (help @copylib-help) +) + + +; Install device + +(copylib + (source (tackon #devs-source #dev-name)) + (dest @default-dest) + (help @copylib-help) +) + + diff --git a/Install.info b/Install.info new file mode 100644 index 0000000000000000000000000000000000000000..345717cd2fb33f20c2cc9a18791cf2c32403fed2 GIT binary patch literal 2583 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 literal 0 HcmV?d00001 diff --git a/Read Me b/Read Me new file mode 100644 index 0000000..5e02214 --- /dev/null +++ b/Read Me @@ -0,0 +1,20 @@ +Short: Driver for 3Com PCMCIA network cards +Author: caffer@cs.ucc.ie (Neil Cafferkey) +Uploader: caffer@cs.ucc.ie (Neil Cafferkey) +Version: 1.5 +Type: driver/net +Requires: A1200 or A600, compatible card +Architecture: m68k-amigaos >= 2.0.0 + +3c589.device is a SANA-II network driver for 3Com Etherlink III PC Cards +(PCMCIA cards). Note that not all 3Com cards work with this driver, and that +some compatible cards are rebranded by other manufacturers. See the +documentation in the archive for a list of compatible cards. In short, +10 Mbps cards work; 100 Mbps cards do not. + +This package is released under the GNU General Public Licence. + +Changes in this version: + + - Fixed lock-up when closing device under AmigaOS 4.0. + diff --git a/Read Me.info b/Read Me.info new file mode 100644 index 0000000000000000000000000000000000000000..8c668c80c6115ee8484eabdb7576142c7b2ffd6f GIT binary patch literal 1783 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 literal 0 HcmV?d00001 diff --git a/Source/Makefile b/Source/Makefile new file mode 100644 index 0000000..aec3019 --- /dev/null +++ b/Source/Makefile @@ -0,0 +1,31 @@ +# File: Makefile + +CFLAGS = -msmall-code -O3 -ansi -Wall -Wno-uninitialized -Wno-parentheses +CC = gcc $(CFLAGS) +MAKEFILE = Makefile +LINKER = ld -e _Main -s +AMIGA_LIB = GG:lib/libamiga.a +C_LIB = GG:lib/libnix/libnix13.a + +DEV_NAME = 3c589.device +OBJS = device.o unit.o request.o +HDRS = device.h + +.c.o : + $(CC) -c $< + +$(DEV_NAME): $(MAKEFILE) $(OBJS) + $(LINKER) $(OBJS) $(AMIGA_LIB) $(C_LIB) -o $(DEV_NAME) + Protect "$(DEV_NAME)" "-e" + +$(OBJS): $(MAKEFILE) $(HDRS) + +unit.o: etherlink3.h + +install: $(DEV_NAME) + Copy CLONE "$(DEV_NAME)" "DEVS:networks/" + Flush "$(DEV_NAME)" + +clean: + Delete "$(DEV_NAME)" "#?.o" + diff --git a/Source/Notes b/Source/Notes new file mode 100644 index 0000000..2a59821 --- /dev/null +++ b/Source/Notes @@ -0,0 +1,27 @@ + +DESIGN NOTES: + + - Type tracking has been implemented in an unusual way in order to make it + more suitable for multiple users. Each client that tracks a particular + packet type is given the impression that it is the only one doing so. + When a client begins tracking a packet type that is already being + tracked, the current packet statistics are recorded internally. These + initial statistics are then subtracted from the figures returned from + every S2_GETTYPESTATS call the client makes. + - The cards' 8-bit statistics registers appear to be unreadable using the + A1200's PCMCIA slot. + - S2_CopyToBuff32 functions are not used because the non-raw portion of + received packets is not 32-bit aligned. + + +TCP/IP STACK BUGS TO CONSIDER: + + - Miami(DX) doesn't like requests being aborted upon S2_OFFLINE. + - MiamiDX's CopyFromBuff16/32 functions appear to be broken. + - Genesis calls S2_ONLINE before S2_CONFIGINTERFACE? + - When a device goes back online without Genesis's intervention, Genesis + displays the message "eth0 is online again" or similar, but keeps the + interface's indicator red and doesn't disable the "Online" button or + enable the "Offline" button. + + diff --git a/Source/device.c b/Source/device.c new file mode 100644 index 0000000..9903b31 --- /dev/null +++ b/Source/device.c @@ -0,0 +1,651 @@ +/* + +File: device.c +Author: Neil Cafferkey +Copyright (C) 2000-2010 Neil Cafferkey + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. + +*/ + + +#include +#include +#include +#include +#include "initializers.h" + +#include +#include +#include + +#include "device.h" + +#include "unit_protos.h" +#include "request_protos.h" + +#define VERSION 1 +#define REVISION 5 +#define UNIT_COUNT 1 +#define UTILITY_VERSION 36 +#define PCCARD_VERSION 1 + + +/* Private prototypes */ + +static struct DevBase *DevInit(struct DevBase *dev_base REG("d0"), + APTR seg_list REG("a0"),struct DevBase *base REG(BASE_REG)); +static BYTE DevOpen(ULONG unit_no REG("d0"), + struct IOSana2Req *request REG("a1"),ULONG flags REG("d1"), + struct DevBase *base REG(BASE_REG)); +static APTR DevClose(struct IOSana2Req *request REG("a1"), + struct DevBase *base REG(BASE_REG)); +static APTR DevExpunge(struct DevBase *base REG(BASE_REG)); +static APTR DevReserved(); +static VOID DevBeginIO(struct IOSana2Req *request REG("a1"), + struct DevBase *base REG(BASE_REG)); +static VOID DevAbortIO(struct IOSana2Req *request REG("a1"), + struct DevBase *base REG(BASE_REG)); +VOID DeleteDevice(struct DevBase *base); + +extern const APTR vectors[]; +extern const APTR init_table[]; + + +/* Return an error immediately if someone tries to run the device */ + +LONG Main() +{ + return -1; +} + +#define DEVICE_NAME "3c589.device" + +const TEXT device_name[]=DEVICE_NAME; +static const TEXT version_string[]=DEVICE_NAME " 1.5 (3.2.2010)\n"; +static const TEXT card_name[]=CARDRESNAME; +static const TEXT utility_name[]=UTILITYNAME; +static const TEXT pccard_name[]=PCCARDNAME; +static const TEXT timer_name[]=TIMERNAME; + + +const struct Resident device_rom_tag= +{ + RTC_MATCHWORD, + (struct Resident *)&device_rom_tag, + (APTR)init_table, + RTF_AUTOINIT, + VERSION, + NT_DEVICE, + 0, + (STRPTR)device_name, + (STRPTR)version_string, + (APTR)init_table +}; + + +static const APTR vectors[]= +{ + (APTR)DevOpen, + (APTR)DevClose, + (APTR)DevExpunge, + (APTR)DevReserved, + (APTR)DevBeginIO, + (APTR)DevAbortIO, + (APTR)-1 +}; + + +static const struct +{ + SMALLINITBYTEDEF(type); + SMALLINITPINTDEF(name); + SMALLINITBYTEDEF(flags); + SMALLINITWORDDEF(version); + SMALLINITWORDDEF(revision); + SMALLINITPINTDEF(id_string); + INITENDDEF; +} +init_data= +{ + SMALLINITBYTE(OFFSET(Node,ln_Type),NT_DEVICE), + SMALLINITPINT(OFFSET(Node,ln_Name),device_name), + SMALLINITBYTE(OFFSET(Library,lib_Flags),LIBF_SUMUSED|LIBF_CHANGED), + SMALLINITWORD(OFFSET(Library,lib_Version),VERSION), + SMALLINITWORD(OFFSET(Library,lib_Revision),REVISION), + SMALLINITPINT(OFFSET(Library,lib_IdString),version_string), + INITEND +}; + + +static const APTR init_table[]= +{ + (APTR)sizeof(struct DevBase), + (APTR)vectors, + (APTR)&init_data, + (APTR)DevInit +}; + + +static const ULONG rx_tags[]= +{ + S2_CopyToBuff, + S2_CopyToBuff16 +}; + + +static const ULONG tx_tags[]= +{ + S2_CopyFromBuff, + S2_CopyFromBuff16, + S2_CopyFromBuff32 +}; + + + +/****i* 3c589.device/DevInit *********************************************** +* +* NAME +* DevInit -- . +* +* SYNOPSIS +* dev_base = DevInit(dev_base,seg_list) +* +* struct DevBase *DevInit(struct DevBase *,APTR); +* +* FUNCTION +* +* INPUTS +* +* RESULT +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static struct DevBase *DevInit(struct DevBase *dev_base REG("d0"), + APTR seg_list REG("a0"),struct DevBase *base REG(BASE_REG)) +{ + BOOL success=TRUE; + + dev_base->sys_base=(APTR)base; + base=dev_base; + base->seg_list=seg_list; + + base->card_base=OpenResource(card_name); + base->utility_base=(APTR)OpenLibrary(utility_name,UTILITY_VERSION); + base->pccard_base=OpenLibrary(pccard_name,PCCARD_VERSION); + if((base->card_base==NULL)||(base->utility_base==NULL)|| + (base->pccard_base==NULL)) + success=FALSE; + + if(OpenDevice(timer_name,UNIT_VBLANK,(APTR)&base->timer_request,0)!=0) + success=FALSE; + + NewList((APTR)(&dev_base->units)); + + if(!success) + { + DeleteDevice(base); + base=NULL; + } + + return base; +} + + + +/****i* 3c589.device/DevOpen *********************************************** +* +* NAME +* DevOpen -- . +* +* SYNOPSIS +* error = DevOpen(unit_num,request,flags) +* +* BYTE DevOpen(ULONG,struct IOSana2Req *,ULONG); +* +* FUNCTION +* +* INPUTS +* +* RESULT +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BYTE DevOpen(ULONG unit_num REG("d0"), + struct IOSana2Req *request REG("a1"),ULONG flags REG("d1"), + struct DevBase *base REG(BASE_REG)) +{ + struct DevUnit *unit; + BYTE error=0; + struct Opener *opener; + struct TagItem *tag_list; + UWORD i; + + base->device.dd_Library.lib_OpenCnt++; + base->device.dd_Library.lib_Flags&=~LIBF_DELEXP; + + request->ios2_Req.io_Unit=NULL; + tag_list=request->ios2_BufferManagement; + request->ios2_BufferManagement=NULL; + + /* Check request size and unit number */ + + if((request->ios2_Req.io_Message.mn_Length=UNIT_COUNT)) + error=IOERR_OPENFAIL; + + /* Get the requested unit */ + + if(error==0) + { + request->ios2_Req.io_Unit=(APTR)unit=GetUnit(unit_num,base); + if(unit==NULL) + error=IOERR_OPENFAIL; + } + + /* Handle device sharing */ + + if(error==0) + { + if((unit->open_count!=0)&&(((unit->flags&UNITF_SHARED)==0)|| + ((flags&SANA2OPF_MINE)!=0))) + error=IOERR_UNITBUSY; + unit->open_count++; + } + + if(error==0) + { + if((flags&SANA2OPF_MINE)==0) + unit->flags|=UNITF_SHARED; + else if((flags&SANA2OPF_PROM)!=0) + unit->flags|=UNITF_PROM; + + /* Set up buffer-management structure and get hooks */ + + request->ios2_BufferManagement=opener= + AllocVec(sizeof(struct Opener),MEMF_PUBLIC); + if(opener==NULL) + error=IOERR_OPENFAIL; + } + + if(error==0) + { + NewList(&opener->read_port.mp_MsgList); + opener->read_port.mp_Flags=PA_IGNORE; + NewList((APTR)&opener->initial_stats); + + for(i=0;i<2;i++) + opener->rx_function=(APTR)GetTagData(rx_tags[i], + (UPINT)opener->rx_function,tag_list); + for(i=0;i<3;i++) + opener->tx_function=(APTR)GetTagData(tx_tags[i], + (UPINT)opener->tx_function,tag_list); + + opener->filter_hook=(APTR)GetTagData(S2_PacketFilter,NULL,tag_list); + opener->dma_tx_function= + (APTR)GetTagData(S2_DMACopyFromBuff32,NULL,tag_list); + + Disable(); + AddTail((APTR)&unit->openers,(APTR)opener); + Enable(); + } + + /* Back out if anything went wrong */ + + if(error!=0) + DevClose(request,base); + + /* Return */ + + request->ios2_Req.io_Error=error; + return error; +} + + + +/****i* 3c589.device/DevClose ********************************************** +* +* NAME +* DevClose -- . +* +* SYNOPSIS +* seg_list = DevClose(request) +* +* APTR DevClose(struct IOSana2Req *); +* +* FUNCTION +* +* INPUTS +* +* RESULT +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static APTR DevClose(struct IOSana2Req *request REG("a1"), + struct DevBase *base REG(BASE_REG)) +{ + struct DevUnit *unit; + APTR seg_list; + struct Opener *opener; + + /* Free buffer-management resources */ + + opener=(APTR)request->ios2_BufferManagement; + if(opener!=NULL) + { + Disable(); + Remove((APTR)opener); + Enable(); + FreeVec(opener); + } + + /* Delete the unit if it's no longer in use */ + + unit=(APTR)request->ios2_Req.io_Unit; + if(unit!=NULL) + { + if((--unit->open_count)==0) + { + Remove((APTR)unit); + DeleteUnit(unit,base); + } + } + + /* Expunge the device if a delayed expunge is pending */ + + seg_list=NULL; + + if((--base->device.dd_Library.lib_OpenCnt)==0) + { + if((base->device.dd_Library.lib_Flags&LIBF_DELEXP)!=0) + seg_list=DevExpunge(base); + } + + return seg_list; +} + + + +/****i* 3c589.device/DevExpunge ******************************************** +* +* NAME +* DevExpunge -- . +* +* SYNOPSIS +* seg_list = DevExpunge() +* +* APTR DevExpunge(VOID); +* +* FUNCTION +* +* INPUTS +* +* RESULT +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static APTR DevExpunge(struct DevBase *base REG(BASE_REG)) +{ + APTR seg_list; + + if(base->device.dd_Library.lib_OpenCnt==0) + { + seg_list=base->seg_list; + Remove((APTR)base); + DeleteDevice(base); + } + else + { + base->device.dd_Library.lib_Flags|=LIBF_DELEXP; + seg_list=NULL; + } + + return seg_list; +} + + + +/****i* 3c589.device/DevReserved ******************************************* +* +* NAME +* DevReserved -- . +* +* SYNOPSIS +* result = DevReserved() +* +* APTR DevReserved(VOID); +* +* FUNCTION +* +* INPUTS +* +* RESULT +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static APTR DevReserved() +{ + return NULL; +} + + + +/****i* 3c589.device/DevBeginIO ******************************************** +* +* NAME +* DevBeginIO -- . +* +* SYNOPSIS +* DevBeginIO(request) +* +* VOID DevBeginIO(struct IORequest *); +* +* FUNCTION +* +* INPUTS +* +* RESULT +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static VOID DevBeginIO(struct IOSana2Req *request REG("a1"), + struct DevBase *base REG(BASE_REG)) +{ + struct DevUnit *unit; + + request->ios2_Req.io_Error=0; + unit=(APTR)request->ios2_Req.io_Unit; + + if(AttemptSemaphore(&unit->access_lock)) + ServiceRequest(request,base); + else + { + PutRequest(unit->request_ports[GENERAL_QUEUE],(APTR)request,base); + } + + return; +} + + + +/****i* 3c589.device/DevAbortIO ******************************************** +* +* NAME +* DevAbortIO -- Try to stop a request. +* +* SYNOPSIS +* DevAbortIO(request) +* +* VOID DevAbortIO(struct IOSana2Req *); +* +* FUNCTION +* Do our best to halt the progress of a request. +* +* INPUTS +* +* RESULT +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +* Disable() used instead of a semaphore because device uses interrupts. +* +*/ + +static VOID DevAbortIO(struct IOSana2Req *request REG("a1"), + struct DevBase *base REG(BASE_REG)) +{ + struct DevUnit *unit; + + unit=(APTR)request->ios2_Req.io_Unit; + + Disable(); + if((request->ios2_Req.io_Message.mn_Node.ln_Type==NT_MESSAGE) + &&((request->ios2_Req.io_Flags&IOF_QUICK)==0)) + { + Remove((APTR)request); + request->ios2_Req.io_Error=IOERR_ABORTED; + request->ios2_WireError=S2WERR_GENERIC_ERROR; + ReplyMsg((APTR)request); + } + Enable(); + + return; +} + + + +/****i* 3c589.device/DeleteDevice ****************************************** +* +* NAME +* DeleteDevice -- . +* +* SYNOPSIS +* DeleteDevice() +* +* VOID DeleteDevice(VOID); +* +* FUNCTION +* +* INPUTS +* +* RESULT +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +VOID DeleteDevice(struct DevBase *base) +{ + UWORD neg_size,pos_size; + + /* Close devices */ + + CloseDevice((APTR)&base->timer_request); + + /* Close libraries */ + + if(base->pccard_base!=NULL) + CloseLibrary(base->pccard_base); + if(base->utility_base!=NULL) + CloseLibrary((APTR)base->utility_base); + + /* Free device's memory */ + + neg_size=base->device.dd_Library.lib_NegSize; + pos_size=base->device.dd_Library.lib_PosSize; + FreeMem((UBYTE *)base-neg_size,pos_size+neg_size); + + return; +} + + + diff --git a/Source/device.h b/Source/device.h new file mode 100644 index 0000000..6184048 --- /dev/null +++ b/Source/device.h @@ -0,0 +1,257 @@ +/* + +Copyright (C) 2001-2004 Neil Cafferkey + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. + +*/ + +#ifndef DEVICE_H +#define DEVICE_H + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef UPINT +typedef ULONG UPINT; +typedef LONG PINT; +#endif + +#ifdef __mc68000 +#define REG(A) __asm(A) +#else +#define REG(A) +#endif + +#define USE_HACKS + + +struct DevBase +{ + struct Device device; + APTR seg_list; + struct ExecBase *sys_base; + APTR card_base; + struct UtilityBase *utility_base; + struct Library *pccard_base; + struct MinList units; + struct timerequest timer_request; +}; + + +enum +{ + WRITE_QUEUE, + ADOPT_QUEUE, + EVENT_QUEUE, + GENERAL_QUEUE, + REQUEST_QUEUE_COUNT +}; + +#define ADDRESS_SIZE 6 +#define HEADER_SIZE 14 +#define PREAMBLE_SIZE 4 +#define PACKET_DEST 0 +#define PACKET_SOURCE 6 +#define PACKET_TYPE 12 +#define PACKET_DATA 14 +#define MTU 1500 +#define MAX_PACKET_SIZE ((HEADER_SIZE)+(MTU)) + +#define STAT_COUNT 3 + + +struct DevUnit +{ + struct MinNode node; + ULONG unit_num; + ULONG open_count; + UWORD flags; + UWORD transceiver; + struct Task *task; + struct MsgPort *request_ports[REQUEST_QUEUE_COUNT]; + struct DevBase *device; + struct CardHandle *card_handle; + UBYTE *tuple_buffer; + UBYTE *rx_buffer; + UBYTE *tx_buffer; + volatile UBYTE *config_base; + volatile UBYTE *io_base; + ULONG card_removed_signal; + ULONG card_inserted_signal; + ULONG range_count; + UBYTE address[ADDRESS_SIZE]; + UBYTE default_address[ADDRESS_SIZE]; + struct MinList openers; + struct MinList type_trackers; + struct MinList multicast_ranges; + struct Interrupt rx_int; + struct Interrupt tx_int; + struct Sana2DeviceStats stats; + ULONG special_stats[STAT_COUNT]; + struct SignalSemaphore access_lock; + UWORD rx_filter_cmd; +}; + + +struct Opener +{ + struct MinNode node; + struct MsgPort read_port; + BOOL (*rx_function)(APTR REG("a0"),APTR REG("a1"),ULONG REG("d0")); + BOOL (*tx_function)(APTR REG("a0"),APTR REG("a1"),ULONG REG("d0")); + ULONG *(*dma_tx_function)(APTR REG("a0")); + struct Hook *filter_hook; + struct MinList initial_stats; +}; + + +struct TypeStats +{ + struct MinNode node; + ULONG packet_type; + struct Sana2PacketTypeStats stats; +}; + + +struct TypeTracker +{ + struct MinNode node; + ULONG packet_type; + struct Sana2PacketTypeStats stats; + ULONG user_count; +}; + + +struct AddressRange +{ + struct MinNode node; + ULONG add_count; + ULONG lower_bound_left; + ULONG upper_bound_left; + UWORD lower_bound_right; + UWORD upper_bound_right; +}; + + +/* Unit flags */ + +#define UNITF_SHARED (1<<0) +#define UNITF_ONLINE (1<<1) +#define UNITF_HAVECARD (1<<2) +#define UNITF_HAVEADAPTER (1<<3) +#define UNITF_CONFIGURED (1<<4) +#define UNITF_PROM (1<<5) +#define UNITF_ROADRUNNER (1<<6) + + +IMPORT const TEXT device_name[]; + +#define HANDLE_PRIORITY 10 + +#define S2_3C589_WRITEEEPROM 0x998f + + +/* Endianness macros */ + +#define BEWord(A)\ + (A) + +#define MakeBEWord(A)\ + BEWord(A) + +#define LEWord(A)\ + ({\ + UWORD _LEWord_A=(A);\ + _LEWord_A=((_LEWord_A)<<8)|((_LEWord_A)>>8);\ + }) + +#define MakeLEWord(A)\ + LEWord(A) + +#define BELong(A)\ + (A) + +#define LELong(A)\ + ({\ + ULONG _LELong_A=(A);\ + _LELong_A=(LEWord(_LELong_A)<<16)|LEWord((_LELong_A)>>16);\ + }) + +#define MakeLELong(A)\ + LELong(A) + + +/* I/O macros */ + +#define ByteIn(address)\ + (*((volatile UBYTE *)(address))) + +#define ByteOut(address,value)\ + *((volatile UBYTE *)(address))=(value) + +#define WordIn(address)\ + (*((volatile UWORD *)(address))) + +#define WordOut(address,value)\ + *((volatile UWORD *)(address))=(value) + +#define LongIn(address)\ + (*((volatile ULONG *)(address))) + +#define LongOut(address,value)\ + *((volatile ULONG *)(address))=(value) + +#define LEWordIn(address)\ + LEWord(WordIn(address)) + +#define LEWordOut(address,value)\ + WordOut(address,MakeLEWord(value)) + +#define LELongIn(address)\ + LELong(LongIn(address)) + +#define LELongOut(address,value)\ + LongOut(address,MakeLELong(value)) + +#define BEWordOut(address,value)\ + WordOut(address,MakeBEWord(value)) + + +/* Library and device bases */ + +#define SysBase (base->sys_base) +#define CardResource (base->card_base) +#define UtilityBase (base->utility_base) +#define PCCardBase (base->pccard_base) +#define TimerBase (base->timer_request.tr_node.io_Device) + +#ifndef BASE_REG +#define BASE_REG "a6" +#endif + +/*register APTR base asm(BASE_REG);*/ + + +#endif diff --git a/Source/etherlink3.h b/Source/etherlink3.h new file mode 100644 index 0000000..164700d --- /dev/null +++ b/Source/etherlink3.h @@ -0,0 +1,320 @@ +/* + +Copyright (C) 2002 Neil Cafferkey + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. + +*/ + +#ifndef ETHERLINK3_H +#define ETHERLINK3_H + + +/* Registers */ +/* ========= */ + +/* All Windows */ + +#define EL3REG_COMMAND 14 +#define EL3REG_STATUS 14 + +/* Window 0 */ + +#define EL3REG_MAKERID 0 +#define EL3REG_PRODUCTID 2 +#define EL3REG_ADAPTERID 2 +#define EL3REG_CONFIG 4 +#define EL3REG_ADDRCONFIG 6 +#define EL3REG_RESCONFIG 8 /* also in window 3 */ +#define EL3REG_EEPROMCMD 10 /* window 2 has alternative version */ +#define EL3REG_EEPROMDATA 12 + +/* Window 1 */ + +#define EL3REG_DATA0 0 +#define EL3REG_DATA1 2 +#define EL3REG_RXSTATUS 8 +#define EL3REG_TIMER 10 +#define EL3REG_TXSTATUS 11 +#define EL3REG_TXSPACE 12 /* also in window 3 */ + +/* Window 2 */ + +#define EL3REG_ADDRESS0 0 +#define EL3REG_ADDRESS1 1 +#define EL3REG_ADDRESS2 2 +#define EL3REG_ADDRESS3 3 +#define EL3REG_ADDRESS4 4 +#define EL3REG_ADDRESS5 5 +#define EL3REG_SRAMDIAG 6 +#define EL3REG_MULTIFUNCCONFIG 8 +#define EL3REG_ALTEEPROMCMD 10 + +/* Window 3 */ + +#define EL3REG_ROMCONTROL 4 +#define EL3REG_TXRECLAIM 6 +#define EL3REG_RXSPACE 10 + +/* Window 4 */ + +#define EL3REG_FIFODIAG 4 +#define EL3REG_NETDIAG 6 +#define EL3REG_CONTROLLERSTATUS 8 +#define EL3REG_MEDIA 10 + +/* Window 5 */ + +#define EL3REG_TXSTARTTHRESH 0 +#define EL3REG_TXAVAILTHRESH 2 +#define EL3REG_RXEARLYTHRESH 6 +#define EL3REG_RXFILTER 8 +#define EL3REG_INTMASK 10 +#define EL3REG_READZEROMASK 12 + + +/* (Some) EEPROM data offsets */ +/* ========================== */ + +#define EL3EEPROM_ADDRESS0 0 +#define EL3EEPROM_ADDRESS1 1 +#define EL3EEPROM_ADDRESS2 2 +#define EL3EEPROM_PRODUCTID 3 +#define EL3EEPROM_MANFDATA0 4 +#define EL3EEPROM_MANFDATA1 5 +#define EL3EEPROM_MANFDATA2 6 +#define EL3EEPROM_MAKERID 7 +#define EL3EEPROM_ADDRCONFIG 8 +#define EL3EEPROM_RESCONFIG 9 +#define EL3EEPROM_ALTADDRESS0 10 +#define EL3EEPROM_ALTADDRESS1 11 +#define EL3EEPROM_ALTADDRESS2 12 +#define EL3EEPROM_SOFTWAREINFO 13 +#define EL3EEPROM_COMPATIBILITY 14 +#define EL3EEPROM_CHECKSUM 15 + + +/* EEPROM commands */ +/* =============== */ + +#define EL3ECMD_WRITEDISABLE (0x0<<4) +#define EL3ECMD_WRITEALL (0x1<<4) +#define EL3ECMD_ERASEALL (0x2<<4) +#define EL3ECMD_WRITEENABLE (0x3<<4) +#define EL3ECMD_WRITE (0x4<<4) +#define EL3ECMD_READ (0x8<<4) +#define EL3ECMD_ERASE (0xc<<4) + + +/* Commands */ +/* ======== */ + +#define EL3CMD_GLOBALRESET (0<<11) +#define EL3CMD_SELECTWINDOW (1<<11) +#define EL3CMD_STARTCOAX (2<<11) +#define EL3CMD_RXDISABLE (3<<11) +#define EL3CMD_RXENABLE (4<<11) +#define EL3CMD_RXRESET (5<<11) +#define EL3CMD_RXDISCARD (8<<11) +#define EL3CMD_TXENABLE (9<<11) +#define EL3CMD_TXDISABLE (10<<11) +#define EL3CMD_TXRESET (11<<11) +#define EL3CMD_REQINT (12<<11) +#define EL3CMD_ACKINT (13<<11) +#define EL3CMD_SETINTMASK (14<<11) +#define EL3CMD_SETZEROMASK (15<<11) +#define EL3CMD_SETRXFILTER (16<<11) +#define EL3CMD_SETRXTHRESH (17<<11) +#define EL3CMD_SETTXTHRESH (18<<11) +#define EL3CMD_SETTXSTART (19<<11) +#define EL3CMD_STATSENABLE (21<<11) +#define EL3CMD_STATSDISABLE (22<<11) +#define EL3CMD_STOPCOAX (23<<11) +#define EL3CMD_POWERUP (27<<11) +#define EL3CMD_POWERDOWN (28<<11) +#define EL3CMD_POWERAUTO (29<<11) + + +/* Interrupt types */ +/* =============== */ + +#define EL3INTB_UPDATESTATS 7 +#define EL3INTB_REQINT 6 +#define EL3INTB_RXEARLY 5 +#define EL3INTB_RXCOMPLETE 4 +#define EL3INTB_TXAVAIL 3 +#define EL3INTB_TXCOMPLETE 2 +#define EL3INTB_FAILURE 1 +#define EL3INTB_ANY 0 + +#define EL3INTF_UPDATESTATS (1< + + +/* Use the OFFSET macro as the offset parameter of one of the other + macros */ +/* +#ifdef OFFSET +#undef OFFSET +#endif +*/ +#define OFFSET(struct_name, struct_field) \ + ((ULONG)(&(((struct struct_name *)0)->struct_field))) + +/* Use the following macros in the structure definition */ + +#define INITBYTEDEF(name) \ + UBYTE name ## _c; UBYTE name ## _o1; UBYTE name ## _o2; \ + UBYTE name ## _o3; UBYTE name ## _v; UBYTE name ## _p +#define INITWORDDEF(name) \ + UBYTE name ## _c; UBYTE name ## _o1; UBYTE name ## _o2; \ + UWORD name ## _v +#define INITLONGDEF(name) \ + UBYTE name ## _c; UBYTE name ## _o1; UBYTE name ## _o2; \ + ULONG name ## _v +#define INITPINTDEF(name) \ + UBYTE name ## _c; UBYTE name ## _o1; UBYTE name ## _o2; \ + UPINT name ## _v + +#define SMALLINITBYTEDEF(name) \ + UBYTE name ## _c; UBYTE name ## _o; UBYTE name ## _v; UBYTE name ## _p +#define SMALLINITWORDDEF(name) \ + UBYTE name ## _c; UBYTE name ## _o; UWORD name ## _v +#define SMALLINITLONGDEF(name) \ + UBYTE name ## _c; UBYTE name ## _o; ULONG name ## _v +#define SMALLINITPINTDEF(name) \ + UBYTE name ## _c; UBYTE name ## _o; UPINT name ## _v + +#define INITENDDEF UBYTE the_end + +/* Use the following macros to fill in a structure */ + +#define NEWINITBYTE(offset, value) \ + 0xe0, (UBYTE)((offset) >> 16), (UBYTE)((offset) >> 8), (UBYTE)(offset), \ + (UBYTE)(value), 0 +#define NEWINITWORD(offset, value) \ + 0xd0, (UBYTE)((offset) >> 16), (UBYTE)((offset) >> 8), (UBYTE)(offset), \ + (UWORD)(value) +#define NEWINITLONG(offset, value) \ + 0xc0, (UBYTE)((offset) >> 16), (UBYTE)((offset) >> 8), (UBYTE)(offset), \ + (ULONG)(value) +#define INITPINT(offset, value) \ + 0xc0, (UBYTE)((offset) >> 16), (UBYTE)((offset) >> 8), (UBYTE)(offset), \ + (UPINT)(value) + +#define SMALLINITBYTE(offset, value) \ + 0xa0, (offset), (UBYTE)(value), 0 +#define SMALLINITWORD(offset, value) \ + 0x90, (offset), (UWORD)(value) +#define SMALLINITLONG(offset, value) \ + 0x80, (offset), (ULONG)(value) +#define SMALLINITPINT(offset, value) \ + 0x80, (offset), (UPINT)(value) + +#define INITEND 0 + +/* Obsolete definitions */ + +#define INITBYTE(offset, value) \ + (0xe000 | ((UWORD)(offset) >> 16)), \ + (UWORD)(offset), (UWORD)((value) << 8) +#define INITWORD(offset, value) \ + (0xd000 | ((UWORD)(offset) >> 16)), (UWORD)(offset), (UWORD)(value) +#define INITLONG(offset, value) \ + (0xc000 | ((UWORD)(offset) >> 16)), (UWORD)(offset), \ + (UWORD)((value) >> 16), (UWORD)(value) +#define INITAPTR(offset, value) \ + (0xc000 | ((UWORD)(offset) >> 16)), (UWORD)(offset), \ + (UWORD)((ULONG)(value) >> 16), (UWORD)(value) + +#endif diff --git a/Source/request.c b/Source/request.c new file mode 100644 index 0000000..02ca84e --- /dev/null +++ b/Source/request.c @@ -0,0 +1,1523 @@ +/* + +File: request.c +Author: Neil Cafferkey +Copyright (C) 2001-2010 Neil Cafferkey + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. + +*/ + + +#include +#include +#include +#include + +#include +#include + +#include "device.h" + +#include "request_protos.h" +#include "unit_protos.h" + + +#define KNOWN_EVENTS (S2EVENT_ERROR|S2EVENT_TX|S2EVENT_RX|S2EVENT_ONLINE|\ + S2EVENT_OFFLINE|S2EVENT_BUFF|S2EVENT_HARDWARE|S2EVENT_SOFTWARE) + + +static BOOL CmdInvalid(struct IOSana2Req *request,struct DevBase *base); +static BOOL CmdRead(struct IOSana2Req *request,struct DevBase *base); +static BOOL CmdWrite(struct IOSana2Req *request,struct DevBase *base); +static BOOL CmdFlush(struct IORequest *request,struct DevBase *base); +static BOOL CmdS2DeviceQuery(struct IOSana2Req *request, + struct DevBase *base); +static BOOL CmdGetStationAddress(struct IOSana2Req *request, + struct DevBase *base); +static BOOL CmdConfigInterface(struct IOSana2Req *request, + struct DevBase *base); +static BOOL CmdBroadcast(struct IOSana2Req *request, + struct DevBase *base); +static BOOL CmdTrackType(struct IOSana2Req *request, + struct DevBase *base); +static BOOL CmdUntrackType(struct IOSana2Req *request, + struct DevBase *base); +static BOOL CmdGetTypeStats(struct IOSana2Req *request, + struct DevBase *base); +static BOOL CmdGetSpecialStats(struct IOSana2Req *request, + struct DevBase *base); +static BOOL CmdGetGlobalStats(struct IOSana2Req *request, + struct DevBase *base); +static BOOL CmdOnEvent(struct IOSana2Req *request,struct DevBase *base); +static BOOL CmdReadOrphan(struct IOSana2Req *request, + struct DevBase *base); +static BOOL CmdOnline(struct IOSana2Req *request,struct DevBase *base); +static BOOL CmdOffline(struct IOSana2Req *request,struct DevBase *base); +static BOOL CmdDeviceQuery(struct IOStdReq *request, + struct DevBase *base); +static BOOL CmdAddMulticastAddresses(struct IOSana2Req *request, + struct DevBase *base); +static BOOL CmdDelMulticastAddresses(struct IOSana2Req *request, + struct DevBase *base); + + +static const UWORD supported_commands[]= +{ + CMD_READ, + CMD_WRITE, + CMD_FLUSH, + S2_DEVICEQUERY, + S2_GETSTATIONADDRESS, + S2_CONFIGINTERFACE, + S2_ADDMULTICASTADDRESS, + S2_DELMULTICASTADDRESS, + S2_MULTICAST, + S2_BROADCAST, + S2_TRACKTYPE, + S2_UNTRACKTYPE, + S2_GETTYPESTATS, + S2_GETSPECIALSTATS, + S2_GETGLOBALSTATS, + S2_ONEVENT, + S2_READORPHAN, + S2_ONLINE, + S2_OFFLINE, + NSCMD_DEVICEQUERY, + S2_ADDMULTICASTADDRESSES, + S2_DELMULTICASTADDRESSES, + 0 +}; + + +struct Sana2DeviceQuery sana2_info= +{ + 0, + 0, + 0, + 0, + ADDRESS_SIZE*8, + MTU, + 10000000, + S2WireType_Ethernet +}; + + + +/****i* 3c589.device/ServiceRequest **************************************** +* +* NAME +* ServiceRequest -- Attempt to service a device request. +* +* SYNOPSIS +* ServiceRequest(request) +* +* VOID ServiceRequest(struct IORequest *); +* +* FUNCTION +* Attempts to carry out a request. The relevant unit's semaphore must +* be obtained before calling this function. This function releases the +* semaphore before returning. +* +* INPUTS +* request +* +* RESULT +* None. +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +VOID ServiceRequest(struct IOSana2Req *request,struct DevBase *base) +{ + BOOL complete; + + switch(request->ios2_Req.io_Command) + { + case CMD_READ: + complete=CmdRead(request,base); + break; + case CMD_WRITE: + complete=CmdWrite(request,base); + break; + case CMD_FLUSH: + complete=CmdFlush((APTR)request,base); + break; + case S2_DEVICEQUERY: + complete=CmdS2DeviceQuery((APTR)request,base); + break; + case S2_GETSTATIONADDRESS: + complete=CmdGetStationAddress((APTR)request,base); + break; + case S2_CONFIGINTERFACE: + complete=CmdConfigInterface((APTR)request,base); + break; + case S2_ADDMULTICASTADDRESS: + complete=CmdAddMulticastAddresses((APTR)request,base); + break; + case S2_DELMULTICASTADDRESS: + complete=CmdDelMulticastAddresses((APTR)request,base); + break; + case S2_MULTICAST: + complete=CmdWrite((APTR)request,base); + break; + case S2_BROADCAST: + complete=CmdBroadcast((APTR)request,base); + break; + case S2_TRACKTYPE: + complete=CmdTrackType((APTR)request,base); + break; + case S2_UNTRACKTYPE: + complete=CmdUntrackType((APTR)request,base); + break; + case S2_GETTYPESTATS: + complete=CmdGetTypeStats((APTR)request,base); + break; + case S2_GETSPECIALSTATS: + complete=CmdGetSpecialStats((APTR)request,base); + break; + case S2_GETGLOBALSTATS: + complete=CmdGetGlobalStats((APTR)request,base); + break; + case S2_ONEVENT: + complete=CmdOnEvent((APTR)request,base); + break; + case S2_READORPHAN: + complete=CmdReadOrphan((APTR)request,base); + break; + case S2_ONLINE: + complete=CmdOnline((APTR)request,base); + break; + case S2_OFFLINE: + complete=CmdOffline((APTR)request,base); + break; + case NSCMD_DEVICEQUERY: + complete=CmdDeviceQuery((APTR)request,base); + break; + case S2_ADDMULTICASTADDRESSES: + complete=CmdAddMulticastAddresses((APTR)request,base); + break; + case S2_DELMULTICASTADDRESSES: + complete=CmdDelMulticastAddresses((APTR)request,base); + break; + default: + complete=CmdInvalid((APTR)request,base); + } + + if(complete&&((request->ios2_Req.io_Flags&IOF_QUICK)==0)) + ReplyMsg((APTR)request); + + ReleaseSemaphore(&((struct DevUnit *)request->ios2_Req.io_Unit)-> + access_lock); + return; +} + + + +/****i* 3c589.device/CMD_INVALID ******************************************* +* +* NAME +* CMD_INVALID -- Reject invalid commands. +* +* FUNCTION +* +* INPUTS +* None. +* +* RESULTS +* io_Error - IOERR_NOCMD. +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BOOL CmdInvalid(struct IOSana2Req *request,struct DevBase *base) +{ + request->ios2_Req.io_Error=IOERR_NOCMD; + request->ios2_WireError=S2WERR_GENERIC_ERROR; + + return TRUE; +} + + + +/****** 3c589.device/CMD_READ ********************************************** +* +* NAME +* CMD_READ -- Read data. +* +* FUNCTION +* +* INPUTS +* io_Flags +* ios2_PacketType +* ios2_Data +* +* RESULTS +* io_Flags +* io_Error +* ios2_WireError +* ios2_SrcAddr +* ios2_DstAddr +* ios2_DataLength +* ios2_Data +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BOOL CmdRead(struct IOSana2Req *request,struct DevBase *base) +{ + struct DevUnit *unit; + struct Opener *opener; + BOOL complete=FALSE; + + unit=(APTR)request->ios2_Req.io_Unit; + + if((unit->flags&UNITF_ONLINE)!=0) + { + opener=request->ios2_BufferManagement; + PutRequest(&opener->read_port,(APTR)request,base); + } + else + { + request->ios2_Req.io_Error=S2ERR_OUTOFSERVICE; + request->ios2_WireError=S2WERR_UNIT_OFFLINE; + complete=TRUE; + } + + /* Return */ + + return complete; +} + + + +/****** 3c589.device/CMD_WRITE ********************************************* +* +* NAME +* CMD_WRITE -- Write data. +* +* FUNCTION +* +* INPUTS +* io_Flags +* ios2_DstAddr +* ios2_PacketType +* ios2_DataLength +* ios2_Data +* +* RESULTS +* io_Error +* ios2_WireError +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +/****** 3c589.device/S2_MULTICAST ****************************************** +* +* NAME +* S2_MULTICAST -- +* +* FUNCTION +* +* INPUTS +* io_Flags +* ios2_DstAddr - multicast address. +* ios2_PacketType +* ios2_DataLength +* ios2_Data +* +* RESULTS +* io_Error +* ios2_WireError +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BOOL CmdWrite(struct IOSana2Req *request,struct DevBase *base) +{ + struct DevUnit *unit; + BYTE error=0; + ULONG wire_error; + BOOL complete=FALSE; + + /* Check request is valid */ + + unit=(APTR)request->ios2_Req.io_Unit; + if((unit->flags&UNITF_ONLINE)==0) + { + error=S2ERR_OUTOFSERVICE; + wire_error=S2WERR_UNIT_OFFLINE; + } + else if((request->ios2_Req.io_Command==S2_MULTICAST)&& + ((request->ios2_DstAddr[0]&0x1)==0)) + { + error=S2ERR_BAD_ADDRESS; + wire_error=S2WERR_BAD_MULTICAST; + } + + /* Queue request for sending */ + + if(error==0) + PutRequest(unit->request_ports[WRITE_QUEUE],(APTR)request,base); + else + { + request->ios2_Req.io_Error=error; + request->ios2_WireError=wire_error; + complete=TRUE; + } + + /* Return */ + + return complete; +} + + + +/****** 3c589.device/CMD_FLUSH ********************************************* +* +* NAME +* CMD_FLUSH -- . +* +* FUNCTION +* +* INPUTS +* None. +* +* RESULTS +* io_Error +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BOOL CmdFlush(struct IORequest *request,struct DevBase *base) +{ + FlushUnit((APTR)request->io_Unit,EVENT_QUEUE,IOERR_ABORTED,base); + + return TRUE; +} + + + +/****** 3c589.device/S2_DEVICEQUERY **************************************** +* +* NAME +* S2_DEVICEQUERY -- Query device capabilities. +* +* FUNCTION +* +* INPUTS +* ios2_StatData - Pointer to Sana2DeviceQuery structure. +* +* RESULTS +* io_Error +* ios2_WireError +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BOOL CmdS2DeviceQuery(struct IOSana2Req *request, + struct DevBase *base) +{ + struct DevUnit *unit; + struct Sana2DeviceQuery *info; + ULONG size_available,size; + + /* Copy device info */ + + unit=(APTR)request->ios2_Req.io_Unit; + info=request->ios2_StatData; + size=size_available=info->SizeAvailable; + if(size>sizeof(struct Sana2DeviceQuery)) + size=sizeof(struct Sana2DeviceQuery); + + CopyMem(&sana2_info,info,size); + if((unit->flags&UNITF_ROADRUNNER)!=0) + info->BPS=100000000; + + info->SizeAvailable=size_available; + info->SizeSupplied=size; + + /* Return */ + + return TRUE; +} + + + +/****** 3c589.device/S2_GETSTATIONADDDRESS ********************************* +* +* NAME +* S2_GETSTATIONADDDRESS -- +* +* FUNCTION +* +* INPUTS +* None. +* +* RESULTS +* io_Error +* ios2_WireError +* ios2_SrcAddr - current address. +* ios2_DstAddr - default address (zero if none?). +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BOOL CmdGetStationAddress(struct IOSana2Req *request, + struct DevBase *base) +{ + struct DevUnit *unit; + + /* Copy addresses */ + + unit=(APTR)request->ios2_Req.io_Unit; + CopyMem(unit->address,request->ios2_SrcAddr,ADDRESS_SIZE); + CopyMem(unit->default_address,request->ios2_DstAddr,ADDRESS_SIZE); + + /* Return */ + + return TRUE; +} + + + +/****** 3c589.device/S2_CONFIGINTERFACE ************************************ +* +* NAME +* S2_CONFIGINTERFACE -- +* +* FUNCTION +* +* INPUTS +* ios2_SrcAddr - address to use. +* +* RESULTS +* io_Error +* ios2_WireError +* ios2_SrcAddr - address used. +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BOOL CmdConfigInterface(struct IOSana2Req *request, + struct DevBase *base) +{ + struct DevUnit *unit; + + /* Configure adapter */ + + unit=(APTR)request->ios2_Req.io_Unit; + if((unit->flags&UNITF_CONFIGURED)==0) + { + CopyMem(request->ios2_SrcAddr,unit->address,ADDRESS_SIZE); + if((unit->flags&UNITF_HAVEADAPTER)!=0) + ConfigureAdapter(unit,base); + unit->flags|=UNITF_CONFIGURED; + } + else + { + request->ios2_Req.io_Error=S2ERR_BAD_STATE; + request->ios2_WireError=S2WERR_IS_CONFIGURED; + } + + /* Return */ + + return TRUE; +} + + + +/****** 3c589.device/S2_BROADCAST ****************************************** +* +* NAME +* S2_BROADCAST -- +* +* FUNCTION +* +* INPUTS +* io_Flags +* ios2_PacketType +* ios2_DataLength +* ios2_Data +* +* RESULTS +* io_Error +* ios2_WireError +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BOOL CmdBroadcast(struct IOSana2Req *request, + struct DevBase *base) +{ + /* Fill in the broadcast address as destination */ + + *((ULONG *)request->ios2_DstAddr)=0xffffffff; + *((UWORD *)(request->ios2_DstAddr+4))=0xffff; + + /* Queue the write as normal */ + + return CmdWrite(request,base); +} + + + +/****** 3c589.device/S2_TRACKTYPE ****************************************** +* +* NAME +* S2_TRACKTYPE -- +* +* FUNCTION +* +* INPUTS +* ios2_PacketType - packet type to start tracking. +* +* RESULTS +* io_Error +* ios2_WireError +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BOOL CmdTrackType(struct IOSana2Req *request, + struct DevBase *base) +{ + struct DevUnit *unit; + struct Opener *opener; + ULONG packet_type,wire_error; + struct TypeTracker *tracker; + struct TypeStats *initial_stats; + BYTE error=0; + + unit=(APTR)request->ios2_Req.io_Unit; + packet_type=request->ios2_PacketType; + + /* Get global tracker */ + + tracker=(struct TypeTracker *) + FindTypeStats(unit,&unit->type_trackers,packet_type,base); + + if(tracker!=NULL) + tracker->user_count++; + else + { + tracker=AllocMem(sizeof(struct TypeTracker),MEMF_PUBLIC|MEMF_CLEAR); + if(tracker!=NULL) + { + tracker->packet_type=packet_type; + tracker->user_count=1; + + Disable(); + AddTail((APTR)&unit->type_trackers,(APTR)tracker); + Enable(); + } + } + + /* Store initial figures for this opener */ + + opener=request->ios2_BufferManagement; + initial_stats=FindTypeStats(unit,&opener->initial_stats,packet_type, + base); + + if(initial_stats!=NULL) + { + error=S2ERR_BAD_STATE; + wire_error=S2WERR_ALREADY_TRACKED; + } + + if(error==0) + { + initial_stats=AllocMem(sizeof(struct TypeStats),MEMF_PUBLIC); + if(initial_stats==NULL) + { + error=S2ERR_NO_RESOURCES; + wire_error=S2WERR_GENERIC_ERROR; + } + } + + if(error==0) + { + CopyMem(tracker,initial_stats,sizeof(struct TypeStats)); + AddTail((APTR)&opener->initial_stats,(APTR)initial_stats); + } + + /* Return */ + + request->ios2_Req.io_Error=error; + request->ios2_WireError=wire_error; + return TRUE; +} + + + +/****** 3c589.device/S2_UNTRACKTYPE **************************************** +* +* NAME +* S2_UNTRACKTYPE -- +* +* FUNCTION +* +* INPUTS +* ios2_PacketType - packet type to stop tracking. +* +* RESULTS +* io_Error +* ios2_WireError +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BOOL CmdUntrackType(struct IOSana2Req *request, + struct DevBase *base) +{ + struct DevUnit *unit; + struct Opener *opener; + ULONG packet_type; + struct TypeTracker *tracker; + struct TypeStats *initial_stats; + + unit=(APTR)request->ios2_Req.io_Unit; + packet_type=request->ios2_PacketType; + + /* Get global tracker and initial figures */ + + tracker=(struct TypeTracker *) + FindTypeStats(unit,&unit->type_trackers,packet_type,base); + opener=request->ios2_BufferManagement; + initial_stats=FindTypeStats(unit,&opener->initial_stats,packet_type, + base); + + /* Decrement tracker usage and free unused structures */ + + if(initial_stats!=NULL) + { + if((--tracker->user_count)==0) + { + Disable(); + Remove((APTR)tracker); + Enable(); + FreeMem(tracker,sizeof(struct TypeTracker)); + } + + Remove((APTR)initial_stats); + FreeMem(initial_stats,sizeof(struct TypeStats)); + } + else + { + request->ios2_Req.io_Error=S2ERR_BAD_STATE; + request->ios2_WireError=S2WERR_NOT_TRACKED; + } + + /* Return */ + + return TRUE; +} + + + +/****** 3c589.device/S2_GETTYPESTATS *************************************** +* +* NAME +* S2_GETTYPESTATS -- +* +* FUNCTION +* +* INPUTS +* ios2_PacketType - packet type to get statistics on. +* ios2_StatData - pointer to a Sana2PacketTypeStats structure. +* +* RESULTS +* io_Error +* ios2_WireError +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BOOL CmdGetTypeStats(struct IOSana2Req *request, + struct DevBase *base) +{ + struct DevUnit *unit; + struct Opener *opener; + ULONG packet_type; + struct TypeStats *initial_stats,*tracker; + struct Sana2PacketTypeStats *stats; + + unit=(APTR)request->ios2_Req.io_Unit; + packet_type=request->ios2_PacketType; + + /* Get global tracker and initial figures */ + + tracker=FindTypeStats(unit,&unit->type_trackers,packet_type,base); + opener=request->ios2_BufferManagement; + initial_stats=FindTypeStats(unit,&opener->initial_stats,packet_type, + base); + + /* Copy and adjust figures */ + + if(initial_stats!=NULL) + { + stats=request->ios2_StatData; + CopyMem(&tracker->stats,stats,sizeof(struct Sana2PacketTypeStats)); + stats->PacketsSent-=initial_stats->stats.PacketsSent; + stats->PacketsReceived-=initial_stats->stats.PacketsReceived; + stats->BytesSent-=initial_stats->stats.BytesSent; + stats->BytesReceived-=initial_stats->stats.BytesReceived; + stats->PacketsDropped-=initial_stats->stats.PacketsDropped; + } + else + { + request->ios2_Req.io_Error=S2ERR_BAD_STATE; + request->ios2_WireError=S2WERR_NOT_TRACKED; + } + + /* Return */ + + return TRUE; +} + + + +/****** 3c589.device/S2_GETSPECIALSTATS ************************************ +* +* NAME +* S2_GETSPECIALSTATS -- +* +* FUNCTION +* +* INPUTS +* ios2_StatData - Pointer to Sana2SpecialStatHeader structure. +* +* RESULTS +* io_Error +* ios2_WireError +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BOOL CmdGetSpecialStats(struct IOSana2Req *request, + struct DevBase *base) +{ + struct DevUnit *unit; + UWORD i,stat_count; + struct Sana2SpecialStatHeader *header; + struct Sana2SpecialStatRecord *record; + + /* Fill in stats */ + + unit=(APTR)request->ios2_Req.io_Unit; + header=request->ios2_StatData; + record=(APTR)(header+1); + + stat_count=header->RecordCountMax; + if(stat_count>STAT_COUNT) + stat_count=STAT_COUNT; + + for(i=0;iType=(S2WireType_Ethernet<<16)+i; + record->Count=unit->special_stats[i]; + record->String=(TEXT *)&unit->openers.mlh_Tail; + record++; + } + + header->RecordCountSupplied=stat_count; + + /* Return */ + + return TRUE; +} + + + +/****** 3c589.device/S2_GETGLOBALSTATS ************************************* +* +* NAME +* S2_GETGLOBALSTATS -- +* +* FUNCTION +* +* INPUTS +* ios2_StatData - Pointer to Sana2DeviceStats structure. +* +* RESULTS +* io_Error +* ios2_WireError +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BOOL CmdGetGlobalStats(struct IOSana2Req *request, + struct DevBase *base) +{ + struct DevUnit *unit; + + /* Copy stats */ + + unit=(APTR)request->ios2_Req.io_Unit; + CopyMem(&unit->stats,request->ios2_StatData, + sizeof(struct Sana2DeviceStats)); + + /* Return */ + + return TRUE; +} + + + +/****** 3c589.device/S2_ONEVENT ******************************************** +* +* NAME +* S2_ONEVENT -- +* +* FUNCTION +* +* INPUTS +* ios2_WireError +* +* RESULTS +* io_Error +* ios2_WireError +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BOOL CmdOnEvent(struct IOSana2Req *request,struct DevBase *base) +{ + struct DevUnit *unit; + ULONG events,wanted_events; + BOOL complete=FALSE; + + /* Check if we understand the event types */ + + unit=(APTR)request->ios2_Req.io_Unit; + wanted_events=request->ios2_WireError; + if((wanted_events&~KNOWN_EVENTS)!=0) + { + request->ios2_Req.io_Error=S2ERR_NOT_SUPPORTED; + events=S2WERR_BAD_EVENT; + } + else + { + if((unit->flags&UNITF_ONLINE)!=0) + events=S2EVENT_ONLINE; + else + events=S2EVENT_OFFLINE; + + events&=wanted_events; + } + + /* Reply request if a wanted event has already occurred */ + + if(events!=0) + { + request->ios2_WireError=events; + complete=TRUE; + } + else + PutRequest(unit->request_ports[EVENT_QUEUE],(APTR)request,base); + + /* Return */ + + return complete; +} + + + +/****** 3c589.device/S2_READORPHAN ***************************************** +* +* NAME +* S2_READORPHAN -- +* +* FUNCTION +* +* INPUTS +* io_Flags +* ios2_Data +* +* RESULTS +* io_Flags +* io_Error +* ios2_WireError +* ios2_PacketType - A copy of the packet's type field. +* ios2_SrcAddr +* ios2_DstAddr +* ios2_DataLength +* ios2_Data +* +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BOOL CmdReadOrphan(struct IOSana2Req *request, + struct DevBase *base) +{ + struct DevUnit *unit; + BYTE error=0; + ULONG wire_error; + BOOL complete=FALSE; + + /* Check request is valid */ + + unit=(APTR)request->ios2_Req.io_Unit; + if((unit->flags&UNITF_ONLINE)==0) + { + error=S2ERR_OUTOFSERVICE; + wire_error=S2WERR_UNIT_OFFLINE; + } + + /* Queue request */ + + if(error==0) + PutRequest(unit->request_ports[ADOPT_QUEUE],(APTR)request,base); + else + { + request->ios2_Req.io_Error=error; + request->ios2_WireError=wire_error; + complete=TRUE; + } + + /* Return */ + + return complete; +} + + + +/****** 3c589.device/S2_ONLINE ********************************************* +* +* NAME +* S2_ONLINE -- +* +* FUNCTION +* +* INPUTS +* None. +* +* RESULTS +* io_Error +* ios2_WireError +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BOOL CmdOnline(struct IOSana2Req *request,struct DevBase *base) +{ + struct DevUnit *unit; + BYTE error=0; + ULONG wire_error; + UWORD i; + + /* Check request is valid */ + + unit=(APTR)request->ios2_Req.io_Unit; + if((unit->flags&UNITF_CONFIGURED)==0) + { + error=S2ERR_BAD_STATE; + wire_error=S2WERR_NOT_CONFIGURED; + } + if((unit->flags&UNITF_HAVEADAPTER)==0) + { + error=S2ERR_OUTOFSERVICE; + wire_error=S2WERR_RCVREL_HDW_ERR; + } + + /* Clear global and special stats and put adapter back online */ + + if((error==0)&&((unit->flags&UNITF_ONLINE)==0)) + { + unit->stats.PacketsReceived=0; + unit->stats.PacketsSent=0; + unit->stats.BadData=0; + unit->stats.Overruns=0; + unit->stats.UnknownTypesReceived=0; + unit->stats.Reconfigurations=0; + + for(i=0;ispecial_stats[i]=0; + + GoOnline(unit,base); + } + + /* Return */ + + request->ios2_Req.io_Error=error; + request->ios2_WireError=wire_error; + return TRUE; +} + + + +/****** 3c589.device/S2_OFFLINE ******************************************** +* +* NAME +* S2_OFFLINE -- +* +* FUNCTION +* +* INPUTS +* None. +* +* RESULTS +* io_Error +* ios2_WireError +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BOOL CmdOffline(struct IOSana2Req *request,struct DevBase *base) +{ + struct DevUnit *unit; + + /* Put adapter offline */ + + unit=(APTR)request->ios2_Req.io_Unit; + if((unit->flags&UNITF_ONLINE)!=0) + GoOffline(unit,base); + + /* Return */ + + return TRUE; +} + + + +/****** 3c589.device/NSCMD_DEVICEQUERY ************************************* +* +* NAME +* NSCMD_DEVICEQUERY -- Query device capabilities. +* +* FUNCTION +* +* INPUTS +* io_Length - ???. +* io_Data - pointer to NSDeviceQueryResult structure. +* +* RESULTS +* io_Error +* io_Actual - size of structure device can handle. +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +* Note that we have to pretend the request structure is an IOStdReq. +* +*/ + +static BOOL CmdDeviceQuery(struct IOStdReq *request, + struct DevBase *base) +{ + struct NSDeviceQueryResult *info; + + /* Set structure size twice */ + + info=request->io_Data; + request->io_Actual=info->SizeAvailable= + (ULONG)OFFSET(NSDeviceQueryResult,SupportedCommands)+sizeof(APTR); + + /* Report device details */ + + info->DeviceType=NSDEVTYPE_SANA2; + info->DeviceSubType=0; + + info->SupportedCommands=(APTR)supported_commands; + + /* Return */ + + return TRUE; +} + + + +/****** 3c589.device/S2_ADDMULTICASTADDRESS ******************************** +* +* NAME +* S2_ADDMULTICASTADDRESS -- +* +* FUNCTION +* +* INPUTS +* ios2_SrcAddr - multicast address. +* +* RESULTS +* io_Error +* ios2_WireError +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +/****** 3c589.device/S2_ADDMULTICASTADDRESSES ****************************** +* +* NAME +* S2_ADDMULTICASTADDRESSES -- +* +* FUNCTION +* +* INPUTS +* ios2_SrcAddr - lower bound. +* ios2_DstAddr - upper bound. +* +* RESULTS +* io_Error +* ios2_WireError +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BOOL CmdAddMulticastAddresses(struct IOSana2Req *request, + struct DevBase *base) +{ + struct DevUnit *unit; + UBYTE *lower_bound,*upper_bound; + + unit=(APTR)request->ios2_Req.io_Unit; + + lower_bound=request->ios2_SrcAddr; + if(request->ios2_Req.io_Command==S2_ADDMULTICASTADDRESS) + upper_bound=lower_bound; + else + upper_bound=request->ios2_DstAddr; + + if(!AddMulticastRange(unit,lower_bound,upper_bound,base)) + { + request->ios2_Req.io_Error=S2ERR_NO_RESOURCES; + request->ios2_WireError=S2WERR_GENERIC_ERROR; + } + + /* Return */ + + return TRUE; +} + + + +/****** 3c589.device/S2_DELMULTICASTADDRESS ******************************** +* +* NAME +* S2_DELMULTICASTADDRESS -- +* +* FUNCTION +* +* INPUTS +* ios2_SrcAddr - multicast address. +* +* RESULTS +* io_Error +* ios2_WireError +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +/****** 3c589.device/S2_DELMULTICASTADDRESSES ****************************** +* +* NAME +* S2_DELMULTICASTADDRESSES -- +* +* FUNCTION +* +* INPUTS +* ios2_SrcAddr - lower bound. +* ios2_DstAddr - upper bound. +* +* RESULTS +* io_Error +* ios2_WireError +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BOOL CmdDelMulticastAddresses(struct IOSana2Req *request, + struct DevBase *base) +{ + struct DevUnit *unit; + UBYTE *lower_bound,*upper_bound; + + unit=(APTR)request->ios2_Req.io_Unit; + + lower_bound=request->ios2_SrcAddr; + if(request->ios2_Req.io_Command==S2_DELMULTICASTADDRESS) + upper_bound=lower_bound; + else + upper_bound=request->ios2_DstAddr; + + if(!RemMulticastRange(unit,lower_bound,upper_bound,base)) + { + request->ios2_Req.io_Error=S2ERR_BAD_STATE; + request->ios2_WireError=S2WERR_BAD_MULTICAST; + } + + /* Return */ + + return TRUE; +} + + + +/****i* 3c589.device/PutRequest ******************************************** +* +* NAME +* PutRequest -- . +* +* SYNOPSIS +* PutRequest(port,request) +* +* VOID PutRequest(struct MsgPort *,struct IORequest *); +* +* FUNCTION +* +* INPUTS +* port +* request +* +* RESULT +* None. +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +VOID PutRequest(struct MsgPort *port,struct IORequest *request, + struct DevBase *base) +{ + request->io_Flags&=~IOF_QUICK; + PutMsg(port,(APTR)request); + + return; +} + + + diff --git a/Source/request_protos.h b/Source/request_protos.h new file mode 100644 index 0000000..e52ad7f --- /dev/null +++ b/Source/request_protos.h @@ -0,0 +1,36 @@ +/* + +File: request_protos.h +Author: Neil Cafferkey +Copyright (C) 2002 Neil Cafferkey + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. + +*/ + +#ifndef REQUEST_PROTOS_H +#define REQUEST_PROTOS_H + + +#include "device.h" + +VOID ServiceRequest(struct IOSana2Req *request,struct DevBase *base); +VOID PutRequest(struct MsgPort *port,struct IORequest *request, + struct DevBase *base); + +#endif + + diff --git a/Source/unit.c b/Source/unit.c new file mode 100644 index 0000000..cb1f9bc --- /dev/null +++ b/Source/unit.c @@ -0,0 +1,2166 @@ +/* + +File: unit.c +Author: Neil Cafferkey +Copyright (C) 2001-2010 Neil Cafferkey + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. + +*/ + + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "device.h" +#include "etherlink3.h" + +#include "unit_protos.h" +#include "request_protos.h" + + +#define TASK_PRIORITY 0 +#define STACK_SIZE 4096 +#define MAX_TUPLE_SIZE 0xff +#define TUPLE_BUFFER_SIZE (MAX_TUPLE_SIZE+8) +#define INT_MASK\ + (EL3INTF_RXCOMPLETE|EL3INTF_TXAVAIL|EL3INTF_TXCOMPLETE) + + +IMPORT struct ExecBase *AbsExecBase; + +static BOOL InitialiseCard(struct DevUnit *unit,struct DevBase *base); +static VOID InitialiseAdapter(struct DevUnit *unit,struct DevBase *base); +static struct AddressRange *FindMulticastRange(struct DevUnit *unit, + ULONG lower_bound_left,UWORD lower_bound_right,ULONG upper_bound_left, + UWORD upper_bound_right,struct DevBase *base); +static VOID CardRemovedInt(struct DevUnit *unit REG("a1")); +static VOID CardInsertedInt(struct DevUnit *unit REG("a1")); +static UBYTE CardStatusInt(UBYTE mask REG("d0"), + struct DevUnit *unit REG("a1")); +static VOID RxInt(struct DevUnit *unit REG("a1")); +static VOID CopyPacket(struct DevUnit *unit,struct IOSana2Req *request, + UWORD packet_size,UWORD packet_type,BOOL all_read,struct DevBase *base); +static BOOL AddressFilter(struct DevUnit *unit,UBYTE *address, + struct DevBase *base); +static VOID TxInt(struct DevUnit *unit REG("a1")); +static VOID TxError(struct DevUnit *unit,struct DevBase *base); +static VOID ReportEvents(struct DevUnit *unit,ULONG events, + struct DevBase *base); +static VOID UnitTask(); +static UWORD ReadEEPROM(volatile UBYTE *io_base,UWORD index); + + + +/****i* 3c589.device/GetUnit *********************************************** +* +* NAME +* GetUnit -- Get a unit by number. +* +* SYNOPSIS +* unit = GetUnit(unit_num) +* +* struct DevUnit *GetUnit(ULONG); +* +* FUNCTION +* +* INPUTS +* +* RESULT +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +struct DevUnit *GetUnit(ULONG unit_num,struct DevBase *base) +{ + struct DevUnit *unit; + + unit=FindUnit(unit_num,base); + + if(unit==NULL) + { + unit=CreateUnit(unit_num,base); + if(unit!=NULL) + AddTail((APTR)&base->units,(APTR)unit); + } + + return unit; +} + + + +/****i* 3c589.device/FindUnit ********************************************** +* +* NAME +* FindUnit -- Find a unit by number. +* +* SYNOPSIS +* unit = FindUnit(unit_num) +* +* struct DevUnit *FindUnit(ULONG); +* +* FUNCTION +* +* INPUTS +* +* RESULT +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +struct DevUnit *FindUnit(ULONG unit_num,struct DevBase *base) +{ + struct DevUnit *unit,*tail; + BOOL found; + + unit=(APTR)base->units.mlh_Head; + tail=(APTR)&base->units.mlh_Tail; + found=FALSE; + + while((unit!=tail)&&!found) + { + if(unit->unit_num==unit_num) + found=TRUE; + else + unit=(APTR)unit->node.mln_Succ; + } + + if(!found) + unit=NULL; + + return unit; +} + + + +/****i* 3c589.device/CreateUnit ******************************************** +* +* NAME +* CreateUnit -- Create a unit. +* +* SYNOPSIS +* unit = CreateUnit(unit_num) +* +* struct DevUnit *CreateUnit(ULONG); +* +* FUNCTION +* Creates a new unit. +* +* INPUTS +* +* RESULT +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +struct DevUnit *CreateUnit(ULONG unit_num,struct DevBase *base) +{ + BOOL success=TRUE; + struct DevUnit *unit; + struct Task *task; + struct MsgPort *port; + UBYTE i; + struct CardHandle *card_handle; + APTR stack; + struct Interrupt *card_removed_int,*card_inserted_int,*card_status_int; + + unit=AllocMem(sizeof(struct DevUnit),MEMF_CLEAR); + if(unit==NULL) + success=FALSE; + + if(success) + { + unit->unit_num=unit_num; + unit->device=base; + + InitSemaphore(&unit->access_lock); + + /* Set up packet filter command */ + + unit->rx_filter_cmd=EL3CMD_SETRXFILTER|EL3CMD_SETRXFILTERF_BCAST + |EL3CMD_SETRXFILTERF_UCAST; + + /* Create the message ports for queuing requests */ + + for(i=0;irequest_ports[i]=port=AllocMem(sizeof(struct MsgPort), + MEMF_PUBLIC|MEMF_CLEAR); + if(port==NULL) + success=FALSE; + + if(success) + { + NewList(&port->mp_MsgList); + port->mp_Flags=PA_IGNORE; + port->mp_SigTask=&unit->tx_int; + } + } + + card_handle=unit->card_handle= + AllocMem(sizeof(struct CardHandle),MEMF_PUBLIC|MEMF_CLEAR); + unit->tuple_buffer= + AllocVec(TUPLE_BUFFER_SIZE,MEMF_ANY); + unit->rx_buffer=AllocVec((MAX_PACKET_SIZE+3)&~3,MEMF_PUBLIC); + unit->tx_buffer=AllocVec(MAX_PACKET_SIZE,MEMF_PUBLIC); + if((card_handle==NULL)||(unit->tuple_buffer==NULL)|| + (unit->rx_buffer==NULL)||(unit->tx_buffer==NULL)) + success=FALSE; + } + + if(success) + { + NewList((APTR)&unit->openers); + NewList((APTR)&unit->type_trackers); + NewList((APTR)&unit->multicast_ranges); + + /* Initialise transmit and receive interrupts */ + + unit->rx_int.is_Node.ln_Name=(TEXT *)device_name; + unit->rx_int.is_Node.ln_Pri=16; + unit->rx_int.is_Code=RxInt; + unit->rx_int.is_Data=unit; + + unit->tx_int.is_Node.ln_Name=(TEXT *)device_name; + unit->tx_int.is_Code=TxInt; + unit->tx_int.is_Data=unit; + + unit->request_ports[WRITE_QUEUE]->mp_Flags=PA_SOFTINT; + } + + if(success) + { + /* Set up card handle */ + + card_handle->cah_CardNode.ln_Pri=HANDLE_PRIORITY; + card_handle->cah_CardNode.ln_Name=(APTR)device_name; + card_handle->cah_CardFlags=CARDF_IFAVAILABLE; + + card_handle->cah_CardRemoved=card_removed_int= + AllocVec(sizeof(struct Interrupt),MEMF_PUBLIC|MEMF_CLEAR); + + card_handle->cah_CardInserted=card_inserted_int= + AllocVec(sizeof(struct Interrupt),MEMF_PUBLIC|MEMF_CLEAR); + + card_handle->cah_CardStatus=card_status_int= + AllocVec(sizeof(struct Interrupt),MEMF_PUBLIC|MEMF_CLEAR); + + if((card_removed_int==NULL) + ||(card_inserted_int==NULL) + ||(card_status_int==NULL)) + success=FALSE; + } + + if(success) + { + /* Try to gain access to card */ + + card_removed_int->is_Code=CardRemovedInt; + card_removed_int->is_Data=unit; + card_inserted_int->is_Code=CardInsertedInt; + card_inserted_int->is_Data=unit; + card_status_int->is_Code=(APTR)CardStatusInt; + card_status_int->is_Data=unit; + + if(OwnCard(card_handle)!=0) + success=FALSE; + } + + if(success) + { + unit->flags|=UNITF_HAVECARD; + if(!InitialiseCard(unit,base)) + success=FALSE; + + /* Create a new task */ + + unit->task=task=AllocMem(sizeof(struct Task),MEMF_PUBLIC|MEMF_CLEAR); + if(task==NULL) + success=FALSE; + } + + if(success) + { + stack=AllocMem(STACK_SIZE,MEMF_PUBLIC); + if(stack==NULL) + success=FALSE; + } + + if(success) + { + /* Initialise and start task */ + + task->tc_Node.ln_Type=NT_TASK; + task->tc_Node.ln_Pri=TASK_PRIORITY; + task->tc_Node.ln_Name=(APTR)device_name; + task->tc_SPUpper=stack+STACK_SIZE; + task->tc_SPLower=stack; + task->tc_SPReg=stack+STACK_SIZE; + NewList(&task->tc_MemEntry); + + if(AddTask(task,UnitTask,NULL)==NULL) + success=FALSE; + } + + /* Send the unit to the new task */ + + if(success) + task->tc_UserData=unit; + + if(!success) + { + DeleteUnit(unit,base); + unit=NULL; + } + + return unit; +} + + + +/****i* 3c589.device/DeleteUnit ******************************************** +* +* NAME +* DeleteUnit -- Delete a unit. +* +* SYNOPSIS +* DeleteUnit(unit) +* +* VOID DeleteUnit(struct DevUnit *); +* +* FUNCTION +* Deletes a unit. +* +* INPUTS +* unit - Device unit (can be NULL). +* +* RESULT +* None. +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +VOID DeleteUnit(struct DevUnit *unit,struct DevBase *base) +{ + UBYTE i; + struct CardHandle *card_handle; + struct Task *task; + + if(unit!=NULL) + { + task=unit->task; + if(task!=NULL) + { + if(task->tc_SPLower!=NULL) + { + RemTask(task); + FreeMem(task->tc_SPLower,STACK_SIZE); + } + FreeMem(task,sizeof(struct Task)); + } + + for(i=0;irequest_ports[i]!=NULL) + FreeMem(unit->request_ports[i],sizeof(struct MsgPort)); + } + + FreeVec(unit->tuple_buffer); + + card_handle=unit->card_handle; + if(card_handle!=NULL) + { + if((unit->flags&UNITF_HAVECARD)!=0) + { + if((unit->flags&UNITF_HAVEADAPTER)!=0) + GoOffline(unit,base); + + unit->flags&=~UNITF_HAVEADAPTER; + CardMiscControl(card_handle,0); + CardResetCard(card_handle); + ReleaseCard(card_handle,CARDF_REMOVEHANDLE); + } + + FreeVec(card_handle->cah_CardStatus); + FreeVec(card_handle->cah_CardInserted); + FreeVec(card_handle->cah_CardRemoved); + + FreeMem(card_handle,sizeof(struct CardHandle)); + } + + FreeVec(unit->tx_buffer); + FreeVec(unit->rx_buffer); + + FreeMem(unit,sizeof(struct DevUnit)); + } + + return; +} + + + +/****i* 3c589.device/InitialiseCard **************************************** +* +* NAME +* InitialiseCard -- . +* +* SYNOPSIS +* success = InitialiseCard(unit) +* +* BOOL InitialiseCard(struct DevUnit *); +* +* FUNCTION +* +* INPUTS +* unit +* +* RESULT +* success +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BOOL InitialiseCard(struct DevUnit *unit,struct DevBase *base) +{ + BOOL success=TRUE; + struct CardMemoryMap *card_map; + struct CardHandle *card_handle; + UBYTE config_value,i,window_count,*tuple_buffer; + const struct TagItem *tuple_tags=NULL; + ULONG *io_bases,*io_lengths,io_base=0,config_base_offset; + UWORD maker,product; + + /* Wake up card */ + + card_handle=unit->card_handle; + CardMiscControl(card_handle,CARD_ENABLEF_DIGAUDIO|CARD_DISABLEF_WP); + + /* Get card's make and model */ + + tuple_buffer=unit->tuple_buffer; + if(CopyTuple(card_handle,tuple_buffer,PCCARD_TPL_MANFID,MAX_TUPLE_SIZE)) + { + tuple_tags=PCCard_GetTupleInfo(tuple_buffer); + if(tuple_tags!=NULL) + { + maker=GetTagData(PCCARD_Maker,0,tuple_tags); + product=GetTagData(PCCARD_Product,0,tuple_tags); + } + } + + /* Check this is a card we can use */ + + if((tuple_tags==NULL)||!((maker==0x101)&&((product==0x35)|| + (product==0x3d)||(product==0x562)||(product==0x589)|| + (product==0x556)||(product==0x574)))) + success=FALSE; + + if((product==0x556)||(product==0x574)) + unit->flags|=UNITF_ROADRUNNER; + + /* Get configuration data */ + + if(!CopyTuple(card_handle,tuple_buffer,PCCARD_TPL_CONFIG,MAX_TUPLE_SIZE)) + success=FALSE; + + if(success) + { + PCCard_FreeTupleInfo(tuple_tags); + tuple_tags=PCCard_GetTupleInfo(tuple_buffer); + if(tuple_tags==NULL) + success=FALSE; + } + + if(success) + { + config_base_offset=GetTagData(PCCARD_RegisterBase,0,tuple_tags); + + PCCard_FreeTupleInfo(tuple_tags); + tuple_tags=NULL; + + /* Get IO base */ + + if(!CopyTuple(card_handle,tuple_buffer,PCCARD_TPL_CFTABLEENTRY, + MAX_TUPLE_SIZE)) + success=FALSE; + } + + if(success) + { + tuple_tags=PCCard_GetTupleInfo(tuple_buffer); + if(tuple_tags==NULL) + success=FALSE; + } + + if(success) + { + config_value=GetTagData(PCCARD_ModeNo,0,tuple_tags); + if(product = 0x562 && config_value == 9) + config_value = 7; + + io_bases=(APTR)GetTagData(PCCARD_IOWinBases,NULL,tuple_tags); + if(io_bases==NULL) + success=FALSE; + } + + if(success) + { + io_lengths=(APTR)GetTagData(PCCARD_IOWinLengths,NULL,tuple_tags); + + window_count=GetTagData(PCCARD_IOWinCount,0,tuple_tags); + + for(i=0;(iconfig_base=card_map->cmm_AttributeMemory+config_base_offset; + + unit->io_base=card_map->cmm_IOMemory+io_base; + unit->config_base[PCCARD_REG_COR]=config_value; + unit->config_base[PCCARD_REG_CCSR]|=PCCARD_REG_CCSRF_AUDIOENABLE; + + InitialiseAdapter(unit,base); + unit->flags|=UNITF_HAVEADAPTER; + } + + return success; +} + + + +/****i* 3c589.device/InitialiseAdapter ************************************* +* +* NAME +* InitialiseAdapter -- . +* +* SYNOPSIS +* InitialiseAdapter(unit) +* +* VOID InitialiseAdapter(struct DevUnit *); +* +* FUNCTION +* +* INPUTS +* unit +* +* RESULT +* None. +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static VOID InitialiseAdapter(struct DevUnit *unit,struct DevBase *base) +{ + volatile UBYTE *io_base; + UBYTE *p,i; + UWORD address_part,config,link,media,new_media,medium,media_status; + + /* Select IO addresses and interrupt */ + + io_base=unit->io_base; + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|0); + LEWordOut(io_base+EL3REG_RESCONFIG,0x3f00); + + /* Get default MAC address */ + + p=unit->default_address; + + for(i=0;i>8; + *p++=address_part&0xff; + } + + /* Get available transceivers */ + + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|0); + media=LEWordIn(io_base+EL3REG_CONFIG); + + /* Get transceivers with an active link */ + + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|4); + link=0; + media_status=LEWordIn(io_base+EL3REG_MEDIA); + if((media_status&EL3REG_MEDIAF_BEAT)!=0) + link|=EL3REG_CONFIGF_HASTP; + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|0); + + new_media=media&link; + if((new_media)!=0) + media=new_media; + else + { + /* Get transceiver choice from EEPROM */ + + config=ReadEEPROM(io_base,EL3EEPROM_ADDRCONFIG)& + (EL3REG_ADDRCONFIG_XCVRMASK|EL3REG_ADDRCONFIGF_AUTOSELECT); + + if(config==EL3REG_ADDRCONFIG_XCVRTP) + new_media=EL3REG_CONFIGF_HASTP; + else if(config==EL3REG_ADDRCONFIG_XCVRAUI) + new_media=EL3REG_CONFIGF_HASAUI; + else if(config==EL3REG_ADDRCONFIG_XCVRCOAX) + new_media=EL3REG_CONFIGF_HASCOAX; + else + new_media=EL3REG_CONFIGF_HASTP|EL3REG_CONFIGF_HASCOAX| + EL3REG_CONFIGF_HASAUI; + + new_media&=media; + if(new_media!=0) + media=new_media; + } + + /* Prioritised choice from remaining transceivers */ + + if((media&EL3REG_CONFIGF_HASTP)!=0) + medium=EL3REG_ADDRCONFIG_XCVRTP; + else if((media&EL3REG_CONFIGF_HASCOAX)!=0) + medium=EL3REG_ADDRCONFIG_XCVRCOAX; + else + medium=EL3REG_ADDRCONFIG_XCVRAUI; + unit->transceiver=medium; + + return; +} + + + +/****i* 3c589.device/ConfigureAdapter ************************************** +* +* NAME +* ConfigureAdapter -- . +* +* SYNOPSIS +* ConfigureAdapter(unit) +* +* VOID ConfigureAdapter(struct DevUnit *); +* +* FUNCTION +* +* INPUTS +* unit +* +* RESULT +* None. +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +VOID ConfigureAdapter(struct DevUnit *unit,struct DevBase *base) +{ + volatile UBYTE *io_base; + UBYTE i; + + /* Set MAC address */ + + io_base=unit->io_base; + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|2); + + for(i=0;iaddress[i]); + + /* Decide on promiscuous mode */ + + if((unit->flags&UNITF_PROM)!=0) + unit->rx_filter_cmd|=EL3CMD_SETRXFILTERF_PROM; + + /* Select chosen transceiver */ + + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|0); + LEWordOut(io_base+EL3REG_ADDRCONFIG,unit->transceiver); + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|1); + + /* Go online */ + + GoOnline(unit,base); + + /* Return */ + + return; +} + + + +/****i* 3c589.device/GoOnline ********************************************** +* +* NAME +* GoOnline -- . +* +* SYNOPSIS +* GoOnline(unit) +* +* VOID GoOnline(struct DevUnit *); +* +* FUNCTION +* +* INPUTS +* unit +* +* RESULT +* None. +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +VOID GoOnline(struct DevUnit *unit,struct DevBase *base) +{ + volatile UBYTE *io_base; + UWORD transceiver; + + /* Choose interrupts */ + + unit->flags|=UNITF_ONLINE; + io_base=unit->io_base; + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SETINTMASK|INT_MASK); + LEWordOut(io_base+EL3REG_COMMAND,(EL3CMD_SETZEROMASK)|0xff); + + /* Enable the transceiver */ + + transceiver=unit->transceiver; + + if(transceiver==EL3REG_ADDRCONFIG_XCVRTP) + { + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|4); + LEWordOut(io_base+EL3REG_MEDIA, + EL3REG_MEDIAF_BEATENABLE|EL3REG_MEDIAF_JABBERENABLE); + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|1); + } + else if(transceiver==EL3REG_ADDRCONFIG_XCVRCOAX) + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_STARTCOAX|0); + + LEWordOut(io_base+EL3REG_COMMAND,unit->rx_filter_cmd); + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_RXENABLE); + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_TXENABLE); + + /* Record start time and report Online event */ + + GetSysTime(&unit->stats.LastStart); + ReportEvents(unit,S2EVENT_ONLINE,base); + + return; +} + + + +/****i* 3c589.device/GoOffline ********************************************* +* +* NAME +* GoOffline -- . +* +* SYNOPSIS +* GoOffline(unit) +* +* VOID GoOffline(struct DevUnit *); +* +* FUNCTION +* +* INPUTS +* unit +* +* RESULT +* None. +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +VOID GoOffline(struct DevUnit *unit,struct DevBase *base) +{ + volatile UBYTE *io_base; + + io_base=unit->io_base; + unit->flags&=~UNITF_ONLINE; + + if((unit->flags&UNITF_HAVEADAPTER)!=0) + { + /* Stop interrupts */ + + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SETINTMASK|0); + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_ACKINT|EL3INTF_ANY); + + /* Stop transmission and reception */ + + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_RXDISABLE); + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_TXDISABLE); + + /* Turn off media functions */ + + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|4); + LEWordOut(io_base+EL3REG_MEDIA,0); + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|1); + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_STOPCOAX|0); + } + + /* Flush pending read and write requests */ + + FlushUnit(unit,WRITE_QUEUE,S2ERR_OUTOFSERVICE,base); + + /* Report Offline event and return */ + + ReportEvents(unit,S2EVENT_OFFLINE,base); + return; +} + + + +/****i* 3c589.device/AddMulticastRange ************************************* +* +* NAME +* AddMulticastRange -- . +* +* SYNOPSIS +* success = AddMulticastRange(unit,lower_bound,upper_bound) +* +* BOOL AddMulticastRange(struct DevUnit *,UBYTE *,UBYTE *); +* +* FUNCTION +* +* INPUTS +* +* RESULT +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +BOOL AddMulticastRange(struct DevUnit *unit,UBYTE *lower_bound, + UBYTE *upper_bound,struct DevBase *base) +{ + struct AddressRange *range; + ULONG lower_bound_left,upper_bound_left; + UWORD lower_bound_right,upper_bound_right; + + lower_bound_left=BELong(*((ULONG *)lower_bound)); + lower_bound_right=BEWord(*((UWORD *)(lower_bound+4))); + upper_bound_left=BELong(*((ULONG *)upper_bound)); + upper_bound_right=BEWord(*((UWORD *)(upper_bound+4))); + + range=FindMulticastRange(unit,lower_bound_left,lower_bound_right, + upper_bound_left,upper_bound_right,base); + + if(range!=NULL) + range->add_count++; + else + { + range=AllocMem(sizeof(struct AddressRange),MEMF_PUBLIC); + if(range!=NULL) + { + range->lower_bound_left=lower_bound_left; + range->lower_bound_right=lower_bound_right; + range->upper_bound_left=upper_bound_left; + range->upper_bound_right=upper_bound_right; + range->add_count=1; + + Disable(); + AddTail((APTR)&unit->multicast_ranges,(APTR)range); + Enable(); + + if(unit->range_count++==0) + { + unit->rx_filter_cmd|=EL3CMD_SETRXFILTERF_MCAST; + LEWordOut(unit->io_base+EL3REG_COMMAND,unit->rx_filter_cmd); + } + } + } + + return range!=NULL; +} + + + +/****i* 3c589.device/RemMulticastRange ************************************* +* +* NAME +* RemMulticastRange -- . +* +* SYNOPSIS +* found = RemMulticastRange(unit,lower_bound,upper_bound) +* +* BOOL RemMulticastRange(struct DevUnit *,UBYTE *,UBYTE *); +* +* FUNCTION +* +* INPUTS +* +* RESULT +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +BOOL RemMulticastRange(struct DevUnit *unit,UBYTE *lower_bound, + UBYTE *upper_bound,struct DevBase *base) +{ + struct AddressRange *range; + ULONG lower_bound_left,upper_bound_left; + UWORD lower_bound_right,upper_bound_right; + + lower_bound_left=BELong(*((ULONG *)lower_bound)); + lower_bound_right=BEWord(*((UWORD *)(lower_bound+4))); + upper_bound_left=BELong(*((ULONG *)upper_bound)); + upper_bound_right=BEWord(*((UWORD *)(upper_bound+4))); + + range=FindMulticastRange(unit,lower_bound_left,lower_bound_right, + upper_bound_left,upper_bound_right,base); + + if(range!=NULL) + { + if(--range->add_count==0) + { + Disable(); + Remove((APTR)range); + Enable(); + FreeMem(range,sizeof(struct AddressRange)); + + if(--unit->range_count==0) + { + unit->rx_filter_cmd&=~EL3CMD_SETRXFILTERF_MCAST; + LEWordOut(unit->io_base+EL3REG_COMMAND,unit->rx_filter_cmd); + } + } + } + + return range!=NULL; +} + + + +/****i* 3c589.device/FindMulticastRange ************************************* +* +* NAME +* FindMulticastRange -- . +* +* SYNOPSIS +* range = FindMulticastRange(unit,lower_bound_left, +* lower_bound_right,upper_bound_left,upper_bound_right) +* +* struct AddressRange *FindMulticastRange(struct DevUnit *,ULONG, +* UWORD,ULONG,UWORD); +* +* FUNCTION +* +* INPUTS +* +* RESULT +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static struct AddressRange *FindMulticastRange(struct DevUnit *unit, + ULONG lower_bound_left,UWORD lower_bound_right,ULONG upper_bound_left, + UWORD upper_bound_right,struct DevBase *base) +{ + struct AddressRange *range,*tail; + BOOL found; + + range=(APTR)unit->multicast_ranges.mlh_Head; + tail=(APTR)&unit->multicast_ranges.mlh_Tail; + found=FALSE; + + while((range!=tail)&&!found) + { + if((lower_bound_left==range->lower_bound_left)&& + (lower_bound_right==range->lower_bound_right)&& + (upper_bound_left==range->upper_bound_left)&& + (upper_bound_right==range->upper_bound_right)) + found=TRUE; + else + range=(APTR)range->node.mln_Succ; + } + + if(!found) + range=NULL; + + return range; +} + + + +/****i* 3c589.device/FindTypeStats ***************************************** +* +* NAME +* FindTypeStats -- . +* +* SYNOPSIS +* stats = FindTypeStats(unit,list, +* packet_type) +* +* struct TypeStats *FindTypeStats(struct DevUnit *,struct MinList *, +* ULONG); +* +* FUNCTION +* +* INPUTS +* +* RESULT +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +struct TypeStats *FindTypeStats(struct DevUnit *unit,struct MinList *list, + ULONG packet_type,struct DevBase *base) +{ + struct TypeStats *stats,*tail; + BOOL found; + + stats=(APTR)list->mlh_Head; + tail=(APTR)&list->mlh_Tail; + found=FALSE; + + while((stats!=tail)&&!found) + { + if(stats->packet_type==packet_type) + found=TRUE; + else + stats=(APTR)stats->node.mln_Succ; + } + + if(!found) + stats=NULL; + + return stats; +} + + + +/****i* 3c589.device/FlushUnit ********************************************* +* +* NAME +* FlushUnit -- . +* +* SYNOPSIS +* FlushUnit(unit) +* +* VOID FlushUnit(struct DevUnit *); +* +* FUNCTION +* +* INPUTS +* +* RESULT +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +VOID FlushUnit(struct DevUnit *unit,UBYTE last_queue,BYTE error, + struct DevBase *base) +{ + struct IORequest *request; + UBYTE i; + struct Opener *opener,*tail; + + /* Abort queued requests */ + + for(i=0;i<=last_queue;i++) + { + while((request=(APTR)GetMsg(unit->request_ports[i]))!=NULL) + { + request->io_Error=IOERR_ABORTED; + ReplyMsg((APTR)request); + } + } + +#if 1 + opener=(APTR)unit->openers.mlh_Head; + tail=(APTR)&unit->openers.mlh_Tail; + + /* Flush every opener's read queue */ + + while(opener!=tail) + { + while((request=(APTR)GetMsg(&opener->read_port))!=NULL) + { + request->io_Error=error; + ReplyMsg((APTR)request); + } + opener=(APTR)opener->node.mln_Succ; + } + +#else + opener=request->ios2_BufferManagement; + while((request=(APTR)GetMsg(&opener->read_port))!=NULL) + { + request->io_Error=IOERR_ABORTED; + ReplyMsg((APTR)request); + } +#endif + + /* Return */ + + return; +} + + + +/****i* 3c589.device/CardRemovedInt **************************************** +* +* NAME +* CardRemovedInt -- . +* +* SYNOPSIS +* CardRemovedInt(unit) +* +* VOID CardRemovedInt(struct DevUnit *); +* +* FUNCTION +* +* INPUTS +* unit +* +* RESULT +* None. +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static VOID CardRemovedInt(struct DevUnit *unit REG("a1")) +{ + struct DevBase *base; + + /* Record loss of card and get our task to call ReleaseCard() */ + + base=unit->device; + unit->flags&=~(UNITF_HAVEADAPTER|UNITF_HAVECARD|UNITF_ONLINE); + Signal(unit->task,unit->card_removed_signal); + + return; +} + + + +/****i* 3c589.device/CardInsertedInt *************************************** +* +* NAME +* CardInsertedInt -- . +* +* SYNOPSIS +* CardInsertedInt(unit) +* +* VOID CardInsertedInt(struct DevUnit *); +* +* FUNCTION +* +* INPUTS +* unit +* +* RESULT +* None. +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static VOID CardInsertedInt(struct DevUnit *unit REG("a1")) +{ + struct DevBase *base; + + base=unit->device; + + Signal(unit->task,unit->card_inserted_signal); + + return; +} + + + +/****i* 3c589.device/CardStatusInt ***************************************** +* +* NAME +* CardStatusInt -- . +* +* SYNOPSIS +* mask = CardStatusInt(mask,unit) +* +* UBYTE CardStatusInt(UBYTE mask,struct DevUnit *); +* +* FUNCTION +* +* INPUTS +* mask +* unit +* +* RESULT +* None. +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static UBYTE CardStatusInt(UBYTE mask REG("d0"), + struct DevUnit *unit REG("a1")) +{ + struct DevBase *base; + volatile UBYTE *io_base; + UWORD ints; + + base=unit->device; + + if(((unit->flags&UNITF_HAVEADAPTER)!=0)&&((mask&CARD_STATUSF_IRQ)!=0)) + { + io_base=unit->io_base; + ints=LEWordIn(io_base+EL3REG_STATUS); + + if((ints&EL3INTF_ANY)!=0) /* ??? */ + { + /* Handle interrupts */ + + if((ints&EL3INTF_RXCOMPLETE)!=0) + { + LEWordOut(io_base+EL3REG_COMMAND, + EL3CMD_SETINTMASK|(INT_MASK&~EL3INTF_RXCOMPLETE)); + Cause(&unit->rx_int); + } + if((ints&EL3INTF_TXAVAIL)!=0) + { + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_ACKINT| + EL3INTF_TXAVAIL); + Cause(&unit->tx_int); + } + if((ints&EL3INTF_TXCOMPLETE)!=0) + TxError(unit,base); + + /* Acknowledge interrupt request */ + + LEWordOut(io_base+EL3REG_COMMAND, + EL3CMD_ACKINT|EL3INTF_ANY); + } + + /* Work around gayle interrupt bug */ + + *((volatile UBYTE *)0xda9000)=(mask^0x2c)|0xc0; + mask=0; + } + + return mask; +} + + + +/****i* 3c589.device/RxInt ************************************************* +* +* NAME +* RxInt -- . +* +* SYNOPSIS +* RxInt(unit) +* +* VOID RxInt(struct DevUnit *); +* +* FUNCTION +* +* INPUTS +* unit - A unit of this device. +* +* RESULT +* None. +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static VOID RxInt(struct DevUnit *unit REG("a1")) +{ + volatile UBYTE *io_base; + UWORD rx_status,packet_size; + struct DevBase *base; + BOOL is_orphan,accepted; + ULONG packet_type,*p,*end; + UBYTE *buffer; + struct IOSana2Req *request,*request_tail; + struct Opener *opener,*opener_tail; + struct TypeStats *tracker; + + base=unit->device; + io_base=unit->io_base; + buffer=unit->rx_buffer; + end=(ULONG *)(buffer+HEADER_SIZE); + + while(((rx_status=LEWordIn(io_base+EL3REG_RXSTATUS)) + &EL3REG_RXSTATUSF_INCOMPLETE)==0) + { + if((rx_status&EL3REG_RXSTATUSF_ERROR)==0) + { + /* Read packet header */ + + is_orphan=TRUE; + packet_size=rx_status&EL3REG_RXSTATUS_SIZEMASK; + p=(ULONG *)buffer; + while(popeners.mlh_Head; + opener_tail=(APTR)&unit->openers.mlh_Tail; + + /* Offer packet to every opener */ + + while(opener!=opener_tail) + { + request=(APTR)opener->read_port.mp_MsgList.lh_Head; + request_tail=(APTR)&opener->read_port.mp_MsgList.lh_Tail; + accepted=FALSE; + + /* Offer packet to each request until it's accepted */ + + while((request!=request_tail)&&!accepted) + { + if(request->ios2_PacketType==packet_type + ||request->ios2_PacketType<=MTU + &&packet_type<=MTU) + { + CopyPacket(unit,request,packet_size,packet_type, + !is_orphan,base); + accepted=TRUE; + } + request= + (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ; + } + + if(accepted) + is_orphan=FALSE; + opener=(APTR)opener->node.mln_Succ; + } + + /* If packet was unwanted, give it to S2_READORPHAN request */ + + if(is_orphan) + { + unit->stats.UnknownTypesReceived++; + if(!IsMsgPortEmpty(unit->request_ports[ADOPT_QUEUE])) + { + CopyPacket(unit, + (APTR)unit->request_ports[ADOPT_QUEUE]-> + mp_MsgList.lh_Head,packet_size,packet_type, + FALSE,base); + } + } + + /* Update remaining statistics */ + + unit->stats.PacketsReceived++; + + tracker= + FindTypeStats(unit,&unit->type_trackers,packet_type,base); + if(tracker!=NULL) + { + tracker->stats.PacketsReceived++; + tracker->stats.BytesReceived+=packet_size; + } + } + } + else + { + unit->stats.BadData++; + ReportEvents(unit,S2EVENT_ERROR|S2EVENT_HARDWARE|S2EVENT_RX,base); + } + + /* Discard packet */ + + Disable(); /* Needed? */ + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_RXDISCARD); + while((LEWordIn(io_base+EL3REG_STATUS)& + EL3REG_STATUSF_CMDINPROGRESS)!=0); + Enable(); + } + + /* Return */ + + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SETINTMASK|INT_MASK); + return; +} + + + +/****i* 3c589.device/CopyPacket ******************************************** +* +* NAME +* CopyPacket -- . +* +* SYNOPSIS +* CopyPacket(unit,request,packet_size,packet_type, +* all_read) +* +* VOID CopyPacket(struct DevUnit *,struct IOSana2Req *,UWORD,UWORD, +* BOOL); +* +* FUNCTION +* +* INPUTS +* +* RESULT +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static VOID CopyPacket(struct DevUnit *unit,struct IOSana2Req *request, + UWORD packet_size,UWORD packet_type,BOOL all_read,struct DevBase *base) +{ + volatile UBYTE *io_base; + struct Opener *opener; + UBYTE *buffer; + BOOL filtered=FALSE; + ULONG *p,*end; + + /* Set multicast and broadcast flags */ + + io_base=unit->io_base; + buffer=unit->rx_buffer; + request->ios2_Req.io_Flags&=~(SANA2IOF_BCAST|SANA2IOF_MCAST); + if((*((ULONG *)(buffer+PACKET_DEST))==0xffffffff)&& + (*((UWORD *)(buffer+PACKET_DEST+4))==0xffff)) + request->ios2_Req.io_Flags|=SANA2IOF_BCAST; + else if((buffer[PACKET_DEST]&0x1)!=0) + request->ios2_Req.io_Flags|=SANA2IOF_MCAST; + + /* Set source and destination addresses and packet type */ + + CopyMem(buffer+PACKET_SOURCE,request->ios2_SrcAddr,ADDRESS_SIZE); + CopyMem(buffer+PACKET_DEST,request->ios2_DstAddr,ADDRESS_SIZE); + request->ios2_PacketType=packet_type; + + /* Read rest of packet */ + + if(!all_read) + { + p=(ULONG *)(buffer+((PACKET_DATA+3)&~3)); + end=(ULONG *)(buffer+packet_size); + while(pios2_Req.io_Flags&SANA2IOF_RAW)==0) + { + packet_size-=PACKET_DATA; + buffer+=PACKET_DATA; + } +#ifdef USE_HACKS + else + packet_size+=4; /* Needed for Shapeshifter & Fusion */ +#endif + + request->ios2_DataLength=packet_size; + + /* Filter packet */ + + opener=request->ios2_BufferManagement; + if((request->ios2_Req.io_Command==CMD_READ)&& + (opener->filter_hook!=NULL)) + if(!CallHookPkt(opener->filter_hook,request,buffer)) + filtered=TRUE; + + if(!filtered) + { + /* Copy packet into opener's buffer and reply packet */ + + if(!opener->rx_function(request->ios2_Data,buffer,packet_size)) + { + request->ios2_Req.io_Error=S2ERR_NO_RESOURCES; + request->ios2_WireError=S2WERR_BUFF_ERROR; + ReportEvents(unit, + S2EVENT_ERROR|S2EVENT_SOFTWARE|S2EVENT_BUFF|S2EVENT_RX,base); + } + Remove((APTR)request); + ReplyMsg((APTR)request); + + } + + return; +} + + + +/****i* 3c589.device/AddressFilter ***************************************** +* +* NAME +* AddressFilter -- . +* +* SYNOPSIS +* accept = AddressFilter(unit,address) +* +* BOOL AddressFilter(struct DevUnit *,UBYTE *); +* +* FUNCTION +* +* INPUTS +* +* RESULT +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static BOOL AddressFilter(struct DevUnit *unit,UBYTE *address, + struct DevBase *base) +{ + struct AddressRange *range,*tail; + BOOL accept=TRUE; + ULONG address_left; + UWORD address_right; + + /* Check whether address is unicast/broadcast or multicast */ + + address_left=BELong(*((ULONG *)address)); + address_right=BEWord(*((UWORD *)(address+4))); + + if(((address_left&0x01000000)!=0)&& + !((address_left==0xffffffff)&&(address_right==0xffff))) + { + /* Check if this multicast address is wanted */ + + range=(APTR)unit->multicast_ranges.mlh_Head; + tail=(APTR)&unit->multicast_ranges.mlh_Tail; + accept=FALSE; + + while((range!=tail)&&!accept) + { + if(((address_left>range->lower_bound_left)|| + (address_left==range->lower_bound_left)&& + (address_right>=range->lower_bound_right))&& + ((address_leftupper_bound_left)|| + (address_left==range->upper_bound_left)&& + (address_right<=range->upper_bound_right))) + accept=TRUE; + range=(APTR)range->node.mln_Succ; + } + + if(!accept) + unit->special_stats[S2SS_ETHERNET_BADMULTICAST&0xffff]++; + } + + return accept; +} + + + +/****i* 3c589.device/TxInt ************************************************* +* +* NAME +* TxInt -- . +* +* SYNOPSIS +* TxInt(unit) +* +* VOID TxInt(struct DevUnit *); +* +* FUNCTION +* +* INPUTS +* unit - A unit of this device. +* +* RESULT +* None. +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static VOID TxInt(struct DevUnit *unit REG("a1")) +{ + volatile UBYTE *io_base; + UWORD packet_size,data_size,send_size; + struct DevBase *base; + struct IOSana2Req *request; + BOOL proceed=TRUE; + struct Opener *opener; + ULONG *buffer,*end,wire_error; + ULONG *(*dma_tx_function)(APTR REG("a0")); + BYTE error; + struct MsgPort *port; + struct TypeStats *tracker; + + base=unit->device; + io_base=unit->io_base; + + port=unit->request_ports[WRITE_QUEUE]; + + while(proceed&&(!IsMsgPortEmpty(port))) + { + error=0; + + request=(APTR)port->mp_MsgList.lh_Head; + data_size=packet_size=request->ios2_DataLength; + + if((request->ios2_Req.io_Flags&SANA2IOF_RAW)==0) + packet_size+=PACKET_DATA; + + if(LEWordIn(io_base+EL3REG_TXSPACE)>PREAMBLE_SIZE+packet_size) + { + /* Write packet preamble */ + + LELongOut(io_base+EL3REG_DATA0,packet_size); + + /* Write packet header */ + + send_size=(packet_size+3)&(~0x3); + if((request->ios2_Req.io_Flags&SANA2IOF_RAW)==0) + { + LongOut(io_base+EL3REG_DATA0,*((ULONG *)request->ios2_DstAddr)); + WordOut(io_base+EL3REG_DATA0, + *((UWORD *)(request->ios2_DstAddr+4))); + WordOut(io_base+EL3REG_DATA0,*((UWORD *)unit->address)); + LongOut(io_base+EL3REG_DATA0,*((ULONG *)(unit->address+2))); + BEWordOut(io_base+EL3REG_DATA0,request->ios2_PacketType); + send_size-=PACKET_DATA; + } + + /* Get packet data */ + + opener=(APTR)request->ios2_BufferManagement; + dma_tx_function=opener->dma_tx_function; + if(dma_tx_function!=NULL) + buffer=dma_tx_function(request->ios2_Data); + else + buffer=NULL; + + if(buffer==NULL) + { + buffer=(ULONG *)unit->tx_buffer; + if(!opener->tx_function(buffer,request->ios2_Data,data_size)) + { + error=S2ERR_NO_RESOURCES; + wire_error=S2WERR_BUFF_ERROR; + ReportEvents(unit, + S2EVENT_ERROR|S2EVENT_SOFTWARE|S2EVENT_BUFF|S2EVENT_TX, + base); + } + } + + /* Write packet data */ + + if(error==0) + { + end=buffer+(send_size>>2); + while(bufferios2_Req.io_Error=error; + request->ios2_WireError=wire_error; + Remove((APTR)request); + ReplyMsg((APTR)request); + + /* Update statistics */ + + if(error==0) + { + unit->stats.PacketsSent++; + + tracker=FindTypeStats(unit,&unit->type_trackers, + request->ios2_PacketType,base); + if(tracker!=NULL) + { + tracker->stats.PacketsSent++; + tracker->stats.BytesSent+=packet_size; + } + } + } + else + proceed=FALSE; + } + + if(proceed) + unit->request_ports[WRITE_QUEUE]->mp_Flags=PA_SOFTINT; + else + { + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SETTXTHRESH + |(PREAMBLE_SIZE+packet_size)); + unit->request_ports[WRITE_QUEUE]->mp_Flags=PA_IGNORE; + } + + return; +} + + + +/****i* 3c589.device/TxError *********************************************** +* +* NAME +* TxError -- . +* +* SYNOPSIS +* TxError(unit) +* +* VOID TxError(struct DevUnit *); +* +* FUNCTION +* +* INPUTS +* unit - A unit of this device. +* +* RESULT +* None. +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +VOID TxError(struct DevUnit *unit,struct DevBase *base) +{ + volatile UBYTE *io_base; + UBYTE tx_status,flags=0; + + io_base=unit->io_base; + + /* Gather all errors */ + + while(((tx_status=ByteIn(io_base+EL3REG_TXSTATUS)) + &EL3REG_TXSTATUSF_COMPLETE)!=0) + { + flags|=tx_status; + ByteOut(io_base+EL3REG_TXSTATUS,0); + } + + /* Restart transmitter if necessary */ + + if((flags&EL3REG_TXSTATUSF_JABBER)!=0) + { + Disable(); + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_TXRESET); + while((LEWordIn(io_base+EL3REG_STATUS)& + EL3REG_STATUSF_CMDINPROGRESS)!=0); + Enable(); + } + + if((flags&(EL3REG_TXSTATUSF_JABBER|EL3REG_TXSTATUSF_OVERFLOW))!=0) + LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_TXENABLE); + + /* Report the error(s) */ + + ReportEvents(unit,S2EVENT_ERROR|S2EVENT_HARDWARE|S2EVENT_TX,base); + + return; +} + + + +/****i* 3c589.device/ReportEvents ****************************************** +* +* NAME +* ReportEvents -- . +* +* SYNOPSIS +* ReportEvents(unit,events) +* +* VOID ReportEvents(struct DevUnit *,ULONG); +* +* FUNCTION +* +* INPUTS +* unit - A unit of this device. +* events - A mask of events to report. +* +* RESULT +* None. +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static VOID ReportEvents(struct DevUnit *unit,ULONG events, + struct DevBase *base) +{ + struct IOSana2Req *request,*tail,*next_request; + struct List *list; + + list=&unit->request_ports[EVENT_QUEUE]->mp_MsgList; + next_request=(APTR)list->lh_Head; + tail=(APTR)&list->lh_Tail; + + Disable(); + while(next_request!=tail) + { + request=next_request; + next_request=(APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ; + + if((request->ios2_WireError&events)!=0) + { + request->ios2_WireError=events; + Remove((APTR)request); + ReplyMsg((APTR)request); + } + } + Enable(); + + return; +} + + + +/****i* 3c589.device/UnitTask ********************************************** +* +* NAME +* UnitTask -- . +* +* SYNOPSIS +* UnitTask() +* +* VOID UnitTask(); +* +* FUNCTION +* +* INPUTS +* +* RESULT +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static VOID UnitTask() +{ + struct Task *task; + struct IORequest *request; + struct DevUnit *unit; + struct DevBase *base; + struct MsgPort *general_port; + ULONG signals,wait_signals,card_removed_signal,card_inserted_signal, + general_port_signal; + + /* Get parameters */ + + task=AbsExecBase->ThisTask; + unit=task->tc_UserData; + base=unit->device; + + /* Activate general request port */ + + general_port=unit->request_ports[GENERAL_QUEUE]; + general_port->mp_SigTask=task; + general_port->mp_SigBit=AllocSignal(-1); + general_port_signal=1<mp_SigBit; + general_port->mp_Flags=PA_SIGNAL; + + /* Allocate a signal for notification of card removal */ + + card_removed_signal=unit->card_removed_signal=1<card_inserted_signal=1<mp_SigBit)|card_removed_signal + |card_inserted_signal; + + /* Tell ourselves to check port for old messages */ + + Signal(task,general_port_signal); + + /* Infinite loop to service requests and signals */ + + while(TRUE) + { + signals=Wait(wait_signals); + + if((signals&card_inserted_signal)!=0) + { + if(InitialiseCard(unit,base)) + { + unit->flags|=UNITF_HAVECARD; + if((unit->flags&UNITF_CONFIGURED)!=0) + ConfigureAdapter(unit,base); + } + else + ReleaseCard(unit->card_handle,0); + } + + if((signals&card_removed_signal)!=0) + { + ReleaseCard(unit->card_handle,0); + GoOffline(unit,base); + } + + if((signals&general_port_signal)!=0) + { + while((request=(APTR)GetMsg(general_port))!=NULL) + { + /* Service the request as soon as the unit is free */ + + ObtainSemaphore(&unit->access_lock); + ServiceRequest((APTR)request,base); + } + } + } +} + + + +/****i* 3c589.device/ReadEEPROM ******************************************** +* +* NAME +* ReadEEPROM -- . +* +* SYNOPSIS +* value = ReadEEPROM(io_base,index) +* +* UWORD ReadEEPROM(UBYTE *,UWORD); +* +* FUNCTION +* +* INPUTS +* io_base - Base of adapter's register window. +* index - Offset within EEPROM. +* +* RESULT +* value - Contents of specified EEPROM location. +* +* EXAMPLE +* +* NOTES +* +* BUGS +* +* SEE ALSO +* +**************************************************************************** +* +*/ + +static UWORD ReadEEPROM(volatile UBYTE *io_base,UWORD index) +{ + LEWordOut(io_base+EL3REG_EEPROMCMD,EL3ECMD_READ|index); + while((LEWordIn(io_base+EL3REG_EEPROMCMD)&EL3REG_EEPROMCMDF_BUSY) + !=0); + return LEWordIn(io_base+EL3REG_EEPROMDATA); +} + + + diff --git a/Source/unit_protos.h b/Source/unit_protos.h new file mode 100644 index 0000000..d0bcbd3 --- /dev/null +++ b/Source/unit_protos.h @@ -0,0 +1,49 @@ +/* + +File: unit_protos.h +Author: Neil Cafferkey +Copyright (C) 2002 Neil Cafferkey + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. + +*/ + +#ifndef UNIT_PROTOS_H +#define UNIT_PROTOS_H + + +#include "device.h" + +struct DevUnit *GetUnit(ULONG unit_num,struct DevBase *base); +struct DevUnit *FindUnit(ULONG unit_num,struct DevBase *base); +struct DevUnit *CreateUnit(ULONG unit_num,struct DevBase *base); +VOID DeleteUnit(struct DevUnit *unit,struct DevBase *base); +VOID ConfigureAdapter(struct DevUnit *unit,struct DevBase *base); +VOID GoOnline(struct DevUnit *unit,struct DevBase *base); +VOID GoOffline(struct DevUnit *unit,struct DevBase *base); +BOOL AddMulticastRange(struct DevUnit *unit,UBYTE *lower_bound, + UBYTE *upper_bound,struct DevBase *base); +BOOL RemMulticastRange(struct DevUnit *unit,UBYTE *lower_bound, + UBYTE *upper_bound,struct DevBase *base); +struct TypeStats *FindTypeStats(struct DevUnit *unit,struct MinList *list, + ULONG packet_type,struct DevBase *base); +VOID FlushUnit(struct DevUnit *unit,UBYTE last_queue,BYTE error, + struct DevBase *base); + + +#endif + +