1 // Copyright (C) 2013 Michael McMaster <michael@codesrc.com>
2 // Copyright (C) 2014 Doug Brown <doug@downtowndougbrown.com>
4 // This file is part of SCSI2SD.
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.
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.
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/>.
19 #include "stm32f2xx.h"
21 // For SD write direct routines
23 #include "bsp_driver_sd.h"
43 if (blockDev
.state
& DISK_PRESENT
)
45 blockDev
.state
= blockDev
.state
| DISK_INITIALISED
;
50 // Callback once all data has been read in the data out phase.
51 static void doFormatUnitComplete(void)
53 // TODO start writing the initialisation pattern to the SD
55 scsiDev
.phase
= STATUS
;
58 static void doFormatUnitSkipData(int bytes
)
60 // We may not have enough memory to store the initialisation pattern and
61 // defect list data. Since we're not making use of it yet anyway, just
63 scsiEnterPhase(DATA_OUT
);
65 for (i
= 0; i
< bytes
; ++i
)
71 // Callback from the data out phase.
72 static void doFormatUnitPatternHeader(void)
75 ((((uint16_t)scsiDev
.data
[2])) << 8) +
79 ((((uint16_t)scsiDev
.data
[4 + 2])) << 8) +
82 doFormatUnitSkipData(defectLength
+ patternLength
);
83 doFormatUnitComplete();
86 // Callback from the data out phase.
87 static void doFormatUnitHeader(void)
89 int IP
= (scsiDev
.data
[1] & 0x08) ? 1 : 0;
90 int DSP
= (scsiDev
.data
[1] & 0x04) ? 1 : 0;
92 if (! DSP
) // disable save parameters
94 // Save the "MODE SELECT savable parameters"
96 scsiDev
.target
->targetId
,
97 scsiDev
.target
->liveCfg
.bytesPerSector
);
102 // We need to read the initialisation pattern header first.
103 scsiDev
.dataLen
+= 4;
104 scsiDev
.phase
= DATA_OUT
;
105 scsiDev
.postDataOutHook
= doFormatUnitPatternHeader
;
109 // Read the defect list data
111 ((((uint16_t)scsiDev
.data
[2])) << 8) +
113 doFormatUnitSkipData(defectLength
);
114 doFormatUnitComplete();
118 static void doReadCapacity()
120 uint32_t lba
= (((uint32_t) scsiDev
.cdb
[2]) << 24) +
121 (((uint32_t) scsiDev
.cdb
[3]) << 16) +
122 (((uint32_t) scsiDev
.cdb
[4]) << 8) +
124 int pmi
= scsiDev
.cdb
[8] & 1;
126 uint32_t capacity
= getScsiCapacity(
127 scsiDev
.target
->cfg
->sdSectorStart
,
128 scsiDev
.target
->liveCfg
.bytesPerSector
,
129 scsiDev
.target
->cfg
->scsiSectors
);
134 // We don't do anything with the "partial medium indicator", and
135 // assume that delays are constant across each block. But the spec
136 // says we must return this error if pmi is specified incorrectly.
137 scsiDev
.status
= CHECK_CONDITION
;
138 scsiDev
.target
->sense
.code
= ILLEGAL_REQUEST
;
139 scsiDev
.target
->sense
.asc
= INVALID_FIELD_IN_CDB
;
140 scsiDev
.phase
= STATUS
;
142 else if (capacity
> 0)
144 uint32_t highestBlock
= capacity
- 1;
146 scsiDev
.data
[0] = highestBlock
>> 24;
147 scsiDev
.data
[1] = highestBlock
>> 16;
148 scsiDev
.data
[2] = highestBlock
>> 8;
149 scsiDev
.data
[3] = highestBlock
;
151 uint32_t bytesPerSector
= scsiDev
.target
->liveCfg
.bytesPerSector
;
152 scsiDev
.data
[4] = bytesPerSector
>> 24;
153 scsiDev
.data
[5] = bytesPerSector
>> 16;
154 scsiDev
.data
[6] = bytesPerSector
>> 8;
155 scsiDev
.data
[7] = bytesPerSector
;
157 scsiDev
.phase
= DATA_IN
;
161 scsiDev
.status
= CHECK_CONDITION
;
162 scsiDev
.target
->sense
.code
= NOT_READY
;
163 scsiDev
.target
->sense
.asc
= MEDIUM_NOT_PRESENT
;
164 scsiDev
.phase
= STATUS
;
168 static void doWrite(uint32_t lba
, uint32_t blocks
)
170 if (unlikely(scsiDev
.target
->cfg
->deviceType
== S2S_CFG_FLOPPY_14MB
)) {
171 // Floppies are supposed to be slow. Some systems can't handle a floppy
172 // without an access time
176 uint32_t bytesPerSector
= scsiDev
.target
->liveCfg
.bytesPerSector
;
178 if (unlikely(blockDev
.state
& DISK_WP
) ||
179 unlikely(scsiDev
.target
->cfg
->deviceType
== S2S_CFG_OPTICAL
))
182 scsiDev
.status
= CHECK_CONDITION
;
183 scsiDev
.target
->sense
.code
= ILLEGAL_REQUEST
;
184 scsiDev
.target
->sense
.asc
= WRITE_PROTECTED
;
185 scsiDev
.phase
= STATUS
;
187 else if (unlikely(((uint64_t) lba
) + blocks
>
189 scsiDev
.target
->cfg
->sdSectorStart
,
191 scsiDev
.target
->cfg
->scsiSectors
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
;
203 transfer
.blocks
= blocks
;
204 transfer
.currentBlock
= 0;
205 scsiDev
.phase
= DATA_OUT
;
206 scsiDev
.dataLen
= bytesPerSector
;
207 scsiDev
.dataPtr
= bytesPerSector
;
209 // No need for single-block writes atm. Overhead of the
210 // multi-block write is minimal.
211 transfer
.multiBlock
= 1;
214 // TODO uint32_t sdLBA =
215 // TODO SCSISector2SD(
216 // TODO scsiDev.target->cfg->sdSectorStart,
217 // TODO bytesPerSector,
219 // TODO uint32_t sdBlocks = blocks * SDSectorsPerSCSISector(bytesPerSector);
220 // TODO sdWriteMultiSectorPrep(sdLBA, sdBlocks);
225 static void doRead(uint32_t lba
, uint32_t blocks
)
227 if (unlikely(scsiDev
.target
->cfg
->deviceType
== S2S_CFG_FLOPPY_14MB
)) {
228 // Floppies are supposed to be slow. Some systems can't handle a floppy
229 // without an access time
233 uint32_t capacity
= getScsiCapacity(
234 scsiDev
.target
->cfg
->sdSectorStart
,
235 scsiDev
.target
->liveCfg
.bytesPerSector
,
236 scsiDev
.target
->cfg
->scsiSectors
);
237 if (unlikely(((uint64_t) lba
) + blocks
> capacity
))
239 scsiDev
.status
= CHECK_CONDITION
;
240 scsiDev
.target
->sense
.code
= ILLEGAL_REQUEST
;
241 scsiDev
.target
->sense
.asc
= LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE
;
242 scsiDev
.phase
= STATUS
;
247 transfer
.blocks
= blocks
;
248 transfer
.currentBlock
= 0;
249 scsiDev
.phase
= DATA_IN
;
250 scsiDev
.dataLen
= 0; // No data yet
252 uint32_t bytesPerSector
= scsiDev
.target
->liveCfg
.bytesPerSector
;
253 uint32_t sdSectorPerSCSISector
= SDSectorsPerSCSISector(bytesPerSector
);
255 blocks
* sdSectorPerSCSISector
;
259 !(scsiDev
.boardCfg
.flags
& S2S_CFG_ENABLE_CACHE
)
261 unlikely(((uint64_t) lba
) + blocks
== capacity
)
264 // We get errors on reading the last sector using a multi-sector
266 transfer
.multiBlock
= 0;
270 transfer
.multiBlock
= 1;
274 // scsiDev.target->cfg->sdSectorStart,
278 // TODO sdReadMultiSectorPrep(sdLBA, sdSectors);
283 static void doSeek(uint32_t lba
)
287 scsiDev
.target
->cfg
->sdSectorStart
,
288 scsiDev
.target
->liveCfg
.bytesPerSector
,
289 scsiDev
.target
->cfg
->scsiSectors
)
292 scsiDev
.status
= CHECK_CONDITION
;
293 scsiDev
.target
->sense
.code
= ILLEGAL_REQUEST
;
294 scsiDev
.target
->sense
.asc
= LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE
;
295 scsiDev
.phase
= STATUS
;
299 static int doTestUnitReady()
302 if (likely(blockDev
.state
== (DISK_STARTED
| DISK_PRESENT
| DISK_INITIALISED
)))
306 else if (unlikely(!(blockDev
.state
& DISK_STARTED
)))
309 scsiDev
.status
= CHECK_CONDITION
;
310 scsiDev
.target
->sense
.code
= NOT_READY
;
311 scsiDev
.target
->sense
.asc
= LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED
;
312 scsiDev
.phase
= STATUS
;
314 else if (unlikely(!(blockDev
.state
& DISK_PRESENT
)))
317 scsiDev
.status
= CHECK_CONDITION
;
318 scsiDev
.target
->sense
.code
= NOT_READY
;
319 scsiDev
.target
->sense
.asc
= MEDIUM_NOT_PRESENT
;
320 scsiDev
.phase
= STATUS
;
322 else if (unlikely(!(blockDev
.state
& DISK_INITIALISED
)))
325 scsiDev
.status
= CHECK_CONDITION
;
326 scsiDev
.target
->sense
.code
= NOT_READY
;
327 scsiDev
.target
->sense
.asc
= LOGICAL_UNIT_NOT_READY_CAUSE_NOT_REPORTABLE
;
328 scsiDev
.phase
= STATUS
;
333 // Handle direct-access scsi device commands
334 int scsiDiskCommand()
336 int commandHandled
= 1;
338 uint8_t command
= scsiDev
.cdb
[0];
339 if (unlikely(command
== 0x1B))
342 // Enable or disable media access operations.
343 // Ignore load/eject requests. We can't do that.
344 //int immed = scsiDev.cdb[1] & 1;
345 int start
= scsiDev
.cdb
[4] & 1;
349 blockDev
.state
= blockDev
.state
| DISK_STARTED
;
350 if (!(blockDev
.state
& DISK_INITIALISED
))
357 blockDev
.state
&= ~DISK_STARTED
;
360 else if (unlikely(command
== 0x00))
365 else if (unlikely(!doTestUnitReady()))
367 // Status and sense codes already set by doTestUnitReady
369 else if (likely(command
== 0x08))
373 (((uint32_t) scsiDev
.cdb
[1] & 0x1F) << 16) +
374 (((uint32_t) scsiDev
.cdb
[2]) << 8) +
376 uint32_t blocks
= scsiDev
.cdb
[4];
377 if (unlikely(blocks
== 0)) blocks
= 256;
380 else if (likely(command
== 0x28))
383 // Ignore all cache control bits - we don't support a memory cache.
386 (((uint32_t) scsiDev
.cdb
[2]) << 24) +
387 (((uint32_t) scsiDev
.cdb
[3]) << 16) +
388 (((uint32_t) scsiDev
.cdb
[4]) << 8) +
391 (((uint32_t) scsiDev
.cdb
[7]) << 8) +
396 else if (likely(command
== 0x0A))
400 (((uint32_t) scsiDev
.cdb
[1] & 0x1F) << 16) +
401 (((uint32_t) scsiDev
.cdb
[2]) << 8) +
403 uint32_t blocks
= scsiDev
.cdb
[4];
404 if (unlikely(blocks
== 0)) blocks
= 256;
405 doWrite(lba
, blocks
);
407 else if (likely(command
== 0x2A) || // WRITE(10)
408 unlikely(command
== 0x2E)) // WRITE AND VERIFY
410 // Ignore all cache control bits - we don't support a memory cache.
411 // Don't bother verifying either. The SD card likely stores ECC
412 // along with each flash row.
415 (((uint32_t) scsiDev
.cdb
[2]) << 24) +
416 (((uint32_t) scsiDev
.cdb
[3]) << 16) +
417 (((uint32_t) scsiDev
.cdb
[4]) << 8) +
420 (((uint32_t) scsiDev
.cdb
[7]) << 8) +
423 doWrite(lba
, blocks
);
425 else if (unlikely(command
== 0x04))
428 // We don't really do any formatting, but we need to read the correct
429 // number of bytes in the DATA_OUT phase to make the SCSI host happy.
431 int fmtData
= (scsiDev
.cdb
[1] & 0x10) ? 1 : 0;
434 // We need to read the parameter list, but we don't know how
435 // big it is yet. Start with the header.
437 scsiDev
.phase
= DATA_OUT
;
438 scsiDev
.postDataOutHook
= doFormatUnitHeader
;
442 // No data to read, we're already finished!
445 else if (unlikely(command
== 0x25))
450 else if (unlikely(command
== 0x0B))
454 (((uint32_t) scsiDev
.cdb
[1] & 0x1F) << 16) +
455 (((uint32_t) scsiDev
.cdb
[2]) << 8) +
461 else if (unlikely(command
== 0x2B))
465 (((uint32_t) scsiDev
.cdb
[2]) << 24) +
466 (((uint32_t) scsiDev
.cdb
[3]) << 16) +
467 (((uint32_t) scsiDev
.cdb
[4]) << 8) +
472 else if (unlikely(command
== 0x36))
475 // We don't have a cache to lock data into. do nothing.
477 else if (unlikely(command
== 0x34))
480 // We don't have a cache to pre-fetch into. do nothing.
482 else if (unlikely(command
== 0x1E))
484 // PREVENT ALLOW MEDIUM REMOVAL
485 // Not much we can do to prevent the user removing the SD card.
488 else if (unlikely(command
== 0x01))
491 // Set the lun to a vendor-specific state. Ignore.
493 else if (unlikely(command
== 0x35))
496 // We don't have a cache. do nothing.
498 else if (unlikely(command
== 0x2F))
501 // TODO: When they supply data to verify, we should read the data and
502 // verify it. If they don't supply any data, just say success.
503 if ((scsiDev
.cdb
[1] & 0x02) == 0)
505 // They are asking us to do a medium verification with no data
506 // comparison. Assume success, do nothing.
510 // TODO. This means they are supplying data to verify against.
511 // Technically we should probably grab the data and compare it.
512 scsiDev
.status
= CHECK_CONDITION
;
513 scsiDev
.target
->sense
.code
= ILLEGAL_REQUEST
;
514 scsiDev
.target
->sense
.asc
= INVALID_FIELD_IN_CDB
;
515 scsiDev
.phase
= STATUS
;
518 else if (unlikely(command
== 0x37))
521 scsiDev
.status
= CHECK_CONDITION
;
522 scsiDev
.target
->sense
.code
= NO_SENSE
;
523 scsiDev
.target
->sense
.asc
= DEFECT_LIST_NOT_FOUND
;
524 scsiDev
.phase
= STATUS
;
532 return commandHandled
;
537 uint32_t bytesPerSector
= scsiDev
.target
->liveCfg
.bytesPerSector
;
539 if (scsiDev
.phase
== DATA_IN
&&
540 transfer
.currentBlock
!= transfer
.blocks
)
544 transfer
.blocks
* SDSectorsPerSCSISector(bytesPerSector
);
547 scsiDev
.target
->cfg
->sdSectorStart
,
551 const int sdPerScsi
= SDSectorsPerSCSISector(bytesPerSector
);
552 const int buffers
= sizeof(scsiDev
.data
) / SD_SECTOR_SIZE
;
555 int scsiActive
__attribute__((unused
)) = 0; // unused if DMA disabled
558 uint32_t partialScsiChunk
= 0;
560 // Start reading from the SD card FIRST, because we change state and
561 // wai for SCSI signals
562 int dataInStarted
= 0;
564 while ((i
< totalSDSectors
) &&
565 (!dataInStarted
|| likely(scsiDev
.phase
== DATA_IN
)) &&
566 likely(!scsiDev
.resetFlag
))
568 int completedDmaSectors
;
569 if (sdActive
&& (completedDmaSectors
= sdReadDMAPoll(sdActive
)))
571 prep
+= completedDmaSectors
;
572 sdActive
-= completedDmaSectors
;
573 } else if (sdActive
> 1)
575 if ((scsiDev
.data
[SD_SECTOR_SIZE
* (prep
% buffers
) + 510] != 0xAA) ||
576 (scsiDev
.data
[SD_SECTOR_SIZE
* (prep
% buffers
) + 511] != 0x33))
584 (prep
- i
< buffers
) &&
585 (prep
< totalSDSectors
))
587 // Start an SD transfer if we have space.
588 uint32_t startBuffer
= prep
% buffers
;
589 uint32_t sectors
= totalSDSectors
- prep
;
591 uint32_t freeBuffers
= buffers
- (prep
- i
);
593 uint32_t contiguousBuffers
= buffers
- startBuffer
;
594 freeBuffers
= freeBuffers
< contiguousBuffers
595 ? freeBuffers
: contiguousBuffers
;
596 sectors
= sectors
< freeBuffers
? sectors
: freeBuffers
;
598 if (sectors
> 128) sectors
= 128; // 65536 DMA limit !!
600 for (int dodgy
= 0; dodgy
< sectors
; dodgy
++)
602 scsiDev
.data
[SD_SECTOR_SIZE
* (startBuffer
+ dodgy
) + 510] = 0xAA;
603 scsiDev
.data
[SD_SECTOR_SIZE
* (startBuffer
+ dodgy
) + 511] = 0x33;
606 sdReadDMA(sdLBA
+ prep
, sectors
, &scsiDev
.data
[SD_SECTOR_SIZE
* startBuffer
]);
613 scsiEnterPhase(DATA_IN
); // Will wait a few microseconds.
618 #error this code not updated for 256 max bytes in scsi fifo
619 if (scsiActive
&& scsiPhyComplete() && scsiWriteDMAPoll())
625 if (!scsiActive
&& ((prep
- i
) > 0))
627 int dmaBytes
= SD_SECTOR_SIZE
;
628 if ((i
% sdPerScsi
) == (sdPerScsi
- 1))
630 dmaBytes
= bytesPerSector
% SD_SECTOR_SIZE
;
631 if (dmaBytes
== 0) dmaBytes
= SD_SECTOR_SIZE
;
633 scsiWriteDMA(&scsiDev
.data
[SD_SECTOR_SIZE
* (i
% buffers
)], dmaBytes
);
639 int dmaBytes
= SD_SECTOR_SIZE
;
640 if ((i
% sdPerScsi
) == (sdPerScsi
- 1))
642 dmaBytes
= bytesPerSector
% SD_SECTOR_SIZE
;
643 if (dmaBytes
== 0) dmaBytes
= SD_SECTOR_SIZE
;
646 // Manually unrolled loop for performance.
647 // -Os won't unroll this for us automatically,
648 // especially since scsiPhyTx does volatile stuff.
649 // Reduces bus utilisation by making the fsmc split
650 // 32bits into 2 16 bit writes.
652 uint16_t* scsiDmaData
= (uint16_t*) &(scsiDev
.data
[SD_SECTOR_SIZE
* (i
% buffers
) + partialScsiChunk
]);
654 uint32_t chunk
= ((dmaBytes
- partialScsiChunk
) > SCSI_FIFO_DEPTH
)
655 ? SCSI_FIFO_DEPTH
: (dmaBytes
- partialScsiChunk
);
658 for (; k
+ 4 < (chunk
+ 1) / 2; k
+= 4)
660 scsiPhyTx32(scsiDmaData
[k
], scsiDmaData
[k
+1]);
661 scsiPhyTx32(scsiDmaData
[k
+2], scsiDmaData
[k
+3]);
663 for (; k
< (chunk
+ 1) / 2; ++k
)
665 scsiPhyTx(scsiDmaData
[k
]);
667 while (!scsiPhyComplete() && !scsiDev
.resetFlag
)
669 __WFE(); // Wait for event
672 scsiSetDataCount(chunk
);
674 partialScsiChunk
+= chunk
;
675 if (partialScsiChunk
== dmaBytes
)
677 partialScsiChunk
= 0;
684 if (!dataInStarted
&& !scsiDev
.resetFlag
) // zero bytes ?
686 scsiEnterPhase(DATA_IN
); // Will wait a few microseconds.
689 // We've finished transferring the data to the FPGA, now wait until it's
690 // written to he SCSI bus.
691 while (!scsiPhyComplete() &&
692 likely(scsiDev
.phase
== DATA_IN
) &&
693 likely(!scsiDev
.resetFlag
))
695 __WFE(); // Wait for event
699 if (scsiDev
.phase
== DATA_IN
)
701 scsiDev
.phase
= STATUS
;
705 else if (scsiDev
.phase
== DATA_OUT
&&
706 transfer
.currentBlock
!= transfer
.blocks
)
708 scsiEnterPhase(DATA_OUT
);
710 const int sdPerScsi
= SDSectorsPerSCSISector(bytesPerSector
);
711 int totalSDSectors
= transfer
.blocks
* sdPerScsi
;
714 scsiDev
.target
->cfg
->sdSectorStart
,
721 int enableParity
= scsiDev
.boardCfg
.flags
& S2S_CFG_ENABLE_PARITY
;
723 while ((i
< totalSDSectors
) &&
724 likely(scsiDev
.phase
== DATA_OUT
) &&
725 likely(!scsiDev
.resetFlag
) &&
726 likely(!parityError
|| !enableParity
))
728 // Well, until we have some proper non-blocking SD code, we must
729 // do this in a half-duplex fashion. We need to write as much as
730 // possible in each SD card transaction.
731 uint32_t maxSectors
= sizeof(scsiDev
.data
) / SD_SECTOR_SIZE
;
732 uint32_t rem
= totalSDSectors
- i
;
734 rem
< maxSectors
? rem
: maxSectors
;
736 if (bytesPerSector
== SD_SECTOR_SIZE
)
738 // We assume the SD card is faster than the SCSI interface, but has
739 // no flow control. This can be handled if a) the scsi interface
740 // doesn't block and b) we read enough SCSI sectors first so that
741 // the SD interface cannot catch up.
742 uint32_t totalBytes
= sectors
* SD_SECTOR_SIZE
;
743 uint32_t readAheadBytes
= sectors
* SD_SECTOR_SIZE
;
744 uint32_t sdSpeed
= s2s_getSdRateMBs() + (scsiDev
.sdUnderrunCount
/ 2);
745 uint32_t scsiSpeed
= s2s_getScsiRateMBs();
746 // if (have blind writes)
747 if (scsiSpeed
> 0 && scsiDev
.sdUnderrunCount
< 16)
749 // readAhead = sectors * (sd / scsi - 1 + 0.1);
750 readAheadBytes
= totalBytes
* sdSpeed
/ scsiSpeed
- totalBytes
+ SCSI_FIFO_DEPTH
;
751 if (readAheadBytes
< SCSI_FIFO_DEPTH
)
753 readAheadBytes
= SCSI_FIFO_DEPTH
;
756 if (readAheadBytes
> totalBytes
)
758 readAheadBytes
= totalBytes
;
762 uint32_t chunk
= (readAheadBytes
> SCSI_FIFO_DEPTH
) ? SCSI_FIFO_DEPTH
: readAheadBytes
;
763 scsiSetDataCount(chunk
);
765 uint32_t scsiBytesRead
= 0;
766 while (scsiBytesRead
< readAheadBytes
)
768 while (!scsiPhyComplete() && likely(!scsiDev
.resetFlag
))
770 __WFE(); // Wait for event
772 parityError
|= scsiParityError();
774 uint32_t nextChunk
= ((totalBytes
- scsiBytesRead
- chunk
) > SCSI_FIFO_DEPTH
)
775 ? SCSI_FIFO_DEPTH
: (totalBytes
- scsiBytesRead
- chunk
);
777 if (nextChunk
> 0) scsiSetDataCount(nextChunk
);
778 scsiReadPIO(&scsiDev
.data
[scsiBytesRead
], chunk
);
779 scsiBytesRead
+= chunk
;
783 HAL_SD_WriteBlocks_DMA(&hsd
, (uint32_t*) (&scsiDev
.data
[0]), (i
+ sdLBA
) * 512ll, SD_SECTOR_SIZE
, sectors
);
785 while (scsiBytesRead
< totalBytes
)
787 while (!scsiPhyComplete() && likely(!scsiDev
.resetFlag
))
789 __WFE(); // Wait for event
791 parityError
|= scsiParityError();
793 uint32_t nextChunk
= ((totalBytes
- scsiBytesRead
- chunk
) > SCSI_FIFO_DEPTH
)
794 ? SCSI_FIFO_DEPTH
: (totalBytes
- scsiBytesRead
- chunk
);
796 if (nextChunk
> 0) scsiSetDataCount(nextChunk
);
797 scsiReadPIO(&scsiDev
.data
[scsiBytesRead
], chunk
);
798 scsiBytesRead
+= chunk
;
802 // Oh dear, SD finished first.
803 int underrun
= totalBytes
> readAheadBytes
&& hsd
.DmaTransferCplt
;
805 uint32_t dmaFinishTime
= s2s_getTime_ms();
806 while (!hsd
.SdTransferCplt
&&
807 s2s_elapsedTime_ms(dmaFinishTime
) < 180)
809 // Wait while keeping BSY.
811 while((__HAL_SD_SDIO_GET_FLAG(&hsd
, SDIO_FLAG_TXACT
)) &&
812 s2s_elapsedTime_ms(dmaFinishTime
) < 180)
814 // Wait for SD card while keeping BSY.
817 if (i
+ sectors
>= totalSDSectors
&&
819 (!parityError
|| !enableParity
))
821 // We're transferring over the SCSI bus faster than the SD card
822 // can write. All data is buffered, and we're just waiting for
823 // the SD card to complete. The host won't let us disconnect.
824 // Some drivers set a 250ms timeout on transfers to complete.
825 // SD card writes are supposed to complete
826 // within 200ms, but sometimes they don't.
827 // Just pretend we're finished.
829 clearBSY
= process_MessageIn(0); // Will go to BUS_FREE state but keep BSY asserted.
832 HAL_SD_CheckWriteOperation(&hsd
, (uint32_t)SD_DATATIMEOUT
);
836 // Try again. Data is still in memory.
837 sdTmpWrite(&scsiDev
.data
[0], i
+ sdLBA
, sectors
);
838 scsiDev
.sdUnderrunCount
++;
845 // Well, until we have some proper non-blocking SD code, we must
846 // do this in a half-duplex fashion. We need to write as much as
847 // possible in each SD card transaction.
848 // use sg_dd from sg_utils3 tools to test.
849 uint32_t maxSectors
= sizeof(scsiDev
.data
) / SD_SECTOR_SIZE
;
850 uint32_t rem
= totalSDSectors
- i
;
851 uint32_t sectors
= rem
< maxSectors
? rem
: maxSectors
;
853 for (scsiSector
= i
; scsiSector
< i
+ sectors
; ++scsiSector
)
855 int dmaBytes
= SD_SECTOR_SIZE
;
856 if ((scsiSector
% sdPerScsi
) == (sdPerScsi
- 1))
858 dmaBytes
= bytesPerSector
% SD_SECTOR_SIZE
;
859 if (dmaBytes
== 0) dmaBytes
= SD_SECTOR_SIZE
;
861 scsiRead(&scsiDev
.data
[SD_SECTOR_SIZE
* (scsiSector
- i
)], dmaBytes
, &parityError
);
865 sdTmpWrite(&scsiDev
.data
[0], i
+ sdLBA
, sectors
);
876 if (scsiDev
.phase
== DATA_OUT
)
879 (scsiDev
.boardCfg
.flags
& S2S_CFG_ENABLE_PARITY
))
881 scsiDev
.target
->sense
.code
= ABORTED_COMMAND
;
882 scsiDev
.target
->sense
.asc
= SCSI_PARITY_ERROR
;
883 scsiDev
.status
= CHECK_CONDITION
;;
885 scsiDev
.phase
= STATUS
;
894 scsiDev
.savedDataPtr
= 0;
896 // transfer.lba = 0; // Needed in Request Sense to determine failure
898 transfer
.currentBlock
= 0;
900 // Cancel long running commands!
903 ((scsiDev
.boardCfg
.flags
& S2S_CFG_ENABLE_CACHE
) == 0) ||
904 (transfer
.multiBlock
== 0)
908 sdCompleteTransfer();
911 transfer
.multiBlock
= 0;
918 // Don't require the host to send us a START STOP UNIT command
919 blockDev
.state
= DISK_STARTED
;