grub2: bring back build of aros-side grub2 tools
[AROS.git] / rom / usb / classes / massstorage / massstorage.class.c
blob1d32c4abe2bc3c7bfd035024e56be6090ae55bd3
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 strncpy(ncm->ncm_LUNIDStr, &inquirydata[16], 16);
1200 // trim spaces
1201 cnt = strlen(ncm->ncm_LUNIDStr);
1202 while(cnt--)
1204 if(ncm->ncm_LUNIDStr[cnt] == ' ')
1206 ncm->ncm_LUNIDStr[cnt] = 0;
1207 } else {
1208 break;
1212 ncm->ncm_DeviceType = inquirydata[0] & PDT_MASK;
1213 if(ncm->ncm_DeviceType > 0x11)
1215 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Illegal Device Type %02lx", ncm->ncm_DeviceType);
1216 ncm->ncm_DeviceType = 0;
1217 } else {
1218 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Device '%s' is of %s type.", ncm->ncm_LUNIDStr, DeviceTypeStrings[ncm->ncm_DeviceType]);
1220 if((ncm->ncm_DeviceType == PDT_WORM) ||
1221 (ncm->ncm_DeviceType == PDT_CDROM))
1223 // assume 2048 byte blocks
1224 ncm->ncm_BlockSize = 2048;
1225 ncm->ncm_BlockShift = 11;
1226 if(ncm->ncm_CDC->cdc_NakTimeout == DEF_NAKTIMEOUT)
1228 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Silently increasing NAK Timeout value to 15 seconds for CD/DVD drives...");
1229 ncm->ncm_CDC->cdc_NakTimeout = 150;
1230 GM_UNIQUENAME(nStoreConfig)(ncm);
1232 psdSetAttrs(PGA_PIPE, ncm->ncm_EP0Pipe,
1233 PPA_NakTimeout, TRUE,
1234 PPA_NakTimeoutTime, (ncm->ncm_CDC->cdc_NakTimeout+1)*100,
1235 TAG_END);
1236 psdSetAttrs(PGA_PIPE, ncm->ncm_EPInPipe,
1237 PPA_NakTimeout, TRUE,
1238 PPA_NakTimeoutTime, ncm->ncm_CDC->cdc_NakTimeout*100,
1239 TAG_END);
1240 psdSetAttrs(PGA_PIPE, ncm->ncm_EPOutPipe,
1241 PPA_NakTimeout, TRUE,
1242 PPA_NakTimeoutTime, ncm->ncm_CDC->cdc_NakTimeout*100,
1243 TAG_END);
1245 else if(!ncm->ncm_CDC->cdc_NakTimeout)
1247 // that's okay, nak timeout disabled
1249 else if(ncm->ncm_CDC->cdc_NakTimeout < 150)
1251 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "NAK Timeout should be at least 15 seconds for CD/DVD drives!");
1255 if(!(inquirydata[1] & 0x80))
1257 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Device does not seem to use removable media.");
1258 ncm->ncm_Removable = FALSE;
1259 ncm->ncm_UnitReady = TRUE;
1260 ncm->ncm_ChangeCount++;
1264 /* Main task */
1265 sigmask = (1L<<ncm->ncm_Unit.unit_MsgPort.mp_SigBit)|
1266 (1L<<ncm->ncm_TaskMsgPort->mp_SigBit)|
1267 SIGBREAKF_CTRL_C;
1268 if(ncm->ncm_CSType == MS_UFI_SUBCLASS)
1270 struct IOStdReq tmpio;
1271 tmpio.io_Command = CMD_START;
1272 nStartStop(ncm, &tmpio);
1275 // if not removable, call it once to trigger mounting...
1276 if(!ncm->ncm_Removable)
1278 ncm->ncm_ForceRTCheck = TRUE;
1280 ncm->ncm_Running = TRUE;
1284 if(ncm->ncm_Removable || ncm->ncm_ForceRTCheck)
1286 GM_UNIQUENAME(nStartRemovableTask)(ps, ncm->ncm_ClsBase);
1287 ncm->ncm_ForceRTCheck = FALSE;
1289 while((ioreq = (struct IOStdReq *) GetMsg(&ncm->ncm_Unit.unit_MsgPort)))
1291 KPRINTF(5, ("command ioreq: 0x%08lx cmd: %lu len: %ld\n",
1292 ioreq, ioreq->io_Command, ioreq->io_Length));
1294 switch(ioreq->io_Command)
1296 case TD_GETGEOMETRY:
1297 nGetGeometry(ncm, ioreq);
1298 ReplyMsg((struct Message *) ioreq);
1299 break;
1301 case TD_EJECT:
1302 case CMD_START:
1303 case CMD_STOP:
1304 nStartStop(ncm, ioreq);
1305 ReplyMsg((struct Message *) ioreq);
1306 break;
1308 case CMD_READ:
1309 ioreq->io_Actual = 0;
1310 case NSCMD_TD_READ64:
1311 case TD_READ64:
1312 nRead64(ncm, ioreq);
1313 ReplyMsg((struct Message *) ioreq);
1314 break;
1316 case TD_SEEK:
1317 ioreq->io_Actual = 0;
1318 case NSCMD_TD_SEEK64:
1319 case TD_SEEK64:
1320 nSeek64(ncm, ioreq);
1321 ReplyMsg((struct Message *) ioreq);
1322 break;
1324 case TD_FORMAT:
1325 case CMD_WRITE:
1326 ioreq->io_Actual = 0;
1327 case NSCMD_TD_FORMAT64:
1328 case NSCMD_TD_WRITE64:
1329 case TD_FORMAT64:
1330 case TD_WRITE64:
1331 nWrite64(ncm, ioreq);
1332 ReplyMsg((struct Message *) ioreq);
1333 break;
1335 case HD_SCSICMD:
1336 ioreq->io_Error = nScsiDirect(ncm, ioreq->io_Data);
1337 ReplyMsg((struct Message *) ioreq);
1338 break;
1340 case CMD_RESET:
1341 if((ioreq2 = ncm->ncm_XFerPending))
1343 ncm->ncm_XFerPending = NULL;
1344 ioreq2->io_Error = IOERR_ABORTED;
1345 ReplyMsg((struct Message *) ioreq2);
1347 /* Reset does a flush too */
1348 case CMD_FLUSH:
1349 ioreq2 = (struct IOStdReq *) ncm->ncm_XFerQueue.lh_Head;
1350 while(ioreq2->io_Message.mn_Node.ln_Succ)
1352 Remove((struct Node *) ioreq2);
1353 ioreq2->io_Error = IOERR_ABORTED;
1354 ReplyMsg((struct Message *) ioreq2);
1355 ioreq2 = (struct IOStdReq *) ncm->ncm_XFerQueue.lh_Head;
1357 ReplyMsg((struct Message *) ioreq);
1358 break;
1360 default:
1361 ioreq->io_Error = IOERR_NOCMD;
1362 ReplyMsg((struct Message *) ioreq);
1363 break;
1366 sigs = Wait(sigmask);
1367 } while(!(sigs & SIGBREAKF_CTRL_C));
1368 ncm->ncm_DenyRequests = TRUE;
1369 /* Device ejected */
1370 ncm->ncm_UnitReady = FALSE;
1371 ncm->ncm_ChangeCount++;
1372 ioreq = (struct IOStdReq *) ncm->ncm_DCInts.lh_Head;
1373 while(((struct Node *) ioreq)->ln_Succ)
1375 Cause(ioreq->io_Data);
1376 ioreq = (struct IOStdReq *) ((struct Node *) ioreq)->ln_Succ;
1378 if(!ncm->ncm_Removable)
1380 GM_UNIQUENAME(nStartRemovableTask)(ps, ncm->ncm_ClsBase);
1382 KPRINTF(20, ("Going down the river!\n"));
1383 GM_UNIQUENAME(nFreeMS)(ncm);
1385 AROS_USERFUNC_EXIT
1387 /* \\\ */
1389 /* /// "nAllocMS()" */
1390 struct NepClassMS * GM_UNIQUENAME(nAllocMS)(void)
1392 struct Task *thistask;
1393 struct NepClassMS *ncm;
1394 IPTR epnum;
1396 thistask = FindTask(NULL);
1397 ncm = thistask->tc_UserData;
1400 if(!(ncm->ncm_Base = OpenLibrary("poseidon.library", 4)))
1402 Alert(AG_OpenLib | AO_Unknown);
1403 break;
1405 ncm->ncm_EPInt = psdFindEndpoint(ncm->ncm_Interface, NULL,
1406 EA_IsIn, TRUE,
1407 EA_TransferType, USEAF_INTERRUPT,
1408 TAG_END);
1409 ncm->ncm_EPIn = psdFindEndpoint(ncm->ncm_Interface, NULL,
1410 EA_IsIn, TRUE,
1411 EA_TransferType, USEAF_BULK,
1412 TAG_END);
1413 ncm->ncm_EPOut = psdFindEndpoint(ncm->ncm_Interface, NULL,
1414 EA_IsIn, FALSE,
1415 EA_TransferType, USEAF_BULK,
1416 TAG_END);
1417 if(!(ncm->ncm_EPIn && ncm->ncm_EPOut))
1419 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname), "IN or OUT endpoint missing!");
1420 break;
1422 if((!ncm->ncm_EPInt) && (ncm->ncm_TPType == MS_PROTO_CBI))
1424 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname), "INT endpoint missing!");
1425 break;
1426 } else {
1427 psdGetAttrs(PGA_ENDPOINT, ncm->ncm_EPOut,
1428 EA_EndpointNum, &epnum,
1429 TAG_END);
1430 ncm->ncm_EPIntNum = epnum;
1432 psdGetAttrs(PGA_ENDPOINT, ncm->ncm_EPIn,
1433 EA_EndpointNum, &epnum,
1434 TAG_END);
1435 ncm->ncm_EPInNum = epnum;
1436 psdGetAttrs(PGA_ENDPOINT, ncm->ncm_EPOut,
1437 EA_EndpointNum, &epnum,
1438 TAG_END);
1439 ncm->ncm_EPOutNum = epnum;
1441 ncm->ncm_BulkResetBorks = FALSE;
1442 ncm->ncm_GeoChangeCount = 0xffffffff;
1444 ncm->ncm_Unit.unit_MsgPort.mp_SigBit = AllocSignal(-1);
1445 ncm->ncm_Unit.unit_MsgPort.mp_SigTask = thistask;
1446 ncm->ncm_Unit.unit_MsgPort.mp_Node.ln_Type = NT_MSGPORT;
1447 ncm->ncm_Unit.unit_MsgPort.mp_Flags = PA_SIGNAL;
1448 ncm->ncm_XFerPending = NULL;
1449 if((ncm->ncm_TaskMsgPort = CreateMsgPort()))
1451 if((ncm->ncm_EP0Pipe = psdAllocPipe(ncm->ncm_Device, ncm->ncm_TaskMsgPort, NULL)))
1453 if((ncm->ncm_EPOutPipe = psdAllocPipe(ncm->ncm_Device, ncm->ncm_TaskMsgPort, ncm->ncm_EPOut)))
1455 if((ncm->ncm_EPInPipe = psdAllocPipe(ncm->ncm_Device, ncm->ncm_TaskMsgPort, ncm->ncm_EPIn)))
1457 if(ncm->ncm_CDC->cdc_NakTimeout)
1459 psdSetAttrs(PGA_PIPE, ncm->ncm_EP0Pipe,
1460 PPA_NakTimeout, TRUE,
1461 PPA_NakTimeoutTime, (ncm->ncm_CDC->cdc_NakTimeout+1)*100,
1462 TAG_END);
1463 psdSetAttrs(PGA_PIPE, ncm->ncm_EPInPipe,
1464 PPA_NakTimeout, TRUE,
1465 PPA_NakTimeoutTime, ncm->ncm_CDC->cdc_NakTimeout*100,
1466 TAG_END);
1467 psdSetAttrs(PGA_PIPE, ncm->ncm_EPOutPipe,
1468 PPA_NakTimeout, TRUE,
1469 PPA_NakTimeoutTime, ncm->ncm_CDC->cdc_NakTimeout*100,
1470 TAG_END);
1472 psdSetAttrs(PGA_PIPE, ncm->ncm_EPOutPipe,
1473 PPA_NoShortPackets, TRUE,
1474 TAG_END);
1475 if(ncm->ncm_EPInt)
1477 if((ncm->ncm_EPIntPipe = psdAllocPipe(ncm->ncm_Device, ncm->ncm_TaskMsgPort, ncm->ncm_EPInt)))
1479 if(ncm->ncm_CDC->cdc_NakTimeout)
1481 psdSetAttrs(PGA_PIPE, ncm->ncm_EPIntPipe,
1482 PPA_NakTimeout, TRUE,
1483 PPA_NakTimeoutTime, ncm->ncm_CDC->cdc_NakTimeout*100,
1484 TAG_END);
1486 ncm->ncm_Task = thistask;
1487 return(ncm);
1489 } else {
1490 ncm->ncm_Task = thistask;
1491 return(ncm);
1493 psdFreePipe(ncm->ncm_EPInPipe);
1495 psdFreePipe(ncm->ncm_EPOutPipe);
1497 psdFreePipe(ncm->ncm_EP0Pipe);
1499 DeleteMsgPort(ncm->ncm_TaskMsgPort);
1501 FreeSignal((LONG) ncm->ncm_Unit.unit_MsgPort.mp_SigBit);
1502 } while(FALSE);
1503 CloseLibrary(ncm->ncm_Base);
1504 Forbid();
1505 ncm->ncm_Task = NULL;
1506 if(ncm->ncm_ReadySigTask)
1508 Signal(ncm->ncm_ReadySigTask, 1L<<ncm->ncm_ReadySignal);
1510 return(NULL);
1512 /* \\\ */
1514 /* /// "nFreeMS()" */
1515 void GM_UNIQUENAME(nFreeMS)(struct NepClassMS *ncm)
1517 struct IOStdReq *ioreq;
1518 /* Disable the message port, messages may still be queued */
1519 Forbid();
1520 ncm->ncm_Unit.unit_MsgPort.mp_Flags = PA_IGNORE;
1521 ncm->ncm_Unit.unit_MsgPort.mp_SigTask = NULL;
1522 FreeSignal((LONG) ncm->ncm_Unit.unit_MsgPort.mp_SigBit);
1523 // get rid of all messages that still have appeared here
1524 while((ioreq = (struct IOStdReq *) GetMsg(&ncm->ncm_Unit.unit_MsgPort)))
1526 ioreq->io_Error = IOERR_ABORTED;
1527 ReplyMsg((struct Message *) ioreq);
1529 Permit();
1531 psdFreePipe(ncm->ncm_EPIntPipe);
1532 psdFreePipe(ncm->ncm_EPInPipe);
1533 psdFreePipe(ncm->ncm_EPOutPipe);
1534 psdFreePipe(ncm->ncm_EP0Pipe);
1535 DeleteMsgPort(ncm->ncm_TaskMsgPort);
1537 psdFreeVec(ncm->ncm_OneBlock);
1538 ncm->ncm_OneBlock = NULL;
1539 ncm->ncm_OneBlockSize = 0;
1541 CloseLibrary(ncm->ncm_Base);
1542 Forbid();
1543 ncm->ncm_Task = NULL;
1544 if(ncm->ncm_ReadySigTask)
1546 Signal(ncm->ncm_ReadySigTask, 1L<<ncm->ncm_ReadySignal);
1549 /* \\\ */
1551 /* /// "nGetModePage()" */
1552 UBYTE * nGetModePage(struct NepClassMS *ncm, UBYTE page)
1554 UBYTE cmd6[6];
1555 struct SCSICmd scsicmd;
1556 UBYTE sensedata[18];
1557 LONG ioerr;
1558 UBYTE *res;
1559 ULONG pf;
1561 KPRINTF(10, ("page %ld\n", page));
1563 memset(ncm->ncm_ModePageBuf, 0x00, 255);
1564 scsicmd.scsi_Data = (UWORD *) ncm->ncm_ModePageBuf;
1565 scsicmd.scsi_Length = 255;
1566 scsicmd.scsi_Command = cmd6;
1567 scsicmd.scsi_CmdLength = 6;
1568 scsicmd.scsi_Flags = SCSIF_READ|SCSIF_AUTOSENSE;
1569 scsicmd.scsi_SenseData = sensedata;
1570 scsicmd.scsi_SenseLength = 18;
1571 cmd6[0] = SCSI_MODE_SENSE_6;
1572 cmd6[1] = 0x00; /* no block descriptors */
1573 cmd6[2] = page;
1574 cmd6[3] = 0;
1575 cmd6[4] = 255;
1576 cmd6[5] = 0;
1577 if((ioerr = nScsiDirect(ncm, &scsicmd)))
1579 KPRINTF(10, ("ioerr %ld\n", ioerr));
1580 pf = ncm->ncm_CDC->cdc_PatchFlags;
1581 if(pf & PFF_DEBUG)
1583 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1584 "SCSI_MODE_SENSE(0x%02lx) failed: %ld",
1585 page, ioerr);
1587 if((!(pf & PFF_NO_FALLBACK)) && (!(pf & PFF_MODE_XLATE)) && (ioerr == HFERR_Phase))
1589 ncm->ncm_CDC->cdc_PatchFlags |= PFF_MODE_XLATE;
1590 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1591 "Fallback: Enabling CMD6->CMD10.");
1592 GM_UNIQUENAME(nStoreConfig)(ncm);
1594 else if((!(pf & PFF_NO_FALLBACK)) && (pf & PFF_MODE_XLATE) && (!(pf & PFF_SIMPLE_SCSI)) && (ioerr == HFERR_Phase))
1596 ncm->ncm_CDC->cdc_PatchFlags |= PFF_SIMPLE_SCSI;
1597 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1598 "Fallback: Enabling Simple SCSI.");
1599 GM_UNIQUENAME(nStoreConfig)(ncm);
1601 return(NULL);
1603 pf = ncm->ncm_CDC->cdc_PatchFlags;
1604 res = ncm->ncm_ModePageBuf;
1605 if((scsicmd.scsi_Actual < 6) || (scsicmd.scsi_Actual < res[3]+6))
1607 if(pf & PFF_DEBUG)
1609 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1610 "SCSI_MODE_SENSE(0x%02lx) failed: only %ld returned",
1611 page, scsicmd.scsi_Actual);
1613 return(NULL);
1615 if(pf & PFF_DEBUG)
1617 UBYTE hexbuf[12*3+2];
1618 GM_UNIQUENAME(nHexString)(res, 12, hexbuf);
1619 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "ModePage (%ld) header: %s...", scsicmd.scsi_Actual, hexbuf);
1621 if(res[3])
1623 res += res[3];
1624 scsicmd.scsi_Actual -= res[3];
1626 res += 4; // skip mode header */
1627 scsicmd.scsi_Actual -= 4;
1628 if((*res & 0x3f) != (page & 0x3f))
1630 if(pf & PFF_DEBUG)
1632 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1633 "SCSI_MODE_SENSE(0x%02lx) failed: wrong page 0x%02lx returned",
1634 page, *res);
1636 return(NULL);
1638 if(scsicmd.scsi_Actual < res[1])
1640 if(pf & PFF_DEBUG)
1642 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1643 "SCSI_MODE_SENSE(0x%02lx) failed: page incomplete",
1644 page);
1646 return(NULL);
1649 #if 0
1650 if(*res & 0x40) /* subpage mode? */
1652 res += 2;
1654 #endif
1655 return(res);
1657 /* \\\ */
1659 /* /// "nGetBlockSize()" */
1660 LONG nGetBlockSize(struct NepClassMS *ncm)
1662 UBYTE cmd10[10];
1663 struct SCSICmd scsicmd;
1664 UBYTE sensedata[18];
1665 ULONG capacity[2];
1666 LONG ioerr;
1668 scsicmd.scsi_Data = (UWORD *) capacity;
1669 scsicmd.scsi_Length = 8;
1670 scsicmd.scsi_Command = cmd10;
1671 scsicmd.scsi_CmdLength = 10;
1672 scsicmd.scsi_Flags = SCSIF_READ|SCSIF_AUTOSENSE;
1673 scsicmd.scsi_SenseData = sensedata;
1674 scsicmd.scsi_SenseLength = 18;
1675 cmd10[0] = SCSI_DA_READ_CAPACITY;
1676 cmd10[1] = 0;
1677 cmd10[2] = 0;
1678 cmd10[3] = 0;
1679 cmd10[4] = 0;
1680 cmd10[5] = 0;
1681 cmd10[6] = 0;
1682 cmd10[7] = 0;
1683 cmd10[8] = 0;
1684 cmd10[9] = 0;
1685 if((ioerr = nScsiDirect(ncm, &scsicmd)))
1687 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1688 "SCSI_READ_CAPACITY failed: %ld",
1689 ioerr);
1690 if(!ncm->ncm_BlockSize)
1692 ncm->ncm_Geometry.dg_SectorSize = ncm->ncm_BlockSize = 512;
1693 ncm->ncm_BlockShift = 9;
1695 } else {
1696 ncm->ncm_Geometry.dg_SectorSize = ncm->ncm_BlockSize = AROS_BE2LONG(capacity[1]);
1697 ncm->ncm_BlockShift = 0;
1698 while((1<<ncm->ncm_BlockShift) < ncm->ncm_BlockSize)
1700 ncm->ncm_BlockShift++;
1702 ncm->ncm_Geometry.dg_TotalSectors = AROS_BE2LONG(capacity[0])+1;
1704 return(ioerr);
1706 /* \\\ */
1708 /* /// "nFakeGeometry()" */
1709 void nFakeGeometry(struct NepClassMS *ncm, struct DriveGeometry *tddg)
1711 UWORD cnt;
1712 ULONG primes[32];
1713 UWORD count[32];
1714 UWORD curpos;
1715 UWORD curprime;
1716 ULONG curprimesq;
1717 ULONG remblks = tddg->dg_TotalSectors;
1718 UWORD *primetblptr = PrimeTable;
1719 UWORD totfactors;
1720 UWORD factor;
1721 ULONG remfact;
1722 UWORD tries;
1723 BOOL taken;
1725 if(!ncm->ncm_Geometry.dg_TotalSectors)
1727 return;
1729 KPRINTF(10, ("Faking geometry for %ld sectors\n", tddg->dg_TotalSectors));
1730 //psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Prime factorisation for %ld", remblks);
1731 tddg->dg_DeviceType = ncm->ncm_DeviceType;
1732 tddg->dg_Flags = ncm->ncm_Removable ? DGF_REMOVABLE : 0;
1733 tddg->dg_BufMemType = MEMF_PUBLIC;
1734 tddg->dg_Reserved = 0;
1737 KPRINTF(10, ("Loop\n"));
1738 // first prime is counted manually
1739 *primes = 2;
1740 *count = 0;
1741 curpos = 0;
1742 while(!(remblks & 1))
1744 (*count)++;
1745 remblks >>= 1;
1747 if(*count)
1749 curpos++;
1752 primes[curpos] = 3;
1753 count[curpos] = 0;
1754 primetblptr = PrimeTable;
1755 curprime = 3;
1756 curprimesq = 9;
1757 // abort if no primes can be found anymore
1760 KPRINTF(10, ("remblks = %ld, curprime=%ld\n", remblks, curprime));
1761 if(remblks % curprime)
1763 if(remblks >= curprimesq)
1765 // it's a prime!
1766 break;
1768 if(count[curpos]) // prime at least once
1770 // next prime
1771 count[++curpos] = 0;
1772 if(curpos == 31) // end of buffer reached
1774 break;
1777 // try next "prime"
1778 if(*primetblptr)
1780 // use lookup table for the first primes to 2000
1781 curprime = *primetblptr++;
1782 } else {
1783 // do it the hard way :-(
1784 curprime += 2;
1786 primes[curpos] = curprime;
1787 curprimesq = curprime * curprime;
1788 } else {
1789 // factor found
1790 count[curpos]++;
1791 remblks /= curprime;
1793 } while((remblks > 1) && (remblks >= curprime));
1794 if(count[curpos])
1796 curpos++;
1798 if((remblks > 1) && curpos)
1800 count[curpos] = 1;
1801 primes[curpos++] = remblks;
1803 KPRINTF(10, ("Priming done, %ld different primes\n", curpos));
1804 if(curpos)
1806 break;
1808 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "FakeGeometry: Total number of blocks is a prime number!");
1809 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_FIX_CAPACITY)
1811 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_FALLBACK)
1813 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
1814 "This is probably due to the Fix Capacity switch being enabled incorrectly. Please check this.");
1815 return;
1816 } else {
1817 ncm->ncm_CDC->cdc_PatchFlags &= ~PFF_FIX_CAPACITY;
1818 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
1819 "Fallback: Disabling Fix Capacity.");
1820 GM_UNIQUENAME(nStoreConfig)(ncm);
1821 remblks = ++tddg->dg_TotalSectors;
1823 } else {
1824 if(!(ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_FALLBACK))
1826 ncm->ncm_CDC->cdc_PatchFlags |= PFF_FIX_CAPACITY;
1827 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1828 "Fallback: Enabling Fix Capacity.");
1829 GM_UNIQUENAME(nStoreConfig)(ncm);
1830 } else {
1831 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1832 "Assuming Fix Capacity bug (total blocks instead of last block)!");
1834 remblks = --tddg->dg_TotalSectors;
1836 } while(TRUE);
1838 totfactors = 0;
1839 for(cnt = 0; cnt < curpos; cnt++)
1841 totfactors += count[cnt];
1844 // Rules:
1845 // - We want at least blocks per track * heads >= 64
1846 // - We want heads * heads < blocks per track
1847 // - We want blocks per track < cylinders
1848 // - We want heads < 8
1849 // - We want blocks per track < 256
1850 // - The rest goes into cylinders
1851 tddg->dg_TrackSectors = 1;
1852 tddg->dg_Heads = 1;
1853 remfact = tddg->dg_TotalSectors;
1854 tries = 0;
1855 while(totfactors)
1857 KPRINTF(10, ("Totfactors %ld\n", totfactors));
1858 cnt = 0;
1859 while(!count[cnt])
1861 cnt++;
1862 if(cnt >= curpos)
1864 cnt = 0;
1867 taken = TRUE;
1868 factor = primes[cnt];
1869 if((tddg->dg_TrackSectors * factor < 256) &&
1870 (tddg->dg_TrackSectors * factor < remfact))
1872 tddg->dg_TrackSectors *= factor;
1873 remfact /= factor;
1875 else if((tddg->dg_Heads * factor <= 16) &&
1876 (tddg->dg_Heads * tddg->dg_Heads * factor * factor < tddg->dg_TrackSectors))
1878 tddg->dg_Heads *= factor;
1879 remfact /= factor;
1881 else if((tddg->dg_Heads * tddg->dg_TrackSectors >= 64) ||
1882 (tries > curpos))
1884 // do nothing
1885 } else {
1886 taken = FALSE;
1888 if(taken)
1890 totfactors--;
1891 count[cnt]--;
1892 tries = 0;
1893 } else {
1894 tries++;
1896 KPRINTF(10, ("Factor=%ld: Cylinders = %ld, Heads=%ld, TrackSectors=%ld, Blocks=%ld\n",
1897 factor, remfact, tddg->dg_Heads, tddg->dg_TrackSectors,
1898 tddg->dg_TotalSectors));
1901 KPRINTF(10, ("Final: Cylinders = %ld, Heads=%ld, TrackSectors=%ld, Blocks=%ld\n",
1902 remfact, tddg->dg_Heads, tddg->dg_TrackSectors,
1903 tddg->dg_TotalSectors));
1905 tddg->dg_Cylinders = remfact;
1906 tddg->dg_CylSectors = tddg->dg_TrackSectors * tddg->dg_Heads;
1908 /* \\\ */
1910 struct CapacityData
1912 ULONG SectorCount;
1913 ULONG SectorSize;
1916 #define SERVICEACTION_CAPACITY16 0x10
1918 /* /// "nGetGeometry()" */
1919 LONG nGetGeometry(struct NepClassMS *ncm, struct IOStdReq *ioreq)
1921 struct DriveGeometry *tddg;
1922 ULONG length;
1923 UBYTE cmd10[10];
1924 struct SCSICmd scsicmd;
1925 struct CapacityData capacitydata;
1926 UBYTE sensedata[18];
1927 LONG ioerr;
1928 ULONG tmpval;
1929 UBYTE *mpdata;
1930 BOOL gotblks = FALSE;
1931 BOOL gotcyl = FALSE;
1932 BOOL gotheads = FALSE;
1933 BOOL gotsect = FALSE;
1934 BOOL gotcylsect = FALSE;
1935 KPRINTF(10, ("\n"));
1937 ioreq->io_Error = 0;
1938 ioreq->io_Actual = 0;
1939 tddg = (struct DriveGeometry *) ioreq->io_Data;
1940 if(!tddg)
1942 ioreq->io_Error = TDERR_NotSpecified;
1943 return(ioreq->io_Error);
1945 length = min(ioreq->io_Length,sizeof(struct DriveGeometry));
1946 if((ncm->ncm_GeoChangeCount == ncm->ncm_ChangeCount) && ncm->ncm_Geometry.dg_TotalSectors)
1948 // cached
1949 memcpy(tddg,&ncm->ncm_Geometry, (size_t) length);
1950 ioreq->io_Actual = length;
1951 return(0);
1954 ncm->ncm_Geometry.dg_DeviceType = ncm->ncm_DeviceType;
1955 ncm->ncm_Geometry.dg_Flags = ncm->ncm_Removable ? DGF_REMOVABLE : 0;
1958 * Capacity10, 32bit Sectorcount
1960 scsicmd.scsi_Data = (UWORD *) &capacitydata;
1961 scsicmd.scsi_Length = sizeof(capacitydata);
1962 scsicmd.scsi_Command = cmd10;
1963 scsicmd.scsi_CmdLength = 10;
1964 scsicmd.scsi_Flags = SCSIF_READ|SCSIF_AUTOSENSE;
1965 scsicmd.scsi_SenseData = sensedata;
1966 scsicmd.scsi_SenseLength = 18;
1967 cmd10[0] = SCSI_DA_READ_CAPACITY;
1968 cmd10[1] = 0;
1969 cmd10[2] = 0;
1970 cmd10[3] = 0;
1971 cmd10[4] = 0;
1972 cmd10[5] = 0;
1973 cmd10[6] = 0;
1974 cmd10[7] = 0;
1975 cmd10[8] = 0;
1976 cmd10[9] = 0;
1978 if((ioerr = nScsiDirect(ncm, &scsicmd)))
1980 KPRINTF(10, ("ioerr %ld\n",ioerr));
1981 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1982 "SCSI_READ_CAPACITY failed: %ld",
1983 ioerr);
1985 * memset(tddg,0,Length);
1986 * The error should be enough
1988 return(ioreq->io_Error = ioerr);
1989 } else {
1991 * 32Bit Totalsectors
1992 * R.S.
1994 ncm->ncm_BlockSize = ncm->ncm_Geometry.dg_SectorSize = AROS_BE2LONG(capacitydata.SectorSize);
1995 ncm->ncm_Geometry.dg_TotalSectors = AROS_BE2LONG(capacitydata.SectorCount) + 1;
1996 if(capacitydata.SectorCount == 0xffffffff)
1998 ncm->ncm_Geometry.dg_TotalSectors--; // set to maximum
1999 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2000 "Capacity exceeds the maximum supported for 32 bit sector counts (usually >2TB)!");
2001 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2002 "I/O operations will still work, but geometry and partitioning will be unreliable!");
2004 KPRINTF(10, ("blocksize %ld totalsectors %ld\n", ncm->ncm_BlockSize, ncm->ncm_Geometry.dg_TotalSectors));
2005 gotblks = TRUE;
2006 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
2008 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
2009 "Capacity: %ld blocks of %ld bytes", ncm->ncm_Geometry.dg_TotalSectors, ncm->ncm_Geometry.dg_SectorSize);
2011 ncm->ncm_BlockShift = 0;
2012 while((1<<ncm->ncm_BlockShift) < ncm->ncm_BlockSize)
2014 ncm->ncm_BlockShift++;
2017 KPRINTF(10, ("PatchFlags 0x%lx DeviceType %ld\n",ncm->ncm_CDC->cdc_PatchFlags,ncm->ncm_DeviceType));
2019 if(!((ncm->ncm_CDC->cdc_PatchFlags & PFF_SIMPLE_SCSI) ||
2020 (ncm->ncm_DeviceType == PDT_WORM) ||
2021 (ncm->ncm_DeviceType == PDT_CDROM)))
2023 KPRINTF(10, ("SIMPLE_SCSI or PDT_WORM/CDROM\n"));
2024 // cd roms don't have valid or sensible capacity mode pages
2025 if((mpdata = nGetModePage(ncm, 0x03)))
2027 if((tmpval = (mpdata[10]<<8)+mpdata[11]))
2029 ncm->ncm_Geometry.dg_TrackSectors = tmpval;
2030 gotsect = TRUE;
2031 if(!ncm->ncm_Geometry.dg_Cylinders)
2033 ncm->ncm_Geometry.dg_Cylinders = ncm->ncm_Geometry.dg_TotalSectors;
2036 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
2038 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
2039 "Capacity: TrackSectors=%ld",
2040 ncm->ncm_Geometry.dg_TrackSectors);
2045 * Cylinder and co are only defined for old 32Bit Totalsectors.
2046 * >2TB they have no meaning anyway, so they are calculated based
2047 * on 32Bit INT_MAX.
2049 // recheck, could have simple scsi enabled in the meanwhile
2050 if(!((ncm->ncm_CDC->cdc_PatchFlags & PFF_SIMPLE_SCSI) ||
2051 (ncm->ncm_DeviceType == PDT_WORM) ||
2052 (ncm->ncm_DeviceType == PDT_CDROM)))
2054 KPRINTF(10, ("recheck1 SIMPLE_SCSI or PDT_WORM/CDROM\n"));
2055 if((mpdata = nGetModePage(ncm, 0x04)))
2057 if((tmpval = (mpdata[2]<<16)+(mpdata[3]<<8)+mpdata[4]))
2059 ncm->ncm_Geometry.dg_Cylinders = tmpval;
2060 ncm->ncm_Geometry.dg_Heads = mpdata[5];
2061 gotcyl = gotheads = TRUE;
2063 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
2065 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
2066 "Capacity: Cylinders=%ld, Heads=%ld",
2067 ncm->ncm_Geometry.dg_Cylinders, ncm->ncm_Geometry.dg_Heads);
2071 // recheck, could have simple scsi enabled in the meanwhile
2072 if(!((ncm->ncm_CDC->cdc_PatchFlags & PFF_SIMPLE_SCSI) ||
2073 (ncm->ncm_DeviceType == PDT_WORM) ||
2074 (ncm->ncm_DeviceType == PDT_CDROM)))
2076 KPRINTF(10, ("recheck2 SIMPLE_SCSI or PDT_WORM/CDROM\n"));
2077 if((mpdata = nGetModePage(ncm, 0x05)))
2079 if((tmpval = (mpdata[8]<<8)+mpdata[9]))
2081 ncm->ncm_Geometry.dg_Cylinders = tmpval;
2082 ncm->ncm_Geometry.dg_Heads = mpdata[4];
2083 ncm->ncm_Geometry.dg_TrackSectors = mpdata[5];
2085 gotcyl = gotheads = gotsect = TRUE;
2087 if(!gotblks)
2089 ncm->ncm_BlockSize = ncm->ncm_Geometry.dg_SectorSize = (mpdata[6]<<8)+mpdata[7];
2090 ncm->ncm_BlockShift = 0;
2091 while((1<<ncm->ncm_BlockShift) < ncm->ncm_BlockSize)
2093 ncm->ncm_BlockShift++;
2095 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
2097 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
2098 "Capacity: %ld blocks of %ld bytes", ncm->ncm_Geometry.dg_TotalSectors, ncm->ncm_BlockSize);
2101 else if(ncm->ncm_BlockSize != (mpdata[6]<<8)+mpdata[7])
2103 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2104 "Inconsistent block size information %ld != %ld!",
2105 ncm->ncm_BlockSize, (mpdata[6]<<8)+mpdata[7]);
2107 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
2109 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
2110 "Capacity: Cylinders=%ld, Heads=%ld, TrackSectors=%ld",
2111 ncm->ncm_Geometry.dg_Cylinders, ncm->ncm_Geometry.dg_Heads, ncm->ncm_Geometry.dg_TrackSectors);
2116 // missing total blocks?
2117 if((!gotblks) && gotcyl && gotheads && gotsect)
2119 ncm->ncm_Geometry.dg_TotalSectors = ncm->ncm_Geometry.dg_Cylinders * ncm->ncm_Geometry.dg_Heads * ncm->ncm_Geometry.dg_TrackSectors;
2120 gotblks = TRUE;
2122 // missing cylinders?
2123 if(gotblks && (!gotcyl) && gotheads && gotsect)
2125 ncm->ncm_Geometry.dg_Cylinders = ncm->ncm_Geometry.dg_TotalSectors / (ncm->ncm_Geometry.dg_Heads * ncm->ncm_Geometry.dg_TrackSectors);
2126 gotcyl = TRUE;
2128 // missing heads?
2129 if(gotblks && gotcyl && (!gotheads) && gotsect)
2131 ncm->ncm_Geometry.dg_Heads = ncm->ncm_Geometry.dg_TotalSectors / (ncm->ncm_Geometry.dg_Cylinders * ncm->ncm_Geometry.dg_TrackSectors);
2132 gotheads = TRUE;
2134 // missing tracks per sector
2135 if(gotblks && gotcyl && gotheads && (!gotsect))
2137 ncm->ncm_Geometry.dg_TrackSectors = ncm->ncm_Geometry.dg_TotalSectors / (ncm->ncm_Geometry.dg_Cylinders * ncm->ncm_Geometry.dg_Heads);
2138 gotsect = TRUE;
2141 if(gotblks && gotcyl && gotheads && gotsect &&
2142 (ncm->ncm_Geometry.dg_Cylinders * ncm->ncm_Geometry.dg_TrackSectors * ncm->ncm_Geometry.dg_Heads == ncm->ncm_Geometry.dg_TotalSectors - 1) &&
2143 (!(ncm->ncm_CDC->cdc_PatchFlags & PFF_FIX_CAPACITY)))
2145 if(!(ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_FALLBACK))
2147 ncm->ncm_CDC->cdc_PatchFlags |= PFF_FIX_CAPACITY;
2148 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2149 "Fallback: Enabling Fix Capacity.");
2150 GM_UNIQUENAME(nStoreConfig)(ncm);
2151 ncm->ncm_Geometry.dg_TotalSectors--;
2152 } else {
2153 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2154 "Fix Capacity is probably needed for this device. Please check this.");
2157 else if(gotblks && gotcyl && gotheads && gotsect &&
2158 (ncm->ncm_Geometry.dg_Cylinders * ncm->ncm_Geometry.dg_TrackSectors * ncm->ncm_Geometry.dg_Heads == ncm->ncm_Geometry.dg_TotalSectors + 1) &&
2159 ncm->ncm_CDC->cdc_PatchFlags & PFF_FIX_CAPACITY)
2161 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_FALLBACK)
2163 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2164 "Fix Capacity is probably enabled incorrectly. Please check this.");
2165 } else {
2166 ncm->ncm_CDC->cdc_PatchFlags &= ~PFF_FIX_CAPACITY;
2167 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2168 "Fallback: Disabling Fix Capacity.");
2169 GM_UNIQUENAME(nStoreConfig)(ncm);
2170 ncm->ncm_Geometry.dg_TotalSectors++;
2174 // some devices report these bogus values regardless of actual device capacity, though the total number of blocks is correct.
2175 if(((ncm->ncm_Geometry.dg_Cylinders == 500) && (ncm->ncm_Geometry.dg_TrackSectors == 32) && (ncm->ncm_Geometry.dg_Heads == 8)) ||
2176 ((ncm->ncm_Geometry.dg_Cylinders == 16383) && (ncm->ncm_Geometry.dg_TrackSectors == 63) && (ncm->ncm_Geometry.dg_Heads == 16)))
2178 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Firmware returns known bogus geometry, will fall back to faked geometry!");
2179 gotheads = gotcyl = gotsect = FALSE;
2180 if((ncm->ncm_CDC->cdc_PatchFlags & (PFF_SIMPLE_SCSI|PFF_NO_FALLBACK)) == PFF_SIMPLE_SCSI)
2182 ncm->ncm_CDC->cdc_PatchFlags |= PFF_SIMPLE_SCSI;
2183 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2184 "Fallback: Enabling Simple SCSI.");
2185 GM_UNIQUENAME(nStoreConfig)(ncm);
2189 // missing more than one?
2190 if(gotblks && (!(gotheads && gotcyl && gotsect)))
2192 nFakeGeometry(ncm, &ncm->ncm_Geometry);
2194 if(!gotcylsect)
2196 ncm->ncm_Geometry.dg_CylSectors = ncm->ncm_Geometry.dg_TrackSectors * ncm->ncm_Geometry.dg_Heads;
2199 if(ncm->ncm_Geometry.dg_Cylinders * ncm->ncm_Geometry.dg_CylSectors != ncm->ncm_Geometry.dg_TotalSectors)
2201 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2202 "Estimated Geometry yields %ld less total blocks %ld: Cylinders=%ld, CylSectors=%ld, Heads=%ld, TrackSectors=%ld, Blocks=%ld",
2203 ncm->ncm_Geometry.dg_TotalSectors - ncm->ncm_Geometry.dg_Cylinders * ncm->ncm_Geometry.dg_CylSectors,
2204 ncm->ncm_Geometry.dg_Cylinders * ncm->ncm_Geometry.dg_CylSectors,
2205 ncm->ncm_Geometry.dg_Cylinders, ncm->ncm_Geometry.dg_CylSectors, ncm->ncm_Geometry.dg_Heads, ncm->ncm_Geometry.dg_TrackSectors,
2206 ncm->ncm_Geometry.dg_TotalSectors);
2208 else if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
2210 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
2211 "Capacity: Cylinders=%ld, CylSectors=%ld, Heads=%ld, TrackSectors=%ld, Blocks=%ld, SectorSize=%ld",
2212 ncm->ncm_Geometry.dg_Cylinders, ncm->ncm_Geometry.dg_CylSectors, ncm->ncm_Geometry.dg_Heads, ncm->ncm_Geometry.dg_TrackSectors,
2213 ncm->ncm_Geometry.dg_TotalSectors, ncm->ncm_Geometry.dg_SectorSize);
2216 ncm->ncm_Geometry.dg_BufMemType = MEMF_PUBLIC;
2217 ncm->ncm_Geometry.dg_Reserved = 0;
2218 memcpy(tddg, &ncm->ncm_Geometry, (size_t) length);
2219 ioreq->io_Actual = length;
2220 ncm->ncm_GeoChangeCount = ncm->ncm_ChangeCount;
2221 return(ioreq->io_Error);
2223 /* \\\ */
2225 /* /// "nStartStop()" */
2226 LONG nStartStop(struct NepClassMS *ncm, struct IOStdReq *ioreq)
2228 UBYTE cmd6[6];
2229 struct SCSICmd scsicmd;
2230 UBYTE sensedata[18];
2231 LONG ioerr;
2233 if((ncm->ncm_CDC->cdc_PatchFlags & PFF_SIMPLE_SCSI)
2234 && ioreq->io_Command != TD_EJECT)
2236 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Simple SCSI: Ignoring START_STOP_UNIT command");
2237 return(0);
2239 scsicmd.scsi_Data = NULL;
2240 scsicmd.scsi_Length = 0;
2241 scsicmd.scsi_Command = cmd6;
2242 scsicmd.scsi_CmdLength = 6;
2243 scsicmd.scsi_Flags = SCSIF_AUTOSENSE|0x80;
2244 scsicmd.scsi_SenseData = sensedata;
2245 scsicmd.scsi_SenseLength = 18;
2246 cmd6[0] = SCSI_DA_START_STOP_UNIT;
2247 cmd6[1] = 0;
2248 cmd6[2] = 0;
2249 cmd6[3] = 0;
2250 switch(ioreq->io_Command)
2252 case CMD_START:
2253 cmd6[4] = 0x01;
2254 break;
2256 case CMD_STOP:
2257 cmd6[4] = 0x00;
2258 break;
2260 case TD_EJECT:
2261 cmd6[4] = ioreq->io_Length ? 0x02 : 0x03;
2262 break;
2264 cmd6[5] = 0;
2265 if((ioerr = nScsiDirect(ncm, &scsicmd)))
2267 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2268 "START_STOP_UNIT failed: %ld",
2269 ioerr);
2270 ioreq->io_Error = TDERR_NotSpecified;
2272 return(ioreq->io_Error);
2274 /* \\\ */
2276 /* /// "nRead64Emul()" */
2277 LONG nRead64Emul(struct NepClassMS *ncm, struct IOStdReq *ioreq)
2279 UBYTE cmd10[10];
2280 ULONG *cmd10sb = (ULONG *)&cmd10[2];
2281 UBYTE sensedata[18];
2282 ULONG dataoffset = 0;
2283 ULONG dataremain = ioreq->io_Length;
2284 ULONG datalen;
2285 ULONG startblock;
2286 ULONG maxtrans = 1UL<<(ncm->ncm_CDC->cdc_MaxTransfer+16);
2287 ULONG insideblockoffset;
2288 struct SCSICmd scsicmd;
2290 if(dataremain & 511)
2292 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2293 "Attempt to read partial block (%ld %% %ld != 0)!",
2294 dataremain, ncm->ncm_BlockSize);
2295 ioreq->io_Actual = 0;
2296 return(ioreq->io_Error = IOERR_BADLENGTH);
2298 if(ioreq->io_Offset & 511)
2300 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2301 "Attempt to read unaligned block (%ld %% %ld != 0)!",
2302 ioreq->io_Offset, ncm->ncm_BlockSize);
2303 ioreq->io_Actual = 0;
2304 return(ioreq->io_Error = IOERR_BADADDRESS);
2307 if(!ncm->ncm_OneBlock || (ncm->ncm_OneBlockSize < ncm->ncm_BlockSize))
2309 psdFreeVec(ncm->ncm_OneBlock);
2310 if(!(ncm->ncm_OneBlock = psdAllocVec(ncm->ncm_BlockSize)))
2312 return(IOERR_BADADDRESS);
2314 ncm->ncm_OneBlockSize = ncm->ncm_BlockSize;
2317 startblock = (ioreq->io_Offset>>ncm->ncm_BlockShift)|(ioreq->io_Actual<<(32-ncm->ncm_BlockShift));
2318 insideblockoffset = (ioreq->io_Offset & ((1<<ncm->ncm_BlockShift)-1));
2319 while(dataremain)
2321 KPRINTF(10, ("Reading from block %ld, %ld bytes left...\n", startblock, dataremain));
2322 datalen = dataremain;
2323 if(datalen > maxtrans)
2325 datalen = maxtrans;
2327 if(insideblockoffset || (datalen < ncm->ncm_BlockSize))
2329 if(datalen > ncm->ncm_BlockSize-insideblockoffset)
2331 datalen = ncm->ncm_BlockSize-insideblockoffset;
2333 scsicmd.scsi_Data = (UWORD *) ncm->ncm_OneBlock;
2334 scsicmd.scsi_Length = ncm->ncm_BlockSize;
2335 scsicmd.scsi_Command = cmd10;
2336 scsicmd.scsi_CmdLength = 10;
2337 scsicmd.scsi_Flags = SCSIF_READ|SCSIF_AUTOSENSE|0x80;
2338 scsicmd.scsi_SenseData = sensedata;
2339 scsicmd.scsi_SenseLength = 18;
2340 cmd10[0] = SCSI_DA_READ_10;
2341 cmd10[1] = 0;
2342 *cmd10sb = AROS_LONG2BE(startblock);
2343 cmd10[6] = 0;
2344 cmd10[7] = 0;
2345 cmd10[8] = 1;
2346 cmd10[9] = 0;
2347 if((ioreq->io_Error = nScsiDirect(ncm, &scsicmd)))
2349 KPRINTF(10, ("Read error!\n"));
2350 break;
2352 CopyMemQuick(&ncm->ncm_OneBlock[insideblockoffset], &(((UBYTE *) ioreq->io_Data)[dataoffset]), datalen);
2353 insideblockoffset = 0;
2354 startblock++;
2355 } else {
2356 scsicmd.scsi_Data = (UWORD *) &(((UBYTE *) ioreq->io_Data)[dataoffset]);
2357 scsicmd.scsi_Length = datalen;
2358 scsicmd.scsi_Command = cmd10;
2359 scsicmd.scsi_CmdLength = 10;
2360 scsicmd.scsi_Flags = SCSIF_READ|SCSIF_AUTOSENSE|0x80;
2361 scsicmd.scsi_SenseData = sensedata;
2362 scsicmd.scsi_SenseLength = 18;
2363 cmd10[0] = SCSI_DA_READ_10;
2364 cmd10[1] = 0;
2365 *cmd10sb = AROS_LONG2BE(startblock);
2366 cmd10[6] = 0;
2367 cmd10[7] = datalen>>(ncm->ncm_BlockShift+8);
2368 cmd10[8] = datalen>>ncm->ncm_BlockShift;
2369 cmd10[9] = 0;
2370 if((ioreq->io_Error = nScsiDirect(ncm, &scsicmd)))
2372 KPRINTF(10, ("Read error!\n"));
2373 break;
2375 startblock += (insideblockoffset+datalen)>>ncm->ncm_BlockShift;
2377 dataoffset += datalen;
2378 dataremain -= datalen;
2380 ioreq->io_Actual = dataoffset;
2381 return(ioreq->io_Error);
2383 /* \\\ */
2385 /* /// "nWrite64Emul()" */
2386 LONG nWrite64Emul(struct NepClassMS *ncm, struct IOStdReq *ioreq)
2388 UBYTE cmd10[10];
2389 ULONG *cmd10sb = (ULONG *)&cmd10[2];
2390 UBYTE sensedata[18];
2391 ULONG dataoffset = 0;
2392 ULONG dataremain = ioreq->io_Length;
2393 ULONG datalen;
2394 ULONG startblock;
2395 ULONG maxtrans = 1UL<<(ncm->ncm_CDC->cdc_MaxTransfer+16);
2396 ULONG insideblockoffset;
2397 struct SCSICmd scsicmd;
2399 if(dataremain & 511)
2401 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2402 "Attempt to write partial block (%ld %% %ld != 0)!",
2403 dataremain, ncm->ncm_BlockSize);
2404 ioreq->io_Actual = 0;
2405 return(ioreq->io_Error = IOERR_BADLENGTH);
2407 if(ioreq->io_Offset & 511)
2409 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2410 "Attempt to write unaligned block (%ld %% %ld != 0)!",
2411 ioreq->io_Offset, ncm->ncm_BlockSize);
2412 ioreq->io_Actual = 0;
2413 return(ioreq->io_Error = IOERR_BADADDRESS);
2416 if(!ncm->ncm_OneBlock || (ncm->ncm_OneBlockSize < ncm->ncm_BlockSize))
2418 psdFreeVec(ncm->ncm_OneBlock);
2419 if(!(ncm->ncm_OneBlock = psdAllocVec(ncm->ncm_BlockSize)))
2421 return(IOERR_BADADDRESS);
2423 ncm->ncm_OneBlockSize = ncm->ncm_BlockSize;
2426 startblock = (ioreq->io_Offset>>ncm->ncm_BlockShift)|(ioreq->io_Actual<<(32-ncm->ncm_BlockShift));
2427 insideblockoffset = (ioreq->io_Offset & ((1<<ncm->ncm_BlockShift)-1));
2428 while(dataremain)
2430 KPRINTF(10, ("Writing from block %ld, %ld bytes left...\n", startblock, dataremain));
2431 datalen = dataremain;
2432 if(datalen > maxtrans)
2434 datalen = maxtrans;
2436 if(insideblockoffset || (datalen < ncm->ncm_BlockSize))
2438 if(datalen > ncm->ncm_BlockSize-insideblockoffset)
2440 datalen = ncm->ncm_BlockSize-insideblockoffset;
2442 scsicmd.scsi_Data = (UWORD *) ncm->ncm_OneBlock;
2443 scsicmd.scsi_Length = ncm->ncm_BlockSize;
2444 scsicmd.scsi_Command = cmd10;
2445 scsicmd.scsi_CmdLength = 10;
2446 scsicmd.scsi_Flags = SCSIF_READ|SCSIF_AUTOSENSE|0x80;
2447 scsicmd.scsi_SenseData = sensedata;
2448 scsicmd.scsi_SenseLength = 18;
2449 cmd10[0] = SCSI_DA_READ_10;
2450 cmd10[1] = 0;
2451 *cmd10sb = AROS_LONG2BE(startblock);
2452 cmd10[6] = 0;
2453 cmd10[7] = 0;
2454 cmd10[8] = 1;
2455 cmd10[9] = 0;
2456 if((ioreq->io_Error = nScsiDirect(ncm, &scsicmd)))
2458 KPRINTF(10, ("Read error!\n"));
2459 break;
2461 CopyMemQuick(&(((UBYTE *) ioreq->io_Data)[dataoffset]), &ncm->ncm_OneBlock[insideblockoffset], datalen);
2463 //scsicmd.scsi_Data = (UWORD *) ncm->ncm_OneBlock;
2464 //scsicmd.scsi_Length = ncm->ncm_BlockSize;
2465 //scsicmd.scsi_Command = cmd10;
2466 //scsicmd.scsi_CmdLength = 10;
2467 scsicmd.scsi_Flags = SCSIF_WRITE|SCSIF_AUTOSENSE|0x80;
2468 //scsicmd.scsi_SenseData = sensedata;
2469 //scsicmd.scsi_SenseLength = 18;
2470 cmd10[0] = SCSI_DA_WRITE_10;
2471 //cmd10[1] = 0;
2472 //*((ULONG *) (&cmd10[2])) = AROS_LONG2BE(startblock);
2473 //cmd10[6] = 0;
2474 //cmd10[7] = 0;
2475 //cmd10[8] = 1;
2476 //cmd10[9] = 0;
2477 if((ioreq->io_Error = nScsiDirect(ncm, &scsicmd)))
2479 KPRINTF(10, ("Write error!\n"));
2480 break;
2482 insideblockoffset = 0;
2483 startblock++;
2484 } else {
2485 scsicmd.scsi_Data = (UWORD *) &(((UBYTE *) ioreq->io_Data)[dataoffset]);
2486 scsicmd.scsi_Length = datalen;
2487 scsicmd.scsi_Command = cmd10;
2488 scsicmd.scsi_CmdLength = 10;
2489 scsicmd.scsi_Flags = SCSIF_WRITE|SCSIF_AUTOSENSE|0x80;
2490 scsicmd.scsi_SenseData = sensedata;
2491 scsicmd.scsi_SenseLength = 18;
2492 cmd10[0] = SCSI_DA_WRITE_10;
2493 cmd10[1] = 0;
2494 *cmd10sb = AROS_LONG2BE(startblock);
2495 cmd10[6] = 0;
2496 cmd10[7] = datalen>>(ncm->ncm_BlockShift+8);
2497 cmd10[8] = datalen>>ncm->ncm_BlockShift;
2498 cmd10[9] = 0;
2499 if((ioreq->io_Error = nScsiDirect(ncm, &scsicmd)))
2501 KPRINTF(10, ("Write error!\n"));
2502 break;
2504 startblock += (insideblockoffset+datalen)>>ncm->ncm_BlockShift;
2506 dataoffset += datalen;
2507 dataremain -= datalen;
2509 ioreq->io_Actual = dataoffset;
2510 return(ioreq->io_Error);
2512 /* \\\ */
2514 /* /// "nRead64()" */
2515 LONG nRead64(struct NepClassMS *ncm, struct IOStdReq *ioreq)
2517 UBYTE cmd10[10];
2518 UBYTE cmd16[16];
2519 UBYTE sensedata[18];
2520 ULONG dataoffset = 0;
2521 ULONG dataremain = ioreq->io_Length;
2522 ULONG datalen;
2523 ULONG startblockhigh;
2524 ULONG startblock;
2525 ULONG oldstartblock;
2526 ULONG maxtrans = 1UL<<(ncm->ncm_CDC->cdc_MaxTransfer+16);
2527 struct SCSICmd scsicmd;
2529 if(!ncm->ncm_BlockSize)
2531 nGetBlockSize(ncm);
2533 if((((dataremain >> ncm->ncm_BlockShift)<<ncm->ncm_BlockShift) != dataremain) ||
2534 (((ioreq->io_Offset >> ncm->ncm_BlockShift)<<ncm->ncm_BlockShift) != ioreq->io_Offset))
2536 KPRINTF(20, ("unaligned read access offset %ld, length %ld...\n", ioreq->io_Offset, dataremain));
2537 if((!(ncm->ncm_CDC->cdc_PatchFlags & PFF_EMUL_LARGE_BLK)) && (!(ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_FALLBACK)))
2539 ncm->ncm_CDC->cdc_PatchFlags |= PFF_EMUL_LARGE_BLK;
2540 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2541 "Fallback: Enabling emulation for large block devices.");
2542 GM_UNIQUENAME(nStoreConfig)(ncm);
2544 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_EMUL_LARGE_BLK)
2546 return(nRead64Emul(ncm, ioreq));
2548 if((dataremain >> ncm->ncm_BlockShift)<<ncm->ncm_BlockShift != dataremain)
2550 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2551 "Attempt to read partial block (%ld %% %ld != 0)!",
2552 dataremain, ncm->ncm_BlockSize);
2553 ioreq->io_Error = IOERR_BADLENGTH;
2554 } else {
2555 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2556 "Attempt to read unaligned block (%ld %% %ld != 0)!",
2557 ioreq->io_Offset, ncm->ncm_BlockSize);
2558 ioreq->io_Error = IOERR_BADADDRESS;
2560 if(ncm->ncm_BlockSize != 512)
2562 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2563 "The used FileSystem or other software must support %ld byte blocks!",
2564 ncm->ncm_BlockSize);
2566 ioreq->io_Actual = 0;
2567 return(ioreq->io_Error);
2570 startblockhigh = ioreq->io_Actual>>ncm->ncm_BlockShift;
2571 startblock = (ioreq->io_Offset>>ncm->ncm_BlockShift)|(ioreq->io_Actual<<(32-ncm->ncm_BlockShift));
2572 while(dataremain)
2574 KPRINTF(10, ("Reading from block %ld, %ld bytes left...\n", startblock, dataremain));
2575 datalen = dataremain;
2576 if(datalen > maxtrans)
2578 datalen = maxtrans;
2580 scsicmd.scsi_Data = (UWORD *) &(((UBYTE *) ioreq->io_Data)[dataoffset]);
2581 scsicmd.scsi_Length = datalen;
2582 scsicmd.scsi_Flags = SCSIF_READ|SCSIF_AUTOSENSE|0x80;
2583 scsicmd.scsi_SenseData = sensedata;
2584 scsicmd.scsi_SenseLength = 18;
2585 if(startblockhigh)
2587 ULONG *cmd16sbh = (ULONG *)&cmd16[2];
2588 ULONG *cmd16sbl = (ULONG *)&cmd16[6];
2589 // Arithmetics for >2 TB needed
2590 scsicmd.scsi_Command = cmd16;
2591 scsicmd.scsi_CmdLength = 16;
2592 cmd16[0] = SCSI_DA_READ_16;
2593 cmd16[1] = 0;
2594 *cmd16sbh = AROS_LONG2BE(startblockhigh);
2595 *cmd16sbl = AROS_LONG2BE(startblock);
2596 cmd16[10] = datalen>>(ncm->ncm_BlockShift+24);
2597 cmd16[11] = datalen>>(ncm->ncm_BlockShift+16);
2598 cmd16[12] = datalen>>(ncm->ncm_BlockShift+8);
2599 cmd16[13] = datalen>>ncm->ncm_BlockShift;
2600 cmd16[14] = 0;
2601 cmd16[15] = 0;
2602 } else {
2603 ULONG *cmd10sb = (ULONG *)&cmd10[2];
2604 scsicmd.scsi_Command = cmd10;
2605 scsicmd.scsi_CmdLength = 10;
2606 cmd10[0] = SCSI_DA_READ_10;
2607 cmd10[1] = 0;
2608 *cmd10sb = AROS_LONG2BE(startblock);
2609 cmd10[6] = 0;
2610 cmd10[7] = datalen>>(ncm->ncm_BlockShift+8);
2611 cmd10[8] = datalen>>ncm->ncm_BlockShift;
2612 cmd10[9] = 0;
2614 if((ioreq->io_Error = nScsiDirect(ncm, &scsicmd)))
2616 KPRINTF(10, ("Read error!\n"));
2617 break;
2619 dataoffset += datalen;
2620 dataremain -= datalen;
2621 oldstartblock = startblock;
2622 startblock += datalen>>ncm->ncm_BlockShift;
2623 if(startblock < oldstartblock)
2625 // wrap around occurred
2626 startblockhigh++;
2629 ioreq->io_Actual = dataoffset;
2630 return(ioreq->io_Error);
2632 /* \\\ */
2634 /* /// "nSeek64()" */
2635 LONG nSeek64(struct NepClassMS *ncm, struct IOStdReq *ioreq)
2637 UBYTE cmd10[10];
2638 ULONG *cmd10sb = (ULONG *)&cmd10[2];
2639 UBYTE sensedata[18];
2640 struct SCSICmd scsicmd;
2641 ULONG startblock;
2643 if(!ncm->ncm_BlockSize)
2645 nGetBlockSize(ncm);
2647 if(((ioreq->io_Offset >> ncm->ncm_BlockShift)<<ncm->ncm_BlockShift) != ioreq->io_Offset)
2649 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2650 "Attempt to to seek to unaligned block (%ld %% %ld != 0)!",
2651 ioreq->io_Offset, ncm->ncm_BlockSize);
2652 if(ncm->ncm_BlockSize != 512)
2654 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2655 "The used FileSystem or other software must support %ld byte blocks!",
2656 ncm->ncm_BlockSize);
2658 ioreq->io_Actual = 0;
2659 return(ioreq->io_Error = IOERR_BADADDRESS);
2662 startblock = (ioreq->io_Offset>>ncm->ncm_BlockShift)|(ioreq->io_Actual<<(32-ncm->ncm_BlockShift));
2663 scsicmd.scsi_Data = NULL;
2664 scsicmd.scsi_Length = 0;
2665 scsicmd.scsi_CmdLength = 10;
2666 scsicmd.scsi_Flags = SCSIF_READ|SCSIF_AUTOSENSE|0x80;
2667 scsicmd.scsi_SenseData = sensedata;
2668 scsicmd.scsi_SenseLength = 18;
2669 cmd10[0] = SCSI_DA_SEEK_10;
2670 cmd10[1] = 0;
2671 *cmd10sb = AROS_LONG2BE(startblock);
2672 cmd10[6] = 0;
2673 cmd10[7] = 0;
2674 cmd10[8] = 0;
2675 cmd10[9] = 0;
2676 if((ioreq->io_Error = nScsiDirect(ncm, &scsicmd)))
2678 KPRINTF(10, ("Seek error!\n"));
2680 ioreq->io_Actual = 0;
2681 return(ioreq->io_Error);
2683 /* \\\ */
2685 /* /// "nWrite64()" */
2686 LONG nWrite64(struct NepClassMS *ncm, struct IOStdReq *ioreq)
2688 UBYTE cmd10[10];
2689 UBYTE cmd16[16];
2690 UBYTE sensedata[18];
2691 ULONG dataoffset = 0;
2692 ULONG dataremain = ioreq->io_Length;
2693 ULONG datalen;
2694 ULONG startblockhigh;
2695 ULONG startblock;
2696 ULONG oldstartblock;
2697 ULONG maxtrans = 1UL<<(ncm->ncm_CDC->cdc_MaxTransfer+16);
2698 struct SCSICmd scsicmd;
2700 if(!ncm->ncm_BlockSize)
2702 nGetBlockSize(ncm);
2704 if(((dataremain >> ncm->ncm_BlockShift)<<ncm->ncm_BlockShift != dataremain) ||
2705 ((ioreq->io_Offset >> ncm->ncm_BlockShift)<<ncm->ncm_BlockShift != ioreq->io_Offset))
2707 KPRINTF(20, ("unaligned write access offset %ld, length %ld...\n", ioreq->io_Offset, dataremain));
2708 if((!(ncm->ncm_CDC->cdc_PatchFlags & PFF_EMUL_LARGE_BLK)) && (!(ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_FALLBACK)))
2710 ncm->ncm_CDC->cdc_PatchFlags |= PFF_EMUL_LARGE_BLK;
2711 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2712 "Fallback: Enabling emulation for large block devices.");
2713 GM_UNIQUENAME(nStoreConfig)(ncm);
2715 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_EMUL_LARGE_BLK)
2717 return(nWrite64Emul(ncm, ioreq));
2719 if((dataremain >> ncm->ncm_BlockShift)<<ncm->ncm_BlockShift != dataremain)
2721 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2722 "Attempt to write partial block (%ld %% %ld != 0)!",
2723 dataremain, ncm->ncm_BlockSize);
2724 ioreq->io_Error = IOERR_BADLENGTH;
2725 } else {
2726 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2727 "Attempt to write unaligned block (%ld %% %ld != 0)!",
2728 ioreq->io_Offset, ncm->ncm_BlockSize);
2729 ioreq->io_Error = IOERR_BADADDRESS;
2731 if(ncm->ncm_BlockSize != 512)
2733 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2734 "The used FileSystem or other software must support %ld byte blocks!",
2735 ncm->ncm_BlockSize);
2737 ioreq->io_Actual = 0;
2738 return(ioreq->io_Error);
2741 startblockhigh = ioreq->io_Actual>>ncm->ncm_BlockShift;
2742 startblock = (ioreq->io_Offset>>ncm->ncm_BlockShift)|(ioreq->io_Actual<<(32-ncm->ncm_BlockShift));
2743 while(dataremain)
2745 datalen = dataremain;
2746 if(datalen > maxtrans)
2748 datalen = maxtrans;
2750 scsicmd.scsi_Data = (UWORD *) &(((UBYTE *) ioreq->io_Data)[dataoffset]);
2751 scsicmd.scsi_Length = datalen;
2752 scsicmd.scsi_Flags = SCSIF_WRITE|SCSIF_AUTOSENSE|0x80;
2753 scsicmd.scsi_SenseData = sensedata;
2754 scsicmd.scsi_SenseLength = 18;
2755 if(startblockhigh)
2757 ULONG *cmd16sbh = (ULONG *)&cmd16[2];
2758 ULONG *cmd16sbl = (ULONG *)&cmd16[6];
2759 // Arithmetics for >2 TB needed
2760 scsicmd.scsi_Command = cmd16;
2761 scsicmd.scsi_CmdLength = 16;
2762 cmd16[0] = SCSI_DA_WRITE_16;
2763 cmd16[1] = 0;
2764 *cmd16sbh = AROS_LONG2BE(startblockhigh);
2765 *cmd16sbl = AROS_LONG2BE(startblock);
2766 cmd16[10] = datalen>>(ncm->ncm_BlockShift+24);
2767 cmd16[11] = datalen>>(ncm->ncm_BlockShift+16);
2768 cmd16[12] = datalen>>(ncm->ncm_BlockShift+8);
2769 cmd16[13] = datalen>>ncm->ncm_BlockShift;
2770 cmd16[14] = 0;
2771 cmd16[15] = 0;
2772 } else {
2773 ULONG *cmd10sb = (ULONG *)&cmd10[2];
2774 scsicmd.scsi_Command = cmd10;
2775 scsicmd.scsi_CmdLength = 10;
2776 cmd10[0] = SCSI_DA_WRITE_10;
2777 cmd10[1] = 0;
2778 *cmd10sb = AROS_LONG2BE(startblock);
2779 cmd10[6] = 0;
2780 cmd10[7] = datalen>>(ncm->ncm_BlockShift+8);
2781 cmd10[8] = datalen>>ncm->ncm_BlockShift;
2782 cmd10[9] = 0;
2784 if((ioreq->io_Error = nScsiDirect(ncm, &scsicmd)))
2786 break;
2788 dataoffset += datalen;
2789 dataremain -= datalen;
2790 oldstartblock = startblock;
2791 startblock += datalen>>ncm->ncm_BlockShift;
2792 if(startblock < oldstartblock)
2794 // wrap around occurred
2795 startblockhigh++;
2798 ioreq->io_Actual = dataoffset;
2799 return(ioreq->io_Error);
2801 /* \\\ */
2803 /* /// "nCBIRequestSense()" */
2804 LONG nCBIRequestSense(struct NepClassMS *ncm, UBYTE *senseptr, ULONG datalen)
2806 LONG ioerr;
2807 UBYTE sensecmd[12];
2808 LONG actual = 0;
2809 struct UsbMSCBIStatusWrapper umscsw;
2811 memset(sensecmd, 0, 12);
2812 senseptr[2] = SK_ILLEGAL_REQUEST;
2813 sensecmd[0] = SCSI_REQUEST_SENSE;
2814 sensecmd[1] = 0x00;
2815 sensecmd[2] = 0x00;
2816 sensecmd[3] = 0x00;
2817 sensecmd[4] = datalen;
2818 sensecmd[5] = 0;
2819 KPRINTF(2, ("sense command block phase...\n"));
2821 /*psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
2822 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
2823 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);*/
2824 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_CLASS|URTF_INTERFACE,
2825 UMSR_ADSC, 0, (ULONG) ncm->ncm_UnitIfNum);
2826 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, sensecmd, ((ncm->ncm_CSType == MS_ATAPI_SUBCLASS) ||
2827 (ncm->ncm_CSType == MS_FDDATAPI_SUBCLASS) ||
2828 (ncm->ncm_CSType == MS_UFI_SUBCLASS)) ? (ULONG) 12 : (ULONG) 6);
2829 if(!ioerr)
2831 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_CLEAR_EP)
2833 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
2834 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
2835 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
2838 KPRINTF(2, ("sense data phase %ld bytes...\n", datalen));
2839 ioerr = psdDoPipe(ncm->ncm_EPInPipe, senseptr, datalen);
2840 actual = psdGetPipeActual(ncm->ncm_EPInPipe);
2841 if(ioerr == UHIOERR_STALL)
2843 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
2844 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
2845 psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
2847 if((!ioerr) || (ioerr == UHIOERR_RUNTPACKET))
2849 KPRINTF(2, ("sense command status phase...\n"));
2850 if(ncm->ncm_TPType == MS_PROTO_CBI)
2852 umscsw.bType = 0;
2853 umscsw.bValue = USMF_CSW_PHASEERR;
2854 ioerr = psdDoPipe(ncm->ncm_EPIntPipe, &umscsw, sizeof(struct UsbMSCBIStatusWrapper));
2855 if(ioerr && (ioerr != UHIOERR_RUNTPACKET))
2857 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2858 "Status interrupt failed: %s (%ld)",
2859 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2860 return(0);
2862 umscsw.bValue &= USMF_CSW_PERSIST; /* mask out other bits */
2863 } else {
2864 umscsw.bType = 0;
2865 umscsw.bValue = USMF_CSW_PASS;
2866 ioerr = 0;
2868 if((!ioerr) || (ioerr == UHIOERR_RUNTPACKET))
2870 KPRINTF(2, ("sense Status:\n"
2871 " Status : %02lx\n",
2872 umscsw.bValue));
2873 if(umscsw.bValue)
2875 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2876 "Sense failed: %ld",
2877 umscsw.bValue);*/
2878 if(umscsw.bValue == USMF_CSW_PHASEERR)
2880 return(0);
2882 } else {
2883 switch(senseptr[2] & SK_MASK)
2885 case SK_UNIT_ATTENTION:
2886 if((senseptr[12] == 0x28) ||
2887 (senseptr[12] == 0x3A))
2889 ncm->ncm_ChangeCount++;
2891 break;
2894 if((ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG) && (senseptr[2] & SK_MASK))
2896 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2897 "Request Sense Key %lx/%02lx/%02lx",
2898 senseptr[2] & SK_MASK,
2899 senseptr[12],
2900 senseptr[13]);
2903 } else {
2904 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2905 "Sense status failed: %s (%ld)",
2906 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2908 } else {
2909 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2910 "Sense data failed: %s (%ld)",
2911 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2913 } else {
2914 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2915 "Sense block failed: %s (%ld)",
2916 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2918 return(actual);
2920 /* \\\ */
2922 /* /// "nBulkReset()" */
2923 LONG nBulkReset(struct NepClassMS *ncm)
2925 LONG ioerr;
2926 LONG ioerr2 = 0;
2927 static UBYTE cbiresetcmd12[12] = { 0x1D, 0x04, 0xFF, 0xFF, 0xFF, 0xFF,
2928 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
2929 //struct UsbMSCBIStatusWrapper umscsw;
2930 //UBYTE sensedata[18];
2931 if(ncm->ncm_DenyRequests)
2933 return UHIOERR_TIMEOUT;
2935 KPRINTF(1, ("Bulk Reset\n"));
2936 //psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Bulk Reset...");
2937 switch(ncm->ncm_TPType)
2939 case MS_PROTO_BULK:
2940 if(!ncm->ncm_BulkResetBorks)
2942 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_CLASS|URTF_INTERFACE,
2943 UMSR_BULK_ONLY_RESET, 0, (ULONG) ncm->ncm_UnitIfNum);
2944 ioerr2 = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
2945 if(ioerr2 == UHIOERR_TIMEOUT)
2947 return(ioerr2);
2949 if(ioerr2)
2951 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2952 "BULK_ONLY_RESET failed: %s (%ld)",
2953 psdNumToStr(NTS_IOERR, ioerr2, "unknown"), ioerr2);
2954 ncm->ncm_BulkResetBorks = TRUE;
2956 if(ncm->ncm_DenyRequests)
2958 return ioerr2;
2961 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
2962 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
2963 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
2964 if(ioerr)
2966 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2967 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
2968 ncm->ncm_EPInNum, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2970 if(ncm->ncm_DenyRequests)
2972 return ioerr;
2974 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
2975 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPOutNum);
2976 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
2977 if(ioerr)
2979 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2980 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
2981 ncm->ncm_EPOutNum, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2983 return(ioerr2 ? ioerr2 : ioerr);
2985 case MS_PROTO_CBI:
2986 case MS_PROTO_CB:
2987 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_CLASS|URTF_INTERFACE,
2988 UMSR_ADSC, 0, (ULONG) ncm->ncm_UnitIfNum);
2989 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, cbiresetcmd12, 12);
2990 if(ioerr)
2992 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2993 "CBI_RESET failed: %s (%ld)",
2994 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2996 if(ncm->ncm_DenyRequests)
2998 return ioerr;
3000 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3001 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
3002 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
3003 if(ioerr)
3005 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3006 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
3007 ncm->ncm_EPInNum, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
3009 if(ncm->ncm_DenyRequests)
3011 return ioerr;
3013 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3014 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPOutNum);
3015 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
3016 if(ioerr)
3018 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3019 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
3020 ncm->ncm_EPOutNum, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
3022 //nCBIRequestSense(ncm, sensedata, 18);
3023 return(ioerr);
3025 return(0);
3027 /* \\\ */
3029 /* /// "nBulkClear()" */
3030 LONG nBulkClear(struct NepClassMS *ncm)
3032 LONG ioerr;
3033 if(ncm->ncm_DenyRequests)
3035 return UHIOERR_TIMEOUT;
3037 KPRINTF(1, ("Bulk Clear\n"));
3038 //psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Bulk Clear...");
3039 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3040 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
3041 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
3042 if(ioerr == UHIOERR_TIMEOUT)
3044 return(ioerr);
3046 if(ioerr)
3048 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3049 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
3050 ncm->ncm_EPInNum, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
3052 if(ncm->ncm_DenyRequests)
3054 return ioerr;
3056 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3057 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPOutNum);
3058 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
3059 if(ioerr)
3061 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3062 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
3063 ncm->ncm_EPOutNum, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
3065 return(ioerr);
3067 /* \\\ */
3069 /* /// "nScsiDirect()" */
3070 LONG nScsiDirect(struct NepClassMS *ncm, struct SCSICmd *scsicmd)
3072 STRPTR prodname;
3073 STRPTR vendname;
3074 UBYTE cmd12[12];
3075 struct SCSICmd scsicmd10;
3076 BOOL usecmd10 = FALSE;
3077 LONG res;
3078 UBYTE *sensedata = NULL;
3079 UBYTE *buf;
3080 BOOL xlate = FALSE;
3081 ULONG pf = ncm->ncm_CDC->cdc_PatchFlags;
3083 scsicmd->scsi_Actual = 0;
3084 scsicmd->scsi_CmdActual = 0;
3085 scsicmd->scsi_SenseActual = 0;
3087 if(((pf & PFF_MODE_XLATE) && (scsicmd->scsi_CmdLength == 6)) ||
3088 (ncm->ncm_CSType == MS_FDDATAPI_SUBCLASS) ||
3089 (ncm->ncm_CSType == MS_ATAPI_SUBCLASS) ||
3090 (ncm->ncm_CSType == MS_UFI_SUBCLASS))
3092 xlate = TRUE;
3095 if(pf & PFF_SIMPLE_SCSI)
3097 if(scsicmd->scsi_Flags & SCSIF_AUTOSENSE)
3099 if(scsicmd->scsi_SenseLength > 18)
3101 KPRINTF(10, ("Fixing Sense Length to 18!\n"));
3102 scsicmd->scsi_SenseLength = 18;
3105 switch(scsicmd->scsi_Command[0])
3107 case SCSI_TEST_UNIT_READY:
3108 case SCSI_INQUIRY:
3109 //case SCSI_LOG_SELECT:
3110 //case SCSI_LOG_SENSE:
3111 case SCSI_REQUEST_SENSE:
3112 //case SCSI_MODE_SELECT_6:
3113 //case SCSI_MODE_SELECT_10:
3114 //case SCSI_MODE_SENSE_6:
3115 //case SCSI_MODE_SENSE_10:
3116 case SCSI_DA_READ_6:
3117 case SCSI_DA_READ_10:
3118 case SCSI_DA_READ_CAPACITY:
3119 case SCSI_DA_SEEK_6:
3120 case SCSI_DA_SEEK_10:
3121 case SCSI_DA_WRITE_6:
3122 case SCSI_DA_WRITE_10:
3123 break;
3125 case SCSI_MODE_SENSE_6:
3127 UWORD modepage = scsicmd->scsi_Command[2] & 0x3f;
3128 UBYTE *data = (UBYTE *) scsicmd->scsi_Data;
3129 if((modepage == 0x3f) ||
3130 (modepage == 0x03) ||
3131 (modepage == 0x04) ||
3132 (modepage == 0x05))
3134 if(!(ncm->ncm_BlockSize && ncm->ncm_Geometry.dg_TotalSectors))
3136 nGetBlockSize(ncm);
3138 if(ncm->ncm_Geometry.dg_TotalSectors)
3140 nFakeGeometry(ncm, &ncm->ncm_Geometry);
3141 ncm->ncm_GeoChangeCount = ncm->ncm_ChangeCount;
3143 memset(data, 0, (size_t) scsicmd->scsi_Length);
3144 scsicmd->scsi_Status = SCSI_GOOD;
3146 if(modepage == 0x3f) // all available mode pages
3148 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Simple SCSI: Faking All Mode Pages 0x03-0x05");
3149 data[0] = 3+2+22+2+22+2+30;
3150 data += 4;
3151 scsicmd->scsi_Actual = 4;
3152 if(scsicmd->scsi_Length >= 4+2+22)
3154 data[0] = 0x03; // mode page
3155 data[1] = 22; // page length
3156 data[10] = ncm->ncm_Geometry.dg_TrackSectors>>8;
3157 data[11] = ncm->ncm_Geometry.dg_TrackSectors;
3158 data[12] = ncm->ncm_Geometry.dg_SectorSize>>8;
3159 data[13] = ncm->ncm_Geometry.dg_SectorSize;
3160 data += 2+22;
3161 scsicmd->scsi_Actual += 2+22;
3163 if(scsicmd->scsi_Length >= 4+2+22+2+22)
3165 data[0] = 0x04; // mode page
3166 data[1] = 22; // page length
3167 data[2] = ncm->ncm_Geometry.dg_Cylinders>>16;
3168 data[3] = ncm->ncm_Geometry.dg_Cylinders>>8;
3169 data[4] = ncm->ncm_Geometry.dg_Cylinders;
3170 data[5] = ncm->ncm_Geometry.dg_Heads;
3171 data += 2+22;
3172 scsicmd->scsi_Actual += 2+22;
3174 if(scsicmd->scsi_Length >= 4+2+22+2+22+2+30)
3176 data[0] = 0x05; // mode page
3177 data[1] = 30; // page length
3178 data[4] = ncm->ncm_Geometry.dg_Heads;
3179 data[5] = ncm->ncm_Geometry.dg_TrackSectors;
3180 data[6] = ncm->ncm_Geometry.dg_SectorSize>>8;
3181 data[7] = ncm->ncm_Geometry.dg_SectorSize;
3182 data[8] = ncm->ncm_Geometry.dg_Cylinders>>8;
3183 data[9] = ncm->ncm_Geometry.dg_Cylinders;
3184 //data += 2+30;
3185 scsicmd->scsi_Actual += 2+30;
3187 return(0);
3189 else if((modepage == 0x03) && (scsicmd->scsi_Length >= 6+22)) // Format Device mode page
3191 // fake geometry request
3192 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Simple SCSI: Faking Mode Page 0x03 (Format Device)");
3194 data[0] = 5+22; // length
3195 data += 4;
3196 data[0] = 0x03; // mode page
3197 data[1] = 22; // page length
3198 data[10] = ncm->ncm_Geometry.dg_TrackSectors>>8;
3199 data[11] = ncm->ncm_Geometry.dg_TrackSectors;
3200 data[12] = ncm->ncm_Geometry.dg_SectorSize>>8;
3201 data[13] = ncm->ncm_Geometry.dg_SectorSize;
3202 scsicmd->scsi_Actual = 6+22;
3203 return(0);
3205 else if((modepage == 0x04) && (scsicmd->scsi_Length >= 6+22)) // Rigid Disk Geometry mode page
3207 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Simple SCSI: Faking Mode Page 0x04 (Rigid Disk Geometry)");
3208 data[0] = 5+22; // length
3209 data += 4;
3210 data[0] = 0x04; // mode page
3211 data[1] = 22; // page length
3212 data[2] = ncm->ncm_Geometry.dg_Cylinders>>16;
3213 data[3] = ncm->ncm_Geometry.dg_Cylinders>>8;
3214 data[4] = ncm->ncm_Geometry.dg_Cylinders;
3215 data[5] = ncm->ncm_Geometry.dg_Heads;
3216 scsicmd->scsi_Actual = 6+22;
3217 return(0);
3219 else if((modepage == 0x05) && (scsicmd->scsi_Length >= 6+30)) // Flexible Disk mode page
3221 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Simple SCSI: Faking Mode Page 0x05 (Flexible Disk)");
3222 data[0] = 5+30; // length
3223 data += 4;
3224 data[0] = 0x05; // mode page
3225 data[1] = 30; // page length
3226 data[4] = ncm->ncm_Geometry.dg_Heads;
3227 data[5] = ncm->ncm_Geometry.dg_TrackSectors;
3228 data[6] = ncm->ncm_Geometry.dg_SectorSize>>8;
3229 data[7] = ncm->ncm_Geometry.dg_SectorSize;
3230 data[8] = ncm->ncm_Geometry.dg_Cylinders>>8;
3231 data[9] = ncm->ncm_Geometry.dg_Cylinders;
3232 scsicmd->scsi_Actual = 6+30;
3233 return(0);
3235 // fall through
3238 case 0x51: // drive ready
3239 case SCSI_CD_READ_TOC:
3240 case SCSI_CD_PAUSE_RESUME:
3241 case SCSI_CD_PLAY_AUDIO_10:
3242 case SCSI_CD_PLAY_AUDIO_12:
3243 case SCSI_CD_PLAY_AUDIO_MSF:
3244 case SCSI_CD_PLAY_AUDIO_TRACK_INDEX:
3245 case SCSI_CD_PLAY_TRACK_RELATIVE_10:
3246 case SCSI_CD_PLAY_TRACK_RELATIVE_12:
3247 case SCSI_CD_BLANK:
3248 case SCSI_CD_CLOSE_TRACK:
3249 case SCSI_CD_GET_CONFIGURATION:
3250 case SCSI_CD_GET_EVENT_STATUS_NOTIFICATION:
3251 case SCSI_CD_GET_PERFORMANCE:
3252 case SCSI_CD_LOAD_UNLOAD_MEDIUM:
3253 case SCSI_DA_START_STOP_UNIT:
3254 case SCSI_CD_MECHANISM_STATUS:
3255 case SCSI_CD_PRE_FETCH:
3256 case SCSI_CD_PREVENT_ALLOW_MEDIUM_REMOVAL:
3257 case SCSI_CD_READ_HEADER:
3258 case SCSI_CD_READ_SUB_CHANNEL:
3259 if((scsicmd->scsi_Command[0] != SCSI_MODE_SENSE_6) &&
3260 ((ncm->ncm_DeviceType == PDT_WORM) || (ncm->ncm_DeviceType == PDT_CDROM)))
3262 // allows these CD rom commands even with SimpleSCSI enabled.
3263 break;
3266 default:
3268 UBYTE cmdstrbuf[16*3+2];
3270 GM_UNIQUENAME(nHexString)(scsicmd->scsi_Command, (ULONG) (scsicmd->scsi_CmdLength < 16 ? scsicmd->scsi_CmdLength : 16), cmdstrbuf);
3271 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Simple SCSI: Filtering SCSI command %s", cmdstrbuf);
3273 scsicmd->scsi_Status = SCSI_CHECK_CONDITION;
3274 scsicmd->scsi_SenseActual = 0;
3275 if(scsicmd->scsi_Flags & SCSIF_AUTOSENSE)
3277 if(scsicmd->scsi_SenseLength >= 18)
3279 memset(scsicmd->scsi_SenseData, 0x00, 18);
3280 scsicmd->scsi_SenseData[0] = 0x80|0x70;
3281 scsicmd->scsi_SenseData[2] = SK_ILLEGAL_REQUEST;
3282 scsicmd->scsi_SenseData[12] = 0x20; // unsupported command
3283 scsicmd->scsi_SenseActual = 18;
3286 return(-1);
3291 if((scsicmd->scsi_Command[0] == SCSI_TEST_UNIT_READY) && scsicmd->scsi_Length)
3293 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Bogus TEST_UNIT_READY data length set to 0.");
3294 scsicmd->scsi_Length = 0;
3297 if(pf & PFF_FAKE_INQUIRY)
3299 if(scsicmd->scsi_Command[0] == SCSI_INQUIRY)
3301 if(scsicmd->scsi_Length >= 36)
3303 UBYTE *data = (UBYTE *) scsicmd->scsi_Data;
3304 if(pf & PFF_DEBUG)
3306 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Faking Inquiry.");
3308 KPRINTF(10, ("Faking INQUIRY!\n"));
3309 psdGetAttrs(PGA_DEVICE, ncm->ncm_Device,
3310 DA_ProductName, &prodname,
3311 DA_Manufacturer, &vendname,
3312 TAG_END);
3313 memset(data, 0x00, (size_t) scsicmd->scsi_Length);
3314 data[1] = 0x80; // removable media
3315 data[2] = 0x02; // 0x03 would be ANSI X3.301:1997 (SPC).
3316 data[3] = 0x02; // Response data format = 2
3317 data[4] = 32; // additional length n-4
3318 CopyMem(vendname, &data[8], (ULONG) ((strlen(vendname) < 8) ? strlen(vendname) : 8));
3319 CopyMem(prodname, &data[16], (ULONG) ((strlen(prodname) < 16) ? strlen(prodname) : 16));
3320 scsicmd->scsi_CmdActual = scsicmd->scsi_CmdLength;
3321 scsicmd->scsi_Status = SCSI_GOOD;
3322 scsicmd->scsi_SenseActual = 0;
3323 return(0);
3325 return(-1);
3329 if(pf & PFF_FIX_INQ36)
3331 if((scsicmd->scsi_Command)[0] == SCSI_INQUIRY)
3333 if(scsicmd->scsi_Length > 36)
3335 if(pf & PFF_DEBUG)
3337 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Fixing Inquiry.");
3340 KPRINTF(10, ("Fixing INQUIRY!\n"));
3341 scsicmd->scsi_Length = 36;
3343 else if(scsicmd->scsi_Length < 36)
3345 if(pf & PFF_DEBUG)
3347 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3348 "Couldn't fix Inquiry < %ld.",
3349 scsicmd->scsi_Length);
3351 KPRINTF(10, ("Couldn't fix INQUIRY!\n"));
3356 if(xlate)
3358 scsicmd10 = *scsicmd;
3359 scsicmd10.scsi_Command = cmd12;
3360 scsicmd10.scsi_CmdLength = 10;
3361 memset(cmd12, 0x00, 12);
3362 switch(scsicmd->scsi_Command[0])
3364 case SCSI_DA_READ_6:
3365 case SCSI_DA_WRITE_6:
3366 case SCSI_DA_SEEK_6:
3367 cmd12[0] = scsicmd->scsi_Command[0] | 0x20;
3368 cmd12[1] = scsicmd->scsi_Command[1] & 0xe0;
3369 cmd12[3] = scsicmd->scsi_Command[1] & 0x1f;
3370 cmd12[4] = scsicmd->scsi_Command[2];
3371 cmd12[5] = scsicmd->scsi_Command[3];
3372 cmd12[8] = scsicmd->scsi_Command[4];
3373 cmd12[9] = scsicmd->scsi_Command[5];
3374 usecmd10 = TRUE;
3375 break;
3377 case SCSI_MODE_SELECT_6:
3378 cmd12[0] = SCSI_MODE_SELECT_10;
3379 cmd12[1] = scsicmd->scsi_Command[1];
3380 //cmd12[2] = scsicmd->scsi_Command[2]; // reserved
3381 //cmd12[3] = scsicmd->scsi_Command[3]; // reserved
3382 cmd12[7] = (scsicmd->scsi_Command[4]+4)>>8;
3383 cmd12[8] = scsicmd->scsi_Command[4]+4;
3384 cmd12[9] = scsicmd->scsi_Command[5];
3386 sensedata = psdAllocVec(scsicmd->scsi_Length+4);
3387 if(sensedata && (scsicmd->scsi_Length >= 4))
3389 buf = (UBYTE *) scsicmd->scsi_Data;
3390 sensedata[1] = *buf++;
3391 sensedata[2] = *buf++;
3392 sensedata[3] = *buf++;
3393 sensedata[7] = *buf++;
3395 scsicmd10.scsi_Length = scsicmd->scsi_Length+4;
3396 scsicmd10.scsi_Data = (UWORD *) sensedata;
3398 CopyMem(buf, &sensedata[8], scsicmd->scsi_Length-4);
3400 usecmd10 = TRUE;
3401 break;
3403 case SCSI_MODE_SENSE_6:
3404 cmd12[0] = SCSI_MODE_SENSE_10;
3405 cmd12[1] = scsicmd->scsi_Command[1] & 0xf7;
3406 cmd12[2] = scsicmd->scsi_Command[2];
3407 cmd12[3] = scsicmd->scsi_Command[3];
3408 // Workaround: Some devices are seriously broken and do not interpret
3409 // the upper byte of the allocation length field.
3410 // Hence they return 3 bytes instead of 259 bytes. For this special case,
3411 // we will simply truncate the size by four, to get back to a 255 byte
3412 // buffer.
3413 if((scsicmd->scsi_Command[4] > 251) && (scsicmd->scsi_Length == scsicmd->scsi_Command[4]))
3415 scsicmd->scsi_Command[4] -= 4;
3416 scsicmd->scsi_Length -= 4;
3418 cmd12[7] = (scsicmd->scsi_Command[4]+4)>>8;
3419 cmd12[8] = scsicmd->scsi_Command[4]+4;
3420 cmd12[9] = scsicmd->scsi_Command[5];
3421 sensedata = psdAllocVec(scsicmd->scsi_Length+4);
3422 if(sensedata)
3424 scsicmd10.scsi_Length = scsicmd->scsi_Length+4;
3425 scsicmd10.scsi_Data = (UWORD *) sensedata;
3427 usecmd10 = TRUE;
3428 break;
3432 if((ncm->ncm_CSType == MS_ATAPI_SUBCLASS) ||
3433 (ncm->ncm_CSType == MS_FDDATAPI_SUBCLASS) ||
3434 (ncm->ncm_CSType == MS_UFI_SUBCLASS))
3436 if(!usecmd10)
3438 scsicmd10 = *scsicmd;
3439 scsicmd10.scsi_Command = cmd12;
3440 memset(cmd12, 0x00, 12);
3441 CopyMem(scsicmd->scsi_Command, cmd12, (ULONG) scsicmd->scsi_CmdLength);
3442 usecmd10 = TRUE;
3444 scsicmd10.scsi_CmdLength = 12;
3445 if(ncm->ncm_CSType == MS_UFI_SUBCLASS)
3447 switch(cmd12[0])
3449 case SCSI_REQUEST_SENSE:
3450 cmd12[4] = 18; /* restrict UFI response to 18 bytes */
3451 scsicmd10.scsi_Flags &= ~SCSIF_AUTOSENSE;
3452 break;
3454 case SCSI_INQUIRY:
3455 KPRINTF(10, ("Disabling autosense for UFI!\n"));
3456 cmd12[4] = 36; /* restrict UFI response to 36 bytes */
3457 scsicmd10.scsi_Flags &= ~SCSIF_AUTOSENSE;
3458 break;
3460 case SCSI_MODE_SELECT_10:
3461 cmd12[7] = 0;
3462 cmd12[8] = 8;
3463 break;
3469 if(usecmd10)
3471 if(pf & PFF_DEBUG)
3473 UBYTE cmd1strbuf[16*3+2];
3474 UBYTE cmd2strbuf[16*3+2];
3476 GM_UNIQUENAME(nHexString)(scsicmd->scsi_Command, (ULONG) (scsicmd->scsi_CmdLength < 16 ? scsicmd->scsi_CmdLength : 16), cmd1strbuf);
3477 GM_UNIQUENAME(nHexString)(scsicmd10.scsi_Command, (ULONG) (scsicmd10.scsi_CmdLength < 16 ? scsicmd10.scsi_CmdLength : 16), cmd2strbuf);
3478 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3479 "Mode XLATE for %s -> %s", cmd1strbuf, cmd2strbuf);
3480 if(scsicmd->scsi_Length && (scsicmd10.scsi_Command[0] == SCSI_MODE_SELECT_10))
3482 GM_UNIQUENAME(nHexString)((UBYTE *) scsicmd->scsi_Data, (ULONG) (scsicmd->scsi_Length < 16 ? scsicmd->scsi_Length : 16), cmd1strbuf);
3483 GM_UNIQUENAME(nHexString)((UBYTE *) scsicmd10.scsi_Data, (ULONG) (scsicmd10.scsi_Length < 16 ? scsicmd10.scsi_Length : 16), cmd2strbuf);
3484 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3485 "Request: %s (%ld) -> %s (%ld)",
3486 cmd1strbuf, scsicmd->scsi_Length,
3487 cmd2strbuf, scsicmd10.scsi_Length);
3490 KPRINTF(20, ("Mode XLATE for cmd %lx\n", scsicmd->scsi_Command[0]));
3493 switch(ncm->ncm_TPType)
3495 case MS_PROTO_BULK:
3496 res = nScsiDirectBulk(ncm, usecmd10 ? &scsicmd10 : scsicmd);
3497 break;
3499 case MS_PROTO_CB:
3500 case MS_PROTO_CBI:
3501 res = nScsiDirectCBI(ncm, usecmd10 ? &scsicmd10 : scsicmd);
3502 break;
3504 default:
3505 return(-1);
3507 KPRINTF(20, ("Cmd done %ld\n", res));
3508 if(usecmd10)
3510 if(sensedata)
3512 scsicmd->scsi_Actual = 0;
3513 if(scsicmd10.scsi_Command[0] == SCSI_MODE_SENSE_10)
3515 UBYTE cmd1strbuf[16*3+2];
3516 UBYTE cmd2strbuf[16*3+2];
3518 if(scsicmd10.scsi_Actual >= 8)
3520 scsicmd->scsi_Actual = scsicmd10.scsi_Actual - 4;
3521 buf = (UBYTE *) scsicmd->scsi_Data;
3522 *buf++ = sensedata[1];
3523 *buf++ = sensedata[2];
3524 *buf++ = sensedata[3];
3525 *buf++ = sensedata[7];
3526 CopyMem(&sensedata[8], buf, (ULONG) scsicmd10.scsi_Actual - 8);
3527 if(pf & PFF_DEBUG)
3529 GM_UNIQUENAME(nHexString)((UBYTE *) scsicmd10.scsi_Data, scsicmd10.scsi_Actual < 16 ? scsicmd10.scsi_Actual : 16, cmd1strbuf);
3530 GM_UNIQUENAME(nHexString)((UBYTE *) scsicmd->scsi_Data, scsicmd->scsi_Actual < 16 ? scsicmd->scsi_Actual : 16, cmd2strbuf);
3531 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3532 "Response: %s (%ld) -> %s (%ld)",
3533 cmd1strbuf, scsicmd10.scsi_Actual,
3534 cmd2strbuf, scsicmd->scsi_Actual);
3538 psdFreeVec(sensedata);
3539 } else {
3540 scsicmd->scsi_Actual = scsicmd10.scsi_Actual;
3542 scsicmd->scsi_CmdActual = scsicmd10.scsi_CmdActual;
3543 scsicmd->scsi_Status = scsicmd10.scsi_Status;
3544 scsicmd->scsi_SenseActual = scsicmd10.scsi_SenseActual;
3547 pf = ncm->ncm_CDC->cdc_PatchFlags;
3548 if((res == HFERR_Phase) && (!(pf & PFF_NO_FALLBACK)) && (!(pf & PFF_SIMPLE_SCSI)))
3550 switch(scsicmd->scsi_Command[0])
3552 case SCSI_TEST_UNIT_READY:
3553 case SCSI_INQUIRY:
3554 //case SCSI_LOG_SELECT:
3555 //case SCSI_LOG_SENSE:
3556 case SCSI_REQUEST_SENSE:
3557 //case SCSI_MODE_SELECT_6:
3558 //case SCSI_MODE_SELECT_10:
3559 //case SCSI_MODE_SENSE_6:
3560 //case SCSI_MODE_SENSE_10:
3561 case SCSI_DA_READ_6:
3562 case SCSI_DA_READ_10:
3563 case SCSI_DA_READ_CAPACITY:
3564 case SCSI_DA_SEEK_6:
3565 case SCSI_DA_SEEK_10:
3566 case SCSI_DA_WRITE_6:
3567 case SCSI_DA_WRITE_10:
3568 break;
3570 default:
3571 ncm->ncm_CDC->cdc_PatchFlags |= PFF_SIMPLE_SCSI;
3572 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3573 "Fallback: Enabling Simple SCSI.");
3574 GM_UNIQUENAME(nStoreConfig)(ncm);
3575 break;
3579 if((!res) && ((scsicmd->scsi_Command)[0] == SCSI_DA_READ_CAPACITY) && (pf & PFF_FIX_CAPACITY) && (scsicmd->scsi_Length >= 8))
3581 ULONG *capacity = ((ULONG *) scsicmd->scsi_Data);
3582 *capacity = AROS_LONG2BE(AROS_BE2LONG(*capacity)-1);
3583 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3584 "Fix Capacity: Correcting number of blocks.");
3587 if(res && (scsicmd->scsi_Command[0] == SCSI_INQUIRY))
3589 if((!(ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_FALLBACK)) && (!(ncm->ncm_CDC->cdc_PatchFlags & PFF_FIX_INQ36)))
3591 ncm->ncm_CDC->cdc_PatchFlags |= PFF_FIX_INQ36;
3592 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3593 "Fallback: Enabling Trim Inquiry.");
3594 GM_UNIQUENAME(nStoreConfig)(ncm);
3596 else if((!(ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_FALLBACK)) && (!(ncm->ncm_CDC->cdc_PatchFlags & PFF_FAKE_INQUIRY)))
3598 ncm->ncm_CDC->cdc_PatchFlags |= PFF_FAKE_INQUIRY;
3599 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3600 "Fallback: Enabling Fake Inquiry.");
3601 GM_UNIQUENAME(nStoreConfig)(ncm);
3605 if((ncm->ncm_DeviceType == PDT_WORM) ||
3606 (ncm->ncm_DeviceType == PDT_CDROM))
3608 // cd roms are always write protected
3609 ncm->ncm_WriteProtect = TRUE;
3610 return(res);
3612 // don't try to obtain write protection, when there's no media inserted.
3613 if(!ncm->ncm_UnitReady)
3615 return(res);
3617 if((!res) && (scsicmd->scsi_Command[0] == SCSI_MODE_SENSE_6))
3619 if(((UBYTE *) scsicmd->scsi_Data)[2] & 0x80)
3621 if(!ncm->ncm_WriteProtect)
3623 if(pf & PFF_REM_SUPPORT)
3625 ncm->ncm_ChangeCount++;
3626 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
3628 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3629 "Diskchange: Sense6WriteProtect On (count = %ld)",
3630 ncm->ncm_ChangeCount);
3633 ncm->ncm_WriteProtect = TRUE;
3635 } else {
3636 if(ncm->ncm_WriteProtect)
3638 if(pf & PFF_REM_SUPPORT)
3640 ncm->ncm_ChangeCount++;
3641 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
3643 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3644 "Diskchange: Sense6WriteProtect Off (count = %ld)",
3645 ncm->ncm_ChangeCount);
3648 ncm->ncm_WriteProtect = FALSE;
3652 if((!res) && (scsicmd->scsi_Command[0] == SCSI_MODE_SENSE_10))
3654 if(((UBYTE *) scsicmd->scsi_Data)[3] & 0x80)
3656 if(!ncm->ncm_WriteProtect)
3658 if(pf & PFF_REM_SUPPORT)
3660 ncm->ncm_ChangeCount++;
3661 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
3663 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3664 "Diskchange: Sense10WriteProtect On (count = %ld)",
3665 ncm->ncm_ChangeCount);
3668 ncm->ncm_WriteProtect = TRUE;
3670 } else {
3671 if(ncm->ncm_WriteProtect)
3673 if(pf & PFF_REM_SUPPORT)
3675 ncm->ncm_ChangeCount++;
3676 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
3678 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3679 "Diskchange: Sense10WriteProtect Off (count = %ld)",
3680 ncm->ncm_ChangeCount);
3683 ncm->ncm_WriteProtect = FALSE;
3687 return(res);
3689 /* \\\ */
3691 /* /// "nScsiDirectBulk()" */
3692 LONG nScsiDirectBulk(struct NepClassMS *ncm, struct SCSICmd *scsicmd)
3694 LONG ioerr;
3695 struct PsdPipe *pp;
3696 struct UsbMSCmdBlkWrapper umscbw;
3697 struct UsbMSCmdStatusWrapper umscsw;
3698 ULONG datalen;
3699 LONG rioerr;
3700 UWORD retrycnt = 0;
3701 UBYTE cmdstrbuf[16*3+2];
3703 KPRINTF(10, ("\n"));
3705 GM_UNIQUENAME(nHexString)(scsicmd->scsi_Command, (ULONG) (scsicmd->scsi_CmdLength < 16 ? scsicmd->scsi_CmdLength : 16), cmdstrbuf);
3707 if(scsicmd->scsi_Flags & 0x80) /* Autoretry */
3709 retrycnt = 1;
3711 umscbw.dCBWSignature = AROS_LONG2LE(0x43425355);
3712 scsicmd->scsi_Status = SCSI_GOOD;
3713 nLockXFer(ncm);
3716 KPRINTF(10, ("retrycnt %ld\n",retrycnt));
3717 if(ncm->ncm_DenyRequests)
3719 rioerr = HFERR_Phase;
3720 break;
3722 /*nBulkReset(ncm);*/
3724 rioerr = 0;
3726 /*psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3727 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
3728 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);*/
3730 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DELAY_DATA)
3732 psdDelayMS(1);
3735 datalen = scsicmd->scsi_Length;
3736 umscbw.dCBWTag = (IPTR) scsicmd + ++ncm->ncm_TagCount;
3737 umscbw.dCBWDataTransferLength = AROS_LONG2LE(datalen);
3738 umscbw.bmCBWFlags = scsicmd->scsi_Flags & SCSIF_READ ? 0x80 : 0x00;
3739 umscbw.bCBWLUN = ncm->ncm_UnitLUN;
3740 if((scsicmd->scsi_CmdLength) >= 16)
3742 CopyMemQuick(scsicmd->scsi_Command, umscbw.CBWCB, 16);
3743 umscbw.bCBWCBLength = scsicmd->scsi_CmdActual = 16;
3744 } else {
3745 memset(umscbw.CBWCB, 0, 16);
3746 CopyMem(scsicmd->scsi_Command, umscbw.CBWCB, (ULONG) scsicmd->scsi_CmdLength);
3747 umscbw.bCBWCBLength = scsicmd->scsi_CmdActual = scsicmd->scsi_CmdLength;
3749 //psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Issueing command %s Dlen=%ld", cmdstrbuf, datalen);
3751 KPRINTF(2, ("command block phase, tag %08lx, len %ld, flags %02lx...\n",
3752 umscbw.dCBWTag, scsicmd->scsi_CmdLength, scsicmd->scsi_Flags));
3753 KPRINTF(2, ("command: %s\n", cmdstrbuf));
3754 ioerr = psdDoPipe(ncm->ncm_EPOutPipe, &umscbw, UMSCBW_SIZEOF);
3755 if(ioerr == UHIOERR_STALL) /* Retry on stall */
3757 KPRINTF(2, ("stall...\n"));
3758 nBulkClear(ncm);
3759 ioerr = psdDoPipe(ncm->ncm_EPOutPipe, &umscbw, UMSCBW_SIZEOF);
3761 if(ncm->ncm_DenyRequests)
3763 rioerr = HFERR_Phase;
3764 break;
3766 if(!ioerr)
3768 if(datalen)
3770 KPRINTF(2, ("data phase %ld bytes...\n", datalen));
3771 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DELAY_DATA)
3773 psdDelayMS(1);
3775 pp = (scsicmd->scsi_Flags & SCSIF_READ) ? ncm->ncm_EPInPipe : ncm->ncm_EPOutPipe;
3776 ioerr = psdDoPipe(pp, scsicmd->scsi_Data, datalen);
3777 scsicmd->scsi_Actual = psdGetPipeActual(pp);
3778 if(ioerr == UHIOERR_OVERFLOW)
3780 KPRINTF(10, ("Extra Data received, but ignored!\n"));
3781 ioerr = 0;
3783 else if(ioerr == UHIOERR_STALL) /* Accept on stall */
3785 KPRINTF(2, ("stall...\n"));
3786 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3787 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT,
3788 (ULONG) ((scsicmd->scsi_Flags & SCSIF_READ) ? ncm->ncm_EPInNum|URTF_IN : ncm->ncm_EPOutNum));
3789 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
3791 else if(ioerr == UHIOERR_RUNTPACKET)
3793 KPRINTF(10, ("Runt packet ignored...\n"));
3794 ioerr = 0;
3795 /*psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3796 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT,
3797 (ULONG) ncm->ncm_EPInNum|URTF_IN);
3798 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);*/
3800 } else {
3801 ioerr = 0;
3802 scsicmd->scsi_Actual = 0;
3804 if(!ioerr)
3806 KPRINTF(2, ("command status phase...\n"));
3807 ioerr = psdDoPipe(ncm->ncm_EPInPipe, &umscsw, UMSCSW_SIZEOF);
3808 if(ioerr == UHIOERR_STALL) /* Retry on stall */
3810 KPRINTF(2, ("stall...\n"));
3811 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3812 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
3813 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
3814 /*nBulkClear(ncm);*/
3815 ioerr = psdDoPipe(ncm->ncm_EPInPipe, &umscsw, UMSCSW_SIZEOF);
3817 if(ioerr == UHIOERR_RUNTPACKET)
3819 // well, retry then
3820 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3821 "Command status block truncated (%ld bytes), retrying...",
3822 psdGetPipeActual(ncm->ncm_EPInPipe));
3823 ioerr = psdDoPipe(ncm->ncm_EPInPipe, &umscsw, UMSCSW_SIZEOF);
3825 if(ioerr == UHIOERR_OVERFLOW)
3827 KPRINTF(10, ("Extra Status received, but ignored!\n"));
3828 ioerr = 0;
3830 if(ncm->ncm_DenyRequests)
3832 rioerr = HFERR_Phase;
3833 break;
3835 if(!ioerr)
3837 KPRINTF(2, ("Status:\n"
3838 " Signature: %08lx\n"
3839 " Tag : %08lx\n"
3840 " Residue : %08lx\n"
3841 " Status : %02lx\n",
3842 umscsw.dCSWSignature,
3843 umscsw.dCSWTag,
3844 umscsw.dCSWDataResidue,
3845 umscsw.bCSWStatus));
3846 if(((umscsw.dCSWSignature != AROS_LONG2LE(0x53425355)) && (!(ncm->ncm_CDC->cdc_PatchFlags & PFF_CSS_BROKEN))) || (umscsw.dCSWTag != umscbw.dCBWTag))
3848 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Command (%s) failed:", cmdstrbuf);
3849 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
3850 "Illegal command status block (Sig:%08lx, Tag=%08lx/%08lx (TX/RX), Len=%ld)",
3851 umscsw.dCSWSignature,
3852 umscbw.dCBWTag,
3853 umscsw.dCSWTag,
3854 psdGetPipeActual(ncm->ncm_EPInPipe));
3855 scsicmd->scsi_Status = SCSI_CHECK_CONDITION;
3856 rioerr = HFERR_Phase;
3857 nBulkReset(ncm);
3858 continue;
3860 /* ignore this: too many firmwares report shit */
3861 //scsicmd->scsi_Actual = datalen - AROS_LONG2LE(umscsw.dCSWDataResidue);
3862 if((scsicmd->scsi_Actual > 7) && ((AROS_LONG2BE(*((ULONG *) scsicmd->scsi_Data))>>8) == 0x555342) && (((ULONG *) scsicmd->scsi_Data)[1] == umscbw.dCBWTag))
3864 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
3865 "Your MSD has a very bad firmware! Havoc!");
3866 scsicmd->scsi_Actual = 0;
3867 umscsw.bCSWStatus = USMF_CSW_FAIL;
3869 scsicmd->scsi_Status = umscsw.bCSWStatus;
3870 if(umscsw.bCSWStatus)
3872 if(umscsw.bCSWStatus == USMF_CSW_PHASEERR)
3874 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Command (%s) failed: %ld", cmdstrbuf, umscsw.bCSWStatus);
3875 nBulkReset(ncm);
3877 /* Autosensing required? */
3878 if(scsicmd->scsi_Flags & SCSIF_AUTOSENSE)
3880 /*nBulkClear(ncm);*/
3882 datalen = scsicmd->scsi_SenseLength;
3883 umscbw.dCBWTag = (IPTR) scsicmd + ++ncm->ncm_TagCount;
3884 umscbw.dCBWDataTransferLength = AROS_LONG2LE(datalen);
3885 umscbw.bmCBWFlags = 0x80;
3886 /*umscbw.bCBWLUN = ncm->ncm_UnitLun;*/
3887 umscbw.bCBWCBLength = 6;
3888 umscbw.CBWCB[0] = SCSI_REQUEST_SENSE;
3889 umscbw.CBWCB[1] = 0x00;
3890 umscbw.CBWCB[2] = 0x00;
3891 umscbw.CBWCB[3] = 0x00;
3892 umscbw.CBWCB[4] = datalen;
3893 umscbw.CBWCB[5] = 0;
3894 KPRINTF(2, ("sense command block phase...\n"));
3895 ioerr = psdDoPipe(ncm->ncm_EPOutPipe, &umscbw, UMSCBW_SIZEOF);
3896 if(ioerr == UHIOERR_STALL) /* Retry on stall */
3898 KPRINTF(2, ("stall...\n"));
3899 nBulkClear(ncm);
3900 ioerr = psdDoPipe(ncm->ncm_EPOutPipe, &umscbw, UMSCBW_SIZEOF);
3902 if(!ioerr)
3904 KPRINTF(2, ("sense data phase %ld bytes...\n", datalen));
3905 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DELAY_DATA)
3907 psdDelayMS(1);
3909 ioerr = psdDoPipe(ncm->ncm_EPInPipe, scsicmd->scsi_SenseData, datalen);
3910 scsicmd->scsi_SenseActual = psdGetPipeActual(ncm->ncm_EPInPipe);
3911 if(ioerr == UHIOERR_STALL) /* Accept on stall */
3913 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3914 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
3915 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
3917 if((ioerr == UHIOERR_RUNTPACKET) || (ioerr == UHIOERR_OVERFLOW))
3919 KPRINTF(10, ("Extra or less data received, but ignored!\n"));
3920 ioerr = 0;
3923 if(!ioerr)
3925 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DELAY_DATA)
3927 psdDelayMS(1);
3929 KPRINTF(2, ("sense command status phase...\n"));
3930 ioerr = psdDoPipe(ncm->ncm_EPInPipe, &umscsw, UMSCSW_SIZEOF);
3931 if(ioerr == UHIOERR_STALL) /* Retry on stall */
3933 KPRINTF(2, ("stall...\n"));
3934 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
3935 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncm->ncm_EPInNum|URTF_IN);
3936 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
3937 ioerr |= psdDoPipe(ncm->ncm_EPInPipe, &umscsw, UMSCSW_SIZEOF);
3939 if(ioerr == UHIOERR_RUNTPACKET)
3941 // well, retry then
3942 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3943 "Command (sense) status block truncated (%ld bytes), retrying...",
3944 psdGetPipeActual(ncm->ncm_EPInPipe));
3945 ioerr = psdDoPipe(ncm->ncm_EPInPipe, &umscsw, UMSCSW_SIZEOF);
3948 if(ioerr == UHIOERR_OVERFLOW)
3950 KPRINTF(10, ("Extra Status received, but ignored!\n"));
3951 ioerr = 0;
3953 if(!ioerr)
3955 KPRINTF(2, ("sense Status:\n"
3956 " Signature: %08lx\n"
3957 " Tag : %08lx\n"
3958 " Residue : %08lx\n"
3959 " Status : %02lx\n",
3960 umscsw.dCSWSignature,
3961 umscsw.dCSWTag,
3962 umscsw.dCSWDataResidue,
3963 umscsw.bCSWStatus));
3964 if(((umscsw.dCSWSignature != AROS_LONG2LE(0x53425355)) && (!(ncm->ncm_CDC->cdc_PatchFlags & PFF_CSS_BROKEN))) || (umscsw.dCSWTag != umscbw.dCBWTag))
3966 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
3967 "Illegal command (sense) status block (Sig:%08lx, Tag=%08lx/%08lx (TX/RX), Len=%ld)",
3968 umscsw.dCSWSignature,
3969 umscbw.dCBWTag,
3970 umscsw.dCSWTag,
3971 psdGetPipeActual(ncm->ncm_EPInPipe));
3972 scsicmd->scsi_Status = SCSI_CHECK_CONDITION;
3973 rioerr = HFERR_Phase;
3974 nBulkReset(ncm);
3975 continue;
3977 /* ignore this: too many firmwares report shit */
3978 //scsicmd->scsi_SenseActual = datalen - AROS_LONG2LE(umscsw.dCSWDataResidue);
3979 if((scsicmd->scsi_SenseActual > 7) && ((AROS_LONG2BE(*((ULONG *) scsicmd->scsi_SenseData))>>8) == 0x555342) && (((ULONG *) scsicmd->scsi_SenseData)[1] == umscbw.dCBWTag))
3981 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
3982 "Your MSD has a very bad firmware! Havoc!");
3983 scsicmd->scsi_Actual = 0;
3984 umscsw.bCSWStatus = USMF_CSW_FAIL;
3987 if(umscsw.bCSWStatus)
3989 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3990 "Sense failed: %ld",
3991 umscsw.bCSWStatus);*/
3992 if(umscsw.bCSWStatus == USMF_CSW_PHASEERR)
3994 nBulkReset(ncm);
3996 } else {
3997 switch(scsicmd->scsi_SenseData[2] & SK_MASK)
3999 case SK_ILLEGAL_REQUEST:
4000 case SK_NOT_READY:
4001 retrycnt = 0;
4002 break;
4003 case SK_DATA_PROTECT:
4004 if(!ncm->ncm_WriteProtect)
4006 ncm->ncm_WriteProtect = TRUE;
4007 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
4009 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
4010 "WriteProtect On: Sense Data Protect");
4013 break;
4015 case SK_UNIT_ATTENTION:
4016 if((ncm->ncm_CDC->cdc_PatchFlags & PFF_REM_SUPPORT) &&
4017 ((scsicmd->scsi_SenseData[12] == 0x28) ||
4018 (scsicmd->scsi_SenseData[12] == 0x3A)))
4020 ncm->ncm_ChangeCount++;
4021 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
4023 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
4024 "Diskchange: Unit Attention (count = %ld)",
4025 ncm->ncm_ChangeCount);
4028 break;
4030 KPRINTF(10, ("Sense Key: %lx/%02lx/%02lx\n",
4031 scsicmd->scsi_SenseData[2] & SK_MASK,
4032 scsicmd->scsi_SenseData[12],
4033 scsicmd->scsi_SenseData[13]));
4034 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
4036 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
4037 "Cmd %s: Sense Key %lx/%02lx/%02lx",
4038 cmdstrbuf,
4039 scsicmd->scsi_SenseData[2] & SK_MASK,
4040 scsicmd->scsi_SenseData[12],
4041 scsicmd->scsi_SenseData[13]);
4044 } else {
4045 KPRINTF(10, ("Sense status failed: %s (%ld)\n", psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr));
4046 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Command (%s) okay, but:", cmdstrbuf);
4047 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
4048 "Sense status failed: %s (%ld)",
4049 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
4050 nBulkReset(ncm);
4052 } else {
4053 KPRINTF(10, ("Sense data failed: %s (%ld)\n", psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr));
4054 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Command (%s) okay, but:", cmdstrbuf);
4055 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
4056 "Sense data failed: %s (%ld)",
4057 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
4058 nBulkReset(ncm);
4060 } else {
4061 KPRINTF(10, ("Sense block failed: %s (%ld)\n", psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr));
4062 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Command (%s) okay, but:", cmdstrbuf);
4063 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
4064 "Sense block failed: %s (%ld)",
4065 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
4066 /*nBulkReset(ncm);*/
4069 rioerr = HFERR_BadStatus;
4071 } else {
4072 KPRINTF(10, ("Command status failed: %s (%ld)\n", psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr));
4073 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Command (%s) failed:", cmdstrbuf);
4074 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
4075 "Command status failed: %s (%ld)",
4076 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
4077 scsicmd->scsi_Status = SCSI_CHECK_CONDITION;
4078 rioerr = HFERR_Phase;
4079 nBulkReset(ncm);
4081 } else {
4082 KPRINTF(10, ("Data phase failed: %s (%ld)\n", psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr));
4083 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Command (%s) failed:", cmdstrbuf);
4084 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
4085 "Data phase failed: %s (%ld)",
4086 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
4087 scsicmd->scsi_Status = SCSI_CHECK_CONDITION;
4088 rioerr = HFERR_Phase;
4089 nBulkReset(ncm);
4091 } else {
4092 KPRINTF(10, ("Command block failed: %s (%ld)\n", psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr));
4093 scsicmd->scsi_Status = SCSI_CHECK_CONDITION;
4094 rioerr = HFERR_Phase;
4095 if(ioerr == UHIOERR_TIMEOUT)
4097 break;
4099 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Command (%s) failed:", cmdstrbuf);
4100 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
4101 "Command block failed: %s (%ld)",
4102 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
4103 nBulkReset(ncm);
4105 if(!rioerr)
4107 break;
4109 KPRINTF(1, ("Retrying...\n"));
4110 } while(retrycnt--);
4111 nUnlockXFer(ncm);
4112 return(rioerr);
4114 /* \\\ */
4116 /* /// "nScsiDirectCBI()" */
4117 LONG nScsiDirectCBI(struct NepClassMS *ncm, struct SCSICmd *scsicmd)
4119 LONG ioerr;
4120 struct PsdPipe *pp;
4121 struct PsdPipe *backpp;
4122 struct UsbMSCBIStatusWrapper umscsw;
4123 ULONG datalen;
4124 LONG rioerr;
4125 UWORD retrycnt = 0;
4126 UBYTE sensedata[18];
4127 UBYTE *senseptr;
4128 UBYTE asc;
4129 BOOL datadone;
4130 BOOL statusdone;
4131 UBYTE cmdstrbuf[16*3+2];
4133 GM_UNIQUENAME(nHexString)(scsicmd->scsi_Command, (ULONG) (scsicmd->scsi_CmdLength < 16 ? scsicmd->scsi_CmdLength : 16), cmdstrbuf);
4135 if(scsicmd->scsi_Flags & 0x80) /* Autoretry */
4137 retrycnt = 1;
4139 scsicmd->scsi_Status = SCSI_GOOD;
4140 nLockXFer(ncm);
4143 if(ncm->ncm_DenyRequests)
4145 rioerr = HFERR_Phase;
4146 break;
4148 rioerr = 0;
4149 datalen = scsicmd->scsi_Length;
4151 KPRINTF(2, ("command block phase, tag %08lx, len %ld, flags %02lx...\n",
4152 scsicmd, scsicmd->scsi_CmdLength, scsicmd->scsi_Flags));
4154 KPRINTF(2, ("command: %s\n", cmdstrbuf));
4156 //nBulkClear(ncm);
4157 scsicmd->scsi_CmdActual = scsicmd->scsi_CmdLength;
4158 /*if(datalen)
4160 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
4161 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT,
4162 (ULONG) ((scsicmd->scsi_Flags & SCSIF_READ) ? ncm->ncm_EPInNum|URTF_IN : ncm->ncm_EPOutNum));
4163 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
4165 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_CLASS|URTF_INTERFACE,
4166 UMSR_ADSC, 0, (ULONG) ncm->ncm_UnitIfNum);
4167 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, scsicmd->scsi_Command, (ULONG) scsicmd->scsi_CmdLength);
4169 if(ncm->ncm_DenyRequests)
4171 rioerr = HFERR_Phase;
4172 break;
4174 if(!ioerr)
4176 datadone = statusdone = FALSE;
4177 if(datalen)
4179 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_CLEAR_EP)
4181 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
4182 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT,
4183 (ULONG) ((scsicmd->scsi_Flags & SCSIF_READ) ? ncm->ncm_EPInNum|URTF_IN : ncm->ncm_EPOutNum));
4184 ioerr = psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
4187 KPRINTF(2, ("data phase %ld bytes...\n", datalen));
4188 pp = (scsicmd->scsi_Flags & SCSIF_READ) ? ncm->ncm_EPInPipe : ncm->ncm_EPOutPipe;
4190 if(ncm->ncm_TPType == MS_PROTO_CBI)
4192 /* okay, this is a major pain in the arse.
4193 we have to do this asynchroneously */
4194 umscsw.bType = 0;
4195 umscsw.bValue = USMF_CSW_PHASEERR;
4196 psdSendPipe(ncm->ncm_EPIntPipe, &umscsw, sizeof(struct UsbMSCBIStatusWrapper));
4197 psdSendPipe(pp, scsicmd->scsi_Data, datalen);
4200 WaitPort(ncm->ncm_TaskMsgPort);
4201 while((backpp = (struct PsdPipe *) GetMsg(ncm->ncm_TaskMsgPort)))
4203 if(backpp == pp)
4205 /* data transfer finished */
4206 datadone = TRUE;
4208 else if(backpp == ncm->ncm_EPIntPipe)
4210 /* status returned */
4211 statusdone = TRUE;
4214 } while(!statusdone);
4215 if(!datadone)
4217 psdAbortPipe(pp);
4218 psdWaitPipe(pp);
4219 ioerr = 0;
4220 } else {
4221 ioerr = psdGetPipeError(pp);
4224 } else {
4225 ioerr = psdDoPipe(pp, scsicmd->scsi_Data, datalen);
4228 scsicmd->scsi_Actual = psdGetPipeActual(pp);
4229 if(ioerr == UHIOERR_OVERFLOW)
4231 KPRINTF(10, ("Extra Data received, but ignored!\n"));
4232 ioerr = 0;
4234 if(ioerr == UHIOERR_STALL) /* Accept on stall */
4236 KPRINTF(2, ("stall...\n"));
4237 //nBulkClear(ncm);
4238 psdPipeSetup(ncm->ncm_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
4239 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT,
4240 (ULONG) ((scsicmd->scsi_Flags & SCSIF_READ) ? ncm->ncm_EPInNum|URTF_IN : ncm->ncm_EPOutNum));
4241 psdDoPipe(ncm->ncm_EP0Pipe, NULL, 0);
4242 ioerr = 0;
4244 } else {
4245 ioerr = 0;
4246 scsicmd->scsi_Actual = 0;
4248 if((!ioerr) || (ioerr == UHIOERR_RUNTPACKET))
4250 KPRINTF(2, ("command status phase...\n"));
4251 if(ncm->ncm_TPType == MS_PROTO_CBI)
4253 if(!statusdone)
4255 if(ncm->ncm_CSType == MS_UFI_SUBCLASS)
4257 umscsw.bType = 0x04;
4258 umscsw.bValue = 0;
4259 } else {
4260 umscsw.bType = 0;
4261 umscsw.bValue = USMF_CSW_PHASEERR;
4263 ioerr = psdDoPipe(ncm->ncm_EPIntPipe, &umscsw, sizeof(struct UsbMSCBIStatusWrapper));
4264 } else {
4265 ioerr = psdGetPipeError(ncm->ncm_EPIntPipe);
4267 umscsw.bValue &= 0x0f; /* mask out upper nibble */
4268 if(ioerr)
4270 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
4271 "Status interrupt failed: %s (%ld)",
4272 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
4273 nBulkReset(ncm);
4275 if(ncm->ncm_CSType == MS_UFI_SUBCLASS)
4277 asc = umscsw.bType;
4278 if((scsicmd->scsi_Command[0] == SCSI_REQUEST_SENSE) ||
4279 (scsicmd->scsi_Command[0] == SCSI_INQUIRY))
4281 umscsw.bType = 0;
4282 umscsw.bValue = USMF_CSW_PASS;
4283 } else {
4284 umscsw.bType = 0;
4285 umscsw.bValue = asc ? USMF_CSW_FAIL : USMF_CSW_PASS;
4286 if(umscsw.bValue)
4288 rioerr = HFERR_BadStatus;
4291 } else {
4292 umscsw.bValue &= USMF_CSW_PERSIST; /* mask out other bits */
4294 } else {
4295 umscsw.bType = 0;
4296 umscsw.bValue = USMF_CSW_PASS;
4297 ioerr = 0;
4299 if(ncm->ncm_DenyRequests)
4301 rioerr = HFERR_Phase;
4302 break;
4304 if((!ioerr) || (ioerr == UHIOERR_RUNTPACKET))
4306 scsicmd->scsi_Status = umscsw.bValue;
4307 if(umscsw.bValue == USMF_CSW_PHASEERR)
4309 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
4310 "Command (%s) phase error: %ld",
4311 cmdstrbuf,
4312 umscsw.bValue);
4313 nBulkReset(ncm);
4315 else if(umscsw.bValue == USMF_CSW_PERSIST)
4317 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
4318 "Command (%s) persistant error: %ld",
4319 cmdstrbuf,
4320 umscsw.bValue);
4321 nBulkReset(ncm);
4324 /* Autosensing required? */
4325 if(((umscsw.bValue && (scsicmd->scsi_Flags & SCSIF_AUTOSENSE))) ||
4326 (ncm->ncm_TPType == MS_PROTO_CB) || (ncm->ncm_TPType == MS_PROTO_CBI))
4328 if(scsicmd->scsi_Flags & SCSIF_AUTOSENSE)
4330 datalen = scsicmd->scsi_SenseLength;
4331 senseptr = scsicmd->scsi_SenseData;
4332 } else {
4333 datalen = 18;
4334 senseptr = sensedata;
4336 if(!(scsicmd->scsi_SenseActual = nCBIRequestSense(ncm, senseptr, datalen)))
4338 nBulkReset(ncm);
4340 if(senseptr[2] & SK_MASK)
4342 rioerr = HFERR_BadStatus;
4343 scsicmd->scsi_Status = SCSI_CHECK_CONDITION;
4346 } else {
4347 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
4348 "Command status failed: %s (%ld)",
4349 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
4350 scsicmd->scsi_Status = SCSI_CHECK_CONDITION;
4351 rioerr = HFERR_Phase;
4352 nBulkReset(ncm);
4354 } else {
4355 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
4356 "Data phase failed: %s (%ld)",
4357 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
4358 scsicmd->scsi_Status = SCSI_CHECK_CONDITION;
4359 rioerr = HFERR_Phase;
4360 nBulkClear(ncm);
4362 } else {
4363 scsicmd->scsi_Status = SCSI_CHECK_CONDITION;
4364 rioerr = HFERR_Phase;
4365 if(ioerr == UHIOERR_TIMEOUT)
4367 break;
4369 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
4371 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Command (%s) failed:", cmdstrbuf);
4372 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
4373 "Command block failed: %s (%ld)",
4374 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
4376 if(scsicmd->scsi_Flags & SCSIF_AUTOSENSE)
4378 datalen = scsicmd->scsi_SenseLength;
4379 senseptr = scsicmd->scsi_SenseData;
4380 } else {
4381 datalen = 18;
4382 senseptr = sensedata;
4384 if(!(scsicmd->scsi_SenseActual = nCBIRequestSense(ncm, senseptr, datalen)))
4386 nBulkReset(ncm);
4387 retrycnt = 0;
4388 } else {
4389 if(senseptr[2] & SK_MASK)
4391 rioerr = HFERR_BadStatus;
4392 if((senseptr[2] & SK_MASK) == SK_NOT_READY)
4394 retrycnt = 0;
4399 if(!rioerr)
4401 break;
4403 KPRINTF(1, ("Retrying...\n"));
4404 } while(retrycnt--);
4405 nUnlockXFer(ncm);
4406 return(rioerr);
4408 /* \\\ */
4410 /* /// "nLockXFer()" */
4411 void nLockXFer(struct NepClassMS *ncm)
4413 if(ncm->ncm_MaxLUN)
4415 KPRINTF(1, ("PING(lock)\n"));
4416 ObtainSemaphore(&ncm->ncm_UnitLUN0->ncm_XFerLock);
4417 KPRINTF(1, ("PONG(lock)\n"));
4420 /* \\\ */
4422 /* /// "nUnlockXFer()" */
4423 void nUnlockXFer(struct NepClassMS *ncm)
4425 if(ncm->ncm_MaxLUN)
4427 KPRINTF(1, ("PING(unlock)\n"));
4428 ReleaseSemaphore(&ncm->ncm_UnitLUN0->ncm_XFerLock);
4429 KPRINTF(1, ("PONG(unlock)\n"));
4432 /* \\\ */
4434 /* /// "nStoreConfig()" */
4435 BOOL GM_UNIQUENAME(nStoreConfig)(struct NepClassMS *ncm)
4437 APTR pic;
4438 struct NepClassMS *cncm;
4439 if(ncm->ncm_Interface)
4441 pic = psdGetUsbDevCfg(GM_UNIQUENAME(libname), ncm->ncm_DevIDString, ncm->ncm_IfIDString);
4442 if(!pic)
4444 psdSetUsbDevCfg(GM_UNIQUENAME(libname), ncm->ncm_DevIDString, ncm->ncm_IfIDString, NULL);
4445 pic = psdGetUsbDevCfg(GM_UNIQUENAME(libname), ncm->ncm_DevIDString, ncm->ncm_IfIDString);
4447 if(pic)
4449 psdAddCfgEntry(pic, ncm->ncm_CDC);
4450 cncm = ncm;
4451 while(((struct Node *) cncm)->ln_Succ)
4453 if(cncm->ncm_UnitLUN0 != ncm)
4455 break;
4457 psdAddCfgEntry(pic, cncm->ncm_CUC);
4458 cncm = (struct NepClassMS *) ((struct Node *) cncm)->ln_Succ;
4460 return(TRUE);
4462 } else {
4463 return(TRUE);
4465 return(FALSE);
4467 /* \\\ */
4469 /* ********************************************************************* */
4471 /* /// "BSTR Macros" */
4472 #ifdef __AROS__
4474 #define b2cstr(bstr, cstr)\
4477 UWORD _i = 0;\
4478 UWORD _len = AROS_BSTR_strlen(bstr);\
4479 while(_i < _len)\
4481 cstr[_i] = AROS_BSTR_getchar(bstr, _i);\
4482 _i++;\
4484 cstr[_i] = '\0';\
4485 } while(0)
4487 #define c2bstr(cstr, bstr)\
4490 UWORD _i = 0;\
4491 while(cstr[_i] != '\0')\
4493 AROS_BSTR_putchar(bstr, _i, cstr[_i]);\
4494 _i++;\
4496 AROS_BSTR_setstrlen(bstr, _i);\
4497 } while(0)
4498 #else
4500 #define b2cstr(bstr, cstr) { ULONG i; for (i = 0; i < bstr[0]; i++) cstr[i] = bstr[i + 1]; cstr[i] = 0x00; }
4502 #define c2bstr(cstr, bstr)\
4505 int i = 0;\
4506 UBYTE c;\
4507 STRPTR cp = (STRPTR) (cstr);\
4508 STRPTR bp = (STRPTR) (bstr);\
4509 while((c = cp[i]))\
4511 bp[++i] = c;\
4513 bp[0] = i;\
4514 } while(0)
4516 #endif
4517 /* \\\ */
4519 #undef ps
4520 #define ps nh->nh_PsdBase
4522 /* /// "nRemovableTask()" */
4523 AROS_UFH0(void, GM_UNIQUENAME(nRemovableTask))
4525 AROS_USERFUNC_INIT
4527 struct NepMSBase *nh;
4528 struct NepClassMS *ncm;
4529 ULONG sigmask;
4530 ULONG sigs;
4531 LONG ioerr;
4532 struct SCSICmd scsicmd;
4533 UBYTE cmd6[6];
4534 UBYTE sensedata[18];
4535 struct IOStdReq *ioreq;
4536 BOOL dontquit = TRUE;
4538 if((nh = GM_UNIQUENAME(nAllocRT)()))
4540 Forbid();
4541 if(nh->nh_ReadySigTask)
4543 Signal(nh->nh_ReadySigTask, 1L<<nh->nh_ReadySignal);
4545 Permit();
4546 /* Main task */
4547 sigmask = (1L<<nh->nh_TimerMsgPort->mp_SigBit)|
4548 SIGBREAKF_CTRL_C;
4551 while((ioreq = (struct IOStdReq *) GetMsg(nh->nh_TimerMsgPort)))
4553 dontquit = FALSE;
4554 KPRINTF(2, ("Timer interrupt\n"));
4555 ncm = (struct NepClassMS *) nh->nh_Units.lh_Head;
4556 while(ncm->ncm_Unit.unit_MsgPort.mp_Node.ln_Succ)
4558 if(ncm->ncm_Task && (!ncm->ncm_DenyRequests))
4560 dontquit = TRUE;
4562 if(ncm->ncm_Removable && ncm->ncm_Running)
4564 scsicmd.scsi_Data = NULL;
4565 scsicmd.scsi_Length = 0;
4566 scsicmd.scsi_Command = cmd6;
4567 scsicmd.scsi_CmdLength = 6;
4568 scsicmd.scsi_Flags = SCSIF_READ|SCSIF_AUTOSENSE|0x80;
4569 scsicmd.scsi_SenseData = sensedata;
4570 scsicmd.scsi_SenseLength = 18;
4571 cmd6[0] = SCSI_TEST_UNIT_READY;
4572 cmd6[1] = 0;
4573 cmd6[2] = 0;
4574 cmd6[3] = 0;
4575 cmd6[4] = 0;
4576 cmd6[5] = 0;
4577 if((ioerr = nScsiDirectTunnel(ncm, &scsicmd)))
4579 KPRINTF(1, ("Test unit ready yielded: %ld/%ld\n", sensedata[2], sensedata[12]));
4580 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
4581 "SCSI_TEST_UNIT_READY failed: %ld",
4582 ioerr);*/
4583 /* Check for MEDIUM NOT PRESENT */
4584 if(((sensedata[2] & SK_MASK) == SK_NOT_READY) &&
4585 ((sensedata[12] == 0x3a) || (sensedata[12] == 0x04)))
4587 if(ncm->ncm_UnitReady)
4589 ncm->ncm_UnitReady = FALSE;
4590 ncm->ncm_ChangeCount++;
4591 KPRINTF(10, ("Diskchange: Medium removed (count = %ld)!\n", ncm->ncm_ChangeCount));
4592 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
4594 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
4595 "Diskchange: Medium removed (count = %ld)",
4596 ncm->ncm_ChangeCount);
4600 } else {
4601 if(!ncm->ncm_UnitReady)
4603 ncm->ncm_UnitReady = TRUE;
4604 ncm->ncm_ChangeCount++;
4605 KPRINTF(10, ("Diskchange: Medium inserted (count = %ld)!\n", ncm->ncm_ChangeCount));
4606 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
4608 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
4609 "Diskchange: Medium inserted (count = %ld)",
4610 ncm->ncm_ChangeCount);
4612 if(ncm->ncm_CSType == MS_UFI_SUBCLASS)
4614 nh->nh_IOReq.io_Command = CMD_START;
4615 nIOCmdTunnel(ncm, &nh->nh_IOReq);
4617 } else {
4618 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_REM_SUPPORT)
4620 nGetWriteProtect(ncm);
4625 if(ncm->ncm_LastChange != ncm->ncm_ChangeCount)
4627 if(ncm->ncm_UnitReady)
4629 nGetWriteProtect(ncm);
4630 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_REM_SUPPORT)
4632 nh->nh_IOReq.io_Command = TD_GETGEOMETRY;
4633 nh->nh_IOReq.io_Data = &ncm->ncm_Geometry;
4634 nh->nh_IOReq.io_Length = sizeof(ncm->ncm_Geometry);
4635 nIOCmdTunnel(ncm, &nh->nh_IOReq);
4638 ioreq = (struct IOStdReq *) ncm->ncm_DCInts.lh_Head;
4639 while(((struct Node *) ioreq)->ln_Succ)
4641 Cause(ioreq->io_Data);
4642 ioreq = (struct IOStdReq *) ((struct Node *) ioreq)->ln_Succ;
4644 if(ncm->ncm_UnitReady)
4646 // obtain blocksize first
4647 if(!ncm->ncm_BlockSize)
4649 nh->nh_IOReq.io_Command = TD_GETGEOMETRY;
4650 nh->nh_IOReq.io_Data = &ncm->ncm_Geometry;
4651 nh->nh_IOReq.io_Length = sizeof(ncm->ncm_Geometry);
4652 nIOCmdTunnel(ncm, &nh->nh_IOReq);
4654 ncm->ncm_HasMounted = TRUE;
4656 // find and mount partitions
4657 if(!CheckPartitions(ncm) && ncm->ncm_CUC->cuc_AutoMountFAT)
4659 // check for FAT volume with no partition table
4660 CheckFATPartition(ncm, 0);
4662 if((ncm->ncm_BlockSize == 2048) &&
4663 ((ncm->ncm_DeviceType == PDT_WORM) || (ncm->ncm_DeviceType == PDT_CDROM)))
4665 if(ncm->ncm_CUC->cuc_AutoMountCD)
4667 CheckISO9660(ncm);
4671 ncm->ncm_LastChange = ncm->ncm_ChangeCount;
4673 } else {
4674 if(ncm->ncm_DenyRequests && ncm->ncm_CUC->cuc_AutoUnmount && ncm->ncm_HasMounted)
4676 nUnmountPartition(ncm);
4677 ncm->ncm_HasMounted = FALSE;
4680 ncm = (struct NepClassMS *) ncm->ncm_Unit.unit_MsgPort.mp_Node.ln_Succ;
4682 nh->nh_TimerIOReq->tr_time.tv_secs = 3;
4683 nh->nh_TimerIOReq->tr_time.tv_micro = 0;
4684 SendIO((struct IORequest *) nh->nh_TimerIOReq);
4687 if(nh->nh_RemovableTask->tc_Node.ln_Type == NT_TASK)
4689 APTR doslib;
4690 if((doslib = OpenLibrary("dos.library", 39)))
4692 CloseLibrary(doslib);
4693 // increase disk change count to force mounting
4694 ncm = (struct NepClassMS *) nh->nh_Units.lh_Head;
4695 while(ncm->ncm_Unit.unit_MsgPort.mp_Node.ln_Succ)
4697 ncm->ncm_ChangeCount++;
4698 ncm->ncm_ForceRTCheck = TRUE;
4699 ncm = (struct NepClassMS *) ncm->ncm_Unit.unit_MsgPort.mp_Node.ln_Succ;
4702 /* restart task */
4703 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
4704 "DOS found, stopping removable task...");
4705 nh->nh_RestartIt = TRUE;
4706 break;
4708 // don't quit task, otherwise nobody will be there to restart it and retry mounting stuff
4709 dontquit = TRUE;
4712 if(!dontquit)
4714 break;
4716 sigs = Wait(sigmask);
4717 } while(!(sigs & SIGBREAKF_CTRL_C));
4718 ncm = (struct NepClassMS *) nh->nh_Units.lh_Head;
4719 while(ncm->ncm_Unit.unit_MsgPort.mp_Node.ln_Succ)
4721 if(ncm->ncm_DenyRequests && ncm->ncm_CUC->cuc_AutoUnmount && ncm->ncm_HasMounted)
4723 nUnmountPartition(ncm);
4724 ncm->ncm_HasMounted = FALSE;
4726 ncm = (struct NepClassMS *) ncm->ncm_Unit.unit_MsgPort.mp_Node.ln_Succ;
4728 KPRINTF(20, ("Going down the river!\n"));
4729 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Removable Task stopped.");
4730 GM_UNIQUENAME(nFreeRT)(nh);
4732 AROS_USERFUNC_EXIT
4734 /* \\\ */
4736 /* /// "nAllocRT()" */
4737 struct NepMSBase * GM_UNIQUENAME(nAllocRT)(void)
4739 struct Task *thistask;
4740 struct NepMSBase *nh;
4742 thistask = FindTask(NULL);
4743 nh = thistask->tc_UserData;
4744 #undef ExpansionBase
4745 #define ExpansionBase nh->nh_ExpansionBase
4746 #undef PartitionBase
4747 #define PartitionBase nh->nh_PartitionBase
4750 if(!(ExpansionBase = OpenLibrary("expansion.library", 37)))
4752 Alert(AG_OpenLib | AO_ExpansionLib);
4753 break;
4755 if(!(PartitionBase = OpenLibrary("partition.library", 1)))
4757 Alert(AG_OpenLib | AO_Unknown);
4758 break;
4760 if(!(ps = OpenLibrary("poseidon.library", 4)))
4762 Alert(AG_OpenLib | AO_Unknown);
4763 break;
4765 if(!(nh->nh_IOMsgPort = CreateMsgPort()))
4767 break;
4769 nh->nh_IOReq.io_Message.mn_ReplyPort = nh->nh_IOMsgPort;
4770 if(!(nh->nh_TimerMsgPort = CreateMsgPort()))
4772 break;
4774 if(!(nh->nh_TimerIOReq = (struct timerequest *) CreateIORequest(nh->nh_TimerMsgPort, sizeof(struct timerequest))))
4776 break;
4778 if(OpenDevice("timer.device", UNIT_VBLANK, (struct IORequest *) nh->nh_TimerIOReq, 0))
4780 break;
4782 /* Start removable interrupt */
4783 nh->nh_TimerIOReq->tr_node.io_Command = TR_ADDREQUEST;
4784 nh->nh_TimerIOReq->tr_time.tv_secs = 0;
4785 nh->nh_TimerIOReq->tr_time.tv_micro = 50;
4786 SendIO((struct IORequest *) nh->nh_TimerIOReq);
4787 nh->nh_RemovableTask = thistask;
4788 return(nh);
4789 } while(FALSE);
4790 if(ExpansionBase)
4792 CloseLibrary(ExpansionBase);
4793 ExpansionBase = NULL;
4795 if(PartitionBase)
4797 CloseLibrary(PartitionBase);
4798 PartitionBase = NULL;
4800 if(ps)
4802 CloseLibrary(ps);
4803 ps = NULL;
4806 if(nh->nh_TimerIOReq)
4808 if(nh->nh_TimerIOReq->tr_node.io_Device)
4810 CloseDevice((struct IORequest *) nh->nh_TimerIOReq);
4812 DeleteIORequest((struct IORequest *) nh->nh_TimerIOReq);
4813 nh->nh_TimerIOReq = NULL;
4815 if(nh->nh_TimerMsgPort)
4817 DeleteMsgPort(nh->nh_TimerMsgPort);
4818 nh->nh_TimerMsgPort = NULL;
4820 if(nh->nh_IOMsgPort)
4822 DeleteMsgPort(nh->nh_IOMsgPort);
4823 nh->nh_IOMsgPort = NULL;
4825 Forbid();
4826 nh->nh_RemovableTask = NULL;
4827 if(nh->nh_ReadySigTask)
4829 Signal(nh->nh_ReadySigTask, 1L<<nh->nh_ReadySignal);
4831 return(NULL);
4833 /* \\\ */
4835 /* /// "nFreeRT()" */
4836 void GM_UNIQUENAME(nFreeRT)(struct NepMSBase *nh)
4839 psdFreeVec(nh->nh_OneBlock);
4840 nh->nh_OneBlock = NULL;
4841 nh->nh_OneBlockSize = 0;
4843 if(nh->nh_DOSBase)
4845 CloseLibrary(nh->nh_DOSBase);
4846 nh->nh_DOSBase = NULL;
4848 CloseLibrary(ExpansionBase);
4849 ExpansionBase = NULL;
4850 CloseLibrary(PartitionBase);
4851 PartitionBase = NULL;
4852 CloseLibrary(ps);
4853 ps = NULL;
4855 AbortIO((struct IORequest *) nh->nh_TimerIOReq);
4856 WaitIO((struct IORequest *) nh->nh_TimerIOReq);
4857 CloseDevice((struct IORequest *) nh->nh_TimerIOReq);
4858 DeleteIORequest((struct IORequest *) nh->nh_TimerIOReq);
4859 DeleteMsgPort(nh->nh_TimerMsgPort);
4860 nh->nh_TimerMsgPort = NULL;
4861 nh->nh_TimerIOReq = NULL;
4863 Forbid();
4864 nh->nh_RemovableTask = NULL;
4865 if(nh->nh_ReadySigTask)
4867 Signal(nh->nh_ReadySigTask, 1L<<nh->nh_ReadySignal);
4869 if(nh->nh_RestartIt)
4871 // wake up every task to relaunch removable task
4872 struct NepClassMS *ncm;
4873 ncm = (struct NepClassMS *) nh->nh_Units.lh_Head;
4874 while(ncm->ncm_Unit.unit_MsgPort.mp_Node.ln_Succ)
4876 if(ncm->ncm_Task)
4878 Signal(ncm->ncm_Task, 1L<<ncm->ncm_TaskMsgPort->mp_SigBit);
4880 ncm = (struct NepClassMS *) ncm->ncm_Unit.unit_MsgPort.mp_Node.ln_Succ;
4882 nh->nh_RestartIt = FALSE;
4885 /* \\\ */
4887 /* /// "GM_UNIQUENAME(nOpenDOS)()" */
4888 BOOL GM_UNIQUENAME(nOpenDOS)(struct NepMSBase *nh)
4890 if(nh->nh_DOSBase)
4892 return(TRUE);
4894 if(nh->nh_RemovableTask->tc_Node.ln_Type != NT_PROCESS)
4896 return(FALSE);
4898 if((nh->nh_DOSBase = OpenLibrary("dos.library", 39)))
4900 KPRINTF(10, ("Opened dos.library!\n"));
4901 return(TRUE);
4903 return(FALSE);
4905 /* \\\ */
4907 #undef DOSBase
4908 #define DOSBase nh->nh_DOSBase
4910 /* /// "nUnmountPartition()" */
4911 void nUnmountPartition(struct NepClassMS *ncm)
4913 struct NepMSBase *nh = ncm->ncm_ClsBase;
4914 struct DosList *list;
4915 struct DeviceNode *node;
4916 struct DeviceNode *oldnode = NULL;
4917 char partname[32];
4918 UBYTE *bstr;
4920 if(!GM_UNIQUENAME(nOpenDOS)(nh))
4922 return;
4924 while((node = FindMatchingDevice(ncm, NULL)))
4926 if(oldnode == node)
4928 break;
4930 bstr = (UBYTE *) BADDR(node->dn_Name);
4931 b2cstr(bstr, partname);
4932 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
4933 "Unmounting partition %s...",
4934 partname);
4935 DoPkt(node->dn_Task, ACTION_INHIBIT, TRUE, 0, 0, 0, 0);
4936 DoPkt(node->dn_Task, ACTION_DIE, 0, 0, 0, 0, 0);
4937 if((list = LockDosList(LDF_DEVICES | LDF_WRITE)))
4939 list = FindDosEntry(list, partname, LDF_DEVICES);
4940 if(list)
4942 RemDosEntry(list);
4944 UnLockDosList(LDF_DEVICES | LDF_WRITE);
4946 /*psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
4947 "Unmounting %s done.",
4948 partname);*/
4949 oldnode = node;
4952 /* \\\ */
4954 /* /// "nIOCmdTunnel()" */
4955 LONG nIOCmdTunnel(struct NepClassMS *ncm, struct IOStdReq *ioreq)
4957 struct NepMSBase *nh = ncm->ncm_ClsBase;
4958 Forbid();
4959 if(ncm->ncm_DenyRequests)
4961 Permit();
4962 return(ioreq->io_Error = IOERR_ABORTED);
4964 PutMsg(&ncm->ncm_Unit.unit_MsgPort, (struct Message *) ioreq);
4965 Permit();
4966 while(!GetMsg(nh->nh_IOMsgPort))
4968 WaitPort(nh->nh_IOMsgPort);
4970 return(ioreq->io_Error);
4972 /* \\\ */
4974 /* /// "nScsiDirectTunnel()" */
4975 LONG nScsiDirectTunnel(struct NepClassMS *ncm, struct SCSICmd *scsicmd)
4977 struct NepMSBase *nh = ncm->ncm_ClsBase;
4978 struct IOStdReq *ioreq = &nh->nh_IOReq;
4979 ioreq->io_Command = HD_SCSICMD;
4980 ioreq->io_Data = scsicmd;
4981 ioreq->io_Length = sizeof(*scsicmd);
4982 return(nIOCmdTunnel(ncm, ioreq));
4984 /* \\\ */
4986 /* /// "nGetWriteProtect()" */
4987 LONG nGetWriteProtect(struct NepClassMS *ncm)
4989 struct NepMSBase *nh = ncm->ncm_ClsBase;
4990 UBYTE cmd10[10];
4991 struct SCSICmd scsicmd;
4992 UBYTE inquirydata[256];
4993 UBYTE sensedata[18];
4994 LONG ioerr;
4996 if((ncm->ncm_DeviceType == PDT_WORM) ||
4997 (ncm->ncm_DeviceType == PDT_CDROM))
4999 // cd roms are always write protected
5000 return(ncm->ncm_WriteProtect = TRUE);
5002 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_SIMPLE_SCSI)
5004 return(ncm->ncm_WriteProtect = FALSE);
5006 scsicmd.scsi_Data = (UWORD *) inquirydata;
5007 scsicmd.scsi_Length = 8;
5008 scsicmd.scsi_Command = cmd10;
5009 scsicmd.scsi_CmdLength = 10;
5010 scsicmd.scsi_Flags = SCSIF_READ|SCSIF_AUTOSENSE|0x80;
5011 scsicmd.scsi_SenseData = sensedata;
5012 scsicmd.scsi_SenseLength = 18;
5013 cmd10[0] = SCSI_MODE_SENSE_10;
5014 cmd10[1] = 0x00; /* no block descriptors */
5015 cmd10[2] = 0x3f; /* no page, only header */
5016 cmd10[3] = 0;
5017 cmd10[4] = 0;
5018 cmd10[5] = 0;
5019 cmd10[6] = 0;
5020 cmd10[7] = 0;
5021 cmd10[8] = 8;
5022 cmd10[9] = 0;
5023 if((ioerr = nScsiDirectTunnel(ncm, &scsicmd)))
5025 cmd10[2] = 0x00; /* try again with vendor page, only header */
5026 if((ioerr = nScsiDirectTunnel(ncm, &scsicmd)))
5028 cmd10[2] = 0x3f; /* try again with 255 length */
5029 cmd10[8] = 0xff;
5030 if((ioerr = nScsiDirectTunnel(ncm, &scsicmd)))
5032 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
5034 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
5035 "Failed to get write protection state: %ld",
5036 ioerr);
5038 if(!(ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_FALLBACK))
5040 ncm->ncm_CDC->cdc_PatchFlags |= PFF_SIMPLE_SCSI;
5041 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
5042 "Fallback: Enabling Simple SCSI.");
5044 GM_UNIQUENAME(nStoreConfig)(ncm);
5045 return(0);
5049 if(inquirydata[3] & 0x80)
5051 if(!ncm->ncm_WriteProtect)
5053 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_REM_SUPPORT)
5055 ncm->ncm_ChangeCount++;
5056 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
5058 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
5059 "Diskchange: GetWriteProtect On (count = %ld)",
5060 ncm->ncm_ChangeCount);
5063 ncm->ncm_WriteProtect = TRUE;
5065 } else {
5066 if(ncm->ncm_WriteProtect)
5068 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_REM_SUPPORT)
5070 ncm->ncm_ChangeCount++;
5071 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
5073 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
5074 "Diskchange: GetWriteProtect Off (count = %ld)",
5075 ncm->ncm_ChangeCount);
5078 ncm->ncm_WriteProtect = FALSE;
5081 return(ncm->ncm_WriteProtect);
5083 /* \\\ */
5085 /* /// "SearchHardBlock()" */
5086 APTR SearchHardBlock(struct NepClassMS *ncm,
5087 struct IOStdReq *ioreq,
5088 ULONG id,
5089 ULONG start)
5091 struct NepMSBase *nh = ncm->ncm_ClsBase;
5092 ULONG curBlock;
5094 if(!nh->nh_OneBlock || (nh->nh_OneBlockSize < ncm->ncm_BlockSize))
5096 psdFreeVec(nh->nh_OneBlock);
5097 if(!(nh->nh_OneBlock = psdAllocVec(ncm->ncm_BlockSize)))
5099 return(NULL);
5101 nh->nh_OneBlockSize = ncm->ncm_BlockSize;
5104 curBlock = start;
5107 ioreq->io_Command = TD_READ64;
5108 ioreq->io_Data = nh->nh_OneBlock;
5109 ioreq->io_Length = ncm->ncm_BlockSize;
5110 ioreq->io_Offset = curBlock<<ncm->ncm_BlockShift;
5111 ioreq->io_Actual = curBlock>>(32-ncm->ncm_BlockShift);
5113 if(!nIOCmdTunnel(ncm, ioreq))
5115 curBlock++;
5116 if((*(ULONG *) nh->nh_OneBlock) == id)
5118 return(nh->nh_OneBlock);
5120 } else {
5121 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Error searching hardblock in block %ld.", curBlock);
5122 return(NULL);
5124 } while(curBlock <= RDB_LOCATION_LIMIT);
5125 return(NULL);
5127 /* \\\ */
5129 /* /// "ReadRDSK()" */
5130 BOOL ReadRDSK(struct NepClassMS *ncm,
5131 struct IOStdReq *ioreq,
5132 struct RigidDiskBlock *rdb)
5134 APTR blkaddr = SearchHardBlock(ncm, ioreq, IDNAME_RIGIDDISK, 0);
5135 if(blkaddr)
5137 CopyMemQuick(blkaddr, rdb, sizeof(struct RigidDiskBlock));
5138 // endianess conversion
5139 rdb->rdb_ID = AROS_BE2LONG(rdb->rdb_ID);
5140 rdb->rdb_SummedLongs = AROS_BE2LONG(rdb->rdb_SummedLongs);
5141 rdb->rdb_ChkSum = AROS_BE2LONG(rdb->rdb_ChkSum);
5142 rdb->rdb_HostID = AROS_BE2LONG(rdb->rdb_HostID);
5143 rdb->rdb_BlockBytes = AROS_BE2LONG(rdb->rdb_BlockBytes);
5144 rdb->rdb_PartitionList = AROS_BE2LONG(rdb->rdb_PartitionList);
5145 rdb->rdb_FileSysHeaderList = AROS_BE2LONG(rdb->rdb_FileSysHeaderList);
5146 rdb->rdb_DriveInit = AROS_BE2LONG(rdb->rdb_DriveInit);
5147 rdb->rdb_Cylinders = AROS_BE2LONG(rdb->rdb_Cylinders);
5148 rdb->rdb_Sectors = AROS_BE2LONG(rdb->rdb_Sectors);
5149 rdb->rdb_Heads = AROS_BE2LONG(rdb->rdb_Heads);
5150 rdb->rdb_Interleave = AROS_BE2LONG(rdb->rdb_Interleave);
5151 rdb->rdb_Park = AROS_BE2LONG(rdb->rdb_Park);
5152 rdb->rdb_WritePreComp = AROS_BE2LONG(rdb->rdb_WritePreComp);
5153 rdb->rdb_ReducedWrite = AROS_BE2LONG(rdb->rdb_ReducedWrite);
5154 rdb->rdb_StepRate = AROS_BE2LONG(rdb->rdb_StepRate);
5155 rdb->rdb_RDBBlocksLo = AROS_BE2LONG(rdb->rdb_RDBBlocksLo);
5156 rdb->rdb_RDBBlocksHi = AROS_BE2LONG(rdb->rdb_RDBBlocksHi);
5157 rdb->rdb_LoCylinder = AROS_BE2LONG(rdb->rdb_LoCylinder);
5158 rdb->rdb_HiCylinder = AROS_BE2LONG(rdb->rdb_HiCylinder);
5159 rdb->rdb_CylBlocks = AROS_BE2LONG(rdb->rdb_CylBlocks);
5160 rdb->rdb_AutoParkSeconds = AROS_BE2LONG(rdb->rdb_AutoParkSeconds);
5161 rdb->rdb_HighRDSKBlock = AROS_BE2LONG(rdb->rdb_HighRDSKBlock);
5162 return(TRUE);
5164 return(FALSE);
5166 /* \\\ */
5168 /* /// "ReadPART()" */
5169 BOOL ReadPART(struct NepClassMS *ncm,
5170 struct IOStdReq *ioreq,
5171 struct PartitionBlock *part,
5172 ULONG which)
5174 APTR blkaddr = SearchHardBlock(ncm, ioreq, IDNAME_PARTITION, which);
5175 if(blkaddr)
5177 UWORD cnt;
5178 CopyMemQuick(blkaddr, part, sizeof(struct PartitionBlock));
5179 // endianess conversion
5180 part->pb_ID = AROS_BE2LONG(part->pb_ID);
5181 part->pb_SummedLongs = AROS_BE2LONG(part->pb_SummedLongs);
5182 part->pb_ChkSum = AROS_BE2LONG(part->pb_ChkSum);
5183 part->pb_HostID = AROS_BE2LONG(part->pb_HostID);
5184 part->pb_Next = AROS_BE2LONG(part->pb_Next);
5185 part->pb_Flags = AROS_BE2LONG(part->pb_Flags);
5186 part->pb_DevFlags = AROS_BE2LONG(part->pb_DevFlags);
5187 for(cnt = 0; cnt < 20; cnt++)
5189 part->pb_Environment[cnt] = AROS_BE2LONG(part->pb_Environment[cnt]);
5191 return(TRUE);
5193 return(FALSE);
5195 /* \\\ */
5197 /* /// "ReadFSHD()" */
5198 BOOL ReadFSHD(struct NepClassMS *ncm,
5199 struct IOStdReq *ioreq,
5200 struct FileSysHeaderBlock *fshd,
5201 ULONG which)
5203 APTR blkaddr = SearchHardBlock(ncm, ioreq, IDNAME_FILESYSHEADER, which);
5204 if(blkaddr)
5206 CopyMemQuick(blkaddr, fshd, sizeof(struct FileSysHeaderBlock));
5207 // endianess conversion
5208 fshd->fhb_ID = AROS_BE2LONG(fshd->fhb_ID);
5209 fshd->fhb_SummedLongs = AROS_BE2LONG(fshd->fhb_SummedLongs);
5210 fshd->fhb_ChkSum = AROS_BE2LONG(fshd->fhb_ChkSum);
5211 fshd->fhb_HostID = AROS_BE2LONG(fshd->fhb_HostID);
5212 fshd->fhb_Next = AROS_BE2LONG(fshd->fhb_Next);
5213 fshd->fhb_Flags = AROS_BE2LONG(fshd->fhb_Flags);
5214 fshd->fhb_DosType = AROS_BE2LONG(fshd->fhb_DosType);
5215 fshd->fhb_Version = AROS_BE2LONG(fshd->fhb_Version);
5216 fshd->fhb_PatchFlags = AROS_BE2LONG(fshd->fhb_PatchFlags);
5217 fshd->fhb_Type = AROS_BE2LONG(fshd->fhb_Type);
5218 fshd->fhb_Task = AROS_BE2LONG(fshd->fhb_Task);
5219 fshd->fhb_Lock = AROS_BE2LONG(fshd->fhb_Lock);
5220 fshd->fhb_Handler = AROS_BE2LONG(fshd->fhb_Handler);
5221 fshd->fhb_StackSize = AROS_BE2LONG(fshd->fhb_StackSize);
5222 fshd->fhb_Priority = AROS_BE2LONG(fshd->fhb_Priority);
5223 fshd->fhb_Startup = AROS_BE2LONG(fshd->fhb_Startup);
5224 fshd->fhb_SegListBlocks = AROS_BE2LONG(fshd->fhb_SegListBlocks);
5225 fshd->fhb_GlobalVec = AROS_BE2LONG(fshd->fhb_GlobalVec);
5226 return(TRUE);
5228 return(FALSE);
5230 /* \\\ */
5232 /* /// "ReadLSEG()" */
5233 struct LoadSegBlock * ReadLSEG(struct NepClassMS *ncm,
5234 struct IOStdReq *ioreq,
5235 ULONG which)
5237 return((struct LoadSegBlock *) SearchHardBlock(ncm, ioreq, IDNAME_LOADSEG, which));
5239 /* \\\ */
5241 /* /// "FindFileSystem()" */
5242 struct FileSysEntry * FindFileSystem(struct NepClassMS *ncm, ULONG dosType)
5244 struct FileSysResource *fsr;
5245 struct FileSysEntry *fse;
5247 KPRINTF(10, ("looking up %08lx fs\n", dosType));
5248 if((fsr = (struct FileSysResource *) OpenResource(FSRNAME)))
5250 Forbid();
5251 fse = (struct FileSysEntry *) fsr->fsr_FileSysEntries.lh_Head;
5252 while(fse->fse_Node.ln_Succ)
5254 if(fse->fse_DosType == dosType)
5256 Permit();
5257 return(fse);
5259 fse = (struct FileSysEntry *) fse->fse_Node.ln_Succ;
5261 Permit();
5264 return(NULL);
5266 /* \\\ */
5268 /* /// "BuildFileSystem()" */
5269 ULONG BuildFileSystem(struct NepClassMS *ncm,
5270 UBYTE *fsBuffer,
5271 BOOL readAndCopy)
5273 struct NepMSBase *nh = ncm->ncm_ClsBase;
5274 struct RigidDisk *rdsk = &nh->nh_RDsk;
5275 ULONG result = 0;
5276 ULONG nextLSEG;
5277 ULONG add;
5278 struct LoadSegBlock *lseg;
5280 nextLSEG = rdsk->rdsk_FSHD.fhb_SegListBlocks;
5284 if((lseg = ReadLSEG(ncm, &nh->nh_IOReq, nextLSEG)))
5286 add = (AROS_BE2LONG(lseg->lsb_SummedLongs) - 5) * sizeof(ULONG);
5287 if(readAndCopy)
5289 CopyMem(lseg->lsb_LoadData, fsBuffer, add);
5290 fsBuffer += add;
5292 result += add;
5293 nextLSEG = lseg->lsb_Next;
5294 } else {
5295 result = 0;
5296 break;
5298 } while(nextLSEG != NIL_PTR);
5299 return(result);
5301 /* \\\ */
5303 /* /// "LoadFileSystem()" */
5304 BPTR LoadFileSystem(struct NepClassMS *ncm, ULONG dosType, struct FileSysEntry *fse)
5306 struct NepMSBase *nh = ncm->ncm_ClsBase;
5307 struct RigidDisk *rdsk = &nh->nh_RDsk;
5308 ULONG nextFSHD;
5309 BPTR fh, seg = BNULL;
5310 ULONG fsLength;
5311 UBYTE *fsBuffer;
5312 UBYTE fsFile[32];
5313 BOOL ok;
5315 if(rdsk->rdsk_RDB.rdb_FileSysHeaderList != NIL_PTR)
5317 nextFSHD = rdsk->rdsk_RDB.rdb_FileSysHeaderList;
5320 if(ReadFSHD(ncm, &nh->nh_IOReq, &rdsk->rdsk_FSHD, nextFSHD))
5322 nextFSHD = rdsk->rdsk_FSHD.fhb_Next;
5323 } else {
5324 break;
5326 KPRINTF(10, ("Found 0x%08lx FS in FSHD...\n", rdsk->rdsk_FSHD.fhb_ID));
5327 } while((rdsk->rdsk_FSHD.fhb_DosType != dosType) && (nextFSHD != NIL_PTR));
5329 if(rdsk->rdsk_FSHD.fhb_DosType == dosType)
5331 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Found filesystem %s in RDB!",
5332 nh->nh_RDsk.rdsk_FSHD.fhb_FileSysName);
5333 KPRINTF(10, ("found matching fs in FSHD, trying to load from LSEG blocks\n"));
5335 CopyMem(&rdsk->rdsk_FSHD.fhb_DosType, &fse->fse_DosType, sizeof(struct FileSysEntry) - sizeof(struct Node));
5337 if(rdsk->rdsk_FSHD.fhb_SegListBlocks > 0)
5339 fsLength = BuildFileSystem(ncm, NULL, FALSE);
5341 if(fsLength > 0)
5343 if((fsBuffer = psdAllocVec(fsLength)))
5345 BuildFileSystem(ncm, fsBuffer, TRUE);
5347 if(GM_UNIQUENAME(nOpenDOS)(nh))
5349 psdSafeRawDoFmt(fsFile, 32, "T:UMSD_%08lx.fs", dosType);
5350 if((fh = Open(fsFile, MODE_NEWFILE)))
5352 ok = (Write(fh, fsBuffer, fsLength) == fsLength);
5353 Close(fh);
5354 if(ok)
5356 seg = LoadSeg(fsFile);
5359 DeleteFile(fsFile);
5360 } else {
5361 KPRINTF(10, ("No DOS available, trying own load seg stuff\n"));
5362 // FIXME this code is unavailable and doesn't make sense for AROS as it doesn't use DOS_HUNK format
5363 //seg = CreateSegment(ncm, (const ULONG *) fsBuffer);
5365 psdFreeVec(fsBuffer);
5372 if(!seg)
5374 if(GM_UNIQUENAME(nOpenDOS)(nh))
5376 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Loading filesystem %s from RDB failed. Trying DOS...",
5377 nh->nh_RDsk.rdsk_FSHD.fhb_FileSysName);
5378 KPRINTF(10, ("loading fs from LSEG blocks failed, trying fs file %s mentioned in FSHD\n", (char *) nh->nh_RDsk.rdsk_FSHD.fhb_FileSysName));
5379 //seg = LoadSeg(rdsk->rdsk_FSHD.fhb_FileSysName);
5380 seg = LoadSeg((char *) nh->nh_RDsk.rdsk_FSHD.fhb_FileSysName);
5381 if(seg)
5383 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Loaded filesystem %s via DOS!",
5384 nh->nh_RDsk.rdsk_FSHD.fhb_FileSysName);
5385 } else {
5386 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Loading filesystem %s via DOS failed!",
5387 nh->nh_RDsk.rdsk_FSHD.fhb_FileSysName);
5389 } else {
5390 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Loading filesystem %s from RDB failed.",
5391 nh->nh_RDsk.rdsk_FSHD.fhb_FileSysName);
5394 if(seg)
5396 fse->fse_SegList = seg;
5398 return(seg);
5400 /* \\\ */
5402 /* /// "MatchPartition()" */
5403 BOOL MatchPartition(struct NepClassMS *ncm,
5404 struct DosEnvec *envec1,
5405 struct FileSysStartupMsg *fssm)
5407 BOOL result = FALSE;
5408 UBYTE *bstr;
5409 UBYTE device[256];
5410 struct DosEnvec *envec2;
5412 if(fssm)
5414 envec2 = (struct DosEnvec *) BADDR(fssm->fssm_Environ);
5416 if(envec2)
5418 bstr = (UBYTE *) BADDR(fssm->fssm_Device);
5419 b2cstr(bstr, device);
5421 if(envec1)
5423 if((envec1->de_DosType & 0xffffff00) == 0x46415400)
5425 result = ((ncm->ncm_UnitNo == fssm->fssm_Unit) &&
5426 (strcmp(DEVNAME, device) == 0) &&
5427 (envec1->de_DosType == envec2->de_DosType));
5428 } else {
5429 result = ((ncm->ncm_UnitNo == fssm->fssm_Unit) &&
5430 (strcmp(DEVNAME, device) == 0) &&
5431 (envec1->de_SizeBlock == envec2->de_SizeBlock) &&
5432 (envec1->de_Surfaces == envec2->de_Surfaces) &&
5433 (envec1->de_SectorPerBlock == envec2->de_SectorPerBlock) &&
5434 (envec1->de_BlocksPerTrack == envec2->de_BlocksPerTrack) &&
5435 (envec1->de_Reserved == envec2->de_Reserved) &&
5436 (envec1->de_PreAlloc == envec2->de_PreAlloc) &&
5437 (envec1->de_Interleave == envec2->de_Interleave) &&
5438 (envec1->de_LowCyl == envec2->de_LowCyl) &&
5439 (envec1->de_HighCyl == envec2->de_HighCyl) &&
5440 (envec1->de_DosType == envec2->de_DosType));
5442 } else {
5443 result = (ncm->ncm_UnitNo == fssm->fssm_Unit) &&
5444 (strcmp(DEVNAME, device) == 0);
5448 return(result);
5450 /* \\\ */
5452 /* /// "FindDeviceNode()" */
5453 struct DeviceNode * FindDeviceNode(struct NepClassMS *ncm, STRPTR device)
5455 struct NepMSBase *nh = ncm->ncm_ClsBase;
5456 struct DosList *list;
5457 struct DeviceNode *node = NULL;
5459 if(!GM_UNIQUENAME(nOpenDOS)(nh))
5461 return(NULL);
5464 if((list = LockDosList(LDF_DEVICES | LDF_READ)))
5466 node = (struct DeviceNode *) FindDosEntry(list, device, LDF_DEVICES);
5467 UnLockDosList(LDF_DEVICES | LDF_READ);
5469 return(node);
5471 /* \\\ */
5473 /* /// "CheckVolumesOrAssignsMatch()" */
5474 BOOL CheckVolumesOrAssignsMatch(struct NepClassMS *ncm, STRPTR device)
5476 struct NepMSBase *nh = ncm->ncm_ClsBase;
5477 struct DosList *list;
5478 BOOL found = FALSE;
5480 if(!GM_UNIQUENAME(nOpenDOS)(nh))
5482 return(FALSE);
5485 if((list = LockDosList(LDF_ALL | LDF_READ)))
5487 if(FindDosEntry(list, device, LDF_ALL))
5489 found = TRUE;
5491 UnLockDosList(LDF_ALL | LDF_READ);
5493 return(found);
5495 /* \\\ */
5497 /* /// "FindMatchingDevice()" */
5498 struct DeviceNode * FindMatchingDevice(struct NepClassMS *ncm, struct DosEnvec *envec)
5500 struct NepMSBase *nh = ncm->ncm_ClsBase;
5501 struct DosList *list;
5502 struct DeviceNode *node = NULL;
5503 struct FileSysStartupMsg *fssm;
5505 if(!GM_UNIQUENAME(nOpenDOS)(nh))
5507 return(NULL);
5510 if((list = LockDosList(LDF_DEVICES | LDF_READ)))
5512 while((list = NextDosEntry(list, LDF_DEVICES | LDF_READ)))
5514 fssm = NULL;
5516 /*if((!(((ULONG) list->dol_misc.dol_handler.dol_Startup) >> 30)) &&
5517 TypeOfMem(BADDR(list->dol_misc.dol_handler.dol_Startup)))*/
5519 fssm = BADDR(list->dol_misc.dol_handler.dol_Startup);
5522 if(fssm > (struct FileSysStartupMsg *) 0x1000)
5524 // if((*((UBYTE *) fssm)) == 0)
5526 struct DosEnvec *de = BADDR(fssm->fssm_Environ);
5527 STRPTR devname = BADDR(fssm->fssm_Device);
5529 if(TypeOfMem(de) && TypeOfMem(devname) && (de->de_TableSize > 0) && (de->de_TableSize < 32))
5530 /*if((!((ULONG) de >> 30)) && TypeOfMem(de) &&
5531 (!((ULONG) devname >> 30)) && TypeOfMem(devname) &&
5532 (de->de_TableSize > 0) && (de->de_TableSize < 32))*/
5534 if(MatchPartition(ncm, envec, fssm))
5536 node = (struct DeviceNode *) list;
5537 break;
5543 UnLockDosList(LDF_DEVICES | LDF_READ);
5545 return(node);
5547 /* \\\ */
5549 /* /// "MountPartition()" */
5550 BOOL MountPartition(struct NepClassMS *ncm, STRPTR dosDevice)
5552 struct NepMSBase *nh = ncm->ncm_ClsBase;
5553 struct RigidDisk *rdsk = &nh->nh_RDsk;
5554 IPTR *params;
5555 struct DeviceNode *node;
5556 struct FileSysEntry *fse;
5557 struct FileSysEntry patch;
5558 BPTR segList = BNULL;
5559 BOOL fsFound = FALSE;
5560 BOOL result = FALSE;
5561 STRPTR devname = DEVNAME;
5563 if((fse = FindFileSystem(ncm, rdsk->rdsk_PART.pb_Environment[DE_DOSTYPE])))
5565 KPRINTF(10, ("fs found in filesys resource\n"));
5566 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Found FS in filesystem.resource!");
5568 CopyMem(fse, &patch, sizeof(struct FileSysEntry));
5569 fsFound = TRUE;
5570 } else {
5571 memset(&patch, 0x00, sizeof(struct FileSysEntry));
5572 patch.fse_DosType = rdsk->rdsk_PART.pb_Environment[DE_DOSTYPE];
5574 if((segList = LoadFileSystem(ncm, rdsk->rdsk_PART.pb_Environment[DE_DOSTYPE], &patch)))
5576 KPRINTF(10, ("fs loaded from RDB\n"));
5578 patch.fse_PatchFlags = 0x0080|0x0010;
5579 patch.fse_SegList = segList;
5580 patch.fse_StackSize = 16384;
5581 //if(((patch.fse_DosType & 0xffffff00) == 0x46415400) || (patch.fse_DosType == 0x4d534800))
5583 KPRINTF(10, ("setting up certain fs values for MS-DOS fs\n"));
5584 // Stack, SegList, Pri und GlobVec eintragen
5585 patch.fse_PatchFlags |= 0x0020|0x0100;
5586 patch.fse_Priority = 10;
5587 patch.fse_GlobalVec = (BPTR) 0xffffffff;
5590 fsFound = TRUE;
5594 if(!fsFound)
5596 STRPTR handler = (STRPTR) nh->nh_RDsk.rdsk_FSHD.fhb_FileSysName;
5597 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Experimental AROS patch to load %s", handler);
5598 patch.fse_Handler = MKBADDR(AllocVec(AROS_BSTR_MEMSIZE4LEN(strlen(handler)), MEMF_PUBLIC | MEMF_CLEAR));
5599 if(patch.fse_Handler)
5601 c2bstr(handler, patch.fse_Handler);
5602 patch.fse_PatchFlags |= 0x0008;
5603 fsFound = TRUE;
5607 if(fsFound)
5609 if((params = psdAllocVec(sizeof(struct DosEnvec) + 4 * sizeof(IPTR))))
5611 params[0] = (IPTR) dosDevice;
5612 params[1] = (IPTR) DEVNAME;
5613 params[2] = ncm->ncm_UnitNo;
5614 params[3] = 0x00; // Flags for OpenDevice
5615 CopyMem(rdsk->rdsk_PART.pb_Environment, &params[4], sizeof(struct DosEnvec));
5617 if((node = MakeDosNode(params)))
5619 BOOL installboot;
5620 KPRINTF(10, ("MakeDosNode() succeeded, patchflags %04lx\n", patch.fse_PatchFlags));
5621 node->dn_StackSize = 16384;
5623 /*node->dn_Priority = 5;*/
5624 if(patch.fse_PatchFlags & 0x0001) node->dn_Type = patch.fse_Type;
5625 if(patch.fse_PatchFlags & 0x0002) node->dn_Task = (struct MsgPort *) patch.fse_Task;
5626 if(patch.fse_PatchFlags & 0x0004) node->dn_Lock = patch.fse_Lock;
5627 if(patch.fse_PatchFlags & 0x0008) node->dn_Handler = patch.fse_Handler;
5628 if(patch.fse_PatchFlags & 0x0010) node->dn_StackSize = patch.fse_StackSize;
5629 if(patch.fse_PatchFlags & 0x0020) node->dn_Priority = patch.fse_Priority;
5630 if(patch.fse_PatchFlags & 0x0040) node->dn_Startup = patch.fse_Startup;
5631 if(patch.fse_PatchFlags & 0x0080) node->dn_SegList = patch.fse_SegList;
5632 if(patch.fse_PatchFlags & 0x0100) node->dn_GlobalVec = patch.fse_GlobalVec;
5634 KPRINTF(10, ("dn_Next = %08lx\n"
5635 "dn_Type = %08lx\n"
5636 "dn_Task = %08lx\n"
5637 "dn_Lock = %08lx\n"
5638 "dn_Handler = %08lx\n"
5639 "dn_StackSize = %08ld\n"
5640 "dn_Priority = %08ld\n"
5641 "dn_Startup = %08lx\n"
5642 "dn_SegList = %08lx\n"
5643 "dn_GlobalVec = %08lx\n"
5644 "dn_Name = %08lx\n",
5645 node->dn_Next,
5646 node->dn_Type,
5647 node->dn_Task,
5648 node->dn_Lock,
5649 node->dn_Handler,
5650 node->dn_StackSize,
5651 node->dn_Priority,
5652 node->dn_Startup,
5653 node->dn_SegList,
5654 node->dn_GlobalVec,
5655 node->dn_Name));
5657 installboot = ncm->ncm_CUC->cuc_BootRDB;
5658 if((nh->nh_RemovableTask->tc_Node.ln_Type == NT_PROCESS) ||
5659 (!(nh->nh_RDsk.rdsk_PART.pb_Flags & PBFF_BOOTABLE)))
5661 installboot = FALSE;
5663 if(installboot)
5665 // avoid sys partition being unmounted (actually it should better check at
5666 // unmounting, but I can't think of a clever way yet to retrieve the SYS:
5667 // device
5668 ncm->ncm_CUC->cuc_AutoUnmount = FALSE;
5669 GM_UNIQUENAME(nStoreConfig)(ncm);
5672 if(AddBootNode(nh->nh_RDsk.rdsk_PART.pb_Environment[DE_BOOTPRI], ADNF_STARTPROC, node, NULL))
5674 KPRINTF(10, ("AddBootNode() succeeded\n"));
5675 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
5676 "Mounted %s unit %ld as %s:",
5677 devname, ncm->ncm_UnitNo, dosDevice);
5679 result = TRUE;
5680 } else {
5681 KPRINTF(10, ("AddBootNode() failed\n"));
5682 /* There is a memory leak here! No way to deallocate the node created by
5683 MakeDosNode()! */
5686 psdFreeVec(params);
5689 if(!result)
5691 if(GM_UNIQUENAME(nOpenDOS)(nh))
5693 UnLoadSeg(segList);
5696 } else {
5697 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
5698 "Couldn't find/load filesystem for %s unit %ld as %s:",
5699 devname, ncm->ncm_UnitNo, dosDevice);
5700 KPRINTF(10, ("fs %08lx not found\n", rdsk->rdsk_PART.pb_Environment[DE_DOSTYPE]));
5703 return(result);
5705 /* \\\ */
5707 /* /// "CheckPartition()" */
5708 void CheckPartition(struct NepClassMS *ncm)
5710 struct NepMSBase *nh = ncm->ncm_ClsBase;
5711 struct RigidDisk *rdsk = &nh->nh_RDsk;
5712 struct DosEnvec *envec;
5713 UBYTE dosDevice[32], temp[32];
5714 ULONG spareNum;
5715 struct DeviceNode *node;
5716 BOOL done = FALSE, doMount = TRUE;
5717 STRPTR devname = DEVNAME;
5718 BOOL bump;
5719 ULONG slen;
5721 envec = (struct DosEnvec *) rdsk->rdsk_PART.pb_Environment;
5722 if((node = FindMatchingDevice(ncm, envec)))
5724 KPRINTF(10, ("found suitable device entry, no need to mount anything new\n"));
5726 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
5727 "Matching partition for %s unit %ld already found. No remount required.",
5728 devname, ncm->ncm_UnitNo);
5729 doMount = FALSE;
5730 } else {
5731 spareNum = 0;
5733 b2cstr(rdsk->rdsk_PART.pb_DriveName, dosDevice);
5735 KPRINTF(10, ("trying to mount partition \"%s\"\n", dosDevice));
5737 /*if(envec->de_TableSize >= DE_DOSTYPE) SHOWVALUE(envec->de_DosType);*/
5740 bump = FALSE;
5741 if((node = FindDeviceNode(ncm, dosDevice)))
5743 KPRINTF(10, ("%s is already mounted, comparing fssm\n", dosDevice));
5745 if(MatchPartition(ncm, envec, BADDR(node->dn_Startup)))
5747 KPRINTF(10, ("fssm match, no need to mount\n"));
5749 doMount = FALSE;
5750 done = TRUE;
5751 } else {
5752 bump = TRUE;
5754 } else {
5755 if(CheckVolumesOrAssignsMatch(ncm, dosDevice))
5757 bump = TRUE;
5758 } else {
5759 done = TRUE;
5762 if(bump)
5764 slen = strlen(dosDevice);
5765 if((slen > 0) && (dosDevice[slen-1] >= '0') && (dosDevice[slen-1] <= '9'))
5767 if(dosDevice[slen-1] == '9')
5769 if((slen > 1) && (dosDevice[slen-2] >= '0') && (dosDevice[slen-2] <= '8'))
5771 dosDevice[slen-2]++;
5772 dosDevice[slen-1] = '0';
5773 } else {
5774 if(slen < 30)
5776 dosDevice[slen-1] = '1';
5777 dosDevice[slen] = '0';
5778 dosDevice[slen+1] = 0;
5779 } else {
5780 break;
5783 } else {
5784 dosDevice[slen-1]++;
5786 } else {
5787 b2cstr(rdsk->rdsk_PART.pb_DriveName, temp);
5788 psdSafeRawDoFmt(dosDevice, 32, "%s.%ld", temp, spareNum);
5790 KPRINTF(10, ("fssm don't match, trying as %s\n", dosDevice));
5791 spareNum++;
5793 } while(!done && (spareNum < 16));
5796 if(done && doMount)
5798 KPRINTF(10, ("mounting %s\n", dosDevice));
5800 MountPartition(ncm, dosDevice);
5803 /* \\\ */
5805 /* /// "IsFATSuperBlock()" */
5806 BOOL IsFATSuperBlock(struct FATSuperBlock *fsb)
5808 BOOL result;
5809 result = (BOOL)(strncmp(fsb->fsb_Vendor, "MSDOS", 5) == 0 ||
5810 strncmp(fsb->fsb_Vendor, "MSWIN", 5) == 0 ||
5811 strncmp(fsb->fsb_FileSystem, "FAT12", 5) == 0 ||
5812 strncmp(fsb->fsb_FileSystem, "FAT16", 5) == 0 ||
5813 strncmp(fsb->fsb_FileSystem2, "FAT32", 5) == 0);
5815 return(result);
5817 /* \\\ */
5819 /* /// "GetFATDosType()" */
5820 ULONG GetFATDosType(struct FATSuperBlock *fsb)
5822 ULONG result = 0x46415400;
5823 if(strncmp(fsb->fsb_FileSystem2, "FAT32", 5) == 0)
5824 result |= 2;
5825 else if(strncmp(fsb->fsb_FileSystem, "FAT16", 5) == 0)
5826 result |= 1;
5828 return(result);
5830 /* \\\ */
5832 /* /// "CheckFATPartition()" */
5833 void CheckFATPartition(struct NepClassMS *ncm, ULONG startblock)
5835 struct NepMSBase *nh = ncm->ncm_ClsBase;
5836 struct MasterBootRecord *mbr;
5837 struct DosEnvec *envec;
5838 struct IOStdReq *stdIO = &nh->nh_IOReq;
5839 struct DriveGeometry *tddg = &ncm->ncm_Geometry;
5840 BOOL isfat = FALSE;
5841 BOOL isntfs = FALSE;
5843 mbr = (struct MasterBootRecord *) psdAllocVec(ncm->ncm_BlockSize<<1);
5844 if(!mbr)
5846 return;
5849 stdIO->io_Command = TD_READ64;
5850 stdIO->io_Offset = startblock<<ncm->ncm_BlockShift;
5851 stdIO->io_Actual = startblock>>(32-ncm->ncm_BlockShift);
5852 stdIO->io_Length = ncm->ncm_BlockSize;
5853 stdIO->io_Data = mbr;
5854 if(!nIOCmdTunnel(ncm, stdIO))
5856 /* do (super)floppy check */
5857 if(IsFATSuperBlock((struct FATSuperBlock *) mbr))
5859 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Media is FAT formatted!");
5860 isfat = TRUE;
5861 nh->nh_RDsk.rdsk_PART.pb_DevFlags = 0;
5863 if(*(ncm->ncm_CUC->cuc_FATDOSName))
5865 c2bstr(ncm->ncm_CUC->cuc_FATDOSName, nh->nh_RDsk.rdsk_PART.pb_DriveName);
5866 } else {
5867 c2bstr("UF0", nh->nh_RDsk.rdsk_PART.pb_DriveName);
5870 envec = (struct DosEnvec *) nh->nh_RDsk.rdsk_PART.pb_Environment;
5871 memset(envec, 0x00, sizeof(struct DosEnvec));
5872 stdIO->io_Command = TD_GETGEOMETRY;
5873 stdIO->io_Data = tddg;
5874 stdIO->io_Length = sizeof(*tddg);
5876 if(nIOCmdTunnel(ncm, stdIO))
5878 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Couldn't read drive geometry, using floppy defaults");
5879 envec->de_SizeBlock = ncm->ncm_BlockSize>>2;
5880 envec->de_Surfaces = 2;
5881 envec->de_BlocksPerTrack = 18;
5882 envec->de_LowCyl = 0;
5883 envec->de_HighCyl = 79;
5884 } else {
5885 envec->de_SizeBlock = ncm->ncm_BlockSize>>2;
5886 envec->de_Surfaces = tddg->dg_Heads;
5887 envec->de_BlocksPerTrack = tddg->dg_TrackSectors;
5888 envec->de_LowCyl = 0;
5889 envec->de_HighCyl = tddg->dg_Cylinders-1;
5891 envec->de_TableSize = DE_BOOTBLOCKS;
5892 envec->de_SectorPerBlock = 1;
5893 envec->de_NumBuffers = ncm->ncm_CUC->cuc_FATBuffers;
5894 envec->de_BufMemType = MEMF_PUBLIC;
5895 envec->de_MaxTransfer = (1UL<<(ncm->ncm_CDC->cdc_MaxTransfer+16))-1;
5896 envec->de_Mask = 0xffffffff;
5897 envec->de_BootPri = 0;
5898 envec->de_Baud = 1200;
5899 if(*ncm->ncm_CDC->cdc_FATControl)
5901 UBYTE *bptr = ncm->ncm_FATControlBSTR;
5902 bptr = (UBYTE *) ((((IPTR) bptr) + 3) & (~3));
5903 c2bstr(ncm->ncm_CDC->cdc_FATControl, bptr);
5904 envec->de_Control = (IPTR) MKBADDR(bptr);
5905 } else {
5906 envec->de_Control = 0;
5908 envec->de_BootBlocks = 0;
5909 envec->de_Interleave = 0;
5910 envec->de_DosType = ncm->ncm_CDC->cdc_FATDosType; //0x46415401; // FAT1
5911 if((ncm->ncm_CDC->cdc_FATDosType & 0xffffff00) == 0x46415400)
5913 envec->de_DosType =
5914 GetFATDosType((struct FATSuperBlock *) mbr);
5917 // we have no FSHD and LSEG blocks
5918 nh->nh_RDsk.rdsk_RDB.rdb_FileSysHeaderList = NIL_PTR;
5919 nh->nh_RDsk.rdsk_FSHD.fhb_SegListBlocks = 0;
5921 KPRINTF(5, ("building FAT95 style environment\n"));
5923 strncpy((char *) nh->nh_RDsk.rdsk_FSHD.fhb_FileSysName, ncm->ncm_CDC->cdc_FATFSName, 84);
5924 CheckPartition(ncm);
5926 if(!(isfat || isntfs))
5928 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
5929 "Media does not seem to be FAT nor NTFS formatted.");
5931 } else {
5932 KPRINTF(10, ("failed to read MBR\n"));
5933 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
5935 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
5936 "Failed to read MasterBootRecord for FAT/NTFS AutoMounting.");
5939 psdFreeVec(mbr);
5941 /* \\\ */
5943 /* /// "CheckISO9660()" */
5944 void CheckISO9660(struct NepClassMS *ncm)
5946 struct NepMSBase *nh = ncm->ncm_ClsBase;
5947 UBYTE *blockbuf;
5948 struct IOStdReq *stdIO = &nh->nh_IOReq;
5950 blockbuf = (UBYTE *) psdAllocVec(ncm->ncm_BlockSize);
5951 if(!blockbuf)
5953 return;
5955 stdIO->io_Command = TD_READ64;
5956 stdIO->io_Offset = 0x8000;
5957 stdIO->io_Actual = 0;
5958 stdIO->io_Length = ncm->ncm_BlockSize;
5959 stdIO->io_Data = blockbuf;
5960 if(!nIOCmdTunnel(ncm, stdIO))
5962 if((((ULONG *) blockbuf)[0] == AROS_LONG2BE(0x01434430)) && (((ULONG *) blockbuf)[1] == AROS_LONG2BE(0x30310100)))
5964 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Media is ISO9660.");
5965 AutoMountCD(ncm);
5967 } else {
5968 KPRINTF(10, ("failed to read ISO sector\n"));
5969 if(ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG)
5971 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
5972 "Failed to read block 16 for CDFS AutoMounting.");
5975 psdFreeVec(blockbuf);
5977 /* \\\ */
5979 /* /// "AutoMountCD()" */
5980 void AutoMountCD(struct NepClassMS *ncm)
5982 struct NepMSBase *nh = ncm->ncm_ClsBase;
5983 struct DosEnvec *envec;
5985 nh->nh_RDsk.rdsk_PART.pb_DevFlags = 0;
5987 if(*(ncm->ncm_CUC->cuc_FATDOSName))
5989 c2bstr(ncm->ncm_CUC->cuc_FATDOSName, nh->nh_RDsk.rdsk_PART.pb_DriveName);
5990 } else {
5991 c2bstr("UCD0", nh->nh_RDsk.rdsk_PART.pb_DriveName);
5994 envec = (struct DosEnvec *) nh->nh_RDsk.rdsk_PART.pb_Environment;
5995 memset(envec, 0x00, sizeof(struct DosEnvec));
5997 envec->de_TableSize = DE_BOOTBLOCKS;
5998 envec->de_SizeBlock = ncm->ncm_BlockSize>>2;
5999 envec->de_Surfaces = 1;
6000 envec->de_SectorPerBlock = 1;
6001 envec->de_Reserved = 0xffffffff;
6002 envec->de_NumBuffers = ncm->ncm_CUC->cuc_FATBuffers;
6003 envec->de_BufMemType = MEMF_PUBLIC;
6004 envec->de_MaxTransfer = (1UL<<(ncm->ncm_CDC->cdc_MaxTransfer+16))-1;
6005 envec->de_Mask = 0xffffffff;
6006 envec->de_BootPri = 0;
6007 envec->de_Baud = 1200;
6008 if(*ncm->ncm_CDC->cdc_CDControl)
6010 UBYTE *bptr = ncm->ncm_FATControlBSTR;
6011 bptr = (UBYTE *) ((((IPTR) bptr) + 3) & (~3));
6012 c2bstr(ncm->ncm_CDC->cdc_CDControl, bptr);
6013 envec->de_Control = (IPTR) MKBADDR(bptr);
6014 } else {
6015 envec->de_Control = 0;
6017 envec->de_BootBlocks = 0;
6019 // we have no FSHD and LSEG blocks
6020 nh->nh_RDsk.rdsk_RDB.rdb_FileSysHeaderList = NIL_PTR;
6021 nh->nh_RDsk.rdsk_FSHD.fhb_SegListBlocks = 0;
6023 KPRINTF(5, ("building CDFS style environment\n"));
6025 envec->de_BlocksPerTrack = 1;
6026 envec->de_Interleave = 0;
6027 envec->de_DosType = ncm->ncm_CDC->cdc_CDDosType;
6028 envec->de_LowCyl = 0;
6029 envec->de_HighCyl = 1;
6031 strncpy((char *) nh->nh_RDsk.rdsk_FSHD.fhb_FileSysName, ncm->ncm_CDC->cdc_CDFSName, 84);
6032 CheckPartition(ncm);
6034 /* \\\ */
6036 /**************************************************************************/
6038 static const char *MaxTransferStrings[] =
6040 " 64 KB",
6041 "128 KB",
6042 "256 KB",
6043 "512 KB",
6044 " 1 MB",
6045 " 2 MB",
6046 NULL
6049 static char *MainGUIPages[] = { "Device Settings", "LUN Settings", NULL };
6050 static char *MainGUIPagesDefault[] = { "Device Defaults", "LUN Defaults", NULL };
6052 /* /// "nGetDosType()" */
6053 ULONG nGetDosType(STRPTR tmpstr)
6055 ULONG dostype = 0;
6056 UBYTE ch;
6058 while((ch = *tmpstr++))
6060 dostype <<= 4;
6061 if((ch >= '0') && (ch <= '9'))
6063 dostype += ch - '0';
6065 else if((ch >= 'a') && (ch <= 'f'))
6067 dostype += ch - 'a' + 10;
6069 else if((ch >= 'A') && (ch <= 'F'))
6071 dostype += ch - 'A' + 10;
6074 return(dostype);
6076 /* \\\ */
6078 /* /// "nGUITask()" */
6079 AROS_UFH0(void, GM_UNIQUENAME(nGUITask))
6081 AROS_USERFUNC_INIT
6083 struct Task *thistask;
6084 struct NepMSBase *nh;
6085 struct NepClassMS *ncm;
6086 struct NepClassMS *cncm;
6087 struct NepClassMS *curncm = NULL;
6088 APTR pic;
6089 char dostypebuf[10];
6090 char cddostypebuf[10];
6091 char ntfsdostypebuf[10];
6092 char bar[] = "BAR,";
6094 thistask = FindTask(NULL);
6095 #undef ps
6096 #define ps ncm->ncm_PsdBase
6097 #undef IntuitionBase
6098 #define IntuitionBase ncm->ncm_IntBase
6099 #undef MUIMasterBase
6100 #define MUIMasterBase ncm->ncm_MUIBase
6102 ncm = thistask->tc_UserData;
6103 nh = ncm->ncm_ClsBase;
6105 ++nh->nh_Library.lib_OpenCnt;
6106 if(!(MUIMasterBase = OpenLibrary(MUIMASTER_NAME, MUIMASTER_VMIN)))
6108 KPRINTF(10, ("Couldn't open muimaster.library.\n"));
6109 GM_UNIQUENAME(nGUITaskCleanup)(ncm);
6110 return;
6113 if(!(IntuitionBase = OpenLibrary("intuition.library", 39)))
6115 KPRINTF(10, ("Couldn't open intuition.library.\n"));
6116 GM_UNIQUENAME(nGUITaskCleanup)(ncm);
6117 return;
6119 if(!(ps = OpenLibrary("poseidon.library", 4)))
6121 KPRINTF(10, ("Couldn't open poseidon.library.\n"));
6122 GM_UNIQUENAME(nGUITaskCleanup)(ncm);
6123 return;
6126 ncm->ncm_LUNListDisplayHook.h_Data = NULL;
6127 ncm->ncm_LUNListDisplayHook.h_Entry = (APTR) GM_UNIQUENAME(LUNListDisplayHook);
6129 psdSafeRawDoFmt(dostypebuf, 10, "%08lx", ncm->ncm_CDC->cdc_FATDosType);
6130 psdSafeRawDoFmt(ntfsdostypebuf, 10, "%08lx", ncm->ncm_CDC->cdc_NTFSDosType);
6131 psdSafeRawDoFmt(cddostypebuf, 10, "%08lx", ncm->ncm_CDC->cdc_CDDosType);
6133 ncm->ncm_App = (APTR) ApplicationObject,
6134 MUIA_Application_Title , (IPTR) GM_UNIQUENAME(libname),
6135 MUIA_Application_Version , (IPTR) VERSION_STRING,
6136 MUIA_Application_Copyright , (IPTR) "©2002-2009 Chris Hodges",
6137 MUIA_Application_Author , (IPTR) "Chris Hodges <chrisly@platon42.de>",
6138 MUIA_Application_Description, (IPTR) "Settings for the massstorage.class",
6139 MUIA_Application_Base , (IPTR) "MASSSTORAGE",
6140 MUIA_Application_HelpFile , (IPTR) "HELP:Poseidon.guide",
6141 MUIA_Application_Menustrip , (IPTR) MenustripObject,
6142 Child, (IPTR) MenuObjectT((IPTR) "Project"),
6143 Child, (IPTR) (ncm->ncm_AboutMI = (APTR) MenuitemObject,
6144 MUIA_Menuitem_Title, (IPTR) "About...",
6145 MUIA_Menuitem_Shortcut, (IPTR) "?",
6146 End),
6147 End,
6148 Child, (IPTR) MenuObjectT((IPTR) "Settings"),
6149 Child, (IPTR) (ncm->ncm_UseMI = (APTR) MenuitemObject,
6150 MUIA_Menuitem_Title, (IPTR) "Save",
6151 MUIA_Menuitem_Shortcut, (IPTR) "S",
6152 End),
6153 Child, (IPTR) (ncm->ncm_SetDefaultMI = (APTR) MenuitemObject,
6154 MUIA_Menuitem_Title, (IPTR) "Save as Default",
6155 MUIA_Menuitem_Shortcut, (IPTR) "D",
6156 End),
6157 Child, (IPTR) MenuitemObject,
6158 MUIA_Menuitem_Title, (IPTR) NM_BARLABEL,
6159 End,
6160 Child, (IPTR) (ncm->ncm_MUIPrefsMI = (APTR) MenuitemObject,
6161 MUIA_Menuitem_Title, (IPTR) "MUI Settings",
6162 MUIA_Menuitem_Shortcut, (IPTR) "M",
6163 End),
6164 End,
6165 End,
6167 SubWindow, (IPTR) (ncm->ncm_MainWindow = (APTR) WindowObject,
6168 MUIA_Window_ID , MAKE_ID('M','A','I','N'),
6169 MUIA_Window_Title, (IPTR) GM_UNIQUENAME(libname),
6170 MUIA_HelpNode, (IPTR) GM_UNIQUENAME(libname),
6172 WindowContents, (IPTR) VGroup,
6173 Child, (IPTR) RegisterGroup(ncm->ncm_Interface ? MainGUIPages : MainGUIPagesDefault),
6174 MUIA_CycleChain, 1,
6175 MUIA_Register_Frame, TRUE,
6176 Child, (IPTR) VGroup,
6177 Child, (IPTR) VSpace(0),
6178 Child, (IPTR) ColGroup(2),
6179 Child, (IPTR) Label("NAK Timeout:"),
6180 Child, (IPTR) (ncm->ncm_NakTimeoutObj = (APTR) SliderObject, SliderFrame,
6181 MUIA_CycleChain, 1,
6182 MUIA_Numeric_Min, 0,
6183 MUIA_Numeric_Max, 600,
6184 MUIA_Numeric_Value, ncm->ncm_CDC->cdc_NakTimeout,
6185 MUIA_Numeric_Format, (IPTR) "%ld00ms",
6186 End),
6187 Child, (IPTR) Label("Startup delay:"),
6188 Child, (IPTR) (ncm->ncm_StartupDelayObj = (APTR) SliderObject, SliderFrame,
6189 MUIA_CycleChain, 1,
6190 MUIA_Numeric_Min, 0,
6191 MUIA_Numeric_Max, 100,
6192 MUIA_Numeric_Value, ncm->ncm_CDC->cdc_StartupDelay,
6193 MUIA_Numeric_Format, (IPTR) "%ld00ms",
6194 End),
6195 Child, (IPTR) Label("Single LUN:"),
6196 Child, (IPTR) HGroup,
6197 Child, (IPTR) (ncm->ncm_SingleLunObj = (APTR) ImageObject, ImageButtonFrame,
6198 MUIA_Background, MUII_ButtonBack,
6199 MUIA_CycleChain, 1,
6200 MUIA_InputMode, MUIV_InputMode_Toggle,
6201 MUIA_Image_Spec, MUII_CheckMark,
6202 MUIA_Image_FreeVert, TRUE,
6203 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_SINGLE_LUN,
6204 MUIA_ShowSelState, FALSE,
6205 End),
6206 Child, (IPTR) HSpace(0),
6207 Child, (IPTR) Label("No Initial Reset:"),
6208 Child, (IPTR) (ncm->ncm_InitialResetObj = (APTR) ImageObject, ImageButtonFrame,
6209 MUIA_Background, MUII_ButtonBack,
6210 MUIA_CycleChain, 1,
6211 MUIA_InputMode, MUIV_InputMode_Toggle,
6212 MUIA_Image_Spec, MUII_CheckMark,
6213 MUIA_Image_FreeVert, TRUE,
6214 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_RESET,
6215 MUIA_ShowSelState, FALSE,
6216 End),
6217 End,
6218 Child, (IPTR) Label("Simple SCSI:"),
6219 Child, (IPTR) HGroup,
6220 Child, (IPTR) (ncm->ncm_SimpleSCSIObj = (APTR) ImageObject, ImageButtonFrame,
6221 MUIA_Background, MUII_ButtonBack,
6222 MUIA_CycleChain, 1,
6223 MUIA_InputMode, MUIV_InputMode_Toggle,
6224 MUIA_Image_Spec, MUII_CheckMark,
6225 MUIA_Image_FreeVert, TRUE,
6226 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_SIMPLE_SCSI,
6227 MUIA_ShowSelState, FALSE,
6228 End),
6229 Child, (IPTR) HSpace(0),
6230 Child, (IPTR) Label("Translate CMD6->CMD10:"),
6231 Child, (IPTR) (ncm->ncm_XLate610Obj = (APTR) ImageObject, ImageButtonFrame,
6232 MUIA_Background, MUII_ButtonBack,
6233 MUIA_CycleChain, 1,
6234 MUIA_InputMode, MUIV_InputMode_Toggle,
6235 MUIA_Image_Spec, MUII_CheckMark,
6236 MUIA_Image_FreeVert, TRUE,
6237 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_MODE_XLATE,
6238 MUIA_ShowSelState, FALSE,
6239 End),
6240 End,
6241 Child, (IPTR) Label("Fake Inquiry:"),
6242 Child, (IPTR) HGroup,
6243 Child, (IPTR) (ncm->ncm_FakeInquiryObj = (APTR) ImageObject, ImageButtonFrame,
6244 MUIA_Background, MUII_ButtonBack,
6245 MUIA_CycleChain, 1,
6246 MUIA_InputMode, MUIV_InputMode_Toggle,
6247 MUIA_Image_Spec, MUII_CheckMark,
6248 MUIA_Image_FreeVert, TRUE,
6249 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_FAKE_INQUIRY,
6250 MUIA_ShowSelState, FALSE,
6251 End),
6252 Child, (IPTR) HSpace(0),
6253 Child, (IPTR) Label("Better Removable Support:"),
6254 Child, (IPTR) (ncm->ncm_RemSupportObj = (APTR) ImageObject, ImageButtonFrame,
6255 MUIA_Background, MUII_ButtonBack,
6256 MUIA_CycleChain, 1,
6257 MUIA_InputMode, MUIV_InputMode_Toggle,
6258 MUIA_Image_Spec, MUII_CheckMark,
6259 MUIA_Image_FreeVert, TRUE,
6260 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_REM_SUPPORT,
6261 MUIA_ShowSelState, FALSE,
6262 End),
6263 End,
6264 Child, (IPTR) Label("Trim Inquiry:"),
6265 Child, (IPTR) HGroup,
6266 Child, (IPTR) (ncm->ncm_FixInquiryObj = (APTR) ImageObject, ImageButtonFrame,
6267 MUIA_Background, MUII_ButtonBack,
6268 MUIA_CycleChain, 1,
6269 MUIA_InputMode, MUIV_InputMode_Toggle,
6270 MUIA_Image_Spec, MUII_CheckMark,
6271 MUIA_Image_FreeVert, TRUE,
6272 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_FIX_INQ36,
6273 MUIA_ShowSelState, FALSE,
6274 End),
6275 Child, (IPTR) HSpace(0),
6276 Child, (IPTR) Label("Ignore broken CSS-ID:"),
6277 Child, (IPTR) (ncm->ncm_CSSBrokenObj = (APTR) ImageObject, ImageButtonFrame,
6278 MUIA_Background, MUII_ButtonBack,
6279 MUIA_CycleChain, 1,
6280 MUIA_InputMode, MUIV_InputMode_Toggle,
6281 MUIA_Image_Spec, MUII_CheckMark,
6282 MUIA_Image_FreeVert, TRUE,
6283 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_CSS_BROKEN,
6284 MUIA_ShowSelState, FALSE,
6285 End),
6286 End,
6287 Child, (IPTR) Label("Fix Capacity:"),
6288 Child, (IPTR) HGroup,
6289 Child, (IPTR) (ncm->ncm_FixCapacityObj = (APTR) ImageObject, ImageButtonFrame,
6290 MUIA_Background, MUII_ButtonBack,
6291 MUIA_CycleChain, 1,
6292 MUIA_InputMode, MUIV_InputMode_Toggle,
6293 MUIA_Image_Spec, MUII_CheckMark,
6294 MUIA_Image_FreeVert, TRUE,
6295 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_FIX_CAPACITY,
6296 MUIA_ShowSelState, FALSE,
6297 End),
6298 Child, (IPTR) HSpace(0),
6299 Child, (IPTR) Label("Emulate on larger block sizes:"),
6300 Child, (IPTR) (ncm->ncm_EmulLargeBlkObj = (APTR) ImageObject, ImageButtonFrame,
6301 MUIA_Background, MUII_ButtonBack,
6302 MUIA_CycleChain, 1,
6303 MUIA_InputMode, MUIV_InputMode_Toggle,
6304 MUIA_Image_Spec, MUII_CheckMark,
6305 MUIA_Image_FreeVert, TRUE,
6306 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_EMUL_LARGE_BLK,
6307 MUIA_ShowSelState, FALSE,
6308 End),
6309 End,
6310 Child, (IPTR) Label("No Fallback:"),
6311 Child, (IPTR) HGroup,
6312 Child, (IPTR) (ncm->ncm_NoFallbackObj = (APTR) ImageObject, ImageButtonFrame,
6313 MUIA_Background, MUII_ButtonBack,
6314 MUIA_CycleChain, 1,
6315 MUIA_InputMode, MUIV_InputMode_Toggle,
6316 MUIA_Image_Spec, MUII_CheckMark,
6317 MUIA_Image_FreeVert, TRUE,
6318 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_NO_FALLBACK,
6319 MUIA_ShowSelState, FALSE,
6320 End),
6321 Child, (IPTR) HSpace(0),
6322 Child, (IPTR) Label("Debug:"),
6323 Child, (IPTR) (ncm->ncm_DebugObj = (APTR) ImageObject, ImageButtonFrame,
6324 MUIA_Background, MUII_ButtonBack,
6325 MUIA_CycleChain, 1,
6326 MUIA_InputMode, MUIV_InputMode_Toggle,
6327 MUIA_Image_Spec, MUII_CheckMark,
6328 MUIA_Image_FreeVert, TRUE,
6329 MUIA_Selected, ncm->ncm_CDC->cdc_PatchFlags & PFF_DEBUG,
6330 MUIA_ShowSelState, FALSE,
6331 End),
6332 End,
6333 Child, (IPTR) Label("Max Transfer:"),
6334 Child, (IPTR) HGroup,
6335 Child, (IPTR) (ncm->ncm_MaxTransferObj = (APTR) CycleObject,
6336 MUIA_Cycle_Entries, (IPTR) MaxTransferStrings,
6337 MUIA_Cycle_Active, ncm->ncm_CDC->cdc_MaxTransfer,
6338 End),
6339 //Child, HSpace(0),
6340 Child, (IPTR) (ncm->ncm_AutoDtxMaxTransObj = (APTR) TextObject, ButtonFrame,
6341 MUIA_Disabled, !ncm->ncm_Interface,
6342 MUIA_Background, MUII_ButtonBack,
6343 MUIA_CycleChain, 1,
6344 MUIA_InputMode, MUIV_InputMode_RelVerify,
6345 MUIA_Text_Contents, (IPTR) "\33c Auto-detect ",
6346 End),
6347 End,
6348 End,
6349 Child, (IPTR) VSpace(0),
6351 Child, (IPTR) ColGroup(6),
6352 Child, (IPTR) Label("FAT:"),
6353 Child, (IPTR) PopaslObject,
6354 MUIA_Popstring_String, (IPTR) (ncm->ncm_FatFSObj = (APTR) StringObject,
6355 StringFrame,
6356 MUIA_CycleChain, 1,
6357 MUIA_String_AdvanceOnCR, TRUE,
6358 MUIA_String_Contents, (IPTR) ncm->ncm_CDC->cdc_FATFSName,
6359 MUIA_String_MaxLen, 63,
6360 End),
6361 MUIA_Popstring_Button, (IPTR) PopButton(MUII_PopFile),
6362 ASLFR_TitleText, (IPTR) "Select filesystem to use with FAT partitions...",
6363 End,
6364 Child, (IPTR) Label("DosType:"),
6365 Child, (IPTR) (ncm->ncm_FatDosTypeObj = (APTR) StringObject,
6366 StringFrame,
6367 MUIA_HorizWeight, 50,
6368 MUIA_CycleChain, 1,
6369 MUIA_String_AdvanceOnCR, TRUE,
6370 MUIA_String_Contents, (IPTR) dostypebuf,
6371 MUIA_String_Accept, (IPTR) "0123456789abcdefABCDEF",
6372 MUIA_String_MaxLen, 9,
6373 End),
6374 Child, (IPTR) Label("Ctrl:"),
6375 Child, (IPTR) (ncm->ncm_FatControlObj = (APTR) StringObject,
6376 StringFrame,
6377 MUIA_HorizWeight, 50,
6378 MUIA_CycleChain, 1,
6379 MUIA_String_AdvanceOnCR, TRUE,
6380 MUIA_String_Contents, (IPTR) ncm->ncm_CDC->cdc_FATControl,
6381 MUIA_String_MaxLen, 63,
6382 End),
6383 Child, (IPTR) Label("NTFS:"),
6384 Child, (IPTR) PopaslObject,
6385 MUIA_Popstring_String, (IPTR) (ncm->ncm_NTFSObj = (APTR) StringObject,
6386 StringFrame,
6387 MUIA_CycleChain, 1,
6388 MUIA_String_AdvanceOnCR, TRUE,
6389 MUIA_String_Contents, (IPTR) ncm->ncm_CDC->cdc_NTFSName,
6390 MUIA_String_MaxLen, 63,
6391 End),
6392 MUIA_Popstring_Button, (IPTR) PopButton(MUII_PopFile),
6393 ASLFR_TitleText, (IPTR) "Select filesystem to use with NTFS partitions...",
6394 End,
6395 Child, (IPTR) Label("DosType:"),
6396 Child, (IPTR) (ncm->ncm_NTFSDosTypeObj = (APTR) StringObject,
6397 StringFrame,
6398 MUIA_HorizWeight, 50,
6399 MUIA_CycleChain, 1,
6400 MUIA_String_AdvanceOnCR, TRUE,
6401 MUIA_String_Contents, (IPTR) ntfsdostypebuf,
6402 MUIA_String_Accept, (IPTR) "0123456789abcdefABCDEF",
6403 MUIA_String_MaxLen, 9,
6404 End),
6405 Child, (IPTR) Label("Ctrl:"),
6406 Child, (IPTR) (ncm->ncm_NTFSControlObj = (APTR) StringObject,
6407 StringFrame,
6408 MUIA_HorizWeight, 50,
6409 MUIA_CycleChain, 1,
6410 MUIA_String_AdvanceOnCR, TRUE,
6411 MUIA_String_Contents, (IPTR) ncm->ncm_CDC->cdc_NTFSControl,
6412 MUIA_String_MaxLen, 63,
6413 End),
6414 Child, (IPTR) Label("CD/DVD:"),
6415 Child, (IPTR) PopaslObject,
6416 MUIA_Popstring_String, (IPTR) (ncm->ncm_CDFSObj = (APTR) StringObject,
6417 StringFrame,
6418 MUIA_CycleChain, 1,
6419 MUIA_String_AdvanceOnCR, TRUE,
6420 MUIA_String_Contents, (IPTR) ncm->ncm_CDC->cdc_CDFSName,
6421 MUIA_String_MaxLen, 63,
6422 End),
6423 MUIA_Popstring_Button, (IPTR) PopButton(MUII_PopFile),
6424 ASLFR_TitleText, (IPTR) "Select filesystem to use with CD/DVD partitions...",
6425 End,
6426 Child, (IPTR) Label("DosType:"),
6427 Child, (IPTR) (ncm->ncm_CDDosTypeObj = (APTR) StringObject,
6428 StringFrame,
6429 MUIA_HorizWeight, 50,
6430 MUIA_CycleChain, 1,
6431 MUIA_String_AdvanceOnCR, TRUE,
6432 MUIA_String_Contents, (IPTR) cddostypebuf,
6433 MUIA_String_Accept, (IPTR) "0123456789abcdefABCDEF",
6434 MUIA_String_MaxLen, 9,
6435 End),
6436 Child, (IPTR) Label("Ctrl:"),
6437 Child, (IPTR) (ncm->ncm_CDControlObj = (APTR) StringObject,
6438 StringFrame,
6439 MUIA_HorizWeight, 50,
6440 MUIA_CycleChain, 1,
6441 MUIA_String_AdvanceOnCR, TRUE,
6442 MUIA_String_Contents, (IPTR) ncm->ncm_CDC->cdc_CDControl,
6443 MUIA_String_MaxLen, 63,
6444 End),
6445 End,
6446 Child, (IPTR) VSpace(0),
6447 End,
6448 Child, (IPTR) VGroup,
6449 Child, (IPTR) ListviewObject,
6450 MUIA_CycleChain, 1,
6451 MUIA_Listview_List, (IPTR) (ncm->ncm_LunLVObj = (APTR) ListObject,
6452 ReadListFrame,
6453 MUIA_List_Format, (IPTR) bar,
6454 MUIA_List_Title, TRUE,
6455 MUIA_List_DisplayHook, (IPTR) &ncm->ncm_LUNListDisplayHook,
6456 End),
6457 End,
6458 Child, (IPTR) (ncm->ncm_LunGroupObj = (APTR) VGroup,
6459 MUIA_Disabled, TRUE,
6460 Child, (IPTR) VSpace(0),
6461 Child, (IPTR) HGroup,
6462 Child, (IPTR) (ncm->ncm_AutoMountRDBObj = (APTR) ImageObject, ImageButtonFrame,
6463 MUIA_Background, MUII_ButtonBack,
6464 MUIA_CycleChain, 1,
6465 MUIA_InputMode, MUIV_InputMode_Toggle,
6466 MUIA_Image_Spec, MUII_CheckMark,
6467 MUIA_Image_FreeVert, TRUE,
6468 MUIA_Selected, TRUE,
6469 MUIA_ShowSelState, FALSE,
6470 End),
6471 Child, (IPTR) Label("AutoMount RDB partitions"),
6472 Child, (IPTR) HSpace(0),
6473 End,
6474 Child, (IPTR) HGroup,
6475 Child, (IPTR) (ncm->ncm_BootRDBObj = (APTR) ImageObject, ImageButtonFrame,
6476 MUIA_Background, MUII_ButtonBack,
6477 MUIA_CycleChain, 1,
6478 MUIA_InputMode, MUIV_InputMode_Toggle,
6479 MUIA_Image_Spec, MUII_CheckMark,
6480 MUIA_Image_FreeVert, TRUE,
6481 MUIA_Selected, FALSE,
6482 MUIA_ShowSelState, FALSE,
6483 End),
6484 Child, (IPTR) Label("Boot from RDB partitions"),
6485 Child, (IPTR) HSpace(0),
6486 End,
6487 Child, (IPTR) VSpace(0),
6488 Child, (IPTR) HGroup,
6489 Child, (IPTR) (ncm->ncm_AutoMountFATObj = (APTR) ImageObject, ImageButtonFrame,
6490 MUIA_Background, MUII_ButtonBack,
6491 MUIA_CycleChain, 1,
6492 MUIA_InputMode, MUIV_InputMode_Toggle,
6493 MUIA_Image_Spec, MUII_CheckMark,
6494 MUIA_Image_FreeVert, TRUE,
6495 MUIA_Selected, TRUE,
6496 MUIA_ShowSelState, FALSE,
6497 End),
6498 Child, (IPTR) Label("AutoMount FAT/NTFS partitions"),
6499 Child, (IPTR) HSpace(0),
6500 End,
6501 Child, (IPTR) HGroup,
6502 Child, (IPTR) (ncm->ncm_MountAllFATObj = (APTR) ImageObject, ImageButtonFrame,
6503 MUIA_Background, MUII_ButtonBack,
6504 MUIA_CycleChain, 1,
6505 MUIA_InputMode, MUIV_InputMode_Toggle,
6506 MUIA_Image_Spec, MUII_CheckMark,
6507 MUIA_Image_FreeVert, TRUE,
6508 MUIA_Selected, TRUE,
6509 MUIA_ShowSelState, FALSE,
6510 End),
6511 Child, (IPTR) Label("Mount all FAT partitions"),
6512 Child, (IPTR) HSpace(0),
6513 End,
6514 Child, (IPTR) VSpace(0),
6515 Child, (IPTR) HGroup,
6516 Child, (IPTR) (ncm->ncm_AutoMountCDObj = (APTR) ImageObject, ImageButtonFrame,
6517 MUIA_Background, MUII_ButtonBack,
6518 MUIA_CycleChain, 1,
6519 MUIA_InputMode, MUIV_InputMode_Toggle,
6520 MUIA_Image_Spec, MUII_CheckMark,
6521 MUIA_Image_FreeVert, TRUE,
6522 MUIA_Selected, TRUE,
6523 MUIA_ShowSelState, FALSE,
6524 End),
6525 Child, (IPTR) Label("AutoMount CD/DVD"),
6526 Child, (IPTR) HSpace(0),
6527 End,
6528 Child, (IPTR) VSpace(0),
6529 Child, (IPTR) HGroup,
6530 Child, (IPTR) (ncm->ncm_UnmountObj = (APTR) ImageObject, ImageButtonFrame,
6531 MUIA_Background, MUII_ButtonBack,
6532 MUIA_CycleChain, 1,
6533 MUIA_InputMode, MUIV_InputMode_Toggle,
6534 MUIA_Image_Spec, MUII_CheckMark,
6535 MUIA_Image_FreeVert, TRUE,
6536 MUIA_Selected, FALSE,
6537 MUIA_ShowSelState, FALSE,
6538 End),
6539 Child, (IPTR) HGroup,
6540 Child, (IPTR) Label("Unmount partitions after removal"),
6541 Child, (IPTR) HSpace(0),
6542 End,
6543 End,
6544 Child, (IPTR) VSpace(0),
6545 Child, (IPTR) HGroup,
6546 Child, (IPTR) Label("DOSName:"),
6547 Child, (IPTR) (ncm->ncm_FatDOSNameObj = (APTR) StringObject,
6548 StringFrame,
6549 MUIA_CycleChain, 1,
6550 MUIA_String_AdvanceOnCR, TRUE,
6551 MUIA_String_Contents, (IPTR) "UMSD",
6552 MUIA_String_Reject, (IPTR) "/ :?#*",
6553 MUIA_String_MaxLen, 31,
6554 End),
6555 Child, (IPTR) Label("Buffers:"),
6556 Child, (IPTR) (ncm->ncm_FatBuffersObj = (APTR) StringObject,
6557 StringFrame,
6558 MUIA_CycleChain, 1,
6559 MUIA_String_AdvanceOnCR, TRUE,
6560 MUIA_String_Integer, 100,
6561 MUIA_String_Accept, (IPTR) "0123456789",
6562 End),
6563 End,
6564 Child, (IPTR) VSpace(0),
6565 Child, (IPTR) HGroup,
6566 Child, (IPTR) Label("Default " DEVNAME " unit:"),
6567 Child, (IPTR) (ncm->ncm_UnitObj = (APTR) StringObject,
6568 StringFrame,
6569 MUIA_CycleChain, 1,
6570 MUIA_String_AdvanceOnCR, TRUE,
6571 MUIA_String_Integer, 0,
6572 MUIA_String_Accept, (IPTR) "0123456789",
6573 End),
6574 End,
6575 End),
6576 End,
6577 End,
6578 Child, (IPTR) HGroup,
6579 MUIA_Group_SameWidth, TRUE,
6580 Child, (IPTR) (ncm->ncm_UseObj = (APTR) TextObject, ButtonFrame,
6581 MUIA_ShowMe, (IPTR) ncm->ncm_Interface,
6582 MUIA_Background, MUII_ButtonBack,
6583 MUIA_CycleChain, 1,
6584 MUIA_InputMode, MUIV_InputMode_RelVerify,
6585 MUIA_Text_Contents, (IPTR) "\33c Save ",
6586 End),
6587 Child, (IPTR) (ncm->ncm_SetDefaultObj = (APTR) TextObject, ButtonFrame,
6588 MUIA_Background, MUII_ButtonBack,
6589 MUIA_CycleChain, 1,
6590 MUIA_InputMode, MUIV_InputMode_RelVerify,
6591 MUIA_Text_Contents, ncm->ncm_Interface ? (IPTR) "\33c Save as Default " : (IPTR) "\33c Save Defaults ",
6592 End),
6593 Child, (IPTR) (ncm->ncm_CloseObj = (APTR) TextObject, ButtonFrame,
6594 MUIA_Background, MUII_ButtonBack,
6595 MUIA_CycleChain, 1,
6596 MUIA_InputMode, MUIV_InputMode_RelVerify,
6597 MUIA_Text_Contents, (IPTR) "\33c Use ",
6598 End),
6599 End,
6600 End,
6601 End),
6602 End;
6604 if(!ncm->ncm_App)
6606 KPRINTF(10, ("Couldn't create application\n"));
6607 GM_UNIQUENAME(nGUITaskCleanup)(ncm);
6608 return;
6611 if(ncm->ncm_Interface)
6613 cncm = ncm;
6614 while(((struct Node *) cncm)->ln_Succ)
6616 if(cncm->ncm_UnitLUN0 != ncm)
6618 break;
6620 DoMethod(ncm->ncm_LunLVObj, MUIM_List_InsertSingle, cncm, MUIV_List_Insert_Bottom);
6621 cncm = (struct NepClassMS *) ((struct Node *) cncm)->ln_Succ;
6623 } else {
6624 DoMethod(ncm->ncm_LunLVObj, MUIM_List_InsertSingle, ncm, MUIV_List_Insert_Bottom);
6626 DoMethod(ncm->ncm_MainWindow, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
6627 ncm->ncm_App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
6628 DoMethod(ncm->ncm_UseObj, MUIM_Notify, MUIA_Pressed, FALSE,
6629 ncm->ncm_App, 2, MUIM_Application_ReturnID, ID_STORE_CONFIG);
6630 DoMethod(ncm->ncm_SetDefaultObj, MUIM_Notify, MUIA_Pressed, FALSE,
6631 ncm->ncm_App, 2, MUIM_Application_ReturnID, ID_DEF_CONFIG);
6632 DoMethod(ncm->ncm_CloseObj, MUIM_Notify, MUIA_Pressed, FALSE,
6633 ncm->ncm_App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
6635 DoMethod(ncm->ncm_AutoDtxMaxTransObj, MUIM_Notify, MUIA_Pressed, FALSE,
6636 ncm->ncm_App, 2, MUIM_Application_ReturnID, ID_AUTODTXMAXTX);
6637 DoMethod(ncm->ncm_LunLVObj, MUIM_Notify, MUIA_List_Active, MUIV_EveryTime,
6638 ncm->ncm_App, 2, MUIM_Application_ReturnID, ID_SELECT_LUN);
6640 DoMethod(ncm->ncm_AboutMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
6641 ncm->ncm_App, 2, MUIM_Application_ReturnID, ID_ABOUT);
6642 DoMethod(ncm->ncm_UseMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
6643 ncm->ncm_App, 2, MUIM_Application_ReturnID, ID_STORE_CONFIG);
6644 DoMethod(ncm->ncm_SetDefaultMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
6645 ncm->ncm_App, 2, MUIM_Application_ReturnID, ID_DEF_CONFIG);
6646 DoMethod(ncm->ncm_MUIPrefsMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
6647 ncm->ncm_App, 2, MUIM_Application_OpenConfigWindow, 0);
6649 set(ncm->ncm_LunLVObj, MUIA_List_Active, MUIV_List_Active_Top);
6651 IPTR isopen = 0;
6652 IPTR iconify = 0;
6653 ULONG sigs;
6654 ULONG sigmask;
6655 LONG retid;
6657 get(ncm->ncm_App, MUIA_Application_Iconified, &iconify);
6658 set(ncm->ncm_MainWindow, MUIA_Window_Open, TRUE);
6659 get(ncm->ncm_MainWindow, MUIA_Window_Open, &isopen);
6660 if(!(isopen || iconify))
6662 GM_UNIQUENAME(nGUITaskCleanup)(ncm);
6663 return;
6665 sigmask = 0;
6668 retid = DoMethod(ncm->ncm_App, MUIM_Application_NewInput, &sigs);
6669 switch(retid)
6671 case ID_DEF_CONFIG:
6672 case ID_STORE_CONFIG:
6673 case MUIV_Application_ReturnID_Quit:
6675 ULONG tmpflags;
6676 ULONG patchflags;
6677 STRPTR tmpstr;
6679 get(ncm->ncm_NakTimeoutObj, MUIA_Numeric_Value, &ncm->ncm_CDC->cdc_NakTimeout);
6680 get(ncm->ncm_StartupDelayObj, MUIA_Numeric_Value, &ncm->ncm_CDC->cdc_StartupDelay);
6681 patchflags = ncm->ncm_CDC->cdc_PatchFlags & ~(PFF_SINGLE_LUN|PFF_FAKE_INQUIRY|PFF_SIMPLE_SCSI|PFF_NO_RESET|PFF_MODE_XLATE|PFF_DEBUG|PFF_NO_FALLBACK|PFF_REM_SUPPORT|PFF_FIX_INQ36|PFF_CSS_BROKEN|PFF_FIX_CAPACITY|PFF_EMUL_LARGE_BLK);
6682 tmpflags = 0;
6683 get(ncm->ncm_SingleLunObj, MUIA_Selected, &tmpflags);
6684 if(tmpflags) patchflags |= PFF_SINGLE_LUN;
6685 tmpflags = 0;
6686 get(ncm->ncm_FakeInquiryObj, MUIA_Selected, &tmpflags);
6687 if(tmpflags) patchflags |= PFF_FAKE_INQUIRY;
6688 tmpflags = 0;
6689 get(ncm->ncm_SimpleSCSIObj, MUIA_Selected, &tmpflags);
6690 if(tmpflags) patchflags |= PFF_SIMPLE_SCSI;
6691 tmpflags = 0;
6692 get(ncm->ncm_InitialResetObj, MUIA_Selected, &tmpflags);
6693 if(tmpflags) patchflags |= PFF_NO_RESET;
6694 tmpflags = 0;
6695 get(ncm->ncm_XLate610Obj, MUIA_Selected, &tmpflags);
6696 if(tmpflags) patchflags |= PFF_MODE_XLATE;
6697 tmpflags = 0;
6698 get(ncm->ncm_RemSupportObj, MUIA_Selected, &tmpflags);
6699 if(tmpflags) patchflags |= PFF_REM_SUPPORT;
6700 tmpflags = 0;
6701 get(ncm->ncm_FixInquiryObj, MUIA_Selected, &tmpflags);
6702 if(tmpflags) patchflags |= PFF_FIX_INQ36;
6703 tmpflags = 0;
6704 get(ncm->ncm_CSSBrokenObj, MUIA_Selected, &tmpflags);
6705 if(tmpflags) patchflags |= PFF_CSS_BROKEN;
6706 tmpflags = 0;
6707 get(ncm->ncm_FixCapacityObj, MUIA_Selected, &tmpflags);
6708 if(tmpflags) patchflags |= PFF_FIX_CAPACITY;
6709 tmpflags = 0;
6710 get(ncm->ncm_EmulLargeBlkObj, MUIA_Selected, &tmpflags);
6711 if(tmpflags) patchflags |= PFF_EMUL_LARGE_BLK;
6712 tmpflags = 0;
6713 get(ncm->ncm_NoFallbackObj, MUIA_Selected, &tmpflags);
6714 if(tmpflags) patchflags |= PFF_NO_FALLBACK;
6715 tmpflags = 0;
6716 get(ncm->ncm_DebugObj, MUIA_Selected, &tmpflags);
6717 if(tmpflags) patchflags |= PFF_DEBUG;
6718 ncm->ncm_CDC->cdc_PatchFlags = patchflags;
6720 get(ncm->ncm_MaxTransferObj, MUIA_Cycle_Active, &ncm->ncm_CDC->cdc_MaxTransfer);
6722 tmpstr = "";
6723 get(ncm->ncm_FatFSObj, MUIA_String_Contents, &tmpstr);
6724 strncpy(ncm->ncm_CDC->cdc_FATFSName, tmpstr, 63);
6725 tmpstr = "";
6726 get(ncm->ncm_FatControlObj, MUIA_String_Contents, &tmpstr);
6727 strncpy(ncm->ncm_CDC->cdc_FATControl, tmpstr, 63);
6728 tmpstr = "";
6729 get(ncm->ncm_FatDosTypeObj, MUIA_String_Contents, &tmpstr);
6730 ncm->ncm_CDC->cdc_FATDosType = nGetDosType(tmpstr);
6732 tmpstr = "";
6733 get(ncm->ncm_NTFSObj, MUIA_String_Contents, &tmpstr);
6734 strncpy(ncm->ncm_CDC->cdc_NTFSName, tmpstr, 63);
6735 tmpstr = "";
6736 get(ncm->ncm_NTFSControlObj, MUIA_String_Contents, &tmpstr);
6737 strncpy(ncm->ncm_CDC->cdc_NTFSControl, tmpstr, 63);
6738 tmpstr = "";
6739 get(ncm->ncm_NTFSDosTypeObj, MUIA_String_Contents, &tmpstr);
6740 ncm->ncm_CDC->cdc_NTFSDosType = nGetDosType(tmpstr);
6742 tmpstr = "";
6743 get(ncm->ncm_CDFSObj, MUIA_String_Contents, &tmpstr);
6744 strncpy(ncm->ncm_CDC->cdc_CDFSName, tmpstr, 63);
6745 tmpstr = "";
6746 get(ncm->ncm_CDControlObj, MUIA_String_Contents, &tmpstr);
6747 strncpy(ncm->ncm_CDC->cdc_CDControl, tmpstr, 63);
6748 tmpstr = "";
6749 get(ncm->ncm_CDDosTypeObj, MUIA_String_Contents, &tmpstr);
6750 ncm->ncm_CDC->cdc_CDDosType = nGetDosType(tmpstr);
6752 if(ncm->ncm_Interface)
6754 /* copy device config to all luns */
6755 cncm = (struct NepClassMS *) ((struct Node *) ncm)->ln_Succ;
6756 while(((struct Node *) cncm)->ln_Succ)
6758 if(cncm->ncm_UnitLUN0 != ncm)
6760 break;
6762 *(cncm->ncm_CDC) = *(ncm->ncm_CDC);
6763 cncm = (struct NepClassMS *) ((struct Node *) cncm)->ln_Succ;
6766 if(curncm)
6768 get(ncm->ncm_AutoMountFATObj, MUIA_Selected, &curncm->ncm_CUC->cuc_AutoMountFAT);
6769 get(ncm->ncm_MountAllFATObj, MUIA_Selected, &curncm->ncm_CUC->cuc_MountAllFAT);
6770 get(ncm->ncm_AutoMountCDObj, MUIA_Selected, &curncm->ncm_CUC->cuc_AutoMountCD);
6771 tmpstr = "";
6772 get(ncm->ncm_FatDOSNameObj, MUIA_String_Contents, &tmpstr);
6773 strncpy(curncm->ncm_CUC->cuc_FATDOSName, tmpstr, 31);
6774 get(ncm->ncm_FatBuffersObj, MUIA_String_Integer, &curncm->ncm_CUC->cuc_FATBuffers);
6775 get(ncm->ncm_AutoMountRDBObj, MUIA_Selected, &curncm->ncm_CUC->cuc_AutoMountRDB);
6776 get(ncm->ncm_BootRDBObj, MUIA_Selected, &curncm->ncm_CUC->cuc_BootRDB);
6777 get(ncm->ncm_UnitObj, MUIA_String_Integer, &curncm->ncm_CUC->cuc_DefaultUnit);
6778 get(ncm->ncm_UnmountObj, MUIA_Selected, &curncm->ncm_CUC->cuc_AutoUnmount);
6781 if(retid == ID_DEF_CONFIG)
6783 pic = psdGetClsCfg(GM_UNIQUENAME(libname));
6784 if(!pic)
6786 psdSetClsCfg(GM_UNIQUENAME(libname), NULL);
6787 pic = psdGetClsCfg(GM_UNIQUENAME(libname));
6789 if(pic)
6791 psdAddCfgEntry(pic, ncm->ncm_CDC);
6792 psdAddCfgEntry(pic, ncm->ncm_CUC);
6793 psdSaveCfgToDisk(NULL, FALSE);
6796 if(GM_UNIQUENAME(nStoreConfig)(ncm))
6798 if(retid != MUIV_Application_ReturnID_Quit)
6800 psdSaveCfgToDisk(NULL, FALSE);
6802 retid = MUIV_Application_ReturnID_Quit;
6804 break;
6807 case ID_SELECT_LUN:
6809 STRPTR tmpstr;
6810 DoMethod(ncm->ncm_LunLVObj, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &cncm);
6811 if(curncm != cncm)
6813 if(curncm)
6815 get(ncm->ncm_AutoMountFATObj, MUIA_Selected, &curncm->ncm_CUC->cuc_AutoMountFAT);
6816 get(ncm->ncm_MountAllFATObj, MUIA_Selected, &curncm->ncm_CUC->cuc_MountAllFAT);
6817 get(ncm->ncm_AutoMountCDObj, MUIA_Selected, &curncm->ncm_CUC->cuc_AutoMountCD);
6818 tmpstr = "";
6819 get(ncm->ncm_FatDOSNameObj, MUIA_String_Contents, &tmpstr);
6820 strncpy(curncm->ncm_CUC->cuc_FATDOSName, tmpstr, 31);
6821 get(ncm->ncm_FatBuffersObj, MUIA_String_Integer, &curncm->ncm_CUC->cuc_FATBuffers);
6822 get(ncm->ncm_AutoMountRDBObj, MUIA_Selected, &curncm->ncm_CUC->cuc_AutoMountRDB);
6823 get(ncm->ncm_BootRDBObj, MUIA_Selected, &curncm->ncm_CUC->cuc_BootRDB);
6824 get(ncm->ncm_UnitObj, MUIA_String_Integer, &curncm->ncm_CUC->cuc_DefaultUnit);
6825 get(ncm->ncm_UnmountObj, MUIA_Selected, &curncm->ncm_CUC->cuc_AutoUnmount);
6828 if((curncm = cncm))
6830 set(ncm->ncm_AutoMountFATObj, MUIA_Selected, curncm->ncm_CUC->cuc_AutoMountFAT);
6831 set(ncm->ncm_MountAllFATObj, MUIA_Selected, curncm->ncm_CUC->cuc_MountAllFAT);
6832 set(ncm->ncm_AutoMountCDObj, MUIA_Selected, curncm->ncm_CUC->cuc_AutoMountCD);
6833 set(ncm->ncm_FatDOSNameObj, MUIA_String_Contents, curncm->ncm_CUC->cuc_FATDOSName);
6834 set(ncm->ncm_FatBuffersObj, MUIA_String_Integer, curncm->ncm_CUC->cuc_FATBuffers);
6835 set(ncm->ncm_AutoMountRDBObj, MUIA_Selected, curncm->ncm_CUC->cuc_AutoMountRDB);
6836 set(ncm->ncm_BootRDBObj, MUIA_Selected, curncm->ncm_CUC->cuc_BootRDB);
6837 set(ncm->ncm_UnitObj, MUIA_String_Integer, curncm->ncm_CUC->cuc_DefaultUnit);
6838 set(ncm->ncm_UnmountObj, MUIA_Selected, curncm->ncm_CUC->cuc_AutoUnmount);
6839 set(ncm->ncm_LunGroupObj, MUIA_Disabled, FALSE);
6840 } else {
6841 set(ncm->ncm_LunGroupObj, MUIA_Disabled, TRUE);
6843 break;
6845 case ID_AUTODTXMAXTX:
6847 DoMethod(ncm->ncm_LunLVObj, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &cncm);
6848 set(ncm->ncm_App, MUIA_Application_Sleep, TRUE);
6849 AutoDetectMaxTransfer(cncm);
6850 set(ncm->ncm_App, MUIA_Application_Sleep, FALSE);
6851 set(ncm->ncm_MaxTransferObj, MUIA_Cycle_Active, ncm->ncm_CDC->cdc_MaxTransfer);
6852 break;
6855 case ID_ABOUT:
6856 MUI_RequestA(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Blimey!", VERSION_STRING "\n\nCode for AutoMounting based\non work by Thore Böckelmann.", NULL);
6857 break;
6859 if(retid == MUIV_Application_ReturnID_Quit)
6861 break;
6863 if(sigs)
6865 sigs = Wait(sigs | sigmask | SIGBREAKF_CTRL_C);
6866 if(sigs & SIGBREAKF_CTRL_C)
6868 break;
6871 } while(TRUE);
6872 set(ncm->ncm_MainWindow, MUIA_Window_Open, FALSE);
6874 GM_UNIQUENAME(nGUITaskCleanup)(ncm);
6876 AROS_USERFUNC_EXIT
6878 /* \\\ */
6880 /* /// "AutoDetectMaxTransfer()" */
6881 void AutoDetectMaxTransfer(struct NepClassMS *cncm)
6883 LONG res;
6884 UBYTE *memory;
6885 UBYTE *orgbuffer;
6886 UBYTE *cmpbuffer;
6887 ULONG *lbufptr;
6888 struct MsgPort *mp;
6889 struct IOStdReq *ioreq;
6890 struct NepClassMS *ncm = cncm->ncm_UnitLUN0;
6891 ULONG numblocks;
6892 ULONG memsize = 4<<20;
6893 ULONG block;
6894 ULONG maxtrans;
6895 LONG ioerr;
6896 BOOL bail = FALSE;
6897 ULONG cnt;
6899 res = MUI_RequestA(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Continue|Cancel",
6900 "Auto-detection of the maximum transfer rate\n"
6901 "will need some media inserted in the selected\n"
6902 "LUN of the drive. Moreover, the contents of the\n"
6903 "media may not be empty.\n"
6904 "The test will need about 4 MB of temporary memory!\n"
6905 "No data is written to the disk!", NULL);
6906 if(!res)
6908 return;
6910 if(!cncm->ncm_UnitReady)
6912 MUI_RequestA(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Argh!", "No disk/media in drive!", NULL);
6913 return;
6915 memory = (UBYTE *) AllocVec(memsize, MEMF_CLEAR);
6916 if(!memory)
6918 MUI_RequestA(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Argh!", "Sorry, out of memory!", NULL);
6919 return;
6921 mp = CreateMsgPort();
6922 if(mp)
6924 ioreq = (struct IOStdReq *) CreateIORequest(mp, sizeof(struct IOStdReq));
6925 if(ioreq)
6927 if(!OpenDevice(DEVNAME, cncm->ncm_UnitNo, (struct IORequest *) ioreq, 0))
6929 ncm->ncm_CDC->cdc_MaxTransfer = 0;
6930 if(!cncm->ncm_BlockSize)
6932 ioreq->io_Command = TD_GETGEOMETRY;
6933 ioreq->io_Data = &cncm->ncm_Geometry;
6934 ioreq->io_Length = sizeof(cncm->ncm_Geometry);
6935 DoIO((struct IORequest *) ioreq);
6938 numblocks = (memsize>>1) / cncm->ncm_BlockSize;
6939 orgbuffer = memory;
6940 cmpbuffer = &memory[memsize>>1];
6944 for(block = 0; block < numblocks; block++)
6946 ioreq->io_Command = TD_READ64;
6947 ioreq->io_Actual = 0;
6948 ioreq->io_Offset = block*cncm->ncm_BlockSize;
6949 ioreq->io_Length = cncm->ncm_BlockSize;
6950 ioreq->io_Data = &orgbuffer[ioreq->io_Offset];
6951 ioerr = DoIO((struct IORequest *) ioreq);
6952 if(ioerr)
6954 MUI_Request(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, ">:-{", "Error %ld while reading block %ld!\nAborting process...", ioerr, block);
6955 bail = TRUE;
6956 break;
6959 if(bail) break;
6963 maxtrans = (1UL<<(ncm->ncm_CDC->cdc_MaxTransfer+16));
6964 // do a quick check on block contents
6965 numblocks = (memsize>>1) / maxtrans;
6966 if(numblocks)
6968 for(block = 0; block < numblocks-1; block++)
6970 if(!memcmp(&orgbuffer[block * maxtrans], &orgbuffer[(block + 1) * maxtrans], (size_t) maxtrans))
6972 res = MUI_RequestA(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Continue|Abort", "Sorry, media contents do not\nseem to be diversive enough!\nResults might be wrong!", NULL);
6973 if(!res)
6975 bail = TRUE;
6977 break;
6981 if(bail) break;
6983 // fill compare buffer with garbage
6984 cnt = (memsize>>3);
6985 lbufptr = (ULONG *) cmpbuffer;
6988 *lbufptr = (IPTR) lbufptr;
6989 lbufptr++;
6991 while(--cnt);
6993 // start reading the chunks
6994 numblocks = (memsize>>1) / maxtrans;
6995 for(block = 0; block < numblocks; block++)
6997 ioreq->io_Command = TD_READ64;
6998 ioreq->io_Actual = 0;
6999 ioreq->io_Offset = block*maxtrans;
7000 ioreq->io_Length = maxtrans;
7001 ioreq->io_Data = &cmpbuffer[ioreq->io_Offset];
7002 ioerr = DoIO((struct IORequest *) ioreq);
7003 if(ioerr)
7005 MUI_Request(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, ">:-{", "Error %ld while reading at offset %ld!\nAborting process...", ioerr, &ioreq->io_Offset);
7006 bail = TRUE;
7007 break;
7009 if(memcmp(&orgbuffer[ioreq->io_Offset], &cmpbuffer[ioreq->io_Offset], (size_t) maxtrans))
7011 MUI_Request(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Hmpf!", "Reading failed at MaxTrans = %08lx", maxtrans-1);
7012 if(ncm->ncm_CDC->cdc_MaxTransfer)
7014 ncm->ncm_CDC->cdc_MaxTransfer--;
7016 bail = TRUE;
7017 break;
7020 if(bail) break;
7021 //MUI_Request(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Wow!", "Test with %ld (%ld) succeeded!", maxtrans, numblocks);
7022 if(ncm->ncm_CDC->cdc_MaxTransfer < 5)
7024 ncm->ncm_CDC->cdc_MaxTransfer++;
7025 } else {
7026 break;
7028 } while(TRUE);
7029 if(!bail)
7031 MUI_RequestA(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Wow!", "Test succeeded, setting MaxTrans to maximum value!", NULL);
7033 } while(FALSE);
7034 CloseDevice((struct IORequest *) ioreq);
7035 } else {
7036 MUI_RequestA(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Argh!", "Couldn't open device!", NULL);
7038 DeleteIORequest((struct IORequest *) ioreq);
7039 } else {
7040 MUI_RequestA(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Argh!", "No IOReq!", NULL);
7042 DeleteMsgPort(mp);
7043 } else {
7044 MUI_RequestA(ncm->ncm_App, ncm->ncm_MainWindow, 0, NULL, "Argh!", "No MsgPort!", NULL);
7046 FreeVec(memory);
7048 /* \\\ */
7050 /* /// "nGUITaskCleanup()" */
7051 void GM_UNIQUENAME(nGUITaskCleanup)(struct NepClassMS *ncm)
7053 if(ncm->ncm_App)
7055 MUI_DisposeObject(ncm->ncm_App);
7056 ncm->ncm_App = NULL;
7058 if(MUIMasterBase)
7060 CloseLibrary(MUIMasterBase);
7061 MUIMasterBase = NULL;
7063 if(IntuitionBase)
7065 CloseLibrary(IntuitionBase);
7066 IntuitionBase = NULL;
7068 if(ps)
7070 CloseLibrary(ps);
7071 ps = NULL;
7073 Forbid();
7074 ncm->ncm_GUIBinding = NULL;
7075 ncm->ncm_GUITask = NULL;
7076 --ncm->ncm_ClsBase->nh_Library.lib_OpenCnt;
7078 /* \\\ */
7080 /* /// "LUNListDisplayHook()" */
7081 AROS_UFH3(LONG, GM_UNIQUENAME(LUNListDisplayHook),
7082 AROS_UFHA(struct Hook *, hook, A0),
7083 AROS_UFHA(char **, strarr, A2),
7084 AROS_UFHA(struct NepClassMS *, ncm, A1))
7086 AROS_USERFUNC_INIT
7088 //struct NepMSBase *nh = ncm->ncm_ClsBase;
7089 if(ncm)
7091 *strarr++ = ncm->ncm_LUNNumStr;
7092 *strarr = ncm->ncm_LUNIDStr;
7093 } else {
7094 *strarr++ = "\33l\33uLUN";
7095 *strarr = "\33l\33uID";
7097 return(0);
7099 AROS_USERFUNC_EXIT
7101 /* \\\ */