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,
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>
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 */
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
[] =
79 SMALLINITBYTEDEF(type
);
80 SMALLINITPINTDEF(name
);
81 SMALLINITBYTEDEF(flags
);
82 SMALLINITWORDDEF(version
);
83 SMALLINITWORDDEF(revision
);
84 SMALLINITPINTDEF(id_string
);
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
),
102 static const APTR init_table
[] =
104 (APTR
)sizeof(struct DevBase
),
111 const struct Resident rom_tag
=
114 (struct Resident
*)&rom_tag
,
115 (APTR
)(&rom_tag
+ 1),
121 (STRPTR
)version_string
,
126 static const ULONG rx_tags
[] =
133 static const ULONG tx_tags
[] =
142 /****i* realtek8180.device/DevInit *****************************************
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
))
161 /* Initialise base structure */
163 dev_base
->sys_base
= (APTR
)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
)
176 if(OpenDevice(timer_name
, UNIT_ECLOCK
, (APTR
)&base
->timer_request
, 0)
191 /****i* realtek8180.device/DevOpen *****************************************
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
;
211 struct Opener
*opener
;
212 struct TagItem
*tag_list
;
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 */
231 request
->ios2_Req
.io_Unit
= (APTR
)(unit
= GetUnit(unit_num
, base
));
233 error
= IOERR_OPENFAIL
;
236 /* Handle device sharing */
240 if(unit
->open_count
!= 0 && ((unit
->flags
& UNITF_SHARED
) == 0
241 || (flags
& SANA2OPF_MINE
) != 0))
242 error
= IOERR_UNITBUSY
;
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
);
258 error
= IOERR_OPENFAIL
;
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
,
278 opener
->dma_tx_function
=
279 (APTR
)GetTagData(S2_DMACopyFromBuff32
, (UPINT
)NULL
, tag_list
);
282 AddTail((APTR
)&unit
->openers
, (APTR
)opener
);
286 /* Back out if anything went wrong */
289 CloseUnit(request
, base
);
293 request
->ios2_Req
.io_Error
= error
;
299 /****i* realtek8180.device/DevClose ****************************************
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
;
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
);
335 /****i* realtek8180.device/DevExpunge **************************************
341 * seg_list = DevExpunge()
343 * APTR DevExpunge(VOID);
345 ****************************************************************************
349 APTR
DevExpunge(REG(BASE_REG
, struct DevBase
*base
))
353 if(base
->device
.dd_Library
.lib_OpenCnt
== 0)
355 seg_list
= base
->seg_list
;
361 base
->device
.dd_Library
.lib_Flags
|= LIBF_DELEXP
;
370 /****i* realtek8180.device/DevReserved *************************************
376 * result = DevReserved()
378 * APTR DevReserved(VOID);
380 ****************************************************************************
391 /****i* realtek8180.device/DevBeginIO **************************************
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
);
416 PutRequest(unit
->request_ports
[GENERAL_QUEUE
], (APTR
)request
, base
);
423 /****i* realtek8180.device/DevAbortIO **************************************
426 * DevAbortIO -- Try to stop a request.
429 * DevAbortIO(request)
431 * VOID DevAbortIO(struct IOSana2Req *);
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
))
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
);
459 /****i* realtek8180.device/DeleteDevice ************************************
467 * VOID DeleteDevice(VOID);
469 ****************************************************************************
473 VOID
DeleteDevice(struct DevBase
*base
)
475 UWORD neg_size
, pos_size
;
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
);
499 /****i* realtek8180.device/CloseUnit ***************************************
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
;
525 Remove((APTR
)opener
);
530 /* Delete the unit if it's no longer in use */
532 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
535 if((--unit
->open_count
) == 0)
541 DeleteUSBUnit(unit
, base
);
552 /****i* realtek8180.device/GetUnit *****************************************
555 * GetUnit -- Get a unit by number.
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
;
571 usb_limit
= GetUSBCount(base
);
573 if(unit_num
< usb_limit
)
574 unit
= GetUSBUnit(unit_num
, base
);
583 /****i* realtek8180.device/WrapInt *****************************************
588 ****************************************************************************
592 BOOL
WrapInt(struct Interrupt
*interrupt
, struct DevBase
*base
)
597 if(base
->wrapper_int_code
!= NULL
)
599 int_data
= AllocMem(2 * sizeof(APTR
), MEMF_PUBLIC
| MEMF_CLEAR
);
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
;
616 /****i* realtek8180.device/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
));