1 /* dev.c - usbraw.device by Chris Hodges
6 #include "rawwrap.class.h"
8 AROS_UFH3(DEVBASETYPEPTR
, devInit
,
9 AROS_UFHA(DEVBASETYPEPTR
, base
, D0
),
10 AROS_UFHA(BPTR
, seglist
, A0
),
11 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
15 KPRINTF(10, ("devInit base: 0x%08lx seglist: 0x%08lx SysBase: 0x%08lx\n",
16 base
, seglist
, SysBase
));
18 base
->np_Library
.lib_Node
.ln_Type
= NT_DEVICE
;
19 base
->np_Library
.lib_Node
.ln_Name
= DEVNAME
;
20 base
->np_Library
.lib_Flags
= LIBF_SUMUSED
|LIBF_CHANGED
;
21 base
->np_Library
.lib_Version
= VERSION_NUMBER
;
22 base
->np_Library
.lib_Revision
= REVISION_NUMBER
;
23 base
->np_Library
.lib_IdString
= VERSION_STRING
;
26 base
->np_SegList
= seglist
;
28 if((base
->np_UtilityBase
= OpenLibrary("utility.library", 0)))
30 KPRINTF(10, ("devInit: Ok\n"));
31 KPRINTF(10, ("devInit: openCnt = %ld\n", base
->np_Library
.lib_OpenCnt
));
44 #define UtilityBase base->np_UtilityBase
46 AROS_LH3(DEVBASETYPEPTR
, devOpen
,
47 AROS_LHA(struct IOStdReq
*, ioreq
, A1
),
48 AROS_LHA(ULONG
, unit
, D0
),
49 AROS_LHA(ULONG
, flags
, D1
),
50 DEVBASETYPEPTR
, base
, 1, dev
)
54 struct NepClassRawWrap
*ncp
;
56 KPRINTF(10, ("devOpen ioreq: 0x%08lx unit: %ld flags: 0x%08lx base: 0x%08lx\n",
57 ioreq
, unit
, flags
, base
));
59 ++base
->np_Library
.lib_OpenCnt
;
60 base
->np_Library
.lib_Flags
&= ~LIBF_DELEXP
;
62 KPRINTF(10, ("devOpen: openCnt = %ld\n", base
->np_Library
.lib_OpenCnt
));
63 /* Damn f*cking programs which leave this field to zero! */
64 if(ioreq
->io_Message
.mn_Length
&& (ioreq
->io_Message
.mn_Length
< sizeof(struct IOStdReq
)))
66 KPRINTF(20, ("devOpen: invalid MN_LENGTH (%ld < %ld)!\n",
67 ioreq
->io_Message
.mn_Length
, sizeof(struct IOStdReq
)));
69 ioreq
->io_Error
= IOERR_BADLENGTH
;
71 /* Default to open failure. */
72 ioreq
->io_Error
= IOERR_OPENFAIL
;
74 ioreq
->io_Unit
= NULL
;
75 ncp
= (struct NepClassRawWrap
*) base
->np_ClsBase
->nh_Units
.lh_Head
;
76 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
78 if(ncp
->ncp_UnitNo
== unit
)
80 if(ncp
->ncp_Unit
.unit_OpenCnt
&& ncp
->ncp_CDC
->cdc_UnitExclusive
)
82 ioreq
->io_Error
= IOERR_UNITBUSY
;
84 ioreq
->io_Unit
= (struct Unit
*) ncp
;
88 ncp
= (struct NepClassRawWrap
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
93 ioreq
->io_Error
= IOERR_OPENFAIL
;
94 KPRINTF(20, ("devOpen: could not open unit!\n"));
97 ioreq
->io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
99 ioreq
->io_Unit
->unit_OpenCnt
++;
102 ncp
->ncp_DenyRequests
= FALSE
;
108 ioreq
->io_Unit
= (APTR
) -1;
109 ioreq
->io_Device
= (APTR
) -1;
110 base
->np_Library
.lib_OpenCnt
--;
118 AROS_LH1(BPTR
, devClose
,
119 AROS_LHA(struct IOStdReq
*, ioreq
, A1
),
120 DEVBASETYPEPTR
, base
, 2, dev
)
125 struct NepClassRawWrap
*ncp
= (struct NepClassRawWrap
*) ioreq
->io_Unit
;
127 KPRINTF(10, ("devClose ioreq: 0x%08lx base: 0x%08lx\n", ioreq
, base
));
130 /* Try to flush the last buffer */
132 if(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
)
134 Signal(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
, 1L<<(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
));
139 ncp
->ncp_DenyRequests
= FALSE
;
141 ncp
->ncp_Unit
.unit_OpenCnt
--;
142 ioreq
->io_Unit
= (APTR
) -1;
143 ioreq
->io_Device
= (APTR
) -1;
145 if(--base
->np_Library
.lib_OpenCnt
== 0)
147 if(base
->np_Library
.lib_Flags
& LIBF_DELEXP
)
149 KPRINTF(5, ("devClose: calling expunge...\n"));
150 ret
= AROS_LC1(BPTR
, devExpunge
,
151 AROS_LCA(DEVBASETYPEPTR
, base
, D0
),
152 DEVBASETYPEPTR
, base
, 3, dev
);
156 KPRINTF(5, ("devClose: lib_OpenCnt = %ld\n", base
->np_Library
.lib_OpenCnt
));
164 AROS_LH1(BPTR
, devExpunge
,
165 AROS_LHA(DEVBASETYPEPTR
, extralh
, D0
),
166 DEVBASETYPEPTR
, base
, 3, dev
)
172 KPRINTF(10, ("devExpunge base: 0x%08lx\n", base
));
176 if(base
->np_Library
.lib_OpenCnt
== 0)
178 KPRINTF(5, ("devExpunge: Unloading...\n"));
180 CloseLibrary(base
->np_UtilityBase
);
182 ret
= base
->np_SegList
;
184 KPRINTF(5, ("devExpunge: removing device node 0x%08lx\n",
185 &base
->np_Library
.lib_Node
));
186 Remove(&base
->np_Library
.lib_Node
);
188 KPRINTF(5, ("devExpunge: FreeMem()...\n"));
189 FreeMem((char *) base
- base
->np_Library
.lib_NegSize
,
190 (ULONG
) (base
->np_Library
.lib_NegSize
+ base
->np_Library
.lib_PosSize
));
192 KPRINTF(5, ("devExpunge: Unloading done! " DEVNAME
" expunged!\n\n"));
198 KPRINTF(5, ("devExpunge: Could not expunge, LIBF_DELEXP set!\n"));
199 base
->np_Library
.lib_Flags
|= LIBF_DELEXP
;
207 AROS_LH0(DEVBASETYPEPTR
, devReserved
,
208 DEVBASETYPEPTR
, base
, 4, dev
)
215 AROS_LH1(void, devBeginIO
,
216 AROS_LHA(struct IOStdReq
*, ioreq
, A1
),
217 DEVBASETYPEPTR
, base
, 5, dev
)
221 struct NepClassRawWrap
*ncp
= (struct NepClassRawWrap
*) ioreq
->io_Unit
;
222 WORD ret
= IOERR_NOCMD
;
224 KPRINTF(1, ("devBeginIO ioreq: 0x%08lx base: 0x%08lx cmd: %lu\n", ioreq
, base
, ioreq
->io_Command
));
226 ioreq
->io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
229 if(ioreq
->io_Command
< NSCMD_DEVICEQUERY
)
231 switch (ioreq
->io_Command
)
238 if(!ncp
->ncp_DenyRequests
)
240 ioreq
->io_Flags
&= ~IOF_QUICK
;
242 PutMsg(&ncp
->ncp_Unit
.unit_MsgPort
, (struct Message
*) ioreq
);
249 ioreq
->io_Actual
= ncp
->ncp_RBufFull
;
251 case SDCMD_SETPARAMS
:
260 switch(ioreq
->io_Command
)
262 case NSCMD_DEVICEQUERY
:
263 ret
= cmdNSDeviceQuery((struct IOStdReq
*) ioreq
, ncp
, base
);
272 if(ret
!= RC_DONTREPLY
)
274 KPRINTF(1, ("TermIO\n"));
279 ioreq
->io_Error
= ret
& 0xff;
281 /* Terminate the iorequest
289 AROS_LH1(LONG
, devAbortIO
,
290 AROS_LHA(struct IOStdReq
*, ioreq
, A1
),
291 DEVBASETYPEPTR
, base
, 6, dev
)
295 struct NepClassRawWrap
*ncp
= (struct NepClassRawWrap
*) ioreq
->io_Unit
;
297 struct IOStdReq
*iocmp
;
299 KPRINTF(5, ("devAbortIO ioreq: 0x%08lx\n", ioreq
));
304 if(ioreq
->io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
)
306 if(ncp
->ncp_ReadPending
== ioreq
)
308 ncp
->ncp_AbortRead
= TRUE
;
309 Signal(ncp
->ncp_Task
, 1L<<ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
);
313 if(ncp
->ncp_WritePending
== ioreq
)
315 ncp
->ncp_AbortWrite
= TRUE
;
316 Signal(ncp
->ncp_Task
, 1L<<ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
);
320 iocmp
= (struct IOStdReq
*) ncp
->ncp_ReadQueue
.lh_Head
;
321 while(iocmp
->io_Message
.mn_Node
.ln_Succ
)
325 Remove((struct Node
*) ioreq
);
326 ioreq
->io_Error
= IOERR_ABORTED
;
327 ReplyMsg(&ioreq
->io_Message
);
331 iocmp
= (struct IOStdReq
*) iocmp
->io_Message
.mn_Node
.ln_Succ
;
333 iocmp
= (struct IOStdReq
*) ncp
->ncp_WriteQueue
.lh_Head
;
334 while(iocmp
->io_Message
.mn_Node
.ln_Succ
)
338 Remove((struct Node
*) ioreq
);
339 ioreq
->io_Error
= IOERR_ABORTED
;
340 ReplyMsg(&ioreq
->io_Message
);
344 iocmp
= (struct IOStdReq
*) iocmp
->io_Message
.mn_Node
.ln_Succ
;
357 const UWORD NSDSupported
[] =
359 CMD_RESET
, CMD_CLEAR
,
365 WORD
cmdNSDeviceQuery(struct IOStdReq
*ioreq
,
366 struct NepClassRawWrap
*ncp
,
367 struct NepRawDevBase
*base
)
369 struct my_NSDeviceQueryResult
*query
;
371 query
= (struct my_NSDeviceQueryResult
*) ioreq
->io_Data
;
373 KPRINTF(10, ("NSCMD_DEVICEQUERY ioreq: 0x%08lx query: 0x%08lx\n", ioreq
, query
));
380 (ioreq
->io_Length
< sizeof(struct my_NSDeviceQueryResult
)) ||
381 (query
->DevQueryFormat
!= 0) ||
382 (query
->SizeAvailable
!= 0))
384 /* Return error. This is special handling, since iorequest is only
385 guaranteed to be sizeof(struct IOStdReq). If we'd let our
386 devBeginIO dispatcher return the error, it would trash some
387 memory past end of the iorequest (ios2_WireError field).
389 ioreq
->io_Error
= IOERR_NOCMD
;
390 TermIO((struct IOStdReq
*) ioreq
, base
);
392 /* Don't reply, we already did.
397 ioreq
->io_Actual
= query
->SizeAvailable
398 = sizeof(struct my_NSDeviceQueryResult
);
399 query
->DeviceType
= NSDEVTYPE_UNKNOWN
;
400 query
->DeviceSubType
= 0;
401 query
->SupportedCommands
= NSDSupported
;
403 /* Return success (note that this will NOT poke ios2_WireError).
409 *===========================================================
410 * TermIO(ioreq, base)
411 *===========================================================
413 * Return completed ioreq to sender.
417 void TermIO(struct IOStdReq
*ioreq
,
418 struct NepRawDevBase
*base
)
420 ioreq
->io_Message
.mn_Node
.ln_Type
= NT_FREEMSG
;
422 /* If not quick I/O, reply the message
424 if(!(ioreq
->io_Flags
& IOF_QUICK
))
426 ReplyMsg(&ioreq
->io_Message
);