Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / slof / fs / scsi-disk.fs
diff --git a/qemu/roms/SLOF/slof/fs/scsi-disk.fs b/qemu/roms/SLOF/slof/fs/scsi-disk.fs
new file mode 100644 (file)
index 0000000..1978471
--- /dev/null
@@ -0,0 +1,324 @@
+\ *****************************************************************************
+\ * Copyright (c) 2011 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ *     IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ Create new VSCSI child device
+
+\ Create device
+new-device
+
+\ Set name
+s" disk" device-name
+
+s" block" device-type
+
+false VALUE scsi-disk-debug?
+
+\ Get SCSI bits
+scsi-open
+
+\ Send SCSI commands to controller
+
+: execute-scsi-command ( buf-addr buf-len dir cmd-addr cmd-len -- ... )
+                       ( ... [ sense-buf sense-len ] stat )
+    " execute-scsi-command" $call-parent
+;
+
+: retry-scsi-command ( buf-addr buf-len dir cmd-addr cmd-len #retries -- ... )
+                     ( ... 0 | [ sense-buf sense-len ] stat )
+    " retry-scsi-command" $call-parent
+;
+
+\ ---------------------------------\
+\ Common SCSI Commands and helpers \
+\ ---------------------------------\
+
+0 INSTANCE VALUE block-size
+0 INSTANCE VALUE max-transfer
+0 INSTANCE VALUE max-block-num
+0 INSTANCE VALUE is_cdrom
+INSTANCE VARIABLE deblocker
+
+\ This scratch area is made global for now as we only
+\ use it for small temporary commands such as inquiry
+\ read-capacity or media events
+CREATE scratch 100 allot
+CREATE cdb 10 allot
+
+: dump-scsi-error ( sense-buf sense-len stat name namelen -- )
+    ." SCSI-DISK: " my-self instance>path type ." ," type ."  failed" cr
+    ." SCSI-DISK: Status " dup . .status-text
+    0<> IF
+        ."  Sense " scsi-get-sense-data dup . .sense-text
+       ."  ASC " . ." ASCQ " . cr
+    ELSE drop THEN
+;
+
+: read-blocks ( addr block# #blocks -- #read )
+    scsi-disk-debug? IF
+        ." SCSI-DISK: read-blocks " .s cr
+    THEN
+
+    \ Bound check. This should probably be done by deblocker
+    \ but it doesn't at this point so do it here
+    2dup + max-block-num > IF
+        ." SCSI-DISK: Access beyond end of device ! " cr
+       drop
+       dup max-block-num > IF
+         drop drop 0 EXIT
+       THEN
+       dup max-block-num swap -
+    THEN
+
+    dup block-size *                            ( addr block# #blocks len )
+    >r rot r>                                  ( block# #blocks addr len )
+    2swap                                       ( addr len block# #blocks )
+    dup >r
+    cdb scsi-build-read-10                      ( addr len )
+    r> -rot                                     ( #blocks addr len )
+    scsi-dir-read cdb scsi-param-size 10
+    retry-scsi-command
+                                                ( #blocks [ sense-buf sense-len ] stat )
+    dup 0<> IF " read-blocks" dump-scsi-error -65 throw ELSE drop THEN
+;
+
+: (inquiry) ( size -- buffer | NULL )
+    dup cdb scsi-build-inquiry
+    \ 16 retries for inquiry to flush out any UAs
+    scratch swap scsi-dir-read cdb scsi-param-size 10 retry-scsi-command
+    \ Success ?
+    0= IF scratch ELSE 2drop 0 THEN
+;
+
+: inquiry ( -- buffer | NULL )
+    scsi-disk-debug? IF
+       ." SCSI-DISK: inquiry " .s cr
+    THEN
+    d# 36 (inquiry) 0= IF 0 EXIT THEN
+    scratch inquiry-data>add-length c@ 5 +
+    (inquiry)
+;
+
+: read-capacity ( -- blocksize #blocks )
+    \ Now issue the read-capacity command
+    scsi-disk-debug? IF
+        ." SCSI-DISK: read-capacity " .s cr
+    THEN
+    \ Make sure that there are zeros in the buffer in case something goes wrong:
+    scratch 10 erase
+    cdb scsi-build-read-cap-10 scratch scsi-length-read-cap-10-data scsi-dir-read
+    cdb scsi-param-size 1 retry-scsi-command
+    \ Success ?
+    dup 0<> IF " read-capacity" dump-scsi-error 0 0 EXIT THEN
+    drop scratch scsi-get-capacity-10 1 +
+;
+
+100 CONSTANT test-unit-retries
+
+\ SCSI test-unit-read
+: test-unit-ready ( true | [ ascq asc sense-key false ] )
+    scsi-disk-debug? IF
+        ." SCSI-DISK: test-unit-ready " .s cr
+    THEN
+    cdb scsi-build-test-unit-ready
+    0 0 0 cdb scsi-param-size test-unit-retries retry-scsi-command
+    \ stat == 0, return
+    0= IF true EXIT THEN
+    \ check sense len, no sense -> return HW error
+    0= IF drop 0 0 4 false EXIT THEN
+    \ get sense
+    scsi-get-sense-data false
+;
+
+
+: start-stop-unit ( state# -- true | false )
+    scsi-disk-debug? IF
+        ." SCSI-DISK: start-stop-unit " .s cr
+    THEN
+    cdb scsi-build-start-stop-unit
+    0 0 0 cdb scsi-param-size 10 retry-scsi-command
+    \ Success ?
+    0= IF true ELSE 2drop false THEN
+;
+
+: compare-sense ( ascq asc key ascq2 asc2 key2 -- true | false )
+    3 pick =       ( ascq asc key ascq2 asc2 keycmp )
+    swap 4 pick =   ( ascq asc key ascq2 keycmp asccmp )
+    rot 5 pick =    ( ascq asc key keycmp asccmp ascqcmp )
+    and and nip nip nip
+;
+
+\ -------------------------\
+\ CDROM specific functions \
+\ -------------------------\
+
+0 CONSTANT CDROM-READY
+1 CONSTANT CDROM-NOT-READY
+2 CONSTANT CDROM-NO-DISK
+3 CONSTANT CDROM-TRAY-OPEN
+4 CONSTANT CDROM-INIT-REQUIRED
+5 CONSTANT CDROM-TRAY-MAYBE-OPEN
+
+: cdrom-try-close-tray ( -- )
+    scsi-const-load start-stop-unit drop
+;
+
+: cdrom-must-close-tray ( -- )
+    scsi-const-load start-stop-unit not IF
+        ." Tray open !" cr -65 throw
+    THEN
+;
+
+: get-media-event ( -- true | false )
+    scsi-disk-debug? IF
+        ." SCSI-DISK: get-media-event " .s cr
+    THEN
+    cdb scsi-build-get-media-event
+    scratch scsi-length-media-event scsi-dir-read cdb scsi-param-size 1 retry-scsi-command
+    \ Success ?
+    0= IF true ELSE 2drop false THEN
+;
+
+: cdrom-status ( -- status )
+    test-unit-ready
+    IF CDROM-READY EXIT THEN
+
+    scsi-disk-debug? IF
+        ." TestUnitReady sense: " 3dup . . . cr
+    THEN
+
+    3dup 1 4 2 compare-sense IF
+        3drop CDROM-NOT-READY EXIT
+    THEN
+
+    get-media-event IF
+        scratch w@ 4 >= IF
+           scratch 2 + c@ 04 = IF
+               scratch 5 + c@
+               dup 02 and 0<> IF drop 3drop CDROM-READY EXIT THEN
+               dup 01 and 0<> IF drop 3drop CDROM-TRAY-OPEN EXIT THEN
+               drop 3drop CDROM-NO-DISK EXIT
+           THEN
+       THEN
+    THEN
+
+    3dup 2 4 2 compare-sense IF
+        3drop CDROM-INIT-REQUIRED EXIT
+    THEN
+    over 4 = over 2 = and IF
+        \ Format in progress... what do we do ? Just ignore
+       3drop CDROM-READY EXIT
+    THEN
+    over 3a = IF
+        3drop CDROM-NO-DISK EXIT
+    THEN
+
+    \ Other error...
+    3drop CDROM-TRAY-MAYBE-OPEN
+;
+
+: prep-cdrom ( -- ready? )
+    5 0 DO
+        cdrom-status CASE
+           CDROM-READY           OF UNLOOP true EXIT ENDOF
+           CDROM-NO-DISK         OF ." No medium !" cr UNLOOP false EXIT ENDOF
+           CDROM-TRAY-OPEN       OF cdrom-must-close-tray ENDOF
+           CDROM-INIT-REQUIRED   OF cdrom-try-close-tray ENDOF
+           CDROM-TRAY-MAYBE-OPEN OF cdrom-try-close-tray ENDOF
+       ENDCASE
+       d# 1000 ms
+    LOOP
+    ." Drive not ready !" cr false
+;
+
+\ ------------------------\
+\ Disk specific functions \
+\ ------------------------\
+
+: prep-disk ( -- ready? )
+    test-unit-ready not IF
+        ." SCSI-DISK: Disk not ready ! "
+        ." Sense " dup .sense-text ." [" . ." ]"
+       ."  ASC " . ."  ASCQ " . cr
+       false EXIT THEN true
+;
+
+\ --------------------------\
+\ Standard device interface \
+\ --------------------------\
+
+: open ( -- true | false )
+    scsi-disk-debug? IF
+        ." SCSI-DISK: open [" .s ." ] unit is " my-unit . . ."  [" .s ." ]" cr
+    THEN
+    my-unit " set-address" $call-parent
+
+    inquiry dup 0= IF drop false EXIT THEN
+    scsi-disk-debug? IF
+        ." ---- inquiry: ----" cr
+        dup 100 dump cr
+        ." ------------------" cr
+    THEN
+
+    \ Skip devices with PQ != 0
+    dup inquiry-data>peripheral c@ e0 and 0 <> IF
+        ." SCSI-DISK: Unsupported PQ != 0" cr
+       false EXIT
+    THEN
+
+    inquiry-data>peripheral c@ CASE
+        5   OF true to is_cdrom ENDOF
+        7   OF true to is_cdrom ENDOF
+    ENDCASE
+
+    scsi-disk-debug? IF
+        is_cdrom IF
+            ." SCSI-DISK: device treated as CD-ROM" cr
+        ELSE
+            ." SCSI-DISK: device treated as disk" cr
+        THEN
+    THEN
+
+    is_cdrom IF prep-cdrom ELSE prep-disk THEN
+    not IF false EXIT THEN
+
+    " max-transfer" $call-parent to max-transfer
+
+    read-capacity to max-block-num to block-size
+    max-block-num 0= block-size 0= OR IF
+       ." SCSI-DISK: Failed to get disk capacity!" cr
+       FALSE EXIT
+    THEN
+
+    scsi-disk-debug? IF
+        ." Capacity: " max-block-num . ." blocks of " block-size . cr
+    THEN
+
+    0 0 " deblocker" $open-package dup deblocker ! dup IF 
+        " disk-label" find-package IF
+            my-args rot interpose
+        THEN
+   THEN 0<>
+;
+
+: close ( -- )
+    deblocker @ close-package ;
+
+: seek ( pos.lo pos.hi -- status )
+    s" seek" deblocker @ $call-method ;
+
+: read ( addr len -- actual )
+    s" read" deblocker @ $call-method ;
+
+\ Get rid of SCSI bits
+scsi-close
+
+finish-device