Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / board-qemu / slof / virtio-scsi.fs
diff --git a/qemu/roms/SLOF/board-qemu/slof/virtio-scsi.fs b/qemu/roms/SLOF/board-qemu/slof/virtio-scsi.fs
new file mode 100644 (file)
index 0000000..ca5fb13
--- /dev/null
@@ -0,0 +1,232 @@
+\ *****************************************************************************
+\ * Copyright (c) 2012 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
+\ ****************************************************************************/
+
+." Populating " pwd cr
+
+FALSE CONSTANT virtio-scsi-debug
+
+2 encode-int s" #address-cells" property
+0 encode-int s" #size-cells" property
+
+: decode-unit 2 hex64-decode-unit ;
+: encode-unit 2 hex64-encode-unit ;
+
+FALSE VALUE initialized?
+
+/vd-len BUFFER: virtiodev
+virtiodev virtio-setup-vd
+
+STRUCT \ virtio-scsi-config
+    /l FIELD vs-cfg>num-queues
+    /l FIELD vs-cfg>seg-max
+    /l FIELD vs-cfg>max-sectors
+    /l FIELD vs-cfg>cmd-per-lun
+    /l FIELD vs-cfg>event-info-size
+    /l FIELD vs-cfg>sense_size
+    /l FIELD vs-cfg>cdb-size
+    /w FIELD vs-cfg>max-channel
+    /w FIELD vs-cfg>max-target
+    /l FIELD vs-cfg>max-lun
+CONSTANT vs-cfg-length
+
+STRUCT \ virtio-scsi-req
+    8  FIELD vs-req>lun
+    8  FIELD vs-req>tag
+    /c FIELD vs-req>task-attr
+    /c FIELD vs-req>prio
+    /c FIELD vs-req>crn
+    20 FIELD vs-req>cdb
+CONSTANT vs-req-length
+
+STRUCT \ virtio-scsi-resp
+    /l FIELD vs-rsp>sense-len
+    /l FIELD vs-rsp>residual
+    /w FIELD vs-rsp>status-qualifier
+    /c FIELD vs-rsp>status
+    /c FIELD vs-rsp>response
+    60 FIELD vs-rsp>sense
+CONSTANT vs-rsp-length
+
+CREATE vs-req vs-req-length allot
+CREATE vs-rsp vs-rsp-length allot
+
+scsi-open
+
+\ -----------------------------------------------------------
+\ Perform SCSI commands
+\ -----------------------------------------------------------
+
+0 INSTANCE VALUE current-target
+
+\ SCSI command. We do *NOT* implement the "standard" execute-command
+\ because that doesn't have a way to return the sense buffer back, and
+\ we do have auto-sense with some hosts. Instead we implement a made-up
+\ do-scsi-command.
+\
+\ Note: stat is -1 for "hw error" (ie, error queuing the command or
+\ getting the response).
+\
+\ A sense buffer is returned whenever the status is non-0 however
+\ if sense-len is 0 then no sense data is actually present
+\
+
+: execute-scsi-command ( buf-addr buf-len dir cmd-addr cmd-len -- ... )
+                       ( ... [ sense-buf sense-len ] stat )
+    \ Cleanup virtio request and response
+    vs-req vs-req-length erase
+    vs-rsp vs-rsp-length erase
+
+    \ Populate the request
+    current-target vs-req vs-req>lun x!
+    vs-req vs-req>cdb swap move
+
+    \ Send it
+    vs-req vs-rsp virtiodev
+    virtio-scsi-send
+
+    0 <> IF
+        ." VIRTIO-SCSI: Queuing failure !" cr
+        0 0 -1 EXIT
+    THEN
+
+    \ Check virtio response
+    vs-rsp vs-rsp>response c@ CASE
+        0 OF ENDOF                     \ Good
+        5 OF drop 0 0 8 EXIT ENDOF     \ Busy
+        dup OF 0 0 -1 EXIT ENDOF       \ Anything else -> HW error
+    ENDCASE
+
+    \ Other error status
+    vs-rsp vs-rsp>status c@ dup 0<> IF
+        vs-rsp vs-rsp>sense-len l@ dup 0= IF
+            \ This relies on auto-sense from qemu... if that isn't always the
+            \ case we should request sense here
+            ." VIRTIO-SCSI: No sense data" cr
+           0 EXIT
+        THEN
+        vs-rsp vs-rsp>sense swap
+        virtio-scsi-debug IF
+            over scsi-get-sense-data
+            ." VIRTIO-SCSI: Sense key [ " dup . ." ] " .sense-text
+           ."  ASC,ASCQ: " . . cr
+        THEN
+       rot
+    THEN    
+;
+
+\ --------------------------------
+\ Include the generic host helpers
+\ --------------------------------
+
+" scsi-host-helpers.fs" included
+
+\ FIXME: Check max transfer coming from virtio config
+: max-transfer ( -- n )
+    10000 \ Larger value seem to have problems with some CDROMs
+;
+
+\ -----------------------------------------------------------
+\ SCSI scan at boot and child device support
+\ -----------------------------------------------------------
+
+\ We use SRP luns of the form 01000000 | (target << 16) | lun
+\ in the top 32 bits of the 64-bit LUN
+: (set-target)
+    to current-target
+;
+
+: dev-generate-srplun ( target lun-id -- srplun )
+    swap 0100 or 10 << or 20 <<
+;
+
+\ We obtain here a unit address on the stack, since our #address-cells
+\ is 2, the 64-bit srplun is split in two cells that we need to join
+\
+\ Note: This diverges a bit from the original OF scsi spec as the two
+\ cells are the 2 words of a 64-bit SRP LUN
+: set-address ( srplun.lo srplun.hi -- )
+    lxjoin (set-target)
+;
+
+100 CONSTANT #target
+: dev-max-target ( -- #target )
+    #target
+;
+
+" scsi-probe-helpers.fs" included
+
+scsi-close        \ no further scsi words required
+
+0 VALUE queue-control-addr
+0 VALUE queue-event-addr
+0 VALUE queue-cmd-addr
+
+: setup-virt-queues
+    \ add 3 queues 0-controlq, 1-eventq, 2-cmdq
+    \ fixme: do we need to find more than the above 3 queues if exists
+    virtiodev 0 virtio-get-qsize virtio-vring-size
+    alloc-mem to queue-control-addr
+    virtiodev 0 queue-control-addr virtio-set-qaddr
+
+    virtiodev 1 virtio-get-qsize virtio-vring-size
+    alloc-mem to queue-event-addr
+    virtiodev 1 queue-event-addr virtio-set-qaddr
+
+    virtiodev 2 virtio-get-qsize virtio-vring-size
+    alloc-mem to queue-cmd-addr
+    virtiodev 2 queue-cmd-addr virtio-set-qaddr
+;
+
+\ Set scsi alias if none is set yet
+: setup-alias
+    s" scsi" find-alias 0= IF
+       s" scsi" get-node node>path set-alias
+    ELSE
+       drop
+    THEN
+;
+
+: shutdown ( -- )
+    initialized? IF
+       my-phandle node>path open-dev ?dup IF
+          virtiodev virtio-scsi-shutdown
+          close-dev
+       THEN
+       FALSE to initialized?
+    THEN
+;
+
+: virtio-scsi-init-and-scan  ( -- )
+    \ Create instance for scanning:
+    0 0 get-node open-node ?dup 0= IF ." exiting " cr EXIT THEN
+    my-self >r
+    dup to my-self
+    \ Scan the VSCSI bus:
+    virtiodev virtio-scsi-init
+    0= IF
+       setup-virt-queues
+       scsi-find-disks
+       setup-alias
+       TRUE to initialized?
+       ['] shutdown add-quiesce-xt
+    THEN
+    \ Close the temporary instance:
+    close-node
+    r> to my-self
+;
+
+: virtio-scsi-add-disk
+    " scsi-disk.fs" included
+;
+
+virtio-scsi-add-disk
+virtio-scsi-init-and-scan