~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/SLOF/slof/fs/scsi-support.fs

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 (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
 
426
28 CONSTANT scsi-cmd-read-10
 
427
 
 
428
\ CDB structure
 
429
STRUCT
 
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
 
436
CONSTANT 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
 
455
a8 CONSTANT scsi-cmd-read-12
 
456
 
 
457
\ CDB structure
 
458
STRUCT
 
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
 
465
CONSTANT 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
 
484
88 CONSTANT scsi-cmd-read-16
 
485
 
 
486
\ CDB structure
 
487
STRUCT
 
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
 
494
CONSTANT 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
 
540
2A CONSTANT scsi-cmd-write-10
 
541
 
 
542
\ CDB structure
 
543
STRUCT
 
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
 
550
CONSTANT 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
 
569
8A CONSTANT scsi-cmd-write-16
 
570
 
 
571
\ CDB structure
 
572
STRUCT
 
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
 
579
CONSTANT 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
 
598
1b CONSTANT scsi-cmd-start-stop-unit
 
599
 
 
600
\ CDB structure
 
601
STRUCT
 
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
 
607
CONSTANT scsi-length-start-stop-unit
 
608
 
 
609
\ START/STOP constants
 
610
\ (see spec: SBC-3 clause 5.19)
 
611
f1 CONSTANT scsi-const-active-power    \ param used for start-stop-unit
 
612
f2 CONSTANT scsi-const-idle-power      \ param used for start-stop-unit
 
613
f3 CONSTANT scsi-const-standby-power   \ param used for start-stop-unit
 
614
3  CONSTANT scsi-const-load            \ param used for start-stop-unit
 
615
2  CONSTANT scsi-const-eject           \ param used for start-stop-unit
 
616
1  CONSTANT scsi-const-start
 
617
0  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
 
641
2b CONSTANT scsi-cmd-seek
 
642
 
 
643
\ CDB structure
 
644
STRUCT
 
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
 
650
CONSTANT 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
 
 
664
STRUCT
 
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
 
669
CONSTANT 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
\ ***************************************************************************
 
821
true  CONSTANT scsi-dir-read
 
822
false CONSTANT scsi-dir-write
 
823
 
 
824
 
 
825
\ ***************************************************************************
 
826
\ scsi loader
 
827
\ ***************************************************************************
 
828
0 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
 
 
880
s" scsi-init" $find drop               \ return execution pointer, when included
 
881
 
 
882
previous                               \ remove scsi word list from search path
 
883
definitions                            \ place next definitions into previous list
 
884