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
20 #include "stm32f2xx.h"
\r
23 #include "stm32f4xx.h"
\r
28 // For SD write direct routines
\r
30 #include "bsp_driver_sd.h"
\r
34 #include "scsiPhy.h"
\r
44 BlockDevice blockDev;
\r
47 static int doSdInit()
\r
50 if (blockDev.state & DISK_PRESENT)
\r
52 blockDev.state = blockDev.state | DISK_INITIALISED;
\r
57 // Callback once all data has been read in the data out phase.
\r
58 static void doFormatUnitComplete(void)
\r
60 // TODO start writing the initialisation pattern to the SD
\r
62 scsiDev.phase = STATUS;
\r
65 static void doFormatUnitSkipData(int bytes)
\r
67 // We may not have enough memory to store the initialisation pattern and
\r
68 // defect list data. Since we're not making use of it yet anyway, just
\r
69 // discard the bytes.
\r
70 scsiEnterPhase(DATA_OUT);
\r
72 for (i = 0; i < bytes; ++i)
\r
78 // Callback from the data out phase.
\r
79 static void doFormatUnitPatternHeader(void)
\r
82 ((((uint16_t)scsiDev.data[2])) << 8) +
\r
86 ((((uint16_t)scsiDev.data[4 + 2])) << 8) +
\r
87 scsiDev.data[4 + 3];
\r
89 doFormatUnitSkipData(defectLength + patternLength);
\r
90 doFormatUnitComplete();
\r
93 // Callback from the data out phase.
\r
94 static void doFormatUnitHeader(void)
\r
96 int IP = (scsiDev.data[1] & 0x08) ? 1 : 0;
\r
97 int DSP = (scsiDev.data[1] & 0x04) ? 1 : 0;
\r
99 if (! DSP) // disable save parameters
\r
101 // Save the "MODE SELECT savable parameters"
\r
103 scsiDev.target->targetId,
\r
104 scsiDev.target->liveCfg.bytesPerSector);
\r
109 // We need to read the initialisation pattern header first.
\r
110 scsiDev.dataLen += 4;
\r
111 scsiDev.phase = DATA_OUT;
\r
112 scsiDev.postDataOutHook = doFormatUnitPatternHeader;
\r
116 // Read the defect list data
\r
118 ((((uint16_t)scsiDev.data[2])) << 8) +
\r
120 doFormatUnitSkipData(defectLength);
\r
121 doFormatUnitComplete();
\r
125 static void doReadCapacity()
\r
127 uint32_t lba = (((uint32_t) scsiDev.cdb[2]) << 24) +
\r
128 (((uint32_t) scsiDev.cdb[3]) << 16) +
\r
129 (((uint32_t) scsiDev.cdb[4]) << 8) +
\r
131 int pmi = scsiDev.cdb[8] & 1;
\r
133 uint32_t capacity = getScsiCapacity(
\r
134 scsiDev.target->cfg->sdSectorStart,
\r
135 scsiDev.target->liveCfg.bytesPerSector,
\r
136 scsiDev.target->cfg->scsiSectors);
\r
141 // We don't do anything with the "partial medium indicator", and
\r
142 // assume that delays are constant across each block. But the spec
\r
143 // says we must return this error if pmi is specified incorrectly.
\r
144 scsiDev.status = CHECK_CONDITION;
\r
145 scsiDev.target->sense.code = ILLEGAL_REQUEST;
\r
146 scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
\r
147 scsiDev.phase = STATUS;
\r
149 else if (capacity > 0)
\r
151 uint32_t highestBlock = capacity - 1;
\r
153 scsiDev.data[0] = highestBlock >> 24;
\r
154 scsiDev.data[1] = highestBlock >> 16;
\r
155 scsiDev.data[2] = highestBlock >> 8;
\r
156 scsiDev.data[3] = highestBlock;
\r
158 uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
\r
159 scsiDev.data[4] = bytesPerSector >> 24;
\r
160 scsiDev.data[5] = bytesPerSector >> 16;
\r
161 scsiDev.data[6] = bytesPerSector >> 8;
\r
162 scsiDev.data[7] = bytesPerSector;
\r
163 scsiDev.dataLen = 8;
\r
164 scsiDev.phase = DATA_IN;
\r
168 scsiDev.status = CHECK_CONDITION;
\r
169 scsiDev.target->sense.code = NOT_READY;
\r
170 scsiDev.target->sense.asc = MEDIUM_NOT_PRESENT;
\r
171 scsiDev.phase = STATUS;
\r
175 static void doWrite(uint32_t lba, uint32_t blocks)
\r
177 if (unlikely(scsiDev.target->cfg->deviceType == S2S_CFG_FLOPPY_14MB)) {
\r
178 // Floppies are supposed to be slow. Some systems can't handle a floppy
\r
179 // without an access time
\r
183 uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
\r
185 if (unlikely(blockDev.state & DISK_WP) ||
\r
186 unlikely(scsiDev.target->cfg->deviceType == S2S_CFG_OPTICAL))
\r
189 scsiDev.status = CHECK_CONDITION;
\r
190 scsiDev.target->sense.code = ILLEGAL_REQUEST;
\r
191 scsiDev.target->sense.asc = WRITE_PROTECTED;
\r
192 scsiDev.phase = STATUS;
\r
194 else if (unlikely(((uint64_t) lba) + blocks >
\r
196 scsiDev.target->cfg->sdSectorStart,
\r
198 scsiDev.target->cfg->scsiSectors
\r
202 scsiDev.status = CHECK_CONDITION;
\r
203 scsiDev.target->sense.code = ILLEGAL_REQUEST;
\r
204 scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
\r
205 scsiDev.phase = STATUS;
\r
209 transfer.lba = lba;
\r
210 transfer.blocks = blocks;
\r
211 transfer.currentBlock = 0;
\r
212 scsiDev.phase = DATA_OUT;
\r
213 scsiDev.dataLen = bytesPerSector;
\r
214 scsiDev.dataPtr = bytesPerSector;
\r
216 // No need for single-block writes atm. Overhead of the
\r
217 // multi-block write is minimal.
\r
218 transfer.multiBlock = 1;
\r
223 static void doRead(uint32_t lba, uint32_t blocks)
\r
225 if (unlikely(scsiDev.target->cfg->deviceType == S2S_CFG_FLOPPY_14MB)) {
\r
226 // Floppies are supposed to be slow. Some systems can't handle a floppy
\r
227 // without an access time
\r
231 uint32_t capacity = getScsiCapacity(
\r
232 scsiDev.target->cfg->sdSectorStart,
\r
233 scsiDev.target->liveCfg.bytesPerSector,
\r
234 scsiDev.target->cfg->scsiSectors);
\r
235 if (unlikely(((uint64_t) lba) + blocks > capacity))
\r
237 scsiDev.status = CHECK_CONDITION;
\r
238 scsiDev.target->sense.code = ILLEGAL_REQUEST;
\r
239 scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
\r
240 scsiDev.phase = STATUS;
\r
244 transfer.lba = lba;
\r
245 transfer.blocks = blocks;
\r
246 transfer.currentBlock = 0;
\r
247 scsiDev.phase = DATA_IN;
\r
248 scsiDev.dataLen = 0; // No data yet
\r
250 uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
\r
251 uint32_t sdSectorPerSCSISector = SDSectorsPerSCSISector(bytesPerSector);
\r
252 uint32_t sdSectors =
\r
253 blocks * sdSectorPerSCSISector;
\r
256 (sdSectors == 1) &&
\r
257 !(scsiDev.boardCfg.flags & S2S_CFG_ENABLE_CACHE)
\r
259 unlikely(((uint64_t) lba) + blocks == capacity)
\r
262 // We get errors on reading the last sector using a multi-sector
\r
264 transfer.multiBlock = 0;
\r
268 transfer.multiBlock = 1;
\r
270 // uint32_t sdLBA =
\r
272 // scsiDev.target->cfg->sdSectorStart,
\r
276 // TODO sdReadMultiSectorPrep(sdLBA, sdSectors);
\r
281 static void doSeek(uint32_t lba)
\r
285 scsiDev.target->cfg->sdSectorStart,
\r
286 scsiDev.target->liveCfg.bytesPerSector,
\r
287 scsiDev.target->cfg->scsiSectors)
\r
290 scsiDev.status = CHECK_CONDITION;
\r
291 scsiDev.target->sense.code = ILLEGAL_REQUEST;
\r
292 scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
\r
293 scsiDev.phase = STATUS;
\r
297 if (unlikely(scsiDev.target->cfg->deviceType == S2S_CFG_FLOPPY_14MB) ||
\r
298 scsiDev.compatMode < COMPAT_SCSI2)
\r
309 static int doTestUnitReady()
\r
312 if (likely(blockDev.state == (DISK_PRESENT | DISK_INITIALISED) &&
\r
313 scsiDev.target->started))
\r
317 else if (unlikely(!scsiDev.target->started))
\r
320 scsiDev.status = CHECK_CONDITION;
\r
321 scsiDev.target->sense.code = NOT_READY;
\r
322 scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED;
\r
323 scsiDev.phase = STATUS;
\r
325 else if (unlikely(!(blockDev.state & DISK_PRESENT)))
\r
328 scsiDev.status = CHECK_CONDITION;
\r
329 scsiDev.target->sense.code = NOT_READY;
\r
330 scsiDev.target->sense.asc = MEDIUM_NOT_PRESENT;
\r
331 scsiDev.phase = STATUS;
\r
333 else if (unlikely(!(blockDev.state & DISK_INITIALISED)))
\r
336 scsiDev.status = CHECK_CONDITION;
\r
337 scsiDev.target->sense.code = NOT_READY;
\r
338 scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_READY_CAUSE_NOT_REPORTABLE;
\r
339 scsiDev.phase = STATUS;
\r
344 // Handle direct-access scsi device commands
\r
345 int scsiDiskCommand()
\r
347 int commandHandled = 1;
\r
349 uint8_t command = scsiDev.cdb[0];
\r
350 if (unlikely(command == 0x1B))
\r
353 // Enable or disable media access operations.
\r
354 //int immed = scsiDev.cdb[1] & 1;
\r
355 int start = scsiDev.cdb[4] & 1;
\r
356 int loadEject = scsiDev.cdb[4] & 2;
\r
360 // Ignore load/eject requests. We can't do that.
\r
364 scsiDev.target->started = 1;
\r
365 if (!(blockDev.state & DISK_INITIALISED))
\r
372 scsiDev.target->started = 0;
\r
375 else if (unlikely(command == 0x00))
\r
380 else if (unlikely(!doTestUnitReady()))
\r
382 // Status and sense codes already set by doTestUnitReady
\r
384 else if (likely(command == 0x08))
\r
388 (((uint32_t) scsiDev.cdb[1] & 0x1F) << 16) +
\r
389 (((uint32_t) scsiDev.cdb[2]) << 8) +
\r
391 uint32_t blocks = scsiDev.cdb[4];
\r
392 if (unlikely(blocks == 0)) blocks = 256;
\r
393 doRead(lba, blocks);
\r
395 else if (likely(command == 0x28))
\r
398 // Ignore all cache control bits - we don't support a memory cache.
\r
401 (((uint32_t) scsiDev.cdb[2]) << 24) +
\r
402 (((uint32_t) scsiDev.cdb[3]) << 16) +
\r
403 (((uint32_t) scsiDev.cdb[4]) << 8) +
\r
406 (((uint32_t) scsiDev.cdb[7]) << 8) +
\r
409 doRead(lba, blocks);
\r
411 else if (likely(command == 0x0A))
\r
415 (((uint32_t) scsiDev.cdb[1] & 0x1F) << 16) +
\r
416 (((uint32_t) scsiDev.cdb[2]) << 8) +
\r
418 uint32_t blocks = scsiDev.cdb[4];
\r
419 if (unlikely(blocks == 0)) blocks = 256;
\r
420 doWrite(lba, blocks);
\r
422 else if (likely(command == 0x2A) || // WRITE(10)
\r
423 unlikely(command == 0x2E)) // WRITE AND VERIFY
\r
425 // Ignore all cache control bits - we don't support a memory cache.
\r
426 // Don't bother verifying either. The SD card likely stores ECC
\r
427 // along with each flash row.
\r
430 (((uint32_t) scsiDev.cdb[2]) << 24) +
\r
431 (((uint32_t) scsiDev.cdb[3]) << 16) +
\r
432 (((uint32_t) scsiDev.cdb[4]) << 8) +
\r
435 (((uint32_t) scsiDev.cdb[7]) << 8) +
\r
438 doWrite(lba, blocks);
\r
440 else if (unlikely(command == 0x04))
\r
443 // We don't really do any formatting, but we need to read the correct
\r
444 // number of bytes in the DATA_OUT phase to make the SCSI host happy.
\r
446 int fmtData = (scsiDev.cdb[1] & 0x10) ? 1 : 0;
\r
449 // We need to read the parameter list, but we don't know how
\r
450 // big it is yet. Start with the header.
\r
451 scsiDev.dataLen = 4;
\r
452 scsiDev.phase = DATA_OUT;
\r
453 scsiDev.postDataOutHook = doFormatUnitHeader;
\r
457 // No data to read, we're already finished!
\r
460 else if (unlikely(command == 0x25))
\r
465 else if (unlikely(command == 0x0B))
\r
469 (((uint32_t) scsiDev.cdb[1] & 0x1F) << 16) +
\r
470 (((uint32_t) scsiDev.cdb[2]) << 8) +
\r
476 else if (unlikely(command == 0x2B))
\r
480 (((uint32_t) scsiDev.cdb[2]) << 24) +
\r
481 (((uint32_t) scsiDev.cdb[3]) << 16) +
\r
482 (((uint32_t) scsiDev.cdb[4]) << 8) +
\r
487 else if (unlikely(command == 0x36))
\r
489 // LOCK UNLOCK CACHE
\r
490 // We don't have a cache to lock data into. do nothing.
\r
492 else if (unlikely(command == 0x34))
\r
495 // We don't have a cache to pre-fetch into. do nothing.
\r
497 else if (unlikely(command == 0x1E))
\r
499 // PREVENT ALLOW MEDIUM REMOVAL
\r
500 // Not much we can do to prevent the user removing the SD card.
\r
503 else if (unlikely(command == 0x01))
\r
506 // Set the lun to a vendor-specific state. Ignore.
\r
508 else if (unlikely(command == 0x35))
\r
510 // SYNCHRONIZE CACHE
\r
511 // We don't have a cache. do nothing.
\r
513 else if (unlikely(command == 0x2F))
\r
516 // TODO: When they supply data to verify, we should read the data and
\r
517 // verify it. If they don't supply any data, just say success.
\r
518 if ((scsiDev.cdb[1] & 0x02) == 0)
\r
520 // They are asking us to do a medium verification with no data
\r
521 // comparison. Assume success, do nothing.
\r
525 // TODO. This means they are supplying data to verify against.
\r
526 // Technically we should probably grab the data and compare it.
\r
527 scsiDev.status = CHECK_CONDITION;
\r
528 scsiDev.target->sense.code = ILLEGAL_REQUEST;
\r
529 scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
\r
530 scsiDev.phase = STATUS;
\r
533 else if (unlikely(command == 0x37))
\r
535 // READ DEFECT DATA
\r
536 uint32_t allocLength = (((uint16_t)scsiDev.cdb[7]) << 8) |
\r
539 scsiDev.data[0] = 0;
\r
540 scsiDev.data[1] = scsiDev.cdb[1];
\r
541 scsiDev.data[2] = 0;
\r
542 scsiDev.data[3] = 0;
\r
543 scsiDev.dataLen = 4;
\r
545 if (scsiDev.dataLen > allocLength)
\r
547 scsiDev.dataLen = allocLength;
\r
550 scsiDev.phase = DATA_IN;
\r
554 commandHandled = 0;
\r
557 return commandHandled;
\r
560 static void diskDataInBuffered(int totalSDSectors, uint32_t sdLBA, int useSlowDataCount, uint32_t* phaseChangeDelayNs)
\r
562 uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
\r
564 const int sdPerScsi = SDSectorsPerSCSISector(bytesPerSector);
\r
565 const int buffers = sizeof(scsiDev.data) / SD_SECTOR_SIZE;
\r
568 int scsiActive __attribute__((unused)) = 0; // unused if DMA disabled
\r
574 while ((i < totalSDSectors) &&
\r
575 likely(scsiDev.phase == DATA_IN) &&
\r
576 likely(!scsiDev.resetFlag))
\r
578 int completedDmaSectors;
\r
579 if (sdActive && (completedDmaSectors = sdReadDMAPoll(sdActive)))
\r
581 prep += completedDmaSectors;
\r
582 sdActive -= completedDmaSectors;
\r
585 else if (sdActive > 1)
\r
587 if ((scsiDev.data[SD_SECTOR_SIZE * (prep % buffers) + 510] != 0xAA) ||
\r
588 (scsiDev.data[SD_SECTOR_SIZE * (prep % buffers) + 511] != 0x33))
\r
594 else if (scsiDev.data[SD_SECTOR_SIZE * (prep % buffers) + 127] != 0xAA)
\r
602 (prep - i < buffers) &&
\r
603 (prep < totalSDSectors) &&
\r
604 ((totalSDSectors - prep) >= sdPerScsi) &&
\r
605 (likely(!useSlowDataCount) || scsiPhyComplete()) &&
\r
606 (HAL_SD_GetState(&hsd) != HAL_SD_STATE_BUSY)) // rx complete but IRQ not fired yet.
\r
608 // Start an SD transfer if we have space.
\r
609 uint32_t startBuffer = prep % buffers;
\r
610 uint32_t sectors = totalSDSectors - prep;
\r
611 uint32_t freeBuffers = buffers - (prep - i);
\r
613 uint32_t contiguousBuffers = buffers - startBuffer;
\r
614 freeBuffers = freeBuffers < contiguousBuffers
\r
615 ? freeBuffers : contiguousBuffers;
\r
616 sectors = sectors < freeBuffers ? sectors : freeBuffers;
\r
618 if (sectors > 128) sectors = 128; // 65536 DMA limit !!
\r
620 // Round-down when we have odd sector sizes.
\r
621 if (sdPerScsi != 1)
\r
623 sectors = (sectors / sdPerScsi) * sdPerScsi;
\r
626 for (int dodgy = 0; dodgy < sectors; dodgy++)
\r
628 scsiDev.data[SD_SECTOR_SIZE * (startBuffer + dodgy) + 127] = 0xAA;
\r
630 scsiDev.data[SD_SECTOR_SIZE * (startBuffer + dodgy) + 510] = 0xAA;
\r
631 scsiDev.data[SD_SECTOR_SIZE * (startBuffer + dodgy) + 511] = 0x33;
\r
634 sdReadDMA(sdLBA + prep, sectors, &scsiDev.data[SD_SECTOR_SIZE * startBuffer]);
\r
636 sdActive = sectors;
\r
638 if (useSlowDataCount)
\r
640 scsiSetDataCount((sectors / sdPerScsi) * bytesPerSector);
\r
643 // Wait now that the SD card is busy
\r
644 // Chances are we've probably already waited sufficient time,
\r
645 // but it's hard to measure microseconds cheaply. So just wait
\r
646 // extra just-in-case. Hopefully it's in parallel with dma.
\r
647 if (*phaseChangeDelayNs > 0)
\r
649 s2s_delay_ns(*phaseChangeDelayNs);
\r
650 *phaseChangeDelayNs = 0;
\r
654 int fifoReady = scsiFifoReady();
\r
655 if (((prep - i) > 0) && fifoReady)
\r
657 int dmaBytes = SD_SECTOR_SIZE;
\r
658 if ((i % sdPerScsi) == (sdPerScsi - 1))
\r
660 dmaBytes = bytesPerSector % SD_SECTOR_SIZE;
\r
661 if (dmaBytes == 0) dmaBytes = SD_SECTOR_SIZE;
\r
664 uint8_t* scsiDmaData = &(scsiDev.data[SD_SECTOR_SIZE * (i % buffers)]);
\r
668 scsiDmaData += SD_SECTOR_SIZE / 2;
\r
669 dmaBytes -= (SD_SECTOR_SIZE / 2);
\r
671 scsiWritePIO(scsiDmaData, dmaBytes);
\r
677 else if (gotHalf && !sentHalf && fifoReady && bytesPerSector == SD_SECTOR_SIZE)
\r
679 uint8_t* scsiDmaData = &(scsiDev.data[SD_SECTOR_SIZE * (i % buffers)]);
\r
680 scsiWritePIO(scsiDmaData, SD_SECTOR_SIZE / 2);
\r
686 // Transfer from the SD card straight to the SCSI Fifo without storing in memory first for lower latency
\r
687 // This requires hardware flow control on the SD device (broken on stm32f205)
\r
688 // Only functional for 512 byte sectors.
\r
689 static void diskDataInDirect(uint32_t totalSDSectors, uint32_t sdLBA, int useSlowDataCount, uint32_t* phaseChangeDelayNs)
\r
691 sdReadCmd(sdLBA, totalSDSectors);
\r
693 // Wait while the SD card starts buffering data
\r
694 if (*phaseChangeDelayNs > 0)
\r
696 s2s_delay_ns(*phaseChangeDelayNs);
\r
697 *phaseChangeDelayNs = 0;
\r
700 for (int i = 0; i < totalSDSectors && !scsiDev.resetFlag; ++i)
\r
704 // SD DPSM has 24 bit limit. Re-use 128 (DMA limit)
\r
705 uint32_t chunk = totalSDSectors - i > 128 ? 128 : totalSDSectors - i;
\r
706 sdReadPIOData(chunk);
\r
708 if (useSlowDataCount)
\r
710 while (!scsiDev.resetFlag && !scsiPhyComplete())
\r
712 scsiSetDataCount(chunk * SD_SECTOR_SIZE); // SCSI_XFER_MAX > 65536
\r
716 // The SCSI fifo is a full sector so we only need to check once.
\r
717 while (!scsiFifoReady() && !scsiDev.resetFlag)
\r
721 while(byteCount < SD_SECTOR_SIZE &&
\r
722 likely(!scsiDev.resetFlag) &&
\r
723 likely(scsiDev.phase == DATA_IN) &&
\r
724 !__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT))
\r
726 if(__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXFIFOHF))
\r
728 // The SDIO fifo is 32 x 32bits. As we're using the "half full" flag we must
\r
729 // always read half the FIFO.
\r
731 for (int j = 0; j < 4; ++j)
\r
734 data[0] = SDIO_ReadFIFO(hsd.Instance);
\r
735 data[1] = SDIO_ReadFIFO(hsd.Instance);
\r
736 data[2] = SDIO_ReadFIFO(hsd.Instance);
\r
737 data[3] = SDIO_ReadFIFO(hsd.Instance);
\r
739 *((volatile uint32_t*)SCSI_FIFO_DATA) = data[0];
\r
740 *((volatile uint32_t*)SCSI_FIFO_DATA) = data[1];
\r
741 *((volatile uint32_t*)SCSI_FIFO_DATA) = data[2];
\r
742 *((volatile uint32_t*)SCSI_FIFO_DATA) = data[3];
\r
750 if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_DTIMEOUT))
\r
752 __HAL_SD_CLEAR_FLAG(&hsd, SDIO_FLAG_DTIMEOUT);
\r
755 else if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_DCRCFAIL))
\r
757 __HAL_SD_CLEAR_FLAG(&hsd, SDIO_FLAG_DCRCFAIL);
\r
760 else if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXOVERR))
\r
762 __HAL_SD_CLEAR_FLAG(&hsd, SDIO_FLAG_RXOVERR);
\r
766 if (error && scsiDev.phase == DATA_IN)
\r
768 __HAL_SD_CLEAR_FLAG(&hsd, SDIO_STATIC_FLAGS);
\r
772 scsiDev.status = CHECK_CONDITION;
\r
773 scsiDev.target->sense.code = HARDWARE_ERROR;
\r
774 scsiDev.target->sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;
\r
775 scsiDev.phase = STATUS;
\r
778 // We need the SCSI FIFO count to complete even after the SD read has failed
\r
779 while (byteCount < SD_SECTOR_SIZE &&
\r
780 likely(!scsiDev.resetFlag))
\r
787 /* Send stop transmission command in case of multiblock read */
\r
788 if(totalSDSectors > 1U)
\r
790 SDMMC_CmdStopTransfer(hsd.Instance);
\r
793 // Read remaining data
\r
794 uint32_t extraCount = SD_DATATIMEOUT;
\r
795 while ((__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXDAVL)) && (extraCount > 0))
\r
797 SDIO_ReadFIFO(hsd.Instance);
\r
801 __HAL_SD_CLEAR_FLAG(&hsd, SDIO_STATIC_DATA_FLAGS);
\r
802 hsd.State = HAL_SD_STATE_READY;
\r
804 sdCompleteTransfer(); // Probably overkill
\r
807 static void diskDataIn()
\r
809 uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
\r
811 // Take responsibility for waiting for the phase delays
\r
812 uint32_t phaseChangeDelayNs = scsiEnterPhaseImmediate(DATA_IN);
\r
814 int totalSDSectors =
\r
815 transfer.blocks * SDSectorsPerSCSISector(bytesPerSector);
\r
818 scsiDev.target->cfg->sdSectorStart,
\r
822 // It's highly unlikely that someone is going to use huge transfers
\r
823 // per scsi command, but if they do it'll be slower than usual.
\r
824 uint32_t totalScsiBytes = transfer.blocks * bytesPerSector;
\r
825 int useSlowDataCount = totalScsiBytes >= SCSI_XFER_MAX;
\r
826 if (!useSlowDataCount)
\r
828 scsiSetDataCount(totalScsiBytes);
\r
832 // Direct mode requires hardware flow control to be working on the SD peripheral
\r
833 // Code isn't currently working above 128 sectors. TODO investigate
\r
834 if (totalSDSectors < 128 && bytesPerSector == SD_SECTOR_SIZE)
\r
836 diskDataInDirect(totalSDSectors, sdLBA, useSlowDataCount, &phaseChangeDelayNs);
\r
841 diskDataInBuffered(totalSDSectors, sdLBA, useSlowDataCount, &phaseChangeDelayNs);
\r
844 if (phaseChangeDelayNs > 0 && !scsiDev.resetFlag) // zero bytes ?
\r
846 s2s_delay_ns(phaseChangeDelayNs);
\r
847 phaseChangeDelayNs = 0;
\r
850 if (scsiDev.resetFlag)
\r
852 HAL_SD_Abort(&hsd);
\r
856 // Wait for the SD transfer to complete before we disable IRQs.
\r
857 // (Otherwise some cards will cause an error if we don't sent the
\r
858 // stop transfer command via the DMA complete handler in time)
\r
859 while (HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY)
\r
861 // Wait while keeping BSY.
\r
865 HAL_SD_CardStateTypeDef cardState = HAL_SD_GetCardState(&hsd);
\r
866 while (cardState == HAL_SD_CARD_PROGRAMMING || cardState == HAL_SD_CARD_SENDING)
\r
868 cardState = HAL_SD_GetCardState(&hsd);
\r
871 // We've finished transferring the data to the FPGA, now wait until it's
\r
872 // written to he SCSI bus.
\r
873 while (!scsiPhyComplete() &&
\r
874 likely(scsiDev.phase == DATA_IN) &&
\r
875 likely(!scsiDev.resetFlag))
\r
880 if (scsiDev.phase == DATA_IN)
\r
882 scsiDev.phase = STATUS;
\r
887 void diskDataOut_512(int totalSDSectors, uint32_t sdLBA, int useSlowDataCount, int* clearBSY, int* parityError)
\r
890 int disconnected = 0;
\r
892 int enableParity = scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY;
\r
894 uint32_t maxSectors = sizeof(scsiDev.data) / SD_SECTOR_SIZE;
\r
896 int lastWriteSize = 0;
\r
898 while ((i < totalSDSectors) &&
\r
899 likely(scsiDev.phase == DATA_OUT) &&
\r
900 likely(!scsiDev.resetFlag))
\r
901 // KEEP GOING to ensure FIFOs are in a good state.
\r
902 // likely(!parityError || !enableParity))
\r
905 uint32_t maxXferSectors = SCSI_XFER_MAX / SD_SECTOR_SIZE;
\r
906 uint32_t rem = totalSDSectors - i;
\r
907 uint32_t sectors = rem < maxXferSectors ? rem : maxXferSectors;
\r
909 uint32_t totalBytes = sectors * SD_SECTOR_SIZE;
\r
911 if (useSlowDataCount)
\r
913 scsiSetDataCount(totalBytes);
\r
916 lastWriteSize = sectors;
\r
917 HAL_SD_WriteBlocks_DMA(&hsd, i + sdLBA, sectors);
\r
921 uint32_t dmaFinishTime = 0;
\r
922 while (j < sectors && !scsiDev.resetFlag)
\r
925 HAL_SD_GetState(&hsd) != HAL_SD_STATE_BUSY &&
\r
931 if (!sdActive && ((prep - j) > 0))
\r
933 // Start an SD transfer if we have space.
\r
934 HAL_SD_WriteBlocks_Data(&hsd, &scsiDev.data[SD_SECTOR_SIZE * (j % maxSectors)]);
\r
939 if (((prep - j) < maxSectors) &&
\r
940 (prep < sectors) &&
\r
944 &scsiDev.data[(prep % maxSectors) * SD_SECTOR_SIZE],
\r
948 if (prep == sectors)
\r
950 dmaFinishTime = s2s_getTime_ms();
\r
954 if (i + prep >= totalSDSectors &&
\r
956 (!(*parityError) || !enableParity) &&
\r
957 s2s_elapsedTime_ms(dmaFinishTime) >= 180)
\r
959 // We're transferring over the SCSI bus faster than the SD card
\r
960 // can write. All data is buffered, and we're just waiting for
\r
961 // the SD card to complete. The host won't let us disconnect.
\r
962 // Some drivers set a 250ms timeout on transfers to complete.
\r
963 // SD card writes are supposed to complete
\r
964 // within 200ms, but sometimes they don't.
\r
965 // Just pretend we're finished.
\r
967 *clearBSY = process_MessageIn(0); // Will go to BUS_FREE state but keep BSY asserted.
\r
972 if (scsiDev.resetFlag)
\r
974 HAL_SD_Abort(&hsd);
\r
978 while (HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY) {} // Waits for DMA to complete
\r
979 if (lastWriteSize > 1)
\r
981 SDMMC_CmdStopTransfer(hsd.Instance);
\r
985 while (sdIsBusy() &&
\r
986 s2s_elapsedTime_ms(dmaFinishTime) < 180)
\r
988 // Wait while the SD card is writing buffer to flash
\r
989 // The card may remain in the RECEIVING state (even though it's programming) if
\r
990 // it has buffer space to receive more data available.
\r
993 if (!disconnected &&
\r
994 i + sectors >= totalSDSectors &&
\r
995 (!parityError || !enableParity))
\r
997 // We're transferring over the SCSI bus faster than the SD card
\r
998 // can write. All data is buffered, and we're just waiting for
\r
999 // the SD card to complete. The host won't let us disconnect.
\r
1000 // Some drivers set a 250ms timeout on transfers to complete.
\r
1001 // SD card writes are supposed to complete
\r
1002 // within 200ms, but sometimes they don't.
\r
1003 // Just pretend we're finished.
\r
1005 *clearBSY = process_MessageIn(0); // Will go to BUS_FREE state but keep BSY asserted.
\r
1008 // Wait while the SD card is writing buffer to flash
\r
1009 // The card may remain in the RECEIVING state (even though it's programming) if
\r
1010 // it has buffer space to receive more data available.
\r
1011 while (sdIsBusy()) {}
\r
1012 HAL_SD_CardStateTypeDef cardState = HAL_SD_GetCardState(&hsd);
\r
1013 while (cardState == HAL_SD_CARD_PROGRAMMING || cardState == HAL_SD_CARD_RECEIVING)
\r
1015 // Wait while the SD card is writing buffer to flash
\r
1016 // The card may remain in the RECEIVING state (even though it's programming) if
\r
1017 // it has buffer space to receive more data available.
\r
1018 cardState = HAL_SD_GetCardState(&hsd);
\r
1026 void diskDataOut_variableSectorSize(int sdPerScsi, int totalSDSectors, uint32_t sdLBA, int useSlowDataCount, int* parityError)
\r
1028 uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
\r
1032 int enableParity = scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY;
\r
1034 uint32_t maxSectors = sizeof(scsiDev.data) / SD_SECTOR_SIZE;
\r
1036 while ((i < totalSDSectors) &&
\r
1037 likely(scsiDev.phase == DATA_OUT) &&
\r
1038 likely(!scsiDev.resetFlag))
\r
1039 // KEEP GOING to ensure FIFOs are in a good state.
\r
1040 // likely(!parityError || !enableParity))
\r
1042 // Well, until we have some proper non-blocking SD code, we must
\r
1043 // do this in a half-duplex fashion. We need to write as much as
\r
1044 // possible in each SD card transaction.
\r
1045 // use sg_dd from sg_utils3 tools to test.
\r
1047 uint32_t rem = totalSDSectors - i;
\r
1049 if (rem <= maxSectors)
\r
1055 sectors = maxSectors;
\r
1056 while (sectors % sdPerScsi) sectors--;
\r
1060 if (useSlowDataCount)
\r
1062 scsiSetDataCount((sectors / sdPerScsi) * bytesPerSector);
\r
1065 for (int scsiSector = i; scsiSector < i + sectors; ++scsiSector)
\r
1067 int dmaBytes = SD_SECTOR_SIZE;
\r
1068 if ((scsiSector % sdPerScsi) == (sdPerScsi - 1))
\r
1070 dmaBytes = bytesPerSector % SD_SECTOR_SIZE;
\r
1071 if (dmaBytes == 0) dmaBytes = SD_SECTOR_SIZE;
\r
1074 scsiReadPIO(&scsiDev.data[SD_SECTOR_SIZE * (scsiSector - i)], dmaBytes, parityError);
\r
1076 if (!(*parityError) || !enableParity)
\r
1078 BSP_SD_WriteBlocks_DMA(&scsiDev.data[0], i + sdLBA, sectors);
\r
1084 void diskDataOut()
\r
1086 uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
\r
1088 scsiEnterPhase(DATA_OUT);
\r
1090 const int sdPerScsi = SDSectorsPerSCSISector(bytesPerSector);
\r
1091 int totalSDSectors = transfer.blocks * sdPerScsi;
\r
1094 scsiDev.target->cfg->sdSectorStart,
\r
1099 int parityError = 0;
\r
1101 static_assert(SCSI_XFER_MAX >= sizeof(scsiDev.data), "Assumes SCSI_XFER_MAX >= sizeof(scsiDev.data)");
\r
1103 // Start reading and filling fifos as soon as possible.
\r
1104 // It's highly unlikely that someone is going to use huge transfers
\r
1105 // per scsi command, but if they do it'll be slower than usual.
\r
1106 // Note: Happens in Macintosh FWB HDD Toolkit benchmarks which default
\r
1108 uint32_t totalTransferBytes = transfer.blocks * bytesPerSector;
\r
1109 int useSlowDataCount = totalTransferBytes >= SCSI_XFER_MAX;
\r
1110 if (!useSlowDataCount)
\r
1112 DWT->CYCCNT = 0; // Start counting cycles
\r
1113 scsiSetDataCount(totalTransferBytes);
\r
1116 if (bytesPerSector == SD_SECTOR_SIZE)
\r
1118 diskDataOut_512(totalSDSectors, sdLBA, useSlowDataCount, &clearBSY, &parityError);
\r
1122 diskDataOut_variableSectorSize(sdPerScsi, totalSDSectors, sdLBA, useSlowDataCount, &parityError);
\r
1126 // Should already be complete here as we've ready the FIFOs
\r
1127 // by now. Check anyway.
\r
1128 while (!scsiPhyComplete() && likely(!scsiDev.resetFlag))
\r
1138 if (scsiDev.phase == DATA_OUT)
\r
1140 if (parityError &&
\r
1141 (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY))
\r
1143 scsiDev.target->sense.code = ABORTED_COMMAND;
\r
1144 scsiDev.target->sense.asc = SCSI_PARITY_ERROR;
\r
1145 scsiDev.status = CHECK_CONDITION;;
\r
1147 scsiDev.phase = STATUS;
\r
1153 void scsiDiskPoll()
\r
1155 if (scsiDev.phase == DATA_IN &&
\r
1156 transfer.currentBlock != transfer.blocks)
\r
1160 else if (scsiDev.phase == DATA_OUT &&
\r
1161 transfer.currentBlock != transfer.blocks)
\r
1168 void scsiDiskReset()
\r
1170 scsiDev.dataPtr = 0;
\r
1171 scsiDev.savedDataPtr = 0;
\r
1172 scsiDev.dataLen = 0;
\r
1173 // transfer.lba = 0; // Needed in Request Sense to determine failure
\r
1174 transfer.blocks = 0;
\r
1175 transfer.currentBlock = 0;
\r
1177 // Cancel long running commands!
\r
1180 ((scsiDev.boardCfg.flags & S2S_CFG_ENABLE_CACHE) == 0) ||
\r
1181 (transfer.multiBlock == 0)
\r
1185 sdCompleteTransfer();
\r
1188 transfer.multiBlock = 0;
\r
1191 void scsiDiskInit()
\r