af1c50a944062f78bf88f501708d711fe065a4cc
[SCSI2SD-V6.git] / software / SCSI2SD / src / disk.c
1 // Copyright (C) 2013 Michael McMaster <michael@codesrc.com>
2 // Copyright (C) 2014 Doug Brown <doug@downtowndougbrown.com>
3 //
4 // This file is part of SCSI2SD.
5 //
6 // SCSI2SD is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // SCSI2SD is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
18 #pragma GCC push_options
19 #pragma GCC optimize("-flto")
20
21 #include "device.h"
22 #include "scsi.h"
23 #include "scsiPhy.h"
24 #include "config.h"
25 #include "debug.h"
26 #include "debug.h"
27 #include "disk.h"
28 #include "sd.h"
29 #include "time.h"
30
31 #include <string.h>
32
33 // Global
34 BlockDevice blockDev;
35 Transfer transfer;
36
37 static int doSdInit()
38 {
39 int result = 0;
40 if (blockDev.state & DISK_PRESENT)
41 {
42 result = sdInit();
43
44 if (result)
45 {
46 blockDev.state = blockDev.state | DISK_INITIALISED;
47 }
48 }
49 return result;
50 }
51
52 // Callback once all data has been read in the data out phase.
53 static void doFormatUnitComplete(void)
54 {
55 // TODO start writing the initialisation pattern to the SD
56 // card
57 scsiDev.phase = STATUS;
58 }
59
60 static void doFormatUnitSkipData(int bytes)
61 {
62 // We may not have enough memory to store the initialisation pattern and
63 // defect list data. Since we're not making use of it yet anyway, just
64 // discard the bytes.
65 scsiEnterPhase(DATA_OUT);
66 int i;
67 for (i = 0; i < bytes; ++i)
68 {
69 scsiReadByte();
70 }
71 }
72
73 // Callback from the data out phase.
74 static void doFormatUnitPatternHeader(void)
75 {
76 int defectLength =
77 ((((uint16_t)scsiDev.data[2])) << 8) +
78 scsiDev.data[3];
79
80 int patternLength =
81 ((((uint16_t)scsiDev.data[4 + 2])) << 8) +
82 scsiDev.data[4 + 3];
83
84 doFormatUnitSkipData(defectLength + patternLength);
85 doFormatUnitComplete();
86 }
87
88 // Callback from the data out phase.
89 static void doFormatUnitHeader(void)
90 {
91 int IP = (scsiDev.data[1] & 0x08) ? 1 : 0;
92 int DSP = (scsiDev.data[1] & 0x04) ? 1 : 0;
93
94 if (! DSP) // disable save parameters
95 {
96 // Save the "MODE SELECT savable parameters"
97 configSave(
98 scsiDev.target->targetId,
99 scsiDev.target->liveCfg.bytesPerSector);
100 }
101
102 if (IP)
103 {
104 // We need to read the initialisation pattern header first.
105 scsiDev.dataLen += 4;
106 scsiDev.phase = DATA_OUT;
107 scsiDev.postDataOutHook = doFormatUnitPatternHeader;
108 }
109 else
110 {
111 // Read the defect list data
112 int defectLength =
113 ((((uint16_t)scsiDev.data[2])) << 8) +
114 scsiDev.data[3];
115 doFormatUnitSkipData(defectLength);
116 doFormatUnitComplete();
117 }
118 }
119
120 static void doReadCapacity()
121 {
122 uint32_t lba = (((uint32) scsiDev.cdb[2]) << 24) +
123 (((uint32) scsiDev.cdb[3]) << 16) +
124 (((uint32) scsiDev.cdb[4]) << 8) +
125 scsiDev.cdb[5];
126 int pmi = scsiDev.cdb[8] & 1;
127
128 uint32_t capacity = getScsiCapacity(
129 scsiDev.target->cfg->sdSectorStart,
130 scsiDev.target->liveCfg.bytesPerSector,
131 scsiDev.target->cfg->scsiSectors);
132
133 if (!pmi && lba)
134 {
135 // error.
136 // We don't do anything with the "partial medium indicator", and
137 // assume that delays are constant across each block. But the spec
138 // says we must return this error if pmi is specified incorrectly.
139 scsiDev.status = CHECK_CONDITION;
140 scsiDev.target->sense.code = ILLEGAL_REQUEST;
141 scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
142 scsiDev.phase = STATUS;
143 }
144 else if (capacity > 0)
145 {
146 uint32_t highestBlock = capacity - 1;
147
148 scsiDev.data[0] = highestBlock >> 24;
149 scsiDev.data[1] = highestBlock >> 16;
150 scsiDev.data[2] = highestBlock >> 8;
151 scsiDev.data[3] = highestBlock;
152
153 uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
154 scsiDev.data[4] = bytesPerSector >> 24;
155 scsiDev.data[5] = bytesPerSector >> 16;
156 scsiDev.data[6] = bytesPerSector >> 8;
157 scsiDev.data[7] = bytesPerSector;
158 scsiDev.dataLen = 8;
159 scsiDev.phase = DATA_IN;
160 }
161 else
162 {
163 scsiDev.status = CHECK_CONDITION;
164 scsiDev.target->sense.code = NOT_READY;
165 scsiDev.target->sense.asc = MEDIUM_NOT_PRESENT;
166 scsiDev.phase = STATUS;
167 }
168 }
169
170 static void doWrite(uint32 lba, uint32 blocks)
171 {
172 if (unlikely(blockDev.state & DISK_WP) ||
173 unlikely(scsiDev.target->cfg->deviceType == CONFIG_OPTICAL))
174
175 {
176 scsiDev.status = CHECK_CONDITION;
177 scsiDev.target->sense.code = ILLEGAL_REQUEST;
178 scsiDev.target->sense.asc = WRITE_PROTECTED;
179 scsiDev.phase = STATUS;
180 }
181 else if (unlikely(((uint64) lba) + blocks >
182 getScsiCapacity(
183 scsiDev.target->cfg->sdSectorStart,
184 scsiDev.target->liveCfg.bytesPerSector,
185 scsiDev.target->cfg->scsiSectors
186 )
187 ))
188 {
189 scsiDev.status = CHECK_CONDITION;
190 scsiDev.target->sense.code = ILLEGAL_REQUEST;
191 scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
192 scsiDev.phase = STATUS;
193 }
194 else
195 {
196 transfer.dir = TRANSFER_WRITE;
197 transfer.lba = lba;
198 transfer.blocks = blocks;
199 transfer.currentBlock = 0;
200 scsiDev.phase = DATA_OUT;
201 scsiDev.dataLen = scsiDev.target->liveCfg.bytesPerSector;
202 scsiDev.dataPtr = scsiDev.target->liveCfg.bytesPerSector;
203
204 // No need for single-block writes atm. Overhead of the
205 // multi-block write is minimal.
206 transfer.multiBlock = 1;
207
208 sdWriteMultiSectorPrep();
209 }
210 }
211
212
213 static void doRead(uint32 lba, uint32 blocks)
214 {
215 uint32_t capacity = getScsiCapacity(
216 scsiDev.target->cfg->sdSectorStart,
217 scsiDev.target->liveCfg.bytesPerSector,
218 scsiDev.target->cfg->scsiSectors);
219 if (unlikely(((uint64) lba) + blocks > capacity))
220 {
221 scsiDev.status = CHECK_CONDITION;
222 scsiDev.target->sense.code = ILLEGAL_REQUEST;
223 scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
224 scsiDev.phase = STATUS;
225 }
226 else
227 {
228 transfer.dir = TRANSFER_READ;
229 transfer.lba = lba;
230 transfer.blocks = blocks;
231 transfer.currentBlock = 0;
232 scsiDev.phase = DATA_IN;
233 scsiDev.dataLen = 0; // No data yet
234
235 if ((blocks == 1) ||
236 unlikely(((uint64) lba) + blocks == capacity)
237 )
238 {
239 // We get errors on reading the last sector using a multi-sector
240 // read :-(
241 transfer.multiBlock = 0;
242 }
243 else
244 {
245 transfer.multiBlock = 1;
246 sdReadMultiSectorPrep();
247 }
248 }
249 }
250
251 static void doSeek(uint32 lba)
252 {
253 if (lba >=
254 getScsiCapacity(
255 scsiDev.target->cfg->sdSectorStart,
256 scsiDev.target->liveCfg.bytesPerSector,
257 scsiDev.target->cfg->scsiSectors)
258 )
259 {
260 scsiDev.status = CHECK_CONDITION;
261 scsiDev.target->sense.code = ILLEGAL_REQUEST;
262 scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
263 scsiDev.phase = STATUS;
264 }
265 }
266
267 static int doTestUnitReady()
268 {
269 int ready = 1;
270 if (likely(blockDev.state == (DISK_STARTED | DISK_PRESENT | DISK_INITIALISED)))
271 {
272 // nothing to do.
273 }
274 else if (unlikely(!(blockDev.state & DISK_STARTED)))
275 {
276 ready = 0;
277 scsiDev.status = CHECK_CONDITION;
278 scsiDev.target->sense.code = NOT_READY;
279 scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED;
280 scsiDev.phase = STATUS;
281 }
282 else if (unlikely(!(blockDev.state & DISK_PRESENT)))
283 {
284 ready = 0;
285 scsiDev.status = CHECK_CONDITION;
286 scsiDev.target->sense.code = NOT_READY;
287 scsiDev.target->sense.asc = MEDIUM_NOT_PRESENT;
288 scsiDev.phase = STATUS;
289 }
290 else if (unlikely(!(blockDev.state & DISK_INITIALISED)))
291 {
292 ready = 0;
293 scsiDev.status = CHECK_CONDITION;
294 scsiDev.target->sense.code = NOT_READY;
295 scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_READY_CAUSE_NOT_REPORTABLE;
296 scsiDev.phase = STATUS;
297 }
298 return ready;
299 }
300
301 // Handle direct-access scsi device commands
302 int scsiDiskCommand()
303 {
304 int commandHandled = 1;
305
306 uint8 command = scsiDev.cdb[0];
307 if (unlikely(command == 0x1B))
308 {
309 // START STOP UNIT
310 // Enable or disable media access operations.
311 // Ignore load/eject requests. We can't do that.
312 //int immed = scsiDev.cdb[1] & 1;
313 int start = scsiDev.cdb[4] & 1;
314
315 if (start)
316 {
317 blockDev.state = blockDev.state | DISK_STARTED;
318 if (!(blockDev.state & DISK_INITIALISED))
319 {
320 doSdInit();
321 }
322 }
323 else
324 {
325 blockDev.state &= ~DISK_STARTED;
326 }
327 }
328 else if (unlikely(command == 0x00))
329 {
330 // TEST UNIT READY
331 doTestUnitReady();
332 }
333 else if (unlikely(!doTestUnitReady()))
334 {
335 // Status and sense codes already set by doTestUnitReady
336 }
337 else if (likely(command == 0x08))
338 {
339 // READ(6)
340 uint32 lba =
341 (((uint32) scsiDev.cdb[1] & 0x1F) << 16) +
342 (((uint32) scsiDev.cdb[2]) << 8) +
343 scsiDev.cdb[3];
344 uint32 blocks = scsiDev.cdb[4];
345 if (unlikely(blocks == 0)) blocks = 256;
346 doRead(lba, blocks);
347 }
348 else if (likely(command == 0x28))
349 {
350 // READ(10)
351 // Ignore all cache control bits - we don't support a memory cache.
352
353 uint32 lba =
354 (((uint32) scsiDev.cdb[2]) << 24) +
355 (((uint32) scsiDev.cdb[3]) << 16) +
356 (((uint32) scsiDev.cdb[4]) << 8) +
357 scsiDev.cdb[5];
358 uint32 blocks =
359 (((uint32) scsiDev.cdb[7]) << 8) +
360 scsiDev.cdb[8];
361
362 doRead(lba, blocks);
363 }
364 else if (likely(command == 0x0A))
365 {
366 // WRITE(6)
367 uint32 lba =
368 (((uint32) scsiDev.cdb[1] & 0x1F) << 16) +
369 (((uint32) scsiDev.cdb[2]) << 8) +
370 scsiDev.cdb[3];
371 uint32 blocks = scsiDev.cdb[4];
372 if (unlikely(blocks == 0)) blocks = 256;
373 doWrite(lba, blocks);
374 }
375 else if (likely(command == 0x2A) || // WRITE(10)
376 unlikely(command == 0x2E)) // WRITE AND VERIFY
377 {
378 // Ignore all cache control bits - we don't support a memory cache.
379 // Don't bother verifying either. The SD card likely stores ECC
380 // along with each flash row.
381
382 uint32 lba =
383 (((uint32) scsiDev.cdb[2]) << 24) +
384 (((uint32) scsiDev.cdb[3]) << 16) +
385 (((uint32) scsiDev.cdb[4]) << 8) +
386 scsiDev.cdb[5];
387 uint32 blocks =
388 (((uint32) scsiDev.cdb[7]) << 8) +
389 scsiDev.cdb[8];
390
391 doWrite(lba, blocks);
392 }
393
394 else if (unlikely(command == 0x04))
395 {
396 // FORMAT UNIT
397 // We don't really do any formatting, but we need to read the correct
398 // number of bytes in the DATA_OUT phase to make the SCSI host happy.
399
400 int fmtData = (scsiDev.cdb[1] & 0x10) ? 1 : 0;
401 if (fmtData)
402 {
403 // We need to read the parameter list, but we don't know how
404 // big it is yet. Start with the header.
405 scsiDev.dataLen = 4;
406 scsiDev.phase = DATA_OUT;
407 scsiDev.postDataOutHook = doFormatUnitHeader;
408 }
409 else
410 {
411 // No data to read, we're already finished!
412 }
413 }
414 else if (unlikely(command == 0x25))
415 {
416 // READ CAPACITY
417 doReadCapacity();
418 }
419 else if (unlikely(command == 0x0B))
420 {
421 // SEEK(6)
422 uint32 lba =
423 (((uint32) scsiDev.cdb[1] & 0x1F) << 16) +
424 (((uint32) scsiDev.cdb[2]) << 8) +
425 scsiDev.cdb[3];
426
427 doSeek(lba);
428 }
429
430 else if (unlikely(command == 0x2B))
431 {
432 // SEEK(10)
433 uint32 lba =
434 (((uint32) scsiDev.cdb[2]) << 24) +
435 (((uint32) scsiDev.cdb[3]) << 16) +
436 (((uint32) scsiDev.cdb[4]) << 8) +
437 scsiDev.cdb[5];
438
439 doSeek(lba);
440 }
441 else if (unlikely(command == 0x36))
442 {
443 // LOCK UNLOCK CACHE
444 // We don't have a cache to lock data into. do nothing.
445 }
446 else if (unlikely(command == 0x34))
447 {
448 // PRE-FETCH.
449 // We don't have a cache to pre-fetch into. do nothing.
450 }
451 else if (unlikely(command == 0x1E))
452 {
453 // PREVENT ALLOW MEDIUM REMOVAL
454 // Not much we can do to prevent the user removing the SD card.
455 // do nothing.
456 }
457 else if (unlikely(command == 0x01))
458 {
459 // REZERO UNIT
460 // Set the lun to a vendor-specific state. Ignore.
461 }
462 else if (unlikely(command == 0x35))
463 {
464 // SYNCHRONIZE CACHE
465 // We don't have a cache. do nothing.
466 }
467 else if (unlikely(command == 0x2F))
468 {
469 // VERIFY
470 // TODO: When they supply data to verify, we should read the data and
471 // verify it. If they don't supply any data, just say success.
472 if ((scsiDev.cdb[1] & 0x02) == 0)
473 {
474 // They are asking us to do a medium verification with no data
475 // comparison. Assume success, do nothing.
476 }
477 else
478 {
479 // TODO. This means they are supplying data to verify against.
480 // Technically we should probably grab the data and compare it.
481 scsiDev.status = CHECK_CONDITION;
482 scsiDev.target->sense.code = ILLEGAL_REQUEST;
483 scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
484 scsiDev.phase = STATUS;
485 }
486 }
487 else
488 {
489 commandHandled = 0;
490 }
491
492 return commandHandled;
493 }
494
495 void scsiDiskPoll()
496 {
497 debugPause(); // TODO comment re. timeouts.
498
499 if (scsiDev.phase == DATA_IN &&
500 transfer.currentBlock != transfer.blocks)
501 {
502 scsiEnterPhase(DATA_IN);
503
504 int totalSDSectors =
505 transfer.blocks *
506 SDSectorsPerSCSISector(scsiDev.target->liveCfg.bytesPerSector);
507 uint32_t sdLBA =
508 SCSISector2SD(
509 scsiDev.target->cfg->sdSectorStart,
510 scsiDev.target->liveCfg.bytesPerSector,
511 transfer.lba);
512
513 const int sdPerScsi =
514 SDSectorsPerSCSISector(scsiDev.target->liveCfg.bytesPerSector);
515 int buffers = sizeof(scsiDev.data) / SD_SECTOR_SIZE;
516 int prep = 0;
517 int i = 0;
518 int scsiActive = 0;
519 int sdActive = 0;
520 while ((i < totalSDSectors) &&
521 likely(scsiDev.phase == DATA_IN) &&
522 likely(!scsiDev.resetFlag))
523 {
524 // Wait for the next DMA interrupt. It's beneficial to halt the
525 // processor to give the DMA controller more memory bandwidth to
526 // work with.
527 // We're optimistically assuming a race condition won't occur
528 // between these checks and the interrupt handers. The 1ms
529 // systick timer interrupt saves us on the event of a race.
530 int scsiBusy = scsiDMABusy();
531 int sdBusy = sdDMABusy();
532 if (scsiBusy && sdBusy) __WFI();
533
534 if (sdActive && !sdBusy && sdReadSectorDMAPoll())
535 {
536 sdActive = 0;
537 prep++;
538 }
539 else if (!sdActive &&
540 (prep - i < buffers) &&
541 (prep < totalSDSectors))
542 {
543 // Start an SD transfer if we have space.
544 if (transfer.multiBlock)
545 {
546 sdReadMultiSectorDMA(&scsiDev.data[SD_SECTOR_SIZE * (prep % buffers)]);
547 }
548 else
549 {
550 sdReadSingleSectorDMA(sdLBA + prep, &scsiDev.data[SD_SECTOR_SIZE * (prep % buffers)]);
551 }
552 sdActive = 1;
553 }
554
555 if (scsiActive && !scsiBusy && scsiWriteDMAPoll())
556 {
557 scsiActive = 0;
558 ++i;
559 }
560 else if (!scsiActive && ((prep - i) > 0))
561 {
562 int dmaBytes = SD_SECTOR_SIZE;
563 if ((i % sdPerScsi) == (sdPerScsi - 1))
564 {
565 dmaBytes = scsiDev.target->liveCfg.bytesPerSector % SD_SECTOR_SIZE;
566 if (dmaBytes == 0) dmaBytes = SD_SECTOR_SIZE;
567 }
568 scsiWriteDMA(&scsiDev.data[SD_SECTOR_SIZE * (i % buffers)], dmaBytes);
569 scsiActive = 1;
570 }
571 }
572 if (scsiDev.phase == DATA_IN)
573 {
574 scsiDev.phase = STATUS;
575 }
576 scsiDiskReset();
577 }
578 else if (scsiDev.phase == DATA_OUT &&
579 transfer.currentBlock != transfer.blocks)
580 {
581 scsiEnterPhase(DATA_OUT);
582
583 const int sdPerScsi =
584 SDSectorsPerSCSISector(scsiDev.target->liveCfg.bytesPerSector);
585 int totalSDSectors = transfer.blocks * sdPerScsi;
586 int buffers = sizeof(scsiDev.data) / SD_SECTOR_SIZE;
587 int prep = 0;
588 int i = 0;
589 int scsiDisconnected = 0;
590 int scsiComplete = 0;
591 uint32_t lastActivityTime = getTime_ms();
592 int scsiActive = 0;
593 int sdActive = 0;
594
595 while ((i < totalSDSectors) &&
596 (likely(scsiDev.phase == DATA_OUT) || // scsiDisconnect keeps our phase.
597 scsiComplete) &&
598 likely(!scsiDev.resetFlag))
599 {
600 // Wait for the next DMA interrupt. It's beneficial to halt the
601 // processor to give the DMA controller more memory bandwidth to
602 // work with.
603 // We're optimistically assuming a race condition won't occur
604 // between these checks and the interrupt handers. The 1ms
605 // systick timer interrupt saves us on the event of a race.
606 int scsiBusy = scsiDMABusy();
607 int sdBusy = sdDMABusy();
608 if (scsiBusy && sdBusy) __WFI();
609
610 if (sdActive && !sdBusy && sdWriteSectorDMAPoll(i == (totalSDSectors - 1)))
611 {
612 sdActive = 0;
613 i++;
614 }
615 else if (!sdActive && ((prep - i) > 0))
616 {
617 // Start an SD transfer if we have space.
618 sdWriteMultiSectorDMA(&scsiDev.data[SD_SECTOR_SIZE * (i % buffers)]);
619 sdActive = 1;
620 }
621
622 uint32_t now = getTime_ms();
623
624 if (scsiActive && !scsiBusy && scsiReadDMAPoll())
625 {
626 scsiActive = 0;
627 ++prep;
628 lastActivityTime = now;
629 }
630 else if (!scsiActive &&
631 ((prep - i) < buffers) &&
632 (prep < totalSDSectors) &&
633 likely(!scsiDisconnected))
634 {
635 int dmaBytes = SD_SECTOR_SIZE;
636 if ((prep % sdPerScsi) == (sdPerScsi - 1))
637 {
638 dmaBytes = scsiDev.target->liveCfg.bytesPerSector % SD_SECTOR_SIZE;
639 if (dmaBytes == 0) dmaBytes = SD_SECTOR_SIZE;
640 }
641 scsiReadDMA(&scsiDev.data[SD_SECTOR_SIZE * (prep % buffers)], dmaBytes);
642 scsiActive = 1;
643 }
644 else if (
645 (scsiActive == 0) &&
646 likely(!scsiDisconnected) &&
647 unlikely(scsiDev.discPriv) &&
648 unlikely(diffTime_ms(lastActivityTime, now) >= 20) &&
649 likely(scsiDev.phase == DATA_OUT))
650 {
651 // We're transferring over the SCSI bus faster than the SD card
652 // can write. There is no more buffer space once we've finished
653 // this SCSI transfer.
654 // The NCR 53C700 interface chips have a 250ms "byte-to-byte"
655 // timeout buffer. SD card writes are supposed to complete
656 // within 200ms, but sometimes they don't.
657 // The NCR 53C700 series is used on HP 9000 workstations.
658 scsiDisconnect();
659 scsiDisconnected = 1;
660 lastActivityTime = getTime_ms();
661 }
662 else if (unlikely(scsiDisconnected) &&
663 (
664 (prep == i) || // Buffers empty.
665 // Send some messages every 100ms so we don't timeout.
666 // At a minimum, a reselection involves an IDENTIFY message.
667 unlikely(diffTime_ms(lastActivityTime, now) >= 100)
668 ))
669 {
670 int reconnected = scsiReconnect();
671 if (reconnected)
672 {
673 scsiDisconnected = 0;
674 lastActivityTime = getTime_ms(); // Don't disconnect immediately.
675 }
676 else if (diffTime_ms(lastActivityTime, getTime_ms()) >= 10000)
677 {
678 // Give up after 10 seconds of trying to reconnect.
679 scsiDev.resetFlag = 1;
680 }
681 }
682 else if (
683 likely(!scsiComplete) &&
684 (sdActive == 1) &&
685 (prep == totalSDSectors) && // All scsi data read and buffered
686 likely(!scsiDev.discPriv) && // Prefer disconnect where possible.
687 unlikely(diffTime_ms(lastActivityTime, now) >= 150) &&
688
689 likely(scsiDev.phase == DATA_OUT) &&
690 !(scsiDev.cdb[scsiDev.cdbLen - 1] & 0x01) // Not linked command
691 )
692 {
693 // We're transferring over the SCSI bus faster than the SD card
694 // can write. All data is buffered, and we're just waiting for
695 // the SD card to complete. The host won't let us disconnect.
696 // Some drivers set a 250ms timeout on transfers to complete.
697 // SD card writes are supposed to complete
698 // within 200ms, but sometimes they don'to.
699 // Just pretend we're finished.
700 scsiComplete = 1;
701
702 process_Status();
703 process_MessageIn(); // Will go to BUS_FREE state
704
705 // Try and prevent anyone else using the SCSI bus while we're not ready.
706 SCSI_SetPin(SCSI_Out_BSY);
707 }
708 }
709
710 if (scsiComplete)
711 {
712 SCSI_ClearPin(SCSI_Out_BSY);
713 }
714 while (
715 !scsiDev.resetFlag &&
716 unlikely(scsiDisconnected) &&
717 (elapsedTime_ms(lastActivityTime) <= 10000))
718 {
719 scsiDisconnected = !scsiReconnect();
720 }
721 if (scsiDisconnected)
722 {
723 // Failed to reconnect
724 scsiDev.resetFlag = 1;
725 }
726
727 if (scsiDev.phase == DATA_OUT)
728 {
729 if (scsiDev.parityError &&
730 (scsiDev.target->cfg->flags & CONFIG_ENABLE_PARITY) &&
731 !scsiDev.compatMode)
732 {
733 scsiDev.target->sense.code = ABORTED_COMMAND;
734 scsiDev.target->sense.asc = SCSI_PARITY_ERROR;
735 scsiDev.status = CHECK_CONDITION;;
736 }
737 scsiDev.phase = STATUS;
738 }
739 scsiDiskReset();
740 }
741 debugResume(); // TODO comment re. timeouts.
742 }
743
744 void scsiDiskReset()
745 {
746 scsiDev.dataPtr = 0;
747 scsiDev.savedDataPtr = 0;
748 scsiDev.dataLen = 0;
749 // transfer.lba = 0; // Needed in Request Sense to determine failure
750 transfer.blocks = 0;
751 transfer.currentBlock = 0;
752
753 // Cancel long running commands!
754 if (unlikely(transfer.inProgress == 1))
755 {
756 if (transfer.dir == TRANSFER_WRITE)
757 {
758 sdCompleteWrite();
759 }
760 else
761 {
762 sdCompleteRead();
763 }
764 }
765 transfer.inProgress = 0;
766 transfer.multiBlock = 0;
767 }
768
769 void scsiDiskInit()
770 {
771 transfer.inProgress = 0;
772 scsiDiskReset();
773
774 // Don't require the host to send us a START STOP UNIT command
775 blockDev.state = DISK_STARTED;
776 // WP pin not available for micro-sd
777 // TODO read card WP register
778 #if 0
779 if (SD_WP_Read())
780 {
781 blockDev.state = blockDev.state | DISK_WP;
782 }
783 #endif
784 }
785
786 #pragma GCC pop_options