3 Copyright (C) 2000-2005 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>
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>
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 extern const APTR vectors
[];
63 extern const struct TagItem init_tags
[];
66 /* Return an error immediately if someone tries to run the device */
73 const TEXT device_name
[] = DEVICE_NAME
;
74 static const TEXT version_string
[] =
75 DEVICE_NAME
" " STR(VERSION
) "." STR(REVISION
) " (" DATE
")\n";
76 static const TEXT manager_name
[] = "__device";
77 static const TEXT utility_name
[] = UTILITYNAME
;
78 static const TEXT expansion_name
[] = EXPANSIONNAME
;
79 static const TEXT timer_name
[] = TIMERNAME
;
82 const struct Resident rom_tag
=
85 (struct Resident
*)&rom_tag
,
87 RTF_AUTOINIT
| RTF_NATIVE
,
92 (STRPTR
)version_string
,
97 static const APTR manager_vectors
[] =
113 static const struct TagItem manager_tags
[] =
115 {MIT_Name
, (UPINT
)manager_name
},
116 {MIT_VectorTable
, (UPINT
)manager_vectors
},
122 static const struct TagItem
*interfaces
[] =
129 static const struct TagItem init_tags
[] =
131 {CLT_DataSize
, sizeof(struct DevBase
)},
132 {CLT_InitFunc
, (UPINT
)DevInit
},
133 {CLT_Interfaces
, (UPINT
)interfaces
},
138 static const ULONG rx_tags
[] =
145 static const ULONG tx_tags
[] =
154 /****i* intelpro100.device/DevInit *****************************************
160 * dev_base = DevInit(dev_base, seg_list, i_exec)
162 * struct DevBase *DevInit(struct DevBase *, APTR, ExecIFace *);
164 ****************************************************************************
168 static struct DevBase
*DevInit(struct DevBase
*dev_base
, APTR seg_list
,
169 struct ExecIFace
*i_exec
)
171 struct DevBase
*base
;
174 dev_base
->i_exec
= i_exec
;
176 base
->seg_list
= seg_list
;
177 base
->sys_base
= (APTR
)i_exec
->Data
.LibBase
;
179 base
->device
.dd_Library
.lib_Node
.ln_Type
= NT_DEVICE
;
180 base
->device
.dd_Library
.lib_Node
.ln_Name
= (TEXT
*)device_name
;
181 base
->device
.dd_Library
.lib_Flags
= LIBF_SUMUSED
| LIBF_CHANGED
;
182 base
->device
.dd_Library
.lib_Version
= VERSION
;
183 base
->device
.dd_Library
.lib_Revision
= REVISION
;
184 base
->device
.dd_Library
.lib_IdString
= (TEXT
*)version_string
;
187 base
->utility_base
= (APTR
)OpenLibrary(utility_name
, UTILITY_VERSION
);
188 base
->expansion_base
= OpenLibrary(expansion_name
, EXPANSION_VERSION
);
189 if(base
->utility_base
== NULL
|| base
->expansion_base
== NULL
)
192 if(OpenDevice(timer_name
, UNIT_VBLANK
, (APTR
)&base
->timer_request
, 0) !=
196 NewList((APTR
)(&dev_base
->pci_units
));
197 base
->wrapper_int_code
= (APTR
)OS4Int
;
202 (APTR
)GetInterface((APTR
)UtilityBase
, "main", 1, NULL
);
204 (APTR
)GetInterface(ExpansionBase
, "pci", 1, NULL
);
206 (APTR
)GetInterface((APTR
)TimerBase
, "main", 1, NULL
);
207 if(base
->i_utility
== NULL
|| base
->i_pci
== NULL
208 || base
->i_timer
== NULL
)
223 /****i* intelpro100.device/IfaceObtain *************************************
229 * ref_count = IfaceObtain(self)
231 * ULONG IfaceObtain(struct Interface *);
233 ****************************************************************************
237 static ULONG
IfaceObtain(struct Interface
*self
)
239 return self
->Data
.RefCount
++;
244 /****i* intelpro100.device/IfaceRelease ************************************
250 * ref_count = IfaceRelease(self)
252 * ULONG IfaceRelease(struct Interface *);
254 ****************************************************************************
258 static ULONG
IfaceRelease(struct Interface
*self
)
260 return --self
->Data
.RefCount
;
265 /****i* intelpro100.device/DevOpen *****************************************
271 * error = DevOpen(self, request, unit_num, flags)
273 * LONG DevOpen(struct Interface *, struct IOSana2Req *, ULONG, ULONG);
275 ****************************************************************************
279 static LONG
DevOpen(struct Interface
*self
, struct IOSana2Req
*request
,
280 ULONG unit_num
, ULONG flags
)
282 struct DevBase
*base
;
283 struct DevUnit
*unit
;
285 struct Opener
*opener
;
286 struct TagItem
*tag_list
;
289 base
= (APTR
)self
->Data
.LibBase
;
290 base
->device
.dd_Library
.lib_OpenCnt
++;
291 base
->device
.dd_Library
.lib_Flags
&= ~LIBF_DELEXP
;
293 request
->ios2_Req
.io_Unit
= NULL
;
294 tag_list
= request
->ios2_BufferManagement
;
295 request
->ios2_BufferManagement
= NULL
;
297 /* Check request size */
299 if(request
->ios2_Req
.io_Message
.mn_Length
< sizeof(struct IOSana2Req
))
300 error
= IOERR_OPENFAIL
;
302 /* Get the requested unit */
306 request
->ios2_Req
.io_Unit
= (APTR
)(unit
= GetUnit(unit_num
, base
));
308 error
= IOERR_OPENFAIL
;
311 /* Handle device sharing */
315 if((unit
->open_count
!= 0) && (((unit
->flags
& UNITF_SHARED
) == 0)
316 || ((flags
& SANA2OPF_MINE
) != 0)))
317 error
= IOERR_UNITBUSY
;
323 if((flags
& SANA2OPF_MINE
) == 0)
324 unit
->flags
|= UNITF_SHARED
;
325 else if((flags
& SANA2OPF_PROM
) != 0)
326 unit
->flags
|= UNITF_PROM
;
328 /* Set up buffer-management structure and get hooks */
330 request
->ios2_BufferManagement
= opener
=
331 AllocVec(sizeof(struct Opener
), MEMF_PUBLIC
| MEMF_CLEAR
);
333 error
= IOERR_OPENFAIL
;
338 NewList(&opener
->read_port
.mp_MsgList
);
339 opener
->read_port
.mp_Flags
= PA_IGNORE
;
340 NewList((APTR
)&opener
->initial_stats
);
342 for(i
= 0; i
< 2; i
++)
343 opener
->real_rx_function
= (APTR
)GetTagData(rx_tags
[i
],
344 (UPINT
)opener
->real_rx_function
, tag_list
);
345 for(i
= 0; i
< 3; i
++)
346 opener
->real_tx_function
= (APTR
)GetTagData(tx_tags
[i
],
347 (UPINT
)opener
->real_tx_function
, tag_list
);
349 opener
->filter_hook
= (APTR
)GetTagData(S2_PacketFilter
, (UPINT
)NULL
,
351 opener
->real_dma_tx_function
=
352 (APTR
)GetTagData(S2_DMACopyFromBuff32
, (UPINT
)NULL
, tag_list
);
354 opener
->rx_function
= (APTR
)RXFunction
;
355 opener
->tx_function
= (APTR
)TXFunction
;
356 if(opener
->real_dma_tx_function
!= NULL
)
357 opener
->dma_tx_function
= (APTR
)DMATXFunction
;
360 AddTail((APTR
)&unit
->openers
, (APTR
)opener
);
364 /* Back out if anything went wrong */
367 DevClose(self
, request
);
371 request
->ios2_Req
.io_Error
= error
;
377 /****i* intelpro100.device/DevClose ****************************************
383 * seg_list = DevClose(request)
385 * APTR DevClose(struct IOSana2Req *);
387 ****************************************************************************
391 static APTR
DevClose(struct Interface
*self
, struct IOSana2Req
*request
)
393 struct DevBase
*base
;
394 struct DevUnit
*unit
;
396 struct Opener
*opener
;
398 /* Free buffer-management resources */
400 base
= (APTR
)self
->Data
.LibBase
;
401 opener
= (APTR
)request
->ios2_BufferManagement
;
405 Remove((APTR
)opener
);
410 /* Delete the unit if it's no longer in use */
412 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
415 if((--unit
->open_count
) == 0)
421 DeletePCIUnit(unit
, base
);
426 /* Expunge the device if a delayed expunge is pending */
430 if((--base
->device
.dd_Library
.lib_OpenCnt
) == 0)
432 if((base
->device
.dd_Library
.lib_Flags
& LIBF_DELEXP
) != 0)
433 seg_list
= DevExpunge(self
);
441 /****i* intelpro100.device/DevExpunge **************************************
447 * seg_list = DevExpunge()
449 * APTR DevExpunge(VOID);
451 ****************************************************************************
455 static APTR
DevExpunge(struct Interface
*self
)
457 struct DevBase
*base
;
460 base
= (APTR
)self
->Data
.LibBase
;
461 if(base
->device
.dd_Library
.lib_OpenCnt
== 0)
463 seg_list
= base
->seg_list
;
469 base
->device
.dd_Library
.lib_Flags
|= LIBF_DELEXP
;
478 /****i* intelpro100.device/DevBeginIO **************************************
484 * DevBeginIO(request)
486 * VOID DevBeginIO(struct IORequest *);
488 ****************************************************************************
492 static VOID
DevBeginIO(struct Interface
*self
, struct IOSana2Req
*request
)
494 struct DevBase
*base
;
495 struct DevUnit
*unit
;
497 /* Replace caller's cookie with our own */
499 base
= (APTR
)self
->Data
.LibBase
;
500 request
->ios2_Req
.io_Error
= 0;
501 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
502 switch(request
->ios2_Req
.io_Command
)
509 request
->ios2_StatData
= request
->ios2_Data
;
510 request
->ios2_Data
= request
;
513 /* Send request for processing */
515 if(AttemptSemaphore(&unit
->access_lock
))
516 ServiceRequest(request
, base
);
519 PutRequest(unit
->request_ports
[GENERAL_QUEUE
], (APTR
)request
, base
);
527 /****i* intelpro100.device/DevAbortIO **************************************
530 * DevAbortIO -- Try to stop a request.
533 * DevAbortIO(request)
535 * VOID DevAbortIO(struct IOSana2Req *);
537 ****************************************************************************
539 * Disable() used instead of a semaphore because device uses interrupts.
543 static VOID
DevAbortIO(struct Interface
*self
, struct IOSana2Req
*request
)
545 struct DevBase
*base
;
546 struct DevUnit
*unit
;
548 base
= (APTR
)self
->Data
.LibBase
;
549 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
552 if((request
->ios2_Req
.io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
)
553 && ((request
->ios2_Req
.io_Flags
& IOF_QUICK
) == 0))
555 Remove((APTR
)request
);
556 request
->ios2_Req
.io_Error
= IOERR_ABORTED
;
557 request
->ios2_WireError
= S2WERR_GENERIC_ERROR
;
558 ReplyMsg((APTR
)request
);
567 /****i* intelpro100.device/DeleteDevice ************************************
575 * VOID DeleteDevice(VOID);
577 ****************************************************************************
581 static VOID
DeleteDevice(struct DevBase
*base
)
583 /* Close interfaces */
585 DropInterface((APTR
)base
->i_timer
);
586 DropInterface((APTR
)base
->i_pci
);
587 DropInterface((APTR
)base
->i_utility
);
591 CloseDevice((APTR
)&base
->timer_request
);
593 /* Close libraries */
595 if(base
->expansion_base
!= NULL
)
596 CloseLibrary(base
->expansion_base
);
597 if(base
->utility_base
!= NULL
)
598 CloseLibrary((APTR
)base
->utility_base
);
600 /* Free device's memory */
602 DeleteLibrary((APTR
)base
);
609 /****i* intelpro100.device/GetUnit *****************************************
612 * GetUnit -- Get a unit by number.
615 * unit = GetUnit(unit_num)
617 * struct DevUnit *GetUnit(ULONG);
619 ****************************************************************************
623 static struct DevUnit
*GetUnit(ULONG unit_num
, struct DevBase
*base
)
625 struct DevUnit
*unit
;
628 pci_limit
= GetPCICount(base
);
630 if(unit_num
< pci_limit
)
631 unit
= GetPCIUnit(unit_num
, base
);
640 /****i* intelpro100.device/RXFunction **************************************
645 ****************************************************************************
649 static BOOL
RXFunction(struct IOSana2Req
*request
, APTR buffer
, ULONG size
)
651 struct DevBase
*base
;
652 struct Opener
*opener
;
655 opener
= request
->ios2_BufferManagement
;
656 cookie
= request
->ios2_StatData
;
657 base
= (struct DevBase
*)request
->ios2_Req
.io_Device
;
658 request
->ios2_Data
= cookie
;
660 return EmulateTags(opener
->real_rx_function
,
661 ET_RegisterA0
, cookie
, ET_RegisterA1
, buffer
,
662 ET_RegisterD0
, size
, TAG_END
);
667 /****i* intelpro100.device/TXFunction **************************************
672 ****************************************************************************
676 static BOOL
TXFunction(APTR buffer
, struct IOSana2Req
*request
, ULONG size
)
678 struct DevBase
*base
;
679 struct Opener
*opener
;
682 opener
= request
->ios2_BufferManagement
;
683 cookie
= request
->ios2_StatData
;
684 base
= (struct DevBase
*)request
->ios2_Req
.io_Device
;
685 request
->ios2_Data
= cookie
;
686 return EmulateTags(opener
->real_tx_function
,
687 ET_RegisterA0
, buffer
, ET_RegisterA1
, cookie
,
688 ET_RegisterD0
, size
, TAG_END
);
693 /****i* intelpro100.device/DMATXFunction ***********************************
698 ****************************************************************************
702 static UBYTE
*DMATXFunction(struct IOSana2Req
*request
)
704 struct DevBase
*base
;
705 struct Opener
*opener
;
708 opener
= request
->ios2_BufferManagement
;
709 cookie
= request
->ios2_StatData
;
710 base
= (struct DevBase
*)request
->ios2_Req
.io_Device
;
711 request
->ios2_Data
= cookie
;
712 return (UBYTE
*)EmulateTags(opener
->real_dma_tx_function
,
713 ET_RegisterA0
, cookie
, TAG_END
);
718 /****i* intelpro100.device/OS4Int ******************************************
723 ****************************************************************************
727 static ULONG
OS4Int(struct ExceptionContext ex_context
,
728 struct ExecBase
*sys_base
, APTR
*int_data
)
730 BOOL (*int_code
)(APTR
, APTR
);
732 int_code
= int_data
[0];
733 return int_code(int_data
[1], int_code
);