Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / slof / fs / scsi-support.fs
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 \ ************************************************
16 vocabulary scsi-words                  \ create new word list named 'scsi-words'
17 also 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'
22 false  value   scsi-param-debug        \ common debugging flag
23 d# 0   value   scsi-param-size         \ length of CDB processed last
24 h# 0   value   scsi-param-control      \ control word for CDBs as defined in SAM-4
25 d# 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:
41 00 CONSTANT scsi-cmd-test-unit-ready
42 \ CDB structure:
43 STRUCT
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
47 CONSTANT 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:
66 a0 CONSTANT scsi-cmd-report-luns
67 \ CDB structure:
68 STRUCT
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
76 CONSTANT 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:
99 03 CONSTANT scsi-cmd-request-sense
100 \ CDB structure:
101 STRUCT
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
106 CONSTANT 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 \ ----------------------------------------
133 70 CONSTANT scsi-response(request-sense-0)
134 71 CONSTANT scsi-response(request-sense-1)
135
136 STRUCT
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
148 CONSTANT 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:
213 12 CONSTANT scsi-cmd-inquiry
214
215 \ CDB structure
216 STRUCT
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
222 CONSTANT 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 \ ----------------------------------------
237 STRUCT
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
251 CONSTANT 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 \ ***************************************************************************
259 25 CONSTANT scsi-cmd-read-capacity-10  \ command code
260
261 STRUCT                                 \ 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
268 CONSTANT 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
288 STRUCT
289         /l      FIELD read-cap-10-data>max-lba
290         /l      FIELD read-cap-10-data>block-size
291 CONSTANT 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 \ ***************************************************************************
306 9e CONSTANT scsi-cmd-read-capacity-16        \ command code
307
308 STRUCT                                       \ 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
316 CONSTANT 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
339 STRUCT
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
347 CONSTANT 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 \ ***************************************************************************
364 5a CONSTANT scsi-cmd-mode-sense-10
365
366 \ CDB structure
367 STRUCT
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
375 CONSTANT 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
394 STRUCT
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
401 CONSTANT 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 (6)
421 \         Type: Block Command (SBC-3 clause 5.7)
422 \ ***************************************************************************
423 \ Forth Word:   scsi-build-read-6  ( block# #blocks cdb -- )
424 \ ***************************************************************************
425 \ this SCSI command uses 21 bits to represent start LBA
426 \ and 8 bits to specify the numbers of blocks to read
427 \ The value of 0 blocks is interpreted as 256 blocks
428 \
429 \ command code
430 08 CONSTANT scsi-cmd-read-6
431
432 \ CDB structure
433 STRUCT
434    /c FIELD read-6>operation-code      \ 08h
435    /c FIELD read-6>block-address-msb   \ upper 5 bits
436    /w FIELD read-6>block-address       \ lower 16 bits
437    /c FIELD read-6>length              \ number of blocks to read
438    /c FIELD read-6>control             \ CDB control
439 CONSTANT scsi-length-read-6
440
441 : scsi-build-read-6                    ( block# #blocks cdb -- )
442    >r                                  ( block# #blocks ) ( R: -- cdb )
443    r@ scsi-length-read-6 erase         \ 6 bytes CDB
444         scsi-cmd-read-6 r@ read-6>operation-code c! ( block# #blocks )
445
446    \ check block count to read (#blocks)
447    dup d# 255 >                        \ #blocks exceeded limit ?
448    IF
449       scsi-inc-errors
450       drop 1                           \ replace with any valid number
451    THEN
452    r@ read-6>length c!                 \ set #blocks to read
453
454    \ check starting block number (block#)
455    dup 1fffff >                        \ check address upper limit
456    IF
457       scsi-inc-errors
458       drop                             \ remove original block#
459       1fffff                           \ replace with any valid address
460    THEN
461    dup d# 16 rshift
462    r@ read-6>block-address-msb c!      \ set upper 5 bits
463    ffff and
464    r@ read-6>block-address w!                \ set lower 16 bits
465    scsi-param-control r> read-6>control c!   ( R: cdb -- )
466    scsi-length-read-6 to scsi-param-size     \ update CDB length
467 ;
468
469 \ ***************************************************************************
470 \ SCSI-Command: READ (10)
471 \         Type: Block Command (SBC-3 clause 5.8)
472 \ ***************************************************************************
473 \ Forth Word:   scsi-build-read-10  ( block# #blocks cdb -- )
474 \ ***************************************************************************
475 \ command code
476 28 CONSTANT scsi-cmd-read-10
477
478 \ CDB structure
479 STRUCT
480    /c FIELD read-10>operation-code
481    /c FIELD read-10>protect
482    /l FIELD read-10>block-address      \ logical block address (32bits)
483    /c FIELD read-10>group
484    /w FIELD read-10>length             \ transfer length (16-bits)
485    /c FIELD read-10>control
486 CONSTANT scsi-length-read-10
487
488 : scsi-build-read-10                         ( block# #blocks cdb -- )
489    >r                                        ( block# #blocks )  ( R: -- cdb )
490    r@ scsi-length-read-10 erase             \ 10 bytes CDB
491         scsi-cmd-read-10 r@ read-10>operation-code c! ( block# #blocks )
492    r@ read-10>length w!                      ( block# )
493    r@ read-10>block-address l!               (  )
494    scsi-param-control r> read-10>control c!  ( R: cdb -- )
495    scsi-length-read-10 to scsi-param-size    \ update CDB length
496 ;
497
498 \ ***************************************************************************
499 \ SCSI-Command: READ (12)
500 \         Type: Block Command (SBC-3 clause 5.9)
501 \ ***************************************************************************
502 \ Forth Word:   scsi-build-read-12  ( block# #blocks cdb -- )
503 \ ***************************************************************************
504 \ command code
505 a8 CONSTANT scsi-cmd-read-12
506
507 \ CDB structure
508 STRUCT
509    /c FIELD read-12>operation-code     \ code: a8
510    /c FIELD read-12>protect            \ RDPROTECT, DPO, FUA, FUA_NV
511    /l FIELD read-12>block-address      \ lba
512    /l FIELD read-12>length             \ transfer length (32bits)
513    /c FIELD read-12>group              \ group number
514    /c FIELD read-12>control
515 CONSTANT scsi-length-read-12
516
517 : scsi-build-read-12                         ( block# #blocks cdb -- )
518    >r                                        ( block# #blocks )  ( R: -- cdb )
519    r@ scsi-length-read-12 erase             \ 12 bytes CDB
520         scsi-cmd-read-12 r@ read-12>operation-code c! ( block# #blocks )
521    r@ read-12>length l!                      ( block# )
522    r@ read-12>block-address l!               (  )
523    scsi-param-control r> read-12>control c!  ( R: cdb -- )
524    scsi-length-read-12 to scsi-param-size    \ update CDB length
525 ;
526
527 \ ***************************************************************************
528 \ SCSI-Command: READ with autodetection of required command
529 \               read(10) or read(12) depending on parameter size
530 \               (read(6) removed because obsolete in some cases (USB))
531 \         Type: Block Command
532 \ ***************************************************************************
533 \ Forth Word:   scsi-build-read?    ( block# #blocks cdb -- )
534 \
535 \                         +----------------+---------------------------|
536 \                         |  block# (lba)  |  #block (transfer-length) |
537 \             +-----------+----------------+---------------------------|
538 \             | read-6    |  16-Bits       |  8  Bits                  |
539 \             | read-10   |  32-Bits       |  16 Bits                  |
540 \             | read-12   |  32-Bits       |  32 Bits                  |
541 \ ***************************************************************************
542 : scsi-build-read?   ( block# #blocks cdb -- length )
543    over              ( block# #blocks cdb #blocks )
544    fffe >            \ tx-length (#blocks) exceeds 16-bit limit ?
545    IF
546       scsi-build-read-12   ( block# #blocks cdb -- )
547       scsi-length-read-12  ( length )
548    ELSE                    ( block# #blocks cdb )
549       scsi-build-read-10   ( block# #blocks cdb -- )
550       scsi-length-read-10  ( length )
551    THEN
552 ;
553
554 \ ***************************************************************************
555 \ SCSI-Command: START STOP UNIT
556 \         Type: Block Command (SBC-3 clause 5.19)
557 \ ***************************************************************************
558 \ Forth Word:   scsi-build-start-stop-unit  ( state# cdb -- )
559 \ ***************************************************************************
560 \ command code
561 1b CONSTANT scsi-cmd-start-stop-unit
562
563 \ CDB structure
564 STRUCT
565    /c FIELD start-stop-unit>operation-code
566    /c FIELD start-stop-unit>immed
567    /w FIELD start-stop-unit>reserved
568    /c FIELD start-stop-unit>pow-condition
569    /c FIELD start-stop-unit>control
570 CONSTANT scsi-length-start-stop-unit
571
572 \ START/STOP constants
573 \ (see spec: SBC-3 clause 5.19)
574 f1 CONSTANT scsi-const-active-power    \ param used for start-stop-unit
575 f2 CONSTANT scsi-const-idle-power      \ param used for start-stop-unit
576 f3 CONSTANT scsi-const-standby-power   \ param used for start-stop-unit
577 3  CONSTANT scsi-const-load            \ param used for start-stop-unit
578 2  CONSTANT scsi-const-eject           \ param used for start-stop-unit
579 1  CONSTANT scsi-const-start
580 0  CONSTANT scsi-const-stop
581
582 : scsi-build-start-stop-unit                 ( state# cdb -- )
583    >r                                        ( state# )  ( R: -- cdb )
584    r@ scsi-length-start-stop-unit erase      \ 6 bytes CDB
585         scsi-cmd-start-stop-unit r@ start-stop-unit>operation-code c!
586    dup 3 >
587    IF
588       4 lshift                         \ shift to upper nibble
589    THEN                                ( state )
590    r@ start-stop-unit>pow-condition c!       (  )
591    scsi-param-control r> start-stop-unit>control c!  ( R: cdb -- )
592    scsi-length-start-stop-unit to scsi-param-size  \ update CDB length
593 ;
594
595 \ ***************************************************************************
596 \ SCSI-Command: SEEK(10)
597 \         Type: Block Command (obsolete)
598 \ ***************************************************************************
599 \ Forth Word:   scsi-build-seek  ( state# cdb -- )
600 \ Obsolete function (last listed in spec SBC / Nov. 1997)
601 \ implemented only for the sake of completeness
602 \ ***************************************************************************
603 \ command code
604 2b CONSTANT scsi-cmd-seek
605
606 \ CDB structure
607 STRUCT
608    /c FIELD seek>operation-code
609    /c FIELD seek>reserved1
610    /l FIELD seek>lba
611    3  FIELD seek>reserved2
612    /c FIELD seek>control
613 CONSTANT scsi-length-seek
614
615 : scsi-build-seek  ( lba cdb -- )
616    >r              ( lba )  ( R: -- cdb )
617    r@ scsi-length-seek erase           \ 10 bytes CDB
618         scsi-cmd-seek r@ seek>operation-code c!
619    r> seek>lba l!  (  )  ( R: cdb -- )
620    scsi-length-seek to scsi-param-size \ update CDB length
621 ;
622
623 \ ****************************************************************************
624 \ CDROM media event stuff
625 \ ****************************************************************************
626
627 STRUCT
628     /w FIELD media-event-data-len
629     /c FIELD media-event-nea-class
630     /c FIELD media-event-supp-class
631     /l FIELD media-event-data
632 CONSTANT scsi-length-media-event
633
634 : scsi-build-get-media-event                     ( cdb -- )
635    dup c erase                                   ( cdb )
636    4a over c!                                    ( cdb )
637    01 over 1 + c!
638    10 over 4 + c!
639    08 over 8 + c!
640    drop
641 ;
642
643
644
645 \ ***************************************************************************
646 \ SCSI-Utility: .sense-code
647 \ ***************************************************************************
648 \ this utility prints a string associated to the sense code
649 \ see specs: SPC-3/r23 clause 4.5.6
650 \ ***************************************************************************
651 : .sense-text ( scode -- )
652    case
653       0    OF s" OK"               ENDOF
654       1    OF s" RECOVERED ERR"    ENDOF
655       2    OF s" NOT READY"        ENDOF
656       3    OF s" MEDIUM ERROR"     ENDOF
657       4    OF s" HARDWARE ERR"     ENDOF
658       5    OF s" ILLEGAL REQUEST"  ENDOF
659       6    OF s" UNIT ATTENTION"   ENDOF
660       7    OF s" DATA PROTECT"     ENDOF
661       8    OF s" BLANK CHECK"      ENDOF
662       9    OF s" VENDOR SPECIFIC"  ENDOF
663       a    OF s" COPY ABORTED"     ENDOF
664       b    OF s" ABORTED COMMAND"  ENDOF
665       d    OF s" VOLUME OVERFLOW"  ENDOF
666       e    OF s" MISCOMPARE"       ENDOF
667       dup  OF s" UNKNOWN"          ENDOF
668    endcase
669    5b emit type 5d emit
670 ;
671
672 \ ***************************************************************************
673 \ SCSI-Utility: .status-code
674 \ ***************************************************************************
675 \ this utility prints a string associated to the status code
676 \ see specs: SAM-3/r14 clause 5.3
677 \ ***************************************************************************
678 : .status-text  ( stat -- )
679    case
680       00  OF s" GOOD"                  ENDOF
681       02  OF s" CHECK CONDITION"       ENDOF
682       04  OF s" CONDITION MET"         ENDOF
683       08  OF s" BUSY"                  ENDOF
684       18  OF s" RESERVATION CONFLICT"  ENDOF
685       28  OF s" TASK SET FULL"         ENDOF
686       30  OF s" ACA ACTIVE"            ENDOF
687       40  OF s" TASK ABORTED"          ENDOF
688       dup OF s" UNKNOWN"               ENDOF
689    endcase
690    5b emit type 5d emit
691 ;
692
693 \ ***************************************************************************
694 \ SCSI-Utility: .capacity-text
695 \ ***************************************************************************
696 \ utility that shows total capacity on screen by use of the return data
697 \ from read-capacity calculation is SI conform (base 10)
698 \ ***************************************************************************
699 \ sub function to print a 3 digit decimal
700 \ number with 2 post decimal positions xxx.yy
701 : .dec3-2 ( prenum postnum -- )
702    swap
703    base @ >r                           \ save actual base setting
704    decimal                             \ show decimal values
705    4 .r 2e emit
706    dup 9 <= IF 30 emit THEN .d         \ 3 pre-decimal, right aligned
707    r> base !                           \ restore base
708 ;
709
710 : .capacity-text  ( block-size #blocks -- )
711    scsi-param-debug                    \ debugging flag set ?
712    IF                                  \ show additional info
713       2dup
714       cr
715       ." LBAs: " .d                    \ highest logical block number
716       ." / Block-Size: " .d
717       ." / Total Capacity: "
718    THEN
719    *                                   \ calculate total capacity
720    dup d# 1000000000000 >=             \ check terabyte limit
721    IF
722       d# 1000000000000 /mod
723       swap
724       d# 10000000000 /                 \ limit remainder to two digits
725       .dec3-2 ." TB"                   \ show terabytes as xxx.yy
726    ELSE
727       dup d# 1000000000 >=             \ check gigabyte limit
728       IF
729          d# 1000000000 /mod
730          swap
731          d# 10000000 /
732          .dec3-2 ." GB"                \ show gigabytes as xxx.yy
733       ELSE
734          dup d# 1000000 >=
735          IF
736             d# 1000000 /mod            \ check mega byte limit
737             swap
738             d# 10000 /
739             .dec3-2 ." MB"             \ show megabytes as xxx.yy
740          ELSE
741             dup d# 1000 >=             \ check kilo byte limit
742             IF
743                d# 1000 /mod
744                swap
745                d# 10 /
746                .dec3-2 ." kB"
747             ELSE
748                .d ."  Bytes"
749             THEN
750          THEN
751       THEN
752    THEN
753 ;
754
755 \ ***************************************************************************
756 \ SCSI-Utility: .inquiry-text  ( addr -- )
757 \ ***************************************************************************
758 \ utility that shows:
759 \     vendor-ident product-ident and revision
760 \ from an inquiry return data block (addr)
761 \ ***************************************************************************
762 : .inquiry-text  ( addr -- )
763    22 emit     \ enclose text with "
764    dup inquiry-data>vendor-ident      8 type space
765    dup inquiry-data>product-ident    10 type space
766        inquiry-data>product-revision  4 type
767    22 emit
768 ;
769
770 \ ***************************************************************************
771 \ SCSI-Utility: scsi-supp-init  ( -- )
772 \ ***************************************************************************
773 \ utility that helps to ensure that parameters are set to valid values
774 : scsi-supp-init  ( -- )
775    false   to scsi-param-debug         \ no debug strings
776    h# 0   to scsi-param-size
777    h# 0   to scsi-param-control        \ common CDB control byte
778    d# 0   to scsi-param-errors         \ local errors (param limits)
779 ;
780
781 \ ***************************************************************************
782 \ Constants used by SCSI controller's execute-scsi-command
783 \ ***************************************************************************
784 true  CONSTANT scsi-dir-read
785 false CONSTANT scsi-dir-write
786
787
788 \ ***************************************************************************
789 \ scsi loader
790 \ ***************************************************************************
791 0 VALUE scsi-context                   \ addr of word list on top
792
793
794 \ ****************************************************************************
795 \ open scsi-support by adding a new word list on top of search path
796 \   precondition: scsi-support.fs must have been included
797 \ ****************************************************************************
798 : scsi-init  ( -- )
799    also scsi-words                     \ append scsi word-list
800    context  to scsi-context            \ save for close process
801    scsi-supp-init                      \ preset all scsi-param-xxx values
802    scsi-param-debug
803    IF
804       space ." SCSI-SUPPORT OPENED" cr
805       .wordlists
806    THEN
807 ;
808
809 \ ****************************************************************************
810 \ close scsi-session and remove scsi word list (if exists)
811 \ ****************************************************************************
812 \ if 'previous' is used without a preceding 'also' all forth words are lost !
813 \ ****************************************************************************
814 : scsi-close  ( -- )
815 \ FIXME This only works if scsi-words is the last vocabulary on the stack
816 \       Instead we could use get-order to find us on the "wordlist stack",
817 \       remove us and write the wordlist stack back with set-order.
818 \       BUT: Is this worth the effort?
819
820    scsi-param-debug
821    IF
822       space ." Closing SCSI-SUPPORT .. " cr
823    THEN
824    context scsi-context =              \ scsi word list still active ?
825    IF
826       scsi-param-errors 0<>          \ any errors occurred ?
827       IF
828          cr ." ** WARNING: " scsi-param-errors .d
829          ." SCSI Errors occurred ** " cr
830       THEN
831       previous                         \ remove scsi word list on top
832       0 to scsi-context                \ prevent from being misinterpreted
833    ELSE
834       cr ." ** WARNING: Trying to close non-open SCSI-SUPPORT (1) ** " cr
835    THEN
836    scsi-param-debug
837    IF
838      .wordlists
839    THEN
840 ;
841
842
843 s" scsi-init" $find drop               \ return execution pointer, when included
844
845 previous                               \ remove scsi word list from search path
846 definitions                            \ place next definitions into previous list
847