|
|
1.1 root 1: \ *****************************************************************************
2: \ * Copyright (c) 2011 IBM Corporation
3: \ * All rights reserved.
4: \ * This program and the accompanying materials
5: \ * are made available under the terms of the BSD License
6: \ * which accompanies this distribution, and is available at
7: \ * http://www.opensource.org/licenses/bsd-license.php
8: \ *
9: \ * Contributors:
10: \ * IBM Corporation - initial implementation
11: \ ****************************************************************************/
12:
13: ." Populating " pwd
14:
15: 0 CONSTANT vscsi-debug
16:
17: 0 VALUE vscsi-unit
18:
19: \ -----------------------------------------------------------
20: \ Direct DMA conversion hack
21: \ -----------------------------------------------------------
22: : l2dma ( laddr - dma_addr)
23: ;
24:
25: \ -----------------------------------------------------------
26: \ CRQ related functions
27: \ -----------------------------------------------------------
28:
29: 0 VALUE crq-base
30: 0 VALUE crq-dma
31: 0 VALUE crq-offset
32: 1000 CONSTANT CRQ-SIZE
33:
34: CREATE crq 10 allot
35:
36: : crq-alloc ( -- )
37: \ XXX We rely on SLOF alloc-mem being aligned
38: CRQ-SIZE alloc-mem to crq-base 0 to crq-offset
39: crq-base l2dma to crq-dma
40: ;
41:
42: : crq-free ( -- )
43: vscsi-unit hv-free-crq
44: crq-base CRQ-SIZE free-mem 0 to crq-base
45: ;
46:
47: : crq-init ( -- res )
48: \ Allocate CRQ. XXX deal with fail
49: crq-alloc
50:
51: vscsi-debug IF
52: ." VSCSI: allocated crq at " crq-base . cr
53: THEN
54:
55: \ Clear buffer
56: crq-base CRQ-SIZE erase
57:
58: \ Register with HV
59: vscsi-unit crq-dma CRQ-SIZE hv-reg-crq
60:
61: \ Fail case
62: dup 0 <> IF
63: ." VSCSI: Error " . ." registering CRQ !" cr
64: crq-free
65: THEN
66: ;
67:
68: : crq-cleanup ( -- )
69: crq-base 0 = IF EXIT THEN
70:
71: vscsi-debug IF
72: ." VSCSI: freeing crq at " crq-base . cr
73: THEN
74: crq-free
75: ;
76:
77: : crq-send ( msgaddr -- true | false )
78: vscsi-unit swap hv-send-crq 0 =
79: ;
80:
81: : crq-poll ( -- true | false)
82: crq-offset crq-base + dup
83: vscsi-debug IF
84: ." VSCSI: crq poll " dup .
85: THEN
86: c@
87: vscsi-debug IF
88: ." value=" dup . cr
89: THEN
90: 80 and 0 <> IF
91: dup crq 10 move
92: 0 swap c!
93: crq-offset 10 + dup CRQ-SIZE >= IF drop 0 THEN to crq-offset
94: true
95: ELSE drop false THEN
96: ;
97:
98: : crq-wait ( -- true | false)
99: \ FIXME: Add timeout
100: 0 BEGIN drop crq-poll dup not WHILE d# 1 ms REPEAT
101: dup not IF
102: ." VSCSI: Timeout waiting response !" cr EXIT
103: ELSE
104: vscsi-debug IF
105: ." VSCSI: got crq: " crq dup l@ . ." " 4 + dup l@ . ." "
106: 4 + dup l@ . ." " 4 + l@ . cr
107: THEN
108: THEN
109: ;
110:
111: \ -----------------------------------------------------------
112: \ CRQ encapsulated SRP definitions
113: \ -----------------------------------------------------------
114:
115: 01 CONSTANT VIOSRP_SRP_FORMAT
116: 02 CONSTANT VIOSRP_MAD_FORMAT
117: 03 CONSTANT VIOSRP_OS400_FORMAT
118: 04 CONSTANT VIOSRP_AIX_FORMAT
119: 06 CONSTANT VIOSRP_LINUX_FORMAT
120: 07 CONSTANT VIOSRP_INLINE_FORMAT
121:
122: struct
123: 1 field >crq-valid
124: 1 field >crq-format
125: 1 field >crq-reserved
126: 1 field >crq-status
127: 2 field >crq-timeout
128: 2 field >crq-iu-len
129: 8 field >crq-iu-data-ptr
130: constant /crq
131:
132: : srp-send-crq ( addr len -- )
133: 80 crq >crq-valid c!
134: VIOSRP_SRP_FORMAT crq >crq-format c!
135: 0 crq >crq-reserved c!
136: 0 crq >crq-status c!
137: 0 crq >crq-timeout w!
138: ( len ) crq >crq-iu-len w!
139: ( addr ) l2dma crq >crq-iu-data-ptr x!
140: crq crq-send
141: not IF
142: ." VSCSI: Error sending CRQ !" cr
143: THEN
144: ;
145:
146: : srp-wait-crq ( -- [tag true] | false )
147: crq-wait not IF false EXIT THEN
148:
149: crq >crq-format c@ VIOSRP_SRP_FORMAT <> IF
150: ." VSCSI: Unsupported SRP response: "
151: crq >crq-format c@ . cr
152: false EXIT
153: THEN
154:
155: crq >crq-iu-data-ptr x@ true
156: ;
157:
158: \ Add scsi functions to dictionary
159: scsi-open
160:
161:
162: \ -----------------------------------------------------------
163: \ SRP definitions
164: \ -----------------------------------------------------------
165:
166: 0 VALUE >srp_opcode
167:
168: 00 CONSTANT SRP_LOGIN_REQ
169: 01 CONSTANT SRP_TSK_MGMT
170: 02 CONSTANT SRP_CMD
171: 03 CONSTANT SRP_I_LOGOUT
172: c0 CONSTANT SRP_LOGIN_RSP
173: c1 CONSTANT SRP_RSP
174: c2 CONSTANT SRP_LOGIN_REJ
175: 80 CONSTANT SRP_T_LOGOUT
176: 81 CONSTANT SRP_CRED_REQ
177: 82 CONSTANT SRP_AER_REQ
178: 41 CONSTANT SRP_CRED_RSP
179: 42 CONSTANT SRP_AER_RSP
180:
181: 02 CONSTANT SRP_BUF_FORMAT_DIRECT
182: 04 CONSTANT SRP_BUF_FORMAT_INDIRECT
183:
184: struct
185: 1 field >srp-login-opcode
186: 3 +
187: 8 field >srp-login-tag
188: 4 field >srp-login-req-it-iu-len
189: 4 +
190: 2 field >srp-login-req-buf-fmt
191: 1 field >srp-login-req-flags
192: 5 +
193: 10 field >srp-login-init-port-ids
194: 10 field >srp-login-trgt-port-ids
195: constant /srp-login
196:
197: struct
198: 1 field >srp-lresp-opcode
199: 3 +
200: 4 field >srp-lresp-req-lim-delta
201: 8 field >srp-lresp-tag
202: 4 field >srp-lresp-max-it-iu-len
203: 4 field >srp-lresp-max-ti-iu-len
204: 2 field >srp-lresp-buf-fmt
205: 1 field >srp-lresp-flags
206: constant /srp-login-resp
207:
208: struct
209: 1 field >srp-lrej-opcode
210: 3 +
211: 4 field >srp-lrej-reason
212: 8 field >srp-lrej-tag
213: 8 +
214: 2 field >srp-lrej-buf-fmt
215: constant /srp-login-rej
216:
217: 00 CONSTANT SRP_NO_DATA_DESC
218: 01 CONSTANT SRP_DATA_DESC_DIRECT
219: 02 CONSTANT SRP_DATA_DESC_INDIRECT
220:
221: struct
222: 1 field >srp-cmd-opcode
223: 1 field >srp-cmd-sol-not
224: 3 +
225: 1 field >srp-cmd-buf-fmt
226: 1 field >srp-cmd-dout-desc-cnt
227: 1 field >srp-cmd-din-desc-cnt
228: 8 field >srp-cmd-tag
229: 4 +
230: 8 field >srp-cmd-lun
231: 1 +
232: 1 field >srp-cmd-task-attr
233: 1 +
234: 1 field >srp-cmd-add-cdb-len
235: 10 field >srp-cmd-cdb
236: 0 field >srp-cmd-cdb-add
237: constant /srp-cmd
238:
239: struct
240: 1 field >srp-rsp-opcode
241: 1 field >srp-rsp-sol-not
242: 2 +
243: 4 field >srp-rsp-req-lim-delta
244: 8 field >srp-rsp-tag
245: 2 +
246: 1 field >srp-rsp-flags
247: 1 field >srp-rsp-status
248: 4 field >srp-rsp-dout-res-cnt
249: 4 field >srp-rsp-din-res-cnt
250: 4 field >srp-rsp-sense-len
251: 4 field >srp-rsp-resp-len
252: 0 field >srp-rsp-data
253: constant /srp-rsp
254:
255: \ Storage for up to 256 bytes SRP request */
256: CREATE srp 100 allot
257: 0 VALUE srp-len
258:
259: : srp-prep-cmd-nodata ( id lun -- )
260: srp /srp-cmd erase
261: SRP_CMD srp >srp-cmd-opcode c!
262: 1 srp >srp-cmd-tag x!
1.1.1.2 root 263: srp >srp-cmd-lun 1 + c! \ lun
264: 80 or \ select logical unit addressing method
265: srp >srp-cmd-lun c! \ id
1.1 root 266: /srp-cmd to srp-len
267: ;
268:
269: : srp-prep-cmd-io ( addr len id lun -- )
270: srp-prep-cmd-nodata ( addr len )
271: swap l2dma ( len dmaaddr )
272: srp srp-len + ( len dmaaddr descaddr )
273: dup >r x! r> 8 + ( len descaddr+8 )
274: dup 0 swap l! 4 + ( len descaddr+c )
275: l!
276: srp-len 10 + to srp-len
277: ;
278:
279: : srp-prep-cmd-read ( addr len id lun -- )
280: srp-prep-cmd-io
281: 01 srp >srp-cmd-buf-fmt c! \ in direct buffer
282: 1 srp >srp-cmd-din-desc-cnt c!
283: ;
284:
285: : srp-prep-cmd-write ( addr len id lun -- )
286: srp-prep-cmd-io
287: 10 srp >srp-cmd-buf-fmt c! \ out direct buffer
288: 1 srp >srp-cmd-dout-desc-cnt c!
289: ;
290:
291: : srp-send-cmd ( -- )
292: vscsi-debug IF
293: ." VSCSI: Sending SCSI cmd " srp >srp-cmd-cdb c@ . cr
294: THEN
295: srp srp-len srp-send-crq
296: ;
297:
298: : srp-rsp-find-sense ( -- addr )
299: \ XXX FIXME: Always in same position
300: srp >srp-rsp-data
301: ;
302:
303: : srp-wait-rsp ( -- true | [ ascq asc sense-key false ] )
304: srp-wait-crq not IF false EXIT THEN
305: dup 1 <> IF
306: ." VSCSI: Invalid CRQ response tag, want 1 got " . cr
307: false EXIT
308: THEN drop
309:
310: srp >srp-rsp-tag x@ dup 1 <> IF
311: ." VSCSI: Invalid SRP response tag, want 1 got " . cr
312: false EXIT
313: THEN drop
314:
315: srp >srp-rsp-status c@
316: vscsi-debug IF
317: ." VSCSI: Got response status: "
318: dup .status-text cr
319: THEN
320:
321: 0 <> IF
322: srp-rsp-find-sense
323: scsi-get-sense-data
324: vscsi-debug IF
325: ." VSCSI: Sense key: " dup .sense-text cr
326: THEN
327: false EXIT
328: THEN
329: true
330: ;
331:
332:
333: \ -----------------------------------------------------------
334: \ Core VSCSI
335: \ -----------------------------------------------------------
336:
337: CREATE sector d# 512 allot
338:
1.1.1.2 root 339: 0 INSTANCE VALUE current-id
340: 0 INSTANCE VALUE current-lun
1.1 root 341:
342: \ SCSI test-unit-read
343: : test-unit-ready ( -- true | [ ascq asc sense-key false ] )
344: current-id current-lun srp-prep-cmd-nodata
345: srp >srp-cmd-cdb scsi-build-test-unit-ready
346: srp-send-cmd
347: srp-wait-rsp
348: ;
349:
350: : inquiry ( -- true | false )
351: \ WARNING: ATAPI devices with libata seem to ignore the MSB of
352: \ the allocation length... let's only ask for ff bytes
353: sector ff current-id current-lun srp-prep-cmd-read
354: ff srp >srp-cmd-cdb scsi-build-inquiry
355: srp-send-cmd
356: srp-wait-rsp
357: dup not IF nip nip nip EXIT THEN \ swallow sense
358: ;
359:
360: : read-capacity ( -- true | false )
361: sector scsi-length-read-cap-10 current-id current-lun srp-prep-cmd-read
362: srp >srp-cmd-cdb scsi-build-read-cap-10
363: srp-send-cmd
364: srp-wait-rsp
365: dup not IF nip nip nip EXIT THEN \ swallow sense
366: ;
367:
368: : start-stop-unit ( state# -- true | false )
369: current-id current-lun srp-prep-cmd-nodata
370: srp >srp-cmd-cdb scsi-build-start-stop-unit
371: srp-send-cmd
372: srp-wait-rsp
373: dup not IF nip nip nip EXIT THEN \ swallow sense
374: ;
375:
376: : get-media-event ( -- true | false )
377: sector scsi-length-media-event current-id current-lun srp-prep-cmd-read
378: srp >srp-cmd-cdb scsi-build-get-media-event
379: srp-send-cmd
380: srp-wait-rsp
381: dup not IF nip nip nip EXIT THEN \ swallow sense
382: ;
383:
384: : read-blocks ( -- addr block# #blocks blksz -- [ #read-blocks true ] | false )
385: over * ( addr block# #blocks len )
386: >r rot r> ( block# #blocks addr len )
387: 5 0 DO
388: 2dup current-id current-lun
389: srp-prep-cmd-read ( block# #blocks addr len )
390: 2swap ( addr len block# #blocks )
391: 2dup srp >srp-cmd-cdb scsi-build-read-10 ( addr len block# #blocks )
392: 2swap ( block# #blocks addr len )
393: srp-send-cmd
394: srp-wait-rsp
395: IF 2drop nip true UNLOOP EXIT THEN
396: srp >srp-rsp-status c@ 8 <> IF
397: nip nip nip 2drop 2drop false EXIT
398: THEN
399: 3drop
400: 100 ms
401: LOOP
402: 2drop 2drop false
403: ;
404:
405: \ Cleanup behind us
406: : vscsi-cleanup
1.1.1.3 ! root 407: \ ." VSCSI: Cleaning up" cr
1.1 root 408: crq-cleanup
1.1.1.3 ! root 409: \ Disable TCE bypass:
1.1 root 410: vscsi-unit 0 rtas-set-tce-bypass
411: ;
412:
413: \ Initialize our vscsi instance
414: : vscsi-init ( -- true | false )
415: ." VSCSI: Initializing" cr
416:
417: \ Can't use my-unit bcs we aren't instanciating (fix this ?)
418: " reg" get-node get-package-property IF
419: ." VSCSI: Not reg property !!!" 0
420: THEN
421: decode-int to vscsi-unit 2drop
422:
423: \ Enable TCE bypass special qemu feature
424: vscsi-unit 1 rtas-set-tce-bypass
425:
426: \ Initialize CRQ
427: crq-init 0 <> IF false EXIT THEN
428:
429: \ Send init command
430: " "(C0 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00)" drop
431: crq-send not IF
432: ." VSCSI: Error sending init command"
433: crq-cleanup false EXIT
434: THEN
435:
436: \ Wait reply
437: crq-wait not IF
438: crq-cleanup false EXIT
439: THEN
440:
441: \ Check init reply
442: crq c@ c0 <> crq 1 + c@ 02 <> or IF
443: ." VSCSI: Initial handshake failed"
444: crq-cleanup false EXIT
445: THEN
446:
447: \ We should now login etc.. but we really don't need to
448: \ with our qemu model
449:
450: \ Ensure we cleanup after booting
451: ['] vscsi-cleanup add-quiesce-xt
452:
453: true
454: ;
455:
456: \ -----------------------------------------------------------
457: \ SCSI scan at boot and child device support
458: \ -----------------------------------------------------------
459:
460: : set-address ( lun id -- )
1.1.1.2 root 461: to current-id to current-lun
1.1 root 462: ;
463:
464: : dev-max-transfer ( -- n )
465: 10000 \ Larger value seem to have problems with some CDROMs
466: ;
467:
468: : dev-get-capacity ( -- blocksize #blocks )
1.1.1.2 root 469: \ Make sure that there are zeros in the buffer in case something goes wrong:
470: sector 10 erase
471: \ Now issue the read-capacity command
472: read-capacity not IF
473: 0 0 EXIT
474: THEN
1.1 root 475: sector scsi-get-capacity-10
476: ;
477:
478: : dev-read-blocks ( -- addr block# #blocks blksize -- #read-blocks )
479: read-blocks
480: ;
481:
482: : initial-test-unit-ready ( -- true | [ ascq asc sense-key false ] )
483: 0 0 0 false
484: 3 0 DO
485: 2drop 2drop
486: test-unit-ready dup IF UNLOOP EXIT THEN
487: LOOP
488: ;
489:
490: : compare-sense ( ascq asc key ascq2 asc2 key2 -- true | false )
491: 3 pick = ( ascq asc key ascq2 asc2 keycmp )
492: swap 4 pick = ( ascq asc key ascq2 keycmp asccmp )
493: rot 5 pick = ( ascq asc key keycmp asccmp ascqcmp )
494: and and nip nip nip
495: ;
496:
497: 0 CONSTANT CDROM-READY
498: 1 CONSTANT CDROM-NOT-READY
499: 2 CONSTANT CDROM-NO-DISK
500: 3 CONSTANT CDROM-TRAY-OPEN
501: 4 CONSTANT CDROM-INIT-REQUIRED
502: 5 CONSTANT CDROM-TRAY-MAYBE-OPEN
503:
504: : cdrom-status ( -- status )
505: initial-test-unit-ready
506: IF CDROM-READY EXIT THEN
507:
508: vscsi-debug IF
509: ." TestUnitReady sense: " 3dup . . . cr
510: THEN
511:
512: 3dup 1 4 2 compare-sense IF
513: 3drop CDROM-NOT-READY EXIT
514: THEN
515:
516: get-media-event IF
517: sector w@ 4 >= IF
518: sector 2 + c@ 04 = IF
519: sector 5 + c@
520: dup 02 and 0<> IF drop 3drop CDROM-READY EXIT THEN
521: dup 01 and 0<> IF drop 3drop CDROM-TRAY-OPEN EXIT THEN
522: drop 3drop CDROM-NO-DISK EXIT
523: THEN
524: THEN
525: THEN
526:
527: 3dup 2 4 2 compare-sense IF
528: 3drop CDROM-INIT-REQUIRED EXIT
529: THEN
530: over 4 = over 2 = and IF
531: \ Format in progress... what do we do ? Just ignore
532: 3drop CDROM-READY EXIT
533: THEN
534: over 3a = IF
535: 3drop CDROM-NO-DISK EXIT
536: THEN
537:
538: \ Other error...
539: 3drop CDROM-TRAY-MAYBE-OPEN
540: ;
541:
542: : cdrom-try-close-tray ( -- )
543: scsi-const-load start-stop-unit drop
544: ;
545:
546: : cdrom-must-close-tray ( -- )
547: scsi-const-load start-stop-unit not IF
548: ." Tray open !" cr -65 throw
549: THEN
550: ;
551:
552: : dev-prep-cdrom ( -- )
553: 5 0 DO
554: cdrom-status CASE
555: CDROM-READY OF UNLOOP EXIT ENDOF
556: CDROM-NO-DISK OF ." No medium !" cr -65 THROW ENDOF
557: CDROM-TRAY-OPEN OF cdrom-must-close-tray ENDOF
558: CDROM-INIT-REQUIRED OF cdrom-try-close-tray ENDOF
559: CDROM-TRAY-MAYBE-OPEN OF cdrom-try-close-tray ENDOF
560: ENDCASE
561: d# 1000 ms
562: LOOP
563: ." Drive not ready !" cr -65 THROW
564: ;
565:
566: : dev-prep-disk ( -- )
1.1.1.2 root 567: initial-test-unit-ready 0= IF
568: ." Disk not ready!" cr
569: 3drop
570: THEN
1.1 root 571: ;
572:
573: : vscsi-create-disk ( lun id -- )
574: " disk" 0 " vio-vscsi-device.fs" included
575: ;
576:
577: : vscsi-create-cdrom ( lun id -- )
578: " cdrom" 1 " vio-vscsi-device.fs" included
579: ;
580:
581: : wrapped-inquiry ( -- true | false )
582: inquiry not IF false EXIT THEN
583: \ Skip devices with PQ != 0
584: sector inquiry-data>peripheral c@ e0 and 0 =
585: ;
586:
587: 8 CONSTANT #dev
588: : vscsi-find-disks ( -- )
589: ." VSCSI: Looking for disks" cr
590: #dev 0 DO \ check 8 devices (no LUNs)
1.1.1.2 root 591: 0 i set-address
1.1 root 592: wrapped-inquiry IF
593: ." SCSI ID " i .
594: \ XXX FIXME: Check top bits to ignore unsupported units
595: \ and maybe provide better printout & more cases
596: sector inquiry-data>peripheral c@ CASE
597: 0 OF ." DISK : " 0 i vscsi-create-disk ENDOF
598: 5 OF ." CD-ROM : " 0 i vscsi-create-cdrom ENDOF
599: 7 OF ." OPTICAL : " 0 i vscsi-create-cdrom ENDOF
600: e OF ." RED-BLOCK: " 0 i vscsi-create-disk ENDOF
601: dup dup OF ." ? (" . 8 emit 29 emit 5 spaces ENDOF
602: ENDCASE
603: sector .inquiry-text cr
604: THEN
605: LOOP
606: ;
607:
608: \ Remove scsi functions from word list
609: scsi-close
610:
611: : setup-alias
612: " scsi" find-alias 0= IF
613: " scsi" get-node node>path set-alias
1.1.1.3 ! root 614: ELSE
! 615: drop
! 616: THEN
1.1 root 617: ;
618:
619: : vscsi-init-and-scan ( -- )
1.1.1.2 root 620: \ Create instance for scanning:
621: 0 0 get-node open-node ?dup 0= IF EXIT THEN
622: my-self >r
623: dup to my-self
624: \ Scan the VSCSI bus:
1.1 root 625: vscsi-init IF
626: vscsi-find-disks
1.1.1.2 root 627: setup-alias
1.1 root 628: THEN
1.1.1.2 root 629: \ Close the temporary instance:
630: close-node
631: r> to my-self
1.1 root 632: ;
633:
634: vscsi-init-and-scan
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.