2 *----------------------------------------------------------------------------
3 * massstorage class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
10 #include "massstorage.class.h"
12 #define DEF_NAKTIMEOUT (100)
15 static const STRPTR
GM_UNIQUENAME(libname
) = MOD_NAME_STRING
;
18 const APTR
GM_UNIQUENAME(DevFuncTable
)[] =
20 &AROS_SLIB_ENTRY(devOpen
, usbscsidev
, 1),
21 &AROS_SLIB_ENTRY(devClose
, usbscsidev
, 2),
22 &AROS_SLIB_ENTRY(devExpunge
, usbscsidev
, 3),
23 &AROS_SLIB_ENTRY(devReserved
, usbscsidev
, 4),
24 &AROS_SLIB_ENTRY(devBeginIO
, usbscsidev
, 5),
25 &AROS_SLIB_ENTRY(devAbortIO
, usbscsidev
, 6),
29 static int GM_UNIQUENAME(libInit
)(LIBBASETYPEPTR nh
)
31 struct ClsDevCfg
*cdc
= NULL
;
32 struct ClsUnitCfg
*cuc
= NULL
;
33 struct NepClassMS
*ncm
;
34 struct NepMSBase
*ret
= NULL
;
36 KPRINTF(10, ("libInit nh: 0x%08lx SysBase: 0x%08lx\n", nh
, SysBase
));
38 #define UtilityBase nh->nh_UtilityBase
39 nh
->nh_UtilityBase
= OpenLibrary("utility.library", 39);
42 /* Initialize device node & library struct */
43 KPRINTF(1, ("UtilityOkay\n"));
44 NewList(&nh
->nh_Units
);
45 InitSemaphore(&nh
->nh_TaskLock
);
47 ncm
= &nh
->nh_DummyNCM
;
48 ncm
->ncm_ClsBase
= nh
;
49 ncm
->ncm_Interface
= NULL
;
50 strcpy(ncm
->ncm_LUNIDStr
, "Default");
51 strcpy(ncm
->ncm_LUNNumStr
, "All");
52 ncm
->ncm_CDC
= cdc
= AllocVec(sizeof(struct ClsDevCfg
), MEMF_PUBLIC
|MEMF_CLEAR
);
53 ncm
->ncm_CUC
= cuc
= AllocVec(sizeof(struct ClsUnitCfg
), MEMF_PUBLIC
|MEMF_CLEAR
);
56 KPRINTF(1, ("MakeLibrary\n"));
57 if((nh
->nh_DevBase
= (struct NepMSDevBase
*) MakeLibrary((APTR
) GM_UNIQUENAME(DevFuncTable
), NULL
, (APTR
) GM_UNIQUENAME(devInit
),
58 sizeof(struct NepMSDevBase
), NULL
)))
60 KPRINTF(1,("AddDevice\n"));
61 nh
->nh_DevBase
->np_ClsBase
= nh
;
63 AddDevice((struct Device
*) nh
->nh_DevBase
);
64 nh
->nh_DevBase
->np_Library
.lib_OpenCnt
++;
68 KPRINTF(20, ("failed to create usbscsi.device\n"));
72 KPRINTF(20, ("libInit: OpenLibrary(\"utility.library\", 39) failed!\n"));
78 CloseLibrary(UtilityBase
);
80 KPRINTF(10, ("libInit: Ok\n"));
81 return(ret
? TRUE
: FALSE
);
84 static int GM_UNIQUENAME(libOpen
)(LIBBASETYPEPTR nh
)
86 KPRINTF(10, ("libOpen nh: 0x%08lx\n", nh
));
87 GM_UNIQUENAME(nLoadClassConfig
)(nh
);
92 static int GM_UNIQUENAME(libClose
)(LIBBASETYPEPTR nh
)
94 if(nh
->nh_Library
.lib_OpenCnt
== 0) // FIXME is this 0 or 1? Does AROS decrease it before calling libClose?
96 ObtainSemaphore(&nh
->nh_TaskLock
);
98 nh
->nh_ReadySignal
= SIGB_SINGLE
;
99 nh
->nh_ReadySigTask
= FindTask(NULL
);
100 if(nh
->nh_RemovableTask
)
102 Signal(nh
->nh_RemovableTask
, SIGBREAKF_CTRL_C
);
105 while(nh
->nh_RemovableTask
)
107 Wait(1L<<nh
->nh_ReadySignal
);
109 //FreeSignal(nh->nh_ReadySignal);
110 ReleaseSemaphore(&nh
->nh_TaskLock
);
112 KPRINTF(5, ("libClose: lib_OpenCnt = %ld\n", nh
->nh_Library
.lib_OpenCnt
));
116 static int GM_UNIQUENAME(libExpunge
)(LIBBASETYPEPTR nh
)
118 struct NepClassMS
*ncm
;
120 KPRINTF(10, ("libExpunge nh: 0x%08lx\n", nh
));
122 if((nh
->nh_DevBase
->np_Library
.lib_OpenCnt
== 1))
124 KPRINTF(1, ("libExpunge: closelibrary utilitybase 0x%08lx\n",
127 Remove(&nh
->nh_Library
.lib_Node
);
128 ncm
= (struct NepClassMS
*) nh
->nh_Units
.lh_Head
;
129 while(ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
131 Remove((struct Node
*) ncm
);
132 FreeVec(ncm
->ncm_CDC
);
133 FreeVec(ncm
->ncm_CUC
);
134 FreeVec(ncm
->ncm_DevIDString
);
135 FreeVec(ncm
->ncm_IfIDString
);
137 ncm
= (struct NepClassMS
*) nh
->nh_Units
.lh_Head
;
140 ncm
= &nh
->nh_DummyNCM
;
141 FreeVec(ncm
->ncm_CDC
);
142 FreeVec(ncm
->ncm_CUC
);
144 nh
->nh_DevBase
->np_Library
.lib_OpenCnt
--;
145 RemDevice((struct Device
*) nh
->nh_DevBase
);
146 KPRINTF(5, ("libExpunge: Unloading done! massstorage.class expunged!\n\n"));
148 KPRINTF(5, ("libExpunge: Could not expunge, LIBF_DELEXP set!\n"));
155 ADD2INITLIB(GM_UNIQUENAME(libInit
), 0)
156 ADD2OPENLIB(GM_UNIQUENAME(libOpen
), 0)
157 ADD2CLOSELIB(GM_UNIQUENAME(libClose
), 0)
158 ADD2EXPUNGELIB(GM_UNIQUENAME(libExpunge
), 0)
162 * ***********************************************************************
163 * * Library functions *
164 * ***********************************************************************
167 /* /// "usbAttemptInterfaceBinding()" */
168 struct NepClassMS
* GM_UNIQUENAME(usbAttemptInterfaceBinding
)(struct NepMSBase
*nh
, struct PsdInterface
*pif
)
174 struct PsdConfig
*pc
;
175 struct PsdDevice
*pd
;
179 KPRINTF(1, ("nepMSAttemptInterfaceBinding(%08lx)\n", pif
));
180 if((ps
= OpenLibrary("poseidon.library", 4)))
182 psdGetAttrs(PGA_INTERFACE
, pif
,
184 IFA_SubClass
, &subclass
,
185 IFA_Protocol
, &proto
,
188 psdGetAttrs(PGA_CONFIG
, pc
,
191 psdGetAttrs(PGA_DEVICE
, pd
,
192 DA_ProductID
, &prodid
,
193 DA_VendorID
, &vendid
,
198 // Huawei modem, massstorage is useless.
199 if( (vendid
== 0x12d1 ) && (prodid
== 0x1001 || prodid
== 0x1003 ) ) return(NULL
);
201 if((ifclass
== MASSSTORE_CLASSCODE
) &&
202 ((subclass
== MS_SCSI_SUBCLASS
) ||
203 (subclass
== MS_RBC_SUBCLASS
) ||
204 (subclass
== MS_ATAPI_SUBCLASS
) ||
205 (subclass
== MS_FDDATAPI_SUBCLASS
) ||
206 (subclass
== MS_UFI_SUBCLASS
)) &&
207 ((proto
== MS_PROTO_BULK
) ||
208 (proto
== MS_PROTO_CB
) ||
209 (proto
== MS_PROTO_CBI
)))
211 return(GM_UNIQUENAME(usbForceInterfaceBinding
)(nh
, pif
));
218 /* /// "usbForceInterfaceBinding()" */
219 struct NepClassMS
* GM_UNIQUENAME(usbForceInterfaceBinding
)(struct NepMSBase
*nh
, struct PsdInterface
*pif
)
222 struct Task
*subtask
;
223 struct NepClassMS
*ncm
;
224 struct NepClassMS
*firstncm
= NULL
;
225 struct NepClassMS
*tmpncm
;
227 struct PsdConfig
*pc
;
228 struct PsdDevice
*pd
;
230 struct ClsDevCfg
*cdc
;
231 struct ClsUnitCfg
*cuc
;
248 ULONG patchflags
= 0;
249 BOOL delayedstore
= FALSE
;
251 KPRINTF(1, ("nepMSAttemptInterfaceBinding(%08lx)\n", pif
));
252 if(!(mp
= CreateMsgPort()))
256 if((ps
= OpenLibrary("poseidon.library", 4)))
258 psdGetAttrs(PGA_INTERFACE
, pif
,
260 IFA_SubClass
, &subclass
,
261 IFA_Protocol
, &proto
,
262 IFA_InterfaceNum
, &ifnum
,
264 IFA_IDString
, &ifidstr
,
266 psdGetAttrs(PGA_CONFIG
, pc
,
269 psdGetAttrs(PGA_DEVICE
, pd
,
270 DA_ProductID
, &prodid
,
271 DA_VendorID
, &vendid
,
272 DA_ProductName
, &devname
,
273 DA_IDString
, &devidstr
,
276 /* Patches and fixes */
277 if((proto
!= MS_PROTO_BULK
) && (proto
!= MS_PROTO_CB
) && (proto
!= MS_PROTO_CBI
))
279 proto
= MS_PROTO_BULK
;
281 if((subclass
!= MS_SCSI_SUBCLASS
) &&
282 (subclass
!= MS_RBC_SUBCLASS
) &&
283 (subclass
!= MS_ATAPI_SUBCLASS
) &&
284 (subclass
!= MS_FDDATAPI_SUBCLASS
) &&
285 (subclass
!= MS_UFI_SUBCLASS
))
287 subclass
= MS_SCSI_SUBCLASS
;
290 if(proto
== MS_PROTO_BULK
)
292 if(vendid
== 0x05e3) /* 2.5 HD Wrapper by Eagle Tec */
294 patchflags
|= PFF_FIX_INQ36
|PFF_SIMPLE_SCSI
|PFF_DELAY_DATA
;
295 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
296 "Broken Genesys firmware data phase delay activated. Performance loss!");
298 if((vendid
== 0x0d7d) && (prodid
== 0x1600)) /* HAMA Memory stick */
300 patchflags
|= PFF_SIMPLE_SCSI
;
302 if(((vendid
== 0x04cb) && (prodid
== 0x0100)) || /* Fujifilm FinePix 1400Zoom */
303 ((vendid
== 0x0204) && (prodid
== 0x6025)) || /* Brock's EXIGO Flashstick */
304 ((vendid
== 0x0aec) && (prodid
== 0x5010))) /* SOYO Multislot Reader */
306 patchflags
|= PFF_FIX_INQ36
;
308 if(((vendid
== 0x0c76) && (prodid
== 0x0005)) || /* JetFlash */
309 ((vendid
== 0x066f) && (prodid
== 0x8000))) /* Aiptek_mp3-310_128MB.txt */
311 patchflags
|= PFF_NO_RESET
;
314 if(((vendid
== 0x059b) && (prodid
== 0x0031)) || /* ZIP 100 */
315 //((vendid == 0x0aec) && (prodid == 0x5010)) || /* Neodio CF-Reader */
316 ((vendid
== 0x058f) && (prodid
== 0x9380)) || /* guido's stick */
317 ((vendid
== 0x3579) && (prodid
== 0x6901)))
318 //((vendid == 0x07c4) && (prodid == 0xb00b))) /* USB Memory Stick */
320 patchflags
|= PFF_SINGLE_LUN
;
324 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
325 "Preconfig patchflags 0x%04lx", patchflags
);
329 while(lunnum
<= maxlun
)
333 unitno = firstncm->ncm_UnitNo + lunnum;
339 ncm
= (struct NepClassMS
*) nh
->nh_Units
.lh_Head
;
340 while(ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
342 if((strcmp(devidstr
, ncm
->ncm_DevIDString
) == 0) &&
343 (strcmp(ifidstr
, ncm
->ncm_IfIDString
) == 0) &&
344 (ncm
->ncm_UnitLUN
== lunnum
))
346 unitno
= ncm
->ncm_UnitNo
;
350 ncm
= (struct NepClassMS
*) ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
354 /* as units are freed in the expunge-vector, the memory is
355 outside the scope of the poseidon library */
356 if(!(ncm
= AllocVec(sizeof(struct NepClassMS
), MEMF_PUBLIC
|MEMF_CLEAR
)))
363 ncm
->ncm_ClsBase
= nh
;
364 ncm
->ncm_UnitNo
= (ULONG
) ~0;
365 ncm
->ncm_CDC
= cdc
= AllocVec(sizeof(struct ClsDevCfg
), MEMF_PUBLIC
|MEMF_CLEAR
);
366 ncm
->ncm_CUC
= cuc
= AllocVec(sizeof(struct ClsUnitCfg
), MEMF_PUBLIC
|MEMF_CLEAR
);
367 ncm
->ncm_DevIDString
= AllocVec((ULONG
) strlen(devidstr
)+1, MEMF_PUBLIC
|MEMF_CLEAR
);
368 ncm
->ncm_IfIDString
= AllocVec((ULONG
) strlen(ifidstr
)+1, MEMF_PUBLIC
|MEMF_CLEAR
);
369 if(!(cdc
&& cuc
&& ncm
->ncm_DevIDString
&& ncm
->ncm_IfIDString
))
373 FreeVec(ncm
->ncm_DevIDString
);
374 FreeVec(ncm
->ncm_IfIDString
);
381 /* IORequests may be queued even if the task is gone. */
382 NewList(&ncm
->ncm_Unit
.unit_MsgPort
.mp_MsgList
);
383 NewList(&ncm
->ncm_XFerQueue
);
384 NewList(&ncm
->ncm_DCInts
);
385 InitSemaphore(&ncm
->ncm_XFerLock
);
386 AddTail(&nh
->nh_Units
, &ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
);
387 strcpy(ncm
->ncm_DevIDString
, devidstr
);
388 strcpy(ncm
->ncm_IfIDString
, ifidstr
);
391 ncm
->ncm_Interface
= pif
;
392 ncm
->ncm_Device
= pd
;
393 ncm
->ncm_Config
= pc
;
394 ncm
->ncm_UnitLUN
= lunnum
;
395 ncm
->ncm_UnitIfNum
= ifnum
;
396 ncm
->ncm_UnitProdID
= prodid
;
397 ncm
->ncm_UnitVendorID
= vendid
;
398 ncm
->ncm_TPType
= proto
;
399 ncm
->ncm_CSType
= subclass
;
400 ncm
->ncm_BlockSize
= 0;
401 ncm
->ncm_BlockShift
= 9;
402 psdSafeRawDoFmt(ncm
->ncm_LUNNumStr
, 4, "%ld", ncm
->ncm_UnitLUN
);
408 ncm
->ncm_UnitLUN0
= firstncm
;
410 GM_UNIQUENAME(nLoadBindingConfig
)(ncm
);
411 if(ncm
->ncm_UsingDefaultCfg
)
413 ncm
->ncm_CDC
->cdc_PatchFlags
|= nh
->nh_DummyNCM
.ncm_CDC
->cdc_PatchFlags
;
415 patchflags
= 0; // specific flags override defaults, ALL defaults.
418 patchflags
|= ncm
->ncm_CDC
->cdc_PatchFlags
;
419 if((vendid
== 0x090a) && (prodid
== 0x1100))
421 patchflags
|= PFF_CLEAR_EP
;
422 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Enabling clear endpoint halt mode for this device!");
424 if(vendid
== 0x07b4) /* Olympus C-xx */
426 patchflags
|= PFF_CSS_BROKEN
;
427 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Workaround for broken Olympus cameras enabled.");
429 if(vendid
== 0x067b) /* Prolific */
431 patchflags
|= PFF_CSS_BROKEN
;
432 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Workaround for broken Prolific signature enabled.");
434 if((vendid
== 0x0c76) && (prodid
== 0x0005))
436 patchflags
|= PFF_FIX_INQ36
|PFF_FAKE_INQUIRY
|PFF_MODE_XLATE
;
439 // do this for the first LUN only
442 if((pp
= psdAllocPipe(pd
, mp
, NULL
)))
444 psdSetAttrs(PGA_PIPE
, pp
,
445 PPA_NakTimeout
, TRUE
,
446 PPA_NakTimeoutTime
, 1000,
448 if(((vendid
== 0x04e6) && ((prodid
== 0x0002) || (prodid
== 0x000b) || (prodid
== 0x000c))) ||
449 ((vendid
== 0x050d) && (prodid
== 0x0115)) ||
450 ((vendid
== 0x07af) && ((prodid
== 0x0004) || (prodid
== 0x0005))))
452 UBYTE databyte
= 0x01;
453 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
454 "Attempting to do special eUSCSI init...");
456 psdPipeSetup(pp
, URTF_VENDOR
|URTF_INTERFACE
, 0x0c, 0x01, ifnum
);
457 ioerr
= psdDoPipe(pp
, &databyte
, 1);
460 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
461 "eUSCSI_init failed: %s (%ld)",
462 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
465 if((vendid
== 0x1019) && (prodid
== 0x0C55))
467 struct UsbMSCmdBlkWrapper umscbw
;
468 struct UsbMSCmdStatusWrapper umscsw
;
469 struct PsdPipe
*outep
, *inep
;
470 struct PsdPipe
*outpp
, *inpp
;
472 inep
= psdFindEndpoint(pif
, NULL
,
474 EA_TransferType
, USEAF_BULK
,
476 outep
= psdFindEndpoint(pif
, NULL
,
478 EA_TransferType
, USEAF_BULK
,
482 inpp
= psdAllocPipe(pd
, mp
, inep
);
483 outpp
= psdAllocPipe(pd
, mp
, outep
);
486 psdSetAttrs(PGA_PIPE
, inpp
,
487 PPA_NakTimeout
, TRUE
,
488 PPA_NakTimeoutTime
, 5000,
490 psdSetAttrs(PGA_PIPE
, outpp
,
491 PPA_NakTimeout
, TRUE
,
492 PPA_NakTimeoutTime
, 5000,
493 PPA_NoShortPackets
, TRUE
,
496 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
497 "Attempting to do special UCR-61S2B init...");
498 umscbw
.dCBWSignature
= AROS_LONG2LE(0x43425355);
500 umscbw
.dCBWDataTransferLength
= 0;
501 umscbw
.bmCBWFlags
= 0;
503 umscbw
.bCBWCBLength
= 12;
504 memset(umscbw
.CBWCB
, 0, 16);
505 CopyMem("\xec\x0a\x06\x00$PCCHIPS", umscbw
.CBWCB
, (ULONG
) umscbw
.bCBWCBLength
);
506 ioerr
= psdDoPipe(outpp
, &umscbw
, UMSCBW_SIZEOF
);
509 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
510 "UCR-61S2B init command failed: %s (%ld)",
511 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
513 ioerr
= psdDoPipe(inpp
, &umscsw
, UMSCSW_SIZEOF
);
516 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
517 "UCR-61S2B init status failed: %s (%ld)",
518 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
532 if(!(patchflags
& PFF_SINGLE_LUN
))
538 psdPipeSetup(pp
, URTF_IN
|URTF_CLASS
|URTF_INTERFACE
,
539 UMSR_GET_MAX_LUN
, 0, ifnum
);
540 ioerr
= psdDoPipe(pp
, &maxlun
, 1);
544 if((retry
> 1) && (ioerr
!= UHIOERR_NAKTIMEOUT
) && (ioerr
!= UHIOERR_TIMEOUT
))
546 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
547 "GET_MAX_LUN failed: %s (%ld), retrying in 0.5secs.",
548 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
551 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
552 "GET_MAX_LUN failed: %s (%ld)",
553 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
556 /*psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
557 "Number of logical units: %ld", (ULONG) maxlun+1);*/
563 if((!(patchflags
& PFF_NO_FALLBACK
)) && (!(patchflags
& PFF_SINGLE_LUN
)))
565 patchflags
|= PFF_SINGLE_LUN
;
566 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
567 "Fallback: Enabling SingleLUN.");
573 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
574 "MaxLUN value %ld does not seem reasonable. Reducing to %ld.", maxlun
, 3);
583 ncm
->ncm_MaxLUN
= maxlun
;
585 /* Find next free unit number */
586 if(ncm
->ncm_UnitNo
== (ULONG
) ~0)
588 unitno
= ncm
->ncm_CUC
->cuc_DefaultUnit
;
589 tmpncm
= (struct NepClassMS
*) nh
->nh_Units
.lh_Head
;
590 while(tmpncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
592 if(tmpncm
->ncm_UnitNo
== unitno
)
595 tmpncm
= (struct NepClassMS
*) nh
->nh_Units
.lh_Head
;
597 tmpncm
= (struct NepClassMS
*) tmpncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
600 ncm
->ncm_UnitNo
= unitno
;
602 ncm
->ncm_CDC
->cdc_PatchFlags
= patchflags
;
608 GM_UNIQUENAME(nStoreConfig
)(ncm
);
609 delayedstore
= FALSE
;
611 psdSafeRawDoFmt(buf
, 64, "massstorage.class<%08lx,%ld>", ncm
, lunnum
);
612 ncm
->ncm_ReadySignal
= SIGB_SINGLE
;
613 ncm
->ncm_ReadySigTask
= FindTask(NULL
);
614 SetSignal(0, SIGF_SINGLE
);
615 subtask
= psdSpawnSubTask(buf
, (APTR
) GM_UNIQUENAME(nMSTask
), ncm
);
618 psdBorrowLocksWait(subtask
, 1UL<<ncm
->ncm_ReadySignal
);
621 //ncm->ncm_ReadySigTask = NULL;
622 //FreeSignal(ncm->ncm_ReadySignal);
623 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
624 "MSD '%s' LUN %ld available through %s unit %ld!",
625 devname
, lunnum
, nh
->nh_DevBase
->np_Library
.lib_Node
.ln_Name
,
631 ncm
->ncm_ReadySigTask
= NULL
;
632 //FreeSignal(ncm->ncm_ReadySignal);
633 /* Get rid of unit structure */
634 /* Well, actually don't. maybe we will be able to get back to it later */
652 /* /// "usbReleaseInterfaceBinding()" */
653 void GM_UNIQUENAME(usbReleaseInterfaceBinding
)(struct NepMSBase
*nh
, struct NepClassMS
*ncm
)
657 struct NepClassMS
*ncmhead
;
659 KPRINTF(1, ("nepMSReleaseInterfaceBinding(%08lx)\n", ncm
));
660 if((ps
= OpenLibrary("poseidon.library", 4)))
665 Signal(ncm
->ncm_GUITask
, SIGBREAKF_CTRL_C
);
668 psdGetAttrs(PGA_DEVICE
, ncm
->ncm_Device
, DA_ProductName
, &devname
, TAG_END
);
670 ncm
= (struct NepClassMS
*) nh
->nh_Units
.lh_Head
;
671 while(ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
673 KPRINTF(10, ("ncm = %08lx, ncmhead = %08lx, unit0 = %08lx\n", ncm
, ncmhead
, ncm
->ncm_UnitLUN0
));
674 if((ncm
->ncm_UnitLUN0
== ncmhead
) && (ncm
->ncm_Task
))
676 /*ncm->ncm_UnitLUN0 = NULL;*/
678 ncm
->ncm_ReadySignal
= SIGB_SINGLE
;
679 ncm
->ncm_ReadySigTask
= FindTask(NULL
);
680 ncm
->ncm_DenyRequests
= TRUE
;
683 Signal(ncm
->ncm_Task
, SIGBREAKF_CTRL_C
);
688 psdBorrowLocksWait(ncm
->ncm_Task
, 1UL<<ncm
->ncm_ReadySignal
);
690 //FreeSignal(ncm->ncm_ReadySignal);
692 ncm
= (struct NepClassMS
*) ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
694 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
695 "'%s' retreated, pitiful coward.",
702 /* /// "usbGetAttrsA()" */
703 AROS_LH3(LONG
, usbGetAttrsA
,
704 AROS_LHA(ULONG
, type
, D0
),
705 AROS_LHA(APTR
, usbstruct
, A0
),
706 AROS_LHA(struct TagItem
*, tags
, A1
),
707 LIBBASETYPEPTR
, nh
, 5, massstorage
)
714 KPRINTF(1, ("nepMSGetAttrsA(%ld, %08lx, %08lx)\n", type
, usbstruct
, tags
));
718 if((ti
= FindTagItem(UCCA_Priority
, tags
)))
720 *((SIPTR
*) ti
->ti_Data
) = 0;
723 if((ti
= FindTagItem(UCCA_Description
, tags
)))
725 *((STRPTR
*) ti
->ti_Data
) = "Supports storage devices via usbscsi.device";
728 if((ti
= FindTagItem(UCCA_HasClassCfgGUI
, tags
)))
730 *((IPTR
*) ti
->ti_Data
) = TRUE
;
733 if((ti
= FindTagItem(UCCA_HasBindingCfgGUI
, tags
)))
735 *((IPTR
*) ti
->ti_Data
) = TRUE
;
738 if((ti
= FindTagItem(UCCA_AfterDOSRestart
, tags
)))
740 *((IPTR
*) ti
->ti_Data
) = FALSE
;
743 if((ti
= FindTagItem(UCCA_UsingDefaultCfg
, tags
)))
745 *((IPTR
*) ti
->ti_Data
) = nh
->nh_DummyNCM
.ncm_UsingDefaultCfg
;
748 if((ti
= FindTagItem(UCCA_SupportsSuspend
, tags
)))
750 *((IPTR
*) ti
->ti_Data
) = TRUE
;
756 if((ti
= FindTagItem(UCBA_UsingDefaultCfg
, tags
)))
758 *((IPTR
*) ti
->ti_Data
) = ((struct NepClassMS
*) usbstruct
)->ncm_UsingDefaultCfg
;
769 /* /// "usbSetAttrsA()" */
770 AROS_LH3(LONG
, usbSetAttrsA
,
771 AROS_LHA(ULONG
, type
, D0
),
772 AROS_LHA(APTR
, usbstruct
, A0
),
773 AROS_LHA(struct TagItem
*, tags
, A1
),
774 LIBBASETYPEPTR
, nh
, 6, massstorage
)
782 /* /// "usbDoMethodA()" */
783 AROS_LH2(IPTR
, usbDoMethodA
,
784 AROS_LHA(ULONG
, methodid
, D0
),
785 AROS_LHA(IPTR
*, methoddata
, A1
),
786 LIBBASETYPEPTR
, nh
, 7, massstorage
)
790 struct NepClassMS
*ncm
;
792 KPRINTF(10, ("Do Method %ld\n", methodid
));
795 case UCM_AttemptInterfaceBinding
:
796 return((IPTR
) GM_UNIQUENAME(usbAttemptInterfaceBinding
)(nh
, (struct PsdInterface
*) methoddata
[0]));
798 case UCM_ForceInterfaceBinding
:
799 return((IPTR
) GM_UNIQUENAME(usbForceInterfaceBinding
)(nh
, (struct PsdInterface
*) methoddata
[0]));
801 case UCM_ReleaseInterfaceBinding
:
802 GM_UNIQUENAME(usbReleaseInterfaceBinding
)(nh
, (struct NepClassMS
*) methoddata
[0]);
805 case UCM_OpenCfgWindow
:
806 return(GM_UNIQUENAME(nOpenBindingCfgWindow
)(nh
, &nh
->nh_DummyNCM
));
808 case UCM_OpenBindingCfgWindow
:
809 return(GM_UNIQUENAME(nOpenBindingCfgWindow
)(nh
, (struct NepClassMS
*) methoddata
[0]));
811 case UCM_ConfigChangedEvent
:
812 GM_UNIQUENAME(nLoadClassConfig
)(nh
);
814 ncm
= (struct NepClassMS
*) nh
->nh_Units
.lh_Head
;
815 while(ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
817 GM_UNIQUENAME(nLoadBindingConfig
)(ncm
);
818 ncm
= (struct NepClassMS
*) ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
823 case UCM_AttemptSuspendDevice
:
824 ncm
= (struct NepClassMS
*) methoddata
[0];
825 ncm
->ncm_Running
= FALSE
;
828 case UCM_AttemptResumeDevice
:
829 ncm
= (struct NepClassMS
*) methoddata
[0];
830 ncm
->ncm_Running
= TRUE
;
831 Signal(ncm
->ncm_Task
, (1L<<ncm
->ncm_TaskMsgPort
->mp_SigBit
));
842 /* /// "nLoadClassConfig()" */
843 BOOL
GM_UNIQUENAME(nLoadClassConfig
)(struct NepMSBase
*nh
)
845 struct NepClassMS
*ncm
= &nh
->nh_DummyNCM
;
847 struct ClsDevCfg
*cdc
;
848 struct ClsUnitCfg
*cuc
;
849 struct PsdIFFContext
*pic
;
851 KPRINTF(10, ("Loading Class Config...\n"));
856 if(!(ps
= OpenLibrary("poseidon.library", 4)))
862 /* Create default config */
864 cdc
->cdc_ChunkID
= AROS_LONG2BE(MAKE_ID('M','S','D','C'));
865 cdc
->cdc_Length
= AROS_LONG2BE(sizeof(struct ClsDevCfg
)-8);
866 cdc
->cdc_NakTimeout
= DEF_NAKTIMEOUT
;
867 cdc
->cdc_PatchFlags
= PFF_MODE_XLATE
|PFF_NO_RESET
|PFF_FIX_INQ36
|PFF_SIMPLE_SCSI
;
868 cdc
->cdc_FATDosType
= 0x46415400;
869 cdc
->cdc_StartupDelay
= 0;
870 cdc
->cdc_MaxTransfer
= 5;
871 strcpy(cdc
->cdc_FATFSName
, "fat-handler");
872 strcpy(cdc
->cdc_FATControl
, ""); // FIXME
874 cdc
->cdc_CDDosType
= 0x43444653; // FIXME
875 strcpy(cdc
->cdc_CDFSName
, "cdrom-handler"); // FIXME
876 strcpy(cdc
->cdc_CDControl
, ""); // FIXME
877 cdc
->cdc_NTFSDosType
= 0x4e544653; // FIXME
878 strcpy(cdc
->cdc_NTFSName
, "ntfs-handler"); // FIXME
881 cuc
->cuc_ChunkID
= AROS_LONG2BE(MAKE_ID('L','U','N','0'));
882 cuc
->cuc_Length
= AROS_LONG2BE(sizeof(struct ClsUnitCfg
)-8);
883 cuc
->cuc_AutoMountFAT
= TRUE
;
884 strcpy(cuc
->cuc_FATDOSName
, "UMSD");
885 cuc
->cuc_FATBuffers
= 100;
886 cuc
->cuc_AutoMountRDB
= TRUE
;
887 cuc
->cuc_BootRDB
= TRUE
;
888 cuc
->cuc_DefaultUnit
= 0;
889 cuc
->cuc_AutoUnmount
= TRUE
;
890 cuc
->cuc_MountAllFAT
= TRUE
;
891 cuc
->cuc_AutoMountCD
= TRUE
;
893 ncm
->ncm_UsingDefaultCfg
= TRUE
;
894 /* try to load default config */
895 pic
= psdGetClsCfg(GM_UNIQUENAME(libname
));
898 cdc
= psdGetCfgChunk(pic
, AROS_LONG2BE(ncm
->ncm_CDC
->cdc_ChunkID
));
901 CopyMem(((UBYTE
*) cdc
) + 8, ((UBYTE
*) ncm
->ncm_CDC
) + 8, min(AROS_LONG2BE(cdc
->cdc_Length
), AROS_LONG2BE(ncm
->ncm_CDC
->cdc_Length
)));
903 ncm
->ncm_UsingDefaultCfg
= FALSE
;
905 cuc
= psdGetCfgChunk(pic
, AROS_LONG2BE(ncm
->ncm_CUC
->cuc_ChunkID
));
908 CopyMem(((UBYTE
*) cuc
) + 8, ((UBYTE
*) ncm
->ncm_CUC
) + 8, min(AROS_LONG2BE(cuc
->cuc_Length
), AROS_LONG2BE(ncm
->ncm_CUC
->cuc_Length
)));
910 ncm
->ncm_UsingDefaultCfg
= FALSE
;
919 /* /// "nLoadBindingConfig()" */
920 BOOL
GM_UNIQUENAME(nLoadBindingConfig
)(struct NepClassMS
*ncm
)
922 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
924 struct ClsDevCfg
*cdc
;
925 struct ClsUnitCfg
*cuc
;
926 struct PsdIFFContext
*pic
;
928 KPRINTF(10, ("Loading Binding Config...\n"));
933 //GM_UNIQUENAME(nLoadClassConfig)(nh);
934 *ncm
->ncm_CDC
= *nh
->nh_DummyNCM
.ncm_CDC
;
935 *ncm
->ncm_CUC
= *nh
->nh_DummyNCM
.ncm_CUC
;
936 ncm
->ncm_CUC
->cuc_ChunkID
= AROS_LONG2BE(MAKE_ID('L','U','N','0')+ncm
->ncm_UnitLUN
);
937 ncm
->ncm_UsingDefaultCfg
= TRUE
;
939 if(!(ps
= OpenLibrary("poseidon.library", 4)))
946 pic
= psdGetUsbDevCfg(GM_UNIQUENAME(libname
), ncm
->ncm_DevIDString
, ncm
->ncm_IfIDString
);
949 cdc
= psdGetCfgChunk(pic
, AROS_LONG2BE(ncm
->ncm_CDC
->cdc_ChunkID
));
952 CopyMem(((UBYTE
*) cdc
) + 8, ((UBYTE
*) ncm
->ncm_CDC
) + 8, min(AROS_LONG2BE(cdc
->cdc_Length
), AROS_LONG2BE(ncm
->ncm_CDC
->cdc_Length
)));
954 ncm
->ncm_UsingDefaultCfg
= FALSE
;
956 cuc
= psdGetCfgChunk(pic
, AROS_LONG2BE(ncm
->ncm_CUC
->cuc_ChunkID
));
959 CopyMem(((UBYTE
*) cuc
) + 8, ((UBYTE
*) ncm
->ncm_CUC
) + 8, min(AROS_LONG2BE(cuc
->cuc_Length
), AROS_LONG2BE(ncm
->ncm_CUC
->cuc_Length
)));
961 ncm
->ncm_UsingDefaultCfg
= FALSE
;
970 /* /// "nOpenBindingCfgWindow()" */
971 LONG
GM_UNIQUENAME(nOpenBindingCfgWindow
)(struct NepMSBase
*nh
, struct NepClassMS
*ncm
)
974 KPRINTF(10, ("Opening GUI...\n"));
975 if(!(ps
= OpenLibrary("poseidon.library", 4)))
980 if(!ncm
->ncm_GUITask
)
982 if((ncm
->ncm_GUITask
= psdSpawnSubTask(MOD_NAME_STRING
" GUI", GM_UNIQUENAME(nGUITask
), ncm
)))
995 /* /// "nStartRemovableTask()" */
996 BOOL
GM_UNIQUENAME(nStartRemovableTask
)(struct Library
*ps
, struct NepMSBase
*nh
)
998 struct Task
*tmptask
;
999 ObtainSemaphore(&nh
->nh_TaskLock
);
1000 if(nh
->nh_RemovableTask
)
1002 ReleaseSemaphore(&nh
->nh_TaskLock
);
1006 nh
->nh_ReadySignal
= SIGB_SINGLE
;
1007 nh
->nh_ReadySigTask
= FindTask(NULL
);
1008 SetSignal(0, SIGF_SINGLE
);
1009 if((tmptask
= psdSpawnSubTask(MOD_NAME_STRING
" Removable Task", GM_UNIQUENAME(nRemovableTask
), nh
)))
1011 psdBorrowLocksWait(tmptask
, 1UL<<nh
->nh_ReadySignal
);
1013 nh
->nh_ReadySigTask
= NULL
;
1014 //FreeSignal(nh->nh_ReadySignal);
1015 if(nh
->nh_RemovableTask
)
1017 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
1018 "Removable Task started.");
1019 ReleaseSemaphore(&nh
->nh_TaskLock
);
1022 ReleaseSemaphore(&nh
->nh_TaskLock
);
1027 /**************************************************************************/
1030 #define ps ncm->ncm_Base
1032 const STRPTR DeviceTypeStrings
[] =
1035 "Sequential Access",
1048 "Simple Direct Access",
1054 UWORD PrimeTable
[] =
1056 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
1057 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149,
1058 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
1059 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307,
1060 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389,
1061 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467,
1062 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571,
1063 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653,
1064 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751,
1065 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853,
1066 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947,
1067 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033,
1068 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109,
1069 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213,
1070 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
1071 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399,
1072 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481,
1073 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559,
1074 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627,
1075 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733,
1076 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831,
1077 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931,
1078 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 0
1081 /* /// "nHexString()" */
1082 void GM_UNIQUENAME(nHexString
)(UBYTE
*src
, ULONG len
, UBYTE
*buf
)
1084 static char *hexchars
= "0123456789ABCDEF";
1093 *buf
++ = hexchars
[*src
>>4];
1094 *buf
++ = hexchars
[*src
++ & 0xf];
1100 /* /// "nMSTask()" */
1101 AROS_UFH0(void, GM_UNIQUENAME(nMSTask
))
1105 struct NepClassMS
*ncm
;
1111 struct IOStdReq
*ioreq
;
1112 struct IOStdReq
*ioreq2
;
1114 struct SCSICmd scsicmd
;
1115 UBYTE inquirydata
[36];
1118 UBYTE sensedata
[18];
1120 if((ncm
= GM_UNIQUENAME(nAllocMS())))
1123 if(ncm
->ncm_ReadySigTask
)
1125 Signal(ncm
->ncm_ReadySigTask
, 1L<<ncm
->ncm_ReadySignal
);
1129 if(ncm
->ncm_CDC
->cdc_PatchFlags
)
1131 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
1132 "Postconfig patchflags 0x%04lx%s%s%s%s%s%s%s%s%s%s%s%s%s%s.",
1133 ncm
->ncm_CDC
->cdc_PatchFlags
,
1134 (ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_SINGLE_LUN
) ? " SingleLun" : "",
1135 (ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_MODE_XLATE
) ? " ModeXLate" : "",
1136 (ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_EMUL_LARGE_BLK
) ? " EmulLarge" : "",
1137 (ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_REM_SUPPORT
) ? " RemSupport" : "",
1138 (ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_FIX_INQ36
) ? " FixInq36" : "",
1139 (ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DELAY_DATA
) ? " DelayData" : "",
1140 (ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_SIMPLE_SCSI
) ? " SimpleSCSI" : "",
1141 (ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_RESET
) ? " NoReset" : "",
1142 (ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_FAKE_INQUIRY
) ? " FakeInq" : "",
1143 (ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_FIX_CAPACITY
) ? " FixCapacity" : "",
1144 (ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
) ? " NoFallback" : "",
1145 (ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_CSS_BROKEN
) ? " CSSBroken" : "",
1146 (ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_CLEAR_EP
) ? " ClearEP" : "",
1147 (ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
) ? " Debug" : "");
1150 if(ncm
->ncm_CDC
->cdc_StartupDelay
)
1152 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
1153 "Delaying init sequence by %ld00ms.",
1154 ncm
->ncm_CDC
->cdc_StartupDelay
);
1156 psdDelayMS(ncm
->ncm_CDC
->cdc_StartupDelay
*100);
1158 if(!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_RESET
))
1163 if((!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
)) && (!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_RESET
)))
1165 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_NO_RESET
;
1166 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1167 "Fallback: Enabling No Reset.");
1168 GM_UNIQUENAME(nStoreConfig
)(ncm
);
1174 ncm
->ncm_UnitReady
= FALSE
;
1175 ncm
->ncm_Removable
= TRUE
;
1176 ncm
->ncm_DenyRequests
= FALSE
;
1178 scsicmd
.scsi_Data
= (UWORD
*) inquirydata
;
1179 scsicmd
.scsi_Length
= 36;
1180 scsicmd
.scsi_Command
= cmd6
;
1181 scsicmd
.scsi_CmdLength
= 6;
1182 scsicmd
.scsi_Flags
= SCSIF_READ
|SCSIF_AUTOSENSE
|0x80;
1183 scsicmd
.scsi_SenseData
= sensedata
;
1184 scsicmd
.scsi_SenseLength
= 18;
1185 cmd6
[0] = SCSI_INQUIRY
;
1191 if((ioerr
= nScsiDirect(ncm
, &scsicmd
)))
1193 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1194 "SCSI_INQUIRY failed: %ld",
1196 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1197 "Try increasing the startup delay value or fake inquiry.");
1199 CopyMem(&inquirydata
[16], ncm
->ncm_LUNIDStr
, 16);
1200 ncm
->ncm_LUNIDStr
[15] = '\0';
1203 cnt
= strlen(ncm
->ncm_LUNIDStr
);
1206 if(ncm
->ncm_LUNIDStr
[cnt
] == ' ')
1208 ncm
->ncm_LUNIDStr
[cnt
] = '\0';
1214 ncm
->ncm_DeviceType
= inquirydata
[0] & PDT_MASK
;
1215 if(ncm
->ncm_DeviceType
> 0x11)
1217 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Illegal Device Type %02lx", ncm
->ncm_DeviceType
);
1218 ncm
->ncm_DeviceType
= 0;
1220 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Device '%s' is of %s type.", ncm
->ncm_LUNIDStr
, DeviceTypeStrings
[ncm
->ncm_DeviceType
]);
1222 if((ncm
->ncm_DeviceType
== PDT_WORM
) ||
1223 (ncm
->ncm_DeviceType
== PDT_CDROM
))
1225 // assume 2048 byte blocks
1226 ncm
->ncm_BlockSize
= 2048;
1227 ncm
->ncm_BlockShift
= 11;
1228 if(ncm
->ncm_CDC
->cdc_NakTimeout
== DEF_NAKTIMEOUT
)
1230 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Silently increasing NAK Timeout value to 15 seconds for CD/DVD drives...");
1231 ncm
->ncm_CDC
->cdc_NakTimeout
= 150;
1232 GM_UNIQUENAME(nStoreConfig
)(ncm
);
1234 psdSetAttrs(PGA_PIPE
, ncm
->ncm_EP0Pipe
,
1235 PPA_NakTimeout
, TRUE
,
1236 PPA_NakTimeoutTime
, (ncm
->ncm_CDC
->cdc_NakTimeout
+1)*100,
1238 psdSetAttrs(PGA_PIPE
, ncm
->ncm_EPInPipe
,
1239 PPA_NakTimeout
, TRUE
,
1240 PPA_NakTimeoutTime
, ncm
->ncm_CDC
->cdc_NakTimeout
*100,
1242 psdSetAttrs(PGA_PIPE
, ncm
->ncm_EPOutPipe
,
1243 PPA_NakTimeout
, TRUE
,
1244 PPA_NakTimeoutTime
, ncm
->ncm_CDC
->cdc_NakTimeout
*100,
1247 else if(!ncm
->ncm_CDC
->cdc_NakTimeout
)
1249 // that's okay, nak timeout disabled
1251 else if(ncm
->ncm_CDC
->cdc_NakTimeout
< 150)
1253 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "NAK Timeout should be at least 15 seconds for CD/DVD drives!");
1257 if(!(inquirydata
[1] & 0x80))
1259 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Device does not seem to use removable media.");
1260 ncm
->ncm_Removable
= FALSE
;
1261 ncm
->ncm_UnitReady
= TRUE
;
1262 ncm
->ncm_ChangeCount
++;
1267 sigmask
= (1L<<ncm
->ncm_Unit
.unit_MsgPort
.mp_SigBit
)|
1268 (1L<<ncm
->ncm_TaskMsgPort
->mp_SigBit
)|
1270 if(ncm
->ncm_CSType
== MS_UFI_SUBCLASS
)
1272 struct IOStdReq tmpio
;
1273 tmpio
.io_Command
= CMD_START
;
1274 nStartStop(ncm
, &tmpio
);
1277 // if not removable, call it once to trigger mounting...
1278 if(!ncm
->ncm_Removable
)
1280 ncm
->ncm_ForceRTCheck
= TRUE
;
1282 ncm
->ncm_Running
= TRUE
;
1286 if(ncm
->ncm_Removable
|| ncm
->ncm_ForceRTCheck
)
1288 GM_UNIQUENAME(nStartRemovableTask
)(ps
, ncm
->ncm_ClsBase
);
1289 ncm
->ncm_ForceRTCheck
= FALSE
;
1291 while((ioreq
= (struct IOStdReq
*) GetMsg(&ncm
->ncm_Unit
.unit_MsgPort
)))
1293 KPRINTF(5, ("command ioreq: 0x%08lx cmd: %lu len: %ld\n",
1294 ioreq
, ioreq
->io_Command
, ioreq
->io_Length
));
1296 switch(ioreq
->io_Command
)
1298 case TD_GETGEOMETRY
:
1299 nGetGeometry(ncm
, ioreq
);
1300 ReplyMsg((struct Message
*) ioreq
);
1306 nStartStop(ncm
, ioreq
);
1307 ReplyMsg((struct Message
*) ioreq
);
1311 ioreq
->io_Actual
= 0;
1312 case NSCMD_TD_READ64
:
1314 nRead64(ncm
, ioreq
);
1315 ReplyMsg((struct Message
*) ioreq
);
1319 ioreq
->io_Actual
= 0;
1320 case NSCMD_TD_SEEK64
:
1322 nSeek64(ncm
, ioreq
);
1323 ReplyMsg((struct Message
*) ioreq
);
1328 ioreq
->io_Actual
= 0;
1329 case NSCMD_TD_FORMAT64
:
1330 case NSCMD_TD_WRITE64
:
1333 nWrite64(ncm
, ioreq
);
1334 ReplyMsg((struct Message
*) ioreq
);
1338 ioreq
->io_Error
= nScsiDirect(ncm
, ioreq
->io_Data
);
1339 ReplyMsg((struct Message
*) ioreq
);
1343 if((ioreq2
= ncm
->ncm_XFerPending
))
1345 ncm
->ncm_XFerPending
= NULL
;
1346 ioreq2
->io_Error
= IOERR_ABORTED
;
1347 ReplyMsg((struct Message
*) ioreq2
);
1349 /* Reset does a flush too */
1351 ioreq2
= (struct IOStdReq
*) ncm
->ncm_XFerQueue
.lh_Head
;
1352 while(ioreq2
->io_Message
.mn_Node
.ln_Succ
)
1354 Remove((struct Node
*) ioreq2
);
1355 ioreq2
->io_Error
= IOERR_ABORTED
;
1356 ReplyMsg((struct Message
*) ioreq2
);
1357 ioreq2
= (struct IOStdReq
*) ncm
->ncm_XFerQueue
.lh_Head
;
1359 ReplyMsg((struct Message
*) ioreq
);
1363 ioreq
->io_Error
= IOERR_NOCMD
;
1364 ReplyMsg((struct Message
*) ioreq
);
1368 sigs
= Wait(sigmask
);
1369 } while(!(sigs
& SIGBREAKF_CTRL_C
));
1370 ncm
->ncm_DenyRequests
= TRUE
;
1371 /* Device ejected */
1372 ncm
->ncm_UnitReady
= FALSE
;
1373 ncm
->ncm_ChangeCount
++;
1374 ioreq
= (struct IOStdReq
*) ncm
->ncm_DCInts
.lh_Head
;
1375 while(((struct Node
*) ioreq
)->ln_Succ
)
1377 Cause(ioreq
->io_Data
);
1378 ioreq
= (struct IOStdReq
*) ((struct Node
*) ioreq
)->ln_Succ
;
1380 if(!ncm
->ncm_Removable
)
1382 GM_UNIQUENAME(nStartRemovableTask
)(ps
, ncm
->ncm_ClsBase
);
1384 KPRINTF(20, ("Going down the river!\n"));
1385 GM_UNIQUENAME(nFreeMS
)(ncm
);
1391 /* /// "nAllocMS()" */
1392 struct NepClassMS
* GM_UNIQUENAME(nAllocMS
)(void)
1394 struct Task
*thistask
;
1395 struct NepClassMS
*ncm
;
1398 thistask
= FindTask(NULL
);
1399 ncm
= thistask
->tc_UserData
;
1402 if(!(ncm
->ncm_Base
= OpenLibrary("poseidon.library", 4)))
1404 Alert(AG_OpenLib
| AO_Unknown
);
1407 ncm
->ncm_EPInt
= psdFindEndpoint(ncm
->ncm_Interface
, NULL
,
1409 EA_TransferType
, USEAF_INTERRUPT
,
1411 ncm
->ncm_EPIn
= psdFindEndpoint(ncm
->ncm_Interface
, NULL
,
1413 EA_TransferType
, USEAF_BULK
,
1415 ncm
->ncm_EPOut
= psdFindEndpoint(ncm
->ncm_Interface
, NULL
,
1417 EA_TransferType
, USEAF_BULK
,
1419 if(!(ncm
->ncm_EPIn
&& ncm
->ncm_EPOut
))
1421 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "IN or OUT endpoint missing!");
1424 if((!ncm
->ncm_EPInt
) && (ncm
->ncm_TPType
== MS_PROTO_CBI
))
1426 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "INT endpoint missing!");
1429 psdGetAttrs(PGA_ENDPOINT
, ncm
->ncm_EPOut
,
1430 EA_EndpointNum
, &epnum
,
1432 ncm
->ncm_EPIntNum
= epnum
;
1434 psdGetAttrs(PGA_ENDPOINT
, ncm
->ncm_EPIn
,
1435 EA_EndpointNum
, &epnum
,
1437 ncm
->ncm_EPInNum
= epnum
;
1438 psdGetAttrs(PGA_ENDPOINT
, ncm
->ncm_EPOut
,
1439 EA_EndpointNum
, &epnum
,
1441 ncm
->ncm_EPOutNum
= epnum
;
1443 ncm
->ncm_BulkResetBorks
= FALSE
;
1444 ncm
->ncm_GeoChangeCount
= 0xffffffff;
1446 ncm
->ncm_Unit
.unit_MsgPort
.mp_SigBit
= AllocSignal(-1);
1447 ncm
->ncm_Unit
.unit_MsgPort
.mp_SigTask
= thistask
;
1448 ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
1449 ncm
->ncm_Unit
.unit_MsgPort
.mp_Flags
= PA_SIGNAL
;
1450 ncm
->ncm_XFerPending
= NULL
;
1451 if((ncm
->ncm_TaskMsgPort
= CreateMsgPort()))
1453 if((ncm
->ncm_EP0Pipe
= psdAllocPipe(ncm
->ncm_Device
, ncm
->ncm_TaskMsgPort
, NULL
)))
1455 if((ncm
->ncm_EPOutPipe
= psdAllocPipe(ncm
->ncm_Device
, ncm
->ncm_TaskMsgPort
, ncm
->ncm_EPOut
)))
1457 if((ncm
->ncm_EPInPipe
= psdAllocPipe(ncm
->ncm_Device
, ncm
->ncm_TaskMsgPort
, ncm
->ncm_EPIn
)))
1459 if(ncm
->ncm_CDC
->cdc_NakTimeout
)
1461 psdSetAttrs(PGA_PIPE
, ncm
->ncm_EP0Pipe
,
1462 PPA_NakTimeout
, TRUE
,
1463 PPA_NakTimeoutTime
, (ncm
->ncm_CDC
->cdc_NakTimeout
+1)*100,
1465 psdSetAttrs(PGA_PIPE
, ncm
->ncm_EPInPipe
,
1466 PPA_NakTimeout
, TRUE
,
1467 PPA_NakTimeoutTime
, ncm
->ncm_CDC
->cdc_NakTimeout
*100,
1469 psdSetAttrs(PGA_PIPE
, ncm
->ncm_EPOutPipe
,
1470 PPA_NakTimeout
, TRUE
,
1471 PPA_NakTimeoutTime
, ncm
->ncm_CDC
->cdc_NakTimeout
*100,
1474 psdSetAttrs(PGA_PIPE
, ncm
->ncm_EPOutPipe
,
1475 PPA_NoShortPackets
, TRUE
,
1479 if((ncm
->ncm_EPIntPipe
= psdAllocPipe(ncm
->ncm_Device
, ncm
->ncm_TaskMsgPort
, ncm
->ncm_EPInt
)))
1481 if(ncm
->ncm_CDC
->cdc_NakTimeout
)
1483 psdSetAttrs(PGA_PIPE
, ncm
->ncm_EPIntPipe
,
1484 PPA_NakTimeout
, TRUE
,
1485 PPA_NakTimeoutTime
, ncm
->ncm_CDC
->cdc_NakTimeout
*100,
1488 ncm
->ncm_Task
= thistask
;
1492 ncm
->ncm_Task
= thistask
;
1495 psdFreePipe(ncm
->ncm_EPInPipe
);
1497 psdFreePipe(ncm
->ncm_EPOutPipe
);
1499 psdFreePipe(ncm
->ncm_EP0Pipe
);
1501 DeleteMsgPort(ncm
->ncm_TaskMsgPort
);
1503 FreeSignal((LONG
) ncm
->ncm_Unit
.unit_MsgPort
.mp_SigBit
);
1505 CloseLibrary(ncm
->ncm_Base
);
1507 ncm
->ncm_Task
= NULL
;
1508 if(ncm
->ncm_ReadySigTask
)
1510 Signal(ncm
->ncm_ReadySigTask
, 1L<<ncm
->ncm_ReadySignal
);
1516 /* /// "nFreeMS()" */
1517 void GM_UNIQUENAME(nFreeMS
)(struct NepClassMS
*ncm
)
1519 struct IOStdReq
*ioreq
;
1520 /* Disable the message port, messages may still be queued */
1522 ncm
->ncm_Unit
.unit_MsgPort
.mp_Flags
= PA_IGNORE
;
1523 ncm
->ncm_Unit
.unit_MsgPort
.mp_SigTask
= NULL
;
1524 FreeSignal((LONG
) ncm
->ncm_Unit
.unit_MsgPort
.mp_SigBit
);
1525 // get rid of all messages that still have appeared here
1526 while((ioreq
= (struct IOStdReq
*) GetMsg(&ncm
->ncm_Unit
.unit_MsgPort
)))
1528 ioreq
->io_Error
= IOERR_ABORTED
;
1529 ReplyMsg((struct Message
*) ioreq
);
1533 psdFreePipe(ncm
->ncm_EPIntPipe
);
1534 psdFreePipe(ncm
->ncm_EPInPipe
);
1535 psdFreePipe(ncm
->ncm_EPOutPipe
);
1536 psdFreePipe(ncm
->ncm_EP0Pipe
);
1537 DeleteMsgPort(ncm
->ncm_TaskMsgPort
);
1539 psdFreeVec(ncm
->ncm_OneBlock
);
1540 ncm
->ncm_OneBlock
= NULL
;
1541 ncm
->ncm_OneBlockSize
= 0;
1543 CloseLibrary(ncm
->ncm_Base
);
1545 ncm
->ncm_Task
= NULL
;
1546 if(ncm
->ncm_ReadySigTask
)
1548 Signal(ncm
->ncm_ReadySigTask
, 1L<<ncm
->ncm_ReadySignal
);
1553 /* /// "nGetModePage()" */
1554 UBYTE
* nGetModePage(struct NepClassMS
*ncm
, UBYTE page
)
1557 struct SCSICmd scsicmd
;
1558 UBYTE sensedata
[18];
1563 KPRINTF(10, ("page %ld\n", page
));
1565 memset(ncm
->ncm_ModePageBuf
, 0x00, 255);
1566 scsicmd
.scsi_Data
= (UWORD
*) ncm
->ncm_ModePageBuf
;
1567 scsicmd
.scsi_Length
= 255;
1568 scsicmd
.scsi_Command
= cmd6
;
1569 scsicmd
.scsi_CmdLength
= 6;
1570 scsicmd
.scsi_Flags
= SCSIF_READ
|SCSIF_AUTOSENSE
;
1571 scsicmd
.scsi_SenseData
= sensedata
;
1572 scsicmd
.scsi_SenseLength
= 18;
1573 cmd6
[0] = SCSI_MODE_SENSE_6
;
1574 cmd6
[1] = 0x00; /* no block descriptors */
1579 if((ioerr
= nScsiDirect(ncm
, &scsicmd
)))
1581 KPRINTF(10, ("ioerr %ld\n", ioerr
));
1582 pf
= ncm
->ncm_CDC
->cdc_PatchFlags
;
1585 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1586 "SCSI_MODE_SENSE(0x%02lx) failed: %ld",
1589 if((!(pf
& PFF_NO_FALLBACK
)) && (!(pf
& PFF_MODE_XLATE
)) && (ioerr
== HFERR_Phase
))
1591 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_MODE_XLATE
;
1592 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1593 "Fallback: Enabling CMD6->CMD10.");
1594 GM_UNIQUENAME(nStoreConfig
)(ncm
);
1596 else if((!(pf
& PFF_NO_FALLBACK
)) && (pf
& PFF_MODE_XLATE
) && (!(pf
& PFF_SIMPLE_SCSI
)) && (ioerr
== HFERR_Phase
))
1598 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_SIMPLE_SCSI
;
1599 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1600 "Fallback: Enabling Simple SCSI.");
1601 GM_UNIQUENAME(nStoreConfig
)(ncm
);
1605 pf
= ncm
->ncm_CDC
->cdc_PatchFlags
;
1606 res
= ncm
->ncm_ModePageBuf
;
1607 if((scsicmd
.scsi_Actual
< 6) || (scsicmd
.scsi_Actual
< res
[3]+6))
1611 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1612 "SCSI_MODE_SENSE(0x%02lx) failed: only %ld returned",
1613 page
, scsicmd
.scsi_Actual
);
1619 UBYTE hexbuf
[12*3+2];
1620 GM_UNIQUENAME(nHexString
)(res
, 12, hexbuf
);
1621 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "ModePage (%ld) header: %s...", scsicmd
.scsi_Actual
, hexbuf
);
1626 scsicmd
.scsi_Actual
-= res
[3];
1628 res
+= 4; // skip mode header */
1629 scsicmd
.scsi_Actual
-= 4;
1630 if((*res
& 0x3f) != (page
& 0x3f))
1634 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1635 "SCSI_MODE_SENSE(0x%02lx) failed: wrong page 0x%02lx returned",
1640 if(scsicmd
.scsi_Actual
< res
[1])
1644 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1645 "SCSI_MODE_SENSE(0x%02lx) failed: page incomplete",
1652 if(*res
& 0x40) /* subpage mode? */
1661 /* /// "nGetBlockSize()" */
1662 LONG
nGetBlockSize(struct NepClassMS
*ncm
)
1665 struct SCSICmd scsicmd
;
1666 UBYTE sensedata
[18];
1670 scsicmd
.scsi_Data
= (UWORD
*) capacity
;
1671 scsicmd
.scsi_Length
= 8;
1672 scsicmd
.scsi_Command
= cmd10
;
1673 scsicmd
.scsi_CmdLength
= 10;
1674 scsicmd
.scsi_Flags
= SCSIF_READ
|SCSIF_AUTOSENSE
;
1675 scsicmd
.scsi_SenseData
= sensedata
;
1676 scsicmd
.scsi_SenseLength
= 18;
1677 cmd10
[0] = SCSI_DA_READ_CAPACITY
;
1687 if((ioerr
= nScsiDirect(ncm
, &scsicmd
)))
1689 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1690 "SCSI_READ_CAPACITY failed: %ld",
1692 if(!ncm
->ncm_BlockSize
)
1694 ncm
->ncm_Geometry
.dg_SectorSize
= ncm
->ncm_BlockSize
= 512;
1695 ncm
->ncm_BlockShift
= 9;
1698 ncm
->ncm_Geometry
.dg_SectorSize
= ncm
->ncm_BlockSize
= AROS_BE2LONG(capacity
[1]);
1699 ncm
->ncm_BlockShift
= 0;
1700 while((1<<ncm
->ncm_BlockShift
) < ncm
->ncm_BlockSize
)
1702 ncm
->ncm_BlockShift
++;
1704 ncm
->ncm_Geometry
.dg_TotalSectors
= AROS_BE2LONG(capacity
[0])+1;
1710 /* /// "nFakeGeometry()" */
1711 void nFakeGeometry(struct NepClassMS
*ncm
, struct DriveGeometry
*tddg
)
1719 ULONG remblks
= tddg
->dg_TotalSectors
;
1720 UWORD
*primetblptr
= PrimeTable
;
1727 if(!ncm
->ncm_Geometry
.dg_TotalSectors
)
1731 KPRINTF(10, ("Faking geometry for %ld sectors\n", tddg
->dg_TotalSectors
));
1732 //psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Prime factorisation for %ld", remblks);
1733 tddg
->dg_DeviceType
= ncm
->ncm_DeviceType
;
1734 tddg
->dg_Flags
= ncm
->ncm_Removable
? DGF_REMOVABLE
: 0;
1735 tddg
->dg_BufMemType
= MEMF_PUBLIC
;
1736 tddg
->dg_Reserved
= 0;
1739 KPRINTF(10, ("Loop\n"));
1740 // first prime is counted manually
1744 while(!(remblks
& 1))
1756 primetblptr
= PrimeTable
;
1759 // abort if no primes can be found anymore
1762 KPRINTF(10, ("remblks = %ld, curprime=%ld\n", remblks
, curprime
));
1763 if(remblks
% curprime
)
1765 if(remblks
>= curprimesq
)
1770 if(count
[curpos
]) // prime at least once
1773 count
[++curpos
] = 0;
1774 if(curpos
== 31) // end of buffer reached
1782 // use lookup table for the first primes to 2000
1783 curprime
= *primetblptr
++;
1785 // do it the hard way :-(
1788 primes
[curpos
] = curprime
;
1789 curprimesq
= curprime
* curprime
;
1793 remblks
/= curprime
;
1795 } while((remblks
> 1) && (remblks
>= curprime
));
1800 if((remblks
> 1) && curpos
)
1803 primes
[curpos
++] = remblks
;
1805 KPRINTF(10, ("Priming done, %ld different primes\n", curpos
));
1810 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "FakeGeometry: Total number of blocks is a prime number!");
1811 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_FIX_CAPACITY
)
1813 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
)
1815 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
1816 "This is probably due to the Fix Capacity switch being enabled incorrectly. Please check this.");
1819 ncm
->ncm_CDC
->cdc_PatchFlags
&= ~PFF_FIX_CAPACITY
;
1820 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
1821 "Fallback: Disabling Fix Capacity.");
1822 GM_UNIQUENAME(nStoreConfig
)(ncm
);
1823 remblks
= ++tddg
->dg_TotalSectors
;
1826 if(!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
))
1828 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_FIX_CAPACITY
;
1829 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1830 "Fallback: Enabling Fix Capacity.");
1831 GM_UNIQUENAME(nStoreConfig
)(ncm
);
1833 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1834 "Assuming Fix Capacity bug (total blocks instead of last block)!");
1836 remblks
= --tddg
->dg_TotalSectors
;
1841 for(cnt
= 0; cnt
< curpos
; cnt
++)
1843 totfactors
+= count
[cnt
];
1847 // - We want at least blocks per track * heads >= 64
1848 // - We want heads * heads < blocks per track
1849 // - We want blocks per track < cylinders
1850 // - We want heads < 8
1851 // - We want blocks per track < 256
1852 // - The rest goes into cylinders
1853 tddg
->dg_TrackSectors
= 1;
1855 remfact
= tddg
->dg_TotalSectors
;
1859 KPRINTF(10, ("Totfactors %ld\n", totfactors
));
1870 factor
= primes
[cnt
];
1871 if((tddg
->dg_TrackSectors
* factor
< 256) &&
1872 (tddg
->dg_TrackSectors
* factor
< remfact
))
1874 tddg
->dg_TrackSectors
*= factor
;
1877 else if((tddg
->dg_Heads
* factor
<= 16) &&
1878 (tddg
->dg_Heads
* tddg
->dg_Heads
* factor
* factor
< tddg
->dg_TrackSectors
))
1880 tddg
->dg_Heads
*= factor
;
1883 else if((tddg
->dg_Heads
* tddg
->dg_TrackSectors
>= 64) ||
1898 KPRINTF(10, ("Factor=%ld: Cylinders = %ld, Heads=%ld, TrackSectors=%ld, Blocks=%ld\n",
1899 factor
, remfact
, tddg
->dg_Heads
, tddg
->dg_TrackSectors
,
1900 tddg
->dg_TotalSectors
));
1903 KPRINTF(10, ("Final: Cylinders = %ld, Heads=%ld, TrackSectors=%ld, Blocks=%ld\n",
1904 remfact
, tddg
->dg_Heads
, tddg
->dg_TrackSectors
,
1905 tddg
->dg_TotalSectors
));
1907 tddg
->dg_Cylinders
= remfact
;
1908 tddg
->dg_CylSectors
= tddg
->dg_TrackSectors
* tddg
->dg_Heads
;
1918 #define SERVICEACTION_CAPACITY16 0x10
1920 /* /// "nGetGeometry()" */
1921 LONG
nGetGeometry(struct NepClassMS
*ncm
, struct IOStdReq
*ioreq
)
1923 struct DriveGeometry
*tddg
;
1926 struct SCSICmd scsicmd
;
1927 struct CapacityData capacitydata
;
1928 UBYTE sensedata
[18];
1932 BOOL gotblks
= FALSE
;
1933 BOOL gotcyl
= FALSE
;
1934 BOOL gotheads
= FALSE
;
1935 BOOL gotsect
= FALSE
;
1936 BOOL gotcylsect
= FALSE
;
1937 KPRINTF(10, ("\n"));
1939 ioreq
->io_Error
= 0;
1940 ioreq
->io_Actual
= 0;
1941 tddg
= (struct DriveGeometry
*) ioreq
->io_Data
;
1944 ioreq
->io_Error
= TDERR_NotSpecified
;
1945 return(ioreq
->io_Error
);
1947 length
= min(ioreq
->io_Length
,sizeof(struct DriveGeometry
));
1948 if((ncm
->ncm_GeoChangeCount
== ncm
->ncm_ChangeCount
) && ncm
->ncm_Geometry
.dg_TotalSectors
)
1951 memcpy(tddg
,&ncm
->ncm_Geometry
, (size_t) length
);
1952 ioreq
->io_Actual
= length
;
1956 ncm
->ncm_Geometry
.dg_DeviceType
= ncm
->ncm_DeviceType
;
1957 ncm
->ncm_Geometry
.dg_Flags
= ncm
->ncm_Removable
? DGF_REMOVABLE
: 0;
1960 * Capacity10, 32bit Sectorcount
1962 scsicmd
.scsi_Data
= (UWORD
*) &capacitydata
;
1963 scsicmd
.scsi_Length
= sizeof(capacitydata
);
1964 scsicmd
.scsi_Command
= cmd10
;
1965 scsicmd
.scsi_CmdLength
= 10;
1966 scsicmd
.scsi_Flags
= SCSIF_READ
|SCSIF_AUTOSENSE
;
1967 scsicmd
.scsi_SenseData
= sensedata
;
1968 scsicmd
.scsi_SenseLength
= 18;
1969 cmd10
[0] = SCSI_DA_READ_CAPACITY
;
1980 if((ioerr
= nScsiDirect(ncm
, &scsicmd
)))
1982 KPRINTF(10, ("ioerr %ld\n",ioerr
));
1983 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1984 "SCSI_READ_CAPACITY failed: %ld",
1987 * memset(tddg,0,Length);
1988 * The error should be enough
1990 return(ioreq
->io_Error
= ioerr
);
1993 * 32Bit Totalsectors
1996 ncm
->ncm_BlockSize
= ncm
->ncm_Geometry
.dg_SectorSize
= AROS_BE2LONG(capacitydata
.SectorSize
);
1997 ncm
->ncm_Geometry
.dg_TotalSectors
= AROS_BE2LONG(capacitydata
.SectorCount
) + 1;
1998 if(capacitydata
.SectorCount
== 0xffffffff)
2000 ncm
->ncm_Geometry
.dg_TotalSectors
--; // set to maximum
2001 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2002 "Capacity exceeds the maximum supported for 32 bit sector counts (usually >2TB)!");
2003 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2004 "I/O operations will still work, but geometry and partitioning will be unreliable!");
2006 KPRINTF(10, ("blocksize %ld totalsectors %ld\n", ncm
->ncm_BlockSize
, ncm
->ncm_Geometry
.dg_TotalSectors
));
2008 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
2010 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
2011 "Capacity: %ld blocks of %ld bytes", ncm
->ncm_Geometry
.dg_TotalSectors
, ncm
->ncm_Geometry
.dg_SectorSize
);
2013 ncm
->ncm_BlockShift
= 0;
2014 while((1<<ncm
->ncm_BlockShift
) < ncm
->ncm_BlockSize
)
2016 ncm
->ncm_BlockShift
++;
2019 KPRINTF(10, ("PatchFlags 0x%lx DeviceType %ld\n",ncm
->ncm_CDC
->cdc_PatchFlags
,ncm
->ncm_DeviceType
));
2021 if(!((ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_SIMPLE_SCSI
) ||
2022 (ncm
->ncm_DeviceType
== PDT_WORM
) ||
2023 (ncm
->ncm_DeviceType
== PDT_CDROM
)))
2025 KPRINTF(10, ("SIMPLE_SCSI or PDT_WORM/CDROM\n"));
2026 // cd roms don't have valid or sensible capacity mode pages
2027 if((mpdata
= nGetModePage(ncm
, 0x03)))
2029 if((tmpval
= (mpdata
[10]<<8)+mpdata
[11]))
2031 ncm
->ncm_Geometry
.dg_TrackSectors
= tmpval
;
2033 if(!ncm
->ncm_Geometry
.dg_Cylinders
)
2035 ncm
->ncm_Geometry
.dg_Cylinders
= ncm
->ncm_Geometry
.dg_TotalSectors
;
2038 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
2040 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
2041 "Capacity: TrackSectors=%ld",
2042 ncm
->ncm_Geometry
.dg_TrackSectors
);
2047 * Cylinder and co are only defined for old 32Bit Totalsectors.
2048 * >2TB they have no meaning anyway, so they are calculated based
2051 // recheck, could have simple scsi enabled in the meanwhile
2052 if(!((ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_SIMPLE_SCSI
) ||
2053 (ncm
->ncm_DeviceType
== PDT_WORM
) ||
2054 (ncm
->ncm_DeviceType
== PDT_CDROM
)))
2056 KPRINTF(10, ("recheck1 SIMPLE_SCSI or PDT_WORM/CDROM\n"));
2057 if((mpdata
= nGetModePage(ncm
, 0x04)))
2059 if((tmpval
= (mpdata
[2]<<16)+(mpdata
[3]<<8)+mpdata
[4]))
2061 ncm
->ncm_Geometry
.dg_Cylinders
= tmpval
;
2062 ncm
->ncm_Geometry
.dg_Heads
= mpdata
[5];
2063 gotcyl
= gotheads
= TRUE
;
2065 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
2067 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
2068 "Capacity: Cylinders=%ld, Heads=%ld",
2069 ncm
->ncm_Geometry
.dg_Cylinders
, ncm
->ncm_Geometry
.dg_Heads
);
2073 // recheck, could have simple scsi enabled in the meanwhile
2074 if(!((ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_SIMPLE_SCSI
) ||
2075 (ncm
->ncm_DeviceType
== PDT_WORM
) ||
2076 (ncm
->ncm_DeviceType
== PDT_CDROM
)))
2078 KPRINTF(10, ("recheck2 SIMPLE_SCSI or PDT_WORM/CDROM\n"));
2079 if((mpdata
= nGetModePage(ncm
, 0x05)))
2081 if((tmpval
= (mpdata
[8]<<8)+mpdata
[9]))
2083 ncm
->ncm_Geometry
.dg_Cylinders
= tmpval
;
2084 ncm
->ncm_Geometry
.dg_Heads
= mpdata
[4];
2085 ncm
->ncm_Geometry
.dg_TrackSectors
= mpdata
[5];
2087 gotcyl
= gotheads
= gotsect
= TRUE
;
2091 ncm
->ncm_BlockSize
= ncm
->ncm_Geometry
.dg_SectorSize
= (mpdata
[6]<<8)+mpdata
[7];
2092 ncm
->ncm_BlockShift
= 0;
2093 while((1<<ncm
->ncm_BlockShift
) < ncm
->ncm_BlockSize
)
2095 ncm
->ncm_BlockShift
++;
2097 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
2099 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
2100 "Capacity: %ld blocks of %ld bytes", ncm
->ncm_Geometry
.dg_TotalSectors
, ncm
->ncm_BlockSize
);
2103 else if(ncm
->ncm_BlockSize
!= (mpdata
[6]<<8)+mpdata
[7])
2105 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2106 "Inconsistent block size information %ld != %ld!",
2107 ncm
->ncm_BlockSize
, (mpdata
[6]<<8)+mpdata
[7]);
2109 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
2111 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
2112 "Capacity: Cylinders=%ld, Heads=%ld, TrackSectors=%ld",
2113 ncm
->ncm_Geometry
.dg_Cylinders
, ncm
->ncm_Geometry
.dg_Heads
, ncm
->ncm_Geometry
.dg_TrackSectors
);
2118 // missing total blocks?
2119 if((!gotblks
) && gotcyl
&& gotheads
&& gotsect
)
2121 ncm
->ncm_Geometry
.dg_TotalSectors
= ncm
->ncm_Geometry
.dg_Cylinders
* ncm
->ncm_Geometry
.dg_Heads
* ncm
->ncm_Geometry
.dg_TrackSectors
;
2124 // missing cylinders?
2125 if(gotblks
&& (!gotcyl
) && gotheads
&& gotsect
)
2127 ncm
->ncm_Geometry
.dg_Cylinders
= ncm
->ncm_Geometry
.dg_TotalSectors
/ (ncm
->ncm_Geometry
.dg_Heads
* ncm
->ncm_Geometry
.dg_TrackSectors
);
2131 if(gotblks
&& gotcyl
&& (!gotheads
) && gotsect
)
2133 ncm
->ncm_Geometry
.dg_Heads
= ncm
->ncm_Geometry
.dg_TotalSectors
/ (ncm
->ncm_Geometry
.dg_Cylinders
* ncm
->ncm_Geometry
.dg_TrackSectors
);
2136 // missing tracks per sector
2137 if(gotblks
&& gotcyl
&& gotheads
&& (!gotsect
))
2139 ncm
->ncm_Geometry
.dg_TrackSectors
= ncm
->ncm_Geometry
.dg_TotalSectors
/ (ncm
->ncm_Geometry
.dg_Cylinders
* ncm
->ncm_Geometry
.dg_Heads
);
2143 if(gotblks
&& gotcyl
&& gotheads
&& gotsect
&&
2144 (ncm
->ncm_Geometry
.dg_Cylinders
* ncm
->ncm_Geometry
.dg_TrackSectors
* ncm
->ncm_Geometry
.dg_Heads
== ncm
->ncm_Geometry
.dg_TotalSectors
- 1) &&
2145 (!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_FIX_CAPACITY
)))
2147 if(!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
))
2149 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_FIX_CAPACITY
;
2150 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2151 "Fallback: Enabling Fix Capacity.");
2152 GM_UNIQUENAME(nStoreConfig
)(ncm
);
2153 ncm
->ncm_Geometry
.dg_TotalSectors
--;
2155 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2156 "Fix Capacity is probably needed for this device. Please check this.");
2159 else if(gotblks
&& gotcyl
&& gotheads
&& gotsect
&&
2160 (ncm
->ncm_Geometry
.dg_Cylinders
* ncm
->ncm_Geometry
.dg_TrackSectors
* ncm
->ncm_Geometry
.dg_Heads
== ncm
->ncm_Geometry
.dg_TotalSectors
+ 1) &&
2161 ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_FIX_CAPACITY
)
2163 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
)
2165 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2166 "Fix Capacity is probably enabled incorrectly. Please check this.");
2168 ncm
->ncm_CDC
->cdc_PatchFlags
&= ~PFF_FIX_CAPACITY
;
2169 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2170 "Fallback: Disabling Fix Capacity.");
2171 GM_UNIQUENAME(nStoreConfig
)(ncm
);
2172 ncm
->ncm_Geometry
.dg_TotalSectors
++;
2176 // some devices report these bogus values regardless of actual device capacity, though the total number of blocks is correct.
2177 if(((ncm
->ncm_Geometry
.dg_Cylinders
== 500) && (ncm
->ncm_Geometry
.dg_TrackSectors
== 32) && (ncm
->ncm_Geometry
.dg_Heads
== 8)) ||
2178 ((ncm
->ncm_Geometry
.dg_Cylinders
== 16383) && (ncm
->ncm_Geometry
.dg_TrackSectors
== 63) && (ncm
->ncm_Geometry
.dg_Heads
== 16)))
2180 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Firmware returns known bogus geometry, will fall back to faked geometry!");
2181 gotheads
= gotcyl
= gotsect
= FALSE
;
2182 if((ncm
->ncm_CDC
->cdc_PatchFlags
& (PFF_SIMPLE_SCSI
|PFF_NO_FALLBACK
)) == PFF_SIMPLE_SCSI
)
2184 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_SIMPLE_SCSI
;
2185 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2186 "Fallback: Enabling Simple SCSI.");
2187 GM_UNIQUENAME(nStoreConfig
)(ncm
);
2191 // missing more than one?
2192 if(gotblks
&& (!(gotheads
&& gotcyl
&& gotsect
)))
2194 nFakeGeometry(ncm
, &ncm
->ncm_Geometry
);
2198 ncm
->ncm_Geometry
.dg_CylSectors
= ncm
->ncm_Geometry
.dg_TrackSectors
* ncm
->ncm_Geometry
.dg_Heads
;
2201 if(ncm
->ncm_Geometry
.dg_Cylinders
* ncm
->ncm_Geometry
.dg_CylSectors
!= ncm
->ncm_Geometry
.dg_TotalSectors
)
2203 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2204 "Estimated Geometry yields %ld less total blocks %ld: Cylinders=%ld, CylSectors=%ld, Heads=%ld, TrackSectors=%ld, Blocks=%ld",
2205 ncm
->ncm_Geometry
.dg_TotalSectors
- ncm
->ncm_Geometry
.dg_Cylinders
* ncm
->ncm_Geometry
.dg_CylSectors
,
2206 ncm
->ncm_Geometry
.dg_Cylinders
* ncm
->ncm_Geometry
.dg_CylSectors
,
2207 ncm
->ncm_Geometry
.dg_Cylinders
, ncm
->ncm_Geometry
.dg_CylSectors
, ncm
->ncm_Geometry
.dg_Heads
, ncm
->ncm_Geometry
.dg_TrackSectors
,
2208 ncm
->ncm_Geometry
.dg_TotalSectors
);
2210 else if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
2212 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
2213 "Capacity: Cylinders=%ld, CylSectors=%ld, Heads=%ld, TrackSectors=%ld, Blocks=%ld, SectorSize=%ld",
2214 ncm
->ncm_Geometry
.dg_Cylinders
, ncm
->ncm_Geometry
.dg_CylSectors
, ncm
->ncm_Geometry
.dg_Heads
, ncm
->ncm_Geometry
.dg_TrackSectors
,
2215 ncm
->ncm_Geometry
.dg_TotalSectors
, ncm
->ncm_Geometry
.dg_SectorSize
);
2218 ncm
->ncm_Geometry
.dg_BufMemType
= MEMF_PUBLIC
;
2219 ncm
->ncm_Geometry
.dg_Reserved
= 0;
2220 memcpy(tddg
, &ncm
->ncm_Geometry
, (size_t) length
);
2221 ioreq
->io_Actual
= length
;
2222 ncm
->ncm_GeoChangeCount
= ncm
->ncm_ChangeCount
;
2223 return(ioreq
->io_Error
);
2227 /* /// "nStartStop()" */
2228 LONG
nStartStop(struct NepClassMS
*ncm
, struct IOStdReq
*ioreq
)
2231 struct SCSICmd scsicmd
;
2232 UBYTE sensedata
[18];
2235 if((ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_SIMPLE_SCSI
)
2236 && ioreq
->io_Command
!= TD_EJECT
)
2238 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Simple SCSI: Ignoring START_STOP_UNIT command");
2241 scsicmd
.scsi_Data
= NULL
;
2242 scsicmd
.scsi_Length
= 0;
2243 scsicmd
.scsi_Command
= cmd6
;
2244 scsicmd
.scsi_CmdLength
= 6;
2245 scsicmd
.scsi_Flags
= SCSIF_AUTOSENSE
|0x80;
2246 scsicmd
.scsi_SenseData
= sensedata
;
2247 scsicmd
.scsi_SenseLength
= 18;
2248 cmd6
[0] = SCSI_DA_START_STOP_UNIT
;
2252 switch(ioreq
->io_Command
)
2263 cmd6
[4] = ioreq
->io_Length
? 0x02 : 0x03;
2267 if((ioerr
= nScsiDirect(ncm
, &scsicmd
)))
2269 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2270 "START_STOP_UNIT failed: %ld",
2272 ioreq
->io_Error
= TDERR_NotSpecified
;
2274 return(ioreq
->io_Error
);
2278 /* /// "nRead64Emul()" */
2279 LONG
nRead64Emul(struct NepClassMS
*ncm
, struct IOStdReq
*ioreq
)
2282 ULONG
*cmd10sb
= (ULONG
*)&cmd10
[2];
2283 UBYTE sensedata
[18];
2284 ULONG dataoffset
= 0;
2285 ULONG dataremain
= ioreq
->io_Length
;
2288 ULONG maxtrans
= 1UL<<(ncm
->ncm_CDC
->cdc_MaxTransfer
+16);
2289 ULONG insideblockoffset
;
2290 struct SCSICmd scsicmd
;
2292 if(dataremain
& 511)
2294 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2295 "Attempt to read partial block (%ld %% %ld != 0)!",
2296 dataremain
, ncm
->ncm_BlockSize
);
2297 ioreq
->io_Actual
= 0;
2298 return(ioreq
->io_Error
= IOERR_BADLENGTH
);
2300 if(ioreq
->io_Offset
& 511)
2302 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2303 "Attempt to read unaligned block (%ld %% %ld != 0)!",
2304 ioreq
->io_Offset
, ncm
->ncm_BlockSize
);
2305 ioreq
->io_Actual
= 0;
2306 return(ioreq
->io_Error
= IOERR_BADADDRESS
);
2309 if(!ncm
->ncm_OneBlock
|| (ncm
->ncm_OneBlockSize
< ncm
->ncm_BlockSize
))
2311 psdFreeVec(ncm
->ncm_OneBlock
);
2312 if(!(ncm
->ncm_OneBlock
= psdAllocVec(ncm
->ncm_BlockSize
)))
2314 return(IOERR_BADADDRESS
);
2316 ncm
->ncm_OneBlockSize
= ncm
->ncm_BlockSize
;
2319 startblock
= (ioreq
->io_Offset
>>ncm
->ncm_BlockShift
)|(ioreq
->io_Actual
<<(32-ncm
->ncm_BlockShift
));
2320 insideblockoffset
= (ioreq
->io_Offset
& ((1<<ncm
->ncm_BlockShift
)-1));
2323 KPRINTF(10, ("Reading from block %ld, %ld bytes left...\n", startblock
, dataremain
));
2324 datalen
= dataremain
;
2325 if(datalen
> maxtrans
)
2329 if(insideblockoffset
|| (datalen
< ncm
->ncm_BlockSize
))
2331 if(datalen
> ncm
->ncm_BlockSize
-insideblockoffset
)
2333 datalen
= ncm
->ncm_BlockSize
-insideblockoffset
;
2335 scsicmd
.scsi_Data
= (UWORD
*) ncm
->ncm_OneBlock
;
2336 scsicmd
.scsi_Length
= ncm
->ncm_BlockSize
;
2337 scsicmd
.scsi_Command
= cmd10
;
2338 scsicmd
.scsi_CmdLength
= 10;
2339 scsicmd
.scsi_Flags
= SCSIF_READ
|SCSIF_AUTOSENSE
|0x80;
2340 scsicmd
.scsi_SenseData
= sensedata
;
2341 scsicmd
.scsi_SenseLength
= 18;
2342 cmd10
[0] = SCSI_DA_READ_10
;
2344 *cmd10sb
= AROS_LONG2BE(startblock
);
2349 if((ioreq
->io_Error
= nScsiDirect(ncm
, &scsicmd
)))
2351 KPRINTF(10, ("Read error!\n"));
2354 CopyMemQuick(&ncm
->ncm_OneBlock
[insideblockoffset
], &(((UBYTE
*) ioreq
->io_Data
)[dataoffset
]), datalen
);
2355 insideblockoffset
= 0;
2358 scsicmd
.scsi_Data
= (UWORD
*) &(((UBYTE
*) ioreq
->io_Data
)[dataoffset
]);
2359 scsicmd
.scsi_Length
= datalen
;
2360 scsicmd
.scsi_Command
= cmd10
;
2361 scsicmd
.scsi_CmdLength
= 10;
2362 scsicmd
.scsi_Flags
= SCSIF_READ
|SCSIF_AUTOSENSE
|0x80;
2363 scsicmd
.scsi_SenseData
= sensedata
;
2364 scsicmd
.scsi_SenseLength
= 18;
2365 cmd10
[0] = SCSI_DA_READ_10
;
2367 *cmd10sb
= AROS_LONG2BE(startblock
);
2369 cmd10
[7] = datalen
>>(ncm
->ncm_BlockShift
+8);
2370 cmd10
[8] = datalen
>>ncm
->ncm_BlockShift
;
2372 if((ioreq
->io_Error
= nScsiDirect(ncm
, &scsicmd
)))
2374 KPRINTF(10, ("Read error!\n"));
2377 startblock
+= (insideblockoffset
+datalen
)>>ncm
->ncm_BlockShift
;
2379 dataoffset
+= datalen
;
2380 dataremain
-= datalen
;
2382 ioreq
->io_Actual
= dataoffset
;
2383 return(ioreq
->io_Error
);
2387 /* /// "nWrite64Emul()" */
2388 LONG
nWrite64Emul(struct NepClassMS
*ncm
, struct IOStdReq
*ioreq
)
2391 ULONG
*cmd10sb
= (ULONG
*)&cmd10
[2];
2392 UBYTE sensedata
[18];
2393 ULONG dataoffset
= 0;
2394 ULONG dataremain
= ioreq
->io_Length
;
2397 ULONG maxtrans
= 1UL<<(ncm
->ncm_CDC
->cdc_MaxTransfer
+16);
2398 ULONG insideblockoffset
;
2399 struct SCSICmd scsicmd
;
2401 if(dataremain
& 511)
2403 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2404 "Attempt to write partial block (%ld %% %ld != 0)!",
2405 dataremain
, ncm
->ncm_BlockSize
);
2406 ioreq
->io_Actual
= 0;
2407 return(ioreq
->io_Error
= IOERR_BADLENGTH
);
2409 if(ioreq
->io_Offset
& 511)
2411 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2412 "Attempt to write unaligned block (%ld %% %ld != 0)!",
2413 ioreq
->io_Offset
, ncm
->ncm_BlockSize
);
2414 ioreq
->io_Actual
= 0;
2415 return(ioreq
->io_Error
= IOERR_BADADDRESS
);
2418 if(!ncm
->ncm_OneBlock
|| (ncm
->ncm_OneBlockSize
< ncm
->ncm_BlockSize
))
2420 psdFreeVec(ncm
->ncm_OneBlock
);
2421 if(!(ncm
->ncm_OneBlock
= psdAllocVec(ncm
->ncm_BlockSize
)))
2423 return(IOERR_BADADDRESS
);
2425 ncm
->ncm_OneBlockSize
= ncm
->ncm_BlockSize
;
2428 startblock
= (ioreq
->io_Offset
>>ncm
->ncm_BlockShift
)|(ioreq
->io_Actual
<<(32-ncm
->ncm_BlockShift
));
2429 insideblockoffset
= (ioreq
->io_Offset
& ((1<<ncm
->ncm_BlockShift
)-1));
2432 KPRINTF(10, ("Writing from block %ld, %ld bytes left...\n", startblock
, dataremain
));
2433 datalen
= dataremain
;
2434 if(datalen
> maxtrans
)
2438 if(insideblockoffset
|| (datalen
< ncm
->ncm_BlockSize
))
2440 if(datalen
> ncm
->ncm_BlockSize
-insideblockoffset
)
2442 datalen
= ncm
->ncm_BlockSize
-insideblockoffset
;
2444 scsicmd
.scsi_Data
= (UWORD
*) ncm
->ncm_OneBlock
;
2445 scsicmd
.scsi_Length
= ncm
->ncm_BlockSize
;
2446 scsicmd
.scsi_Command
= cmd10
;
2447 scsicmd
.scsi_CmdLength
= 10;
2448 scsicmd
.scsi_Flags
= SCSIF_READ
|SCSIF_AUTOSENSE
|0x80;
2449 scsicmd
.scsi_SenseData
= sensedata
;
2450 scsicmd
.scsi_SenseLength
= 18;
2451 cmd10
[0] = SCSI_DA_READ_10
;
2453 *cmd10sb
= AROS_LONG2BE(startblock
);
2458 if((ioreq
->io_Error
= nScsiDirect(ncm
, &scsicmd
)))
2460 KPRINTF(10, ("Read error!\n"));
2463 CopyMemQuick(&(((UBYTE
*) ioreq
->io_Data
)[dataoffset
]), &ncm
->ncm_OneBlock
[insideblockoffset
], datalen
);
2465 //scsicmd.scsi_Data = (UWORD *) ncm->ncm_OneBlock;
2466 //scsicmd.scsi_Length = ncm->ncm_BlockSize;
2467 //scsicmd.scsi_Command = cmd10;
2468 //scsicmd.scsi_CmdLength = 10;
2469 scsicmd
.scsi_Flags
= SCSIF_WRITE
|SCSIF_AUTOSENSE
|0x80;
2470 //scsicmd.scsi_SenseData = sensedata;
2471 //scsicmd.scsi_SenseLength = 18;
2472 cmd10
[0] = SCSI_DA_WRITE_10
;
2474 //*((ULONG *) (&cmd10[2])) = AROS_LONG2BE(startblock);
2479 if((ioreq
->io_Error
= nScsiDirect(ncm
, &scsicmd
)))
2481 KPRINTF(10, ("Write error!\n"));
2484 insideblockoffset
= 0;
2487 scsicmd
.scsi_Data
= (UWORD
*) &(((UBYTE
*) ioreq
->io_Data
)[dataoffset
]);
2488 scsicmd
.scsi_Length
= datalen
;
2489 scsicmd
.scsi_Command
= cmd10
;
2490 scsicmd
.scsi_CmdLength
= 10;
2491 scsicmd
.scsi_Flags
= SCSIF_WRITE
|SCSIF_AUTOSENSE
|0x80;
2492 scsicmd
.scsi_SenseData
= sensedata
;
2493 scsicmd
.scsi_SenseLength
= 18;
2494 cmd10
[0] = SCSI_DA_WRITE_10
;
2496 *cmd10sb
= AROS_LONG2BE(startblock
);
2498 cmd10
[7] = datalen
>>(ncm
->ncm_BlockShift
+8);
2499 cmd10
[8] = datalen
>>ncm
->ncm_BlockShift
;
2501 if((ioreq
->io_Error
= nScsiDirect(ncm
, &scsicmd
)))
2503 KPRINTF(10, ("Write error!\n"));
2506 startblock
+= (insideblockoffset
+datalen
)>>ncm
->ncm_BlockShift
;
2508 dataoffset
+= datalen
;
2509 dataremain
-= datalen
;
2511 ioreq
->io_Actual
= dataoffset
;
2512 return(ioreq
->io_Error
);
2516 /* /// "nRead64()" */
2517 LONG
nRead64(struct NepClassMS
*ncm
, struct IOStdReq
*ioreq
)
2521 UBYTE sensedata
[18];
2522 ULONG dataoffset
= 0;
2523 ULONG dataremain
= ioreq
->io_Length
;
2525 ULONG startblockhigh
;
2527 ULONG oldstartblock
;
2528 ULONG maxtrans
= 1UL<<(ncm
->ncm_CDC
->cdc_MaxTransfer
+16);
2529 struct SCSICmd scsicmd
;
2531 if(!ncm
->ncm_BlockSize
)
2535 if((((dataremain
>> ncm
->ncm_BlockShift
)<<ncm
->ncm_BlockShift
) != dataremain
) ||
2536 (((ioreq
->io_Offset
>> ncm
->ncm_BlockShift
)<<ncm
->ncm_BlockShift
) != ioreq
->io_Offset
))
2538 KPRINTF(20, ("unaligned read access offset %ld, length %ld...\n", ioreq
->io_Offset
, dataremain
));
2539 if((!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_EMUL_LARGE_BLK
)) && (!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
)))
2541 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_EMUL_LARGE_BLK
;
2542 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2543 "Fallback: Enabling emulation for large block devices.");
2544 GM_UNIQUENAME(nStoreConfig
)(ncm
);
2546 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_EMUL_LARGE_BLK
)
2548 return(nRead64Emul(ncm
, ioreq
));
2550 if((dataremain
>> ncm
->ncm_BlockShift
)<<ncm
->ncm_BlockShift
!= dataremain
)
2552 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2553 "Attempt to read partial block (%ld %% %ld != 0)!",
2554 dataremain
, ncm
->ncm_BlockSize
);
2555 ioreq
->io_Error
= IOERR_BADLENGTH
;
2557 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2558 "Attempt to read unaligned block (%ld %% %ld != 0)!",
2559 ioreq
->io_Offset
, ncm
->ncm_BlockSize
);
2560 ioreq
->io_Error
= IOERR_BADADDRESS
;
2562 if(ncm
->ncm_BlockSize
!= 512)
2564 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2565 "The used FileSystem or other software must support %ld byte blocks!",
2566 ncm
->ncm_BlockSize
);
2568 ioreq
->io_Actual
= 0;
2569 return(ioreq
->io_Error
);
2572 startblockhigh
= ioreq
->io_Actual
>>ncm
->ncm_BlockShift
;
2573 startblock
= (ioreq
->io_Offset
>>ncm
->ncm_BlockShift
)|(ioreq
->io_Actual
<<(32-ncm
->ncm_BlockShift
));
2576 KPRINTF(10, ("Reading from block %ld, %ld bytes left...\n", startblock
, dataremain
));
2577 datalen
= dataremain
;
2578 if(datalen
> maxtrans
)
2582 scsicmd
.scsi_Data
= (UWORD
*) &(((UBYTE
*) ioreq
->io_Data
)[dataoffset
]);
2583 scsicmd
.scsi_Length
= datalen
;
2584 scsicmd
.scsi_Flags
= SCSIF_READ
|SCSIF_AUTOSENSE
|0x80;
2585 scsicmd
.scsi_SenseData
= sensedata
;
2586 scsicmd
.scsi_SenseLength
= 18;
2589 ULONG
*cmd16sbh
= (ULONG
*)&cmd16
[2];
2590 ULONG
*cmd16sbl
= (ULONG
*)&cmd16
[6];
2591 // Arithmetics for >2 TB needed
2592 scsicmd
.scsi_Command
= cmd16
;
2593 scsicmd
.scsi_CmdLength
= 16;
2594 cmd16
[0] = SCSI_DA_READ_16
;
2596 *cmd16sbh
= AROS_LONG2BE(startblockhigh
);
2597 *cmd16sbl
= AROS_LONG2BE(startblock
);
2598 cmd16
[10] = datalen
>>(ncm
->ncm_BlockShift
+24);
2599 cmd16
[11] = datalen
>>(ncm
->ncm_BlockShift
+16);
2600 cmd16
[12] = datalen
>>(ncm
->ncm_BlockShift
+8);
2601 cmd16
[13] = datalen
>>ncm
->ncm_BlockShift
;
2605 ULONG
*cmd10sb
= (ULONG
*)&cmd10
[2];
2606 scsicmd
.scsi_Command
= cmd10
;
2607 scsicmd
.scsi_CmdLength
= 10;
2608 cmd10
[0] = SCSI_DA_READ_10
;
2610 *cmd10sb
= AROS_LONG2BE(startblock
);
2612 cmd10
[7] = datalen
>>(ncm
->ncm_BlockShift
+8);
2613 cmd10
[8] = datalen
>>ncm
->ncm_BlockShift
;
2616 if((ioreq
->io_Error
= nScsiDirect(ncm
, &scsicmd
)))
2618 KPRINTF(10, ("Read error!\n"));
2621 dataoffset
+= datalen
;
2622 dataremain
-= datalen
;
2623 oldstartblock
= startblock
;
2624 startblock
+= datalen
>>ncm
->ncm_BlockShift
;
2625 if(startblock
< oldstartblock
)
2627 // wrap around occurred
2631 ioreq
->io_Actual
= dataoffset
;
2632 return(ioreq
->io_Error
);
2636 /* /// "nSeek64()" */
2637 LONG
nSeek64(struct NepClassMS
*ncm
, struct IOStdReq
*ioreq
)
2640 ULONG
*cmd10sb
= (ULONG
*)&cmd10
[2];
2641 UBYTE sensedata
[18];
2642 struct SCSICmd scsicmd
;
2645 if(!ncm
->ncm_BlockSize
)
2649 if(((ioreq
->io_Offset
>> ncm
->ncm_BlockShift
)<<ncm
->ncm_BlockShift
) != ioreq
->io_Offset
)
2651 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2652 "Attempt to to seek to unaligned block (%ld %% %ld != 0)!",
2653 ioreq
->io_Offset
, ncm
->ncm_BlockSize
);
2654 if(ncm
->ncm_BlockSize
!= 512)
2656 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2657 "The used FileSystem or other software must support %ld byte blocks!",
2658 ncm
->ncm_BlockSize
);
2660 ioreq
->io_Actual
= 0;
2661 return(ioreq
->io_Error
= IOERR_BADADDRESS
);
2664 startblock
= (ioreq
->io_Offset
>>ncm
->ncm_BlockShift
)|(ioreq
->io_Actual
<<(32-ncm
->ncm_BlockShift
));
2665 scsicmd
.scsi_Data
= NULL
;
2666 scsicmd
.scsi_Length
= 0;
2667 scsicmd
.scsi_CmdLength
= 10;
2668 scsicmd
.scsi_Flags
= SCSIF_READ
|SCSIF_AUTOSENSE
|0x80;
2669 scsicmd
.scsi_SenseData
= sensedata
;
2670 scsicmd
.scsi_SenseLength
= 18;
2671 cmd10
[0] = SCSI_DA_SEEK_10
;
2673 *cmd10sb
= AROS_LONG2BE(startblock
);
2678 if((ioreq
->io_Error
= nScsiDirect(ncm
, &scsicmd
)))
2680 KPRINTF(10, ("Seek error!\n"));
2682 ioreq
->io_Actual
= 0;
2683 return(ioreq
->io_Error
);
2687 /* /// "nWrite64()" */
2688 LONG
nWrite64(struct NepClassMS
*ncm
, struct IOStdReq
*ioreq
)
2692 UBYTE sensedata
[18];
2693 ULONG dataoffset
= 0;
2694 ULONG dataremain
= ioreq
->io_Length
;
2696 ULONG startblockhigh
;
2698 ULONG oldstartblock
;
2699 ULONG maxtrans
= 1UL<<(ncm
->ncm_CDC
->cdc_MaxTransfer
+16);
2700 struct SCSICmd scsicmd
;
2702 if(!ncm
->ncm_BlockSize
)
2706 if(((dataremain
>> ncm
->ncm_BlockShift
)<<ncm
->ncm_BlockShift
!= dataremain
) ||
2707 ((ioreq
->io_Offset
>> ncm
->ncm_BlockShift
)<<ncm
->ncm_BlockShift
!= ioreq
->io_Offset
))
2709 KPRINTF(20, ("unaligned write access offset %ld, length %ld...\n", ioreq
->io_Offset
, dataremain
));
2710 if((!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_EMUL_LARGE_BLK
)) && (!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
)))
2712 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_EMUL_LARGE_BLK
;
2713 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2714 "Fallback: Enabling emulation for large block devices.");
2715 GM_UNIQUENAME(nStoreConfig
)(ncm
);
2717 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_EMUL_LARGE_BLK
)
2719 return(nWrite64Emul(ncm
, ioreq
));
2721 if((dataremain
>> ncm
->ncm_BlockShift
)<<ncm
->ncm_BlockShift
!= dataremain
)
2723 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2724 "Attempt to write partial block (%ld %% %ld != 0)!",
2725 dataremain
, ncm
->ncm_BlockSize
);
2726 ioreq
->io_Error
= IOERR_BADLENGTH
;
2728 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2729 "Attempt to write unaligned block (%ld %% %ld != 0)!",
2730 ioreq
->io_Offset
, ncm
->ncm_BlockSize
);
2731 ioreq
->io_Error
= IOERR_BADADDRESS
;
2733 if(ncm
->ncm_BlockSize
!= 512)
2735 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2736 "The used FileSystem or other software must support %ld byte blocks!",
2737 ncm
->ncm_BlockSize
);
2739 ioreq
->io_Actual
= 0;
2740 return(ioreq
->io_Error
);
2743 startblockhigh
= ioreq
->io_Actual
>>ncm
->ncm_BlockShift
;
2744 startblock
= (ioreq
->io_Offset
>>ncm
->ncm_BlockShift
)|(ioreq
->io_Actual
<<(32-ncm
->ncm_BlockShift
));
2747 datalen
= dataremain
;
2748 if(datalen
> maxtrans
)
2752 scsicmd
.scsi_Data
= (UWORD
*) &(((UBYTE
*) ioreq
->io_Data
)[dataoffset
]);
2753 scsicmd
.scsi_Length
= datalen
;
2754 scsicmd
.scsi_Flags
= SCSIF_WRITE
|SCSIF_AUTOSENSE
|0x80;
2755 scsicmd
.scsi_SenseData
= sensedata
;
2756 scsicmd
.scsi_SenseLength
= 18;
2759 ULONG
*cmd16sbh
= (ULONG
*)&cmd16
[2];
2760 ULONG
*cmd16sbl
= (ULONG
*)&cmd16
[6];
2761 // Arithmetics for >2 TB needed
2762 scsicmd
.scsi_Command
= cmd16
;
2763 scsicmd
.scsi_CmdLength
= 16;
2764 cmd16
[0] = SCSI_DA_WRITE_16
;
2766 *cmd16sbh
= AROS_LONG2BE(startblockhigh
);
2767 *cmd16sbl
= AROS_LONG2BE(startblock
);
2768 cmd16
[10] = datalen
>>(ncm
->ncm_BlockShift
+24);
2769 cmd16
[11] = datalen
>>(ncm
->ncm_BlockShift
+16);
2770 cmd16
[12] = datalen
>>(ncm
->ncm_BlockShift
+8);
2771 cmd16
[13] = datalen
>>ncm
->ncm_BlockShift
;
2775 ULONG
*cmd10sb
= (ULONG
*)&cmd10
[2];
2776 scsicmd
.scsi_Command
= cmd10
;
2777 scsicmd
.scsi_CmdLength
= 10;
2778 cmd10
[0] = SCSI_DA_WRITE_10
;
2780 *cmd10sb
= AROS_LONG2BE(startblock
);
2782 cmd10
[7] = datalen
>>(ncm
->ncm_BlockShift
+8);
2783 cmd10
[8] = datalen
>>ncm
->ncm_BlockShift
;
2786 if((ioreq
->io_Error
= nScsiDirect(ncm
, &scsicmd
)))
2790 dataoffset
+= datalen
;
2791 dataremain
-= datalen
;
2792 oldstartblock
= startblock
;
2793 startblock
+= datalen
>>ncm
->ncm_BlockShift
;
2794 if(startblock
< oldstartblock
)
2796 // wrap around occurred
2800 ioreq
->io_Actual
= dataoffset
;
2801 return(ioreq
->io_Error
);
2805 /* /// "nCBIRequestSense()" */
2806 LONG
nCBIRequestSense(struct NepClassMS
*ncm
, UBYTE
*senseptr
, ULONG datalen
)
2811 struct UsbMSCBIStatusWrapper umscsw
;
2813 memset(sensecmd
, 0, 12);
2814 senseptr
[2] = SK_ILLEGAL_REQUEST
;
2815 sensecmd
[0] = SCSI_REQUEST_SENSE
;
2819 sensecmd
[4] = datalen
;
2821 KPRINTF(2, ("sense command block phase...\n"));
2823 /*psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
2824 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
2825 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);*/
2826 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_CLASS
|URTF_INTERFACE
,
2827 UMSR_ADSC
, 0, (ULONG
) ncm
->ncm_UnitIfNum
);
2828 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, sensecmd
, ((ncm
->ncm_CSType
== MS_ATAPI_SUBCLASS
) ||
2829 (ncm
->ncm_CSType
== MS_FDDATAPI_SUBCLASS
) ||
2830 (ncm
->ncm_CSType
== MS_UFI_SUBCLASS
)) ? (ULONG
) 12 : (ULONG
) 6);
2833 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_CLEAR_EP
)
2835 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
2836 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPInNum
|URTF_IN
);
2837 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
2840 KPRINTF(2, ("sense data phase %ld bytes...\n", datalen
));
2841 ioerr
= psdDoPipe(ncm
->ncm_EPInPipe
, senseptr
, datalen
);
2842 actual
= psdGetPipeActual(ncm
->ncm_EPInPipe
);
2843 if(ioerr
== UHIOERR_STALL
)
2845 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
2846 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPInNum
|URTF_IN
);
2847 psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
2849 if((!ioerr
) || (ioerr
== UHIOERR_RUNTPACKET
))
2851 KPRINTF(2, ("sense command status phase...\n"));
2852 if(ncm
->ncm_TPType
== MS_PROTO_CBI
)
2855 umscsw
.bValue
= USMF_CSW_PHASEERR
;
2856 ioerr
= psdDoPipe(ncm
->ncm_EPIntPipe
, &umscsw
, sizeof(struct UsbMSCBIStatusWrapper
));
2857 if(ioerr
&& (ioerr
!= UHIOERR_RUNTPACKET
))
2859 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2860 "Status interrupt failed: %s (%ld)",
2861 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2864 umscsw
.bValue
&= USMF_CSW_PERSIST
; /* mask out other bits */
2867 umscsw
.bValue
= USMF_CSW_PASS
;
2870 if((!ioerr
) || (ioerr
== UHIOERR_RUNTPACKET
))
2872 KPRINTF(2, ("sense Status:\n"
2873 " Status : %02lx\n",
2877 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2878 "Sense failed: %ld",
2880 if(umscsw
.bValue
== USMF_CSW_PHASEERR
)
2885 switch(senseptr
[2] & SK_MASK
)
2887 case SK_UNIT_ATTENTION
:
2888 if((senseptr
[12] == 0x28) ||
2889 (senseptr
[12] == 0x3A))
2891 ncm
->ncm_ChangeCount
++;
2896 if((ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
) && (senseptr
[2] & SK_MASK
))
2898 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2899 "Request Sense Key %lx/%02lx/%02lx",
2900 senseptr
[2] & SK_MASK
,
2906 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2907 "Sense status failed: %s (%ld)",
2908 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2911 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2912 "Sense data failed: %s (%ld)",
2913 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2916 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2917 "Sense block failed: %s (%ld)",
2918 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2924 /* /// "nBulkReset()" */
2925 LONG
nBulkReset(struct NepClassMS
*ncm
)
2929 static UBYTE cbiresetcmd12
[12] = { 0x1D, 0x04, 0xFF, 0xFF, 0xFF, 0xFF,
2930 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
2931 //struct UsbMSCBIStatusWrapper umscsw;
2932 //UBYTE sensedata[18];
2933 if(ncm
->ncm_DenyRequests
)
2935 return UHIOERR_TIMEOUT
;
2937 KPRINTF(1, ("Bulk Reset\n"));
2938 //psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Bulk Reset...");
2939 switch(ncm
->ncm_TPType
)
2942 if(!ncm
->ncm_BulkResetBorks
)
2944 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_CLASS
|URTF_INTERFACE
,
2945 UMSR_BULK_ONLY_RESET
, 0, (ULONG
) ncm
->ncm_UnitIfNum
);
2946 ioerr2
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
2947 if(ioerr2
== UHIOERR_TIMEOUT
)
2953 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2954 "BULK_ONLY_RESET failed: %s (%ld)",
2955 psdNumToStr(NTS_IOERR
, ioerr2
, "unknown"), ioerr2
);
2956 ncm
->ncm_BulkResetBorks
= TRUE
;
2958 if(ncm
->ncm_DenyRequests
)
2963 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
2964 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPInNum
|URTF_IN
);
2965 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
2968 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2969 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
2970 ncm
->ncm_EPInNum
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2972 if(ncm
->ncm_DenyRequests
)
2976 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
2977 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPOutNum
);
2978 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
2981 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2982 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
2983 ncm
->ncm_EPOutNum
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2985 return(ioerr2
? ioerr2
: ioerr
);
2989 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_CLASS
|URTF_INTERFACE
,
2990 UMSR_ADSC
, 0, (ULONG
) ncm
->ncm_UnitIfNum
);
2991 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, cbiresetcmd12
, 12);
2994 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2995 "CBI_RESET failed: %s (%ld)",
2996 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2998 if(ncm
->ncm_DenyRequests
)
3002 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
3003 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPInNum
|URTF_IN
);
3004 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
3007 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3008 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
3009 ncm
->ncm_EPInNum
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
3011 if(ncm
->ncm_DenyRequests
)
3015 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
3016 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPOutNum
);
3017 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
3020 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3021 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
3022 ncm
->ncm_EPOutNum
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
3024 //nCBIRequestSense(ncm, sensedata, 18);
3031 /* /// "nBulkClear()" */
3032 LONG
nBulkClear(struct NepClassMS
*ncm
)
3035 if(ncm
->ncm_DenyRequests
)
3037 return UHIOERR_TIMEOUT
;
3039 KPRINTF(1, ("Bulk Clear\n"));
3040 //psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Bulk Clear...");
3041 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
3042 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPInNum
|URTF_IN
);
3043 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
3044 if(ioerr
== UHIOERR_TIMEOUT
)
3050 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3051 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
3052 ncm
->ncm_EPInNum
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
3054 if(ncm
->ncm_DenyRequests
)
3058 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
3059 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPOutNum
);
3060 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
3063 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3064 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
3065 ncm
->ncm_EPOutNum
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
3071 /* /// "nScsiDirect()" */
3072 LONG
nScsiDirect(struct NepClassMS
*ncm
, struct SCSICmd
*scsicmd
)
3077 struct SCSICmd scsicmd10
;
3078 BOOL usecmd10
= FALSE
;
3080 UBYTE
*sensedata
= NULL
;
3083 ULONG pf
= ncm
->ncm_CDC
->cdc_PatchFlags
;
3085 scsicmd
->scsi_Actual
= 0;
3086 scsicmd
->scsi_CmdActual
= 0;
3087 scsicmd
->scsi_SenseActual
= 0;
3089 if(((pf
& PFF_MODE_XLATE
) && (scsicmd
->scsi_CmdLength
== 6)) ||
3090 (ncm
->ncm_CSType
== MS_FDDATAPI_SUBCLASS
) ||
3091 (ncm
->ncm_CSType
== MS_ATAPI_SUBCLASS
) ||
3092 (ncm
->ncm_CSType
== MS_UFI_SUBCLASS
))
3097 if(pf
& PFF_SIMPLE_SCSI
)
3099 if(scsicmd
->scsi_Flags
& SCSIF_AUTOSENSE
)
3101 if(scsicmd
->scsi_SenseLength
> 18)
3103 KPRINTF(10, ("Fixing Sense Length to 18!\n"));
3104 scsicmd
->scsi_SenseLength
= 18;
3107 switch(scsicmd
->scsi_Command
[0])
3109 case SCSI_TEST_UNIT_READY
:
3111 //case SCSI_LOG_SELECT:
3112 //case SCSI_LOG_SENSE:
3113 case SCSI_REQUEST_SENSE
:
3114 //case SCSI_MODE_SELECT_6:
3115 //case SCSI_MODE_SELECT_10:
3116 //case SCSI_MODE_SENSE_6:
3117 //case SCSI_MODE_SENSE_10:
3118 case SCSI_DA_READ_6
:
3119 case SCSI_DA_READ_10
:
3120 case SCSI_DA_READ_CAPACITY
:
3121 case SCSI_DA_SEEK_6
:
3122 case SCSI_DA_SEEK_10
:
3123 case SCSI_DA_WRITE_6
:
3124 case SCSI_DA_WRITE_10
:
3127 case SCSI_MODE_SENSE_6
:
3129 UWORD modepage
= scsicmd
->scsi_Command
[2] & 0x3f;
3130 UBYTE
*data
= (UBYTE
*) scsicmd
->scsi_Data
;
3131 if((modepage
== 0x3f) ||
3132 (modepage
== 0x03) ||
3133 (modepage
== 0x04) ||
3136 if(!(ncm
->ncm_BlockSize
&& ncm
->ncm_Geometry
.dg_TotalSectors
))
3140 if(ncm
->ncm_Geometry
.dg_TotalSectors
)
3142 nFakeGeometry(ncm
, &ncm
->ncm_Geometry
);
3143 ncm
->ncm_GeoChangeCount
= ncm
->ncm_ChangeCount
;
3145 memset(data
, 0, (size_t) scsicmd
->scsi_Length
);
3146 scsicmd
->scsi_Status
= SCSI_GOOD
;
3148 if(modepage
== 0x3f) // all available mode pages
3150 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Simple SCSI: Faking All Mode Pages 0x03-0x05");
3151 data
[0] = 3+2+22+2+22+2+30;
3153 scsicmd
->scsi_Actual
= 4;
3154 if(scsicmd
->scsi_Length
>= 4+2+22)
3156 data
[0] = 0x03; // mode page
3157 data
[1] = 22; // page length
3158 data
[10] = ncm
->ncm_Geometry
.dg_TrackSectors
>>8;
3159 data
[11] = ncm
->ncm_Geometry
.dg_TrackSectors
;
3160 data
[12] = ncm
->ncm_Geometry
.dg_SectorSize
>>8;
3161 data
[13] = ncm
->ncm_Geometry
.dg_SectorSize
;
3163 scsicmd
->scsi_Actual
+= 2+22;
3165 if(scsicmd
->scsi_Length
>= 4+2+22+2+22)
3167 data
[0] = 0x04; // mode page
3168 data
[1] = 22; // page length
3169 data
[2] = ncm
->ncm_Geometry
.dg_Cylinders
>>16;
3170 data
[3] = ncm
->ncm_Geometry
.dg_Cylinders
>>8;
3171 data
[4] = ncm
->ncm_Geometry
.dg_Cylinders
;
3172 data
[5] = ncm
->ncm_Geometry
.dg_Heads
;
3174 scsicmd
->scsi_Actual
+= 2+22;
3176 if(scsicmd
->scsi_Length
>= 4+2+22+2+22+2+30)
3178 data
[0] = 0x05; // mode page
3179 data
[1] = 30; // page length
3180 data
[4] = ncm
->ncm_Geometry
.dg_Heads
;
3181 data
[5] = ncm
->ncm_Geometry
.dg_TrackSectors
;
3182 data
[6] = ncm
->ncm_Geometry
.dg_SectorSize
>>8;
3183 data
[7] = ncm
->ncm_Geometry
.dg_SectorSize
;
3184 data
[8] = ncm
->ncm_Geometry
.dg_Cylinders
>>8;
3185 data
[9] = ncm
->ncm_Geometry
.dg_Cylinders
;
3187 scsicmd
->scsi_Actual
+= 2+30;
3191 else if((modepage
== 0x03) && (scsicmd
->scsi_Length
>= 6+22)) // Format Device mode page
3193 // fake geometry request
3194 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Simple SCSI: Faking Mode Page 0x03 (Format Device)");
3196 data
[0] = 5+22; // length
3198 data
[0] = 0x03; // mode page
3199 data
[1] = 22; // page length
3200 data
[10] = ncm
->ncm_Geometry
.dg_TrackSectors
>>8;
3201 data
[11] = ncm
->ncm_Geometry
.dg_TrackSectors
;
3202 data
[12] = ncm
->ncm_Geometry
.dg_SectorSize
>>8;
3203 data
[13] = ncm
->ncm_Geometry
.dg_SectorSize
;
3204 scsicmd
->scsi_Actual
= 6+22;
3207 else if((modepage
== 0x04) && (scsicmd
->scsi_Length
>= 6+22)) // Rigid Disk Geometry mode page
3209 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Simple SCSI: Faking Mode Page 0x04 (Rigid Disk Geometry)");
3210 data
[0] = 5+22; // length
3212 data
[0] = 0x04; // mode page
3213 data
[1] = 22; // page length
3214 data
[2] = ncm
->ncm_Geometry
.dg_Cylinders
>>16;
3215 data
[3] = ncm
->ncm_Geometry
.dg_Cylinders
>>8;
3216 data
[4] = ncm
->ncm_Geometry
.dg_Cylinders
;
3217 data
[5] = ncm
->ncm_Geometry
.dg_Heads
;
3218 scsicmd
->scsi_Actual
= 6+22;
3221 else if((modepage
== 0x05) && (scsicmd
->scsi_Length
>= 6+30)) // Flexible Disk mode page
3223 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Simple SCSI: Faking Mode Page 0x05 (Flexible Disk)");
3224 data
[0] = 5+30; // length
3226 data
[0] = 0x05; // mode page
3227 data
[1] = 30; // page length
3228 data
[4] = ncm
->ncm_Geometry
.dg_Heads
;
3229 data
[5] = ncm
->ncm_Geometry
.dg_TrackSectors
;
3230 data
[6] = ncm
->ncm_Geometry
.dg_SectorSize
>>8;
3231 data
[7] = ncm
->ncm_Geometry
.dg_SectorSize
;
3232 data
[8] = ncm
->ncm_Geometry
.dg_Cylinders
>>8;
3233 data
[9] = ncm
->ncm_Geometry
.dg_Cylinders
;
3234 scsicmd
->scsi_Actual
= 6+30;
3240 case 0x51: // drive ready
3241 case SCSI_CD_READ_TOC
:
3242 case SCSI_CD_PAUSE_RESUME
:
3243 case SCSI_CD_PLAY_AUDIO_10
:
3244 case SCSI_CD_PLAY_AUDIO_12
:
3245 case SCSI_CD_PLAY_AUDIO_MSF
:
3246 case SCSI_CD_PLAY_AUDIO_TRACK_INDEX
:
3247 case SCSI_CD_PLAY_TRACK_RELATIVE_10
:
3248 case SCSI_CD_PLAY_TRACK_RELATIVE_12
:
3250 case SCSI_CD_CLOSE_TRACK
:
3251 case SCSI_CD_GET_CONFIGURATION
:
3252 case SCSI_CD_GET_EVENT_STATUS_NOTIFICATION
:
3253 case SCSI_CD_GET_PERFORMANCE
:
3254 case SCSI_CD_LOAD_UNLOAD_MEDIUM
:
3255 case SCSI_DA_START_STOP_UNIT
:
3256 case SCSI_CD_MECHANISM_STATUS
:
3257 case SCSI_CD_PRE_FETCH
:
3258 case SCSI_CD_PREVENT_ALLOW_MEDIUM_REMOVAL
:
3259 case SCSI_CD_READ_HEADER
:
3260 case SCSI_CD_READ_SUB_CHANNEL
:
3261 if((scsicmd
->scsi_Command
[0] != SCSI_MODE_SENSE_6
) &&
3262 ((ncm
->ncm_DeviceType
== PDT_WORM
) || (ncm
->ncm_DeviceType
== PDT_CDROM
)))
3264 // allows these CD rom commands even with SimpleSCSI enabled.
3270 UBYTE cmdstrbuf
[16*3+2];
3272 GM_UNIQUENAME(nHexString
)(scsicmd
->scsi_Command
, (ULONG
) (scsicmd
->scsi_CmdLength
< 16 ? scsicmd
->scsi_CmdLength
: 16), cmdstrbuf
);
3273 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Simple SCSI: Filtering SCSI command %s", cmdstrbuf
);
3275 scsicmd
->scsi_Status
= SCSI_CHECK_CONDITION
;
3276 scsicmd
->scsi_SenseActual
= 0;
3277 if(scsicmd
->scsi_Flags
& SCSIF_AUTOSENSE
)
3279 if(scsicmd
->scsi_SenseLength
>= 18)
3281 memset(scsicmd
->scsi_SenseData
, 0x00, 18);
3282 scsicmd
->scsi_SenseData
[0] = 0x80|0x70;
3283 scsicmd
->scsi_SenseData
[2] = SK_ILLEGAL_REQUEST
;
3284 scsicmd
->scsi_SenseData
[12] = 0x20; // unsupported command
3285 scsicmd
->scsi_SenseActual
= 18;
3293 if((scsicmd
->scsi_Command
[0] == SCSI_TEST_UNIT_READY
) && scsicmd
->scsi_Length
)
3295 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Bogus TEST_UNIT_READY data length set to 0.");
3296 scsicmd
->scsi_Length
= 0;
3299 if(pf
& PFF_FAKE_INQUIRY
)
3301 if(scsicmd
->scsi_Command
[0] == SCSI_INQUIRY
)
3303 if(scsicmd
->scsi_Length
>= 36)
3305 UBYTE
*data
= (UBYTE
*) scsicmd
->scsi_Data
;
3308 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Faking Inquiry.");
3310 KPRINTF(10, ("Faking INQUIRY!\n"));
3311 psdGetAttrs(PGA_DEVICE
, ncm
->ncm_Device
,
3312 DA_ProductName
, &prodname
,
3313 DA_Manufacturer
, &vendname
,
3315 memset(data
, 0x00, (size_t) scsicmd
->scsi_Length
);
3316 data
[1] = 0x80; // removable media
3317 data
[2] = 0x02; // 0x03 would be ANSI X3.301:1997 (SPC).
3318 data
[3] = 0x02; // Response data format = 2
3319 data
[4] = 32; // additional length n-4
3320 CopyMem(vendname
, &data
[8], (ULONG
) ((strlen(vendname
) < 8) ? strlen(vendname
) : 8));
3321 CopyMem(prodname
, &data
[16], (ULONG
) ((strlen(prodname
) < 16) ? strlen(prodname
) : 16));
3322 scsicmd
->scsi_CmdActual
= scsicmd
->scsi_CmdLength
;
3323 scsicmd
->scsi_Status
= SCSI_GOOD
;
3324 scsicmd
->scsi_SenseActual
= 0;
3331 if(pf
& PFF_FIX_INQ36
)
3333 if((scsicmd
->scsi_Command
)[0] == SCSI_INQUIRY
)
3335 if(scsicmd
->scsi_Length
> 36)
3339 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing Inquiry.");
3342 KPRINTF(10, ("Fixing INQUIRY!\n"));
3343 scsicmd
->scsi_Length
= 36;
3345 else if(scsicmd
->scsi_Length
< 36)
3349 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3350 "Couldn't fix Inquiry < %ld.",
3351 scsicmd
->scsi_Length
);
3353 KPRINTF(10, ("Couldn't fix INQUIRY!\n"));
3360 scsicmd10
= *scsicmd
;
3361 scsicmd10
.scsi_Command
= cmd12
;
3362 scsicmd10
.scsi_CmdLength
= 10;
3363 memset(cmd12
, 0x00, 12);
3364 switch(scsicmd
->scsi_Command
[0])
3366 case SCSI_DA_READ_6
:
3367 case SCSI_DA_WRITE_6
:
3368 case SCSI_DA_SEEK_6
:
3369 cmd12
[0] = scsicmd
->scsi_Command
[0] | 0x20;
3370 cmd12
[1] = scsicmd
->scsi_Command
[1] & 0xe0;
3371 cmd12
[3] = scsicmd
->scsi_Command
[1] & 0x1f;
3372 cmd12
[4] = scsicmd
->scsi_Command
[2];
3373 cmd12
[5] = scsicmd
->scsi_Command
[3];
3374 cmd12
[8] = scsicmd
->scsi_Command
[4];
3375 cmd12
[9] = scsicmd
->scsi_Command
[5];
3379 case SCSI_MODE_SELECT_6
:
3380 cmd12
[0] = SCSI_MODE_SELECT_10
;
3381 cmd12
[1] = scsicmd
->scsi_Command
[1];
3382 //cmd12[2] = scsicmd->scsi_Command[2]; // reserved
3383 //cmd12[3] = scsicmd->scsi_Command[3]; // reserved
3384 cmd12
[7] = (scsicmd
->scsi_Command
[4]+4)>>8;
3385 cmd12
[8] = scsicmd
->scsi_Command
[4]+4;
3386 cmd12
[9] = scsicmd
->scsi_Command
[5];
3388 sensedata
= psdAllocVec(scsicmd
->scsi_Length
+4);
3389 if(sensedata
&& (scsicmd
->scsi_Length
>= 4))
3391 buf
= (UBYTE
*) scsicmd
->scsi_Data
;
3392 sensedata
[1] = *buf
++;
3393 sensedata
[2] = *buf
++;
3394 sensedata
[3] = *buf
++;
3395 sensedata
[7] = *buf
++;
3397 scsicmd10
.scsi_Length
= scsicmd
->scsi_Length
+4;
3398 scsicmd10
.scsi_Data
= (UWORD
*) sensedata
;
3400 CopyMem(buf
, &sensedata
[8], scsicmd
->scsi_Length
-4);
3405 case SCSI_MODE_SENSE_6
:
3406 cmd12
[0] = SCSI_MODE_SENSE_10
;
3407 cmd12
[1] = scsicmd
->scsi_Command
[1] & 0xf7;
3408 cmd12
[2] = scsicmd
->scsi_Command
[2];
3409 cmd12
[3] = scsicmd
->scsi_Command
[3];
3410 // Workaround: Some devices are seriously broken and do not interpret
3411 // the upper byte of the allocation length field.
3412 // Hence they return 3 bytes instead of 259 bytes. For this special case,
3413 // we will simply truncate the size by four, to get back to a 255 byte
3415 if((scsicmd
->scsi_Command
[4] > 251) && (scsicmd
->scsi_Length
== scsicmd
->scsi_Command
[4]))
3417 scsicmd
->scsi_Command
[4] -= 4;
3418 scsicmd
->scsi_Length
-= 4;
3420 cmd12
[7] = (scsicmd
->scsi_Command
[4]+4)>>8;
3421 cmd12
[8] = scsicmd
->scsi_Command
[4]+4;
3422 cmd12
[9] = scsicmd
->scsi_Command
[5];
3423 sensedata
= psdAllocVec(scsicmd
->scsi_Length
+4);
3426 scsicmd10
.scsi_Length
= scsicmd
->scsi_Length
+4;
3427 scsicmd10
.scsi_Data
= (UWORD
*) sensedata
;
3434 if((ncm
->ncm_CSType
== MS_ATAPI_SUBCLASS
) ||
3435 (ncm
->ncm_CSType
== MS_FDDATAPI_SUBCLASS
) ||
3436 (ncm
->ncm_CSType
== MS_UFI_SUBCLASS
))
3440 scsicmd10
= *scsicmd
;
3441 scsicmd10
.scsi_Command
= cmd12
;
3442 memset(cmd12
, 0x00, 12);
3443 CopyMem(scsicmd
->scsi_Command
, cmd12
, (ULONG
) scsicmd
->scsi_CmdLength
);
3446 scsicmd10
.scsi_CmdLength
= 12;
3447 if(ncm
->ncm_CSType
== MS_UFI_SUBCLASS
)
3451 case SCSI_REQUEST_SENSE
:
3452 cmd12
[4] = 18; /* restrict UFI response to 18 bytes */
3453 scsicmd10
.scsi_Flags
&= ~SCSIF_AUTOSENSE
;
3457 KPRINTF(10, ("Disabling autosense for UFI!\n"));
3458 cmd12
[4] = 36; /* restrict UFI response to 36 bytes */
3459 scsicmd10
.scsi_Flags
&= ~SCSIF_AUTOSENSE
;
3462 case SCSI_MODE_SELECT_10
:
3475 UBYTE cmd1strbuf
[16*3+2];
3476 UBYTE cmd2strbuf
[16*3+2];
3478 GM_UNIQUENAME(nHexString
)(scsicmd
->scsi_Command
, (ULONG
) (scsicmd
->scsi_CmdLength
< 16 ? scsicmd
->scsi_CmdLength
: 16), cmd1strbuf
);
3479 GM_UNIQUENAME(nHexString
)(scsicmd10
.scsi_Command
, (ULONG
) (scsicmd10
.scsi_CmdLength
< 16 ? scsicmd10
.scsi_CmdLength
: 16), cmd2strbuf
);
3480 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3481 "Mode XLATE for %s -> %s", cmd1strbuf
, cmd2strbuf
);
3482 if(scsicmd
->scsi_Length
&& (scsicmd10
.scsi_Command
[0] == SCSI_MODE_SELECT_10
))
3484 GM_UNIQUENAME(nHexString
)((UBYTE
*) scsicmd
->scsi_Data
, (ULONG
) (scsicmd
->scsi_Length
< 16 ? scsicmd
->scsi_Length
: 16), cmd1strbuf
);
3485 GM_UNIQUENAME(nHexString
)((UBYTE
*) scsicmd10
.scsi_Data
, (ULONG
) (scsicmd10
.scsi_Length
< 16 ? scsicmd10
.scsi_Length
: 16), cmd2strbuf
);
3486 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3487 "Request: %s (%ld) -> %s (%ld)",
3488 cmd1strbuf
, scsicmd
->scsi_Length
,
3489 cmd2strbuf
, scsicmd10
.scsi_Length
);
3492 KPRINTF(20, ("Mode XLATE for cmd %lx\n", scsicmd
->scsi_Command
[0]));
3495 switch(ncm
->ncm_TPType
)
3498 res
= nScsiDirectBulk(ncm
, usecmd10
? &scsicmd10
: scsicmd
);
3503 res
= nScsiDirectCBI(ncm
, usecmd10
? &scsicmd10
: scsicmd
);
3509 KPRINTF(20, ("Cmd done %ld\n", res
));
3514 scsicmd
->scsi_Actual
= 0;
3515 if(scsicmd10
.scsi_Command
[0] == SCSI_MODE_SENSE_10
)
3517 UBYTE cmd1strbuf
[16*3+2];
3518 UBYTE cmd2strbuf
[16*3+2];
3520 if(scsicmd10
.scsi_Actual
>= 8)
3522 scsicmd
->scsi_Actual
= scsicmd10
.scsi_Actual
- 4;
3523 buf
= (UBYTE
*) scsicmd
->scsi_Data
;
3524 *buf
++ = sensedata
[1];
3525 *buf
++ = sensedata
[2];
3526 *buf
++ = sensedata
[3];
3527 *buf
++ = sensedata
[7];
3528 CopyMem(&sensedata
[8], buf
, (ULONG
) scsicmd10
.scsi_Actual
- 8);
3531 GM_UNIQUENAME(nHexString
)((UBYTE
*) scsicmd10
.scsi_Data
, scsicmd10
.scsi_Actual
< 16 ? scsicmd10
.scsi_Actual
: 16, cmd1strbuf
);
3532 GM_UNIQUENAME(nHexString
)((UBYTE
*) scsicmd
->scsi_Data
, scsicmd
->scsi_Actual
< 16 ? scsicmd
->scsi_Actual
: 16, cmd2strbuf
);
3533 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3534 "Response: %s (%ld) -> %s (%ld)",
3535 cmd1strbuf
, scsicmd10
.scsi_Actual
,
3536 cmd2strbuf
, scsicmd
->scsi_Actual
);
3540 psdFreeVec(sensedata
);
3542 scsicmd
->scsi_Actual
= scsicmd10
.scsi_Actual
;
3544 scsicmd
->scsi_CmdActual
= scsicmd10
.scsi_CmdActual
;
3545 scsicmd
->scsi_Status
= scsicmd10
.scsi_Status
;
3546 scsicmd
->scsi_SenseActual
= scsicmd10
.scsi_SenseActual
;
3549 pf
= ncm
->ncm_CDC
->cdc_PatchFlags
;
3550 if((res
== HFERR_Phase
) && (!(pf
& PFF_NO_FALLBACK
)) && (!(pf
& PFF_SIMPLE_SCSI
)))
3552 switch(scsicmd
->scsi_Command
[0])
3554 case SCSI_TEST_UNIT_READY
:
3556 //case SCSI_LOG_SELECT:
3557 //case SCSI_LOG_SENSE:
3558 case SCSI_REQUEST_SENSE
:
3559 //case SCSI_MODE_SELECT_6:
3560 //case SCSI_MODE_SELECT_10:
3561 //case SCSI_MODE_SENSE_6:
3562 //case SCSI_MODE_SENSE_10:
3563 case SCSI_DA_READ_6
:
3564 case SCSI_DA_READ_10
:
3565 case SCSI_DA_READ_CAPACITY
:
3566 case SCSI_DA_SEEK_6
:
3567 case SCSI_DA_SEEK_10
:
3568 case SCSI_DA_WRITE_6
:
3569 case SCSI_DA_WRITE_10
:
3573 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_SIMPLE_SCSI
;
3574 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3575 "Fallback: Enabling Simple SCSI.");
3576 GM_UNIQUENAME(nStoreConfig
)(ncm
);
3581 if((!res
) && ((scsicmd
->scsi_Command
)[0] == SCSI_DA_READ_CAPACITY
) && (pf
& PFF_FIX_CAPACITY
) && (scsicmd
->scsi_Length
>= 8))
3583 ULONG
*capacity
= ((ULONG
*) scsicmd
->scsi_Data
);
3584 *capacity
= AROS_LONG2BE(AROS_BE2LONG(*capacity
)-1);
3585 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3586 "Fix Capacity: Correcting number of blocks.");
3589 if(res
&& (scsicmd
->scsi_Command
[0] == SCSI_INQUIRY
))
3591 if((!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
)) && (!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_FIX_INQ36
)))
3593 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_FIX_INQ36
;
3594 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3595 "Fallback: Enabling Trim Inquiry.");
3596 GM_UNIQUENAME(nStoreConfig
)(ncm
);
3598 else if((!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
)) && (!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_FAKE_INQUIRY
)))
3600 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_FAKE_INQUIRY
;
3601 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3602 "Fallback: Enabling Fake Inquiry.");
3603 GM_UNIQUENAME(nStoreConfig
)(ncm
);
3607 if((ncm
->ncm_DeviceType
== PDT_WORM
) ||
3608 (ncm
->ncm_DeviceType
== PDT_CDROM
))
3610 // cd roms are always write protected
3611 ncm
->ncm_WriteProtect
= TRUE
;
3614 // don't try to obtain write protection, when there's no media inserted.
3615 if(!ncm
->ncm_UnitReady
)
3619 if((!res
) && (scsicmd
->scsi_Command
[0] == SCSI_MODE_SENSE_6
))
3621 if(((UBYTE
*) scsicmd
->scsi_Data
)[2] & 0x80)
3623 if(!ncm
->ncm_WriteProtect
)
3625 if(pf
& PFF_REM_SUPPORT
)
3627 ncm
->ncm_ChangeCount
++;
3628 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
3630 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3631 "Diskchange: Sense6WriteProtect On (count = %ld)",
3632 ncm
->ncm_ChangeCount
);
3635 ncm
->ncm_WriteProtect
= TRUE
;
3638 if(ncm
->ncm_WriteProtect
)
3640 if(pf
& PFF_REM_SUPPORT
)
3642 ncm
->ncm_ChangeCount
++;
3643 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
3645 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3646 "Diskchange: Sense6WriteProtect Off (count = %ld)",
3647 ncm
->ncm_ChangeCount
);
3650 ncm
->ncm_WriteProtect
= FALSE
;
3654 if((!res
) && (scsicmd
->scsi_Command
[0] == SCSI_MODE_SENSE_10
))
3656 if(((UBYTE
*) scsicmd
->scsi_Data
)[3] & 0x80)
3658 if(!ncm
->ncm_WriteProtect
)
3660 if(pf
& PFF_REM_SUPPORT
)
3662 ncm
->ncm_ChangeCount
++;
3663 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
3665 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3666 "Diskchange: Sense10WriteProtect On (count = %ld)",
3667 ncm
->ncm_ChangeCount
);
3670 ncm
->ncm_WriteProtect
= TRUE
;
3673 if(ncm
->ncm_WriteProtect
)
3675 if(pf
& PFF_REM_SUPPORT
)
3677 ncm
->ncm_ChangeCount
++;
3678 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
3680 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3681 "Diskchange: Sense10WriteProtect Off (count = %ld)",
3682 ncm
->ncm_ChangeCount
);
3685 ncm
->ncm_WriteProtect
= FALSE
;
3693 /* /// "nScsiDirectBulk()" */
3694 LONG
nScsiDirectBulk(struct NepClassMS
*ncm
, struct SCSICmd
*scsicmd
)
3698 struct UsbMSCmdBlkWrapper umscbw
;
3699 struct UsbMSCmdStatusWrapper umscsw
;
3703 UBYTE cmdstrbuf
[16*3+2];
3705 KPRINTF(10, ("\n"));
3707 GM_UNIQUENAME(nHexString
)(scsicmd
->scsi_Command
, (ULONG
) (scsicmd
->scsi_CmdLength
< 16 ? scsicmd
->scsi_CmdLength
: 16), cmdstrbuf
);
3709 if(scsicmd
->scsi_Flags
& 0x80) /* Autoretry */
3713 umscbw
.dCBWSignature
= AROS_LONG2LE(0x43425355);
3714 scsicmd
->scsi_Status
= SCSI_GOOD
;
3718 KPRINTF(10, ("retrycnt %ld\n",retrycnt
));
3719 if(ncm
->ncm_DenyRequests
)
3721 rioerr
= HFERR_Phase
;
3724 /*nBulkReset(ncm);*/
3728 /*psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3729 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
3730 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);*/
3732 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DELAY_DATA
)
3737 datalen
= scsicmd
->scsi_Length
;
3738 umscbw
.dCBWTag
= (IPTR
) scsicmd
+ ++ncm
->ncm_TagCount
;
3739 umscbw
.dCBWDataTransferLength
= AROS_LONG2LE(datalen
);
3740 umscbw
.bmCBWFlags
= scsicmd
->scsi_Flags
& SCSIF_READ
? 0x80 : 0x00;
3741 umscbw
.bCBWLUN
= ncm
->ncm_UnitLUN
;
3742 if((scsicmd
->scsi_CmdLength
) >= 16)
3744 CopyMemQuick(scsicmd
->scsi_Command
, umscbw
.CBWCB
, 16);
3745 umscbw
.bCBWCBLength
= scsicmd
->scsi_CmdActual
= 16;
3747 memset(umscbw
.CBWCB
, 0, 16);
3748 CopyMem(scsicmd
->scsi_Command
, umscbw
.CBWCB
, (ULONG
) scsicmd
->scsi_CmdLength
);
3749 umscbw
.bCBWCBLength
= scsicmd
->scsi_CmdActual
= scsicmd
->scsi_CmdLength
;
3751 //psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Issueing command %s Dlen=%ld", cmdstrbuf, datalen);
3753 KPRINTF(2, ("command block phase, tag %08lx, len %ld, flags %02lx...\n",
3754 umscbw
.dCBWTag
, scsicmd
->scsi_CmdLength
, scsicmd
->scsi_Flags
));
3755 KPRINTF(2, ("command: %s\n", cmdstrbuf
));
3756 ioerr
= psdDoPipe(ncm
->ncm_EPOutPipe
, &umscbw
, UMSCBW_SIZEOF
);
3757 if(ioerr
== UHIOERR_STALL
) /* Retry on stall */
3759 KPRINTF(2, ("stall...\n"));
3761 ioerr
= psdDoPipe(ncm
->ncm_EPOutPipe
, &umscbw
, UMSCBW_SIZEOF
);
3763 if(ncm
->ncm_DenyRequests
)
3765 rioerr
= HFERR_Phase
;
3772 KPRINTF(2, ("data phase %ld bytes...\n", datalen
));
3773 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DELAY_DATA
)
3777 pp
= (scsicmd
->scsi_Flags
& SCSIF_READ
) ? ncm
->ncm_EPInPipe
: ncm
->ncm_EPOutPipe
;
3778 ioerr
= psdDoPipe(pp
, scsicmd
->scsi_Data
, datalen
);
3779 scsicmd
->scsi_Actual
= psdGetPipeActual(pp
);
3780 if(ioerr
== UHIOERR_OVERFLOW
)
3782 KPRINTF(10, ("Extra Data received, but ignored!\n"));
3785 else if(ioerr
== UHIOERR_STALL
) /* Accept on stall */
3787 KPRINTF(2, ("stall...\n"));
3788 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
3789 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
,
3790 (ULONG
) ((scsicmd
->scsi_Flags
& SCSIF_READ
) ? ncm
->ncm_EPInNum
|URTF_IN
: ncm
->ncm_EPOutNum
));
3791 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
3793 else if(ioerr
== UHIOERR_RUNTPACKET
)
3795 KPRINTF(10, ("Runt packet ignored...\n"));
3797 /*psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3798 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT,
3799 (ULONG) ncm->ncm_EPInNum|URTF_IN);
3800 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);*/
3804 scsicmd
->scsi_Actual
= 0;
3808 KPRINTF(2, ("command status phase...\n"));
3809 ioerr
= psdDoPipe(ncm
->ncm_EPInPipe
, &umscsw
, UMSCSW_SIZEOF
);
3810 if(ioerr
== UHIOERR_STALL
) /* Retry on stall */
3812 KPRINTF(2, ("stall...\n"));
3813 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
3814 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPInNum
|URTF_IN
);
3815 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
3816 /*nBulkClear(ncm);*/
3817 ioerr
= psdDoPipe(ncm
->ncm_EPInPipe
, &umscsw
, UMSCSW_SIZEOF
);
3819 if(ioerr
== UHIOERR_RUNTPACKET
)
3822 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3823 "Command status block truncated (%ld bytes), retrying...",
3824 psdGetPipeActual(ncm
->ncm_EPInPipe
));
3825 ioerr
= psdDoPipe(ncm
->ncm_EPInPipe
, &umscsw
, UMSCSW_SIZEOF
);
3827 if(ioerr
== UHIOERR_OVERFLOW
)
3829 KPRINTF(10, ("Extra Status received, but ignored!\n"));
3832 if(ncm
->ncm_DenyRequests
)
3834 rioerr
= HFERR_Phase
;
3839 KPRINTF(2, ("Status:\n"
3840 " Signature: %08lx\n"
3842 " Residue : %08lx\n"
3843 " Status : %02lx\n",
3844 umscsw
.dCSWSignature
,
3846 umscsw
.dCSWDataResidue
,
3847 umscsw
.bCSWStatus
));
3848 if(((umscsw
.dCSWSignature
!= AROS_LONG2LE(0x53425355)) && (!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_CSS_BROKEN
))) || (umscsw
.dCSWTag
!= umscbw
.dCBWTag
))
3850 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Command (%s) failed:", cmdstrbuf
);
3851 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3852 "Illegal command status block (Sig:%08lx, Tag=%08lx/%08lx (TX/RX), Len=%ld)",
3853 umscsw
.dCSWSignature
,
3856 psdGetPipeActual(ncm
->ncm_EPInPipe
));
3857 scsicmd
->scsi_Status
= SCSI_CHECK_CONDITION
;
3858 rioerr
= HFERR_Phase
;
3862 /* ignore this: too many firmwares report shit */
3863 //scsicmd->scsi_Actual = datalen - AROS_LONG2LE(umscsw.dCSWDataResidue);
3864 if((scsicmd
->scsi_Actual
> 7) && ((AROS_LONG2BE(*((ULONG
*) scsicmd
->scsi_Data
))>>8) == 0x555342) && (((ULONG
*) scsicmd
->scsi_Data
)[1] == umscbw
.dCBWTag
))
3866 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3867 "Your MSD has a very bad firmware! Havoc!");
3868 scsicmd
->scsi_Actual
= 0;
3869 umscsw
.bCSWStatus
= USMF_CSW_FAIL
;
3871 scsicmd
->scsi_Status
= umscsw
.bCSWStatus
;
3872 if(umscsw
.bCSWStatus
)
3874 if(umscsw
.bCSWStatus
== USMF_CSW_PHASEERR
)
3876 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Command (%s) failed: %ld", cmdstrbuf
, umscsw
.bCSWStatus
);
3879 /* Autosensing required? */
3880 if(scsicmd
->scsi_Flags
& SCSIF_AUTOSENSE
)
3882 /*nBulkClear(ncm);*/
3884 datalen
= scsicmd
->scsi_SenseLength
;
3885 umscbw
.dCBWTag
= (IPTR
) scsicmd
+ ++ncm
->ncm_TagCount
;
3886 umscbw
.dCBWDataTransferLength
= AROS_LONG2LE(datalen
);
3887 umscbw
.bmCBWFlags
= 0x80;
3888 /*umscbw.bCBWLUN = ncm->ncm_UnitLun;*/
3889 umscbw
.bCBWCBLength
= 6;
3890 umscbw
.CBWCB
[0] = SCSI_REQUEST_SENSE
;
3891 umscbw
.CBWCB
[1] = 0x00;
3892 umscbw
.CBWCB
[2] = 0x00;
3893 umscbw
.CBWCB
[3] = 0x00;
3894 umscbw
.CBWCB
[4] = datalen
;
3895 umscbw
.CBWCB
[5] = 0;
3896 KPRINTF(2, ("sense command block phase...\n"));
3897 ioerr
= psdDoPipe(ncm
->ncm_EPOutPipe
, &umscbw
, UMSCBW_SIZEOF
);
3898 if(ioerr
== UHIOERR_STALL
) /* Retry on stall */
3900 KPRINTF(2, ("stall...\n"));
3902 ioerr
= psdDoPipe(ncm
->ncm_EPOutPipe
, &umscbw
, UMSCBW_SIZEOF
);
3906 KPRINTF(2, ("sense data phase %ld bytes...\n", datalen
));
3907 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DELAY_DATA
)
3911 ioerr
= psdDoPipe(ncm
->ncm_EPInPipe
, scsicmd
->scsi_SenseData
, datalen
);
3912 scsicmd
->scsi_SenseActual
= psdGetPipeActual(ncm
->ncm_EPInPipe
);
3913 if(ioerr
== UHIOERR_STALL
) /* Accept on stall */
3915 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
3916 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPInNum
|URTF_IN
);
3917 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
3919 if((ioerr
== UHIOERR_RUNTPACKET
) || (ioerr
== UHIOERR_OVERFLOW
))
3921 KPRINTF(10, ("Extra or less data received, but ignored!\n"));
3927 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DELAY_DATA
)
3931 KPRINTF(2, ("sense command status phase...\n"));
3932 ioerr
= psdDoPipe(ncm
->ncm_EPInPipe
, &umscsw
, UMSCSW_SIZEOF
);
3933 if(ioerr
== UHIOERR_STALL
) /* Retry on stall */
3935 KPRINTF(2, ("stall...\n"));
3936 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
3937 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPInNum
|URTF_IN
);
3938 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
3939 ioerr
|= psdDoPipe(ncm
->ncm_EPInPipe
, &umscsw
, UMSCSW_SIZEOF
);
3941 if(ioerr
== UHIOERR_RUNTPACKET
)
3944 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3945 "Command (sense) status block truncated (%ld bytes), retrying...",
3946 psdGetPipeActual(ncm
->ncm_EPInPipe
));
3947 ioerr
= psdDoPipe(ncm
->ncm_EPInPipe
, &umscsw
, UMSCSW_SIZEOF
);
3950 if(ioerr
== UHIOERR_OVERFLOW
)
3952 KPRINTF(10, ("Extra Status received, but ignored!\n"));
3957 KPRINTF(2, ("sense Status:\n"
3958 " Signature: %08lx\n"
3960 " Residue : %08lx\n"
3961 " Status : %02lx\n",
3962 umscsw
.dCSWSignature
,
3964 umscsw
.dCSWDataResidue
,
3965 umscsw
.bCSWStatus
));
3966 if(((umscsw
.dCSWSignature
!= AROS_LONG2LE(0x53425355)) && (!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_CSS_BROKEN
))) || (umscsw
.dCSWTag
!= umscbw
.dCBWTag
))
3968 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3969 "Illegal command (sense) status block (Sig:%08lx, Tag=%08lx/%08lx (TX/RX), Len=%ld)",
3970 umscsw
.dCSWSignature
,
3973 psdGetPipeActual(ncm
->ncm_EPInPipe
));
3974 scsicmd
->scsi_Status
= SCSI_CHECK_CONDITION
;
3975 rioerr
= HFERR_Phase
;
3979 /* ignore this: too many firmwares report shit */
3980 //scsicmd->scsi_SenseActual = datalen - AROS_LONG2LE(umscsw.dCSWDataResidue);
3981 if((scsicmd
->scsi_SenseActual
> 7) && ((AROS_LONG2BE(*((ULONG
*) scsicmd
->scsi_SenseData
))>>8) == 0x555342) && (((ULONG
*) scsicmd
->scsi_SenseData
)[1] == umscbw
.dCBWTag
))
3983 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3984 "Your MSD has a very bad firmware! Havoc!");
3985 scsicmd
->scsi_Actual
= 0;
3986 umscsw
.bCSWStatus
= USMF_CSW_FAIL
;
3989 if(umscsw
.bCSWStatus
)
3991 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3992 "Sense failed: %ld",
3993 umscsw.bCSWStatus);*/
3994 if(umscsw
.bCSWStatus
== USMF_CSW_PHASEERR
)
3999 switch(scsicmd
->scsi_SenseData
[2] & SK_MASK
)
4001 case SK_ILLEGAL_REQUEST
:
4005 case SK_DATA_PROTECT
:
4006 if(!ncm
->ncm_WriteProtect
)
4008 ncm
->ncm_WriteProtect
= TRUE
;
4009 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
4011 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
4012 "WriteProtect On: Sense Data Protect");
4017 case SK_UNIT_ATTENTION
:
4018 if((ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_REM_SUPPORT
) &&
4019 ((scsicmd
->scsi_SenseData
[12] == 0x28) ||
4020 (scsicmd
->scsi_SenseData
[12] == 0x3A)))
4022 ncm
->ncm_ChangeCount
++;
4023 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
4025 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
4026 "Diskchange: Unit Attention (count = %ld)",
4027 ncm
->ncm_ChangeCount
);
4032 KPRINTF(10, ("Sense Key: %lx/%02lx/%02lx\n",
4033 scsicmd
->scsi_SenseData
[2] & SK_MASK
,
4034 scsicmd
->scsi_SenseData
[12],
4035 scsicmd
->scsi_SenseData
[13]));
4036 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
4038 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
4039 "Cmd %s: Sense Key %lx/%02lx/%02lx",
4041 scsicmd
->scsi_SenseData
[2] & SK_MASK
,
4042 scsicmd
->scsi_SenseData
[12],
4043 scsicmd
->scsi_SenseData
[13]);
4047 KPRINTF(10, ("Sense status failed: %s (%ld)\n", psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
));
4048 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Command (%s) okay, but:", cmdstrbuf
);
4049 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4050 "Sense status failed: %s (%ld)",
4051 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4055 KPRINTF(10, ("Sense data failed: %s (%ld)\n", psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
));
4056 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Command (%s) okay, but:", cmdstrbuf
);
4057 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4058 "Sense data failed: %s (%ld)",
4059 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4063 KPRINTF(10, ("Sense block failed: %s (%ld)\n", psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
));
4064 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Command (%s) okay, but:", cmdstrbuf
);
4065 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4066 "Sense block failed: %s (%ld)",
4067 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4068 /*nBulkReset(ncm);*/
4071 rioerr
= HFERR_BadStatus
;
4074 KPRINTF(10, ("Command status failed: %s (%ld)\n", psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
));
4075 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Command (%s) failed:", cmdstrbuf
);
4076 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4077 "Command status failed: %s (%ld)",
4078 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4079 scsicmd
->scsi_Status
= SCSI_CHECK_CONDITION
;
4080 rioerr
= HFERR_Phase
;
4084 KPRINTF(10, ("Data phase failed: %s (%ld)\n", psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
));
4085 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Command (%s) failed:", cmdstrbuf
);
4086 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4087 "Data phase failed: %s (%ld)",
4088 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4089 scsicmd
->scsi_Status
= SCSI_CHECK_CONDITION
;
4090 rioerr
= HFERR_Phase
;
4094 KPRINTF(10, ("Command block failed: %s (%ld)\n", psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
));
4095 scsicmd
->scsi_Status
= SCSI_CHECK_CONDITION
;
4096 rioerr
= HFERR_Phase
;
4097 if(ioerr
== UHIOERR_TIMEOUT
)
4101 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Command (%s) failed:", cmdstrbuf
);
4102 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4103 "Command block failed: %s (%ld)",
4104 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4111 KPRINTF(1, ("Retrying...\n"));
4112 } while(retrycnt
--);
4118 /* /// "nScsiDirectCBI()" */
4119 LONG
nScsiDirectCBI(struct NepClassMS
*ncm
, struct SCSICmd
*scsicmd
)
4123 struct PsdPipe
*backpp
;
4124 struct UsbMSCBIStatusWrapper umscsw
;
4128 UBYTE sensedata
[18];
4133 UBYTE cmdstrbuf
[16*3+2];
4135 GM_UNIQUENAME(nHexString
)(scsicmd
->scsi_Command
, (ULONG
) (scsicmd
->scsi_CmdLength
< 16 ? scsicmd
->scsi_CmdLength
: 16), cmdstrbuf
);
4137 if(scsicmd
->scsi_Flags
& 0x80) /* Autoretry */
4141 scsicmd
->scsi_Status
= SCSI_GOOD
;
4145 if(ncm
->ncm_DenyRequests
)
4147 rioerr
= HFERR_Phase
;
4151 datalen
= scsicmd
->scsi_Length
;
4153 KPRINTF(2, ("command block phase, tag %08lx, len %ld, flags %02lx...\n",
4154 scsicmd
, scsicmd
->scsi_CmdLength
, scsicmd
->scsi_Flags
));
4156 KPRINTF(2, ("command: %s\n", cmdstrbuf
));
4159 scsicmd
->scsi_CmdActual
= scsicmd
->scsi_CmdLength
;
4162 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
4163 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT,
4164 (ULONG) ((scsicmd->scsi_Flags & SCSIF_READ) ? ncm->ncm_EPInNum|URTF_IN : ncm->ncm_EPOutNum));
4165 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
4167 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_CLASS
|URTF_INTERFACE
,
4168 UMSR_ADSC
, 0, (ULONG
) ncm
->ncm_UnitIfNum
);
4169 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, scsicmd
->scsi_Command
, (ULONG
) scsicmd
->scsi_CmdLength
);
4171 if(ncm
->ncm_DenyRequests
)
4173 rioerr
= HFERR_Phase
;
4178 datadone
= statusdone
= FALSE
;
4181 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_CLEAR_EP
)
4183 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
4184 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
,
4185 (ULONG
) ((scsicmd
->scsi_Flags
& SCSIF_READ
) ? ncm
->ncm_EPInNum
|URTF_IN
: ncm
->ncm_EPOutNum
));
4186 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
4189 KPRINTF(2, ("data phase %ld bytes...\n", datalen
));
4190 pp
= (scsicmd
->scsi_Flags
& SCSIF_READ
) ? ncm
->ncm_EPInPipe
: ncm
->ncm_EPOutPipe
;
4192 if(ncm
->ncm_TPType
== MS_PROTO_CBI
)
4194 /* okay, this is a major pain in the arse.
4195 we have to do this asynchroneously */
4197 umscsw
.bValue
= USMF_CSW_PHASEERR
;
4198 psdSendPipe(ncm
->ncm_EPIntPipe
, &umscsw
, sizeof(struct UsbMSCBIStatusWrapper
));
4199 psdSendPipe(pp
, scsicmd
->scsi_Data
, datalen
);
4202 WaitPort(ncm
->ncm_TaskMsgPort
);
4203 while((backpp
= (struct PsdPipe
*) GetMsg(ncm
->ncm_TaskMsgPort
)))
4207 /* data transfer finished */
4210 else if(backpp
== ncm
->ncm_EPIntPipe
)
4212 /* status returned */
4216 } while(!statusdone
);
4223 ioerr
= psdGetPipeError(pp
);
4227 ioerr
= psdDoPipe(pp
, scsicmd
->scsi_Data
, datalen
);
4230 scsicmd
->scsi_Actual
= psdGetPipeActual(pp
);
4231 if(ioerr
== UHIOERR_OVERFLOW
)
4233 KPRINTF(10, ("Extra Data received, but ignored!\n"));
4236 if(ioerr
== UHIOERR_STALL
) /* Accept on stall */
4238 KPRINTF(2, ("stall...\n"));
4240 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
4241 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
,
4242 (ULONG
) ((scsicmd
->scsi_Flags
& SCSIF_READ
) ? ncm
->ncm_EPInNum
|URTF_IN
: ncm
->ncm_EPOutNum
));
4243 psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
4248 scsicmd
->scsi_Actual
= 0;
4250 if((!ioerr
) || (ioerr
== UHIOERR_RUNTPACKET
))
4252 KPRINTF(2, ("command status phase...\n"));
4253 if(ncm
->ncm_TPType
== MS_PROTO_CBI
)
4257 if(ncm
->ncm_CSType
== MS_UFI_SUBCLASS
)
4259 umscsw
.bType
= 0x04;
4263 umscsw
.bValue
= USMF_CSW_PHASEERR
;
4265 ioerr
= psdDoPipe(ncm
->ncm_EPIntPipe
, &umscsw
, sizeof(struct UsbMSCBIStatusWrapper
));
4267 ioerr
= psdGetPipeError(ncm
->ncm_EPIntPipe
);
4269 umscsw
.bValue
&= 0x0f; /* mask out upper nibble */
4272 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4273 "Status interrupt failed: %s (%ld)",
4274 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4277 if(ncm
->ncm_CSType
== MS_UFI_SUBCLASS
)
4280 if((scsicmd
->scsi_Command
[0] == SCSI_REQUEST_SENSE
) ||
4281 (scsicmd
->scsi_Command
[0] == SCSI_INQUIRY
))
4284 umscsw
.bValue
= USMF_CSW_PASS
;
4287 umscsw
.bValue
= asc
? USMF_CSW_FAIL
: USMF_CSW_PASS
;
4290 rioerr
= HFERR_BadStatus
;
4294 umscsw
.bValue
&= USMF_CSW_PERSIST
; /* mask out other bits */
4298 umscsw
.bValue
= USMF_CSW_PASS
;
4301 if(ncm
->ncm_DenyRequests
)
4303 rioerr
= HFERR_Phase
;
4306 if((!ioerr
) || (ioerr
== UHIOERR_RUNTPACKET
))
4308 scsicmd
->scsi_Status
= umscsw
.bValue
;
4309 if(umscsw
.bValue
== USMF_CSW_PHASEERR
)
4311 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
4312 "Command (%s) phase error: %ld",
4317 else if(umscsw
.bValue
== USMF_CSW_PERSIST
)
4319 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
4320 "Command (%s) persistant error: %ld",
4326 /* Autosensing required? */
4327 if(((umscsw
.bValue
&& (scsicmd
->scsi_Flags
& SCSIF_AUTOSENSE
))) ||
4328 (ncm
->ncm_TPType
== MS_PROTO_CB
) || (ncm
->ncm_TPType
== MS_PROTO_CBI
))
4330 if(scsicmd
->scsi_Flags
& SCSIF_AUTOSENSE
)
4332 datalen
= scsicmd
->scsi_SenseLength
;
4333 senseptr
= scsicmd
->scsi_SenseData
;
4336 senseptr
= sensedata
;
4338 if(!(scsicmd
->scsi_SenseActual
= nCBIRequestSense(ncm
, senseptr
, datalen
)))
4342 if(senseptr
[2] & SK_MASK
)
4344 rioerr
= HFERR_BadStatus
;
4345 scsicmd
->scsi_Status
= SCSI_CHECK_CONDITION
;
4349 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4350 "Command status failed: %s (%ld)",
4351 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4352 scsicmd
->scsi_Status
= SCSI_CHECK_CONDITION
;
4353 rioerr
= HFERR_Phase
;
4357 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4358 "Data phase failed: %s (%ld)",
4359 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4360 scsicmd
->scsi_Status
= SCSI_CHECK_CONDITION
;
4361 rioerr
= HFERR_Phase
;
4365 scsicmd
->scsi_Status
= SCSI_CHECK_CONDITION
;
4366 rioerr
= HFERR_Phase
;
4367 if(ioerr
== UHIOERR_TIMEOUT
)
4371 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
4373 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Command (%s) failed:", cmdstrbuf
);
4374 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4375 "Command block failed: %s (%ld)",
4376 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4378 if(scsicmd
->scsi_Flags
& SCSIF_AUTOSENSE
)
4380 datalen
= scsicmd
->scsi_SenseLength
;
4381 senseptr
= scsicmd
->scsi_SenseData
;
4384 senseptr
= sensedata
;
4386 if(!(scsicmd
->scsi_SenseActual
= nCBIRequestSense(ncm
, senseptr
, datalen
)))
4391 if(senseptr
[2] & SK_MASK
)
4393 rioerr
= HFERR_BadStatus
;
4394 if((senseptr
[2] & SK_MASK
) == SK_NOT_READY
)
4405 KPRINTF(1, ("Retrying...\n"));
4406 } while(retrycnt
--);
4412 /* /// "nLockXFer()" */
4413 void nLockXFer(struct NepClassMS
*ncm
)
4417 KPRINTF(1, ("PING(lock)\n"));
4418 ObtainSemaphore(&ncm
->ncm_UnitLUN0
->ncm_XFerLock
);
4419 KPRINTF(1, ("PONG(lock)\n"));
4424 /* /// "nUnlockXFer()" */
4425 void nUnlockXFer(struct NepClassMS
*ncm
)
4429 KPRINTF(1, ("PING(unlock)\n"));
4430 ReleaseSemaphore(&ncm
->ncm_UnitLUN0
->ncm_XFerLock
);
4431 KPRINTF(1, ("PONG(unlock)\n"));
4436 /* /// "nStoreConfig()" */
4437 BOOL
GM_UNIQUENAME(nStoreConfig
)(struct NepClassMS
*ncm
)
4440 struct NepClassMS
*cncm
;
4441 if(ncm
->ncm_Interface
)
4443 pic
= psdGetUsbDevCfg(GM_UNIQUENAME(libname
), ncm
->ncm_DevIDString
, ncm
->ncm_IfIDString
);
4446 psdSetUsbDevCfg(GM_UNIQUENAME(libname
), ncm
->ncm_DevIDString
, ncm
->ncm_IfIDString
, NULL
);
4447 pic
= psdGetUsbDevCfg(GM_UNIQUENAME(libname
), ncm
->ncm_DevIDString
, ncm
->ncm_IfIDString
);
4451 psdAddCfgEntry(pic
, ncm
->ncm_CDC
);
4453 while(((struct Node
*) cncm
)->ln_Succ
)
4455 if(cncm
->ncm_UnitLUN0
!= ncm
)
4459 psdAddCfgEntry(pic
, cncm
->ncm_CUC
);
4460 cncm
= (struct NepClassMS
*) ((struct Node
*) cncm
)->ln_Succ
;
4471 /* ********************************************************************* */
4473 /* /// "BSTR Macros" */
4476 #define b2cstr(bstr, cstr)\
4480 UWORD _len = AROS_BSTR_strlen(bstr);\
4483 cstr[_i] = AROS_BSTR_getchar(bstr, _i);\
4489 #define c2bstr(cstr, bstr)\
4493 while(cstr[_i] != '\0')\
4495 AROS_BSTR_putchar(bstr, _i, cstr[_i]);\
4498 AROS_BSTR_setstrlen(bstr, _i);\
4502 #define b2cstr(bstr, cstr) { ULONG i; for (i = 0; i < bstr[0]; i++) cstr[i] = bstr[i + 1]; cstr[i] = 0x00; }
4504 #define c2bstr(cstr, bstr)\
4509 STRPTR cp = (STRPTR) (cstr);\
4510 STRPTR bp = (STRPTR) (bstr);\
4522 #define ps nh->nh_PsdBase
4524 /* /// "nRemovableTask()" */
4525 AROS_UFH0(void, GM_UNIQUENAME(nRemovableTask
))
4529 struct NepMSBase
*nh
;
4530 struct NepClassMS
*ncm
;
4534 struct SCSICmd scsicmd
;
4536 UBYTE sensedata
[18];
4537 struct IOStdReq
*ioreq
;
4538 BOOL dontquit
= TRUE
;
4540 if((nh
= GM_UNIQUENAME(nAllocRT
)()))
4543 if(nh
->nh_ReadySigTask
)
4545 Signal(nh
->nh_ReadySigTask
, 1L<<nh
->nh_ReadySignal
);
4549 sigmask
= (1L<<nh
->nh_TimerMsgPort
->mp_SigBit
)|
4553 while((ioreq
= (struct IOStdReq
*) GetMsg(nh
->nh_TimerMsgPort
)))
4556 KPRINTF(2, ("Timer interrupt\n"));
4557 ncm
= (struct NepClassMS
*) nh
->nh_Units
.lh_Head
;
4558 while(ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
4560 if(ncm
->ncm_Task
&& (!ncm
->ncm_DenyRequests
))
4564 if(ncm
->ncm_Removable
&& ncm
->ncm_Running
)
4566 scsicmd
.scsi_Data
= NULL
;
4567 scsicmd
.scsi_Length
= 0;
4568 scsicmd
.scsi_Command
= cmd6
;
4569 scsicmd
.scsi_CmdLength
= 6;
4570 scsicmd
.scsi_Flags
= SCSIF_READ
|SCSIF_AUTOSENSE
|0x80;
4571 scsicmd
.scsi_SenseData
= sensedata
;
4572 scsicmd
.scsi_SenseLength
= 18;
4573 cmd6
[0] = SCSI_TEST_UNIT_READY
;
4579 if((ioerr
= nScsiDirectTunnel(ncm
, &scsicmd
)))
4581 KPRINTF(1, ("Test unit ready yielded: %ld/%ld\n", sensedata
[2], sensedata
[12]));
4582 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
4583 "SCSI_TEST_UNIT_READY failed: %ld",
4585 /* Check for MEDIUM NOT PRESENT */
4586 if(((sensedata
[2] & SK_MASK
) == SK_NOT_READY
) &&
4587 ((sensedata
[12] == 0x3a) || (sensedata
[12] == 0x04)))
4589 if(ncm
->ncm_UnitReady
)
4591 ncm
->ncm_UnitReady
= FALSE
;
4592 ncm
->ncm_ChangeCount
++;
4593 KPRINTF(10, ("Diskchange: Medium removed (count = %ld)!\n", ncm
->ncm_ChangeCount
));
4594 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
4596 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
4597 "Diskchange: Medium removed (count = %ld)",
4598 ncm
->ncm_ChangeCount
);
4603 if(!ncm
->ncm_UnitReady
)
4605 ncm
->ncm_UnitReady
= TRUE
;
4606 ncm
->ncm_ChangeCount
++;
4607 KPRINTF(10, ("Diskchange: Medium inserted (count = %ld)!\n", ncm
->ncm_ChangeCount
));
4608 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
4610 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
4611 "Diskchange: Medium inserted (count = %ld)",
4612 ncm
->ncm_ChangeCount
);
4614 if(ncm
->ncm_CSType
== MS_UFI_SUBCLASS
)
4616 nh
->nh_IOReq
.io_Command
= CMD_START
;
4617 nIOCmdTunnel(ncm
, &nh
->nh_IOReq
);
4620 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_REM_SUPPORT
)
4622 nGetWriteProtect(ncm
);
4627 if(ncm
->ncm_LastChange
!= ncm
->ncm_ChangeCount
)
4629 if(ncm
->ncm_UnitReady
)
4631 nGetWriteProtect(ncm
);
4632 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_REM_SUPPORT
)
4634 nh
->nh_IOReq
.io_Command
= TD_GETGEOMETRY
;
4635 nh
->nh_IOReq
.io_Data
= &ncm
->ncm_Geometry
;
4636 nh
->nh_IOReq
.io_Length
= sizeof(ncm
->ncm_Geometry
);
4637 nIOCmdTunnel(ncm
, &nh
->nh_IOReq
);
4640 ioreq
= (struct IOStdReq
*) ncm
->ncm_DCInts
.lh_Head
;
4641 while(((struct Node
*) ioreq
)->ln_Succ
)
4643 Cause(ioreq
->io_Data
);
4644 ioreq
= (struct IOStdReq
*) ((struct Node
*) ioreq
)->ln_Succ
;
4646 if(ncm
->ncm_UnitReady
)
4648 // obtain blocksize first
4649 if(!ncm
->ncm_BlockSize
)
4651 nh
->nh_IOReq
.io_Command
= TD_GETGEOMETRY
;
4652 nh
->nh_IOReq
.io_Data
= &ncm
->ncm_Geometry
;
4653 nh
->nh_IOReq
.io_Length
= sizeof(ncm
->ncm_Geometry
);
4654 nIOCmdTunnel(ncm
, &nh
->nh_IOReq
);
4656 ncm
->ncm_HasMounted
= TRUE
;
4658 // find and mount partitions
4659 if(!CheckPartitions(ncm
) && ncm
->ncm_CUC
->cuc_AutoMountFAT
)
4661 // check for FAT volume with no partition table
4662 CheckFATPartition(ncm
, 0);
4664 if((ncm
->ncm_BlockSize
== 2048) &&
4665 ((ncm
->ncm_DeviceType
== PDT_WORM
) || (ncm
->ncm_DeviceType
== PDT_CDROM
)))
4667 if(ncm
->ncm_CUC
->cuc_AutoMountCD
)
4673 ncm
->ncm_LastChange
= ncm
->ncm_ChangeCount
;
4676 if(ncm
->ncm_DenyRequests
&& ncm
->ncm_CUC
->cuc_AutoUnmount
&& ncm
->ncm_HasMounted
)
4678 nUnmountPartition(ncm
);
4679 ncm
->ncm_HasMounted
= FALSE
;
4682 ncm
= (struct NepClassMS
*) ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
4684 nh
->nh_TimerIOReq
->tr_time
.tv_secs
= 3;
4685 nh
->nh_TimerIOReq
->tr_time
.tv_micro
= 0;
4686 SendIO((struct IORequest
*) nh
->nh_TimerIOReq
);
4689 if(nh
->nh_RemovableTask
->tc_Node
.ln_Type
== NT_TASK
)
4692 if((doslib
= OpenLibrary("dos.library", 39)))
4694 CloseLibrary(doslib
);
4695 // increase disk change count to force mounting
4696 ncm
= (struct NepClassMS
*) nh
->nh_Units
.lh_Head
;
4697 while(ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
4699 ncm
->ncm_ChangeCount
++;
4700 ncm
->ncm_ForceRTCheck
= TRUE
;
4701 ncm
= (struct NepClassMS
*) ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
4705 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
4706 "DOS found, stopping removable task...");
4707 nh
->nh_RestartIt
= TRUE
;
4710 // don't quit task, otherwise nobody will be there to restart it and retry mounting stuff
4718 sigs
= Wait(sigmask
);
4719 } while(!(sigs
& SIGBREAKF_CTRL_C
));
4720 ncm
= (struct NepClassMS
*) nh
->nh_Units
.lh_Head
;
4721 while(ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
4723 if(ncm
->ncm_DenyRequests
&& ncm
->ncm_CUC
->cuc_AutoUnmount
&& ncm
->ncm_HasMounted
)
4725 nUnmountPartition(ncm
);
4726 ncm
->ncm_HasMounted
= FALSE
;
4728 ncm
= (struct NepClassMS
*) ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
4730 KPRINTF(20, ("Going down the river!\n"));
4731 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Removable Task stopped.");
4732 GM_UNIQUENAME(nFreeRT
)(nh
);
4738 /* /// "nAllocRT()" */
4739 struct NepMSBase
* GM_UNIQUENAME(nAllocRT
)(void)
4741 struct Task
*thistask
;
4742 struct NepMSBase
*nh
;
4744 thistask
= FindTask(NULL
);
4745 nh
= thistask
->tc_UserData
;
4746 #undef ExpansionBase
4747 #define ExpansionBase nh->nh_ExpansionBase
4748 #undef PartitionBase
4749 #define PartitionBase nh->nh_PartitionBase
4752 if(!(ExpansionBase
= OpenLibrary("expansion.library", 37)))
4754 Alert(AG_OpenLib
| AO_ExpansionLib
);
4757 if(!(PartitionBase
= OpenLibrary("partition.library", 1)))
4759 Alert(AG_OpenLib
| AO_Unknown
);
4762 if(!(ps
= OpenLibrary("poseidon.library", 4)))
4764 Alert(AG_OpenLib
| AO_Unknown
);
4767 if(!(nh
->nh_IOMsgPort
= CreateMsgPort()))
4771 nh
->nh_IOReq
.io_Message
.mn_ReplyPort
= nh
->nh_IOMsgPort
;
4772 if(!(nh
->nh_TimerMsgPort
= CreateMsgPort()))
4776 if(!(nh
->nh_TimerIOReq
= (struct timerequest
*) CreateIORequest(nh
->nh_TimerMsgPort
, sizeof(struct timerequest
))))
4780 if(OpenDevice("timer.device", UNIT_VBLANK
, (struct IORequest
*) nh
->nh_TimerIOReq
, 0))
4784 /* Start removable interrupt */
4785 nh
->nh_TimerIOReq
->tr_node
.io_Command
= TR_ADDREQUEST
;
4786 nh
->nh_TimerIOReq
->tr_time
.tv_secs
= 0;
4787 nh
->nh_TimerIOReq
->tr_time
.tv_micro
= 50;
4788 SendIO((struct IORequest
*) nh
->nh_TimerIOReq
);
4789 nh
->nh_RemovableTask
= thistask
;
4794 CloseLibrary(ExpansionBase
);
4795 ExpansionBase
= NULL
;
4799 CloseLibrary(PartitionBase
);
4800 PartitionBase
= NULL
;
4808 if(nh
->nh_TimerIOReq
)
4810 if(nh
->nh_TimerIOReq
->tr_node
.io_Device
)
4812 CloseDevice((struct IORequest
*) nh
->nh_TimerIOReq
);
4814 DeleteIORequest((struct IORequest
*) nh
->nh_TimerIOReq
);
4815 nh
->nh_TimerIOReq
= NULL
;
4817 if(nh
->nh_TimerMsgPort
)
4819 DeleteMsgPort(nh
->nh_TimerMsgPort
);
4820 nh
->nh_TimerMsgPort
= NULL
;
4822 if(nh
->nh_IOMsgPort
)
4824 DeleteMsgPort(nh
->nh_IOMsgPort
);
4825 nh
->nh_IOMsgPort
= NULL
;
4828 nh
->nh_RemovableTask
= NULL
;
4829 if(nh
->nh_ReadySigTask
)
4831 Signal(nh
->nh_ReadySigTask
, 1L<<nh
->nh_ReadySignal
);
4837 /* /// "nFreeRT()" */
4838 void GM_UNIQUENAME(nFreeRT
)(struct NepMSBase
*nh
)
4841 psdFreeVec(nh
->nh_OneBlock
);
4842 nh
->nh_OneBlock
= NULL
;
4843 nh
->nh_OneBlockSize
= 0;
4847 CloseLibrary(nh
->nh_DOSBase
);
4848 nh
->nh_DOSBase
= NULL
;
4850 CloseLibrary(ExpansionBase
);
4851 ExpansionBase
= NULL
;
4852 CloseLibrary(PartitionBase
);
4853 PartitionBase
= NULL
;
4857 AbortIO((struct IORequest
*) nh
->nh_TimerIOReq
);
4858 WaitIO((struct IORequest
*) nh
->nh_TimerIOReq
);
4859 CloseDevice((struct IORequest
*) nh
->nh_TimerIOReq
);
4860 DeleteIORequest((struct IORequest
*) nh
->nh_TimerIOReq
);
4861 DeleteMsgPort(nh
->nh_TimerMsgPort
);
4862 nh
->nh_TimerMsgPort
= NULL
;
4863 nh
->nh_TimerIOReq
= NULL
;
4866 nh
->nh_RemovableTask
= NULL
;
4867 if(nh
->nh_ReadySigTask
)
4869 Signal(nh
->nh_ReadySigTask
, 1L<<nh
->nh_ReadySignal
);
4871 if(nh
->nh_RestartIt
)
4873 // wake up every task to relaunch removable task
4874 struct NepClassMS
*ncm
;
4875 ncm
= (struct NepClassMS
*) nh
->nh_Units
.lh_Head
;
4876 while(ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
4880 Signal(ncm
->ncm_Task
, 1L<<ncm
->ncm_TaskMsgPort
->mp_SigBit
);
4882 ncm
= (struct NepClassMS
*) ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
4884 nh
->nh_RestartIt
= FALSE
;
4889 /* /// "GM_UNIQUENAME(nOpenDOS)()" */
4890 BOOL
GM_UNIQUENAME(nOpenDOS
)(struct NepMSBase
*nh
)
4896 if(nh
->nh_RemovableTask
->tc_Node
.ln_Type
!= NT_PROCESS
)
4900 if((nh
->nh_DOSBase
= OpenLibrary("dos.library", 39)))
4902 KPRINTF(10, ("Opened dos.library!\n"));
4910 #define DOSBase nh->nh_DOSBase
4912 /* /// "nUnmountPartition()" */
4913 void nUnmountPartition(struct NepClassMS
*ncm
)
4915 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
4916 struct DosList
*list
;
4917 struct DeviceNode
*node
;
4918 struct DeviceNode
*oldnode
= NULL
;
4922 if(!GM_UNIQUENAME(nOpenDOS
)(nh
))
4926 while((node
= FindMatchingDevice(ncm
, NULL
)))
4932 bstr
= (UBYTE
*) BADDR(node
->dn_Name
);
4933 b2cstr(bstr
, partname
);
4934 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
4935 "Unmounting partition %s...",
4937 DoPkt(node
->dn_Task
, ACTION_INHIBIT
, TRUE
, 0, 0, 0, 0);
4938 DoPkt(node
->dn_Task
, ACTION_DIE
, 0, 0, 0, 0, 0);
4939 if((list
= LockDosList(LDF_DEVICES
| LDF_WRITE
)))
4941 list
= FindDosEntry(list
, partname
, LDF_DEVICES
);
4946 UnLockDosList(LDF_DEVICES
| LDF_WRITE
);
4948 /*psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
4949 "Unmounting %s done.",
4956 /* /// "nIOCmdTunnel()" */
4957 LONG
nIOCmdTunnel(struct NepClassMS
*ncm
, struct IOStdReq
*ioreq
)
4959 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
4961 if(ncm
->ncm_DenyRequests
)
4964 return(ioreq
->io_Error
= IOERR_ABORTED
);
4966 PutMsg(&ncm
->ncm_Unit
.unit_MsgPort
, (struct Message
*) ioreq
);
4968 while(!GetMsg(nh
->nh_IOMsgPort
))
4970 WaitPort(nh
->nh_IOMsgPort
);
4972 return(ioreq
->io_Error
);
4976 /* /// "nScsiDirectTunnel()" */
4977 LONG
nScsiDirectTunnel(struct NepClassMS
*ncm
, struct SCSICmd
*scsicmd
)
4979 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
4980 struct IOStdReq
*ioreq
= &nh
->nh_IOReq
;
4981 ioreq
->io_Command
= HD_SCSICMD
;
4982 ioreq
->io_Data
= scsicmd
;
4983 ioreq
->io_Length
= sizeof(*scsicmd
);
4984 return(nIOCmdTunnel(ncm
, ioreq
));
4988 /* /// "nGetWriteProtect()" */
4989 LONG
nGetWriteProtect(struct NepClassMS
*ncm
)
4991 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
4993 struct SCSICmd scsicmd
;
4994 UBYTE inquirydata
[256];
4995 UBYTE sensedata
[18];
4998 if((ncm
->ncm_DeviceType
== PDT_WORM
) ||
4999 (ncm
->ncm_DeviceType
== PDT_CDROM
))
5001 // cd roms are always write protected
5002 return(ncm
->ncm_WriteProtect
= TRUE
);
5004 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_SIMPLE_SCSI
)
5006 return(ncm
->ncm_WriteProtect
= FALSE
);
5008 scsicmd
.scsi_Data
= (UWORD
*) inquirydata
;
5009 scsicmd
.scsi_Length
= 8;
5010 scsicmd
.scsi_Command
= cmd10
;
5011 scsicmd
.scsi_CmdLength
= 10;
5012 scsicmd
.scsi_Flags
= SCSIF_READ
|SCSIF_AUTOSENSE
|0x80;
5013 scsicmd
.scsi_SenseData
= sensedata
;
5014 scsicmd
.scsi_SenseLength
= 18;
5015 cmd10
[0] = SCSI_MODE_SENSE_10
;
5016 cmd10
[1] = 0x00; /* no block descriptors */
5017 cmd10
[2] = 0x3f; /* no page, only header */
5025 if((ioerr
= nScsiDirectTunnel(ncm
, &scsicmd
)))
5027 cmd10
[2] = 0x00; /* try again with vendor page, only header */
5028 if((ioerr
= nScsiDirectTunnel(ncm
, &scsicmd
)))
5030 cmd10
[2] = 0x3f; /* try again with 255 length */
5032 if((ioerr
= nScsiDirectTunnel(ncm
, &scsicmd
)))
5034 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
5036 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
5037 "Failed to get write protection state: %ld",
5040 if(!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
))
5042 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_SIMPLE_SCSI
;
5043 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
5044 "Fallback: Enabling Simple SCSI.");
5046 GM_UNIQUENAME(nStoreConfig
)(ncm
);
5051 if(inquirydata
[3] & 0x80)
5053 if(!ncm
->ncm_WriteProtect
)
5055 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_REM_SUPPORT
)
5057 ncm
->ncm_ChangeCount
++;
5058 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
5060 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5061 "Diskchange: GetWriteProtect On (count = %ld)",
5062 ncm
->ncm_ChangeCount
);
5065 ncm
->ncm_WriteProtect
= TRUE
;
5068 if(ncm
->ncm_WriteProtect
)
5070 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_REM_SUPPORT
)
5072 ncm
->ncm_ChangeCount
++;
5073 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
5075 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5076 "Diskchange: GetWriteProtect Off (count = %ld)",
5077 ncm
->ncm_ChangeCount
);
5080 ncm
->ncm_WriteProtect
= FALSE
;
5083 return(ncm
->ncm_WriteProtect
);
5087 /* /// "SearchHardBlock()" */
5088 APTR
SearchHardBlock(struct NepClassMS
*ncm
,
5089 struct IOStdReq
*ioreq
,
5093 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5096 if(!nh
->nh_OneBlock
|| (nh
->nh_OneBlockSize
< ncm
->ncm_BlockSize
))
5098 psdFreeVec(nh
->nh_OneBlock
);
5099 if(!(nh
->nh_OneBlock
= psdAllocVec(ncm
->ncm_BlockSize
)))
5103 nh
->nh_OneBlockSize
= ncm
->ncm_BlockSize
;
5109 ioreq
->io_Command
= TD_READ64
;
5110 ioreq
->io_Data
= nh
->nh_OneBlock
;
5111 ioreq
->io_Length
= ncm
->ncm_BlockSize
;
5112 ioreq
->io_Offset
= curBlock
<<ncm
->ncm_BlockShift
;
5113 ioreq
->io_Actual
= curBlock
>>(32-ncm
->ncm_BlockShift
);
5115 if(!nIOCmdTunnel(ncm
, ioreq
))
5118 if((*(ULONG
*) nh
->nh_OneBlock
) == id
)
5120 return(nh
->nh_OneBlock
);
5123 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Error searching hardblock in block %ld.", curBlock
);
5126 } while(curBlock
<= RDB_LOCATION_LIMIT
);
5131 /* /// "ReadRDSK()" */
5132 BOOL
ReadRDSK(struct NepClassMS
*ncm
,
5133 struct IOStdReq
*ioreq
,
5134 struct RigidDiskBlock
*rdb
)
5136 APTR blkaddr
= SearchHardBlock(ncm
, ioreq
, IDNAME_RIGIDDISK
, 0);
5139 CopyMemQuick(blkaddr
, rdb
, sizeof(struct RigidDiskBlock
));
5140 // endianess conversion
5141 rdb
->rdb_ID
= AROS_BE2LONG(rdb
->rdb_ID
);
5142 rdb
->rdb_SummedLongs
= AROS_BE2LONG(rdb
->rdb_SummedLongs
);
5143 rdb
->rdb_ChkSum
= AROS_BE2LONG(rdb
->rdb_ChkSum
);
5144 rdb
->rdb_HostID
= AROS_BE2LONG(rdb
->rdb_HostID
);
5145 rdb
->rdb_BlockBytes
= AROS_BE2LONG(rdb
->rdb_BlockBytes
);
5146 rdb
->rdb_PartitionList
= AROS_BE2LONG(rdb
->rdb_PartitionList
);
5147 rdb
->rdb_FileSysHeaderList
= AROS_BE2LONG(rdb
->rdb_FileSysHeaderList
);
5148 rdb
->rdb_DriveInit
= AROS_BE2LONG(rdb
->rdb_DriveInit
);
5149 rdb
->rdb_Cylinders
= AROS_BE2LONG(rdb
->rdb_Cylinders
);
5150 rdb
->rdb_Sectors
= AROS_BE2LONG(rdb
->rdb_Sectors
);
5151 rdb
->rdb_Heads
= AROS_BE2LONG(rdb
->rdb_Heads
);
5152 rdb
->rdb_Interleave
= AROS_BE2LONG(rdb
->rdb_Interleave
);
5153 rdb
->rdb_Park
= AROS_BE2LONG(rdb
->rdb_Park
);
5154 rdb
->rdb_WritePreComp
= AROS_BE2LONG(rdb
->rdb_WritePreComp
);
5155 rdb
->rdb_ReducedWrite
= AROS_BE2LONG(rdb
->rdb_ReducedWrite
);
5156 rdb
->rdb_StepRate
= AROS_BE2LONG(rdb
->rdb_StepRate
);
5157 rdb
->rdb_RDBBlocksLo
= AROS_BE2LONG(rdb
->rdb_RDBBlocksLo
);
5158 rdb
->rdb_RDBBlocksHi
= AROS_BE2LONG(rdb
->rdb_RDBBlocksHi
);
5159 rdb
->rdb_LoCylinder
= AROS_BE2LONG(rdb
->rdb_LoCylinder
);
5160 rdb
->rdb_HiCylinder
= AROS_BE2LONG(rdb
->rdb_HiCylinder
);
5161 rdb
->rdb_CylBlocks
= AROS_BE2LONG(rdb
->rdb_CylBlocks
);
5162 rdb
->rdb_AutoParkSeconds
= AROS_BE2LONG(rdb
->rdb_AutoParkSeconds
);
5163 rdb
->rdb_HighRDSKBlock
= AROS_BE2LONG(rdb
->rdb_HighRDSKBlock
);
5170 /* /// "ReadPART()" */
5171 BOOL
ReadPART(struct NepClassMS
*ncm
,
5172 struct IOStdReq
*ioreq
,
5173 struct PartitionBlock
*part
,
5176 APTR blkaddr
= SearchHardBlock(ncm
, ioreq
, IDNAME_PARTITION
, which
);
5180 CopyMemQuick(blkaddr
, part
, sizeof(struct PartitionBlock
));
5181 // endianess conversion
5182 part
->pb_ID
= AROS_BE2LONG(part
->pb_ID
);
5183 part
->pb_SummedLongs
= AROS_BE2LONG(part
->pb_SummedLongs
);
5184 part
->pb_ChkSum
= AROS_BE2LONG(part
->pb_ChkSum
);
5185 part
->pb_HostID
= AROS_BE2LONG(part
->pb_HostID
);
5186 part
->pb_Next
= AROS_BE2LONG(part
->pb_Next
);
5187 part
->pb_Flags
= AROS_BE2LONG(part
->pb_Flags
);
5188 part
->pb_DevFlags
= AROS_BE2LONG(part
->pb_DevFlags
);
5189 for(cnt
= 0; cnt
< 20; cnt
++)
5191 part
->pb_Environment
[cnt
] = AROS_BE2LONG(part
->pb_Environment
[cnt
]);
5199 /* /// "ReadFSHD()" */
5200 BOOL
ReadFSHD(struct NepClassMS
*ncm
,
5201 struct IOStdReq
*ioreq
,
5202 struct FileSysHeaderBlock
*fshd
,
5205 APTR blkaddr
= SearchHardBlock(ncm
, ioreq
, IDNAME_FILESYSHEADER
, which
);
5208 CopyMemQuick(blkaddr
, fshd
, sizeof(struct FileSysHeaderBlock
));
5209 // endianess conversion
5210 fshd
->fhb_ID
= AROS_BE2LONG(fshd
->fhb_ID
);
5211 fshd
->fhb_SummedLongs
= AROS_BE2LONG(fshd
->fhb_SummedLongs
);
5212 fshd
->fhb_ChkSum
= AROS_BE2LONG(fshd
->fhb_ChkSum
);
5213 fshd
->fhb_HostID
= AROS_BE2LONG(fshd
->fhb_HostID
);
5214 fshd
->fhb_Next
= AROS_BE2LONG(fshd
->fhb_Next
);
5215 fshd
->fhb_Flags
= AROS_BE2LONG(fshd
->fhb_Flags
);
5216 fshd
->fhb_DosType
= AROS_BE2LONG(fshd
->fhb_DosType
);
5217 fshd
->fhb_Version
= AROS_BE2LONG(fshd
->fhb_Version
);
5218 fshd
->fhb_PatchFlags
= AROS_BE2LONG(fshd
->fhb_PatchFlags
);
5219 fshd
->fhb_Type
= AROS_BE2LONG(fshd
->fhb_Type
);
5220 fshd
->fhb_Task
= AROS_BE2LONG(fshd
->fhb_Task
);
5221 fshd
->fhb_Lock
= AROS_BE2LONG(fshd
->fhb_Lock
);
5222 fshd
->fhb_Handler
= AROS_BE2LONG(fshd
->fhb_Handler
);
5223 fshd
->fhb_StackSize
= AROS_BE2LONG(fshd
->fhb_StackSize
);
5224 fshd
->fhb_Priority
= AROS_BE2LONG(fshd
->fhb_Priority
);
5225 fshd
->fhb_Startup
= AROS_BE2LONG(fshd
->fhb_Startup
);
5226 fshd
->fhb_SegListBlocks
= AROS_BE2LONG(fshd
->fhb_SegListBlocks
);
5227 fshd
->fhb_GlobalVec
= AROS_BE2LONG(fshd
->fhb_GlobalVec
);
5234 /* /// "ReadLSEG()" */
5235 struct LoadSegBlock
* ReadLSEG(struct NepClassMS
*ncm
,
5236 struct IOStdReq
*ioreq
,
5239 return((struct LoadSegBlock
*) SearchHardBlock(ncm
, ioreq
, IDNAME_LOADSEG
, which
));
5243 /* /// "FindFileSystem()" */
5244 struct FileSysEntry
* FindFileSystem(struct NepClassMS
*ncm
, ULONG dosType
)
5246 struct FileSysResource
*fsr
;
5247 struct FileSysEntry
*fse
;
5249 KPRINTF(10, ("looking up %08lx fs\n", dosType
));
5250 if((fsr
= (struct FileSysResource
*) OpenResource(FSRNAME
)))
5253 fse
= (struct FileSysEntry
*) fsr
->fsr_FileSysEntries
.lh_Head
;
5254 while(fse
->fse_Node
.ln_Succ
)
5256 if(fse
->fse_DosType
== dosType
)
5261 fse
= (struct FileSysEntry
*) fse
->fse_Node
.ln_Succ
;
5270 /* /// "BuildFileSystem()" */
5271 ULONG
BuildFileSystem(struct NepClassMS
*ncm
,
5275 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5276 struct RigidDisk
*rdsk
= &nh
->nh_RDsk
;
5280 struct LoadSegBlock
*lseg
;
5282 nextLSEG
= rdsk
->rdsk_FSHD
.fhb_SegListBlocks
;
5286 if((lseg
= ReadLSEG(ncm
, &nh
->nh_IOReq
, nextLSEG
)))
5288 add
= (AROS_BE2LONG(lseg
->lsb_SummedLongs
) - 5) * sizeof(ULONG
);
5291 CopyMem(lseg
->lsb_LoadData
, fsBuffer
, add
);
5295 nextLSEG
= lseg
->lsb_Next
;
5300 } while(nextLSEG
!= NIL_PTR
);
5305 /* /// "LoadFileSystem()" */
5306 BPTR
LoadFileSystem(struct NepClassMS
*ncm
, ULONG dosType
, struct FileSysEntry
*fse
)
5308 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5309 struct RigidDisk
*rdsk
= &nh
->nh_RDsk
;
5311 BPTR fh
, seg
= BNULL
;
5317 if(rdsk
->rdsk_RDB
.rdb_FileSysHeaderList
!= NIL_PTR
)
5319 nextFSHD
= rdsk
->rdsk_RDB
.rdb_FileSysHeaderList
;
5322 if(ReadFSHD(ncm
, &nh
->nh_IOReq
, &rdsk
->rdsk_FSHD
, nextFSHD
))
5324 nextFSHD
= rdsk
->rdsk_FSHD
.fhb_Next
;
5328 KPRINTF(10, ("Found 0x%08lx FS in FSHD...\n", rdsk
->rdsk_FSHD
.fhb_ID
));
5329 } while((rdsk
->rdsk_FSHD
.fhb_DosType
!= dosType
) && (nextFSHD
!= NIL_PTR
));
5331 if(rdsk
->rdsk_FSHD
.fhb_DosType
== dosType
)
5333 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Found filesystem %s in RDB!",
5334 nh
->nh_RDsk
.rdsk_FSHD
.fhb_FileSysName
);
5335 KPRINTF(10, ("found matching fs in FSHD, trying to load from LSEG blocks\n"));
5337 CopyMem(&rdsk
->rdsk_FSHD
.fhb_DosType
, &fse
->fse_DosType
, sizeof(struct FileSysEntry
) - sizeof(struct Node
));
5339 if(rdsk
->rdsk_FSHD
.fhb_SegListBlocks
> 0)
5341 fsLength
= BuildFileSystem(ncm
, NULL
, FALSE
);
5345 if((fsBuffer
= psdAllocVec(fsLength
)))
5347 BuildFileSystem(ncm
, fsBuffer
, TRUE
);
5349 if(GM_UNIQUENAME(nOpenDOS
)(nh
))
5351 psdSafeRawDoFmt(fsFile
, 32, "T:UMSD_%08lx.fs", dosType
);
5352 if((fh
= Open(fsFile
, MODE_NEWFILE
)))
5354 ok
= (Write(fh
, fsBuffer
, fsLength
) == fsLength
);
5358 seg
= LoadSeg(fsFile
);
5363 KPRINTF(10, ("No DOS available, trying own load seg stuff\n"));
5364 // FIXME this code is unavailable and doesn't make sense for AROS as it doesn't use DOS_HUNK format
5365 //seg = CreateSegment(ncm, (const ULONG *) fsBuffer);
5367 psdFreeVec(fsBuffer
);
5376 if(GM_UNIQUENAME(nOpenDOS
)(nh
))
5378 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Loading filesystem %s from RDB failed. Trying DOS...",
5379 nh
->nh_RDsk
.rdsk_FSHD
.fhb_FileSysName
);
5380 KPRINTF(10, ("loading fs from LSEG blocks failed, trying fs file %s mentioned in FSHD\n", (char *) nh
->nh_RDsk
.rdsk_FSHD
.fhb_FileSysName
));
5381 //seg = LoadSeg(rdsk->rdsk_FSHD.fhb_FileSysName);
5382 seg
= LoadSeg((char *) nh
->nh_RDsk
.rdsk_FSHD
.fhb_FileSysName
);
5385 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Loaded filesystem %s via DOS!",
5386 nh
->nh_RDsk
.rdsk_FSHD
.fhb_FileSysName
);
5388 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Loading filesystem %s via DOS failed!",
5389 nh
->nh_RDsk
.rdsk_FSHD
.fhb_FileSysName
);
5392 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Loading filesystem %s from RDB failed.",
5393 nh
->nh_RDsk
.rdsk_FSHD
.fhb_FileSysName
);
5398 fse
->fse_SegList
= seg
;
5404 /* /// "MatchPartition()" */
5405 BOOL
MatchPartition(struct NepClassMS
*ncm
,
5406 struct DosEnvec
*envec1
,
5407 struct FileSysStartupMsg
*fssm
)
5409 BOOL result
= FALSE
;
5412 struct DosEnvec
*envec2
;
5416 envec2
= (struct DosEnvec
*) BADDR(fssm
->fssm_Environ
);
5420 bstr
= (UBYTE
*) BADDR(fssm
->fssm_Device
);
5421 b2cstr(bstr
, device
);
5425 if((envec1
->de_DosType
& 0xffffff00) == 0x46415400)
5427 result
= ((ncm
->ncm_UnitNo
== fssm
->fssm_Unit
) &&
5428 (strcmp(DEVNAME
, device
) == 0) &&
5429 (envec1
->de_DosType
== envec2
->de_DosType
));
5431 result
= ((ncm
->ncm_UnitNo
== fssm
->fssm_Unit
) &&
5432 (strcmp(DEVNAME
, device
) == 0) &&
5433 (envec1
->de_SizeBlock
== envec2
->de_SizeBlock
) &&
5434 (envec1
->de_Surfaces
== envec2
->de_Surfaces
) &&
5435 (envec1
->de_SectorPerBlock
== envec2
->de_SectorPerBlock
) &&
5436 (envec1
->de_BlocksPerTrack
== envec2
->de_BlocksPerTrack
) &&
5437 (envec1
->de_Reserved
== envec2
->de_Reserved
) &&
5438 (envec1
->de_PreAlloc
== envec2
->de_PreAlloc
) &&
5439 (envec1
->de_Interleave
== envec2
->de_Interleave
) &&
5440 (envec1
->de_LowCyl
== envec2
->de_LowCyl
) &&
5441 (envec1
->de_HighCyl
== envec2
->de_HighCyl
) &&
5442 (envec1
->de_DosType
== envec2
->de_DosType
));
5445 result
= (ncm
->ncm_UnitNo
== fssm
->fssm_Unit
) &&
5446 (strcmp(DEVNAME
, device
) == 0);
5454 /* /// "FindDeviceNode()" */
5455 struct DeviceNode
* FindDeviceNode(struct NepClassMS
*ncm
, STRPTR device
)
5457 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5458 struct DosList
*list
;
5459 struct DeviceNode
*node
= NULL
;
5461 if(!GM_UNIQUENAME(nOpenDOS
)(nh
))
5466 if((list
= LockDosList(LDF_DEVICES
| LDF_READ
)))
5468 node
= (struct DeviceNode
*) FindDosEntry(list
, device
, LDF_DEVICES
);
5469 UnLockDosList(LDF_DEVICES
| LDF_READ
);
5475 /* /// "CheckVolumesOrAssignsMatch()" */
5476 BOOL
CheckVolumesOrAssignsMatch(struct NepClassMS
*ncm
, STRPTR device
)
5478 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5479 struct DosList
*list
;
5482 if(!GM_UNIQUENAME(nOpenDOS
)(nh
))
5487 if((list
= LockDosList(LDF_ALL
| LDF_READ
)))
5489 if(FindDosEntry(list
, device
, LDF_ALL
))
5493 UnLockDosList(LDF_ALL
| LDF_READ
);
5499 /* /// "FindMatchingDevice()" */
5500 struct DeviceNode
* FindMatchingDevice(struct NepClassMS
*ncm
, struct DosEnvec
*envec
)
5502 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5503 struct DosList
*list
;
5504 struct DeviceNode
*node
= NULL
;
5505 struct FileSysStartupMsg
*fssm
;
5507 if(!GM_UNIQUENAME(nOpenDOS
)(nh
))
5512 if((list
= LockDosList(LDF_DEVICES
| LDF_READ
)))
5514 while((list
= NextDosEntry(list
, LDF_DEVICES
| LDF_READ
)))
5518 /*if((!(((ULONG) list->dol_misc.dol_handler.dol_Startup) >> 30)) &&
5519 TypeOfMem(BADDR(list->dol_misc.dol_handler.dol_Startup)))*/
5521 fssm
= BADDR(list
->dol_misc
.dol_handler
.dol_Startup
);
5524 if(fssm
> (struct FileSysStartupMsg
*) 0x1000)
5526 // if((*((UBYTE *) fssm)) == 0)
5528 struct DosEnvec
*de
= BADDR(fssm
->fssm_Environ
);
5529 STRPTR devname
= BADDR(fssm
->fssm_Device
);
5531 if(TypeOfMem(de
) && TypeOfMem(devname
) && (de
->de_TableSize
> 0) && (de
->de_TableSize
< 32))
5532 /*if((!((ULONG) de >> 30)) && TypeOfMem(de) &&
5533 (!((ULONG) devname >> 30)) && TypeOfMem(devname) &&
5534 (de->de_TableSize > 0) && (de->de_TableSize < 32))*/
5536 if(MatchPartition(ncm
, envec
, fssm
))
5538 node
= (struct DeviceNode
*) list
;
5545 UnLockDosList(LDF_DEVICES
| LDF_READ
);
5551 /* /// "MountPartition()" */
5552 BOOL
MountPartition(struct NepClassMS
*ncm
, STRPTR dosDevice
)
5554 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5555 struct RigidDisk
*rdsk
= &nh
->nh_RDsk
;
5557 struct DeviceNode
*node
;
5558 struct FileSysEntry
*fse
;
5559 struct FileSysEntry patch
;
5560 BPTR segList
= BNULL
;
5561 BOOL fsFound
= FALSE
;
5562 BOOL result
= FALSE
;
5563 STRPTR devname
= DEVNAME
;
5565 if((fse
= FindFileSystem(ncm
, rdsk
->rdsk_PART
.pb_Environment
[DE_DOSTYPE
])))
5567 KPRINTF(10, ("fs found in filesys resource\n"));
5568 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Found FS in filesystem.resource!");
5570 CopyMem(fse
, &patch
, sizeof(struct FileSysEntry
));
5573 memset(&patch
, 0x00, sizeof(struct FileSysEntry
));
5574 patch
.fse_DosType
= rdsk
->rdsk_PART
.pb_Environment
[DE_DOSTYPE
];
5576 if((segList
= LoadFileSystem(ncm
, rdsk
->rdsk_PART
.pb_Environment
[DE_DOSTYPE
], &patch
)))
5578 KPRINTF(10, ("fs loaded from RDB\n"));
5580 patch
.fse_PatchFlags
= 0x0080|0x0010;
5581 patch
.fse_SegList
= segList
;
5582 patch
.fse_StackSize
= (AROS_STACKSIZE
<< 1);
5583 //if(((patch.fse_DosType & 0xffffff00) == 0x46415400) || (patch.fse_DosType == 0x4d534800))
5585 KPRINTF(10, ("setting up certain fs values for MS-DOS fs\n"));
5586 // Stack, SegList, Pri und GlobVec eintragen
5587 patch
.fse_PatchFlags
|= 0x0020|0x0100;
5588 patch
.fse_Priority
= 10;
5589 patch
.fse_GlobalVec
= (BPTR
) 0xffffffff;
5598 STRPTR handler
= (STRPTR
) nh
->nh_RDsk
.rdsk_FSHD
.fhb_FileSysName
;
5599 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Experimental AROS patch to load %s", handler
);
5600 patch
.fse_Handler
= MKBADDR(AllocVec(AROS_BSTR_MEMSIZE4LEN(strlen(handler
)), MEMF_PUBLIC
| MEMF_CLEAR
));
5601 if(patch
.fse_Handler
)
5603 c2bstr(handler
, patch
.fse_Handler
);
5604 patch
.fse_PatchFlags
|= 0x0008;
5611 if((params
= psdAllocVec(sizeof(struct DosEnvec
) + 4 * sizeof(IPTR
))))
5613 params
[0] = (IPTR
) dosDevice
;
5614 params
[1] = (IPTR
) DEVNAME
;
5615 params
[2] = ncm
->ncm_UnitNo
;
5616 params
[3] = 0x00; // Flags for OpenDevice
5617 CopyMem(rdsk
->rdsk_PART
.pb_Environment
, ¶ms
[4], sizeof(struct DosEnvec
));
5619 if((node
= MakeDosNode(params
)))
5622 KPRINTF(10, ("MakeDosNode() succeeded, patchflags %04lx\n", patch
.fse_PatchFlags
));
5623 node
->dn_StackSize
= (AROS_STACKSIZE
<< 1);
5625 /*node->dn_Priority = 5;*/
5626 if(patch
.fse_PatchFlags
& 0x0001) node
->dn_Type
= patch
.fse_Type
;
5627 if(patch
.fse_PatchFlags
& 0x0002) node
->dn_Task
= (struct MsgPort
*) patch
.fse_Task
;
5628 if(patch
.fse_PatchFlags
& 0x0004) node
->dn_Lock
= patch
.fse_Lock
;
5629 if(patch
.fse_PatchFlags
& 0x0008) node
->dn_Handler
= patch
.fse_Handler
;
5630 if(patch
.fse_PatchFlags
& 0x0010) node
->dn_StackSize
= patch
.fse_StackSize
;
5631 if(patch
.fse_PatchFlags
& 0x0020) node
->dn_Priority
= patch
.fse_Priority
;
5632 if(patch
.fse_PatchFlags
& 0x0040) node
->dn_Startup
= patch
.fse_Startup
;
5633 if(patch
.fse_PatchFlags
& 0x0080) node
->dn_SegList
= patch
.fse_SegList
;
5634 if(patch
.fse_PatchFlags
& 0x0100) node
->dn_GlobalVec
= patch
.fse_GlobalVec
;
5636 KPRINTF(10, ("dn_Next = %08lx\n"
5640 "dn_Handler = %08lx\n"
5641 "dn_StackSize = %08ld\n"
5642 "dn_Priority = %08ld\n"
5643 "dn_Startup = %08lx\n"
5644 "dn_SegList = %08lx\n"
5645 "dn_GlobalVec = %08lx\n"
5646 "dn_Name = %08lx\n",
5659 installboot
= ncm
->ncm_CUC
->cuc_BootRDB
;
5660 if((nh
->nh_RemovableTask
->tc_Node
.ln_Type
== NT_PROCESS
) ||
5661 (!(nh
->nh_RDsk
.rdsk_PART
.pb_Flags
& PBFF_BOOTABLE
)))
5663 installboot
= FALSE
;
5667 // avoid sys partition being unmounted (actually it should better check at
5668 // unmounting, but I can't think of a clever way yet to retrieve the SYS:
5670 ncm
->ncm_CUC
->cuc_AutoUnmount
= FALSE
;
5671 GM_UNIQUENAME(nStoreConfig
)(ncm
);
5674 if(AddBootNode(nh
->nh_RDsk
.rdsk_PART
.pb_Environment
[DE_BOOTPRI
], ADNF_STARTPROC
, node
, NULL
))
5676 KPRINTF(10, ("AddBootNode() succeeded\n"));
5677 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5678 "Mounted %s unit %ld as %s:",
5679 devname
, ncm
->ncm_UnitNo
, dosDevice
);
5683 KPRINTF(10, ("AddBootNode() failed\n"));
5684 /* There is a memory leak here! No way to deallocate the node created by
5693 if(GM_UNIQUENAME(nOpenDOS
)(nh
))
5699 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
5700 "Couldn't find/load filesystem for %s unit %ld as %s:",
5701 devname
, ncm
->ncm_UnitNo
, dosDevice
);
5702 KPRINTF(10, ("fs %08lx not found\n", rdsk
->rdsk_PART
.pb_Environment
[DE_DOSTYPE
]));
5709 /* /// "CheckPartition()" */
5710 void CheckPartition(struct NepClassMS
*ncm
)
5712 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5713 struct RigidDisk
*rdsk
= &nh
->nh_RDsk
;
5714 struct DosEnvec
*envec
;
5715 UBYTE dosDevice
[32], temp
[32];
5717 struct DeviceNode
*node
;
5718 BOOL done
= FALSE
, doMount
= TRUE
;
5719 STRPTR devname
= DEVNAME
;
5723 envec
= (struct DosEnvec
*) rdsk
->rdsk_PART
.pb_Environment
;
5724 if((node
= FindMatchingDevice(ncm
, envec
)))
5726 KPRINTF(10, ("found suitable device entry, no need to mount anything new\n"));
5728 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5729 "Matching partition for %s unit %ld already found. No remount required.",
5730 devname
, ncm
->ncm_UnitNo
);
5735 b2cstr(rdsk
->rdsk_PART
.pb_DriveName
, dosDevice
);
5737 KPRINTF(10, ("trying to mount partition \"%s\"\n", dosDevice
));
5739 /*if(envec->de_TableSize >= DE_DOSTYPE) SHOWVALUE(envec->de_DosType);*/
5743 if((node
= FindDeviceNode(ncm
, dosDevice
)))
5745 KPRINTF(10, ("%s is already mounted, comparing fssm\n", dosDevice
));
5747 if(MatchPartition(ncm
, envec
, BADDR(node
->dn_Startup
)))
5749 KPRINTF(10, ("fssm match, no need to mount\n"));
5757 if(CheckVolumesOrAssignsMatch(ncm
, dosDevice
))
5766 slen
= strlen(dosDevice
);
5767 if((slen
> 0) && (dosDevice
[slen
-1] >= '0') && (dosDevice
[slen
-1] <= '9'))
5769 if(dosDevice
[slen
-1] == '9')
5771 if((slen
> 1) && (dosDevice
[slen
-2] >= '0') && (dosDevice
[slen
-2] <= '8'))
5773 dosDevice
[slen
-2]++;
5774 dosDevice
[slen
-1] = '0';
5778 dosDevice
[slen
-1] = '1';
5779 dosDevice
[slen
] = '0';
5780 dosDevice
[slen
+1] = 0;
5786 dosDevice
[slen
-1]++;
5789 b2cstr(rdsk
->rdsk_PART
.pb_DriveName
, temp
);
5790 psdSafeRawDoFmt(dosDevice
, 32, "%s.%ld", temp
, spareNum
);
5792 KPRINTF(10, ("fssm don't match, trying as %s\n", dosDevice
));
5795 } while(!done
&& (spareNum
< 16));
5800 KPRINTF(10, ("mounting %s\n", dosDevice
));
5802 MountPartition(ncm
, dosDevice
);
5807 /* /// "IsFATSuperBlock()" */
5808 BOOL
IsFATSuperBlock(struct FATSuperBlock
*fsb
)
5811 result
= (BOOL
)(strncmp(fsb
->fsb_Vendor
, "MSDOS", 5) == 0 ||
5812 strncmp(fsb
->fsb_Vendor
, "MSWIN", 5) == 0 ||
5813 strncmp(fsb
->fsb_FileSystem
, "FAT12", 5) == 0 ||
5814 strncmp(fsb
->fsb_FileSystem
, "FAT16", 5) == 0 ||
5815 strncmp(fsb
->fsb_FileSystem2
, "FAT32", 5) == 0);
5821 /* /// "GetFATDosType()" */
5822 ULONG
GetFATDosType(struct FATSuperBlock
*fsb
)
5824 ULONG result
= 0x46415400;
5825 if(strncmp(fsb
->fsb_FileSystem2
, "FAT32", 5) == 0)
5827 else if(strncmp(fsb
->fsb_FileSystem
, "FAT16", 5) == 0)
5834 /* /// "CheckFATPartition()" */
5835 void CheckFATPartition(struct NepClassMS
*ncm
, ULONG startblock
)
5837 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5838 struct MasterBootRecord
*mbr
;
5839 struct DosEnvec
*envec
;
5840 struct IOStdReq
*stdIO
= &nh
->nh_IOReq
;
5841 struct DriveGeometry
*tddg
= &ncm
->ncm_Geometry
;
5843 BOOL isntfs
= FALSE
;
5845 mbr
= (struct MasterBootRecord
*) psdAllocVec(ncm
->ncm_BlockSize
<<1);
5851 stdIO
->io_Command
= TD_READ64
;
5852 stdIO
->io_Offset
= startblock
<<ncm
->ncm_BlockShift
;
5853 stdIO
->io_Actual
= startblock
>>(32-ncm
->ncm_BlockShift
);
5854 stdIO
->io_Length
= ncm
->ncm_BlockSize
;
5855 stdIO
->io_Data
= mbr
;
5856 if(!nIOCmdTunnel(ncm
, stdIO
))
5858 /* do (super)floppy check */
5859 if(IsFATSuperBlock((struct FATSuperBlock
*) mbr
))
5861 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Media is FAT formatted!");
5863 nh
->nh_RDsk
.rdsk_PART
.pb_DevFlags
= 0;
5865 if(*(ncm
->ncm_CUC
->cuc_FATDOSName
))
5867 c2bstr(ncm
->ncm_CUC
->cuc_FATDOSName
, nh
->nh_RDsk
.rdsk_PART
.pb_DriveName
);
5869 c2bstr("UF0", nh
->nh_RDsk
.rdsk_PART
.pb_DriveName
);
5872 envec
= (struct DosEnvec
*) nh
->nh_RDsk
.rdsk_PART
.pb_Environment
;
5873 memset(envec
, 0x00, sizeof(struct DosEnvec
));
5874 stdIO
->io_Command
= TD_GETGEOMETRY
;
5875 stdIO
->io_Data
= tddg
;
5876 stdIO
->io_Length
= sizeof(*tddg
);
5878 if(nIOCmdTunnel(ncm
, stdIO
))
5880 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Couldn't read drive geometry, using floppy defaults");
5881 envec
->de_SizeBlock
= ncm
->ncm_BlockSize
>>2;
5882 envec
->de_Surfaces
= 2;
5883 envec
->de_BlocksPerTrack
= 18;
5884 envec
->de_LowCyl
= 0;
5885 envec
->de_HighCyl
= 79;
5887 envec
->de_SizeBlock
= ncm
->ncm_BlockSize
>>2;
5888 envec
->de_Surfaces
= tddg
->dg_Heads
;
5889 envec
->de_BlocksPerTrack
= tddg
->dg_TrackSectors
;
5890 envec
->de_LowCyl
= 0;
5891 envec
->de_HighCyl
= tddg
->dg_Cylinders
-1;
5893 envec
->de_TableSize
= DE_BOOTBLOCKS
;
5894 envec
->de_SectorPerBlock
= 1;
5895 envec
->de_NumBuffers
= ncm
->ncm_CUC
->cuc_FATBuffers
;
5896 envec
->de_BufMemType
= MEMF_PUBLIC
;
5897 envec
->de_MaxTransfer
= (1UL<<(ncm
->ncm_CDC
->cdc_MaxTransfer
+16))-1;
5898 envec
->de_Mask
= 0xffffffff;
5899 envec
->de_BootPri
= 0;
5900 envec
->de_Baud
= 1200;
5901 if(*ncm
->ncm_CDC
->cdc_FATControl
)
5903 UBYTE
*bptr
= ncm
->ncm_FATControlBSTR
;
5904 bptr
= (UBYTE
*) ((((IPTR
) bptr
) + 3) & (~3));
5905 c2bstr(ncm
->ncm_CDC
->cdc_FATControl
, bptr
);
5906 envec
->de_Control
= (IPTR
) MKBADDR(bptr
);
5908 envec
->de_Control
= 0;
5910 envec
->de_BootBlocks
= 0;
5911 envec
->de_Interleave
= 0;
5912 envec
->de_DosType
= ncm
->ncm_CDC
->cdc_FATDosType
; //0x46415401; // FAT1
5913 if((ncm
->ncm_CDC
->cdc_FATDosType
& 0xffffff00) == 0x46415400)
5916 GetFATDosType((struct FATSuperBlock
*) mbr
);
5919 // we have no FSHD and LSEG blocks
5920 nh
->nh_RDsk
.rdsk_RDB
.rdb_FileSysHeaderList
= NIL_PTR
;
5921 nh
->nh_RDsk
.rdsk_FSHD
.fhb_SegListBlocks
= 0;
5923 KPRINTF(5, ("building FAT95 style environment\n"));
5925 strncpy((char *) nh
->nh_RDsk
.rdsk_FSHD
.fhb_FileSysName
, ncm
->ncm_CDC
->cdc_FATFSName
, 84);
5926 CheckPartition(ncm
);
5928 if(!(isfat
|| isntfs
))
5930 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5931 "Media does not seem to be FAT nor NTFS formatted.");
5934 KPRINTF(10, ("failed to read MBR\n"));
5935 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
5937 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
5938 "Failed to read MasterBootRecord for FAT/NTFS AutoMounting.");
5945 /* /// "CheckISO9660()" */
5946 void CheckISO9660(struct NepClassMS
*ncm
)
5948 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5950 struct IOStdReq
*stdIO
= &nh
->nh_IOReq
;
5952 blockbuf
= (UBYTE
*) psdAllocVec(ncm
->ncm_BlockSize
);
5957 stdIO
->io_Command
= TD_READ64
;
5958 stdIO
->io_Offset
= 0x8000;
5959 stdIO
->io_Actual
= 0;
5960 stdIO
->io_Length
= ncm
->ncm_BlockSize
;
5961 stdIO
->io_Data
= blockbuf
;
5962 if(!nIOCmdTunnel(ncm
, stdIO
))
5964 if((((ULONG
*) blockbuf
)[0] == AROS_LONG2BE(0x01434430)) && (((ULONG
*) blockbuf
)[1] == AROS_LONG2BE(0x30310100)))
5966 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Media is ISO9660.");
5970 KPRINTF(10, ("failed to read ISO sector\n"));
5971 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
5973 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
5974 "Failed to read block 16 for CDFS AutoMounting.");
5977 psdFreeVec(blockbuf
);
5981 /* /// "AutoMountCD()" */
5982 void AutoMountCD(struct NepClassMS
*ncm
)
5984 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5985 struct DosEnvec
*envec
;
5987 nh
->nh_RDsk
.rdsk_PART
.pb_DevFlags
= 0;
5989 if(*(ncm
->ncm_CUC
->cuc_FATDOSName
))
5991 c2bstr(ncm
->ncm_CUC
->cuc_FATDOSName
, nh
->nh_RDsk
.rdsk_PART
.pb_DriveName
);
5993 c2bstr("UCD0", nh
->nh_RDsk
.rdsk_PART
.pb_DriveName
);
5996 envec
= (struct DosEnvec
*) nh
->nh_RDsk
.rdsk_PART
.pb_Environment
;
5997 memset(envec
, 0x00, sizeof(struct DosEnvec
));
5999 envec
->de_TableSize
= DE_BOOTBLOCKS
;
6000 envec
->de_SizeBlock
= ncm
->ncm_BlockSize
>>2;
6001 envec
->de_Surfaces
= 1;
6002 envec
->de_SectorPerBlock
= 1;
6003 envec
->de_Reserved
= 0xffffffff;
6004 envec
->de_NumBuffers
= ncm
->ncm_CUC
->cuc_FATBuffers
;
6005 envec
->de_BufMemType
= MEMF_PUBLIC
;
6006 envec
->de_MaxTransfer
= (1UL<<(ncm
->ncm_CDC
->cdc_MaxTransfer
+16))-1;
6007 envec
->de_Mask
= 0xffffffff;
6008 envec
->de_BootPri
= 0;
6009 envec
->de_Baud
= 1200;
6010 if(*ncm
->ncm_CDC
->cdc_CDControl
)
6012 UBYTE
*bptr
= ncm
->ncm_FATControlBSTR
;
6013 bptr
= (UBYTE
*) ((((IPTR
) bptr
) + 3) & (~3));
6014 c2bstr(ncm
->ncm_CDC
->cdc_CDControl
, bptr
);
6015 envec
->de_Control
= (IPTR
) MKBADDR(bptr
);
6017 envec
->de_Control
= 0;
6019 envec
->de_BootBlocks
= 0;
6021 // we have no FSHD and LSEG blocks
6022 nh
->nh_RDsk
.rdsk_RDB
.rdb_FileSysHeaderList
= NIL_PTR
;
6023 nh
->nh_RDsk
.rdsk_FSHD
.fhb_SegListBlocks
= 0;
6025 KPRINTF(5, ("building CDFS style environment\n"));
6027 envec
->de_BlocksPerTrack
= 1;
6028 envec
->de_Interleave
= 0;
6029 envec
->de_DosType
= ncm
->ncm_CDC
->cdc_CDDosType
;
6030 envec
->de_LowCyl
= 0;
6031 envec
->de_HighCyl
= 1;
6033 strncpy((char *) nh
->nh_RDsk
.rdsk_FSHD
.fhb_FileSysName
, ncm
->ncm_CDC
->cdc_CDFSName
, 84);
6034 CheckPartition(ncm
);
6038 /**************************************************************************/
6040 static const char *MaxTransferStrings
[] =
6051 static char *MainGUIPages
[] = { "Device Settings", "LUN Settings", NULL
};
6052 static char *MainGUIPagesDefault
[] = { "Device Defaults", "LUN Defaults", NULL
};
6054 /* /// "nGetDosType()" */
6055 ULONG
nGetDosType(STRPTR tmpstr
)
6060 while((ch
= *tmpstr
++))
6063 if((ch
>= '0') && (ch
<= '9'))
6065 dostype
+= ch
- '0';
6067 else if((ch
>= 'a') && (ch
<= 'f'))
6069 dostype
+= ch
- 'a' + 10;
6071 else if((ch
>= 'A') && (ch
<= 'F'))
6073 dostype
+= ch
- 'A' + 10;
6080 /* /// "nGUITask()" */
6081 AROS_UFH0(void, GM_UNIQUENAME(nGUITask
))
6085 struct Task
*thistask
;
6086 struct NepMSBase
*nh
;
6087 struct NepClassMS
*ncm
;
6088 struct NepClassMS
*cncm
;
6089 struct NepClassMS
*curncm
= NULL
;
6091 char dostypebuf
[10];
6092 char cddostypebuf
[10];
6093 char ntfsdostypebuf
[10];
6094 char bar
[] = "BAR,";
6096 thistask
= FindTask(NULL
);
6098 #define ps ncm->ncm_PsdBase
6099 #undef IntuitionBase
6100 #define IntuitionBase ncm->ncm_IntBase
6101 #undef MUIMasterBase
6102 #define MUIMasterBase ncm->ncm_MUIBase
6104 ncm
= thistask
->tc_UserData
;
6105 nh
= ncm
->ncm_ClsBase
;
6107 ++nh
->nh_Library
.lib_OpenCnt
;
6108 if(!(MUIMasterBase
= OpenLibrary(MUIMASTER_NAME
, MUIMASTER_VMIN
)))
6110 KPRINTF(10, ("Couldn't open muimaster.library.\n"));
6111 GM_UNIQUENAME(nGUITaskCleanup
)(ncm
);
6115 if(!(IntuitionBase
= OpenLibrary("intuition.library", 39)))
6117 KPRINTF(10, ("Couldn't open intuition.library.\n"));
6118 GM_UNIQUENAME(nGUITaskCleanup
)(ncm
);
6121 if(!(ps
= OpenLibrary("poseidon.library", 4)))
6123 KPRINTF(10, ("Couldn't open poseidon.library.\n"));
6124 GM_UNIQUENAME(nGUITaskCleanup
)(ncm
);
6128 ncm
->ncm_LUNListDisplayHook
.h_Data
= NULL
;
6129 ncm
->ncm_LUNListDisplayHook
.h_Entry
= (APTR
) GM_UNIQUENAME(LUNListDisplayHook
);
6131 psdSafeRawDoFmt(dostypebuf
, 10, "%08lx", ncm
->ncm_CDC
->cdc_FATDosType
);
6132 psdSafeRawDoFmt(ntfsdostypebuf
, 10, "%08lx", ncm
->ncm_CDC
->cdc_NTFSDosType
);
6133 psdSafeRawDoFmt(cddostypebuf
, 10, "%08lx", ncm
->ncm_CDC
->cdc_CDDosType
);
6135 ncm
->ncm_App
= (APTR
) ApplicationObject
,
6136 MUIA_Application_Title
, (IPTR
) GM_UNIQUENAME(libname
),
6137 MUIA_Application_Version
, (IPTR
) VERSION_STRING
,
6138 MUIA_Application_Copyright
, (IPTR
) "©2002-2009 Chris Hodges",
6139 MUIA_Application_Author
, (IPTR
) "Chris Hodges <chrisly@platon42.de>",
6140 MUIA_Application_Description
, (IPTR
) "Settings for the massstorage.class",
6141 MUIA_Application_Base
, (IPTR
) "MASSSTORAGE",
6142 MUIA_Application_HelpFile
, (IPTR
) "HELP:Poseidon.guide",
6143 MUIA_Application_Menustrip
, (IPTR
) MenustripObject
,
6144 Child
, (IPTR
) MenuObjectT((IPTR
) "Project"),
6145 Child
, (IPTR
) (ncm
->ncm_AboutMI
= (APTR
) MenuitemObject
,
6146 MUIA_Menuitem_Title
, (IPTR
) "About...",
6147 MUIA_Menuitem_Shortcut
, (IPTR
) "?",
6150 Child
, (IPTR
) MenuObjectT((IPTR
) "Settings"),
6151 Child
, (IPTR
) (ncm
->ncm_UseMI
= (APTR
) MenuitemObject
,
6152 MUIA_Menuitem_Title
, (IPTR
) "Save",
6153 MUIA_Menuitem_Shortcut
, (IPTR
) "S",
6155 Child
, (IPTR
) (ncm
->ncm_SetDefaultMI
= (APTR
) MenuitemObject
,
6156 MUIA_Menuitem_Title
, (IPTR
) "Save as Default",
6157 MUIA_Menuitem_Shortcut
, (IPTR
) "D",
6159 Child
, (IPTR
) MenuitemObject
,
6160 MUIA_Menuitem_Title
, (IPTR
) NM_BARLABEL
,
6162 Child
, (IPTR
) (ncm
->ncm_MUIPrefsMI
= (APTR
) MenuitemObject
,
6163 MUIA_Menuitem_Title
, (IPTR
) "MUI Settings",
6164 MUIA_Menuitem_Shortcut
, (IPTR
) "M",
6169 SubWindow
, (IPTR
) (ncm
->ncm_MainWindow
= (APTR
) WindowObject
,
6170 MUIA_Window_ID
, MAKE_ID('M','A','I','N'),
6171 MUIA_Window_Title
, (IPTR
) GM_UNIQUENAME(libname
),
6172 MUIA_HelpNode
, (IPTR
) GM_UNIQUENAME(libname
),
6174 WindowContents
, (IPTR
) VGroup
,
6175 Child
, (IPTR
) RegisterGroup(ncm
->ncm_Interface
? MainGUIPages
: MainGUIPagesDefault
),
6177 MUIA_Register_Frame
, TRUE
,
6178 Child
, (IPTR
) VGroup
,
6179 Child
, (IPTR
) VSpace(0),
6180 Child
, (IPTR
) ColGroup(2),
6181 Child
, (IPTR
) Label("NAK Timeout:"),
6182 Child
, (IPTR
) (ncm
->ncm_NakTimeoutObj
= (APTR
) SliderObject
, SliderFrame
,
6184 MUIA_Numeric_Min
, 0,
6185 MUIA_Numeric_Max
, 600,
6186 MUIA_Numeric_Value
, ncm
->ncm_CDC
->cdc_NakTimeout
,
6187 MUIA_Numeric_Format
, (IPTR
) "%ld00ms",
6189 Child
, (IPTR
) Label("Startup delay:"),
6190 Child
, (IPTR
) (ncm
->ncm_StartupDelayObj
= (APTR
) SliderObject
, SliderFrame
,
6192 MUIA_Numeric_Min
, 0,
6193 MUIA_Numeric_Max
, 100,
6194 MUIA_Numeric_Value
, ncm
->ncm_CDC
->cdc_StartupDelay
,
6195 MUIA_Numeric_Format
, (IPTR
) "%ld00ms",
6197 Child
, (IPTR
) Label("Single LUN:"),
6198 Child
, (IPTR
) HGroup
,
6199 Child
, (IPTR
) (ncm
->ncm_SingleLunObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6200 MUIA_Background
, MUII_ButtonBack
,
6202 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6203 MUIA_Image_Spec
, MUII_CheckMark
,
6204 MUIA_Image_FreeVert
, TRUE
,
6205 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_SINGLE_LUN
,
6206 MUIA_ShowSelState
, FALSE
,
6208 Child
, (IPTR
) HSpace(0),
6209 Child
, (IPTR
) Label("No Initial Reset:"),
6210 Child
, (IPTR
) (ncm
->ncm_InitialResetObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6211 MUIA_Background
, MUII_ButtonBack
,
6213 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6214 MUIA_Image_Spec
, MUII_CheckMark
,
6215 MUIA_Image_FreeVert
, TRUE
,
6216 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_RESET
,
6217 MUIA_ShowSelState
, FALSE
,
6220 Child
, (IPTR
) Label("Simple SCSI:"),
6221 Child
, (IPTR
) HGroup
,
6222 Child
, (IPTR
) (ncm
->ncm_SimpleSCSIObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6223 MUIA_Background
, MUII_ButtonBack
,
6225 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6226 MUIA_Image_Spec
, MUII_CheckMark
,
6227 MUIA_Image_FreeVert
, TRUE
,
6228 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_SIMPLE_SCSI
,
6229 MUIA_ShowSelState
, FALSE
,
6231 Child
, (IPTR
) HSpace(0),
6232 Child
, (IPTR
) Label("Translate CMD6->CMD10:"),
6233 Child
, (IPTR
) (ncm
->ncm_XLate610Obj
= (APTR
) ImageObject
, ImageButtonFrame
,
6234 MUIA_Background
, MUII_ButtonBack
,
6236 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6237 MUIA_Image_Spec
, MUII_CheckMark
,
6238 MUIA_Image_FreeVert
, TRUE
,
6239 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_MODE_XLATE
,
6240 MUIA_ShowSelState
, FALSE
,
6243 Child
, (IPTR
) Label("Fake Inquiry:"),
6244 Child
, (IPTR
) HGroup
,
6245 Child
, (IPTR
) (ncm
->ncm_FakeInquiryObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6246 MUIA_Background
, MUII_ButtonBack
,
6248 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6249 MUIA_Image_Spec
, MUII_CheckMark
,
6250 MUIA_Image_FreeVert
, TRUE
,
6251 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_FAKE_INQUIRY
,
6252 MUIA_ShowSelState
, FALSE
,
6254 Child
, (IPTR
) HSpace(0),
6255 Child
, (IPTR
) Label("Better Removable Support:"),
6256 Child
, (IPTR
) (ncm
->ncm_RemSupportObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6257 MUIA_Background
, MUII_ButtonBack
,
6259 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6260 MUIA_Image_Spec
, MUII_CheckMark
,
6261 MUIA_Image_FreeVert
, TRUE
,
6262 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_REM_SUPPORT
,
6263 MUIA_ShowSelState
, FALSE
,
6266 Child
, (IPTR
) Label("Trim Inquiry:"),
6267 Child
, (IPTR
) HGroup
,
6268 Child
, (IPTR
) (ncm
->ncm_FixInquiryObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6269 MUIA_Background
, MUII_ButtonBack
,
6271 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6272 MUIA_Image_Spec
, MUII_CheckMark
,
6273 MUIA_Image_FreeVert
, TRUE
,
6274 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_FIX_INQ36
,
6275 MUIA_ShowSelState
, FALSE
,
6277 Child
, (IPTR
) HSpace(0),
6278 Child
, (IPTR
) Label("Ignore broken CSS-ID:"),
6279 Child
, (IPTR
) (ncm
->ncm_CSSBrokenObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6280 MUIA_Background
, MUII_ButtonBack
,
6282 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6283 MUIA_Image_Spec
, MUII_CheckMark
,
6284 MUIA_Image_FreeVert
, TRUE
,
6285 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_CSS_BROKEN
,
6286 MUIA_ShowSelState
, FALSE
,
6289 Child
, (IPTR
) Label("Fix Capacity:"),
6290 Child
, (IPTR
) HGroup
,
6291 Child
, (IPTR
) (ncm
->ncm_FixCapacityObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6292 MUIA_Background
, MUII_ButtonBack
,
6294 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6295 MUIA_Image_Spec
, MUII_CheckMark
,
6296 MUIA_Image_FreeVert
, TRUE
,
6297 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_FIX_CAPACITY
,
6298 MUIA_ShowSelState
, FALSE
,
6300 Child
, (IPTR
) HSpace(0),
6301 Child
, (IPTR
) Label("Emulate on larger block sizes:"),
6302 Child
, (IPTR
) (ncm
->ncm_EmulLargeBlkObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6303 MUIA_Background
, MUII_ButtonBack
,
6305 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6306 MUIA_Image_Spec
, MUII_CheckMark
,
6307 MUIA_Image_FreeVert
, TRUE
,
6308 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_EMUL_LARGE_BLK
,
6309 MUIA_ShowSelState
, FALSE
,
6312 Child
, (IPTR
) Label("No Fallback:"),
6313 Child
, (IPTR
) HGroup
,
6314 Child
, (IPTR
) (ncm
->ncm_NoFallbackObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6315 MUIA_Background
, MUII_ButtonBack
,
6317 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6318 MUIA_Image_Spec
, MUII_CheckMark
,
6319 MUIA_Image_FreeVert
, TRUE
,
6320 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
,
6321 MUIA_ShowSelState
, FALSE
,
6323 Child
, (IPTR
) HSpace(0),
6324 Child
, (IPTR
) Label("Debug:"),
6325 Child
, (IPTR
) (ncm
->ncm_DebugObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6326 MUIA_Background
, MUII_ButtonBack
,
6328 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6329 MUIA_Image_Spec
, MUII_CheckMark
,
6330 MUIA_Image_FreeVert
, TRUE
,
6331 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
,
6332 MUIA_ShowSelState
, FALSE
,
6335 Child
, (IPTR
) Label("Max Transfer:"),
6336 Child
, (IPTR
) HGroup
,
6337 Child
, (IPTR
) (ncm
->ncm_MaxTransferObj
= (APTR
) CycleObject
,
6338 MUIA_Cycle_Entries
, (IPTR
) MaxTransferStrings
,
6339 MUIA_Cycle_Active
, ncm
->ncm_CDC
->cdc_MaxTransfer
,
6342 Child
, (IPTR
) (ncm
->ncm_AutoDtxMaxTransObj
= (APTR
) TextObject
, ButtonFrame
,
6343 MUIA_Disabled
, !ncm
->ncm_Interface
,
6344 MUIA_Background
, MUII_ButtonBack
,
6346 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
6347 MUIA_Text_Contents
, (IPTR
) "\33c Auto-detect ",
6351 Child
, (IPTR
) VSpace(0),
6353 Child
, (IPTR
) ColGroup(6),
6354 Child
, (IPTR
) Label("FAT:"),
6355 Child
, (IPTR
) PopaslObject
,
6356 MUIA_Popstring_String
, (IPTR
) (ncm
->ncm_FatFSObj
= (APTR
) StringObject
,
6359 MUIA_String_AdvanceOnCR
, TRUE
,
6360 MUIA_String_Contents
, (IPTR
) ncm
->ncm_CDC
->cdc_FATFSName
,
6361 MUIA_String_MaxLen
, 63,
6363 MUIA_Popstring_Button
, (IPTR
) PopButton(MUII_PopFile
),
6364 ASLFR_TitleText
, (IPTR
) "Select filesystem to use with FAT partitions...",
6366 Child
, (IPTR
) Label("DosType:"),
6367 Child
, (IPTR
) (ncm
->ncm_FatDosTypeObj
= (APTR
) StringObject
,
6369 MUIA_HorizWeight
, 50,
6371 MUIA_String_AdvanceOnCR
, TRUE
,
6372 MUIA_String_Contents
, (IPTR
) dostypebuf
,
6373 MUIA_String_Accept
, (IPTR
) "0123456789abcdefABCDEF",
6374 MUIA_String_MaxLen
, 9,
6376 Child
, (IPTR
) Label("Ctrl:"),
6377 Child
, (IPTR
) (ncm
->ncm_FatControlObj
= (APTR
) StringObject
,
6379 MUIA_HorizWeight
, 50,
6381 MUIA_String_AdvanceOnCR
, TRUE
,
6382 MUIA_String_Contents
, (IPTR
) ncm
->ncm_CDC
->cdc_FATControl
,
6383 MUIA_String_MaxLen
, 63,
6385 Child
, (IPTR
) Label("NTFS:"),
6386 Child
, (IPTR
) PopaslObject
,
6387 MUIA_Popstring_String
, (IPTR
) (ncm
->ncm_NTFSObj
= (APTR
) StringObject
,
6390 MUIA_String_AdvanceOnCR
, TRUE
,
6391 MUIA_String_Contents
, (IPTR
) ncm
->ncm_CDC
->cdc_NTFSName
,
6392 MUIA_String_MaxLen
, 63,
6394 MUIA_Popstring_Button
, (IPTR
) PopButton(MUII_PopFile
),
6395 ASLFR_TitleText
, (IPTR
) "Select filesystem to use with NTFS partitions...",
6397 Child
, (IPTR
) Label("DosType:"),
6398 Child
, (IPTR
) (ncm
->ncm_NTFSDosTypeObj
= (APTR
) StringObject
,
6400 MUIA_HorizWeight
, 50,
6402 MUIA_String_AdvanceOnCR
, TRUE
,
6403 MUIA_String_Contents
, (IPTR
) ntfsdostypebuf
,
6404 MUIA_String_Accept
, (IPTR
) "0123456789abcdefABCDEF",
6405 MUIA_String_MaxLen
, 9,
6407 Child
, (IPTR
) Label("Ctrl:"),
6408 Child
, (IPTR
) (ncm
->ncm_NTFSControlObj
= (APTR
) StringObject
,
6410 MUIA_HorizWeight
, 50,
6412 MUIA_String_AdvanceOnCR
, TRUE
,
6413 MUIA_String_Contents
, (IPTR
) ncm
->ncm_CDC
->cdc_NTFSControl
,
6414 MUIA_String_MaxLen
, 63,
6416 Child
, (IPTR
) Label("CD/DVD:"),
6417 Child
, (IPTR
) PopaslObject
,
6418 MUIA_Popstring_String
, (IPTR
) (ncm
->ncm_CDFSObj
= (APTR
) StringObject
,
6421 MUIA_String_AdvanceOnCR
, TRUE
,
6422 MUIA_String_Contents
, (IPTR
) ncm
->ncm_CDC
->cdc_CDFSName
,
6423 MUIA_String_MaxLen
, 63,
6425 MUIA_Popstring_Button
, (IPTR
) PopButton(MUII_PopFile
),
6426 ASLFR_TitleText
, (IPTR
) "Select filesystem to use with CD/DVD partitions...",
6428 Child
, (IPTR
) Label("DosType:"),
6429 Child
, (IPTR
) (ncm
->ncm_CDDosTypeObj
= (APTR
) StringObject
,
6431 MUIA_HorizWeight
, 50,
6433 MUIA_String_AdvanceOnCR
, TRUE
,
6434 MUIA_String_Contents
, (IPTR
) cddostypebuf
,
6435 MUIA_String_Accept
, (IPTR
) "0123456789abcdefABCDEF",
6436 MUIA_String_MaxLen
, 9,
6438 Child
, (IPTR
) Label("Ctrl:"),
6439 Child
, (IPTR
) (ncm
->ncm_CDControlObj
= (APTR
) StringObject
,
6441 MUIA_HorizWeight
, 50,
6443 MUIA_String_AdvanceOnCR
, TRUE
,
6444 MUIA_String_Contents
, (IPTR
) ncm
->ncm_CDC
->cdc_CDControl
,
6445 MUIA_String_MaxLen
, 63,
6448 Child
, (IPTR
) VSpace(0),
6450 Child
, (IPTR
) VGroup
,
6451 Child
, (IPTR
) ListviewObject
,
6453 MUIA_Listview_List
, (IPTR
) (ncm
->ncm_LunLVObj
= (APTR
) ListObject
,
6455 MUIA_List_Format
, (IPTR
) bar
,
6456 MUIA_List_Title
, TRUE
,
6457 MUIA_List_DisplayHook
, (IPTR
) &ncm
->ncm_LUNListDisplayHook
,
6460 Child
, (IPTR
) (ncm
->ncm_LunGroupObj
= (APTR
) VGroup
,
6461 MUIA_Disabled
, TRUE
,
6462 Child
, (IPTR
) VSpace(0),
6463 Child
, (IPTR
) HGroup
,
6464 Child
, (IPTR
) (ncm
->ncm_AutoMountRDBObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6465 MUIA_Background
, MUII_ButtonBack
,
6467 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6468 MUIA_Image_Spec
, MUII_CheckMark
,
6469 MUIA_Image_FreeVert
, TRUE
,
6470 MUIA_Selected
, TRUE
,
6471 MUIA_ShowSelState
, FALSE
,
6473 Child
, (IPTR
) Label("AutoMount RDB partitions"),
6474 Child
, (IPTR
) HSpace(0),
6476 Child
, (IPTR
) HGroup
,
6477 Child
, (IPTR
) (ncm
->ncm_BootRDBObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6478 MUIA_Background
, MUII_ButtonBack
,
6480 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6481 MUIA_Image_Spec
, MUII_CheckMark
,
6482 MUIA_Image_FreeVert
, TRUE
,
6483 MUIA_Selected
, FALSE
,
6484 MUIA_ShowSelState
, FALSE
,
6486 Child
, (IPTR
) Label("Boot from RDB partitions"),
6487 Child
, (IPTR
) HSpace(0),
6489 Child
, (IPTR
) VSpace(0),
6490 Child
, (IPTR
) HGroup
,
6491 Child
, (IPTR
) (ncm
->ncm_AutoMountFATObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6492 MUIA_Background
, MUII_ButtonBack
,
6494 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6495 MUIA_Image_Spec
, MUII_CheckMark
,
6496 MUIA_Image_FreeVert
, TRUE
,
6497 MUIA_Selected
, TRUE
,
6498 MUIA_ShowSelState
, FALSE
,
6500 Child
, (IPTR
) Label("AutoMount FAT/NTFS partitions"),
6501 Child
, (IPTR
) HSpace(0),
6503 Child
, (IPTR
) HGroup
,
6504 Child
, (IPTR
) (ncm
->ncm_MountAllFATObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6505 MUIA_Background
, MUII_ButtonBack
,
6507 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6508 MUIA_Image_Spec
, MUII_CheckMark
,
6509 MUIA_Image_FreeVert
, TRUE
,
6510 MUIA_Selected
, TRUE
,
6511 MUIA_ShowSelState
, FALSE
,
6513 Child
, (IPTR
) Label("Mount all FAT partitions"),
6514 Child
, (IPTR
) HSpace(0),
6516 Child
, (IPTR
) VSpace(0),
6517 Child
, (IPTR
) HGroup
,
6518 Child
, (IPTR
) (ncm
->ncm_AutoMountCDObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6519 MUIA_Background
, MUII_ButtonBack
,
6521 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6522 MUIA_Image_Spec
, MUII_CheckMark
,
6523 MUIA_Image_FreeVert
, TRUE
,
6524 MUIA_Selected
, TRUE
,
6525 MUIA_ShowSelState
, FALSE
,
6527 Child
, (IPTR
) Label("AutoMount CD/DVD"),
6528 Child
, (IPTR
) HSpace(0),
6530 Child
, (IPTR
) VSpace(0),
6531 Child
, (IPTR
) HGroup
,
6532 Child
, (IPTR
) (ncm
->ncm_UnmountObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6533 MUIA_Background
, MUII_ButtonBack
,
6535 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6536 MUIA_Image_Spec
, MUII_CheckMark
,
6537 MUIA_Image_FreeVert
, TRUE
,
6538 MUIA_Selected
, FALSE
,
6539 MUIA_ShowSelState
, FALSE
,
6541 Child
, (IPTR
) HGroup
,
6542 Child
, (IPTR
) Label("Unmount partitions after removal"),
6543 Child
, (IPTR
) HSpace(0),
6546 Child
, (IPTR
) VSpace(0),
6547 Child
, (IPTR
) HGroup
,
6548 Child
, (IPTR
) Label("DOSName:"),
6549 Child
, (IPTR
) (ncm
->ncm_FatDOSNameObj
= (APTR
) StringObject
,
6552 MUIA_String_AdvanceOnCR
, TRUE
,
6553 MUIA_String_Contents
, (IPTR
) "UMSD",
6554 MUIA_String_Reject
, (IPTR
) "/ :?#*",
6555 MUIA_String_MaxLen
, 31,
6557 Child
, (IPTR
) Label("Buffers:"),
6558 Child
, (IPTR
) (ncm
->ncm_FatBuffersObj
= (APTR
) StringObject
,
6561 MUIA_String_AdvanceOnCR
, TRUE
,
6562 MUIA_String_Integer
, 100,
6563 MUIA_String_Accept
, (IPTR
) "0123456789",
6566 Child
, (IPTR
) VSpace(0),
6567 Child
, (IPTR
) HGroup
,
6568 Child
, (IPTR
) Label("Default " DEVNAME
" unit:"),
6569 Child
, (IPTR
) (ncm
->ncm_UnitObj
= (APTR
) StringObject
,
6572 MUIA_String_AdvanceOnCR
, TRUE
,
6573 MUIA_String_Integer
, 0,
6574 MUIA_String_Accept
, (IPTR
) "0123456789",
6580 Child
, (IPTR
) HGroup
,
6581 MUIA_Group_SameWidth
, TRUE
,
6582 Child
, (IPTR
) (ncm
->ncm_UseObj
= (APTR
) TextObject
, ButtonFrame
,
6583 MUIA_ShowMe
, (IPTR
) ncm
->ncm_Interface
,
6584 MUIA_Background
, MUII_ButtonBack
,
6586 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
6587 MUIA_Text_Contents
, (IPTR
) "\33c Save ",
6589 Child
, (IPTR
) (ncm
->ncm_SetDefaultObj
= (APTR
) TextObject
, ButtonFrame
,
6590 MUIA_Background
, MUII_ButtonBack
,
6592 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
6593 MUIA_Text_Contents
, ncm
->ncm_Interface
? (IPTR
) "\33c Save as Default " : (IPTR
) "\33c Save Defaults ",
6595 Child
, (IPTR
) (ncm
->ncm_CloseObj
= (APTR
) TextObject
, ButtonFrame
,
6596 MUIA_Background
, MUII_ButtonBack
,
6598 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
6599 MUIA_Text_Contents
, (IPTR
) "\33c Use ",
6608 KPRINTF(10, ("Couldn't create application\n"));
6609 GM_UNIQUENAME(nGUITaskCleanup
)(ncm
);
6613 if(ncm
->ncm_Interface
)
6616 while(((struct Node
*) cncm
)->ln_Succ
)
6618 if(cncm
->ncm_UnitLUN0
!= ncm
)
6622 DoMethod(ncm
->ncm_LunLVObj
, MUIM_List_InsertSingle
, cncm
, MUIV_List_Insert_Bottom
);
6623 cncm
= (struct NepClassMS
*) ((struct Node
*) cncm
)->ln_Succ
;
6626 DoMethod(ncm
->ncm_LunLVObj
, MUIM_List_InsertSingle
, ncm
, MUIV_List_Insert_Bottom
);
6628 DoMethod(ncm
->ncm_MainWindow
, MUIM_Notify
, MUIA_Window_CloseRequest
, TRUE
,
6629 ncm
->ncm_App
, 2, MUIM_Application_ReturnID
, MUIV_Application_ReturnID_Quit
);
6630 DoMethod(ncm
->ncm_UseObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
6631 ncm
->ncm_App
, 2, MUIM_Application_ReturnID
, ID_STORE_CONFIG
);
6632 DoMethod(ncm
->ncm_SetDefaultObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
6633 ncm
->ncm_App
, 2, MUIM_Application_ReturnID
, ID_DEF_CONFIG
);
6634 DoMethod(ncm
->ncm_CloseObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
6635 ncm
->ncm_App
, 2, MUIM_Application_ReturnID
, MUIV_Application_ReturnID_Quit
);
6637 DoMethod(ncm
->ncm_AutoDtxMaxTransObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
6638 ncm
->ncm_App
, 2, MUIM_Application_ReturnID
, ID_AUTODTXMAXTX
);
6639 DoMethod(ncm
->ncm_LunLVObj
, MUIM_Notify
, MUIA_List_Active
, MUIV_EveryTime
,
6640 ncm
->ncm_App
, 2, MUIM_Application_ReturnID
, ID_SELECT_LUN
);
6642 DoMethod(ncm
->ncm_AboutMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
6643 ncm
->ncm_App
, 2, MUIM_Application_ReturnID
, ID_ABOUT
);
6644 DoMethod(ncm
->ncm_UseMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
6645 ncm
->ncm_App
, 2, MUIM_Application_ReturnID
, ID_STORE_CONFIG
);
6646 DoMethod(ncm
->ncm_SetDefaultMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
6647 ncm
->ncm_App
, 2, MUIM_Application_ReturnID
, ID_DEF_CONFIG
);
6648 DoMethod(ncm
->ncm_MUIPrefsMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
6649 ncm
->ncm_App
, 2, MUIM_Application_OpenConfigWindow
, 0);
6651 set(ncm
->ncm_LunLVObj
, MUIA_List_Active
, MUIV_List_Active_Top
);
6659 get(ncm
->ncm_App
, MUIA_Application_Iconified
, &iconify
);
6660 set(ncm
->ncm_MainWindow
, MUIA_Window_Open
, TRUE
);
6661 get(ncm
->ncm_MainWindow
, MUIA_Window_Open
, &isopen
);
6662 if(!(isopen
|| iconify
))
6664 GM_UNIQUENAME(nGUITaskCleanup
)(ncm
);
6670 retid
= DoMethod(ncm
->ncm_App
, MUIM_Application_NewInput
, &sigs
);
6674 case ID_STORE_CONFIG
:
6675 case MUIV_Application_ReturnID_Quit
:
6681 get(ncm
->ncm_NakTimeoutObj
, MUIA_Numeric_Value
, &ncm
->ncm_CDC
->cdc_NakTimeout
);
6682 get(ncm
->ncm_StartupDelayObj
, MUIA_Numeric_Value
, &ncm
->ncm_CDC
->cdc_StartupDelay
);
6683 patchflags
= ncm
->ncm_CDC
->cdc_PatchFlags
& ~(PFF_SINGLE_LUN
|PFF_FAKE_INQUIRY
|PFF_SIMPLE_SCSI
|PFF_NO_RESET
|PFF_MODE_XLATE
|PFF_DEBUG
|PFF_NO_FALLBACK
|PFF_REM_SUPPORT
|PFF_FIX_INQ36
|PFF_CSS_BROKEN
|PFF_FIX_CAPACITY
|PFF_EMUL_LARGE_BLK
);
6685 get(ncm
->ncm_SingleLunObj
, MUIA_Selected
, &tmpflags
);
6686 if(tmpflags
) patchflags
|= PFF_SINGLE_LUN
;
6688 get(ncm
->ncm_FakeInquiryObj
, MUIA_Selected
, &tmpflags
);
6689 if(tmpflags
) patchflags
|= PFF_FAKE_INQUIRY
;
6691 get(ncm
->ncm_SimpleSCSIObj
, MUIA_Selected
, &tmpflags
);
6692 if(tmpflags
) patchflags
|= PFF_SIMPLE_SCSI
;
6694 get(ncm
->ncm_InitialResetObj
, MUIA_Selected
, &tmpflags
);
6695 if(tmpflags
) patchflags
|= PFF_NO_RESET
;
6697 get(ncm
->ncm_XLate610Obj
, MUIA_Selected
, &tmpflags
);
6698 if(tmpflags
) patchflags
|= PFF_MODE_XLATE
;
6700 get(ncm
->ncm_RemSupportObj
, MUIA_Selected
, &tmpflags
);
6701 if(tmpflags
) patchflags
|= PFF_REM_SUPPORT
;
6703 get(ncm
->ncm_FixInquiryObj
, MUIA_Selected
, &tmpflags
);
6704 if(tmpflags
) patchflags
|= PFF_FIX_INQ36
;
6706 get(ncm
->ncm_CSSBrokenObj
, MUIA_Selected
, &tmpflags
);
6707 if(tmpflags
) patchflags
|= PFF_CSS_BROKEN
;
6709 get(ncm
->ncm_FixCapacityObj
, MUIA_Selected
, &tmpflags
);
6710 if(tmpflags
) patchflags
|= PFF_FIX_CAPACITY
;
6712 get(ncm
->ncm_EmulLargeBlkObj
, MUIA_Selected
, &tmpflags
);
6713 if(tmpflags
) patchflags
|= PFF_EMUL_LARGE_BLK
;
6715 get(ncm
->ncm_NoFallbackObj
, MUIA_Selected
, &tmpflags
);
6716 if(tmpflags
) patchflags
|= PFF_NO_FALLBACK
;
6718 get(ncm
->ncm_DebugObj
, MUIA_Selected
, &tmpflags
);
6719 if(tmpflags
) patchflags
|= PFF_DEBUG
;
6720 ncm
->ncm_CDC
->cdc_PatchFlags
= patchflags
;
6722 get(ncm
->ncm_MaxTransferObj
, MUIA_Cycle_Active
, &ncm
->ncm_CDC
->cdc_MaxTransfer
);
6725 get(ncm
->ncm_FatFSObj
, MUIA_String_Contents
, &tmpstr
);
6726 strncpy(ncm
->ncm_CDC
->cdc_FATFSName
, tmpstr
, 63);
6728 get(ncm
->ncm_FatControlObj
, MUIA_String_Contents
, &tmpstr
);
6729 strncpy(ncm
->ncm_CDC
->cdc_FATControl
, tmpstr
, 63);
6731 get(ncm
->ncm_FatDosTypeObj
, MUIA_String_Contents
, &tmpstr
);
6732 ncm
->ncm_CDC
->cdc_FATDosType
= nGetDosType(tmpstr
);
6735 get(ncm
->ncm_NTFSObj
, MUIA_String_Contents
, &tmpstr
);
6736 strncpy(ncm
->ncm_CDC
->cdc_NTFSName
, tmpstr
, 63);
6738 get(ncm
->ncm_NTFSControlObj
, MUIA_String_Contents
, &tmpstr
);
6739 strncpy(ncm
->ncm_CDC
->cdc_NTFSControl
, tmpstr
, 63);
6741 get(ncm
->ncm_NTFSDosTypeObj
, MUIA_String_Contents
, &tmpstr
);
6742 ncm
->ncm_CDC
->cdc_NTFSDosType
= nGetDosType(tmpstr
);
6745 get(ncm
->ncm_CDFSObj
, MUIA_String_Contents
, &tmpstr
);
6746 strncpy(ncm
->ncm_CDC
->cdc_CDFSName
, tmpstr
, 63);
6748 get(ncm
->ncm_CDControlObj
, MUIA_String_Contents
, &tmpstr
);
6749 strncpy(ncm
->ncm_CDC
->cdc_CDControl
, tmpstr
, 63);
6751 get(ncm
->ncm_CDDosTypeObj
, MUIA_String_Contents
, &tmpstr
);
6752 ncm
->ncm_CDC
->cdc_CDDosType
= nGetDosType(tmpstr
);
6754 if(ncm
->ncm_Interface
)
6756 /* copy device config to all luns */
6757 cncm
= (struct NepClassMS
*) ((struct Node
*) ncm
)->ln_Succ
;
6758 while(((struct Node
*) cncm
)->ln_Succ
)
6760 if(cncm
->ncm_UnitLUN0
!= ncm
)
6764 *(cncm
->ncm_CDC
) = *(ncm
->ncm_CDC
);
6765 cncm
= (struct NepClassMS
*) ((struct Node
*) cncm
)->ln_Succ
;
6770 get(ncm
->ncm_AutoMountFATObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_AutoMountFAT
);
6771 get(ncm
->ncm_MountAllFATObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_MountAllFAT
);
6772 get(ncm
->ncm_AutoMountCDObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_AutoMountCD
);
6774 get(ncm
->ncm_FatDOSNameObj
, MUIA_String_Contents
, &tmpstr
);
6775 strncpy(curncm
->ncm_CUC
->cuc_FATDOSName
, tmpstr
, 31);
6776 get(ncm
->ncm_FatBuffersObj
, MUIA_String_Integer
, &curncm
->ncm_CUC
->cuc_FATBuffers
);
6777 get(ncm
->ncm_AutoMountRDBObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_AutoMountRDB
);
6778 get(ncm
->ncm_BootRDBObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_BootRDB
);
6779 get(ncm
->ncm_UnitObj
, MUIA_String_Integer
, &curncm
->ncm_CUC
->cuc_DefaultUnit
);
6780 get(ncm
->ncm_UnmountObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_AutoUnmount
);
6783 if(retid
== ID_DEF_CONFIG
)
6785 pic
= psdGetClsCfg(GM_UNIQUENAME(libname
));
6788 psdSetClsCfg(GM_UNIQUENAME(libname
), NULL
);
6789 pic
= psdGetClsCfg(GM_UNIQUENAME(libname
));
6793 psdAddCfgEntry(pic
, ncm
->ncm_CDC
);
6794 psdAddCfgEntry(pic
, ncm
->ncm_CUC
);
6795 psdSaveCfgToDisk(NULL
, FALSE
);
6798 if(GM_UNIQUENAME(nStoreConfig
)(ncm
))
6800 if(retid
!= MUIV_Application_ReturnID_Quit
)
6802 psdSaveCfgToDisk(NULL
, FALSE
);
6804 retid
= MUIV_Application_ReturnID_Quit
;
6812 DoMethod(ncm
->ncm_LunLVObj
, MUIM_List_GetEntry
, MUIV_List_GetEntry_Active
, &cncm
);
6817 get(ncm
->ncm_AutoMountFATObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_AutoMountFAT
);
6818 get(ncm
->ncm_MountAllFATObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_MountAllFAT
);
6819 get(ncm
->ncm_AutoMountCDObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_AutoMountCD
);
6821 get(ncm
->ncm_FatDOSNameObj
, MUIA_String_Contents
, &tmpstr
);
6822 strncpy(curncm
->ncm_CUC
->cuc_FATDOSName
, tmpstr
, 31);
6823 get(ncm
->ncm_FatBuffersObj
, MUIA_String_Integer
, &curncm
->ncm_CUC
->cuc_FATBuffers
);
6824 get(ncm
->ncm_AutoMountRDBObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_AutoMountRDB
);
6825 get(ncm
->ncm_BootRDBObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_BootRDB
);
6826 get(ncm
->ncm_UnitObj
, MUIA_String_Integer
, &curncm
->ncm_CUC
->cuc_DefaultUnit
);
6827 get(ncm
->ncm_UnmountObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_AutoUnmount
);
6832 set(ncm
->ncm_AutoMountFATObj
, MUIA_Selected
, curncm
->ncm_CUC
->cuc_AutoMountFAT
);
6833 set(ncm
->ncm_MountAllFATObj
, MUIA_Selected
, curncm
->ncm_CUC
->cuc_MountAllFAT
);
6834 set(ncm
->ncm_AutoMountCDObj
, MUIA_Selected
, curncm
->ncm_CUC
->cuc_AutoMountCD
);
6835 set(ncm
->ncm_FatDOSNameObj
, MUIA_String_Contents
, curncm
->ncm_CUC
->cuc_FATDOSName
);
6836 set(ncm
->ncm_FatBuffersObj
, MUIA_String_Integer
, curncm
->ncm_CUC
->cuc_FATBuffers
);
6837 set(ncm
->ncm_AutoMountRDBObj
, MUIA_Selected
, curncm
->ncm_CUC
->cuc_AutoMountRDB
);
6838 set(ncm
->ncm_BootRDBObj
, MUIA_Selected
, curncm
->ncm_CUC
->cuc_BootRDB
);
6839 set(ncm
->ncm_UnitObj
, MUIA_String_Integer
, curncm
->ncm_CUC
->cuc_DefaultUnit
);
6840 set(ncm
->ncm_UnmountObj
, MUIA_Selected
, curncm
->ncm_CUC
->cuc_AutoUnmount
);
6841 set(ncm
->ncm_LunGroupObj
, MUIA_Disabled
, FALSE
);
6843 set(ncm
->ncm_LunGroupObj
, MUIA_Disabled
, TRUE
);
6847 case ID_AUTODTXMAXTX
:
6849 DoMethod(ncm
->ncm_LunLVObj
, MUIM_List_GetEntry
, MUIV_List_GetEntry_Active
, &cncm
);
6850 set(ncm
->ncm_App
, MUIA_Application_Sleep
, TRUE
);
6851 AutoDetectMaxTransfer(cncm
);
6852 set(ncm
->ncm_App
, MUIA_Application_Sleep
, FALSE
);
6853 set(ncm
->ncm_MaxTransferObj
, MUIA_Cycle_Active
, ncm
->ncm_CDC
->cdc_MaxTransfer
);
6858 MUI_RequestA(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, "Blimey!", VERSION_STRING
"\n\nCode for AutoMounting based\non work by Thore Böckelmann.", NULL
);
6861 if(retid
== MUIV_Application_ReturnID_Quit
)
6867 sigs
= Wait(sigs
| sigmask
| SIGBREAKF_CTRL_C
);
6868 if(sigs
& SIGBREAKF_CTRL_C
)
6874 set(ncm
->ncm_MainWindow
, MUIA_Window_Open
, FALSE
);
6876 GM_UNIQUENAME(nGUITaskCleanup
)(ncm
);
6882 /* /// "AutoDetectMaxTransfer()" */
6883 void AutoDetectMaxTransfer(struct NepClassMS
*cncm
)
6891 struct IOStdReq
*ioreq
;
6892 struct NepClassMS
*ncm
= cncm
->ncm_UnitLUN0
;
6894 ULONG memsize
= 4<<20;
6901 res
= MUI_RequestA(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, "Continue|Cancel",
6902 "Auto-detection of the maximum transfer rate\n"
6903 "will need some media inserted in the selected\n"
6904 "LUN of the drive. Moreover, the contents of the\n"
6905 "media may not be empty.\n"
6906 "The test will need about 4 MB of temporary memory!\n"
6907 "No data is written to the disk!", NULL
);
6912 if(!cncm
->ncm_UnitReady
)
6914 MUI_RequestA(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, "Argh!", "No disk/media in drive!", NULL
);
6917 memory
= (UBYTE
*) AllocVec(memsize
, MEMF_CLEAR
);
6920 MUI_RequestA(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, "Argh!", "Sorry, out of memory!", NULL
);
6923 mp
= CreateMsgPort();
6926 ioreq
= (struct IOStdReq
*) CreateIORequest(mp
, sizeof(struct IOStdReq
));
6929 if(!OpenDevice(DEVNAME
, cncm
->ncm_UnitNo
, (struct IORequest
*) ioreq
, 0))
6931 ncm
->ncm_CDC
->cdc_MaxTransfer
= 0;
6932 if(!cncm
->ncm_BlockSize
)
6934 ioreq
->io_Command
= TD_GETGEOMETRY
;
6935 ioreq
->io_Data
= &cncm
->ncm_Geometry
;
6936 ioreq
->io_Length
= sizeof(cncm
->ncm_Geometry
);
6937 DoIO((struct IORequest
*) ioreq
);
6940 numblocks
= (memsize
>>1) / cncm
->ncm_BlockSize
;
6942 cmpbuffer
= &memory
[memsize
>>1];
6946 for(block
= 0; block
< numblocks
; block
++)
6948 ioreq
->io_Command
= TD_READ64
;
6949 ioreq
->io_Actual
= 0;
6950 ioreq
->io_Offset
= block
*cncm
->ncm_BlockSize
;
6951 ioreq
->io_Length
= cncm
->ncm_BlockSize
;
6952 ioreq
->io_Data
= &orgbuffer
[ioreq
->io_Offset
];
6953 ioerr
= DoIO((struct IORequest
*) ioreq
);
6956 MUI_Request(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, ">:-{", "Error %ld while reading block %ld!\nAborting process...", ioerr
, block
);
6965 maxtrans
= (1UL<<(ncm
->ncm_CDC
->cdc_MaxTransfer
+16));
6966 // do a quick check on block contents
6967 numblocks
= (memsize
>>1) / maxtrans
;
6970 for(block
= 0; block
< numblocks
-1; block
++)
6972 if(!memcmp(&orgbuffer
[block
* maxtrans
], &orgbuffer
[(block
+ 1) * maxtrans
], (size_t) maxtrans
))
6974 res
= MUI_RequestA(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, "Continue|Abort", "Sorry, media contents do not\nseem to be diversive enough!\nResults might be wrong!", NULL
);
6985 // fill compare buffer with garbage
6987 lbufptr
= (ULONG
*) cmpbuffer
;
6990 *lbufptr
= (IPTR
) lbufptr
;
6995 // start reading the chunks
6996 numblocks
= (memsize
>>1) / maxtrans
;
6997 for(block
= 0; block
< numblocks
; block
++)
6999 ioreq
->io_Command
= TD_READ64
;
7000 ioreq
->io_Actual
= 0;
7001 ioreq
->io_Offset
= block
*maxtrans
;
7002 ioreq
->io_Length
= maxtrans
;
7003 ioreq
->io_Data
= &cmpbuffer
[ioreq
->io_Offset
];
7004 ioerr
= DoIO((struct IORequest
*) ioreq
);
7007 MUI_Request(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, ">:-{", "Error %ld while reading at offset %ld!\nAborting process...", ioerr
, &ioreq
->io_Offset
);
7011 if(memcmp(&orgbuffer
[ioreq
->io_Offset
], &cmpbuffer
[ioreq
->io_Offset
], (size_t) maxtrans
))
7013 MUI_Request(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, "Hmpf!", "Reading failed at MaxTrans = %08lx", maxtrans
-1);
7014 if(ncm
->ncm_CDC
->cdc_MaxTransfer
)
7016 ncm
->ncm_CDC
->cdc_MaxTransfer
--;
7023 //MUI_Request(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Wow!", "Test with %ld (%ld) succeeded!", maxtrans, numblocks);
7024 if(ncm
->ncm_CDC
->cdc_MaxTransfer
< 5)
7026 ncm
->ncm_CDC
->cdc_MaxTransfer
++;
7033 MUI_RequestA(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, "Wow!", "Test succeeded, setting MaxTrans to maximum value!", NULL
);
7036 CloseDevice((struct IORequest
*) ioreq
);
7038 MUI_RequestA(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, "Argh!", "Couldn't open device!", NULL
);
7040 DeleteIORequest((struct IORequest
*) ioreq
);
7042 MUI_RequestA(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, "Argh!", "No IOReq!", NULL
);
7046 MUI_RequestA(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, "Argh!", "No MsgPort!", NULL
);
7052 /* /// "nGUITaskCleanup()" */
7053 void GM_UNIQUENAME(nGUITaskCleanup
)(struct NepClassMS
*ncm
)
7057 MUI_DisposeObject(ncm
->ncm_App
);
7058 ncm
->ncm_App
= NULL
;
7062 CloseLibrary(MUIMasterBase
);
7063 MUIMasterBase
= NULL
;
7067 CloseLibrary(IntuitionBase
);
7068 IntuitionBase
= NULL
;
7076 ncm
->ncm_GUIBinding
= NULL
;
7077 ncm
->ncm_GUITask
= NULL
;
7078 --ncm
->ncm_ClsBase
->nh_Library
.lib_OpenCnt
;
7082 /* /// "LUNListDisplayHook()" */
7083 AROS_UFH3(LONG
, GM_UNIQUENAME(LUNListDisplayHook
),
7084 AROS_UFHA(struct Hook
*, hook
, A0
),
7085 AROS_UFHA(char **, strarr
, A2
),
7086 AROS_UFHA(struct NepClassMS
*, ncm
, A1
))
7090 //struct NepMSBase *nh = ncm->ncm_ClsBase;
7093 *strarr
++ = ncm
->ncm_LUNNumStr
;
7094 *strarr
= ncm
->ncm_LUNIDStr
;
7096 *strarr
++ = "\33l\33uLUN";
7097 *strarr
= "\33l\33uID";