884 lines
36 KiB
Forth
884 lines
36 KiB
Forth
\ *****************************************************************************
|
|
\ * 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 (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 (16)
|
|
\ Type: Block Command
|
|
\ ***************************************************************************
|
|
\ Forth Word: scsi-build-read-16 ( block# #blocks cdb -- )
|
|
\ ***************************************************************************
|
|
\ command code
|
|
88 CONSTANT scsi-cmd-read-16
|
|
|
|
\ CDB structure
|
|
STRUCT
|
|
/c FIELD read-16>operation-code \ code: 88
|
|
/c FIELD read-16>protect \ RDPROTECT, DPO, FUA, FUA_NV
|
|
/x FIELD read-16>block-address \ lba
|
|
/l FIELD read-16>length \ transfer length (32bits)
|
|
/c FIELD read-16>group \ group number
|
|
/c FIELD read-16>control
|
|
CONSTANT scsi-length-read-16
|
|
|
|
: scsi-build-read-16 ( block# #blocks cdb -- )
|
|
>r ( block# #blocks ) ( R: -- cdb )
|
|
r@ scsi-length-read-16 erase \ 16 bytes CDB
|
|
scsi-cmd-read-16 r@ read-16>operation-code c! ( block# #blocks )
|
|
r@ read-16>length l! ( block# )
|
|
r@ read-16>block-address x! ( )
|
|
scsi-param-control r> read-16>control c! ( R: cdb -- )
|
|
scsi-length-read-16 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: WRITE (10)
|
|
\ Type: Block Command
|
|
\ ***************************************************************************
|
|
\ Forth Word: scsi-build-write-10 ( block# #blocks cdb -- )
|
|
\ ***************************************************************************
|
|
\ command code
|
|
2A CONSTANT scsi-cmd-write-10
|
|
|
|
\ CDB structure
|
|
STRUCT
|
|
/c FIELD write-10>operation-code
|
|
/c FIELD write-10>protect
|
|
/l FIELD write-10>block-address \ logical block address (32bits)
|
|
/c FIELD write-10>group
|
|
/w FIELD write-10>length \ transfer length (16-bits)
|
|
/c FIELD write-10>control
|
|
CONSTANT scsi-length-write-10
|
|
|
|
: scsi-build-write-10 ( block# #blocks cdb -- )
|
|
>r ( block# #blocks ) ( R: -- cdb )
|
|
r@ scsi-length-write-10 erase \ 10 bytes CDB
|
|
scsi-cmd-write-10 r@ write-10>operation-code c! ( block# #blocks )
|
|
r@ write-10>length w! ( block# )
|
|
r@ write-10>block-address l! ( )
|
|
scsi-param-control r> write-10>control c! ( R: cdb -- )
|
|
scsi-length-write-10 to scsi-param-size \ update CDB length
|
|
;
|
|
|
|
\ ***************************************************************************
|
|
\ SCSI-Command: WRITE (16)
|
|
\ Type: Block Command
|
|
\ ***************************************************************************
|
|
\ Forth Word: scsi-build-write-16 ( block# #blocks cdb -- )
|
|
\ ***************************************************************************
|
|
\ command code
|
|
8A CONSTANT scsi-cmd-write-16
|
|
|
|
\ CDB structure
|
|
STRUCT
|
|
/c FIELD write-16>operation-code
|
|
/c FIELD write-16>protect \ RDPROTECT, DPO, FUA, FUA_NV
|
|
/x FIELD write-16>block-address \ LBA
|
|
/l FIELD write-16>length \ Transfer length (32-bits)
|
|
/c FIELD write-16>group \ Group number
|
|
/c FIELD write-16>control
|
|
CONSTANT scsi-length-write-16
|
|
|
|
: scsi-build-write-16 ( block# #blocks cdb -- )
|
|
>r ( block# #blocks ) ( R: -- cdb )
|
|
r@ scsi-length-write-16 erase \ 16 bytes CDB
|
|
scsi-cmd-write-16 r@ write-16>operation-code c! ( block# #blocks )
|
|
r@ write-16>length l! ( block# )
|
|
r@ write-16>block-address x! ( )
|
|
scsi-param-control r> write-16>control c! ( R: cdb -- )
|
|
scsi-length-write-16 to scsi-param-size \ update CDB length
|
|
;
|
|
|
|
\ ***************************************************************************
|
|
\ 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
|
|
|