1\ ***************************************************************************** 2\ * Copyright (c) 2004, 2008 IBM Corporation 3\ * All rights reserved. 4\ * This program and the accompanying materials 5\ * are made available under the terms of the BSD License 6\ * which accompanies this distribution, and is available at 7\ * http://www.opensource.org/licenses/bsd-license.php 8\ * 9\ * Contributors: 10\ * IBM Corporation - initial implementation 11\ ****************************************************************************/ 12 13\ ************************************************ 14\ create a new scsi word-list named 'scsi-words' 15\ ************************************************ 16vocabulary scsi-words \ create new word list named 'scsi-words' 17also scsi-words definitions \ place next definitions into new list 18 19\ for some commands specific parameters are used, which normally 20\ need not to be altered. These values are preset at include time 21\ or explicit by a call of 'scsi-supp-init' 22false value scsi-param-debug \ common debugging flag 23d# 0 value scsi-param-size \ length of CDB processed last 24h# 0 value scsi-param-control \ control word for CDBs as defined in SAM-4 25d# 0 value scsi-param-errors \ counter for detected errors 26 27\ utility to increment error counter 28: scsi-inc-errors 29 scsi-param-errors 1 + to scsi-param-errors 30; 31 32\ *************************************************************************** 33\ SCSI-Command: TEST UNIT READY 34\ Type: Primary Command (SPC-3 clause 6.33) 35\ *************************************************************************** 36\ Forth Word: scsi-build-test-unit-ready ( cdb -- ) 37\ *************************************************************************** 38\ checks if a device is ready to receive commands 39\ *************************************************************************** 40\ command code: 4100 CONSTANT scsi-cmd-test-unit-ready 42\ CDB structure: 43STRUCT 44 /c FIELD test-unit-ready>operation-code \ 00h 45 4 FIELD test-unit-ready>reserved \ unused 46 /c FIELD test-unit-ready>control \ control byte as specified in SAM-4 47CONSTANT scsi-length-test-unit-ready 48 49\ cdb build: 50\ all fields are zeroed 51: scsi-build-test-unit-ready ( cdb -- ) 52 dup scsi-length-test-unit-ready erase ( cdb ) 53 scsi-param-control swap test-unit-ready>control c! ( ) 54 scsi-length-test-unit-ready to scsi-param-size \ update CDB length 55; 56 57\ *************************************************************************** 58\ SCSI-Command: REPORT LUNS 59\ Type: Primary Command 60\ *************************************************************************** 61\ Forth Word: scsi-build-report-luns ( cdb -- ) 62\ *************************************************************************** 63\ report all LUNs supported by a device 64\ *************************************************************************** 65\ command code: 66a0 CONSTANT scsi-cmd-report-luns 67\ CDB structure: 68STRUCT 69 /c FIELD report-luns>operation-code \ a0h 70 1 FIELD report-luns>reserved \ unused 71 /c FIELD report-luns>select-report \ report select byte 72 3 FIELD report-luns>reserved2 \ unused 73 /l FIELD report-luns>alloc-length \ report length 74 1 FIELD report-luns>reserved3 \ unused 75 /c FIELD report-luns>control \ control byte 76CONSTANT scsi-length-report-luns 77 78\ cdb build: 79\ all fields are zeroed 80: scsi-build-report-luns ( alloc-len cdb -- ) 81 dup scsi-length-report-luns erase \ 12 bytes CDB 82 scsi-cmd-report-luns over ( alloc-len cdb cmd cdb ) 83 report-luns>operation-code c! ( alloc-len cdb ) 84 scsi-param-control over report-luns>control c! ( alloc-len cdb ) 85 report-luns>alloc-length l! \ size of Data-In Buffer 86 scsi-length-report-luns to scsi-param-size \ update CDB length 87; 88 89\ *************************************************************************** 90\ SCSI-Command: REQUEST SENSE 91\ Type: Primary Command (SPC-3 clause 6.27) 92\ *************************************************************************** 93\ Forth Word: scsi-build-request-sense ( cdb -- ) 94\ *************************************************************************** 95\ for return data a buffer of at least 252 bytes must be present! 96\ see spec: SPC-3 (r23) / clauses 4.5 and 6.27 97\ *************************************************************************** 98\ command code: 9903 CONSTANT scsi-cmd-request-sense 100\ CDB structure: 101STRUCT 102 /c FIELD request-sense>operation-code \ 03h 103 3 FIELD request-sense>reserved \ unused 104 /c FIELD request-sense>allocation-length \ buffer-length for data response 105 /c FIELD request-sense>control \ control byte as specified in SAM-4 106CONSTANT scsi-length-request-sense 107 108\ cdb build: 109: scsi-build-request-sense ( alloc-len cdb -- ) 110 >r ( alloc-len ) ( R: -- cdb ) 111 r@ scsi-length-request-sense erase ( alloc-len ) 112 scsi-cmd-request-sense r@ ( alloc-len cmd cdb ) 113 request-sense>operation-code c! ( alloc-len ) 114 dup d# 252 > \ buffer length too big ? 115 IF 116 scsi-inc-errors 117 drop d# 252 \ replace with 252 118 ELSE 119 dup d# 18 < \ allocated buffer too small ? 120 IF 121 scsi-inc-errors 122 drop 0 \ reject return data 123 THEN 124 THEN ( alloclen ) 125 r@ request-sense>allocation-length c! ( ) 126 scsi-param-control r> request-sense>control c! ( alloc-len cdb ) ( R: cdb -- ) 127 scsi-length-request-sense to scsi-param-size \ update CDB length 128; 129 130\ ---------------------------------------- 131\ SCSI-Response: SENSE_DATA 132\ ---------------------------------------- 13370 CONSTANT scsi-response(request-sense-0) 13471 CONSTANT scsi-response(request-sense-1) 135 136STRUCT 137 /c FIELD sense-data>response-code \ 70h (current errors) or 71h (deferred errors) 138 /c FIELD sense-data>obsolete 139 /c FIELD sense-data>sense-key \ D3..D0 = sense key, D7 = EndOfMedium 140 /l FIELD sense-data>info 141 /c FIELD sense-data>alloc-length \ <= 244 (for max size) 142 /l FIELD sense-data>command-info 143 /c FIELD sense-data>asc \ additional sense key 144 /c FIELD sense-data>ascq \ additional sense key qualifier 145 /c FIELD sense-data>unit-code 146 3 FIELD sense-data>key-specific 147 /c FIELD sense-data>add-sense-bytes \ start of appended extra bytes 148CONSTANT scsi-length-sense-data 149 150\ ---------------------------------------- 151\ get from SCSI response block: 152\ - Additional Sense Code Qualifier 153\ - Additional Sense Code 154\ - sense-key 155\ ---------------------------------------- 156\ Forth Word: scsi-get-sense-data ( addr -- ascq asc sense-key ) 157\ ---------------------------------------- 158: scsi-get-sense-data ( addr -- ascq asc sense-key ) 159 >r ( R: -- addr ) 160 r@ sense-data>response-code c@ 7f and 72 >= IF 161 r@ 3 + c@ ( ascq ) 162 r@ 2 + c@ ( ascq asc ) 163 r> 1 + c@ 0f and ( ascq asc sense-key ) 164 ELSE 165 r@ sense-data>ASCQ c@ ( ascq ) 166 r@ sense-data>ASC c@ ( ascq asc ) 167 r> sense-data>sense-key c@ 0f and ( ascq asc sense-key ) ( R: addr -- ) 168 THEN 169; 170 171\ -------------------------------------------------------------------------- 172\ Forth Word: scsi-get-sense-data? ( addr -- false | ascq asc sense-key true ) 173\ -------------------------------------------------------------------------- 174: scsi-get-sense-data? ( addr -- false | ascq asc sense-key true ) 175 dup 176 sense-data>response-code c@ 177 7e AND dup 70 = swap 72 = or \ Response code (some devices have MSB set) 178 IF 179 scsi-get-sense-data TRUE 180 ELSE 181 drop FALSE \ drop addr 182 THEN 183 184; 185 186\ -------------------------------------------------------------------------- 187\ Forth Word: scsi-get-sense-ID? ( addr -- false | sense-ID true ) 188\ same as scsi-get-sense-data? but returns 189\ a single word composed of: sense-key<<16 | asc<<8 | ascq 190\ -------------------------------------------------------------------------- 191: scsi-get-sense-ID? ( addr -- false | ascq asc sense-key true ) 192 dup 193 sense-data>response-code c@ 194 7e AND 70 = \ Response code (some devices have MSB set) 195 IF 196 scsi-get-sense-data ( ascq asc sense-key ) 197 10 lshift ( ascq asc sense-key16 ) 198 swap 8 lshift or ( ascq sense-key+asc ) 199 swap or \ 24-bit sense-ID ( sense-key+asc+ascq ) 200 TRUE 201 ELSE 202 drop FALSE \ drop addr 203 THEN 204; 205 206\ *************************************************************************** 207\ SCSI-Command: INQUIRY 208\ Type: Primary Command (SPC-3 clause 6.4) 209\ *************************************************************************** 210\ Forth Word: scsi-build-inquiry ( alloc-len cdb -- ) 211\ *************************************************************************** 212\ command code: 21312 CONSTANT scsi-cmd-inquiry 214 215\ CDB structure 216STRUCT 217 /c FIELD inquiry>operation-code \ 0x12 218 /c FIELD inquiry>reserved \ + EVPD-Bit (vital product data) 219 /c FIELD inquiry>page-code \ page code for vital product data (if used) 220 /w FIELD inquiry>allocation-length \ length of Data-In-Buffer 221 /c FIELD inquiry>control \ control byte as specified in SAM-4 222CONSTANT scsi-length-inquiry 223 224\ Setup command INQUIRY 225: scsi-build-inquiry ( alloc-len cdb -- ) 226 dup scsi-length-inquiry erase \ 6 bytes CDB 227 scsi-cmd-inquiry over ( alloc-len cdb cmd cdb ) 228 inquiry>operation-code c! ( alloc-len cdb ) 229 scsi-param-control over inquiry>control c! ( alloc-len cdb ) 230 inquiry>allocation-length w! \ size of Data-In Buffer 231 scsi-length-inquiry to scsi-param-size \ update CDB length 232; 233 234\ ---------------------------------------- 235\ block structure of inquiry return data: 236\ ---------------------------------------- 237STRUCT 238 /c FIELD inquiry-data>peripheral \ qualifier and device type 239 /c FIELD inquiry-data>reserved1 240 /c FIELD inquiry-data>version \ supported SCSI version (1,2,3) 241 /c FIELD inquiry-data>data-format 242 /c FIELD inquiry-data>add-length \ total block length - 4 243 /c FIELD inquiry-data>flags1 244 /c FIELD inquiry-data>flags2 245 /c FIELD inquiry-data>flags3 246 d# 8 FIELD inquiry-data>vendor-ident \ vendor string 247 d# 16 FIELD inquiry-data>product-ident \ device string 248 /l FIELD inquiry-data>product-revision \ revision string 249 d# 20 FIELD inquiry-data>vendor-specific \ optional params 250\ can be increased by vendor specific fields 251CONSTANT scsi-length-inquiry-data 252 253\ *************************************************************************** 254\ SCSI-Command: READ CAPACITY (10) 255\ Type: Block Command (SBC-3 clause 5.12) 256\ *************************************************************************** 257\ Forth Word: scsi-build-read-capacity-10 ( cdb -- ) 258\ *************************************************************************** 25925 CONSTANT scsi-cmd-read-capacity-10 \ command code 260 261STRUCT \ SCSI 10-byte CDB structure 262 /c FIELD read-cap-10>operation-code 263 /c FIELD read-cap-10>reserved1 264 /l FIELD read-cap-10>lba 265 /w FIELD read-cap-10>reserved2 266 /c FIELD read-cap-10>reserved3 267 /c FIELD read-cap-10>control 268CONSTANT scsi-length-read-cap-10 269 270\ Setup READ CAPACITY (10) command 271: scsi-build-read-cap-10 ( cdb -- ) 272 dup scsi-length-read-cap-10 erase ( cdb ) 273 scsi-cmd-read-capacity-10 over ( cdb cmd cdb ) 274 read-cap-10>operation-code c! ( cdb ) 275 scsi-param-control swap read-cap-10>control c! ( ) 276 scsi-length-read-cap-10 to scsi-param-size \ update CDB length 277; 278 279\ ---------------------------------------- 280\ get from SCSI response block: 281\ - Additional Sense Code Qualifier 282\ - Additional Sense Code 283\ - sense-key 284\ ---------------------------------------- 285\ Forth Word: scsi-get-capacity-10 ( addr -- block-size #blocks ) 286\ ---------------------------------------- 287\ Block structure 288STRUCT 289 /l FIELD read-cap-10-data>max-lba 290 /l FIELD read-cap-10-data>block-size 291CONSTANT scsi-length-read-cap-10-data 292 293\ get data-block 294: scsi-get-capacity-10 ( addr -- block-size #blocks ) 295 >r ( addr -- ) ( R: -- addr ) 296 r@ read-cap-10-data>block-size l@ ( block-size ) 297 r> read-cap-10-data>max-lba l@ ( block-size #blocks ) ( R: addr -- ) 298; 299 300\ *************************************************************************** 301\ SCSI-Command: READ CAPACITY (16) 302\ Type: Block Command (SBC-3 clause 5.13) 303\ *************************************************************************** 304\ Forth Word: scsi-build-read-capacity-16 ( cdb -- ) 305\ *************************************************************************** 3069e CONSTANT scsi-cmd-read-capacity-16 \ command code 307 308STRUCT \ SCSI 16-byte CDB structure 309 /c FIELD read-cap-16>operation-code 310 /c FIELD read-cap-16>service-action 311 /l FIELD read-cap-16>lba-high 312 /l FIELD read-cap-16>lba-low 313 /l FIELD read-cap-16>allocation-length \ should be 32 314 /c FIELD read-cap-16>reserved 315 /c FIELD read-cap-16>control 316CONSTANT scsi-length-read-cap-16 317 318\ Setup READ CAPACITY (16) command 319: scsi-build-read-cap-16 ( cdb -- ) 320 >r r@ ( R: -- cdb ) 321 scsi-length-read-cap-16 erase ( ) 322 scsi-cmd-read-capacity-16 ( code ) 323 r@ read-cap-16>operation-code c! ( ) 324 10 r@ read-cap-16>service-action c! 325 d# 32 \ response size 32 bytes 326 r@ read-cap-16>allocation-length l! ( ) 327 scsi-param-control r> read-cap-16>control c! ( R: cdb -- ) 328 scsi-length-read-cap-16 to scsi-param-size \ update CDB length 329; 330 331\ ---------------------------------------- 332\ get from SCSI response block: 333\ - Block Size (in Bytes) 334\ - Number of Blocks 335\ ---------------------------------------- 336\ Forth Word: scsi-get-capacity-16 ( addr -- block-size #blocks ) 337\ ---------------------------------------- 338\ Block structure for return data 339STRUCT 340 /l FIELD read-cap-16-data>max-lba-high \ upper quadlet of Max-LBA 341 /l FIELD read-cap-16-data>max-lba-low \ lower quadlet of Max-LBA 342 /l FIELD read-cap-16-data>block-size \ logical block length in bytes 343 /c FIELD read-cap-16-data>protect \ type of protection (4 bits) 344 /c FIELD read-cap-16-data>exponent \ logical blocks per physical blocks 345 /w FIELD read-cap-16-data>lowest-aligned \ first LBA of a phsy. block 346 10 FIELD read-cap-16-data>reserved \ 16 reserved bytes 347CONSTANT scsi-length-read-cap-16-data \ results in 32 348 349\ get data-block 350: scsi-get-capacity-16 ( addr -- block-size #blocks ) 351 >r ( R: -- addr ) 352 r@ read-cap-16-data>block-size l@ ( block-size ) 353 r@ read-cap-16-data>max-lba-high l@ ( block-size #blocks-high ) 354 d# 32 lshift ( block-size #blocks-upper ) 355 r> read-cap-16-data>max-lba-low l@ + ( block-size #blocks ) ( R: addr -- ) 356; 357 358\ *************************************************************************** 359\ SCSI-Command: MODE SENSE (10) 360\ Type: Primary Command (SPC-3 clause 6.10) 361\ *************************************************************************** 362\ Forth Word: scsi-build-mode-sense-10 ( alloc-len subpage page cdb -- ) 363\ *************************************************************************** 3645a CONSTANT scsi-cmd-mode-sense-10 365 366\ CDB structure 367STRUCT 368 /c FIELD mode-sense-10>operation-code 369 /c FIELD mode-sense-10>res-llbaa-dbd-res 370 /c FIELD mode-sense-10>pc-page-code \ page code + page control 371 /c FIELD mode-sense-10>sub-page-code 372 3 FIELD mode-sense-10>reserved2 373 /w FIELD mode-sense-10>allocation-length 374 /c FIELD mode-sense-10>control 375CONSTANT scsi-length-mode-sense-10 376 377: scsi-build-mode-sense-10 ( alloc-len subpage page cdb -- ) 378 >r ( alloc-len subpage page ) ( R: -- cdb ) 379 r@ scsi-length-mode-sense-10 erase \ 10 bytes CDB 380 scsi-cmd-mode-sense-10 ( alloc-len subpage page cmd ) 381 r@ mode-sense-10>operation-code c! ( alloc-len subpage page ) 382 10 r@ mode-sense-10>res-llbaa-dbd-res c! \ long LBAs accepted 383 r@ mode-sense-10>pc-page-code c! ( alloc-len subpage ) 384 r@ mode-sense-10>sub-page-code c! ( alloc-len ) 385 r@ mode-sense-10>allocation-length w! ( ) 386 387 scsi-param-control r> mode-sense-10>control c! ( R: cdb -- ) 388 scsi-length-mode-sense-10 to scsi-param-size \ update CDB length 389; 390 391\ return data processing 392\ (see spec: SPC-3 clause 7.4.3) 393 394STRUCT 395 /w FIELD mode-sense-10-data>head-length 396 /c FIELD mode-sense-10-data>head-medium 397 /c FIELD mode-sense-10-data>head-param 398 /c FIELD mode-sense-10-data>head-longlba 399 /c FIELD mode-sense-10-data>head-reserved 400 /w FIELD mode-sense-10-data>head-descr-len 401CONSTANT scsi-length-mode-sense-10-data 402 403\ **************************************** 404\ This function shows the mode page header 405\ helpful for further analysis 406\ **************************************** 407: .mode-sense-data ( addr -- ) 408 cr 409 dup mode-sense-10-data>head-length 410 w@ ." Mode Length: " .d space 411 dup mode-sense-10-data>head-medium 412 c@ ." / Medium Type: " .d space 413 dup mode-sense-10-data>head-longlba 414 c@ ." / Long LBA: " .d space 415 mode-sense-10-data>head-descr-len 416 w@ ." / Descr. Length: " .d 417; 418 419\ *************************************************************************** 420\ SCSI-Command: READ (10) 421\ Type: Block Command (SBC-3 clause 5.8) 422\ *************************************************************************** 423\ Forth Word: scsi-build-read-10 ( block# #blocks cdb -- ) 424\ *************************************************************************** 425\ command code 42628 CONSTANT scsi-cmd-read-10 427 428\ CDB structure 429STRUCT 430 /c FIELD read-10>operation-code 431 /c FIELD read-10>protect 432 /l FIELD read-10>block-address \ logical block address (32bits) 433 /c FIELD read-10>group 434 /w FIELD read-10>length \ transfer length (16-bits) 435 /c FIELD read-10>control 436CONSTANT scsi-length-read-10 437 438: scsi-build-read-10 ( block# #blocks cdb -- ) 439 >r ( block# #blocks ) ( R: -- cdb ) 440 r@ scsi-length-read-10 erase \ 10 bytes CDB 441 scsi-cmd-read-10 r@ read-10>operation-code c! ( block# #blocks ) 442 r@ read-10>length w! ( block# ) 443 r@ read-10>block-address l! ( ) 444 scsi-param-control r> read-10>control c! ( R: cdb -- ) 445 scsi-length-read-10 to scsi-param-size \ update CDB length 446; 447 448\ *************************************************************************** 449\ SCSI-Command: READ (12) 450\ Type: Block Command (SBC-3 clause 5.9) 451\ *************************************************************************** 452\ Forth Word: scsi-build-read-12 ( block# #blocks cdb -- ) 453\ *************************************************************************** 454\ command code 455a8 CONSTANT scsi-cmd-read-12 456 457\ CDB structure 458STRUCT 459 /c FIELD read-12>operation-code \ code: a8 460 /c FIELD read-12>protect \ RDPROTECT, DPO, FUA, FUA_NV 461 /l FIELD read-12>block-address \ lba 462 /l FIELD read-12>length \ transfer length (32bits) 463 /c FIELD read-12>group \ group number 464 /c FIELD read-12>control 465CONSTANT scsi-length-read-12 466 467: scsi-build-read-12 ( block# #blocks cdb -- ) 468 >r ( block# #blocks ) ( R: -- cdb ) 469 r@ scsi-length-read-12 erase \ 12 bytes CDB 470 scsi-cmd-read-12 r@ read-12>operation-code c! ( block# #blocks ) 471 r@ read-12>length l! ( block# ) 472 r@ read-12>block-address l! ( ) 473 scsi-param-control r> read-12>control c! ( R: cdb -- ) 474 scsi-length-read-12 to scsi-param-size \ update CDB length 475; 476 477\ *************************************************************************** 478\ SCSI-Command: READ (16) 479\ Type: Block Command 480\ *************************************************************************** 481\ Forth Word: scsi-build-read-16 ( block# #blocks cdb -- ) 482\ *************************************************************************** 483\ command code 48488 CONSTANT scsi-cmd-read-16 485 486\ CDB structure 487STRUCT 488 /c FIELD read-16>operation-code \ code: 88 489 /c FIELD read-16>protect \ RDPROTECT, DPO, FUA, FUA_NV 490 /x FIELD read-16>block-address \ lba 491 /l FIELD read-16>length \ transfer length (32bits) 492 /c FIELD read-16>group \ group number 493 /c FIELD read-16>control 494CONSTANT scsi-length-read-16 495 496: scsi-build-read-16 ( block# #blocks cdb -- ) 497 >r ( block# #blocks ) ( R: -- cdb ) 498 r@ scsi-length-read-16 erase \ 16 bytes CDB 499 scsi-cmd-read-16 r@ read-16>operation-code c! ( block# #blocks ) 500 r@ read-16>length l! ( block# ) 501 r@ read-16>block-address x! ( ) 502 scsi-param-control r> read-16>control c! ( R: cdb -- ) 503 scsi-length-read-16 to scsi-param-size \ update CDB length 504; 505 506\ *************************************************************************** 507\ SCSI-Command: READ with autodetection of required command 508\ read(10) or read(12) depending on parameter size 509\ (read(6) removed because obsolete in some cases (USB)) 510\ Type: Block Command 511\ *************************************************************************** 512\ Forth Word: scsi-build-read? ( block# #blocks cdb -- ) 513\ 514\ +----------------+---------------------------| 515\ | block# (lba) | #block (transfer-length) | 516\ +-----------+----------------+---------------------------| 517\ | read-6 | 16-Bits | 8 Bits | 518\ | read-10 | 32-Bits | 16 Bits | 519\ | read-12 | 32-Bits | 32 Bits | 520\ *************************************************************************** 521: scsi-build-read? ( block# #blocks cdb -- length ) 522 over ( block# #blocks cdb #blocks ) 523 fffe > \ tx-length (#blocks) exceeds 16-bit limit ? 524 IF 525 scsi-build-read-12 ( block# #blocks cdb -- ) 526 scsi-length-read-12 ( length ) 527 ELSE ( block# #blocks cdb ) 528 scsi-build-read-10 ( block# #blocks cdb -- ) 529 scsi-length-read-10 ( length ) 530 THEN 531; 532 533\ *************************************************************************** 534\ SCSI-Command: WRITE (10) 535\ Type: Block Command 536\ *************************************************************************** 537\ Forth Word: scsi-build-write-10 ( block# #blocks cdb -- ) 538\ *************************************************************************** 539\ command code 5402A CONSTANT scsi-cmd-write-10 541 542\ CDB structure 543STRUCT 544 /c FIELD write-10>operation-code 545 /c FIELD write-10>protect 546 /l FIELD write-10>block-address \ logical block address (32bits) 547 /c FIELD write-10>group 548 /w FIELD write-10>length \ transfer length (16-bits) 549 /c FIELD write-10>control 550CONSTANT scsi-length-write-10 551 552: scsi-build-write-10 ( block# #blocks cdb -- ) 553 >r ( block# #blocks ) ( R: -- cdb ) 554 r@ scsi-length-write-10 erase \ 10 bytes CDB 555 scsi-cmd-write-10 r@ write-10>operation-code c! ( block# #blocks ) 556 r@ write-10>length w! ( block# ) 557 r@ write-10>block-address l! ( ) 558 scsi-param-control r> write-10>control c! ( R: cdb -- ) 559 scsi-length-write-10 to scsi-param-size \ update CDB length 560; 561 562\ *************************************************************************** 563\ SCSI-Command: WRITE (16) 564\ Type: Block Command 565\ *************************************************************************** 566\ Forth Word: scsi-build-write-16 ( block# #blocks cdb -- ) 567\ *************************************************************************** 568\ command code 5698A CONSTANT scsi-cmd-write-16 570 571\ CDB structure 572STRUCT 573 /c FIELD write-16>operation-code 574 /c FIELD write-16>protect \ RDPROTECT, DPO, FUA, FUA_NV 575 /x FIELD write-16>block-address \ LBA 576 /l FIELD write-16>length \ Transfer length (32-bits) 577 /c FIELD write-16>group \ Group number 578 /c FIELD write-16>control 579CONSTANT scsi-length-write-16 580 581: scsi-build-write-16 ( block# #blocks cdb -- ) 582 >r ( block# #blocks ) ( R: -- cdb ) 583 r@ scsi-length-write-16 erase \ 16 bytes CDB 584 scsi-cmd-write-16 r@ write-16>operation-code c! ( block# #blocks ) 585 r@ write-16>length l! ( block# ) 586 r@ write-16>block-address x! ( ) 587 scsi-param-control r> write-16>control c! ( R: cdb -- ) 588 scsi-length-write-16 to scsi-param-size \ update CDB length 589; 590 591\ *************************************************************************** 592\ SCSI-Command: START STOP UNIT 593\ Type: Block Command (SBC-3 clause 5.19) 594\ *************************************************************************** 595\ Forth Word: scsi-build-start-stop-unit ( state# cdb -- ) 596\ *************************************************************************** 597\ command code 5981b CONSTANT scsi-cmd-start-stop-unit 599 600\ CDB structure 601STRUCT 602 /c FIELD start-stop-unit>operation-code 603 /c FIELD start-stop-unit>immed 604 /w FIELD start-stop-unit>reserved 605 /c FIELD start-stop-unit>pow-condition 606 /c FIELD start-stop-unit>control 607CONSTANT scsi-length-start-stop-unit 608 609\ START/STOP constants 610\ (see spec: SBC-3 clause 5.19) 611f1 CONSTANT scsi-const-active-power \ param used for start-stop-unit 612f2 CONSTANT scsi-const-idle-power \ param used for start-stop-unit 613f3 CONSTANT scsi-const-standby-power \ param used for start-stop-unit 6143 CONSTANT scsi-const-load \ param used for start-stop-unit 6152 CONSTANT scsi-const-eject \ param used for start-stop-unit 6161 CONSTANT scsi-const-start 6170 CONSTANT scsi-const-stop 618 619: scsi-build-start-stop-unit ( state# cdb -- ) 620 >r ( state# ) ( R: -- cdb ) 621 r@ scsi-length-start-stop-unit erase \ 6 bytes CDB 622 scsi-cmd-start-stop-unit r@ start-stop-unit>operation-code c! 623 dup 3 > 624 IF 625 4 lshift \ shift to upper nibble 626 THEN ( state ) 627 r@ start-stop-unit>pow-condition c! ( ) 628 scsi-param-control r> start-stop-unit>control c! ( R: cdb -- ) 629 scsi-length-start-stop-unit to scsi-param-size \ update CDB length 630; 631 632\ *************************************************************************** 633\ SCSI-Command: SEEK(10) 634\ Type: Block Command (obsolete) 635\ *************************************************************************** 636\ Forth Word: scsi-build-seek ( state# cdb -- ) 637\ Obsolete function (last listed in spec SBC / Nov. 1997) 638\ implemented only for the sake of completeness 639\ *************************************************************************** 640\ command code 6412b CONSTANT scsi-cmd-seek 642 643\ CDB structure 644STRUCT 645 /c FIELD seek>operation-code 646 /c FIELD seek>reserved1 647 /l FIELD seek>lba 648 3 FIELD seek>reserved2 649 /c FIELD seek>control 650CONSTANT scsi-length-seek 651 652: scsi-build-seek ( lba cdb -- ) 653 >r ( lba ) ( R: -- cdb ) 654 r@ scsi-length-seek erase \ 10 bytes CDB 655 scsi-cmd-seek r@ seek>operation-code c! 656 r> seek>lba l! ( ) ( R: cdb -- ) 657 scsi-length-seek to scsi-param-size \ update CDB length 658; 659 660\ **************************************************************************** 661\ CDROM media event stuff 662\ **************************************************************************** 663 664STRUCT 665 /w FIELD media-event-data-len 666 /c FIELD media-event-nea-class 667 /c FIELD media-event-supp-class 668 /l FIELD media-event-data 669CONSTANT scsi-length-media-event 670 671: scsi-build-get-media-event ( cdb -- ) 672 dup c erase ( cdb ) 673 4a over c! ( cdb ) 674 01 over 1 + c! 675 10 over 4 + c! 676 08 over 8 + c! 677 drop 678; 679 680 681 682\ *************************************************************************** 683\ SCSI-Utility: .sense-code 684\ *************************************************************************** 685\ this utility prints a string associated to the sense code 686\ see specs: SPC-3/r23 clause 4.5.6 687\ *************************************************************************** 688: .sense-text ( scode -- ) 689 case 690 0 OF s" OK" ENDOF 691 1 OF s" RECOVERED ERR" ENDOF 692 2 OF s" NOT READY" ENDOF 693 3 OF s" MEDIUM ERROR" ENDOF 694 4 OF s" HARDWARE ERR" ENDOF 695 5 OF s" ILLEGAL REQUEST" ENDOF 696 6 OF s" UNIT ATTENTION" ENDOF 697 7 OF s" DATA PROTECT" ENDOF 698 8 OF s" BLANK CHECK" ENDOF 699 9 OF s" VENDOR SPECIFIC" ENDOF 700 a OF s" COPY ABORTED" ENDOF 701 b OF s" ABORTED COMMAND" ENDOF 702 d OF s" VOLUME OVERFLOW" ENDOF 703 e OF s" MISCOMPARE" ENDOF 704 dup OF s" UNKNOWN" ENDOF 705 endcase 706 5b emit type 5d emit 707; 708 709\ *************************************************************************** 710\ SCSI-Utility: .status-code 711\ *************************************************************************** 712\ this utility prints a string associated to the status code 713\ see specs: SAM-3/r14 clause 5.3 714\ *************************************************************************** 715: .status-text ( stat -- ) 716 case 717 00 OF s" GOOD" ENDOF 718 02 OF s" CHECK CONDITION" ENDOF 719 04 OF s" CONDITION MET" ENDOF 720 08 OF s" BUSY" ENDOF 721 18 OF s" RESERVATION CONFLICT" ENDOF 722 28 OF s" TASK SET FULL" ENDOF 723 30 OF s" ACA ACTIVE" ENDOF 724 40 OF s" TASK ABORTED" ENDOF 725 dup OF s" UNKNOWN" ENDOF 726 endcase 727 5b emit type 5d emit 728; 729 730\ *************************************************************************** 731\ SCSI-Utility: .capacity-text 732\ *************************************************************************** 733\ utility that shows total capacity on screen by use of the return data 734\ from read-capacity calculation is SI conform (base 10) 735\ *************************************************************************** 736\ sub function to print a 3 digit decimal 737\ number with 2 post decimal positions xxx.yy 738: .dec3-2 ( prenum postnum -- ) 739 swap 740 base @ >r \ save actual base setting 741 decimal \ show decimal values 742 4 .r 2e emit 743 dup 9 <= IF 30 emit THEN .d \ 3 pre-decimal, right aligned 744 r> base ! \ restore base 745; 746 747: .capacity-text ( block-size #blocks -- ) 748 scsi-param-debug \ debugging flag set ? 749 IF \ show additional info 750 2dup 751 cr 752 ." LBAs: " .d \ highest logical block number 753 ." / Block-Size: " .d 754 ." / Total Capacity: " 755 THEN 756 * \ calculate total capacity 757 dup d# 1000000000000 >= \ check terabyte limit 758 IF 759 d# 1000000000000 /mod 760 swap 761 d# 10000000000 / \ limit remainder to two digits 762 .dec3-2 ." TB" \ show terabytes as xxx.yy 763 ELSE 764 dup d# 1000000000 >= \ check gigabyte limit 765 IF 766 d# 1000000000 /mod 767 swap 768 d# 10000000 / 769 .dec3-2 ." GB" \ show gigabytes as xxx.yy 770 ELSE 771 dup d# 1000000 >= 772 IF 773 d# 1000000 /mod \ check mega byte limit 774 swap 775 d# 10000 / 776 .dec3-2 ." MB" \ show megabytes as xxx.yy 777 ELSE 778 dup d# 1000 >= \ check kilo byte limit 779 IF 780 d# 1000 /mod 781 swap 782 d# 10 / 783 .dec3-2 ." kB" 784 ELSE 785 .d ." Bytes" 786 THEN 787 THEN 788 THEN 789 THEN 790; 791 792\ *************************************************************************** 793\ SCSI-Utility: .inquiry-text ( addr -- ) 794\ *************************************************************************** 795\ utility that shows: 796\ vendor-ident product-ident and revision 797\ from an inquiry return data block (addr) 798\ *************************************************************************** 799: .inquiry-text ( addr -- ) 800 22 emit \ enclose text with " 801 dup inquiry-data>vendor-ident 8 type space 802 dup inquiry-data>product-ident 10 type space 803 inquiry-data>product-revision 4 type 804 22 emit 805; 806 807\ *************************************************************************** 808\ SCSI-Utility: scsi-supp-init ( -- ) 809\ *************************************************************************** 810\ utility that helps to ensure that parameters are set to valid values 811: scsi-supp-init ( -- ) 812 false to scsi-param-debug \ no debug strings 813 h# 0 to scsi-param-size 814 h# 0 to scsi-param-control \ common CDB control byte 815 d# 0 to scsi-param-errors \ local errors (param limits) 816; 817 818\ *************************************************************************** 819\ Constants used by SCSI controller's execute-scsi-command 820\ *************************************************************************** 821true CONSTANT scsi-dir-read 822false CONSTANT scsi-dir-write 823 824 825\ *************************************************************************** 826\ scsi loader 827\ *************************************************************************** 8280 VALUE scsi-context \ addr of word list on top 829 830 831\ **************************************************************************** 832\ open scsi-support by adding a new word list on top of search path 833\ precondition: scsi-support.fs must have been included 834\ **************************************************************************** 835: scsi-init ( -- ) 836 also scsi-words \ append scsi word-list 837 context to scsi-context \ save for close process 838 scsi-supp-init \ preset all scsi-param-xxx values 839 scsi-param-debug 840 IF 841 space ." SCSI-SUPPORT OPENED" cr 842 .wordlists 843 THEN 844; 845 846\ **************************************************************************** 847\ close scsi-session and remove scsi word list (if exists) 848\ **************************************************************************** 849\ if 'previous' is used without a preceding 'also' all forth words are lost ! 850\ **************************************************************************** 851: scsi-close ( -- ) 852\ FIXME This only works if scsi-words is the last vocabulary on the stack 853\ Instead we could use get-order to find us on the "wordlist stack", 854\ remove us and write the wordlist stack back with set-order. 855\ BUT: Is this worth the effort? 856 857 scsi-param-debug 858 IF 859 space ." Closing SCSI-SUPPORT .. " cr 860 THEN 861 context scsi-context = \ scsi word list still active ? 862 IF 863 scsi-param-errors 0<> \ any errors occurred ? 864 IF 865 cr ." ** WARNING: " scsi-param-errors .d 866 ." SCSI Errors occurred ** " cr 867 THEN 868 previous \ remove scsi word list on top 869 0 to scsi-context \ prevent from being misinterpreted 870 ELSE 871 cr ." ** WARNING: Trying to close non-open SCSI-SUPPORT (1) ** " cr 872 THEN 873 scsi-param-debug 874 IF 875 .wordlists 876 THEN 877; 878 879 880s" scsi-init" $find drop \ return execution pointer, when included 881 882previous \ remove scsi word list from search path 883definitions \ place next definitions into previous list 884 885