grub2: bring back build of aros-side grub2 tools
[AROS.git] / workbench / devs / networks / prism2 / device.c
blob78d848bdd2d0b9422aabd39211dff6f8f263aea7
1 /*
3 Copyright (C) 2000-2011 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 <dos/dos.h>
27 #include <utility/utility.h>
28 #include "initializers.h"
30 #include <proto/exec.h>
31 #include <clib/alib_protos.h>
32 #include <proto/utility.h>
34 #include "device.h"
36 #include "device_protos.h"
37 #include "pci_protos.h"
38 #include "pccard_protos.h"
39 #include "request_protos.h"
42 /* Private prototypes */
44 static VOID DeleteDevice(struct DevBase *base);
47 /* Return an error immediately if someone tries to run the device */
49 LONG Main()
51 return -1;
55 const TEXT device_name[] = DEVICE_NAME;
56 const TEXT version_string[] =
57 DEVICE_NAME " " STR(VERSION) "." STR(REVISION) " (" DATE ")\n";
58 const TEXT utility_name[] = UTILITYNAME;
59 static const TEXT prometheus_name[] = "prometheus.library";
60 static const TEXT powerpci_name[] = "powerpci.library";
61 static const TEXT cybpci_name[] = "cybpci.library";
62 const TEXT pccard_name[] = "pccard.library";
63 const TEXT card_name[] = "card.resource";
64 const TEXT dos_name[] = DOSNAME;
65 const TEXT timer_name[] = TIMERNAME;
68 static const APTR vectors[] =
70 (APTR)DevOpen,
71 (APTR)DevClose,
72 (APTR)DevExpunge,
73 (APTR)DevReserved,
74 (APTR)DevBeginIO,
75 (APTR)DevAbortIO,
76 (APTR)-1
80 #ifdef __MORPHOS__
81 #pragma pack(2)
82 #endif
83 const struct
85 SMALLINITBYTEDEF(type);
86 SMALLINITPINTDEF(name);
87 SMALLINITBYTEDEF(flags);
88 SMALLINITWORDDEF(version);
89 SMALLINITWORDDEF(revision);
90 SMALLINITPINTDEF(id_string);
91 INITENDDEF;
93 init_data =
95 SMALLINITBYTE(OFFSET(Node, ln_Type), NT_DEVICE),
96 SMALLINITPINT(OFFSET(Node, ln_Name), device_name),
97 SMALLINITBYTE(OFFSET(Library, lib_Flags), LIBF_SUMUSED | LIBF_CHANGED),
98 SMALLINITWORD(OFFSET(Library, lib_Version), VERSION),
99 SMALLINITWORD(OFFSET(Library, lib_Revision), REVISION),
100 SMALLINITPINT(OFFSET(Library, lib_IdString), version_string),
101 INITEND
103 #ifdef __MORPHOS__
104 #pragma pack()
105 #endif
108 static const APTR init_table[] =
110 (APTR)sizeof(struct DevBase),
111 (APTR)vectors,
112 (APTR)&init_data,
113 (APTR)DevInit
117 const struct Resident rom_tag =
119 RTC_MATCHWORD,
120 (struct Resident *)&rom_tag,
121 (APTR)(&rom_tag + 1),
122 RTF_AUTOINIT,
123 VERSION,
124 NT_DEVICE,
126 (STRPTR)device_name,
127 (STRPTR)version_string,
128 (APTR)init_table
132 static const ULONG rx_tags[] =
134 S2_CopyToBuff,
135 S2_CopyToBuff16,
139 static const ULONG tx_tags[] =
141 S2_CopyFromBuff,
142 S2_CopyFromBuff16,
143 S2_CopyFromBuff32
148 /****i* prism2.device/DevInit **********************************************
150 * NAME
151 * DevInit
153 * SYNOPSIS
154 * dev_base = DevInit(dev_base, seg_list)
156 * struct DevBase *DevInit(struct DevBase *, APTR);
158 ****************************************************************************
162 struct DevBase *DevInit(REG(d0, struct DevBase *dev_base),
163 REG(a0, APTR seg_list), REG(BASE_REG, struct DevBase *base))
165 BOOL success = TRUE;
167 /* Initialise base structure */
169 dev_base->sys_base = (APTR)base;
170 base = dev_base;
171 base->seg_list = seg_list;
172 NewList((APTR)(&base->pci_units));
173 NewList((APTR)(&base->pccard_units));
175 /* Open libraries, resources and devices */
177 base->utility_base = (APTR)OpenLibrary(utility_name, UTILITY_VERSION);
178 base->prometheus_base = OpenLibrary(prometheus_name, PROMETHEUS_VERSION);
179 if(base->prometheus_base == NULL)
181 base->powerpci_base = OpenLibrary(powerpci_name, POWERPCI_VERSION);
182 if(base->powerpci_base == NULL)
183 base->cybpci_base = OpenLibrary(cybpci_name, CYBPCI_VERSION);
185 base->pccard_base = OpenLibrary(pccard_name, PCCARD_VERSION);
186 if(base->pccard_base != NULL)
187 base->card_base = OpenResource(card_name);
188 base->dos_base = (APTR)OpenLibrary(dos_name, DOS_VERSION);
190 if(base->utility_base == NULL || base->dos_base == NULL)
191 success = FALSE;
193 if(OpenDevice(timer_name, UNIT_VBLANK, (APTR)&base->timer_request, 0)
194 != 0)
195 success = FALSE;
197 if(!success)
199 DeleteDevice(base);
200 base = NULL;
203 return base;
208 /****i* prism2.device/DevOpen **********************************************
210 * NAME
211 * DevOpen
213 * SYNOPSIS
214 * error = DevOpen(request, unit_num, flags)
216 * BYTE DevOpen(struct IOSana2Req *, ULONG, ULONG);
218 ****************************************************************************
222 BYTE DevOpen(REG(a1, struct IOSana2Req *request),
223 REG(d0, ULONG unit_num), REG(d1, ULONG flags),
224 REG(BASE_REG, struct DevBase *base))
226 struct DevUnit *unit;
227 BYTE error = 0;
228 struct Opener *opener;
229 struct TagItem *tag_list;
230 UWORD i;
232 base->device.dd_Library.lib_OpenCnt++;
233 base->device.dd_Library.lib_Flags &= ~LIBF_DELEXP;
235 request->ios2_Req.io_Unit = NULL;
236 tag_list = request->ios2_BufferManagement;
237 request->ios2_BufferManagement = NULL;
239 /* Check request size */
241 if(request->ios2_Req.io_Message.mn_Length < sizeof(struct IOSana2Req))
242 error = IOERR_OPENFAIL;
244 /* Get the requested unit */
246 if(error == 0)
248 request->ios2_Req.io_Unit = (APTR)(unit = GetUnit(unit_num, base));
249 if(unit == NULL)
250 error = IOERR_OPENFAIL;
253 /* Handle device sharing */
255 if(error == 0)
257 if(unit->open_count != 0 && ((unit->flags & UNITF_SHARED) == 0
258 || (flags & SANA2OPF_MINE) != 0))
259 error = IOERR_UNITBUSY;
260 unit->open_count++;
263 if(error == 0)
265 if((flags & SANA2OPF_MINE) == 0)
266 unit->flags |= UNITF_SHARED;
267 else if((flags & SANA2OPF_PROM) != 0)
268 unit->flags |= UNITF_PROM;
270 /* Set up buffer-management structure and get hooks */
272 request->ios2_BufferManagement = opener =
273 AllocVec(sizeof(struct Opener), MEMF_PUBLIC | MEMF_CLEAR);
274 if(opener == NULL)
275 error = IOERR_OPENFAIL;
278 if(error == 0)
280 NewList(&opener->read_port.mp_MsgList);
281 opener->read_port.mp_Flags = PA_IGNORE;
282 NewList((APTR)&opener->initial_stats);
284 for(i = 0; i < 2; i++)
285 opener->rx_function = (APTR)GetTagData(rx_tags[i],
286 (UPINT)opener->rx_function, tag_list);
287 for(i = 0; i < 3; i++)
288 opener->tx_function = (APTR)GetTagData(tx_tags[i],
289 (UPINT)opener->tx_function, tag_list);
291 opener->filter_hook = (APTR)GetTagData(S2_PacketFilter, (UPINT)NULL,
292 tag_list);
293 opener->dma_tx_function =
294 (APTR)GetTagData(S2_DMACopyFromBuff32, (UPINT)NULL, tag_list);
296 Disable();
297 AddTail((APTR)&unit->openers, (APTR)opener);
298 Enable();
301 /* Back out if anything went wrong */
303 if(error != 0)
304 CloseUnit(request, base);
306 /* Return */
308 request->ios2_Req.io_Error = error;
309 return error;
314 /****i* prism2.device/DevClose *********************************************
316 * NAME
317 * DevClose
319 * SYNOPSIS
320 * seg_list = DevClose(request)
322 * APTR DevClose(struct IOSana2Req *);
324 ****************************************************************************
328 APTR DevClose(REG(a1, struct IOSana2Req *request),
329 REG(BASE_REG, struct DevBase *base))
331 APTR seg_list = NULL;
333 /* Close the unit */
335 CloseUnit(request, base);
337 /* Expunge the device if a delayed expunge is pending */
339 if(base->device.dd_Library.lib_OpenCnt == 0)
341 if((base->device.dd_Library.lib_Flags & LIBF_DELEXP) != 0)
342 seg_list = DevExpunge(base);
345 return seg_list;
350 /****i* prism2.device/DevExpunge *******************************************
352 * NAME
353 * DevExpunge
355 * SYNOPSIS
356 * seg_list = DevExpunge()
358 * APTR DevExpunge(VOID);
360 ****************************************************************************
364 APTR DevExpunge(REG(BASE_REG, struct DevBase *base))
366 APTR seg_list;
368 if(base->device.dd_Library.lib_OpenCnt == 0)
370 seg_list = base->seg_list;
371 Remove((APTR)base);
372 DeleteDevice(base);
374 else
376 base->device.dd_Library.lib_Flags |= LIBF_DELEXP;
377 seg_list = NULL;
380 return seg_list;
385 /****i* prism2.device/DevReserved ******************************************
387 * NAME
388 * DevReserved
390 * SYNOPSIS
391 * result = DevReserved()
393 * APTR DevReserved(VOID);
395 ****************************************************************************
399 APTR DevReserved()
401 return NULL;
406 /****i* prism2.device/DevBeginIO *******************************************
408 * NAME
409 * DevBeginIO
411 * SYNOPSIS
412 * DevBeginIO(request)
414 * VOID DevBeginIO(struct IORequest *);
416 ****************************************************************************
420 VOID DevBeginIO(REG(a1, struct IOSana2Req *request),
421 REG(BASE_REG, struct DevBase *base))
423 struct DevUnit *unit;
425 request->ios2_Req.io_Error = 0;
426 unit = (APTR)request->ios2_Req.io_Unit;
428 if(AttemptSemaphore(&unit->access_lock))
429 ServiceRequest(request, base);
430 else
431 PutRequest(unit->request_ports[GENERAL_QUEUE], (APTR)request, base);
433 return;
438 /****i* prism2.device/DevAbortIO *******************************************
440 * NAME
441 * DevAbortIO -- Try to stop a request.
443 * SYNOPSIS
444 * DevAbortIO(request)
446 * VOID DevAbortIO(struct IOSana2Req *);
448 * FUNCTION
449 * Do our best to halt the progress of a request.
451 ****************************************************************************
455 VOID DevAbortIO(REG(a1, struct IOSana2Req *request),
456 REG(BASE_REG, struct DevBase *base))
458 Disable();
459 if(request->ios2_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE &&
460 (request->ios2_Req.io_Flags & IOF_QUICK) == 0)
462 Remove((APTR)request);
463 request->ios2_Req.io_Error = IOERR_ABORTED;
464 request->ios2_WireError = S2WERR_GENERIC_ERROR;
465 ReplyMsg((APTR)request);
467 Enable();
469 return;
474 /****i* prism2.device/DeleteDevice *****************************************
476 * NAME
477 * DeleteDevice
479 * SYNOPSIS
480 * DeleteDevice()
482 * VOID DeleteDevice(VOID);
484 ****************************************************************************
488 VOID DeleteDevice(struct DevBase *base)
490 UWORD neg_size, pos_size;
492 /* Close devices */
494 CloseDevice((APTR)&base->timer_request);
496 /* Close libraries */
498 if(base->dos_base != NULL)
499 CloseLibrary((APTR)base->dos_base);
500 if(base->openpci_base != NULL)
501 CloseLibrary(base->openpci_base);
502 if(base->pccard_base != NULL)
503 CloseLibrary(base->pccard_base);
504 if(base->cybpci_base != NULL)
505 CloseLibrary(base->cybpci_base);
506 if(base->powerpci_base != NULL)
507 CloseLibrary(base->powerpci_base);
508 if(base->prometheus_base != NULL)
509 CloseLibrary(base->prometheus_base);
510 if(base->utility_base != NULL)
511 CloseLibrary((APTR)base->utility_base);
513 /* Free device's memory */
515 neg_size = base->device.dd_Library.lib_NegSize;
516 pos_size = base->device.dd_Library.lib_PosSize;
517 FreeMem((UBYTE *)base - neg_size, pos_size + neg_size);
519 return;
524 /****i* prism2.device/CloseUnit ********************************************
526 * NAME
527 * CloseUnit
529 * SYNOPSIS
530 * CloseUnit(request)
532 * VOID CloseUnit(struct IOSana2Req *);
534 ****************************************************************************
538 VOID CloseUnit(struct IOSana2Req *request, struct DevBase *base)
540 struct DevUnit *unit;
541 struct Opener *opener;
543 /* Decrement device usage count and free buffer-management resources */
545 base->device.dd_Library.lib_OpenCnt--;
546 opener = (APTR)request->ios2_BufferManagement;
547 if(opener != NULL)
549 Disable();
550 Remove((APTR)opener);
551 Enable();
552 FreeVec(opener);
555 /* Delete the unit if it's no longer in use */
557 unit = (APTR)request->ios2_Req.io_Unit;
558 if(unit != NULL)
560 if((--unit->open_count) == 0)
562 Remove((APTR)unit);
563 switch(unit->bus)
565 case PCI_BUS:
566 case TMD_BUS:
567 case PLX_BUS:
568 DeletePCIUnit(unit, base);
569 break;
570 case PCCARD_BUS:
571 DeletePCCardUnit(unit, base);
572 break;
577 return;
582 /****i* prism2.device/GetUnit **********************************************
584 * NAME
585 * GetUnit -- Get a unit by number.
587 * SYNOPSIS
588 * unit = GetUnit(unit_num)
590 * struct DevUnit *GetUnit(ULONG);
592 ****************************************************************************
596 struct DevUnit *GetUnit(ULONG unit_num, struct DevBase *base)
598 struct DevUnit *unit;
599 ULONG pci_limit, pccard_limit;
601 pci_limit = GetPCICount(base);
602 pccard_limit = pci_limit + GetPCCardCount(base);
604 if(unit_num < pci_limit)
605 unit = GetPCIUnit(unit_num, base);
606 else if(unit_num < pccard_limit)
607 unit = GetPCCardUnit(unit_num - pci_limit, base);
608 else
609 unit = NULL;
611 return unit;
616 /****i* prism2.device/WrapInt **********************************************
618 * NAME
619 * WrapInt
621 ****************************************************************************
625 BOOL WrapInt(struct Interrupt *interrupt, struct DevBase *base)
627 BOOL success = TRUE;
628 APTR *int_data;
630 if(base->wrapper_int_code != NULL)
632 int_data = AllocMem(2 * sizeof(APTR), MEMF_PUBLIC | MEMF_CLEAR);
633 if(int_data != NULL)
635 int_data[0] = interrupt->is_Code;
636 int_data[1] = interrupt->is_Data;
637 interrupt->is_Code = base->wrapper_int_code;
638 interrupt->is_Data = int_data;
640 else
641 success = FALSE;
644 return success;
649 /****i* prism2.device/UnwrapInt ********************************************
651 * NAME
652 * UnwrapInt
654 ****************************************************************************
658 VOID UnwrapInt(struct Interrupt *interrupt, struct DevBase *base)
660 if(interrupt->is_Code == base->wrapper_int_code)
661 FreeMem(interrupt->is_Data, 2 * sizeof(APTR));
663 return;
668 /****i* prism2.device/WrapCardInt ******************************************
670 * NAME
671 * WrapCardInt
673 ****************************************************************************
677 BOOL WrapCardInt(struct Interrupt *interrupt, struct DevBase *base)
679 BOOL success = TRUE;
680 APTR *int_data;
682 if(base->wrapper_card_code != NULL)
684 int_data = AllocMem(2 * sizeof(APTR), MEMF_PUBLIC | MEMF_CLEAR);
685 if(int_data != NULL)
687 int_data[0] = interrupt->is_Code;
688 int_data[1] = interrupt->is_Data;
689 interrupt->is_Code = base->wrapper_card_code;
690 interrupt->is_Data = int_data;
692 else
693 success = FALSE;
696 return success;
701 /****i* prism2.device/UnwrapCardInt ****************************************
703 * NAME
704 * UnwrapCardInt
706 ****************************************************************************
710 VOID UnwrapCardInt(struct Interrupt *interrupt, struct DevBase *base)
712 if(interrupt->is_Code == base->wrapper_card_code)
713 FreeMem(interrupt->is_Data, 2 * sizeof(APTR));
715 return;