1 // Copyright (C) 2013 Michael McMaster <michael@codesrc.com>
\r
2 // Copyright (C) 2014 Doug Brown <doug@downtowndougbrown.com>
\r
4 // This file is part of SCSI2SD.
\r
6 // SCSI2SD is free software: you can redistribute it and/or modify
\r
7 // it under the terms of the GNU General Public License as published by
\r
8 // the Free Software Foundation, either version 3 of the License, or
\r
9 // (at your option) any later version.
\r
11 // SCSI2SD is distributed in the hope that it will be useful,
\r
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 // GNU General Public License for more details.
\r
16 // You should have received a copy of the GNU General Public License
\r
17 // along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
\r
19 #include "stm32f2xx.h"
\r
23 // For SD write direct routines
\r
25 #include "bsp_driver_sd.h"
\r
29 #include "scsiPhy.h"
\r
39 BlockDevice blockDev;
\r
42 static int doSdInit()
\r
45 if (blockDev.state & DISK_PRESENT)
\r
47 blockDev.state = blockDev.state | DISK_INITIALISED;
\r
52 // Callback once all data has been read in the data out phase.
\r
53 static void doFormatUnitComplete(void)
\r
55 // TODO start writing the initialisation pattern to the SD
\r
57 scsiDev.phase = STATUS;
\r
60 static void doFormatUnitSkipData(int bytes)
\r
62 // We may not have enough memory to store the initialisation pattern and
\r
63 // defect list data. Since we're not making use of it yet anyway, just
\r
64 // discard the bytes.
\r
65 scsiEnterPhase(DATA_OUT);
\r
67 for (i = 0; i < bytes; ++i)
\r
73 // Callback from the data out phase.
\r
74 static void doFormatUnitPatternHeader(void)
\r
77 ((((uint16_t)scsiDev.data[2])) << 8) +
\r
81 ((((uint16_t)scsiDev.data[4 + 2])) << 8) +
\r
82 scsiDev.data[4 + 3];
\r
84 doFormatUnitSkipData(defectLength + patternLength);
\r
85 doFormatUnitComplete();
\r
88 // Callback from the data out phase.
\r
89 static void doFormatUnitHeader(void)
\r
91 int IP = (scsiDev.data[1] & 0x08) ? 1 : 0;
\r
92 int DSP = (scsiDev.data[1] & 0x04) ? 1 : 0;
\r
94 if (! DSP) // disable save parameters
\r
96 // Save the "MODE SELECT savable parameters"
\r
98 scsiDev.target->targetId,
\r
99 scsiDev.target->liveCfg.bytesPerSector);
\r
104 // We need to read the initialisation pattern header first.
\r
105 scsiDev.dataLen += 4;
\r
106 scsiDev.phase = DATA_OUT;
\r
107 scsiDev.postDataOutHook = doFormatUnitPatternHeader;
\r
111 // Read the defect list data
\r
113 ((((uint16_t)scsiDev.data[2])) << 8) +
\r
115 doFormatUnitSkipData(defectLength);
\r
116 doFormatUnitComplete();
\r
120 static void doReadCapacity()
\r
122 uint32_t lba = (((uint32_t) scsiDev.cdb[2]) << 24) +
\r
123 (((uint32_t) scsiDev.cdb[3]) << 16) +
\r
124 (((uint32_t) scsiDev.cdb[4]) << 8) +
\r
126 int pmi = scsiDev.cdb[8] & 1;
\r
128 uint32_t capacity = getScsiCapacity(
\r
129 scsiDev.target->cfg->sdSectorStart,
\r
130 scsiDev.target->liveCfg.bytesPerSector,
\r
131 scsiDev.target->cfg->scsiSectors);
\r
136 // We don't do anything with the "partial medium indicator", and
\r
137 // assume that delays are constant across each block. But the spec
\r
138 // says we must return this error if pmi is specified incorrectly.
\r
139 scsiDev.status = CHECK_CONDITION;
\r
140 scsiDev.target->sense.code = ILLEGAL_REQUEST;
\r
141 scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
\r
142 scsiDev.phase = STATUS;
\r
144 else if (capacity > 0)
\r
146 uint32_t highestBlock = capacity - 1;
\r
148 scsiDev.data[0] = highestBlock >> 24;
\r
149 scsiDev.data[1] = highestBlock >> 16;
\r
150 scsiDev.data[2] = highestBlock >> 8;
\r
151 scsiDev.data[3] = highestBlock;
\r
153 uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
\r
154 scsiDev.data[4] = bytesPerSector >> 24;
\r
155 scsiDev.data[5] = bytesPerSector >> 16;
\r
156 scsiDev.data[6] = bytesPerSector >> 8;
\r
157 scsiDev.data[7] = bytesPerSector;
\r
158 scsiDev.dataLen = 8;
\r
159 scsiDev.phase = DATA_IN;
\r
163 scsiDev.status = CHECK_CONDITION;
\r
164 scsiDev.target->sense.code = NOT_READY;
\r
165 scsiDev.target->sense.asc = MEDIUM_NOT_PRESENT;
\r
166 scsiDev.phase = STATUS;
\r
170 static void doWrite(uint32_t lba, uint32_t blocks)
\r
172 if (unlikely(scsiDev.target->cfg->deviceType == S2S_CFG_FLOPPY_14MB)) {
\r
173 // Floppies are supposed to be slow. Some systems can't handle a floppy
\r
174 // without an access time
\r
178 uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
\r
180 if (unlikely(blockDev.state & DISK_WP) ||
\r
181 unlikely(scsiDev.target->cfg->deviceType == S2S_CFG_OPTICAL))
\r
184 scsiDev.status = CHECK_CONDITION;
\r
185 scsiDev.target->sense.code = ILLEGAL_REQUEST;
\r
186 scsiDev.target->sense.asc = WRITE_PROTECTED;
\r
187 scsiDev.phase = STATUS;
\r
189 else if (unlikely(((uint64_t) lba) + blocks >
\r
191 scsiDev.target->cfg->sdSectorStart,
\r
193 scsiDev.target->cfg->scsiSectors
\r
197 scsiDev.status = CHECK_CONDITION;
\r
198 scsiDev.target->sense.code = ILLEGAL_REQUEST;
\r
199 scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
\r
200 scsiDev.phase = STATUS;
\r
204 transfer.lba = lba;
\r
205 transfer.blocks = blocks;
\r
206 transfer.currentBlock = 0;
\r
207 scsiDev.phase = DATA_OUT;
\r
208 scsiDev.dataLen = bytesPerSector;
\r
209 scsiDev.dataPtr = bytesPerSector;
\r
211 // No need for single-block writes atm. Overhead of the
\r
212 // multi-block write is minimal.
\r
213 transfer.multiBlock = 1;
\r
216 // TODO uint32_t sdLBA =
\r
217 // TODO SCSISector2SD(
\r
218 // TODO scsiDev.target->cfg->sdSectorStart,
\r
219 // TODO bytesPerSector,
\r
221 // TODO uint32_t sdBlocks = blocks * SDSectorsPerSCSISector(bytesPerSector);
\r
222 // TODO sdWriteMultiSectorPrep(sdLBA, sdBlocks);
\r
227 static void doRead(uint32_t lba, uint32_t blocks)
\r
229 if (unlikely(scsiDev.target->cfg->deviceType == S2S_CFG_FLOPPY_14MB)) {
\r
230 // Floppies are supposed to be slow. Some systems can't handle a floppy
\r
231 // without an access time
\r
235 uint32_t capacity = getScsiCapacity(
\r
236 scsiDev.target->cfg->sdSectorStart,
\r
237 scsiDev.target->liveCfg.bytesPerSector,
\r
238 scsiDev.target->cfg->scsiSectors);
\r
239 if (unlikely(((uint64_t) lba) + blocks > capacity))
\r
241 scsiDev.status = CHECK_CONDITION;
\r
242 scsiDev.target->sense.code = ILLEGAL_REQUEST;
\r
243 scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
\r
244 scsiDev.phase = STATUS;
\r
248 transfer.lba = lba;
\r
249 transfer.blocks = blocks;
\r
250 transfer.currentBlock = 0;
\r
251 scsiDev.phase = DATA_IN;
\r
252 scsiDev.dataLen = 0; // No data yet
\r
254 uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
\r
255 uint32_t sdSectorPerSCSISector = SDSectorsPerSCSISector(bytesPerSector);
\r
256 uint32_t sdSectors =
\r
257 blocks * sdSectorPerSCSISector;
\r
260 (sdSectors == 1) &&
\r
261 !(scsiDev.boardCfg.flags & S2S_CFG_ENABLE_CACHE)
\r
263 unlikely(((uint64_t) lba) + blocks == capacity)
\r
266 // We get errors on reading the last sector using a multi-sector
\r
268 transfer.multiBlock = 0;
\r
272 transfer.multiBlock = 1;
\r
274 // uint32_t sdLBA =
\r
276 // scsiDev.target->cfg->sdSectorStart,
\r
280 // TODO sdReadMultiSectorPrep(sdLBA, sdSectors);
\r
285 static void doSeek(uint32_t lba)
\r
289 scsiDev.target->cfg->sdSectorStart,
\r
290 scsiDev.target->liveCfg.bytesPerSector,
\r
291 scsiDev.target->cfg->scsiSectors)
\r
294 scsiDev.status = CHECK_CONDITION;
\r
295 scsiDev.target->sense.code = ILLEGAL_REQUEST;
\r
296 scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
\r
297 scsiDev.phase = STATUS;
\r
305 static int doTestUnitReady()
\r
308 if (likely(blockDev.state == (DISK_STARTED | DISK_PRESENT | DISK_INITIALISED)))
\r
312 else if (unlikely(!(blockDev.state & DISK_STARTED)))
\r
315 scsiDev.status = CHECK_CONDITION;
\r
316 scsiDev.target->sense.code = NOT_READY;
\r
317 scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED;
\r
318 scsiDev.phase = STATUS;
\r
320 else if (unlikely(!(blockDev.state & DISK_PRESENT)))
\r
323 scsiDev.status = CHECK_CONDITION;
\r
324 scsiDev.target->sense.code = NOT_READY;
\r
325 scsiDev.target->sense.asc = MEDIUM_NOT_PRESENT;
\r
326 scsiDev.phase = STATUS;
\r
328 else if (unlikely(!(blockDev.state & DISK_INITIALISED)))
\r
331 scsiDev.status = CHECK_CONDITION;
\r
332 scsiDev.target->sense.code = NOT_READY;
\r
333 scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_READY_CAUSE_NOT_REPORTABLE;
\r
334 scsiDev.phase = STATUS;
\r
339 // Handle direct-access scsi device commands
\r
340 int scsiDiskCommand()
\r
342 int commandHandled = 1;
\r
344 uint8_t command = scsiDev.cdb[0];
\r
345 if (unlikely(command == 0x1B))
\r
348 // Enable or disable media access operations.
\r
349 // Ignore load/eject requests. We can't do that.
\r
350 //int immed = scsiDev.cdb[1] & 1;
\r
351 int start = scsiDev.cdb[4] & 1;
\r
355 blockDev.state = blockDev.state | DISK_STARTED;
\r
356 if (!(blockDev.state & DISK_INITIALISED))
\r
363 blockDev.state &= ~DISK_STARTED;
\r
366 else if (unlikely(command == 0x00))
\r
371 else if (unlikely(!doTestUnitReady()))
\r
373 // Status and sense codes already set by doTestUnitReady
\r
375 else if (likely(command == 0x08))
\r
379 (((uint32_t) scsiDev.cdb[1] & 0x1F) << 16) +
\r
380 (((uint32_t) scsiDev.cdb[2]) << 8) +
\r
382 uint32_t blocks = scsiDev.cdb[4];
\r
383 if (unlikely(blocks == 0)) blocks = 256;
\r
384 doRead(lba, blocks);
\r
386 else if (likely(command == 0x28))
\r
389 // Ignore all cache control bits - we don't support a memory cache.
\r
392 (((uint32_t) scsiDev.cdb[2]) << 24) +
\r
393 (((uint32_t) scsiDev.cdb[3]) << 16) +
\r
394 (((uint32_t) scsiDev.cdb[4]) << 8) +
\r
397 (((uint32_t) scsiDev.cdb[7]) << 8) +
\r
400 doRead(lba, blocks);
\r
402 else if (likely(command == 0x0A))
\r
406 (((uint32_t) scsiDev.cdb[1] & 0x1F) << 16) +
\r
407 (((uint32_t) scsiDev.cdb[2]) << 8) +
\r
409 uint32_t blocks = scsiDev.cdb[4];
\r
410 if (unlikely(blocks == 0)) blocks = 256;
\r
411 doWrite(lba, blocks);
\r
413 else if (likely(command == 0x2A) || // WRITE(10)
\r
414 unlikely(command == 0x2E)) // WRITE AND VERIFY
\r
416 // Ignore all cache control bits - we don't support a memory cache.
\r
417 // Don't bother verifying either. The SD card likely stores ECC
\r
418 // along with each flash row.
\r
421 (((uint32_t) scsiDev.cdb[2]) << 24) +
\r
422 (((uint32_t) scsiDev.cdb[3]) << 16) +
\r
423 (((uint32_t) scsiDev.cdb[4]) << 8) +
\r
426 (((uint32_t) scsiDev.cdb[7]) << 8) +
\r
429 doWrite(lba, blocks);
\r
431 else if (unlikely(command == 0x04))
\r
434 // We don't really do any formatting, but we need to read the correct
\r
435 // number of bytes in the DATA_OUT phase to make the SCSI host happy.
\r
437 int fmtData = (scsiDev.cdb[1] & 0x10) ? 1 : 0;
\r
440 // We need to read the parameter list, but we don't know how
\r
441 // big it is yet. Start with the header.
\r
442 scsiDev.dataLen = 4;
\r
443 scsiDev.phase = DATA_OUT;
\r
444 scsiDev.postDataOutHook = doFormatUnitHeader;
\r
448 // No data to read, we're already finished!
\r
451 else if (unlikely(command == 0x25))
\r
456 else if (unlikely(command == 0x0B))
\r
460 (((uint32_t) scsiDev.cdb[1] & 0x1F) << 16) +
\r
461 (((uint32_t) scsiDev.cdb[2]) << 8) +
\r
467 else if (unlikely(command == 0x2B))
\r
471 (((uint32_t) scsiDev.cdb[2]) << 24) +
\r
472 (((uint32_t) scsiDev.cdb[3]) << 16) +
\r
473 (((uint32_t) scsiDev.cdb[4]) << 8) +
\r
478 else if (unlikely(command == 0x36))
\r
480 // LOCK UNLOCK CACHE
\r
481 // We don't have a cache to lock data into. do nothing.
\r
483 else if (unlikely(command == 0x34))
\r
486 // We don't have a cache to pre-fetch into. do nothing.
\r
488 else if (unlikely(command == 0x1E))
\r
490 // PREVENT ALLOW MEDIUM REMOVAL
\r
491 // Not much we can do to prevent the user removing the SD card.
\r
494 else if (unlikely(command == 0x01))
\r
497 // Set the lun to a vendor-specific state. Ignore.
\r
499 else if (unlikely(command == 0x35))
\r
501 // SYNCHRONIZE CACHE
\r
502 // We don't have a cache. do nothing.
\r
504 else if (unlikely(command == 0x2F))
\r
507 // TODO: When they supply data to verify, we should read the data and
\r
508 // verify it. If they don't supply any data, just say success.
\r
509 if ((scsiDev.cdb[1] & 0x02) == 0)
\r
511 // They are asking us to do a medium verification with no data
\r
512 // comparison. Assume success, do nothing.
\r
516 // TODO. This means they are supplying data to verify against.
\r
517 // Technically we should probably grab the data and compare it.
\r
518 scsiDev.status = CHECK_CONDITION;
\r
519 scsiDev.target->sense.code = ILLEGAL_REQUEST;
\r
520 scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
\r
521 scsiDev.phase = STATUS;
\r
524 else if (unlikely(command == 0x37))
\r
526 // READ DEFECT DATA
\r
527 uint32_t allocLength = (((uint16_t)scsiDev.cdb[7]) << 8) |
\r
530 scsiDev.data[0] = 0;
\r
531 scsiDev.data[1] = scsiDev.cdb[1];
\r
532 scsiDev.data[2] = 0;
\r
533 scsiDev.data[3] = 0;
\r
534 scsiDev.dataLen = 4;
\r
536 if (scsiDev.dataLen > allocLength)
\r
538 scsiDev.dataLen = allocLength;
\r
541 scsiDev.phase = DATA_IN;
\r
545 commandHandled = 0;
\r
548 return commandHandled;
\r
552 calcReadahead(uint32_t totalBytes, uint32_t sdSpeedKBs, uint32_t scsiSpeedKBs)
\r
554 if (!(scsiDev.boardCfg.flags6 & S2S_CFG_ENABLE_BLIND_WRITES) ||
\r
555 (scsiSpeedKBs == 0) ||
\r
556 (scsiDev.hostSpeedMeasured == 0))
\r
561 // uint32_t readAheadBytes = totalBytes * (1 - scsiSpeedKBs / sdSpeedKBs);
\r
562 // Won't overflow with 65536 max bytes, 20000 max scsi speed.
\r
563 uint32_t readAheadBytes = totalBytes - totalBytes * scsiSpeedKBs / sdSpeedKBs;
\r
565 // Round up to nearest FIFO size (* 4 for safety)
\r
566 readAheadBytes = ((readAheadBytes / SCSI_FIFO_DEPTH) + 4) * SCSI_FIFO_DEPTH;
\r
568 if (readAheadBytes > totalBytes)
\r
570 readAheadBytes = totalBytes;
\r
573 return readAheadBytes;
\r
576 void scsiDiskPoll()
\r
578 uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
\r
580 if (scsiDev.phase == DATA_IN &&
\r
581 transfer.currentBlock != transfer.blocks)
\r
583 // Take responsibility for waiting for the phase delays
\r
584 uint32_t phaseChangeDelayUs = scsiEnterPhaseImmediate(DATA_IN);
\r
586 int totalSDSectors =
\r
587 transfer.blocks * SDSectorsPerSCSISector(bytesPerSector);
\r
590 scsiDev.target->cfg->sdSectorStart,
\r
594 const int sdPerScsi = SDSectorsPerSCSISector(bytesPerSector);
\r
595 const int buffers = sizeof(scsiDev.data) / SD_SECTOR_SIZE;
\r
598 int scsiActive __attribute__((unused)) = 0; // unused if DMA disabled
\r
601 // It's highly unlikely that someone is going to use huge transfers
\r
602 // per scsi command, but if they do it'll be slower than usual.
\r
603 uint32_t totalScsiBytes = transfer.blocks * bytesPerSector;
\r
604 int useSlowDataCount = totalScsiBytes >= SCSI_XFER_MAX;
\r
605 if (!useSlowDataCount)
\r
607 scsiSetDataCount(totalScsiBytes);
\r
610 while ((i < totalSDSectors) &&
\r
611 likely(scsiDev.phase == DATA_IN) &&
\r
612 likely(!scsiDev.resetFlag))
\r
614 int completedDmaSectors;
\r
615 if (sdActive && (completedDmaSectors = sdReadDMAPoll(sdActive)))
\r
617 prep += completedDmaSectors;
\r
618 sdActive -= completedDmaSectors;
\r
619 } else if (sdActive > 1)
\r
621 if ((scsiDev.data[SD_SECTOR_SIZE * (prep % buffers) + 510] != 0xAA) ||
\r
622 (scsiDev.data[SD_SECTOR_SIZE * (prep % buffers) + 511] != 0x33))
\r
630 (prep - i < buffers) &&
\r
631 (prep < totalSDSectors) &&
\r
632 ((totalSDSectors - prep) >= sdPerScsi) &&
\r
633 (likely(!useSlowDataCount) || scsiPhyComplete()))
\r
635 // Start an SD transfer if we have space.
\r
636 uint32_t startBuffer = prep % buffers;
\r
637 uint32_t sectors = totalSDSectors - prep;
\r
638 uint32_t freeBuffers = buffers - (prep - i);
\r
640 uint32_t contiguousBuffers = buffers - startBuffer;
\r
641 freeBuffers = freeBuffers < contiguousBuffers
\r
642 ? freeBuffers : contiguousBuffers;
\r
643 sectors = sectors < freeBuffers ? sectors : freeBuffers;
\r
645 if (sectors > 128) sectors = 128; // 65536 DMA limit !!
\r
647 // Round-down when we have odd sector sizes.
\r
648 if (sdPerScsi != 1)
\r
650 sectors = (sectors / sdPerScsi) * sdPerScsi;
\r
653 for (int dodgy = 0; dodgy < sectors; dodgy++)
\r
655 scsiDev.data[SD_SECTOR_SIZE * (startBuffer + dodgy) + 510] = 0xAA;
\r
656 scsiDev.data[SD_SECTOR_SIZE * (startBuffer + dodgy) + 511] = 0x33;
\r
659 sdReadDMA(sdLBA + prep, sectors, &scsiDev.data[SD_SECTOR_SIZE * startBuffer]);
\r
661 sdActive = sectors;
\r
663 if (useSlowDataCount)
\r
665 scsiSetDataCount((sectors / sdPerScsi) * bytesPerSector);
\r
668 // Wait now that the SD card is busy
\r
669 // Chances are we've probably already waited sufficient time,
\r
670 // but it's hard to measure microseconds cheaply. So just wait
\r
671 // extra just-in-case. Hopefully it's in parallel with dma.
\r
672 if (phaseChangeDelayUs > 0)
\r
674 s2s_delay_us(phaseChangeDelayUs);
\r
675 phaseChangeDelayUs = 0;
\r
679 if ((prep - i) > 0)
\r
681 int dmaBytes = SD_SECTOR_SIZE;
\r
682 if ((i % sdPerScsi) == (sdPerScsi - 1))
\r
684 dmaBytes = bytesPerSector % SD_SECTOR_SIZE;
\r
685 if (dmaBytes == 0) dmaBytes = SD_SECTOR_SIZE;
\r
688 uint8_t* scsiDmaData = &(scsiDev.data[SD_SECTOR_SIZE * (i % buffers)]);
\r
689 scsiWritePIO(scsiDmaData, dmaBytes);
\r
695 if (phaseChangeDelayUs > 0 && !scsiDev.resetFlag) // zero bytes ?
\r
697 s2s_delay_us(phaseChangeDelayUs);
\r
698 phaseChangeDelayUs = 0;
\r
701 // We've finished transferring the data to the FPGA, now wait until it's
\r
702 // written to he SCSI bus.
\r
704 while (!scsiPhyComplete() &&
\r
705 likely(scsiDev.phase == DATA_IN) &&
\r
706 likely(!scsiDev.resetFlag))
\r
712 if (scsiDev.phase == DATA_IN)
\r
714 scsiDev.phase = STATUS;
\r
718 else if (scsiDev.phase == DATA_OUT &&
\r
719 transfer.currentBlock != transfer.blocks)
\r
721 scsiEnterPhase(DATA_OUT);
\r
723 const int sdPerScsi = SDSectorsPerSCSISector(bytesPerSector);
\r
724 int totalSDSectors = transfer.blocks * sdPerScsi;
\r
727 scsiDev.target->cfg->sdSectorStart,
\r
733 int parityError = 0;
\r
734 int enableParity = scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY;
\r
736 uint32_t maxSectors = sizeof(scsiDev.data) / SD_SECTOR_SIZE;
\r
738 static_assert(SCSI_XFER_MAX >= sizeof(scsiDev.data), "Assumes SCSI_XFER_MAX >= sizeof(scsiDev.data)");
\r
740 // Start reading and filling fifos as soon as possible.
\r
741 // It's highly unlikely that someone is going to use huge transfers
\r
742 // per scsi command, but if they do it'll be slower than usual.
\r
743 // Note: Happens in Macintosh FWB HDD Toolkit benchmarks which default
\r
745 uint32_t totalTransferBytes = transfer.blocks * bytesPerSector;
\r
746 int useSlowDataCount = totalTransferBytes >= SCSI_XFER_MAX;
\r
747 if (!useSlowDataCount)
\r
749 DWT->CYCCNT = 0; // Start counting cycles
\r
750 scsiSetDataCount(totalTransferBytes);
\r
753 while ((i < totalSDSectors) &&
\r
754 likely(scsiDev.phase == DATA_OUT) &&
\r
755 likely(!scsiDev.resetFlag))
\r
756 // KEEP GOING to ensure FIFOs are in a good state.
\r
757 // likely(!parityError || !enableParity))
\r
759 uint32_t rem = totalSDSectors - i;
\r
760 uint32_t sectors = rem < maxSectors ? rem : maxSectors;
\r
762 if (bytesPerSector == SD_SECTOR_SIZE)
\r
764 // We assume the SD card is faster than the SCSI interface, but has
\r
765 // no flow control. This can be handled if a) the scsi interface
\r
766 // doesn't block and b) we read enough SCSI sectors first so that
\r
767 // the SD interface cannot catch up.
\r
768 uint32_t totalBytes = sectors * SD_SECTOR_SIZE;
\r
770 uint32_t sdSpeedKBs = s2s_getSdRateKBs() + (scsiDev.sdUnderrunCount * 256);
\r
771 uint32_t readAheadBytes = calcReadahead(
\r
774 scsiDev.hostSpeedKBs);
\r
776 if (useSlowDataCount)
\r
778 DWT->CYCCNT = 0; // Start counting cycles
\r
779 scsiSetDataCount(totalBytes);
\r
782 uint32_t scsiBytesRead = 0;
\r
783 if (readAheadBytes > 0)
\r
786 &scsiDev.data[scsiBytesRead],
\r
789 scsiBytesRead += readAheadBytes;
\r
791 if (i == 0 && !useSlowDataCount)
\r
793 uint32_t elapsedCycles = DWT->CYCCNT;
\r
795 // uint32_t rateKBs = (readAheadBytes / 1000) / (elapsedCycles / HAL_RCC_GetHCLKFreq());
\r
796 // Scaled by 4 to avoid overflow w/ max 65536 at 108MHz.
\r
797 uint32_t rateKBs = ((readAheadBytes / 4) * (HAL_RCC_GetHCLKFreq() / 1000) / elapsedCycles) * 4;
\r
799 scsiDev.hostSpeedKBs = (scsiDev.hostSpeedKBs + rateKBs) / 2;
\r
800 scsiDev.hostSpeedMeasured = 1;
\r
802 if (rateKBs < scsiDev.hostSpeedKBs)
\r
804 // Our readahead was too slow; assume remaining bytes
\r
805 // will be as well.
\r
806 if (readAheadBytes < totalBytes)
\r
808 uint32_t properReadahead = calcReadahead(
\r
813 if (properReadahead > readAheadBytes)
\r
815 uint32_t diff = properReadahead - readAheadBytes;
\r
816 readAheadBytes = properReadahead;
\r
818 &scsiDev.data[scsiBytesRead],
\r
821 scsiBytesRead += diff;
\r
828 HAL_SD_WriteBlocks_DMA(&hsd, (uint32_t*) (&scsiDev.data[0]), (i + sdLBA) * 512ll, SD_SECTOR_SIZE, sectors);
\r
831 if (scsiBytesRead < totalBytes && !scsiDev.resetFlag)
\r
834 &scsiDev.data[scsiBytesRead],
\r
835 totalBytes - readAheadBytes,
\r
838 // Oh dear, SD finished first.
\r
839 underrun = hsd.DmaTransferCplt;
\r
841 scsiBytesRead += (totalBytes - readAheadBytes);
\r
844 uint32_t dmaFinishTime = s2s_getTime_ms();
\r
845 while ((!hsd.SdTransferCplt ||
\r
846 __HAL_SD_SDIO_GET_FLAG(&hsd, SDIO_FLAG_TXACT)) &&
\r
847 s2s_elapsedTime_ms(dmaFinishTime) < 180)
\r
849 // Wait while keeping BSY.
\r
852 if (i + sectors >= totalSDSectors &&
\r
854 (!parityError || !enableParity))
\r
856 // We're transferring over the SCSI bus faster than the SD card
\r
857 // can write. All data is buffered, and we're just waiting for
\r
858 // the SD card to complete. The host won't let us disconnect.
\r
859 // Some drivers set a 250ms timeout on transfers to complete.
\r
860 // SD card writes are supposed to complete
\r
861 // within 200ms, but sometimes they don't.
\r
862 // Just pretend we're finished.
\r
864 clearBSY = process_MessageIn(0); // Will go to BUS_FREE state but keep BSY asserted.
\r
867 HAL_SD_CheckWriteOperation(&hsd, (uint32_t)SD_DATATIMEOUT);
\r
869 if (underrun && (!parityError || !enableParity))
\r
871 // Try again. Data is still in memory.
\r
872 sdTmpWrite(&scsiDev.data[0], i + sdLBA, sectors);
\r
873 scsiDev.sdUnderrunCount++;
\r
880 // Well, until we have some proper non-blocking SD code, we must
\r
881 // do this in a half-duplex fashion. We need to write as much as
\r
882 // possible in each SD card transaction.
\r
883 // use sg_dd from sg_utils3 tools to test.
\r
885 if (useSlowDataCount)
\r
887 scsiSetDataCount(sectors * bytesPerSector);
\r
890 for (int scsiSector = i; scsiSector < i + sectors; ++scsiSector)
\r
892 int dmaBytes = SD_SECTOR_SIZE;
\r
893 if ((scsiSector % sdPerScsi) == (sdPerScsi - 1))
\r
895 dmaBytes = bytesPerSector % SD_SECTOR_SIZE;
\r
896 if (dmaBytes == 0) dmaBytes = SD_SECTOR_SIZE;
\r
899 scsiReadPIO(&scsiDev.data[SD_SECTOR_SIZE * (scsiSector - i)], dmaBytes, &parityError);
\r
901 if (!parityError || !enableParity)
\r
903 sdTmpWrite(&scsiDev.data[0], i + sdLBA, sectors);
\r
909 // Should already be complete here as we've ready the FIFOs
\r
910 // by now. Check anyway.
\r
912 while (!scsiPhyComplete() && likely(!scsiDev.resetFlag))
\r
923 if (scsiDev.phase == DATA_OUT)
\r
926 (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY))
\r
928 scsiDev.target->sense.code = ABORTED_COMMAND;
\r
929 scsiDev.target->sense.asc = SCSI_PARITY_ERROR;
\r
930 scsiDev.status = CHECK_CONDITION;;
\r
932 scsiDev.phase = STATUS;
\r
938 void scsiDiskReset()
\r
940 scsiDev.dataPtr = 0;
\r
941 scsiDev.savedDataPtr = 0;
\r
942 scsiDev.dataLen = 0;
\r
943 // transfer.lba = 0; // Needed in Request Sense to determine failure
\r
944 transfer.blocks = 0;
\r
945 transfer.currentBlock = 0;
\r
947 // Cancel long running commands!
\r
950 ((scsiDev.boardCfg.flags & S2S_CFG_ENABLE_CACHE) == 0) ||
\r
951 (transfer.multiBlock == 0)
\r
955 sdCompleteTransfer();
\r
958 transfer.multiBlock = 0;
\r
961 void scsiDiskInit()
\r
965 // Don't require the host to send us a START STOP UNIT command
\r
966 blockDev.state = DISK_STARTED;
\r