revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / networks / intelpro100 / os4_device.c
blob1e2075333aa87d320abf5a88242f0849b7a96092
1 /*
3 Copyright (C) 2000-2009 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 <exec/emulation.h>
27 #include <utility/utility.h>
28 #include <expansion/expansion.h>
30 #include <proto/exec.h>
31 #include <clib/alib_protos.h>
32 #include <proto/utility.h>
34 #include "device.h"
36 #include "unit_protos.h"
37 #include "pci_protos.h"
38 #include "request_protos.h"
41 /* Private prototypes */
43 static struct DevBase *DevInit(struct DevBase *dev_base, APTR seg_list,
44 struct ExecIFace *i_exec);
45 static ULONG IfaceObtain(struct Interface *self);
46 static ULONG IfaceRelease(struct Interface *self);
47 static LONG DevOpen(struct Interface *self, struct IOSana2Req *request,
48 ULONG unit_num, ULONG flags);
49 static APTR DevClose(struct Interface *self, struct IOSana2Req *request);
50 static APTR DevExpunge(struct Interface *self);
51 static VOID DevBeginIO(struct Interface *self, struct IOSana2Req *request);
52 static VOID DevAbortIO(struct Interface *self, struct IOSana2Req *request);
53 static VOID DeleteDevice(struct DevBase *base);
54 static struct DevUnit *GetUnit(ULONG unit_num, struct DevBase *base);
55 static BOOL RXFunction(struct IOSana2Req *request, APTR buffer, ULONG size);
56 static BOOL TXFunction(APTR buffer, struct IOSana2Req *request, ULONG size);
57 static UBYTE *DMATXFunction(struct IOSana2Req *request);
58 static ULONG OS4Int(struct ExceptionContext ex_context,
59 struct ExecBase *sys_base, APTR *int_data);
62 /* Return an error immediately if someone tries to run the device */
64 LONG Main()
66 return -1;
69 const TEXT device_name[] = DEVICE_NAME;
70 static const TEXT version_string[] =
71 DEVICE_NAME " " STR(VERSION) "." STR(REVISION) " (" DATE ")\n";
72 static const TEXT manager_name[] = "__device";
73 static const TEXT utility_name[] = UTILITYNAME;
74 static const TEXT expansion_name[] = EXPANSIONNAME;
75 static const TEXT timer_name[] = TIMERNAME;
78 static const APTR manager_vectors[] =
80 (APTR)IfaceObtain,
81 (APTR)IfaceRelease,
82 (APTR)NULL,
83 (APTR)NULL,
84 (APTR)DevOpen,
85 (APTR)DevClose,
86 (APTR)DevExpunge,
87 (APTR)NULL,
88 (APTR)DevBeginIO,
89 (APTR)DevAbortIO,
90 (APTR)-1
94 static const struct TagItem manager_tags[] =
96 {MIT_Name, (UPINT)manager_name},
97 {MIT_VectorTable, (UPINT)manager_vectors},
98 {MIT_Version, 1},
99 {TAG_END, 0}
103 static const struct TagItem *interfaces[] =
105 manager_tags,
106 NULL
110 static const struct TagItem init_tags[] =
112 {CLT_DataSize, sizeof(struct DevBase)},
113 {CLT_InitFunc, (UPINT)DevInit},
114 {CLT_Interfaces, (UPINT)interfaces},
115 {TAG_END, 0}
119 const struct Resident rom_tag =
121 RTC_MATCHWORD,
122 (struct Resident *)&rom_tag,
123 (APTR)(&rom_tag + 1),
124 RTF_AUTOINIT | RTF_NATIVE,
125 VERSION,
126 NT_DEVICE,
128 (STRPTR)device_name,
129 (STRPTR)version_string,
130 (APTR)init_tags
134 static const ULONG rx_tags[] =
136 S2_CopyToBuff,
137 S2_CopyToBuff16,
141 static const ULONG tx_tags[] =
143 S2_CopyFromBuff,
144 S2_CopyFromBuff16,
145 S2_CopyFromBuff32
150 /****i* intelpro100.device/DevInit *****************************************
152 * NAME
153 * DevInit
155 * SYNOPSIS
156 * dev_base = DevInit(dev_base, seg_list, i_exec)
158 * struct DevBase *DevInit(struct DevBase *, APTR, ExecIFace *);
160 ****************************************************************************
164 static struct DevBase *DevInit(struct DevBase *dev_base, APTR seg_list,
165 struct ExecIFace *i_exec)
167 struct DevBase *base;
168 BOOL success = TRUE;
170 dev_base->i_exec = i_exec;
171 base = dev_base;
172 base->seg_list = seg_list;
173 base->sys_base = (APTR)i_exec->Data.LibBase;
175 base->device.dd_Library.lib_Node.ln_Type = NT_DEVICE;
176 base->device.dd_Library.lib_Node.ln_Name = (TEXT *)device_name;
177 base->device.dd_Library.lib_Flags = LIBF_SUMUSED | LIBF_CHANGED;
178 base->device.dd_Library.lib_Version = VERSION;
179 base->device.dd_Library.lib_Revision = REVISION;
180 base->device.dd_Library.lib_IdString = (TEXT *)version_string;
183 base->utility_base = (APTR)OpenLibrary(utility_name, UTILITY_VERSION);
184 base->expansion_base = OpenLibrary(expansion_name, EXPANSION_VERSION);
185 if(base->utility_base == NULL || base->expansion_base == NULL)
186 success = FALSE;
188 if(OpenDevice(timer_name, UNIT_VBLANK, (APTR)&base->timer_request, 0) !=
190 success = FALSE;
192 NewList((APTR)(&dev_base->pci_units));
193 base->wrapper_int_code = (APTR)OS4Int;
195 if(success)
197 base->i_utility =
198 (APTR)GetInterface((APTR)UtilityBase, "main", 1, NULL);
199 base->i_pci =
200 (APTR)GetInterface(ExpansionBase, "pci", 1, NULL);
201 base->i_timer =
202 (APTR)GetInterface((APTR)TimerBase, "main", 1, NULL);
203 if(base->i_utility == NULL || base->i_pci == NULL
204 || base->i_timer == NULL)
205 success = FALSE;
208 if(!success)
210 DeleteDevice(base);
211 base = NULL;
214 return base;
219 /****i* intelpro100.device/IfaceObtain *************************************
221 * NAME
222 * IfaceObtain
224 * SYNOPSIS
225 * ref_count = IfaceObtain(self)
227 * ULONG IfaceObtain(struct Interface *);
229 ****************************************************************************
233 static ULONG IfaceObtain(struct Interface *self)
235 return self->Data.RefCount++;
240 /****i* intelpro100.device/IfaceRelease ************************************
242 * NAME
243 * IfaceRelease
245 * SYNOPSIS
246 * ref_count = IfaceRelease(self)
248 * ULONG IfaceRelease(struct Interface *);
250 ****************************************************************************
254 static ULONG IfaceRelease(struct Interface *self)
256 return --self->Data.RefCount;
261 /****i* intelpro100.device/DevOpen *****************************************
263 * NAME
264 * DevOpen
266 * SYNOPSIS
267 * error = DevOpen(self, request, unit_num, flags)
269 * LONG DevOpen(struct Interface *, struct IOSana2Req *, ULONG, ULONG);
271 ****************************************************************************
275 static LONG DevOpen(struct Interface *self, struct IOSana2Req *request,
276 ULONG unit_num, ULONG flags)
278 struct DevBase *base;
279 struct DevUnit *unit;
280 BYTE error = 0;
281 struct Opener *opener;
282 struct TagItem *tag_list;
283 UWORD i;
285 base = (APTR)self->Data.LibBase;
286 base->device.dd_Library.lib_OpenCnt++;
287 base->device.dd_Library.lib_Flags &= ~LIBF_DELEXP;
289 request->ios2_Req.io_Unit = NULL;
290 tag_list = request->ios2_BufferManagement;
291 request->ios2_BufferManagement = NULL;
293 /* Check request size */
295 if(request->ios2_Req.io_Message.mn_Length < sizeof(struct IOSana2Req))
296 error = IOERR_OPENFAIL;
298 /* Get the requested unit */
300 if(error == 0)
302 request->ios2_Req.io_Unit = (APTR)(unit = GetUnit(unit_num, base));
303 if(unit == NULL)
304 error = IOERR_OPENFAIL;
307 /* Handle device sharing */
309 if(error == 0)
311 if((unit->open_count != 0) && (((unit->flags & UNITF_SHARED) == 0)
312 || ((flags & SANA2OPF_MINE) != 0)))
313 error = IOERR_UNITBUSY;
314 unit->open_count++;
317 if(error == 0)
319 if((flags & SANA2OPF_MINE) == 0)
320 unit->flags |= UNITF_SHARED;
321 else if((flags & SANA2OPF_PROM) != 0)
322 unit->flags |= UNITF_PROM;
324 /* Set up buffer-management structure and get hooks */
326 request->ios2_BufferManagement = opener =
327 AllocVec(sizeof(struct Opener), MEMF_PUBLIC | MEMF_CLEAR);
328 if(opener == NULL)
329 error = IOERR_OPENFAIL;
332 if(error == 0)
334 NewList(&opener->read_port.mp_MsgList);
335 opener->read_port.mp_Flags = PA_IGNORE;
336 NewList((APTR)&opener->initial_stats);
338 for(i = 0; i < 2; i++)
339 opener->real_rx_function = (APTR)GetTagData(rx_tags[i],
340 (UPINT)opener->real_rx_function, tag_list);
341 for(i = 0; i < 3; i++)
342 opener->real_tx_function = (APTR)GetTagData(tx_tags[i],
343 (UPINT)opener->real_tx_function, tag_list);
345 opener->filter_hook = (APTR)GetTagData(S2_PacketFilter, (UPINT)NULL,
346 tag_list);
347 opener->real_dma_tx_function =
348 (APTR)GetTagData(S2_DMACopyFromBuff32, (UPINT)NULL, tag_list);
350 opener->rx_function = (APTR)RXFunction;
351 opener->tx_function = (APTR)TXFunction;
352 if(opener->real_dma_tx_function != NULL)
353 opener->dma_tx_function = (APTR)DMATXFunction;
355 Disable();
356 AddTail((APTR)&unit->openers, (APTR)opener);
357 Enable();
360 /* Back out if anything went wrong */
362 if(error != 0)
363 DevClose(self, request);
365 /* Return */
367 request->ios2_Req.io_Error = error;
368 return error;
373 /****i* intelpro100.device/DevClose ****************************************
375 * NAME
376 * DevClose
378 * SYNOPSIS
379 * seg_list = DevClose(request)
381 * APTR DevClose(struct IOSana2Req *);
383 ****************************************************************************
387 static APTR DevClose(struct Interface *self, struct IOSana2Req *request)
389 struct DevBase *base;
390 struct DevUnit *unit;
391 APTR seg_list;
392 struct Opener *opener;
394 /* Free buffer-management resources */
396 base = (APTR)self->Data.LibBase;
397 opener = (APTR)request->ios2_BufferManagement;
398 if(opener != NULL)
400 Disable();
401 Remove((APTR)opener);
402 Enable();
403 FreeVec(opener);
406 /* Delete the unit if it's no longer in use */
408 unit = (APTR)request->ios2_Req.io_Unit;
409 if(unit != NULL)
411 if((--unit->open_count) == 0)
413 Remove((APTR)unit);
414 switch(unit->bus)
416 case PCI_BUS:
417 DeletePCIUnit(unit, base);
422 /* Expunge the device if a delayed expunge is pending */
424 seg_list = NULL;
426 if((--base->device.dd_Library.lib_OpenCnt) == 0)
428 if((base->device.dd_Library.lib_Flags & LIBF_DELEXP) != 0)
429 seg_list = DevExpunge(self);
432 return seg_list;
437 /****i* intelpro100.device/DevExpunge **************************************
439 * NAME
440 * DevExpunge
442 * SYNOPSIS
443 * seg_list = DevExpunge()
445 * APTR DevExpunge(VOID);
447 ****************************************************************************
451 static APTR DevExpunge(struct Interface *self)
453 struct DevBase *base;
454 APTR seg_list;
456 base = (APTR)self->Data.LibBase;
457 if(base->device.dd_Library.lib_OpenCnt == 0)
459 seg_list = base->seg_list;
460 Remove((APTR)base);
461 DeleteDevice(base);
463 else
465 base->device.dd_Library.lib_Flags |= LIBF_DELEXP;
466 seg_list = NULL;
469 return seg_list;
474 /****i* intelpro100.device/DevBeginIO **************************************
476 * NAME
477 * DevBeginIO
479 * SYNOPSIS
480 * DevBeginIO(request)
482 * VOID DevBeginIO(struct IORequest *);
484 ****************************************************************************
488 static VOID DevBeginIO(struct Interface *self, struct IOSana2Req *request)
490 struct DevBase *base;
491 struct DevUnit *unit;
493 /* Replace caller's cookie with our own */
495 base = (APTR)self->Data.LibBase;
496 request->ios2_Req.io_Error = 0;
497 unit = (APTR)request->ios2_Req.io_Unit;
498 switch(request->ios2_Req.io_Command)
500 case CMD_READ:
501 case CMD_WRITE:
502 case S2_MULTICAST:
503 case S2_BROADCAST:
504 case S2_READORPHAN:
505 request->ios2_StatData = request->ios2_Data;
506 request->ios2_Data = request;
509 /* Send request for processing */
511 if(AttemptSemaphore(&unit->access_lock))
512 ServiceRequest(request, base);
513 else
515 PutRequest(unit->request_ports[GENERAL_QUEUE], (APTR)request, base);
518 return;
523 /****i* intelpro100.device/DevAbortIO **************************************
525 * NAME
526 * DevAbortIO -- Try to stop a request.
528 * SYNOPSIS
529 * DevAbortIO(request)
531 * VOID DevAbortIO(struct IOSana2Req *);
533 ****************************************************************************
535 * Disable() used instead of a semaphore because device uses interrupts.
539 static VOID DevAbortIO(struct Interface *self, struct IOSana2Req *request)
541 struct DevBase *base;
542 struct DevUnit *unit;
544 base = (APTR)self->Data.LibBase;
545 unit = (APTR)request->ios2_Req.io_Unit;
547 Disable();
548 if((request->ios2_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE)
549 && ((request->ios2_Req.io_Flags & IOF_QUICK) == 0))
551 Remove((APTR)request);
552 request->ios2_Req.io_Error = IOERR_ABORTED;
553 request->ios2_WireError = S2WERR_GENERIC_ERROR;
554 ReplyMsg((APTR)request);
556 Enable();
558 return;
563 /****i* intelpro100.device/DeleteDevice ************************************
565 * NAME
566 * DeleteDevice
568 * SYNOPSIS
569 * DeleteDevice()
571 * VOID DeleteDevice(VOID);
573 ****************************************************************************
577 static VOID DeleteDevice(struct DevBase *base)
579 /* Close interfaces */
581 DropInterface((APTR)base->i_timer);
582 DropInterface((APTR)base->i_pci);
583 DropInterface((APTR)base->i_utility);
585 /* Close devices */
587 CloseDevice((APTR)&base->timer_request);
589 /* Close libraries */
591 if(base->expansion_base != NULL)
592 CloseLibrary(base->expansion_base);
593 if(base->utility_base != NULL)
594 CloseLibrary((APTR)base->utility_base);
596 /* Free device's memory */
598 DeleteLibrary((APTR)base);
600 return;
605 /****i* intelpro100.device/GetUnit *****************************************
607 * NAME
608 * GetUnit -- Get a unit by number.
610 * SYNOPSIS
611 * unit = GetUnit(unit_num)
613 * struct DevUnit *GetUnit(ULONG);
615 ****************************************************************************
619 static struct DevUnit *GetUnit(ULONG unit_num, struct DevBase *base)
621 struct DevUnit *unit;
622 ULONG pci_limit;
624 pci_limit = GetPCICount(base);
626 if(unit_num < pci_limit)
627 unit = GetPCIUnit(unit_num, base);
628 else
629 unit = NULL;
631 return unit;
636 /****i* intelpro100.device/RXFunction **************************************
638 * NAME
639 * RXFunction
641 ****************************************************************************
645 static BOOL RXFunction(struct IOSana2Req *request, APTR buffer, ULONG size)
647 struct DevBase *base;
648 struct Opener *opener;
649 APTR cookie;
651 opener = request->ios2_BufferManagement;
652 cookie = request->ios2_StatData;
653 base = (struct DevBase *)request->ios2_Req.io_Device;
654 request->ios2_Data = cookie;
656 return EmulateTags(opener->real_rx_function,
657 ET_RegisterA0, cookie, ET_RegisterA1, buffer,
658 ET_RegisterD0, size, TAG_END);
663 /****i* intelpro100.device/TXFunction **************************************
665 * NAME
666 * TXFunction
668 ****************************************************************************
672 static BOOL TXFunction(APTR buffer, struct IOSana2Req *request, ULONG size)
674 struct DevBase *base;
675 struct Opener *opener;
676 APTR cookie;
678 opener = request->ios2_BufferManagement;
679 cookie = request->ios2_StatData;
680 base = (struct DevBase *)request->ios2_Req.io_Device;
681 request->ios2_Data = cookie;
682 return EmulateTags(opener->real_tx_function,
683 ET_RegisterA0, buffer, ET_RegisterA1, cookie,
684 ET_RegisterD0, size, TAG_END);
689 /****i* intelpro100.device/DMATXFunction ***********************************
691 * NAME
692 * DMATXFunction
694 ****************************************************************************
698 static UBYTE *DMATXFunction(struct IOSana2Req *request)
700 struct DevBase *base;
701 struct Opener *opener;
702 APTR cookie;
704 opener = request->ios2_BufferManagement;
705 cookie = request->ios2_StatData;
706 base = (struct DevBase *)request->ios2_Req.io_Device;
707 request->ios2_Data = cookie;
708 return (UBYTE *)EmulateTags(opener->real_dma_tx_function,
709 ET_RegisterA0, cookie, TAG_END);
714 /****i* intelpro100.device/OS4Int ******************************************
716 * NAME
717 * OS4Int
719 ****************************************************************************
723 static ULONG OS4Int(struct ExceptionContext ex_context,
724 struct ExecBase *sys_base, APTR *int_data)
726 BOOL (*int_code)(APTR, APTR);
728 int_code = int_data[0];
729 return int_code(int_data[1], int_code);