Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | \ ========== Copyright Header Begin ========================================== |
2 | \ | |
3 | \ Hypervisor Software File: hacom.fth | |
4 | \ | |
5 | \ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
6 | \ | |
7 | \ - Do no alter or remove copyright notices | |
8 | \ | |
9 | \ - Redistribution and use of this software in source and binary forms, with | |
10 | \ or without modification, are permitted provided that the following | |
11 | \ conditions are met: | |
12 | \ | |
13 | \ - Redistribution of source code must retain the above copyright notice, | |
14 | \ this list of conditions and the following disclaimer. | |
15 | \ | |
16 | \ - Redistribution in binary form must reproduce the above copyright notice, | |
17 | \ this list of conditions and the following disclaimer in the | |
18 | \ documentation and/or other materials provided with the distribution. | |
19 | \ | |
20 | \ Neither the name of Sun Microsystems, Inc. or the names of contributors | |
21 | \ may be used to endorse or promote products derived from this software | |
22 | \ without specific prior written permission. | |
23 | \ | |
24 | \ This software is provided "AS IS," without a warranty of any kind. | |
25 | \ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, | |
26 | \ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A | |
27 | \ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN | |
28 | \ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR | |
29 | \ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR | |
30 | \ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN | |
31 | \ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR | |
32 | \ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE | |
33 | \ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, | |
34 | \ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF | |
35 | \ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. | |
36 | \ | |
37 | \ You acknowledge that this software is not designed, licensed or | |
38 | \ intended for use in the design, construction, operation or maintenance of | |
39 | \ any nuclear facility. | |
40 | \ | |
41 | \ ========== Copyright Header End ============================================ | |
42 | id: @(#)hacom.fth 1.12 04/03/18 | |
43 | purpose: | |
44 | copyright: Copyright 1995-2004 Sun Microsystems, Inc. All rights reserved | |
45 | copyright: Use is subject to license terms. | |
46 | ||
47 | \ Common code for SCSI host adapter drivers. | |
48 | ||
49 | \ The following code is intended to be independent of the details of the | |
50 | \ SCSI hardware implementation. It is loaded after the hardware-dependent | |
51 | \ file that defines execute-command, set-address, open-hardware, etc. | |
52 | ||
53 | headers | |
54 | ||
55 | -1 instance value inq-buf \ Address of inquiry data buffer | |
56 | -1 instance value sense-buf \ holds extended error information | |
57 | -1 instance value luns-buf \ Address of report luns data buffer | |
58 | ||
59 | ||
60 | 0 value #retries ( -- n ) \ number of times to retry SCSI transaction | |
61 | ||
62 | h# 1.0000 constant debug-sense-codes | |
63 | ||
64 | : .buf ( strt-adr cnt -- ) | |
65 | base @ >r hex | |
66 | bounds do i c@ 3 u.r loop | |
67 | r> base ! | |
68 | ; | |
69 | ||
70 | \ Classifies the sense condition as either okay (0), retryable (1), | |
71 | \ or non-retryable (-1) | |
72 | : classify-sense ( -- 0 | 1 | -1 ) | |
73 | debug? debug-sense-codes and if | |
74 | ." Sense: " sense-buf 11 .buf ." ..." cr | |
75 | then | |
76 | sense-buf | |
77 | ||
78 | \ Make sure we understand the error class code | |
79 | dup c@ h# 7f and h# 70 <> if drop -1 exit then | |
80 | ||
81 | \ Check for filemark, end-of-media, or illegal block length | |
82 | dup 2+ c@ h# e0 and if drop -1 exit then | |
83 | ||
84 | 2 + c@ h# f and ( sense-key ) | |
85 | ||
86 | \ no_sense(0) and recoverable(1) are okay | |
87 | dup 1 <= if drop 0 exit then ( sense-key ) | |
88 | ||
89 | \ not-ready(2) may be retryable | |
90 | dup 2 = if | |
91 | \ check (tapes, especially) for MEDIA NOT PRESENT: if the | |
92 | \ media's not there the command is not retryable | |
93 | drop sense-buf h# c + c@ h# 3a = sense-buf h# d + c@ 0= | |
94 | and if -1 else 1 then | |
95 | exit | |
96 | then | |
97 | ||
98 | \ media-error(3), attention(6), and target aborted (b) are retryable | |
99 | \ media error really should not be retryable, but Toshiba 3601 CDROMs | |
100 | \ sometimes return "media error" during the spin-up process. | |
101 | dup 3 = over 6 = or swap 0b = or if 1 else -1 then | |
102 | ; | |
103 | ||
104 | external | |
105 | ||
106 | \ The SCSI device node defines an address space for its children. That | |
107 | \ address space is of the form "target#,unit#". target# and unit# are | |
108 | \ both integers. parse-2int converts a text string (e.g. "3,4") into | |
109 | \ a pair of binary integers. | |
110 | ||
111 | : open ( -- flag ) | |
112 | open-count if | |
113 | reopen-hardware dup if open-count 1+ to open-count then | |
114 | exit | |
115 | else | |
116 | open-hardware dup if | |
117 | 1 to open-count | |
118 | h# 100 dma-alloc to sense-buf | |
119 | h# 100 dma-alloc to inq-buf | |
120 | h# 2000 dma-alloc to luns-buf | |
121 | then | |
122 | then | |
123 | ; | |
124 | : close ( -- ) | |
125 | open-count 1- to open-count | |
126 | open-count if | |
127 | reclose-hardware | |
128 | else | |
129 | close-hardware | |
130 | luns-buf h# 2000 dma-free | |
131 | inq-buf h# 100 dma-free | |
132 | sense-buf h# 100 dma-free | |
133 | then | |
134 | ; | |
135 | ||
136 | ||
137 | headers | |
138 | ||
139 | \ REQUEST-SENSE is HA specific, here is typical implementation | |
140 | \ | |
141 | \ create sense-cmd 3 c, 0 c, 0 c, 0 c, ff c, 0 c, | |
142 | \ : request-sense ( buf,len -- hwresult | statbyte 0 ) | |
143 | \ true sense-cmd 6 execute-command | |
144 | \ ; | |
145 | ||
146 | \ Issue REQUEST SENSE, which is not supposed to fail | |
147 | : get-sense ( -- ) | |
148 | sense-buf ff request-sense 0= if drop then | |
149 | ; | |
150 | ||
151 | \ Give the device a little time to recover before retrying the command. | |
152 | : delay-retry ( -- ) d# 100 ms ; | |
153 | ||
154 | 0 instance value statbyte \ Local variable used by retry? | |
155 | ||
156 | \ RETRY? is used by RETRY-COMMAND to determine whether or not to retry the | |
157 | \ command, considering the following factors: | |
158 | \ - Success or failure of the command at the hardware level (failure at | |
159 | \ this level is usually fatal, except in the case of an incoming bus reset) | |
160 | \ - The value of the status byte returned by the command | |
161 | \ - The condition indicated by the sense bytes | |
162 | \ - The number of previous retries | |
163 | \ | |
164 | \ The input arguments are as returned by "scsi-exec" | |
165 | \ On output, the top of the stack is true if the command is to be retried, | |
166 | \ otherwise the top of the stack is false and the results that should be | |
167 | \ returned by retry-command are underneath it; those results indicate the type | |
168 | \ of error that occurred. | |
169 | ||
170 | : retry? ( hw-result | statbyte 0 -- true | [[sensebuf] f-hw] error? false ) | |
171 | case | |
172 | 0 of to statbyte endof \ No hardware error; continue checking | |
173 | bus-reset of true exit endof \ Retry after incoming bus reset | |
174 | ( hw-result ) true false exit \ Other hardware errors are fatal | |
175 | endcase | |
176 | ||
177 | statbyte 0= if false false exit then \ If successful, return "no-error" | |
178 | ||
179 | statbyte 2 and if \ "Check Condition", so get extended status | |
180 | get-sense classify-sense case ( -1|0|1 ) | |
181 | \ If the sense information says "no sense", return "no-error" | |
182 | 0 of false false exit endof | |
183 | ||
184 | \ If the error is fatal, return "sense-buf,valid,statbyte" | |
185 | -1 of sense-buf false statbyte false exit endof | |
186 | endcase | |
187 | ||
188 | \ Otherwise, the error was retryable. However, if we have | |
189 | \ have already retried the specified number of times, don't | |
190 | \ retry again; instead return sense buffer and status. | |
191 | #retries 0= if sense-buf false statbyte false exit then | |
192 | then | |
193 | ||
194 | \ Don't retry if vendor-unique, reserved, intermediate, or | |
195 | \ "condition met/good" bits are set. Return "no-sense,status" | |
196 | statbyte h# f5 and if true statbyte false exit then | |
197 | ||
198 | \ Don't retry if we have already retried the specified number | |
199 | \ of times. Return "no-sense,status" | |
200 | #retries 0= if true statbyte false exit then | |
201 | ||
202 | \ Otherwise, it was either a busy or a retryable check condition, | |
203 | \ so we retry. | |
204 | ||
205 | true | |
206 | ; | |
207 | ||
208 | \ RETRY-COMMAND executes a SCSI command. If a check condition is indicated, | |
209 | \ performs a "get-sense" command. If the sense bytes indicate a non-fatal | |
210 | \ condition (e.g. power-on reset occurred, not ready yet, or recoverable | |
211 | \ error), the command is retried until the condition either goes away or | |
212 | \ changes to a fatal error. | |
213 | \ | |
214 | \ The command is retried until: | |
215 | \ a) The command succeeds, or | |
216 | \ b) The select fails, or dma fails, or | |
217 | \ c) The sense bytes indicate an error that we can't retry at this level | |
218 | \ d) The number of retries is exceeded. | |
219 | ||
220 | \ #retries is number of times to retry (0: don't retry, -1: retry forever) | |
221 | \ | |
222 | \ sensebuf is the address of the sense buffer; it is present only | |
223 | \ if f-hw is 0 and error? is non-zero. The length of the sense buffer | |
224 | \ is 8 bytes plus the value in byte 7 of the sense buffer. | |
225 | \ | |
226 | \ f-hw is non-zero if there is a hardware error -- dma fails, select fails, | |
227 | \ etc -- or if the status byte was neither 0 (okay) nor 2 (check condition) | |
228 | \ | |
229 | \ error? is non-zero if there is a transaction error. If error? is 0, | |
230 | \ f-hw and sensebuf are not returned. | |
231 | \ | |
232 | \ If sensebuf is returned, the contents are valid until the next call to | |
233 | \ retry-command. sensebuf becomes inaccessable when this package is closed. | |
234 | \ | |
235 | \ dma-dir is necessary because it is not always possible to infer the DMA | |
236 | \ direction from the command. | |
237 | ||
238 | \ Local variables used by retry-command? | |
239 | ||
240 | 0 instance value dbuf \ Data transfer buffer | |
241 | 0 instance value dlen \ Expected length of data transfer | |
242 | 0 instance value direction-in \ Direction for data transfer | |
243 | ||
244 | -1 instance value cbuf \ Command base address | |
245 | 0 instance value clen \ Actual length of this command | |
246 | ||
247 | external | |
248 | ||
249 | : retry-command ( dma-buf dma-len dma-dir cmdbuf cmdlen #retries -- ... ) | |
250 | ( ... -- [[sensebuf] f-hw] error? ) | |
251 | to #retries to clen to cbuf to direction-in to dlen to dbuf | |
252 | ||
253 | begin | |
254 | dbuf dlen direction-in cbuf clen execute-command ( hwerr | stat 0 ) | |
255 | retry? | |
256 | while | |
257 | #retries 1- to #retries | |
258 | delay-retry | |
259 | repeat | |
260 | ; | |
261 | ||
262 | headers | |
263 | ||
264 | \ Collapses the complete error information returned by retry-command into | |
265 | \ a single error/no-error flag. | |
266 | ||
267 | : error? ( false | true true | sensebuf false true -- error? ) | |
268 | dup if swap 0= if nip then then | |
269 | ; | |
270 | ||
271 | external | |
272 | ||
273 | \ Simplified "retry-command" routine for commands with no data transfer phase | |
274 | \ and simple error checking requirements. | |
275 | ||
276 | : no-data-command ( cmdbuf -- error? ) | |
277 | >r 0 0 true r> 6 -1 retry-command error? | |
278 | ; | |
279 | ||
280 | \ short-data-command executes a command with the following characteristics: | |
281 | \ a) The data direction is incoming | |
282 | \ b) The data length is less than 256 bytes | |
283 | ||
284 | \ The host adapter driver is responsible for supplying the DMA data | |
285 | \ buffer; if the command succeeds, the buffer address is returned. | |
286 | \ The buffer contents become invalid when another SCSI command is | |
287 | \ executed, or when the driver is closed. | |
288 | ||
289 | : short-data-command ( data-len cmdbuf cmdlen -- true | buffer false ) | |
290 | >r >r inq-buf swap true r> r> -1 retry-command ( retry-cmd-results ) | |
291 | error? dup 0= if inq-buf swap then | |
292 | ; | |
293 | ||
294 | headers | |
295 | ||
296 | \ Here begins the implementation of "show-children", a word that | |
297 | \ is intended to be executed interactively, showing the user the | |
298 | \ devices that are attached to the SCSI bus. | |
299 | ||
300 | \ Tool for storing a big-endian 24-bit number at an unaligned address | |
301 | ||
302 | : 3c! ( n addr -- ) >r lbsplit drop r@ c! r@ 1+ c! r> 2+ c! ; | |
303 | ||
304 | ||
305 | \ Command block template for Inquiry command | |
306 | ||
307 | create inquiry-cmd h# 12 c, 0 c, 0 c, 0 c, ff c, 0 c, | |
308 | ||
309 | : inquiry ( -- error? ) | |
310 | \ 8 retries should be more than enough; inquiry commands aren't | |
311 | \ supposed to respond with "check condition". | |
312 | ||
313 | inq-buf ff true inquiry-cmd 6 8 retry-command error? | |
314 | ; | |
315 | ||
316 | : ??line ( lmargin char threshold -- ) | |
317 | #out @ <= if cr 2dup bl = if 1- then spaces then | |
318 | ; | |
319 | : formatted-type ( adr len -- ) | |
320 | #out @ -rot | |
321 | bounds ?do | |
322 | i c@ dup bl = if d# 70 ??line then | |
323 | d# 78 ??line | |
324 | emit | |
325 | loop | |
326 | drop | |
327 | ; | |
328 | ||
329 | \ Reads the indicated byte from the Inquiry data buffer | |
330 | ||
331 | : inq@ ( offset -- value ) inq-buf + c@ ; | |
332 | ||
333 | : .scsi1-inquiry ( -- ) inq-buf 5 ca+ 4 inq@ h# fa min formatted-type ; | |
334 | : .scsi2-inquiry ( -- ) inq-buf 8 ca+ d# 28 formatted-type ; | |
335 | ||
336 | headerless | |
337 | ||
338 | create report-luns-cmd | |
339 | h# 0c c, | |
340 | h# a0 c, 00 c, 00 c, 00 c, 00 c, 00 c, | |
341 | h# 00 c, 00 c, 20 c, 00 c, 00 c, 00 c, | |
342 | ||
343 | : report-luns ( -- error? ) | |
344 | luns-buf h# 2000 -1 report-luns-cmd count 8 retry-command error? | |
345 | ; | |
346 | ||
347 | headers | |
348 | ||
349 | \ The diagnose command is useful for generic SCSI devices. | |
350 | \ It executes bothe "test-unit-ready" and "send-diagnostic" | |
351 | \ commands, decoding the error status information they return. | |
352 | ||
353 | create test-unit-rdy-cmd 0 c, 0 c, 0 c, 0 c, 0 c, 0 c, | |
354 | create send-diagnostic-cmd h# 1d c, 4 c, 0 c, 0 c, 0 c, 0 c, | |
355 | ||
356 | : send-diagnostic ( -- error? ) send-diagnostic-cmd no-data-command ; | |
357 | ||
358 | ||
359 | external | |
360 | ||
361 | : diagnose ( -- flag ) | |
362 | 0 0 true test-unit-rdy-cmd 6 -1 ( dma$ dir cmd$ #retries ) | |
363 | retry-command if ( [ sensebuf ] hardware-error? ) | |
364 | ." Test unit ready failed - " ( [ sensebuf ] hardware-error? ) | |
365 | if ( ) | |
366 | ." hardware error (no such device?)" cr ( ) | |
367 | else ( sensebuf ) | |
368 | ." extended status = " cr ( sensebuf ) | |
369 | 8 .buf cr | |
370 | then | |
371 | true | |
372 | else | |
373 | send-diagnostic ( fail? ) | |
374 | then | |
375 | ; | |
376 | ||
377 | headers |