|
|
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
407: ." VSCSI: Cleaning up" cr
408:
409: crq-cleanup
410:
411: \ Disable TCE bypass
412: vscsi-unit 0 rtas-set-tce-bypass
413: ;
414:
415: \ Initialize our vscsi instance
416: : vscsi-init ( -- true | false )
417: ." VSCSI: Initializing" cr
418:
419: \ Can't use my-unit bcs we aren't instanciating (fix this ?)
420: " reg" get-node get-package-property IF
421: ." VSCSI: Not reg property !!!" 0
422: THEN
423: decode-int to vscsi-unit 2drop
424:
425: \ Enable TCE bypass special qemu feature
426: vscsi-unit 1 rtas-set-tce-bypass
427:
428: \ Initialize CRQ
429: crq-init 0 <> IF false EXIT THEN
430:
431: \ Send init command
432: " "(C0 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00)" drop
433: crq-send not IF
434: ." VSCSI: Error sending init command"
435: crq-cleanup false EXIT
436: THEN
437:
438: \ Wait reply
439: crq-wait not IF
440: crq-cleanup false EXIT
441: THEN
442:
443: \ Check init reply
444: crq c@ c0 <> crq 1 + c@ 02 <> or IF
445: ." VSCSI: Initial handshake failed"
446: crq-cleanup false EXIT
447: THEN
448:
449: \ We should now login etc.. but we really don't need to
450: \ with our qemu model
451:
452: \ Ensure we cleanup after booting
453: ['] vscsi-cleanup add-quiesce-xt
454:
455: true
456: ;
457:
458: \ -----------------------------------------------------------
459: \ SCSI scan at boot and child device support
460: \ -----------------------------------------------------------
461:
462: : set-address ( lun id -- )
1.1.1.2 ! root 463: to current-id to current-lun
1.1 root 464: ;
465:
466: : dev-max-transfer ( -- n )
467: 10000 \ Larger value seem to have problems with some CDROMs
468: ;
469:
470: : dev-get-capacity ( -- blocksize #blocks )
1.1.1.2 ! root 471: \ Make sure that there are zeros in the buffer in case something goes wrong:
! 472: sector 10 erase
! 473: \ Now issue the read-capacity command
! 474: read-capacity not IF
! 475: 0 0 EXIT
! 476: THEN
1.1 root 477: sector scsi-get-capacity-10
478: ;
479:
480: : dev-read-blocks ( -- addr block# #blocks blksize -- #read-blocks )
481: read-blocks
482: ;
483:
484: : initial-test-unit-ready ( -- true | [ ascq asc sense-key false ] )
485: 0 0 0 false
486: 3 0 DO
487: 2drop 2drop
488: test-unit-ready dup IF UNLOOP EXIT THEN
489: LOOP
490: ;
491:
492: : compare-sense ( ascq asc key ascq2 asc2 key2 -- true | false )
493: 3 pick = ( ascq asc key ascq2 asc2 keycmp )
494: swap 4 pick = ( ascq asc key ascq2 keycmp asccmp )
495: rot 5 pick = ( ascq asc key keycmp asccmp ascqcmp )
496: and and nip nip nip
497: ;
498:
499: 0 CONSTANT CDROM-READY
500: 1 CONSTANT CDROM-NOT-READY
501: 2 CONSTANT CDROM-NO-DISK
502: 3 CONSTANT CDROM-TRAY-OPEN
503: 4 CONSTANT CDROM-INIT-REQUIRED
504: 5 CONSTANT CDROM-TRAY-MAYBE-OPEN
505:
506: : cdrom-status ( -- status )
507: initial-test-unit-ready
508: IF CDROM-READY EXIT THEN
509:
510: vscsi-debug IF
511: ." TestUnitReady sense: " 3dup . . . cr
512: THEN
513:
514: 3dup 1 4 2 compare-sense IF
515: 3drop CDROM-NOT-READY EXIT
516: THEN
517:
518: get-media-event IF
519: sector w@ 4 >= IF
520: sector 2 + c@ 04 = IF
521: sector 5 + c@
522: dup 02 and 0<> IF drop 3drop CDROM-READY EXIT THEN
523: dup 01 and 0<> IF drop 3drop CDROM-TRAY-OPEN EXIT THEN
524: drop 3drop CDROM-NO-DISK EXIT
525: THEN
526: THEN
527: THEN
528:
529: 3dup 2 4 2 compare-sense IF
530: 3drop CDROM-INIT-REQUIRED EXIT
531: THEN
532: over 4 = over 2 = and IF
533: \ Format in progress... what do we do ? Just ignore
534: 3drop CDROM-READY EXIT
535: THEN
536: over 3a = IF
537: 3drop CDROM-NO-DISK EXIT
538: THEN
539:
540: \ Other error...
541: 3drop CDROM-TRAY-MAYBE-OPEN
542: ;
543:
544: : cdrom-try-close-tray ( -- )
545: scsi-const-load start-stop-unit drop
546: ;
547:
548: : cdrom-must-close-tray ( -- )
549: scsi-const-load start-stop-unit not IF
550: ." Tray open !" cr -65 throw
551: THEN
552: ;
553:
554: : dev-prep-cdrom ( -- )
555: 5 0 DO
556: cdrom-status CASE
557: CDROM-READY OF UNLOOP EXIT ENDOF
558: CDROM-NO-DISK OF ." No medium !" cr -65 THROW ENDOF
559: CDROM-TRAY-OPEN OF cdrom-must-close-tray ENDOF
560: CDROM-INIT-REQUIRED OF cdrom-try-close-tray ENDOF
561: CDROM-TRAY-MAYBE-OPEN OF cdrom-try-close-tray ENDOF
562: ENDCASE
563: d# 1000 ms
564: LOOP
565: ." Drive not ready !" cr -65 THROW
566: ;
567:
568: : dev-prep-disk ( -- )
1.1.1.2 ! root 569: initial-test-unit-ready 0= IF
! 570: ." Disk not ready!" cr
! 571: 3drop
! 572: THEN
1.1 root 573: ;
574:
575: : vscsi-create-disk ( lun id -- )
576: " disk" 0 " vio-vscsi-device.fs" included
577: ;
578:
579: : vscsi-create-cdrom ( lun id -- )
580: " cdrom" 1 " vio-vscsi-device.fs" included
581: ;
582:
583: : wrapped-inquiry ( -- true | false )
584: inquiry not IF false EXIT THEN
585: \ Skip devices with PQ != 0
586: sector inquiry-data>peripheral c@ e0 and 0 =
587: ;
588:
589: 8 CONSTANT #dev
590: : vscsi-find-disks ( -- )
591: ." VSCSI: Looking for disks" cr
592: #dev 0 DO \ check 8 devices (no LUNs)
1.1.1.2 ! root 593: 0 i set-address
1.1 root 594: wrapped-inquiry IF
595: ." SCSI ID " i .
596: \ XXX FIXME: Check top bits to ignore unsupported units
597: \ and maybe provide better printout & more cases
598: sector inquiry-data>peripheral c@ CASE
599: 0 OF ." DISK : " 0 i vscsi-create-disk ENDOF
600: 5 OF ." CD-ROM : " 0 i vscsi-create-cdrom ENDOF
601: 7 OF ." OPTICAL : " 0 i vscsi-create-cdrom ENDOF
602: e OF ." RED-BLOCK: " 0 i vscsi-create-disk ENDOF
603: dup dup OF ." ? (" . 8 emit 29 emit 5 spaces ENDOF
604: ENDCASE
605: sector .inquiry-text cr
606: THEN
607: LOOP
608: ;
609:
610: \ Remove scsi functions from word list
611: scsi-close
612:
613: : setup-alias
614: " scsi" find-alias 0= IF
615: " scsi" get-node node>path set-alias
616: ELSE THEN
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.