summaryrefslogtreecommitdiffstats
path: root/qemu/roms/SLOF/slof/fs/scsi-support.fs
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/SLOF/slof/fs/scsi-support.fs')
-rw-r--r--qemu/roms/SLOF/slof/fs/scsi-support.fs847
1 files changed, 847 insertions, 0 deletions
diff --git a/qemu/roms/SLOF/slof/fs/scsi-support.fs b/qemu/roms/SLOF/slof/fs/scsi-support.fs
new file mode 100644
index 000000000..3e65c8781
--- /dev/null
+++ b/qemu/roms/SLOF/slof/fs/scsi-support.fs
@@ -0,0 +1,847 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2008 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ ************************************************
+\ create a new scsi word-list named 'scsi-words'
+\ ************************************************
+vocabulary scsi-words \ create new word list named 'scsi-words'
+also scsi-words definitions \ place next definitions into new list
+
+\ for some commands specific parameters are used, which normally
+\ need not to be altered. These values are preset at include time
+\ or explicit by a call of 'scsi-supp-init'
+false value scsi-param-debug \ common debugging flag
+d# 0 value scsi-param-size \ length of CDB processed last
+h# 0 value scsi-param-control \ control word for CDBs as defined in SAM-4
+d# 0 value scsi-param-errors \ counter for detected errors
+
+\ utility to increment error counter
+: scsi-inc-errors
+ scsi-param-errors 1 + to scsi-param-errors
+;
+
+\ ***************************************************************************
+\ SCSI-Command: TEST UNIT READY
+\ Type: Primary Command (SPC-3 clause 6.33)
+\ ***************************************************************************
+\ Forth Word: scsi-build-test-unit-ready ( cdb -- )
+\ ***************************************************************************
+\ checks if a device is ready to receive commands
+\ ***************************************************************************
+\ command code:
+00 CONSTANT scsi-cmd-test-unit-ready
+\ CDB structure:
+STRUCT
+ /c FIELD test-unit-ready>operation-code \ 00h
+ 4 FIELD test-unit-ready>reserved \ unused
+ /c FIELD test-unit-ready>control \ control byte as specified in SAM-4
+CONSTANT scsi-length-test-unit-ready
+
+\ cdb build:
+\ all fields are zeroed
+: scsi-build-test-unit-ready ( cdb -- )
+ dup scsi-length-test-unit-ready erase ( cdb )
+ scsi-param-control swap test-unit-ready>control c! ( )
+ scsi-length-test-unit-ready to scsi-param-size \ update CDB length
+;
+
+\ ***************************************************************************
+\ SCSI-Command: REPORT LUNS
+\ Type: Primary Command
+\ ***************************************************************************
+\ Forth Word: scsi-build-report-luns ( cdb -- )
+\ ***************************************************************************
+\ report all LUNs supported by a device
+\ ***************************************************************************
+\ command code:
+a0 CONSTANT scsi-cmd-report-luns
+\ CDB structure:
+STRUCT
+ /c FIELD report-luns>operation-code \ a0h
+ 1 FIELD report-luns>reserved \ unused
+ /c FIELD report-luns>select-report \ report select byte
+ 3 FIELD report-luns>reserved2 \ unused
+ /l FIELD report-luns>alloc-length \ report length
+ 1 FIELD report-luns>reserved3 \ unused
+ /c FIELD report-luns>control \ control byte
+CONSTANT scsi-length-report-luns
+
+\ cdb build:
+\ all fields are zeroed
+: scsi-build-report-luns ( alloc-len cdb -- )
+ dup scsi-length-report-luns erase \ 12 bytes CDB
+ scsi-cmd-report-luns over ( alloc-len cdb cmd cdb )
+ report-luns>operation-code c! ( alloc-len cdb )
+ scsi-param-control over report-luns>control c! ( alloc-len cdb )
+ report-luns>alloc-length l! \ size of Data-In Buffer
+ scsi-length-report-luns to scsi-param-size \ update CDB length
+;
+
+\ ***************************************************************************
+\ SCSI-Command: REQUEST SENSE
+\ Type: Primary Command (SPC-3 clause 6.27)
+\ ***************************************************************************
+\ Forth Word: scsi-build-request-sense ( cdb -- )
+\ ***************************************************************************
+\ for return data a buffer of at least 252 bytes must be present!
+\ see spec: SPC-3 (r23) / clauses 4.5 and 6.27
+\ ***************************************************************************
+\ command code:
+03 CONSTANT scsi-cmd-request-sense
+\ CDB structure:
+STRUCT
+ /c FIELD request-sense>operation-code \ 03h
+ 3 FIELD request-sense>reserved \ unused
+ /c FIELD request-sense>allocation-length \ buffer-length for data response
+ /c FIELD request-sense>control \ control byte as specified in SAM-4
+CONSTANT scsi-length-request-sense
+
+\ cdb build:
+: scsi-build-request-sense ( alloc-len cdb -- )
+ >r ( alloc-len ) ( R: -- cdb )
+ r@ scsi-length-request-sense erase ( alloc-len )
+ scsi-cmd-request-sense r@ ( alloc-len cmd cdb )
+ request-sense>operation-code c! ( alloc-len )
+ dup d# 252 > \ buffer length too big ?
+ IF
+ scsi-inc-errors
+ drop d# 252 \ replace with 252
+ ELSE
+ dup d# 18 < \ allocated buffer too small ?
+ IF
+ scsi-inc-errors
+ drop 0 \ reject return data
+ THEN
+ THEN ( alloclen )
+ r@ request-sense>allocation-length c! ( )
+ scsi-param-control r> request-sense>control c! ( alloc-len cdb ) ( R: cdb -- )
+ scsi-length-request-sense to scsi-param-size \ update CDB length
+;
+
+\ ----------------------------------------
+\ SCSI-Response: SENSE_DATA
+\ ----------------------------------------
+70 CONSTANT scsi-response(request-sense-0)
+71 CONSTANT scsi-response(request-sense-1)
+
+STRUCT
+ /c FIELD sense-data>response-code \ 70h (current errors) or 71h (deferred errors)
+ /c FIELD sense-data>obsolete
+ /c FIELD sense-data>sense-key \ D3..D0 = sense key, D7 = EndOfMedium
+ /l FIELD sense-data>info
+ /c FIELD sense-data>alloc-length \ <= 244 (for max size)
+ /l FIELD sense-data>command-info
+ /c FIELD sense-data>asc \ additional sense key
+ /c FIELD sense-data>ascq \ additional sense key qualifier
+ /c FIELD sense-data>unit-code
+ 3 FIELD sense-data>key-specific
+ /c FIELD sense-data>add-sense-bytes \ start of appended extra bytes
+CONSTANT scsi-length-sense-data
+
+\ ----------------------------------------
+\ get from SCSI response block:
+\ - Additional Sense Code Qualifier
+\ - Additional Sense Code
+\ - sense-key
+\ ----------------------------------------
+\ Forth Word: scsi-get-sense-data ( addr -- ascq asc sense-key )
+\ ----------------------------------------
+: scsi-get-sense-data ( addr -- ascq asc sense-key )
+ >r ( R: -- addr )
+ r@ sense-data>response-code c@ 7f and 72 >= IF
+ r@ 3 + c@ ( ascq )
+ r@ 2 + c@ ( ascq asc )
+ r> 1 + c@ 0f and ( ascq asc sense-key )
+ ELSE
+ r@ sense-data>ASCQ c@ ( ascq )
+ r@ sense-data>ASC c@ ( ascq asc )
+ r> sense-data>sense-key c@ 0f and ( ascq asc sense-key ) ( R: addr -- )
+ THEN
+;
+
+\ --------------------------------------------------------------------------
+\ Forth Word: scsi-get-sense-data? ( addr -- false | ascq asc sense-key true )
+\ --------------------------------------------------------------------------
+: scsi-get-sense-data? ( addr -- false | ascq asc sense-key true )
+ dup
+ sense-data>response-code c@
+ 7e AND dup 70 = swap 72 = or \ Response code (some devices have MSB set)
+ IF
+ scsi-get-sense-data TRUE
+ ELSE
+ drop FALSE \ drop addr
+ THEN
+
+;
+
+\ --------------------------------------------------------------------------
+\ Forth Word: scsi-get-sense-ID? ( addr -- false | sense-ID true )
+\ same as scsi-get-sense-data? but returns
+\ a single word composed of: sense-key<<16 | asc<<8 | ascq
+\ --------------------------------------------------------------------------
+: scsi-get-sense-ID? ( addr -- false | ascq asc sense-key true )
+ dup
+ sense-data>response-code c@
+ 7e AND 70 = \ Response code (some devices have MSB set)
+ IF
+ scsi-get-sense-data ( ascq asc sense-key )
+ 10 lshift ( ascq asc sense-key16 )
+ swap 8 lshift or ( ascq sense-key+asc )
+ swap or \ 24-bit sense-ID ( sense-key+asc+ascq )
+ TRUE
+ ELSE
+ drop FALSE \ drop addr
+ THEN
+;
+
+\ ***************************************************************************
+\ SCSI-Command: INQUIRY
+\ Type: Primary Command (SPC-3 clause 6.4)
+\ ***************************************************************************
+\ Forth Word: scsi-build-inquiry ( alloc-len cdb -- )
+\ ***************************************************************************
+\ command code:
+12 CONSTANT scsi-cmd-inquiry
+
+\ CDB structure
+STRUCT
+ /c FIELD inquiry>operation-code \ 0x12
+ /c FIELD inquiry>reserved \ + EVPD-Bit (vital product data)
+ /c FIELD inquiry>page-code \ page code for vital product data (if used)
+ /w FIELD inquiry>allocation-length \ length of Data-In-Buffer
+ /c FIELD inquiry>control \ control byte as specified in SAM-4
+CONSTANT scsi-length-inquiry
+
+\ Setup command INQUIRY
+: scsi-build-inquiry ( alloc-len cdb -- )
+ dup scsi-length-inquiry erase \ 6 bytes CDB
+ scsi-cmd-inquiry over ( alloc-len cdb cmd cdb )
+ inquiry>operation-code c! ( alloc-len cdb )
+ scsi-param-control over inquiry>control c! ( alloc-len cdb )
+ inquiry>allocation-length w! \ size of Data-In Buffer
+ scsi-length-inquiry to scsi-param-size \ update CDB length
+;
+
+\ ----------------------------------------
+\ block structure of inquiry return data:
+\ ----------------------------------------
+STRUCT
+ /c FIELD inquiry-data>peripheral \ qualifier and device type
+ /c FIELD inquiry-data>reserved1
+ /c FIELD inquiry-data>version \ supported SCSI version (1,2,3)
+ /c FIELD inquiry-data>data-format
+ /c FIELD inquiry-data>add-length \ total block length - 4
+ /c FIELD inquiry-data>flags1
+ /c FIELD inquiry-data>flags2
+ /c FIELD inquiry-data>flags3
+ d# 8 FIELD inquiry-data>vendor-ident \ vendor string
+ d# 16 FIELD inquiry-data>product-ident \ device string
+ /l FIELD inquiry-data>product-revision \ revision string
+ d# 20 FIELD inquiry-data>vendor-specific \ optional params
+\ can be increased by vendor specific fields
+CONSTANT scsi-length-inquiry-data
+
+\ ***************************************************************************
+\ SCSI-Command: READ CAPACITY (10)
+\ Type: Block Command (SBC-3 clause 5.12)
+\ ***************************************************************************
+\ Forth Word: scsi-build-read-capacity-10 ( cdb -- )
+\ ***************************************************************************
+25 CONSTANT scsi-cmd-read-capacity-10 \ command code
+
+STRUCT \ SCSI 10-byte CDB structure
+ /c FIELD read-cap-10>operation-code
+ /c FIELD read-cap-10>reserved1
+ /l FIELD read-cap-10>lba
+ /w FIELD read-cap-10>reserved2
+ /c FIELD read-cap-10>reserved3
+ /c FIELD read-cap-10>control
+CONSTANT scsi-length-read-cap-10
+
+\ Setup READ CAPACITY (10) command
+: scsi-build-read-cap-10 ( cdb -- )
+ dup scsi-length-read-cap-10 erase ( cdb )
+ scsi-cmd-read-capacity-10 over ( cdb cmd cdb )
+ read-cap-10>operation-code c! ( cdb )
+ scsi-param-control swap read-cap-10>control c! ( )
+ scsi-length-read-cap-10 to scsi-param-size \ update CDB length
+;
+
+\ ----------------------------------------
+\ get from SCSI response block:
+\ - Additional Sense Code Qualifier
+\ - Additional Sense Code
+\ - sense-key
+\ ----------------------------------------
+\ Forth Word: scsi-get-capacity-10 ( addr -- block-size #blocks )
+\ ----------------------------------------
+\ Block structure
+STRUCT
+ /l FIELD read-cap-10-data>max-lba
+ /l FIELD read-cap-10-data>block-size
+CONSTANT scsi-length-read-cap-10-data
+
+\ get data-block
+: scsi-get-capacity-10 ( addr -- block-size #blocks )
+ >r ( addr -- ) ( R: -- addr )
+ r@ read-cap-10-data>block-size l@ ( block-size )
+ r> read-cap-10-data>max-lba l@ ( block-size #blocks ) ( R: addr -- )
+;
+
+\ ***************************************************************************
+\ SCSI-Command: READ CAPACITY (16)
+\ Type: Block Command (SBC-3 clause 5.13)
+\ ***************************************************************************
+\ Forth Word: scsi-build-read-capacity-16 ( cdb -- )
+\ ***************************************************************************
+9e CONSTANT scsi-cmd-read-capacity-16 \ command code
+
+STRUCT \ SCSI 16-byte CDB structure
+ /c FIELD read-cap-16>operation-code
+ /c FIELD read-cap-16>service-action
+ /l FIELD read-cap-16>lba-high
+ /l FIELD read-cap-16>lba-low
+ /l FIELD read-cap-16>allocation-length \ should be 32
+ /c FIELD read-cap-16>reserved
+ /c FIELD read-cap-16>control
+CONSTANT scsi-length-read-cap-16
+
+\ Setup READ CAPACITY (16) command
+: scsi-build-read-cap-16 ( cdb -- )
+ >r r@ ( R: -- cdb )
+ scsi-length-read-cap-16 erase ( )
+ scsi-cmd-read-capacity-16 ( code )
+ r@ read-cap-16>operation-code c! ( )
+ 10 r@ read-cap-16>service-action c!
+ d# 32 \ response size 32 bytes
+ r@ read-cap-16>allocation-length l! ( )
+ scsi-param-control r> read-cap-16>control c! ( R: cdb -- )
+ scsi-length-read-cap-16 to scsi-param-size \ update CDB length
+;
+
+\ ----------------------------------------
+\ get from SCSI response block:
+\ - Block Size (in Bytes)
+\ - Number of Blocks
+\ ----------------------------------------
+\ Forth Word: scsi-get-capacity-16 ( addr -- block-size #blocks )
+\ ----------------------------------------
+\ Block structure for return data
+STRUCT
+ /l FIELD read-cap-16-data>max-lba-high \ upper quadlet of Max-LBA
+ /l FIELD read-cap-16-data>max-lba-low \ lower quadlet of Max-LBA
+ /l FIELD read-cap-16-data>block-size \ logical block length in bytes
+ /c FIELD read-cap-16-data>protect \ type of protection (4 bits)
+ /c FIELD read-cap-16-data>exponent \ logical blocks per physical blocks
+ /w FIELD read-cap-16-data>lowest-aligned \ first LBA of a phsy. block
+ 10 FIELD read-cap-16-data>reserved \ 16 reserved bytes
+CONSTANT scsi-length-read-cap-16-data \ results in 32
+
+\ get data-block
+: scsi-get-capacity-16 ( addr -- block-size #blocks )
+ >r ( R: -- addr )
+ r@ read-cap-16-data>block-size l@ ( block-size )
+ r@ read-cap-16-data>max-lba-high l@ ( block-size #blocks-high )
+ d# 32 lshift ( block-size #blocks-upper )
+ r> read-cap-16-data>max-lba-low l@ + ( block-size #blocks ) ( R: addr -- )
+;
+
+\ ***************************************************************************
+\ SCSI-Command: MODE SENSE (10)
+\ Type: Primary Command (SPC-3 clause 6.10)
+\ ***************************************************************************
+\ Forth Word: scsi-build-mode-sense-10 ( alloc-len subpage page cdb -- )
+\ ***************************************************************************
+5a CONSTANT scsi-cmd-mode-sense-10
+
+\ CDB structure
+STRUCT
+ /c FIELD mode-sense-10>operation-code
+ /c FIELD mode-sense-10>res-llbaa-dbd-res
+ /c FIELD mode-sense-10>pc-page-code \ page code + page control
+ /c FIELD mode-sense-10>sub-page-code
+ 3 FIELD mode-sense-10>reserved2
+ /w FIELD mode-sense-10>allocation-length
+ /c FIELD mode-sense-10>control
+CONSTANT scsi-length-mode-sense-10
+
+: scsi-build-mode-sense-10 ( alloc-len subpage page cdb -- )
+ >r ( alloc-len subpage page ) ( R: -- cdb )
+ r@ scsi-length-mode-sense-10 erase \ 10 bytes CDB
+ scsi-cmd-mode-sense-10 ( alloc-len subpage page cmd )
+ r@ mode-sense-10>operation-code c! ( alloc-len subpage page )
+ 10 r@ mode-sense-10>res-llbaa-dbd-res c! \ long LBAs accepted
+ r@ mode-sense-10>pc-page-code c! ( alloc-len subpage )
+ r@ mode-sense-10>sub-page-code c! ( alloc-len )
+ r@ mode-sense-10>allocation-length w! ( )
+
+ scsi-param-control r> mode-sense-10>control c! ( R: cdb -- )
+ scsi-length-mode-sense-10 to scsi-param-size \ update CDB length
+;
+
+\ return data processing
+\ (see spec: SPC-3 clause 7.4.3)
+
+STRUCT
+ /w FIELD mode-sense-10-data>head-length
+ /c FIELD mode-sense-10-data>head-medium
+ /c FIELD mode-sense-10-data>head-param
+ /c FIELD mode-sense-10-data>head-longlba
+ /c FIELD mode-sense-10-data>head-reserved
+ /w FIELD mode-sense-10-data>head-descr-len
+CONSTANT scsi-length-mode-sense-10-data
+
+\ ****************************************
+\ This function shows the mode page header
+\ helpful for further analysis
+\ ****************************************
+: .mode-sense-data ( addr -- )
+ cr
+ dup mode-sense-10-data>head-length
+ w@ ." Mode Length: " .d space
+ dup mode-sense-10-data>head-medium
+ c@ ." / Medium Type: " .d space
+ dup mode-sense-10-data>head-longlba
+ c@ ." / Long LBA: " .d space
+ mode-sense-10-data>head-descr-len
+ w@ ." / Descr. Length: " .d
+;
+
+\ ***************************************************************************
+\ SCSI-Command: READ (6)
+\ Type: Block Command (SBC-3 clause 5.7)
+\ ***************************************************************************
+\ Forth Word: scsi-build-read-6 ( block# #blocks cdb -- )
+\ ***************************************************************************
+\ this SCSI command uses 21 bits to represent start LBA
+\ and 8 bits to specify the numbers of blocks to read
+\ The value of 0 blocks is interpreted as 256 blocks
+\
+\ command code
+08 CONSTANT scsi-cmd-read-6
+
+\ CDB structure
+STRUCT
+ /c FIELD read-6>operation-code \ 08h
+ /c FIELD read-6>block-address-msb \ upper 5 bits
+ /w FIELD read-6>block-address \ lower 16 bits
+ /c FIELD read-6>length \ number of blocks to read
+ /c FIELD read-6>control \ CDB control
+CONSTANT scsi-length-read-6
+
+: scsi-build-read-6 ( block# #blocks cdb -- )
+ >r ( block# #blocks ) ( R: -- cdb )
+ r@ scsi-length-read-6 erase \ 6 bytes CDB
+ scsi-cmd-read-6 r@ read-6>operation-code c! ( block# #blocks )
+
+ \ check block count to read (#blocks)
+ dup d# 255 > \ #blocks exceeded limit ?
+ IF
+ scsi-inc-errors
+ drop 1 \ replace with any valid number
+ THEN
+ r@ read-6>length c! \ set #blocks to read
+
+ \ check starting block number (block#)
+ dup 1fffff > \ check address upper limit
+ IF
+ scsi-inc-errors
+ drop \ remove original block#
+ 1fffff \ replace with any valid address
+ THEN
+ dup d# 16 rshift
+ r@ read-6>block-address-msb c! \ set upper 5 bits
+ ffff and
+ r@ read-6>block-address w! \ set lower 16 bits
+ scsi-param-control r> read-6>control c! ( R: cdb -- )
+ scsi-length-read-6 to scsi-param-size \ update CDB length
+;
+
+\ ***************************************************************************
+\ SCSI-Command: READ (10)
+\ Type: Block Command (SBC-3 clause 5.8)
+\ ***************************************************************************
+\ Forth Word: scsi-build-read-10 ( block# #blocks cdb -- )
+\ ***************************************************************************
+\ command code
+28 CONSTANT scsi-cmd-read-10
+
+\ CDB structure
+STRUCT
+ /c FIELD read-10>operation-code
+ /c FIELD read-10>protect
+ /l FIELD read-10>block-address \ logical block address (32bits)
+ /c FIELD read-10>group
+ /w FIELD read-10>length \ transfer length (16-bits)
+ /c FIELD read-10>control
+CONSTANT scsi-length-read-10
+
+: scsi-build-read-10 ( block# #blocks cdb -- )
+ >r ( block# #blocks ) ( R: -- cdb )
+ r@ scsi-length-read-10 erase \ 10 bytes CDB
+ scsi-cmd-read-10 r@ read-10>operation-code c! ( block# #blocks )
+ r@ read-10>length w! ( block# )
+ r@ read-10>block-address l! ( )
+ scsi-param-control r> read-10>control c! ( R: cdb -- )
+ scsi-length-read-10 to scsi-param-size \ update CDB length
+;
+
+\ ***************************************************************************
+\ SCSI-Command: READ (12)
+\ Type: Block Command (SBC-3 clause 5.9)
+\ ***************************************************************************
+\ Forth Word: scsi-build-read-12 ( block# #blocks cdb -- )
+\ ***************************************************************************
+\ command code
+a8 CONSTANT scsi-cmd-read-12
+
+\ CDB structure
+STRUCT
+ /c FIELD read-12>operation-code \ code: a8
+ /c FIELD read-12>protect \ RDPROTECT, DPO, FUA, FUA_NV
+ /l FIELD read-12>block-address \ lba
+ /l FIELD read-12>length \ transfer length (32bits)
+ /c FIELD read-12>group \ group number
+ /c FIELD read-12>control
+CONSTANT scsi-length-read-12
+
+: scsi-build-read-12 ( block# #blocks cdb -- )
+ >r ( block# #blocks ) ( R: -- cdb )
+ r@ scsi-length-read-12 erase \ 12 bytes CDB
+ scsi-cmd-read-12 r@ read-12>operation-code c! ( block# #blocks )
+ r@ read-12>length l! ( block# )
+ r@ read-12>block-address l! ( )
+ scsi-param-control r> read-12>control c! ( R: cdb -- )
+ scsi-length-read-12 to scsi-param-size \ update CDB length
+;
+
+\ ***************************************************************************
+\ SCSI-Command: READ with autodetection of required command
+\ read(10) or read(12) depending on parameter size
+\ (read(6) removed because obsolete in some cases (USB))
+\ Type: Block Command
+\ ***************************************************************************
+\ Forth Word: scsi-build-read? ( block# #blocks cdb -- )
+\
+\ +----------------+---------------------------|
+\ | block# (lba) | #block (transfer-length) |
+\ +-----------+----------------+---------------------------|
+\ | read-6 | 16-Bits | 8 Bits |
+\ | read-10 | 32-Bits | 16 Bits |
+\ | read-12 | 32-Bits | 32 Bits |
+\ ***************************************************************************
+: scsi-build-read? ( block# #blocks cdb -- length )
+ over ( block# #blocks cdb #blocks )
+ fffe > \ tx-length (#blocks) exceeds 16-bit limit ?
+ IF
+ scsi-build-read-12 ( block# #blocks cdb -- )
+ scsi-length-read-12 ( length )
+ ELSE ( block# #blocks cdb )
+ scsi-build-read-10 ( block# #blocks cdb -- )
+ scsi-length-read-10 ( length )
+ THEN
+;
+
+\ ***************************************************************************
+\ SCSI-Command: START STOP UNIT
+\ Type: Block Command (SBC-3 clause 5.19)
+\ ***************************************************************************
+\ Forth Word: scsi-build-start-stop-unit ( state# cdb -- )
+\ ***************************************************************************
+\ command code
+1b CONSTANT scsi-cmd-start-stop-unit
+
+\ CDB structure
+STRUCT
+ /c FIELD start-stop-unit>operation-code
+ /c FIELD start-stop-unit>immed
+ /w FIELD start-stop-unit>reserved
+ /c FIELD start-stop-unit>pow-condition
+ /c FIELD start-stop-unit>control
+CONSTANT scsi-length-start-stop-unit
+
+\ START/STOP constants
+\ (see spec: SBC-3 clause 5.19)
+f1 CONSTANT scsi-const-active-power \ param used for start-stop-unit
+f2 CONSTANT scsi-const-idle-power \ param used for start-stop-unit
+f3 CONSTANT scsi-const-standby-power \ param used for start-stop-unit
+3 CONSTANT scsi-const-load \ param used for start-stop-unit
+2 CONSTANT scsi-const-eject \ param used for start-stop-unit
+1 CONSTANT scsi-const-start
+0 CONSTANT scsi-const-stop
+
+: scsi-build-start-stop-unit ( state# cdb -- )
+ >r ( state# ) ( R: -- cdb )
+ r@ scsi-length-start-stop-unit erase \ 6 bytes CDB
+ scsi-cmd-start-stop-unit r@ start-stop-unit>operation-code c!
+ dup 3 >
+ IF
+ 4 lshift \ shift to upper nibble
+ THEN ( state )
+ r@ start-stop-unit>pow-condition c! ( )
+ scsi-param-control r> start-stop-unit>control c! ( R: cdb -- )
+ scsi-length-start-stop-unit to scsi-param-size \ update CDB length
+;
+
+\ ***************************************************************************
+\ SCSI-Command: SEEK(10)
+\ Type: Block Command (obsolete)
+\ ***************************************************************************
+\ Forth Word: scsi-build-seek ( state# cdb -- )
+\ Obsolete function (last listed in spec SBC / Nov. 1997)
+\ implemented only for the sake of completeness
+\ ***************************************************************************
+\ command code
+2b CONSTANT scsi-cmd-seek
+
+\ CDB structure
+STRUCT
+ /c FIELD seek>operation-code
+ /c FIELD seek>reserved1
+ /l FIELD seek>lba
+ 3 FIELD seek>reserved2
+ /c FIELD seek>control
+CONSTANT scsi-length-seek
+
+: scsi-build-seek ( lba cdb -- )
+ >r ( lba ) ( R: -- cdb )
+ r@ scsi-length-seek erase \ 10 bytes CDB
+ scsi-cmd-seek r@ seek>operation-code c!
+ r> seek>lba l! ( ) ( R: cdb -- )
+ scsi-length-seek to scsi-param-size \ update CDB length
+;
+
+\ ****************************************************************************
+\ CDROM media event stuff
+\ ****************************************************************************
+
+STRUCT
+ /w FIELD media-event-data-len
+ /c FIELD media-event-nea-class
+ /c FIELD media-event-supp-class
+ /l FIELD media-event-data
+CONSTANT scsi-length-media-event
+
+: scsi-build-get-media-event ( cdb -- )
+ dup c erase ( cdb )
+ 4a over c! ( cdb )
+ 01 over 1 + c!
+ 10 over 4 + c!
+ 08 over 8 + c!
+ drop
+;
+
+
+
+\ ***************************************************************************
+\ SCSI-Utility: .sense-code
+\ ***************************************************************************
+\ this utility prints a string associated to the sense code
+\ see specs: SPC-3/r23 clause 4.5.6
+\ ***************************************************************************
+: .sense-text ( scode -- )
+ case
+ 0 OF s" OK" ENDOF
+ 1 OF s" RECOVERED ERR" ENDOF
+ 2 OF s" NOT READY" ENDOF
+ 3 OF s" MEDIUM ERROR" ENDOF
+ 4 OF s" HARDWARE ERR" ENDOF
+ 5 OF s" ILLEGAL REQUEST" ENDOF
+ 6 OF s" UNIT ATTENTION" ENDOF
+ 7 OF s" DATA PROTECT" ENDOF
+ 8 OF s" BLANK CHECK" ENDOF
+ 9 OF s" VENDOR SPECIFIC" ENDOF
+ a OF s" COPY ABORTED" ENDOF
+ b OF s" ABORTED COMMAND" ENDOF
+ d OF s" VOLUME OVERFLOW" ENDOF
+ e OF s" MISCOMPARE" ENDOF
+ dup OF s" UNKNOWN" ENDOF
+ endcase
+ 5b emit type 5d emit
+;
+
+\ ***************************************************************************
+\ SCSI-Utility: .status-code
+\ ***************************************************************************
+\ this utility prints a string associated to the status code
+\ see specs: SAM-3/r14 clause 5.3
+\ ***************************************************************************
+: .status-text ( stat -- )
+ case
+ 00 OF s" GOOD" ENDOF
+ 02 OF s" CHECK CONDITION" ENDOF
+ 04 OF s" CONDITION MET" ENDOF
+ 08 OF s" BUSY" ENDOF
+ 18 OF s" RESERVATION CONFLICT" ENDOF
+ 28 OF s" TASK SET FULL" ENDOF
+ 30 OF s" ACA ACTIVE" ENDOF
+ 40 OF s" TASK ABORTED" ENDOF
+ dup OF s" UNKNOWN" ENDOF
+ endcase
+ 5b emit type 5d emit
+;
+
+\ ***************************************************************************
+\ SCSI-Utility: .capacity-text
+\ ***************************************************************************
+\ utility that shows total capacity on screen by use of the return data
+\ from read-capacity calculation is SI conform (base 10)
+\ ***************************************************************************
+\ sub function to print a 3 digit decimal
+\ number with 2 post decimal positions xxx.yy
+: .dec3-2 ( prenum postnum -- )
+ swap
+ base @ >r \ save actual base setting
+ decimal \ show decimal values
+ 4 .r 2e emit
+ dup 9 <= IF 30 emit THEN .d \ 3 pre-decimal, right aligned
+ r> base ! \ restore base
+;
+
+: .capacity-text ( block-size #blocks -- )
+ scsi-param-debug \ debugging flag set ?
+ IF \ show additional info
+ 2dup
+ cr
+ ." LBAs: " .d \ highest logical block number
+ ." / Block-Size: " .d
+ ." / Total Capacity: "
+ THEN
+ * \ calculate total capacity
+ dup d# 1000000000000 >= \ check terabyte limit
+ IF
+ d# 1000000000000 /mod
+ swap
+ d# 10000000000 / \ limit remainder to two digits
+ .dec3-2 ." TB" \ show terabytes as xxx.yy
+ ELSE
+ dup d# 1000000000 >= \ check gigabyte limit
+ IF
+ d# 1000000000 /mod
+ swap
+ d# 10000000 /
+ .dec3-2 ." GB" \ show gigabytes as xxx.yy
+ ELSE
+ dup d# 1000000 >=
+ IF
+ d# 1000000 /mod \ check mega byte limit
+ swap
+ d# 10000 /
+ .dec3-2 ." MB" \ show megabytes as xxx.yy
+ ELSE
+ dup d# 1000 >= \ check kilo byte limit
+ IF
+ d# 1000 /mod
+ swap
+ d# 10 /
+ .dec3-2 ." kB"
+ ELSE
+ .d ." Bytes"
+ THEN
+ THEN
+ THEN
+ THEN
+;
+
+\ ***************************************************************************
+\ SCSI-Utility: .inquiry-text ( addr -- )
+\ ***************************************************************************
+\ utility that shows:
+\ vendor-ident product-ident and revision
+\ from an inquiry return data block (addr)
+\ ***************************************************************************
+: .inquiry-text ( addr -- )
+ 22 emit \ enclose text with "
+ dup inquiry-data>vendor-ident 8 type space
+ dup inquiry-data>product-ident 10 type space
+ inquiry-data>product-revision 4 type
+ 22 emit
+;
+
+\ ***************************************************************************
+\ SCSI-Utility: scsi-supp-init ( -- )
+\ ***************************************************************************
+\ utility that helps to ensure that parameters are set to valid values
+: scsi-supp-init ( -- )
+ false to scsi-param-debug \ no debug strings
+ h# 0 to scsi-param-size
+ h# 0 to scsi-param-control \ common CDB control byte
+ d# 0 to scsi-param-errors \ local errors (param limits)
+;
+
+\ ***************************************************************************
+\ Constants used by SCSI controller's execute-scsi-command
+\ ***************************************************************************
+true CONSTANT scsi-dir-read
+false CONSTANT scsi-dir-write
+
+
+\ ***************************************************************************
+\ scsi loader
+\ ***************************************************************************
+0 VALUE scsi-context \ addr of word list on top
+
+
+\ ****************************************************************************
+\ open scsi-support by adding a new word list on top of search path
+\ precondition: scsi-support.fs must have been included
+\ ****************************************************************************
+: scsi-init ( -- )
+ also scsi-words \ append scsi word-list
+ context to scsi-context \ save for close process
+ scsi-supp-init \ preset all scsi-param-xxx values
+ scsi-param-debug
+ IF
+ space ." SCSI-SUPPORT OPENED" cr
+ .wordlists
+ THEN
+;
+
+\ ****************************************************************************
+\ close scsi-session and remove scsi word list (if exists)
+\ ****************************************************************************
+\ if 'previous' is used without a preceding 'also' all forth words are lost !
+\ ****************************************************************************
+: scsi-close ( -- )
+\ FIXME This only works if scsi-words is the last vocabulary on the stack
+\ Instead we could use get-order to find us on the "wordlist stack",
+\ remove us and write the wordlist stack back with set-order.
+\ BUT: Is this worth the effort?
+
+ scsi-param-debug
+ IF
+ space ." Closing SCSI-SUPPORT .. " cr
+ THEN
+ context scsi-context = \ scsi word list still active ?
+ IF
+ scsi-param-errors 0<> \ any errors occurred ?
+ IF
+ cr ." ** WARNING: " scsi-param-errors .d
+ ." SCSI Errors occurred ** " cr
+ THEN
+ previous \ remove scsi word list on top
+ 0 to scsi-context \ prevent from being misinterpreted
+ ELSE
+ cr ." ** WARNING: Trying to close non-open SCSI-SUPPORT (1) ** " cr
+ THEN
+ scsi-param-debug
+ IF
+ .wordlists
+ THEN
+;
+
+
+s" scsi-init" $find drop \ return execution pointer, when included
+
+previous \ remove scsi word list from search path
+definitions \ place next definitions into previous list
+