summaryrefslogtreecommitdiffstats
path: root/qemu/roms/SLOF/board-qemu/slof/virtio-scsi.fs
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/SLOF/board-qemu/slof/virtio-scsi.fs')
-rw-r--r--qemu/roms/SLOF/board-qemu/slof/virtio-scsi.fs232
1 files changed, 232 insertions, 0 deletions
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
index 000000000..ca5fb13aa
--- /dev/null
+++ b/qemu/roms/SLOF/board-qemu/slof/virtio-scsi.fs
@@ -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