\ ***************************************************************************** \ * 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