Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / slof / fs / scsi-host-helpers.fs
diff --git a/qemu/roms/SLOF/slof/fs/scsi-host-helpers.fs b/qemu/roms/SLOF/slof/fs/scsi-host-helpers.fs
new file mode 100644 (file)
index 0000000..579ce37
--- /dev/null
@@ -0,0 +1,127 @@
+\ This file is meant to be included by SCSI hosts to provide
+\ helpers such as retry-scsi-command
+
+\ Returns 1 for retry, 0 for return with no error and
+\ -1 for return with an error
+\
+: check-retry-sense? ( sense-buf sense-len -- retry? )
+    \ Check if the sense-len is at least 8 bytes
+    8 < IF -1 EXIT THEN
+
+    \ Fixed sense record, look for filemark etc...
+    dup sense-data>response-code c@ 7e and 70 = IF
+        dup sense-data>sense-key c@ e0 and IF drop -1 EXIT THEN
+    THEN
+
+    \ Get sense data
+    scsi-get-sense-data? IF    ( ascq asc sense-key )
+        \ No sense or recoverable, return success
+       dup 2 < IF 3drop 0 EXIT THEN
+       \ not ready and unit attention, retry
+       dup 2 = swap 6 = or nip nip IF 1 EXIT THEN
+    THEN
+    \ Return failure
+    -1
+;
+
+\ This is almost as the standard retry-command but returns
+\ additionally the length of the returned sense information
+\
+\ The hw-err? field is gone, stat is -1 for a HW error, and
+\ the sense data is provided iff stat is CHECK_CONDITION (02)
+\
+\ Additionally we wait 10ms between retries
+\
+0 INSTANCE VALUE rcmd-buf-addr
+0 INSTANCE VALUE rcmd-buf-len
+0 INSTANCE VALUE rcmd-dir
+0 INSTANCE VALUE rcmd-cmd-addr
+0 INSTANCE VALUE rcmd-cmd-len
+
+: retry-scsi-command ( buf-addr buf-len dir cmd-addr cmd-len #retries -- ... )
+                     ( ... 0 | [ sense-buf sense-len ] stat )
+    >r \ stash #retries
+    to rcmd-cmd-len to rcmd-cmd-addr to rcmd-dir to rcmd-buf-len to rcmd-buf-addr
+    0  \ dummy status & sense
+    r> \ retreive #retries              ( stat #retries )
+    0 DO
+        \ drop previous status & sense
+        0<> IF 2drop THEN
+
+       \ Restore arguments
+       rcmd-buf-addr
+       rcmd-buf-len
+       rcmd-dir
+       rcmd-cmd-addr
+       rcmd-cmd-len
+
+       \ Send command
+       execute-scsi-command            ( [ sense-buf sense-len ] stat )
+
+       \ Success ?
+       dup 0= IF LEAVE THEN
+
+       \ HW error ?
+       dup -1 = IF LEAVE THEN
+
+       \ Check condition ?
+       dup 2 = IF                      ( sense-buf sense-len stat )
+           >r  \ stash stat            ( sense-buf sense len )
+           2dup
+           check-retry-sense?          ( sense-buf sense-len retry? )
+           r> swap \ unstash stat      ( sense-buf sense-len stat retry? )
+           \ Check retry? result
+           CASE
+                0 OF 3drop 0 LEAVE ENDOF       \ Swallow error, return 0
+               -1 OF LEAVE ENDOF               \ No retry
+           ENDCASE
+        ELSE \ Anything other than busy -> exit
+            dup 8 <> IF LEAVE THEN
+       THEN
+       a ms
+    LOOP
+;
+
+\ -----------------------------------------------------------
+\ Some command helpers
+\ -----------------------------------------------------------
+\
+\ TODO: Get rid of global "sector" and instead return an
+\ allocated block for the caller to free
+
+CREATE sector d# 512 allot
+CREATE cdb 10 allot
+
+: (inquiry) ( size -- buffer | NULL )
+    dup cdb scsi-build-inquiry
+    \ 16 retries for inquiry to flush out any UAs
+    sector swap scsi-dir-read cdb scsi-param-size 10 retry-scsi-command
+    \ Success ?
+    0= IF sector ELSE 2drop 0 THEN
+;
+
+\ Read the initial 36bytes and then decide how much more is to be read
+: inquiry ( -- buffer | NULL )
+    d# 36 (inquiry) 0= IF 0 EXIT THEN
+    sector inquiry-data>add-length c@ 5 +
+    (inquiry)
+;
+
+: report-luns ( -- [ sector ] true | false )
+    200 cdb scsi-build-report-luns
+    \ 16 retries to flush out any UAs
+    sector 200 scsi-dir-read cdb scsi-param-size 10 retry-scsi-command
+    \ Success ?
+    0= IF sector true ELSE drop false THEN
+;
+
+\ This routine creates a disk alias for the first found disk/cdrom
+: make-disk-alias                               ( $name srplun -- )
+    >r 2dup r> -rot                             ( $name srplun $name)
+    find-alias 0<> IF 4drop exit THEN
+    get-node node>path
+    20 allot
+    " /disk@" string-cat                        ( $name srplun npath npathl )
+    rot base @ >r hex (u.) r> base ! string-cat ( $name $diskpath )
+    set-alias
+;