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,
23 #include <exec/types.h>
24 #include <exec/resident.h>
25 #include <exec/errors.h>
26 #include <exec/emulation.h>
28 #include <utility/utility.h>
29 #include <expansion/expansion.h>
30 #include <resources/card.h>
31 #include <libraries/pccard.h>
33 #include <proto/exec.h>
34 #include <clib/alib_protos.h>
35 #include <proto/utility.h>
39 #include "device_protos.h"
40 #include "unit_protos.h"
41 #include "pci_protos.h"
42 #include "request_protos.h"
45 /* Private prototypes */
47 static struct DevBase
*OS4DevInit(struct DevBase
*dev_base
, APTR seg_list
,
48 struct ExecIFace
*i_exec
);
49 static ULONG
IfaceObtain(struct Interface
*self
);
50 static ULONG
IfaceRelease(struct Interface
*self
);
51 static LONG
OS4DevOpen(struct Interface
*self
, struct IOSana2Req
*request
,
52 ULONG unit_num
, ULONG flags
);
53 static APTR
OS4DevClose(struct Interface
*self
, struct IOSana2Req
*request
);
54 static APTR
OS4DevExpunge(struct Interface
*self
);
55 static VOID
OS4DevBeginIO(struct Interface
*self
,
56 struct IOSana2Req
*request
);
57 static VOID
OS4DevAbortIO(struct Interface
*self
,
58 struct IOSana2Req
*request
);
59 static VOID
DeleteDevice(struct DevBase
*base
);
60 static BOOL
RXFunction(struct IOSana2Req
*request
, APTR buffer
, ULONG size
);
61 static BOOL
TXFunction(APTR buffer
, struct IOSana2Req
*request
, ULONG size
);
62 static UBYTE
*DMATXFunction(struct IOSana2Req
*request
);
63 static ULONG
OS4Int(struct ExceptionContext ex_context
,
64 struct ExecBase
*sys_base
, APTR
*int_data
);
67 extern const TEXT device_name
[];
68 extern const TEXT version_string
[];
69 extern const TEXT utility_name
[];
70 extern const TEXT pccard_name
[];
71 extern const TEXT card_name
[];
72 extern const TEXT dos_name
[];
73 extern const TEXT timer_name
[];
74 extern const struct Resident rom_tag
;
76 static const TEXT manager_name
[] = "__device";
77 static const TEXT expansion_name
[] = EXPANSIONNAME
;
80 static const APTR manager_vectors
[] =
96 static const struct TagItem manager_tags
[] =
98 {MIT_Name
, (UPINT
)manager_name
},
99 {MIT_VectorTable
, (UPINT
)manager_vectors
},
105 static const struct TagItem
*interfaces
[] =
112 static const struct TagItem init_tags
[] =
114 {CLT_DataSize
, sizeof(struct DevBase
)},
115 {CLT_InitFunc
, (UPINT
)OS4DevInit
},
116 {CLT_Interfaces
, (UPINT
)interfaces
},
121 const struct Resident os4_rom_tag
=
124 (struct Resident
*)&os4_rom_tag
,
125 (APTR
)(&rom_tag
+ 1),
126 RTF_AUTOINIT
| RTF_NATIVE
,
131 (STRPTR
)version_string
,
136 static const ULONG rx_tags
[] =
143 static const ULONG tx_tags
[] =
152 /****i* prism2.device/OS4DevInit *******************************************
158 * dev_base = OS4DevInit(dev_base, seg_list, i_exec)
160 * struct DevBase *OS4DevInit(struct DevBase *, APTR, ExecIFace *);
162 ****************************************************************************
166 static struct DevBase
*OS4DevInit(struct DevBase
*dev_base
, APTR seg_list
,
167 struct ExecIFace
*i_exec
)
169 struct DevBase
*base
;
172 dev_base
->i_exec
= i_exec
;
174 base
->seg_list
= seg_list
;
175 base
->sys_base
= (APTR
)i_exec
->Data
.LibBase
;
177 base
->device
.dd_Library
.lib_Node
.ln_Type
= NT_DEVICE
;
178 base
->device
.dd_Library
.lib_Node
.ln_Name
= (TEXT
*)device_name
;
179 base
->device
.dd_Library
.lib_Flags
= LIBF_SUMUSED
| LIBF_CHANGED
;
180 base
->device
.dd_Library
.lib_Version
= VERSION
;
181 base
->device
.dd_Library
.lib_Revision
= REVISION
;
182 base
->device
.dd_Library
.lib_IdString
= (TEXT
*)version_string
;
184 base
->utility_base
= (APTR
)OpenLibrary(utility_name
, UTILITY_VERSION
);
185 base
->expansion_base
= OpenLibrary(expansion_name
, EXPANSION_VERSION
);
186 base
->dos_base
= (APTR
)OpenLibrary(dos_name
, DOS_VERSION
);
187 if(base
->utility_base
== NULL
|| base
->expansion_base
== NULL
188 || base
->dos_base
== NULL
)
190 base
->pccard_base
= (APTR
)OpenLibrary(pccard_name
, PCCARD_VERSION
);
191 if(base
->pccard_base
!= NULL
)
192 base
->card_base
= (APTR
)OpenResource(card_name
);
194 if(OpenDevice(timer_name
, UNIT_VBLANK
, (APTR
)&base
->timer_request
, 0) !=
198 NewList((APTR
)(&dev_base
->pci_units
));
199 NewList((APTR
)(&dev_base
->pccard_units
));
200 base
->wrapper_int_code
= (APTR
)OS4Int
;
205 (APTR
)GetInterface((APTR
)UtilityBase
, "main", 1, NULL
);
206 base
->i_pci
= (APTR
)GetInterface(ExpansionBase
, "pci", 1, NULL
);
207 base
->i_dos
= (APTR
)GetInterface((APTR
)DOSBase
, "main", 1, NULL
);
208 if(CardResource
!= NULL
)
211 (APTR
)GetInterface(PCCardBase
, "main", 1, NULL
);
213 (APTR
)GetInterface(CardResource
, "main", 1, NULL
);
214 // if(base->i_pccard == NULL || base->i_card == NULL)
215 if(base
->i_card
== NULL
)
218 base
->i_timer
= (APTR
)GetInterface((APTR
)TimerBase
, "main", 1, NULL
);
219 if(base
->i_utility
== NULL
|| base
->i_dos
== NULL
220 || base
->i_timer
== NULL
)
235 /****i* prism2.device/IfaceObtain ******************************************
241 * ref_count = IfaceObtain(self)
243 * ULONG IfaceObtain(struct Interface *);
245 ****************************************************************************
249 static ULONG
IfaceObtain(struct Interface
*self
)
251 return self
->Data
.RefCount
++;
256 /****i* prism2.device/IfaceRelease *****************************************
262 * ref_count = IfaceRelease(self)
264 * ULONG IfaceRelease(struct Interface *);
266 ****************************************************************************
270 static ULONG
IfaceRelease(struct Interface
*self
)
272 return --self
->Data
.RefCount
;
277 /****i* prism2.device/OS4DevOpen *******************************************
283 * error = OS4DevOpen(self, request, unit_num,
286 * LONG OS4DevOpen(struct Interface *, struct IOSana2Req *, ULONG,
289 ****************************************************************************
293 static LONG
OS4DevOpen(struct Interface
*self
, struct IOSana2Req
*request
,
294 ULONG unit_num
, ULONG flags
)
296 struct Opener
*opener
;
299 error
= DevOpen(request
, unit_num
, flags
, (APTR
)self
->Data
.LibBase
);
301 /* Set up wrapper hooks to hide 68k emulation */
305 opener
= request
->ios2_BufferManagement
;
306 opener
->real_rx_function
= opener
->rx_function
;
307 opener
->real_tx_function
= opener
->tx_function
;
308 opener
->rx_function
= (APTR
)RXFunction
;
309 opener
->tx_function
= (APTR
)TXFunction
;
310 if(opener
->dma_tx_function
!= NULL
)
312 opener
->real_dma_tx_function
= opener
->dma_tx_function
;
313 opener
->dma_tx_function
= (APTR
)DMATXFunction
;
322 /****i* prism2.device/OS4DevClose ******************************************
328 * seg_list = OS4DevClose(request)
330 * APTR OS4DevClose(struct IOSana2Req *);
332 ****************************************************************************
336 static APTR
OS4DevClose(struct Interface
*self
, struct IOSana2Req
*request
)
338 struct DevBase
*base
;
339 APTR seg_list
= NULL
;
343 base
= (APTR
)self
->Data
.LibBase
;
344 CloseUnit(request
, base
);
346 /* Expunge the device if a delayed expunge is pending */
348 if(base
->device
.dd_Library
.lib_OpenCnt
== 0)
350 if((base
->device
.dd_Library
.lib_Flags
& LIBF_DELEXP
) != 0)
351 seg_list
= OS4DevExpunge(self
);
359 /****i* prism2.device/OS4DevExpunge ****************************************
365 * seg_list = OS4DevExpunge()
367 * APTR OS4DevExpunge(VOID);
369 ****************************************************************************
373 static APTR
OS4DevExpunge(struct Interface
*self
)
375 struct DevBase
*base
;
378 base
= (APTR
)self
->Data
.LibBase
;
379 if(base
->device
.dd_Library
.lib_OpenCnt
== 0)
381 seg_list
= base
->seg_list
;
387 base
->device
.dd_Library
.lib_Flags
|= LIBF_DELEXP
;
396 /****i* prism2.device/OS4DevBeginIO ****************************************
402 * OS4DevBeginIO(request)
404 * VOID OS4DevBeginIO(struct IORequest *);
406 ****************************************************************************
410 static VOID
OS4DevBeginIO(struct Interface
*self
,
411 struct IOSana2Req
*request
)
413 /* Replace caller's cookie with our own */
415 request
->ios2_Req
.io_Error
= 0;
416 switch(request
->ios2_Req
.io_Command
)
423 request
->ios2_StatData
= request
->ios2_Data
;
424 request
->ios2_Data
= request
;
427 /* Send request for processing */
429 DevBeginIO(request
, (APTR
)self
->Data
.LibBase
);
436 /****i* prism2.device/OS4DevAbortIO ****************************************
439 * OS4DevAbortIO -- Try to stop a request.
442 * OS4DevAbortIO(request)
444 * VOID OS4DevAbortIO(struct IOSana2Req *);
446 ****************************************************************************
448 * Disable() used instead of a semaphore because device uses interrupts.
452 static VOID
OS4DevAbortIO(struct Interface
*self
,
453 struct IOSana2Req
*request
)
455 DevAbortIO(request
, (APTR
)self
->Data
.LibBase
);
462 /****i* prism2.device/DeleteDevice *****************************************
470 * VOID DeleteDevice(VOID);
472 ****************************************************************************
476 static VOID
DeleteDevice(struct DevBase
*base
)
478 /* Close interfaces */
480 DropInterface((APTR
)base
->i_timer
);
481 DropInterface((APTR
)base
->i_card
);
482 DropInterface((APTR
)base
->i_pccard
);
483 DropInterface((APTR
)base
->i_dos
);
484 DropInterface((APTR
)base
->i_pci
);
485 DropInterface((APTR
)base
->i_utility
);
489 CloseDevice((APTR
)&base
->timer_request
);
491 /* Close libraries */
493 if(base
->pccard_base
!= NULL
)
494 CloseLibrary(base
->pccard_base
);
495 if(base
->dos_base
!= NULL
)
496 CloseLibrary((APTR
)base
->dos_base
);
497 if(base
->expansion_base
!= NULL
)
498 CloseLibrary(base
->expansion_base
);
499 if(base
->utility_base
!= NULL
)
500 CloseLibrary((APTR
)base
->utility_base
);
502 /* Free device's memory */
504 DeleteLibrary((APTR
)base
);
511 /****i* prism2.device/RXFunction *******************************************
516 ****************************************************************************
520 static BOOL
RXFunction(struct IOSana2Req
*request
, APTR buffer
, ULONG size
)
522 struct DevBase
*base
;
523 struct Opener
*opener
;
526 opener
= request
->ios2_BufferManagement
;
527 cookie
= request
->ios2_StatData
;
528 base
= (struct DevBase
*)request
->ios2_Req
.io_Device
;
529 request
->ios2_Data
= cookie
;
531 return EmulateTags(opener
->real_rx_function
,
532 ET_RegisterA0
, cookie
, ET_RegisterA1
, buffer
,
533 ET_RegisterD0
, size
, TAG_END
);
538 /****i* prism2.device/TXFunction *******************************************
543 ****************************************************************************
547 static BOOL
TXFunction(APTR buffer
, struct IOSana2Req
*request
, ULONG size
)
549 struct DevBase
*base
;
550 struct Opener
*opener
;
553 opener
= request
->ios2_BufferManagement
;
554 cookie
= request
->ios2_StatData
;
555 base
= (struct DevBase
*)request
->ios2_Req
.io_Device
;
556 request
->ios2_Data
= cookie
;
557 return EmulateTags(opener
->real_tx_function
,
558 ET_RegisterA0
, buffer
, ET_RegisterA1
, cookie
,
559 ET_RegisterD0
, size
, TAG_END
);
564 /****i* prism2.device/DMATXFunction ****************************************
569 ****************************************************************************
573 static UBYTE
*DMATXFunction(struct IOSana2Req
*request
)
575 struct DevBase
*base
;
576 struct Opener
*opener
;
579 opener
= request
->ios2_BufferManagement
;
580 cookie
= request
->ios2_StatData
;
581 base
= (struct DevBase
*)request
->ios2_Req
.io_Device
;
582 request
->ios2_Data
= cookie
;
583 return (UBYTE
*)EmulateTags(opener
->real_dma_tx_function
,
584 ET_RegisterA0
, cookie
, TAG_END
);
589 /****i* prism2.device/OS4Int ***********************************************
594 ****************************************************************************
598 static ULONG
OS4Int(struct ExceptionContext ex_context
,
599 struct ExecBase
*sys_base
, APTR
*int_data
)
601 BOOL (*int_code
)(APTR
, APTR
, UBYTE
);
603 int_code
= int_data
[0];
604 return int_code(int_data
[1], int_code
, 0x4);