1 \ *****************************************************************************
2 \ * Copyright (c) 2012 IBM Corporation
3 \ * All rights reserved.
4 \ * This program and the accompanying materials
5 \ * are made available under the terms of the BSD License
6 \ * which accompanies this distribution, and is available at
7 \ * http://www.opensource.org/licenses/bsd-license.php
10 \ * IBM Corporation - initial implementation
11 \ ****************************************************************************/
13 ." Populating " pwd cr
15 FALSE CONSTANT virtio-scsi-debug
17 2 encode-int s" #address-cells" property
18 0 encode-int s" #size-cells" property
20 : decode-unit 2 hex64-decode-unit ;
21 : encode-unit 2 hex64-encode-unit ;
23 FALSE VALUE initialized?
25 /vd-len BUFFER: virtiodev
26 virtiodev virtio-setup-vd
28 STRUCT \ virtio-scsi-config
29 /l FIELD vs-cfg>num-queues
30 /l FIELD vs-cfg>seg-max
31 /l FIELD vs-cfg>max-sectors
32 /l FIELD vs-cfg>cmd-per-lun
33 /l FIELD vs-cfg>event-info-size
34 /l FIELD vs-cfg>sense_size
35 /l FIELD vs-cfg>cdb-size
36 /w FIELD vs-cfg>max-channel
37 /w FIELD vs-cfg>max-target
38 /l FIELD vs-cfg>max-lun
39 CONSTANT vs-cfg-length
41 STRUCT \ virtio-scsi-req
44 /c FIELD vs-req>task-attr
48 CONSTANT vs-req-length
50 STRUCT \ virtio-scsi-resp
51 /l FIELD vs-rsp>sense-len
52 /l FIELD vs-rsp>residual
53 /w FIELD vs-rsp>status-qualifier
54 /c FIELD vs-rsp>status
55 /c FIELD vs-rsp>response
57 CONSTANT vs-rsp-length
59 CREATE vs-req vs-req-length allot
60 CREATE vs-rsp vs-rsp-length allot
64 \ -----------------------------------------------------------
65 \ Perform SCSI commands
66 \ -----------------------------------------------------------
68 0 INSTANCE VALUE current-target
70 \ SCSI command. We do *NOT* implement the "standard" execute-command
71 \ because that doesn't have a way to return the sense buffer back, and
72 \ we do have auto-sense with some hosts. Instead we implement a made-up
75 \ Note: stat is -1 for "hw error" (ie, error queuing the command or
76 \ getting the response).
78 \ A sense buffer is returned whenever the status is non-0 however
79 \ if sense-len is 0 then no sense data is actually present
82 : execute-scsi-command ( buf-addr buf-len dir cmd-addr cmd-len -- ... )
83 ( ... [ sense-buf sense-len ] stat )
84 \ Cleanup virtio request and response
85 vs-req vs-req-length erase
86 vs-rsp vs-rsp-length erase
88 \ Populate the request
89 current-target vs-req vs-req>lun x!
90 vs-req vs-req>cdb swap move
93 vs-req vs-rsp virtiodev
97 ." VIRTIO-SCSI: Queuing failure !" cr
101 \ Check virtio response
102 vs-rsp vs-rsp>response c@ CASE
104 5 OF drop 0 0 8 EXIT ENDOF \ Busy
105 dup OF 0 0 -1 EXIT ENDOF \ Anything else -> HW error
109 vs-rsp vs-rsp>status c@ dup 0<> IF
110 vs-rsp vs-rsp>sense-len l@ dup 0= IF
111 \ This relies on auto-sense from qemu... if that isn't always the
112 \ case we should request sense here
113 ." VIRTIO-SCSI: No sense data" cr
116 vs-rsp vs-rsp>sense swap
118 over scsi-get-sense-data
119 ." VIRTIO-SCSI: Sense key [ " dup . ." ] " .sense-text
120 ." ASC,ASCQ: " . . cr
126 \ --------------------------------
127 \ Include the generic host helpers
128 \ --------------------------------
130 " scsi-host-helpers.fs" included
132 \ FIXME: Check max transfer coming from virtio config
133 : max-transfer ( -- n )
134 10000 \ Larger value seem to have problems with some CDROMs
137 \ -----------------------------------------------------------
138 \ SCSI scan at boot and child device support
139 \ -----------------------------------------------------------
141 \ We use SRP luns of the form 01000000 | (target << 16) | lun
142 \ in the top 32 bits of the 64-bit LUN
147 : dev-generate-srplun ( target lun-id -- srplun )
148 swap 0100 or 10 << or 20 <<
151 \ We obtain here a unit address on the stack, since our #address-cells
152 \ is 2, the 64-bit srplun is split in two cells that we need to join
154 \ Note: This diverges a bit from the original OF scsi spec as the two
155 \ cells are the 2 words of a 64-bit SRP LUN
156 : set-address ( srplun.lo srplun.hi -- )
161 : dev-max-target ( -- #target )
165 " scsi-probe-helpers.fs" included
167 scsi-close \ no further scsi words required
169 0 VALUE queue-control-addr
170 0 VALUE queue-event-addr
171 0 VALUE queue-cmd-addr
174 \ add 3 queues 0-controlq, 1-eventq, 2-cmdq
175 \ fixme: do we need to find more than the above 3 queues if exists
176 virtiodev 0 virtio-get-qsize virtio-vring-size
177 alloc-mem to queue-control-addr
178 virtiodev 0 queue-control-addr virtio-set-qaddr
180 virtiodev 1 virtio-get-qsize virtio-vring-size
181 alloc-mem to queue-event-addr
182 virtiodev 1 queue-event-addr virtio-set-qaddr
184 virtiodev 2 virtio-get-qsize virtio-vring-size
185 alloc-mem to queue-cmd-addr
186 virtiodev 2 queue-cmd-addr virtio-set-qaddr
189 \ Set scsi alias if none is set yet
191 s" scsi" find-alias 0= IF
192 s" scsi" get-node node>path set-alias
200 my-phandle node>path open-dev ?dup IF
201 virtiodev virtio-scsi-shutdown
204 FALSE to initialized?
208 : virtio-scsi-init-and-scan ( -- )
209 \ Create instance for scanning:
210 0 0 get-node open-node ?dup 0= IF ." exiting " cr EXIT THEN
213 \ Scan the VSCSI bus:
214 virtiodev virtio-scsi-init
220 ['] shutdown add-quiesce-xt
222 \ Close the temporary instance:
227 : virtio-scsi-add-disk
228 " scsi-disk.fs" included
232 virtio-scsi-init-and-scan