|
|
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!
263: srp >srp-cmd-lun 1 + c! \ lun
264: srp >srp-cmd-lun c! \ id
265: /srp-cmd to srp-len
266: ;
267:
268: : srp-prep-cmd-io ( addr len id lun -- )
269: srp-prep-cmd-nodata ( addr len )
270: swap l2dma ( len dmaaddr )
271: srp srp-len + ( len dmaaddr descaddr )
272: dup >r x! r> 8 + ( len descaddr+8 )
273: dup 0 swap l! 4 + ( len descaddr+c )
274: l!
275: srp-len 10 + to srp-len
276: ;
277:
278: : srp-prep-cmd-read ( addr len id lun -- )
279: srp-prep-cmd-io
280: 01 srp >srp-cmd-buf-fmt c! \ in direct buffer
281: 1 srp >srp-cmd-din-desc-cnt c!
282: ;
283:
284: : srp-prep-cmd-write ( addr len id lun -- )
285: srp-prep-cmd-io
286: 10 srp >srp-cmd-buf-fmt c! \ out direct buffer
287: 1 srp >srp-cmd-dout-desc-cnt c!
288: ;
289:
290: : srp-send-cmd ( -- )
291: vscsi-debug IF
292: ." VSCSI: Sending SCSI cmd " srp >srp-cmd-cdb c@ . cr
293: THEN
294: srp srp-len srp-send-crq
295: ;
296:
297: : srp-rsp-find-sense ( -- addr )
298: \ XXX FIXME: Always in same position
299: srp >srp-rsp-data
300: ;
301:
302: : srp-wait-rsp ( -- true | [ ascq asc sense-key false ] )
303: srp-wait-crq not IF false EXIT THEN
304: dup 1 <> IF
305: ." VSCSI: Invalid CRQ response tag, want 1 got " . cr
306: false EXIT
307: THEN drop
308:
309: srp >srp-rsp-tag x@ dup 1 <> IF
310: ." VSCSI: Invalid SRP response tag, want 1 got " . cr
311: false EXIT
312: THEN drop
313:
314: srp >srp-rsp-status c@
315: vscsi-debug IF
316: ." VSCSI: Got response status: "
317: dup .status-text cr
318: THEN
319:
320: 0 <> IF
321: srp-rsp-find-sense
322: scsi-get-sense-data
323: vscsi-debug IF
324: ." VSCSI: Sense key: " dup .sense-text cr
325: THEN
326: false EXIT
327: THEN
328: true
329: ;
330:
331:
332: \ -----------------------------------------------------------
333: \ Core VSCSI
334: \ -----------------------------------------------------------
335:
336: CREATE sector d# 512 allot
337:
338: 0 VALUE current-id
339: 0 VALUE current-lun
340:
341: \ SCSI test-unit-read
342: : test-unit-ready ( -- true | [ ascq asc sense-key false ] )
343: current-id current-lun srp-prep-cmd-nodata
344: srp >srp-cmd-cdb scsi-build-test-unit-ready
345: srp-send-cmd
346: srp-wait-rsp
347: ;
348:
349: : inquiry ( -- true | false )
350: \ WARNING: ATAPI devices with libata seem to ignore the MSB of
351: \ the allocation length... let's only ask for ff bytes
352: sector ff current-id current-lun srp-prep-cmd-read
353: ff srp >srp-cmd-cdb scsi-build-inquiry
354: srp-send-cmd
355: srp-wait-rsp
356: dup not IF nip nip nip EXIT THEN \ swallow sense
357: ;
358:
359: : read-capacity ( -- true | false )
360: sector scsi-length-read-cap-10 current-id current-lun srp-prep-cmd-read
361: srp >srp-cmd-cdb scsi-build-read-cap-10
362: srp-send-cmd
363: srp-wait-rsp
364: dup not IF nip nip nip EXIT THEN \ swallow sense
365: ;
366:
367: : start-stop-unit ( state# -- true | false )
368: current-id current-lun srp-prep-cmd-nodata
369: srp >srp-cmd-cdb scsi-build-start-stop-unit
370: srp-send-cmd
371: srp-wait-rsp
372: dup not IF nip nip nip EXIT THEN \ swallow sense
373: ;
374:
375: : get-media-event ( -- true | false )
376: sector scsi-length-media-event current-id current-lun srp-prep-cmd-read
377: srp >srp-cmd-cdb scsi-build-get-media-event
378: srp-send-cmd
379: srp-wait-rsp
380: dup not IF nip nip nip EXIT THEN \ swallow sense
381: ;
382:
383: : read-blocks ( -- addr block# #blocks blksz -- [ #read-blocks true ] | false )
384: over * ( addr block# #blocks len )
385: >r rot r> ( block# #blocks addr len )
386: 5 0 DO
387: 2dup current-id current-lun
388: srp-prep-cmd-read ( block# #blocks addr len )
389: 2swap ( addr len block# #blocks )
390: 2dup srp >srp-cmd-cdb scsi-build-read-10 ( addr len block# #blocks )
391: 2swap ( block# #blocks addr len )
392: srp-send-cmd
393: srp-wait-rsp
394: IF 2drop nip true UNLOOP EXIT THEN
395: srp >srp-rsp-status c@ 8 <> IF
396: nip nip nip 2drop 2drop false EXIT
397: THEN
398: 3drop
399: 100 ms
400: LOOP
401: 2drop 2drop false
402: ;
403:
404: \ Cleanup behind us
405: : vscsi-cleanup
406: ." VSCSI: Cleaning up" cr
407:
408: crq-cleanup
409:
410: \ Disable TCE bypass
411: vscsi-unit 0 rtas-set-tce-bypass
412: ;
413:
414: \ Initialize our vscsi instance
415: : vscsi-init ( -- true | false )
416: ." VSCSI: Initializing" cr
417:
418: \ Can't use my-unit bcs we aren't instanciating (fix this ?)
419: " reg" get-node get-package-property IF
420: ." VSCSI: Not reg property !!!" 0
421: THEN
422: decode-int to vscsi-unit 2drop
423:
424: \ Enable TCE bypass special qemu feature
425: vscsi-unit 1 rtas-set-tce-bypass
426:
427: \ Initialize CRQ
428: crq-init 0 <> IF false EXIT THEN
429:
430: \ Send init command
431: " "(C0 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00)" drop
432: crq-send not IF
433: ." VSCSI: Error sending init command"
434: crq-cleanup false EXIT
435: THEN
436:
437: \ Wait reply
438: crq-wait not IF
439: crq-cleanup false EXIT
440: THEN
441:
442: \ Check init reply
443: crq c@ c0 <> crq 1 + c@ 02 <> or IF
444: ." VSCSI: Initial handshake failed"
445: crq-cleanup false EXIT
446: THEN
447:
448: \ We should now login etc.. but we really don't need to
449: \ with our qemu model
450:
451: \ Ensure we cleanup after booting
452: ['] vscsi-cleanup add-quiesce-xt
453:
454: true
455: ;
456:
457: \ -----------------------------------------------------------
458: \ SCSI scan at boot and child device support
459: \ -----------------------------------------------------------
460:
461: 0 INSTANCE VALUE target-id
462: 0 INSTANCE VALUE target-lun
463:
464: : set-address ( lun id -- )
465: to target-id to target-lun
466: ;
467:
468: : dev-max-transfer ( -- n )
469: 10000 \ Larger value seem to have problems with some CDROMs
470: ;
471:
472: : dev-get-capacity ( -- blocksize #blocks )
473: target-id to current-id target-lun to current-lun
474: read-capacity not IF 0 0 EXIT THEN
475: sector scsi-get-capacity-10
476: ;
477:
478: : dev-read-blocks ( -- addr block# #blocks blksize -- #read-blocks )
479: target-id to current-id target-lun to current-lun
480: read-blocks
481: ;
482:
483: : initial-test-unit-ready ( -- true | [ ascq asc sense-key false ] )
484: 0 0 0 false
485: 3 0 DO
486: 2drop 2drop
487: test-unit-ready dup IF UNLOOP EXIT THEN
488: LOOP
489: ;
490:
491: : compare-sense ( ascq asc key ascq2 asc2 key2 -- true | false )
492: 3 pick = ( ascq asc key ascq2 asc2 keycmp )
493: swap 4 pick = ( ascq asc key ascq2 keycmp asccmp )
494: rot 5 pick = ( ascq asc key keycmp asccmp ascqcmp )
495: and and nip nip nip
496: ;
497:
498: 0 CONSTANT CDROM-READY
499: 1 CONSTANT CDROM-NOT-READY
500: 2 CONSTANT CDROM-NO-DISK
501: 3 CONSTANT CDROM-TRAY-OPEN
502: 4 CONSTANT CDROM-INIT-REQUIRED
503: 5 CONSTANT CDROM-TRAY-MAYBE-OPEN
504:
505: : cdrom-status ( -- status )
506: initial-test-unit-ready
507: IF CDROM-READY EXIT THEN
508:
509: vscsi-debug IF
510: ." TestUnitReady sense: " 3dup . . . cr
511: THEN
512:
513: 3dup 1 4 2 compare-sense IF
514: 3drop CDROM-NOT-READY EXIT
515: THEN
516:
517: get-media-event IF
518: sector w@ 4 >= IF
519: sector 2 + c@ 04 = IF
520: sector 5 + c@
521: dup 02 and 0<> IF drop 3drop CDROM-READY EXIT THEN
522: dup 01 and 0<> IF drop 3drop CDROM-TRAY-OPEN EXIT THEN
523: drop 3drop CDROM-NO-DISK EXIT
524: THEN
525: THEN
526: THEN
527:
528: 3dup 2 4 2 compare-sense IF
529: 3drop CDROM-INIT-REQUIRED EXIT
530: THEN
531: over 4 = over 2 = and IF
532: \ Format in progress... what do we do ? Just ignore
533: 3drop CDROM-READY EXIT
534: THEN
535: over 3a = IF
536: 3drop CDROM-NO-DISK EXIT
537: THEN
538:
539: \ Other error...
540: 3drop CDROM-TRAY-MAYBE-OPEN
541: ;
542:
543: : cdrom-try-close-tray ( -- )
544: scsi-const-load start-stop-unit drop
545: ;
546:
547: : cdrom-must-close-tray ( -- )
548: scsi-const-load start-stop-unit not IF
549: ." Tray open !" cr -65 throw
550: THEN
551: ;
552:
553: : dev-prep-cdrom ( -- )
554: target-id to current-id target-lun to current-lun
555:
556: 5 0 DO
557: cdrom-status CASE
558: CDROM-READY OF UNLOOP EXIT ENDOF
559: CDROM-NO-DISK OF ." No medium !" cr -65 THROW ENDOF
560: CDROM-TRAY-OPEN OF cdrom-must-close-tray ENDOF
561: CDROM-INIT-REQUIRED OF cdrom-try-close-tray ENDOF
562: CDROM-TRAY-MAYBE-OPEN OF cdrom-try-close-tray ENDOF
563: ENDCASE
564: d# 1000 ms
565: LOOP
566: ." Drive not ready !" cr -65 THROW
567: ;
568:
569: : dev-prep-disk ( -- )
570: ;
571:
572: : vscsi-create-disk ( lun id -- )
573: " disk" 0 " vio-vscsi-device.fs" included
574: ;
575:
576: : vscsi-create-cdrom ( lun id -- )
577: " cdrom" 1 " vio-vscsi-device.fs" included
578: ;
579:
580: : wrapped-inquiry ( -- true | false )
581: inquiry not IF false EXIT THEN
582: \ Skip devices with PQ != 0
583: sector inquiry-data>peripheral c@ e0 and 0 =
584: ;
585:
586: 8 CONSTANT #dev
587: : vscsi-find-disks ( -- )
588: ." VSCSI: Looking for disks" cr
589: #dev 0 DO \ check 8 devices (no LUNs)
590: i to current-id 0 to current-lun
591: wrapped-inquiry IF
592: ." SCSI ID " i .
593: \ XXX FIXME: Check top bits to ignore unsupported units
594: \ and maybe provide better printout & more cases
595: sector inquiry-data>peripheral c@ CASE
596: 0 OF ." DISK : " 0 i vscsi-create-disk ENDOF
597: 5 OF ." CD-ROM : " 0 i vscsi-create-cdrom ENDOF
598: 7 OF ." OPTICAL : " 0 i vscsi-create-cdrom ENDOF
599: e OF ." RED-BLOCK: " 0 i vscsi-create-disk ENDOF
600: dup dup OF ." ? (" . 8 emit 29 emit 5 spaces ENDOF
601: ENDCASE
602: sector .inquiry-text cr
603: THEN
604: LOOP
605: ;
606:
607: \ Remove scsi functions from word list
608: scsi-close
609:
610: : setup-alias
611: " scsi" find-alias 0= IF
612: " scsi" get-node node>path set-alias
613: ELSE THEN
614: ;
615:
616: : vscsi-init-and-scan ( -- )
617: vscsi-init IF
618: vscsi-find-disks
619: setup-alias
620: THEN
621: ;
622:
623: vscsi-init-and-scan
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.