Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / board-qemu / slof / virtio-scsi.fs
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
8 \ *
9 \ * Contributors:
10 \ *     IBM Corporation - initial implementation
11 \ ****************************************************************************/
12
13 ." Populating " pwd cr
14
15 FALSE CONSTANT virtio-scsi-debug
16
17 2 encode-int s" #address-cells" property
18 0 encode-int s" #size-cells" property
19
20 : decode-unit 2 hex64-decode-unit ;
21 : encode-unit 2 hex64-encode-unit ;
22
23 FALSE VALUE initialized?
24
25 /vd-len BUFFER: virtiodev
26 virtiodev virtio-setup-vd
27
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
40
41 STRUCT \ virtio-scsi-req
42     8  FIELD vs-req>lun
43     8  FIELD vs-req>tag
44     /c FIELD vs-req>task-attr
45     /c FIELD vs-req>prio
46     /c FIELD vs-req>crn
47     20 FIELD vs-req>cdb
48 CONSTANT vs-req-length
49
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
56     60 FIELD vs-rsp>sense
57 CONSTANT vs-rsp-length
58
59 CREATE vs-req vs-req-length allot
60 CREATE vs-rsp vs-rsp-length allot
61
62 scsi-open
63
64 \ -----------------------------------------------------------
65 \ Perform SCSI commands
66 \ -----------------------------------------------------------
67
68 0 INSTANCE VALUE current-target
69
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
73 \ do-scsi-command.
74 \
75 \ Note: stat is -1 for "hw error" (ie, error queuing the command or
76 \ getting the response).
77 \
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
80 \
81
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
87
88     \ Populate the request
89     current-target vs-req vs-req>lun x!
90     vs-req vs-req>cdb swap move
91
92     \ Send it
93     vs-req vs-rsp virtiodev
94     virtio-scsi-send
95
96     0 <> IF
97         ." VIRTIO-SCSI: Queuing failure !" cr
98         0 0 -1 EXIT
99     THEN
100
101     \ Check virtio response
102     vs-rsp vs-rsp>response c@ CASE
103         0 OF ENDOF                      \ Good
104         5 OF drop 0 0 8 EXIT ENDOF      \ Busy
105         dup OF 0 0 -1 EXIT ENDOF        \ Anything else -> HW error
106     ENDCASE
107
108     \ Other error status
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
114             0 EXIT
115         THEN
116         vs-rsp vs-rsp>sense swap
117         virtio-scsi-debug IF
118             over scsi-get-sense-data
119             ." VIRTIO-SCSI: Sense key [ " dup . ." ] " .sense-text
120             ."  ASC,ASCQ: " . . cr
121         THEN
122        rot
123     THEN    
124 ;
125
126 \ --------------------------------
127 \ Include the generic host helpers
128 \ --------------------------------
129
130 " scsi-host-helpers.fs" included
131
132 \ FIXME: Check max transfer coming from virtio config
133 : max-transfer ( -- n )
134     10000 \ Larger value seem to have problems with some CDROMs
135 ;
136
137 \ -----------------------------------------------------------
138 \ SCSI scan at boot and child device support
139 \ -----------------------------------------------------------
140
141 \ We use SRP luns of the form 01000000 | (target << 16) | lun
142 \ in the top 32 bits of the 64-bit LUN
143 : (set-target)
144     to current-target
145 ;
146
147 : dev-generate-srplun ( target lun-id -- srplun )
148     swap 0100 or 10 << or 20 <<
149 ;
150
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
153 \
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 -- )
157     lxjoin (set-target)
158 ;
159
160 100 CONSTANT #target
161 : dev-max-target ( -- #target )
162     #target
163 ;
164
165 " scsi-probe-helpers.fs" included
166
167 scsi-close        \ no further scsi words required
168
169 0 VALUE queue-control-addr
170 0 VALUE queue-event-addr
171 0 VALUE queue-cmd-addr
172
173 : setup-virt-queues
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
179
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
183
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
187 ;
188
189 \ Set scsi alias if none is set yet
190 : setup-alias
191     s" scsi" find-alias 0= IF
192         s" scsi" get-node node>path set-alias
193     ELSE
194         drop
195     THEN
196 ;
197
198 : shutdown ( -- )
199     initialized? IF
200        my-phandle node>path open-dev ?dup IF
201           virtiodev virtio-scsi-shutdown
202           close-dev
203        THEN
204        FALSE to initialized?
205     THEN
206 ;
207
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
211     my-self >r
212     dup to my-self
213     \ Scan the VSCSI bus:
214     virtiodev virtio-scsi-init
215     0= IF
216         setup-virt-queues
217         scsi-find-disks
218         setup-alias
219         TRUE to initialized?
220         ['] shutdown add-quiesce-xt
221     THEN
222     \ Close the temporary instance:
223     close-node
224     r> to my-self
225 ;
226
227 : virtio-scsi-add-disk
228     " scsi-disk.fs" included
229 ;
230
231 virtio-scsi-add-disk
232 virtio-scsi-init-and-scan