poseidon: Fix a number of BPTR issues
[AROS.git] / rom / usb / classes / rawwrap / dev.c
blob8db9bf427e648965515a34720dab9265651dc436
1 /* dev.c - usbraw.device by Chris Hodges
2 */
4 #include "debug.h"
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))
13 AROS_USERFUNC_INIT
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;
25 /* Store segment */
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));
32 return(base);
34 else
36 return(NULL);
38 return(base);
40 AROS_USERFUNC_EXIT
43 #undef UtilityBase
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)
52 AROS_LIBFUNC_INIT
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;
70 } else {
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;
83 } else {
84 ioreq->io_Unit = (struct Unit *) ncp;
86 break;
88 ncp = (struct NepClassRawWrap *) ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
91 if(!ioreq->io_Unit)
93 ioreq->io_Error = IOERR_OPENFAIL;
94 KPRINTF(20, ("devOpen: could not open unit!\n"));
95 } else {
96 /* Opended ok! */
97 ioreq->io_Message.mn_Node.ln_Type = NT_REPLYMSG;
98 ioreq->io_Error = 0;
99 ioreq->io_Unit->unit_OpenCnt++;
101 /* Allow queuing */
102 ncp->ncp_DenyRequests = FALSE;
104 return base;
108 ioreq->io_Unit = (APTR) -1;
109 ioreq->io_Device = (APTR) -1;
110 base->np_Library.lib_OpenCnt--;
112 return(NULL);
114 AROS_LIBFUNC_EXIT
118 AROS_LH1(BPTR, devClose,
119 AROS_LHA(struct IOStdReq *, ioreq, A1),
120 DEVBASETYPEPTR, base, 2, dev)
122 AROS_LIBFUNC_INIT
124 BPTR ret;
125 struct NepClassRawWrap *ncp = (struct NepClassRawWrap *) ioreq->io_Unit;
127 KPRINTF(10, ("devClose ioreq: 0x%08lx base: 0x%08lx\n", ioreq, base));
129 ret = BNULL;
130 /* Try to flush the last buffer */
131 Forbid();
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));
136 Permit();
138 /* Allow queuing */
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));
158 return(ret);
160 AROS_LIBFUNC_EXIT
164 AROS_LH1(BPTR, devExpunge,
165 AROS_LHA(DEVBASETYPEPTR, extralh, D0),
166 DEVBASETYPEPTR, base, 3, dev)
168 AROS_LIBFUNC_INIT
170 BPTR ret;
172 KPRINTF(10, ("devExpunge base: 0x%08lx\n", base));
174 ret = BNULL;
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"));
194 return(ret);
196 else
198 KPRINTF(5, ("devExpunge: Could not expunge, LIBF_DELEXP set!\n"));
199 base->np_Library.lib_Flags |= LIBF_DELEXP;
202 return(BNULL);
204 AROS_LIBFUNC_EXIT
207 AROS_LH0(DEVBASETYPEPTR, devReserved,
208 DEVBASETYPEPTR, base, 4, dev)
210 AROS_LIBFUNC_INIT
211 return NULL;
212 AROS_LIBFUNC_EXIT
215 AROS_LH1(void, devBeginIO,
216 AROS_LHA(struct IOStdReq *, ioreq, A1),
217 DEVBASETYPEPTR, base, 5, dev)
219 AROS_LIBFUNC_INIT
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;
227 ioreq->io_Error = 0;
229 if(ioreq->io_Command < NSCMD_DEVICEQUERY)
231 switch (ioreq->io_Command)
233 case CMD_FLUSH:
234 case CMD_READ:
235 case CMD_WRITE:
236 case CMD_RESET:
237 case CMD_CLEAR:
238 if(!ncp->ncp_DenyRequests)
240 ioreq->io_Flags &= ~IOF_QUICK;
241 ret = RC_DONTREPLY;
242 PutMsg(&ncp->ncp_Unit.unit_MsgPort, (struct Message *) ioreq);
243 } else {
244 ret = IOERR_ABORTED;
246 break;
248 case SDCMD_QUERY:
249 ioreq->io_Actual = ncp->ncp_RBufFull;
250 case SDCMD_BREAK:
251 case SDCMD_SETPARAMS:
252 ret = 0;
253 break;
255 default:
256 ret = IOERR_NOCMD;
257 break;
259 } else {
260 switch(ioreq->io_Command)
262 case NSCMD_DEVICEQUERY:
263 ret = cmdNSDeviceQuery((struct IOStdReq *) ioreq, ncp, base);
264 break;
266 default:
267 ret = IOERR_NOCMD;
268 break;
272 if(ret != RC_DONTREPLY)
274 KPRINTF(1, ("TermIO\n"));
275 if (ret != RC_OK)
277 /* Set error codes
279 ioreq->io_Error = ret & 0xff;
281 /* Terminate the iorequest
283 TermIO(ioreq, base);
286 AROS_LIBFUNC_EXIT
289 AROS_LH1(LONG, devAbortIO,
290 AROS_LHA(struct IOStdReq *, ioreq, A1),
291 DEVBASETYPEPTR, base, 6, dev)
293 AROS_LIBFUNC_INIT
295 struct NepClassRawWrap *ncp = (struct NepClassRawWrap *) ioreq->io_Unit;
297 struct IOStdReq *iocmp;
299 KPRINTF(5, ("devAbortIO ioreq: 0x%08lx\n", ioreq));
301 /* Is it pending?
303 Forbid();
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);
310 Permit();
311 return(0);
313 if(ncp->ncp_WritePending == ioreq)
315 ncp->ncp_AbortWrite = TRUE;
316 Signal(ncp->ncp_Task, 1L<<ncp->ncp_Unit.unit_MsgPort.mp_SigBit);
317 Permit();
318 return(0);
320 iocmp = (struct IOStdReq *) ncp->ncp_ReadQueue.lh_Head;
321 while(iocmp->io_Message.mn_Node.ln_Succ)
323 if(iocmp == ioreq)
325 Remove((struct Node *) ioreq);
326 ioreq->io_Error = IOERR_ABORTED;
327 ReplyMsg(&ioreq->io_Message);
328 Permit();
329 return(0);
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)
336 if(iocmp == ioreq)
338 Remove((struct Node *) ioreq);
339 ioreq->io_Error = IOERR_ABORTED;
340 ReplyMsg(&ioreq->io_Message);
341 Permit();
342 return(0);
344 iocmp = (struct IOStdReq *) iocmp->io_Message.mn_Node.ln_Succ;
347 Permit();
348 return(-1);
350 AROS_LIBFUNC_EXIT
353 /* NSD stuff
356 static
357 const UWORD NSDSupported[] =
359 CMD_RESET, CMD_CLEAR,
360 CMD_FLUSH, CMD_READ,
361 CMD_WRITE,
362 NSCMD_DEVICEQUERY, 0
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));
375 /* NULL ptr?
376 Enough data?
377 Valid request?
379 if((!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.
394 return RC_DONTREPLY;
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).
405 return RC_OK;
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);