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.2 07/07/05 | |
43 | purpose: Common code for SCSI host adapter drivers. | |
44 | copyright: Copyright 2007 Sun Microsystems, Inc. All Rights Reserved | |
45 | \ See license at end of file | |
46 | ||
47 | \ The following code is intended to be independent of the details of the | |
48 | \ SCSI hardware implementation. It is loaded after the hardware-dependent | |
49 | \ file that defines execute-command, set-address, open-hardware, etc. | |
50 | ||
51 | headers | |
52 | ||
53 | -1 value inq-buf \ Address of inquiry data buffer | |
54 | -1 value sense-buf \ holds extended error information | |
55 | ||
56 | ||
57 | 0 value #retries ( -- n ) \ number of times to retry SCSI transaction | |
58 | ||
59 | \ Classifies the sense condition as either okay (0), retryable (1), | |
60 | \ or non-retryable (-1) | |
61 | : classify-sense ( -- 0 | 1 | -1 ) | |
62 | debug? if | |
63 | base @ >r hex | |
64 | ." Sense: " sense-buf 11 bounds do i c@ 3 u.r loop ." ..." cr | |
65 | r> base ! | |
66 | then | |
67 | sense-buf | |
68 | ||
69 | \ Make sure we understand the error class code | |
70 | dup c@ h# 7f and h# 70 <> if drop -1 exit then | |
71 | ||
72 | \ Check for filemark, end-of-media, or illegal block length | |
73 | dup 2+ c@ h# e0 and if drop -1 exit then | |
74 | ||
75 | 2 + c@ h# f and ( sense-key ) | |
76 | ||
77 | \ no_sense(0) and recoverable(1) are okay | |
78 | dup 1 <= if drop 0 exit then ( sense-key ) | |
79 | ||
80 | \ not-ready(2) may be retryable | |
81 | dup 2 = if | |
82 | \ check for MEDIA NOT PRESENT: if the media's not there the | |
83 | \ command is not retryable. Unlike the legacy SCSI FCode, we | |
84 | \ don't look at the ASCQ field of the SENSE buffer since we | |
85 | \ want to fail for all ASCQ values when dealing with USB devices. | |
86 | drop sense-buf h# c + c@ h# 3a = if | |
87 | -1 else 1 | |
88 | then exit | |
89 | then | |
90 | ||
91 | \ Media-error(3) is not retryable | |
92 | dup 3 = if drop -1 exit then | |
93 | ||
94 | \ Attention(6), and target aborted (b) are retryable. | |
95 | dup 6 = swap 0b = or if 1 else -1 then | |
96 | ; | |
97 | ||
98 | 0 value open-count | |
99 | ||
100 | : $= ( $1 $2 -- flag ) | |
101 | rot tuck <> if 3drop false exit then | |
102 | comp 0= | |
103 | ; | |
104 | ||
105 | external | |
106 | : open ( -- flag ) | |
107 | my-args " debug" $= if debug-on then | |
108 | open-count if | |
109 | reopen-hardware dup if open-count 1+ to open-count then | |
110 | exit | |
111 | else | |
112 | open-hardware dup if | |
113 | 1 to open-count | |
114 | 100 dma-alloc to sense-buf | |
115 | 100 dma-alloc to inq-buf | |
116 | then | |
117 | then | |
118 | ; | |
119 | : close ( -- ) | |
120 | open-count 1- to open-count | |
121 | open-count if | |
122 | reclose-hardware | |
123 | else | |
124 | close-hardware | |
125 | inq-buf 100 dma-free | |
126 | sense-buf 100 dma-free | |
127 | then | |
128 | ; | |
129 | ||
130 | ||
131 | headers | |
132 | ||
133 | create sense-cmd 3 c, 0 c, 0 c, 0 c, ff c, 0 c, | |
134 | ||
135 | : get-sense ( -- ) \ Issue REQUEST SENSE, which is not supposed to fail | |
136 | sense-buf ff true sense-cmd 6 execute-command 0= if drop then | |
137 | ; | |
138 | ||
139 | \ Give the device a little time to recover before retrying the command. | |
140 | : delay-retry ( -- ) 2000 0 do loop ; | |
141 | ||
142 | 0 value statbyte \ Local variable used by retry? | |
143 | ||
144 | \ RETRY? is used by RETRY-COMMAND to determine whether or not to retry the | |
145 | \ command, considering the following factors: | |
146 | \ - Success or failure of the command at the hardware level (failure at | |
147 | \ this level is usually fatal, except in the case of an incoming bus reset) | |
148 | \ - The value of the status byte returned by the command | |
149 | \ - The condition indicated by the sense bytes | |
150 | \ - The number of previous retries | |
151 | \ | |
152 | \ The input arguments are as returned by "scsi-exec" | |
153 | \ On output, the top of the stack is true if the command is to be retried, | |
154 | \ otherwise the top of the stack is false and the results that should be | |
155 | \ returned by retry-command are underneath it; those results indicate the type | |
156 | \ of error that occurred. | |
157 | ||
158 | : retry? ( hw-result | statbyte 0 -- true | [[sensebuf] f-hw] error? false ) | |
159 | case | |
160 | 0 of to statbyte endof \ No hardware error; continue checking | |
161 | bus-reset of true exit endof \ Retry after incoming bus reset | |
162 | ( hw-result ) true false exit \ Other hardware errors are fatal | |
163 | endcase | |
164 | ||
165 | statbyte 0= if false false exit then \ If successful, return "no-error" | |
166 | ||
167 | statbyte 2 and if \ "Check Condition", so get extended status | |
168 | get-sense classify-sense case ( -1|0|1 ) | |
169 | \ If the sense information says "no sense", return "no-error" | |
170 | 0 of false false exit endof | |
171 | ||
172 | \ If the error is fatal, return "sense-buf,valid,statbyte" | |
173 | -1 of sense-buf false statbyte false exit endof | |
174 | endcase | |
175 | ||
176 | \ Otherwise, the error was retryable. However, if we have | |
177 | \ have already retried the specified number of times, don't | |
178 | \ retry again; instead return sense buffer and status. | |
179 | #retries 0= if sense-buf false statbyte false exit then | |
180 | then | |
181 | ||
182 | \ Don't retry if vendor-unique, reserved, intermediate, or | |
183 | \ "condition met/good" bits are set. Return "no-sense,status" | |
184 | statbyte h# f5 and if true statbyte false exit then | |
185 | ||
186 | \ Don't retry if we have already retried the specified number | |
187 | \ of times. Return "no-sense,status" | |
188 | #retries 0= if true statbyte false exit then | |
189 | ||
190 | \ Otherwise, it was either a busy or a retryable check condition, | |
191 | \ so we retry. | |
192 | ||
193 | true | |
194 | ; | |
195 | ||
196 | \ RETRY-COMMAND executes a SCSI command. If a check condition is indicated, | |
197 | \ performs a "get-sense" command. If the sense bytes indicate a non-fatal | |
198 | \ condition (e.g. power-on reset occurred, not ready yet, or recoverable | |
199 | \ error), the command is retried until the condition either goes away or | |
200 | \ changes to a fatal error. | |
201 | \ | |
202 | \ The command is retried until: | |
203 | \ a) The command succeeds, or | |
204 | \ b) The select fails, or dma fails, or | |
205 | \ c) The sense bytes indicate an error that we can't retry at this level | |
206 | \ d) The number of retries is exceeded. | |
207 | ||
208 | \ #retries is number of times to retry (0: don't retry, -1: retry forever) | |
209 | \ | |
210 | \ sensebuf is the address of the sense buffer; it is present only | |
211 | \ if f-hw is 0 and error? is non-zero. The length of the sense buffer | |
212 | \ is 8 bytes plus the value in byte 7 of the sense buffer. | |
213 | \ | |
214 | \ f-hw is non-zero if there is a hardware error -- dma fails, select fails, | |
215 | \ etc -- or if the status byte was neither 0 (okay) nor 2 (check condition) | |
216 | \ | |
217 | \ error? is non-zero if there is a transaction error. If error? is 0, | |
218 | \ f-hw and sensebuf are not returned. | |
219 | \ | |
220 | \ If sensebuf is returned, the contents are valid until the next call to | |
221 | \ retry-command. sensebuf becomes inaccessable when this package is closed. | |
222 | \ | |
223 | \ dma-dir is necessary because it is not always possible to infer the DMA | |
224 | \ direction from the command. | |
225 | ||
226 | \ Local variables used by retry-command? | |
227 | ||
228 | 0 instance value dbuf \ Data transfer buffer | |
229 | 0 instance value dlen \ Expected length of data transfer | |
230 | 0 instance value direction-in \ Direction for data transfer | |
231 | ||
232 | -1 instance value cbuf \ Command base address | |
233 | 0 instance value clen \ Actual length of this command | |
234 | ||
235 | external | |
236 | ||
237 | : retry-command ( dma-buf dma-len dma-dir cmdbuf cmdlen #retries -- ... ) | |
238 | ( ... -- [[sensebuf] f-hw] error? ) | |
239 | to #retries to clen to cbuf to direction-in to dlen to dbuf | |
240 | ||
241 | begin | |
242 | dbuf dlen direction-in cbuf clen execute-command ( hwerr | stat 0 ) | |
243 | retry? | |
244 | while | |
245 | #retries 1- to #retries | |
246 | delay-retry | |
247 | repeat | |
248 | ; | |
249 | ||
250 | headers | |
251 | ||
252 | \ Collapses the complete error information returned by retry-command into | |
253 | \ a single error/no-error flag. | |
254 | ||
255 | : error? ( false | true true | sensebuf false true -- error? ) | |
256 | dup if swap 0= if nip then then | |
257 | ; | |
258 | ||
259 | external | |
260 | ||
261 | \ Simplified "retry-command" routine for commands with no data transfer phase | |
262 | \ and simple error checking requirements. | |
263 | ||
264 | : no-data-command ( cmdbuf -- error? ) | |
265 | >r 0 0 true r> 6 -1 retry-command error? | |
266 | ; | |
267 | ||
268 | \ short-data-command executes a command with the following characteristics: | |
269 | \ a) The data direction is incoming | |
270 | \ b) The data length is less than 256 bytes | |
271 | ||
272 | \ The host adapter driver is responsible for supplying the DMA data | |
273 | \ buffer; if the command succeeds, the buffer address is returned. | |
274 | \ The buffer contents become invalid when another SCSI command is | |
275 | \ executed, or when the driver is closed. | |
276 | ||
277 | : short-data-command ( data-len cmdbuf cmdlen -- true | buffer false ) | |
278 | >r >r inq-buf swap true r> r> -1 retry-command ( retry-cmd-results ) | |
279 | error? dup 0= if inq-buf swap then | |
280 | ; | |
281 | ||
282 | headers | |
283 | ||
284 | \ Here begins the implementation of "show-children", a word that | |
285 | \ is intended to be executed interactively, showing the user the | |
286 | \ devices that are attached to the SCSI bus. | |
287 | ||
288 | \ Tool for storing a big-endian 24-bit number at an unaligned address | |
289 | ||
290 | : 3c! ( n addr -- ) >r lbsplit drop r@ c! r@ 1+ c! r> 2+ c! ; | |
291 | ||
292 | ||
293 | \ Command block template for Inquiry command | |
294 | ||
295 | create inquiry-cmd h# 12 c, 0 c, 0 c, 0 c, ff c, 0 c, | |
296 | ||
297 | external | |
298 | ||
299 | : inquiry ( -- error? ) | |
300 | \ 8 retries should be more than enough; inquiry commands aren't | |
301 | \ supposed to respond with "check condition". | |
302 | \ However, empirically, on MC2 EVT1, 8 proves insufficient. | |
303 | ||
304 | inq-buf ff true inquiry-cmd 6 10 retry-command error? | |
305 | ; | |
306 | ||
307 | headers | |
308 | ||
309 | \ Reads the indicated byte from the Inquiry data buffer | |
310 | ||
311 | : inq@ ( offset -- value ) inq-buf + c@ ; | |
312 | ||
313 | : .scsi1-inquiry ( -- ) inq-buf 5 ca+ 4 inq@ fa min type ; | |
314 | : .scsi2-inquiry ( -- ) inq-buf 8 ca+ d# 28 type ; | |
315 | ||
316 | \ Displays the results of an Inquiry command to the indicated device | |
317 | ||
318 | : show-lun ( unit -- ) | |
319 | \ SUN Note - scsi unit address is two cells (target, lun) | |
320 | dup 0 set-address ( unit ) | |
321 | inquiry if drop exit then ( unit ) | |
322 | 0 inq@ h# 60 and if drop exit then ( unit ) | |
323 | ." Unit " . ." " ( ) | |
324 | 1 inq@ h# 80 and if ." Removable " then ( ) | |
325 | 0 inq@ case ( ) | |
326 | ||
327 | 0 of ." Disk " endof | |
328 | 1 of ." Tape " endof | |
329 | 2 of ." Printer " endof | |
330 | 3 of ." Processor " endof | |
331 | 4 of ." WORM " endof | |
332 | 5 of ." Read Only device" endof | |
333 | ( default ) ." Device type " dup .h | |
334 | endcase ( ) | |
335 | ||
336 | 4 spaces | |
337 | 3 inq@ 0f and 2 = if .scsi2-inquiry else .scsi1-inquiry then | |
338 | cr | |
339 | ; | |
340 | ||
341 | external | |
342 | ||
343 | \ Searches for devices on the SCSI bus, displaying the Inquiry information | |
344 | \ for each device that responds. | |
345 | ||
346 | : show-children ( -- ) | |
347 | open 0= if ." Can't open SCSI host adapter" cr exit then | |
348 | ||
349 | max-lun 1+ 0 do i show-lun loop | |
350 | ||
351 | close | |
352 | ; | |
353 | ||
354 | \ Inquire into the specified scsi device type and return the scsi | |
355 | \ type and true if the device at the specified scsi address is found. | |
356 | ||
357 | : get-scsi-type ( lun -- false | type true ) | |
358 | open 0= if 2drop false exit then | |
359 | \ SUN Note - scsi unit address is two cells (target, lun) | |
360 | 0 set-address inquiry | |
361 | if false else 0 inq@ dup 7f = if drop false else true then then | |
362 | close | |
363 | ; | |
364 | ||
365 | headers | |
366 | ||
367 | \ The diagnose command is useful for generic SCSI devices. | |
368 | \ It executes bothe "test-unit-ready" and "send-diagnostic" | |
369 | \ commands, decoding the error status information they return. | |
370 | ||
371 | create test-unit-rdy-cmd 0 c, 0 c, 0 c, 0 c, 0 c, 0 c, | |
372 | create send-diagnostic-cmd h# 1d c, 4 c, 0 c, 0 c, 0 c, 0 c, | |
373 | ||
374 | : send-diagnostic ( -- error? ) send-diagnostic-cmd no-data-command ; | |
375 | ||
376 | ||
377 | external | |
378 | ||
379 | : diagnose ( -- flag ) | |
380 | 0 0 true test-unit-rdy-cmd 6 -1 ( dma$ dir cmd$ #retries ) | |
381 | retry-command if ( [ sensebuf ] hardware-error? ) | |
382 | ." Test unit ready failed - " ( [ sensebuf ] hardware-error? ) | |
383 | if ( ) | |
384 | ." hardware error (no such device?)" cr ( ) | |
385 | else ( sensebuf ) | |
386 | ." extended status = " cr ( sensebuf ) | |
387 | base @ >r hex ( sensebuf ) | |
388 | 8 bounds ?do i 3 u.r loop cr ( ) | |
389 | r> base ! | |
390 | then | |
391 | true | |
392 | else | |
393 | send-diagnostic ( fail? ) | |
394 | then | |
395 | ; | |
396 | ||
397 | headers | |
398 | ||
399 | \ LICENSE_BEGIN | |
400 | \ Copyright (c) 2006 FirmWorks | |
401 | \ | |
402 | \ Permission is hereby granted, free of charge, to any person obtaining | |
403 | \ a copy of this software and associated documentation files (the | |
404 | \ "Software"), to deal in the Software without restriction, including | |
405 | \ without limitation the rights to use, copy, modify, merge, publish, | |
406 | \ distribute, sublicense, and/or sell copies of the Software, and to | |
407 | \ permit persons to whom the Software is furnished to do so, subject to | |
408 | \ the following conditions: | |
409 | \ | |
410 | \ The above copyright notice and this permission notice shall be | |
411 | \ included in all copies or substantial portions of the Software. | |
412 | \ | |
413 | \ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
414 | \ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
415 | \ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
416 | \ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |
417 | \ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |
418 | \ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
419 | \ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
420 | \ | |
421 | \ LICENSE_END |