211 lines
5.5 KiB
Forth
211 lines
5.5 KiB
Forth
\ *****************************************************************************
|
|
\ * 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?
|
|
|
|
virtio-setup-vd VALUE virtiodev
|
|
|
|
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 )
|
|
dup ff > IF 4000 or THEN \ Use the LUN "flat space addressing method"
|
|
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
|
|
|
|
\ 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
|
|
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
|