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
15FALSE CONSTANT virtio-scsi-debug
16
172 encode-int s" #address-cells" property
180 encode-int s" #size-cells" property
19
20: decode-unit 2 hex64-decode-unit ;
21: encode-unit 2 hex64-encode-unit ;
22
23FALSE VALUE initialized?
24
25virtio-setup-vd VALUE virtiodev
26
27STRUCT \ virtio-scsi-config
28    /l FIELD vs-cfg>num-queues
29    /l FIELD vs-cfg>seg-max
30    /l FIELD vs-cfg>max-sectors
31    /l FIELD vs-cfg>cmd-per-lun
32    /l FIELD vs-cfg>event-info-size
33    /l FIELD vs-cfg>sense_size
34    /l FIELD vs-cfg>cdb-size
35    /w FIELD vs-cfg>max-channel
36    /w FIELD vs-cfg>max-target
37    /l FIELD vs-cfg>max-lun
38CONSTANT vs-cfg-length
39
40STRUCT \ virtio-scsi-req
41    8  FIELD vs-req>lun
42    8  FIELD vs-req>tag
43    /c FIELD vs-req>task-attr
44    /c FIELD vs-req>prio
45    /c FIELD vs-req>crn
46    20 FIELD vs-req>cdb
47CONSTANT vs-req-length
48
49STRUCT \ virtio-scsi-resp
50    /l FIELD vs-rsp>sense-len
51    /l FIELD vs-rsp>residual
52    /w FIELD vs-rsp>status-qualifier
53    /c FIELD vs-rsp>status
54    /c FIELD vs-rsp>response
55    60 FIELD vs-rsp>sense
56CONSTANT vs-rsp-length
57
58CREATE vs-req vs-req-length allot
59CREATE vs-rsp vs-rsp-length allot
60
61scsi-open
62
63\ -----------------------------------------------------------
64\ Perform SCSI commands
65\ -----------------------------------------------------------
66
670 INSTANCE VALUE current-target
68
69\ SCSI command. We do *NOT* implement the "standard" execute-command
70\ because that doesn't have a way to return the sense buffer back, and
71\ we do have auto-sense with some hosts. Instead we implement a made-up
72\ do-scsi-command.
73\
74\ Note: stat is -1 for "hw error" (ie, error queuing the command or
75\ getting the response).
76\
77\ A sense buffer is returned whenever the status is non-0 however
78\ if sense-len is 0 then no sense data is actually present
79\
80
81: execute-scsi-command ( buf-addr buf-len dir cmd-addr cmd-len -- ... )
82                       ( ... [ sense-buf sense-len ] stat )
83    \ Cleanup virtio request and response
84    vs-req vs-req-length erase
85    vs-rsp vs-rsp-length erase
86
87    \ Populate the request
88    current-target vs-req vs-req>lun x!
89    vs-req vs-req>cdb swap move
90
91    \ Send it
92    vs-req vs-rsp virtiodev
93    virtio-scsi-send
94
95    0 <> IF
96        ." VIRTIO-SCSI: Queuing failure !" cr
97        0 0 -1 EXIT
98    THEN
99
100    \ Check virtio response
101    vs-rsp vs-rsp>response c@ CASE
102        0 OF ENDOF			\ Good
103        5 OF drop 0 0 8 EXIT ENDOF	\ Busy
104        dup OF 0 0 -1 EXIT ENDOF	\ Anything else -> HW error
105    ENDCASE
106
107    \ Other error status
108    vs-rsp vs-rsp>status c@ dup 0<> IF
109        vs-rsp vs-rsp>sense-len l@ dup 0= IF
110            \ This relies on auto-sense from qemu... if that isn't always the
111            \ case we should request sense here
112            ." VIRTIO-SCSI: No sense data" cr
113	    0 EXIT
114        THEN
115        vs-rsp vs-rsp>sense swap
116        virtio-scsi-debug IF
117            over scsi-get-sense-data
118            ." VIRTIO-SCSI: Sense key [ " dup . ." ] " .sense-text
119	    ."  ASC,ASCQ: " . . cr
120        THEN
121       rot
122    THEN
123;
124
125\ --------------------------------
126\ Include the generic host helpers
127\ --------------------------------
128
129" scsi-host-helpers.fs" included
130
131\ FIXME: Check max transfer coming from virtio config
132: max-transfer ( -- n )
133    10000 \ Larger value seem to have problems with some CDROMs
134;
135
136\ -----------------------------------------------------------
137\ SCSI scan at boot and child device support
138\ -----------------------------------------------------------
139
140\ We use SRP luns of the form 01000000 | (target << 16) | lun
141\ in the top 32 bits of the 64-bit LUN
142: (set-target)
143    to current-target
144;
145
146: dev-generate-srplun ( target lun-id -- srplun )
147    dup ff > IF 4000 or THEN    \ Use the LUN "flat space addressing method"
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
160100 CONSTANT #target
161: dev-max-target ( -- #target )
162    #target
163;
164
165" scsi-probe-helpers.fs" included
166
167scsi-close        \ no further scsi words required
168
169\ Set scsi alias if none is set yet
170: setup-alias
171    s" scsi" find-alias 0= IF
172	s" scsi" get-node node>path set-alias
173    ELSE
174	drop
175    THEN
176;
177
178: shutdown ( -- )
179    initialized? IF
180       my-phandle node>path open-dev ?dup IF
181          virtiodev virtio-scsi-shutdown
182          close-dev
183       THEN
184       FALSE to initialized?
185    THEN
186;
187
188: virtio-scsi-init-and-scan  ( -- )
189    \ Create instance for scanning:
190    0 0 get-node open-node ?dup 0= IF ." exiting " cr EXIT THEN
191    my-self >r
192    dup to my-self
193    \ Scan the VSCSI bus:
194    virtiodev virtio-scsi-init
195    0= IF
196	scsi-find-disks
197	setup-alias
198	TRUE to initialized?
199	['] shutdown add-quiesce-xt
200    THEN
201    \ Close the temporary instance:
202    close-node
203    r> to my-self
204;
205
206: virtio-scsi-add-disk
207    " scsi-disk.fs" included
208;
209
210virtio-scsi-add-disk
211virtio-scsi-init-and-scan
212