Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / networks / etherlink3 / device.c
bloba63e09f7f8a73e62563c16a278711404607569e5
1 /*
3 Copyright (C) 2000-2008 Neil Cafferkey
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 MA 02111-1307, USA.
23 #include <exec/types.h>
24 #include <exec/resident.h>
25 #include <exec/errors.h>
26 #include <utility/utility.h>
27 #include "initializers.h"
29 #include <proto/exec.h>
30 #include <clib/alib_protos.h>
31 #include <proto/utility.h>
33 #include "device.h"
35 #include "device_protos.h"
36 #include "pci_protos.h"
37 #include "pccard_protos.h"
38 #include "request_protos.h"
41 /* Private prototypes */
43 static VOID DeleteDevice(struct DevBase *base);
46 /* Return an error immediately if someone tries to run the device */
48 LONG Main()
50 return -1;
54 const TEXT device_name[] = DEVICE_NAME;
55 const TEXT version_string[] =
56 DEVICE_NAME " " STR(VERSION) "." STR(REVISION) " (" DATE ")\n";
57 const TEXT utility_name[] = UTILITYNAME;
58 static const TEXT prometheus_name[] = "prometheus.library";
59 static const TEXT powerpci_name[] = "powerpci.library";
60 const TEXT pccard_name[] = "pccard.library";
61 const TEXT card_name[] = "card.resource";
62 const TEXT timer_name[] = TIMERNAME;
65 static const APTR vectors[] =
67 (APTR)DevOpen,
68 (APTR)DevClose,
69 (APTR)DevExpunge,
70 (APTR)DevReserved,
71 (APTR)DevBeginIO,
72 (APTR)DevAbortIO,
73 (APTR)-1
77 #ifdef __MORPHOS__
78 #pragma pack(2)
79 #endif
80 const struct
82 SMALLINITBYTEDEF(type);
83 SMALLINITPINTDEF(name);
84 SMALLINITBYTEDEF(flags);
85 SMALLINITWORDDEF(version);
86 SMALLINITWORDDEF(revision);
87 SMALLINITPINTDEF(id_string);
88 INITENDDEF;
90 init_data =
92 SMALLINITBYTE(OFFSET(Node, ln_Type), NT_DEVICE),
93 SMALLINITPINT(OFFSET(Node, ln_Name), device_name),
94 SMALLINITBYTE(OFFSET(Library, lib_Flags), LIBF_SUMUSED | LIBF_CHANGED),
95 SMALLINITWORD(OFFSET(Library, lib_Version), VERSION),
96 SMALLINITWORD(OFFSET(Library, lib_Revision), REVISION),
97 SMALLINITPINT(OFFSET(Library, lib_IdString), version_string),
98 INITEND
100 #ifdef __MORPHOS__
101 #pragma pack()
102 #endif
105 static const APTR init_table[] =
107 (APTR)sizeof(struct DevBase),
108 (APTR)vectors,
109 (APTR)&init_data,
110 (APTR)DevInit
114 const struct Resident rom_tag =
116 RTC_MATCHWORD,
117 (struct Resident *)&rom_tag,
118 (APTR)(&rom_tag + 1),
119 RTF_AUTOINIT,
120 VERSION,
121 NT_DEVICE,
123 (STRPTR)device_name,
124 (STRPTR)version_string,
125 (APTR)init_table
129 static const ULONG rx_tags[] =
131 S2_CopyToBuff,
132 S2_CopyToBuff16,
136 static const ULONG tx_tags[] =
138 S2_CopyFromBuff,
139 S2_CopyFromBuff16,
140 S2_CopyFromBuff32
145 /****i* etherlink3.device/DevInit ******************************************
147 * NAME
148 * DevInit
150 * SYNOPSIS
151 * dev_base = DevInit(dev_base, seg_list)
153 * struct DevBase *DevInit(struct DevBase *, APTR);
155 ****************************************************************************
159 struct DevBase *DevInit(REG(d0, struct DevBase *dev_base),
160 REG(a0, APTR seg_list), REG(BASE_REG, struct DevBase *base))
162 BOOL success = TRUE;
164 /* Initialise base structure */
166 dev_base->sys_base = (APTR)base;
167 base = dev_base;
168 base->seg_list = seg_list;
169 NewList((APTR)(&base->pci_units));
170 NewList((APTR)(&base->isa_units));
171 NewList((APTR)(&base->pccard_units));
173 /* Open libraries, resources and devices */
175 base->utility_base = (APTR)OpenLibrary(utility_name, UTILITY_VERSION);
176 base->prometheus_base = OpenLibrary(prometheus_name, PROMETHEUS_VERSION);
177 if(base->prometheus_base == NULL)
178 base->powerpci_base = OpenLibrary(powerpci_name, POWERPCI_VERSION);
179 base->pccard_base = OpenLibrary(pccard_name, PCCARD_VERSION);
180 if(base->pccard_base != NULL)
181 base->card_base = OpenResource(card_name);
183 if(base->utility_base == NULL)
184 success = FALSE;
186 if(OpenDevice(timer_name, UNIT_ECLOCK, (APTR)&base->timer_request, 0)
187 != 0)
188 success = FALSE;
190 if(!success)
192 DeleteDevice(base);
193 base = NULL;
196 return base;
201 /****i* etherlink3.device/DevOpen ******************************************
203 * NAME
204 * DevOpen
206 * SYNOPSIS
207 * error = DevOpen(request, unit_num, flags)
209 * BYTE DevOpen(struct IOSana2Req *, ULONG, ULONG);
211 ****************************************************************************
215 BYTE DevOpen(REG(a1, struct IOSana2Req *request),
216 REG(d0, ULONG unit_num), REG(d1, ULONG flags),
217 REG(BASE_REG, struct DevBase *base))
219 struct DevUnit *unit;
220 BYTE error = 0;
221 struct Opener *opener;
222 struct TagItem *tag_list;
223 UWORD i;
225 base->device.dd_Library.lib_OpenCnt++;
226 base->device.dd_Library.lib_Flags &= ~LIBF_DELEXP;
228 request->ios2_Req.io_Unit = NULL;
229 tag_list = request->ios2_BufferManagement;
230 request->ios2_BufferManagement = NULL;
232 /* Check request size */
234 if(request->ios2_Req.io_Message.mn_Length < sizeof(struct IOSana2Req))
235 error = IOERR_OPENFAIL;
237 /* Get the requested unit */
239 if(error == 0)
241 request->ios2_Req.io_Unit = (APTR)(unit = GetUnit(unit_num, base));
242 if(unit == NULL)
243 error = IOERR_OPENFAIL;
246 /* Handle device sharing */
248 if(error == 0)
250 if(unit->open_count != 0 && ((unit->flags & UNITF_SHARED) == 0
251 || (flags & SANA2OPF_MINE) != 0))
252 error = IOERR_UNITBUSY;
253 unit->open_count++;
256 if(error == 0)
258 if((flags & SANA2OPF_MINE) == 0)
259 unit->flags |= UNITF_SHARED;
260 else if((flags & SANA2OPF_PROM) != 0)
261 unit->flags |= UNITF_PROM;
263 /* Set up buffer-management structure and get hooks */
265 request->ios2_BufferManagement = opener =
266 AllocVec(sizeof(struct Opener), MEMF_PUBLIC | MEMF_CLEAR);
267 if(opener == NULL)
268 error = IOERR_OPENFAIL;
271 if(error == 0)
273 NewList(&opener->read_port.mp_MsgList);
274 opener->read_port.mp_Flags = PA_IGNORE;
275 NewList((APTR)&opener->initial_stats);
277 for(i = 0; i < 2; i++)
278 opener->rx_function = (APTR)GetTagData(rx_tags[i],
279 (UPINT)opener->rx_function, tag_list);
280 for(i = 0; i < 3; i++)
281 opener->tx_function = (APTR)GetTagData(tx_tags[i],
282 (UPINT)opener->tx_function, tag_list);
284 opener->filter_hook = (APTR)GetTagData(S2_PacketFilter, (UPINT)NULL,
285 tag_list);
286 opener->dma_tx_function =
287 (APTR)GetTagData(S2_DMACopyFromBuff32, (UPINT)NULL, tag_list);
289 Disable();
290 AddTail((APTR)&unit->openers, (APTR)opener);
291 Enable();
294 /* Back out if anything went wrong */
296 if(error != 0)
297 CloseUnit(request, base);
299 /* Return */
301 request->ios2_Req.io_Error = error;
302 return error;
307 /****i* etherlink3.device/DevClose *****************************************
309 * NAME
310 * DevClose
312 * SYNOPSIS
313 * seg_list = DevClose(request)
315 * APTR DevClose(struct IOSana2Req *);
317 ****************************************************************************
321 APTR DevClose(REG(a1, struct IOSana2Req *request),
322 REG(BASE_REG, struct DevBase *base))
324 APTR seg_list = NULL;
326 /* Close the unit */
328 CloseUnit(request, base);
330 /* Expunge the device if a delayed expunge is pending */
332 if(base->device.dd_Library.lib_OpenCnt == 0)
334 if((base->device.dd_Library.lib_Flags & LIBF_DELEXP) != 0)
335 seg_list = DevExpunge(base);
338 return seg_list;
343 /****i* etherlink3.device/DevExpunge ***************************************
345 * NAME
346 * DevExpunge
348 * SYNOPSIS
349 * seg_list = DevExpunge()
351 * APTR DevExpunge(VOID);
353 ****************************************************************************
357 APTR DevExpunge(REG(BASE_REG, struct DevBase *base))
359 APTR seg_list;
361 if(base->device.dd_Library.lib_OpenCnt == 0)
363 seg_list = base->seg_list;
364 Remove((APTR)base);
365 DeleteDevice(base);
367 else
369 base->device.dd_Library.lib_Flags |= LIBF_DELEXP;
370 seg_list = NULL;
373 return seg_list;
378 /****i* etherlink3.device/DevReserved **************************************
380 * NAME
381 * DevReserved
383 * SYNOPSIS
384 * result = DevReserved()
386 * APTR DevReserved(VOID);
388 ****************************************************************************
392 APTR DevReserved()
394 return NULL;
399 /****i* etherlink3.device/DevBeginIO ***************************************
401 * NAME
402 * DevBeginIO
404 * SYNOPSIS
405 * DevBeginIO(request)
407 * VOID DevBeginIO(struct IORequest *);
409 ****************************************************************************
413 VOID DevBeginIO(REG(a1, struct IOSana2Req *request),
414 REG(BASE_REG, struct DevBase *base))
416 struct DevUnit *unit;
418 request->ios2_Req.io_Error = 0;
419 unit = (APTR)request->ios2_Req.io_Unit;
421 if(AttemptSemaphore(&unit->access_lock))
422 ServiceRequest(request, base);
423 else
424 PutRequest(unit->request_ports[GENERAL_QUEUE], (APTR)request, base);
426 return;
431 /****i* etherlink3.device/DevAbortIO ***************************************
433 * NAME
434 * DevAbortIO -- Try to stop a request.
436 * SYNOPSIS
437 * DevAbortIO(request)
439 * VOID DevAbortIO(struct IOSana2Req *);
441 * FUNCTION
442 * Do our best to halt the progress of a request.
444 ****************************************************************************
446 * Disable() used instead of a semaphore because device uses interrupts.
450 VOID DevAbortIO(REG(a1, struct IOSana2Req *request),
451 REG(BASE_REG, struct DevBase *base))
453 Disable();
454 if(request->ios2_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE &&
455 (request->ios2_Req.io_Flags & IOF_QUICK) == 0)
457 Remove((APTR)request);
458 request->ios2_Req.io_Error = IOERR_ABORTED;
459 request->ios2_WireError = S2WERR_GENERIC_ERROR;
460 ReplyMsg((APTR)request);
462 Enable();
464 return;
469 /****i* etherlink3.device/DeleteDevice *************************************
471 * NAME
472 * DeleteDevice
474 * SYNOPSIS
475 * DeleteDevice()
477 * VOID DeleteDevice(VOID);
479 ****************************************************************************
483 VOID DeleteDevice(struct DevBase *base)
485 UWORD neg_size, pos_size;
487 /* Close devices */
489 CloseDevice((APTR)&base->timer_request);
491 /* Close libraries */
493 if(base->openpci_base != NULL)
494 CloseLibrary(base->openpci_base);
495 if(base->pccard_base != NULL)
496 CloseLibrary(base->pccard_base);
497 if(base->powerpci_base != NULL)
498 CloseLibrary(base->powerpci_base);
499 if(base->prometheus_base != NULL)
500 CloseLibrary(base->prometheus_base);
501 if(base->utility_base != NULL)
502 CloseLibrary((APTR)base->utility_base);
504 /* Free device's memory */
506 neg_size = base->device.dd_Library.lib_NegSize;
507 pos_size = base->device.dd_Library.lib_PosSize;
508 FreeMem((UBYTE *)base - neg_size, pos_size + neg_size);
510 return;
515 /****i* etherlink3.device/CloseUnit ****************************************
517 * NAME
518 * CloseUnit
520 * SYNOPSIS
521 * CloseUnit(request)
523 * VOID CloseUnit(struct IOSana2Req *);
525 ****************************************************************************
529 VOID CloseUnit(struct IOSana2Req *request, struct DevBase *base)
531 struct DevUnit *unit;
532 struct Opener *opener;
534 /* Decrement device usage count and free buffer-management resources */
536 base->device.dd_Library.lib_OpenCnt--;
537 opener = (APTR)request->ios2_BufferManagement;
538 if(opener != NULL)
540 Disable();
541 Remove((APTR)opener);
542 Enable();
543 FreeVec(opener);
546 /* Delete the unit if it's no longer in use */
548 unit = (APTR)request->ios2_Req.io_Unit;
549 if(unit != NULL)
551 if((--unit->open_count) == 0)
553 Remove((APTR)unit);
554 switch(unit->bus)
556 case PCI_BUS:
557 DeletePCIUnit(unit, base);
558 break;
559 case PCCARD_BUS:
560 DeletePCCardUnit(unit, base);
561 break;
566 return;
571 /****i* etherlink3.device/GetUnit ******************************************
573 * NAME
574 * GetUnit -- Get a unit by number.
576 * SYNOPSIS
577 * unit = GetUnit(unit_num)
579 * struct DevUnit *GetUnit(ULONG);
581 ****************************************************************************
585 struct DevUnit *GetUnit(ULONG unit_num, struct DevBase *base)
587 struct DevUnit *unit;
588 ULONG pci_limit;
589 ULONG pccard_limit;
591 pci_limit = GetPCICount(base);
592 pccard_limit = pci_limit + GetPCCardCount(base);
594 if(unit_num < pci_limit)
595 unit = GetPCIUnit(unit_num, base);
596 else if(unit_num < pccard_limit)
597 unit = GetPCCardUnit(unit_num - pci_limit, base);
598 else
599 unit = NULL;
601 return unit;
606 /****i* etherlink3.device/WrapInt ******************************************
608 * NAME
609 * WrapInt
611 ****************************************************************************
615 BOOL WrapInt(struct Interrupt *interrupt, struct DevBase *base)
617 BOOL success = TRUE;
618 APTR *int_data;
620 if(base->wrapper_int_code != NULL)
622 int_data = AllocMem(2 * sizeof(APTR), MEMF_PUBLIC | MEMF_CLEAR);
623 if(int_data != NULL)
625 int_data[0] = interrupt->is_Code;
626 int_data[1] = interrupt->is_Data;
627 interrupt->is_Code = base->wrapper_int_code;
628 interrupt->is_Data = int_data;
630 else
631 success = FALSE;
634 return success;
639 /****i* etherlink3.device/UnwrapInt ****************************************
641 * NAME
642 * UnwrapInt
644 ****************************************************************************
648 VOID UnwrapInt(struct Interrupt *interrupt, struct DevBase *base)
650 if(interrupt->is_Code == base->wrapper_int_code)
651 FreeMem(interrupt->is_Data, 2 * sizeof(APTR));
653 return;
657 /****i* etherlink3.device/WrapCardInt **************************************
659 * NAME
660 * WrapCardInt
662 ****************************************************************************
666 BOOL WrapCardInt(struct Interrupt *interrupt, struct DevBase *base)
668 BOOL success = TRUE;
669 APTR *int_data;
671 if(base->wrapper_card_code != NULL)
673 int_data = AllocMem(2 * sizeof(APTR), MEMF_PUBLIC | MEMF_CLEAR);
674 if(int_data != NULL)
676 int_data[0] = interrupt->is_Code;
677 int_data[1] = interrupt->is_Data;
678 interrupt->is_Code = base->wrapper_card_code;
679 interrupt->is_Data = int_data;
681 else
682 success = FALSE;
685 return success;
690 /****i* etherlink3.device/UnwrapCardInt ************************************
692 * NAME
693 * UnwrapCardInt
695 ****************************************************************************
699 VOID UnwrapCardInt(struct Interrupt *interrupt, struct DevBase *base)
701 if(interrupt->is_Code == base->wrapper_card_code)
702 FreeMem(interrupt->is_Data, 2 * sizeof(APTR));
704 return;