| \ ***************************************************************************** |
| \ * Copyright (c) 2012 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 cr |
| |
| FALSE CONSTANT virtio-scsi-debug |
| |
| 2 encode-int s" #address-cells" property |
| 0 encode-int s" #size-cells" property |
| |
| : decode-unit 2 hex64-decode-unit ; |
| : encode-unit 2 hex64-encode-unit ; |
| |
| FALSE VALUE initialized? |
| |
| virtio-setup-vd VALUE virtiodev |
| |
| STRUCT \ virtio-scsi-config |
| /l FIELD vs-cfg>num-queues |
| /l FIELD vs-cfg>seg-max |
| /l FIELD vs-cfg>max-sectors |
| /l FIELD vs-cfg>cmd-per-lun |
| /l FIELD vs-cfg>event-info-size |
| /l FIELD vs-cfg>sense_size |
| /l FIELD vs-cfg>cdb-size |
| /w FIELD vs-cfg>max-channel |
| /w FIELD vs-cfg>max-target |
| /l FIELD vs-cfg>max-lun |
| CONSTANT vs-cfg-length |
| |
| STRUCT \ virtio-scsi-req |
| 8 FIELD vs-req>lun |
| 8 FIELD vs-req>tag |
| /c FIELD vs-req>task-attr |
| /c FIELD vs-req>prio |
| /c FIELD vs-req>crn |
| 20 FIELD vs-req>cdb |
| CONSTANT vs-req-length |
| |
| STRUCT \ virtio-scsi-resp |
| /l FIELD vs-rsp>sense-len |
| /l FIELD vs-rsp>residual |
| /w FIELD vs-rsp>status-qualifier |
| /c FIELD vs-rsp>status |
| /c FIELD vs-rsp>response |
| 60 FIELD vs-rsp>sense |
| CONSTANT vs-rsp-length |
| |
| CREATE vs-req vs-req-length allot |
| CREATE vs-rsp vs-rsp-length allot |
| |
| scsi-open |
| |
| \ ----------------------------------------------------------- |
| \ Perform SCSI commands |
| \ ----------------------------------------------------------- |
| |
| 0 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 ) |
| \ Cleanup virtio request and response |
| vs-req vs-req-length erase |
| vs-rsp vs-rsp-length erase |
| |
| \ Populate the request |
| current-target vs-req vs-req>lun x! |
| vs-req vs-req>cdb swap move |
| |
| \ Send it |
| vs-req vs-rsp virtiodev |
| virtio-scsi-send |
| |
| 0 <> IF |
| ." VIRTIO-SCSI: Queuing failure !" cr |
| 0 0 -1 EXIT |
| THEN |
| |
| \ Check virtio response |
| vs-rsp vs-rsp>response c@ CASE |
| 0 OF ENDOF \ Good |
| 5 OF drop 0 0 8 EXIT ENDOF \ Busy |
| dup OF 0 0 -1 EXIT ENDOF \ Anything else -> HW error |
| ENDCASE |
| |
| \ Other error status |
| vs-rsp vs-rsp>status c@ dup 0<> IF |
| vs-rsp vs-rsp>sense-len l@ dup 0= IF |
| \ This relies on auto-sense from qemu... if that isn't always the |
| \ case we should request sense here |
| ." VIRTIO-SCSI: No sense data" cr |
| 0 EXIT |
| THEN |
| vs-rsp vs-rsp>sense swap |
| virtio-scsi-debug IF |
| over scsi-get-sense-data |
| ." VIRTIO-SCSI: Sense key [ " dup . ." ] " .sense-text |
| ." ASC,ASCQ: " . . cr |
| THEN |
| rot |
| THEN |
| ; |
| |
| \ -------------------------------- |
| \ Include the generic host helpers |
| \ -------------------------------- |
| |
| " scsi-host-helpers.fs" included |
| |
| \ FIXME: Check max transfer coming from virtio config |
| : max-transfer ( -- n ) |
| 10000 \ Larger value seem to have problems with some CDROMs |
| ; |
| |
| \ ----------------------------------------------------------- |
| \ SCSI scan at boot and child device support |
| \ ----------------------------------------------------------- |
| |
| \ We use SRP luns of the form 01000000 | (target << 16) | lun |
| \ in the top 32 bits of the 64-bit LUN |
| : (set-target) |
| to current-target |
| ; |
| |
| : dev-generate-srplun ( target lun-id -- srplun ) |
| dup ff > IF 4000 or THEN \ Use the LUN "flat space addressing method" |
| swap 0100 or 10 << or 20 << |
| ; |
| |
| \ 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) |
| ; |
| |
| 100 CONSTANT #target |
| : dev-max-target ( -- #target ) |
| #target |
| ; |
| |
| " scsi-probe-helpers.fs" included |
| |
| scsi-close \ no further scsi words required |
| |
| \ Set scsi alias if none is set yet |
| : setup-alias |
| s" scsi" find-alias 0= IF |
| s" scsi" get-node node>path set-alias |
| ELSE |
| drop |
| THEN |
| ; |
| |
| : shutdown ( -- ) |
| initialized? IF |
| my-phandle node>path open-dev ?dup IF |
| virtiodev virtio-scsi-shutdown |
| close-dev |
| THEN |
| FALSE to initialized? |
| THEN |
| ; |
| |
| : virtio-scsi-init-and-scan ( -- ) |
| \ Create instance for scanning: |
| 0 0 get-node open-node ?dup 0= IF ." exiting " cr EXIT THEN |
| my-self >r |
| dup to my-self |
| \ Scan the VSCSI bus: |
| virtiodev virtio-scsi-init |
| 0= IF |
| scsi-find-disks |
| setup-alias |
| TRUE to initialized? |
| ['] shutdown add-quiesce-xt |
| THEN |
| \ Close the temporary instance: |
| close-node |
| r> to my-self |
| ; |
| |
| : virtio-scsi-add-disk |
| " scsi-disk.fs" included |
| ; |
| |
| virtio-scsi-add-disk |
| virtio-scsi-init-and-scan |