summaryrefslogtreecommitdiffstats
path: root/qemu/roms/SLOF/board-qemu/slof/vio-vscsi.fs
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/SLOF/board-qemu/slof/vio-vscsi.fs')
-rw-r--r--qemu/roms/SLOF/board-qemu/slof/vio-vscsi.fs546
1 files changed, 546 insertions, 0 deletions
diff --git a/qemu/roms/SLOF/board-qemu/slof/vio-vscsi.fs b/qemu/roms/SLOF/board-qemu/slof/vio-vscsi.fs
new file mode 100644
index 000000000..f2d4c6fcc
--- /dev/null
+++ b/qemu/roms/SLOF/board-qemu/slof/vio-vscsi.fs
@@ -0,0 +1,546 @@
+\ *****************************************************************************
+\ * Copyright (c) 2011 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+." Populating " pwd
+
+false VALUE vscsi-debug?
+0 VALUE vscsi-unit
+
+\ -----------------------------------------------------------
+\ Direct DMA conversion hack
+\ -----------------------------------------------------------
+: l2dma ( laddr - dma_addr)
+;
+
+\ -----------------------------------------------------------
+\ CRQ related functions
+\ -----------------------------------------------------------
+
+0 VALUE crq-real-base
+0 VALUE crq-base
+0 VALUE crq-dma
+0 VALUE crq-offset
+1000 CONSTANT CRQ-SIZE
+
+CREATE crq 10 allot
+
+: crq-alloc ( -- )
+ \ Allocate enough to align to a page
+ CRQ-SIZE fff + alloc-mem to crq-real-base
+ \ align the result
+ crq-real-base fff + fffff000 AND to crq-base 0 to crq-offset
+ crq-base l2dma to crq-dma
+;
+
+: crq-free ( -- )
+ vscsi-unit hv-free-crq
+ crq-real-base CRQ-SIZE fff + free-mem 0 to crq-base 0 to crq-real-base
+;
+
+: crq-init ( -- res )
+ \ Allocate CRQ. XXX deal with fail
+ crq-alloc
+
+ vscsi-debug? IF
+ ." VSCSI: allocated crq at " crq-base . cr
+ THEN
+
+ \ Clear buffer
+ crq-base CRQ-SIZE erase
+
+ \ Register with HV
+ vscsi-unit crq-dma CRQ-SIZE hv-reg-crq
+
+ \ Fail case
+ dup 0 <> IF
+ ." VSCSI: Error " . ." registering CRQ !" cr
+ crq-free
+ THEN
+;
+
+: crq-cleanup ( -- )
+ crq-base 0 = IF EXIT THEN
+
+ vscsi-debug? IF
+ ." VSCSI: freeing crq at " crq-base . cr
+ THEN
+ crq-free
+;
+
+: crq-send ( msgaddr -- true | false )
+ vscsi-unit swap hv-send-crq 0 =
+;
+
+: crq-poll ( -- true | false)
+ crq-offset crq-base + dup
+ vscsi-debug? IF
+ ." VSCSI: crq poll " dup .
+ THEN
+ c@
+ vscsi-debug? IF
+ ." value=" dup . cr
+ THEN
+ 80 and 0 <> IF
+ dup crq 10 move
+ 0 swap c!
+ crq-offset 10 + dup CRQ-SIZE >= IF drop 0 THEN to crq-offset
+ true
+ ELSE drop false THEN
+;
+
+: crq-wait ( -- true | false)
+ \ FIXME: Add timeout
+ 0 BEGIN drop crq-poll dup not WHILE d# 1 ms REPEAT
+ dup not IF
+ ." VSCSI: Timeout waiting response !" cr EXIT
+ ELSE
+ vscsi-debug? IF
+ ." VSCSI: got crq: " crq dup l@ . ." " 4 + dup l@ . ." "
+ 4 + dup l@ . ." " 4 + l@ . cr
+ THEN
+ THEN
+;
+
+\ -----------------------------------------------------------
+\ CRQ encapsulated SRP definitions
+\ -----------------------------------------------------------
+
+01 CONSTANT VIOSRP_SRP_FORMAT
+02 CONSTANT VIOSRP_MAD_FORMAT
+03 CONSTANT VIOSRP_OS400_FORMAT
+04 CONSTANT VIOSRP_AIX_FORMAT
+06 CONSTANT VIOSRP_LINUX_FORMAT
+07 CONSTANT VIOSRP_INLINE_FORMAT
+
+struct
+ 1 field >crq-valid
+ 1 field >crq-format
+ 1 field >crq-reserved
+ 1 field >crq-status
+ 2 field >crq-timeout
+ 2 field >crq-iu-len
+ 8 field >crq-iu-data-ptr
+constant /crq
+
+: srp-send-crq ( addr len -- )
+ 80 crq >crq-valid c!
+ VIOSRP_SRP_FORMAT crq >crq-format c!
+ 0 crq >crq-reserved c!
+ 0 crq >crq-status c!
+ 0 crq >crq-timeout w!
+ ( len ) crq >crq-iu-len w!
+ ( addr ) l2dma crq >crq-iu-data-ptr x!
+ crq crq-send
+ not IF
+ ." VSCSI: Error sending CRQ !" cr
+ THEN
+;
+
+: srp-wait-crq ( -- [tag true] | false )
+ crq-wait not IF false EXIT THEN
+
+ crq >crq-format c@ VIOSRP_SRP_FORMAT <> IF
+ ." VSCSI: Unsupported SRP response: "
+ crq >crq-format c@ . cr
+ false EXIT
+ THEN
+
+ crq >crq-iu-data-ptr x@ true
+;
+
+\ Add scsi functions to dictionary
+scsi-open
+
+
+\ -----------------------------------------------------------
+\ SRP definitions
+\ -----------------------------------------------------------
+
+0 VALUE >srp_opcode
+
+00 CONSTANT SRP_LOGIN_REQ
+01 CONSTANT SRP_TSK_MGMT
+02 CONSTANT SRP_CMD
+03 CONSTANT SRP_I_LOGOUT
+c0 CONSTANT SRP_LOGIN_RSP
+c1 CONSTANT SRP_RSP
+c2 CONSTANT SRP_LOGIN_REJ
+80 CONSTANT SRP_T_LOGOUT
+81 CONSTANT SRP_CRED_REQ
+82 CONSTANT SRP_AER_REQ
+41 CONSTANT SRP_CRED_RSP
+42 CONSTANT SRP_AER_RSP
+
+02 CONSTANT SRP_BUF_FORMAT_DIRECT
+04 CONSTANT SRP_BUF_FORMAT_INDIRECT
+
+struct
+ 1 field >srp-login-opcode
+ 3 +
+ 8 field >srp-login-tag
+ 4 field >srp-login-req-it-iu-len
+ 4 +
+ 2 field >srp-login-req-buf-fmt
+ 1 field >srp-login-req-flags
+ 5 +
+ 10 field >srp-login-init-port-ids
+ 10 field >srp-login-trgt-port-ids
+constant /srp-login
+
+struct
+ 1 field >srp-lresp-opcode
+ 3 +
+ 4 field >srp-lresp-req-lim-delta
+ 8 field >srp-lresp-tag
+ 4 field >srp-lresp-max-it-iu-len
+ 4 field >srp-lresp-max-ti-iu-len
+ 2 field >srp-lresp-buf-fmt
+ 1 field >srp-lresp-flags
+constant /srp-login-resp
+
+struct
+ 1 field >srp-lrej-opcode
+ 3 +
+ 4 field >srp-lrej-reason
+ 8 field >srp-lrej-tag
+ 8 +
+ 2 field >srp-lrej-buf-fmt
+constant /srp-login-rej
+
+00 CONSTANT SRP_NO_DATA_DESC
+01 CONSTANT SRP_DATA_DESC_DIRECT
+02 CONSTANT SRP_DATA_DESC_INDIRECT
+
+struct
+ 1 field >srp-cmd-opcode
+ 1 field >srp-cmd-sol-not
+ 3 +
+ 1 field >srp-cmd-buf-fmt
+ 1 field >srp-cmd-dout-desc-cnt
+ 1 field >srp-cmd-din-desc-cnt
+ 8 field >srp-cmd-tag
+ 4 +
+ 8 field >srp-cmd-lun
+ 1 +
+ 1 field >srp-cmd-task-attr
+ 1 +
+ 1 field >srp-cmd-add-cdb-len
+ 10 field >srp-cmd-cdb
+ 0 field >srp-cmd-cdb-add
+constant /srp-cmd
+
+struct
+ 1 field >srp-rsp-opcode
+ 1 field >srp-rsp-sol-not
+ 2 +
+ 4 field >srp-rsp-req-lim-delta
+ 8 field >srp-rsp-tag
+ 2 +
+ 1 field >srp-rsp-flags
+ 1 field >srp-rsp-status
+ 4 field >srp-rsp-dout-res-cnt
+ 4 field >srp-rsp-din-res-cnt
+ 4 field >srp-rsp-sense-len
+ 4 field >srp-rsp-resp-len
+ 0 field >srp-rsp-data
+constant /srp-rsp
+
+\ Constants for srp-rsp-flags
+01 CONSTANT SRP_RSP_FLAG_RSPVALID
+02 CONSTANT SRP_RSP_FLAG_SNSVALID
+04 CONSTANT SRP_RSP_FLAG_DOOVER
+05 CONSTANT SRP_RSP_FLAG_DOUNDER
+06 CONSTANT SRP_RSP_FLAG_DIOVER
+07 CONSTANT SRP_RSP_FLAG_DIUNDER
+
+\ Storage for up to 256 bytes SRP request */
+CREATE srp 100 allot
+0 VALUE srp-len
+
+: srp-prep-cmd-nodata ( srplun -- )
+ srp /srp-cmd erase
+ SRP_CMD srp >srp-cmd-opcode c!
+ 1 srp >srp-cmd-tag x!
+ srp >srp-cmd-lun x! \ 8 bytes lun
+ /srp-cmd to srp-len
+;
+
+: srp-prep-cmd-io ( addr len srplun -- )
+ srp-prep-cmd-nodata ( addr len )
+ swap l2dma ( len dmaaddr )
+ srp srp-len + ( len dmaaddr descaddr )
+ dup >r x! r> 8 + ( len descaddr+8 )
+ dup 0 swap l! 4 + ( len descaddr+c )
+ l!
+ srp-len 10 + to srp-len
+;
+
+: srp-prep-cmd-read ( addr len srplun -- )
+ srp-prep-cmd-io
+ 01 srp >srp-cmd-buf-fmt c! \ in direct buffer
+ 1 srp >srp-cmd-din-desc-cnt c!
+;
+
+: srp-prep-cmd-write ( addr len srplun -- )
+ srp-prep-cmd-io
+ 10 srp >srp-cmd-buf-fmt c! \ out direct buffer
+ 1 srp >srp-cmd-dout-desc-cnt c!
+;
+
+: srp-send-cmd ( -- )
+ vscsi-debug? IF
+ ." VSCSI: Sending SCSI cmd " srp >srp-cmd-cdb c@ . cr
+ THEN
+ srp srp-len srp-send-crq
+;
+
+: srp-rsp-find-sense ( -- addr len true | false )
+ srp >srp-rsp-flags c@ SRP_RSP_FLAG_SNSVALID and 0= IF
+ false EXIT
+ THEN
+ \ XXX FIXME: We assume the sense data is right at response
+ \ data. A different server might actually have both
+ \ some response data we need to skip *and* some sense
+ \ data.
+ srp >srp-rsp-data srp >srp-rsp-sense-len l@ true
+;
+
+\ Wait for a response to the last sent SRP command
+\ returns a SCSI status code or -1 (HW error).
+\
+: srp-wait-rsp ( -- stat )
+ srp-wait-crq not IF false EXIT THEN
+ dup 1 <> IF
+ ." VSCSI: Invalid CRQ response tag, want 1 got " . cr
+ -1 EXIT
+ THEN drop
+
+ srp >srp-rsp-tag x@ dup 1 <> IF
+ ." VSCSI: Invalid SRP response tag, want 1 got " . cr
+ -1 EXIT
+ THEN drop
+
+ srp >srp-rsp-status c@
+ vscsi-debug? IF
+ ." VSCSI: Got response status: "
+ dup .status-text cr
+ THEN
+;
+
+\ -----------------------------------------------------------
+\ Perform SCSI commands
+\ -----------------------------------------------------------
+
+8000000000000000 INSTANCE VALUE current-target
+
+\ SCSI command. We do *NOT* implement the "standard" execute-command
+\ because that doesn't have a way to return the sense buffer back, and
+\ we do have auto-sense with some hosts. Instead we implement a made-up
+\ do-scsi-command.
+\
+\ Note: stat is -1 for "hw error" (ie, error queuing the command or
+\ getting the response).
+\
+\ A sense buffer is returned whenever the status is non-0 however
+\ if sense-len is 0 then no sense data is actually present
+\
+
+: execute-scsi-command ( buf-addr buf-len dir cmd-addr cmd-len -- ... )
+ ( ... [ sense-buf sense-len ] stat )
+ \ Stash command addr & len
+ >r >r ( buf-addr buf-len dir )
+ \ Command has no data ?
+ over 0= IF
+ 3drop current-target srp-prep-cmd-nodata
+ ELSE
+ \ Command is a read ?
+ current-target swap IF srp-prep-cmd-read ELSE srp-prep-cmd-write THEN
+ THEN
+ \ Recover command and copy it to our srp buffer
+ r> r>
+ srp >srp-cmd-cdb swap move
+ srp-send-cmd
+ srp-wait-rsp
+
+ \ Check for HW error
+ dup -1 = IF
+ 0 0 rot EXIT
+ THEN
+
+ \ Other error status
+ dup 0<> IF
+ srp-rsp-find-sense IF
+ vscsi-debug? IF
+ over scsi-get-sense-data
+ ." VSCSI: Sense key [ " dup . ." ] " .sense-text
+ ." ASC,ASCQ: " . . cr
+ THEN
+ ELSE 0 0
+ \ This relies on auto-sense from qemu... if that isn't always the
+ \ case we should request sense here
+ ." VSCSI: No sense data" cr
+ THEN
+ rot
+ THEN
+;
+
+\ --------------------------------
+\ Include the generic host helpers
+\ --------------------------------
+
+" scsi-host-helpers.fs" included
+
+TRUE VALUE first-time-init?
+0 VALUE open-count
+
+\ Cleanup behind us
+: vscsi-cleanup
+ vscsi-debug? IF ." VSCSI: Cleaning up" cr THEN
+ crq-cleanup
+
+ \ Disable TCE bypass:
+ vscsi-unit 0 rtas-set-tce-bypass
+;
+
+\ Initialize our vscsi instance
+: vscsi-init ( -- true | false )
+ vscsi-debug? IF ." VSCSI: Initializing" cr THEN
+
+ my-unit to vscsi-unit
+
+ \ Enable TCE bypass special qemu feature
+ vscsi-unit 1 rtas-set-tce-bypass
+
+ \ Initialize CRQ
+ crq-init 0 <> IF false EXIT THEN
+
+ \ Send init command
+ " "(C0 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00)" drop
+ crq-send not IF
+ ." VSCSI: Error sending init command"
+ crq-cleanup false EXIT
+ THEN
+
+ \ Wait reply
+ crq-wait not IF
+ crq-cleanup false EXIT
+ THEN
+
+ \ Check init reply
+ crq c@ c0 <> crq 1 + c@ 02 <> or IF
+ ." VSCSI: Initial handshake failed"
+ crq-cleanup false EXIT
+ THEN
+
+ \ We should now login etc.. but we really don't need to
+ \ with our qemu model
+
+ \ Ensure we cleanup after booting
+ first-time-init? IF
+ ['] vscsi-cleanup add-quiesce-xt
+ false to first-time-init?
+ THEN
+
+ true
+;
+
+: open
+ vscsi-debug? IF ." VSCSI: Opening (count is " open-count . ." )" cr THEN
+
+ open-count 0= IF
+ vscsi-init IF
+ 1 to open-count true
+ ELSE ." VSCSI initialization failed !" cr false THEN
+ ELSE
+ open-count 1 + to open-count
+ true
+ THEN
+;
+
+: close
+ vscsi-debug? IF ." VSCSI: Closing (count is " open-count . ." )" cr THEN
+
+ open-count 0> IF
+ open-count 1 - dup to open-count
+ 0= IF
+ vscsi-cleanup
+ THEN
+ THEN
+;
+
+\ -----------------------------------------------------------
+\ SCSI scan at boot and child device support
+\ -----------------------------------------------------------
+
+\ We use SRP luns of the form 8000 | (bus << 8) | (id << 5) | lun
+\ in the top 16 bits of the 64-bit LUN
+: (set-target)
+ to current-target
+;
+
+: dev-generate-srplun ( target lun -- )
+ swap 8 << 8000 or or 30 <<
+;
+
+\ We obtain here a unit address on the stack, since our #address-cells
+\ is 2, the 64-bit srplun is split in two cells that we need to join
+\
+\ Note: This diverges a bit from the original OF scsi spec as the two
+\ cells are the 2 words of a 64-bit SRP LUN
+: set-address ( srplun.lo srplun.hi -- )
+ lxjoin (set-target)
+;
+
+\ We set max-transfer to a fixed value for now to avoid problems
+\ with some CD-ROM drives.
+\ FIXME: Check max transfer coming from VSCSI
+: max-transfer ( -- n )
+ 10000 \ Larger value seem to have problems with some CDROMs
+;
+
+8 CONSTANT #dev
+: dev-max-target ( -- #max-target )
+ #dev
+;
+
+" scsi-probe-helpers.fs" included
+
+\ Remove scsi functions from word list
+scsi-close
+
+: setup-alias
+ " scsi" find-alias 0= IF
+ " scsi" get-node node>path set-alias
+ ELSE
+ drop
+ THEN
+;
+
+: vscsi-init-and-scan ( -- )
+ \ Create instance for scanning:
+ 0 0 get-node open-node ?dup 0= IF EXIT THEN
+ my-self >r
+ dup to my-self
+ \ Scan the VSCSI bus:
+ scsi-find-disks
+ setup-alias
+ \ Close the temporary instance:
+ close-node
+ r> to my-self
+;
+
+: vscsi-add-disk
+ " scsi-disk.fs" included
+;
+
+vscsi-add-disk
+vscsi-init-and-scan