Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / obp / dev / usb2 / device / storage / scsidisk.fth
\ ========== Copyright Header Begin ==========================================
\
\ Hypervisor Software File: scsidisk.fth
\
\ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
\
\ - Do no alter or remove copyright notices
\
\ - Redistribution and use of this software in source and binary forms, with
\ or without modification, are permitted provided that the following
\ conditions are met:
\
\ - Redistribution of source code must retain the above copyright notice,
\ this list of conditions and the following disclaimer.
\
\ - Redistribution in binary form must reproduce the above copyright notice,
\ this list of conditions and the following disclaimer in the
\ documentation and/or other materials provided with the distribution.
\
\ Neither the name of Sun Microsystems, Inc. or the names of contributors
\ may be used to endorse or promote products derived from this software
\ without specific prior written permission.
\
\ This software is provided "AS IS," without a warranty of any kind.
\ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
\ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
\ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
\ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
\ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
\ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
\ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
\ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
\ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
\ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
\ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
\
\ You acknowledge that this software is not designed, licensed or
\ intended for use in the design, construction, operation or maintenance of
\ any nuclear facility.
\
\ ========== Copyright Header End ============================================
id: @(#)scsidisk.fth 1.1 07/01/04
purpose: SCSI disk package implementing a "block" device-type interface.
copyright: Copyright 2007 Sun Microsystems, Inc. All Rights Reserved
\ See license at end of file
hex
" block" device-type
" sd" encode-string \ SUN Note - ancient history, our disk driver is "sd"
" disk" encode-string encode+ " compatible" property
fload ${BP}/dev/usb2/device/storage/scsicom.fth \ Utility routines for SCSI commands
hex
\ 0 means no timeout
: set-timeout ( msecs -- ) " set-timeout" $call-parent ;
0 instance value offset-low \ Offset to start of partition
0 instance value offset-high
external
0 instance value label-package
true value report-failure
headers
\ Sets offset-low and offset-high, reflecting the starting location of the
\ partition specified by the "my-args" string.
: init-label-package ( -- okay? )
0 to offset-high 0 to offset-low
my-args " disk-label" $open-package to label-package
label-package dup if
0 0 " offset" label-package $call-method to offset-high to offset-low
else
report-failure if
." Can't open disk label package" cr
then
then
;
\ Ensures that the disk is spinning, but doesn't wait forever
create sstart-cmd h# 1b c, 0 c, 0 c, 0 c, 1 c, 0 c,
: timed-spin ( -- error? )
\ Set timeout to 45 sec: some large (>1GB) drives take
\ up to 30 secs to spin up.
d# 45 d# 1000 * set-timeout
0 0 true sstart-cmd 6 -1 retry-command if ( true | sensebuf false )
\ true on top of the stack indicates a hardware error.
\ We don't treat "illegal request" as an error because some drives
\ don't support the start command. Everything else other than
\ success is considered an error.
if true else 2+ c@ 5 <> then ( error? )
else ( )
false ( false )
then ( error? )
0 set-timeout
;
0 instance value /block \ Device native block size
create mode-sense-bd h# 1a c, 0 c, 0 c, 0 c, d# 12 c, 0 c,
create read-capacity-cmd h# 25 c, 0 c, 0 c, 0 c, 0 c, 0 c, 0 c, 0 c, 0 c, 0 c,
: read-block-extent ( -- true | block-size #blocks false )
\ First try "read capacity" - data returned in bytes 4,5,6,7
\ The SCSI-2 standard requires disk devices to implement
\ the "read capacity" command.
8 read-capacity-cmd 0a short-data-command 0= if
dup 4 + 4c@ swap 4c@ 1+ false exit
then
\ Failing that, try "mode sense" with an allocation length big enough only
\ for the header and the block descriptor, in case it's a SCSI-1 device
d# 12 mode-sense-bd 6 short-data-command 0= if ( adr )
dup 9 + 3c@ swap 4 + 4c@ false exit
then
true
;
: read-block-size ( -- n ) \ Ask device about its block size
read-block-extent if d# 512 else drop then
;
external
[ifdef] report-geometry
create mode-sense-geometry h# 1a c, 0 c, 4 c, 0 c, d# 36 c, 0 c,
\ The sector/track value reported below is an average, because modern SCSI
\ disks often have variable geometry - fewer sectors on the inner cylinders
\ and spare sectors and tracks located at various places on the disk.
\ If you multiply the sectors/track number obtained from the format info
\ mode sense code page by the heads and cylinders obtained from the geometry
\ page, the number of blocks thus calculated usually exceeds the number of
\ logical blocks reported in the mode sense block descriptor, often by a
\ factor of about 25%.
\ Return true for error, otherwise disk geometry and false
: geometry ( -- true | sectors/track #heads #cylinders false )
d# 36 mode-sense-geometry 6 short-data-command if true exit then >r
r@ d# 17 + c@ r@ d# 14 + 3c@ ( heads cylinders )
2dup * r> d# 4 + 4c@ ( heads cylinders heads*cylinders #blocks )
swap / -rot ( sectors/track heads cylinders )
false
;
[then]
: #blocks ( -- true | n false )
read-block-extent if true else nip then
;
\ Return device block size; cache it the first time we find the information
\ This method is called by the deblocker
: block-size ( -- n )
/block if /block exit then \ Don't ask if we already know
read-block-size dup to /block
;
headers
\ Read or write "#blks" blocks starting at "block#" into memory at "addr"
\ Input? is true for reading or false for writing.
\ command is 8 for reading or h# a for writing
\ We use the 6-byte forms of the disk read and write commands where possible.
: 2c! ( n addr -- ) >r lbsplit 2drop r> +c! c! ;
: 4c! ( n addr -- ) >r lbsplit r> +c! +c! +c! c! ;
: r/w-blocks ( addr block# #blks input? command -- actual# )
cmdbuf /cmdbuf erase
[ifdef] use-short-form
2over h# 100 u> swap h# 20.0000 u>= or if ( addr block# #blks dir cmd )
[then]
\ Use 10-byte form
h# 20 or 0 cb! \ 28 (read) or 2a (write) ( addr block# #blks dir )
-rot swap ( addr dir #blks block# )
cmdbuf 2 + 4c! ( addr dir #blks )
dup cmdbuf 7 + 2c! ( addr dir #blks )
d# 10 ( addr dir #blks cmdlen )
[ifdef] use-short-form
else ( addr block# #blks dir cmd )
\ Use 6-byte form
0 cb! ( addr block# #blks dir )
-rot swap ( addr dir #blks block# )
cmdbuf 1+ 3c! ( addr dir #blks )
dup 4 cb! ( addr dir #blks )
6 ( addr dir #blks cmdlen )
then
[then]
swap ( addr dir cmdlen #blks )
dup >r ( addr input? cmdlen #blks )
/block * -rot cmdbuf swap -1 ( addr #bytes input? cmd cmdlen #retries )
retry-command if ( [ sensebuf ] hw? )
0= if drop then r> drop 0
else
r>
then ( actual# )
;
external
\ These three methods are called by the deblocker.
: max-transfer ( -- n ) parent-max-transfer ;
: read-blocks ( addr block# #blocks -- #read )
\ SUN Note - the following does not exist on SUN machines. Besides,
\ sticking an "evaluate" in the middle of code is bad form.
\ " show-progress" evaluate
true d# 8 r/w-blocks
;
: write-blocks ( addr block# #blocks -- #written ) false d# 10 r/w-blocks ;
\ Methods used by external clients
: open ( -- flag )
my-unit " set-address" $call-parent
\ It might be a good idea to do an inquiry here to determine the
\ device configuration, checking the result to see if the device
\ really is a disk.
\ Make sure the disk is spinning
timed-spin if false exit then
block-size to /block
init-deblocker 0= if false exit then
init-label-package 0= if
deblocker close-package false exit
then
true
;
: close ( -- )
label-package close-package
deblocker close-package
;
: seek ( offset.low offset.high -- okay? )
offset-low offset-high d+ " seek" deblocker $call-method
;
: read ( addr len -- actual-len ) " read" deblocker $call-method ;
: write ( addr len -- actual-len ) " write" deblocker $call-method ;
: load ( addr -- size ) " load" label-package $call-method ;
: size ( -- d.size ) " size" label-package $call-method ;
headers
\ LICENSE_BEGIN
\ Copyright (c) 2006 FirmWorks
\
\ Permission is hereby granted, free of charge, to any person obtaining
\ a copy of this software and associated documentation files (the
\ "Software"), to deal in the Software without restriction, including
\ without limitation the rights to use, copy, modify, merge, publish,
\ distribute, sublicense, and/or sell copies of the Software, and to
\ permit persons to whom the Software is furnished to do so, subject to
\ the following conditions:
\
\ The above copyright notice and this permission notice shall be
\ included in all copies or substantial portions of the Software.
\
\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
\ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
\ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
\ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\
\ LICENSE_END