Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / slof / fs / scsi-host-helpers.fs
1 \ This file is meant to be included by SCSI hosts to provide
2 \ helpers such as retry-scsi-command
3
4 \ Returns 1 for retry, 0 for return with no error and
5 \ -1 for return with an error
6 \
7 : check-retry-sense? ( sense-buf sense-len -- retry? )
8     \ Check if the sense-len is at least 8 bytes
9     8 < IF -1 EXIT THEN
10
11     \ Fixed sense record, look for filemark etc...
12     dup sense-data>response-code c@ 7e and 70 = IF
13         dup sense-data>sense-key c@ e0 and IF drop -1 EXIT THEN
14     THEN
15
16     \ Get sense data
17     scsi-get-sense-data? IF     ( ascq asc sense-key )
18         \ No sense or recoverable, return success
19         dup 2 < IF 3drop 0 EXIT THEN
20         \ not ready and unit attention, retry
21         dup 2 = swap 6 = or nip nip IF 1 EXIT THEN
22     THEN
23     \ Return failure
24     -1
25 ;
26
27 \ This is almost as the standard retry-command but returns
28 \ additionally the length of the returned sense information
29 \
30 \ The hw-err? field is gone, stat is -1 for a HW error, and
31 \ the sense data is provided iff stat is CHECK_CONDITION (02)
32 \
33 \ Additionally we wait 10ms between retries
34 \
35 0 INSTANCE VALUE rcmd-buf-addr
36 0 INSTANCE VALUE rcmd-buf-len
37 0 INSTANCE VALUE rcmd-dir
38 0 INSTANCE VALUE rcmd-cmd-addr
39 0 INSTANCE VALUE rcmd-cmd-len
40
41 : retry-scsi-command ( buf-addr buf-len dir cmd-addr cmd-len #retries -- ... )
42                      ( ... 0 | [ sense-buf sense-len ] stat )
43     >r \ stash #retries
44     to rcmd-cmd-len to rcmd-cmd-addr to rcmd-dir to rcmd-buf-len to rcmd-buf-addr
45     0  \ dummy status & sense
46     r> \ retreive #retries              ( stat #retries )
47     0 DO
48         \ drop previous status & sense
49         0<> IF 2drop THEN
50
51         \ Restore arguments
52         rcmd-buf-addr
53         rcmd-buf-len
54         rcmd-dir
55         rcmd-cmd-addr
56         rcmd-cmd-len
57
58         \ Send command
59         execute-scsi-command            ( [ sense-buf sense-len ] stat )
60
61         \ Success ?
62         dup 0= IF LEAVE THEN
63
64         \ HW error ?
65         dup -1 = IF LEAVE THEN
66
67         \ Check condition ?
68         dup 2 = IF                      ( sense-buf sense-len stat )
69             >r  \ stash stat            ( sense-buf sense len )
70             2dup
71             check-retry-sense?          ( sense-buf sense-len retry? )
72             r> swap \ unstash stat      ( sense-buf sense-len stat retry? )
73             \ Check retry? result
74             CASE
75                  0 OF 3drop 0 LEAVE ENDOF       \ Swallow error, return 0
76                 -1 OF LEAVE ENDOF               \ No retry
77             ENDCASE
78         ELSE \ Anything other than busy -> exit
79             dup 8 <> IF LEAVE THEN
80         THEN
81         a ms
82     LOOP
83 ;
84
85 \ -----------------------------------------------------------
86 \ Some command helpers
87 \ -----------------------------------------------------------
88 \
89 \ TODO: Get rid of global "sector" and instead return an
90 \ allocated block for the caller to free
91
92 CREATE sector d# 512 allot
93 CREATE cdb 10 allot
94
95 : (inquiry) ( size -- buffer | NULL )
96     dup cdb scsi-build-inquiry
97     \ 16 retries for inquiry to flush out any UAs
98     sector swap scsi-dir-read cdb scsi-param-size 10 retry-scsi-command
99     \ Success ?
100     0= IF sector ELSE 2drop 0 THEN
101 ;
102
103 \ Read the initial 36bytes and then decide how much more is to be read
104 : inquiry ( -- buffer | NULL )
105     d# 36 (inquiry) 0= IF 0 EXIT THEN
106     sector inquiry-data>add-length c@ 5 +
107     (inquiry)
108 ;
109
110 : report-luns ( -- [ sector ] true | false )
111     200 cdb scsi-build-report-luns
112     \ 16 retries to flush out any UAs
113     sector 200 scsi-dir-read cdb scsi-param-size 10 retry-scsi-command
114     \ Success ?
115     0= IF sector true ELSE drop false THEN
116 ;
117
118 \ This routine creates a disk alias for the first found disk/cdrom
119 : make-disk-alias                               ( $name srplun -- )
120     >r 2dup r> -rot                             ( $name srplun $name)
121     find-alias 0<> IF 4drop exit THEN
122     get-node node>path
123     20 allot
124     " /disk@" string-cat                        ( $name srplun npath npathl )
125     rot base @ >r hex (u.) r> base ! string-cat ( $name $diskpath )
126     set-alias
127 ;