edda97e58fa394ada4bac71a1e097827e6bd6328
[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(scsiDev.target->cfg->deviceType == CONFIG_FLOPPY_14MB)) {
173 // Floppies are supposed to be slow. Some systems can't handle a floppy
174 // without an access time
175 CyDelay(10);
176 }
177
178 if (unlikely(blockDev.state & DISK_WP) ||
179 unlikely(scsiDev.target->cfg->deviceType == CONFIG_OPTICAL))
180
181 {
182 scsiDev.status = CHECK_CONDITION;
183 scsiDev.target->sense.code = ILLEGAL_REQUEST;
184 scsiDev.target->sense.asc = WRITE_PROTECTED;
185 scsiDev.phase = STATUS;
186 }
187 else if (unlikely(((uint64) lba) + blocks >
188 getScsiCapacity(
189 scsiDev.target->cfg->sdSectorStart,
190 scsiDev.target->liveCfg.bytesPerSector,
191 scsiDev.target->cfg->scsiSectors
192 )
193 ))
194 {
195 scsiDev.status = CHECK_CONDITION;
196 scsiDev.target->sense.code = ILLEGAL_REQUEST;
197 scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
198 scsiDev.phase = STATUS;
199 }
200 else
201 {
202 transfer.dir = TRANSFER_WRITE;
203 transfer.lba = lba;
204 transfer.blocks = blocks;
205 transfer.currentBlock = 0;
206 scsiDev.phase = DATA_OUT;
207 scsiDev.dataLen = scsiDev.target->liveCfg.bytesPerSector;
208 scsiDev.dataPtr = scsiDev.target->liveCfg.bytesPerSector;
209
210 // No need for single-block writes atm. Overhead of the
211 // multi-block write is minimal.
212 transfer.multiBlock = 1;
213
214 sdWriteMultiSectorPrep();
215 }
216 }
217
218
219 static void doRead(uint32 lba, uint32 blocks)
220 {
221 if (unlikely(scsiDev.target->cfg->deviceType == CONFIG_FLOPPY_14MB)) {
222 // Floppies are supposed to be slow. Some systems can't handle a floppy
223 // without an access time
224 CyDelay(10);
225 }
226
227 uint32_t capacity = getScsiCapacity(
228 scsiDev.target->cfg->sdSectorStart,
229 scsiDev.target->liveCfg.bytesPerSector,
230 scsiDev.target->cfg->scsiSectors);
231 if (unlikely(((uint64) lba) + blocks > capacity))
232 {
233 scsiDev.status = CHECK_CONDITION;
234 scsiDev.target->sense.code = ILLEGAL_REQUEST;
235 scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
236 scsiDev.phase = STATUS;
237 }
238 else
239 {
240 transfer.dir = TRANSFER_READ;
241 transfer.lba = lba;
242 transfer.blocks = blocks;
243 transfer.currentBlock = 0;
244 scsiDev.phase = DATA_IN;
245 scsiDev.dataLen = 0; // No data yet
246
247 if ((blocks == 1) ||
248 unlikely(((uint64) lba) + blocks == capacity)
249 )
250 {
251 // We get errors on reading the last sector using a multi-sector
252 // read :-(
253 transfer.multiBlock = 0;
254 }
255 else
256 {
257 transfer.multiBlock = 1;
258 sdReadMultiSectorPrep();
259 }
260 }
261 }
262
263 static void doSeek(uint32 lba)
264 {
265 if (lba >=
266 getScsiCapacity(
267 scsiDev.target->cfg->sdSectorStart,
268 scsiDev.target->liveCfg.bytesPerSector,
269 scsiDev.target->cfg->scsiSectors)
270 )
271 {
272 scsiDev.status = CHECK_CONDITION;
273 scsiDev.target->sense.code = ILLEGAL_REQUEST;
274 scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
275 scsiDev.phase = STATUS;
276 }
277 }
278
279 static int doTestUnitReady()
280 {
281 int ready = 1;
282 if (likely(blockDev.state == (DISK_STARTED | DISK_PRESENT | DISK_INITIALISED)))
283 {
284 // nothing to do.
285 }
286 else if (unlikely(!(blockDev.state & DISK_STARTED)))
287 {
288 ready = 0;
289 scsiDev.status = CHECK_CONDITION;
290 scsiDev.target->sense.code = NOT_READY;
291 scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED;
292 scsiDev.phase = STATUS;
293 }
294 else if (unlikely(!(blockDev.state & DISK_PRESENT)))
295 {
296 ready = 0;
297 scsiDev.status = CHECK_CONDITION;
298 scsiDev.target->sense.code = NOT_READY;
299 scsiDev.target->sense.asc = MEDIUM_NOT_PRESENT;
300 scsiDev.phase = STATUS;
301 }
302 else if (unlikely(!(blockDev.state & DISK_INITIALISED)))
303 {
304 ready = 0;
305 scsiDev.status = CHECK_CONDITION;
306 scsiDev.target->sense.code = NOT_READY;
307 scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_READY_CAUSE_NOT_REPORTABLE;
308 scsiDev.phase = STATUS;
309 }
310 return ready;
311 }
312
313 // Handle direct-access scsi device commands
314 int scsiDiskCommand()
315 {
316 int commandHandled = 1;
317
318 uint8 command = scsiDev.cdb[0];
319 if (unlikely(command == 0x1B))
320 {
321 // START STOP UNIT
322 // Enable or disable media access operations.
323 // Ignore load/eject requests. We can't do that.
324 //int immed = scsiDev.cdb[1] & 1;
325 int start = scsiDev.cdb[4] & 1;
326
327 if (start)
328 {
329 blockDev.state = blockDev.state | DISK_STARTED;
330 if (!(blockDev.state & DISK_INITIALISED))
331 {
332 doSdInit();
333 }
334 }
335 else
336 {
337 blockDev.state &= ~DISK_STARTED;
338 }
339 }
340 else if (unlikely(command == 0x00))
341 {
342 // TEST UNIT READY
343 doTestUnitReady();
344 }
345 else if (unlikely(!doTestUnitReady()))
346 {
347 // Status and sense codes already set by doTestUnitReady
348 }
349 else if (likely(command == 0x08))
350 {
351 // READ(6)
352 uint32 lba =
353 (((uint32) scsiDev.cdb[1] & 0x1F) << 16) +
354 (((uint32) scsiDev.cdb[2]) << 8) +
355 scsiDev.cdb[3];
356 uint32 blocks = scsiDev.cdb[4];
357 if (unlikely(blocks == 0)) blocks = 256;
358 doRead(lba, blocks);
359 }
360 else if (likely(command == 0x28))
361 {
362 // READ(10)
363 // Ignore all cache control bits - we don't support a memory cache.
364
365 uint32 lba =
366 (((uint32) scsiDev.cdb[2]) << 24) +
367 (((uint32) scsiDev.cdb[3]) << 16) +
368 (((uint32) scsiDev.cdb[4]) << 8) +
369 scsiDev.cdb[5];
370 uint32 blocks =
371 (((uint32) scsiDev.cdb[7]) << 8) +
372 scsiDev.cdb[8];
373
374 doRead(lba, blocks);
375 }
376 else if (likely(command == 0x0A))
377 {
378 // WRITE(6)
379 uint32 lba =
380 (((uint32) scsiDev.cdb[1] & 0x1F) << 16) +
381 (((uint32) scsiDev.cdb[2]) << 8) +
382 scsiDev.cdb[3];
383 uint32 blocks = scsiDev.cdb[4];
384 if (unlikely(blocks == 0)) blocks = 256;
385 doWrite(lba, blocks);
386 }
387 else if (likely(command == 0x2A) || // WRITE(10)
388 unlikely(command == 0x2E)) // WRITE AND VERIFY
389 {
390 // Ignore all cache control bits - we don't support a memory cache.
391 // Don't bother verifying either. The SD card likely stores ECC
392 // along with each flash row.
393
394 uint32 lba =
395 (((uint32) scsiDev.cdb[2]) << 24) +
396 (((uint32) scsiDev.cdb[3]) << 16) +
397 (((uint32) scsiDev.cdb[4]) << 8) +
398 scsiDev.cdb[5];
399 uint32 blocks =
400 (((uint32) scsiDev.cdb[7]) << 8) +
401 scsiDev.cdb[8];
402
403 doWrite(lba, blocks);
404 }
405
406 else if (unlikely(command == 0x04))
407 {
408 // FORMAT UNIT
409 // We don't really do any formatting, but we need to read the correct
410 // number of bytes in the DATA_OUT phase to make the SCSI host happy.
411
412 int fmtData = (scsiDev.cdb[1] & 0x10) ? 1 : 0;
413 if (fmtData)
414 {
415 // We need to read the parameter list, but we don't know how
416 // big it is yet. Start with the header.
417 scsiDev.dataLen = 4;
418 scsiDev.phase = DATA_OUT;
419 scsiDev.postDataOutHook = doFormatUnitHeader;
420 }
421 else
422 {
423 // No data to read, we're already finished!
424 }
425 }
426 else if (unlikely(command == 0x25))
427 {
428 // READ CAPACITY
429 doReadCapacity();
430 }
431 else if (unlikely(command == 0x0B))
432 {
433 // SEEK(6)
434 uint32 lba =
435 (((uint32) scsiDev.cdb[1] & 0x1F) << 16) +
436 (((uint32) scsiDev.cdb[2]) << 8) +
437 scsiDev.cdb[3];
438
439 doSeek(lba);
440 }
441
442 else if (unlikely(command == 0x2B))
443 {
444 // SEEK(10)
445 uint32 lba =
446 (((uint32) scsiDev.cdb[2]) << 24) +
447 (((uint32) scsiDev.cdb[3]) << 16) +
448 (((uint32) scsiDev.cdb[4]) << 8) +
449 scsiDev.cdb[5];
450
451 doSeek(lba);
452 }
453 else if (unlikely(command == 0x36))
454 {
455 // LOCK UNLOCK CACHE
456 // We don't have a cache to lock data into. do nothing.
457 }
458 else if (unlikely(command == 0x34))
459 {
460 // PRE-FETCH.
461 // We don't have a cache to pre-fetch into. do nothing.
462 }
463 else if (unlikely(command == 0x1E))
464 {
465 // PREVENT ALLOW MEDIUM REMOVAL
466 // Not much we can do to prevent the user removing the SD card.
467 // do nothing.
468 }
469 else if (unlikely(command == 0x01))
470 {
471 // REZERO UNIT
472 // Set the lun to a vendor-specific state. Ignore.
473 }
474 else if (unlikely(command == 0x35))
475 {
476 // SYNCHRONIZE CACHE
477 // We don't have a cache. do nothing.
478 }
479 else if (unlikely(command == 0x2F))
480 {
481 // VERIFY
482 // TODO: When they supply data to verify, we should read the data and
483 // verify it. If they don't supply any data, just say success.
484 if ((scsiDev.cdb[1] & 0x02) == 0)
485 {
486 // They are asking us to do a medium verification with no data
487 // comparison. Assume success, do nothing.
488 }
489 else
490 {
491 // TODO. This means they are supplying data to verify against.
492 // Technically we should probably grab the data and compare it.
493 scsiDev.status = CHECK_CONDITION;
494 scsiDev.target->sense.code = ILLEGAL_REQUEST;
495 scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
496 scsiDev.phase = STATUS;
497 }
498 }
499 else if (unlikely(command == 0x37))
500 {
501 // READ DEFECT DATA
502 scsiDev.status = CHECK_CONDITION;
503 scsiDev.target->sense.code = NO_SENSE;
504 scsiDev.target->sense.asc = DEFECT_LIST_NOT_FOUND;
505 scsiDev.phase = STATUS;
506
507 }
508 else
509 {
510 commandHandled = 0;
511 }
512
513 return commandHandled;
514 }
515
516 void scsiDiskPoll()
517 {
518 if (scsiDev.phase == DATA_IN &&
519 transfer.currentBlock != transfer.blocks)
520 {
521 scsiEnterPhase(DATA_IN);
522
523 int totalSDSectors =
524 transfer.blocks *
525 SDSectorsPerSCSISector(scsiDev.target->liveCfg.bytesPerSector);
526 uint32_t sdLBA =
527 SCSISector2SD(
528 scsiDev.target->cfg->sdSectorStart,
529 scsiDev.target->liveCfg.bytesPerSector,
530 transfer.lba);
531
532 const int sdPerScsi =
533 SDSectorsPerSCSISector(scsiDev.target->liveCfg.bytesPerSector);
534 int buffers = sizeof(scsiDev.data) / SD_SECTOR_SIZE;
535 int prep = 0;
536 int i = 0;
537 int scsiActive = 0;
538 int sdActive = 0;
539 while ((i < totalSDSectors) &&
540 likely(scsiDev.phase == DATA_IN) &&
541 likely(!scsiDev.resetFlag))
542 {
543 // Wait for the next DMA interrupt. It's beneficial to halt the
544 // processor to give the DMA controller more memory bandwidth to
545 // work with.
546 // We're optimistically assuming a race condition won't occur
547 // between these checks and the interrupt handers. The 1ms
548 // systick timer interrupt saves us on the event of a race.
549 int scsiBusy = scsiDMABusy();
550 int sdBusy = sdDMABusy();
551 while (scsiBusy && sdBusy)
552 {
553 __WFI();
554 scsiBusy = scsiDMABusy();
555 sdBusy = sdDMABusy();
556 }
557
558 if (sdActive && !sdBusy && sdReadSectorDMAPoll())
559 {
560 sdActive = 0;
561 prep++;
562 }
563
564 // Usually SD is slower than the SCSI interface.
565 // Prioritise starting the read of the next sector over starting a
566 // SCSI transfer for the last sector
567 // ie. NO "else" HERE.
568 if (!sdActive &&
569 (prep - i < buffers) &&
570 (prep < totalSDSectors))
571 {
572 // Start an SD transfer if we have space.
573 if (transfer.multiBlock)
574 {
575 sdReadMultiSectorDMA(&scsiDev.data[SD_SECTOR_SIZE * (prep % buffers)]);
576 }
577 else
578 {
579 sdReadSingleSectorDMA(sdLBA + prep, &scsiDev.data[SD_SECTOR_SIZE * (prep % buffers)]);
580 }
581 sdActive = 1;
582 }
583
584 if (scsiActive && !scsiBusy && scsiWriteDMAPoll())
585 {
586 scsiActive = 0;
587 ++i;
588 }
589 if (!scsiActive && ((prep - i) > 0))
590 {
591 int dmaBytes = SD_SECTOR_SIZE;
592 if ((i % sdPerScsi) == (sdPerScsi - 1))
593 {
594 dmaBytes = scsiDev.target->liveCfg.bytesPerSector % SD_SECTOR_SIZE;
595 if (dmaBytes == 0) dmaBytes = SD_SECTOR_SIZE;
596 }
597 scsiWriteDMA(&scsiDev.data[SD_SECTOR_SIZE * (i % buffers)], dmaBytes);
598 scsiActive = 1;
599 }
600 }
601 if (scsiDev.phase == DATA_IN)
602 {
603 scsiDev.phase = STATUS;
604 }
605 scsiDiskReset();
606 }
607 else if (scsiDev.phase == DATA_OUT &&
608 transfer.currentBlock != transfer.blocks)
609 {
610 scsiEnterPhase(DATA_OUT);
611
612 const int sdPerScsi =
613 SDSectorsPerSCSISector(scsiDev.target->liveCfg.bytesPerSector);
614 int totalSDSectors = transfer.blocks * sdPerScsi;
615 int buffers = sizeof(scsiDev.data) / SD_SECTOR_SIZE;
616 int prep = 0;
617 int i = 0;
618 int scsiDisconnected = 0;
619 int scsiComplete = 0;
620 uint32_t lastActivityTime = getTime_ms();
621 int scsiActive = 0;
622 int sdActive = 0;
623
624 while ((i < totalSDSectors) &&
625 (likely(scsiDev.phase == DATA_OUT) || // scsiDisconnect keeps our phase.
626 scsiComplete) &&
627 likely(!scsiDev.resetFlag))
628 {
629 // Wait for the next DMA interrupt. It's beneficial to halt the
630 // processor to give the DMA controller more memory bandwidth to
631 // work with.
632 // We're optimistically assuming a race condition won't occur
633 // between these checks and the interrupt handers. The 1ms
634 // systick timer interrupt saves us on the event of a race.
635 int scsiBusy = scsiDMABusy();
636 int sdBusy = sdDMABusy();
637 while (scsiBusy && sdBusy)
638 {
639 __WFI();
640 scsiBusy = scsiDMABusy();
641 sdBusy = sdDMABusy();
642 }
643
644 if (sdActive && !sdBusy && sdWriteSectorDMAPoll(i == (totalSDSectors - 1)))
645 {
646 sdActive = 0;
647 i++;
648 }
649 if (!sdActive && ((prep - i) > 0))
650 {
651 // Start an SD transfer if we have space.
652 sdWriteMultiSectorDMA(&scsiDev.data[SD_SECTOR_SIZE * (i % buffers)]);
653 sdActive = 1;
654 }
655
656 uint32_t now = getTime_ms();
657
658 if (scsiActive && !scsiBusy && scsiReadDMAPoll())
659 {
660 scsiActive = 0;
661 ++prep;
662 lastActivityTime = now;
663 }
664 if (!scsiActive &&
665 ((prep - i) < buffers) &&
666 (prep < totalSDSectors) &&
667 likely(!scsiDisconnected))
668 {
669 int dmaBytes = SD_SECTOR_SIZE;
670 if ((prep % sdPerScsi) == (sdPerScsi - 1))
671 {
672 dmaBytes = scsiDev.target->liveCfg.bytesPerSector % SD_SECTOR_SIZE;
673 if (dmaBytes == 0) dmaBytes = SD_SECTOR_SIZE;
674 }
675 scsiReadDMA(&scsiDev.data[SD_SECTOR_SIZE * (prep % buffers)], dmaBytes);
676 scsiActive = 1;
677 }
678 else if (
679 (scsiActive == 0) &&
680 likely(!scsiDisconnected) &&
681 unlikely(scsiDev.discPriv) &&
682 unlikely(diffTime_ms(lastActivityTime, now) >= 20) &&
683 likely(scsiDev.phase == DATA_OUT))
684 {
685 // We're transferring over the SCSI bus faster than the SD card
686 // can write. There is no more buffer space once we've finished
687 // this SCSI transfer.
688 // The NCR 53C700 interface chips have a 250ms "byte-to-byte"
689 // timeout buffer. SD card writes are supposed to complete
690 // within 200ms, but sometimes they don't.
691 // The NCR 53C700 series is used on HP 9000 workstations.
692 scsiDisconnect();
693 scsiDisconnected = 1;
694 lastActivityTime = getTime_ms();
695 }
696 else if (unlikely(scsiDisconnected) &&
697 (
698 (prep == i) || // Buffers empty.
699 // Send some messages every 100ms so we don't timeout.
700 // At a minimum, a reselection involves an IDENTIFY message.
701 unlikely(diffTime_ms(lastActivityTime, now) >= 100)
702 ))
703 {
704 int reconnected = scsiReconnect();
705 if (reconnected)
706 {
707 scsiDisconnected = 0;
708 lastActivityTime = getTime_ms(); // Don't disconnect immediately.
709 }
710 else if (diffTime_ms(lastActivityTime, getTime_ms()) >= 10000)
711 {
712 // Give up after 10 seconds of trying to reconnect.
713 scsiDev.resetFlag = 1;
714 }
715 }
716 else if (
717 likely(!scsiComplete) &&
718 (sdActive == 1) &&
719 (prep == totalSDSectors) && // All scsi data read and buffered
720 likely(!scsiDev.discPriv) && // Prefer disconnect where possible.
721 unlikely(diffTime_ms(lastActivityTime, now) >= 150) &&
722
723 likely(scsiDev.phase == DATA_OUT) &&
724 !(scsiDev.cdb[scsiDev.cdbLen - 1] & 0x01) // Not linked command
725 )
726 {
727 // We're transferring over the SCSI bus faster than the SD card
728 // can write. All data is buffered, and we're just waiting for
729 // the SD card to complete. The host won't let us disconnect.
730 // Some drivers set a 250ms timeout on transfers to complete.
731 // SD card writes are supposed to complete
732 // within 200ms, but sometimes they don'to.
733 // Just pretend we're finished.
734 scsiComplete = 1;
735
736 process_Status();
737 process_MessageIn(); // Will go to BUS_FREE state
738
739 // Try and prevent anyone else using the SCSI bus while we're not ready.
740 SCSI_SetPin(SCSI_Out_BSY);
741 }
742 }
743
744 if (scsiComplete)
745 {
746 SCSI_ClearPin(SCSI_Out_BSY);
747 }
748 while (
749 !scsiDev.resetFlag &&
750 unlikely(scsiDisconnected) &&
751 (elapsedTime_ms(lastActivityTime) <= 10000))
752 {
753 scsiDisconnected = !scsiReconnect();
754 }
755 if (scsiDisconnected)
756 {
757 // Failed to reconnect
758 scsiDev.resetFlag = 1;
759 }
760
761 if (scsiDev.phase == DATA_OUT)
762 {
763 if (scsiDev.parityError &&
764 (scsiDev.target->cfg->flags & CONFIG_ENABLE_PARITY) &&
765 (scsiDev.compatMode >= COMPAT_SCSI2))
766 {
767 scsiDev.target->sense.code = ABORTED_COMMAND;
768 scsiDev.target->sense.asc = SCSI_PARITY_ERROR;
769 scsiDev.status = CHECK_CONDITION;;
770 }
771 scsiDev.phase = STATUS;
772 }
773 scsiDiskReset();
774 }
775 }
776
777 void scsiDiskReset()
778 {
779 scsiDev.dataPtr = 0;
780 scsiDev.savedDataPtr = 0;
781 scsiDev.dataLen = 0;
782 // transfer.lba = 0; // Needed in Request Sense to determine failure
783 transfer.blocks = 0;
784 transfer.currentBlock = 0;
785
786 // Cancel long running commands!
787 if (unlikely(transfer.inProgress == 1))
788 {
789 if (transfer.dir == TRANSFER_WRITE)
790 {
791 sdCompleteWrite();
792 }
793 else
794 {
795 sdCompleteRead();
796 }
797 }
798 transfer.inProgress = 0;
799 transfer.multiBlock = 0;
800 }
801
802 void scsiDiskInit()
803 {
804 transfer.inProgress = 0;
805 scsiDiskReset();
806
807 // Don't require the host to send us a START STOP UNIT command
808 blockDev.state = DISK_STARTED;
809 // WP pin not available for micro-sd
810 // TODO read card WP register
811 #if 0
812 if (SD_WP_Read())
813 {
814 blockDev.state = blockDev.state | DISK_WP;
815 }
816 #endif
817 }
818
819 #pragma GCC pop_options