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 strncpy(ncm
->ncm_LUNIDStr
, &inquirydata
[16], 16);
1201 cnt
= strlen(ncm
->ncm_LUNIDStr
);
1204 if(ncm
->ncm_LUNIDStr
[cnt
] == ' ')
1206 ncm
->ncm_LUNIDStr
[cnt
] = 0;
1212 ncm
->ncm_DeviceType
= inquirydata
[0] & PDT_MASK
;
1213 if(ncm
->ncm_DeviceType
> 0x11)
1215 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Illegal Device Type %02lx", ncm
->ncm_DeviceType
);
1216 ncm
->ncm_DeviceType
= 0;
1218 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Device '%s' is of %s type.", ncm
->ncm_LUNIDStr
, DeviceTypeStrings
[ncm
->ncm_DeviceType
]);
1220 if((ncm
->ncm_DeviceType
== PDT_WORM
) ||
1221 (ncm
->ncm_DeviceType
== PDT_CDROM
))
1223 // assume 2048 byte blocks
1224 ncm
->ncm_BlockSize
= 2048;
1225 ncm
->ncm_BlockShift
= 11;
1226 if(ncm
->ncm_CDC
->cdc_NakTimeout
== DEF_NAKTIMEOUT
)
1228 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Silently increasing NAK Timeout value to 15 seconds for CD/DVD drives...");
1229 ncm
->ncm_CDC
->cdc_NakTimeout
= 150;
1230 GM_UNIQUENAME(nStoreConfig
)(ncm
);
1232 psdSetAttrs(PGA_PIPE
, ncm
->ncm_EP0Pipe
,
1233 PPA_NakTimeout
, TRUE
,
1234 PPA_NakTimeoutTime
, (ncm
->ncm_CDC
->cdc_NakTimeout
+1)*100,
1236 psdSetAttrs(PGA_PIPE
, ncm
->ncm_EPInPipe
,
1237 PPA_NakTimeout
, TRUE
,
1238 PPA_NakTimeoutTime
, ncm
->ncm_CDC
->cdc_NakTimeout
*100,
1240 psdSetAttrs(PGA_PIPE
, ncm
->ncm_EPOutPipe
,
1241 PPA_NakTimeout
, TRUE
,
1242 PPA_NakTimeoutTime
, ncm
->ncm_CDC
->cdc_NakTimeout
*100,
1245 else if(!ncm
->ncm_CDC
->cdc_NakTimeout
)
1247 // that's okay, nak timeout disabled
1249 else if(ncm
->ncm_CDC
->cdc_NakTimeout
< 150)
1251 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "NAK Timeout should be at least 15 seconds for CD/DVD drives!");
1255 if(!(inquirydata
[1] & 0x80))
1257 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Device does not seem to use removable media.");
1258 ncm
->ncm_Removable
= FALSE
;
1259 ncm
->ncm_UnitReady
= TRUE
;
1260 ncm
->ncm_ChangeCount
++;
1265 sigmask
= (1L<<ncm
->ncm_Unit
.unit_MsgPort
.mp_SigBit
)|
1266 (1L<<ncm
->ncm_TaskMsgPort
->mp_SigBit
)|
1268 if(ncm
->ncm_CSType
== MS_UFI_SUBCLASS
)
1270 struct IOStdReq tmpio
;
1271 tmpio
.io_Command
= CMD_START
;
1272 nStartStop(ncm
, &tmpio
);
1275 // if not removable, call it once to trigger mounting...
1276 if(!ncm
->ncm_Removable
)
1278 ncm
->ncm_ForceRTCheck
= TRUE
;
1280 ncm
->ncm_Running
= TRUE
;
1284 if(ncm
->ncm_Removable
|| ncm
->ncm_ForceRTCheck
)
1286 GM_UNIQUENAME(nStartRemovableTask
)(ps
, ncm
->ncm_ClsBase
);
1287 ncm
->ncm_ForceRTCheck
= FALSE
;
1289 while((ioreq
= (struct IOStdReq
*) GetMsg(&ncm
->ncm_Unit
.unit_MsgPort
)))
1291 KPRINTF(5, ("command ioreq: 0x%08lx cmd: %lu len: %ld\n",
1292 ioreq
, ioreq
->io_Command
, ioreq
->io_Length
));
1294 switch(ioreq
->io_Command
)
1296 case TD_GETGEOMETRY
:
1297 nGetGeometry(ncm
, ioreq
);
1298 ReplyMsg((struct Message
*) ioreq
);
1304 nStartStop(ncm
, ioreq
);
1305 ReplyMsg((struct Message
*) ioreq
);
1309 ioreq
->io_Actual
= 0;
1310 case NSCMD_TD_READ64
:
1312 nRead64(ncm
, ioreq
);
1313 ReplyMsg((struct Message
*) ioreq
);
1317 ioreq
->io_Actual
= 0;
1318 case NSCMD_TD_SEEK64
:
1320 nSeek64(ncm
, ioreq
);
1321 ReplyMsg((struct Message
*) ioreq
);
1326 ioreq
->io_Actual
= 0;
1327 case NSCMD_TD_FORMAT64
:
1328 case NSCMD_TD_WRITE64
:
1331 nWrite64(ncm
, ioreq
);
1332 ReplyMsg((struct Message
*) ioreq
);
1336 ioreq
->io_Error
= nScsiDirect(ncm
, ioreq
->io_Data
);
1337 ReplyMsg((struct Message
*) ioreq
);
1341 if((ioreq2
= ncm
->ncm_XFerPending
))
1343 ncm
->ncm_XFerPending
= NULL
;
1344 ioreq2
->io_Error
= IOERR_ABORTED
;
1345 ReplyMsg((struct Message
*) ioreq2
);
1347 /* Reset does a flush too */
1349 ioreq2
= (struct IOStdReq
*) ncm
->ncm_XFerQueue
.lh_Head
;
1350 while(ioreq2
->io_Message
.mn_Node
.ln_Succ
)
1352 Remove((struct Node
*) ioreq2
);
1353 ioreq2
->io_Error
= IOERR_ABORTED
;
1354 ReplyMsg((struct Message
*) ioreq2
);
1355 ioreq2
= (struct IOStdReq
*) ncm
->ncm_XFerQueue
.lh_Head
;
1357 ReplyMsg((struct Message
*) ioreq
);
1361 ioreq
->io_Error
= IOERR_NOCMD
;
1362 ReplyMsg((struct Message
*) ioreq
);
1366 sigs
= Wait(sigmask
);
1367 } while(!(sigs
& SIGBREAKF_CTRL_C
));
1368 ncm
->ncm_DenyRequests
= TRUE
;
1369 /* Device ejected */
1370 ncm
->ncm_UnitReady
= FALSE
;
1371 ncm
->ncm_ChangeCount
++;
1372 ioreq
= (struct IOStdReq
*) ncm
->ncm_DCInts
.lh_Head
;
1373 while(((struct Node
*) ioreq
)->ln_Succ
)
1375 Cause(ioreq
->io_Data
);
1376 ioreq
= (struct IOStdReq
*) ((struct Node
*) ioreq
)->ln_Succ
;
1378 if(!ncm
->ncm_Removable
)
1380 GM_UNIQUENAME(nStartRemovableTask
)(ps
, ncm
->ncm_ClsBase
);
1382 KPRINTF(20, ("Going down the river!\n"));
1383 GM_UNIQUENAME(nFreeMS
)(ncm
);
1389 /* /// "nAllocMS()" */
1390 struct NepClassMS
* GM_UNIQUENAME(nAllocMS
)(void)
1392 struct Task
*thistask
;
1393 struct NepClassMS
*ncm
;
1396 thistask
= FindTask(NULL
);
1397 ncm
= thistask
->tc_UserData
;
1400 if(!(ncm
->ncm_Base
= OpenLibrary("poseidon.library", 4)))
1402 Alert(AG_OpenLib
| AO_Unknown
);
1405 ncm
->ncm_EPInt
= psdFindEndpoint(ncm
->ncm_Interface
, NULL
,
1407 EA_TransferType
, USEAF_INTERRUPT
,
1409 ncm
->ncm_EPIn
= psdFindEndpoint(ncm
->ncm_Interface
, NULL
,
1411 EA_TransferType
, USEAF_BULK
,
1413 ncm
->ncm_EPOut
= psdFindEndpoint(ncm
->ncm_Interface
, NULL
,
1415 EA_TransferType
, USEAF_BULK
,
1417 if(!(ncm
->ncm_EPIn
&& ncm
->ncm_EPOut
))
1419 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "IN or OUT endpoint missing!");
1422 if((!ncm
->ncm_EPInt
) && (ncm
->ncm_TPType
== MS_PROTO_CBI
))
1424 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "INT endpoint missing!");
1427 psdGetAttrs(PGA_ENDPOINT
, ncm
->ncm_EPOut
,
1428 EA_EndpointNum
, &epnum
,
1430 ncm
->ncm_EPIntNum
= epnum
;
1432 psdGetAttrs(PGA_ENDPOINT
, ncm
->ncm_EPIn
,
1433 EA_EndpointNum
, &epnum
,
1435 ncm
->ncm_EPInNum
= epnum
;
1436 psdGetAttrs(PGA_ENDPOINT
, ncm
->ncm_EPOut
,
1437 EA_EndpointNum
, &epnum
,
1439 ncm
->ncm_EPOutNum
= epnum
;
1441 ncm
->ncm_BulkResetBorks
= FALSE
;
1442 ncm
->ncm_GeoChangeCount
= 0xffffffff;
1444 ncm
->ncm_Unit
.unit_MsgPort
.mp_SigBit
= AllocSignal(-1);
1445 ncm
->ncm_Unit
.unit_MsgPort
.mp_SigTask
= thistask
;
1446 ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
1447 ncm
->ncm_Unit
.unit_MsgPort
.mp_Flags
= PA_SIGNAL
;
1448 ncm
->ncm_XFerPending
= NULL
;
1449 if((ncm
->ncm_TaskMsgPort
= CreateMsgPort()))
1451 if((ncm
->ncm_EP0Pipe
= psdAllocPipe(ncm
->ncm_Device
, ncm
->ncm_TaskMsgPort
, NULL
)))
1453 if((ncm
->ncm_EPOutPipe
= psdAllocPipe(ncm
->ncm_Device
, ncm
->ncm_TaskMsgPort
, ncm
->ncm_EPOut
)))
1455 if((ncm
->ncm_EPInPipe
= psdAllocPipe(ncm
->ncm_Device
, ncm
->ncm_TaskMsgPort
, ncm
->ncm_EPIn
)))
1457 if(ncm
->ncm_CDC
->cdc_NakTimeout
)
1459 psdSetAttrs(PGA_PIPE
, ncm
->ncm_EP0Pipe
,
1460 PPA_NakTimeout
, TRUE
,
1461 PPA_NakTimeoutTime
, (ncm
->ncm_CDC
->cdc_NakTimeout
+1)*100,
1463 psdSetAttrs(PGA_PIPE
, ncm
->ncm_EPInPipe
,
1464 PPA_NakTimeout
, TRUE
,
1465 PPA_NakTimeoutTime
, ncm
->ncm_CDC
->cdc_NakTimeout
*100,
1467 psdSetAttrs(PGA_PIPE
, ncm
->ncm_EPOutPipe
,
1468 PPA_NakTimeout
, TRUE
,
1469 PPA_NakTimeoutTime
, ncm
->ncm_CDC
->cdc_NakTimeout
*100,
1472 psdSetAttrs(PGA_PIPE
, ncm
->ncm_EPOutPipe
,
1473 PPA_NoShortPackets
, TRUE
,
1477 if((ncm
->ncm_EPIntPipe
= psdAllocPipe(ncm
->ncm_Device
, ncm
->ncm_TaskMsgPort
, ncm
->ncm_EPInt
)))
1479 if(ncm
->ncm_CDC
->cdc_NakTimeout
)
1481 psdSetAttrs(PGA_PIPE
, ncm
->ncm_EPIntPipe
,
1482 PPA_NakTimeout
, TRUE
,
1483 PPA_NakTimeoutTime
, ncm
->ncm_CDC
->cdc_NakTimeout
*100,
1486 ncm
->ncm_Task
= thistask
;
1490 ncm
->ncm_Task
= thistask
;
1493 psdFreePipe(ncm
->ncm_EPInPipe
);
1495 psdFreePipe(ncm
->ncm_EPOutPipe
);
1497 psdFreePipe(ncm
->ncm_EP0Pipe
);
1499 DeleteMsgPort(ncm
->ncm_TaskMsgPort
);
1501 FreeSignal((LONG
) ncm
->ncm_Unit
.unit_MsgPort
.mp_SigBit
);
1503 CloseLibrary(ncm
->ncm_Base
);
1505 ncm
->ncm_Task
= NULL
;
1506 if(ncm
->ncm_ReadySigTask
)
1508 Signal(ncm
->ncm_ReadySigTask
, 1L<<ncm
->ncm_ReadySignal
);
1514 /* /// "nFreeMS()" */
1515 void GM_UNIQUENAME(nFreeMS
)(struct NepClassMS
*ncm
)
1517 struct IOStdReq
*ioreq
;
1518 /* Disable the message port, messages may still be queued */
1520 ncm
->ncm_Unit
.unit_MsgPort
.mp_Flags
= PA_IGNORE
;
1521 ncm
->ncm_Unit
.unit_MsgPort
.mp_SigTask
= NULL
;
1522 FreeSignal((LONG
) ncm
->ncm_Unit
.unit_MsgPort
.mp_SigBit
);
1523 // get rid of all messages that still have appeared here
1524 while((ioreq
= (struct IOStdReq
*) GetMsg(&ncm
->ncm_Unit
.unit_MsgPort
)))
1526 ioreq
->io_Error
= IOERR_ABORTED
;
1527 ReplyMsg((struct Message
*) ioreq
);
1531 psdFreePipe(ncm
->ncm_EPIntPipe
);
1532 psdFreePipe(ncm
->ncm_EPInPipe
);
1533 psdFreePipe(ncm
->ncm_EPOutPipe
);
1534 psdFreePipe(ncm
->ncm_EP0Pipe
);
1535 DeleteMsgPort(ncm
->ncm_TaskMsgPort
);
1537 psdFreeVec(ncm
->ncm_OneBlock
);
1538 ncm
->ncm_OneBlock
= NULL
;
1539 ncm
->ncm_OneBlockSize
= 0;
1541 CloseLibrary(ncm
->ncm_Base
);
1543 ncm
->ncm_Task
= NULL
;
1544 if(ncm
->ncm_ReadySigTask
)
1546 Signal(ncm
->ncm_ReadySigTask
, 1L<<ncm
->ncm_ReadySignal
);
1551 /* /// "nGetModePage()" */
1552 UBYTE
* nGetModePage(struct NepClassMS
*ncm
, UBYTE page
)
1555 struct SCSICmd scsicmd
;
1556 UBYTE sensedata
[18];
1561 KPRINTF(10, ("page %ld\n", page
));
1563 memset(ncm
->ncm_ModePageBuf
, 0x00, 255);
1564 scsicmd
.scsi_Data
= (UWORD
*) ncm
->ncm_ModePageBuf
;
1565 scsicmd
.scsi_Length
= 255;
1566 scsicmd
.scsi_Command
= cmd6
;
1567 scsicmd
.scsi_CmdLength
= 6;
1568 scsicmd
.scsi_Flags
= SCSIF_READ
|SCSIF_AUTOSENSE
;
1569 scsicmd
.scsi_SenseData
= sensedata
;
1570 scsicmd
.scsi_SenseLength
= 18;
1571 cmd6
[0] = SCSI_MODE_SENSE_6
;
1572 cmd6
[1] = 0x00; /* no block descriptors */
1577 if((ioerr
= nScsiDirect(ncm
, &scsicmd
)))
1579 KPRINTF(10, ("ioerr %ld\n", ioerr
));
1580 pf
= ncm
->ncm_CDC
->cdc_PatchFlags
;
1583 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1584 "SCSI_MODE_SENSE(0x%02lx) failed: %ld",
1587 if((!(pf
& PFF_NO_FALLBACK
)) && (!(pf
& PFF_MODE_XLATE
)) && (ioerr
== HFERR_Phase
))
1589 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_MODE_XLATE
;
1590 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1591 "Fallback: Enabling CMD6->CMD10.");
1592 GM_UNIQUENAME(nStoreConfig
)(ncm
);
1594 else if((!(pf
& PFF_NO_FALLBACK
)) && (pf
& PFF_MODE_XLATE
) && (!(pf
& PFF_SIMPLE_SCSI
)) && (ioerr
== HFERR_Phase
))
1596 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_SIMPLE_SCSI
;
1597 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1598 "Fallback: Enabling Simple SCSI.");
1599 GM_UNIQUENAME(nStoreConfig
)(ncm
);
1603 pf
= ncm
->ncm_CDC
->cdc_PatchFlags
;
1604 res
= ncm
->ncm_ModePageBuf
;
1605 if((scsicmd
.scsi_Actual
< 6) || (scsicmd
.scsi_Actual
< res
[3]+6))
1609 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1610 "SCSI_MODE_SENSE(0x%02lx) failed: only %ld returned",
1611 page
, scsicmd
.scsi_Actual
);
1617 UBYTE hexbuf
[12*3+2];
1618 GM_UNIQUENAME(nHexString
)(res
, 12, hexbuf
);
1619 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "ModePage (%ld) header: %s...", scsicmd
.scsi_Actual
, hexbuf
);
1624 scsicmd
.scsi_Actual
-= res
[3];
1626 res
+= 4; // skip mode header */
1627 scsicmd
.scsi_Actual
-= 4;
1628 if((*res
& 0x3f) != (page
& 0x3f))
1632 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1633 "SCSI_MODE_SENSE(0x%02lx) failed: wrong page 0x%02lx returned",
1638 if(scsicmd
.scsi_Actual
< res
[1])
1642 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1643 "SCSI_MODE_SENSE(0x%02lx) failed: page incomplete",
1650 if(*res
& 0x40) /* subpage mode? */
1659 /* /// "nGetBlockSize()" */
1660 LONG
nGetBlockSize(struct NepClassMS
*ncm
)
1663 struct SCSICmd scsicmd
;
1664 UBYTE sensedata
[18];
1668 scsicmd
.scsi_Data
= (UWORD
*) capacity
;
1669 scsicmd
.scsi_Length
= 8;
1670 scsicmd
.scsi_Command
= cmd10
;
1671 scsicmd
.scsi_CmdLength
= 10;
1672 scsicmd
.scsi_Flags
= SCSIF_READ
|SCSIF_AUTOSENSE
;
1673 scsicmd
.scsi_SenseData
= sensedata
;
1674 scsicmd
.scsi_SenseLength
= 18;
1675 cmd10
[0] = SCSI_DA_READ_CAPACITY
;
1685 if((ioerr
= nScsiDirect(ncm
, &scsicmd
)))
1687 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1688 "SCSI_READ_CAPACITY failed: %ld",
1690 if(!ncm
->ncm_BlockSize
)
1692 ncm
->ncm_Geometry
.dg_SectorSize
= ncm
->ncm_BlockSize
= 512;
1693 ncm
->ncm_BlockShift
= 9;
1696 ncm
->ncm_Geometry
.dg_SectorSize
= ncm
->ncm_BlockSize
= AROS_BE2LONG(capacity
[1]);
1697 ncm
->ncm_BlockShift
= 0;
1698 while((1<<ncm
->ncm_BlockShift
) < ncm
->ncm_BlockSize
)
1700 ncm
->ncm_BlockShift
++;
1702 ncm
->ncm_Geometry
.dg_TotalSectors
= AROS_BE2LONG(capacity
[0])+1;
1708 /* /// "nFakeGeometry()" */
1709 void nFakeGeometry(struct NepClassMS
*ncm
, struct DriveGeometry
*tddg
)
1717 ULONG remblks
= tddg
->dg_TotalSectors
;
1718 UWORD
*primetblptr
= PrimeTable
;
1725 if(!ncm
->ncm_Geometry
.dg_TotalSectors
)
1729 KPRINTF(10, ("Faking geometry for %ld sectors\n", tddg
->dg_TotalSectors
));
1730 //psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Prime factorisation for %ld", remblks);
1731 tddg
->dg_DeviceType
= ncm
->ncm_DeviceType
;
1732 tddg
->dg_Flags
= ncm
->ncm_Removable
? DGF_REMOVABLE
: 0;
1733 tddg
->dg_BufMemType
= MEMF_PUBLIC
;
1734 tddg
->dg_Reserved
= 0;
1737 KPRINTF(10, ("Loop\n"));
1738 // first prime is counted manually
1742 while(!(remblks
& 1))
1754 primetblptr
= PrimeTable
;
1757 // abort if no primes can be found anymore
1760 KPRINTF(10, ("remblks = %ld, curprime=%ld\n", remblks
, curprime
));
1761 if(remblks
% curprime
)
1763 if(remblks
>= curprimesq
)
1768 if(count
[curpos
]) // prime at least once
1771 count
[++curpos
] = 0;
1772 if(curpos
== 31) // end of buffer reached
1780 // use lookup table for the first primes to 2000
1781 curprime
= *primetblptr
++;
1783 // do it the hard way :-(
1786 primes
[curpos
] = curprime
;
1787 curprimesq
= curprime
* curprime
;
1791 remblks
/= curprime
;
1793 } while((remblks
> 1) && (remblks
>= curprime
));
1798 if((remblks
> 1) && curpos
)
1801 primes
[curpos
++] = remblks
;
1803 KPRINTF(10, ("Priming done, %ld different primes\n", curpos
));
1808 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "FakeGeometry: Total number of blocks is a prime number!");
1809 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_FIX_CAPACITY
)
1811 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
)
1813 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
1814 "This is probably due to the Fix Capacity switch being enabled incorrectly. Please check this.");
1817 ncm
->ncm_CDC
->cdc_PatchFlags
&= ~PFF_FIX_CAPACITY
;
1818 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
1819 "Fallback: Disabling Fix Capacity.");
1820 GM_UNIQUENAME(nStoreConfig
)(ncm
);
1821 remblks
= ++tddg
->dg_TotalSectors
;
1824 if(!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
))
1826 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_FIX_CAPACITY
;
1827 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1828 "Fallback: Enabling Fix Capacity.");
1829 GM_UNIQUENAME(nStoreConfig
)(ncm
);
1831 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1832 "Assuming Fix Capacity bug (total blocks instead of last block)!");
1834 remblks
= --tddg
->dg_TotalSectors
;
1839 for(cnt
= 0; cnt
< curpos
; cnt
++)
1841 totfactors
+= count
[cnt
];
1845 // - We want at least blocks per track * heads >= 64
1846 // - We want heads * heads < blocks per track
1847 // - We want blocks per track < cylinders
1848 // - We want heads < 8
1849 // - We want blocks per track < 256
1850 // - The rest goes into cylinders
1851 tddg
->dg_TrackSectors
= 1;
1853 remfact
= tddg
->dg_TotalSectors
;
1857 KPRINTF(10, ("Totfactors %ld\n", totfactors
));
1868 factor
= primes
[cnt
];
1869 if((tddg
->dg_TrackSectors
* factor
< 256) &&
1870 (tddg
->dg_TrackSectors
* factor
< remfact
))
1872 tddg
->dg_TrackSectors
*= factor
;
1875 else if((tddg
->dg_Heads
* factor
<= 16) &&
1876 (tddg
->dg_Heads
* tddg
->dg_Heads
* factor
* factor
< tddg
->dg_TrackSectors
))
1878 tddg
->dg_Heads
*= factor
;
1881 else if((tddg
->dg_Heads
* tddg
->dg_TrackSectors
>= 64) ||
1896 KPRINTF(10, ("Factor=%ld: Cylinders = %ld, Heads=%ld, TrackSectors=%ld, Blocks=%ld\n",
1897 factor
, remfact
, tddg
->dg_Heads
, tddg
->dg_TrackSectors
,
1898 tddg
->dg_TotalSectors
));
1901 KPRINTF(10, ("Final: Cylinders = %ld, Heads=%ld, TrackSectors=%ld, Blocks=%ld\n",
1902 remfact
, tddg
->dg_Heads
, tddg
->dg_TrackSectors
,
1903 tddg
->dg_TotalSectors
));
1905 tddg
->dg_Cylinders
= remfact
;
1906 tddg
->dg_CylSectors
= tddg
->dg_TrackSectors
* tddg
->dg_Heads
;
1916 #define SERVICEACTION_CAPACITY16 0x10
1918 /* /// "nGetGeometry()" */
1919 LONG
nGetGeometry(struct NepClassMS
*ncm
, struct IOStdReq
*ioreq
)
1921 struct DriveGeometry
*tddg
;
1924 struct SCSICmd scsicmd
;
1925 struct CapacityData capacitydata
;
1926 UBYTE sensedata
[18];
1930 BOOL gotblks
= FALSE
;
1931 BOOL gotcyl
= FALSE
;
1932 BOOL gotheads
= FALSE
;
1933 BOOL gotsect
= FALSE
;
1934 BOOL gotcylsect
= FALSE
;
1935 KPRINTF(10, ("\n"));
1937 ioreq
->io_Error
= 0;
1938 ioreq
->io_Actual
= 0;
1939 tddg
= (struct DriveGeometry
*) ioreq
->io_Data
;
1942 ioreq
->io_Error
= TDERR_NotSpecified
;
1943 return(ioreq
->io_Error
);
1945 length
= min(ioreq
->io_Length
,sizeof(struct DriveGeometry
));
1946 if((ncm
->ncm_GeoChangeCount
== ncm
->ncm_ChangeCount
) && ncm
->ncm_Geometry
.dg_TotalSectors
)
1949 memcpy(tddg
,&ncm
->ncm_Geometry
, (size_t) length
);
1950 ioreq
->io_Actual
= length
;
1954 ncm
->ncm_Geometry
.dg_DeviceType
= ncm
->ncm_DeviceType
;
1955 ncm
->ncm_Geometry
.dg_Flags
= ncm
->ncm_Removable
? DGF_REMOVABLE
: 0;
1958 * Capacity10, 32bit Sectorcount
1960 scsicmd
.scsi_Data
= (UWORD
*) &capacitydata
;
1961 scsicmd
.scsi_Length
= sizeof(capacitydata
);
1962 scsicmd
.scsi_Command
= cmd10
;
1963 scsicmd
.scsi_CmdLength
= 10;
1964 scsicmd
.scsi_Flags
= SCSIF_READ
|SCSIF_AUTOSENSE
;
1965 scsicmd
.scsi_SenseData
= sensedata
;
1966 scsicmd
.scsi_SenseLength
= 18;
1967 cmd10
[0] = SCSI_DA_READ_CAPACITY
;
1978 if((ioerr
= nScsiDirect(ncm
, &scsicmd
)))
1980 KPRINTF(10, ("ioerr %ld\n",ioerr
));
1981 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1982 "SCSI_READ_CAPACITY failed: %ld",
1985 * memset(tddg,0,Length);
1986 * The error should be enough
1988 return(ioreq
->io_Error
= ioerr
);
1991 * 32Bit Totalsectors
1994 ncm
->ncm_BlockSize
= ncm
->ncm_Geometry
.dg_SectorSize
= AROS_BE2LONG(capacitydata
.SectorSize
);
1995 ncm
->ncm_Geometry
.dg_TotalSectors
= AROS_BE2LONG(capacitydata
.SectorCount
) + 1;
1996 if(capacitydata
.SectorCount
== 0xffffffff)
1998 ncm
->ncm_Geometry
.dg_TotalSectors
--; // set to maximum
1999 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2000 "Capacity exceeds the maximum supported for 32 bit sector counts (usually >2TB)!");
2001 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2002 "I/O operations will still work, but geometry and partitioning will be unreliable!");
2004 KPRINTF(10, ("blocksize %ld totalsectors %ld\n", ncm
->ncm_BlockSize
, ncm
->ncm_Geometry
.dg_TotalSectors
));
2006 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
2008 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
2009 "Capacity: %ld blocks of %ld bytes", ncm
->ncm_Geometry
.dg_TotalSectors
, ncm
->ncm_Geometry
.dg_SectorSize
);
2011 ncm
->ncm_BlockShift
= 0;
2012 while((1<<ncm
->ncm_BlockShift
) < ncm
->ncm_BlockSize
)
2014 ncm
->ncm_BlockShift
++;
2017 KPRINTF(10, ("PatchFlags 0x%lx DeviceType %ld\n",ncm
->ncm_CDC
->cdc_PatchFlags
,ncm
->ncm_DeviceType
));
2019 if(!((ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_SIMPLE_SCSI
) ||
2020 (ncm
->ncm_DeviceType
== PDT_WORM
) ||
2021 (ncm
->ncm_DeviceType
== PDT_CDROM
)))
2023 KPRINTF(10, ("SIMPLE_SCSI or PDT_WORM/CDROM\n"));
2024 // cd roms don't have valid or sensible capacity mode pages
2025 if((mpdata
= nGetModePage(ncm
, 0x03)))
2027 if((tmpval
= (mpdata
[10]<<8)+mpdata
[11]))
2029 ncm
->ncm_Geometry
.dg_TrackSectors
= tmpval
;
2031 if(!ncm
->ncm_Geometry
.dg_Cylinders
)
2033 ncm
->ncm_Geometry
.dg_Cylinders
= ncm
->ncm_Geometry
.dg_TotalSectors
;
2036 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
2038 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
2039 "Capacity: TrackSectors=%ld",
2040 ncm
->ncm_Geometry
.dg_TrackSectors
);
2045 * Cylinder and co are only defined for old 32Bit Totalsectors.
2046 * >2TB they have no meaning anyway, so they are calculated based
2049 // recheck, could have simple scsi enabled in the meanwhile
2050 if(!((ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_SIMPLE_SCSI
) ||
2051 (ncm
->ncm_DeviceType
== PDT_WORM
) ||
2052 (ncm
->ncm_DeviceType
== PDT_CDROM
)))
2054 KPRINTF(10, ("recheck1 SIMPLE_SCSI or PDT_WORM/CDROM\n"));
2055 if((mpdata
= nGetModePage(ncm
, 0x04)))
2057 if((tmpval
= (mpdata
[2]<<16)+(mpdata
[3]<<8)+mpdata
[4]))
2059 ncm
->ncm_Geometry
.dg_Cylinders
= tmpval
;
2060 ncm
->ncm_Geometry
.dg_Heads
= mpdata
[5];
2061 gotcyl
= gotheads
= TRUE
;
2063 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
2065 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
2066 "Capacity: Cylinders=%ld, Heads=%ld",
2067 ncm
->ncm_Geometry
.dg_Cylinders
, ncm
->ncm_Geometry
.dg_Heads
);
2071 // recheck, could have simple scsi enabled in the meanwhile
2072 if(!((ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_SIMPLE_SCSI
) ||
2073 (ncm
->ncm_DeviceType
== PDT_WORM
) ||
2074 (ncm
->ncm_DeviceType
== PDT_CDROM
)))
2076 KPRINTF(10, ("recheck2 SIMPLE_SCSI or PDT_WORM/CDROM\n"));
2077 if((mpdata
= nGetModePage(ncm
, 0x05)))
2079 if((tmpval
= (mpdata
[8]<<8)+mpdata
[9]))
2081 ncm
->ncm_Geometry
.dg_Cylinders
= tmpval
;
2082 ncm
->ncm_Geometry
.dg_Heads
= mpdata
[4];
2083 ncm
->ncm_Geometry
.dg_TrackSectors
= mpdata
[5];
2085 gotcyl
= gotheads
= gotsect
= TRUE
;
2089 ncm
->ncm_BlockSize
= ncm
->ncm_Geometry
.dg_SectorSize
= (mpdata
[6]<<8)+mpdata
[7];
2090 ncm
->ncm_BlockShift
= 0;
2091 while((1<<ncm
->ncm_BlockShift
) < ncm
->ncm_BlockSize
)
2093 ncm
->ncm_BlockShift
++;
2095 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
2097 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
2098 "Capacity: %ld blocks of %ld bytes", ncm
->ncm_Geometry
.dg_TotalSectors
, ncm
->ncm_BlockSize
);
2101 else if(ncm
->ncm_BlockSize
!= (mpdata
[6]<<8)+mpdata
[7])
2103 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2104 "Inconsistent block size information %ld != %ld!",
2105 ncm
->ncm_BlockSize
, (mpdata
[6]<<8)+mpdata
[7]);
2107 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
2109 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
2110 "Capacity: Cylinders=%ld, Heads=%ld, TrackSectors=%ld",
2111 ncm
->ncm_Geometry
.dg_Cylinders
, ncm
->ncm_Geometry
.dg_Heads
, ncm
->ncm_Geometry
.dg_TrackSectors
);
2116 // missing total blocks?
2117 if((!gotblks
) && gotcyl
&& gotheads
&& gotsect
)
2119 ncm
->ncm_Geometry
.dg_TotalSectors
= ncm
->ncm_Geometry
.dg_Cylinders
* ncm
->ncm_Geometry
.dg_Heads
* ncm
->ncm_Geometry
.dg_TrackSectors
;
2122 // missing cylinders?
2123 if(gotblks
&& (!gotcyl
) && gotheads
&& gotsect
)
2125 ncm
->ncm_Geometry
.dg_Cylinders
= ncm
->ncm_Geometry
.dg_TotalSectors
/ (ncm
->ncm_Geometry
.dg_Heads
* ncm
->ncm_Geometry
.dg_TrackSectors
);
2129 if(gotblks
&& gotcyl
&& (!gotheads
) && gotsect
)
2131 ncm
->ncm_Geometry
.dg_Heads
= ncm
->ncm_Geometry
.dg_TotalSectors
/ (ncm
->ncm_Geometry
.dg_Cylinders
* ncm
->ncm_Geometry
.dg_TrackSectors
);
2134 // missing tracks per sector
2135 if(gotblks
&& gotcyl
&& gotheads
&& (!gotsect
))
2137 ncm
->ncm_Geometry
.dg_TrackSectors
= ncm
->ncm_Geometry
.dg_TotalSectors
/ (ncm
->ncm_Geometry
.dg_Cylinders
* ncm
->ncm_Geometry
.dg_Heads
);
2141 if(gotblks
&& gotcyl
&& gotheads
&& gotsect
&&
2142 (ncm
->ncm_Geometry
.dg_Cylinders
* ncm
->ncm_Geometry
.dg_TrackSectors
* ncm
->ncm_Geometry
.dg_Heads
== ncm
->ncm_Geometry
.dg_TotalSectors
- 1) &&
2143 (!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_FIX_CAPACITY
)))
2145 if(!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
))
2147 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_FIX_CAPACITY
;
2148 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2149 "Fallback: Enabling Fix Capacity.");
2150 GM_UNIQUENAME(nStoreConfig
)(ncm
);
2151 ncm
->ncm_Geometry
.dg_TotalSectors
--;
2153 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2154 "Fix Capacity is probably needed for this device. Please check this.");
2157 else if(gotblks
&& gotcyl
&& gotheads
&& gotsect
&&
2158 (ncm
->ncm_Geometry
.dg_Cylinders
* ncm
->ncm_Geometry
.dg_TrackSectors
* ncm
->ncm_Geometry
.dg_Heads
== ncm
->ncm_Geometry
.dg_TotalSectors
+ 1) &&
2159 ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_FIX_CAPACITY
)
2161 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
)
2163 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2164 "Fix Capacity is probably enabled incorrectly. Please check this.");
2166 ncm
->ncm_CDC
->cdc_PatchFlags
&= ~PFF_FIX_CAPACITY
;
2167 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2168 "Fallback: Disabling Fix Capacity.");
2169 GM_UNIQUENAME(nStoreConfig
)(ncm
);
2170 ncm
->ncm_Geometry
.dg_TotalSectors
++;
2174 // some devices report these bogus values regardless of actual device capacity, though the total number of blocks is correct.
2175 if(((ncm
->ncm_Geometry
.dg_Cylinders
== 500) && (ncm
->ncm_Geometry
.dg_TrackSectors
== 32) && (ncm
->ncm_Geometry
.dg_Heads
== 8)) ||
2176 ((ncm
->ncm_Geometry
.dg_Cylinders
== 16383) && (ncm
->ncm_Geometry
.dg_TrackSectors
== 63) && (ncm
->ncm_Geometry
.dg_Heads
== 16)))
2178 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Firmware returns known bogus geometry, will fall back to faked geometry!");
2179 gotheads
= gotcyl
= gotsect
= FALSE
;
2180 if((ncm
->ncm_CDC
->cdc_PatchFlags
& (PFF_SIMPLE_SCSI
|PFF_NO_FALLBACK
)) == PFF_SIMPLE_SCSI
)
2182 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_SIMPLE_SCSI
;
2183 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2184 "Fallback: Enabling Simple SCSI.");
2185 GM_UNIQUENAME(nStoreConfig
)(ncm
);
2189 // missing more than one?
2190 if(gotblks
&& (!(gotheads
&& gotcyl
&& gotsect
)))
2192 nFakeGeometry(ncm
, &ncm
->ncm_Geometry
);
2196 ncm
->ncm_Geometry
.dg_CylSectors
= ncm
->ncm_Geometry
.dg_TrackSectors
* ncm
->ncm_Geometry
.dg_Heads
;
2199 if(ncm
->ncm_Geometry
.dg_Cylinders
* ncm
->ncm_Geometry
.dg_CylSectors
!= ncm
->ncm_Geometry
.dg_TotalSectors
)
2201 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2202 "Estimated Geometry yields %ld less total blocks %ld: Cylinders=%ld, CylSectors=%ld, Heads=%ld, TrackSectors=%ld, Blocks=%ld",
2203 ncm
->ncm_Geometry
.dg_TotalSectors
- ncm
->ncm_Geometry
.dg_Cylinders
* ncm
->ncm_Geometry
.dg_CylSectors
,
2204 ncm
->ncm_Geometry
.dg_Cylinders
* ncm
->ncm_Geometry
.dg_CylSectors
,
2205 ncm
->ncm_Geometry
.dg_Cylinders
, ncm
->ncm_Geometry
.dg_CylSectors
, ncm
->ncm_Geometry
.dg_Heads
, ncm
->ncm_Geometry
.dg_TrackSectors
,
2206 ncm
->ncm_Geometry
.dg_TotalSectors
);
2208 else if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
2210 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
2211 "Capacity: Cylinders=%ld, CylSectors=%ld, Heads=%ld, TrackSectors=%ld, Blocks=%ld, SectorSize=%ld",
2212 ncm
->ncm_Geometry
.dg_Cylinders
, ncm
->ncm_Geometry
.dg_CylSectors
, ncm
->ncm_Geometry
.dg_Heads
, ncm
->ncm_Geometry
.dg_TrackSectors
,
2213 ncm
->ncm_Geometry
.dg_TotalSectors
, ncm
->ncm_Geometry
.dg_SectorSize
);
2216 ncm
->ncm_Geometry
.dg_BufMemType
= MEMF_PUBLIC
;
2217 ncm
->ncm_Geometry
.dg_Reserved
= 0;
2218 memcpy(tddg
, &ncm
->ncm_Geometry
, (size_t) length
);
2219 ioreq
->io_Actual
= length
;
2220 ncm
->ncm_GeoChangeCount
= ncm
->ncm_ChangeCount
;
2221 return(ioreq
->io_Error
);
2225 /* /// "nStartStop()" */
2226 LONG
nStartStop(struct NepClassMS
*ncm
, struct IOStdReq
*ioreq
)
2229 struct SCSICmd scsicmd
;
2230 UBYTE sensedata
[18];
2233 if((ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_SIMPLE_SCSI
)
2234 && ioreq
->io_Command
!= TD_EJECT
)
2236 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Simple SCSI: Ignoring START_STOP_UNIT command");
2239 scsicmd
.scsi_Data
= NULL
;
2240 scsicmd
.scsi_Length
= 0;
2241 scsicmd
.scsi_Command
= cmd6
;
2242 scsicmd
.scsi_CmdLength
= 6;
2243 scsicmd
.scsi_Flags
= SCSIF_AUTOSENSE
|0x80;
2244 scsicmd
.scsi_SenseData
= sensedata
;
2245 scsicmd
.scsi_SenseLength
= 18;
2246 cmd6
[0] = SCSI_DA_START_STOP_UNIT
;
2250 switch(ioreq
->io_Command
)
2261 cmd6
[4] = ioreq
->io_Length
? 0x02 : 0x03;
2265 if((ioerr
= nScsiDirect(ncm
, &scsicmd
)))
2267 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2268 "START_STOP_UNIT failed: %ld",
2270 ioreq
->io_Error
= TDERR_NotSpecified
;
2272 return(ioreq
->io_Error
);
2276 /* /// "nRead64Emul()" */
2277 LONG
nRead64Emul(struct NepClassMS
*ncm
, struct IOStdReq
*ioreq
)
2280 ULONG
*cmd10sb
= (ULONG
*)&cmd10
[2];
2281 UBYTE sensedata
[18];
2282 ULONG dataoffset
= 0;
2283 ULONG dataremain
= ioreq
->io_Length
;
2286 ULONG maxtrans
= 1UL<<(ncm
->ncm_CDC
->cdc_MaxTransfer
+16);
2287 ULONG insideblockoffset
;
2288 struct SCSICmd scsicmd
;
2290 if(dataremain
& 511)
2292 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2293 "Attempt to read partial block (%ld %% %ld != 0)!",
2294 dataremain
, ncm
->ncm_BlockSize
);
2295 ioreq
->io_Actual
= 0;
2296 return(ioreq
->io_Error
= IOERR_BADLENGTH
);
2298 if(ioreq
->io_Offset
& 511)
2300 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2301 "Attempt to read unaligned block (%ld %% %ld != 0)!",
2302 ioreq
->io_Offset
, ncm
->ncm_BlockSize
);
2303 ioreq
->io_Actual
= 0;
2304 return(ioreq
->io_Error
= IOERR_BADADDRESS
);
2307 if(!ncm
->ncm_OneBlock
|| (ncm
->ncm_OneBlockSize
< ncm
->ncm_BlockSize
))
2309 psdFreeVec(ncm
->ncm_OneBlock
);
2310 if(!(ncm
->ncm_OneBlock
= psdAllocVec(ncm
->ncm_BlockSize
)))
2312 return(IOERR_BADADDRESS
);
2314 ncm
->ncm_OneBlockSize
= ncm
->ncm_BlockSize
;
2317 startblock
= (ioreq
->io_Offset
>>ncm
->ncm_BlockShift
)|(ioreq
->io_Actual
<<(32-ncm
->ncm_BlockShift
));
2318 insideblockoffset
= (ioreq
->io_Offset
& ((1<<ncm
->ncm_BlockShift
)-1));
2321 KPRINTF(10, ("Reading from block %ld, %ld bytes left...\n", startblock
, dataremain
));
2322 datalen
= dataremain
;
2323 if(datalen
> maxtrans
)
2327 if(insideblockoffset
|| (datalen
< ncm
->ncm_BlockSize
))
2329 if(datalen
> ncm
->ncm_BlockSize
-insideblockoffset
)
2331 datalen
= ncm
->ncm_BlockSize
-insideblockoffset
;
2333 scsicmd
.scsi_Data
= (UWORD
*) ncm
->ncm_OneBlock
;
2334 scsicmd
.scsi_Length
= ncm
->ncm_BlockSize
;
2335 scsicmd
.scsi_Command
= cmd10
;
2336 scsicmd
.scsi_CmdLength
= 10;
2337 scsicmd
.scsi_Flags
= SCSIF_READ
|SCSIF_AUTOSENSE
|0x80;
2338 scsicmd
.scsi_SenseData
= sensedata
;
2339 scsicmd
.scsi_SenseLength
= 18;
2340 cmd10
[0] = SCSI_DA_READ_10
;
2342 *cmd10sb
= AROS_LONG2BE(startblock
);
2347 if((ioreq
->io_Error
= nScsiDirect(ncm
, &scsicmd
)))
2349 KPRINTF(10, ("Read error!\n"));
2352 CopyMemQuick(&ncm
->ncm_OneBlock
[insideblockoffset
], &(((UBYTE
*) ioreq
->io_Data
)[dataoffset
]), datalen
);
2353 insideblockoffset
= 0;
2356 scsicmd
.scsi_Data
= (UWORD
*) &(((UBYTE
*) ioreq
->io_Data
)[dataoffset
]);
2357 scsicmd
.scsi_Length
= datalen
;
2358 scsicmd
.scsi_Command
= cmd10
;
2359 scsicmd
.scsi_CmdLength
= 10;
2360 scsicmd
.scsi_Flags
= SCSIF_READ
|SCSIF_AUTOSENSE
|0x80;
2361 scsicmd
.scsi_SenseData
= sensedata
;
2362 scsicmd
.scsi_SenseLength
= 18;
2363 cmd10
[0] = SCSI_DA_READ_10
;
2365 *cmd10sb
= AROS_LONG2BE(startblock
);
2367 cmd10
[7] = datalen
>>(ncm
->ncm_BlockShift
+8);
2368 cmd10
[8] = datalen
>>ncm
->ncm_BlockShift
;
2370 if((ioreq
->io_Error
= nScsiDirect(ncm
, &scsicmd
)))
2372 KPRINTF(10, ("Read error!\n"));
2375 startblock
+= (insideblockoffset
+datalen
)>>ncm
->ncm_BlockShift
;
2377 dataoffset
+= datalen
;
2378 dataremain
-= datalen
;
2380 ioreq
->io_Actual
= dataoffset
;
2381 return(ioreq
->io_Error
);
2385 /* /// "nWrite64Emul()" */
2386 LONG
nWrite64Emul(struct NepClassMS
*ncm
, struct IOStdReq
*ioreq
)
2389 ULONG
*cmd10sb
= (ULONG
*)&cmd10
[2];
2390 UBYTE sensedata
[18];
2391 ULONG dataoffset
= 0;
2392 ULONG dataremain
= ioreq
->io_Length
;
2395 ULONG maxtrans
= 1UL<<(ncm
->ncm_CDC
->cdc_MaxTransfer
+16);
2396 ULONG insideblockoffset
;
2397 struct SCSICmd scsicmd
;
2399 if(dataremain
& 511)
2401 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2402 "Attempt to write partial block (%ld %% %ld != 0)!",
2403 dataremain
, ncm
->ncm_BlockSize
);
2404 ioreq
->io_Actual
= 0;
2405 return(ioreq
->io_Error
= IOERR_BADLENGTH
);
2407 if(ioreq
->io_Offset
& 511)
2409 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2410 "Attempt to write unaligned block (%ld %% %ld != 0)!",
2411 ioreq
->io_Offset
, ncm
->ncm_BlockSize
);
2412 ioreq
->io_Actual
= 0;
2413 return(ioreq
->io_Error
= IOERR_BADADDRESS
);
2416 if(!ncm
->ncm_OneBlock
|| (ncm
->ncm_OneBlockSize
< ncm
->ncm_BlockSize
))
2418 psdFreeVec(ncm
->ncm_OneBlock
);
2419 if(!(ncm
->ncm_OneBlock
= psdAllocVec(ncm
->ncm_BlockSize
)))
2421 return(IOERR_BADADDRESS
);
2423 ncm
->ncm_OneBlockSize
= ncm
->ncm_BlockSize
;
2426 startblock
= (ioreq
->io_Offset
>>ncm
->ncm_BlockShift
)|(ioreq
->io_Actual
<<(32-ncm
->ncm_BlockShift
));
2427 insideblockoffset
= (ioreq
->io_Offset
& ((1<<ncm
->ncm_BlockShift
)-1));
2430 KPRINTF(10, ("Writing from block %ld, %ld bytes left...\n", startblock
, dataremain
));
2431 datalen
= dataremain
;
2432 if(datalen
> maxtrans
)
2436 if(insideblockoffset
|| (datalen
< ncm
->ncm_BlockSize
))
2438 if(datalen
> ncm
->ncm_BlockSize
-insideblockoffset
)
2440 datalen
= ncm
->ncm_BlockSize
-insideblockoffset
;
2442 scsicmd
.scsi_Data
= (UWORD
*) ncm
->ncm_OneBlock
;
2443 scsicmd
.scsi_Length
= ncm
->ncm_BlockSize
;
2444 scsicmd
.scsi_Command
= cmd10
;
2445 scsicmd
.scsi_CmdLength
= 10;
2446 scsicmd
.scsi_Flags
= SCSIF_READ
|SCSIF_AUTOSENSE
|0x80;
2447 scsicmd
.scsi_SenseData
= sensedata
;
2448 scsicmd
.scsi_SenseLength
= 18;
2449 cmd10
[0] = SCSI_DA_READ_10
;
2451 *cmd10sb
= AROS_LONG2BE(startblock
);
2456 if((ioreq
->io_Error
= nScsiDirect(ncm
, &scsicmd
)))
2458 KPRINTF(10, ("Read error!\n"));
2461 CopyMemQuick(&(((UBYTE
*) ioreq
->io_Data
)[dataoffset
]), &ncm
->ncm_OneBlock
[insideblockoffset
], datalen
);
2463 //scsicmd.scsi_Data = (UWORD *) ncm->ncm_OneBlock;
2464 //scsicmd.scsi_Length = ncm->ncm_BlockSize;
2465 //scsicmd.scsi_Command = cmd10;
2466 //scsicmd.scsi_CmdLength = 10;
2467 scsicmd
.scsi_Flags
= SCSIF_WRITE
|SCSIF_AUTOSENSE
|0x80;
2468 //scsicmd.scsi_SenseData = sensedata;
2469 //scsicmd.scsi_SenseLength = 18;
2470 cmd10
[0] = SCSI_DA_WRITE_10
;
2472 //*((ULONG *) (&cmd10[2])) = AROS_LONG2BE(startblock);
2477 if((ioreq
->io_Error
= nScsiDirect(ncm
, &scsicmd
)))
2479 KPRINTF(10, ("Write error!\n"));
2482 insideblockoffset
= 0;
2485 scsicmd
.scsi_Data
= (UWORD
*) &(((UBYTE
*) ioreq
->io_Data
)[dataoffset
]);
2486 scsicmd
.scsi_Length
= datalen
;
2487 scsicmd
.scsi_Command
= cmd10
;
2488 scsicmd
.scsi_CmdLength
= 10;
2489 scsicmd
.scsi_Flags
= SCSIF_WRITE
|SCSIF_AUTOSENSE
|0x80;
2490 scsicmd
.scsi_SenseData
= sensedata
;
2491 scsicmd
.scsi_SenseLength
= 18;
2492 cmd10
[0] = SCSI_DA_WRITE_10
;
2494 *cmd10sb
= AROS_LONG2BE(startblock
);
2496 cmd10
[7] = datalen
>>(ncm
->ncm_BlockShift
+8);
2497 cmd10
[8] = datalen
>>ncm
->ncm_BlockShift
;
2499 if((ioreq
->io_Error
= nScsiDirect(ncm
, &scsicmd
)))
2501 KPRINTF(10, ("Write error!\n"));
2504 startblock
+= (insideblockoffset
+datalen
)>>ncm
->ncm_BlockShift
;
2506 dataoffset
+= datalen
;
2507 dataremain
-= datalen
;
2509 ioreq
->io_Actual
= dataoffset
;
2510 return(ioreq
->io_Error
);
2514 /* /// "nRead64()" */
2515 LONG
nRead64(struct NepClassMS
*ncm
, struct IOStdReq
*ioreq
)
2519 UBYTE sensedata
[18];
2520 ULONG dataoffset
= 0;
2521 ULONG dataremain
= ioreq
->io_Length
;
2523 ULONG startblockhigh
;
2525 ULONG oldstartblock
;
2526 ULONG maxtrans
= 1UL<<(ncm
->ncm_CDC
->cdc_MaxTransfer
+16);
2527 struct SCSICmd scsicmd
;
2529 if(!ncm
->ncm_BlockSize
)
2533 if((((dataremain
>> ncm
->ncm_BlockShift
)<<ncm
->ncm_BlockShift
) != dataremain
) ||
2534 (((ioreq
->io_Offset
>> ncm
->ncm_BlockShift
)<<ncm
->ncm_BlockShift
) != ioreq
->io_Offset
))
2536 KPRINTF(20, ("unaligned read access offset %ld, length %ld...\n", ioreq
->io_Offset
, dataremain
));
2537 if((!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_EMUL_LARGE_BLK
)) && (!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
)))
2539 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_EMUL_LARGE_BLK
;
2540 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2541 "Fallback: Enabling emulation for large block devices.");
2542 GM_UNIQUENAME(nStoreConfig
)(ncm
);
2544 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_EMUL_LARGE_BLK
)
2546 return(nRead64Emul(ncm
, ioreq
));
2548 if((dataremain
>> ncm
->ncm_BlockShift
)<<ncm
->ncm_BlockShift
!= dataremain
)
2550 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2551 "Attempt to read partial block (%ld %% %ld != 0)!",
2552 dataremain
, ncm
->ncm_BlockSize
);
2553 ioreq
->io_Error
= IOERR_BADLENGTH
;
2555 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2556 "Attempt to read unaligned block (%ld %% %ld != 0)!",
2557 ioreq
->io_Offset
, ncm
->ncm_BlockSize
);
2558 ioreq
->io_Error
= IOERR_BADADDRESS
;
2560 if(ncm
->ncm_BlockSize
!= 512)
2562 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2563 "The used FileSystem or other software must support %ld byte blocks!",
2564 ncm
->ncm_BlockSize
);
2566 ioreq
->io_Actual
= 0;
2567 return(ioreq
->io_Error
);
2570 startblockhigh
= ioreq
->io_Actual
>>ncm
->ncm_BlockShift
;
2571 startblock
= (ioreq
->io_Offset
>>ncm
->ncm_BlockShift
)|(ioreq
->io_Actual
<<(32-ncm
->ncm_BlockShift
));
2574 KPRINTF(10, ("Reading from block %ld, %ld bytes left...\n", startblock
, dataremain
));
2575 datalen
= dataremain
;
2576 if(datalen
> maxtrans
)
2580 scsicmd
.scsi_Data
= (UWORD
*) &(((UBYTE
*) ioreq
->io_Data
)[dataoffset
]);
2581 scsicmd
.scsi_Length
= datalen
;
2582 scsicmd
.scsi_Flags
= SCSIF_READ
|SCSIF_AUTOSENSE
|0x80;
2583 scsicmd
.scsi_SenseData
= sensedata
;
2584 scsicmd
.scsi_SenseLength
= 18;
2587 ULONG
*cmd16sbh
= (ULONG
*)&cmd16
[2];
2588 ULONG
*cmd16sbl
= (ULONG
*)&cmd16
[6];
2589 // Arithmetics for >2 TB needed
2590 scsicmd
.scsi_Command
= cmd16
;
2591 scsicmd
.scsi_CmdLength
= 16;
2592 cmd16
[0] = SCSI_DA_READ_16
;
2594 *cmd16sbh
= AROS_LONG2BE(startblockhigh
);
2595 *cmd16sbl
= AROS_LONG2BE(startblock
);
2596 cmd16
[10] = datalen
>>(ncm
->ncm_BlockShift
+24);
2597 cmd16
[11] = datalen
>>(ncm
->ncm_BlockShift
+16);
2598 cmd16
[12] = datalen
>>(ncm
->ncm_BlockShift
+8);
2599 cmd16
[13] = datalen
>>ncm
->ncm_BlockShift
;
2603 ULONG
*cmd10sb
= (ULONG
*)&cmd10
[2];
2604 scsicmd
.scsi_Command
= cmd10
;
2605 scsicmd
.scsi_CmdLength
= 10;
2606 cmd10
[0] = SCSI_DA_READ_10
;
2608 *cmd10sb
= AROS_LONG2BE(startblock
);
2610 cmd10
[7] = datalen
>>(ncm
->ncm_BlockShift
+8);
2611 cmd10
[8] = datalen
>>ncm
->ncm_BlockShift
;
2614 if((ioreq
->io_Error
= nScsiDirect(ncm
, &scsicmd
)))
2616 KPRINTF(10, ("Read error!\n"));
2619 dataoffset
+= datalen
;
2620 dataremain
-= datalen
;
2621 oldstartblock
= startblock
;
2622 startblock
+= datalen
>>ncm
->ncm_BlockShift
;
2623 if(startblock
< oldstartblock
)
2625 // wrap around occurred
2629 ioreq
->io_Actual
= dataoffset
;
2630 return(ioreq
->io_Error
);
2634 /* /// "nSeek64()" */
2635 LONG
nSeek64(struct NepClassMS
*ncm
, struct IOStdReq
*ioreq
)
2638 ULONG
*cmd10sb
= (ULONG
*)&cmd10
[2];
2639 UBYTE sensedata
[18];
2640 struct SCSICmd scsicmd
;
2643 if(!ncm
->ncm_BlockSize
)
2647 if(((ioreq
->io_Offset
>> ncm
->ncm_BlockShift
)<<ncm
->ncm_BlockShift
) != ioreq
->io_Offset
)
2649 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2650 "Attempt to to seek to unaligned block (%ld %% %ld != 0)!",
2651 ioreq
->io_Offset
, ncm
->ncm_BlockSize
);
2652 if(ncm
->ncm_BlockSize
!= 512)
2654 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2655 "The used FileSystem or other software must support %ld byte blocks!",
2656 ncm
->ncm_BlockSize
);
2658 ioreq
->io_Actual
= 0;
2659 return(ioreq
->io_Error
= IOERR_BADADDRESS
);
2662 startblock
= (ioreq
->io_Offset
>>ncm
->ncm_BlockShift
)|(ioreq
->io_Actual
<<(32-ncm
->ncm_BlockShift
));
2663 scsicmd
.scsi_Data
= NULL
;
2664 scsicmd
.scsi_Length
= 0;
2665 scsicmd
.scsi_CmdLength
= 10;
2666 scsicmd
.scsi_Flags
= SCSIF_READ
|SCSIF_AUTOSENSE
|0x80;
2667 scsicmd
.scsi_SenseData
= sensedata
;
2668 scsicmd
.scsi_SenseLength
= 18;
2669 cmd10
[0] = SCSI_DA_SEEK_10
;
2671 *cmd10sb
= AROS_LONG2BE(startblock
);
2676 if((ioreq
->io_Error
= nScsiDirect(ncm
, &scsicmd
)))
2678 KPRINTF(10, ("Seek error!\n"));
2680 ioreq
->io_Actual
= 0;
2681 return(ioreq
->io_Error
);
2685 /* /// "nWrite64()" */
2686 LONG
nWrite64(struct NepClassMS
*ncm
, struct IOStdReq
*ioreq
)
2690 UBYTE sensedata
[18];
2691 ULONG dataoffset
= 0;
2692 ULONG dataremain
= ioreq
->io_Length
;
2694 ULONG startblockhigh
;
2696 ULONG oldstartblock
;
2697 ULONG maxtrans
= 1UL<<(ncm
->ncm_CDC
->cdc_MaxTransfer
+16);
2698 struct SCSICmd scsicmd
;
2700 if(!ncm
->ncm_BlockSize
)
2704 if(((dataremain
>> ncm
->ncm_BlockShift
)<<ncm
->ncm_BlockShift
!= dataremain
) ||
2705 ((ioreq
->io_Offset
>> ncm
->ncm_BlockShift
)<<ncm
->ncm_BlockShift
!= ioreq
->io_Offset
))
2707 KPRINTF(20, ("unaligned write access offset %ld, length %ld...\n", ioreq
->io_Offset
, dataremain
));
2708 if((!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_EMUL_LARGE_BLK
)) && (!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
)))
2710 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_EMUL_LARGE_BLK
;
2711 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2712 "Fallback: Enabling emulation for large block devices.");
2713 GM_UNIQUENAME(nStoreConfig
)(ncm
);
2715 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_EMUL_LARGE_BLK
)
2717 return(nWrite64Emul(ncm
, ioreq
));
2719 if((dataremain
>> ncm
->ncm_BlockShift
)<<ncm
->ncm_BlockShift
!= dataremain
)
2721 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2722 "Attempt to write partial block (%ld %% %ld != 0)!",
2723 dataremain
, ncm
->ncm_BlockSize
);
2724 ioreq
->io_Error
= IOERR_BADLENGTH
;
2726 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2727 "Attempt to write unaligned block (%ld %% %ld != 0)!",
2728 ioreq
->io_Offset
, ncm
->ncm_BlockSize
);
2729 ioreq
->io_Error
= IOERR_BADADDRESS
;
2731 if(ncm
->ncm_BlockSize
!= 512)
2733 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2734 "The used FileSystem or other software must support %ld byte blocks!",
2735 ncm
->ncm_BlockSize
);
2737 ioreq
->io_Actual
= 0;
2738 return(ioreq
->io_Error
);
2741 startblockhigh
= ioreq
->io_Actual
>>ncm
->ncm_BlockShift
;
2742 startblock
= (ioreq
->io_Offset
>>ncm
->ncm_BlockShift
)|(ioreq
->io_Actual
<<(32-ncm
->ncm_BlockShift
));
2745 datalen
= dataremain
;
2746 if(datalen
> maxtrans
)
2750 scsicmd
.scsi_Data
= (UWORD
*) &(((UBYTE
*) ioreq
->io_Data
)[dataoffset
]);
2751 scsicmd
.scsi_Length
= datalen
;
2752 scsicmd
.scsi_Flags
= SCSIF_WRITE
|SCSIF_AUTOSENSE
|0x80;
2753 scsicmd
.scsi_SenseData
= sensedata
;
2754 scsicmd
.scsi_SenseLength
= 18;
2757 ULONG
*cmd16sbh
= (ULONG
*)&cmd16
[2];
2758 ULONG
*cmd16sbl
= (ULONG
*)&cmd16
[6];
2759 // Arithmetics for >2 TB needed
2760 scsicmd
.scsi_Command
= cmd16
;
2761 scsicmd
.scsi_CmdLength
= 16;
2762 cmd16
[0] = SCSI_DA_WRITE_16
;
2764 *cmd16sbh
= AROS_LONG2BE(startblockhigh
);
2765 *cmd16sbl
= AROS_LONG2BE(startblock
);
2766 cmd16
[10] = datalen
>>(ncm
->ncm_BlockShift
+24);
2767 cmd16
[11] = datalen
>>(ncm
->ncm_BlockShift
+16);
2768 cmd16
[12] = datalen
>>(ncm
->ncm_BlockShift
+8);
2769 cmd16
[13] = datalen
>>ncm
->ncm_BlockShift
;
2773 ULONG
*cmd10sb
= (ULONG
*)&cmd10
[2];
2774 scsicmd
.scsi_Command
= cmd10
;
2775 scsicmd
.scsi_CmdLength
= 10;
2776 cmd10
[0] = SCSI_DA_WRITE_10
;
2778 *cmd10sb
= AROS_LONG2BE(startblock
);
2780 cmd10
[7] = datalen
>>(ncm
->ncm_BlockShift
+8);
2781 cmd10
[8] = datalen
>>ncm
->ncm_BlockShift
;
2784 if((ioreq
->io_Error
= nScsiDirect(ncm
, &scsicmd
)))
2788 dataoffset
+= datalen
;
2789 dataremain
-= datalen
;
2790 oldstartblock
= startblock
;
2791 startblock
+= datalen
>>ncm
->ncm_BlockShift
;
2792 if(startblock
< oldstartblock
)
2794 // wrap around occurred
2798 ioreq
->io_Actual
= dataoffset
;
2799 return(ioreq
->io_Error
);
2803 /* /// "nCBIRequestSense()" */
2804 LONG
nCBIRequestSense(struct NepClassMS
*ncm
, UBYTE
*senseptr
, ULONG datalen
)
2809 struct UsbMSCBIStatusWrapper umscsw
;
2811 memset(sensecmd
, 0, 12);
2812 senseptr
[2] = SK_ILLEGAL_REQUEST
;
2813 sensecmd
[0] = SCSI_REQUEST_SENSE
;
2817 sensecmd
[4] = datalen
;
2819 KPRINTF(2, ("sense command block phase...\n"));
2821 /*psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
2822 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
2823 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);*/
2824 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_CLASS
|URTF_INTERFACE
,
2825 UMSR_ADSC
, 0, (ULONG
) ncm
->ncm_UnitIfNum
);
2826 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, sensecmd
, ((ncm
->ncm_CSType
== MS_ATAPI_SUBCLASS
) ||
2827 (ncm
->ncm_CSType
== MS_FDDATAPI_SUBCLASS
) ||
2828 (ncm
->ncm_CSType
== MS_UFI_SUBCLASS
)) ? (ULONG
) 12 : (ULONG
) 6);
2831 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_CLEAR_EP
)
2833 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
2834 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPInNum
|URTF_IN
);
2835 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
2838 KPRINTF(2, ("sense data phase %ld bytes...\n", datalen
));
2839 ioerr
= psdDoPipe(ncm
->ncm_EPInPipe
, senseptr
, datalen
);
2840 actual
= psdGetPipeActual(ncm
->ncm_EPInPipe
);
2841 if(ioerr
== UHIOERR_STALL
)
2843 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
2844 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPInNum
|URTF_IN
);
2845 psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
2847 if((!ioerr
) || (ioerr
== UHIOERR_RUNTPACKET
))
2849 KPRINTF(2, ("sense command status phase...\n"));
2850 if(ncm
->ncm_TPType
== MS_PROTO_CBI
)
2853 umscsw
.bValue
= USMF_CSW_PHASEERR
;
2854 ioerr
= psdDoPipe(ncm
->ncm_EPIntPipe
, &umscsw
, sizeof(struct UsbMSCBIStatusWrapper
));
2855 if(ioerr
&& (ioerr
!= UHIOERR_RUNTPACKET
))
2857 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2858 "Status interrupt failed: %s (%ld)",
2859 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2862 umscsw
.bValue
&= USMF_CSW_PERSIST
; /* mask out other bits */
2865 umscsw
.bValue
= USMF_CSW_PASS
;
2868 if((!ioerr
) || (ioerr
== UHIOERR_RUNTPACKET
))
2870 KPRINTF(2, ("sense Status:\n"
2871 " Status : %02lx\n",
2875 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2876 "Sense failed: %ld",
2878 if(umscsw
.bValue
== USMF_CSW_PHASEERR
)
2883 switch(senseptr
[2] & SK_MASK
)
2885 case SK_UNIT_ATTENTION
:
2886 if((senseptr
[12] == 0x28) ||
2887 (senseptr
[12] == 0x3A))
2889 ncm
->ncm_ChangeCount
++;
2894 if((ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
) && (senseptr
[2] & SK_MASK
))
2896 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2897 "Request Sense Key %lx/%02lx/%02lx",
2898 senseptr
[2] & SK_MASK
,
2904 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2905 "Sense status failed: %s (%ld)",
2906 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2909 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2910 "Sense data failed: %s (%ld)",
2911 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2914 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2915 "Sense block failed: %s (%ld)",
2916 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2922 /* /// "nBulkReset()" */
2923 LONG
nBulkReset(struct NepClassMS
*ncm
)
2927 static UBYTE cbiresetcmd12
[12] = { 0x1D, 0x04, 0xFF, 0xFF, 0xFF, 0xFF,
2928 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
2929 //struct UsbMSCBIStatusWrapper umscsw;
2930 //UBYTE sensedata[18];
2931 if(ncm
->ncm_DenyRequests
)
2933 return UHIOERR_TIMEOUT
;
2935 KPRINTF(1, ("Bulk Reset\n"));
2936 //psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Bulk Reset...");
2937 switch(ncm
->ncm_TPType
)
2940 if(!ncm
->ncm_BulkResetBorks
)
2942 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_CLASS
|URTF_INTERFACE
,
2943 UMSR_BULK_ONLY_RESET
, 0, (ULONG
) ncm
->ncm_UnitIfNum
);
2944 ioerr2
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
2945 if(ioerr2
== UHIOERR_TIMEOUT
)
2951 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2952 "BULK_ONLY_RESET failed: %s (%ld)",
2953 psdNumToStr(NTS_IOERR
, ioerr2
, "unknown"), ioerr2
);
2954 ncm
->ncm_BulkResetBorks
= TRUE
;
2956 if(ncm
->ncm_DenyRequests
)
2961 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
2962 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPInNum
|URTF_IN
);
2963 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
2966 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2967 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
2968 ncm
->ncm_EPInNum
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2970 if(ncm
->ncm_DenyRequests
)
2974 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
2975 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPOutNum
);
2976 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
2979 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2980 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
2981 ncm
->ncm_EPOutNum
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2983 return(ioerr2
? ioerr2
: ioerr
);
2987 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_CLASS
|URTF_INTERFACE
,
2988 UMSR_ADSC
, 0, (ULONG
) ncm
->ncm_UnitIfNum
);
2989 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, cbiresetcmd12
, 12);
2992 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2993 "CBI_RESET failed: %s (%ld)",
2994 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2996 if(ncm
->ncm_DenyRequests
)
3000 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
3001 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPInNum
|URTF_IN
);
3002 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
3005 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3006 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
3007 ncm
->ncm_EPInNum
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
3009 if(ncm
->ncm_DenyRequests
)
3013 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
3014 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPOutNum
);
3015 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
3018 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3019 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
3020 ncm
->ncm_EPOutNum
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
3022 //nCBIRequestSense(ncm, sensedata, 18);
3029 /* /// "nBulkClear()" */
3030 LONG
nBulkClear(struct NepClassMS
*ncm
)
3033 if(ncm
->ncm_DenyRequests
)
3035 return UHIOERR_TIMEOUT
;
3037 KPRINTF(1, ("Bulk Clear\n"));
3038 //psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Bulk Clear...");
3039 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
3040 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPInNum
|URTF_IN
);
3041 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
3042 if(ioerr
== UHIOERR_TIMEOUT
)
3048 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3049 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
3050 ncm
->ncm_EPInNum
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
3052 if(ncm
->ncm_DenyRequests
)
3056 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
3057 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPOutNum
);
3058 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
3061 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3062 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
3063 ncm
->ncm_EPOutNum
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
3069 /* /// "nScsiDirect()" */
3070 LONG
nScsiDirect(struct NepClassMS
*ncm
, struct SCSICmd
*scsicmd
)
3075 struct SCSICmd scsicmd10
;
3076 BOOL usecmd10
= FALSE
;
3078 UBYTE
*sensedata
= NULL
;
3081 ULONG pf
= ncm
->ncm_CDC
->cdc_PatchFlags
;
3083 scsicmd
->scsi_Actual
= 0;
3084 scsicmd
->scsi_CmdActual
= 0;
3085 scsicmd
->scsi_SenseActual
= 0;
3087 if(((pf
& PFF_MODE_XLATE
) && (scsicmd
->scsi_CmdLength
== 6)) ||
3088 (ncm
->ncm_CSType
== MS_FDDATAPI_SUBCLASS
) ||
3089 (ncm
->ncm_CSType
== MS_ATAPI_SUBCLASS
) ||
3090 (ncm
->ncm_CSType
== MS_UFI_SUBCLASS
))
3095 if(pf
& PFF_SIMPLE_SCSI
)
3097 if(scsicmd
->scsi_Flags
& SCSIF_AUTOSENSE
)
3099 if(scsicmd
->scsi_SenseLength
> 18)
3101 KPRINTF(10, ("Fixing Sense Length to 18!\n"));
3102 scsicmd
->scsi_SenseLength
= 18;
3105 switch(scsicmd
->scsi_Command
[0])
3107 case SCSI_TEST_UNIT_READY
:
3109 //case SCSI_LOG_SELECT:
3110 //case SCSI_LOG_SENSE:
3111 case SCSI_REQUEST_SENSE
:
3112 //case SCSI_MODE_SELECT_6:
3113 //case SCSI_MODE_SELECT_10:
3114 //case SCSI_MODE_SENSE_6:
3115 //case SCSI_MODE_SENSE_10:
3116 case SCSI_DA_READ_6
:
3117 case SCSI_DA_READ_10
:
3118 case SCSI_DA_READ_CAPACITY
:
3119 case SCSI_DA_SEEK_6
:
3120 case SCSI_DA_SEEK_10
:
3121 case SCSI_DA_WRITE_6
:
3122 case SCSI_DA_WRITE_10
:
3125 case SCSI_MODE_SENSE_6
:
3127 UWORD modepage
= scsicmd
->scsi_Command
[2] & 0x3f;
3128 UBYTE
*data
= (UBYTE
*) scsicmd
->scsi_Data
;
3129 if((modepage
== 0x3f) ||
3130 (modepage
== 0x03) ||
3131 (modepage
== 0x04) ||
3134 if(!(ncm
->ncm_BlockSize
&& ncm
->ncm_Geometry
.dg_TotalSectors
))
3138 if(ncm
->ncm_Geometry
.dg_TotalSectors
)
3140 nFakeGeometry(ncm
, &ncm
->ncm_Geometry
);
3141 ncm
->ncm_GeoChangeCount
= ncm
->ncm_ChangeCount
;
3143 memset(data
, 0, (size_t) scsicmd
->scsi_Length
);
3144 scsicmd
->scsi_Status
= SCSI_GOOD
;
3146 if(modepage
== 0x3f) // all available mode pages
3148 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Simple SCSI: Faking All Mode Pages 0x03-0x05");
3149 data
[0] = 3+2+22+2+22+2+30;
3151 scsicmd
->scsi_Actual
= 4;
3152 if(scsicmd
->scsi_Length
>= 4+2+22)
3154 data
[0] = 0x03; // mode page
3155 data
[1] = 22; // page length
3156 data
[10] = ncm
->ncm_Geometry
.dg_TrackSectors
>>8;
3157 data
[11] = ncm
->ncm_Geometry
.dg_TrackSectors
;
3158 data
[12] = ncm
->ncm_Geometry
.dg_SectorSize
>>8;
3159 data
[13] = ncm
->ncm_Geometry
.dg_SectorSize
;
3161 scsicmd
->scsi_Actual
+= 2+22;
3163 if(scsicmd
->scsi_Length
>= 4+2+22+2+22)
3165 data
[0] = 0x04; // mode page
3166 data
[1] = 22; // page length
3167 data
[2] = ncm
->ncm_Geometry
.dg_Cylinders
>>16;
3168 data
[3] = ncm
->ncm_Geometry
.dg_Cylinders
>>8;
3169 data
[4] = ncm
->ncm_Geometry
.dg_Cylinders
;
3170 data
[5] = ncm
->ncm_Geometry
.dg_Heads
;
3172 scsicmd
->scsi_Actual
+= 2+22;
3174 if(scsicmd
->scsi_Length
>= 4+2+22+2+22+2+30)
3176 data
[0] = 0x05; // mode page
3177 data
[1] = 30; // page length
3178 data
[4] = ncm
->ncm_Geometry
.dg_Heads
;
3179 data
[5] = ncm
->ncm_Geometry
.dg_TrackSectors
;
3180 data
[6] = ncm
->ncm_Geometry
.dg_SectorSize
>>8;
3181 data
[7] = ncm
->ncm_Geometry
.dg_SectorSize
;
3182 data
[8] = ncm
->ncm_Geometry
.dg_Cylinders
>>8;
3183 data
[9] = ncm
->ncm_Geometry
.dg_Cylinders
;
3185 scsicmd
->scsi_Actual
+= 2+30;
3189 else if((modepage
== 0x03) && (scsicmd
->scsi_Length
>= 6+22)) // Format Device mode page
3191 // fake geometry request
3192 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Simple SCSI: Faking Mode Page 0x03 (Format Device)");
3194 data
[0] = 5+22; // length
3196 data
[0] = 0x03; // mode page
3197 data
[1] = 22; // page length
3198 data
[10] = ncm
->ncm_Geometry
.dg_TrackSectors
>>8;
3199 data
[11] = ncm
->ncm_Geometry
.dg_TrackSectors
;
3200 data
[12] = ncm
->ncm_Geometry
.dg_SectorSize
>>8;
3201 data
[13] = ncm
->ncm_Geometry
.dg_SectorSize
;
3202 scsicmd
->scsi_Actual
= 6+22;
3205 else if((modepage
== 0x04) && (scsicmd
->scsi_Length
>= 6+22)) // Rigid Disk Geometry mode page
3207 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Simple SCSI: Faking Mode Page 0x04 (Rigid Disk Geometry)");
3208 data
[0] = 5+22; // length
3210 data
[0] = 0x04; // mode page
3211 data
[1] = 22; // page length
3212 data
[2] = ncm
->ncm_Geometry
.dg_Cylinders
>>16;
3213 data
[3] = ncm
->ncm_Geometry
.dg_Cylinders
>>8;
3214 data
[4] = ncm
->ncm_Geometry
.dg_Cylinders
;
3215 data
[5] = ncm
->ncm_Geometry
.dg_Heads
;
3216 scsicmd
->scsi_Actual
= 6+22;
3219 else if((modepage
== 0x05) && (scsicmd
->scsi_Length
>= 6+30)) // Flexible Disk mode page
3221 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Simple SCSI: Faking Mode Page 0x05 (Flexible Disk)");
3222 data
[0] = 5+30; // length
3224 data
[0] = 0x05; // mode page
3225 data
[1] = 30; // page length
3226 data
[4] = ncm
->ncm_Geometry
.dg_Heads
;
3227 data
[5] = ncm
->ncm_Geometry
.dg_TrackSectors
;
3228 data
[6] = ncm
->ncm_Geometry
.dg_SectorSize
>>8;
3229 data
[7] = ncm
->ncm_Geometry
.dg_SectorSize
;
3230 data
[8] = ncm
->ncm_Geometry
.dg_Cylinders
>>8;
3231 data
[9] = ncm
->ncm_Geometry
.dg_Cylinders
;
3232 scsicmd
->scsi_Actual
= 6+30;
3238 case 0x51: // drive ready
3239 case SCSI_CD_READ_TOC
:
3240 case SCSI_CD_PAUSE_RESUME
:
3241 case SCSI_CD_PLAY_AUDIO_10
:
3242 case SCSI_CD_PLAY_AUDIO_12
:
3243 case SCSI_CD_PLAY_AUDIO_MSF
:
3244 case SCSI_CD_PLAY_AUDIO_TRACK_INDEX
:
3245 case SCSI_CD_PLAY_TRACK_RELATIVE_10
:
3246 case SCSI_CD_PLAY_TRACK_RELATIVE_12
:
3248 case SCSI_CD_CLOSE_TRACK
:
3249 case SCSI_CD_GET_CONFIGURATION
:
3250 case SCSI_CD_GET_EVENT_STATUS_NOTIFICATION
:
3251 case SCSI_CD_GET_PERFORMANCE
:
3252 case SCSI_CD_LOAD_UNLOAD_MEDIUM
:
3253 case SCSI_DA_START_STOP_UNIT
:
3254 case SCSI_CD_MECHANISM_STATUS
:
3255 case SCSI_CD_PRE_FETCH
:
3256 case SCSI_CD_PREVENT_ALLOW_MEDIUM_REMOVAL
:
3257 case SCSI_CD_READ_HEADER
:
3258 case SCSI_CD_READ_SUB_CHANNEL
:
3259 if((scsicmd
->scsi_Command
[0] != SCSI_MODE_SENSE_6
) &&
3260 ((ncm
->ncm_DeviceType
== PDT_WORM
) || (ncm
->ncm_DeviceType
== PDT_CDROM
)))
3262 // allows these CD rom commands even with SimpleSCSI enabled.
3268 UBYTE cmdstrbuf
[16*3+2];
3270 GM_UNIQUENAME(nHexString
)(scsicmd
->scsi_Command
, (ULONG
) (scsicmd
->scsi_CmdLength
< 16 ? scsicmd
->scsi_CmdLength
: 16), cmdstrbuf
);
3271 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Simple SCSI: Filtering SCSI command %s", cmdstrbuf
);
3273 scsicmd
->scsi_Status
= SCSI_CHECK_CONDITION
;
3274 scsicmd
->scsi_SenseActual
= 0;
3275 if(scsicmd
->scsi_Flags
& SCSIF_AUTOSENSE
)
3277 if(scsicmd
->scsi_SenseLength
>= 18)
3279 memset(scsicmd
->scsi_SenseData
, 0x00, 18);
3280 scsicmd
->scsi_SenseData
[0] = 0x80|0x70;
3281 scsicmd
->scsi_SenseData
[2] = SK_ILLEGAL_REQUEST
;
3282 scsicmd
->scsi_SenseData
[12] = 0x20; // unsupported command
3283 scsicmd
->scsi_SenseActual
= 18;
3291 if((scsicmd
->scsi_Command
[0] == SCSI_TEST_UNIT_READY
) && scsicmd
->scsi_Length
)
3293 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Bogus TEST_UNIT_READY data length set to 0.");
3294 scsicmd
->scsi_Length
= 0;
3297 if(pf
& PFF_FAKE_INQUIRY
)
3299 if(scsicmd
->scsi_Command
[0] == SCSI_INQUIRY
)
3301 if(scsicmd
->scsi_Length
>= 36)
3303 UBYTE
*data
= (UBYTE
*) scsicmd
->scsi_Data
;
3306 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Faking Inquiry.");
3308 KPRINTF(10, ("Faking INQUIRY!\n"));
3309 psdGetAttrs(PGA_DEVICE
, ncm
->ncm_Device
,
3310 DA_ProductName
, &prodname
,
3311 DA_Manufacturer
, &vendname
,
3313 memset(data
, 0x00, (size_t) scsicmd
->scsi_Length
);
3314 data
[1] = 0x80; // removable media
3315 data
[2] = 0x02; // 0x03 would be ANSI X3.301:1997 (SPC).
3316 data
[3] = 0x02; // Response data format = 2
3317 data
[4] = 32; // additional length n-4
3318 CopyMem(vendname
, &data
[8], (ULONG
) ((strlen(vendname
) < 8) ? strlen(vendname
) : 8));
3319 CopyMem(prodname
, &data
[16], (ULONG
) ((strlen(prodname
) < 16) ? strlen(prodname
) : 16));
3320 scsicmd
->scsi_CmdActual
= scsicmd
->scsi_CmdLength
;
3321 scsicmd
->scsi_Status
= SCSI_GOOD
;
3322 scsicmd
->scsi_SenseActual
= 0;
3329 if(pf
& PFF_FIX_INQ36
)
3331 if((scsicmd
->scsi_Command
)[0] == SCSI_INQUIRY
)
3333 if(scsicmd
->scsi_Length
> 36)
3337 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing Inquiry.");
3340 KPRINTF(10, ("Fixing INQUIRY!\n"));
3341 scsicmd
->scsi_Length
= 36;
3343 else if(scsicmd
->scsi_Length
< 36)
3347 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3348 "Couldn't fix Inquiry < %ld.",
3349 scsicmd
->scsi_Length
);
3351 KPRINTF(10, ("Couldn't fix INQUIRY!\n"));
3358 scsicmd10
= *scsicmd
;
3359 scsicmd10
.scsi_Command
= cmd12
;
3360 scsicmd10
.scsi_CmdLength
= 10;
3361 memset(cmd12
, 0x00, 12);
3362 switch(scsicmd
->scsi_Command
[0])
3364 case SCSI_DA_READ_6
:
3365 case SCSI_DA_WRITE_6
:
3366 case SCSI_DA_SEEK_6
:
3367 cmd12
[0] = scsicmd
->scsi_Command
[0] | 0x20;
3368 cmd12
[1] = scsicmd
->scsi_Command
[1] & 0xe0;
3369 cmd12
[3] = scsicmd
->scsi_Command
[1] & 0x1f;
3370 cmd12
[4] = scsicmd
->scsi_Command
[2];
3371 cmd12
[5] = scsicmd
->scsi_Command
[3];
3372 cmd12
[8] = scsicmd
->scsi_Command
[4];
3373 cmd12
[9] = scsicmd
->scsi_Command
[5];
3377 case SCSI_MODE_SELECT_6
:
3378 cmd12
[0] = SCSI_MODE_SELECT_10
;
3379 cmd12
[1] = scsicmd
->scsi_Command
[1];
3380 //cmd12[2] = scsicmd->scsi_Command[2]; // reserved
3381 //cmd12[3] = scsicmd->scsi_Command[3]; // reserved
3382 cmd12
[7] = (scsicmd
->scsi_Command
[4]+4)>>8;
3383 cmd12
[8] = scsicmd
->scsi_Command
[4]+4;
3384 cmd12
[9] = scsicmd
->scsi_Command
[5];
3386 sensedata
= psdAllocVec(scsicmd
->scsi_Length
+4);
3387 if(sensedata
&& (scsicmd
->scsi_Length
>= 4))
3389 buf
= (UBYTE
*) scsicmd
->scsi_Data
;
3390 sensedata
[1] = *buf
++;
3391 sensedata
[2] = *buf
++;
3392 sensedata
[3] = *buf
++;
3393 sensedata
[7] = *buf
++;
3395 scsicmd10
.scsi_Length
= scsicmd
->scsi_Length
+4;
3396 scsicmd10
.scsi_Data
= (UWORD
*) sensedata
;
3398 CopyMem(buf
, &sensedata
[8], scsicmd
->scsi_Length
-4);
3403 case SCSI_MODE_SENSE_6
:
3404 cmd12
[0] = SCSI_MODE_SENSE_10
;
3405 cmd12
[1] = scsicmd
->scsi_Command
[1] & 0xf7;
3406 cmd12
[2] = scsicmd
->scsi_Command
[2];
3407 cmd12
[3] = scsicmd
->scsi_Command
[3];
3408 // Workaround: Some devices are seriously broken and do not interpret
3409 // the upper byte of the allocation length field.
3410 // Hence they return 3 bytes instead of 259 bytes. For this special case,
3411 // we will simply truncate the size by four, to get back to a 255 byte
3413 if((scsicmd
->scsi_Command
[4] > 251) && (scsicmd
->scsi_Length
== scsicmd
->scsi_Command
[4]))
3415 scsicmd
->scsi_Command
[4] -= 4;
3416 scsicmd
->scsi_Length
-= 4;
3418 cmd12
[7] = (scsicmd
->scsi_Command
[4]+4)>>8;
3419 cmd12
[8] = scsicmd
->scsi_Command
[4]+4;
3420 cmd12
[9] = scsicmd
->scsi_Command
[5];
3421 sensedata
= psdAllocVec(scsicmd
->scsi_Length
+4);
3424 scsicmd10
.scsi_Length
= scsicmd
->scsi_Length
+4;
3425 scsicmd10
.scsi_Data
= (UWORD
*) sensedata
;
3432 if((ncm
->ncm_CSType
== MS_ATAPI_SUBCLASS
) ||
3433 (ncm
->ncm_CSType
== MS_FDDATAPI_SUBCLASS
) ||
3434 (ncm
->ncm_CSType
== MS_UFI_SUBCLASS
))
3438 scsicmd10
= *scsicmd
;
3439 scsicmd10
.scsi_Command
= cmd12
;
3440 memset(cmd12
, 0x00, 12);
3441 CopyMem(scsicmd
->scsi_Command
, cmd12
, (ULONG
) scsicmd
->scsi_CmdLength
);
3444 scsicmd10
.scsi_CmdLength
= 12;
3445 if(ncm
->ncm_CSType
== MS_UFI_SUBCLASS
)
3449 case SCSI_REQUEST_SENSE
:
3450 cmd12
[4] = 18; /* restrict UFI response to 18 bytes */
3451 scsicmd10
.scsi_Flags
&= ~SCSIF_AUTOSENSE
;
3455 KPRINTF(10, ("Disabling autosense for UFI!\n"));
3456 cmd12
[4] = 36; /* restrict UFI response to 36 bytes */
3457 scsicmd10
.scsi_Flags
&= ~SCSIF_AUTOSENSE
;
3460 case SCSI_MODE_SELECT_10
:
3473 UBYTE cmd1strbuf
[16*3+2];
3474 UBYTE cmd2strbuf
[16*3+2];
3476 GM_UNIQUENAME(nHexString
)(scsicmd
->scsi_Command
, (ULONG
) (scsicmd
->scsi_CmdLength
< 16 ? scsicmd
->scsi_CmdLength
: 16), cmd1strbuf
);
3477 GM_UNIQUENAME(nHexString
)(scsicmd10
.scsi_Command
, (ULONG
) (scsicmd10
.scsi_CmdLength
< 16 ? scsicmd10
.scsi_CmdLength
: 16), cmd2strbuf
);
3478 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3479 "Mode XLATE for %s -> %s", cmd1strbuf
, cmd2strbuf
);
3480 if(scsicmd
->scsi_Length
&& (scsicmd10
.scsi_Command
[0] == SCSI_MODE_SELECT_10
))
3482 GM_UNIQUENAME(nHexString
)((UBYTE
*) scsicmd
->scsi_Data
, (ULONG
) (scsicmd
->scsi_Length
< 16 ? scsicmd
->scsi_Length
: 16), cmd1strbuf
);
3483 GM_UNIQUENAME(nHexString
)((UBYTE
*) scsicmd10
.scsi_Data
, (ULONG
) (scsicmd10
.scsi_Length
< 16 ? scsicmd10
.scsi_Length
: 16), cmd2strbuf
);
3484 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3485 "Request: %s (%ld) -> %s (%ld)",
3486 cmd1strbuf
, scsicmd
->scsi_Length
,
3487 cmd2strbuf
, scsicmd10
.scsi_Length
);
3490 KPRINTF(20, ("Mode XLATE for cmd %lx\n", scsicmd
->scsi_Command
[0]));
3493 switch(ncm
->ncm_TPType
)
3496 res
= nScsiDirectBulk(ncm
, usecmd10
? &scsicmd10
: scsicmd
);
3501 res
= nScsiDirectCBI(ncm
, usecmd10
? &scsicmd10
: scsicmd
);
3507 KPRINTF(20, ("Cmd done %ld\n", res
));
3512 scsicmd
->scsi_Actual
= 0;
3513 if(scsicmd10
.scsi_Command
[0] == SCSI_MODE_SENSE_10
)
3515 UBYTE cmd1strbuf
[16*3+2];
3516 UBYTE cmd2strbuf
[16*3+2];
3518 if(scsicmd10
.scsi_Actual
>= 8)
3520 scsicmd
->scsi_Actual
= scsicmd10
.scsi_Actual
- 4;
3521 buf
= (UBYTE
*) scsicmd
->scsi_Data
;
3522 *buf
++ = sensedata
[1];
3523 *buf
++ = sensedata
[2];
3524 *buf
++ = sensedata
[3];
3525 *buf
++ = sensedata
[7];
3526 CopyMem(&sensedata
[8], buf
, (ULONG
) scsicmd10
.scsi_Actual
- 8);
3529 GM_UNIQUENAME(nHexString
)((UBYTE
*) scsicmd10
.scsi_Data
, scsicmd10
.scsi_Actual
< 16 ? scsicmd10
.scsi_Actual
: 16, cmd1strbuf
);
3530 GM_UNIQUENAME(nHexString
)((UBYTE
*) scsicmd
->scsi_Data
, scsicmd
->scsi_Actual
< 16 ? scsicmd
->scsi_Actual
: 16, cmd2strbuf
);
3531 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3532 "Response: %s (%ld) -> %s (%ld)",
3533 cmd1strbuf
, scsicmd10
.scsi_Actual
,
3534 cmd2strbuf
, scsicmd
->scsi_Actual
);
3538 psdFreeVec(sensedata
);
3540 scsicmd
->scsi_Actual
= scsicmd10
.scsi_Actual
;
3542 scsicmd
->scsi_CmdActual
= scsicmd10
.scsi_CmdActual
;
3543 scsicmd
->scsi_Status
= scsicmd10
.scsi_Status
;
3544 scsicmd
->scsi_SenseActual
= scsicmd10
.scsi_SenseActual
;
3547 pf
= ncm
->ncm_CDC
->cdc_PatchFlags
;
3548 if((res
== HFERR_Phase
) && (!(pf
& PFF_NO_FALLBACK
)) && (!(pf
& PFF_SIMPLE_SCSI
)))
3550 switch(scsicmd
->scsi_Command
[0])
3552 case SCSI_TEST_UNIT_READY
:
3554 //case SCSI_LOG_SELECT:
3555 //case SCSI_LOG_SENSE:
3556 case SCSI_REQUEST_SENSE
:
3557 //case SCSI_MODE_SELECT_6:
3558 //case SCSI_MODE_SELECT_10:
3559 //case SCSI_MODE_SENSE_6:
3560 //case SCSI_MODE_SENSE_10:
3561 case SCSI_DA_READ_6
:
3562 case SCSI_DA_READ_10
:
3563 case SCSI_DA_READ_CAPACITY
:
3564 case SCSI_DA_SEEK_6
:
3565 case SCSI_DA_SEEK_10
:
3566 case SCSI_DA_WRITE_6
:
3567 case SCSI_DA_WRITE_10
:
3571 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_SIMPLE_SCSI
;
3572 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3573 "Fallback: Enabling Simple SCSI.");
3574 GM_UNIQUENAME(nStoreConfig
)(ncm
);
3579 if((!res
) && ((scsicmd
->scsi_Command
)[0] == SCSI_DA_READ_CAPACITY
) && (pf
& PFF_FIX_CAPACITY
) && (scsicmd
->scsi_Length
>= 8))
3581 ULONG
*capacity
= ((ULONG
*) scsicmd
->scsi_Data
);
3582 *capacity
= AROS_LONG2BE(AROS_BE2LONG(*capacity
)-1);
3583 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3584 "Fix Capacity: Correcting number of blocks.");
3587 if(res
&& (scsicmd
->scsi_Command
[0] == SCSI_INQUIRY
))
3589 if((!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
)) && (!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_FIX_INQ36
)))
3591 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_FIX_INQ36
;
3592 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3593 "Fallback: Enabling Trim Inquiry.");
3594 GM_UNIQUENAME(nStoreConfig
)(ncm
);
3596 else if((!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
)) && (!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_FAKE_INQUIRY
)))
3598 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_FAKE_INQUIRY
;
3599 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3600 "Fallback: Enabling Fake Inquiry.");
3601 GM_UNIQUENAME(nStoreConfig
)(ncm
);
3605 if((ncm
->ncm_DeviceType
== PDT_WORM
) ||
3606 (ncm
->ncm_DeviceType
== PDT_CDROM
))
3608 // cd roms are always write protected
3609 ncm
->ncm_WriteProtect
= TRUE
;
3612 // don't try to obtain write protection, when there's no media inserted.
3613 if(!ncm
->ncm_UnitReady
)
3617 if((!res
) && (scsicmd
->scsi_Command
[0] == SCSI_MODE_SENSE_6
))
3619 if(((UBYTE
*) scsicmd
->scsi_Data
)[2] & 0x80)
3621 if(!ncm
->ncm_WriteProtect
)
3623 if(pf
& PFF_REM_SUPPORT
)
3625 ncm
->ncm_ChangeCount
++;
3626 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
3628 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3629 "Diskchange: Sense6WriteProtect On (count = %ld)",
3630 ncm
->ncm_ChangeCount
);
3633 ncm
->ncm_WriteProtect
= TRUE
;
3636 if(ncm
->ncm_WriteProtect
)
3638 if(pf
& PFF_REM_SUPPORT
)
3640 ncm
->ncm_ChangeCount
++;
3641 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
3643 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3644 "Diskchange: Sense6WriteProtect Off (count = %ld)",
3645 ncm
->ncm_ChangeCount
);
3648 ncm
->ncm_WriteProtect
= FALSE
;
3652 if((!res
) && (scsicmd
->scsi_Command
[0] == SCSI_MODE_SENSE_10
))
3654 if(((UBYTE
*) scsicmd
->scsi_Data
)[3] & 0x80)
3656 if(!ncm
->ncm_WriteProtect
)
3658 if(pf
& PFF_REM_SUPPORT
)
3660 ncm
->ncm_ChangeCount
++;
3661 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
3663 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3664 "Diskchange: Sense10WriteProtect On (count = %ld)",
3665 ncm
->ncm_ChangeCount
);
3668 ncm
->ncm_WriteProtect
= TRUE
;
3671 if(ncm
->ncm_WriteProtect
)
3673 if(pf
& PFF_REM_SUPPORT
)
3675 ncm
->ncm_ChangeCount
++;
3676 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
3678 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3679 "Diskchange: Sense10WriteProtect Off (count = %ld)",
3680 ncm
->ncm_ChangeCount
);
3683 ncm
->ncm_WriteProtect
= FALSE
;
3691 /* /// "nScsiDirectBulk()" */
3692 LONG
nScsiDirectBulk(struct NepClassMS
*ncm
, struct SCSICmd
*scsicmd
)
3696 struct UsbMSCmdBlkWrapper umscbw
;
3697 struct UsbMSCmdStatusWrapper umscsw
;
3701 UBYTE cmdstrbuf
[16*3+2];
3703 KPRINTF(10, ("\n"));
3705 GM_UNIQUENAME(nHexString
)(scsicmd
->scsi_Command
, (ULONG
) (scsicmd
->scsi_CmdLength
< 16 ? scsicmd
->scsi_CmdLength
: 16), cmdstrbuf
);
3707 if(scsicmd
->scsi_Flags
& 0x80) /* Autoretry */
3711 umscbw
.dCBWSignature
= AROS_LONG2LE(0x43425355);
3712 scsicmd
->scsi_Status
= SCSI_GOOD
;
3716 KPRINTF(10, ("retrycnt %ld\n",retrycnt
));
3717 if(ncm
->ncm_DenyRequests
)
3719 rioerr
= HFERR_Phase
;
3722 /*nBulkReset(ncm);*/
3726 /*psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3727 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
3728 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);*/
3730 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DELAY_DATA
)
3735 datalen
= scsicmd
->scsi_Length
;
3736 umscbw
.dCBWTag
= (IPTR
) scsicmd
+ ++ncm
->ncm_TagCount
;
3737 umscbw
.dCBWDataTransferLength
= AROS_LONG2LE(datalen
);
3738 umscbw
.bmCBWFlags
= scsicmd
->scsi_Flags
& SCSIF_READ
? 0x80 : 0x00;
3739 umscbw
.bCBWLUN
= ncm
->ncm_UnitLUN
;
3740 if((scsicmd
->scsi_CmdLength
) >= 16)
3742 CopyMemQuick(scsicmd
->scsi_Command
, umscbw
.CBWCB
, 16);
3743 umscbw
.bCBWCBLength
= scsicmd
->scsi_CmdActual
= 16;
3745 memset(umscbw
.CBWCB
, 0, 16);
3746 CopyMem(scsicmd
->scsi_Command
, umscbw
.CBWCB
, (ULONG
) scsicmd
->scsi_CmdLength
);
3747 umscbw
.bCBWCBLength
= scsicmd
->scsi_CmdActual
= scsicmd
->scsi_CmdLength
;
3749 //psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Issueing command %s Dlen=%ld", cmdstrbuf, datalen);
3751 KPRINTF(2, ("command block phase, tag %08lx, len %ld, flags %02lx...\n",
3752 umscbw
.dCBWTag
, scsicmd
->scsi_CmdLength
, scsicmd
->scsi_Flags
));
3753 KPRINTF(2, ("command: %s\n", cmdstrbuf
));
3754 ioerr
= psdDoPipe(ncm
->ncm_EPOutPipe
, &umscbw
, UMSCBW_SIZEOF
);
3755 if(ioerr
== UHIOERR_STALL
) /* Retry on stall */
3757 KPRINTF(2, ("stall...\n"));
3759 ioerr
= psdDoPipe(ncm
->ncm_EPOutPipe
, &umscbw
, UMSCBW_SIZEOF
);
3761 if(ncm
->ncm_DenyRequests
)
3763 rioerr
= HFERR_Phase
;
3770 KPRINTF(2, ("data phase %ld bytes...\n", datalen
));
3771 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DELAY_DATA
)
3775 pp
= (scsicmd
->scsi_Flags
& SCSIF_READ
) ? ncm
->ncm_EPInPipe
: ncm
->ncm_EPOutPipe
;
3776 ioerr
= psdDoPipe(pp
, scsicmd
->scsi_Data
, datalen
);
3777 scsicmd
->scsi_Actual
= psdGetPipeActual(pp
);
3778 if(ioerr
== UHIOERR_OVERFLOW
)
3780 KPRINTF(10, ("Extra Data received, but ignored!\n"));
3783 else if(ioerr
== UHIOERR_STALL
) /* Accept on stall */
3785 KPRINTF(2, ("stall...\n"));
3786 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
3787 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
,
3788 (ULONG
) ((scsicmd
->scsi_Flags
& SCSIF_READ
) ? ncm
->ncm_EPInNum
|URTF_IN
: ncm
->ncm_EPOutNum
));
3789 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
3791 else if(ioerr
== UHIOERR_RUNTPACKET
)
3793 KPRINTF(10, ("Runt packet ignored...\n"));
3795 /*psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3796 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT,
3797 (ULONG) ncm->ncm_EPInNum|URTF_IN);
3798 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);*/
3802 scsicmd
->scsi_Actual
= 0;
3806 KPRINTF(2, ("command status phase...\n"));
3807 ioerr
= psdDoPipe(ncm
->ncm_EPInPipe
, &umscsw
, UMSCSW_SIZEOF
);
3808 if(ioerr
== UHIOERR_STALL
) /* Retry on stall */
3810 KPRINTF(2, ("stall...\n"));
3811 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
3812 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPInNum
|URTF_IN
);
3813 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
3814 /*nBulkClear(ncm);*/
3815 ioerr
= psdDoPipe(ncm
->ncm_EPInPipe
, &umscsw
, UMSCSW_SIZEOF
);
3817 if(ioerr
== UHIOERR_RUNTPACKET
)
3820 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3821 "Command status block truncated (%ld bytes), retrying...",
3822 psdGetPipeActual(ncm
->ncm_EPInPipe
));
3823 ioerr
= psdDoPipe(ncm
->ncm_EPInPipe
, &umscsw
, UMSCSW_SIZEOF
);
3825 if(ioerr
== UHIOERR_OVERFLOW
)
3827 KPRINTF(10, ("Extra Status received, but ignored!\n"));
3830 if(ncm
->ncm_DenyRequests
)
3832 rioerr
= HFERR_Phase
;
3837 KPRINTF(2, ("Status:\n"
3838 " Signature: %08lx\n"
3840 " Residue : %08lx\n"
3841 " Status : %02lx\n",
3842 umscsw
.dCSWSignature
,
3844 umscsw
.dCSWDataResidue
,
3845 umscsw
.bCSWStatus
));
3846 if(((umscsw
.dCSWSignature
!= AROS_LONG2LE(0x53425355)) && (!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_CSS_BROKEN
))) || (umscsw
.dCSWTag
!= umscbw
.dCBWTag
))
3848 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Command (%s) failed:", cmdstrbuf
);
3849 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3850 "Illegal command status block (Sig:%08lx, Tag=%08lx/%08lx (TX/RX), Len=%ld)",
3851 umscsw
.dCSWSignature
,
3854 psdGetPipeActual(ncm
->ncm_EPInPipe
));
3855 scsicmd
->scsi_Status
= SCSI_CHECK_CONDITION
;
3856 rioerr
= HFERR_Phase
;
3860 /* ignore this: too many firmwares report shit */
3861 //scsicmd->scsi_Actual = datalen - AROS_LONG2LE(umscsw.dCSWDataResidue);
3862 if((scsicmd
->scsi_Actual
> 7) && ((AROS_LONG2BE(*((ULONG
*) scsicmd
->scsi_Data
))>>8) == 0x555342) && (((ULONG
*) scsicmd
->scsi_Data
)[1] == umscbw
.dCBWTag
))
3864 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3865 "Your MSD has a very bad firmware! Havoc!");
3866 scsicmd
->scsi_Actual
= 0;
3867 umscsw
.bCSWStatus
= USMF_CSW_FAIL
;
3869 scsicmd
->scsi_Status
= umscsw
.bCSWStatus
;
3870 if(umscsw
.bCSWStatus
)
3872 if(umscsw
.bCSWStatus
== USMF_CSW_PHASEERR
)
3874 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Command (%s) failed: %ld", cmdstrbuf
, umscsw
.bCSWStatus
);
3877 /* Autosensing required? */
3878 if(scsicmd
->scsi_Flags
& SCSIF_AUTOSENSE
)
3880 /*nBulkClear(ncm);*/
3882 datalen
= scsicmd
->scsi_SenseLength
;
3883 umscbw
.dCBWTag
= (IPTR
) scsicmd
+ ++ncm
->ncm_TagCount
;
3884 umscbw
.dCBWDataTransferLength
= AROS_LONG2LE(datalen
);
3885 umscbw
.bmCBWFlags
= 0x80;
3886 /*umscbw.bCBWLUN = ncm->ncm_UnitLun;*/
3887 umscbw
.bCBWCBLength
= 6;
3888 umscbw
.CBWCB
[0] = SCSI_REQUEST_SENSE
;
3889 umscbw
.CBWCB
[1] = 0x00;
3890 umscbw
.CBWCB
[2] = 0x00;
3891 umscbw
.CBWCB
[3] = 0x00;
3892 umscbw
.CBWCB
[4] = datalen
;
3893 umscbw
.CBWCB
[5] = 0;
3894 KPRINTF(2, ("sense command block phase...\n"));
3895 ioerr
= psdDoPipe(ncm
->ncm_EPOutPipe
, &umscbw
, UMSCBW_SIZEOF
);
3896 if(ioerr
== UHIOERR_STALL
) /* Retry on stall */
3898 KPRINTF(2, ("stall...\n"));
3900 ioerr
= psdDoPipe(ncm
->ncm_EPOutPipe
, &umscbw
, UMSCBW_SIZEOF
);
3904 KPRINTF(2, ("sense data phase %ld bytes...\n", datalen
));
3905 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DELAY_DATA
)
3909 ioerr
= psdDoPipe(ncm
->ncm_EPInPipe
, scsicmd
->scsi_SenseData
, datalen
);
3910 scsicmd
->scsi_SenseActual
= psdGetPipeActual(ncm
->ncm_EPInPipe
);
3911 if(ioerr
== UHIOERR_STALL
) /* Accept on stall */
3913 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
3914 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPInNum
|URTF_IN
);
3915 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
3917 if((ioerr
== UHIOERR_RUNTPACKET
) || (ioerr
== UHIOERR_OVERFLOW
))
3919 KPRINTF(10, ("Extra or less data received, but ignored!\n"));
3925 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DELAY_DATA
)
3929 KPRINTF(2, ("sense command status phase...\n"));
3930 ioerr
= psdDoPipe(ncm
->ncm_EPInPipe
, &umscsw
, UMSCSW_SIZEOF
);
3931 if(ioerr
== UHIOERR_STALL
) /* Retry on stall */
3933 KPRINTF(2, ("stall...\n"));
3934 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
3935 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
, (ULONG
) ncm
->ncm_EPInNum
|URTF_IN
);
3936 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
3937 ioerr
|= psdDoPipe(ncm
->ncm_EPInPipe
, &umscsw
, UMSCSW_SIZEOF
);
3939 if(ioerr
== UHIOERR_RUNTPACKET
)
3942 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3943 "Command (sense) status block truncated (%ld bytes), retrying...",
3944 psdGetPipeActual(ncm
->ncm_EPInPipe
));
3945 ioerr
= psdDoPipe(ncm
->ncm_EPInPipe
, &umscsw
, UMSCSW_SIZEOF
);
3948 if(ioerr
== UHIOERR_OVERFLOW
)
3950 KPRINTF(10, ("Extra Status received, but ignored!\n"));
3955 KPRINTF(2, ("sense Status:\n"
3956 " Signature: %08lx\n"
3958 " Residue : %08lx\n"
3959 " Status : %02lx\n",
3960 umscsw
.dCSWSignature
,
3962 umscsw
.dCSWDataResidue
,
3963 umscsw
.bCSWStatus
));
3964 if(((umscsw
.dCSWSignature
!= AROS_LONG2LE(0x53425355)) && (!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_CSS_BROKEN
))) || (umscsw
.dCSWTag
!= umscbw
.dCBWTag
))
3966 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3967 "Illegal command (sense) status block (Sig:%08lx, Tag=%08lx/%08lx (TX/RX), Len=%ld)",
3968 umscsw
.dCSWSignature
,
3971 psdGetPipeActual(ncm
->ncm_EPInPipe
));
3972 scsicmd
->scsi_Status
= SCSI_CHECK_CONDITION
;
3973 rioerr
= HFERR_Phase
;
3977 /* ignore this: too many firmwares report shit */
3978 //scsicmd->scsi_SenseActual = datalen - AROS_LONG2LE(umscsw.dCSWDataResidue);
3979 if((scsicmd
->scsi_SenseActual
> 7) && ((AROS_LONG2BE(*((ULONG
*) scsicmd
->scsi_SenseData
))>>8) == 0x555342) && (((ULONG
*) scsicmd
->scsi_SenseData
)[1] == umscbw
.dCBWTag
))
3981 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3982 "Your MSD has a very bad firmware! Havoc!");
3983 scsicmd
->scsi_Actual
= 0;
3984 umscsw
.bCSWStatus
= USMF_CSW_FAIL
;
3987 if(umscsw
.bCSWStatus
)
3989 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3990 "Sense failed: %ld",
3991 umscsw.bCSWStatus);*/
3992 if(umscsw
.bCSWStatus
== USMF_CSW_PHASEERR
)
3997 switch(scsicmd
->scsi_SenseData
[2] & SK_MASK
)
3999 case SK_ILLEGAL_REQUEST
:
4003 case SK_DATA_PROTECT
:
4004 if(!ncm
->ncm_WriteProtect
)
4006 ncm
->ncm_WriteProtect
= TRUE
;
4007 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
4009 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
4010 "WriteProtect On: Sense Data Protect");
4015 case SK_UNIT_ATTENTION
:
4016 if((ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_REM_SUPPORT
) &&
4017 ((scsicmd
->scsi_SenseData
[12] == 0x28) ||
4018 (scsicmd
->scsi_SenseData
[12] == 0x3A)))
4020 ncm
->ncm_ChangeCount
++;
4021 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
4023 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
4024 "Diskchange: Unit Attention (count = %ld)",
4025 ncm
->ncm_ChangeCount
);
4030 KPRINTF(10, ("Sense Key: %lx/%02lx/%02lx\n",
4031 scsicmd
->scsi_SenseData
[2] & SK_MASK
,
4032 scsicmd
->scsi_SenseData
[12],
4033 scsicmd
->scsi_SenseData
[13]));
4034 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
4036 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
4037 "Cmd %s: Sense Key %lx/%02lx/%02lx",
4039 scsicmd
->scsi_SenseData
[2] & SK_MASK
,
4040 scsicmd
->scsi_SenseData
[12],
4041 scsicmd
->scsi_SenseData
[13]);
4045 KPRINTF(10, ("Sense status failed: %s (%ld)\n", psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
));
4046 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Command (%s) okay, but:", cmdstrbuf
);
4047 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4048 "Sense status failed: %s (%ld)",
4049 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4053 KPRINTF(10, ("Sense data failed: %s (%ld)\n", psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
));
4054 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Command (%s) okay, but:", cmdstrbuf
);
4055 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4056 "Sense data failed: %s (%ld)",
4057 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4061 KPRINTF(10, ("Sense block failed: %s (%ld)\n", psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
));
4062 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Command (%s) okay, but:", cmdstrbuf
);
4063 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4064 "Sense block failed: %s (%ld)",
4065 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4066 /*nBulkReset(ncm);*/
4069 rioerr
= HFERR_BadStatus
;
4072 KPRINTF(10, ("Command status failed: %s (%ld)\n", psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
));
4073 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Command (%s) failed:", cmdstrbuf
);
4074 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4075 "Command status failed: %s (%ld)",
4076 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4077 scsicmd
->scsi_Status
= SCSI_CHECK_CONDITION
;
4078 rioerr
= HFERR_Phase
;
4082 KPRINTF(10, ("Data phase failed: %s (%ld)\n", psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
));
4083 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Command (%s) failed:", cmdstrbuf
);
4084 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4085 "Data phase failed: %s (%ld)",
4086 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4087 scsicmd
->scsi_Status
= SCSI_CHECK_CONDITION
;
4088 rioerr
= HFERR_Phase
;
4092 KPRINTF(10, ("Command block failed: %s (%ld)\n", psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
));
4093 scsicmd
->scsi_Status
= SCSI_CHECK_CONDITION
;
4094 rioerr
= HFERR_Phase
;
4095 if(ioerr
== UHIOERR_TIMEOUT
)
4099 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Command (%s) failed:", cmdstrbuf
);
4100 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4101 "Command block failed: %s (%ld)",
4102 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4109 KPRINTF(1, ("Retrying...\n"));
4110 } while(retrycnt
--);
4116 /* /// "nScsiDirectCBI()" */
4117 LONG
nScsiDirectCBI(struct NepClassMS
*ncm
, struct SCSICmd
*scsicmd
)
4121 struct PsdPipe
*backpp
;
4122 struct UsbMSCBIStatusWrapper umscsw
;
4126 UBYTE sensedata
[18];
4131 UBYTE cmdstrbuf
[16*3+2];
4133 GM_UNIQUENAME(nHexString
)(scsicmd
->scsi_Command
, (ULONG
) (scsicmd
->scsi_CmdLength
< 16 ? scsicmd
->scsi_CmdLength
: 16), cmdstrbuf
);
4135 if(scsicmd
->scsi_Flags
& 0x80) /* Autoretry */
4139 scsicmd
->scsi_Status
= SCSI_GOOD
;
4143 if(ncm
->ncm_DenyRequests
)
4145 rioerr
= HFERR_Phase
;
4149 datalen
= scsicmd
->scsi_Length
;
4151 KPRINTF(2, ("command block phase, tag %08lx, len %ld, flags %02lx...\n",
4152 scsicmd
, scsicmd
->scsi_CmdLength
, scsicmd
->scsi_Flags
));
4154 KPRINTF(2, ("command: %s\n", cmdstrbuf
));
4157 scsicmd
->scsi_CmdActual
= scsicmd
->scsi_CmdLength
;
4160 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
4161 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT,
4162 (ULONG) ((scsicmd->scsi_Flags & SCSIF_READ) ? ncm->ncm_EPInNum|URTF_IN : ncm->ncm_EPOutNum));
4163 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
4165 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_CLASS
|URTF_INTERFACE
,
4166 UMSR_ADSC
, 0, (ULONG
) ncm
->ncm_UnitIfNum
);
4167 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, scsicmd
->scsi_Command
, (ULONG
) scsicmd
->scsi_CmdLength
);
4169 if(ncm
->ncm_DenyRequests
)
4171 rioerr
= HFERR_Phase
;
4176 datadone
= statusdone
= FALSE
;
4179 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_CLEAR_EP
)
4181 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
4182 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
,
4183 (ULONG
) ((scsicmd
->scsi_Flags
& SCSIF_READ
) ? ncm
->ncm_EPInNum
|URTF_IN
: ncm
->ncm_EPOutNum
));
4184 ioerr
= psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
4187 KPRINTF(2, ("data phase %ld bytes...\n", datalen
));
4188 pp
= (scsicmd
->scsi_Flags
& SCSIF_READ
) ? ncm
->ncm_EPInPipe
: ncm
->ncm_EPOutPipe
;
4190 if(ncm
->ncm_TPType
== MS_PROTO_CBI
)
4192 /* okay, this is a major pain in the arse.
4193 we have to do this asynchroneously */
4195 umscsw
.bValue
= USMF_CSW_PHASEERR
;
4196 psdSendPipe(ncm
->ncm_EPIntPipe
, &umscsw
, sizeof(struct UsbMSCBIStatusWrapper
));
4197 psdSendPipe(pp
, scsicmd
->scsi_Data
, datalen
);
4200 WaitPort(ncm
->ncm_TaskMsgPort
);
4201 while((backpp
= (struct PsdPipe
*) GetMsg(ncm
->ncm_TaskMsgPort
)))
4205 /* data transfer finished */
4208 else if(backpp
== ncm
->ncm_EPIntPipe
)
4210 /* status returned */
4214 } while(!statusdone
);
4221 ioerr
= psdGetPipeError(pp
);
4225 ioerr
= psdDoPipe(pp
, scsicmd
->scsi_Data
, datalen
);
4228 scsicmd
->scsi_Actual
= psdGetPipeActual(pp
);
4229 if(ioerr
== UHIOERR_OVERFLOW
)
4231 KPRINTF(10, ("Extra Data received, but ignored!\n"));
4234 if(ioerr
== UHIOERR_STALL
) /* Accept on stall */
4236 KPRINTF(2, ("stall...\n"));
4238 psdPipeSetup(ncm
->ncm_EP0Pipe
, URTF_STANDARD
|URTF_ENDPOINT
,
4239 USR_CLEAR_FEATURE
, UFS_ENDPOINT_HALT
,
4240 (ULONG
) ((scsicmd
->scsi_Flags
& SCSIF_READ
) ? ncm
->ncm_EPInNum
|URTF_IN
: ncm
->ncm_EPOutNum
));
4241 psdDoPipe(ncm
->ncm_EP0Pipe
, NULL
, 0);
4246 scsicmd
->scsi_Actual
= 0;
4248 if((!ioerr
) || (ioerr
== UHIOERR_RUNTPACKET
))
4250 KPRINTF(2, ("command status phase...\n"));
4251 if(ncm
->ncm_TPType
== MS_PROTO_CBI
)
4255 if(ncm
->ncm_CSType
== MS_UFI_SUBCLASS
)
4257 umscsw
.bType
= 0x04;
4261 umscsw
.bValue
= USMF_CSW_PHASEERR
;
4263 ioerr
= psdDoPipe(ncm
->ncm_EPIntPipe
, &umscsw
, sizeof(struct UsbMSCBIStatusWrapper
));
4265 ioerr
= psdGetPipeError(ncm
->ncm_EPIntPipe
);
4267 umscsw
.bValue
&= 0x0f; /* mask out upper nibble */
4270 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4271 "Status interrupt failed: %s (%ld)",
4272 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4275 if(ncm
->ncm_CSType
== MS_UFI_SUBCLASS
)
4278 if((scsicmd
->scsi_Command
[0] == SCSI_REQUEST_SENSE
) ||
4279 (scsicmd
->scsi_Command
[0] == SCSI_INQUIRY
))
4282 umscsw
.bValue
= USMF_CSW_PASS
;
4285 umscsw
.bValue
= asc
? USMF_CSW_FAIL
: USMF_CSW_PASS
;
4288 rioerr
= HFERR_BadStatus
;
4292 umscsw
.bValue
&= USMF_CSW_PERSIST
; /* mask out other bits */
4296 umscsw
.bValue
= USMF_CSW_PASS
;
4299 if(ncm
->ncm_DenyRequests
)
4301 rioerr
= HFERR_Phase
;
4304 if((!ioerr
) || (ioerr
== UHIOERR_RUNTPACKET
))
4306 scsicmd
->scsi_Status
= umscsw
.bValue
;
4307 if(umscsw
.bValue
== USMF_CSW_PHASEERR
)
4309 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
4310 "Command (%s) phase error: %ld",
4315 else if(umscsw
.bValue
== USMF_CSW_PERSIST
)
4317 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
4318 "Command (%s) persistant error: %ld",
4324 /* Autosensing required? */
4325 if(((umscsw
.bValue
&& (scsicmd
->scsi_Flags
& SCSIF_AUTOSENSE
))) ||
4326 (ncm
->ncm_TPType
== MS_PROTO_CB
) || (ncm
->ncm_TPType
== MS_PROTO_CBI
))
4328 if(scsicmd
->scsi_Flags
& SCSIF_AUTOSENSE
)
4330 datalen
= scsicmd
->scsi_SenseLength
;
4331 senseptr
= scsicmd
->scsi_SenseData
;
4334 senseptr
= sensedata
;
4336 if(!(scsicmd
->scsi_SenseActual
= nCBIRequestSense(ncm
, senseptr
, datalen
)))
4340 if(senseptr
[2] & SK_MASK
)
4342 rioerr
= HFERR_BadStatus
;
4343 scsicmd
->scsi_Status
= SCSI_CHECK_CONDITION
;
4347 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4348 "Command status failed: %s (%ld)",
4349 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4350 scsicmd
->scsi_Status
= SCSI_CHECK_CONDITION
;
4351 rioerr
= HFERR_Phase
;
4355 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4356 "Data phase failed: %s (%ld)",
4357 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4358 scsicmd
->scsi_Status
= SCSI_CHECK_CONDITION
;
4359 rioerr
= HFERR_Phase
;
4363 scsicmd
->scsi_Status
= SCSI_CHECK_CONDITION
;
4364 rioerr
= HFERR_Phase
;
4365 if(ioerr
== UHIOERR_TIMEOUT
)
4369 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
4371 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Command (%s) failed:", cmdstrbuf
);
4372 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4373 "Command block failed: %s (%ld)",
4374 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4376 if(scsicmd
->scsi_Flags
& SCSIF_AUTOSENSE
)
4378 datalen
= scsicmd
->scsi_SenseLength
;
4379 senseptr
= scsicmd
->scsi_SenseData
;
4382 senseptr
= sensedata
;
4384 if(!(scsicmd
->scsi_SenseActual
= nCBIRequestSense(ncm
, senseptr
, datalen
)))
4389 if(senseptr
[2] & SK_MASK
)
4391 rioerr
= HFERR_BadStatus
;
4392 if((senseptr
[2] & SK_MASK
) == SK_NOT_READY
)
4403 KPRINTF(1, ("Retrying...\n"));
4404 } while(retrycnt
--);
4410 /* /// "nLockXFer()" */
4411 void nLockXFer(struct NepClassMS
*ncm
)
4415 KPRINTF(1, ("PING(lock)\n"));
4416 ObtainSemaphore(&ncm
->ncm_UnitLUN0
->ncm_XFerLock
);
4417 KPRINTF(1, ("PONG(lock)\n"));
4422 /* /// "nUnlockXFer()" */
4423 void nUnlockXFer(struct NepClassMS
*ncm
)
4427 KPRINTF(1, ("PING(unlock)\n"));
4428 ReleaseSemaphore(&ncm
->ncm_UnitLUN0
->ncm_XFerLock
);
4429 KPRINTF(1, ("PONG(unlock)\n"));
4434 /* /// "nStoreConfig()" */
4435 BOOL
GM_UNIQUENAME(nStoreConfig
)(struct NepClassMS
*ncm
)
4438 struct NepClassMS
*cncm
;
4439 if(ncm
->ncm_Interface
)
4441 pic
= psdGetUsbDevCfg(GM_UNIQUENAME(libname
), ncm
->ncm_DevIDString
, ncm
->ncm_IfIDString
);
4444 psdSetUsbDevCfg(GM_UNIQUENAME(libname
), ncm
->ncm_DevIDString
, ncm
->ncm_IfIDString
, NULL
);
4445 pic
= psdGetUsbDevCfg(GM_UNIQUENAME(libname
), ncm
->ncm_DevIDString
, ncm
->ncm_IfIDString
);
4449 psdAddCfgEntry(pic
, ncm
->ncm_CDC
);
4451 while(((struct Node
*) cncm
)->ln_Succ
)
4453 if(cncm
->ncm_UnitLUN0
!= ncm
)
4457 psdAddCfgEntry(pic
, cncm
->ncm_CUC
);
4458 cncm
= (struct NepClassMS
*) ((struct Node
*) cncm
)->ln_Succ
;
4469 /* ********************************************************************* */
4471 /* /// "BSTR Macros" */
4474 #define b2cstr(bstr, cstr)\
4478 UWORD _len = AROS_BSTR_strlen(bstr);\
4481 cstr[_i] = AROS_BSTR_getchar(bstr, _i);\
4487 #define c2bstr(cstr, bstr)\
4491 while(cstr[_i] != '\0')\
4493 AROS_BSTR_putchar(bstr, _i, cstr[_i]);\
4496 AROS_BSTR_setstrlen(bstr, _i);\
4500 #define b2cstr(bstr, cstr) { ULONG i; for (i = 0; i < bstr[0]; i++) cstr[i] = bstr[i + 1]; cstr[i] = 0x00; }
4502 #define c2bstr(cstr, bstr)\
4507 STRPTR cp = (STRPTR) (cstr);\
4508 STRPTR bp = (STRPTR) (bstr);\
4520 #define ps nh->nh_PsdBase
4522 /* /// "nRemovableTask()" */
4523 AROS_UFH0(void, GM_UNIQUENAME(nRemovableTask
))
4527 struct NepMSBase
*nh
;
4528 struct NepClassMS
*ncm
;
4532 struct SCSICmd scsicmd
;
4534 UBYTE sensedata
[18];
4535 struct IOStdReq
*ioreq
;
4536 BOOL dontquit
= TRUE
;
4538 if((nh
= GM_UNIQUENAME(nAllocRT
)()))
4541 if(nh
->nh_ReadySigTask
)
4543 Signal(nh
->nh_ReadySigTask
, 1L<<nh
->nh_ReadySignal
);
4547 sigmask
= (1L<<nh
->nh_TimerMsgPort
->mp_SigBit
)|
4551 while((ioreq
= (struct IOStdReq
*) GetMsg(nh
->nh_TimerMsgPort
)))
4554 KPRINTF(2, ("Timer interrupt\n"));
4555 ncm
= (struct NepClassMS
*) nh
->nh_Units
.lh_Head
;
4556 while(ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
4558 if(ncm
->ncm_Task
&& (!ncm
->ncm_DenyRequests
))
4562 if(ncm
->ncm_Removable
&& ncm
->ncm_Running
)
4564 scsicmd
.scsi_Data
= NULL
;
4565 scsicmd
.scsi_Length
= 0;
4566 scsicmd
.scsi_Command
= cmd6
;
4567 scsicmd
.scsi_CmdLength
= 6;
4568 scsicmd
.scsi_Flags
= SCSIF_READ
|SCSIF_AUTOSENSE
|0x80;
4569 scsicmd
.scsi_SenseData
= sensedata
;
4570 scsicmd
.scsi_SenseLength
= 18;
4571 cmd6
[0] = SCSI_TEST_UNIT_READY
;
4577 if((ioerr
= nScsiDirectTunnel(ncm
, &scsicmd
)))
4579 KPRINTF(1, ("Test unit ready yielded: %ld/%ld\n", sensedata
[2], sensedata
[12]));
4580 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
4581 "SCSI_TEST_UNIT_READY failed: %ld",
4583 /* Check for MEDIUM NOT PRESENT */
4584 if(((sensedata
[2] & SK_MASK
) == SK_NOT_READY
) &&
4585 ((sensedata
[12] == 0x3a) || (sensedata
[12] == 0x04)))
4587 if(ncm
->ncm_UnitReady
)
4589 ncm
->ncm_UnitReady
= FALSE
;
4590 ncm
->ncm_ChangeCount
++;
4591 KPRINTF(10, ("Diskchange: Medium removed (count = %ld)!\n", ncm
->ncm_ChangeCount
));
4592 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
4594 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
4595 "Diskchange: Medium removed (count = %ld)",
4596 ncm
->ncm_ChangeCount
);
4601 if(!ncm
->ncm_UnitReady
)
4603 ncm
->ncm_UnitReady
= TRUE
;
4604 ncm
->ncm_ChangeCount
++;
4605 KPRINTF(10, ("Diskchange: Medium inserted (count = %ld)!\n", ncm
->ncm_ChangeCount
));
4606 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
4608 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
4609 "Diskchange: Medium inserted (count = %ld)",
4610 ncm
->ncm_ChangeCount
);
4612 if(ncm
->ncm_CSType
== MS_UFI_SUBCLASS
)
4614 nh
->nh_IOReq
.io_Command
= CMD_START
;
4615 nIOCmdTunnel(ncm
, &nh
->nh_IOReq
);
4618 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_REM_SUPPORT
)
4620 nGetWriteProtect(ncm
);
4625 if(ncm
->ncm_LastChange
!= ncm
->ncm_ChangeCount
)
4627 if(ncm
->ncm_UnitReady
)
4629 nGetWriteProtect(ncm
);
4630 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_REM_SUPPORT
)
4632 nh
->nh_IOReq
.io_Command
= TD_GETGEOMETRY
;
4633 nh
->nh_IOReq
.io_Data
= &ncm
->ncm_Geometry
;
4634 nh
->nh_IOReq
.io_Length
= sizeof(ncm
->ncm_Geometry
);
4635 nIOCmdTunnel(ncm
, &nh
->nh_IOReq
);
4638 ioreq
= (struct IOStdReq
*) ncm
->ncm_DCInts
.lh_Head
;
4639 while(((struct Node
*) ioreq
)->ln_Succ
)
4641 Cause(ioreq
->io_Data
);
4642 ioreq
= (struct IOStdReq
*) ((struct Node
*) ioreq
)->ln_Succ
;
4644 if(ncm
->ncm_UnitReady
)
4646 // obtain blocksize first
4647 if(!ncm
->ncm_BlockSize
)
4649 nh
->nh_IOReq
.io_Command
= TD_GETGEOMETRY
;
4650 nh
->nh_IOReq
.io_Data
= &ncm
->ncm_Geometry
;
4651 nh
->nh_IOReq
.io_Length
= sizeof(ncm
->ncm_Geometry
);
4652 nIOCmdTunnel(ncm
, &nh
->nh_IOReq
);
4654 ncm
->ncm_HasMounted
= TRUE
;
4656 // find and mount partitions
4657 if(!CheckPartitions(ncm
) && ncm
->ncm_CUC
->cuc_AutoMountFAT
)
4659 // check for FAT volume with no partition table
4660 CheckFATPartition(ncm
, 0);
4662 if((ncm
->ncm_BlockSize
== 2048) &&
4663 ((ncm
->ncm_DeviceType
== PDT_WORM
) || (ncm
->ncm_DeviceType
== PDT_CDROM
)))
4665 if(ncm
->ncm_CUC
->cuc_AutoMountCD
)
4671 ncm
->ncm_LastChange
= ncm
->ncm_ChangeCount
;
4674 if(ncm
->ncm_DenyRequests
&& ncm
->ncm_CUC
->cuc_AutoUnmount
&& ncm
->ncm_HasMounted
)
4676 nUnmountPartition(ncm
);
4677 ncm
->ncm_HasMounted
= FALSE
;
4680 ncm
= (struct NepClassMS
*) ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
4682 nh
->nh_TimerIOReq
->tr_time
.tv_secs
= 3;
4683 nh
->nh_TimerIOReq
->tr_time
.tv_micro
= 0;
4684 SendIO((struct IORequest
*) nh
->nh_TimerIOReq
);
4687 if(nh
->nh_RemovableTask
->tc_Node
.ln_Type
== NT_TASK
)
4690 if((doslib
= OpenLibrary("dos.library", 39)))
4692 CloseLibrary(doslib
);
4693 // increase disk change count to force mounting
4694 ncm
= (struct NepClassMS
*) nh
->nh_Units
.lh_Head
;
4695 while(ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
4697 ncm
->ncm_ChangeCount
++;
4698 ncm
->ncm_ForceRTCheck
= TRUE
;
4699 ncm
= (struct NepClassMS
*) ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
4703 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
4704 "DOS found, stopping removable task...");
4705 nh
->nh_RestartIt
= TRUE
;
4708 // don't quit task, otherwise nobody will be there to restart it and retry mounting stuff
4716 sigs
= Wait(sigmask
);
4717 } while(!(sigs
& SIGBREAKF_CTRL_C
));
4718 ncm
= (struct NepClassMS
*) nh
->nh_Units
.lh_Head
;
4719 while(ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
4721 if(ncm
->ncm_DenyRequests
&& ncm
->ncm_CUC
->cuc_AutoUnmount
&& ncm
->ncm_HasMounted
)
4723 nUnmountPartition(ncm
);
4724 ncm
->ncm_HasMounted
= FALSE
;
4726 ncm
= (struct NepClassMS
*) ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
4728 KPRINTF(20, ("Going down the river!\n"));
4729 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Removable Task stopped.");
4730 GM_UNIQUENAME(nFreeRT
)(nh
);
4736 /* /// "nAllocRT()" */
4737 struct NepMSBase
* GM_UNIQUENAME(nAllocRT
)(void)
4739 struct Task
*thistask
;
4740 struct NepMSBase
*nh
;
4742 thistask
= FindTask(NULL
);
4743 nh
= thistask
->tc_UserData
;
4744 #undef ExpansionBase
4745 #define ExpansionBase nh->nh_ExpansionBase
4746 #undef PartitionBase
4747 #define PartitionBase nh->nh_PartitionBase
4750 if(!(ExpansionBase
= OpenLibrary("expansion.library", 37)))
4752 Alert(AG_OpenLib
| AO_ExpansionLib
);
4755 if(!(PartitionBase
= OpenLibrary("partition.library", 1)))
4757 Alert(AG_OpenLib
| AO_Unknown
);
4760 if(!(ps
= OpenLibrary("poseidon.library", 4)))
4762 Alert(AG_OpenLib
| AO_Unknown
);
4765 if(!(nh
->nh_IOMsgPort
= CreateMsgPort()))
4769 nh
->nh_IOReq
.io_Message
.mn_ReplyPort
= nh
->nh_IOMsgPort
;
4770 if(!(nh
->nh_TimerMsgPort
= CreateMsgPort()))
4774 if(!(nh
->nh_TimerIOReq
= (struct timerequest
*) CreateIORequest(nh
->nh_TimerMsgPort
, sizeof(struct timerequest
))))
4778 if(OpenDevice("timer.device", UNIT_VBLANK
, (struct IORequest
*) nh
->nh_TimerIOReq
, 0))
4782 /* Start removable interrupt */
4783 nh
->nh_TimerIOReq
->tr_node
.io_Command
= TR_ADDREQUEST
;
4784 nh
->nh_TimerIOReq
->tr_time
.tv_secs
= 0;
4785 nh
->nh_TimerIOReq
->tr_time
.tv_micro
= 50;
4786 SendIO((struct IORequest
*) nh
->nh_TimerIOReq
);
4787 nh
->nh_RemovableTask
= thistask
;
4792 CloseLibrary(ExpansionBase
);
4793 ExpansionBase
= NULL
;
4797 CloseLibrary(PartitionBase
);
4798 PartitionBase
= NULL
;
4806 if(nh
->nh_TimerIOReq
)
4808 if(nh
->nh_TimerIOReq
->tr_node
.io_Device
)
4810 CloseDevice((struct IORequest
*) nh
->nh_TimerIOReq
);
4812 DeleteIORequest((struct IORequest
*) nh
->nh_TimerIOReq
);
4813 nh
->nh_TimerIOReq
= NULL
;
4815 if(nh
->nh_TimerMsgPort
)
4817 DeleteMsgPort(nh
->nh_TimerMsgPort
);
4818 nh
->nh_TimerMsgPort
= NULL
;
4820 if(nh
->nh_IOMsgPort
)
4822 DeleteMsgPort(nh
->nh_IOMsgPort
);
4823 nh
->nh_IOMsgPort
= NULL
;
4826 nh
->nh_RemovableTask
= NULL
;
4827 if(nh
->nh_ReadySigTask
)
4829 Signal(nh
->nh_ReadySigTask
, 1L<<nh
->nh_ReadySignal
);
4835 /* /// "nFreeRT()" */
4836 void GM_UNIQUENAME(nFreeRT
)(struct NepMSBase
*nh
)
4839 psdFreeVec(nh
->nh_OneBlock
);
4840 nh
->nh_OneBlock
= NULL
;
4841 nh
->nh_OneBlockSize
= 0;
4845 CloseLibrary(nh
->nh_DOSBase
);
4846 nh
->nh_DOSBase
= NULL
;
4848 CloseLibrary(ExpansionBase
);
4849 ExpansionBase
= NULL
;
4850 CloseLibrary(PartitionBase
);
4851 PartitionBase
= NULL
;
4855 AbortIO((struct IORequest
*) nh
->nh_TimerIOReq
);
4856 WaitIO((struct IORequest
*) nh
->nh_TimerIOReq
);
4857 CloseDevice((struct IORequest
*) nh
->nh_TimerIOReq
);
4858 DeleteIORequest((struct IORequest
*) nh
->nh_TimerIOReq
);
4859 DeleteMsgPort(nh
->nh_TimerMsgPort
);
4860 nh
->nh_TimerMsgPort
= NULL
;
4861 nh
->nh_TimerIOReq
= NULL
;
4864 nh
->nh_RemovableTask
= NULL
;
4865 if(nh
->nh_ReadySigTask
)
4867 Signal(nh
->nh_ReadySigTask
, 1L<<nh
->nh_ReadySignal
);
4869 if(nh
->nh_RestartIt
)
4871 // wake up every task to relaunch removable task
4872 struct NepClassMS
*ncm
;
4873 ncm
= (struct NepClassMS
*) nh
->nh_Units
.lh_Head
;
4874 while(ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
4878 Signal(ncm
->ncm_Task
, 1L<<ncm
->ncm_TaskMsgPort
->mp_SigBit
);
4880 ncm
= (struct NepClassMS
*) ncm
->ncm_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
4882 nh
->nh_RestartIt
= FALSE
;
4887 /* /// "GM_UNIQUENAME(nOpenDOS)()" */
4888 BOOL
GM_UNIQUENAME(nOpenDOS
)(struct NepMSBase
*nh
)
4894 if(nh
->nh_RemovableTask
->tc_Node
.ln_Type
!= NT_PROCESS
)
4898 if((nh
->nh_DOSBase
= OpenLibrary("dos.library", 39)))
4900 KPRINTF(10, ("Opened dos.library!\n"));
4908 #define DOSBase nh->nh_DOSBase
4910 /* /// "nUnmountPartition()" */
4911 void nUnmountPartition(struct NepClassMS
*ncm
)
4913 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
4914 struct DosList
*list
;
4915 struct DeviceNode
*node
;
4916 struct DeviceNode
*oldnode
= NULL
;
4920 if(!GM_UNIQUENAME(nOpenDOS
)(nh
))
4924 while((node
= FindMatchingDevice(ncm
, NULL
)))
4930 bstr
= (UBYTE
*) BADDR(node
->dn_Name
);
4931 b2cstr(bstr
, partname
);
4932 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
4933 "Unmounting partition %s...",
4935 DoPkt(node
->dn_Task
, ACTION_INHIBIT
, TRUE
, 0, 0, 0, 0);
4936 DoPkt(node
->dn_Task
, ACTION_DIE
, 0, 0, 0, 0, 0);
4937 if((list
= LockDosList(LDF_DEVICES
| LDF_WRITE
)))
4939 list
= FindDosEntry(list
, partname
, LDF_DEVICES
);
4944 UnLockDosList(LDF_DEVICES
| LDF_WRITE
);
4946 /*psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
4947 "Unmounting %s done.",
4954 /* /// "nIOCmdTunnel()" */
4955 LONG
nIOCmdTunnel(struct NepClassMS
*ncm
, struct IOStdReq
*ioreq
)
4957 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
4959 if(ncm
->ncm_DenyRequests
)
4962 return(ioreq
->io_Error
= IOERR_ABORTED
);
4964 PutMsg(&ncm
->ncm_Unit
.unit_MsgPort
, (struct Message
*) ioreq
);
4966 while(!GetMsg(nh
->nh_IOMsgPort
))
4968 WaitPort(nh
->nh_IOMsgPort
);
4970 return(ioreq
->io_Error
);
4974 /* /// "nScsiDirectTunnel()" */
4975 LONG
nScsiDirectTunnel(struct NepClassMS
*ncm
, struct SCSICmd
*scsicmd
)
4977 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
4978 struct IOStdReq
*ioreq
= &nh
->nh_IOReq
;
4979 ioreq
->io_Command
= HD_SCSICMD
;
4980 ioreq
->io_Data
= scsicmd
;
4981 ioreq
->io_Length
= sizeof(*scsicmd
);
4982 return(nIOCmdTunnel(ncm
, ioreq
));
4986 /* /// "nGetWriteProtect()" */
4987 LONG
nGetWriteProtect(struct NepClassMS
*ncm
)
4989 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
4991 struct SCSICmd scsicmd
;
4992 UBYTE inquirydata
[256];
4993 UBYTE sensedata
[18];
4996 if((ncm
->ncm_DeviceType
== PDT_WORM
) ||
4997 (ncm
->ncm_DeviceType
== PDT_CDROM
))
4999 // cd roms are always write protected
5000 return(ncm
->ncm_WriteProtect
= TRUE
);
5002 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_SIMPLE_SCSI
)
5004 return(ncm
->ncm_WriteProtect
= FALSE
);
5006 scsicmd
.scsi_Data
= (UWORD
*) inquirydata
;
5007 scsicmd
.scsi_Length
= 8;
5008 scsicmd
.scsi_Command
= cmd10
;
5009 scsicmd
.scsi_CmdLength
= 10;
5010 scsicmd
.scsi_Flags
= SCSIF_READ
|SCSIF_AUTOSENSE
|0x80;
5011 scsicmd
.scsi_SenseData
= sensedata
;
5012 scsicmd
.scsi_SenseLength
= 18;
5013 cmd10
[0] = SCSI_MODE_SENSE_10
;
5014 cmd10
[1] = 0x00; /* no block descriptors */
5015 cmd10
[2] = 0x3f; /* no page, only header */
5023 if((ioerr
= nScsiDirectTunnel(ncm
, &scsicmd
)))
5025 cmd10
[2] = 0x00; /* try again with vendor page, only header */
5026 if((ioerr
= nScsiDirectTunnel(ncm
, &scsicmd
)))
5028 cmd10
[2] = 0x3f; /* try again with 255 length */
5030 if((ioerr
= nScsiDirectTunnel(ncm
, &scsicmd
)))
5032 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
5034 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
5035 "Failed to get write protection state: %ld",
5038 if(!(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
))
5040 ncm
->ncm_CDC
->cdc_PatchFlags
|= PFF_SIMPLE_SCSI
;
5041 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
5042 "Fallback: Enabling Simple SCSI.");
5044 GM_UNIQUENAME(nStoreConfig
)(ncm
);
5049 if(inquirydata
[3] & 0x80)
5051 if(!ncm
->ncm_WriteProtect
)
5053 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_REM_SUPPORT
)
5055 ncm
->ncm_ChangeCount
++;
5056 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
5058 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5059 "Diskchange: GetWriteProtect On (count = %ld)",
5060 ncm
->ncm_ChangeCount
);
5063 ncm
->ncm_WriteProtect
= TRUE
;
5066 if(ncm
->ncm_WriteProtect
)
5068 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_REM_SUPPORT
)
5070 ncm
->ncm_ChangeCount
++;
5071 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
5073 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5074 "Diskchange: GetWriteProtect Off (count = %ld)",
5075 ncm
->ncm_ChangeCount
);
5078 ncm
->ncm_WriteProtect
= FALSE
;
5081 return(ncm
->ncm_WriteProtect
);
5085 /* /// "SearchHardBlock()" */
5086 APTR
SearchHardBlock(struct NepClassMS
*ncm
,
5087 struct IOStdReq
*ioreq
,
5091 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5094 if(!nh
->nh_OneBlock
|| (nh
->nh_OneBlockSize
< ncm
->ncm_BlockSize
))
5096 psdFreeVec(nh
->nh_OneBlock
);
5097 if(!(nh
->nh_OneBlock
= psdAllocVec(ncm
->ncm_BlockSize
)))
5101 nh
->nh_OneBlockSize
= ncm
->ncm_BlockSize
;
5107 ioreq
->io_Command
= TD_READ64
;
5108 ioreq
->io_Data
= nh
->nh_OneBlock
;
5109 ioreq
->io_Length
= ncm
->ncm_BlockSize
;
5110 ioreq
->io_Offset
= curBlock
<<ncm
->ncm_BlockShift
;
5111 ioreq
->io_Actual
= curBlock
>>(32-ncm
->ncm_BlockShift
);
5113 if(!nIOCmdTunnel(ncm
, ioreq
))
5116 if((*(ULONG
*) nh
->nh_OneBlock
) == id
)
5118 return(nh
->nh_OneBlock
);
5121 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Error searching hardblock in block %ld.", curBlock
);
5124 } while(curBlock
<= RDB_LOCATION_LIMIT
);
5129 /* /// "ReadRDSK()" */
5130 BOOL
ReadRDSK(struct NepClassMS
*ncm
,
5131 struct IOStdReq
*ioreq
,
5132 struct RigidDiskBlock
*rdb
)
5134 APTR blkaddr
= SearchHardBlock(ncm
, ioreq
, IDNAME_RIGIDDISK
, 0);
5137 CopyMemQuick(blkaddr
, rdb
, sizeof(struct RigidDiskBlock
));
5138 // endianess conversion
5139 rdb
->rdb_ID
= AROS_BE2LONG(rdb
->rdb_ID
);
5140 rdb
->rdb_SummedLongs
= AROS_BE2LONG(rdb
->rdb_SummedLongs
);
5141 rdb
->rdb_ChkSum
= AROS_BE2LONG(rdb
->rdb_ChkSum
);
5142 rdb
->rdb_HostID
= AROS_BE2LONG(rdb
->rdb_HostID
);
5143 rdb
->rdb_BlockBytes
= AROS_BE2LONG(rdb
->rdb_BlockBytes
);
5144 rdb
->rdb_PartitionList
= AROS_BE2LONG(rdb
->rdb_PartitionList
);
5145 rdb
->rdb_FileSysHeaderList
= AROS_BE2LONG(rdb
->rdb_FileSysHeaderList
);
5146 rdb
->rdb_DriveInit
= AROS_BE2LONG(rdb
->rdb_DriveInit
);
5147 rdb
->rdb_Cylinders
= AROS_BE2LONG(rdb
->rdb_Cylinders
);
5148 rdb
->rdb_Sectors
= AROS_BE2LONG(rdb
->rdb_Sectors
);
5149 rdb
->rdb_Heads
= AROS_BE2LONG(rdb
->rdb_Heads
);
5150 rdb
->rdb_Interleave
= AROS_BE2LONG(rdb
->rdb_Interleave
);
5151 rdb
->rdb_Park
= AROS_BE2LONG(rdb
->rdb_Park
);
5152 rdb
->rdb_WritePreComp
= AROS_BE2LONG(rdb
->rdb_WritePreComp
);
5153 rdb
->rdb_ReducedWrite
= AROS_BE2LONG(rdb
->rdb_ReducedWrite
);
5154 rdb
->rdb_StepRate
= AROS_BE2LONG(rdb
->rdb_StepRate
);
5155 rdb
->rdb_RDBBlocksLo
= AROS_BE2LONG(rdb
->rdb_RDBBlocksLo
);
5156 rdb
->rdb_RDBBlocksHi
= AROS_BE2LONG(rdb
->rdb_RDBBlocksHi
);
5157 rdb
->rdb_LoCylinder
= AROS_BE2LONG(rdb
->rdb_LoCylinder
);
5158 rdb
->rdb_HiCylinder
= AROS_BE2LONG(rdb
->rdb_HiCylinder
);
5159 rdb
->rdb_CylBlocks
= AROS_BE2LONG(rdb
->rdb_CylBlocks
);
5160 rdb
->rdb_AutoParkSeconds
= AROS_BE2LONG(rdb
->rdb_AutoParkSeconds
);
5161 rdb
->rdb_HighRDSKBlock
= AROS_BE2LONG(rdb
->rdb_HighRDSKBlock
);
5168 /* /// "ReadPART()" */
5169 BOOL
ReadPART(struct NepClassMS
*ncm
,
5170 struct IOStdReq
*ioreq
,
5171 struct PartitionBlock
*part
,
5174 APTR blkaddr
= SearchHardBlock(ncm
, ioreq
, IDNAME_PARTITION
, which
);
5178 CopyMemQuick(blkaddr
, part
, sizeof(struct PartitionBlock
));
5179 // endianess conversion
5180 part
->pb_ID
= AROS_BE2LONG(part
->pb_ID
);
5181 part
->pb_SummedLongs
= AROS_BE2LONG(part
->pb_SummedLongs
);
5182 part
->pb_ChkSum
= AROS_BE2LONG(part
->pb_ChkSum
);
5183 part
->pb_HostID
= AROS_BE2LONG(part
->pb_HostID
);
5184 part
->pb_Next
= AROS_BE2LONG(part
->pb_Next
);
5185 part
->pb_Flags
= AROS_BE2LONG(part
->pb_Flags
);
5186 part
->pb_DevFlags
= AROS_BE2LONG(part
->pb_DevFlags
);
5187 for(cnt
= 0; cnt
< 20; cnt
++)
5189 part
->pb_Environment
[cnt
] = AROS_BE2LONG(part
->pb_Environment
[cnt
]);
5197 /* /// "ReadFSHD()" */
5198 BOOL
ReadFSHD(struct NepClassMS
*ncm
,
5199 struct IOStdReq
*ioreq
,
5200 struct FileSysHeaderBlock
*fshd
,
5203 APTR blkaddr
= SearchHardBlock(ncm
, ioreq
, IDNAME_FILESYSHEADER
, which
);
5206 CopyMemQuick(blkaddr
, fshd
, sizeof(struct FileSysHeaderBlock
));
5207 // endianess conversion
5208 fshd
->fhb_ID
= AROS_BE2LONG(fshd
->fhb_ID
);
5209 fshd
->fhb_SummedLongs
= AROS_BE2LONG(fshd
->fhb_SummedLongs
);
5210 fshd
->fhb_ChkSum
= AROS_BE2LONG(fshd
->fhb_ChkSum
);
5211 fshd
->fhb_HostID
= AROS_BE2LONG(fshd
->fhb_HostID
);
5212 fshd
->fhb_Next
= AROS_BE2LONG(fshd
->fhb_Next
);
5213 fshd
->fhb_Flags
= AROS_BE2LONG(fshd
->fhb_Flags
);
5214 fshd
->fhb_DosType
= AROS_BE2LONG(fshd
->fhb_DosType
);
5215 fshd
->fhb_Version
= AROS_BE2LONG(fshd
->fhb_Version
);
5216 fshd
->fhb_PatchFlags
= AROS_BE2LONG(fshd
->fhb_PatchFlags
);
5217 fshd
->fhb_Type
= AROS_BE2LONG(fshd
->fhb_Type
);
5218 fshd
->fhb_Task
= AROS_BE2LONG(fshd
->fhb_Task
);
5219 fshd
->fhb_Lock
= AROS_BE2LONG(fshd
->fhb_Lock
);
5220 fshd
->fhb_Handler
= AROS_BE2LONG(fshd
->fhb_Handler
);
5221 fshd
->fhb_StackSize
= AROS_BE2LONG(fshd
->fhb_StackSize
);
5222 fshd
->fhb_Priority
= AROS_BE2LONG(fshd
->fhb_Priority
);
5223 fshd
->fhb_Startup
= AROS_BE2LONG(fshd
->fhb_Startup
);
5224 fshd
->fhb_SegListBlocks
= AROS_BE2LONG(fshd
->fhb_SegListBlocks
);
5225 fshd
->fhb_GlobalVec
= AROS_BE2LONG(fshd
->fhb_GlobalVec
);
5232 /* /// "ReadLSEG()" */
5233 struct LoadSegBlock
* ReadLSEG(struct NepClassMS
*ncm
,
5234 struct IOStdReq
*ioreq
,
5237 return((struct LoadSegBlock
*) SearchHardBlock(ncm
, ioreq
, IDNAME_LOADSEG
, which
));
5241 /* /// "FindFileSystem()" */
5242 struct FileSysEntry
* FindFileSystem(struct NepClassMS
*ncm
, ULONG dosType
)
5244 struct FileSysResource
*fsr
;
5245 struct FileSysEntry
*fse
;
5247 KPRINTF(10, ("looking up %08lx fs\n", dosType
));
5248 if((fsr
= (struct FileSysResource
*) OpenResource(FSRNAME
)))
5251 fse
= (struct FileSysEntry
*) fsr
->fsr_FileSysEntries
.lh_Head
;
5252 while(fse
->fse_Node
.ln_Succ
)
5254 if(fse
->fse_DosType
== dosType
)
5259 fse
= (struct FileSysEntry
*) fse
->fse_Node
.ln_Succ
;
5268 /* /// "BuildFileSystem()" */
5269 ULONG
BuildFileSystem(struct NepClassMS
*ncm
,
5273 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5274 struct RigidDisk
*rdsk
= &nh
->nh_RDsk
;
5278 struct LoadSegBlock
*lseg
;
5280 nextLSEG
= rdsk
->rdsk_FSHD
.fhb_SegListBlocks
;
5284 if((lseg
= ReadLSEG(ncm
, &nh
->nh_IOReq
, nextLSEG
)))
5286 add
= (AROS_BE2LONG(lseg
->lsb_SummedLongs
) - 5) * sizeof(ULONG
);
5289 CopyMem(lseg
->lsb_LoadData
, fsBuffer
, add
);
5293 nextLSEG
= lseg
->lsb_Next
;
5298 } while(nextLSEG
!= NIL_PTR
);
5303 /* /// "LoadFileSystem()" */
5304 BPTR
LoadFileSystem(struct NepClassMS
*ncm
, ULONG dosType
, struct FileSysEntry
*fse
)
5306 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5307 struct RigidDisk
*rdsk
= &nh
->nh_RDsk
;
5309 BPTR fh
, seg
= BNULL
;
5315 if(rdsk
->rdsk_RDB
.rdb_FileSysHeaderList
!= NIL_PTR
)
5317 nextFSHD
= rdsk
->rdsk_RDB
.rdb_FileSysHeaderList
;
5320 if(ReadFSHD(ncm
, &nh
->nh_IOReq
, &rdsk
->rdsk_FSHD
, nextFSHD
))
5322 nextFSHD
= rdsk
->rdsk_FSHD
.fhb_Next
;
5326 KPRINTF(10, ("Found 0x%08lx FS in FSHD...\n", rdsk
->rdsk_FSHD
.fhb_ID
));
5327 } while((rdsk
->rdsk_FSHD
.fhb_DosType
!= dosType
) && (nextFSHD
!= NIL_PTR
));
5329 if(rdsk
->rdsk_FSHD
.fhb_DosType
== dosType
)
5331 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Found filesystem %s in RDB!",
5332 nh
->nh_RDsk
.rdsk_FSHD
.fhb_FileSysName
);
5333 KPRINTF(10, ("found matching fs in FSHD, trying to load from LSEG blocks\n"));
5335 CopyMem(&rdsk
->rdsk_FSHD
.fhb_DosType
, &fse
->fse_DosType
, sizeof(struct FileSysEntry
) - sizeof(struct Node
));
5337 if(rdsk
->rdsk_FSHD
.fhb_SegListBlocks
> 0)
5339 fsLength
= BuildFileSystem(ncm
, NULL
, FALSE
);
5343 if((fsBuffer
= psdAllocVec(fsLength
)))
5345 BuildFileSystem(ncm
, fsBuffer
, TRUE
);
5347 if(GM_UNIQUENAME(nOpenDOS
)(nh
))
5349 psdSafeRawDoFmt(fsFile
, 32, "T:UMSD_%08lx.fs", dosType
);
5350 if((fh
= Open(fsFile
, MODE_NEWFILE
)))
5352 ok
= (Write(fh
, fsBuffer
, fsLength
) == fsLength
);
5356 seg
= LoadSeg(fsFile
);
5361 KPRINTF(10, ("No DOS available, trying own load seg stuff\n"));
5362 // FIXME this code is unavailable and doesn't make sense for AROS as it doesn't use DOS_HUNK format
5363 //seg = CreateSegment(ncm, (const ULONG *) fsBuffer);
5365 psdFreeVec(fsBuffer
);
5374 if(GM_UNIQUENAME(nOpenDOS
)(nh
))
5376 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Loading filesystem %s from RDB failed. Trying DOS...",
5377 nh
->nh_RDsk
.rdsk_FSHD
.fhb_FileSysName
);
5378 KPRINTF(10, ("loading fs from LSEG blocks failed, trying fs file %s mentioned in FSHD\n", (char *) nh
->nh_RDsk
.rdsk_FSHD
.fhb_FileSysName
));
5379 //seg = LoadSeg(rdsk->rdsk_FSHD.fhb_FileSysName);
5380 seg
= LoadSeg((char *) nh
->nh_RDsk
.rdsk_FSHD
.fhb_FileSysName
);
5383 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Loaded filesystem %s via DOS!",
5384 nh
->nh_RDsk
.rdsk_FSHD
.fhb_FileSysName
);
5386 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Loading filesystem %s via DOS failed!",
5387 nh
->nh_RDsk
.rdsk_FSHD
.fhb_FileSysName
);
5390 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Loading filesystem %s from RDB failed.",
5391 nh
->nh_RDsk
.rdsk_FSHD
.fhb_FileSysName
);
5396 fse
->fse_SegList
= seg
;
5402 /* /// "MatchPartition()" */
5403 BOOL
MatchPartition(struct NepClassMS
*ncm
,
5404 struct DosEnvec
*envec1
,
5405 struct FileSysStartupMsg
*fssm
)
5407 BOOL result
= FALSE
;
5410 struct DosEnvec
*envec2
;
5414 envec2
= (struct DosEnvec
*) BADDR(fssm
->fssm_Environ
);
5418 bstr
= (UBYTE
*) BADDR(fssm
->fssm_Device
);
5419 b2cstr(bstr
, device
);
5423 if((envec1
->de_DosType
& 0xffffff00) == 0x46415400)
5425 result
= ((ncm
->ncm_UnitNo
== fssm
->fssm_Unit
) &&
5426 (strcmp(DEVNAME
, device
) == 0) &&
5427 (envec1
->de_DosType
== envec2
->de_DosType
));
5429 result
= ((ncm
->ncm_UnitNo
== fssm
->fssm_Unit
) &&
5430 (strcmp(DEVNAME
, device
) == 0) &&
5431 (envec1
->de_SizeBlock
== envec2
->de_SizeBlock
) &&
5432 (envec1
->de_Surfaces
== envec2
->de_Surfaces
) &&
5433 (envec1
->de_SectorPerBlock
== envec2
->de_SectorPerBlock
) &&
5434 (envec1
->de_BlocksPerTrack
== envec2
->de_BlocksPerTrack
) &&
5435 (envec1
->de_Reserved
== envec2
->de_Reserved
) &&
5436 (envec1
->de_PreAlloc
== envec2
->de_PreAlloc
) &&
5437 (envec1
->de_Interleave
== envec2
->de_Interleave
) &&
5438 (envec1
->de_LowCyl
== envec2
->de_LowCyl
) &&
5439 (envec1
->de_HighCyl
== envec2
->de_HighCyl
) &&
5440 (envec1
->de_DosType
== envec2
->de_DosType
));
5443 result
= (ncm
->ncm_UnitNo
== fssm
->fssm_Unit
) &&
5444 (strcmp(DEVNAME
, device
) == 0);
5452 /* /// "FindDeviceNode()" */
5453 struct DeviceNode
* FindDeviceNode(struct NepClassMS
*ncm
, STRPTR device
)
5455 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5456 struct DosList
*list
;
5457 struct DeviceNode
*node
= NULL
;
5459 if(!GM_UNIQUENAME(nOpenDOS
)(nh
))
5464 if((list
= LockDosList(LDF_DEVICES
| LDF_READ
)))
5466 node
= (struct DeviceNode
*) FindDosEntry(list
, device
, LDF_DEVICES
);
5467 UnLockDosList(LDF_DEVICES
| LDF_READ
);
5473 /* /// "CheckVolumesOrAssignsMatch()" */
5474 BOOL
CheckVolumesOrAssignsMatch(struct NepClassMS
*ncm
, STRPTR device
)
5476 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5477 struct DosList
*list
;
5480 if(!GM_UNIQUENAME(nOpenDOS
)(nh
))
5485 if((list
= LockDosList(LDF_ALL
| LDF_READ
)))
5487 if(FindDosEntry(list
, device
, LDF_ALL
))
5491 UnLockDosList(LDF_ALL
| LDF_READ
);
5497 /* /// "FindMatchingDevice()" */
5498 struct DeviceNode
* FindMatchingDevice(struct NepClassMS
*ncm
, struct DosEnvec
*envec
)
5500 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5501 struct DosList
*list
;
5502 struct DeviceNode
*node
= NULL
;
5503 struct FileSysStartupMsg
*fssm
;
5505 if(!GM_UNIQUENAME(nOpenDOS
)(nh
))
5510 if((list
= LockDosList(LDF_DEVICES
| LDF_READ
)))
5512 while((list
= NextDosEntry(list
, LDF_DEVICES
| LDF_READ
)))
5516 /*if((!(((ULONG) list->dol_misc.dol_handler.dol_Startup) >> 30)) &&
5517 TypeOfMem(BADDR(list->dol_misc.dol_handler.dol_Startup)))*/
5519 fssm
= BADDR(list
->dol_misc
.dol_handler
.dol_Startup
);
5522 if(fssm
> (struct FileSysStartupMsg
*) 0x1000)
5524 // if((*((UBYTE *) fssm)) == 0)
5526 struct DosEnvec
*de
= BADDR(fssm
->fssm_Environ
);
5527 STRPTR devname
= BADDR(fssm
->fssm_Device
);
5529 if(TypeOfMem(de
) && TypeOfMem(devname
) && (de
->de_TableSize
> 0) && (de
->de_TableSize
< 32))
5530 /*if((!((ULONG) de >> 30)) && TypeOfMem(de) &&
5531 (!((ULONG) devname >> 30)) && TypeOfMem(devname) &&
5532 (de->de_TableSize > 0) && (de->de_TableSize < 32))*/
5534 if(MatchPartition(ncm
, envec
, fssm
))
5536 node
= (struct DeviceNode
*) list
;
5543 UnLockDosList(LDF_DEVICES
| LDF_READ
);
5549 /* /// "MountPartition()" */
5550 BOOL
MountPartition(struct NepClassMS
*ncm
, STRPTR dosDevice
)
5552 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5553 struct RigidDisk
*rdsk
= &nh
->nh_RDsk
;
5555 struct DeviceNode
*node
;
5556 struct FileSysEntry
*fse
;
5557 struct FileSysEntry patch
;
5558 BPTR segList
= BNULL
;
5559 BOOL fsFound
= FALSE
;
5560 BOOL result
= FALSE
;
5561 STRPTR devname
= DEVNAME
;
5563 if((fse
= FindFileSystem(ncm
, rdsk
->rdsk_PART
.pb_Environment
[DE_DOSTYPE
])))
5565 KPRINTF(10, ("fs found in filesys resource\n"));
5566 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Found FS in filesystem.resource!");
5568 CopyMem(fse
, &patch
, sizeof(struct FileSysEntry
));
5571 memset(&patch
, 0x00, sizeof(struct FileSysEntry
));
5572 patch
.fse_DosType
= rdsk
->rdsk_PART
.pb_Environment
[DE_DOSTYPE
];
5574 if((segList
= LoadFileSystem(ncm
, rdsk
->rdsk_PART
.pb_Environment
[DE_DOSTYPE
], &patch
)))
5576 KPRINTF(10, ("fs loaded from RDB\n"));
5578 patch
.fse_PatchFlags
= 0x0080|0x0010;
5579 patch
.fse_SegList
= segList
;
5580 patch
.fse_StackSize
= 16384;
5581 //if(((patch.fse_DosType & 0xffffff00) == 0x46415400) || (patch.fse_DosType == 0x4d534800))
5583 KPRINTF(10, ("setting up certain fs values for MS-DOS fs\n"));
5584 // Stack, SegList, Pri und GlobVec eintragen
5585 patch
.fse_PatchFlags
|= 0x0020|0x0100;
5586 patch
.fse_Priority
= 10;
5587 patch
.fse_GlobalVec
= (BPTR
) 0xffffffff;
5596 STRPTR handler
= (STRPTR
) nh
->nh_RDsk
.rdsk_FSHD
.fhb_FileSysName
;
5597 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Experimental AROS patch to load %s", handler
);
5598 patch
.fse_Handler
= MKBADDR(AllocVec(AROS_BSTR_MEMSIZE4LEN(strlen(handler
)), MEMF_PUBLIC
| MEMF_CLEAR
));
5599 if(patch
.fse_Handler
)
5601 c2bstr(handler
, patch
.fse_Handler
);
5602 patch
.fse_PatchFlags
|= 0x0008;
5609 if((params
= psdAllocVec(sizeof(struct DosEnvec
) + 4 * sizeof(IPTR
))))
5611 params
[0] = (IPTR
) dosDevice
;
5612 params
[1] = (IPTR
) DEVNAME
;
5613 params
[2] = ncm
->ncm_UnitNo
;
5614 params
[3] = 0x00; // Flags for OpenDevice
5615 CopyMem(rdsk
->rdsk_PART
.pb_Environment
, ¶ms
[4], sizeof(struct DosEnvec
));
5617 if((node
= MakeDosNode(params
)))
5620 KPRINTF(10, ("MakeDosNode() succeeded, patchflags %04lx\n", patch
.fse_PatchFlags
));
5621 node
->dn_StackSize
= 16384;
5623 /*node->dn_Priority = 5;*/
5624 if(patch
.fse_PatchFlags
& 0x0001) node
->dn_Type
= patch
.fse_Type
;
5625 if(patch
.fse_PatchFlags
& 0x0002) node
->dn_Task
= (struct MsgPort
*) patch
.fse_Task
;
5626 if(patch
.fse_PatchFlags
& 0x0004) node
->dn_Lock
= patch
.fse_Lock
;
5627 if(patch
.fse_PatchFlags
& 0x0008) node
->dn_Handler
= patch
.fse_Handler
;
5628 if(patch
.fse_PatchFlags
& 0x0010) node
->dn_StackSize
= patch
.fse_StackSize
;
5629 if(patch
.fse_PatchFlags
& 0x0020) node
->dn_Priority
= patch
.fse_Priority
;
5630 if(patch
.fse_PatchFlags
& 0x0040) node
->dn_Startup
= patch
.fse_Startup
;
5631 if(patch
.fse_PatchFlags
& 0x0080) node
->dn_SegList
= patch
.fse_SegList
;
5632 if(patch
.fse_PatchFlags
& 0x0100) node
->dn_GlobalVec
= patch
.fse_GlobalVec
;
5634 KPRINTF(10, ("dn_Next = %08lx\n"
5638 "dn_Handler = %08lx\n"
5639 "dn_StackSize = %08ld\n"
5640 "dn_Priority = %08ld\n"
5641 "dn_Startup = %08lx\n"
5642 "dn_SegList = %08lx\n"
5643 "dn_GlobalVec = %08lx\n"
5644 "dn_Name = %08lx\n",
5657 installboot
= ncm
->ncm_CUC
->cuc_BootRDB
;
5658 if((nh
->nh_RemovableTask
->tc_Node
.ln_Type
== NT_PROCESS
) ||
5659 (!(nh
->nh_RDsk
.rdsk_PART
.pb_Flags
& PBFF_BOOTABLE
)))
5661 installboot
= FALSE
;
5665 // avoid sys partition being unmounted (actually it should better check at
5666 // unmounting, but I can't think of a clever way yet to retrieve the SYS:
5668 ncm
->ncm_CUC
->cuc_AutoUnmount
= FALSE
;
5669 GM_UNIQUENAME(nStoreConfig
)(ncm
);
5672 if(AddBootNode(nh
->nh_RDsk
.rdsk_PART
.pb_Environment
[DE_BOOTPRI
], ADNF_STARTPROC
, node
, NULL
))
5674 KPRINTF(10, ("AddBootNode() succeeded\n"));
5675 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5676 "Mounted %s unit %ld as %s:",
5677 devname
, ncm
->ncm_UnitNo
, dosDevice
);
5681 KPRINTF(10, ("AddBootNode() failed\n"));
5682 /* There is a memory leak here! No way to deallocate the node created by
5691 if(GM_UNIQUENAME(nOpenDOS
)(nh
))
5697 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
5698 "Couldn't find/load filesystem for %s unit %ld as %s:",
5699 devname
, ncm
->ncm_UnitNo
, dosDevice
);
5700 KPRINTF(10, ("fs %08lx not found\n", rdsk
->rdsk_PART
.pb_Environment
[DE_DOSTYPE
]));
5707 /* /// "CheckPartition()" */
5708 void CheckPartition(struct NepClassMS
*ncm
)
5710 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5711 struct RigidDisk
*rdsk
= &nh
->nh_RDsk
;
5712 struct DosEnvec
*envec
;
5713 UBYTE dosDevice
[32], temp
[32];
5715 struct DeviceNode
*node
;
5716 BOOL done
= FALSE
, doMount
= TRUE
;
5717 STRPTR devname
= DEVNAME
;
5721 envec
= (struct DosEnvec
*) rdsk
->rdsk_PART
.pb_Environment
;
5722 if((node
= FindMatchingDevice(ncm
, envec
)))
5724 KPRINTF(10, ("found suitable device entry, no need to mount anything new\n"));
5726 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5727 "Matching partition for %s unit %ld already found. No remount required.",
5728 devname
, ncm
->ncm_UnitNo
);
5733 b2cstr(rdsk
->rdsk_PART
.pb_DriveName
, dosDevice
);
5735 KPRINTF(10, ("trying to mount partition \"%s\"\n", dosDevice
));
5737 /*if(envec->de_TableSize >= DE_DOSTYPE) SHOWVALUE(envec->de_DosType);*/
5741 if((node
= FindDeviceNode(ncm
, dosDevice
)))
5743 KPRINTF(10, ("%s is already mounted, comparing fssm\n", dosDevice
));
5745 if(MatchPartition(ncm
, envec
, BADDR(node
->dn_Startup
)))
5747 KPRINTF(10, ("fssm match, no need to mount\n"));
5755 if(CheckVolumesOrAssignsMatch(ncm
, dosDevice
))
5764 slen
= strlen(dosDevice
);
5765 if((slen
> 0) && (dosDevice
[slen
-1] >= '0') && (dosDevice
[slen
-1] <= '9'))
5767 if(dosDevice
[slen
-1] == '9')
5769 if((slen
> 1) && (dosDevice
[slen
-2] >= '0') && (dosDevice
[slen
-2] <= '8'))
5771 dosDevice
[slen
-2]++;
5772 dosDevice
[slen
-1] = '0';
5776 dosDevice
[slen
-1] = '1';
5777 dosDevice
[slen
] = '0';
5778 dosDevice
[slen
+1] = 0;
5784 dosDevice
[slen
-1]++;
5787 b2cstr(rdsk
->rdsk_PART
.pb_DriveName
, temp
);
5788 psdSafeRawDoFmt(dosDevice
, 32, "%s.%ld", temp
, spareNum
);
5790 KPRINTF(10, ("fssm don't match, trying as %s\n", dosDevice
));
5793 } while(!done
&& (spareNum
< 16));
5798 KPRINTF(10, ("mounting %s\n", dosDevice
));
5800 MountPartition(ncm
, dosDevice
);
5805 /* /// "IsFATSuperBlock()" */
5806 BOOL
IsFATSuperBlock(struct FATSuperBlock
*fsb
)
5809 result
= (BOOL
)(strncmp(fsb
->fsb_Vendor
, "MSDOS", 5) == 0 ||
5810 strncmp(fsb
->fsb_Vendor
, "MSWIN", 5) == 0 ||
5811 strncmp(fsb
->fsb_FileSystem
, "FAT12", 5) == 0 ||
5812 strncmp(fsb
->fsb_FileSystem
, "FAT16", 5) == 0 ||
5813 strncmp(fsb
->fsb_FileSystem2
, "FAT32", 5) == 0);
5819 /* /// "GetFATDosType()" */
5820 ULONG
GetFATDosType(struct FATSuperBlock
*fsb
)
5822 ULONG result
= 0x46415400;
5823 if(strncmp(fsb
->fsb_FileSystem2
, "FAT32", 5) == 0)
5825 else if(strncmp(fsb
->fsb_FileSystem
, "FAT16", 5) == 0)
5832 /* /// "CheckFATPartition()" */
5833 void CheckFATPartition(struct NepClassMS
*ncm
, ULONG startblock
)
5835 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5836 struct MasterBootRecord
*mbr
;
5837 struct DosEnvec
*envec
;
5838 struct IOStdReq
*stdIO
= &nh
->nh_IOReq
;
5839 struct DriveGeometry
*tddg
= &ncm
->ncm_Geometry
;
5841 BOOL isntfs
= FALSE
;
5843 mbr
= (struct MasterBootRecord
*) psdAllocVec(ncm
->ncm_BlockSize
<<1);
5849 stdIO
->io_Command
= TD_READ64
;
5850 stdIO
->io_Offset
= startblock
<<ncm
->ncm_BlockShift
;
5851 stdIO
->io_Actual
= startblock
>>(32-ncm
->ncm_BlockShift
);
5852 stdIO
->io_Length
= ncm
->ncm_BlockSize
;
5853 stdIO
->io_Data
= mbr
;
5854 if(!nIOCmdTunnel(ncm
, stdIO
))
5856 /* do (super)floppy check */
5857 if(IsFATSuperBlock((struct FATSuperBlock
*) mbr
))
5859 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Media is FAT formatted!");
5861 nh
->nh_RDsk
.rdsk_PART
.pb_DevFlags
= 0;
5863 if(*(ncm
->ncm_CUC
->cuc_FATDOSName
))
5865 c2bstr(ncm
->ncm_CUC
->cuc_FATDOSName
, nh
->nh_RDsk
.rdsk_PART
.pb_DriveName
);
5867 c2bstr("UF0", nh
->nh_RDsk
.rdsk_PART
.pb_DriveName
);
5870 envec
= (struct DosEnvec
*) nh
->nh_RDsk
.rdsk_PART
.pb_Environment
;
5871 memset(envec
, 0x00, sizeof(struct DosEnvec
));
5872 stdIO
->io_Command
= TD_GETGEOMETRY
;
5873 stdIO
->io_Data
= tddg
;
5874 stdIO
->io_Length
= sizeof(*tddg
);
5876 if(nIOCmdTunnel(ncm
, stdIO
))
5878 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Couldn't read drive geometry, using floppy defaults");
5879 envec
->de_SizeBlock
= ncm
->ncm_BlockSize
>>2;
5880 envec
->de_Surfaces
= 2;
5881 envec
->de_BlocksPerTrack
= 18;
5882 envec
->de_LowCyl
= 0;
5883 envec
->de_HighCyl
= 79;
5885 envec
->de_SizeBlock
= ncm
->ncm_BlockSize
>>2;
5886 envec
->de_Surfaces
= tddg
->dg_Heads
;
5887 envec
->de_BlocksPerTrack
= tddg
->dg_TrackSectors
;
5888 envec
->de_LowCyl
= 0;
5889 envec
->de_HighCyl
= tddg
->dg_Cylinders
-1;
5891 envec
->de_TableSize
= DE_BOOTBLOCKS
;
5892 envec
->de_SectorPerBlock
= 1;
5893 envec
->de_NumBuffers
= ncm
->ncm_CUC
->cuc_FATBuffers
;
5894 envec
->de_BufMemType
= MEMF_PUBLIC
;
5895 envec
->de_MaxTransfer
= (1UL<<(ncm
->ncm_CDC
->cdc_MaxTransfer
+16))-1;
5896 envec
->de_Mask
= 0xffffffff;
5897 envec
->de_BootPri
= 0;
5898 envec
->de_Baud
= 1200;
5899 if(*ncm
->ncm_CDC
->cdc_FATControl
)
5901 UBYTE
*bptr
= ncm
->ncm_FATControlBSTR
;
5902 bptr
= (UBYTE
*) ((((IPTR
) bptr
) + 3) & (~3));
5903 c2bstr(ncm
->ncm_CDC
->cdc_FATControl
, bptr
);
5904 envec
->de_Control
= (IPTR
) MKBADDR(bptr
);
5906 envec
->de_Control
= 0;
5908 envec
->de_BootBlocks
= 0;
5909 envec
->de_Interleave
= 0;
5910 envec
->de_DosType
= ncm
->ncm_CDC
->cdc_FATDosType
; //0x46415401; // FAT1
5911 if((ncm
->ncm_CDC
->cdc_FATDosType
& 0xffffff00) == 0x46415400)
5914 GetFATDosType((struct FATSuperBlock
*) mbr
);
5917 // we have no FSHD and LSEG blocks
5918 nh
->nh_RDsk
.rdsk_RDB
.rdb_FileSysHeaderList
= NIL_PTR
;
5919 nh
->nh_RDsk
.rdsk_FSHD
.fhb_SegListBlocks
= 0;
5921 KPRINTF(5, ("building FAT95 style environment\n"));
5923 strncpy((char *) nh
->nh_RDsk
.rdsk_FSHD
.fhb_FileSysName
, ncm
->ncm_CDC
->cdc_FATFSName
, 84);
5924 CheckPartition(ncm
);
5926 if(!(isfat
|| isntfs
))
5928 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5929 "Media does not seem to be FAT nor NTFS formatted.");
5932 KPRINTF(10, ("failed to read MBR\n"));
5933 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
5935 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
5936 "Failed to read MasterBootRecord for FAT/NTFS AutoMounting.");
5943 /* /// "CheckISO9660()" */
5944 void CheckISO9660(struct NepClassMS
*ncm
)
5946 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5948 struct IOStdReq
*stdIO
= &nh
->nh_IOReq
;
5950 blockbuf
= (UBYTE
*) psdAllocVec(ncm
->ncm_BlockSize
);
5955 stdIO
->io_Command
= TD_READ64
;
5956 stdIO
->io_Offset
= 0x8000;
5957 stdIO
->io_Actual
= 0;
5958 stdIO
->io_Length
= ncm
->ncm_BlockSize
;
5959 stdIO
->io_Data
= blockbuf
;
5960 if(!nIOCmdTunnel(ncm
, stdIO
))
5962 if((((ULONG
*) blockbuf
)[0] == AROS_LONG2BE(0x01434430)) && (((ULONG
*) blockbuf
)[1] == AROS_LONG2BE(0x30310100)))
5964 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Media is ISO9660.");
5968 KPRINTF(10, ("failed to read ISO sector\n"));
5969 if(ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
)
5971 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
5972 "Failed to read block 16 for CDFS AutoMounting.");
5975 psdFreeVec(blockbuf
);
5979 /* /// "AutoMountCD()" */
5980 void AutoMountCD(struct NepClassMS
*ncm
)
5982 struct NepMSBase
*nh
= ncm
->ncm_ClsBase
;
5983 struct DosEnvec
*envec
;
5985 nh
->nh_RDsk
.rdsk_PART
.pb_DevFlags
= 0;
5987 if(*(ncm
->ncm_CUC
->cuc_FATDOSName
))
5989 c2bstr(ncm
->ncm_CUC
->cuc_FATDOSName
, nh
->nh_RDsk
.rdsk_PART
.pb_DriveName
);
5991 c2bstr("UCD0", nh
->nh_RDsk
.rdsk_PART
.pb_DriveName
);
5994 envec
= (struct DosEnvec
*) nh
->nh_RDsk
.rdsk_PART
.pb_Environment
;
5995 memset(envec
, 0x00, sizeof(struct DosEnvec
));
5997 envec
->de_TableSize
= DE_BOOTBLOCKS
;
5998 envec
->de_SizeBlock
= ncm
->ncm_BlockSize
>>2;
5999 envec
->de_Surfaces
= 1;
6000 envec
->de_SectorPerBlock
= 1;
6001 envec
->de_Reserved
= 0xffffffff;
6002 envec
->de_NumBuffers
= ncm
->ncm_CUC
->cuc_FATBuffers
;
6003 envec
->de_BufMemType
= MEMF_PUBLIC
;
6004 envec
->de_MaxTransfer
= (1UL<<(ncm
->ncm_CDC
->cdc_MaxTransfer
+16))-1;
6005 envec
->de_Mask
= 0xffffffff;
6006 envec
->de_BootPri
= 0;
6007 envec
->de_Baud
= 1200;
6008 if(*ncm
->ncm_CDC
->cdc_CDControl
)
6010 UBYTE
*bptr
= ncm
->ncm_FATControlBSTR
;
6011 bptr
= (UBYTE
*) ((((IPTR
) bptr
) + 3) & (~3));
6012 c2bstr(ncm
->ncm_CDC
->cdc_CDControl
, bptr
);
6013 envec
->de_Control
= (IPTR
) MKBADDR(bptr
);
6015 envec
->de_Control
= 0;
6017 envec
->de_BootBlocks
= 0;
6019 // we have no FSHD and LSEG blocks
6020 nh
->nh_RDsk
.rdsk_RDB
.rdb_FileSysHeaderList
= NIL_PTR
;
6021 nh
->nh_RDsk
.rdsk_FSHD
.fhb_SegListBlocks
= 0;
6023 KPRINTF(5, ("building CDFS style environment\n"));
6025 envec
->de_BlocksPerTrack
= 1;
6026 envec
->de_Interleave
= 0;
6027 envec
->de_DosType
= ncm
->ncm_CDC
->cdc_CDDosType
;
6028 envec
->de_LowCyl
= 0;
6029 envec
->de_HighCyl
= 1;
6031 strncpy((char *) nh
->nh_RDsk
.rdsk_FSHD
.fhb_FileSysName
, ncm
->ncm_CDC
->cdc_CDFSName
, 84);
6032 CheckPartition(ncm
);
6036 /**************************************************************************/
6038 static const char *MaxTransferStrings
[] =
6049 static char *MainGUIPages
[] = { "Device Settings", "LUN Settings", NULL
};
6050 static char *MainGUIPagesDefault
[] = { "Device Defaults", "LUN Defaults", NULL
};
6052 /* /// "nGetDosType()" */
6053 ULONG
nGetDosType(STRPTR tmpstr
)
6058 while((ch
= *tmpstr
++))
6061 if((ch
>= '0') && (ch
<= '9'))
6063 dostype
+= ch
- '0';
6065 else if((ch
>= 'a') && (ch
<= 'f'))
6067 dostype
+= ch
- 'a' + 10;
6069 else if((ch
>= 'A') && (ch
<= 'F'))
6071 dostype
+= ch
- 'A' + 10;
6078 /* /// "nGUITask()" */
6079 AROS_UFH0(void, GM_UNIQUENAME(nGUITask
))
6083 struct Task
*thistask
;
6084 struct NepMSBase
*nh
;
6085 struct NepClassMS
*ncm
;
6086 struct NepClassMS
*cncm
;
6087 struct NepClassMS
*curncm
= NULL
;
6089 char dostypebuf
[10];
6090 char cddostypebuf
[10];
6091 char ntfsdostypebuf
[10];
6092 char bar
[] = "BAR,";
6094 thistask
= FindTask(NULL
);
6096 #define ps ncm->ncm_PsdBase
6097 #undef IntuitionBase
6098 #define IntuitionBase ncm->ncm_IntBase
6099 #undef MUIMasterBase
6100 #define MUIMasterBase ncm->ncm_MUIBase
6102 ncm
= thistask
->tc_UserData
;
6103 nh
= ncm
->ncm_ClsBase
;
6105 ++nh
->nh_Library
.lib_OpenCnt
;
6106 if(!(MUIMasterBase
= OpenLibrary(MUIMASTER_NAME
, MUIMASTER_VMIN
)))
6108 KPRINTF(10, ("Couldn't open muimaster.library.\n"));
6109 GM_UNIQUENAME(nGUITaskCleanup
)(ncm
);
6113 if(!(IntuitionBase
= OpenLibrary("intuition.library", 39)))
6115 KPRINTF(10, ("Couldn't open intuition.library.\n"));
6116 GM_UNIQUENAME(nGUITaskCleanup
)(ncm
);
6119 if(!(ps
= OpenLibrary("poseidon.library", 4)))
6121 KPRINTF(10, ("Couldn't open poseidon.library.\n"));
6122 GM_UNIQUENAME(nGUITaskCleanup
)(ncm
);
6126 ncm
->ncm_LUNListDisplayHook
.h_Data
= NULL
;
6127 ncm
->ncm_LUNListDisplayHook
.h_Entry
= (APTR
) GM_UNIQUENAME(LUNListDisplayHook
);
6129 psdSafeRawDoFmt(dostypebuf
, 10, "%08lx", ncm
->ncm_CDC
->cdc_FATDosType
);
6130 psdSafeRawDoFmt(ntfsdostypebuf
, 10, "%08lx", ncm
->ncm_CDC
->cdc_NTFSDosType
);
6131 psdSafeRawDoFmt(cddostypebuf
, 10, "%08lx", ncm
->ncm_CDC
->cdc_CDDosType
);
6133 ncm
->ncm_App
= (APTR
) ApplicationObject
,
6134 MUIA_Application_Title
, (IPTR
) GM_UNIQUENAME(libname
),
6135 MUIA_Application_Version
, (IPTR
) VERSION_STRING
,
6136 MUIA_Application_Copyright
, (IPTR
) "©2002-2009 Chris Hodges",
6137 MUIA_Application_Author
, (IPTR
) "Chris Hodges <chrisly@platon42.de>",
6138 MUIA_Application_Description
, (IPTR
) "Settings for the massstorage.class",
6139 MUIA_Application_Base
, (IPTR
) "MASSSTORAGE",
6140 MUIA_Application_HelpFile
, (IPTR
) "HELP:Poseidon.guide",
6141 MUIA_Application_Menustrip
, (IPTR
) MenustripObject
,
6142 Child
, (IPTR
) MenuObjectT((IPTR
) "Project"),
6143 Child
, (IPTR
) (ncm
->ncm_AboutMI
= (APTR
) MenuitemObject
,
6144 MUIA_Menuitem_Title
, (IPTR
) "About...",
6145 MUIA_Menuitem_Shortcut
, (IPTR
) "?",
6148 Child
, (IPTR
) MenuObjectT((IPTR
) "Settings"),
6149 Child
, (IPTR
) (ncm
->ncm_UseMI
= (APTR
) MenuitemObject
,
6150 MUIA_Menuitem_Title
, (IPTR
) "Save",
6151 MUIA_Menuitem_Shortcut
, (IPTR
) "S",
6153 Child
, (IPTR
) (ncm
->ncm_SetDefaultMI
= (APTR
) MenuitemObject
,
6154 MUIA_Menuitem_Title
, (IPTR
) "Save as Default",
6155 MUIA_Menuitem_Shortcut
, (IPTR
) "D",
6157 Child
, (IPTR
) MenuitemObject
,
6158 MUIA_Menuitem_Title
, (IPTR
) NM_BARLABEL
,
6160 Child
, (IPTR
) (ncm
->ncm_MUIPrefsMI
= (APTR
) MenuitemObject
,
6161 MUIA_Menuitem_Title
, (IPTR
) "MUI Settings",
6162 MUIA_Menuitem_Shortcut
, (IPTR
) "M",
6167 SubWindow
, (IPTR
) (ncm
->ncm_MainWindow
= (APTR
) WindowObject
,
6168 MUIA_Window_ID
, MAKE_ID('M','A','I','N'),
6169 MUIA_Window_Title
, (IPTR
) GM_UNIQUENAME(libname
),
6170 MUIA_HelpNode
, (IPTR
) GM_UNIQUENAME(libname
),
6172 WindowContents
, (IPTR
) VGroup
,
6173 Child
, (IPTR
) RegisterGroup(ncm
->ncm_Interface
? MainGUIPages
: MainGUIPagesDefault
),
6175 MUIA_Register_Frame
, TRUE
,
6176 Child
, (IPTR
) VGroup
,
6177 Child
, (IPTR
) VSpace(0),
6178 Child
, (IPTR
) ColGroup(2),
6179 Child
, (IPTR
) Label("NAK Timeout:"),
6180 Child
, (IPTR
) (ncm
->ncm_NakTimeoutObj
= (APTR
) SliderObject
, SliderFrame
,
6182 MUIA_Numeric_Min
, 0,
6183 MUIA_Numeric_Max
, 600,
6184 MUIA_Numeric_Value
, ncm
->ncm_CDC
->cdc_NakTimeout
,
6185 MUIA_Numeric_Format
, (IPTR
) "%ld00ms",
6187 Child
, (IPTR
) Label("Startup delay:"),
6188 Child
, (IPTR
) (ncm
->ncm_StartupDelayObj
= (APTR
) SliderObject
, SliderFrame
,
6190 MUIA_Numeric_Min
, 0,
6191 MUIA_Numeric_Max
, 100,
6192 MUIA_Numeric_Value
, ncm
->ncm_CDC
->cdc_StartupDelay
,
6193 MUIA_Numeric_Format
, (IPTR
) "%ld00ms",
6195 Child
, (IPTR
) Label("Single LUN:"),
6196 Child
, (IPTR
) HGroup
,
6197 Child
, (IPTR
) (ncm
->ncm_SingleLunObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6198 MUIA_Background
, MUII_ButtonBack
,
6200 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6201 MUIA_Image_Spec
, MUII_CheckMark
,
6202 MUIA_Image_FreeVert
, TRUE
,
6203 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_SINGLE_LUN
,
6204 MUIA_ShowSelState
, FALSE
,
6206 Child
, (IPTR
) HSpace(0),
6207 Child
, (IPTR
) Label("No Initial Reset:"),
6208 Child
, (IPTR
) (ncm
->ncm_InitialResetObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6209 MUIA_Background
, MUII_ButtonBack
,
6211 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6212 MUIA_Image_Spec
, MUII_CheckMark
,
6213 MUIA_Image_FreeVert
, TRUE
,
6214 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_RESET
,
6215 MUIA_ShowSelState
, FALSE
,
6218 Child
, (IPTR
) Label("Simple SCSI:"),
6219 Child
, (IPTR
) HGroup
,
6220 Child
, (IPTR
) (ncm
->ncm_SimpleSCSIObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6221 MUIA_Background
, MUII_ButtonBack
,
6223 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6224 MUIA_Image_Spec
, MUII_CheckMark
,
6225 MUIA_Image_FreeVert
, TRUE
,
6226 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_SIMPLE_SCSI
,
6227 MUIA_ShowSelState
, FALSE
,
6229 Child
, (IPTR
) HSpace(0),
6230 Child
, (IPTR
) Label("Translate CMD6->CMD10:"),
6231 Child
, (IPTR
) (ncm
->ncm_XLate610Obj
= (APTR
) ImageObject
, ImageButtonFrame
,
6232 MUIA_Background
, MUII_ButtonBack
,
6234 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6235 MUIA_Image_Spec
, MUII_CheckMark
,
6236 MUIA_Image_FreeVert
, TRUE
,
6237 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_MODE_XLATE
,
6238 MUIA_ShowSelState
, FALSE
,
6241 Child
, (IPTR
) Label("Fake Inquiry:"),
6242 Child
, (IPTR
) HGroup
,
6243 Child
, (IPTR
) (ncm
->ncm_FakeInquiryObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6244 MUIA_Background
, MUII_ButtonBack
,
6246 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6247 MUIA_Image_Spec
, MUII_CheckMark
,
6248 MUIA_Image_FreeVert
, TRUE
,
6249 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_FAKE_INQUIRY
,
6250 MUIA_ShowSelState
, FALSE
,
6252 Child
, (IPTR
) HSpace(0),
6253 Child
, (IPTR
) Label("Better Removable Support:"),
6254 Child
, (IPTR
) (ncm
->ncm_RemSupportObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6255 MUIA_Background
, MUII_ButtonBack
,
6257 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6258 MUIA_Image_Spec
, MUII_CheckMark
,
6259 MUIA_Image_FreeVert
, TRUE
,
6260 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_REM_SUPPORT
,
6261 MUIA_ShowSelState
, FALSE
,
6264 Child
, (IPTR
) Label("Trim Inquiry:"),
6265 Child
, (IPTR
) HGroup
,
6266 Child
, (IPTR
) (ncm
->ncm_FixInquiryObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6267 MUIA_Background
, MUII_ButtonBack
,
6269 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6270 MUIA_Image_Spec
, MUII_CheckMark
,
6271 MUIA_Image_FreeVert
, TRUE
,
6272 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_FIX_INQ36
,
6273 MUIA_ShowSelState
, FALSE
,
6275 Child
, (IPTR
) HSpace(0),
6276 Child
, (IPTR
) Label("Ignore broken CSS-ID:"),
6277 Child
, (IPTR
) (ncm
->ncm_CSSBrokenObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6278 MUIA_Background
, MUII_ButtonBack
,
6280 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6281 MUIA_Image_Spec
, MUII_CheckMark
,
6282 MUIA_Image_FreeVert
, TRUE
,
6283 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_CSS_BROKEN
,
6284 MUIA_ShowSelState
, FALSE
,
6287 Child
, (IPTR
) Label("Fix Capacity:"),
6288 Child
, (IPTR
) HGroup
,
6289 Child
, (IPTR
) (ncm
->ncm_FixCapacityObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6290 MUIA_Background
, MUII_ButtonBack
,
6292 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6293 MUIA_Image_Spec
, MUII_CheckMark
,
6294 MUIA_Image_FreeVert
, TRUE
,
6295 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_FIX_CAPACITY
,
6296 MUIA_ShowSelState
, FALSE
,
6298 Child
, (IPTR
) HSpace(0),
6299 Child
, (IPTR
) Label("Emulate on larger block sizes:"),
6300 Child
, (IPTR
) (ncm
->ncm_EmulLargeBlkObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6301 MUIA_Background
, MUII_ButtonBack
,
6303 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6304 MUIA_Image_Spec
, MUII_CheckMark
,
6305 MUIA_Image_FreeVert
, TRUE
,
6306 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_EMUL_LARGE_BLK
,
6307 MUIA_ShowSelState
, FALSE
,
6310 Child
, (IPTR
) Label("No Fallback:"),
6311 Child
, (IPTR
) HGroup
,
6312 Child
, (IPTR
) (ncm
->ncm_NoFallbackObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6313 MUIA_Background
, MUII_ButtonBack
,
6315 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6316 MUIA_Image_Spec
, MUII_CheckMark
,
6317 MUIA_Image_FreeVert
, TRUE
,
6318 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_NO_FALLBACK
,
6319 MUIA_ShowSelState
, FALSE
,
6321 Child
, (IPTR
) HSpace(0),
6322 Child
, (IPTR
) Label("Debug:"),
6323 Child
, (IPTR
) (ncm
->ncm_DebugObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6324 MUIA_Background
, MUII_ButtonBack
,
6326 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6327 MUIA_Image_Spec
, MUII_CheckMark
,
6328 MUIA_Image_FreeVert
, TRUE
,
6329 MUIA_Selected
, ncm
->ncm_CDC
->cdc_PatchFlags
& PFF_DEBUG
,
6330 MUIA_ShowSelState
, FALSE
,
6333 Child
, (IPTR
) Label("Max Transfer:"),
6334 Child
, (IPTR
) HGroup
,
6335 Child
, (IPTR
) (ncm
->ncm_MaxTransferObj
= (APTR
) CycleObject
,
6336 MUIA_Cycle_Entries
, (IPTR
) MaxTransferStrings
,
6337 MUIA_Cycle_Active
, ncm
->ncm_CDC
->cdc_MaxTransfer
,
6340 Child
, (IPTR
) (ncm
->ncm_AutoDtxMaxTransObj
= (APTR
) TextObject
, ButtonFrame
,
6341 MUIA_Disabled
, !ncm
->ncm_Interface
,
6342 MUIA_Background
, MUII_ButtonBack
,
6344 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
6345 MUIA_Text_Contents
, (IPTR
) "\33c Auto-detect ",
6349 Child
, (IPTR
) VSpace(0),
6351 Child
, (IPTR
) ColGroup(6),
6352 Child
, (IPTR
) Label("FAT:"),
6353 Child
, (IPTR
) PopaslObject
,
6354 MUIA_Popstring_String
, (IPTR
) (ncm
->ncm_FatFSObj
= (APTR
) StringObject
,
6357 MUIA_String_AdvanceOnCR
, TRUE
,
6358 MUIA_String_Contents
, (IPTR
) ncm
->ncm_CDC
->cdc_FATFSName
,
6359 MUIA_String_MaxLen
, 63,
6361 MUIA_Popstring_Button
, (IPTR
) PopButton(MUII_PopFile
),
6362 ASLFR_TitleText
, (IPTR
) "Select filesystem to use with FAT partitions...",
6364 Child
, (IPTR
) Label("DosType:"),
6365 Child
, (IPTR
) (ncm
->ncm_FatDosTypeObj
= (APTR
) StringObject
,
6367 MUIA_HorizWeight
, 50,
6369 MUIA_String_AdvanceOnCR
, TRUE
,
6370 MUIA_String_Contents
, (IPTR
) dostypebuf
,
6371 MUIA_String_Accept
, (IPTR
) "0123456789abcdefABCDEF",
6372 MUIA_String_MaxLen
, 9,
6374 Child
, (IPTR
) Label("Ctrl:"),
6375 Child
, (IPTR
) (ncm
->ncm_FatControlObj
= (APTR
) StringObject
,
6377 MUIA_HorizWeight
, 50,
6379 MUIA_String_AdvanceOnCR
, TRUE
,
6380 MUIA_String_Contents
, (IPTR
) ncm
->ncm_CDC
->cdc_FATControl
,
6381 MUIA_String_MaxLen
, 63,
6383 Child
, (IPTR
) Label("NTFS:"),
6384 Child
, (IPTR
) PopaslObject
,
6385 MUIA_Popstring_String
, (IPTR
) (ncm
->ncm_NTFSObj
= (APTR
) StringObject
,
6388 MUIA_String_AdvanceOnCR
, TRUE
,
6389 MUIA_String_Contents
, (IPTR
) ncm
->ncm_CDC
->cdc_NTFSName
,
6390 MUIA_String_MaxLen
, 63,
6392 MUIA_Popstring_Button
, (IPTR
) PopButton(MUII_PopFile
),
6393 ASLFR_TitleText
, (IPTR
) "Select filesystem to use with NTFS partitions...",
6395 Child
, (IPTR
) Label("DosType:"),
6396 Child
, (IPTR
) (ncm
->ncm_NTFSDosTypeObj
= (APTR
) StringObject
,
6398 MUIA_HorizWeight
, 50,
6400 MUIA_String_AdvanceOnCR
, TRUE
,
6401 MUIA_String_Contents
, (IPTR
) ntfsdostypebuf
,
6402 MUIA_String_Accept
, (IPTR
) "0123456789abcdefABCDEF",
6403 MUIA_String_MaxLen
, 9,
6405 Child
, (IPTR
) Label("Ctrl:"),
6406 Child
, (IPTR
) (ncm
->ncm_NTFSControlObj
= (APTR
) StringObject
,
6408 MUIA_HorizWeight
, 50,
6410 MUIA_String_AdvanceOnCR
, TRUE
,
6411 MUIA_String_Contents
, (IPTR
) ncm
->ncm_CDC
->cdc_NTFSControl
,
6412 MUIA_String_MaxLen
, 63,
6414 Child
, (IPTR
) Label("CD/DVD:"),
6415 Child
, (IPTR
) PopaslObject
,
6416 MUIA_Popstring_String
, (IPTR
) (ncm
->ncm_CDFSObj
= (APTR
) StringObject
,
6419 MUIA_String_AdvanceOnCR
, TRUE
,
6420 MUIA_String_Contents
, (IPTR
) ncm
->ncm_CDC
->cdc_CDFSName
,
6421 MUIA_String_MaxLen
, 63,
6423 MUIA_Popstring_Button
, (IPTR
) PopButton(MUII_PopFile
),
6424 ASLFR_TitleText
, (IPTR
) "Select filesystem to use with CD/DVD partitions...",
6426 Child
, (IPTR
) Label("DosType:"),
6427 Child
, (IPTR
) (ncm
->ncm_CDDosTypeObj
= (APTR
) StringObject
,
6429 MUIA_HorizWeight
, 50,
6431 MUIA_String_AdvanceOnCR
, TRUE
,
6432 MUIA_String_Contents
, (IPTR
) cddostypebuf
,
6433 MUIA_String_Accept
, (IPTR
) "0123456789abcdefABCDEF",
6434 MUIA_String_MaxLen
, 9,
6436 Child
, (IPTR
) Label("Ctrl:"),
6437 Child
, (IPTR
) (ncm
->ncm_CDControlObj
= (APTR
) StringObject
,
6439 MUIA_HorizWeight
, 50,
6441 MUIA_String_AdvanceOnCR
, TRUE
,
6442 MUIA_String_Contents
, (IPTR
) ncm
->ncm_CDC
->cdc_CDControl
,
6443 MUIA_String_MaxLen
, 63,
6446 Child
, (IPTR
) VSpace(0),
6448 Child
, (IPTR
) VGroup
,
6449 Child
, (IPTR
) ListviewObject
,
6451 MUIA_Listview_List
, (IPTR
) (ncm
->ncm_LunLVObj
= (APTR
) ListObject
,
6453 MUIA_List_Format
, (IPTR
) bar
,
6454 MUIA_List_Title
, TRUE
,
6455 MUIA_List_DisplayHook
, (IPTR
) &ncm
->ncm_LUNListDisplayHook
,
6458 Child
, (IPTR
) (ncm
->ncm_LunGroupObj
= (APTR
) VGroup
,
6459 MUIA_Disabled
, TRUE
,
6460 Child
, (IPTR
) VSpace(0),
6461 Child
, (IPTR
) HGroup
,
6462 Child
, (IPTR
) (ncm
->ncm_AutoMountRDBObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6463 MUIA_Background
, MUII_ButtonBack
,
6465 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6466 MUIA_Image_Spec
, MUII_CheckMark
,
6467 MUIA_Image_FreeVert
, TRUE
,
6468 MUIA_Selected
, TRUE
,
6469 MUIA_ShowSelState
, FALSE
,
6471 Child
, (IPTR
) Label("AutoMount RDB partitions"),
6472 Child
, (IPTR
) HSpace(0),
6474 Child
, (IPTR
) HGroup
,
6475 Child
, (IPTR
) (ncm
->ncm_BootRDBObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6476 MUIA_Background
, MUII_ButtonBack
,
6478 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6479 MUIA_Image_Spec
, MUII_CheckMark
,
6480 MUIA_Image_FreeVert
, TRUE
,
6481 MUIA_Selected
, FALSE
,
6482 MUIA_ShowSelState
, FALSE
,
6484 Child
, (IPTR
) Label("Boot from RDB partitions"),
6485 Child
, (IPTR
) HSpace(0),
6487 Child
, (IPTR
) VSpace(0),
6488 Child
, (IPTR
) HGroup
,
6489 Child
, (IPTR
) (ncm
->ncm_AutoMountFATObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6490 MUIA_Background
, MUII_ButtonBack
,
6492 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6493 MUIA_Image_Spec
, MUII_CheckMark
,
6494 MUIA_Image_FreeVert
, TRUE
,
6495 MUIA_Selected
, TRUE
,
6496 MUIA_ShowSelState
, FALSE
,
6498 Child
, (IPTR
) Label("AutoMount FAT/NTFS partitions"),
6499 Child
, (IPTR
) HSpace(0),
6501 Child
, (IPTR
) HGroup
,
6502 Child
, (IPTR
) (ncm
->ncm_MountAllFATObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6503 MUIA_Background
, MUII_ButtonBack
,
6505 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6506 MUIA_Image_Spec
, MUII_CheckMark
,
6507 MUIA_Image_FreeVert
, TRUE
,
6508 MUIA_Selected
, TRUE
,
6509 MUIA_ShowSelState
, FALSE
,
6511 Child
, (IPTR
) Label("Mount all FAT partitions"),
6512 Child
, (IPTR
) HSpace(0),
6514 Child
, (IPTR
) VSpace(0),
6515 Child
, (IPTR
) HGroup
,
6516 Child
, (IPTR
) (ncm
->ncm_AutoMountCDObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6517 MUIA_Background
, MUII_ButtonBack
,
6519 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6520 MUIA_Image_Spec
, MUII_CheckMark
,
6521 MUIA_Image_FreeVert
, TRUE
,
6522 MUIA_Selected
, TRUE
,
6523 MUIA_ShowSelState
, FALSE
,
6525 Child
, (IPTR
) Label("AutoMount CD/DVD"),
6526 Child
, (IPTR
) HSpace(0),
6528 Child
, (IPTR
) VSpace(0),
6529 Child
, (IPTR
) HGroup
,
6530 Child
, (IPTR
) (ncm
->ncm_UnmountObj
= (APTR
) ImageObject
, ImageButtonFrame
,
6531 MUIA_Background
, MUII_ButtonBack
,
6533 MUIA_InputMode
, MUIV_InputMode_Toggle
,
6534 MUIA_Image_Spec
, MUII_CheckMark
,
6535 MUIA_Image_FreeVert
, TRUE
,
6536 MUIA_Selected
, FALSE
,
6537 MUIA_ShowSelState
, FALSE
,
6539 Child
, (IPTR
) HGroup
,
6540 Child
, (IPTR
) Label("Unmount partitions after removal"),
6541 Child
, (IPTR
) HSpace(0),
6544 Child
, (IPTR
) VSpace(0),
6545 Child
, (IPTR
) HGroup
,
6546 Child
, (IPTR
) Label("DOSName:"),
6547 Child
, (IPTR
) (ncm
->ncm_FatDOSNameObj
= (APTR
) StringObject
,
6550 MUIA_String_AdvanceOnCR
, TRUE
,
6551 MUIA_String_Contents
, (IPTR
) "UMSD",
6552 MUIA_String_Reject
, (IPTR
) "/ :?#*",
6553 MUIA_String_MaxLen
, 31,
6555 Child
, (IPTR
) Label("Buffers:"),
6556 Child
, (IPTR
) (ncm
->ncm_FatBuffersObj
= (APTR
) StringObject
,
6559 MUIA_String_AdvanceOnCR
, TRUE
,
6560 MUIA_String_Integer
, 100,
6561 MUIA_String_Accept
, (IPTR
) "0123456789",
6564 Child
, (IPTR
) VSpace(0),
6565 Child
, (IPTR
) HGroup
,
6566 Child
, (IPTR
) Label("Default " DEVNAME
" unit:"),
6567 Child
, (IPTR
) (ncm
->ncm_UnitObj
= (APTR
) StringObject
,
6570 MUIA_String_AdvanceOnCR
, TRUE
,
6571 MUIA_String_Integer
, 0,
6572 MUIA_String_Accept
, (IPTR
) "0123456789",
6578 Child
, (IPTR
) HGroup
,
6579 MUIA_Group_SameWidth
, TRUE
,
6580 Child
, (IPTR
) (ncm
->ncm_UseObj
= (APTR
) TextObject
, ButtonFrame
,
6581 MUIA_ShowMe
, (IPTR
) ncm
->ncm_Interface
,
6582 MUIA_Background
, MUII_ButtonBack
,
6584 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
6585 MUIA_Text_Contents
, (IPTR
) "\33c Save ",
6587 Child
, (IPTR
) (ncm
->ncm_SetDefaultObj
= (APTR
) TextObject
, ButtonFrame
,
6588 MUIA_Background
, MUII_ButtonBack
,
6590 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
6591 MUIA_Text_Contents
, ncm
->ncm_Interface
? (IPTR
) "\33c Save as Default " : (IPTR
) "\33c Save Defaults ",
6593 Child
, (IPTR
) (ncm
->ncm_CloseObj
= (APTR
) TextObject
, ButtonFrame
,
6594 MUIA_Background
, MUII_ButtonBack
,
6596 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
6597 MUIA_Text_Contents
, (IPTR
) "\33c Use ",
6606 KPRINTF(10, ("Couldn't create application\n"));
6607 GM_UNIQUENAME(nGUITaskCleanup
)(ncm
);
6611 if(ncm
->ncm_Interface
)
6614 while(((struct Node
*) cncm
)->ln_Succ
)
6616 if(cncm
->ncm_UnitLUN0
!= ncm
)
6620 DoMethod(ncm
->ncm_LunLVObj
, MUIM_List_InsertSingle
, cncm
, MUIV_List_Insert_Bottom
);
6621 cncm
= (struct NepClassMS
*) ((struct Node
*) cncm
)->ln_Succ
;
6624 DoMethod(ncm
->ncm_LunLVObj
, MUIM_List_InsertSingle
, ncm
, MUIV_List_Insert_Bottom
);
6626 DoMethod(ncm
->ncm_MainWindow
, MUIM_Notify
, MUIA_Window_CloseRequest
, TRUE
,
6627 ncm
->ncm_App
, 2, MUIM_Application_ReturnID
, MUIV_Application_ReturnID_Quit
);
6628 DoMethod(ncm
->ncm_UseObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
6629 ncm
->ncm_App
, 2, MUIM_Application_ReturnID
, ID_STORE_CONFIG
);
6630 DoMethod(ncm
->ncm_SetDefaultObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
6631 ncm
->ncm_App
, 2, MUIM_Application_ReturnID
, ID_DEF_CONFIG
);
6632 DoMethod(ncm
->ncm_CloseObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
6633 ncm
->ncm_App
, 2, MUIM_Application_ReturnID
, MUIV_Application_ReturnID_Quit
);
6635 DoMethod(ncm
->ncm_AutoDtxMaxTransObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
6636 ncm
->ncm_App
, 2, MUIM_Application_ReturnID
, ID_AUTODTXMAXTX
);
6637 DoMethod(ncm
->ncm_LunLVObj
, MUIM_Notify
, MUIA_List_Active
, MUIV_EveryTime
,
6638 ncm
->ncm_App
, 2, MUIM_Application_ReturnID
, ID_SELECT_LUN
);
6640 DoMethod(ncm
->ncm_AboutMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
6641 ncm
->ncm_App
, 2, MUIM_Application_ReturnID
, ID_ABOUT
);
6642 DoMethod(ncm
->ncm_UseMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
6643 ncm
->ncm_App
, 2, MUIM_Application_ReturnID
, ID_STORE_CONFIG
);
6644 DoMethod(ncm
->ncm_SetDefaultMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
6645 ncm
->ncm_App
, 2, MUIM_Application_ReturnID
, ID_DEF_CONFIG
);
6646 DoMethod(ncm
->ncm_MUIPrefsMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
6647 ncm
->ncm_App
, 2, MUIM_Application_OpenConfigWindow
, 0);
6649 set(ncm
->ncm_LunLVObj
, MUIA_List_Active
, MUIV_List_Active_Top
);
6657 get(ncm
->ncm_App
, MUIA_Application_Iconified
, &iconify
);
6658 set(ncm
->ncm_MainWindow
, MUIA_Window_Open
, TRUE
);
6659 get(ncm
->ncm_MainWindow
, MUIA_Window_Open
, &isopen
);
6660 if(!(isopen
|| iconify
))
6662 GM_UNIQUENAME(nGUITaskCleanup
)(ncm
);
6668 retid
= DoMethod(ncm
->ncm_App
, MUIM_Application_NewInput
, &sigs
);
6672 case ID_STORE_CONFIG
:
6673 case MUIV_Application_ReturnID_Quit
:
6679 get(ncm
->ncm_NakTimeoutObj
, MUIA_Numeric_Value
, &ncm
->ncm_CDC
->cdc_NakTimeout
);
6680 get(ncm
->ncm_StartupDelayObj
, MUIA_Numeric_Value
, &ncm
->ncm_CDC
->cdc_StartupDelay
);
6681 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
);
6683 get(ncm
->ncm_SingleLunObj
, MUIA_Selected
, &tmpflags
);
6684 if(tmpflags
) patchflags
|= PFF_SINGLE_LUN
;
6686 get(ncm
->ncm_FakeInquiryObj
, MUIA_Selected
, &tmpflags
);
6687 if(tmpflags
) patchflags
|= PFF_FAKE_INQUIRY
;
6689 get(ncm
->ncm_SimpleSCSIObj
, MUIA_Selected
, &tmpflags
);
6690 if(tmpflags
) patchflags
|= PFF_SIMPLE_SCSI
;
6692 get(ncm
->ncm_InitialResetObj
, MUIA_Selected
, &tmpflags
);
6693 if(tmpflags
) patchflags
|= PFF_NO_RESET
;
6695 get(ncm
->ncm_XLate610Obj
, MUIA_Selected
, &tmpflags
);
6696 if(tmpflags
) patchflags
|= PFF_MODE_XLATE
;
6698 get(ncm
->ncm_RemSupportObj
, MUIA_Selected
, &tmpflags
);
6699 if(tmpflags
) patchflags
|= PFF_REM_SUPPORT
;
6701 get(ncm
->ncm_FixInquiryObj
, MUIA_Selected
, &tmpflags
);
6702 if(tmpflags
) patchflags
|= PFF_FIX_INQ36
;
6704 get(ncm
->ncm_CSSBrokenObj
, MUIA_Selected
, &tmpflags
);
6705 if(tmpflags
) patchflags
|= PFF_CSS_BROKEN
;
6707 get(ncm
->ncm_FixCapacityObj
, MUIA_Selected
, &tmpflags
);
6708 if(tmpflags
) patchflags
|= PFF_FIX_CAPACITY
;
6710 get(ncm
->ncm_EmulLargeBlkObj
, MUIA_Selected
, &tmpflags
);
6711 if(tmpflags
) patchflags
|= PFF_EMUL_LARGE_BLK
;
6713 get(ncm
->ncm_NoFallbackObj
, MUIA_Selected
, &tmpflags
);
6714 if(tmpflags
) patchflags
|= PFF_NO_FALLBACK
;
6716 get(ncm
->ncm_DebugObj
, MUIA_Selected
, &tmpflags
);
6717 if(tmpflags
) patchflags
|= PFF_DEBUG
;
6718 ncm
->ncm_CDC
->cdc_PatchFlags
= patchflags
;
6720 get(ncm
->ncm_MaxTransferObj
, MUIA_Cycle_Active
, &ncm
->ncm_CDC
->cdc_MaxTransfer
);
6723 get(ncm
->ncm_FatFSObj
, MUIA_String_Contents
, &tmpstr
);
6724 strncpy(ncm
->ncm_CDC
->cdc_FATFSName
, tmpstr
, 63);
6726 get(ncm
->ncm_FatControlObj
, MUIA_String_Contents
, &tmpstr
);
6727 strncpy(ncm
->ncm_CDC
->cdc_FATControl
, tmpstr
, 63);
6729 get(ncm
->ncm_FatDosTypeObj
, MUIA_String_Contents
, &tmpstr
);
6730 ncm
->ncm_CDC
->cdc_FATDosType
= nGetDosType(tmpstr
);
6733 get(ncm
->ncm_NTFSObj
, MUIA_String_Contents
, &tmpstr
);
6734 strncpy(ncm
->ncm_CDC
->cdc_NTFSName
, tmpstr
, 63);
6736 get(ncm
->ncm_NTFSControlObj
, MUIA_String_Contents
, &tmpstr
);
6737 strncpy(ncm
->ncm_CDC
->cdc_NTFSControl
, tmpstr
, 63);
6739 get(ncm
->ncm_NTFSDosTypeObj
, MUIA_String_Contents
, &tmpstr
);
6740 ncm
->ncm_CDC
->cdc_NTFSDosType
= nGetDosType(tmpstr
);
6743 get(ncm
->ncm_CDFSObj
, MUIA_String_Contents
, &tmpstr
);
6744 strncpy(ncm
->ncm_CDC
->cdc_CDFSName
, tmpstr
, 63);
6746 get(ncm
->ncm_CDControlObj
, MUIA_String_Contents
, &tmpstr
);
6747 strncpy(ncm
->ncm_CDC
->cdc_CDControl
, tmpstr
, 63);
6749 get(ncm
->ncm_CDDosTypeObj
, MUIA_String_Contents
, &tmpstr
);
6750 ncm
->ncm_CDC
->cdc_CDDosType
= nGetDosType(tmpstr
);
6752 if(ncm
->ncm_Interface
)
6754 /* copy device config to all luns */
6755 cncm
= (struct NepClassMS
*) ((struct Node
*) ncm
)->ln_Succ
;
6756 while(((struct Node
*) cncm
)->ln_Succ
)
6758 if(cncm
->ncm_UnitLUN0
!= ncm
)
6762 *(cncm
->ncm_CDC
) = *(ncm
->ncm_CDC
);
6763 cncm
= (struct NepClassMS
*) ((struct Node
*) cncm
)->ln_Succ
;
6768 get(ncm
->ncm_AutoMountFATObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_AutoMountFAT
);
6769 get(ncm
->ncm_MountAllFATObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_MountAllFAT
);
6770 get(ncm
->ncm_AutoMountCDObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_AutoMountCD
);
6772 get(ncm
->ncm_FatDOSNameObj
, MUIA_String_Contents
, &tmpstr
);
6773 strncpy(curncm
->ncm_CUC
->cuc_FATDOSName
, tmpstr
, 31);
6774 get(ncm
->ncm_FatBuffersObj
, MUIA_String_Integer
, &curncm
->ncm_CUC
->cuc_FATBuffers
);
6775 get(ncm
->ncm_AutoMountRDBObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_AutoMountRDB
);
6776 get(ncm
->ncm_BootRDBObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_BootRDB
);
6777 get(ncm
->ncm_UnitObj
, MUIA_String_Integer
, &curncm
->ncm_CUC
->cuc_DefaultUnit
);
6778 get(ncm
->ncm_UnmountObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_AutoUnmount
);
6781 if(retid
== ID_DEF_CONFIG
)
6783 pic
= psdGetClsCfg(GM_UNIQUENAME(libname
));
6786 psdSetClsCfg(GM_UNIQUENAME(libname
), NULL
);
6787 pic
= psdGetClsCfg(GM_UNIQUENAME(libname
));
6791 psdAddCfgEntry(pic
, ncm
->ncm_CDC
);
6792 psdAddCfgEntry(pic
, ncm
->ncm_CUC
);
6793 psdSaveCfgToDisk(NULL
, FALSE
);
6796 if(GM_UNIQUENAME(nStoreConfig
)(ncm
))
6798 if(retid
!= MUIV_Application_ReturnID_Quit
)
6800 psdSaveCfgToDisk(NULL
, FALSE
);
6802 retid
= MUIV_Application_ReturnID_Quit
;
6810 DoMethod(ncm
->ncm_LunLVObj
, MUIM_List_GetEntry
, MUIV_List_GetEntry_Active
, &cncm
);
6815 get(ncm
->ncm_AutoMountFATObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_AutoMountFAT
);
6816 get(ncm
->ncm_MountAllFATObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_MountAllFAT
);
6817 get(ncm
->ncm_AutoMountCDObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_AutoMountCD
);
6819 get(ncm
->ncm_FatDOSNameObj
, MUIA_String_Contents
, &tmpstr
);
6820 strncpy(curncm
->ncm_CUC
->cuc_FATDOSName
, tmpstr
, 31);
6821 get(ncm
->ncm_FatBuffersObj
, MUIA_String_Integer
, &curncm
->ncm_CUC
->cuc_FATBuffers
);
6822 get(ncm
->ncm_AutoMountRDBObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_AutoMountRDB
);
6823 get(ncm
->ncm_BootRDBObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_BootRDB
);
6824 get(ncm
->ncm_UnitObj
, MUIA_String_Integer
, &curncm
->ncm_CUC
->cuc_DefaultUnit
);
6825 get(ncm
->ncm_UnmountObj
, MUIA_Selected
, &curncm
->ncm_CUC
->cuc_AutoUnmount
);
6830 set(ncm
->ncm_AutoMountFATObj
, MUIA_Selected
, curncm
->ncm_CUC
->cuc_AutoMountFAT
);
6831 set(ncm
->ncm_MountAllFATObj
, MUIA_Selected
, curncm
->ncm_CUC
->cuc_MountAllFAT
);
6832 set(ncm
->ncm_AutoMountCDObj
, MUIA_Selected
, curncm
->ncm_CUC
->cuc_AutoMountCD
);
6833 set(ncm
->ncm_FatDOSNameObj
, MUIA_String_Contents
, curncm
->ncm_CUC
->cuc_FATDOSName
);
6834 set(ncm
->ncm_FatBuffersObj
, MUIA_String_Integer
, curncm
->ncm_CUC
->cuc_FATBuffers
);
6835 set(ncm
->ncm_AutoMountRDBObj
, MUIA_Selected
, curncm
->ncm_CUC
->cuc_AutoMountRDB
);
6836 set(ncm
->ncm_BootRDBObj
, MUIA_Selected
, curncm
->ncm_CUC
->cuc_BootRDB
);
6837 set(ncm
->ncm_UnitObj
, MUIA_String_Integer
, curncm
->ncm_CUC
->cuc_DefaultUnit
);
6838 set(ncm
->ncm_UnmountObj
, MUIA_Selected
, curncm
->ncm_CUC
->cuc_AutoUnmount
);
6839 set(ncm
->ncm_LunGroupObj
, MUIA_Disabled
, FALSE
);
6841 set(ncm
->ncm_LunGroupObj
, MUIA_Disabled
, TRUE
);
6845 case ID_AUTODTXMAXTX
:
6847 DoMethod(ncm
->ncm_LunLVObj
, MUIM_List_GetEntry
, MUIV_List_GetEntry_Active
, &cncm
);
6848 set(ncm
->ncm_App
, MUIA_Application_Sleep
, TRUE
);
6849 AutoDetectMaxTransfer(cncm
);
6850 set(ncm
->ncm_App
, MUIA_Application_Sleep
, FALSE
);
6851 set(ncm
->ncm_MaxTransferObj
, MUIA_Cycle_Active
, ncm
->ncm_CDC
->cdc_MaxTransfer
);
6856 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
);
6859 if(retid
== MUIV_Application_ReturnID_Quit
)
6865 sigs
= Wait(sigs
| sigmask
| SIGBREAKF_CTRL_C
);
6866 if(sigs
& SIGBREAKF_CTRL_C
)
6872 set(ncm
->ncm_MainWindow
, MUIA_Window_Open
, FALSE
);
6874 GM_UNIQUENAME(nGUITaskCleanup
)(ncm
);
6880 /* /// "AutoDetectMaxTransfer()" */
6881 void AutoDetectMaxTransfer(struct NepClassMS
*cncm
)
6889 struct IOStdReq
*ioreq
;
6890 struct NepClassMS
*ncm
= cncm
->ncm_UnitLUN0
;
6892 ULONG memsize
= 4<<20;
6899 res
= MUI_RequestA(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, "Continue|Cancel",
6900 "Auto-detection of the maximum transfer rate\n"
6901 "will need some media inserted in the selected\n"
6902 "LUN of the drive. Moreover, the contents of the\n"
6903 "media may not be empty.\n"
6904 "The test will need about 4 MB of temporary memory!\n"
6905 "No data is written to the disk!", NULL
);
6910 if(!cncm
->ncm_UnitReady
)
6912 MUI_RequestA(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, "Argh!", "No disk/media in drive!", NULL
);
6915 memory
= (UBYTE
*) AllocVec(memsize
, MEMF_CLEAR
);
6918 MUI_RequestA(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, "Argh!", "Sorry, out of memory!", NULL
);
6921 mp
= CreateMsgPort();
6924 ioreq
= (struct IOStdReq
*) CreateIORequest(mp
, sizeof(struct IOStdReq
));
6927 if(!OpenDevice(DEVNAME
, cncm
->ncm_UnitNo
, (struct IORequest
*) ioreq
, 0))
6929 ncm
->ncm_CDC
->cdc_MaxTransfer
= 0;
6930 if(!cncm
->ncm_BlockSize
)
6932 ioreq
->io_Command
= TD_GETGEOMETRY
;
6933 ioreq
->io_Data
= &cncm
->ncm_Geometry
;
6934 ioreq
->io_Length
= sizeof(cncm
->ncm_Geometry
);
6935 DoIO((struct IORequest
*) ioreq
);
6938 numblocks
= (memsize
>>1) / cncm
->ncm_BlockSize
;
6940 cmpbuffer
= &memory
[memsize
>>1];
6944 for(block
= 0; block
< numblocks
; block
++)
6946 ioreq
->io_Command
= TD_READ64
;
6947 ioreq
->io_Actual
= 0;
6948 ioreq
->io_Offset
= block
*cncm
->ncm_BlockSize
;
6949 ioreq
->io_Length
= cncm
->ncm_BlockSize
;
6950 ioreq
->io_Data
= &orgbuffer
[ioreq
->io_Offset
];
6951 ioerr
= DoIO((struct IORequest
*) ioreq
);
6954 MUI_Request(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, ">:-{", "Error %ld while reading block %ld!\nAborting process...", ioerr
, block
);
6963 maxtrans
= (1UL<<(ncm
->ncm_CDC
->cdc_MaxTransfer
+16));
6964 // do a quick check on block contents
6965 numblocks
= (memsize
>>1) / maxtrans
;
6968 for(block
= 0; block
< numblocks
-1; block
++)
6970 if(!memcmp(&orgbuffer
[block
* maxtrans
], &orgbuffer
[(block
+ 1) * maxtrans
], (size_t) maxtrans
))
6972 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
);
6983 // fill compare buffer with garbage
6985 lbufptr
= (ULONG
*) cmpbuffer
;
6988 *lbufptr
= (IPTR
) lbufptr
;
6993 // start reading the chunks
6994 numblocks
= (memsize
>>1) / maxtrans
;
6995 for(block
= 0; block
< numblocks
; block
++)
6997 ioreq
->io_Command
= TD_READ64
;
6998 ioreq
->io_Actual
= 0;
6999 ioreq
->io_Offset
= block
*maxtrans
;
7000 ioreq
->io_Length
= maxtrans
;
7001 ioreq
->io_Data
= &cmpbuffer
[ioreq
->io_Offset
];
7002 ioerr
= DoIO((struct IORequest
*) ioreq
);
7005 MUI_Request(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, ">:-{", "Error %ld while reading at offset %ld!\nAborting process...", ioerr
, &ioreq
->io_Offset
);
7009 if(memcmp(&orgbuffer
[ioreq
->io_Offset
], &cmpbuffer
[ioreq
->io_Offset
], (size_t) maxtrans
))
7011 MUI_Request(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, "Hmpf!", "Reading failed at MaxTrans = %08lx", maxtrans
-1);
7012 if(ncm
->ncm_CDC
->cdc_MaxTransfer
)
7014 ncm
->ncm_CDC
->cdc_MaxTransfer
--;
7021 //MUI_Request(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Wow!", "Test with %ld (%ld) succeeded!", maxtrans, numblocks);
7022 if(ncm
->ncm_CDC
->cdc_MaxTransfer
< 5)
7024 ncm
->ncm_CDC
->cdc_MaxTransfer
++;
7031 MUI_RequestA(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, "Wow!", "Test succeeded, setting MaxTrans to maximum value!", NULL
);
7034 CloseDevice((struct IORequest
*) ioreq
);
7036 MUI_RequestA(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, "Argh!", "Couldn't open device!", NULL
);
7038 DeleteIORequest((struct IORequest
*) ioreq
);
7040 MUI_RequestA(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, "Argh!", "No IOReq!", NULL
);
7044 MUI_RequestA(ncm
->ncm_App
, ncm
->ncm_MainWindow
, 0, NULL
, "Argh!", "No MsgPort!", NULL
);
7050 /* /// "nGUITaskCleanup()" */
7051 void GM_UNIQUENAME(nGUITaskCleanup
)(struct NepClassMS
*ncm
)
7055 MUI_DisposeObject(ncm
->ncm_App
);
7056 ncm
->ncm_App
= NULL
;
7060 CloseLibrary(MUIMasterBase
);
7061 MUIMasterBase
= NULL
;
7065 CloseLibrary(IntuitionBase
);
7066 IntuitionBase
= NULL
;
7074 ncm
->ncm_GUIBinding
= NULL
;
7075 ncm
->ncm_GUITask
= NULL
;
7076 --ncm
->ncm_ClsBase
->nh_Library
.lib_OpenCnt
;
7080 /* /// "LUNListDisplayHook()" */
7081 AROS_UFH3(LONG
, GM_UNIQUENAME(LUNListDisplayHook
),
7082 AROS_UFHA(struct Hook
*, hook
, A0
),
7083 AROS_UFHA(char **, strarr
, A2
),
7084 AROS_UFHA(struct NepClassMS
*, ncm
, A1
))
7088 //struct NepMSBase *nh = ncm->ncm_ClsBase;
7091 *strarr
++ = ncm
->ncm_LUNNumStr
;
7092 *strarr
= ncm
->ncm_LUNIDStr
;
7094 *strarr
++ = "\33l\33uLUN";
7095 *strarr
= "\33l\33uID";