1 /* dev.c - usbscsi.device by Chris Hodges
6 #include "massstorage.class.h"
8 AROS_UFH3(DEVBASETYPEPTR
, GM_UNIQUENAME(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
;
33 AROS_LH3(DEVBASETYPEPTR
, devOpen
,
34 AROS_LHA(struct IORequest
*, ioreq
, A1
),
35 AROS_LHA(ULONG
, unitnum
, D0
),
36 AROS_LHA(ULONG
, flags
, D1
),
37 DEVBASETYPEPTR
, base
, 1, usbscsidev
)
41 struct NepClassMS
*ncm
;
43 KPRINTF(10, ("devOpen ioreq: 0x%08lx unit: %ld flags: 0x%08lx base: 0x%08lx\n",
44 ioreq
, unitnum
, flags
, base
));
46 if(!base
->np_UtilityBase
)
48 if(!(base
->np_UtilityBase
= OpenLibrary("utility.library", 0)))
50 ioreq
->io_Error
= IOERR_OPENFAIL
;
55 ++base
->np_Library
.lib_OpenCnt
;
56 base
->np_Library
.lib_Flags
&= ~LIBF_DELEXP
;
58 KPRINTF(10, ("devOpen: openCnt = %ld\n", base
->np_Library
.lib_OpenCnt
));
60 /* Damn f*cking programs which leave this field to zero! */
61 if(ioreq
->io_Message
.mn_Length
&&
62 (ioreq
->io_Message
.mn_Length
< sizeof(struct IOStdReq
)))
64 KPRINTF(20, ("devOpen: invalid MN_LENGTH (%ld < %ld)!\n",
65 ioreq
->io_Message
.mn_Length
, sizeof(struct IOStdReq
)));
67 ioreq
->io_Error
= IOERR_BADLENGTH
;
69 /* Default to open failure. */
70 ioreq
->io_Error
= IOERR_OPENFAIL
;
72 ioreq
->io_Unit
= NULL
;
73 ncm
= (struct NepClassMS
*) base
->np_ClsBase
->nh_Units
.lh_Head
;
74 while(ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
76 if(ncm
->ncm_UnitNo
== unitnum
)
78 if(!ncm
->ncm_DenyRequests
)
80 ioreq
->io_Unit
= (struct Unit
*) ncm
;
84 ncm
= (struct NepClassMS
*) ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
89 ioreq
->io_Error
= IOERR_OPENFAIL
;
90 KPRINTF(20, ("devOpen: could not open unit!\n"));
93 ioreq
->io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
95 ioreq
->io_Unit
->unit_OpenCnt
++;
101 ioreq
->io_Unit
= (APTR
) -1;
102 ioreq
->io_Device
= (APTR
) -1;
103 base
->np_Library
.lib_OpenCnt
--;
111 AROS_LH1(BPTR
, devClose
,
112 AROS_LHA(struct IORequest
*, ioreq
, A1
),
113 DEVBASETYPEPTR
, base
, 2, usbscsidev
)
118 struct NepClassMS
*unit
= (struct NepClassMS
*) ioreq
->io_Unit
;
120 KPRINTF(10, ("devClose ioreq: 0x%08lx base: 0x%08lx\n", ioreq
, base
));
123 unit
->ncm_Unit
.unit_OpenCnt
--;
124 ioreq
->io_Unit
= (APTR
) -1;
125 ioreq
->io_Device
= (APTR
) -1;
127 if(--base
->np_Library
.lib_OpenCnt
== 0)
129 if(base
->np_Library
.lib_Flags
& LIBF_DELEXP
)
131 KPRINTF(5, ("devClose: calling expunge...\n"));
132 ret
= AROS_LC1(BPTR
, devExpunge
,
133 AROS_LCA(DEVBASETYPEPTR
, base
, D0
),
134 DEVBASETYPEPTR
, base
, 3, dev
);
138 KPRINTF(5, ("devClose: lib_OpenCnt = %ld\n", base
->np_Library
.lib_OpenCnt
));
146 AROS_LH1(BPTR
, devExpunge
,
147 AROS_LHA(DEVBASETYPEPTR
, extralh
, D0
),
148 DEVBASETYPEPTR
, base
, 3,usbscsidev
)
154 KPRINTF(10, ("devExpunge base: 0x%08lx\n", base
));
158 if(base
->np_Library
.lib_OpenCnt
== 0)
160 KPRINTF(5, ("devExpunge: Unloading...\n"));
162 CloseLibrary(base
->np_UtilityBase
);
164 ret
= base
->np_SegList
;
166 KPRINTF(5, ("devExpunge: removing device node 0x%08lx\n",
167 &base
->np_Library
.lib_Node
));
168 Remove(&base
->np_Library
.lib_Node
);
170 KPRINTF(5, ("devExpunge: FreeMem()...\n"));
171 FreeMem((char *) base
- base
->np_Library
.lib_NegSize
,
172 (ULONG
) (base
->np_Library
.lib_NegSize
+ base
->np_Library
.lib_PosSize
));
174 KPRINTF(5, ("devExpunge: Unloading done! " DEVNAME
" expunged!\n\n"));
180 KPRINTF(5, ("devExpunge: Could not expunge, LIBF_DELEXP set!\n"));
181 base
->np_Library
.lib_Flags
|= LIBF_DELEXP
;
189 AROS_LH0(DEVBASETYPEPTR
, devReserved
,
190 DEVBASETYPEPTR
, base
, 4, usbscsidev
)
197 AROS_LH1(void, devBeginIO
,
198 AROS_LHA(struct IOStdReq
*, ioreq
, A1
),
199 DEVBASETYPEPTR
, base
, 5, usbscsidev
)
203 struct NepClassMS
*unit
= (struct NepClassMS
*) ioreq
->io_Unit
;
204 WORD ret
= IOERR_NOCMD
;
206 KPRINTF(5, ("devBeginIO ioreq: 0x%08lx base: 0x%08lx cmd: %lu\n", ioreq
, base
, ioreq
->io_Command
));
208 ioreq
->io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
211 if(ioreq
->io_Command
< NSCMD_DEVICEQUERY
)
213 switch (ioreq
->io_Command
)
215 case TD_ADDCHANGEINT
:
217 AddTail(&unit
->ncm_DCInts
, (struct Node
*) ioreq
);
222 case TD_REMCHANGEINT
:
224 Remove((struct Node
*) ioreq
);
227 ioreq
->io_Flags
&= ~IOF_QUICK
;
231 ioreq
->io_Actual
= unit
->ncm_ChangeCount
;
236 ioreq
->io_Actual
= unit
->ncm_UnitReady
? 0 : ~0;
241 ioreq
->io_Actual
= unit
->ncm_WriteProtect
? ~0 : 0;
260 if(unit
->ncm_DenyRequests
)
262 ret
= TDERR_DiskChanged
;
264 ioreq
->io_Flags
&= ~IOF_QUICK
;
266 PutMsg(&unit
->ncm_Unit
.unit_MsgPort
, (struct Message
*) ioreq
);
282 switch(ioreq
->io_Command
)
284 case NSCMD_DEVICEQUERY
:
285 ret
= GM_UNIQUENAME(cmdNSDeviceQuery
)((struct IOStdReq
*) ioreq
, unit
, base
);
288 case NSCMD_TD_READ64
:
289 case NSCMD_TD_WRITE64
:
290 case NSCMD_TD_FORMAT64
:
291 case NSCMD_TD_SEEK64
:
292 if(unit
->ncm_DenyRequests
)
296 ioreq
->io_Flags
&= ~IOF_QUICK
;
298 PutMsg(&unit
->ncm_Unit
.unit_MsgPort
, (struct Message
*) ioreq
);
308 if(ret
!= RC_DONTREPLY
)
310 KPRINTF(1, ("GM_UNIQUENAME(TermIO)\n"));
313 /* Set error codes */
314 ioreq
->io_Error
= ret
& 0xff;
316 /* Terminate the iorequest */
317 GM_UNIQUENAME(TermIO
)(ioreq
, base
);
323 AROS_LH1(LONG
, devAbortIO
,
324 AROS_LHA(struct IOStdReq
*, ioreq
, A1
),
325 DEVBASETYPEPTR
, base
, 6, usbscsidev
)
329 struct NepClassMS
*unit
= (struct NepClassMS
*) ioreq
->io_Unit
;
330 struct IOStdReq
*iocmp
;
332 KPRINTF(5, ("devAbortIO ioreq: 0x%08lx\n", ioreq
));
335 if(ioreq
->io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
)
337 if(unit
->ncm_XFerPending
== ioreq
)
339 unit
->ncm_XFerPending
= NULL
;
340 ioreq
->io_Error
= IOERR_ABORTED
;
341 ReplyMsg(&ioreq
->io_Message
);
344 iocmp
= (struct IOStdReq
*) unit
->ncm_XFerQueue
.lh_Head
;
345 while(iocmp
->io_Message
.mn_Node
.ln_Succ
)
349 Remove((struct Node
*) ioreq
);
350 ioreq
->io_Error
= IOERR_ABORTED
;
351 ReplyMsg(&ioreq
->io_Message
);
354 iocmp
= (struct IOStdReq
*) iocmp
->io_Message
.mn_Node
.ln_Succ
;
365 const UWORD
GM_UNIQUENAME(NSDSupported
)[] =
367 CMD_CLEAR
, CMD_RESET
,
369 CMD_WRITE
, CMD_START
,
370 CMD_STOP
, CMD_UPDATE
,
373 TD_CHANGENUM
, TD_PROTSTATUS
,
377 TD_ADDCHANGEINT
, TD_REMCHANGEINT
,
378 TD_READ64
, TD_WRITE64
, TD_SEEK64
,
388 WORD
GM_UNIQUENAME(cmdNSDeviceQuery
)(struct IOStdReq
*ioreq
,
389 struct NepClassMS
*unit
,
390 struct NepMSDevBase
*base
)
392 struct my_NSDeviceQueryResult
*query
;
394 query
= (struct my_NSDeviceQueryResult
*) ioreq
->io_Data
;
396 KPRINTF(10, ("NSCMD_DEVICEQUERY ioreq: 0x%08lx query: 0x%08lx\n", ioreq
, query
));
403 (ioreq
->io_Length
< sizeof(struct my_NSDeviceQueryResult
)) ||
404 (query
->DevQueryFormat
!= 0) ||
405 (query
->SizeAvailable
!= 0))
407 /* Return error. This is special handling, since iorequest is only
408 guaranteed to be sizeof(struct IOStdReq). If we'd let our
409 devBeginIO dispatcher return the error, it would trash some
410 memory past end of the iorequest (ios2_WireError field).
412 ioreq
->io_Error
= IOERR_NOCMD
;
413 GM_UNIQUENAME(TermIO
)((struct IOStdReq
*) ioreq
, base
);
415 /* Don't reply, we already did. */
419 ioreq
->io_Actual
= query
->SizeAvailable
420 = sizeof(struct my_NSDeviceQueryResult
);
421 query
->DeviceType
= NSDEVTYPE_TRACKDISK
;
422 query
->DeviceSubType
= 0;
423 query
->SupportedCommands
= GM_UNIQUENAME(NSDSupported
);
425 /* Return success (note that this will NOT poke ios2_WireError).
430 void GM_UNIQUENAME(TermIO
)(struct IOStdReq
*ioreq
,
431 struct NepMSDevBase
*base
)
433 ioreq
->io_Message
.mn_Node
.ln_Type
= NT_FREEMSG
;
435 /* If not quick I/O, reply the message */
436 if(!(ioreq
->io_Flags
& IOF_QUICK
))
438 ReplyMsg(&ioreq
->io_Message
);