revert commit 56204.
[AROS.git] / rom / usb / classes / massstorage / massstorage.class.c
blob033c2de06f38a097ac0d3573908cc2d855b70f3c
1 /*
2 *----------------------------------------------------------------------------
3 * massstorage class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
6 */
8 #include "debug.h"
10 #include "massstorage.class.h"
12 #define DEF_NAKTIMEOUT (100)
14 /* /// "Lib Stuff" */
15 static const STRPTR GM_UNIQUENAME(libname) = MOD_NAME_STRING;
17 static
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),
26 (APTR) -1,
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);
40 if(UtilityBase)
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);
54 if(cdc && cuc)
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;
62 Forbid();
63 AddDevice((struct Device *) nh->nh_DevBase);
64 nh->nh_DevBase->np_Library.lib_OpenCnt++;
65 Permit();
66 ret = nh;
67 } else {
68 KPRINTF(20, ("failed to create usbscsi.device\n"));
71 } else {
72 KPRINTF(20, ("libInit: OpenLibrary(\"utility.library\", 39) failed!\n"));
74 if(!ret)
76 FreeVec(cdc);
77 FreeVec(cuc);
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);
89 return(TRUE);
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);
97 Forbid();
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);
104 Permit();
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));
113 return(TRUE);
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",
125 UtilityBase));
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);
136 FreeVec(ncm);
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"));
147 } else {
148 KPRINTF(5, ("libExpunge: Could not expunge, LIBF_DELEXP set!\n"));
149 return(FALSE);
152 return(TRUE);
155 ADD2INITLIB(GM_UNIQUENAME(libInit), 0)
156 ADD2OPENLIB(GM_UNIQUENAME(libOpen), 0)
157 ADD2CLOSELIB(GM_UNIQUENAME(libClose), 0)
158 ADD2EXPUNGELIB(GM_UNIQUENAME(libExpunge), 0)
159 /* \\\ */
162 * ***********************************************************************
163 * * Library functions *
164 * ***********************************************************************
167 /* /// "usbAttemptInterfaceBinding()" */
168 struct NepClassMS * GM_UNIQUENAME(usbAttemptInterfaceBinding)(struct NepMSBase *nh, struct PsdInterface *pif)
170 struct Library *ps;
171 IPTR ifclass;
172 IPTR subclass;
173 IPTR proto;
174 struct PsdConfig *pc;
175 struct PsdDevice *pd;
176 IPTR prodid;
177 IPTR vendid;
179 KPRINTF(1, ("nepMSAttemptInterfaceBinding(%08lx)\n", pif));
180 if((ps = OpenLibrary("poseidon.library", 4)))
182 psdGetAttrs(PGA_INTERFACE, pif,
183 IFA_Class, &ifclass,
184 IFA_SubClass, &subclass,
185 IFA_Protocol, &proto,
186 IFA_Config, &pc,
187 TAG_END);
188 psdGetAttrs(PGA_CONFIG, pc,
189 CA_Device, &pd,
190 TAG_END);
191 psdGetAttrs(PGA_DEVICE, pd,
192 DA_ProductID, &prodid,
193 DA_VendorID, &vendid,
194 TAG_END);
196 CloseLibrary(ps);
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));
214 return(NULL);
216 /* \\\ */
218 /* /// "usbForceInterfaceBinding()" */
219 struct NepClassMS * GM_UNIQUENAME(usbForceInterfaceBinding)(struct NepMSBase *nh, struct PsdInterface *pif)
221 struct Library *ps;
222 struct Task *subtask;
223 struct NepClassMS *ncm;
224 struct NepClassMS *firstncm = NULL;
225 struct NepClassMS *tmpncm;
226 struct MsgPort *mp;
227 struct PsdConfig *pc;
228 struct PsdDevice *pd;
229 struct PsdPipe *pp;
230 struct ClsDevCfg *cdc;
231 struct ClsUnitCfg *cuc;
232 STRPTR devname;
233 IPTR ifclass;
234 IPTR subclass;
235 IPTR proto;
236 IPTR ifnum;
237 IPTR prodid;
238 IPTR vendid;
239 ULONG unitno;
240 STRPTR devidstr;
241 STRPTR ifidstr;
242 BOOL unitfound;
243 UBYTE buf[64];
244 UBYTE maxlun;
245 UWORD lunnum;
246 LONG ioerr;
247 LONG retry;
248 ULONG patchflags = 0;
249 BOOL delayedstore = FALSE;
251 KPRINTF(1, ("nepMSAttemptInterfaceBinding(%08lx)\n", pif));
252 if(!(mp = CreateMsgPort()))
254 return(NULL);
256 if((ps = OpenLibrary("poseidon.library", 4)))
258 psdGetAttrs(PGA_INTERFACE, pif,
259 IFA_Class, &ifclass,
260 IFA_SubClass, &subclass,
261 IFA_Protocol, &proto,
262 IFA_InterfaceNum, &ifnum,
263 IFA_Config, &pc,
264 IFA_IDString, &ifidstr,
265 TAG_DONE);
266 psdGetAttrs(PGA_CONFIG, pc,
267 CA_Device, &pd,
268 TAG_END);
269 psdGetAttrs(PGA_DEVICE, pd,
270 DA_ProductID, &prodid,
271 DA_VendorID, &vendid,
272 DA_ProductName, &devname,
273 DA_IDString, &devidstr,
274 TAG_END);
275 maxlun = 0;
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;
322 if(patchflags)
324 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
325 "Preconfig patchflags 0x%04lx", patchflags);
328 lunnum = 0;
329 while(lunnum <= maxlun)
331 /*if(firstncm)
333 unitno = firstncm->ncm_UnitNo + lunnum;
334 } else {
335 unitno = lunnum;
337 Forbid();
338 unitfound = FALSE;
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;
347 unitfound = TRUE;
348 break;
350 ncm = (struct NepClassMS *) ncm->ncm_Unit.unit_MsgPort.mp_Node.ln_Succ;
352 if(!unitfound)
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)))
358 Permit();
359 DeleteMsgPort(mp);
360 CloseLibrary(ps);
361 return(NULL);
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))
371 FreeVec(cdc);
372 FreeVec(cuc);
373 FreeVec(ncm->ncm_DevIDString);
374 FreeVec(ncm->ncm_IfIDString);
375 FreeVec(ncm);
376 Permit();
377 DeleteMsgPort(mp);
378 CloseLibrary(ps);
379 return(NULL);
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);
404 if(!firstncm)
406 firstncm = ncm;
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;
414 } else {
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
440 if(lunnum == 0)
442 if((pp = psdAllocPipe(pd, mp, NULL)))
444 psdSetAttrs(PGA_PIPE, pp,
445 PPA_NakTimeout, TRUE,
446 PPA_NakTimeoutTime, 1000,
447 TAG_END);
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);
458 if(ioerr)
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,
473 EA_IsIn, TRUE,
474 EA_TransferType, USEAF_BULK,
475 TAG_END);
476 outep = psdFindEndpoint(pif, NULL,
477 EA_IsIn, FALSE,
478 EA_TransferType, USEAF_BULK,
479 TAG_END);
480 if(inep && outep)
482 inpp = psdAllocPipe(pd, mp, inep);
483 outpp = psdAllocPipe(pd, mp, outep);
484 if(inpp && outpp)
486 psdSetAttrs(PGA_PIPE, inpp,
487 PPA_NakTimeout, TRUE,
488 PPA_NakTimeoutTime, 5000,
489 TAG_END);
490 psdSetAttrs(PGA_PIPE, outpp,
491 PPA_NakTimeout, TRUE,
492 PPA_NakTimeoutTime, 5000,
493 PPA_NoShortPackets, TRUE,
494 TAG_END);
496 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
497 "Attempting to do special UCR-61S2B init...");
498 umscbw.dCBWSignature = AROS_LONG2LE(0x43425355);
499 umscbw.dCBWTag = 0;
500 umscbw.dCBWDataTransferLength = 0;
501 umscbw.bmCBWFlags = 0;
502 umscbw.bCBWLUN = 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);
507 if(ioerr)
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);
514 if(ioerr)
516 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
517 "UCR-61S2B init status failed: %s (%ld)",
518 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
521 if(inpp)
523 psdFreePipe(inpp);
525 if(outpp)
527 psdFreePipe(outpp);
532 if(!(patchflags & PFF_SINGLE_LUN))
534 retry = 3;
535 maxlun = 0;
538 psdPipeSetup(pp, URTF_IN|URTF_CLASS|URTF_INTERFACE,
539 UMSR_GET_MAX_LUN, 0, ifnum);
540 ioerr = psdDoPipe(pp, &maxlun, 1);
541 if(ioerr)
543 maxlun = 0;
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);
549 psdDelayMS(500);
550 } else {
551 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
552 "GET_MAX_LUN failed: %s (%ld)",
553 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
555 } else {
556 /*psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
557 "Number of logical units: %ld", (ULONG) maxlun+1);*/
558 break;
560 } while(--retry);
561 if(ioerr)
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.");
568 delayedstore = TRUE;
571 if(maxlun > 7)
573 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
574 "MaxLUN value %ld does not seem reasonable. Reducing to %ld.", maxlun, 3);
575 maxlun = 3;
577 } else {
578 maxlun = 0;
580 psdFreePipe(pp);
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)
594 unitno++;
595 tmpncm = (struct NepClassMS *) nh->nh_Units.lh_Head;
596 } else {
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;
603 Permit();
605 if(delayedstore)
607 ncm->ncm_Base = ps;
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);
616 if(subtask)
618 psdBorrowLocksWait(subtask, 1UL<<ncm->ncm_ReadySignal);
619 if(ncm->ncm_Task)
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,
626 ncm->ncm_UnitNo);
627 //lunnum++;
628 //continue;
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 */
635 /*Forbid();
636 Remove(ncm);
637 Permit();
638 FreeVec(ncm);
639 if(firstncm == ncm)
641 firstncm = NULL;
643 lunnum++;
645 CloseLibrary(ps);
647 DeleteMsgPort(mp);
648 return(firstncm);
650 /* \\\ */
652 /* /// "usbReleaseInterfaceBinding()" */
653 void GM_UNIQUENAME(usbReleaseInterfaceBinding)(struct NepMSBase *nh, struct NepClassMS *ncm)
655 struct Library *ps;
656 STRPTR devname;
657 struct NepClassMS *ncmhead;
659 KPRINTF(1, ("nepMSReleaseInterfaceBinding(%08lx)\n", ncm));
660 if((ps = OpenLibrary("poseidon.library", 4)))
662 Forbid();
663 if(ncm->ncm_GUITask)
665 Signal(ncm->ncm_GUITask, SIGBREAKF_CTRL_C);
667 Permit();
668 psdGetAttrs(PGA_DEVICE, ncm->ncm_Device, DA_ProductName, &devname, TAG_END);
669 ncmhead = ncm;
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;*/
677 Forbid();
678 ncm->ncm_ReadySignal = SIGB_SINGLE;
679 ncm->ncm_ReadySigTask = FindTask(NULL);
680 ncm->ncm_DenyRequests = TRUE;
681 if(ncm->ncm_Task)
683 Signal(ncm->ncm_Task, SIGBREAKF_CTRL_C);
685 Permit();
686 while(ncm->ncm_Task)
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.",
696 devname);
697 CloseLibrary(ps);
700 /* \\\ */
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)
709 AROS_LIBFUNC_INIT
711 struct TagItem *ti;
712 LONG count = 0;
714 KPRINTF(1, ("nepMSGetAttrsA(%ld, %08lx, %08lx)\n", type, usbstruct, tags));
715 switch(type)
717 case UGA_CLASS:
718 if((ti = FindTagItem(UCCA_Priority, tags)))
720 *((SIPTR *) ti->ti_Data) = 0;
721 count++;
723 if((ti = FindTagItem(UCCA_Description, tags)))
725 *((STRPTR *) ti->ti_Data) = "Supports storage devices via usbscsi.device";
726 count++;
728 if((ti = FindTagItem(UCCA_HasClassCfgGUI, tags)))
730 *((IPTR *) ti->ti_Data) = TRUE;
731 count++;
733 if((ti = FindTagItem(UCCA_HasBindingCfgGUI, tags)))
735 *((IPTR *) ti->ti_Data) = TRUE;
736 count++;
738 if((ti = FindTagItem(UCCA_AfterDOSRestart, tags)))
740 *((IPTR *) ti->ti_Data) = FALSE;
741 count++;
743 if((ti = FindTagItem(UCCA_UsingDefaultCfg, tags)))
745 *((IPTR *) ti->ti_Data) = nh->nh_DummyNCM.ncm_UsingDefaultCfg;
746 count++;
748 if((ti = FindTagItem(UCCA_SupportsSuspend, tags)))
750 *((IPTR *) ti->ti_Data) = TRUE;
751 count++;
753 break;
755 case UGA_BINDING:
756 if((ti = FindTagItem(UCBA_UsingDefaultCfg, tags)))
758 *((IPTR *) ti->ti_Data) = ((struct NepClassMS *) usbstruct)->ncm_UsingDefaultCfg;
759 count++;
761 break;
764 return(count);
765 AROS_LIBFUNC_EXIT
767 /* \\\ */
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)
776 AROS_LIBFUNC_INIT
777 return(0);
778 AROS_LIBFUNC_EXIT
780 /* \\\ */
782 /* /// "usbDoMethodA()" */
783 AROS_LH2(IPTR, usbDoMethodA,
784 AROS_LHA(ULONG, methodid, D0),
785 AROS_LHA(IPTR *, methoddata, A1),
786 LIBBASETYPEPTR, nh, 7, massstorage)
788 AROS_LIBFUNC_INIT
790 struct NepClassMS *ncm;
792 KPRINTF(10, ("Do Method %ld\n", methodid));
793 switch(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]);
803 return(TRUE);
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);
813 Forbid();
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;
820 Permit();
821 return(TRUE);
823 case UCM_AttemptSuspendDevice:
824 ncm = (struct NepClassMS *) methoddata[0];
825 ncm->ncm_Running = FALSE;
826 return(TRUE);
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));
832 return(TRUE);
834 default:
835 break;
837 return(0);
838 AROS_LIBFUNC_EXIT
840 /* \\\ */
842 /* /// "nLoadClassConfig()" */
843 BOOL GM_UNIQUENAME(nLoadClassConfig)(struct NepMSBase *nh)
845 struct NepClassMS *ncm = &nh->nh_DummyNCM;
846 struct Library *ps;
847 struct ClsDevCfg *cdc;
848 struct ClsUnitCfg *cuc;
849 struct PsdIFFContext *pic;
851 KPRINTF(10, ("Loading Class Config...\n"));
852 if(ncm->ncm_GUITask)
854 return(FALSE);
856 if(!(ps = OpenLibrary("poseidon.library", 4)))
858 return(FALSE);
861 Forbid();
862 /* Create default config */
863 cdc = ncm->ncm_CDC;
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
880 cuc = ncm->ncm_CUC;
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));
896 if(pic)
898 cdc = psdGetCfgChunk(pic, AROS_LONG2BE(ncm->ncm_CDC->cdc_ChunkID));
899 if(cdc)
901 CopyMem(((UBYTE *) cdc) + 8, ((UBYTE *) ncm->ncm_CDC) + 8, min(AROS_LONG2BE(cdc->cdc_Length), AROS_LONG2BE(ncm->ncm_CDC->cdc_Length)));
902 psdFreeVec(cdc);
903 ncm->ncm_UsingDefaultCfg = FALSE;
905 cuc = psdGetCfgChunk(pic, AROS_LONG2BE(ncm->ncm_CUC->cuc_ChunkID));
906 if(cuc)
908 CopyMem(((UBYTE *) cuc) + 8, ((UBYTE *) ncm->ncm_CUC) + 8, min(AROS_LONG2BE(cuc->cuc_Length), AROS_LONG2BE(ncm->ncm_CUC->cuc_Length)));
909 psdFreeVec(cuc);
910 ncm->ncm_UsingDefaultCfg = FALSE;
913 Permit();
914 CloseLibrary(ps);
915 return(FALSE);
917 /* \\\ */
919 /* /// "nLoadBindingConfig()" */
920 BOOL GM_UNIQUENAME(nLoadBindingConfig)(struct NepClassMS *ncm)
922 struct NepMSBase *nh = ncm->ncm_ClsBase;
923 struct Library *ps;
924 struct ClsDevCfg *cdc;
925 struct ClsUnitCfg *cuc;
926 struct PsdIFFContext *pic;
928 KPRINTF(10, ("Loading Binding Config...\n"));
929 if(ncm->ncm_GUITask)
931 return(FALSE);
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)))
941 return(FALSE);
944 Forbid();
945 /* Load config */
946 pic = psdGetUsbDevCfg(GM_UNIQUENAME(libname), ncm->ncm_DevIDString, ncm->ncm_IfIDString);
947 if(pic)
949 cdc = psdGetCfgChunk(pic, AROS_LONG2BE(ncm->ncm_CDC->cdc_ChunkID));
950 if(cdc)
952 CopyMem(((UBYTE *) cdc) + 8, ((UBYTE *) ncm->ncm_CDC) + 8, min(AROS_LONG2BE(cdc->cdc_Length), AROS_LONG2BE(ncm->ncm_CDC->cdc_Length)));
953 psdFreeVec(cdc);
954 ncm->ncm_UsingDefaultCfg = FALSE;
956 cuc = psdGetCfgChunk(pic, AROS_LONG2BE(ncm->ncm_CUC->cuc_ChunkID));
957 if(cuc)
959 CopyMem(((UBYTE *) cuc) + 8, ((UBYTE *) ncm->ncm_CUC) + 8, min(AROS_LONG2BE(cuc->cuc_Length), AROS_LONG2BE(ncm->ncm_CUC->cuc_Length)));
960 psdFreeVec(cuc);
961 ncm->ncm_UsingDefaultCfg = FALSE;
964 Permit();
965 CloseLibrary(ps);
966 return(FALSE);
968 /* \\\ */
970 /* /// "nOpenBindingCfgWindow()" */
971 LONG GM_UNIQUENAME(nOpenBindingCfgWindow)(struct NepMSBase *nh, struct NepClassMS *ncm)
973 struct Library *ps;
974 KPRINTF(10, ("Opening GUI...\n"));
975 if(!(ps = OpenLibrary("poseidon.library", 4)))
977 return(FALSE);
979 Forbid();
980 if(!ncm->ncm_GUITask)
982 if((ncm->ncm_GUITask = psdSpawnSubTask(MOD_NAME_STRING " GUI", GM_UNIQUENAME(nGUITask), ncm)))
984 Permit();
985 CloseLibrary(ps);
986 return(TRUE);
989 Permit();
990 CloseLibrary(ps);
991 return(FALSE);
993 /* \\\ */
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);
1003 return(TRUE);
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);
1020 return(TRUE);
1022 ReleaseSemaphore(&nh->nh_TaskLock);
1023 return(FALSE);
1025 /* \\\ */
1027 /**************************************************************************/
1029 #undef ps
1030 #define ps ncm->ncm_Base
1032 const STRPTR DeviceTypeStrings[] =
1034 "Direct Access",
1035 "Sequential Access",
1036 "Printer",
1037 "Processor",
1038 "Worm",
1039 "CD/DVD ROM",
1040 "Scanner",
1041 "Optical",
1042 "Medium Changer",
1043 "Communications",
1044 "Arts 1",
1045 "Arts 2",
1046 "RAID",
1047 "Enclosure",
1048 "Simple Direct Access",
1049 "Optical Card",
1050 "Reserved",
1051 "Object Based"
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";
1085 UWORD cnt = 0;
1087 while(cnt < len)
1089 if(cnt++)
1091 *buf++ = ' ';
1093 *buf++ = hexchars[*src>>4];
1094 *buf++ = hexchars[*src++ & 0xf];
1096 *buf = 0;
1098 /* \\\ */
1100 /* /// "nMSTask()" */
1101 AROS_UFH0(void, GM_UNIQUENAME(nMSTask))
1103 AROS_USERFUNC_INIT
1105 struct NepClassMS *ncm;
1106 ULONG sigmask;
1107 ULONG sigs;
1108 LONG ioerr;
1109 UWORD cnt;
1111 struct IOStdReq *ioreq;
1112 struct IOStdReq *ioreq2;
1114 struct SCSICmd scsicmd;
1115 UBYTE inquirydata[36];
1116 //UBYTE buf[256];
1117 UBYTE cmd6[6];
1118 UBYTE sensedata[18];
1120 if((ncm = GM_UNIQUENAME(nAllocMS())))
1122 Forbid();
1123 if(ncm->ncm_ReadySigTask)
1125 Signal(ncm->ncm_ReadySigTask, 1L<<ncm->ncm_ReadySignal);
1127 Permit();
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))
1160 nLockXFer(ncm);
1161 if(nBulkReset(ncm))
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);
1171 nUnlockXFer(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;
1186 cmd6[1] = 0;
1187 cmd6[2] = 0;
1188 cmd6[3] = 0;
1189 cmd6[4] = 36;
1190 cmd6[5] = 0;
1191 if((ioerr = nScsiDirect(ncm, &scsicmd)))
1193 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1194 "SCSI_INQUIRY failed: %ld",
1195 ioerr);
1196 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1197 "Try increasing the startup delay value or fake inquiry.");
1198 } else {
1199 CopyMem(&inquirydata[16], ncm->ncm_LUNIDStr, 16);
1200 ncm->ncm_LUNIDStr[15] = '\0';
1202 // trim spaces
1203 cnt = strlen(ncm->ncm_LUNIDStr);
1204 while(cnt--)
1206 if(ncm->ncm_LUNIDStr[cnt] == ' ')
1208 ncm->ncm_LUNIDStr[cnt] = '\0';
1209 } else {
1210 break;
1214 ncm->ncm_DeviceType = inquirydata[0] & PDT_MASK;
1215 if(ncm->ncm_DeviceType > 0x11)
1217 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Illegal Device Type %02lx", ncm->ncm_DeviceType);
1218 ncm->ncm_DeviceType = 0;
1219 } else {
1220 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Device '%s' is of %s type.", ncm->ncm_LUNIDStr, DeviceTypeStrings[ncm->ncm_DeviceType]);
1222 if((ncm->ncm_DeviceType == PDT_WORM) ||
1223 (ncm->ncm_DeviceType == PDT_CDROM))
1225 // assume 2048 byte blocks
1226 ncm->ncm_BlockSize = 2048;
1227 ncm->ncm_BlockShift = 11;
1228 if(ncm->ncm_CDC->cdc_NakTimeout == DEF_NAKTIMEOUT)
1230 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Silently increasing NAK Timeout value to 15 seconds for CD/DVD drives...");
1231 ncm->ncm_CDC->cdc_NakTimeout = 150;
1232 GM_UNIQUENAME(nStoreConfig)(ncm);
1234 psdSetAttrs(PGA_PIPE, ncm->ncm_EP0Pipe,
1235 PPA_NakTimeout, TRUE,
1236 PPA_NakTimeoutTime, (ncm->ncm_CDC->cdc_NakTimeout+1)*100,
1237 TAG_END);
1238 psdSetAttrs(PGA_PIPE, ncm->ncm_EPInPipe,
1239 PPA_NakTimeout, TRUE,
1240 PPA_NakTimeoutTime, ncm->ncm_CDC->cdc_NakTimeout*100,
1241 TAG_END);
1242 psdSetAttrs(PGA_PIPE, ncm->ncm_EPOutPipe,
1243 PPA_NakTimeout, TRUE,
1244 PPA_NakTimeoutTime, ncm->ncm_CDC->cdc_NakTimeout*100,
1245 TAG_END);
1247 else if(!ncm->ncm_CDC->cdc_NakTimeout)
1249 // that's okay, nak timeout disabled
1251 else if(ncm->ncm_CDC->cdc_NakTimeout < 150)
1253 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "NAK Timeout should be at least 15 seconds for CD/DVD drives!");
1257 if(!(inquirydata[1] & 0x80))
1259 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Device does not seem to use removable media.");
1260 ncm->ncm_Removable = FALSE;
1261 ncm->ncm_UnitReady = TRUE;
1262 ncm->ncm_ChangeCount++;
1266 /* Main task */
1267 sigmask = (1L<<ncm->ncm_Unit.unit_MsgPort.mp_SigBit)|
1268 (1L<<ncm->ncm_TaskMsgPort->mp_SigBit)|
1269 SIGBREAKF_CTRL_C;
1270 if(ncm->ncm_CSType == MS_UFI_SUBCLASS)
1272 struct IOStdReq tmpio;
1273 tmpio.io_Command = CMD_START;
1274 nStartStop(ncm, &tmpio);
1277 // if not removable, call it once to trigger mounting...
1278 if(!ncm->ncm_Removable)
1280 ncm->ncm_ForceRTCheck = TRUE;
1282 ncm->ncm_Running = TRUE;
1286 if(ncm->ncm_Removable || ncm->ncm_ForceRTCheck)
1288 GM_UNIQUENAME(nStartRemovableTask)(ps, ncm->ncm_ClsBase);
1289 ncm->ncm_ForceRTCheck = FALSE;
1291 while((ioreq = (struct IOStdReq *) GetMsg(&ncm->ncm_Unit.unit_MsgPort)))
1293 KPRINTF(5, ("command ioreq: 0x%08lx cmd: %lu len: %ld\n",
1294 ioreq, ioreq->io_Command, ioreq->io_Length));
1296 switch(ioreq->io_Command)
1298 case TD_GETGEOMETRY:
1299 nGetGeometry(ncm, ioreq);
1300 ReplyMsg((struct Message *) ioreq);
1301 break;
1303 case TD_EJECT:
1304 case CMD_START:
1305 case CMD_STOP:
1306 nStartStop(ncm, ioreq);
1307 ReplyMsg((struct Message *) ioreq);
1308 break;
1310 case CMD_READ:
1311 ioreq->io_Actual = 0;
1312 case NSCMD_TD_READ64:
1313 case TD_READ64:
1314 nRead64(ncm, ioreq);
1315 ReplyMsg((struct Message *) ioreq);
1316 break;
1318 case TD_SEEK:
1319 ioreq->io_Actual = 0;
1320 case NSCMD_TD_SEEK64:
1321 case TD_SEEK64:
1322 nSeek64(ncm, ioreq);
1323 ReplyMsg((struct Message *) ioreq);
1324 break;
1326 case TD_FORMAT:
1327 case CMD_WRITE:
1328 ioreq->io_Actual = 0;
1329 case NSCMD_TD_FORMAT64:
1330 case NSCMD_TD_WRITE64:
1331 case TD_FORMAT64:
1332 case TD_WRITE64:
1333 nWrite64(ncm, ioreq);
1334 ReplyMsg((struct Message *) ioreq);
1335 break;
1337 case HD_SCSICMD:
1338 ioreq->io_Error = nScsiDirect(ncm, ioreq->io_Data);
1339 ReplyMsg((struct Message *) ioreq);
1340 break;
1342 case CMD_RESET:
1343 if((ioreq2 = ncm->ncm_XFerPending))
1345 ncm->ncm_XFerPending = NULL;
1346 ioreq2->io_Error = IOERR_ABORTED;
1347 ReplyMsg((struct Message *) ioreq2);
1349 /* Reset does a flush too */
1350 case CMD_FLUSH:
1351 ioreq2 = (struct IOStdReq *) ncm->ncm_XFerQueue.lh_Head;
1352 while(ioreq2->io_Message.mn_Node.ln_Succ)
1354 Remove((struct Node *) ioreq2);
1355 ioreq2->io_Error = IOERR_ABORTED;
1356 ReplyMsg((struct Message *) ioreq2);
1357 ioreq2 = (struct IOStdReq *) ncm->ncm_XFerQueue.lh_Head;
1359 ReplyMsg((struct Message *) ioreq);
1360 break;
1362 default:
1363 ioreq->io_Error = IOERR_NOCMD;
1364 ReplyMsg((struct Message *) ioreq);
1365 break;
1368 sigs = Wait(sigmask);
1369 } while(!(sigs & SIGBREAKF_CTRL_C));
1370 ncm->ncm_DenyRequests = TRUE;
1371 /* Device ejected */
1372 ncm->ncm_UnitReady = FALSE;
1373 ncm->ncm_ChangeCount++;
1374 ioreq = (struct IOStdReq *) ncm->ncm_DCInts.lh_Head;
1375 while(((struct Node *) ioreq)->ln_Succ)
1377 Cause(ioreq->io_Data);
1378 ioreq = (struct IOStdReq *) ((struct Node *) ioreq)->ln_Succ;
1380 if(!ncm->ncm_Removable)
1382 GM_UNIQUENAME(nStartRemovableTask)(ps, ncm->ncm_ClsBase);
1384 KPRINTF(20, ("Going down the river!\n"));
1385 GM_UNIQUENAME(nFreeMS)(ncm);
1387 AROS_USERFUNC_EXIT
1389 /* \\\ */
1391 /* /// "nAllocMS()" */
1392 struct NepClassMS * GM_UNIQUENAME(nAllocMS)(void)
1394 struct Task *thistask;
1395 struct NepClassMS *ncm;
1396 IPTR epnum;
1398 thistask = FindTask(NULL);
1399 ncm = thistask->tc_UserData;
1402 if(!(ncm->ncm_Base = OpenLibrary("poseidon.library", 4)))
1404 Alert(AG_OpenLib | AO_Unknown);
1405 break;
1407 ncm->ncm_EPInt = psdFindEndpoint(ncm->ncm_Interface, NULL,
1408 EA_IsIn, TRUE,
1409 EA_TransferType, USEAF_INTERRUPT,
1410 TAG_END);
1411 ncm->ncm_EPIn = psdFindEndpoint(ncm->ncm_Interface, NULL,
1412 EA_IsIn, TRUE,
1413 EA_TransferType, USEAF_BULK,
1414 TAG_END);
1415 ncm->ncm_EPOut = psdFindEndpoint(ncm->ncm_Interface, NULL,
1416 EA_IsIn, FALSE,
1417 EA_TransferType, USEAF_BULK,
1418 TAG_END);
1419 if(!(ncm->ncm_EPIn && ncm->ncm_EPOut))
1421 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname), "IN or OUT endpoint missing!");
1422 break;
1424 if((!ncm->ncm_EPInt) && (ncm->ncm_TPType == MS_PROTO_CBI))
1426 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname), "INT endpoint missing!");
1427 break;
1428 } else {
1429 psdGetAttrs(PGA_ENDPOINT, ncm->ncm_EPOut,
1430 EA_EndpointNum, &epnum,
1431 TAG_END);
1432 ncm->ncm_EPIntNum = epnum;
1434 psdGetAttrs(PGA_ENDPOINT, ncm->ncm_EPIn,
1435 EA_EndpointNum, &epnum,
1436 TAG_END);
1437 ncm->ncm_EPInNum = epnum;
1438 psdGetAttrs(PGA_ENDPOINT, ncm->ncm_EPOut,
1439 EA_EndpointNum, &epnum,
1440 TAG_END);
1441 ncm->ncm_EPOutNum = epnum;
1443 ncm->ncm_BulkResetBorks = FALSE;
1444 ncm->ncm_GeoChangeCount = 0xffffffff;
1446 ncm->ncm_Unit.unit_MsgPort.mp_SigBit = AllocSignal(-1);
1447 ncm->ncm_Unit.unit_MsgPort.mp_SigTask = thistask;
1448 ncm->ncm_Unit.unit_MsgPort.mp_Node.ln_Type = NT_MSGPORT;
1449 ncm->ncm_Unit.unit_MsgPort.mp_Flags = PA_SIGNAL;
1450 ncm->ncm_XFerPending = NULL;
1451 if((ncm->ncm_TaskMsgPort = CreateMsgPort()))
1453 if((ncm->ncm_EP0Pipe = psdAllocPipe(ncm->ncm_Device, ncm->ncm_TaskMsgPort, NULL)))
1455 if((ncm->ncm_EPOutPipe = psdAllocPipe(ncm->ncm_Device, ncm->ncm_TaskMsgPort, ncm->ncm_EPOut)))
1457 if((ncm->ncm_EPInPipe = psdAllocPipe(ncm->ncm_Device, ncm->ncm_TaskMsgPort, ncm->ncm_EPIn)))
1459 if(ncm->ncm_CDC->cdc_NakTimeout)
1461 psdSetAttrs(PGA_PIPE, ncm->ncm_EP0Pipe,
1462 PPA_NakTimeout, TRUE,
1463 PPA_NakTimeoutTime, (ncm->ncm_CDC->cdc_NakTimeout+1)*100,
1464 TAG_END);
1465 psdSetAttrs(PGA_PIPE, ncm->ncm_EPInPipe,
1466 PPA_NakTimeout, TRUE,
1467 PPA_NakTimeoutTime, ncm->ncm_CDC->cdc_NakTimeout*100,
1468 TAG_END);
1469 psdSetAttrs(PGA_PIPE, ncm->ncm_EPOutPipe,
1470 PPA_NakTimeout, TRUE,
1471 PPA_NakTimeoutTime, ncm->ncm_CDC->cdc_NakTimeout*100,
1472 TAG_END);
1474 psdSetAttrs(PGA_PIPE, ncm->ncm_EPOutPipe,
1475 PPA_NoShortPackets, TRUE,
1476 TAG_END);
1477 if(ncm->ncm_EPInt)
1479 if((ncm->ncm_EPIntPipe = psdAllocPipe(ncm->ncm_Device, ncm->ncm_TaskMsgPort, ncm->ncm_EPInt)))
1481 if(ncm->ncm_CDC->cdc_NakTimeout)
1483 psdSetAttrs(PGA_PIPE, ncm->ncm_EPIntPipe,
1484 PPA_NakTimeout, TRUE,
1485 PPA_NakTimeoutTime, ncm->ncm_CDC->cdc_NakTimeout*100,
1486 TAG_END);
1488 ncm->ncm_Task = thistask;
1489 return(ncm);
1491 } else {
1492 ncm->ncm_Task = thistask;
1493 return(ncm);
1495 psdFreePipe(ncm->ncm_EPInPipe);
1497 psdFreePipe(ncm->ncm_EPOutPipe);
1499 psdFreePipe(ncm->ncm_EP0Pipe);
1501 DeleteMsgPort(ncm->ncm_TaskMsgPort);
1503 FreeSignal((LONG) ncm->ncm_Unit.unit_MsgPort.mp_SigBit);
1504 } while(FALSE);
1505 CloseLibrary(ncm->ncm_Base);
1506 Forbid();
1507 ncm->ncm_Task = NULL;
1508 if(ncm->ncm_ReadySigTask)
1510 Signal(ncm->ncm_ReadySigTask, 1L<<ncm->ncm_ReadySignal);
1512 return(NULL);
1514 /* \\\ */
1516 /* /// "nFreeMS()" */
1517 void GM_UNIQUENAME(nFreeMS)(struct NepClassMS *ncm)
1519 struct IOStdReq *ioreq;
1520 /* Disable the message port, messages may still be queued */
1521 Forbid();
1522 ncm->ncm_Unit.unit_MsgPort.mp_Flags = PA_IGNORE;
1523 ncm->ncm_Unit.unit_MsgPort.mp_SigTask = NULL;
1524 FreeSignal((LONG) ncm->ncm_Unit.unit_MsgPort.mp_SigBit);
1525 // get rid of all messages that still have appeared here
1526 while((ioreq = (struct IOStdReq *) GetMsg(&ncm->ncm_Unit.unit_MsgPort)))
1528 ioreq->io_Error = IOERR_ABORTED;
1529 ReplyMsg((struct Message *) ioreq);
1531 Permit();
1533 psdFreePipe(ncm->ncm_EPIntPipe);
1534 psdFreePipe(ncm->ncm_EPInPipe);
1535 psdFreePipe(ncm->ncm_EPOutPipe);
1536 psdFreePipe(ncm->ncm_EP0Pipe);
1537 DeleteMsgPort(ncm->ncm_TaskMsgPort);
1539 psdFreeVec(ncm->ncm_OneBlock);
1540 ncm->ncm_OneBlock = NULL;
1541 ncm->ncm_OneBlockSize = 0;
1543 CloseLibrary(ncm->ncm_Base);
1544 Forbid();
1545 ncm->ncm_Task = NULL;
1546 if(ncm->ncm_ReadySigTask)
1548 Signal(ncm->ncm_ReadySigTask, 1L<<ncm->ncm_ReadySignal);
1551 /* \\\ */
1553 /* /// "nGetModePage()" */
1554 UBYTE * nGetModePage(struct NepClassMS *ncm, UBYTE page)
1556 UBYTE cmd6[6];
1557 struct SCSICmd scsicmd;
1558 UBYTE sensedata[18];
1559 LONG ioerr;
1560 UBYTE *res;
1561 ULONG pf;
1563 KPRINTF(10, ("page %ld\n", page));
1565 memset(ncm->ncm_ModePageBuf, 0x00, 255);
1566 scsicmd.scsi_Data = (UWORD *) ncm->ncm_ModePageBuf;
1567 scsicmd.scsi_Length = 255;
1568 scsicmd.scsi_Command = cmd6;
1569 scsicmd.scsi_CmdLength = 6;
1570 scsicmd.scsi_Flags = SCSIF_READ|SCSIF_AUTOSENSE;
1571 scsicmd.scsi_SenseData = sensedata;
1572 scsicmd.scsi_SenseLength = 18;
1573 cmd6[0] = SCSI_MODE_SENSE_6;
1574 cmd6[1] = 0x00; /* no block descriptors */
1575 cmd6[2] = page;
1576 cmd6[3] = 0;
1577 cmd6[4] = 255;
1578 cmd6[5] = 0;
1579 if((ioerr = nScsiDirect(ncm, &scsicmd)))
1581 KPRINTF(10, ("ioerr %ld\n", ioerr));
1582 pf = ncm->ncm_CDC->cdc_PatchFlags;
1583 if(pf & PFF_DEBUG)
1585 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1586 "SCSI_MODE_SENSE(0x%02lx) failed: %ld",
1587 page, ioerr);
1589 if((!(pf & PFF_NO_FALLBACK)) && (!(pf & PFF_MODE_XLATE)) && (ioerr == HFERR_Phase))
1591 ncm->ncm_CDC->cdc_PatchFlags |= PFF_MODE_XLATE;
1592 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1593 "Fallback: Enabling CMD6->CMD10.");
1594 GM_UNIQUENAME(nStoreConfig)(ncm);
1596 else if((!(pf & PFF_NO_FALLBACK)) && (pf & PFF_MODE_XLATE) && (!(pf & PFF_SIMPLE_SCSI)) && (ioerr == HFERR_Phase))
1598 ncm->ncm_CDC->cdc_PatchFlags |= PFF_SIMPLE_SCSI;
1599 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1600 "Fallback: Enabling Simple SCSI.");
1601 GM_UNIQUENAME(nStoreConfig)(ncm);
1603 return(NULL);
1605 pf = ncm->ncm_CDC->cdc_PatchFlags;
1606 res = ncm->ncm_ModePageBuf;
1607 if((scsicmd.scsi_Actual < 6) || (scsicmd.scsi_Actual < res[3]+6))
1609 if(pf & PFF_DEBUG)
1611 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1612 "SCSI_MODE_SENSE(0x%02lx) failed: only %ld returned",
1613 page, scsicmd.scsi_Actual);
1615 return(NULL);
1617 if(pf & PFF_DEBUG)
1619 UBYTE hexbuf[12*3+2];
1620 GM_UNIQUENAME(nHexString)(res, 12, hexbuf);
1621 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "ModePage (%ld) header: %s...", scsicmd.scsi_Actual, hexbuf);
1623 if(res[3])
1625 res += res[3];
1626 scsicmd.scsi_Actual -= res[3];
1628 res += 4; // skip mode header */
1629 scsicmd.scsi_Actual -= 4;
1630 if((*res & 0x3f) != (page & 0x3f))
1632 if(pf & PFF_DEBUG)
1634 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1635 "SCSI_MODE_SENSE(0x%02lx) failed: wrong page 0x%02lx returned",
1636 page, *res);
1638 return(NULL);
1640 if(scsicmd.scsi_Actual < res[1])
1642 if(pf & PFF_DEBUG)
1644 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1645 "SCSI_MODE_SENSE(0x%02lx) failed: page incomplete",
1646 page);
1648 return(NULL);
1651 #if 0
1652 if(*res & 0x40) /* subpage mode? */
1654 res += 2;
1656 #endif
1657 return(res);
1659 /* \\\ */
1661 /* /// "nGetBlockSize()" */
1662 LONG nGetBlockSize(struct NepClassMS *ncm)
1664 UBYTE cmd10[10];
1665 struct SCSICmd scsicmd;
1666 UBYTE sensedata[18];
1667 ULONG capacity[2];
1668 LONG ioerr;
1670 scsicmd.scsi_Data = (UWORD *) capacity;
1671 scsicmd.scsi_Length = 8;
1672 scsicmd.scsi_Command = cmd10;
1673 scsicmd.scsi_CmdLength = 10;
1674 scsicmd.scsi_Flags = SCSIF_READ|SCSIF_AUTOSENSE;
1675 scsicmd.scsi_SenseData = sensedata;
1676 scsicmd.scsi_SenseLength = 18;
1677 cmd10[0] = SCSI_DA_READ_CAPACITY;
1678 cmd10[1] = 0;
1679 cmd10[2] = 0;
1680 cmd10[3] = 0;
1681 cmd10[4] = 0;
1682 cmd10[5] = 0;
1683 cmd10[6] = 0;
1684 cmd10[7] = 0;
1685 cmd10[8] = 0;
1686 cmd10[9] = 0;
1687 if((ioerr = nScsiDirect(ncm, &scsicmd)))
1689 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1690 "SCSI_READ_CAPACITY failed: %ld",
1691 ioerr);
1692 if(!ncm->ncm_BlockSize)
1694 ncm->ncm_Geometry.dg_SectorSize = ncm->ncm_BlockSize = 512;
1695 ncm->ncm_BlockShift = 9;
1697 } else {
1698 ncm->ncm_Geometry.dg_SectorSize = ncm->ncm_BlockSize = AROS_BE2LONG(capacity[1]);
1699 ncm->ncm_BlockShift = 0;
1700 while((1<<ncm->ncm_BlockShift) < ncm->ncm_BlockSize)
1702 ncm->ncm_BlockShift++;
1704 ncm->ncm_Geometry.dg_TotalSectors = AROS_BE2LONG(capacity[0])+1;
1706 return(ioerr);
1708 /* \\\ */
1710 /* /// "nFakeGeometry()" */
1711 void nFakeGeometry(struct NepClassMS *ncm, struct DriveGeometry *tddg)
1713 UWORD cnt;
1714 ULONG primes[32];
1715 UWORD count[32];
1716 UWORD curpos;
1717 UWORD curprime;
1718 ULONG curprimesq;
1719 ULONG remblks = tddg->dg_TotalSectors;
1720 UWORD *primetblptr = PrimeTable;
1721 UWORD totfactors;
1722 UWORD factor;
1723 ULONG remfact;
1724 UWORD tries;
1725 BOOL taken;
1727 if(!ncm->ncm_Geometry.dg_TotalSectors)
1729 return;
1731 KPRINTF(10, ("Faking geometry for %ld sectors\n", tddg->dg_TotalSectors));
1732 //psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Prime factorisation for %ld", remblks);
1733 tddg->dg_DeviceType = ncm->ncm_DeviceType;
1734 tddg->dg_Flags = ncm->ncm_Removable ? DGF_REMOVABLE : 0;
1735 tddg->dg_BufMemType = MEMF_PUBLIC;
1736 tddg->dg_Reserved = 0;
1739 KPRINTF(10, ("Loop\n"));
1740 // first prime is counted manually
1741 *primes = 2;
1742 *count = 0;
1743 curpos = 0;
1744 while(!(remblks & 1))
1746 (*count)++;
1747 remblks >>= 1;
1749 if(*count)
1751 curpos++;
1754 primes[curpos] = 3;
1755 count[curpos] = 0;
1756 primetblptr = PrimeTable;
1757 curprime = 3;
1758 curprimesq = 9;
1759 // abort if no primes can be found anymore
1762 KPRINTF(10, ("remblks = %ld, curprime=%ld\n", remblks, curprime));
1763 if(remblks % curprime)
1765 if(remblks >= curprimesq)
1767 // it's a prime!
1768 break;
1770 if(count[curpos]) // prime at least once
1772 // next prime
1773 count[++curpos] = 0;
1774 if(curpos == 31) // end of buffer reached
1776 break;
1779 // try next "prime"
1780 if(*primetblptr)
1782 // use lookup table for the first primes to 2000
1783 curprime = *primetblptr++;
1784 } else {
1785 // do it the hard way :-(
1786 curprime += 2;
1788 primes[curpos] = curprime;
1789 curprimesq = curprime * curprime;
1790 } else {
1791 // factor found
1792 count[curpos]++;
1793 remblks /= curprime;
1795 } while((remblks > 1) && (remblks >= curprime));
1796 if(count[curpos])
1798 curpos++;
1800 if((remblks > 1) && curpos)
1802 count[curpos] = 1;
1803 primes[curpos++] = remblks;
1805 KPRINTF(10, ("Priming done, %ld different primes\n", curpos));
1806 if(curpos)
1808 break;
1810 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "FakeGeometry: Total number of blocks is a prime number!");
1811 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_FIX_CAPACITY)
1813 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_FALLBACK)
1815 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
1816 "This is probably due to the Fix Capacity switch being enabled incorrectly. Please check this.");
1817 return;
1818 } else {
1819 ncm->ncm_CDC->cdc_PatchFlags &= ~PFF_FIX_CAPACITY;
1820 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
1821 "Fallback: Disabling Fix Capacity.");
1822 GM_UNIQUENAME(nStoreConfig)(ncm);
1823 remblks = ++tddg->dg_TotalSectors;
1825 } else {
1826 if(!(ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_FALLBACK))
1828 ncm->ncm_CDC->cdc_PatchFlags |= PFF_FIX_CAPACITY;
1829 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1830 "Fallback: Enabling Fix Capacity.");
1831 GM_UNIQUENAME(nStoreConfig)(ncm);
1832 } else {
1833 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1834 "Assuming Fix Capacity bug (total blocks instead of last block)!");
1836 remblks = --tddg->dg_TotalSectors;
1838 } while(TRUE);
1840 totfactors = 0;
1841 for(cnt = 0; cnt < curpos; cnt++)
1843 totfactors += count[cnt];
1846 // Rules:
1847 // - We want at least blocks per track * heads >= 64
1848 // - We want heads * heads < blocks per track
1849 // - We want blocks per track < cylinders
1850 // - We want heads < 8
1851 // - We want blocks per track < 256
1852 // - The rest goes into cylinders
1853 tddg->dg_TrackSectors = 1;
1854 tddg->dg_Heads = 1;
1855 remfact = tddg->dg_TotalSectors;
1856 tries = 0;
1857 while(totfactors)
1859 KPRINTF(10, ("Totfactors %ld\n", totfactors));
1860 cnt = 0;
1861 while(!count[cnt])
1863 cnt++;
1864 if(cnt >= curpos)
1866 cnt = 0;
1869 taken = TRUE;
1870 factor = primes[cnt];
1871 if((tddg->dg_TrackSectors * factor < 256) &&
1872 (tddg->dg_TrackSectors * factor < remfact))
1874 tddg->dg_TrackSectors *= factor;
1875 remfact /= factor;
1877 else if((tddg->dg_Heads * factor <= 16) &&
1878 (tddg->dg_Heads * tddg->dg_Heads * factor * factor < tddg->dg_TrackSectors))
1880 tddg->dg_Heads *= factor;
1881 remfact /= factor;
1883 else if((tddg->dg_Heads * tddg->dg_TrackSectors >= 64) ||
1884 (tries > curpos))
1886 // do nothing
1887 } else {
1888 taken = FALSE;
1890 if(taken)
1892 totfactors--;
1893 count[cnt]--;
1894 tries = 0;
1895 } else {
1896 tries++;
1898 KPRINTF(10, ("Factor=%ld: Cylinders = %ld, Heads=%ld, TrackSectors=%ld, Blocks=%ld\n",
1899 factor, remfact, tddg->dg_Heads, tddg->dg_TrackSectors,
1900 tddg->dg_TotalSectors));
1903 KPRINTF(10, ("Final: Cylinders = %ld, Heads=%ld, TrackSectors=%ld, Blocks=%ld\n",
1904 remfact, tddg->dg_Heads, tddg->dg_TrackSectors,
1905 tddg->dg_TotalSectors));
1907 tddg->dg_Cylinders = remfact;
1908 tddg->dg_CylSectors = tddg->dg_TrackSectors * tddg->dg_Heads;
1910 /* \\\ */
1912 struct CapacityData
1914 ULONG SectorCount;
1915 ULONG SectorSize;
1918 #define SERVICEACTION_CAPACITY16 0x10
1920 /* /// "nGetGeometry()" */
1921 LONG nGetGeometry(struct NepClassMS *ncm, struct IOStdReq *ioreq)
1923 struct DriveGeometry *tddg;
1924 ULONG length;
1925 UBYTE cmd10[10];
1926 struct SCSICmd scsicmd;
1927 struct CapacityData capacitydata;
1928 UBYTE sensedata[18];
1929 LONG ioerr;
1930 ULONG tmpval;
1931 UBYTE *mpdata;
1932 BOOL gotblks = FALSE;
1933 BOOL gotcyl = FALSE;
1934 BOOL gotheads = FALSE;
1935 BOOL gotsect = FALSE;
1936 BOOL gotcylsect = FALSE;
1937 KPRINTF(10, ("\n"));
1939 ioreq->io_Error = 0;
1940 ioreq->io_Actual = 0;
1941 tddg = (struct DriveGeometry *) ioreq->io_Data;
1942 if(!tddg)
1944 ioreq->io_Error = TDERR_NotSpecified;
1945 return(ioreq->io_Error);
1947 length = min(ioreq->io_Length,sizeof(struct DriveGeometry));
1948 if((ncm->ncm_GeoChangeCount == ncm->ncm_ChangeCount) && ncm->ncm_Geometry.dg_TotalSectors)
1950 // cached
1951 memcpy(tddg,&ncm->ncm_Geometry, (size_t) length);
1952 ioreq->io_Actual = length;
1953 return(0);
1956 ncm->ncm_Geometry.dg_DeviceType = ncm->ncm_DeviceType;
1957 ncm->ncm_Geometry.dg_Flags = ncm->ncm_Removable ? DGF_REMOVABLE : 0;
1960 * Capacity10, 32bit Sectorcount
1962 scsicmd.scsi_Data = (UWORD *) &capacitydata;
1963 scsicmd.scsi_Length = sizeof(capacitydata);
1964 scsicmd.scsi_Command = cmd10;
1965 scsicmd.scsi_CmdLength = 10;
1966 scsicmd.scsi_Flags = SCSIF_READ|SCSIF_AUTOSENSE;
1967 scsicmd.scsi_SenseData = sensedata;
1968 scsicmd.scsi_SenseLength = 18;
1969 cmd10[0] = SCSI_DA_READ_CAPACITY;
1970 cmd10[1] = 0;
1971 cmd10[2] = 0;
1972 cmd10[3] = 0;
1973 cmd10[4] = 0;
1974 cmd10[5] = 0;
1975 cmd10[6] = 0;
1976 cmd10[7] = 0;
1977 cmd10[8] = 0;
1978 cmd10[9] = 0;
1980 if((ioerr = nScsiDirect(ncm, &scsicmd)))
1982 KPRINTF(10, ("ioerr %ld\n",ioerr));
1983 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1984 "SCSI_READ_CAPACITY failed: %ld",
1985 ioerr);
1987 * memset(tddg,0,Length);
1988 * The error should be enough
1990 return(ioreq->io_Error = ioerr);
1991 } else {
1993 * 32Bit Totalsectors
1994 * R.S.
1996 ncm->ncm_BlockSize = ncm->ncm_Geometry.dg_SectorSize = AROS_BE2LONG(capacitydata.SectorSize);
1997 ncm->ncm_Geometry.dg_TotalSectors = AROS_BE2LONG(capacitydata.SectorCount) + 1;
1998 if(capacitydata.SectorCount == 0xffffffff)
2000 ncm->ncm_Geometry.dg_TotalSectors--; // set to maximum
2001 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2002 "Capacity exceeds the maximum supported for 32 bit sector counts (usually >2TB)!");
2003 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2004 "I/O operations will still work, but geometry and partitioning will be unreliable!");
2006 KPRINTF(10, ("blocksize %ld totalsectors %ld\n", ncm->ncm_BlockSize, ncm->ncm_Geometry.dg_TotalSectors));
2007 gotblks = TRUE;
2008 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
2010 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
2011 "Capacity: %ld blocks of %ld bytes", ncm->ncm_Geometry.dg_TotalSectors, ncm->ncm_Geometry.dg_SectorSize);
2013 ncm->ncm_BlockShift = 0;
2014 while((1<<ncm->ncm_BlockShift) < ncm->ncm_BlockSize)
2016 ncm->ncm_BlockShift++;
2019 KPRINTF(10, ("PatchFlags 0x%lx DeviceType %ld\n",ncm->ncm_CDC->cdc_PatchFlags,ncm->ncm_DeviceType));
2021 if(!((ncm->ncm_CDC->cdc_PatchFlags & PFF_SIMPLE_SCSI) ||
2022 (ncm->ncm_DeviceType == PDT_WORM) ||
2023 (ncm->ncm_DeviceType == PDT_CDROM)))
2025 KPRINTF(10, ("SIMPLE_SCSI or PDT_WORM/CDROM\n"));
2026 // cd roms don't have valid or sensible capacity mode pages
2027 if((mpdata = nGetModePage(ncm, 0x03)))
2029 if((tmpval = (mpdata[10]<<8)+mpdata[11]))
2031 ncm->ncm_Geometry.dg_TrackSectors = tmpval;
2032 gotsect = TRUE;
2033 if(!ncm->ncm_Geometry.dg_Cylinders)
2035 ncm->ncm_Geometry.dg_Cylinders = ncm->ncm_Geometry.dg_TotalSectors;
2038 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
2040 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
2041 "Capacity: TrackSectors=%ld",
2042 ncm->ncm_Geometry.dg_TrackSectors);
2047 * Cylinder and co are only defined for old 32Bit Totalsectors.
2048 * >2TB they have no meaning anyway, so they are calculated based
2049 * on 32Bit INT_MAX.
2051 // recheck, could have simple scsi enabled in the meanwhile
2052 if(!((ncm->ncm_CDC->cdc_PatchFlags & PFF_SIMPLE_SCSI) ||
2053 (ncm->ncm_DeviceType == PDT_WORM) ||
2054 (ncm->ncm_DeviceType == PDT_CDROM)))
2056 KPRINTF(10, ("recheck1 SIMPLE_SCSI or PDT_WORM/CDROM\n"));
2057 if((mpdata = nGetModePage(ncm, 0x04)))
2059 if((tmpval = (mpdata[2]<<16)+(mpdata[3]<<8)+mpdata[4]))
2061 ncm->ncm_Geometry.dg_Cylinders = tmpval;
2062 ncm->ncm_Geometry.dg_Heads = mpdata[5];
2063 gotcyl = gotheads = TRUE;
2065 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
2067 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
2068 "Capacity: Cylinders=%ld, Heads=%ld",
2069 ncm->ncm_Geometry.dg_Cylinders, ncm->ncm_Geometry.dg_Heads);
2073 // recheck, could have simple scsi enabled in the meanwhile
2074 if(!((ncm->ncm_CDC->cdc_PatchFlags & PFF_SIMPLE_SCSI) ||
2075 (ncm->ncm_DeviceType == PDT_WORM) ||
2076 (ncm->ncm_DeviceType == PDT_CDROM)))
2078 KPRINTF(10, ("recheck2 SIMPLE_SCSI or PDT_WORM/CDROM\n"));
2079 if((mpdata = nGetModePage(ncm, 0x05)))
2081 if((tmpval = (mpdata[8]<<8)+mpdata[9]))
2083 ncm->ncm_Geometry.dg_Cylinders = tmpval;
2084 ncm->ncm_Geometry.dg_Heads = mpdata[4];
2085 ncm->ncm_Geometry.dg_TrackSectors = mpdata[5];
2087 gotcyl = gotheads = gotsect = TRUE;
2089 if(!gotblks)
2091 ncm->ncm_BlockSize = ncm->ncm_Geometry.dg_SectorSize = (mpdata[6]<<8)+mpdata[7];
2092 ncm->ncm_BlockShift = 0;
2093 while((1<<ncm->ncm_BlockShift) < ncm->ncm_BlockSize)
2095 ncm->ncm_BlockShift++;
2097 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
2099 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
2100 "Capacity: %ld blocks of %ld bytes", ncm->ncm_Geometry.dg_TotalSectors, ncm->ncm_BlockSize);
2103 else if(ncm->ncm_BlockSize != (mpdata[6]<<8)+mpdata[7])
2105 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2106 "Inconsistent block size information %ld != %ld!",
2107 ncm->ncm_BlockSize, (mpdata[6]<<8)+mpdata[7]);
2109 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
2111 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
2112 "Capacity: Cylinders=%ld, Heads=%ld, TrackSectors=%ld",
2113 ncm->ncm_Geometry.dg_Cylinders, ncm->ncm_Geometry.dg_Heads, ncm->ncm_Geometry.dg_TrackSectors);
2118 // missing total blocks?
2119 if((!gotblks) && gotcyl && gotheads && gotsect)
2121 ncm->ncm_Geometry.dg_TotalSectors = ncm->ncm_Geometry.dg_Cylinders * ncm->ncm_Geometry.dg_Heads * ncm->ncm_Geometry.dg_TrackSectors;
2122 gotblks = TRUE;
2124 // missing cylinders?
2125 if(gotblks && (!gotcyl) && gotheads && gotsect)
2127 ncm->ncm_Geometry.dg_Cylinders = ncm->ncm_Geometry.dg_TotalSectors / (ncm->ncm_Geometry.dg_Heads * ncm->ncm_Geometry.dg_TrackSectors);
2128 gotcyl = TRUE;
2130 // missing heads?
2131 if(gotblks && gotcyl && (!gotheads) && gotsect)
2133 ncm->ncm_Geometry.dg_Heads = ncm->ncm_Geometry.dg_TotalSectors / (ncm->ncm_Geometry.dg_Cylinders * ncm->ncm_Geometry.dg_TrackSectors);
2134 gotheads = TRUE;
2136 // missing tracks per sector
2137 if(gotblks && gotcyl && gotheads && (!gotsect))
2139 ncm->ncm_Geometry.dg_TrackSectors = ncm->ncm_Geometry.dg_TotalSectors / (ncm->ncm_Geometry.dg_Cylinders * ncm->ncm_Geometry.dg_Heads);
2140 gotsect = TRUE;
2143 if(gotblks && gotcyl && gotheads && gotsect &&
2144 (ncm->ncm_Geometry.dg_Cylinders * ncm->ncm_Geometry.dg_TrackSectors * ncm->ncm_Geometry.dg_Heads == ncm->ncm_Geometry.dg_TotalSectors - 1) &&
2145 (!(ncm->ncm_CDC->cdc_PatchFlags & PFF_FIX_CAPACITY)))
2147 if(!(ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_FALLBACK))
2149 ncm->ncm_CDC->cdc_PatchFlags |= PFF_FIX_CAPACITY;
2150 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2151 "Fallback: Enabling Fix Capacity.");
2152 GM_UNIQUENAME(nStoreConfig)(ncm);
2153 ncm->ncm_Geometry.dg_TotalSectors--;
2154 } else {
2155 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2156 "Fix Capacity is probably needed for this device. Please check this.");
2159 else if(gotblks && gotcyl && gotheads && gotsect &&
2160 (ncm->ncm_Geometry.dg_Cylinders * ncm->ncm_Geometry.dg_TrackSectors * ncm->ncm_Geometry.dg_Heads == ncm->ncm_Geometry.dg_TotalSectors + 1) &&
2161 ncm->ncm_CDC->cdc_PatchFlags & PFF_FIX_CAPACITY)
2163 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_FALLBACK)
2165 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2166 "Fix Capacity is probably enabled incorrectly. Please check this.");
2167 } else {
2168 ncm->ncm_CDC->cdc_PatchFlags &= ~PFF_FIX_CAPACITY;
2169 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2170 "Fallback: Disabling Fix Capacity.");
2171 GM_UNIQUENAME(nStoreConfig)(ncm);
2172 ncm->ncm_Geometry.dg_TotalSectors++;
2176 // some devices report these bogus values regardless of actual device capacity, though the total number of blocks is correct.
2177 if(((ncm->ncm_Geometry.dg_Cylinders == 500) && (ncm->ncm_Geometry.dg_TrackSectors == 32) && (ncm->ncm_Geometry.dg_Heads == 8)) ||
2178 ((ncm->ncm_Geometry.dg_Cylinders == 16383) && (ncm->ncm_Geometry.dg_TrackSectors == 63) && (ncm->ncm_Geometry.dg_Heads == 16)))
2180 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Firmware returns known bogus geometry, will fall back to faked geometry!");
2181 gotheads = gotcyl = gotsect = FALSE;
2182 if((ncm->ncm_CDC->cdc_PatchFlags & (PFF_SIMPLE_SCSI|PFF_NO_FALLBACK)) == PFF_SIMPLE_SCSI)
2184 ncm->ncm_CDC->cdc_PatchFlags |= PFF_SIMPLE_SCSI;
2185 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2186 "Fallback: Enabling Simple SCSI.");
2187 GM_UNIQUENAME(nStoreConfig)(ncm);
2191 // missing more than one?
2192 if(gotblks && (!(gotheads && gotcyl && gotsect)))
2194 nFakeGeometry(ncm, &ncm->ncm_Geometry);
2196 if(!gotcylsect)
2198 ncm->ncm_Geometry.dg_CylSectors = ncm->ncm_Geometry.dg_TrackSectors * ncm->ncm_Geometry.dg_Heads;
2201 if(ncm->ncm_Geometry.dg_Cylinders * ncm->ncm_Geometry.dg_CylSectors != ncm->ncm_Geometry.dg_TotalSectors)
2203 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2204 "Estimated Geometry yields %ld less total blocks %ld: Cylinders=%ld, CylSectors=%ld, Heads=%ld, TrackSectors=%ld, Blocks=%ld",
2205 ncm->ncm_Geometry.dg_TotalSectors - ncm->ncm_Geometry.dg_Cylinders * ncm->ncm_Geometry.dg_CylSectors,
2206 ncm->ncm_Geometry.dg_Cylinders * ncm->ncm_Geometry.dg_CylSectors,
2207 ncm->ncm_Geometry.dg_Cylinders, ncm->ncm_Geometry.dg_CylSectors, ncm->ncm_Geometry.dg_Heads, ncm->ncm_Geometry.dg_TrackSectors,
2208 ncm->ncm_Geometry.dg_TotalSectors);
2210 else if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
2212 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
2213 "Capacity: Cylinders=%ld, CylSectors=%ld, Heads=%ld, TrackSectors=%ld, Blocks=%ld, SectorSize=%ld",
2214 ncm->ncm_Geometry.dg_Cylinders, ncm->ncm_Geometry.dg_CylSectors, ncm->ncm_Geometry.dg_Heads, ncm->ncm_Geometry.dg_TrackSectors,
2215 ncm->ncm_Geometry.dg_TotalSectors, ncm->ncm_Geometry.dg_SectorSize);
2218 ncm->ncm_Geometry.dg_BufMemType = MEMF_PUBLIC;
2219 ncm->ncm_Geometry.dg_Reserved = 0;
2220 memcpy(tddg, &ncm->ncm_Geometry, (size_t) length);
2221 ioreq->io_Actual = length;
2222 ncm->ncm_GeoChangeCount = ncm->ncm_ChangeCount;
2223 return(ioreq->io_Error);
2225 /* \\\ */
2227 /* /// "nStartStop()" */
2228 LONG nStartStop(struct NepClassMS *ncm, struct IOStdReq *ioreq)
2230 UBYTE cmd6[6];
2231 struct SCSICmd scsicmd;
2232 UBYTE sensedata[18];
2233 LONG ioerr;
2235 if((ncm->ncm_CDC->cdc_PatchFlags & PFF_SIMPLE_SCSI)
2236 && ioreq->io_Command != TD_EJECT)
2238 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Simple SCSI: Ignoring START_STOP_UNIT command");
2239 return(0);
2241 scsicmd.scsi_Data = NULL;
2242 scsicmd.scsi_Length = 0;
2243 scsicmd.scsi_Command = cmd6;
2244 scsicmd.scsi_CmdLength = 6;
2245 scsicmd.scsi_Flags = SCSIF_AUTOSENSE|0x80;
2246 scsicmd.scsi_SenseData = sensedata;
2247 scsicmd.scsi_SenseLength = 18;
2248 cmd6[0] = SCSI_DA_START_STOP_UNIT;
2249 cmd6[1] = 0;
2250 cmd6[2] = 0;
2251 cmd6[3] = 0;
2252 switch(ioreq->io_Command)
2254 case CMD_START:
2255 cmd6[4] = 0x01;
2256 break;
2258 case CMD_STOP:
2259 cmd6[4] = 0x00;
2260 break;
2262 case TD_EJECT:
2263 cmd6[4] = ioreq->io_Length ? 0x02 : 0x03;
2264 break;
2266 cmd6[5] = 0;
2267 if((ioerr = nScsiDirect(ncm, &scsicmd)))
2269 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2270 "START_STOP_UNIT failed: %ld",
2271 ioerr);
2272 ioreq->io_Error = TDERR_NotSpecified;
2274 return(ioreq->io_Error);
2276 /* \\\ */
2278 /* /// "nRead64Emul()" */
2279 LONG nRead64Emul(struct NepClassMS *ncm, struct IOStdReq *ioreq)
2281 UBYTE cmd10[10];
2282 ULONG *cmd10sb = (ULONG *)&cmd10[2];
2283 UBYTE sensedata[18];
2284 ULONG dataoffset = 0;
2285 ULONG dataremain = ioreq->io_Length;
2286 ULONG datalen;
2287 ULONG startblock;
2288 ULONG maxtrans = 1UL<<(ncm->ncm_CDC->cdc_MaxTransfer+16);
2289 ULONG insideblockoffset;
2290 struct SCSICmd scsicmd;
2292 if(dataremain & 511)
2294 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2295 "Attempt to read partial block (%ld %% %ld != 0)!",
2296 dataremain, ncm->ncm_BlockSize);
2297 ioreq->io_Actual = 0;
2298 return(ioreq->io_Error = IOERR_BADLENGTH);
2300 if(ioreq->io_Offset & 511)
2302 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2303 "Attempt to read unaligned block (%ld %% %ld != 0)!",
2304 ioreq->io_Offset, ncm->ncm_BlockSize);
2305 ioreq->io_Actual = 0;
2306 return(ioreq->io_Error = IOERR_BADADDRESS);
2309 if(!ncm->ncm_OneBlock || (ncm->ncm_OneBlockSize < ncm->ncm_BlockSize))
2311 psdFreeVec(ncm->ncm_OneBlock);
2312 if(!(ncm->ncm_OneBlock = psdAllocVec(ncm->ncm_BlockSize)))
2314 return(IOERR_BADADDRESS);
2316 ncm->ncm_OneBlockSize = ncm->ncm_BlockSize;
2319 startblock = (ioreq->io_Offset>>ncm->ncm_BlockShift)|(ioreq->io_Actual<<(32-ncm->ncm_BlockShift));
2320 insideblockoffset = (ioreq->io_Offset & ((1<<ncm->ncm_BlockShift)-1));
2321 while(dataremain)
2323 KPRINTF(10, ("Reading from block %ld, %ld bytes left...\n", startblock, dataremain));
2324 datalen = dataremain;
2325 if(datalen > maxtrans)
2327 datalen = maxtrans;
2329 if(insideblockoffset || (datalen < ncm->ncm_BlockSize))
2331 if(datalen > ncm->ncm_BlockSize-insideblockoffset)
2333 datalen = ncm->ncm_BlockSize-insideblockoffset;
2335 scsicmd.scsi_Data = (UWORD *) ncm->ncm_OneBlock;
2336 scsicmd.scsi_Length = ncm->ncm_BlockSize;
2337 scsicmd.scsi_Command = cmd10;
2338 scsicmd.scsi_CmdLength = 10;
2339 scsicmd.scsi_Flags = SCSIF_READ|SCSIF_AUTOSENSE|0x80;
2340 scsicmd.scsi_SenseData = sensedata;
2341 scsicmd.scsi_SenseLength = 18;
2342 cmd10[0] = SCSI_DA_READ_10;
2343 cmd10[1] = 0;
2344 *cmd10sb = AROS_LONG2BE(startblock);
2345 cmd10[6] = 0;
2346 cmd10[7] = 0;
2347 cmd10[8] = 1;
2348 cmd10[9] = 0;
2349 if((ioreq->io_Error = nScsiDirect(ncm, &scsicmd)))
2351 KPRINTF(10, ("Read error!\n"));
2352 break;
2354 CopyMemQuick(&ncm->ncm_OneBlock[insideblockoffset], &(((UBYTE *) ioreq->io_Data)[dataoffset]), datalen);
2355 insideblockoffset = 0;
2356 startblock++;
2357 } else {
2358 scsicmd.scsi_Data = (UWORD *) &(((UBYTE *) ioreq->io_Data)[dataoffset]);
2359 scsicmd.scsi_Length = datalen;
2360 scsicmd.scsi_Command = cmd10;
2361 scsicmd.scsi_CmdLength = 10;
2362 scsicmd.scsi_Flags = SCSIF_READ|SCSIF_AUTOSENSE|0x80;
2363 scsicmd.scsi_SenseData = sensedata;
2364 scsicmd.scsi_SenseLength = 18;
2365 cmd10[0] = SCSI_DA_READ_10;
2366 cmd10[1] = 0;
2367 *cmd10sb = AROS_LONG2BE(startblock);
2368 cmd10[6] = 0;
2369 cmd10[7] = datalen>>(ncm->ncm_BlockShift+8);
2370 cmd10[8] = datalen>>ncm->ncm_BlockShift;
2371 cmd10[9] = 0;
2372 if((ioreq->io_Error = nScsiDirect(ncm, &scsicmd)))
2374 KPRINTF(10, ("Read error!\n"));
2375 break;
2377 startblock += (insideblockoffset+datalen)>>ncm->ncm_BlockShift;
2379 dataoffset += datalen;
2380 dataremain -= datalen;
2382 ioreq->io_Actual = dataoffset;
2383 return(ioreq->io_Error);
2385 /* \\\ */
2387 /* /// "nWrite64Emul()" */
2388 LONG nWrite64Emul(struct NepClassMS *ncm, struct IOStdReq *ioreq)
2390 UBYTE cmd10[10];
2391 ULONG *cmd10sb = (ULONG *)&cmd10[2];
2392 UBYTE sensedata[18];
2393 ULONG dataoffset = 0;
2394 ULONG dataremain = ioreq->io_Length;
2395 ULONG datalen;
2396 ULONG startblock;
2397 ULONG maxtrans = 1UL<<(ncm->ncm_CDC->cdc_MaxTransfer+16);
2398 ULONG insideblockoffset;
2399 struct SCSICmd scsicmd;
2401 if(dataremain & 511)
2403 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2404 "Attempt to write partial block (%ld %% %ld != 0)!",
2405 dataremain, ncm->ncm_BlockSize);
2406 ioreq->io_Actual = 0;
2407 return(ioreq->io_Error = IOERR_BADLENGTH);
2409 if(ioreq->io_Offset & 511)
2411 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2412 "Attempt to write unaligned block (%ld %% %ld != 0)!",
2413 ioreq->io_Offset, ncm->ncm_BlockSize);
2414 ioreq->io_Actual = 0;
2415 return(ioreq->io_Error = IOERR_BADADDRESS);
2418 if(!ncm->ncm_OneBlock || (ncm->ncm_OneBlockSize < ncm->ncm_BlockSize))
2420 psdFreeVec(ncm->ncm_OneBlock);
2421 if(!(ncm->ncm_OneBlock = psdAllocVec(ncm->ncm_BlockSize)))
2423 return(IOERR_BADADDRESS);
2425 ncm->ncm_OneBlockSize = ncm->ncm_BlockSize;
2428 startblock = (ioreq->io_Offset>>ncm->ncm_BlockShift)|(ioreq->io_Actual<<(32-ncm->ncm_BlockShift));
2429 insideblockoffset = (ioreq->io_Offset & ((1<<ncm->ncm_BlockShift)-1));
2430 while(dataremain)
2432 KPRINTF(10, ("Writing from block %ld, %ld bytes left...\n", startblock, dataremain));
2433 datalen = dataremain;
2434 if(datalen > maxtrans)
2436 datalen = maxtrans;
2438 if(insideblockoffset || (datalen < ncm->ncm_BlockSize))
2440 if(datalen > ncm->ncm_BlockSize-insideblockoffset)
2442 datalen = ncm->ncm_BlockSize-insideblockoffset;
2444 scsicmd.scsi_Data = (UWORD *) ncm->ncm_OneBlock;
2445 scsicmd.scsi_Length = ncm->ncm_BlockSize;
2446 scsicmd.scsi_Command = cmd10;
2447 scsicmd.scsi_CmdLength = 10;
2448 scsicmd.scsi_Flags = SCSIF_READ|SCSIF_AUTOSENSE|0x80;
2449 scsicmd.scsi_SenseData = sensedata;
2450 scsicmd.scsi_SenseLength = 18;
2451 cmd10[0] = SCSI_DA_READ_10;
2452 cmd10[1] = 0;
2453 *cmd10sb = AROS_LONG2BE(startblock);
2454 cmd10[6] = 0;
2455 cmd10[7] = 0;
2456 cmd10[8] = 1;
2457 cmd10[9] = 0;
2458 if((ioreq->io_Error = nScsiDirect(ncm, &scsicmd)))
2460 KPRINTF(10, ("Read error!\n"));
2461 break;
2463 CopyMemQuick(&(((UBYTE *) ioreq->io_Data)[dataoffset]), &ncm->ncm_OneBlock[insideblockoffset], datalen);
2465 //scsicmd.scsi_Data = (UWORD *) ncm->ncm_OneBlock;
2466 //scsicmd.scsi_Length = ncm->ncm_BlockSize;
2467 //scsicmd.scsi_Command = cmd10;
2468 //scsicmd.scsi_CmdLength = 10;
2469 scsicmd.scsi_Flags = SCSIF_WRITE|SCSIF_AUTOSENSE|0x80;
2470 //scsicmd.scsi_SenseData = sensedata;
2471 //scsicmd.scsi_SenseLength = 18;
2472 cmd10[0] = SCSI_DA_WRITE_10;
2473 //cmd10[1] = 0;
2474 //*((ULONG *) (&cmd10[2])) = AROS_LONG2BE(startblock);
2475 //cmd10[6] = 0;
2476 //cmd10[7] = 0;
2477 //cmd10[8] = 1;
2478 //cmd10[9] = 0;
2479 if((ioreq->io_Error = nScsiDirect(ncm, &scsicmd)))
2481 KPRINTF(10, ("Write error!\n"));
2482 break;
2484 insideblockoffset = 0;
2485 startblock++;
2486 } else {
2487 scsicmd.scsi_Data = (UWORD *) &(((UBYTE *) ioreq->io_Data)[dataoffset]);
2488 scsicmd.scsi_Length = datalen;
2489 scsicmd.scsi_Command = cmd10;
2490 scsicmd.scsi_CmdLength = 10;
2491 scsicmd.scsi_Flags = SCSIF_WRITE|SCSIF_AUTOSENSE|0x80;
2492 scsicmd.scsi_SenseData = sensedata;
2493 scsicmd.scsi_SenseLength = 18;
2494 cmd10[0] = SCSI_DA_WRITE_10;
2495 cmd10[1] = 0;
2496 *cmd10sb = AROS_LONG2BE(startblock);
2497 cmd10[6] = 0;
2498 cmd10[7] = datalen>>(ncm->ncm_BlockShift+8);
2499 cmd10[8] = datalen>>ncm->ncm_BlockShift;
2500 cmd10[9] = 0;
2501 if((ioreq->io_Error = nScsiDirect(ncm, &scsicmd)))
2503 KPRINTF(10, ("Write error!\n"));
2504 break;
2506 startblock += (insideblockoffset+datalen)>>ncm->ncm_BlockShift;
2508 dataoffset += datalen;
2509 dataremain -= datalen;
2511 ioreq->io_Actual = dataoffset;
2512 return(ioreq->io_Error);
2514 /* \\\ */
2516 /* /// "nRead64()" */
2517 LONG nRead64(struct NepClassMS *ncm, struct IOStdReq *ioreq)
2519 UBYTE cmd10[10];
2520 UBYTE cmd16[16];
2521 UBYTE sensedata[18];
2522 ULONG dataoffset = 0;
2523 ULONG dataremain = ioreq->io_Length;
2524 ULONG datalen;
2525 ULONG startblockhigh;
2526 ULONG startblock;
2527 ULONG oldstartblock;
2528 ULONG maxtrans = 1UL<<(ncm->ncm_CDC->cdc_MaxTransfer+16);
2529 struct SCSICmd scsicmd;
2531 if(!ncm->ncm_BlockSize)
2533 nGetBlockSize(ncm);
2535 if((((dataremain >> ncm->ncm_BlockShift)<<ncm->ncm_BlockShift) != dataremain) ||
2536 (((ioreq->io_Offset >> ncm->ncm_BlockShift)<<ncm->ncm_BlockShift) != ioreq->io_Offset))
2538 KPRINTF(20, ("unaligned read access offset %ld, length %ld...\n", ioreq->io_Offset, dataremain));
2539 if((!(ncm->ncm_CDC->cdc_PatchFlags & PFF_EMUL_LARGE_BLK)) && (!(ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_FALLBACK)))
2541 ncm->ncm_CDC->cdc_PatchFlags |= PFF_EMUL_LARGE_BLK;
2542 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2543 "Fallback: Enabling emulation for large block devices.");
2544 GM_UNIQUENAME(nStoreConfig)(ncm);
2546 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_EMUL_LARGE_BLK)
2548 return(nRead64Emul(ncm, ioreq));
2550 if((dataremain >> ncm->ncm_BlockShift)<<ncm->ncm_BlockShift != dataremain)
2552 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2553 "Attempt to read partial block (%ld %% %ld != 0)!",
2554 dataremain, ncm->ncm_BlockSize);
2555 ioreq->io_Error = IOERR_BADLENGTH;
2556 } else {
2557 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2558 "Attempt to read unaligned block (%ld %% %ld != 0)!",
2559 ioreq->io_Offset, ncm->ncm_BlockSize);
2560 ioreq->io_Error = IOERR_BADADDRESS;
2562 if(ncm->ncm_BlockSize != 512)
2564 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2565 "The used FileSystem or other software must support %ld byte blocks!",
2566 ncm->ncm_BlockSize);
2568 ioreq->io_Actual = 0;
2569 return(ioreq->io_Error);
2572 startblockhigh = ioreq->io_Actual>>ncm->ncm_BlockShift;
2573 startblock = (ioreq->io_Offset>>ncm->ncm_BlockShift)|(ioreq->io_Actual<<(32-ncm->ncm_BlockShift));
2574 while(dataremain)
2576 KPRINTF(10, ("Reading from block %ld, %ld bytes left...\n", startblock, dataremain));
2577 datalen = dataremain;
2578 if(datalen > maxtrans)
2580 datalen = maxtrans;
2582 scsicmd.scsi_Data = (UWORD *) &(((UBYTE *) ioreq->io_Data)[dataoffset]);
2583 scsicmd.scsi_Length = datalen;
2584 scsicmd.scsi_Flags = SCSIF_READ|SCSIF_AUTOSENSE|0x80;
2585 scsicmd.scsi_SenseData = sensedata;
2586 scsicmd.scsi_SenseLength = 18;
2587 if(startblockhigh)
2589 ULONG *cmd16sbh = (ULONG *)&cmd16[2];
2590 ULONG *cmd16sbl = (ULONG *)&cmd16[6];
2591 // Arithmetics for >2 TB needed
2592 scsicmd.scsi_Command = cmd16;
2593 scsicmd.scsi_CmdLength = 16;
2594 cmd16[0] = SCSI_DA_READ_16;
2595 cmd16[1] = 0;
2596 *cmd16sbh = AROS_LONG2BE(startblockhigh);
2597 *cmd16sbl = AROS_LONG2BE(startblock);
2598 cmd16[10] = datalen>>(ncm->ncm_BlockShift+24);
2599 cmd16[11] = datalen>>(ncm->ncm_BlockShift+16);
2600 cmd16[12] = datalen>>(ncm->ncm_BlockShift+8);
2601 cmd16[13] = datalen>>ncm->ncm_BlockShift;
2602 cmd16[14] = 0;
2603 cmd16[15] = 0;
2604 } else {
2605 ULONG *cmd10sb = (ULONG *)&cmd10[2];
2606 scsicmd.scsi_Command = cmd10;
2607 scsicmd.scsi_CmdLength = 10;
2608 cmd10[0] = SCSI_DA_READ_10;
2609 cmd10[1] = 0;
2610 *cmd10sb = AROS_LONG2BE(startblock);
2611 cmd10[6] = 0;
2612 cmd10[7] = datalen>>(ncm->ncm_BlockShift+8);
2613 cmd10[8] = datalen>>ncm->ncm_BlockShift;
2614 cmd10[9] = 0;
2616 if((ioreq->io_Error = nScsiDirect(ncm, &scsicmd)))
2618 KPRINTF(10, ("Read error!\n"));
2619 break;
2621 dataoffset += datalen;
2622 dataremain -= datalen;
2623 oldstartblock = startblock;
2624 startblock += datalen>>ncm->ncm_BlockShift;
2625 if(startblock < oldstartblock)
2627 // wrap around occurred
2628 startblockhigh++;
2631 ioreq->io_Actual = dataoffset;
2632 return(ioreq->io_Error);
2634 /* \\\ */
2636 /* /// "nSeek64()" */
2637 LONG nSeek64(struct NepClassMS *ncm, struct IOStdReq *ioreq)
2639 UBYTE cmd10[10];
2640 ULONG *cmd10sb = (ULONG *)&cmd10[2];
2641 UBYTE sensedata[18];
2642 struct SCSICmd scsicmd;
2643 ULONG startblock;
2645 if(!ncm->ncm_BlockSize)
2647 nGetBlockSize(ncm);
2649 if(((ioreq->io_Offset >> ncm->ncm_BlockShift)<<ncm->ncm_BlockShift) != ioreq->io_Offset)
2651 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2652 "Attempt to to seek to unaligned block (%ld %% %ld != 0)!",
2653 ioreq->io_Offset, ncm->ncm_BlockSize);
2654 if(ncm->ncm_BlockSize != 512)
2656 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2657 "The used FileSystem or other software must support %ld byte blocks!",
2658 ncm->ncm_BlockSize);
2660 ioreq->io_Actual = 0;
2661 return(ioreq->io_Error = IOERR_BADADDRESS);
2664 startblock = (ioreq->io_Offset>>ncm->ncm_BlockShift)|(ioreq->io_Actual<<(32-ncm->ncm_BlockShift));
2665 scsicmd.scsi_Data = NULL;
2666 scsicmd.scsi_Length = 0;
2667 scsicmd.scsi_CmdLength = 10;
2668 scsicmd.scsi_Flags = SCSIF_READ|SCSIF_AUTOSENSE|0x80;
2669 scsicmd.scsi_SenseData = sensedata;
2670 scsicmd.scsi_SenseLength = 18;
2671 cmd10[0] = SCSI_DA_SEEK_10;
2672 cmd10[1] = 0;
2673 *cmd10sb = AROS_LONG2BE(startblock);
2674 cmd10[6] = 0;
2675 cmd10[7] = 0;
2676 cmd10[8] = 0;
2677 cmd10[9] = 0;
2678 if((ioreq->io_Error = nScsiDirect(ncm, &scsicmd)))
2680 KPRINTF(10, ("Seek error!\n"));
2682 ioreq->io_Actual = 0;
2683 return(ioreq->io_Error);
2685 /* \\\ */
2687 /* /// "nWrite64()" */
2688 LONG nWrite64(struct NepClassMS *ncm, struct IOStdReq *ioreq)
2690 UBYTE cmd10[10];
2691 UBYTE cmd16[16];
2692 UBYTE sensedata[18];
2693 ULONG dataoffset = 0;
2694 ULONG dataremain = ioreq->io_Length;
2695 ULONG datalen;
2696 ULONG startblockhigh;
2697 ULONG startblock;
2698 ULONG oldstartblock;
2699 ULONG maxtrans = 1UL<<(ncm->ncm_CDC->cdc_MaxTransfer+16);
2700 struct SCSICmd scsicmd;
2702 if(!ncm->ncm_BlockSize)
2704 nGetBlockSize(ncm);
2706 if(((dataremain >> ncm->ncm_BlockShift)<<ncm->ncm_BlockShift != dataremain) ||
2707 ((ioreq->io_Offset >> ncm->ncm_BlockShift)<<ncm->ncm_BlockShift != ioreq->io_Offset))
2709 KPRINTF(20, ("unaligned write access offset %ld, length %ld...\n", ioreq->io_Offset, dataremain));
2710 if((!(ncm->ncm_CDC->cdc_PatchFlags & PFF_EMUL_LARGE_BLK)) && (!(ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_FALLBACK)))
2712 ncm->ncm_CDC->cdc_PatchFlags |= PFF_EMUL_LARGE_BLK;
2713 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2714 "Fallback: Enabling emulation for large block devices.");
2715 GM_UNIQUENAME(nStoreConfig)(ncm);
2717 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_EMUL_LARGE_BLK)
2719 return(nWrite64Emul(ncm, ioreq));
2721 if((dataremain >> ncm->ncm_BlockShift)<<ncm->ncm_BlockShift != dataremain)
2723 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2724 "Attempt to write partial block (%ld %% %ld != 0)!",
2725 dataremain, ncm->ncm_BlockSize);
2726 ioreq->io_Error = IOERR_BADLENGTH;
2727 } else {
2728 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2729 "Attempt to write unaligned block (%ld %% %ld != 0)!",
2730 ioreq->io_Offset, ncm->ncm_BlockSize);
2731 ioreq->io_Error = IOERR_BADADDRESS;
2733 if(ncm->ncm_BlockSize != 512)
2735 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2736 "The used FileSystem or other software must support %ld byte blocks!",
2737 ncm->ncm_BlockSize);
2739 ioreq->io_Actual = 0;
2740 return(ioreq->io_Error);
2743 startblockhigh = ioreq->io_Actual>>ncm->ncm_BlockShift;
2744 startblock = (ioreq->io_Offset>>ncm->ncm_BlockShift)|(ioreq->io_Actual<<(32-ncm->ncm_BlockShift));
2745 while(dataremain)
2747 datalen = dataremain;
2748 if(datalen > maxtrans)
2750 datalen = maxtrans;
2752 scsicmd.scsi_Data = (UWORD *) &(((UBYTE *) ioreq->io_Data)[dataoffset]);
2753 scsicmd.scsi_Length = datalen;
2754 scsicmd.scsi_Flags = SCSIF_WRITE|SCSIF_AUTOSENSE|0x80;
2755 scsicmd.scsi_SenseData = sensedata;
2756 scsicmd.scsi_SenseLength = 18;
2757 if(startblockhigh)
2759 ULONG *cmd16sbh = (ULONG *)&cmd16[2];
2760 ULONG *cmd16sbl = (ULONG *)&cmd16[6];
2761 // Arithmetics for >2 TB needed
2762 scsicmd.scsi_Command = cmd16;
2763 scsicmd.scsi_CmdLength = 16;
2764 cmd16[0] = SCSI_DA_WRITE_16;
2765 cmd16[1] = 0;
2766 *cmd16sbh = AROS_LONG2BE(startblockhigh);
2767 *cmd16sbl = AROS_LONG2BE(startblock);
2768 cmd16[10] = datalen>>(ncm->ncm_BlockShift+24);
2769 cmd16[11] = datalen>>(ncm->ncm_BlockShift+16);
2770 cmd16[12] = datalen>>(ncm->ncm_BlockShift+8);
2771 cmd16[13] = datalen>>ncm->ncm_BlockShift;
2772 cmd16[14] = 0;
2773 cmd16[15] = 0;
2774 } else {
2775 ULONG *cmd10sb = (ULONG *)&cmd10[2];
2776 scsicmd.scsi_Command = cmd10;
2777 scsicmd.scsi_CmdLength = 10;
2778 cmd10[0] = SCSI_DA_WRITE_10;
2779 cmd10[1] = 0;
2780 *cmd10sb = AROS_LONG2BE(startblock);
2781 cmd10[6] = 0;
2782 cmd10[7] = datalen>>(ncm->ncm_BlockShift+8);
2783 cmd10[8] = datalen>>ncm->ncm_BlockShift;
2784 cmd10[9] = 0;
2786 if((ioreq->io_Error = nScsiDirect(ncm, &scsicmd)))
2788 break;
2790 dataoffset += datalen;
2791 dataremain -= datalen;
2792 oldstartblock = startblock;
2793 startblock += datalen>>ncm->ncm_BlockShift;
2794 if(startblock < oldstartblock)
2796 // wrap around occurred
2797 startblockhigh++;
2800 ioreq->io_Actual = dataoffset;
2801 return(ioreq->io_Error);
2803 /* \\\ */
2805 /* /// "nCBIRequestSense()" */
2806 LONG nCBIRequestSense(struct NepClassMS *ncm, UBYTE *senseptr, ULONG datalen)
2808 LONG ioerr;
2809 UBYTE sensecmd[12];
2810 LONG actual = 0;
2811 struct UsbMSCBIStatusWrapper umscsw;
2813 memset(sensecmd, 0, 12);
2814 senseptr[2] = SK_ILLEGAL_REQUEST;
2815 sensecmd[0] = SCSI_REQUEST_SENSE;
2816 sensecmd[1] = 0x00;
2817 sensecmd[2] = 0x00;
2818 sensecmd[3] = 0x00;
2819 sensecmd[4] = datalen;
2820 sensecmd[5] = 0;
2821 KPRINTF(2, ("sense command block phase...\n"));
2823 /*psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
2824 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
2825 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);*/
2826 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_CLASS|URTF_INTERFACE,
2827 UMSR_ADSC, 0, (ULONG) ncm->ncm_UnitIfNum);
2828 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, sensecmd, ((ncm->ncm_CSType == MS_ATAPI_SUBCLASS) ||
2829 (ncm->ncm_CSType == MS_FDDATAPI_SUBCLASS) ||
2830 (ncm->ncm_CSType == MS_UFI_SUBCLASS)) ? (ULONG) 12 : (ULONG) 6);
2831 if(!ioerr)
2833 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_CLEAR_EP)
2835 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
2836 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
2837 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
2840 KPRINTF(2, ("sense data phase %ld bytes...\n", datalen));
2841 ioerr = psdDoPipe(ncm->ncm_EPInPipe, senseptr, datalen);
2842 actual = psdGetPipeActual(ncm->ncm_EPInPipe);
2843 if(ioerr == UHIOERR_STALL)
2845 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
2846 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
2847 psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
2849 if((!ioerr) || (ioerr == UHIOERR_RUNTPACKET))
2851 KPRINTF(2, ("sense command status phase...\n"));
2852 if(ncm->ncm_TPType == MS_PROTO_CBI)
2854 umscsw.bType = 0;
2855 umscsw.bValue = USMF_CSW_PHASEERR;
2856 ioerr = psdDoPipe(ncm->ncm_EPIntPipe, &umscsw, sizeof(struct UsbMSCBIStatusWrapper));
2857 if(ioerr && (ioerr != UHIOERR_RUNTPACKET))
2859 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2860 "Status interrupt failed: %s (%ld)",
2861 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2862 return(0);
2864 umscsw.bValue &= USMF_CSW_PERSIST; /* mask out other bits */
2865 } else {
2866 umscsw.bType = 0;
2867 umscsw.bValue = USMF_CSW_PASS;
2868 ioerr = 0;
2870 if((!ioerr) || (ioerr == UHIOERR_RUNTPACKET))
2872 KPRINTF(2, ("sense Status:\n"
2873 " Status : %02lx\n",
2874 umscsw.bValue));
2875 if(umscsw.bValue)
2877 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2878 "Sense failed: %ld",
2879 umscsw.bValue);*/
2880 if(umscsw.bValue == USMF_CSW_PHASEERR)
2882 return(0);
2884 } else {
2885 switch(senseptr[2] & SK_MASK)
2887 case SK_UNIT_ATTENTION:
2888 if((senseptr[12] == 0x28) ||
2889 (senseptr[12] == 0x3A))
2891 ncm->ncm_ChangeCount++;
2893 break;
2896 if((ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG) && (senseptr[2] & SK_MASK))
2898 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2899 "Request Sense Key %lx/%02lx/%02lx",
2900 senseptr[2] & SK_MASK,
2901 senseptr[12],
2902 senseptr[13]);
2905 } else {
2906 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2907 "Sense status failed: %s (%ld)",
2908 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2910 } else {
2911 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2912 "Sense data failed: %s (%ld)",
2913 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2915 } else {
2916 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2917 "Sense block failed: %s (%ld)",
2918 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2920 return(actual);
2922 /* \\\ */
2924 /* /// "nBulkReset()" */
2925 LONG nBulkReset(struct NepClassMS *ncm)
2927 LONG ioerr;
2928 LONG ioerr2 = 0;
2929 static UBYTE cbiresetcmd12[12] = { 0x1D, 0x04, 0xFF, 0xFF, 0xFF, 0xFF,
2930 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
2931 //struct UsbMSCBIStatusWrapper umscsw;
2932 //UBYTE sensedata[18];
2933 if(ncm->ncm_DenyRequests)
2935 return UHIOERR_TIMEOUT;
2937 KPRINTF(1, ("Bulk Reset\n"));
2938 //psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Bulk Reset...");
2939 switch(ncm->ncm_TPType)
2941 case MS_PROTO_BULK:
2942 if(!ncm->ncm_BulkResetBorks)
2944 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_CLASS|URTF_INTERFACE,
2945 UMSR_BULK_ONLY_RESET, 0, (ULONG) ncm->ncm_UnitIfNum);
2946 ioerr2 = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
2947 if(ioerr2 == UHIOERR_TIMEOUT)
2949 return(ioerr2);
2951 if(ioerr2)
2953 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2954 "BULK_ONLY_RESET failed: %s (%ld)",
2955 psdNumToStr(NTS_IOERR, ioerr2, "unknown"), ioerr2);
2956 ncm->ncm_BulkResetBorks = TRUE;
2958 if(ncm->ncm_DenyRequests)
2960 return ioerr2;
2963 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
2964 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
2965 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
2966 if(ioerr)
2968 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2969 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
2970 ncm->ncm_EPInNum, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2972 if(ncm->ncm_DenyRequests)
2974 return ioerr;
2976 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
2977 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPOutNum);
2978 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
2979 if(ioerr)
2981 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2982 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
2983 ncm->ncm_EPOutNum, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2985 return(ioerr2 ? ioerr2 : ioerr);
2987 case MS_PROTO_CBI:
2988 case MS_PROTO_CB:
2989 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_CLASS|URTF_INTERFACE,
2990 UMSR_ADSC, 0, (ULONG) ncm->ncm_UnitIfNum);
2991 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, cbiresetcmd12, 12);
2992 if(ioerr)
2994 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2995 "CBI_RESET failed: %s (%ld)",
2996 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2998 if(ncm->ncm_DenyRequests)
3000 return ioerr;
3002 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3003 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
3004 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
3005 if(ioerr)
3007 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3008 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
3009 ncm->ncm_EPInNum, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
3011 if(ncm->ncm_DenyRequests)
3013 return ioerr;
3015 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3016 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPOutNum);
3017 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
3018 if(ioerr)
3020 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3021 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
3022 ncm->ncm_EPOutNum, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
3024 //nCBIRequestSense(ncm, sensedata, 18);
3025 return(ioerr);
3027 return(0);
3029 /* \\\ */
3031 /* /// "nBulkClear()" */
3032 LONG nBulkClear(struct NepClassMS *ncm)
3034 LONG ioerr;
3035 if(ncm->ncm_DenyRequests)
3037 return UHIOERR_TIMEOUT;
3039 KPRINTF(1, ("Bulk Clear\n"));
3040 //psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Bulk Clear...");
3041 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3042 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
3043 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
3044 if(ioerr == UHIOERR_TIMEOUT)
3046 return(ioerr);
3048 if(ioerr)
3050 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3051 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
3052 ncm->ncm_EPInNum, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
3054 if(ncm->ncm_DenyRequests)
3056 return ioerr;
3058 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3059 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPOutNum);
3060 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
3061 if(ioerr)
3063 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3064 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
3065 ncm->ncm_EPOutNum, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
3067 return(ioerr);
3069 /* \\\ */
3071 /* /// "nScsiDirect()" */
3072 LONG nScsiDirect(struct NepClassMS *ncm, struct SCSICmd *scsicmd)
3074 STRPTR prodname;
3075 STRPTR vendname;
3076 UBYTE cmd12[12];
3077 struct SCSICmd scsicmd10;
3078 BOOL usecmd10 = FALSE;
3079 LONG res;
3080 UBYTE *sensedata = NULL;
3081 UBYTE *buf;
3082 BOOL xlate = FALSE;
3083 ULONG pf = ncm->ncm_CDC->cdc_PatchFlags;
3085 scsicmd->scsi_Actual = 0;
3086 scsicmd->scsi_CmdActual = 0;
3087 scsicmd->scsi_SenseActual = 0;
3089 if(((pf & PFF_MODE_XLATE) && (scsicmd->scsi_CmdLength == 6)) ||
3090 (ncm->ncm_CSType == MS_FDDATAPI_SUBCLASS) ||
3091 (ncm->ncm_CSType == MS_ATAPI_SUBCLASS) ||
3092 (ncm->ncm_CSType == MS_UFI_SUBCLASS))
3094 xlate = TRUE;
3097 if(pf & PFF_SIMPLE_SCSI)
3099 if(scsicmd->scsi_Flags & SCSIF_AUTOSENSE)
3101 if(scsicmd->scsi_SenseLength > 18)
3103 KPRINTF(10, ("Fixing Sense Length to 18!\n"));
3104 scsicmd->scsi_SenseLength = 18;
3107 switch(scsicmd->scsi_Command[0])
3109 case SCSI_TEST_UNIT_READY:
3110 case SCSI_INQUIRY:
3111 //case SCSI_LOG_SELECT:
3112 //case SCSI_LOG_SENSE:
3113 case SCSI_REQUEST_SENSE:
3114 //case SCSI_MODE_SELECT_6:
3115 //case SCSI_MODE_SELECT_10:
3116 //case SCSI_MODE_SENSE_6:
3117 //case SCSI_MODE_SENSE_10:
3118 case SCSI_DA_READ_6:
3119 case SCSI_DA_READ_10:
3120 case SCSI_DA_READ_CAPACITY:
3121 case SCSI_DA_SEEK_6:
3122 case SCSI_DA_SEEK_10:
3123 case SCSI_DA_WRITE_6:
3124 case SCSI_DA_WRITE_10:
3125 break;
3127 case SCSI_MODE_SENSE_6:
3129 UWORD modepage = scsicmd->scsi_Command[2] & 0x3f;
3130 UBYTE *data = (UBYTE *) scsicmd->scsi_Data;
3131 if((modepage == 0x3f) ||
3132 (modepage == 0x03) ||
3133 (modepage == 0x04) ||
3134 (modepage == 0x05))
3136 if(!(ncm->ncm_BlockSize && ncm->ncm_Geometry.dg_TotalSectors))
3138 nGetBlockSize(ncm);
3140 if(ncm->ncm_Geometry.dg_TotalSectors)
3142 nFakeGeometry(ncm, &ncm->ncm_Geometry);
3143 ncm->ncm_GeoChangeCount = ncm->ncm_ChangeCount;
3145 memset(data, 0, (size_t) scsicmd->scsi_Length);
3146 scsicmd->scsi_Status = SCSI_GOOD;
3148 if(modepage == 0x3f) // all available mode pages
3150 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Simple SCSI: Faking All Mode Pages 0x03-0x05");
3151 data[0] = 3+2+22+2+22+2+30;
3152 data += 4;
3153 scsicmd->scsi_Actual = 4;
3154 if(scsicmd->scsi_Length >= 4+2+22)
3156 data[0] = 0x03; // mode page
3157 data[1] = 22; // page length
3158 data[10] = ncm->ncm_Geometry.dg_TrackSectors>>8;
3159 data[11] = ncm->ncm_Geometry.dg_TrackSectors;
3160 data[12] = ncm->ncm_Geometry.dg_SectorSize>>8;
3161 data[13] = ncm->ncm_Geometry.dg_SectorSize;
3162 data += 2+22;
3163 scsicmd->scsi_Actual += 2+22;
3165 if(scsicmd->scsi_Length >= 4+2+22+2+22)
3167 data[0] = 0x04; // mode page
3168 data[1] = 22; // page length
3169 data[2] = ncm->ncm_Geometry.dg_Cylinders>>16;
3170 data[3] = ncm->ncm_Geometry.dg_Cylinders>>8;
3171 data[4] = ncm->ncm_Geometry.dg_Cylinders;
3172 data[5] = ncm->ncm_Geometry.dg_Heads;
3173 data += 2+22;
3174 scsicmd->scsi_Actual += 2+22;
3176 if(scsicmd->scsi_Length >= 4+2+22+2+22+2+30)
3178 data[0] = 0x05; // mode page
3179 data[1] = 30; // page length
3180 data[4] = ncm->ncm_Geometry.dg_Heads;
3181 data[5] = ncm->ncm_Geometry.dg_TrackSectors;
3182 data[6] = ncm->ncm_Geometry.dg_SectorSize>>8;
3183 data[7] = ncm->ncm_Geometry.dg_SectorSize;
3184 data[8] = ncm->ncm_Geometry.dg_Cylinders>>8;
3185 data[9] = ncm->ncm_Geometry.dg_Cylinders;
3186 //data += 2+30;
3187 scsicmd->scsi_Actual += 2+30;
3189 return(0);
3191 else if((modepage == 0x03) && (scsicmd->scsi_Length >= 6+22)) // Format Device mode page
3193 // fake geometry request
3194 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Simple SCSI: Faking Mode Page 0x03 (Format Device)");
3196 data[0] = 5+22; // length
3197 data += 4;
3198 data[0] = 0x03; // mode page
3199 data[1] = 22; // page length
3200 data[10] = ncm->ncm_Geometry.dg_TrackSectors>>8;
3201 data[11] = ncm->ncm_Geometry.dg_TrackSectors;
3202 data[12] = ncm->ncm_Geometry.dg_SectorSize>>8;
3203 data[13] = ncm->ncm_Geometry.dg_SectorSize;
3204 scsicmd->scsi_Actual = 6+22;
3205 return(0);
3207 else if((modepage == 0x04) && (scsicmd->scsi_Length >= 6+22)) // Rigid Disk Geometry mode page
3209 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Simple SCSI: Faking Mode Page 0x04 (Rigid Disk Geometry)");
3210 data[0] = 5+22; // length
3211 data += 4;
3212 data[0] = 0x04; // mode page
3213 data[1] = 22; // page length
3214 data[2] = ncm->ncm_Geometry.dg_Cylinders>>16;
3215 data[3] = ncm->ncm_Geometry.dg_Cylinders>>8;
3216 data[4] = ncm->ncm_Geometry.dg_Cylinders;
3217 data[5] = ncm->ncm_Geometry.dg_Heads;
3218 scsicmd->scsi_Actual = 6+22;
3219 return(0);
3221 else if((modepage == 0x05) && (scsicmd->scsi_Length >= 6+30)) // Flexible Disk mode page
3223 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Simple SCSI: Faking Mode Page 0x05 (Flexible Disk)");
3224 data[0] = 5+30; // length
3225 data += 4;
3226 data[0] = 0x05; // mode page
3227 data[1] = 30; // page length
3228 data[4] = ncm->ncm_Geometry.dg_Heads;
3229 data[5] = ncm->ncm_Geometry.dg_TrackSectors;
3230 data[6] = ncm->ncm_Geometry.dg_SectorSize>>8;
3231 data[7] = ncm->ncm_Geometry.dg_SectorSize;
3232 data[8] = ncm->ncm_Geometry.dg_Cylinders>>8;
3233 data[9] = ncm->ncm_Geometry.dg_Cylinders;
3234 scsicmd->scsi_Actual = 6+30;
3235 return(0);
3237 // fall through
3240 case 0x51: // drive ready
3241 case SCSI_CD_READ_TOC:
3242 case SCSI_CD_PAUSE_RESUME:
3243 case SCSI_CD_PLAY_AUDIO_10:
3244 case SCSI_CD_PLAY_AUDIO_12:
3245 case SCSI_CD_PLAY_AUDIO_MSF:
3246 case SCSI_CD_PLAY_AUDIO_TRACK_INDEX:
3247 case SCSI_CD_PLAY_TRACK_RELATIVE_10:
3248 case SCSI_CD_PLAY_TRACK_RELATIVE_12:
3249 case SCSI_CD_BLANK:
3250 case SCSI_CD_CLOSE_TRACK:
3251 case SCSI_CD_GET_CONFIGURATION:
3252 case SCSI_CD_GET_EVENT_STATUS_NOTIFICATION:
3253 case SCSI_CD_GET_PERFORMANCE:
3254 case SCSI_CD_LOAD_UNLOAD_MEDIUM:
3255 case SCSI_DA_START_STOP_UNIT:
3256 case SCSI_CD_MECHANISM_STATUS:
3257 case SCSI_CD_PRE_FETCH:
3258 case SCSI_CD_PREVENT_ALLOW_MEDIUM_REMOVAL:
3259 case SCSI_CD_READ_HEADER:
3260 case SCSI_CD_READ_SUB_CHANNEL:
3261 if((scsicmd->scsi_Command[0] != SCSI_MODE_SENSE_6) &&
3262 ((ncm->ncm_DeviceType == PDT_WORM) || (ncm->ncm_DeviceType == PDT_CDROM)))
3264 // allows these CD rom commands even with SimpleSCSI enabled.
3265 break;
3268 default:
3270 UBYTE cmdstrbuf[16*3+2];
3272 GM_UNIQUENAME(nHexString)(scsicmd->scsi_Command, (ULONG) (scsicmd->scsi_CmdLength < 16 ? scsicmd->scsi_CmdLength : 16), cmdstrbuf);
3273 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Simple SCSI: Filtering SCSI command %s", cmdstrbuf);
3275 scsicmd->scsi_Status = SCSI_CHECK_CONDITION;
3276 scsicmd->scsi_SenseActual = 0;
3277 if(scsicmd->scsi_Flags & SCSIF_AUTOSENSE)
3279 if(scsicmd->scsi_SenseLength >= 18)
3281 memset(scsicmd->scsi_SenseData, 0x00, 18);
3282 scsicmd->scsi_SenseData[0] = 0x80|0x70;
3283 scsicmd->scsi_SenseData[2] = SK_ILLEGAL_REQUEST;
3284 scsicmd->scsi_SenseData[12] = 0x20; // unsupported command
3285 scsicmd->scsi_SenseActual = 18;
3288 return(-1);
3293 if((scsicmd->scsi_Command[0] == SCSI_TEST_UNIT_READY) && scsicmd->scsi_Length)
3295 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Bogus TEST_UNIT_READY data length set to 0.");
3296 scsicmd->scsi_Length = 0;
3299 if(pf & PFF_FAKE_INQUIRY)
3301 if(scsicmd->scsi_Command[0] == SCSI_INQUIRY)
3303 if(scsicmd->scsi_Length >= 36)
3305 UBYTE *data = (UBYTE *) scsicmd->scsi_Data;
3306 if(pf & PFF_DEBUG)
3308 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Faking Inquiry.");
3310 KPRINTF(10, ("Faking INQUIRY!\n"));
3311 psdGetAttrs(PGA_DEVICE, ncm->ncm_Device,
3312 DA_ProductName, &prodname,
3313 DA_Manufacturer, &vendname,
3314 TAG_END);
3315 memset(data, 0x00, (size_t) scsicmd->scsi_Length);
3316 data[1] = 0x80; // removable media
3317 data[2] = 0x02; // 0x03 would be ANSI X3.301:1997 (SPC).
3318 data[3] = 0x02; // Response data format = 2
3319 data[4] = 32; // additional length n-4
3320 CopyMem(vendname, &data[8], (ULONG) ((strlen(vendname) < 8) ? strlen(vendname) : 8));
3321 CopyMem(prodname, &data[16], (ULONG) ((strlen(prodname) < 16) ? strlen(prodname) : 16));
3322 scsicmd->scsi_CmdActual = scsicmd->scsi_CmdLength;
3323 scsicmd->scsi_Status = SCSI_GOOD;
3324 scsicmd->scsi_SenseActual = 0;
3325 return(0);
3327 return(-1);
3331 if(pf & PFF_FIX_INQ36)
3333 if((scsicmd->scsi_Command)[0] == SCSI_INQUIRY)
3335 if(scsicmd->scsi_Length > 36)
3337 if(pf & PFF_DEBUG)
3339 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Fixing Inquiry.");
3342 KPRINTF(10, ("Fixing INQUIRY!\n"));
3343 scsicmd->scsi_Length = 36;
3345 else if(scsicmd->scsi_Length < 36)
3347 if(pf & PFF_DEBUG)
3349 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3350 "Couldn't fix Inquiry < %ld.",
3351 scsicmd->scsi_Length);
3353 KPRINTF(10, ("Couldn't fix INQUIRY!\n"));
3358 if(xlate)
3360 scsicmd10 = *scsicmd;
3361 scsicmd10.scsi_Command = cmd12;
3362 scsicmd10.scsi_CmdLength = 10;
3363 memset(cmd12, 0x00, 12);
3364 switch(scsicmd->scsi_Command[0])
3366 case SCSI_DA_READ_6:
3367 case SCSI_DA_WRITE_6:
3368 case SCSI_DA_SEEK_6:
3369 cmd12[0] = scsicmd->scsi_Command[0] | 0x20;
3370 cmd12[1] = scsicmd->scsi_Command[1] & 0xe0;
3371 cmd12[3] = scsicmd->scsi_Command[1] & 0x1f;
3372 cmd12[4] = scsicmd->scsi_Command[2];
3373 cmd12[5] = scsicmd->scsi_Command[3];
3374 cmd12[8] = scsicmd->scsi_Command[4];
3375 cmd12[9] = scsicmd->scsi_Command[5];
3376 usecmd10 = TRUE;
3377 break;
3379 case SCSI_MODE_SELECT_6:
3380 cmd12[0] = SCSI_MODE_SELECT_10;
3381 cmd12[1] = scsicmd->scsi_Command[1];
3382 //cmd12[2] = scsicmd->scsi_Command[2]; // reserved
3383 //cmd12[3] = scsicmd->scsi_Command[3]; // reserved
3384 cmd12[7] = (scsicmd->scsi_Command[4]+4)>>8;
3385 cmd12[8] = scsicmd->scsi_Command[4]+4;
3386 cmd12[9] = scsicmd->scsi_Command[5];
3388 sensedata = psdAllocVec(scsicmd->scsi_Length+4);
3389 if(sensedata && (scsicmd->scsi_Length >= 4))
3391 buf = (UBYTE *) scsicmd->scsi_Data;
3392 sensedata[1] = *buf++;
3393 sensedata[2] = *buf++;
3394 sensedata[3] = *buf++;
3395 sensedata[7] = *buf++;
3397 scsicmd10.scsi_Length = scsicmd->scsi_Length+4;
3398 scsicmd10.scsi_Data = (UWORD *) sensedata;
3400 CopyMem(buf, &sensedata[8], scsicmd->scsi_Length-4);
3402 usecmd10 = TRUE;
3403 break;
3405 case SCSI_MODE_SENSE_6:
3406 cmd12[0] = SCSI_MODE_SENSE_10;
3407 cmd12[1] = scsicmd->scsi_Command[1] & 0xf7;
3408 cmd12[2] = scsicmd->scsi_Command[2];
3409 cmd12[3] = scsicmd->scsi_Command[3];
3410 // Workaround: Some devices are seriously broken and do not interpret
3411 // the upper byte of the allocation length field.
3412 // Hence they return 3 bytes instead of 259 bytes. For this special case,
3413 // we will simply truncate the size by four, to get back to a 255 byte
3414 // buffer.
3415 if((scsicmd->scsi_Command[4] > 251) && (scsicmd->scsi_Length == scsicmd->scsi_Command[4]))
3417 scsicmd->scsi_Command[4] -= 4;
3418 scsicmd->scsi_Length -= 4;
3420 cmd12[7] = (scsicmd->scsi_Command[4]+4)>>8;
3421 cmd12[8] = scsicmd->scsi_Command[4]+4;
3422 cmd12[9] = scsicmd->scsi_Command[5];
3423 sensedata = psdAllocVec(scsicmd->scsi_Length+4);
3424 if(sensedata)
3426 scsicmd10.scsi_Length = scsicmd->scsi_Length+4;
3427 scsicmd10.scsi_Data = (UWORD *) sensedata;
3429 usecmd10 = TRUE;
3430 break;
3434 if((ncm->ncm_CSType == MS_ATAPI_SUBCLASS) ||
3435 (ncm->ncm_CSType == MS_FDDATAPI_SUBCLASS) ||
3436 (ncm->ncm_CSType == MS_UFI_SUBCLASS))
3438 if(!usecmd10)
3440 scsicmd10 = *scsicmd;
3441 scsicmd10.scsi_Command = cmd12;
3442 memset(cmd12, 0x00, 12);
3443 CopyMem(scsicmd->scsi_Command, cmd12, (ULONG) scsicmd->scsi_CmdLength);
3444 usecmd10 = TRUE;
3446 scsicmd10.scsi_CmdLength = 12;
3447 if(ncm->ncm_CSType == MS_UFI_SUBCLASS)
3449 switch(cmd12[0])
3451 case SCSI_REQUEST_SENSE:
3452 cmd12[4] = 18; /* restrict UFI response to 18 bytes */
3453 scsicmd10.scsi_Flags &= ~SCSIF_AUTOSENSE;
3454 break;
3456 case SCSI_INQUIRY:
3457 KPRINTF(10, ("Disabling autosense for UFI!\n"));
3458 cmd12[4] = 36; /* restrict UFI response to 36 bytes */
3459 scsicmd10.scsi_Flags &= ~SCSIF_AUTOSENSE;
3460 break;
3462 case SCSI_MODE_SELECT_10:
3463 cmd12[7] = 0;
3464 cmd12[8] = 8;
3465 break;
3471 if(usecmd10)
3473 if(pf & PFF_DEBUG)
3475 UBYTE cmd1strbuf[16*3+2];
3476 UBYTE cmd2strbuf[16*3+2];
3478 GM_UNIQUENAME(nHexString)(scsicmd->scsi_Command, (ULONG) (scsicmd->scsi_CmdLength < 16 ? scsicmd->scsi_CmdLength : 16), cmd1strbuf);
3479 GM_UNIQUENAME(nHexString)(scsicmd10.scsi_Command, (ULONG) (scsicmd10.scsi_CmdLength < 16 ? scsicmd10.scsi_CmdLength : 16), cmd2strbuf);
3480 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3481 "Mode XLATE for %s -> %s", cmd1strbuf, cmd2strbuf);
3482 if(scsicmd->scsi_Length && (scsicmd10.scsi_Command[0] == SCSI_MODE_SELECT_10))
3484 GM_UNIQUENAME(nHexString)((UBYTE *) scsicmd->scsi_Data, (ULONG) (scsicmd->scsi_Length < 16 ? scsicmd->scsi_Length : 16), cmd1strbuf);
3485 GM_UNIQUENAME(nHexString)((UBYTE *) scsicmd10.scsi_Data, (ULONG) (scsicmd10.scsi_Length < 16 ? scsicmd10.scsi_Length : 16), cmd2strbuf);
3486 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3487 "Request: %s (%ld) -> %s (%ld)",
3488 cmd1strbuf, scsicmd->scsi_Length,
3489 cmd2strbuf, scsicmd10.scsi_Length);
3492 KPRINTF(20, ("Mode XLATE for cmd %lx\n", scsicmd->scsi_Command[0]));
3495 switch(ncm->ncm_TPType)
3497 case MS_PROTO_BULK:
3498 res = nScsiDirectBulk(ncm, usecmd10 ? &scsicmd10 : scsicmd);
3499 break;
3501 case MS_PROTO_CB:
3502 case MS_PROTO_CBI:
3503 res = nScsiDirectCBI(ncm, usecmd10 ? &scsicmd10 : scsicmd);
3504 break;
3506 default:
3507 return(-1);
3509 KPRINTF(20, ("Cmd done %ld\n", res));
3510 if(usecmd10)
3512 if(sensedata)
3514 scsicmd->scsi_Actual = 0;
3515 if(scsicmd10.scsi_Command[0] == SCSI_MODE_SENSE_10)
3517 UBYTE cmd1strbuf[16*3+2];
3518 UBYTE cmd2strbuf[16*3+2];
3520 if(scsicmd10.scsi_Actual >= 8)
3522 scsicmd->scsi_Actual = scsicmd10.scsi_Actual - 4;
3523 buf = (UBYTE *) scsicmd->scsi_Data;
3524 *buf++ = sensedata[1];
3525 *buf++ = sensedata[2];
3526 *buf++ = sensedata[3];
3527 *buf++ = sensedata[7];
3528 CopyMem(&sensedata[8], buf, (ULONG) scsicmd10.scsi_Actual - 8);
3529 if(pf & PFF_DEBUG)
3531 GM_UNIQUENAME(nHexString)((UBYTE *) scsicmd10.scsi_Data, scsicmd10.scsi_Actual < 16 ? scsicmd10.scsi_Actual : 16, cmd1strbuf);
3532 GM_UNIQUENAME(nHexString)((UBYTE *) scsicmd->scsi_Data, scsicmd->scsi_Actual < 16 ? scsicmd->scsi_Actual : 16, cmd2strbuf);
3533 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3534 "Response: %s (%ld) -> %s (%ld)",
3535 cmd1strbuf, scsicmd10.scsi_Actual,
3536 cmd2strbuf, scsicmd->scsi_Actual);
3540 psdFreeVec(sensedata);
3541 } else {
3542 scsicmd->scsi_Actual = scsicmd10.scsi_Actual;
3544 scsicmd->scsi_CmdActual = scsicmd10.scsi_CmdActual;
3545 scsicmd->scsi_Status = scsicmd10.scsi_Status;
3546 scsicmd->scsi_SenseActual = scsicmd10.scsi_SenseActual;
3549 pf = ncm->ncm_CDC->cdc_PatchFlags;
3550 if((res == HFERR_Phase) && (!(pf & PFF_NO_FALLBACK)) && (!(pf & PFF_SIMPLE_SCSI)))
3552 switch(scsicmd->scsi_Command[0])
3554 case SCSI_TEST_UNIT_READY:
3555 case SCSI_INQUIRY:
3556 //case SCSI_LOG_SELECT:
3557 //case SCSI_LOG_SENSE:
3558 case SCSI_REQUEST_SENSE:
3559 //case SCSI_MODE_SELECT_6:
3560 //case SCSI_MODE_SELECT_10:
3561 //case SCSI_MODE_SENSE_6:
3562 //case SCSI_MODE_SENSE_10:
3563 case SCSI_DA_READ_6:
3564 case SCSI_DA_READ_10:
3565 case SCSI_DA_READ_CAPACITY:
3566 case SCSI_DA_SEEK_6:
3567 case SCSI_DA_SEEK_10:
3568 case SCSI_DA_WRITE_6:
3569 case SCSI_DA_WRITE_10:
3570 break;
3572 default:
3573 ncm->ncm_CDC->cdc_PatchFlags |= PFF_SIMPLE_SCSI;
3574 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3575 "Fallback: Enabling Simple SCSI.");
3576 GM_UNIQUENAME(nStoreConfig)(ncm);
3577 break;
3581 if((!res) && ((scsicmd->scsi_Command)[0] == SCSI_DA_READ_CAPACITY) && (pf & PFF_FIX_CAPACITY) && (scsicmd->scsi_Length >= 8))
3583 ULONG *capacity = ((ULONG *) scsicmd->scsi_Data);
3584 *capacity = AROS_LONG2BE(AROS_BE2LONG(*capacity)-1);
3585 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3586 "Fix Capacity: Correcting number of blocks.");
3589 if(res && (scsicmd->scsi_Command[0] == SCSI_INQUIRY))
3591 if((!(ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_FALLBACK)) && (!(ncm->ncm_CDC->cdc_PatchFlags & PFF_FIX_INQ36)))
3593 ncm->ncm_CDC->cdc_PatchFlags |= PFF_FIX_INQ36;
3594 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3595 "Fallback: Enabling Trim Inquiry.");
3596 GM_UNIQUENAME(nStoreConfig)(ncm);
3598 else if((!(ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_FALLBACK)) && (!(ncm->ncm_CDC->cdc_PatchFlags & PFF_FAKE_INQUIRY)))
3600 ncm->ncm_CDC->cdc_PatchFlags |= PFF_FAKE_INQUIRY;
3601 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3602 "Fallback: Enabling Fake Inquiry.");
3603 GM_UNIQUENAME(nStoreConfig)(ncm);
3607 if((ncm->ncm_DeviceType == PDT_WORM) ||
3608 (ncm->ncm_DeviceType == PDT_CDROM))
3610 // cd roms are always write protected
3611 ncm->ncm_WriteProtect = TRUE;
3612 return(res);
3614 // don't try to obtain write protection, when there's no media inserted.
3615 if(!ncm->ncm_UnitReady)
3617 return(res);
3619 if((!res) && (scsicmd->scsi_Command[0] == SCSI_MODE_SENSE_6))
3621 if(((UBYTE *) scsicmd->scsi_Data)[2] & 0x80)
3623 if(!ncm->ncm_WriteProtect)
3625 if(pf & PFF_REM_SUPPORT)
3627 ncm->ncm_ChangeCount++;
3628 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
3630 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3631 "Diskchange: Sense6WriteProtect On (count = %ld)",
3632 ncm->ncm_ChangeCount);
3635 ncm->ncm_WriteProtect = TRUE;
3637 } else {
3638 if(ncm->ncm_WriteProtect)
3640 if(pf & PFF_REM_SUPPORT)
3642 ncm->ncm_ChangeCount++;
3643 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
3645 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3646 "Diskchange: Sense6WriteProtect Off (count = %ld)",
3647 ncm->ncm_ChangeCount);
3650 ncm->ncm_WriteProtect = FALSE;
3654 if((!res) && (scsicmd->scsi_Command[0] == SCSI_MODE_SENSE_10))
3656 if(((UBYTE *) scsicmd->scsi_Data)[3] & 0x80)
3658 if(!ncm->ncm_WriteProtect)
3660 if(pf & PFF_REM_SUPPORT)
3662 ncm->ncm_ChangeCount++;
3663 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
3665 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3666 "Diskchange: Sense10WriteProtect On (count = %ld)",
3667 ncm->ncm_ChangeCount);
3670 ncm->ncm_WriteProtect = TRUE;
3672 } else {
3673 if(ncm->ncm_WriteProtect)
3675 if(pf & PFF_REM_SUPPORT)
3677 ncm->ncm_ChangeCount++;
3678 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
3680 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3681 "Diskchange: Sense10WriteProtect Off (count = %ld)",
3682 ncm->ncm_ChangeCount);
3685 ncm->ncm_WriteProtect = FALSE;
3689 return(res);
3691 /* \\\ */
3693 /* /// "nScsiDirectBulk()" */
3694 LONG nScsiDirectBulk(struct NepClassMS *ncm, struct SCSICmd *scsicmd)
3696 LONG ioerr;
3697 struct PsdPipe *pp;
3698 struct UsbMSCmdBlkWrapper umscbw;
3699 struct UsbMSCmdStatusWrapper umscsw;
3700 ULONG datalen;
3701 LONG rioerr;
3702 UWORD retrycnt = 0;
3703 UBYTE cmdstrbuf[16*3+2];
3705 KPRINTF(10, ("\n"));
3707 GM_UNIQUENAME(nHexString)(scsicmd->scsi_Command, (ULONG) (scsicmd->scsi_CmdLength < 16 ? scsicmd->scsi_CmdLength : 16), cmdstrbuf);
3709 if(scsicmd->scsi_Flags & 0x80) /* Autoretry */
3711 retrycnt = 1;
3713 umscbw.dCBWSignature = AROS_LONG2LE(0x43425355);
3714 scsicmd->scsi_Status = SCSI_GOOD;
3715 nLockXFer(ncm);
3718 KPRINTF(10, ("retrycnt %ld\n",retrycnt));
3719 if(ncm->ncm_DenyRequests)
3721 rioerr = HFERR_Phase;
3722 break;
3724 /*nBulkReset(ncm);*/
3726 rioerr = 0;
3728 /*psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3729 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
3730 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);*/
3732 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DELAY_DATA)
3734 psdDelayMS(1);
3737 datalen = scsicmd->scsi_Length;
3738 umscbw.dCBWTag = (IPTR) scsicmd + ++ncm->ncm_TagCount;
3739 umscbw.dCBWDataTransferLength = AROS_LONG2LE(datalen);
3740 umscbw.bmCBWFlags = scsicmd->scsi_Flags & SCSIF_READ ? 0x80 : 0x00;
3741 umscbw.bCBWLUN = ncm->ncm_UnitLUN;
3742 if((scsicmd->scsi_CmdLength) >= 16)
3744 CopyMemQuick(scsicmd->scsi_Command, umscbw.CBWCB, 16);
3745 umscbw.bCBWCBLength = scsicmd->scsi_CmdActual = 16;
3746 } else {
3747 memset(umscbw.CBWCB, 0, 16);
3748 CopyMem(scsicmd->scsi_Command, umscbw.CBWCB, (ULONG) scsicmd->scsi_CmdLength);
3749 umscbw.bCBWCBLength = scsicmd->scsi_CmdActual = scsicmd->scsi_CmdLength;
3751 //psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Issueing command %s Dlen=%ld", cmdstrbuf, datalen);
3753 KPRINTF(2, ("command block phase, tag %08lx, len %ld, flags %02lx...\n",
3754 umscbw.dCBWTag, scsicmd->scsi_CmdLength, scsicmd->scsi_Flags));
3755 KPRINTF(2, ("command: %s\n", cmdstrbuf));
3756 ioerr = psdDoPipe(ncm->ncm_EPOutPipe, &umscbw, UMSCBW_SIZEOF);
3757 if(ioerr == UHIOERR_STALL) /* Retry on stall */
3759 KPRINTF(2, ("stall...\n"));
3760 nBulkClear(ncm);
3761 ioerr = psdDoPipe(ncm->ncm_EPOutPipe, &umscbw, UMSCBW_SIZEOF);
3763 if(ncm->ncm_DenyRequests)
3765 rioerr = HFERR_Phase;
3766 break;
3768 if(!ioerr)
3770 if(datalen)
3772 KPRINTF(2, ("data phase %ld bytes...\n", datalen));
3773 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DELAY_DATA)
3775 psdDelayMS(1);
3777 pp = (scsicmd->scsi_Flags & SCSIF_READ) ? ncm->ncm_EPInPipe : ncm->ncm_EPOutPipe;
3778 ioerr = psdDoPipe(pp, scsicmd->scsi_Data, datalen);
3779 scsicmd->scsi_Actual = psdGetPipeActual(pp);
3780 if(ioerr == UHIOERR_OVERFLOW)
3782 KPRINTF(10, ("Extra Data received, but ignored!\n"));
3783 ioerr = 0;
3785 else if(ioerr == UHIOERR_STALL) /* Accept on stall */
3787 KPRINTF(2, ("stall...\n"));
3788 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3789 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT,
3790 (ULONG) ((scsicmd->scsi_Flags & SCSIF_READ) ? ncm->ncm_EPInNum|URTF_IN : ncm->ncm_EPOutNum));
3791 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
3793 else if(ioerr == UHIOERR_RUNTPACKET)
3795 KPRINTF(10, ("Runt packet ignored...\n"));
3796 ioerr = 0;
3797 /*psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3798 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT,
3799 (ULONG) ncm->ncm_EPInNum|URTF_IN);
3800 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);*/
3802 } else {
3803 ioerr = 0;
3804 scsicmd->scsi_Actual = 0;
3806 if(!ioerr)
3808 KPRINTF(2, ("command status phase...\n"));
3809 ioerr = psdDoPipe(ncm->ncm_EPInPipe, &umscsw, UMSCSW_SIZEOF);
3810 if(ioerr == UHIOERR_STALL) /* Retry on stall */
3812 KPRINTF(2, ("stall...\n"));
3813 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3814 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
3815 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
3816 /*nBulkClear(ncm);*/
3817 ioerr = psdDoPipe(ncm->ncm_EPInPipe, &umscsw, UMSCSW_SIZEOF);
3819 if(ioerr == UHIOERR_RUNTPACKET)
3821 // well, retry then
3822 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3823 "Command status block truncated (%ld bytes), retrying...",
3824 psdGetPipeActual(ncm->ncm_EPInPipe));
3825 ioerr = psdDoPipe(ncm->ncm_EPInPipe, &umscsw, UMSCSW_SIZEOF);
3827 if(ioerr == UHIOERR_OVERFLOW)
3829 KPRINTF(10, ("Extra Status received, but ignored!\n"));
3830 ioerr = 0;
3832 if(ncm->ncm_DenyRequests)
3834 rioerr = HFERR_Phase;
3835 break;
3837 if(!ioerr)
3839 KPRINTF(2, ("Status:\n"
3840 " Signature: %08lx\n"
3841 " Tag : %08lx\n"
3842 " Residue : %08lx\n"
3843 " Status : %02lx\n",
3844 umscsw.dCSWSignature,
3845 umscsw.dCSWTag,
3846 umscsw.dCSWDataResidue,
3847 umscsw.bCSWStatus));
3848 if(((umscsw.dCSWSignature != AROS_LONG2LE(0x53425355)) && (!(ncm->ncm_CDC->cdc_PatchFlags & PFF_CSS_BROKEN))) || (umscsw.dCSWTag != umscbw.dCBWTag))
3850 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Command (%s) failed:", cmdstrbuf);
3851 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
3852 "Illegal command status block (Sig:%08lx, Tag=%08lx/%08lx (TX/RX), Len=%ld)",
3853 umscsw.dCSWSignature,
3854 umscbw.dCBWTag,
3855 umscsw.dCSWTag,
3856 psdGetPipeActual(ncm->ncm_EPInPipe));
3857 scsicmd->scsi_Status = SCSI_CHECK_CONDITION;
3858 rioerr = HFERR_Phase;
3859 nBulkReset(ncm);
3860 continue;
3862 /* ignore this: too many firmwares report shit */
3863 //scsicmd->scsi_Actual = datalen - AROS_LONG2LE(umscsw.dCSWDataResidue);
3864 if((scsicmd->scsi_Actual > 7) && ((AROS_LONG2BE(*((ULONG *) scsicmd->scsi_Data))>>8) == 0x555342) && (((ULONG *) scsicmd->scsi_Data)[1] == umscbw.dCBWTag))
3866 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
3867 "Your MSD has a very bad firmware! Havoc!");
3868 scsicmd->scsi_Actual = 0;
3869 umscsw.bCSWStatus = USMF_CSW_FAIL;
3871 scsicmd->scsi_Status = umscsw.bCSWStatus;
3872 if(umscsw.bCSWStatus)
3874 if(umscsw.bCSWStatus == USMF_CSW_PHASEERR)
3876 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Command (%s) failed: %ld", cmdstrbuf, umscsw.bCSWStatus);
3877 nBulkReset(ncm);
3879 /* Autosensing required? */
3880 if(scsicmd->scsi_Flags & SCSIF_AUTOSENSE)
3882 /*nBulkClear(ncm);*/
3884 datalen = scsicmd->scsi_SenseLength;
3885 umscbw.dCBWTag = (IPTR) scsicmd + ++ncm->ncm_TagCount;
3886 umscbw.dCBWDataTransferLength = AROS_LONG2LE(datalen);
3887 umscbw.bmCBWFlags = 0x80;
3888 /*umscbw.bCBWLUN = ncm->ncm_UnitLun;*/
3889 umscbw.bCBWCBLength = 6;
3890 umscbw.CBWCB[0] = SCSI_REQUEST_SENSE;
3891 umscbw.CBWCB[1] = 0x00;
3892 umscbw.CBWCB[2] = 0x00;
3893 umscbw.CBWCB[3] = 0x00;
3894 umscbw.CBWCB[4] = datalen;
3895 umscbw.CBWCB[5] = 0;
3896 KPRINTF(2, ("sense command block phase...\n"));
3897 ioerr = psdDoPipe(ncm->ncm_EPOutPipe, &umscbw, UMSCBW_SIZEOF);
3898 if(ioerr == UHIOERR_STALL) /* Retry on stall */
3900 KPRINTF(2, ("stall...\n"));
3901 nBulkClear(ncm);
3902 ioerr = psdDoPipe(ncm->ncm_EPOutPipe, &umscbw, UMSCBW_SIZEOF);
3904 if(!ioerr)
3906 KPRINTF(2, ("sense data phase %ld bytes...\n", datalen));
3907 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DELAY_DATA)
3909 psdDelayMS(1);
3911 ioerr = psdDoPipe(ncm->ncm_EPInPipe, scsicmd->scsi_SenseData, datalen);
3912 scsicmd->scsi_SenseActual = psdGetPipeActual(ncm->ncm_EPInPipe);
3913 if(ioerr == UHIOERR_STALL) /* Accept on stall */
3915 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3916 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
3917 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
3919 if((ioerr == UHIOERR_RUNTPACKET) || (ioerr == UHIOERR_OVERFLOW))
3921 KPRINTF(10, ("Extra or less data received, but ignored!\n"));
3922 ioerr = 0;
3925 if(!ioerr)
3927 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DELAY_DATA)
3929 psdDelayMS(1);
3931 KPRINTF(2, ("sense command status phase...\n"));
3932 ioerr = psdDoPipe(ncm->ncm_EPInPipe, &umscsw, UMSCSW_SIZEOF);
3933 if(ioerr == UHIOERR_STALL) /* Retry on stall */
3935 KPRINTF(2, ("stall...\n"));
3936 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3937 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
3938 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
3939 ioerr |= psdDoPipe(ncm->ncm_EPInPipe, &umscsw, UMSCSW_SIZEOF);
3941 if(ioerr == UHIOERR_RUNTPACKET)
3943 // well, retry then
3944 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3945 "Command (sense) status block truncated (%ld bytes), retrying...",
3946 psdGetPipeActual(ncm->ncm_EPInPipe));
3947 ioerr = psdDoPipe(ncm->ncm_EPInPipe, &umscsw, UMSCSW_SIZEOF);
3950 if(ioerr == UHIOERR_OVERFLOW)
3952 KPRINTF(10, ("Extra Status received, but ignored!\n"));
3953 ioerr = 0;
3955 if(!ioerr)
3957 KPRINTF(2, ("sense Status:\n"
3958 " Signature: %08lx\n"
3959 " Tag : %08lx\n"
3960 " Residue : %08lx\n"
3961 " Status : %02lx\n",
3962 umscsw.dCSWSignature,
3963 umscsw.dCSWTag,
3964 umscsw.dCSWDataResidue,
3965 umscsw.bCSWStatus));
3966 if(((umscsw.dCSWSignature != AROS_LONG2LE(0x53425355)) && (!(ncm->ncm_CDC->cdc_PatchFlags & PFF_CSS_BROKEN))) || (umscsw.dCSWTag != umscbw.dCBWTag))
3968 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
3969 "Illegal command (sense) status block (Sig:%08lx, Tag=%08lx/%08lx (TX/RX), Len=%ld)",
3970 umscsw.dCSWSignature,
3971 umscbw.dCBWTag,
3972 umscsw.dCSWTag,
3973 psdGetPipeActual(ncm->ncm_EPInPipe));
3974 scsicmd->scsi_Status = SCSI_CHECK_CONDITION;
3975 rioerr = HFERR_Phase;
3976 nBulkReset(ncm);
3977 continue;
3979 /* ignore this: too many firmwares report shit */
3980 //scsicmd->scsi_SenseActual = datalen - AROS_LONG2LE(umscsw.dCSWDataResidue);
3981 if((scsicmd->scsi_SenseActual > 7) && ((AROS_LONG2BE(*((ULONG *) scsicmd->scsi_SenseData))>>8) == 0x555342) && (((ULONG *) scsicmd->scsi_SenseData)[1] == umscbw.dCBWTag))
3983 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
3984 "Your MSD has a very bad firmware! Havoc!");
3985 scsicmd->scsi_Actual = 0;
3986 umscsw.bCSWStatus = USMF_CSW_FAIL;
3989 if(umscsw.bCSWStatus)
3991 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3992 "Sense failed: %ld",
3993 umscsw.bCSWStatus);*/
3994 if(umscsw.bCSWStatus == USMF_CSW_PHASEERR)
3996 nBulkReset(ncm);
3998 } else {
3999 switch(scsicmd->scsi_SenseData[2] & SK_MASK)
4001 case SK_ILLEGAL_REQUEST:
4002 case SK_NOT_READY:
4003 retrycnt = 0;
4004 break;
4005 case SK_DATA_PROTECT:
4006 if(!ncm->ncm_WriteProtect)
4008 ncm->ncm_WriteProtect = TRUE;
4009 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
4011 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
4012 "WriteProtect On: Sense Data Protect");
4015 break;
4017 case SK_UNIT_ATTENTION:
4018 if((ncm->ncm_CDC->cdc_PatchFlags & PFF_REM_SUPPORT) &&
4019 ((scsicmd->scsi_SenseData[12] == 0x28) ||
4020 (scsicmd->scsi_SenseData[12] == 0x3A)))
4022 ncm->ncm_ChangeCount++;
4023 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
4025 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
4026 "Diskchange: Unit Attention (count = %ld)",
4027 ncm->ncm_ChangeCount);
4030 break;
4032 KPRINTF(10, ("Sense Key: %lx/%02lx/%02lx\n",
4033 scsicmd->scsi_SenseData[2] & SK_MASK,
4034 scsicmd->scsi_SenseData[12],
4035 scsicmd->scsi_SenseData[13]));
4036 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
4038 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
4039 "Cmd %s: Sense Key %lx/%02lx/%02lx",
4040 cmdstrbuf,
4041 scsicmd->scsi_SenseData[2] & SK_MASK,
4042 scsicmd->scsi_SenseData[12],
4043 scsicmd->scsi_SenseData[13]);
4046 } else {
4047 KPRINTF(10, ("Sense status failed: %s (%ld)\n", psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr));
4048 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Command (%s) okay, but:", cmdstrbuf);
4049 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
4050 "Sense status failed: %s (%ld)",
4051 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
4052 nBulkReset(ncm);
4054 } else {
4055 KPRINTF(10, ("Sense data failed: %s (%ld)\n", psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr));
4056 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Command (%s) okay, but:", cmdstrbuf);
4057 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
4058 "Sense data failed: %s (%ld)",
4059 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
4060 nBulkReset(ncm);
4062 } else {
4063 KPRINTF(10, ("Sense block failed: %s (%ld)\n", psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr));
4064 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Command (%s) okay, but:", cmdstrbuf);
4065 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
4066 "Sense block failed: %s (%ld)",
4067 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
4068 /*nBulkReset(ncm);*/
4071 rioerr = HFERR_BadStatus;
4073 } else {
4074 KPRINTF(10, ("Command status failed: %s (%ld)\n", psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr));
4075 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Command (%s) failed:", cmdstrbuf);
4076 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
4077 "Command status failed: %s (%ld)",
4078 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
4079 scsicmd->scsi_Status = SCSI_CHECK_CONDITION;
4080 rioerr = HFERR_Phase;
4081 nBulkReset(ncm);
4083 } else {
4084 KPRINTF(10, ("Data phase failed: %s (%ld)\n", psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr));
4085 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Command (%s) failed:", cmdstrbuf);
4086 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
4087 "Data phase failed: %s (%ld)",
4088 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
4089 scsicmd->scsi_Status = SCSI_CHECK_CONDITION;
4090 rioerr = HFERR_Phase;
4091 nBulkReset(ncm);
4093 } else {
4094 KPRINTF(10, ("Command block failed: %s (%ld)\n", psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr));
4095 scsicmd->scsi_Status = SCSI_CHECK_CONDITION;
4096 rioerr = HFERR_Phase;
4097 if(ioerr == UHIOERR_TIMEOUT)
4099 break;
4101 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Command (%s) failed:", cmdstrbuf);
4102 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
4103 "Command block failed: %s (%ld)",
4104 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
4105 nBulkReset(ncm);
4107 if(!rioerr)
4109 break;
4111 KPRINTF(1, ("Retrying...\n"));
4112 } while(retrycnt--);
4113 nUnlockXFer(ncm);
4114 return(rioerr);
4116 /* \\\ */
4118 /* /// "nScsiDirectCBI()" */
4119 LONG nScsiDirectCBI(struct NepClassMS *ncm, struct SCSICmd *scsicmd)
4121 LONG ioerr;
4122 struct PsdPipe *pp;
4123 struct PsdPipe *backpp;
4124 struct UsbMSCBIStatusWrapper umscsw;
4125 ULONG datalen;
4126 LONG rioerr;
4127 UWORD retrycnt = 0;
4128 UBYTE sensedata[18];
4129 UBYTE *senseptr;
4130 UBYTE asc;
4131 BOOL datadone;
4132 BOOL statusdone;
4133 UBYTE cmdstrbuf[16*3+2];
4135 GM_UNIQUENAME(nHexString)(scsicmd->scsi_Command, (ULONG) (scsicmd->scsi_CmdLength < 16 ? scsicmd->scsi_CmdLength : 16), cmdstrbuf);
4137 if(scsicmd->scsi_Flags & 0x80) /* Autoretry */
4139 retrycnt = 1;
4141 scsicmd->scsi_Status = SCSI_GOOD;
4142 nLockXFer(ncm);
4145 if(ncm->ncm_DenyRequests)
4147 rioerr = HFERR_Phase;
4148 break;
4150 rioerr = 0;
4151 datalen = scsicmd->scsi_Length;
4153 KPRINTF(2, ("command block phase, tag %08lx, len %ld, flags %02lx...\n",
4154 scsicmd, scsicmd->scsi_CmdLength, scsicmd->scsi_Flags));
4156 KPRINTF(2, ("command: %s\n", cmdstrbuf));
4158 //nBulkClear(ncm);
4159 scsicmd->scsi_CmdActual = scsicmd->scsi_CmdLength;
4160 /*if(datalen)
4162 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
4163 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT,
4164 (ULONG) ((scsicmd->scsi_Flags & SCSIF_READ) ? ncm->ncm_EPInNum|URTF_IN : ncm->ncm_EPOutNum));
4165 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
4167 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_CLASS|URTF_INTERFACE,
4168 UMSR_ADSC, 0, (ULONG) ncm->ncm_UnitIfNum);
4169 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, scsicmd->scsi_Command, (ULONG) scsicmd->scsi_CmdLength);
4171 if(ncm->ncm_DenyRequests)
4173 rioerr = HFERR_Phase;
4174 break;
4176 if(!ioerr)
4178 datadone = statusdone = FALSE;
4179 if(datalen)
4181 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_CLEAR_EP)
4183 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
4184 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT,
4185 (ULONG) ((scsicmd->scsi_Flags & SCSIF_READ) ? ncm->ncm_EPInNum|URTF_IN : ncm->ncm_EPOutNum));
4186 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
4189 KPRINTF(2, ("data phase %ld bytes...\n", datalen));
4190 pp = (scsicmd->scsi_Flags & SCSIF_READ) ? ncm->ncm_EPInPipe : ncm->ncm_EPOutPipe;
4192 if(ncm->ncm_TPType == MS_PROTO_CBI)
4194 /* okay, this is a major pain in the arse.
4195 we have to do this asynchroneously */
4196 umscsw.bType = 0;
4197 umscsw.bValue = USMF_CSW_PHASEERR;
4198 psdSendPipe(ncm->ncm_EPIntPipe, &umscsw, sizeof(struct UsbMSCBIStatusWrapper));
4199 psdSendPipe(pp, scsicmd->scsi_Data, datalen);
4202 WaitPort(ncm->ncm_TaskMsgPort);
4203 while((backpp = (struct PsdPipe *) GetMsg(ncm->ncm_TaskMsgPort)))
4205 if(backpp == pp)
4207 /* data transfer finished */
4208 datadone = TRUE;
4210 else if(backpp == ncm->ncm_EPIntPipe)
4212 /* status returned */
4213 statusdone = TRUE;
4216 } while(!statusdone);
4217 if(!datadone)
4219 psdAbortPipe(pp);
4220 psdWaitPipe(pp);
4221 ioerr = 0;
4222 } else {
4223 ioerr = psdGetPipeError(pp);
4226 } else {
4227 ioerr = psdDoPipe(pp, scsicmd->scsi_Data, datalen);
4230 scsicmd->scsi_Actual = psdGetPipeActual(pp);
4231 if(ioerr == UHIOERR_OVERFLOW)
4233 KPRINTF(10, ("Extra Data received, but ignored!\n"));
4234 ioerr = 0;
4236 if(ioerr == UHIOERR_STALL) /* Accept on stall */
4238 KPRINTF(2, ("stall...\n"));
4239 //nBulkClear(ncm);
4240 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
4241 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT,
4242 (ULONG) ((scsicmd->scsi_Flags & SCSIF_READ) ? ncm->ncm_EPInNum|URTF_IN : ncm->ncm_EPOutNum));
4243 psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
4244 ioerr = 0;
4246 } else {
4247 ioerr = 0;
4248 scsicmd->scsi_Actual = 0;
4250 if((!ioerr) || (ioerr == UHIOERR_RUNTPACKET))
4252 KPRINTF(2, ("command status phase...\n"));
4253 if(ncm->ncm_TPType == MS_PROTO_CBI)
4255 if(!statusdone)
4257 if(ncm->ncm_CSType == MS_UFI_SUBCLASS)
4259 umscsw.bType = 0x04;
4260 umscsw.bValue = 0;
4261 } else {
4262 umscsw.bType = 0;
4263 umscsw.bValue = USMF_CSW_PHASEERR;
4265 ioerr = psdDoPipe(ncm->ncm_EPIntPipe, &umscsw, sizeof(struct UsbMSCBIStatusWrapper));
4266 } else {
4267 ioerr = psdGetPipeError(ncm->ncm_EPIntPipe);
4269 umscsw.bValue &= 0x0f; /* mask out upper nibble */
4270 if(ioerr)
4272 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
4273 "Status interrupt failed: %s (%ld)",
4274 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
4275 nBulkReset(ncm);
4277 if(ncm->ncm_CSType == MS_UFI_SUBCLASS)
4279 asc = umscsw.bType;
4280 if((scsicmd->scsi_Command[0] == SCSI_REQUEST_SENSE) ||
4281 (scsicmd->scsi_Command[0] == SCSI_INQUIRY))
4283 umscsw.bType = 0;
4284 umscsw.bValue = USMF_CSW_PASS;
4285 } else {
4286 umscsw.bType = 0;
4287 umscsw.bValue = asc ? USMF_CSW_FAIL : USMF_CSW_PASS;
4288 if(umscsw.bValue)
4290 rioerr = HFERR_BadStatus;
4293 } else {
4294 umscsw.bValue &= USMF_CSW_PERSIST; /* mask out other bits */
4296 } else {
4297 umscsw.bType = 0;
4298 umscsw.bValue = USMF_CSW_PASS;
4299 ioerr = 0;
4301 if(ncm->ncm_DenyRequests)
4303 rioerr = HFERR_Phase;
4304 break;
4306 if((!ioerr) || (ioerr == UHIOERR_RUNTPACKET))
4308 scsicmd->scsi_Status = umscsw.bValue;
4309 if(umscsw.bValue == USMF_CSW_PHASEERR)
4311 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
4312 "Command (%s) phase error: %ld",
4313 cmdstrbuf,
4314 umscsw.bValue);
4315 nBulkReset(ncm);
4317 else if(umscsw.bValue == USMF_CSW_PERSIST)
4319 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
4320 "Command (%s) persistant error: %ld",
4321 cmdstrbuf,
4322 umscsw.bValue);
4323 nBulkReset(ncm);
4326 /* Autosensing required? */
4327 if(((umscsw.bValue && (scsicmd->scsi_Flags & SCSIF_AUTOSENSE))) ||
4328 (ncm->ncm_TPType == MS_PROTO_CB) || (ncm->ncm_TPType == MS_PROTO_CBI))
4330 if(scsicmd->scsi_Flags & SCSIF_AUTOSENSE)
4332 datalen = scsicmd->scsi_SenseLength;
4333 senseptr = scsicmd->scsi_SenseData;
4334 } else {
4335 datalen = 18;
4336 senseptr = sensedata;
4338 if(!(scsicmd->scsi_SenseActual = nCBIRequestSense(ncm, senseptr, datalen)))
4340 nBulkReset(ncm);
4342 if(senseptr[2] & SK_MASK)
4344 rioerr = HFERR_BadStatus;
4345 scsicmd->scsi_Status = SCSI_CHECK_CONDITION;
4348 } else {
4349 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
4350 "Command status failed: %s (%ld)",
4351 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
4352 scsicmd->scsi_Status = SCSI_CHECK_CONDITION;
4353 rioerr = HFERR_Phase;
4354 nBulkReset(ncm);
4356 } else {
4357 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
4358 "Data phase failed: %s (%ld)",
4359 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
4360 scsicmd->scsi_Status = SCSI_CHECK_CONDITION;
4361 rioerr = HFERR_Phase;
4362 nBulkClear(ncm);
4364 } else {
4365 scsicmd->scsi_Status = SCSI_CHECK_CONDITION;
4366 rioerr = HFERR_Phase;
4367 if(ioerr == UHIOERR_TIMEOUT)
4369 break;
4371 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
4373 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Command (%s) failed:", cmdstrbuf);
4374 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
4375 "Command block failed: %s (%ld)",
4376 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
4378 if(scsicmd->scsi_Flags & SCSIF_AUTOSENSE)
4380 datalen = scsicmd->scsi_SenseLength;
4381 senseptr = scsicmd->scsi_SenseData;
4382 } else {
4383 datalen = 18;
4384 senseptr = sensedata;
4386 if(!(scsicmd->scsi_SenseActual = nCBIRequestSense(ncm, senseptr, datalen)))
4388 nBulkReset(ncm);
4389 retrycnt = 0;
4390 } else {
4391 if(senseptr[2] & SK_MASK)
4393 rioerr = HFERR_BadStatus;
4394 if((senseptr[2] & SK_MASK) == SK_NOT_READY)
4396 retrycnt = 0;
4401 if(!rioerr)
4403 break;
4405 KPRINTF(1, ("Retrying...\n"));
4406 } while(retrycnt--);
4407 nUnlockXFer(ncm);
4408 return(rioerr);
4410 /* \\\ */
4412 /* /// "nLockXFer()" */
4413 void nLockXFer(struct NepClassMS *ncm)
4415 if(ncm->ncm_MaxLUN)
4417 KPRINTF(1, ("PING(lock)\n"));
4418 ObtainSemaphore(&ncm->ncm_UnitLUN0->ncm_XFerLock);
4419 KPRINTF(1, ("PONG(lock)\n"));
4422 /* \\\ */
4424 /* /// "nUnlockXFer()" */
4425 void nUnlockXFer(struct NepClassMS *ncm)
4427 if(ncm->ncm_MaxLUN)
4429 KPRINTF(1, ("PING(unlock)\n"));
4430 ReleaseSemaphore(&ncm->ncm_UnitLUN0->ncm_XFerLock);
4431 KPRINTF(1, ("PONG(unlock)\n"));
4434 /* \\\ */
4436 /* /// "nStoreConfig()" */
4437 BOOL GM_UNIQUENAME(nStoreConfig)(struct NepClassMS *ncm)
4439 APTR pic;
4440 struct NepClassMS *cncm;
4441 if(ncm->ncm_Interface)
4443 pic = psdGetUsbDevCfg(GM_UNIQUENAME(libname), ncm->ncm_DevIDString, ncm->ncm_IfIDString);
4444 if(!pic)
4446 psdSetUsbDevCfg(GM_UNIQUENAME(libname), ncm->ncm_DevIDString, ncm->ncm_IfIDString, NULL);
4447 pic = psdGetUsbDevCfg(GM_UNIQUENAME(libname), ncm->ncm_DevIDString, ncm->ncm_IfIDString);
4449 if(pic)
4451 psdAddCfgEntry(pic, ncm->ncm_CDC);
4452 cncm = ncm;
4453 while(((struct Node *) cncm)->ln_Succ)
4455 if(cncm->ncm_UnitLUN0 != ncm)
4457 break;
4459 psdAddCfgEntry(pic, cncm->ncm_CUC);
4460 cncm = (struct NepClassMS *) ((struct Node *) cncm)->ln_Succ;
4462 return(TRUE);
4464 } else {
4465 return(TRUE);
4467 return(FALSE);
4469 /* \\\ */
4471 /* ********************************************************************* */
4473 /* /// "BSTR Macros" */
4474 #ifdef __AROS__
4476 #define b2cstr(bstr, cstr)\
4479 UWORD _i = 0;\
4480 UWORD _len = AROS_BSTR_strlen(bstr);\
4481 while(_i < _len)\
4483 cstr[_i] = AROS_BSTR_getchar(bstr, _i);\
4484 _i++;\
4486 cstr[_i] = '\0';\
4487 } while(0)
4489 #define c2bstr(cstr, bstr)\
4492 UWORD _i = 0;\
4493 while(cstr[_i] != '\0')\
4495 AROS_BSTR_putchar(bstr, _i, cstr[_i]);\
4496 _i++;\
4498 AROS_BSTR_setstrlen(bstr, _i);\
4499 } while(0)
4500 #else
4502 #define b2cstr(bstr, cstr) { ULONG i; for (i = 0; i < bstr[0]; i++) cstr[i] = bstr[i + 1]; cstr[i] = 0x00; }
4504 #define c2bstr(cstr, bstr)\
4507 int i = 0;\
4508 UBYTE c;\
4509 STRPTR cp = (STRPTR) (cstr);\
4510 STRPTR bp = (STRPTR) (bstr);\
4511 while((c = cp[i]))\
4513 bp[++i] = c;\
4515 bp[0] = i;\
4516 } while(0)
4518 #endif
4519 /* \\\ */
4521 #undef ps
4522 #define ps nh->nh_PsdBase
4524 /* /// "nRemovableTask()" */
4525 AROS_UFH0(void, GM_UNIQUENAME(nRemovableTask))
4527 AROS_USERFUNC_INIT
4529 struct NepMSBase *nh;
4530 struct NepClassMS *ncm;
4531 ULONG sigmask;
4532 ULONG sigs;
4533 LONG ioerr;
4534 struct SCSICmd scsicmd;
4535 UBYTE cmd6[6];
4536 UBYTE sensedata[18];
4537 struct IOStdReq *ioreq;
4538 BOOL dontquit = TRUE;
4540 if((nh = GM_UNIQUENAME(nAllocRT)()))
4542 Forbid();
4543 if(nh->nh_ReadySigTask)
4545 Signal(nh->nh_ReadySigTask, 1L<<nh->nh_ReadySignal);
4547 Permit();
4548 /* Main task */
4549 sigmask = (1L<<nh->nh_TimerMsgPort->mp_SigBit)|
4550 SIGBREAKF_CTRL_C;
4553 while((ioreq = (struct IOStdReq *) GetMsg(nh->nh_TimerMsgPort)))
4555 dontquit = FALSE;
4556 KPRINTF(2, ("Timer interrupt\n"));
4557 ncm = (struct NepClassMS *) nh->nh_Units.lh_Head;
4558 while(ncm->ncm_Unit.unit_MsgPort.mp_Node.ln_Succ)
4560 if(ncm->ncm_Task && (!ncm->ncm_DenyRequests))
4562 dontquit = TRUE;
4564 if(ncm->ncm_Removable && ncm->ncm_Running)
4566 scsicmd.scsi_Data = NULL;
4567 scsicmd.scsi_Length = 0;
4568 scsicmd.scsi_Command = cmd6;
4569 scsicmd.scsi_CmdLength = 6;
4570 scsicmd.scsi_Flags = SCSIF_READ|SCSIF_AUTOSENSE|0x80;
4571 scsicmd.scsi_SenseData = sensedata;
4572 scsicmd.scsi_SenseLength = 18;
4573 cmd6[0] = SCSI_TEST_UNIT_READY;
4574 cmd6[1] = 0;
4575 cmd6[2] = 0;
4576 cmd6[3] = 0;
4577 cmd6[4] = 0;
4578 cmd6[5] = 0;
4579 if((ioerr = nScsiDirectTunnel(ncm, &scsicmd)))
4581 KPRINTF(1, ("Test unit ready yielded: %ld/%ld\n", sensedata[2], sensedata[12]));
4582 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
4583 "SCSI_TEST_UNIT_READY failed: %ld",
4584 ioerr);*/
4585 /* Check for MEDIUM NOT PRESENT */
4586 if(((sensedata[2] & SK_MASK) == SK_NOT_READY) &&
4587 ((sensedata[12] == 0x3a) || (sensedata[12] == 0x04)))
4589 if(ncm->ncm_UnitReady)
4591 ncm->ncm_UnitReady = FALSE;
4592 ncm->ncm_ChangeCount++;
4593 KPRINTF(10, ("Diskchange: Medium removed (count = %ld)!\n", ncm->ncm_ChangeCount));
4594 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
4596 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
4597 "Diskchange: Medium removed (count = %ld)",
4598 ncm->ncm_ChangeCount);
4602 } else {
4603 if(!ncm->ncm_UnitReady)
4605 ncm->ncm_UnitReady = TRUE;
4606 ncm->ncm_ChangeCount++;
4607 KPRINTF(10, ("Diskchange: Medium inserted (count = %ld)!\n", ncm->ncm_ChangeCount));
4608 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
4610 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
4611 "Diskchange: Medium inserted (count = %ld)",
4612 ncm->ncm_ChangeCount);
4614 if(ncm->ncm_CSType == MS_UFI_SUBCLASS)
4616 nh->nh_IOReq.io_Command = CMD_START;
4617 nIOCmdTunnel(ncm, &nh->nh_IOReq);
4619 } else {
4620 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_REM_SUPPORT)
4622 nGetWriteProtect(ncm);
4627 if(ncm->ncm_LastChange != ncm->ncm_ChangeCount)
4629 if(ncm->ncm_UnitReady)
4631 nGetWriteProtect(ncm);
4632 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_REM_SUPPORT)
4634 nh->nh_IOReq.io_Command = TD_GETGEOMETRY;
4635 nh->nh_IOReq.io_Data = &ncm->ncm_Geometry;
4636 nh->nh_IOReq.io_Length = sizeof(ncm->ncm_Geometry);
4637 nIOCmdTunnel(ncm, &nh->nh_IOReq);
4640 ioreq = (struct IOStdReq *) ncm->ncm_DCInts.lh_Head;
4641 while(((struct Node *) ioreq)->ln_Succ)
4643 Cause(ioreq->io_Data);
4644 ioreq = (struct IOStdReq *) ((struct Node *) ioreq)->ln_Succ;
4646 if(ncm->ncm_UnitReady)
4648 // obtain blocksize first
4649 if(!ncm->ncm_BlockSize)
4651 nh->nh_IOReq.io_Command = TD_GETGEOMETRY;
4652 nh->nh_IOReq.io_Data = &ncm->ncm_Geometry;
4653 nh->nh_IOReq.io_Length = sizeof(ncm->ncm_Geometry);
4654 nIOCmdTunnel(ncm, &nh->nh_IOReq);
4656 ncm->ncm_HasMounted = TRUE;
4658 // find and mount partitions
4659 if(!CheckPartitions(ncm) && ncm->ncm_CUC->cuc_AutoMountFAT)
4661 // check for FAT volume with no partition table
4662 CheckFATPartition(ncm, 0);
4664 if((ncm->ncm_BlockSize == 2048) &&
4665 ((ncm->ncm_DeviceType == PDT_WORM) || (ncm->ncm_DeviceType == PDT_CDROM)))
4667 if(ncm->ncm_CUC->cuc_AutoMountCD)
4669 CheckISO9660(ncm);
4673 ncm->ncm_LastChange = ncm->ncm_ChangeCount;
4675 } else {
4676 if(ncm->ncm_DenyRequests && ncm->ncm_CUC->cuc_AutoUnmount && ncm->ncm_HasMounted)
4678 nUnmountPartition(ncm);
4679 ncm->ncm_HasMounted = FALSE;
4682 ncm = (struct NepClassMS *) ncm->ncm_Unit.unit_MsgPort.mp_Node.ln_Succ;
4684 nh->nh_TimerIOReq->tr_time.tv_secs = 3;
4685 nh->nh_TimerIOReq->tr_time.tv_micro = 0;
4686 SendIO((struct IORequest *) nh->nh_TimerIOReq);
4689 if(nh->nh_RemovableTask->tc_Node.ln_Type == NT_TASK)
4691 APTR doslib;
4692 if((doslib = OpenLibrary("dos.library", 39)))
4694 CloseLibrary(doslib);
4695 // increase disk change count to force mounting
4696 ncm = (struct NepClassMS *) nh->nh_Units.lh_Head;
4697 while(ncm->ncm_Unit.unit_MsgPort.mp_Node.ln_Succ)
4699 ncm->ncm_ChangeCount++;
4700 ncm->ncm_ForceRTCheck = TRUE;
4701 ncm = (struct NepClassMS *) ncm->ncm_Unit.unit_MsgPort.mp_Node.ln_Succ;
4704 /* restart task */
4705 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
4706 "DOS found, stopping removable task...");
4707 nh->nh_RestartIt = TRUE;
4708 break;
4710 // don't quit task, otherwise nobody will be there to restart it and retry mounting stuff
4711 dontquit = TRUE;
4714 if(!dontquit)
4716 break;
4718 sigs = Wait(sigmask);
4719 } while(!(sigs & SIGBREAKF_CTRL_C));
4720 ncm = (struct NepClassMS *) nh->nh_Units.lh_Head;
4721 while(ncm->ncm_Unit.unit_MsgPort.mp_Node.ln_Succ)
4723 if(ncm->ncm_DenyRequests && ncm->ncm_CUC->cuc_AutoUnmount && ncm->ncm_HasMounted)
4725 nUnmountPartition(ncm);
4726 ncm->ncm_HasMounted = FALSE;
4728 ncm = (struct NepClassMS *) ncm->ncm_Unit.unit_MsgPort.mp_Node.ln_Succ;
4730 KPRINTF(20, ("Going down the river!\n"));
4731 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Removable Task stopped.");
4732 GM_UNIQUENAME(nFreeRT)(nh);
4734 AROS_USERFUNC_EXIT
4736 /* \\\ */
4738 /* /// "nAllocRT()" */
4739 struct NepMSBase * GM_UNIQUENAME(nAllocRT)(void)
4741 struct Task *thistask;
4742 struct NepMSBase *nh;
4744 thistask = FindTask(NULL);
4745 nh = thistask->tc_UserData;
4746 #undef ExpansionBase
4747 #define ExpansionBase nh->nh_ExpansionBase
4748 #undef PartitionBase
4749 #define PartitionBase nh->nh_PartitionBase
4752 if(!(ExpansionBase = OpenLibrary("expansion.library", 37)))
4754 Alert(AG_OpenLib | AO_ExpansionLib);
4755 break;
4757 if(!(PartitionBase = OpenLibrary("partition.library", 1)))
4759 Alert(AG_OpenLib | AO_Unknown);
4760 break;
4762 if(!(ps = OpenLibrary("poseidon.library", 4)))
4764 Alert(AG_OpenLib | AO_Unknown);
4765 break;
4767 if(!(nh->nh_IOMsgPort = CreateMsgPort()))
4769 break;
4771 nh->nh_IOReq.io_Message.mn_ReplyPort = nh->nh_IOMsgPort;
4772 if(!(nh->nh_TimerMsgPort = CreateMsgPort()))
4774 break;
4776 if(!(nh->nh_TimerIOReq = (struct timerequest *) CreateIORequest(nh->nh_TimerMsgPort, sizeof(struct timerequest))))
4778 break;
4780 if(OpenDevice("timer.device", UNIT_VBLANK, (struct IORequest *) nh->nh_TimerIOReq, 0))
4782 break;
4784 /* Start removable interrupt */
4785 nh->nh_TimerIOReq->tr_node.io_Command = TR_ADDREQUEST;
4786 nh->nh_TimerIOReq->tr_time.tv_secs = 0;
4787 nh->nh_TimerIOReq->tr_time.tv_micro = 50;
4788 SendIO((struct IORequest *) nh->nh_TimerIOReq);
4789 nh->nh_RemovableTask = thistask;
4790 return(nh);
4791 } while(FALSE);
4792 if(ExpansionBase)
4794 CloseLibrary(ExpansionBase);
4795 ExpansionBase = NULL;
4797 if(PartitionBase)
4799 CloseLibrary(PartitionBase);
4800 PartitionBase = NULL;
4802 if(ps)
4804 CloseLibrary(ps);
4805 ps = NULL;
4808 if(nh->nh_TimerIOReq)
4810 if(nh->nh_TimerIOReq->tr_node.io_Device)
4812 CloseDevice((struct IORequest *) nh->nh_TimerIOReq);
4814 DeleteIORequest((struct IORequest *) nh->nh_TimerIOReq);
4815 nh->nh_TimerIOReq = NULL;
4817 if(nh->nh_TimerMsgPort)
4819 DeleteMsgPort(nh->nh_TimerMsgPort);
4820 nh->nh_TimerMsgPort = NULL;
4822 if(nh->nh_IOMsgPort)
4824 DeleteMsgPort(nh->nh_IOMsgPort);
4825 nh->nh_IOMsgPort = NULL;
4827 Forbid();
4828 nh->nh_RemovableTask = NULL;
4829 if(nh->nh_ReadySigTask)
4831 Signal(nh->nh_ReadySigTask, 1L<<nh->nh_ReadySignal);
4833 return(NULL);
4835 /* \\\ */
4837 /* /// "nFreeRT()" */
4838 void GM_UNIQUENAME(nFreeRT)(struct NepMSBase *nh)
4841 psdFreeVec(nh->nh_OneBlock);
4842 nh->nh_OneBlock = NULL;
4843 nh->nh_OneBlockSize = 0;
4845 if(nh->nh_DOSBase)
4847 CloseLibrary(nh->nh_DOSBase);
4848 nh->nh_DOSBase = NULL;
4850 CloseLibrary(ExpansionBase);
4851 ExpansionBase = NULL;
4852 CloseLibrary(PartitionBase);
4853 PartitionBase = NULL;
4854 CloseLibrary(ps);
4855 ps = NULL;
4857 AbortIO((struct IORequest *) nh->nh_TimerIOReq);
4858 WaitIO((struct IORequest *) nh->nh_TimerIOReq);
4859 CloseDevice((struct IORequest *) nh->nh_TimerIOReq);
4860 DeleteIORequest((struct IORequest *) nh->nh_TimerIOReq);
4861 DeleteMsgPort(nh->nh_TimerMsgPort);
4862 nh->nh_TimerMsgPort = NULL;
4863 nh->nh_TimerIOReq = NULL;
4865 Forbid();
4866 nh->nh_RemovableTask = NULL;
4867 if(nh->nh_ReadySigTask)
4869 Signal(nh->nh_ReadySigTask, 1L<<nh->nh_ReadySignal);
4871 if(nh->nh_RestartIt)
4873 // wake up every task to relaunch removable task
4874 struct NepClassMS *ncm;
4875 ncm = (struct NepClassMS *) nh->nh_Units.lh_Head;
4876 while(ncm->ncm_Unit.unit_MsgPort.mp_Node.ln_Succ)
4878 if(ncm->ncm_Task)
4880 Signal(ncm->ncm_Task, 1L<<ncm->ncm_TaskMsgPort->mp_SigBit);
4882 ncm = (struct NepClassMS *) ncm->ncm_Unit.unit_MsgPort.mp_Node.ln_Succ;
4884 nh->nh_RestartIt = FALSE;
4887 /* \\\ */
4889 /* /// "GM_UNIQUENAME(nOpenDOS)()" */
4890 BOOL GM_UNIQUENAME(nOpenDOS)(struct NepMSBase *nh)
4892 if(nh->nh_DOSBase)
4894 return(TRUE);
4896 if(nh->nh_RemovableTask->tc_Node.ln_Type != NT_PROCESS)
4898 return(FALSE);
4900 if((nh->nh_DOSBase = OpenLibrary("dos.library", 39)))
4902 KPRINTF(10, ("Opened dos.library!\n"));
4903 return(TRUE);
4905 return(FALSE);
4907 /* \\\ */
4909 #undef DOSBase
4910 #define DOSBase nh->nh_DOSBase
4912 /* /// "nUnmountPartition()" */
4913 void nUnmountPartition(struct NepClassMS *ncm)
4915 struct NepMSBase *nh = ncm->ncm_ClsBase;
4916 struct DosList *list;
4917 struct DeviceNode *node;
4918 struct DeviceNode *oldnode = NULL;
4919 char partname[32];
4920 UBYTE *bstr;
4922 if(!GM_UNIQUENAME(nOpenDOS)(nh))
4924 return;
4926 while((node = FindMatchingDevice(ncm, NULL)))
4928 if(oldnode == node)
4930 break;
4932 bstr = (UBYTE *) BADDR(node->dn_Name);
4933 b2cstr(bstr, partname);
4934 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
4935 "Unmounting partition %s...",
4936 partname);
4937 DoPkt(node->dn_Task, ACTION_INHIBIT, TRUE, 0, 0, 0, 0);
4938 DoPkt(node->dn_Task, ACTION_DIE, 0, 0, 0, 0, 0);
4939 if((list = LockDosList(LDF_DEVICES | LDF_WRITE)))
4941 list = FindDosEntry(list, partname, LDF_DEVICES);
4942 if(list)
4944 RemDosEntry(list);
4946 UnLockDosList(LDF_DEVICES | LDF_WRITE);
4948 /*psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
4949 "Unmounting %s done.",
4950 partname);*/
4951 oldnode = node;
4954 /* \\\ */
4956 /* /// "nIOCmdTunnel()" */
4957 LONG nIOCmdTunnel(struct NepClassMS *ncm, struct IOStdReq *ioreq)
4959 struct NepMSBase *nh = ncm->ncm_ClsBase;
4960 Forbid();
4961 if(ncm->ncm_DenyRequests)
4963 Permit();
4964 return(ioreq->io_Error = IOERR_ABORTED);
4966 PutMsg(&ncm->ncm_Unit.unit_MsgPort, (struct Message *) ioreq);
4967 Permit();
4968 while(!GetMsg(nh->nh_IOMsgPort))
4970 WaitPort(nh->nh_IOMsgPort);
4972 return(ioreq->io_Error);
4974 /* \\\ */
4976 /* /// "nScsiDirectTunnel()" */
4977 LONG nScsiDirectTunnel(struct NepClassMS *ncm, struct SCSICmd *scsicmd)
4979 struct NepMSBase *nh = ncm->ncm_ClsBase;
4980 struct IOStdReq *ioreq = &nh->nh_IOReq;
4981 ioreq->io_Command = HD_SCSICMD;
4982 ioreq->io_Data = scsicmd;
4983 ioreq->io_Length = sizeof(*scsicmd);
4984 return(nIOCmdTunnel(ncm, ioreq));
4986 /* \\\ */
4988 /* /// "nGetWriteProtect()" */
4989 LONG nGetWriteProtect(struct NepClassMS *ncm)
4991 struct NepMSBase *nh = ncm->ncm_ClsBase;
4992 UBYTE cmd10[10];
4993 struct SCSICmd scsicmd;
4994 UBYTE inquirydata[256];
4995 UBYTE sensedata[18];
4996 LONG ioerr;
4998 if((ncm->ncm_DeviceType == PDT_WORM) ||
4999 (ncm->ncm_DeviceType == PDT_CDROM))
5001 // cd roms are always write protected
5002 return(ncm->ncm_WriteProtect = TRUE);
5004 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_SIMPLE_SCSI)
5006 return(ncm->ncm_WriteProtect = FALSE);
5008 scsicmd.scsi_Data = (UWORD *) inquirydata;
5009 scsicmd.scsi_Length = 8;
5010 scsicmd.scsi_Command = cmd10;
5011 scsicmd.scsi_CmdLength = 10;
5012 scsicmd.scsi_Flags = SCSIF_READ|SCSIF_AUTOSENSE|0x80;
5013 scsicmd.scsi_SenseData = sensedata;
5014 scsicmd.scsi_SenseLength = 18;
5015 cmd10[0] = SCSI_MODE_SENSE_10;
5016 cmd10[1] = 0x00; /* no block descriptors */
5017 cmd10[2] = 0x3f; /* no page, only header */
5018 cmd10[3] = 0;
5019 cmd10[4] = 0;
5020 cmd10[5] = 0;
5021 cmd10[6] = 0;
5022 cmd10[7] = 0;
5023 cmd10[8] = 8;
5024 cmd10[9] = 0;
5025 if((ioerr = nScsiDirectTunnel(ncm, &scsicmd)))
5027 cmd10[2] = 0x00; /* try again with vendor page, only header */
5028 if((ioerr = nScsiDirectTunnel(ncm, &scsicmd)))
5030 cmd10[2] = 0x3f; /* try again with 255 length */
5031 cmd10[8] = 0xff;
5032 if((ioerr = nScsiDirectTunnel(ncm, &scsicmd)))
5034 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
5036 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
5037 "Failed to get write protection state: %ld",
5038 ioerr);
5040 if(!(ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_FALLBACK))
5042 ncm->ncm_CDC->cdc_PatchFlags |= PFF_SIMPLE_SCSI;
5043 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
5044 "Fallback: Enabling Simple SCSI.");
5046 GM_UNIQUENAME(nStoreConfig)(ncm);
5047 return(0);
5051 if(inquirydata[3] & 0x80)
5053 if(!ncm->ncm_WriteProtect)
5055 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_REM_SUPPORT)
5057 ncm->ncm_ChangeCount++;
5058 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
5060 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
5061 "Diskchange: GetWriteProtect On (count = %ld)",
5062 ncm->ncm_ChangeCount);
5065 ncm->ncm_WriteProtect = TRUE;
5067 } else {
5068 if(ncm->ncm_WriteProtect)
5070 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_REM_SUPPORT)
5072 ncm->ncm_ChangeCount++;
5073 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
5075 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
5076 "Diskchange: GetWriteProtect Off (count = %ld)",
5077 ncm->ncm_ChangeCount);
5080 ncm->ncm_WriteProtect = FALSE;
5083 return(ncm->ncm_WriteProtect);
5085 /* \\\ */
5087 /* /// "SearchHardBlock()" */
5088 APTR SearchHardBlock(struct NepClassMS *ncm,
5089 struct IOStdReq *ioreq,
5090 ULONG id,
5091 ULONG start)
5093 struct NepMSBase *nh = ncm->ncm_ClsBase;
5094 ULONG curBlock;
5096 if(!nh->nh_OneBlock || (nh->nh_OneBlockSize < ncm->ncm_BlockSize))
5098 psdFreeVec(nh->nh_OneBlock);
5099 if(!(nh->nh_OneBlock = psdAllocVec(ncm->ncm_BlockSize)))
5101 return(NULL);
5103 nh->nh_OneBlockSize = ncm->ncm_BlockSize;
5106 curBlock = start;
5109 ioreq->io_Command = TD_READ64;
5110 ioreq->io_Data = nh->nh_OneBlock;
5111 ioreq->io_Length = ncm->ncm_BlockSize;
5112 ioreq->io_Offset = curBlock<<ncm->ncm_BlockShift;
5113 ioreq->io_Actual = curBlock>>(32-ncm->ncm_BlockShift);
5115 if(!nIOCmdTunnel(ncm, ioreq))
5117 curBlock++;
5118 if((*(ULONG *) nh->nh_OneBlock) == id)
5120 return(nh->nh_OneBlock);
5122 } else {
5123 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Error searching hardblock in block %ld.", curBlock);
5124 return(NULL);
5126 } while(curBlock <= RDB_LOCATION_LIMIT);
5127 return(NULL);
5129 /* \\\ */
5131 /* /// "ReadRDSK()" */
5132 BOOL ReadRDSK(struct NepClassMS *ncm,
5133 struct IOStdReq *ioreq,
5134 struct RigidDiskBlock *rdb)
5136 APTR blkaddr = SearchHardBlock(ncm, ioreq, IDNAME_RIGIDDISK, 0);
5137 if(blkaddr)
5139 CopyMemQuick(blkaddr, rdb, sizeof(struct RigidDiskBlock));
5140 // endianess conversion
5141 rdb->rdb_ID = AROS_BE2LONG(rdb->rdb_ID);
5142 rdb->rdb_SummedLongs = AROS_BE2LONG(rdb->rdb_SummedLongs);
5143 rdb->rdb_ChkSum = AROS_BE2LONG(rdb->rdb_ChkSum);
5144 rdb->rdb_HostID = AROS_BE2LONG(rdb->rdb_HostID);
5145 rdb->rdb_BlockBytes = AROS_BE2LONG(rdb->rdb_BlockBytes);
5146 rdb->rdb_PartitionList = AROS_BE2LONG(rdb->rdb_PartitionList);
5147 rdb->rdb_FileSysHeaderList = AROS_BE2LONG(rdb->rdb_FileSysHeaderList);
5148 rdb->rdb_DriveInit = AROS_BE2LONG(rdb->rdb_DriveInit);
5149 rdb->rdb_Cylinders = AROS_BE2LONG(rdb->rdb_Cylinders);
5150 rdb->rdb_Sectors = AROS_BE2LONG(rdb->rdb_Sectors);
5151 rdb->rdb_Heads = AROS_BE2LONG(rdb->rdb_Heads);
5152 rdb->rdb_Interleave = AROS_BE2LONG(rdb->rdb_Interleave);
5153 rdb->rdb_Park = AROS_BE2LONG(rdb->rdb_Park);
5154 rdb->rdb_WritePreComp = AROS_BE2LONG(rdb->rdb_WritePreComp);
5155 rdb->rdb_ReducedWrite = AROS_BE2LONG(rdb->rdb_ReducedWrite);
5156 rdb->rdb_StepRate = AROS_BE2LONG(rdb->rdb_StepRate);
5157 rdb->rdb_RDBBlocksLo = AROS_BE2LONG(rdb->rdb_RDBBlocksLo);
5158 rdb->rdb_RDBBlocksHi = AROS_BE2LONG(rdb->rdb_RDBBlocksHi);
5159 rdb->rdb_LoCylinder = AROS_BE2LONG(rdb->rdb_LoCylinder);
5160 rdb->rdb_HiCylinder = AROS_BE2LONG(rdb->rdb_HiCylinder);
5161 rdb->rdb_CylBlocks = AROS_BE2LONG(rdb->rdb_CylBlocks);
5162 rdb->rdb_AutoParkSeconds = AROS_BE2LONG(rdb->rdb_AutoParkSeconds);
5163 rdb->rdb_HighRDSKBlock = AROS_BE2LONG(rdb->rdb_HighRDSKBlock);
5164 return(TRUE);
5166 return(FALSE);
5168 /* \\\ */
5170 /* /// "ReadPART()" */
5171 BOOL ReadPART(struct NepClassMS *ncm,
5172 struct IOStdReq *ioreq,
5173 struct PartitionBlock *part,
5174 ULONG which)
5176 APTR blkaddr = SearchHardBlock(ncm, ioreq, IDNAME_PARTITION, which);
5177 if(blkaddr)
5179 UWORD cnt;
5180 CopyMemQuick(blkaddr, part, sizeof(struct PartitionBlock));
5181 // endianess conversion
5182 part->pb_ID = AROS_BE2LONG(part->pb_ID);
5183 part->pb_SummedLongs = AROS_BE2LONG(part->pb_SummedLongs);
5184 part->pb_ChkSum = AROS_BE2LONG(part->pb_ChkSum);
5185 part->pb_HostID = AROS_BE2LONG(part->pb_HostID);
5186 part->pb_Next = AROS_BE2LONG(part->pb_Next);
5187 part->pb_Flags = AROS_BE2LONG(part->pb_Flags);
5188 part->pb_DevFlags = AROS_BE2LONG(part->pb_DevFlags);
5189 for(cnt = 0; cnt < 20; cnt++)
5191 part->pb_Environment[cnt] = AROS_BE2LONG(part->pb_Environment[cnt]);
5193 return(TRUE);
5195 return(FALSE);
5197 /* \\\ */
5199 /* /// "ReadFSHD()" */
5200 BOOL ReadFSHD(struct NepClassMS *ncm,
5201 struct IOStdReq *ioreq,
5202 struct FileSysHeaderBlock *fshd,
5203 ULONG which)
5205 APTR blkaddr = SearchHardBlock(ncm, ioreq, IDNAME_FILESYSHEADER, which);
5206 if(blkaddr)
5208 CopyMemQuick(blkaddr, fshd, sizeof(struct FileSysHeaderBlock));
5209 // endianess conversion
5210 fshd->fhb_ID = AROS_BE2LONG(fshd->fhb_ID);
5211 fshd->fhb_SummedLongs = AROS_BE2LONG(fshd->fhb_SummedLongs);
5212 fshd->fhb_ChkSum = AROS_BE2LONG(fshd->fhb_ChkSum);
5213 fshd->fhb_HostID = AROS_BE2LONG(fshd->fhb_HostID);
5214 fshd->fhb_Next = AROS_BE2LONG(fshd->fhb_Next);
5215 fshd->fhb_Flags = AROS_BE2LONG(fshd->fhb_Flags);
5216 fshd->fhb_DosType = AROS_BE2LONG(fshd->fhb_DosType);
5217 fshd->fhb_Version = AROS_BE2LONG(fshd->fhb_Version);
5218 fshd->fhb_PatchFlags = AROS_BE2LONG(fshd->fhb_PatchFlags);
5219 fshd->fhb_Type = AROS_BE2LONG(fshd->fhb_Type);
5220 fshd->fhb_Task = AROS_BE2LONG(fshd->fhb_Task);
5221 fshd->fhb_Lock = AROS_BE2LONG(fshd->fhb_Lock);
5222 fshd->fhb_Handler = AROS_BE2LONG(fshd->fhb_Handler);
5223 fshd->fhb_StackSize = AROS_BE2LONG(fshd->fhb_StackSize);
5224 fshd->fhb_Priority = AROS_BE2LONG(fshd->fhb_Priority);
5225 fshd->fhb_Startup = AROS_BE2LONG(fshd->fhb_Startup);
5226 fshd->fhb_SegListBlocks = AROS_BE2LONG(fshd->fhb_SegListBlocks);
5227 fshd->fhb_GlobalVec = AROS_BE2LONG(fshd->fhb_GlobalVec);
5228 return(TRUE);
5230 return(FALSE);
5232 /* \\\ */
5234 /* /// "ReadLSEG()" */
5235 struct LoadSegBlock * ReadLSEG(struct NepClassMS *ncm,
5236 struct IOStdReq *ioreq,
5237 ULONG which)
5239 return((struct LoadSegBlock *) SearchHardBlock(ncm, ioreq, IDNAME_LOADSEG, which));
5241 /* \\\ */
5243 /* /// "FindFileSystem()" */
5244 struct FileSysEntry * FindFileSystem(struct NepClassMS *ncm, ULONG dosType)
5246 struct FileSysResource *fsr;
5247 struct FileSysEntry *fse;
5249 KPRINTF(10, ("looking up %08lx fs\n", dosType));
5250 if((fsr = (struct FileSysResource *) OpenResource(FSRNAME)))
5252 Forbid();
5253 fse = (struct FileSysEntry *) fsr->fsr_FileSysEntries.lh_Head;
5254 while(fse->fse_Node.ln_Succ)
5256 if(fse->fse_DosType == dosType)
5258 Permit();
5259 return(fse);
5261 fse = (struct FileSysEntry *) fse->fse_Node.ln_Succ;
5263 Permit();
5266 return(NULL);
5268 /* \\\ */
5270 /* /// "BuildFileSystem()" */
5271 ULONG BuildFileSystem(struct NepClassMS *ncm,
5272 UBYTE *fsBuffer,
5273 BOOL readAndCopy)
5275 struct NepMSBase *nh = ncm->ncm_ClsBase;
5276 struct RigidDisk *rdsk = &nh->nh_RDsk;
5277 ULONG result = 0;
5278 ULONG nextLSEG;
5279 ULONG add;
5280 struct LoadSegBlock *lseg;
5282 nextLSEG = rdsk->rdsk_FSHD.fhb_SegListBlocks;
5286 if((lseg = ReadLSEG(ncm, &nh->nh_IOReq, nextLSEG)))
5288 add = (AROS_BE2LONG(lseg->lsb_SummedLongs) - 5) * sizeof(ULONG);
5289 if(readAndCopy)
5291 CopyMem(lseg->lsb_LoadData, fsBuffer, add);
5292 fsBuffer += add;
5294 result += add;
5295 nextLSEG = lseg->lsb_Next;
5296 } else {
5297 result = 0;
5298 break;
5300 } while(nextLSEG != NIL_PTR);
5301 return(result);
5303 /* \\\ */
5305 /* /// "LoadFileSystem()" */
5306 BPTR LoadFileSystem(struct NepClassMS *ncm, ULONG dosType, struct FileSysEntry *fse)
5308 struct NepMSBase *nh = ncm->ncm_ClsBase;
5309 struct RigidDisk *rdsk = &nh->nh_RDsk;
5310 ULONG nextFSHD;
5311 BPTR fh, seg = BNULL;
5312 ULONG fsLength;
5313 UBYTE *fsBuffer;
5314 UBYTE fsFile[32];
5315 BOOL ok;
5317 if(rdsk->rdsk_RDB.rdb_FileSysHeaderList != NIL_PTR)
5319 nextFSHD = rdsk->rdsk_RDB.rdb_FileSysHeaderList;
5322 if(ReadFSHD(ncm, &nh->nh_IOReq, &rdsk->rdsk_FSHD, nextFSHD))
5324 nextFSHD = rdsk->rdsk_FSHD.fhb_Next;
5325 } else {
5326 break;
5328 KPRINTF(10, ("Found 0x%08lx FS in FSHD...\n", rdsk->rdsk_FSHD.fhb_ID));
5329 } while((rdsk->rdsk_FSHD.fhb_DosType != dosType) && (nextFSHD != NIL_PTR));
5331 if(rdsk->rdsk_FSHD.fhb_DosType == dosType)
5333 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Found filesystem %s in RDB!",
5334 nh->nh_RDsk.rdsk_FSHD.fhb_FileSysName);
5335 KPRINTF(10, ("found matching fs in FSHD, trying to load from LSEG blocks\n"));
5337 CopyMem(&rdsk->rdsk_FSHD.fhb_DosType, &fse->fse_DosType, sizeof(struct FileSysEntry) - sizeof(struct Node));
5339 if(rdsk->rdsk_FSHD.fhb_SegListBlocks > 0)
5341 fsLength = BuildFileSystem(ncm, NULL, FALSE);
5343 if(fsLength > 0)
5345 if((fsBuffer = psdAllocVec(fsLength)))
5347 BuildFileSystem(ncm, fsBuffer, TRUE);
5349 if(GM_UNIQUENAME(nOpenDOS)(nh))
5351 psdSafeRawDoFmt(fsFile, 32, "T:UMSD_%08lx.fs", dosType);
5352 if((fh = Open(fsFile, MODE_NEWFILE)))
5354 ok = (Write(fh, fsBuffer, fsLength) == fsLength);
5355 Close(fh);
5356 if(ok)
5358 seg = LoadSeg(fsFile);
5361 DeleteFile(fsFile);
5362 } else {
5363 KPRINTF(10, ("No DOS available, trying own load seg stuff\n"));
5364 // FIXME this code is unavailable and doesn't make sense for AROS as it doesn't use DOS_HUNK format
5365 //seg = CreateSegment(ncm, (const ULONG *) fsBuffer);
5367 psdFreeVec(fsBuffer);
5374 if(!seg)
5376 if(GM_UNIQUENAME(nOpenDOS)(nh))
5378 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Loading filesystem %s from RDB failed. Trying DOS...",
5379 nh->nh_RDsk.rdsk_FSHD.fhb_FileSysName);
5380 KPRINTF(10, ("loading fs from LSEG blocks failed, trying fs file %s mentioned in FSHD\n", (char *) nh->nh_RDsk.rdsk_FSHD.fhb_FileSysName));
5381 //seg = LoadSeg(rdsk->rdsk_FSHD.fhb_FileSysName);
5382 seg = LoadSeg((char *) nh->nh_RDsk.rdsk_FSHD.fhb_FileSysName);
5383 if(seg)
5385 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Loaded filesystem %s via DOS!",
5386 nh->nh_RDsk.rdsk_FSHD.fhb_FileSysName);
5387 } else {
5388 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Loading filesystem %s via DOS failed!",
5389 nh->nh_RDsk.rdsk_FSHD.fhb_FileSysName);
5391 } else {
5392 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Loading filesystem %s from RDB failed.",
5393 nh->nh_RDsk.rdsk_FSHD.fhb_FileSysName);
5396 if(seg)
5398 fse->fse_SegList = seg;
5400 return(seg);
5402 /* \\\ */
5404 /* /// "MatchPartition()" */
5405 BOOL MatchPartition(struct NepClassMS *ncm,
5406 struct DosEnvec *envec1,
5407 struct FileSysStartupMsg *fssm)
5409 BOOL result = FALSE;
5410 UBYTE *bstr;
5411 UBYTE device[256];
5412 struct DosEnvec *envec2;
5414 if(fssm)
5416 envec2 = (struct DosEnvec *) BADDR(fssm->fssm_Environ);
5418 if(envec2)
5420 bstr = (UBYTE *) BADDR(fssm->fssm_Device);
5421 b2cstr(bstr, device);
5423 if(envec1)
5425 if((envec1->de_DosType & 0xffffff00) == 0x46415400)
5427 result = ((ncm->ncm_UnitNo == fssm->fssm_Unit) &&
5428 (strcmp(DEVNAME, device) == 0) &&
5429 (envec1->de_DosType == envec2->de_DosType));
5430 } else {
5431 result = ((ncm->ncm_UnitNo == fssm->fssm_Unit) &&
5432 (strcmp(DEVNAME, device) == 0) &&
5433 (envec1->de_SizeBlock == envec2->de_SizeBlock) &&
5434 (envec1->de_Surfaces == envec2->de_Surfaces) &&
5435 (envec1->de_SectorPerBlock == envec2->de_SectorPerBlock) &&
5436 (envec1->de_BlocksPerTrack == envec2->de_BlocksPerTrack) &&
5437 (envec1->de_Reserved == envec2->de_Reserved) &&
5438 (envec1->de_PreAlloc == envec2->de_PreAlloc) &&
5439 (envec1->de_Interleave == envec2->de_Interleave) &&
5440 (envec1->de_LowCyl == envec2->de_LowCyl) &&
5441 (envec1->de_HighCyl == envec2->de_HighCyl) &&
5442 (envec1->de_DosType == envec2->de_DosType));
5444 } else {
5445 result = (ncm->ncm_UnitNo == fssm->fssm_Unit) &&
5446 (strcmp(DEVNAME, device) == 0);
5450 return(result);
5452 /* \\\ */
5454 /* /// "FindDeviceNode()" */
5455 struct DeviceNode * FindDeviceNode(struct NepClassMS *ncm, STRPTR device)
5457 struct NepMSBase *nh = ncm->ncm_ClsBase;
5458 struct DosList *list;
5459 struct DeviceNode *node = NULL;
5461 if(!GM_UNIQUENAME(nOpenDOS)(nh))
5463 return(NULL);
5466 if((list = LockDosList(LDF_DEVICES | LDF_READ)))
5468 node = (struct DeviceNode *) FindDosEntry(list, device, LDF_DEVICES);
5469 UnLockDosList(LDF_DEVICES | LDF_READ);
5471 return(node);
5473 /* \\\ */
5475 /* /// "CheckVolumesOrAssignsMatch()" */
5476 BOOL CheckVolumesOrAssignsMatch(struct NepClassMS *ncm, STRPTR device)
5478 struct NepMSBase *nh = ncm->ncm_ClsBase;
5479 struct DosList *list;
5480 BOOL found = FALSE;
5482 if(!GM_UNIQUENAME(nOpenDOS)(nh))
5484 return(FALSE);
5487 if((list = LockDosList(LDF_ALL | LDF_READ)))
5489 if(FindDosEntry(list, device, LDF_ALL))
5491 found = TRUE;
5493 UnLockDosList(LDF_ALL | LDF_READ);
5495 return(found);
5497 /* \\\ */
5499 /* /// "FindMatchingDevice()" */
5500 struct DeviceNode * FindMatchingDevice(struct NepClassMS *ncm, struct DosEnvec *envec)
5502 struct NepMSBase *nh = ncm->ncm_ClsBase;
5503 struct DosList *list;
5504 struct DeviceNode *node = NULL;
5505 struct FileSysStartupMsg *fssm;
5507 if(!GM_UNIQUENAME(nOpenDOS)(nh))
5509 return(NULL);
5512 if((list = LockDosList(LDF_DEVICES | LDF_READ)))
5514 while((list = NextDosEntry(list, LDF_DEVICES | LDF_READ)))
5516 fssm = NULL;
5518 /*if((!(((ULONG) list->dol_misc.dol_handler.dol_Startup) >> 30)) &&
5519 TypeOfMem(BADDR(list->dol_misc.dol_handler.dol_Startup)))*/
5521 fssm = BADDR(list->dol_misc.dol_handler.dol_Startup);
5524 if(fssm > (struct FileSysStartupMsg *) 0x1000)
5526 // if((*((UBYTE *) fssm)) == 0)
5528 struct DosEnvec *de = BADDR(fssm->fssm_Environ);
5529 STRPTR devname = BADDR(fssm->fssm_Device);
5531 if(TypeOfMem(de) && TypeOfMem(devname) && (de->de_TableSize > 0) && (de->de_TableSize < 32))
5532 /*if((!((ULONG) de >> 30)) && TypeOfMem(de) &&
5533 (!((ULONG) devname >> 30)) && TypeOfMem(devname) &&
5534 (de->de_TableSize > 0) && (de->de_TableSize < 32))*/
5536 if(MatchPartition(ncm, envec, fssm))
5538 node = (struct DeviceNode *) list;
5539 break;
5545 UnLockDosList(LDF_DEVICES | LDF_READ);
5547 return(node);
5549 /* \\\ */
5551 /* /// "MountPartition()" */
5552 BOOL MountPartition(struct NepClassMS *ncm, STRPTR dosDevice)
5554 struct NepMSBase *nh = ncm->ncm_ClsBase;
5555 struct RigidDisk *rdsk = &nh->nh_RDsk;
5556 IPTR *params;
5557 struct DeviceNode *node;
5558 struct FileSysEntry *fse;
5559 struct FileSysEntry patch;
5560 BPTR segList = BNULL;
5561 BOOL fsFound = FALSE;
5562 BOOL result = FALSE;
5563 STRPTR devname = DEVNAME;
5565 if((fse = FindFileSystem(ncm, rdsk->rdsk_PART.pb_Environment[DE_DOSTYPE])))
5567 KPRINTF(10, ("fs found in filesys resource\n"));
5568 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Found FS in filesystem.resource!");
5570 CopyMem(fse, &patch, sizeof(struct FileSysEntry));
5571 fsFound = TRUE;
5572 } else {
5573 memset(&patch, 0x00, sizeof(struct FileSysEntry));
5574 patch.fse_DosType = rdsk->rdsk_PART.pb_Environment[DE_DOSTYPE];
5576 if((segList = LoadFileSystem(ncm, rdsk->rdsk_PART.pb_Environment[DE_DOSTYPE], &patch)))
5578 KPRINTF(10, ("fs loaded from RDB\n"));
5580 patch.fse_PatchFlags = 0x0080|0x0010;
5581 patch.fse_SegList = segList;
5582 patch.fse_StackSize = (AROS_STACKSIZE << 1);
5583 //if(((patch.fse_DosType & 0xffffff00) == 0x46415400) || (patch.fse_DosType == 0x4d534800))
5585 KPRINTF(10, ("setting up certain fs values for MS-DOS fs\n"));
5586 // Stack, SegList, Pri und GlobVec eintragen
5587 patch.fse_PatchFlags |= 0x0020|0x0100;
5588 patch.fse_Priority = 10;
5589 patch.fse_GlobalVec = (BPTR) 0xffffffff;
5592 fsFound = TRUE;
5596 if(!fsFound)
5598 STRPTR handler = (STRPTR) nh->nh_RDsk.rdsk_FSHD.fhb_FileSysName;
5599 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Experimental AROS patch to load %s", handler);
5600 patch.fse_Handler = MKBADDR(AllocVec(AROS_BSTR_MEMSIZE4LEN(strlen(handler)), MEMF_PUBLIC | MEMF_CLEAR));
5601 if(patch.fse_Handler)
5603 c2bstr(handler, patch.fse_Handler);
5604 patch.fse_PatchFlags |= 0x0008;
5605 fsFound = TRUE;
5609 if(fsFound)
5611 if((params = psdAllocVec(sizeof(struct DosEnvec) + 4 * sizeof(IPTR))))
5613 params[0] = (IPTR) dosDevice;
5614 params[1] = (IPTR) DEVNAME;
5615 params[2] = ncm->ncm_UnitNo;
5616 params[3] = 0x00; // Flags for OpenDevice
5617 CopyMem(rdsk->rdsk_PART.pb_Environment, &params[4], sizeof(struct DosEnvec));
5619 if((node = MakeDosNode(params)))
5621 BOOL installboot;
5622 KPRINTF(10, ("MakeDosNode() succeeded, patchflags %04lx\n", patch.fse_PatchFlags));
5623 node->dn_StackSize = (AROS_STACKSIZE << 1);
5625 /*node->dn_Priority = 5;*/
5626 if(patch.fse_PatchFlags & 0x0001) node->dn_Type = patch.fse_Type;
5627 if(patch.fse_PatchFlags & 0x0002) node->dn_Task = (struct MsgPort *) patch.fse_Task;
5628 if(patch.fse_PatchFlags & 0x0004) node->dn_Lock = patch.fse_Lock;
5629 if(patch.fse_PatchFlags & 0x0008) node->dn_Handler = patch.fse_Handler;
5630 if(patch.fse_PatchFlags & 0x0010) node->dn_StackSize = patch.fse_StackSize;
5631 if(patch.fse_PatchFlags & 0x0020) node->dn_Priority = patch.fse_Priority;
5632 if(patch.fse_PatchFlags & 0x0040) node->dn_Startup = patch.fse_Startup;
5633 if(patch.fse_PatchFlags & 0x0080) node->dn_SegList = patch.fse_SegList;
5634 if(patch.fse_PatchFlags & 0x0100) node->dn_GlobalVec = patch.fse_GlobalVec;
5636 KPRINTF(10, ("dn_Next = %08lx\n"
5637 "dn_Type = %08lx\n"
5638 "dn_Task = %08lx\n"
5639 "dn_Lock = %08lx\n"
5640 "dn_Handler = %08lx\n"
5641 "dn_StackSize = %08ld\n"
5642 "dn_Priority = %08ld\n"
5643 "dn_Startup = %08lx\n"
5644 "dn_SegList = %08lx\n"
5645 "dn_GlobalVec = %08lx\n"
5646 "dn_Name = %08lx\n",
5647 node->dn_Next,
5648 node->dn_Type,
5649 node->dn_Task,
5650 node->dn_Lock,
5651 node->dn_Handler,
5652 node->dn_StackSize,
5653 node->dn_Priority,
5654 node->dn_Startup,
5655 node->dn_SegList,
5656 node->dn_GlobalVec,
5657 node->dn_Name));
5659 installboot = ncm->ncm_CUC->cuc_BootRDB;
5660 if((nh->nh_RemovableTask->tc_Node.ln_Type == NT_PROCESS) ||
5661 (!(nh->nh_RDsk.rdsk_PART.pb_Flags & PBFF_BOOTABLE)))
5663 installboot = FALSE;
5665 if(installboot)
5667 // avoid sys partition being unmounted (actually it should better check at
5668 // unmounting, but I can't think of a clever way yet to retrieve the SYS:
5669 // device
5670 ncm->ncm_CUC->cuc_AutoUnmount = FALSE;
5671 GM_UNIQUENAME(nStoreConfig)(ncm);
5674 if(AddBootNode(nh->nh_RDsk.rdsk_PART.pb_Environment[DE_BOOTPRI], ADNF_STARTPROC, node, NULL))
5676 KPRINTF(10, ("AddBootNode() succeeded\n"));
5677 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
5678 "Mounted %s unit %ld as %s:",
5679 devname, ncm->ncm_UnitNo, dosDevice);
5681 result = TRUE;
5682 } else {
5683 KPRINTF(10, ("AddBootNode() failed\n"));
5684 /* There is a memory leak here! No way to deallocate the node created by
5685 MakeDosNode()! */
5688 psdFreeVec(params);
5691 if(!result)
5693 if(GM_UNIQUENAME(nOpenDOS)(nh))
5695 UnLoadSeg(segList);
5698 } else {
5699 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
5700 "Couldn't find/load filesystem for %s unit %ld as %s:",
5701 devname, ncm->ncm_UnitNo, dosDevice);
5702 KPRINTF(10, ("fs %08lx not found\n", rdsk->rdsk_PART.pb_Environment[DE_DOSTYPE]));
5705 return(result);
5707 /* \\\ */
5709 /* /// "CheckPartition()" */
5710 void CheckPartition(struct NepClassMS *ncm)
5712 struct NepMSBase *nh = ncm->ncm_ClsBase;
5713 struct RigidDisk *rdsk = &nh->nh_RDsk;
5714 struct DosEnvec *envec;
5715 UBYTE dosDevice[32], temp[32];
5716 ULONG spareNum;
5717 struct DeviceNode *node;
5718 BOOL done = FALSE, doMount = TRUE;
5719 STRPTR devname = DEVNAME;
5720 BOOL bump;
5721 ULONG slen;
5723 envec = (struct DosEnvec *) rdsk->rdsk_PART.pb_Environment;
5724 if((node = FindMatchingDevice(ncm, envec)))
5726 KPRINTF(10, ("found suitable device entry, no need to mount anything new\n"));
5728 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
5729 "Matching partition for %s unit %ld already found. No remount required.",
5730 devname, ncm->ncm_UnitNo);
5731 doMount = FALSE;
5732 } else {
5733 spareNum = 0;
5735 b2cstr(rdsk->rdsk_PART.pb_DriveName, dosDevice);
5737 KPRINTF(10, ("trying to mount partition \"%s\"\n", dosDevice));
5739 /*if(envec->de_TableSize >= DE_DOSTYPE) SHOWVALUE(envec->de_DosType);*/
5742 bump = FALSE;
5743 if((node = FindDeviceNode(ncm, dosDevice)))
5745 KPRINTF(10, ("%s is already mounted, comparing fssm\n", dosDevice));
5747 if(MatchPartition(ncm, envec, BADDR(node->dn_Startup)))
5749 KPRINTF(10, ("fssm match, no need to mount\n"));
5751 doMount = FALSE;
5752 done = TRUE;
5753 } else {
5754 bump = TRUE;
5756 } else {
5757 if(CheckVolumesOrAssignsMatch(ncm, dosDevice))
5759 bump = TRUE;
5760 } else {
5761 done = TRUE;
5764 if(bump)
5766 slen = strlen(dosDevice);
5767 if((slen > 0) && (dosDevice[slen-1] >= '0') && (dosDevice[slen-1] <= '9'))
5769 if(dosDevice[slen-1] == '9')
5771 if((slen > 1) && (dosDevice[slen-2] >= '0') && (dosDevice[slen-2] <= '8'))
5773 dosDevice[slen-2]++;
5774 dosDevice[slen-1] = '0';
5775 } else {
5776 if(slen < 30)
5778 dosDevice[slen-1] = '1';
5779 dosDevice[slen] = '0';
5780 dosDevice[slen+1] = 0;
5781 } else {
5782 break;
5785 } else {
5786 dosDevice[slen-1]++;
5788 } else {
5789 b2cstr(rdsk->rdsk_PART.pb_DriveName, temp);
5790 psdSafeRawDoFmt(dosDevice, 32, "%s.%ld", temp, spareNum);
5792 KPRINTF(10, ("fssm don't match, trying as %s\n", dosDevice));
5793 spareNum++;
5795 } while(!done && (spareNum < 16));
5798 if(done && doMount)
5800 KPRINTF(10, ("mounting %s\n", dosDevice));
5802 MountPartition(ncm, dosDevice);
5805 /* \\\ */
5807 /* /// "IsFATSuperBlock()" */
5808 BOOL IsFATSuperBlock(struct FATSuperBlock *fsb)
5810 BOOL result;
5811 result = (BOOL)(strncmp(fsb->fsb_Vendor, "MSDOS", 5) == 0 ||
5812 strncmp(fsb->fsb_Vendor, "MSWIN", 5) == 0 ||
5813 strncmp(fsb->fsb_FileSystem, "FAT12", 5) == 0 ||
5814 strncmp(fsb->fsb_FileSystem, "FAT16", 5) == 0 ||
5815 strncmp(fsb->fsb_FileSystem2, "FAT32", 5) == 0);
5817 return(result);
5819 /* \\\ */
5821 /* /// "GetFATDosType()" */
5822 ULONG GetFATDosType(struct FATSuperBlock *fsb)
5824 ULONG result = 0x46415400;
5825 if(strncmp(fsb->fsb_FileSystem2, "FAT32", 5) == 0)
5826 result |= 2;
5827 else if(strncmp(fsb->fsb_FileSystem, "FAT16", 5) == 0)
5828 result |= 1;
5830 return(result);
5832 /* \\\ */
5834 /* /// "CheckFATPartition()" */
5835 void CheckFATPartition(struct NepClassMS *ncm, ULONG startblock)
5837 struct NepMSBase *nh = ncm->ncm_ClsBase;
5838 struct MasterBootRecord *mbr;
5839 struct DosEnvec *envec;
5840 struct IOStdReq *stdIO = &nh->nh_IOReq;
5841 struct DriveGeometry *tddg = &ncm->ncm_Geometry;
5842 BOOL isfat = FALSE;
5843 BOOL isntfs = FALSE;
5845 mbr = (struct MasterBootRecord *) psdAllocVec(ncm->ncm_BlockSize<<1);
5846 if(!mbr)
5848 return;
5851 stdIO->io_Command = TD_READ64;
5852 stdIO->io_Offset = startblock<<ncm->ncm_BlockShift;
5853 stdIO->io_Actual = startblock>>(32-ncm->ncm_BlockShift);
5854 stdIO->io_Length = ncm->ncm_BlockSize;
5855 stdIO->io_Data = mbr;
5856 if(!nIOCmdTunnel(ncm, stdIO))
5858 /* do (super)floppy check */
5859 if(IsFATSuperBlock((struct FATSuperBlock *) mbr))
5861 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Media is FAT formatted!");
5862 isfat = TRUE;
5863 nh->nh_RDsk.rdsk_PART.pb_DevFlags = 0;
5865 if(*(ncm->ncm_CUC->cuc_FATDOSName))
5867 c2bstr(ncm->ncm_CUC->cuc_FATDOSName, nh->nh_RDsk.rdsk_PART.pb_DriveName);
5868 } else {
5869 c2bstr("UF0", nh->nh_RDsk.rdsk_PART.pb_DriveName);
5872 envec = (struct DosEnvec *) nh->nh_RDsk.rdsk_PART.pb_Environment;
5873 memset(envec, 0x00, sizeof(struct DosEnvec));
5874 stdIO->io_Command = TD_GETGEOMETRY;
5875 stdIO->io_Data = tddg;
5876 stdIO->io_Length = sizeof(*tddg);
5878 if(nIOCmdTunnel(ncm, stdIO))
5880 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Couldn't read drive geometry, using floppy defaults");
5881 envec->de_SizeBlock = ncm->ncm_BlockSize>>2;
5882 envec->de_Surfaces = 2;
5883 envec->de_BlocksPerTrack = 18;
5884 envec->de_LowCyl = 0;
5885 envec->de_HighCyl = 79;
5886 } else {
5887 envec->de_SizeBlock = ncm->ncm_BlockSize>>2;
5888 envec->de_Surfaces = tddg->dg_Heads;
5889 envec->de_BlocksPerTrack = tddg->dg_TrackSectors;
5890 envec->de_LowCyl = 0;
5891 envec->de_HighCyl = tddg->dg_Cylinders-1;
5893 envec->de_TableSize = DE_BOOTBLOCKS;
5894 envec->de_SectorPerBlock = 1;
5895 envec->de_NumBuffers = ncm->ncm_CUC->cuc_FATBuffers;
5896 envec->de_BufMemType = MEMF_PUBLIC;
5897 envec->de_MaxTransfer = (1UL<<(ncm->ncm_CDC->cdc_MaxTransfer+16))-1;
5898 envec->de_Mask = 0xffffffff;
5899 envec->de_BootPri = 0;
5900 envec->de_Baud = 1200;
5901 if(*ncm->ncm_CDC->cdc_FATControl)
5903 UBYTE *bptr = ncm->ncm_FATControlBSTR;
5904 bptr = (UBYTE *) ((((IPTR) bptr) + 3) & (~3));
5905 c2bstr(ncm->ncm_CDC->cdc_FATControl, bptr);
5906 envec->de_Control = (IPTR) MKBADDR(bptr);
5907 } else {
5908 envec->de_Control = 0;
5910 envec->de_BootBlocks = 0;
5911 envec->de_Interleave = 0;
5912 envec->de_DosType = ncm->ncm_CDC->cdc_FATDosType; //0x46415401; // FAT1
5913 if((ncm->ncm_CDC->cdc_FATDosType & 0xffffff00) == 0x46415400)
5915 envec->de_DosType =
5916 GetFATDosType((struct FATSuperBlock *) mbr);
5919 // we have no FSHD and LSEG blocks
5920 nh->nh_RDsk.rdsk_RDB.rdb_FileSysHeaderList = NIL_PTR;
5921 nh->nh_RDsk.rdsk_FSHD.fhb_SegListBlocks = 0;
5923 KPRINTF(5, ("building FAT95 style environment\n"));
5925 strncpy((char *) nh->nh_RDsk.rdsk_FSHD.fhb_FileSysName, ncm->ncm_CDC->cdc_FATFSName, 84);
5926 CheckPartition(ncm);
5928 if(!(isfat || isntfs))
5930 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
5931 "Media does not seem to be FAT nor NTFS formatted.");
5933 } else {
5934 KPRINTF(10, ("failed to read MBR\n"));
5935 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
5937 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
5938 "Failed to read MasterBootRecord for FAT/NTFS AutoMounting.");
5941 psdFreeVec(mbr);
5943 /* \\\ */
5945 /* /// "CheckISO9660()" */
5946 void CheckISO9660(struct NepClassMS *ncm)
5948 struct NepMSBase *nh = ncm->ncm_ClsBase;
5949 UBYTE *blockbuf;
5950 struct IOStdReq *stdIO = &nh->nh_IOReq;
5952 blockbuf = (UBYTE *) psdAllocVec(ncm->ncm_BlockSize);
5953 if(!blockbuf)
5955 return;
5957 stdIO->io_Command = TD_READ64;
5958 stdIO->io_Offset = 0x8000;
5959 stdIO->io_Actual = 0;
5960 stdIO->io_Length = ncm->ncm_BlockSize;
5961 stdIO->io_Data = blockbuf;
5962 if(!nIOCmdTunnel(ncm, stdIO))
5964 if((((ULONG *) blockbuf)[0] == AROS_LONG2BE(0x01434430)) && (((ULONG *) blockbuf)[1] == AROS_LONG2BE(0x30310100)))
5966 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Media is ISO9660.");
5967 AutoMountCD(ncm);
5969 } else {
5970 KPRINTF(10, ("failed to read ISO sector\n"));
5971 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
5973 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
5974 "Failed to read block 16 for CDFS AutoMounting.");
5977 psdFreeVec(blockbuf);
5979 /* \\\ */
5981 /* /// "AutoMountCD()" */
5982 void AutoMountCD(struct NepClassMS *ncm)
5984 struct NepMSBase *nh = ncm->ncm_ClsBase;
5985 struct DosEnvec *envec;
5987 nh->nh_RDsk.rdsk_PART.pb_DevFlags = 0;
5989 if(*(ncm->ncm_CUC->cuc_FATDOSName))
5991 c2bstr(ncm->ncm_CUC->cuc_FATDOSName, nh->nh_RDsk.rdsk_PART.pb_DriveName);
5992 } else {
5993 c2bstr("UCD0", nh->nh_RDsk.rdsk_PART.pb_DriveName);
5996 envec = (struct DosEnvec *) nh->nh_RDsk.rdsk_PART.pb_Environment;
5997 memset(envec, 0x00, sizeof(struct DosEnvec));
5999 envec->de_TableSize = DE_BOOTBLOCKS;
6000 envec->de_SizeBlock = ncm->ncm_BlockSize>>2;
6001 envec->de_Surfaces = 1;
6002 envec->de_SectorPerBlock = 1;
6003 envec->de_Reserved = 0xffffffff;
6004 envec->de_NumBuffers = ncm->ncm_CUC->cuc_FATBuffers;
6005 envec->de_BufMemType = MEMF_PUBLIC;
6006 envec->de_MaxTransfer = (1UL<<(ncm->ncm_CDC->cdc_MaxTransfer+16))-1;
6007 envec->de_Mask = 0xffffffff;
6008 envec->de_BootPri = 0;
6009 envec->de_Baud = 1200;
6010 if(*ncm->ncm_CDC->cdc_CDControl)
6012 UBYTE *bptr = ncm->ncm_FATControlBSTR;
6013 bptr = (UBYTE *) ((((IPTR) bptr) + 3) & (~3));
6014 c2bstr(ncm->ncm_CDC->cdc_CDControl, bptr);
6015 envec->de_Control = (IPTR) MKBADDR(bptr);
6016 } else {
6017 envec->de_Control = 0;
6019 envec->de_BootBlocks = 0;
6021 // we have no FSHD and LSEG blocks
6022 nh->nh_RDsk.rdsk_RDB.rdb_FileSysHeaderList = NIL_PTR;
6023 nh->nh_RDsk.rdsk_FSHD.fhb_SegListBlocks = 0;
6025 KPRINTF(5, ("building CDFS style environment\n"));
6027 envec->de_BlocksPerTrack = 1;
6028 envec->de_Interleave = 0;
6029 envec->de_DosType = ncm->ncm_CDC->cdc_CDDosType;
6030 envec->de_LowCyl = 0;
6031 envec->de_HighCyl = 1;
6033 strncpy((char *) nh->nh_RDsk.rdsk_FSHD.fhb_FileSysName, ncm->ncm_CDC->cdc_CDFSName, 84);
6034 CheckPartition(ncm);
6036 /* \\\ */
6038 /**************************************************************************/
6040 static const char *MaxTransferStrings[] =
6042 " 64 KB",
6043 "128 KB",
6044 "256 KB",
6045 "512 KB",
6046 " 1 MB",
6047 " 2 MB",
6048 NULL
6051 static char *MainGUIPages[] = { "Device Settings", "LUN Settings", NULL };
6052 static char *MainGUIPagesDefault[] = { "Device Defaults", "LUN Defaults", NULL };
6054 /* /// "nGetDosType()" */
6055 ULONG nGetDosType(STRPTR tmpstr)
6057 ULONG dostype = 0;
6058 UBYTE ch;
6060 while((ch = *tmpstr++))
6062 dostype <<= 4;
6063 if((ch >= '0') && (ch <= '9'))
6065 dostype += ch - '0';
6067 else if((ch >= 'a') && (ch <= 'f'))
6069 dostype += ch - 'a' + 10;
6071 else if((ch >= 'A') && (ch <= 'F'))
6073 dostype += ch - 'A' + 10;
6076 return(dostype);
6078 /* \\\ */
6080 /* /// "nGUITask()" */
6081 AROS_UFH0(void, GM_UNIQUENAME(nGUITask))
6083 AROS_USERFUNC_INIT
6085 struct Task *thistask;
6086 struct NepMSBase *nh;
6087 struct NepClassMS *ncm;
6088 struct NepClassMS *cncm;
6089 struct NepClassMS *curncm = NULL;
6090 APTR pic;
6091 char dostypebuf[10];
6092 char cddostypebuf[10];
6093 char ntfsdostypebuf[10];
6094 char bar[] = "BAR,";
6096 thistask = FindTask(NULL);
6097 #undef ps
6098 #define ps ncm->ncm_PsdBase
6099 #undef IntuitionBase
6100 #define IntuitionBase ncm->ncm_IntBase
6101 #undef MUIMasterBase
6102 #define MUIMasterBase ncm->ncm_MUIBase
6104 ncm = thistask->tc_UserData;
6105 nh = ncm->ncm_ClsBase;
6107 ++nh->nh_Library.lib_OpenCnt;
6108 if(!(MUIMasterBase = OpenLibrary(MUIMASTER_NAME, MUIMASTER_VMIN)))
6110 KPRINTF(10, ("Couldn't open muimaster.library.\n"));
6111 GM_UNIQUENAME(nGUITaskCleanup)(ncm);
6112 return;
6115 if(!(IntuitionBase = OpenLibrary("intuition.library", 39)))
6117 KPRINTF(10, ("Couldn't open intuition.library.\n"));
6118 GM_UNIQUENAME(nGUITaskCleanup)(ncm);
6119 return;
6121 if(!(ps = OpenLibrary("poseidon.library", 4)))
6123 KPRINTF(10, ("Couldn't open poseidon.library.\n"));
6124 GM_UNIQUENAME(nGUITaskCleanup)(ncm);
6125 return;
6128 ncm->ncm_LUNListDisplayHook.h_Data = NULL;
6129 ncm->ncm_LUNListDisplayHook.h_Entry = (APTR) GM_UNIQUENAME(LUNListDisplayHook);
6131 psdSafeRawDoFmt(dostypebuf, 10, "%08lx", ncm->ncm_CDC->cdc_FATDosType);
6132 psdSafeRawDoFmt(ntfsdostypebuf, 10, "%08lx", ncm->ncm_CDC->cdc_NTFSDosType);
6133 psdSafeRawDoFmt(cddostypebuf, 10, "%08lx", ncm->ncm_CDC->cdc_CDDosType);
6135 ncm->ncm_App = (APTR) ApplicationObject,
6136 MUIA_Application_Title , (IPTR) GM_UNIQUENAME(libname),
6137 MUIA_Application_Version , (IPTR) VERSION_STRING,
6138 MUIA_Application_Copyright , (IPTR) "©2002-2009 Chris Hodges",
6139 MUIA_Application_Author , (IPTR) "Chris Hodges <chrisly@platon42.de>",
6140 MUIA_Application_Description, (IPTR) "Settings for the massstorage.class",
6141 MUIA_Application_Base , (IPTR) "MASSSTORAGE",
6142 MUIA_Application_HelpFile , (IPTR) "HELP:Poseidon.guide",
6143 MUIA_Application_Menustrip , (IPTR) MenustripObject,
6144 Child, (IPTR) MenuObjectT((IPTR) "Project"),
6145 Child, (IPTR) (ncm->ncm_AboutMI = (APTR) MenuitemObject,
6146 MUIA_Menuitem_Title, (IPTR) "About...",
6147 MUIA_Menuitem_Shortcut, (IPTR) "?",
6148 End),
6149 End,
6150 Child, (IPTR) MenuObjectT((IPTR) "Settings"),
6151 Child, (IPTR) (ncm->ncm_UseMI = (APTR) MenuitemObject,
6152 MUIA_Menuitem_Title, (IPTR) "Save",
6153 MUIA_Menuitem_Shortcut, (IPTR) "S",
6154 End),
6155 Child, (IPTR) (ncm->ncm_SetDefaultMI = (APTR) MenuitemObject,
6156 MUIA_Menuitem_Title, (IPTR) "Save as Default",
6157 MUIA_Menuitem_Shortcut, (IPTR) "D",
6158 End),
6159 Child, (IPTR) MenuitemObject,
6160 MUIA_Menuitem_Title, (IPTR) NM_BARLABEL,
6161 End,
6162 Child, (IPTR) (ncm->ncm_MUIPrefsMI = (APTR) MenuitemObject,
6163 MUIA_Menuitem_Title, (IPTR) "MUI Settings",
6164 MUIA_Menuitem_Shortcut, (IPTR) "M",
6165 End),
6166 End,
6167 End,
6169 SubWindow, (IPTR) (ncm->ncm_MainWindow = (APTR) WindowObject,
6170 MUIA_Window_ID , MAKE_ID('M','A','I','N'),
6171 MUIA_Window_Title, (IPTR) GM_UNIQUENAME(libname),
6172 MUIA_HelpNode, (IPTR) GM_UNIQUENAME(libname),
6174 WindowContents, (IPTR) VGroup,
6175 Child, (IPTR) RegisterGroup(ncm->ncm_Interface ? MainGUIPages : MainGUIPagesDefault),
6176 MUIA_CycleChain, 1,
6177 MUIA_Register_Frame, TRUE,
6178 Child, (IPTR) VGroup,
6179 Child, (IPTR) VSpace(0),
6180 Child, (IPTR) ColGroup(2),
6181 Child, (IPTR) Label("NAK Timeout:"),
6182 Child, (IPTR) (ncm->ncm_NakTimeoutObj = (APTR) SliderObject, SliderFrame,
6183 MUIA_CycleChain, 1,
6184 MUIA_Numeric_Min, 0,
6185 MUIA_Numeric_Max, 600,
6186 MUIA_Numeric_Value, ncm->ncm_CDC->cdc_NakTimeout,
6187 MUIA_Numeric_Format, (IPTR) "%ld00ms",
6188 End),
6189 Child, (IPTR) Label("Startup delay:"),
6190 Child, (IPTR) (ncm->ncm_StartupDelayObj = (APTR) SliderObject, SliderFrame,
6191 MUIA_CycleChain, 1,
6192 MUIA_Numeric_Min, 0,
6193 MUIA_Numeric_Max, 100,
6194 MUIA_Numeric_Value, ncm->ncm_CDC->cdc_StartupDelay,
6195 MUIA_Numeric_Format, (IPTR) "%ld00ms",
6196 End),
6197 Child, (IPTR) Label("Single LUN:"),
6198 Child, (IPTR) HGroup,
6199 Child, (IPTR) (ncm->ncm_SingleLunObj = (APTR) ImageObject, ImageButtonFrame,
6200 MUIA_Background, MUII_ButtonBack,
6201 MUIA_CycleChain, 1,
6202 MUIA_InputMode, MUIV_InputMode_Toggle,
6203 MUIA_Image_Spec, MUII_CheckMark,
6204 MUIA_Image_FreeVert, TRUE,
6205 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_SINGLE_LUN,
6206 MUIA_ShowSelState, FALSE,
6207 End),
6208 Child, (IPTR) HSpace(0),
6209 Child, (IPTR) Label("No Initial Reset:"),
6210 Child, (IPTR) (ncm->ncm_InitialResetObj = (APTR) ImageObject, ImageButtonFrame,
6211 MUIA_Background, MUII_ButtonBack,
6212 MUIA_CycleChain, 1,
6213 MUIA_InputMode, MUIV_InputMode_Toggle,
6214 MUIA_Image_Spec, MUII_CheckMark,
6215 MUIA_Image_FreeVert, TRUE,
6216 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_RESET,
6217 MUIA_ShowSelState, FALSE,
6218 End),
6219 End,
6220 Child, (IPTR) Label("Simple SCSI:"),
6221 Child, (IPTR) HGroup,
6222 Child, (IPTR) (ncm->ncm_SimpleSCSIObj = (APTR) ImageObject, ImageButtonFrame,
6223 MUIA_Background, MUII_ButtonBack,
6224 MUIA_CycleChain, 1,
6225 MUIA_InputMode, MUIV_InputMode_Toggle,
6226 MUIA_Image_Spec, MUII_CheckMark,
6227 MUIA_Image_FreeVert, TRUE,
6228 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_SIMPLE_SCSI,
6229 MUIA_ShowSelState, FALSE,
6230 End),
6231 Child, (IPTR) HSpace(0),
6232 Child, (IPTR) Label("Translate CMD6->CMD10:"),
6233 Child, (IPTR) (ncm->ncm_XLate610Obj = (APTR) ImageObject, ImageButtonFrame,
6234 MUIA_Background, MUII_ButtonBack,
6235 MUIA_CycleChain, 1,
6236 MUIA_InputMode, MUIV_InputMode_Toggle,
6237 MUIA_Image_Spec, MUII_CheckMark,
6238 MUIA_Image_FreeVert, TRUE,
6239 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_MODE_XLATE,
6240 MUIA_ShowSelState, FALSE,
6241 End),
6242 End,
6243 Child, (IPTR) Label("Fake Inquiry:"),
6244 Child, (IPTR) HGroup,
6245 Child, (IPTR) (ncm->ncm_FakeInquiryObj = (APTR) ImageObject, ImageButtonFrame,
6246 MUIA_Background, MUII_ButtonBack,
6247 MUIA_CycleChain, 1,
6248 MUIA_InputMode, MUIV_InputMode_Toggle,
6249 MUIA_Image_Spec, MUII_CheckMark,
6250 MUIA_Image_FreeVert, TRUE,
6251 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_FAKE_INQUIRY,
6252 MUIA_ShowSelState, FALSE,
6253 End),
6254 Child, (IPTR) HSpace(0),
6255 Child, (IPTR) Label("Better Removable Support:"),
6256 Child, (IPTR) (ncm->ncm_RemSupportObj = (APTR) ImageObject, ImageButtonFrame,
6257 MUIA_Background, MUII_ButtonBack,
6258 MUIA_CycleChain, 1,
6259 MUIA_InputMode, MUIV_InputMode_Toggle,
6260 MUIA_Image_Spec, MUII_CheckMark,
6261 MUIA_Image_FreeVert, TRUE,
6262 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_REM_SUPPORT,
6263 MUIA_ShowSelState, FALSE,
6264 End),
6265 End,
6266 Child, (IPTR) Label("Trim Inquiry:"),
6267 Child, (IPTR) HGroup,
6268 Child, (IPTR) (ncm->ncm_FixInquiryObj = (APTR) ImageObject, ImageButtonFrame,
6269 MUIA_Background, MUII_ButtonBack,
6270 MUIA_CycleChain, 1,
6271 MUIA_InputMode, MUIV_InputMode_Toggle,
6272 MUIA_Image_Spec, MUII_CheckMark,
6273 MUIA_Image_FreeVert, TRUE,
6274 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_FIX_INQ36,
6275 MUIA_ShowSelState, FALSE,
6276 End),
6277 Child, (IPTR) HSpace(0),
6278 Child, (IPTR) Label("Ignore broken CSS-ID:"),
6279 Child, (IPTR) (ncm->ncm_CSSBrokenObj = (APTR) ImageObject, ImageButtonFrame,
6280 MUIA_Background, MUII_ButtonBack,
6281 MUIA_CycleChain, 1,
6282 MUIA_InputMode, MUIV_InputMode_Toggle,
6283 MUIA_Image_Spec, MUII_CheckMark,
6284 MUIA_Image_FreeVert, TRUE,
6285 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_CSS_BROKEN,
6286 MUIA_ShowSelState, FALSE,
6287 End),
6288 End,
6289 Child, (IPTR) Label("Fix Capacity:"),
6290 Child, (IPTR) HGroup,
6291 Child, (IPTR) (ncm->ncm_FixCapacityObj = (APTR) ImageObject, ImageButtonFrame,
6292 MUIA_Background, MUII_ButtonBack,
6293 MUIA_CycleChain, 1,
6294 MUIA_InputMode, MUIV_InputMode_Toggle,
6295 MUIA_Image_Spec, MUII_CheckMark,
6296 MUIA_Image_FreeVert, TRUE,
6297 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_FIX_CAPACITY,
6298 MUIA_ShowSelState, FALSE,
6299 End),
6300 Child, (IPTR) HSpace(0),
6301 Child, (IPTR) Label("Emulate on larger block sizes:"),
6302 Child, (IPTR) (ncm->ncm_EmulLargeBlkObj = (APTR) ImageObject, ImageButtonFrame,
6303 MUIA_Background, MUII_ButtonBack,
6304 MUIA_CycleChain, 1,
6305 MUIA_InputMode, MUIV_InputMode_Toggle,
6306 MUIA_Image_Spec, MUII_CheckMark,
6307 MUIA_Image_FreeVert, TRUE,
6308 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_EMUL_LARGE_BLK,
6309 MUIA_ShowSelState, FALSE,
6310 End),
6311 End,
6312 Child, (IPTR) Label("No Fallback:"),
6313 Child, (IPTR) HGroup,
6314 Child, (IPTR) (ncm->ncm_NoFallbackObj = (APTR) ImageObject, ImageButtonFrame,
6315 MUIA_Background, MUII_ButtonBack,
6316 MUIA_CycleChain, 1,
6317 MUIA_InputMode, MUIV_InputMode_Toggle,
6318 MUIA_Image_Spec, MUII_CheckMark,
6319 MUIA_Image_FreeVert, TRUE,
6320 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_FALLBACK,
6321 MUIA_ShowSelState, FALSE,
6322 End),
6323 Child, (IPTR) HSpace(0),
6324 Child, (IPTR) Label("Debug:"),
6325 Child, (IPTR) (ncm->ncm_DebugObj = (APTR) ImageObject, ImageButtonFrame,
6326 MUIA_Background, MUII_ButtonBack,
6327 MUIA_CycleChain, 1,
6328 MUIA_InputMode, MUIV_InputMode_Toggle,
6329 MUIA_Image_Spec, MUII_CheckMark,
6330 MUIA_Image_FreeVert, TRUE,
6331 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG,
6332 MUIA_ShowSelState, FALSE,
6333 End),
6334 End,
6335 Child, (IPTR) Label("Max Transfer:"),
6336 Child, (IPTR) HGroup,
6337 Child, (IPTR) (ncm->ncm_MaxTransferObj = (APTR) CycleObject,
6338 MUIA_Cycle_Entries, (IPTR) MaxTransferStrings,
6339 MUIA_Cycle_Active, ncm->ncm_CDC->cdc_MaxTransfer,
6340 End),
6341 //Child, HSpace(0),
6342 Child, (IPTR) (ncm->ncm_AutoDtxMaxTransObj = (APTR) TextObject, ButtonFrame,
6343 MUIA_Disabled, !ncm->ncm_Interface,
6344 MUIA_Background, MUII_ButtonBack,
6345 MUIA_CycleChain, 1,
6346 MUIA_InputMode, MUIV_InputMode_RelVerify,
6347 MUIA_Text_Contents, (IPTR) "\33c Auto-detect ",
6348 End),
6349 End,
6350 End,
6351 Child, (IPTR) VSpace(0),
6353 Child, (IPTR) ColGroup(6),
6354 Child, (IPTR) Label("FAT:"),
6355 Child, (IPTR) PopaslObject,
6356 MUIA_Popstring_String, (IPTR) (ncm->ncm_FatFSObj = (APTR) StringObject,
6357 StringFrame,
6358 MUIA_CycleChain, 1,
6359 MUIA_String_AdvanceOnCR, TRUE,
6360 MUIA_String_Contents, (IPTR) ncm->ncm_CDC->cdc_FATFSName,
6361 MUIA_String_MaxLen, 63,
6362 End),
6363 MUIA_Popstring_Button, (IPTR) PopButton(MUII_PopFile),
6364 ASLFR_TitleText, (IPTR) "Select filesystem to use with FAT partitions...",
6365 End,
6366 Child, (IPTR) Label("DosType:"),
6367 Child, (IPTR) (ncm->ncm_FatDosTypeObj = (APTR) StringObject,
6368 StringFrame,
6369 MUIA_HorizWeight, 50,
6370 MUIA_CycleChain, 1,
6371 MUIA_String_AdvanceOnCR, TRUE,
6372 MUIA_String_Contents, (IPTR) dostypebuf,
6373 MUIA_String_Accept, (IPTR) "0123456789abcdefABCDEF",
6374 MUIA_String_MaxLen, 9,
6375 End),
6376 Child, (IPTR) Label("Ctrl:"),
6377 Child, (IPTR) (ncm->ncm_FatControlObj = (APTR) StringObject,
6378 StringFrame,
6379 MUIA_HorizWeight, 50,
6380 MUIA_CycleChain, 1,
6381 MUIA_String_AdvanceOnCR, TRUE,
6382 MUIA_String_Contents, (IPTR) ncm->ncm_CDC->cdc_FATControl,
6383 MUIA_String_MaxLen, 63,
6384 End),
6385 Child, (IPTR) Label("NTFS:"),
6386 Child, (IPTR) PopaslObject,
6387 MUIA_Popstring_String, (IPTR) (ncm->ncm_NTFSObj = (APTR) StringObject,
6388 StringFrame,
6389 MUIA_CycleChain, 1,
6390 MUIA_String_AdvanceOnCR, TRUE,
6391 MUIA_String_Contents, (IPTR) ncm->ncm_CDC->cdc_NTFSName,
6392 MUIA_String_MaxLen, 63,
6393 End),
6394 MUIA_Popstring_Button, (IPTR) PopButton(MUII_PopFile),
6395 ASLFR_TitleText, (IPTR) "Select filesystem to use with NTFS partitions...",
6396 End,
6397 Child, (IPTR) Label("DosType:"),
6398 Child, (IPTR) (ncm->ncm_NTFSDosTypeObj = (APTR) StringObject,
6399 StringFrame,
6400 MUIA_HorizWeight, 50,
6401 MUIA_CycleChain, 1,
6402 MUIA_String_AdvanceOnCR, TRUE,
6403 MUIA_String_Contents, (IPTR) ntfsdostypebuf,
6404 MUIA_String_Accept, (IPTR) "0123456789abcdefABCDEF",
6405 MUIA_String_MaxLen, 9,
6406 End),
6407 Child, (IPTR) Label("Ctrl:"),
6408 Child, (IPTR) (ncm->ncm_NTFSControlObj = (APTR) StringObject,
6409 StringFrame,
6410 MUIA_HorizWeight, 50,
6411 MUIA_CycleChain, 1,
6412 MUIA_String_AdvanceOnCR, TRUE,
6413 MUIA_String_Contents, (IPTR) ncm->ncm_CDC->cdc_NTFSControl,
6414 MUIA_String_MaxLen, 63,
6415 End),
6416 Child, (IPTR) Label("CD/DVD:"),
6417 Child, (IPTR) PopaslObject,
6418 MUIA_Popstring_String, (IPTR) (ncm->ncm_CDFSObj = (APTR) StringObject,
6419 StringFrame,
6420 MUIA_CycleChain, 1,
6421 MUIA_String_AdvanceOnCR, TRUE,
6422 MUIA_String_Contents, (IPTR) ncm->ncm_CDC->cdc_CDFSName,
6423 MUIA_String_MaxLen, 63,
6424 End),
6425 MUIA_Popstring_Button, (IPTR) PopButton(MUII_PopFile),
6426 ASLFR_TitleText, (IPTR) "Select filesystem to use with CD/DVD partitions...",
6427 End,
6428 Child, (IPTR) Label("DosType:"),
6429 Child, (IPTR) (ncm->ncm_CDDosTypeObj = (APTR) StringObject,
6430 StringFrame,
6431 MUIA_HorizWeight, 50,
6432 MUIA_CycleChain, 1,
6433 MUIA_String_AdvanceOnCR, TRUE,
6434 MUIA_String_Contents, (IPTR) cddostypebuf,
6435 MUIA_String_Accept, (IPTR) "0123456789abcdefABCDEF",
6436 MUIA_String_MaxLen, 9,
6437 End),
6438 Child, (IPTR) Label("Ctrl:"),
6439 Child, (IPTR) (ncm->ncm_CDControlObj = (APTR) StringObject,
6440 StringFrame,
6441 MUIA_HorizWeight, 50,
6442 MUIA_CycleChain, 1,
6443 MUIA_String_AdvanceOnCR, TRUE,
6444 MUIA_String_Contents, (IPTR) ncm->ncm_CDC->cdc_CDControl,
6445 MUIA_String_MaxLen, 63,
6446 End),
6447 End,
6448 Child, (IPTR) VSpace(0),
6449 End,
6450 Child, (IPTR) VGroup,
6451 Child, (IPTR) ListviewObject,
6452 MUIA_CycleChain, 1,
6453 MUIA_Listview_List, (IPTR) (ncm->ncm_LunLVObj = (APTR) ListObject,
6454 ReadListFrame,
6455 MUIA_List_Format, (IPTR) bar,
6456 MUIA_List_Title, TRUE,
6457 MUIA_List_DisplayHook, (IPTR) &ncm->ncm_LUNListDisplayHook,
6458 End),
6459 End,
6460 Child, (IPTR) (ncm->ncm_LunGroupObj = (APTR) VGroup,
6461 MUIA_Disabled, TRUE,
6462 Child, (IPTR) VSpace(0),
6463 Child, (IPTR) HGroup,
6464 Child, (IPTR) (ncm->ncm_AutoMountRDBObj = (APTR) ImageObject, ImageButtonFrame,
6465 MUIA_Background, MUII_ButtonBack,
6466 MUIA_CycleChain, 1,
6467 MUIA_InputMode, MUIV_InputMode_Toggle,
6468 MUIA_Image_Spec, MUII_CheckMark,
6469 MUIA_Image_FreeVert, TRUE,
6470 MUIA_Selected, TRUE,
6471 MUIA_ShowSelState, FALSE,
6472 End),
6473 Child, (IPTR) Label("AutoMount RDB partitions"),
6474 Child, (IPTR) HSpace(0),
6475 End,
6476 Child, (IPTR) HGroup,
6477 Child, (IPTR) (ncm->ncm_BootRDBObj = (APTR) ImageObject, ImageButtonFrame,
6478 MUIA_Background, MUII_ButtonBack,
6479 MUIA_CycleChain, 1,
6480 MUIA_InputMode, MUIV_InputMode_Toggle,
6481 MUIA_Image_Spec, MUII_CheckMark,
6482 MUIA_Image_FreeVert, TRUE,
6483 MUIA_Selected, FALSE,
6484 MUIA_ShowSelState, FALSE,
6485 End),
6486 Child, (IPTR) Label("Boot from RDB partitions"),
6487 Child, (IPTR) HSpace(0),
6488 End,
6489 Child, (IPTR) VSpace(0),
6490 Child, (IPTR) HGroup,
6491 Child, (IPTR) (ncm->ncm_AutoMountFATObj = (APTR) ImageObject, ImageButtonFrame,
6492 MUIA_Background, MUII_ButtonBack,
6493 MUIA_CycleChain, 1,
6494 MUIA_InputMode, MUIV_InputMode_Toggle,
6495 MUIA_Image_Spec, MUII_CheckMark,
6496 MUIA_Image_FreeVert, TRUE,
6497 MUIA_Selected, TRUE,
6498 MUIA_ShowSelState, FALSE,
6499 End),
6500 Child, (IPTR) Label("AutoMount FAT/NTFS partitions"),
6501 Child, (IPTR) HSpace(0),
6502 End,
6503 Child, (IPTR) HGroup,
6504 Child, (IPTR) (ncm->ncm_MountAllFATObj = (APTR) ImageObject, ImageButtonFrame,
6505 MUIA_Background, MUII_ButtonBack,
6506 MUIA_CycleChain, 1,
6507 MUIA_InputMode, MUIV_InputMode_Toggle,
6508 MUIA_Image_Spec, MUII_CheckMark,
6509 MUIA_Image_FreeVert, TRUE,
6510 MUIA_Selected, TRUE,
6511 MUIA_ShowSelState, FALSE,
6512 End),
6513 Child, (IPTR) Label("Mount all FAT partitions"),
6514 Child, (IPTR) HSpace(0),
6515 End,
6516 Child, (IPTR) VSpace(0),
6517 Child, (IPTR) HGroup,
6518 Child, (IPTR) (ncm->ncm_AutoMountCDObj = (APTR) ImageObject, ImageButtonFrame,
6519 MUIA_Background, MUII_ButtonBack,
6520 MUIA_CycleChain, 1,
6521 MUIA_InputMode, MUIV_InputMode_Toggle,
6522 MUIA_Image_Spec, MUII_CheckMark,
6523 MUIA_Image_FreeVert, TRUE,
6524 MUIA_Selected, TRUE,
6525 MUIA_ShowSelState, FALSE,
6526 End),
6527 Child, (IPTR) Label("AutoMount CD/DVD"),
6528 Child, (IPTR) HSpace(0),
6529 End,
6530 Child, (IPTR) VSpace(0),
6531 Child, (IPTR) HGroup,
6532 Child, (IPTR) (ncm->ncm_UnmountObj = (APTR) ImageObject, ImageButtonFrame,
6533 MUIA_Background, MUII_ButtonBack,
6534 MUIA_CycleChain, 1,
6535 MUIA_InputMode, MUIV_InputMode_Toggle,
6536 MUIA_Image_Spec, MUII_CheckMark,
6537 MUIA_Image_FreeVert, TRUE,
6538 MUIA_Selected, FALSE,
6539 MUIA_ShowSelState, FALSE,
6540 End),
6541 Child, (IPTR) HGroup,
6542 Child, (IPTR) Label("Unmount partitions after removal"),
6543 Child, (IPTR) HSpace(0),
6544 End,
6545 End,
6546 Child, (IPTR) VSpace(0),
6547 Child, (IPTR) HGroup,
6548 Child, (IPTR) Label("DOSName:"),
6549 Child, (IPTR) (ncm->ncm_FatDOSNameObj = (APTR) StringObject,
6550 StringFrame,
6551 MUIA_CycleChain, 1,
6552 MUIA_String_AdvanceOnCR, TRUE,
6553 MUIA_String_Contents, (IPTR) "UMSD",
6554 MUIA_String_Reject, (IPTR) "/ :?#*",
6555 MUIA_String_MaxLen, 31,
6556 End),
6557 Child, (IPTR) Label("Buffers:"),
6558 Child, (IPTR) (ncm->ncm_FatBuffersObj = (APTR) StringObject,
6559 StringFrame,
6560 MUIA_CycleChain, 1,
6561 MUIA_String_AdvanceOnCR, TRUE,
6562 MUIA_String_Integer, 100,
6563 MUIA_String_Accept, (IPTR) "0123456789",
6564 End),
6565 End,
6566 Child, (IPTR) VSpace(0),
6567 Child, (IPTR) HGroup,
6568 Child, (IPTR) Label("Default " DEVNAME " unit:"),
6569 Child, (IPTR) (ncm->ncm_UnitObj = (APTR) StringObject,
6570 StringFrame,
6571 MUIA_CycleChain, 1,
6572 MUIA_String_AdvanceOnCR, TRUE,
6573 MUIA_String_Integer, 0,
6574 MUIA_String_Accept, (IPTR) "0123456789",
6575 End),
6576 End,
6577 End),
6578 End,
6579 End,
6580 Child, (IPTR) HGroup,
6581 MUIA_Group_SameWidth, TRUE,
6582 Child, (IPTR) (ncm->ncm_UseObj = (APTR) TextObject, ButtonFrame,
6583 MUIA_ShowMe, (IPTR) ncm->ncm_Interface,
6584 MUIA_Background, MUII_ButtonBack,
6585 MUIA_CycleChain, 1,
6586 MUIA_InputMode, MUIV_InputMode_RelVerify,
6587 MUIA_Text_Contents, (IPTR) "\33c Save ",
6588 End),
6589 Child, (IPTR) (ncm->ncm_SetDefaultObj = (APTR) TextObject, ButtonFrame,
6590 MUIA_Background, MUII_ButtonBack,
6591 MUIA_CycleChain, 1,
6592 MUIA_InputMode, MUIV_InputMode_RelVerify,
6593 MUIA_Text_Contents, ncm->ncm_Interface ? (IPTR) "\33c Save as Default " : (IPTR) "\33c Save Defaults ",
6594 End),
6595 Child, (IPTR) (ncm->ncm_CloseObj = (APTR) TextObject, ButtonFrame,
6596 MUIA_Background, MUII_ButtonBack,
6597 MUIA_CycleChain, 1,
6598 MUIA_InputMode, MUIV_InputMode_RelVerify,
6599 MUIA_Text_Contents, (IPTR) "\33c Use ",
6600 End),
6601 End,
6602 End,
6603 End),
6604 End;
6606 if(!ncm->ncm_App)
6608 KPRINTF(10, ("Couldn't create application\n"));
6609 GM_UNIQUENAME(nGUITaskCleanup)(ncm);
6610 return;
6613 if(ncm->ncm_Interface)
6615 cncm = ncm;
6616 while(((struct Node *) cncm)->ln_Succ)
6618 if(cncm->ncm_UnitLUN0 != ncm)
6620 break;
6622 DoMethod(ncm->ncm_LunLVObj, MUIM_List_InsertSingle, cncm, MUIV_List_Insert_Bottom);
6623 cncm = (struct NepClassMS *) ((struct Node *) cncm)->ln_Succ;
6625 } else {
6626 DoMethod(ncm->ncm_LunLVObj, MUIM_List_InsertSingle, ncm, MUIV_List_Insert_Bottom);
6628 DoMethod(ncm->ncm_MainWindow, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
6629 ncm->ncm_App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
6630 DoMethod(ncm->ncm_UseObj, MUIM_Notify, MUIA_Pressed, FALSE,
6631 ncm->ncm_App, 2, MUIM_Application_ReturnID, ID_STORE_CONFIG);
6632 DoMethod(ncm->ncm_SetDefaultObj, MUIM_Notify, MUIA_Pressed, FALSE,
6633 ncm->ncm_App, 2, MUIM_Application_ReturnID, ID_DEF_CONFIG);
6634 DoMethod(ncm->ncm_CloseObj, MUIM_Notify, MUIA_Pressed, FALSE,
6635 ncm->ncm_App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
6637 DoMethod(ncm->ncm_AutoDtxMaxTransObj, MUIM_Notify, MUIA_Pressed, FALSE,
6638 ncm->ncm_App, 2, MUIM_Application_ReturnID, ID_AUTODTXMAXTX);
6639 DoMethod(ncm->ncm_LunLVObj, MUIM_Notify, MUIA_List_Active, MUIV_EveryTime,
6640 ncm->ncm_App, 2, MUIM_Application_ReturnID, ID_SELECT_LUN);
6642 DoMethod(ncm->ncm_AboutMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
6643 ncm->ncm_App, 2, MUIM_Application_ReturnID, ID_ABOUT);
6644 DoMethod(ncm->ncm_UseMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
6645 ncm->ncm_App, 2, MUIM_Application_ReturnID, ID_STORE_CONFIG);
6646 DoMethod(ncm->ncm_SetDefaultMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
6647 ncm->ncm_App, 2, MUIM_Application_ReturnID, ID_DEF_CONFIG);
6648 DoMethod(ncm->ncm_MUIPrefsMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
6649 ncm->ncm_App, 2, MUIM_Application_OpenConfigWindow, 0);
6651 set(ncm->ncm_LunLVObj, MUIA_List_Active, MUIV_List_Active_Top);
6653 IPTR isopen = 0;
6654 IPTR iconify = 0;
6655 ULONG sigs;
6656 ULONG sigmask;
6657 LONG retid;
6659 get(ncm->ncm_App, MUIA_Application_Iconified, &iconify);
6660 set(ncm->ncm_MainWindow, MUIA_Window_Open, TRUE);
6661 get(ncm->ncm_MainWindow, MUIA_Window_Open, &isopen);
6662 if(!(isopen || iconify))
6664 GM_UNIQUENAME(nGUITaskCleanup)(ncm);
6665 return;
6667 sigmask = 0;
6670 retid = DoMethod(ncm->ncm_App, MUIM_Application_NewInput, &sigs);
6671 switch(retid)
6673 case ID_DEF_CONFIG:
6674 case ID_STORE_CONFIG:
6675 case MUIV_Application_ReturnID_Quit:
6677 ULONG tmpflags;
6678 ULONG patchflags;
6679 STRPTR tmpstr;
6681 get(ncm->ncm_NakTimeoutObj, MUIA_Numeric_Value, &ncm->ncm_CDC->cdc_NakTimeout);
6682 get(ncm->ncm_StartupDelayObj, MUIA_Numeric_Value, &ncm->ncm_CDC->cdc_StartupDelay);
6683 patchflags = ncm->ncm_CDC->cdc_PatchFlags & ~(PFF_SINGLE_LUN|PFF_FAKE_INQUIRY|PFF_SIMPLE_SCSI|PFF_NO_RESET|PFF_MODE_XLATE|PFF_DEBUG|PFF_NO_FALLBACK|PFF_REM_SUPPORT|PFF_FIX_INQ36|PFF_CSS_BROKEN|PFF_FIX_CAPACITY|PFF_EMUL_LARGE_BLK);
6684 tmpflags = 0;
6685 get(ncm->ncm_SingleLunObj, MUIA_Selected, &tmpflags);
6686 if(tmpflags) patchflags |= PFF_SINGLE_LUN;
6687 tmpflags = 0;
6688 get(ncm->ncm_FakeInquiryObj, MUIA_Selected, &tmpflags);
6689 if(tmpflags) patchflags |= PFF_FAKE_INQUIRY;
6690 tmpflags = 0;
6691 get(ncm->ncm_SimpleSCSIObj, MUIA_Selected, &tmpflags);
6692 if(tmpflags) patchflags |= PFF_SIMPLE_SCSI;
6693 tmpflags = 0;
6694 get(ncm->ncm_InitialResetObj, MUIA_Selected, &tmpflags);
6695 if(tmpflags) patchflags |= PFF_NO_RESET;
6696 tmpflags = 0;
6697 get(ncm->ncm_XLate610Obj, MUIA_Selected, &tmpflags);
6698 if(tmpflags) patchflags |= PFF_MODE_XLATE;
6699 tmpflags = 0;
6700 get(ncm->ncm_RemSupportObj, MUIA_Selected, &tmpflags);
6701 if(tmpflags) patchflags |= PFF_REM_SUPPORT;
6702 tmpflags = 0;
6703 get(ncm->ncm_FixInquiryObj, MUIA_Selected, &tmpflags);
6704 if(tmpflags) patchflags |= PFF_FIX_INQ36;
6705 tmpflags = 0;
6706 get(ncm->ncm_CSSBrokenObj, MUIA_Selected, &tmpflags);
6707 if(tmpflags) patchflags |= PFF_CSS_BROKEN;
6708 tmpflags = 0;
6709 get(ncm->ncm_FixCapacityObj, MUIA_Selected, &tmpflags);
6710 if(tmpflags) patchflags |= PFF_FIX_CAPACITY;
6711 tmpflags = 0;
6712 get(ncm->ncm_EmulLargeBlkObj, MUIA_Selected, &tmpflags);
6713 if(tmpflags) patchflags |= PFF_EMUL_LARGE_BLK;
6714 tmpflags = 0;
6715 get(ncm->ncm_NoFallbackObj, MUIA_Selected, &tmpflags);
6716 if(tmpflags) patchflags |= PFF_NO_FALLBACK;
6717 tmpflags = 0;
6718 get(ncm->ncm_DebugObj, MUIA_Selected, &tmpflags);
6719 if(tmpflags) patchflags |= PFF_DEBUG;
6720 ncm->ncm_CDC->cdc_PatchFlags = patchflags;
6722 get(ncm->ncm_MaxTransferObj, MUIA_Cycle_Active, &ncm->ncm_CDC->cdc_MaxTransfer);
6724 tmpstr = "";
6725 get(ncm->ncm_FatFSObj, MUIA_String_Contents, &tmpstr);
6726 strncpy(ncm->ncm_CDC->cdc_FATFSName, tmpstr, 63);
6727 tmpstr = "";
6728 get(ncm->ncm_FatControlObj, MUIA_String_Contents, &tmpstr);
6729 strncpy(ncm->ncm_CDC->cdc_FATControl, tmpstr, 63);
6730 tmpstr = "";
6731 get(ncm->ncm_FatDosTypeObj, MUIA_String_Contents, &tmpstr);
6732 ncm->ncm_CDC->cdc_FATDosType = nGetDosType(tmpstr);
6734 tmpstr = "";
6735 get(ncm->ncm_NTFSObj, MUIA_String_Contents, &tmpstr);
6736 strncpy(ncm->ncm_CDC->cdc_NTFSName, tmpstr, 63);
6737 tmpstr = "";
6738 get(ncm->ncm_NTFSControlObj, MUIA_String_Contents, &tmpstr);
6739 strncpy(ncm->ncm_CDC->cdc_NTFSControl, tmpstr, 63);
6740 tmpstr = "";
6741 get(ncm->ncm_NTFSDosTypeObj, MUIA_String_Contents, &tmpstr);
6742 ncm->ncm_CDC->cdc_NTFSDosType = nGetDosType(tmpstr);
6744 tmpstr = "";
6745 get(ncm->ncm_CDFSObj, MUIA_String_Contents, &tmpstr);
6746 strncpy(ncm->ncm_CDC->cdc_CDFSName, tmpstr, 63);
6747 tmpstr = "";
6748 get(ncm->ncm_CDControlObj, MUIA_String_Contents, &tmpstr);
6749 strncpy(ncm->ncm_CDC->cdc_CDControl, tmpstr, 63);
6750 tmpstr = "";
6751 get(ncm->ncm_CDDosTypeObj, MUIA_String_Contents, &tmpstr);
6752 ncm->ncm_CDC->cdc_CDDosType = nGetDosType(tmpstr);
6754 if(ncm->ncm_Interface)
6756 /* copy device config to all luns */
6757 cncm = (struct NepClassMS *) ((struct Node *) ncm)->ln_Succ;
6758 while(((struct Node *) cncm)->ln_Succ)
6760 if(cncm->ncm_UnitLUN0 != ncm)
6762 break;
6764 *(cncm->ncm_CDC) = *(ncm->ncm_CDC);
6765 cncm = (struct NepClassMS *) ((struct Node *) cncm)->ln_Succ;
6768 if(curncm)
6770 get(ncm->ncm_AutoMountFATObj, MUIA_Selected, &curncm->ncm_CUC->cuc_AutoMountFAT);
6771 get(ncm->ncm_MountAllFATObj, MUIA_Selected, &curncm->ncm_CUC->cuc_MountAllFAT);
6772 get(ncm->ncm_AutoMountCDObj, MUIA_Selected, &curncm->ncm_CUC->cuc_AutoMountCD);
6773 tmpstr = "";
6774 get(ncm->ncm_FatDOSNameObj, MUIA_String_Contents, &tmpstr);
6775 strncpy(curncm->ncm_CUC->cuc_FATDOSName, tmpstr, 31);
6776 get(ncm->ncm_FatBuffersObj, MUIA_String_Integer, &curncm->ncm_CUC->cuc_FATBuffers);
6777 get(ncm->ncm_AutoMountRDBObj, MUIA_Selected, &curncm->ncm_CUC->cuc_AutoMountRDB);
6778 get(ncm->ncm_BootRDBObj, MUIA_Selected, &curncm->ncm_CUC->cuc_BootRDB);
6779 get(ncm->ncm_UnitObj, MUIA_String_Integer, &curncm->ncm_CUC->cuc_DefaultUnit);
6780 get(ncm->ncm_UnmountObj, MUIA_Selected, &curncm->ncm_CUC->cuc_AutoUnmount);
6783 if(retid == ID_DEF_CONFIG)
6785 pic = psdGetClsCfg(GM_UNIQUENAME(libname));
6786 if(!pic)
6788 psdSetClsCfg(GM_UNIQUENAME(libname), NULL);
6789 pic = psdGetClsCfg(GM_UNIQUENAME(libname));
6791 if(pic)
6793 psdAddCfgEntry(pic, ncm->ncm_CDC);
6794 psdAddCfgEntry(pic, ncm->ncm_CUC);
6795 psdSaveCfgToDisk(NULL, FALSE);
6798 if(GM_UNIQUENAME(nStoreConfig)(ncm))
6800 if(retid != MUIV_Application_ReturnID_Quit)
6802 psdSaveCfgToDisk(NULL, FALSE);
6804 retid = MUIV_Application_ReturnID_Quit;
6806 break;
6809 case ID_SELECT_LUN:
6811 STRPTR tmpstr;
6812 DoMethod(ncm->ncm_LunLVObj, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &cncm);
6813 if(curncm != cncm)
6815 if(curncm)
6817 get(ncm->ncm_AutoMountFATObj, MUIA_Selected, &curncm->ncm_CUC->cuc_AutoMountFAT);
6818 get(ncm->ncm_MountAllFATObj, MUIA_Selected, &curncm->ncm_CUC->cuc_MountAllFAT);
6819 get(ncm->ncm_AutoMountCDObj, MUIA_Selected, &curncm->ncm_CUC->cuc_AutoMountCD);
6820 tmpstr = "";
6821 get(ncm->ncm_FatDOSNameObj, MUIA_String_Contents, &tmpstr);
6822 strncpy(curncm->ncm_CUC->cuc_FATDOSName, tmpstr, 31);
6823 get(ncm->ncm_FatBuffersObj, MUIA_String_Integer, &curncm->ncm_CUC->cuc_FATBuffers);
6824 get(ncm->ncm_AutoMountRDBObj, MUIA_Selected, &curncm->ncm_CUC->cuc_AutoMountRDB);
6825 get(ncm->ncm_BootRDBObj, MUIA_Selected, &curncm->ncm_CUC->cuc_BootRDB);
6826 get(ncm->ncm_UnitObj, MUIA_String_Integer, &curncm->ncm_CUC->cuc_DefaultUnit);
6827 get(ncm->ncm_UnmountObj, MUIA_Selected, &curncm->ncm_CUC->cuc_AutoUnmount);
6830 if((curncm = cncm))
6832 set(ncm->ncm_AutoMountFATObj, MUIA_Selected, curncm->ncm_CUC->cuc_AutoMountFAT);
6833 set(ncm->ncm_MountAllFATObj, MUIA_Selected, curncm->ncm_CUC->cuc_MountAllFAT);
6834 set(ncm->ncm_AutoMountCDObj, MUIA_Selected, curncm->ncm_CUC->cuc_AutoMountCD);
6835 set(ncm->ncm_FatDOSNameObj, MUIA_String_Contents, curncm->ncm_CUC->cuc_FATDOSName);
6836 set(ncm->ncm_FatBuffersObj, MUIA_String_Integer, curncm->ncm_CUC->cuc_FATBuffers);
6837 set(ncm->ncm_AutoMountRDBObj, MUIA_Selected, curncm->ncm_CUC->cuc_AutoMountRDB);
6838 set(ncm->ncm_BootRDBObj, MUIA_Selected, curncm->ncm_CUC->cuc_BootRDB);
6839 set(ncm->ncm_UnitObj, MUIA_String_Integer, curncm->ncm_CUC->cuc_DefaultUnit);
6840 set(ncm->ncm_UnmountObj, MUIA_Selected, curncm->ncm_CUC->cuc_AutoUnmount);
6841 set(ncm->ncm_LunGroupObj, MUIA_Disabled, FALSE);
6842 } else {
6843 set(ncm->ncm_LunGroupObj, MUIA_Disabled, TRUE);
6845 break;
6847 case ID_AUTODTXMAXTX:
6849 DoMethod(ncm->ncm_LunLVObj, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &cncm);
6850 set(ncm->ncm_App, MUIA_Application_Sleep, TRUE);
6851 AutoDetectMaxTransfer(cncm);
6852 set(ncm->ncm_App, MUIA_Application_Sleep, FALSE);
6853 set(ncm->ncm_MaxTransferObj, MUIA_Cycle_Active, ncm->ncm_CDC->cdc_MaxTransfer);
6854 break;
6857 case ID_ABOUT:
6858 MUI_RequestA(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Blimey!", VERSION_STRING "\n\nCode for AutoMounting based\non work by Thore Böckelmann.", NULL);
6859 break;
6861 if(retid == MUIV_Application_ReturnID_Quit)
6863 break;
6865 if(sigs)
6867 sigs = Wait(sigs | sigmask | SIGBREAKF_CTRL_C);
6868 if(sigs & SIGBREAKF_CTRL_C)
6870 break;
6873 } while(TRUE);
6874 set(ncm->ncm_MainWindow, MUIA_Window_Open, FALSE);
6876 GM_UNIQUENAME(nGUITaskCleanup)(ncm);
6878 AROS_USERFUNC_EXIT
6880 /* \\\ */
6882 /* /// "AutoDetectMaxTransfer()" */
6883 void AutoDetectMaxTransfer(struct NepClassMS *cncm)
6885 LONG res;
6886 UBYTE *memory;
6887 UBYTE *orgbuffer;
6888 UBYTE *cmpbuffer;
6889 ULONG *lbufptr;
6890 struct MsgPort *mp;
6891 struct IOStdReq *ioreq;
6892 struct NepClassMS *ncm = cncm->ncm_UnitLUN0;
6893 ULONG numblocks;
6894 ULONG memsize = 4<<20;
6895 ULONG block;
6896 ULONG maxtrans;
6897 LONG ioerr;
6898 BOOL bail = FALSE;
6899 ULONG cnt;
6901 res = MUI_RequestA(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Continue|Cancel",
6902 "Auto-detection of the maximum transfer rate\n"
6903 "will need some media inserted in the selected\n"
6904 "LUN of the drive. Moreover, the contents of the\n"
6905 "media may not be empty.\n"
6906 "The test will need about 4 MB of temporary memory!\n"
6907 "No data is written to the disk!", NULL);
6908 if(!res)
6910 return;
6912 if(!cncm->ncm_UnitReady)
6914 MUI_RequestA(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Argh!", "No disk/media in drive!", NULL);
6915 return;
6917 memory = (UBYTE *) AllocVec(memsize, MEMF_CLEAR);
6918 if(!memory)
6920 MUI_RequestA(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Argh!", "Sorry, out of memory!", NULL);
6921 return;
6923 mp = CreateMsgPort();
6924 if(mp)
6926 ioreq = (struct IOStdReq *) CreateIORequest(mp, sizeof(struct IOStdReq));
6927 if(ioreq)
6929 if(!OpenDevice(DEVNAME, cncm->ncm_UnitNo, (struct IORequest *) ioreq, 0))
6931 ncm->ncm_CDC->cdc_MaxTransfer = 0;
6932 if(!cncm->ncm_BlockSize)
6934 ioreq->io_Command = TD_GETGEOMETRY;
6935 ioreq->io_Data = &cncm->ncm_Geometry;
6936 ioreq->io_Length = sizeof(cncm->ncm_Geometry);
6937 DoIO((struct IORequest *) ioreq);
6940 numblocks = (memsize>>1) / cncm->ncm_BlockSize;
6941 orgbuffer = memory;
6942 cmpbuffer = &memory[memsize>>1];
6946 for(block = 0; block < numblocks; block++)
6948 ioreq->io_Command = TD_READ64;
6949 ioreq->io_Actual = 0;
6950 ioreq->io_Offset = block*cncm->ncm_BlockSize;
6951 ioreq->io_Length = cncm->ncm_BlockSize;
6952 ioreq->io_Data = &orgbuffer[ioreq->io_Offset];
6953 ioerr = DoIO((struct IORequest *) ioreq);
6954 if(ioerr)
6956 MUI_Request(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, ">:-{", "Error %ld while reading block %ld!\nAborting process...", ioerr, block);
6957 bail = TRUE;
6958 break;
6961 if(bail) break;
6965 maxtrans = (1UL<<(ncm->ncm_CDC->cdc_MaxTransfer+16));
6966 // do a quick check on block contents
6967 numblocks = (memsize>>1) / maxtrans;
6968 if(numblocks)
6970 for(block = 0; block < numblocks-1; block++)
6972 if(!memcmp(&orgbuffer[block * maxtrans], &orgbuffer[(block + 1) * maxtrans], (size_t) maxtrans))
6974 res = MUI_RequestA(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Continue|Abort", "Sorry, media contents do not\nseem to be diversive enough!\nResults might be wrong!", NULL);
6975 if(!res)
6977 bail = TRUE;
6979 break;
6983 if(bail) break;
6985 // fill compare buffer with garbage
6986 cnt = (memsize>>3);
6987 lbufptr = (ULONG *) cmpbuffer;
6990 *lbufptr = (IPTR) lbufptr;
6991 lbufptr++;
6993 while(--cnt);
6995 // start reading the chunks
6996 numblocks = (memsize>>1) / maxtrans;
6997 for(block = 0; block < numblocks; block++)
6999 ioreq->io_Command = TD_READ64;
7000 ioreq->io_Actual = 0;
7001 ioreq->io_Offset = block*maxtrans;
7002 ioreq->io_Length = maxtrans;
7003 ioreq->io_Data = &cmpbuffer[ioreq->io_Offset];
7004 ioerr = DoIO((struct IORequest *) ioreq);
7005 if(ioerr)
7007 MUI_Request(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, ">:-{", "Error %ld while reading at offset %ld!\nAborting process...", ioerr, &ioreq->io_Offset);
7008 bail = TRUE;
7009 break;
7011 if(memcmp(&orgbuffer[ioreq->io_Offset], &cmpbuffer[ioreq->io_Offset], (size_t) maxtrans))
7013 MUI_Request(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Hmpf!", "Reading failed at MaxTrans = %08lx", maxtrans-1);
7014 if(ncm->ncm_CDC->cdc_MaxTransfer)
7016 ncm->ncm_CDC->cdc_MaxTransfer--;
7018 bail = TRUE;
7019 break;
7022 if(bail) break;
7023 //MUI_Request(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Wow!", "Test with %ld (%ld) succeeded!", maxtrans, numblocks);
7024 if(ncm->ncm_CDC->cdc_MaxTransfer < 5)
7026 ncm->ncm_CDC->cdc_MaxTransfer++;
7027 } else {
7028 break;
7030 } while(TRUE);
7031 if(!bail)
7033 MUI_RequestA(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Wow!", "Test succeeded, setting MaxTrans to maximum value!", NULL);
7035 } while(FALSE);
7036 CloseDevice((struct IORequest *) ioreq);
7037 } else {
7038 MUI_RequestA(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Argh!", "Couldn't open device!", NULL);
7040 DeleteIORequest((struct IORequest *) ioreq);
7041 } else {
7042 MUI_RequestA(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Argh!", "No IOReq!", NULL);
7044 DeleteMsgPort(mp);
7045 } else {
7046 MUI_RequestA(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Argh!", "No MsgPort!", NULL);
7048 FreeVec(memory);
7050 /* \\\ */
7052 /* /// "nGUITaskCleanup()" */
7053 void GM_UNIQUENAME(nGUITaskCleanup)(struct NepClassMS *ncm)
7055 if(ncm->ncm_App)
7057 MUI_DisposeObject(ncm->ncm_App);
7058 ncm->ncm_App = NULL;
7060 if(MUIMasterBase)
7062 CloseLibrary(MUIMasterBase);
7063 MUIMasterBase = NULL;
7065 if(IntuitionBase)
7067 CloseLibrary(IntuitionBase);
7068 IntuitionBase = NULL;
7070 if(ps)
7072 CloseLibrary(ps);
7073 ps = NULL;
7075 Forbid();
7076 ncm->ncm_GUIBinding = NULL;
7077 ncm->ncm_GUITask = NULL;
7078 --ncm->ncm_ClsBase->nh_Library.lib_OpenCnt;
7080 /* \\\ */
7082 /* /// "LUNListDisplayHook()" */
7083 AROS_UFH3(LONG, GM_UNIQUENAME(LUNListDisplayHook),
7084 AROS_UFHA(struct Hook *, hook, A0),
7085 AROS_UFHA(char **, strarr, A2),
7086 AROS_UFHA(struct NepClassMS *, ncm, A1))
7088 AROS_USERFUNC_INIT
7090 //struct NepMSBase *nh = ncm->ncm_ClsBase;
7091 if(ncm)
7093 *strarr++ = ncm->ncm_LUNNumStr;
7094 *strarr = ncm->ncm_LUNIDStr;
7095 } else {
7096 *strarr++ = "\33l\33uLUN";
7097 *strarr = "\33l\33uID";
7099 return(0);
7101 AROS_USERFUNC_EXIT
7103 /* \\\ */