store the pre-alphacomposit hook and allow it to be queried.
[AROS.git] / workbench / devs / networks / realtek8180 / device.c
bloba9ef36783c78366a95a23924b58750cc327fa131
1 /*
3 Copyright (C) 2000-2012 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 "usb_protos.h"
37 #include "request_protos.h"
40 /* Private prototypes */
42 static VOID DeleteDevice(struct DevBase *base);
43 static struct DevUnit *GetUnit(ULONG unit_num, 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 static const TEXT utility_name[] = UTILITYNAME;
58 static const TEXT poseidon_name[] = "poseidon.library";
59 static const TEXT timer_name[] = TIMERNAME;
62 static const APTR vectors[] =
64 (APTR)DevOpen,
65 (APTR)DevClose,
66 (APTR)DevExpunge,
67 (APTR)DevReserved,
68 (APTR)DevBeginIO,
69 (APTR)DevAbortIO,
70 (APTR)-1
74 #ifdef __MORPHOS__
75 #pragma pack(2)
76 #endif
77 const struct
79 SMALLINITBYTEDEF(type);
80 SMALLINITPINTDEF(name);
81 SMALLINITBYTEDEF(flags);
82 SMALLINITWORDDEF(version);
83 SMALLINITWORDDEF(revision);
84 SMALLINITPINTDEF(id_string);
85 INITENDDEF;
87 init_data =
89 SMALLINITBYTE(OFFSET(Node, ln_Type), NT_DEVICE),
90 SMALLINITPINT(OFFSET(Node, ln_Name), device_name),
91 SMALLINITBYTE(OFFSET(Library, lib_Flags), LIBF_SUMUSED | LIBF_CHANGED),
92 SMALLINITWORD(OFFSET(Library, lib_Version), VERSION),
93 SMALLINITWORD(OFFSET(Library, lib_Revision), REVISION),
94 SMALLINITPINT(OFFSET(Library, lib_IdString), version_string),
95 INITEND
97 #ifdef __MORPHOS__
98 #pragma pack()
99 #endif
102 static const APTR init_table[] =
104 (APTR)sizeof(struct DevBase),
105 (APTR)vectors,
106 (APTR)&init_data,
107 (APTR)DevInit
111 const struct Resident rom_tag =
113 RTC_MATCHWORD,
114 (struct Resident *)&rom_tag,
115 (APTR)(&rom_tag + 1),
116 RTF_AUTOINIT,
117 VERSION,
118 NT_DEVICE,
120 (STRPTR)device_name,
121 (STRPTR)version_string,
122 (APTR)init_table
126 static const ULONG rx_tags[] =
128 S2_CopyToBuff,
129 S2_CopyToBuff16,
133 static const ULONG tx_tags[] =
135 S2_CopyFromBuff,
136 S2_CopyFromBuff16,
137 S2_CopyFromBuff32
142 /****i* realtek8180.device/DevInit *****************************************
144 * NAME
145 * DevInit
147 * SYNOPSIS
148 * dev_base = DevInit(dev_base, seg_list)
150 * struct DevBase *DevInit(struct DevBase *, APTR);
152 ****************************************************************************
156 struct DevBase *DevInit(REG(d0, struct DevBase *dev_base),
157 REG(a0, APTR seg_list), REG(BASE_REG, struct DevBase *base))
159 BOOL success = TRUE;
161 /* Initialise base structure */
163 dev_base->sys_base = (APTR)base;
164 base = dev_base;
165 base->seg_list = seg_list;
166 NewList((APTR)(&base->usb_units));
168 /* Open libraries, resources and devices */
170 base->utility_base = (APTR)OpenLibrary(utility_name, UTILITY_VERSION);
171 base->poseidon_base = OpenLibrary(poseidon_name, POSEIDON_VERSION);
173 if(base->utility_base == NULL)
174 success = FALSE;
176 if(OpenDevice(timer_name, UNIT_ECLOCK, (APTR)&base->timer_request, 0)
177 != 0)
178 success = FALSE;
180 if(!success)
182 DeleteDevice(base);
183 base = NULL;
186 return base;
191 /****i* realtek8180.device/DevOpen *****************************************
193 * NAME
194 * DevOpen
196 * SYNOPSIS
197 * error = DevOpen(request, unit_num, flags)
199 * BYTE DevOpen(struct IOSana2Req *, ULONG, ULONG);
201 ****************************************************************************
205 BYTE DevOpen(REG(a1, struct IOSana2Req *request),
206 REG(d0, ULONG unit_num), REG(d1, ULONG flags),
207 REG(BASE_REG, struct DevBase *base))
209 struct DevUnit *unit;
210 BYTE error = 0;
211 struct Opener *opener;
212 struct TagItem *tag_list;
213 UWORD i;
215 base->device.dd_Library.lib_OpenCnt++;
216 base->device.dd_Library.lib_Flags &= ~LIBF_DELEXP;
218 request->ios2_Req.io_Unit = NULL;
219 tag_list = request->ios2_BufferManagement;
220 request->ios2_BufferManagement = NULL;
222 /* Check request size */
224 if(request->ios2_Req.io_Message.mn_Length < sizeof(struct IOSana2Req))
225 error = IOERR_OPENFAIL;
227 /* Get the requested unit */
229 if(error == 0)
231 request->ios2_Req.io_Unit = (APTR)(unit = GetUnit(unit_num, base));
232 if(unit == NULL)
233 error = IOERR_OPENFAIL;
236 /* Handle device sharing */
238 if(error == 0)
240 if(unit->open_count != 0 && ((unit->flags & UNITF_SHARED) == 0
241 || (flags & SANA2OPF_MINE) != 0))
242 error = IOERR_UNITBUSY;
243 unit->open_count++;
246 if(error == 0)
248 if((flags & SANA2OPF_MINE) == 0)
249 unit->flags |= UNITF_SHARED;
250 else if((flags & SANA2OPF_PROM) != 0)
251 unit->flags |= UNITF_PROM;
253 /* Set up buffer-management structure and get hooks */
255 request->ios2_BufferManagement = opener =
256 AllocVec(sizeof(struct Opener), MEMF_PUBLIC | MEMF_CLEAR);
257 if(opener == NULL)
258 error = IOERR_OPENFAIL;
261 if(error == 0)
263 NewList(&opener->read_port.mp_MsgList);
264 opener->read_port.mp_Flags = PA_IGNORE;
265 NewList(&opener->mgmt_port.mp_MsgList);
266 opener->mgmt_port.mp_Flags = PA_IGNORE;
267 NewList((APTR)&opener->initial_stats);
269 for(i = 0; i < 2; i++)
270 opener->rx_function = (APTR)GetTagData(rx_tags[i],
271 (UPINT)opener->rx_function, tag_list);
272 for(i = 0; i < 3; i++)
273 opener->tx_function = (APTR)GetTagData(tx_tags[i],
274 (UPINT)opener->tx_function, tag_list);
276 opener->filter_hook = (APTR)GetTagData(S2_PacketFilter, (UPINT)NULL,
277 tag_list);
278 opener->dma_tx_function =
279 (APTR)GetTagData(S2_DMACopyFromBuff32, (UPINT)NULL, tag_list);
281 Disable();
282 AddTail((APTR)&unit->openers, (APTR)opener);
283 Enable();
286 /* Back out if anything went wrong */
288 if(error != 0)
289 CloseUnit(request, base);
291 /* Return */
293 request->ios2_Req.io_Error = error;
294 return error;
299 /****i* realtek8180.device/DevClose ****************************************
301 * NAME
302 * DevClose
304 * SYNOPSIS
305 * seg_list = DevClose(request)
307 * APTR DevClose(struct IOSana2Req *);
309 ****************************************************************************
313 APTR DevClose(REG(a1, struct IOSana2Req *request),
314 REG(BASE_REG, struct DevBase *base))
316 APTR seg_list = NULL;
318 /* Close the unit */
320 CloseUnit(request, base);
322 /* Expunge the device if a delayed expunge is pending */
324 if(base->device.dd_Library.lib_OpenCnt == 0)
326 if((base->device.dd_Library.lib_Flags & LIBF_DELEXP) != 0)
327 seg_list = DevExpunge(base);
330 return seg_list;
335 /****i* realtek8180.device/DevExpunge **************************************
337 * NAME
338 * DevExpunge
340 * SYNOPSIS
341 * seg_list = DevExpunge()
343 * APTR DevExpunge(VOID);
345 ****************************************************************************
349 APTR DevExpunge(REG(BASE_REG, struct DevBase *base))
351 APTR seg_list;
353 if(base->device.dd_Library.lib_OpenCnt == 0)
355 seg_list = base->seg_list;
356 Remove((APTR)base);
357 DeleteDevice(base);
359 else
361 base->device.dd_Library.lib_Flags |= LIBF_DELEXP;
362 seg_list = NULL;
365 return seg_list;
370 /****i* realtek8180.device/DevReserved *************************************
372 * NAME
373 * DevReserved
375 * SYNOPSIS
376 * result = DevReserved()
378 * APTR DevReserved(VOID);
380 ****************************************************************************
384 APTR DevReserved()
386 return NULL;
391 /****i* realtek8180.device/DevBeginIO **************************************
393 * NAME
394 * DevBeginIO
396 * SYNOPSIS
397 * DevBeginIO(request)
399 * VOID DevBeginIO(struct IORequest *);
401 ****************************************************************************
405 VOID DevBeginIO(REG(a1, struct IOSana2Req *request),
406 REG(BASE_REG, struct DevBase *base))
408 struct DevUnit *unit;
410 request->ios2_Req.io_Error = 0;
411 unit = (APTR)request->ios2_Req.io_Unit;
413 if(AttemptSemaphore(&unit->access_lock))
414 ServiceRequest(request, base);
415 else
416 PutRequest(unit->request_ports[GENERAL_QUEUE], (APTR)request, base);
418 return;
423 /****i* realtek8180.device/DevAbortIO **************************************
425 * NAME
426 * DevAbortIO -- Try to stop a request.
428 * SYNOPSIS
429 * DevAbortIO(request)
431 * VOID DevAbortIO(struct IOSana2Req *);
433 * FUNCTION
434 * Do our best to halt the progress of a request.
436 ****************************************************************************
440 VOID DevAbortIO(REG(a1, struct IOSana2Req *request),
441 REG(BASE_REG, struct DevBase *base))
443 Disable();
444 if(request->ios2_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE &&
445 (request->ios2_Req.io_Flags & IOF_QUICK) == 0)
447 Remove((APTR)request);
448 request->ios2_Req.io_Error = IOERR_ABORTED;
449 request->ios2_WireError = S2WERR_GENERIC_ERROR;
450 ReplyMsg((APTR)request);
452 Enable();
454 return;
459 /****i* realtek8180.device/DeleteDevice ************************************
461 * NAME
462 * DeleteDevice
464 * SYNOPSIS
465 * DeleteDevice()
467 * VOID DeleteDevice(VOID);
469 ****************************************************************************
473 VOID DeleteDevice(struct DevBase *base)
475 UWORD neg_size, pos_size;
477 /* Close devices */
479 CloseDevice((APTR)&base->timer_request);
481 /* Close libraries */
483 if(base->poseidon_base != NULL)
484 CloseLibrary(base->poseidon_base);
485 if(base->utility_base != NULL)
486 CloseLibrary((APTR)base->utility_base);
488 /* Free device's memory */
490 neg_size = base->device.dd_Library.lib_NegSize;
491 pos_size = base->device.dd_Library.lib_PosSize;
492 FreeMem((UBYTE *)base - neg_size, pos_size + neg_size);
494 return;
499 /****i* realtek8180.device/CloseUnit ***************************************
501 * NAME
502 * CloseUnit
504 * SYNOPSIS
505 * CloseUnit(request)
507 * VOID CloseUnit(struct IOSana2Req *);
509 ****************************************************************************
513 VOID CloseUnit(struct IOSana2Req *request, struct DevBase *base)
515 struct DevUnit *unit;
516 struct Opener *opener;
518 /* Decrement device usage count and free buffer-management resources */
520 base->device.dd_Library.lib_OpenCnt--;
521 opener = (APTR)request->ios2_BufferManagement;
522 if(opener != NULL)
524 Disable();
525 Remove((APTR)opener);
526 Enable();
527 FreeVec(opener);
530 /* Delete the unit if it's no longer in use */
532 unit = (APTR)request->ios2_Req.io_Unit;
533 if(unit != NULL)
535 if((--unit->open_count) == 0)
537 Remove((APTR)unit);
538 switch(unit->bus)
540 case USB_BUS:
541 DeleteUSBUnit(unit, base);
542 break;
547 return;
552 /****i* realtek8180.device/GetUnit *****************************************
554 * NAME
555 * GetUnit -- Get a unit by number.
557 * SYNOPSIS
558 * unit = GetUnit(unit_num)
560 * struct DevUnit *GetUnit(ULONG);
562 ****************************************************************************
566 struct DevUnit *GetUnit(ULONG unit_num, struct DevBase *base)
568 struct DevUnit *unit;
569 ULONG usb_limit;
571 usb_limit = GetUSBCount(base);
573 if(unit_num < usb_limit)
574 unit = GetUSBUnit(unit_num, base);
575 else
576 unit = NULL;
578 return unit;
583 /****i* realtek8180.device/WrapInt *****************************************
585 * NAME
586 * WrapInt
588 ****************************************************************************
592 BOOL WrapInt(struct Interrupt *interrupt, struct DevBase *base)
594 BOOL success = TRUE;
595 APTR *int_data;
597 if(base->wrapper_int_code != NULL)
599 int_data = AllocMem(2 * sizeof(APTR), MEMF_PUBLIC | MEMF_CLEAR);
600 if(int_data != NULL)
602 int_data[0] = interrupt->is_Code;
603 int_data[1] = interrupt->is_Data;
604 interrupt->is_Code = base->wrapper_int_code;
605 interrupt->is_Data = int_data;
607 else
608 success = FALSE;
611 return success;
616 /****i* realtek8180.device/UnwrapInt ***************************************
618 * NAME
619 * UnwrapInt
621 ****************************************************************************
625 VOID UnwrapInt(struct Interrupt *interrupt, struct DevBase *base)
627 if(interrupt->is_Code == base->wrapper_int_code)
628 FreeMem(interrupt->is_Data, 2 * sizeof(APTR));
630 return;