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/>.
18 #pragma GCC push_options
19 #pragma GCC optimize("-flto")
40 if (blockDev
.state
& DISK_PRESENT
)
46 blockDev
.state
= blockDev
.state
| DISK_INITIALISED
;
52 // Callback once all data has been read in the data out phase.
53 static void doFormatUnitComplete(void)
55 // TODO start writing the initialisation pattern to the SD
57 scsiDev
.phase
= STATUS
;
60 static void doFormatUnitSkipData(int bytes
)
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
65 scsiEnterPhase(DATA_OUT
);
67 for (i
= 0; i
< bytes
; ++i
)
73 // Callback from the data out phase.
74 static void doFormatUnitPatternHeader(void)
77 ((((uint16_t)scsiDev
.data
[2])) << 8) +
81 ((((uint16_t)scsiDev
.data
[4 + 2])) << 8) +
84 doFormatUnitSkipData(defectLength
+ patternLength
);
85 doFormatUnitComplete();
88 // Callback from the data out phase.
89 static void doFormatUnitHeader(void)
91 int IP
= (scsiDev
.data
[1] & 0x08) ? 1 : 0;
92 int DSP
= (scsiDev
.data
[1] & 0x04) ? 1 : 0;
94 if (! DSP
) // disable save parameters
96 // Save the "MODE SELECT savable parameters"
98 scsiDev
.target
->targetId
,
99 scsiDev
.target
->liveCfg
.bytesPerSector
);
104 // We need to read the initialisation pattern header first.
105 scsiDev
.dataLen
+= 4;
106 scsiDev
.phase
= DATA_OUT
;
107 scsiDev
.postDataOutHook
= doFormatUnitPatternHeader
;
111 // Read the defect list data
113 ((((uint16_t)scsiDev
.data
[2])) << 8) +
115 doFormatUnitSkipData(defectLength
);
116 doFormatUnitComplete();
120 static void doReadCapacity()
122 uint32_t lba
= (((uint32
) scsiDev
.cdb
[2]) << 24) +
123 (((uint32
) scsiDev
.cdb
[3]) << 16) +
124 (((uint32
) scsiDev
.cdb
[4]) << 8) +
126 int pmi
= scsiDev
.cdb
[8] & 1;
128 uint32_t capacity
= getScsiCapacity(
129 scsiDev
.target
->cfg
->sdSectorStart
,
130 scsiDev
.target
->liveCfg
.bytesPerSector
,
131 scsiDev
.target
->cfg
->scsiSectors
);
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
;
144 else if (capacity
> 0)
146 uint32_t highestBlock
= capacity
- 1;
148 scsiDev
.data
[0] = highestBlock
>> 24;
149 scsiDev
.data
[1] = highestBlock
>> 16;
150 scsiDev
.data
[2] = highestBlock
>> 8;
151 scsiDev
.data
[3] = highestBlock
;
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
;
159 scsiDev
.phase
= DATA_IN
;
163 scsiDev
.status
= CHECK_CONDITION
;
164 scsiDev
.target
->sense
.code
= NOT_READY
;
165 scsiDev
.target
->sense
.asc
= MEDIUM_NOT_PRESENT
;
166 scsiDev
.phase
= STATUS
;
170 static void doWrite(uint32 lba
, uint32 blocks
)
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
178 if (unlikely(blockDev
.state
& DISK_WP
) ||
179 unlikely(scsiDev
.target
->cfg
->deviceType
== CONFIG_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
) lba
) + blocks
>
189 scsiDev
.target
->cfg
->sdSectorStart
,
190 scsiDev
.target
->liveCfg
.bytesPerSector
,
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
;
202 transfer
.dir
= TRANSFER_WRITE
;
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
;
210 // No need for single-block writes atm. Overhead of the
211 // multi-block write is minimal.
212 transfer
.multiBlock
= 1;
214 sdWriteMultiSectorPrep();
219 static void doRead(uint32 lba
, uint32 blocks
)
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
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
))
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
;
240 transfer
.dir
= TRANSFER_READ
;
242 transfer
.blocks
= blocks
;
243 transfer
.currentBlock
= 0;
244 scsiDev
.phase
= DATA_IN
;
245 scsiDev
.dataLen
= 0; // No data yet
248 unlikely(((uint64
) lba
) + blocks
== capacity
)
251 // We get errors on reading the last sector using a multi-sector
253 transfer
.multiBlock
= 0;
257 transfer
.multiBlock
= 1;
258 sdReadMultiSectorPrep();
263 static void doSeek(uint32 lba
)
267 scsiDev
.target
->cfg
->sdSectorStart
,
268 scsiDev
.target
->liveCfg
.bytesPerSector
,
269 scsiDev
.target
->cfg
->scsiSectors
)
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
;
279 static int doTestUnitReady()
282 if (likely(blockDev
.state
== (DISK_STARTED
| DISK_PRESENT
| DISK_INITIALISED
)))
286 else if (unlikely(!(blockDev
.state
& DISK_STARTED
)))
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
;
294 else if (unlikely(!(blockDev
.state
& DISK_PRESENT
)))
297 scsiDev
.status
= CHECK_CONDITION
;
298 scsiDev
.target
->sense
.code
= NOT_READY
;
299 scsiDev
.target
->sense
.asc
= MEDIUM_NOT_PRESENT
;
300 scsiDev
.phase
= STATUS
;
302 else if (unlikely(!(blockDev
.state
& DISK_INITIALISED
)))
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
;
313 // Handle direct-access scsi device commands
314 int scsiDiskCommand()
316 int commandHandled
= 1;
318 uint8 command
= scsiDev
.cdb
[0];
319 if (unlikely(command
== 0x1B))
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;
329 blockDev
.state
= blockDev
.state
| DISK_STARTED
;
330 if (!(blockDev
.state
& DISK_INITIALISED
))
337 blockDev
.state
&= ~DISK_STARTED
;
340 else if (unlikely(command
== 0x00))
345 else if (unlikely(!doTestUnitReady()))
347 // Status and sense codes already set by doTestUnitReady
349 else if (likely(command
== 0x08))
353 (((uint32
) scsiDev
.cdb
[1] & 0x1F) << 16) +
354 (((uint32
) scsiDev
.cdb
[2]) << 8) +
356 uint32 blocks
= scsiDev
.cdb
[4];
357 if (unlikely(blocks
== 0)) blocks
= 256;
360 else if (likely(command
== 0x28))
363 // Ignore all cache control bits - we don't support a memory cache.
366 (((uint32
) scsiDev
.cdb
[2]) << 24) +
367 (((uint32
) scsiDev
.cdb
[3]) << 16) +
368 (((uint32
) scsiDev
.cdb
[4]) << 8) +
371 (((uint32
) scsiDev
.cdb
[7]) << 8) +
376 else if (likely(command
== 0x0A))
380 (((uint32
) scsiDev
.cdb
[1] & 0x1F) << 16) +
381 (((uint32
) scsiDev
.cdb
[2]) << 8) +
383 uint32 blocks
= scsiDev
.cdb
[4];
384 if (unlikely(blocks
== 0)) blocks
= 256;
385 doWrite(lba
, blocks
);
387 else if (likely(command
== 0x2A) || // WRITE(10)
388 unlikely(command
== 0x2E)) // WRITE AND VERIFY
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.
395 (((uint32
) scsiDev
.cdb
[2]) << 24) +
396 (((uint32
) scsiDev
.cdb
[3]) << 16) +
397 (((uint32
) scsiDev
.cdb
[4]) << 8) +
400 (((uint32
) scsiDev
.cdb
[7]) << 8) +
403 doWrite(lba
, blocks
);
406 else if (unlikely(command
== 0x04))
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.
412 int fmtData
= (scsiDev
.cdb
[1] & 0x10) ? 1 : 0;
415 // We need to read the parameter list, but we don't know how
416 // big it is yet. Start with the header.
418 scsiDev
.phase
= DATA_OUT
;
419 scsiDev
.postDataOutHook
= doFormatUnitHeader
;
423 // No data to read, we're already finished!
426 else if (unlikely(command
== 0x25))
431 else if (unlikely(command
== 0x0B))
435 (((uint32
) scsiDev
.cdb
[1] & 0x1F) << 16) +
436 (((uint32
) scsiDev
.cdb
[2]) << 8) +
442 else if (unlikely(command
== 0x2B))
446 (((uint32
) scsiDev
.cdb
[2]) << 24) +
447 (((uint32
) scsiDev
.cdb
[3]) << 16) +
448 (((uint32
) scsiDev
.cdb
[4]) << 8) +
453 else if (unlikely(command
== 0x36))
456 // We don't have a cache to lock data into. do nothing.
458 else if (unlikely(command
== 0x34))
461 // We don't have a cache to pre-fetch into. do nothing.
463 else if (unlikely(command
== 0x1E))
465 // PREVENT ALLOW MEDIUM REMOVAL
466 // Not much we can do to prevent the user removing the SD card.
469 else if (unlikely(command
== 0x01))
472 // Set the lun to a vendor-specific state. Ignore.
474 else if (unlikely(command
== 0x35))
477 // We don't have a cache. do nothing.
479 else if (unlikely(command
== 0x2F))
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)
486 // They are asking us to do a medium verification with no data
487 // comparison. Assume success, do nothing.
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
;
499 else if (unlikely(command
== 0x37))
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
;
513 return commandHandled
;
518 if (scsiDev
.phase
== DATA_IN
&&
519 transfer
.currentBlock
!= transfer
.blocks
)
521 scsiEnterPhase(DATA_IN
);
525 SDSectorsPerSCSISector(scsiDev
.target
->liveCfg
.bytesPerSector
);
528 scsiDev
.target
->cfg
->sdSectorStart
,
529 scsiDev
.target
->liveCfg
.bytesPerSector
,
532 const int sdPerScsi
=
533 SDSectorsPerSCSISector(scsiDev
.target
->liveCfg
.bytesPerSector
);
534 int buffers
= sizeof(scsiDev
.data
) / SD_SECTOR_SIZE
;
539 while ((i
< totalSDSectors
) &&
540 likely(scsiDev
.phase
== DATA_IN
) &&
541 likely(!scsiDev
.resetFlag
))
543 // Wait for the next DMA interrupt. It's beneficial to halt the
544 // processor to give the DMA controller more memory bandwidth to
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
)
554 scsiBusy
= scsiDMABusy();
555 sdBusy
= sdDMABusy();
558 if (sdActive
&& !sdBusy
&& sdReadSectorDMAPoll())
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.
569 (prep
- i
< buffers
) &&
570 (prep
< totalSDSectors
))
572 // Start an SD transfer if we have space.
573 if (transfer
.multiBlock
)
575 sdReadMultiSectorDMA(&scsiDev
.data
[SD_SECTOR_SIZE
* (prep
% buffers
)]);
579 sdReadSingleSectorDMA(sdLBA
+ prep
, &scsiDev
.data
[SD_SECTOR_SIZE
* (prep
% buffers
)]);
584 if (scsiActive
&& !scsiBusy
&& scsiWriteDMAPoll())
589 if (!scsiActive
&& ((prep
- i
) > 0))
591 int dmaBytes
= SD_SECTOR_SIZE
;
592 if ((i
% sdPerScsi
) == (sdPerScsi
- 1))
594 dmaBytes
= scsiDev
.target
->liveCfg
.bytesPerSector
% SD_SECTOR_SIZE
;
595 if (dmaBytes
== 0) dmaBytes
= SD_SECTOR_SIZE
;
597 scsiWriteDMA(&scsiDev
.data
[SD_SECTOR_SIZE
* (i
% buffers
)], dmaBytes
);
601 if (scsiDev
.phase
== DATA_IN
)
603 scsiDev
.phase
= STATUS
;
607 else if (scsiDev
.phase
== DATA_OUT
&&
608 transfer
.currentBlock
!= transfer
.blocks
)
610 scsiEnterPhase(DATA_OUT
);
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
;
618 int scsiDisconnected
= 0;
619 int scsiComplete
= 0;
620 uint32_t lastActivityTime
= getTime_ms();
624 while ((i
< totalSDSectors
) &&
625 (likely(scsiDev
.phase
== DATA_OUT
) || // scsiDisconnect keeps our phase.
627 likely(!scsiDev
.resetFlag
))
629 // Wait for the next DMA interrupt. It's beneficial to halt the
630 // processor to give the DMA controller more memory bandwidth to
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
)
640 scsiBusy
= scsiDMABusy();
641 sdBusy
= sdDMABusy();
644 if (sdActive
&& !sdBusy
&& sdWriteSectorDMAPoll(i
== (totalSDSectors
- 1)))
649 if (!sdActive
&& ((prep
- i
) > 0))
651 // Start an SD transfer if we have space.
652 sdWriteMultiSectorDMA(&scsiDev
.data
[SD_SECTOR_SIZE
* (i
% buffers
)]);
656 uint32_t now
= getTime_ms();
658 if (scsiActive
&& !scsiBusy
&& scsiReadDMAPoll())
662 lastActivityTime
= now
;
665 ((prep
- i
) < buffers
) &&
666 (prep
< totalSDSectors
) &&
667 likely(!scsiDisconnected
))
669 int dmaBytes
= SD_SECTOR_SIZE
;
670 if ((prep
% sdPerScsi
) == (sdPerScsi
- 1))
672 dmaBytes
= scsiDev
.target
->liveCfg
.bytesPerSector
% SD_SECTOR_SIZE
;
673 if (dmaBytes
== 0) dmaBytes
= SD_SECTOR_SIZE
;
675 scsiReadDMA(&scsiDev
.data
[SD_SECTOR_SIZE
* (prep
% buffers
)], dmaBytes
);
680 likely(!scsiDisconnected
) &&
681 unlikely(scsiDev
.discPriv
) &&
682 unlikely(diffTime_ms(lastActivityTime
, now
) >= 20) &&
683 likely(scsiDev
.phase
== DATA_OUT
))
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.
693 scsiDisconnected
= 1;
694 lastActivityTime
= getTime_ms();
696 else if (unlikely(scsiDisconnected
) &&
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)
704 int reconnected
= scsiReconnect();
707 scsiDisconnected
= 0;
708 lastActivityTime
= getTime_ms(); // Don't disconnect immediately.
710 else if (diffTime_ms(lastActivityTime
, getTime_ms()) >= 10000)
712 // Give up after 10 seconds of trying to reconnect.
713 scsiDev
.resetFlag
= 1;
717 likely(!scsiComplete
) &&
719 (prep
== totalSDSectors
) && // All scsi data read and buffered
720 likely(!scsiDev
.discPriv
) && // Prefer disconnect where possible.
721 unlikely(diffTime_ms(lastActivityTime
, now
) >= 150) &&
723 likely(scsiDev
.phase
== DATA_OUT
) &&
724 !(scsiDev
.cdb
[scsiDev
.cdbLen
- 1] & 0x01) // Not linked command
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.
737 process_MessageIn(); // Will go to BUS_FREE state
739 // Try and prevent anyone else using the SCSI bus while we're not ready.
740 SCSI_SetPin(SCSI_Out_BSY
);
746 SCSI_ClearPin(SCSI_Out_BSY
);
749 !scsiDev
.resetFlag
&&
750 unlikely(scsiDisconnected
) &&
751 (elapsedTime_ms(lastActivityTime
) <= 10000))
753 scsiDisconnected
= !scsiReconnect();
755 if (scsiDisconnected
)
757 // Failed to reconnect
758 scsiDev
.resetFlag
= 1;
761 if (scsiDev
.phase
== DATA_OUT
)
763 if (scsiDev
.parityError
&&
764 (scsiDev
.target
->cfg
->flags
& CONFIG_ENABLE_PARITY
) &&
765 (scsiDev
.compatMode
>= COMPAT_SCSI2
))
767 scsiDev
.target
->sense
.code
= ABORTED_COMMAND
;
768 scsiDev
.target
->sense
.asc
= SCSI_PARITY_ERROR
;
769 scsiDev
.status
= CHECK_CONDITION
;;
771 scsiDev
.phase
= STATUS
;
780 scsiDev
.savedDataPtr
= 0;
782 // transfer.lba = 0; // Needed in Request Sense to determine failure
784 transfer
.currentBlock
= 0;
786 // Cancel long running commands!
787 if (unlikely(transfer
.inProgress
== 1))
789 if (transfer
.dir
== TRANSFER_WRITE
)
798 transfer
.inProgress
= 0;
799 transfer
.multiBlock
= 0;
804 transfer
.inProgress
= 0;
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
814 blockDev
.state
= blockDev
.state
| DISK_WP
;
819 #pragma GCC pop_options