Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / obp / dev / scsi / targets / scsidisk.fth
CommitLineData
920dae64
AT
1\ ========== Copyright Header Begin ==========================================
2\
3\ Hypervisor Software File: scsidisk.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 ============================================
42id: @(#)scsidisk.fth 1.9 06/04/21
43purpose:
44copyright: Copyright 2006 Sun Microsystems, Inc. All Rights Reserved
45copyright: Use is subject to license terms.
46
47\ SCSI disk package implementing a "block" device-type interface.
48
49" block" device-type
50
51fload ${BP}/dev/scsi/targets/scsicom.fth \ Utility routines
52
53hex
54
55\ 0 means no timeout
56: set-timeout ( msecs -- ) " set-timeout" $call-parent ;
57
580 instance value offset-low \ Offset to start of partition
590 instance value offset-high
60
610 instance value label-package
62
63\ Sets offset-low and offset-high, reflecting the starting location of the
64\ partition specified by the "my-args" string.
65
66: init-label-package ( -- okay? )
67 0 to offset-high 0 to offset-low
68 my-args " disk-label" $open-package to label-package
69 label-package if
70 0 0 " offset" label-package $call-method to offset-high to offset-low
71 true
72 else
73 ." Can't open disk label package" cr false
74 then
75;
76
77
78\ Ensures that the disk is spinning, but doesn't wait forever
79
80create sstart-cmd h# 1b c, 1 c, 0 c, 0 c, 1 c, 0 c,
81
82headers
83
84: timed-spin ( up? -- error? )
85 d# 15000 set-timeout ( up? )
86 sstart-cmd 4 + c! ( )
87 0 0 true sstart-cmd 6 d# 60 retry-command if ( true | sensebuf false )
88 \ true on top of the stack indicates a hardware error.
89 \ We don't treat "illegal request" as an error because some drives
90 \ don't support the start command. Everything else other than
91 \ success is considered an error.
92 if true else 2+ c@ 5 <> then ( error? )
93 else ( )
94 false ( false )
95 then ( error? )
96
97 0 set-timeout
98;
99
100headerless
101
1020 instance value /block \ Device native block size
103
104create mode-sense-bd h# 1a c, 0 c, 0 c, 0 c, d# 12 c, 0 c,
105create read-capacity-cmd h# 25 c, 0 c, 0 c, 0 c, 0 c, 0 c, 0 c, 0 c, 0 c, 0 c,
106
107: read-block-extent ( -- true | block-size #blocks false )
108 \ First try "read capacity" - data returned in bytes 4,5,6,7
109 \ The SCSI-2 standard requires disk devices to implement
110 \ the "read capacity" command.
111
112 8 read-capacity-cmd 0a short-data-command 0= if
113 dup 4 + 4c@ swap 4c@ 1+ false exit
114 then
115
116 \ Failing that, try "mode sense" with an allocation length big enough only
117 \ for the header and the block descriptor
118
119 d# 12 mode-sense-bd 6 short-data-command 0= if
120 dup 9 + 3c@ swap 4 + 4c@ false exit
121 then
122
123 true
124;
125: read-block-size ( -- n ) \ Ask device about its block size
126 read-block-extent if d# 512 else drop then
127;
128
129headers
130
131[ifdef] report-geometry
132create mode-sense-geometry h# 1a c, 0 c, 4 c, 0 c, d# 36 c, 0 c,
133
134\ The sector/track value reported below is an average, because modern SCSI
135\ disks often have variable geometry - fewer sectors on the inner cylinders
136\ and spare sectors and tracks located at various places on the disk.
137\ If you multiply the sectors/track number obtained from the format info
138\ mode sense code page by the heads and cylinders obtained from the geometry
139\ page, the number of blocks thus calculated usually exceeds the number of
140\ logical blocks reported in the mode sense block descriptor, often by a
141\ factor of about 25%.
142
143\ Return true for error, otherwise disk geometry and false
144: geometry ( -- true | sectors/track #heads #cylinders false )
145 d# 36 mode-sense-geometry 6 short-data-command if true exit then >r
146 r@ d# 17 + c@ r@ d# 14 + 3c@ ( heads cylinders )
147 2dup * r> d# 4 + 4c@ ( heads cylinders heads*cylinders #blocks )
148 swap / -rot ( sectors/track heads cylinders )
149 false
150;
151[then]
152
153external
154
155: #blocks ( -- true | n false )
156 read-block-extent if true else nip then
157;
158
159\ Return device block size; cache it the first time we find the information
160\ This method is called by the deblocker
161: block-size ( -- n )
162 /block if /block exit then \ Don't ask if we already know
163
164 read-block-size dup to /block
165;
166
167headers
168
169\ Read or write "#blks" blocks starting at "block#" into memory at "addr"
170\ Input? is true for reading or false for writing.
171\ command is 8 for reading or h# a for writing
172\ We use the 6-byte forms of the disk read and write commands where possible.
173
174: 2c! ( n addr -- ) >r lbsplit 2drop r> +c! c! ;
175: 4c! ( n addr -- ) >r lbsplit r> +c! +c! +c! c! ;
176
177: r/w-blocks ( addr block# #blks input? command -- actual# )
178 cmdbuf d# 10 erase ( addr block# #blks dir cmd )
179[ifndef] FORCE-READ10?
180 2over h# 100 u> swap h# 200000 u>= or if ( addr block# #blks dir cmd )
181[then]
182 \ Use 10-byte form
183 h# 20 or 0 cb! \ 28 (read) or 2a (write) ( addr block# #blks dir )
184 -rot swap ( addr dir #blks block# )
185 cmdbuf 2 + 4c! ( addr dir #blks )
186 dup cmdbuf 7 + 2c! ( addr dir #blks )
187 d# 10 ( addr dir #blks cmdlen )
188[ifndef] FORCE-READ10?
189 else ( addr block# #blks dir cmd )
190 \ Use 6-byte form
191 0 cb! ( addr block# #blks dir )
192 -rot swap ( addr dir #blks block# )
193 cmdbuf 1+ 3c! ( addr dir #blks )
194 dup 4 cb! ( addr dir #blks )
195 6 ( addr dir #blks cmdlen )
196 then
197[then]
198 swap ( addr dir cmdlen #blks )
199 dup >r ( addr input? cmdlen #blks )
200 /block * -rot cmdbuf swap -1 ( addr #bytes input? cmd cmdlen #retries )
201 retry-command if ( [ sensebuf ] hw? )
202 0= if drop then r> drop 0
203 else
204 r>
205 then ( actual# )
206;
207
208: set-address ( -- ) my-unit " set-address" $call-parent ;
209
210headers
211
212: device-present? ( -- condition )
213 my-unit " device-present?" $call-parent
214;
215
216headerless
217create eject-cmd h# 1b c, 1 c, 0 c, 0 c, 2 c, 0 c,
218
219external
220: eject ( -- )
221 set-address device-present? if
222 eject-cmd no-data-command drop
223 then
224;
225
226\ These three methods are called by the deblocker.
227
228: max-transfer ( -- n ) parent-max-transfer ;
229: read-blocks ( addr block# #blocks -- #read ) true d# 8 r/w-blocks ;
230: write-blocks ( addr block# #blocks -- #written ) false d# 10 r/w-blocks ;
231
232\ Methods used by external clients
233
234\ Spun down devices and empty CDROMs return condition 2
235\ so we will attempt to spin up the device and then check its
236\ condition again.
237
238: retry-device? ( condition -- condition' )
239 dup 2 = if
240 drop 1 timed-spin if
241 device-present?
242 else
243 true
244 then
245 then
246;
247
248external
249
250: open ( -- flag )
251
252 set-address device-present? retry-device?
253 case
254 0 of true endof \ missing so bail
255 2 of true endof \ Check Condition.. bail
256 false swap \ Everything else looks cool.
257 endcase
258 if false exit then
259
260 block-size to /block
261
262 init-deblocker 0= if false exit then
263
264 init-label-package 0= if
265 deblocker close-package false exit
266 then
267 true
268;
269
270: close ( -- )
271 label-package close-package
272 deblocker close-package
273;
274
275: seek ( offset.low offset.high -- okay? )
276 offset-low offset-high d+ " seek" deblocker $call-method
277;
278
279: read ( addr len -- actual-len ) " read" deblocker $call-method ;
280: write ( addr len -- actual-len ) " write" deblocker $call-method ;
281: load ( addr -- size ) " load" label-package $call-method ;
282
283: size ( -- d.size ) " size" label-package $call-method ;
284headers