Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / slof / fs / ide.fs
diff --git a/qemu/roms/SLOF/slof/fs/ide.fs b/qemu/roms/SLOF/slof/fs/ide.fs
new file mode 100644 (file)
index 0000000..d6f16ed
--- /dev/null
@@ -0,0 +1,612 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2008 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
+\ ****************************************************************************/
+\
+\ 26.06.2007  added: two devices (Master/Slave) per channel
+
+1 encode-int s" #address-cells" property
+0 encode-int s" #size-cells" property
+
+: decode-unit  1 hex-decode-unit ;
+: encode-unit  1 hex-encode-unit ;
+
+0 VALUE >ata                                 \ base address for command-block
+0 VALUE >ata1                                \ base address for control block
+
+true VALUE no-timeout                        \ flag that no timeout occurred
+
+0c  CONSTANT #cdb-bytes                      \ command descriptor block (12 bytes)
+800 CONSTANT atapi-size
+200 CONSTANT ata-size
+
+\ *****************************
+\ Some register access helpers.
+\ *****************************
+: ata-ctrl! 2 >ata1 + io-c! ;                      \ device control reg
+: ata-astat@ 2 >ata1 + io-c@ ;                     \ read alternate status
+                                                   
+: ata-data@ 0 >ata + io-w@ ;                       \ data reg
+: ata-data! 0 >ata + io-w! ;                       \ data reg
+: ata-err@  1 >ata + io-c@ ;                       \ error reg
+: ata-feat! 1 >ata + io-c! ;                       \ feature reg
+: ata-cnt@  2 >ata + io-c@ ;                       \ sector count reg
+: ata-cnt!  2 >ata + io-c! ;                       \ sector count reg
+: ata-lbal! 3 >ata + io-c! ;                       \ lba low reg
+: ata-lbal@ 3 >ata + io-c@ ;                       \ lba low reg
+: ata-lbam! 4 >ata + io-c! ;                       \ lba mid reg
+: ata-lbam@ 4 >ata + io-c@ ;                       \ lba mid reg
+: ata-lbah! 5 >ata + io-c! ;                       \ lba high reg
+: ata-lbah@ 5 >ata + io-c@ ;                       \ lba high reg
+: ata-dev!  6 >ata + io-c! ;                       \ device reg
+: ata-dev@  6 >ata + io-c@ ;                       \ device reg
+: ata-cmd!  7 >ata + io-c! ;                       \ command reg
+: ata-stat@ 7 >ata + io-c@ ;                       \ status reg
+
+\ **********************************************************************
+\ ATA / ATAPI Commands specifications:
+\ - AT Attachment 8 - ATA/ATAPI Command Set (ATA8-ACS)
+\ - ATA Packet Interface for CD-ROMs SFF-8020i
+\ - ATA/ATAPI Host Adapters Standard (T13/1510D)
+\ **********************************************************************
+00 CONSTANT cmd#nop                                \ ATA and ATAPI
+08 CONSTANT cmd#device-reset                       \ ATAPI only (mandatory)
+20 CONSTANT cmd#read-sector                        \ ATA and ATAPI
+90 CONSTANT cmd#execute-device-diagnostic          \ ATA and ATAPI
+a0 CONSTANT cmd#packet                             \ ATAPI only (mandatory)
+a1 CONSTANT cmd#identify-packet-device             \ ATAPI only (mandatory)
+ec CONSTANT cmd#identify-device                    \ ATA and ATAPI
+
+\ *****************************
+\ Setup Regs for ATA:
+\ BAR 0 & 1 : Device 0
+\ BAR 2 & 3 : Device 1
+\ *****************************
+: set-regs ( n -- )
+   dup
+   01 and                                    \ only Chan 0 or Chan 1 allowed
+   3 lshift dup 10 + config-l@ -4 and to >ata
+   14 + config-l@ -4 and to >ata1
+   02 ata-ctrl!                              \ disable interrupts
+   02 and
+   IF
+      10
+   ELSE
+      00
+   THEN
+   ata-dev!
+;
+
+ata-size VALUE block-size
+80000    VALUE max-transfer            \ Arbitrary, really
+
+CREATE sector d# 512 allot
+CREATE packet-cdb #cdb-bytes allot
+CREATE return-buffer atapi-size allot
+
+scsi-open                             \ add scsi functions
+
+\ ********************************
+\ show all ATAPI-registers
+\ data-register not read in order
+\ to not influence PIO mode
+\ ********************************
+: show-regs
+   cr
+   cr ." alt. Status: " ata-astat@ .
+   cr ." Status     : " ata-stat@ .
+   cr ." Device     : " ata-dev@ .
+   cr ." Error-Reg  : " ata-err@ .
+   cr ." Sect-Count : " ata-cnt@ .
+   cr ." LBA-Low    : " ata-lbal@ .
+   cr ." LBA-Med    : " ata-lbam@ .
+   cr ." LBA-High   : " ata-lbah@ .
+;
+
+\ ***************************************************
+\ reads ATAPI-Status and displays it if check-bit set
+\ ***************************************************
+: status-check               ( -- )
+   ata-stat@
+   dup   
+   01 and                                    \ is 'check' flag set ?
+   IF
+      cr
+      ."    - ATAPI-Status: " .
+      ata-err@                               \ retrieve sense code
+      dup
+      60 =                                   \ sense code = 6 ?
+      IF
+         ." ( media changed or reset )"      \ 'unit attention'
+         drop                                \ drop err-reg content
+      ELSE
+         dup
+         ." (Err : " .                       \ show err-reg content
+         space
+         rshift 4 .sense-text                \ show text string
+         29 emit
+      THEN
+      cr
+   ELSE
+      drop                                   \ remove unused status      
+   THEN      
+;
+
+\ *************************************
+\ Wait for interface ready condition
+\ Bit 7 of Status-Register is busy flag
+\ new version with abort after 5 sec.
+\ *************************************
+: wait-for-ready
+   get-msecs                                 \ start timer
+   BEGIN
+      ata-stat@ 80 and 0<>                   \ busy flag still set ?
+      no-timeout and
+      WHILE                                  \ yes
+         dup get-msecs swap
+         -                                   \ calculate timer difference
+         FFFF AND                            \ reduce to 65.5 seconds
+         d# 5000 >                           \ difference > 5 seconds ?
+         IF
+            false to no-timeout
+         THEN
+      REPEAT
+   drop
+;
+
+\ *************************************
+\ wait for specific status bits
+\ new version with abort after 5 sec.
+\ *************************************
+: wait-for-status          ( val mask -- )
+   get-msecs                                 \ initial timer value (start)
+   >r
+   BEGIN
+      2dup                                   \ val mask
+      ata-stat@ and <>                       \ expected status ?
+      no-timeout and                         \ and no timeout ?
+      WHILE      
+      get-msecs r@ -                         \ calculate timer difference
+      FFFF AND                               \ mask-off overflow bits
+      d# 5000 >                              \ 5 seconds exceeded ?
+      IF
+         false to no-timeout                 \ set global flag
+      THEN      
+   REPEAT                  
+   r>                                        \ clean return stack
+   3drop
+;
+
+\ *********************************    
+\ remove extra spaces from string end
+\ *********************************    
+: cut-string      ( saddr nul -- )
+   swap
+   over +
+   swap   
+   1 rshift                                  \ bytecount -> wordcount
+   0 do
+      /w -
+      dup               ( addr -- addr addr )
+      w@                ( addr addr -- addr nuw )
+      dup               ( addr nuw -- addr nuw nuw )
+      2020 =
+      IF
+         drop
+         0 
+      ELSE
+         LEAVE         
+      THEN
+      over         
+      w!
+   LOOP
+   drop
+   drop
+; 
+
+\ ****************************************************
+\ prints model-string received by identify device
+\ ****************************************************
+: show-model          ( dev# chan# -- )
+   2dup
+   ."    CH " .                  \ channel 0 / 1
+   0= IF ." / MA"                \ Master / Slave
+   ELSE  ." / SL"
+   THEN
+   swap
+   2 * + ."  (@" . ." ) : "      \ device number
+   sector 1 +
+   c@
+   80 AND 0=
+   IF
+      ." ATA-Drive    "
+   ELSE
+      ." ATAPI-Drive  "
+   THEN
+
+   22 emit                       \ start string display with "
+   sector d# 54 +                \ string starts 54 bytes from buffer start
+   dup
+   d# 40                         \ and is 40 chars long
+   cut-string                    \ remove all trailing spaces
+   
+   BEGIN
+      dup
+      w@
+      wbflip
+      wbsplit
+      dup 0<>                    \ first char
+      IF                   
+         emit
+         dup 0<>                 \ second char
+         IF
+            emit
+            wa1+                 \ increment address for next
+            false
+         ELSE                    \ second char = EndOfString
+            drop
+            true
+         THEN   
+      ELSE                       \ first char = EndOfString
+         drop
+         drop
+         true
+      THEN
+   UNTIL                         \ end of string detected
+   drop
+   22 emit                       \ end string display
+                                                  
+   sector c@                     \ get lower byte of first doublet
+   80 AND                        \ check bit 7
+   IF
+      ."  (removable media)"
+   THEN
+   
+   sector 1 +
+   c@
+   80 AND 0= IF                  \ is this an ATA drive ?
+      sector d# 120 +            \ get word 60 + 61
+      rl@-le                     \ read 32-bit as little endian value
+      d# 512                     \ standard ATA block-size
+      swap
+      .capacity-text ( block-size #blocks -- )
+   THEN
+   
+    sector d# 98 +               \ goto word 49
+    w@
+    wbflip
+    200 and 0= IF cr ."    ** LBA is not supported " THEN   
+
+   sector c@                     \ get lower byte of first doublet
+   03 AND 01 =                   \ we use 12-byte packet commands (=00b)
+   IF
+      cr ."    packet size = 16 ** not supported ! **"
+   THEN
+   no-timeout not                \ any timeout occurred so far ?
+   IF
+      cr   ."    ** timeout **"
+   THEN
+;
+
+\ ****************************
+\ ATA functions
+\ ****************************
+: pio-sector ( addr -- )  100 0 DO ata-data@
+   over w! wa1+ LOOP drop ;
+: pio-sector ( addr -- ) 
+  wait-for-ready pio-sector ;
+: pio-sectors ( n addr -- )  swap 0 ?DO dup pio-sector 200 + LOOP drop ;
+
+: lba!  lbsplit   
+   0f and 40 or                  \ always set LBA-mode + LBA (27..24)
+   ata-dev@ 10 and or            \ add current device-bit (DEV)
+   ata-dev!                      \ set LBA (27..24)
+   ata-lbah!                     \ set LBA (23..16)
+   ata-lbam!                     \ set LBA (15..8)
+   ata-lbal!                     \ set LBA (7..0)
+;
+
+: read-sectors ( lba count addr -- ) 
+  >r dup >r ata-cnt! lba! 20 ata-cmd! r> r> pio-sectors ;
+
+: read-sectors ( lba count addr dev-nr -- )
+    set-regs             ( lba count addr ) \ Set ata regs 
+    BEGIN >r dup 100 > WHILE
+       over 100 r@ read-sectors
+       >r 100 + r> 100 - r> 20000 + REPEAT
+    r> read-sectors
+;
+
+: ata-read-blocks                ( addr block# #blocks dev# -- #read )
+   swap dup >r swap >r rot r>    ( addr block# #blocks dev # R: #blocks )
+   read-sectors r>               ( R: #read )
+;    
+
+\ *******************************
+\ ATAPI functions
+\ preset LBA register with maximum
+\ allowed block-size (16-bits)
+\ *******************************
+: set-lba                              ( block-length -- )
+   lbsplit                             ( quad -- b1.lo b2 b3 b4.hi )
+   drop                                \ skip upper two bytes
+   drop
+   ata-lbah!
+   ata-lbam!
+;
+   
+\ *******************************************
+\ gets byte-count and reads a block of words
+\ from data-register to a buffer
+\ *******************************************
+: read-pio-block                        ( buff-addr -- buff-addr-new )
+   ata-lbah@ 8 lshift                  \ get block length High
+   ata-lbam@ or                        \ get block length Low
+   1 rshift                            \ bcount -> wcount
+   dup
+   0> IF                               \ any data to transfer?
+      0 DO                             \ words to read
+         dup                           \ buffer-address
+         ata-data@ swap w!             \ write 16-bits
+         wa1+                          \ address of next entry
+         LOOP
+      ELSE
+         drop                          ( buff-addr wcount -- buff-addr )
+      THEN
+   wait-for-ready
+;
+
+\ ********************************************
+\ ATAPI support
+\ Send a command block (12 bytes) in PIO mode
+\ read data if requested
+\ ********************************************
+: send-atapi-packet                    ( req-buffer -- )
+   >r                                  (   R: req-buffer )
+   atapi-size set-lba                  \ set regs to length limit
+   00 ata-feat!
+   cmd#packet ata-cmd!                 \ A0 = ATAPI packet command
+   48 C8  wait-for-status     ( val mask -- )  \ BSY:0 DRDY:1 DRQ:1
+   6 0  do
+      packet-cdb i 2 * +                \ transfer command block (12 bytes)
+      w@
+      ata-data!                        \ 6 doublets PIO transfer to device
+      loop                             \ copy packet to data-reg
+   status-check                        ( -- ) \ status err bit set ? -> display
+   wait-for-ready                      ( -- ) \ busy released ?
+   BEGIN
+   ata-stat@ 08 and 08 = WHILE         \ Data-Request-Bit set ?
+      r>                               \ get last target buffer address
+      read-pio-block                   \ only if from device requested
+      >r                               \ start of next block
+      REPEAT
+   r>                                  \ original value
+   drop                                \ return clean
+;   
+
+: atapi-packet-io                      ( -- )
+   return-buffer atapi-size erase      \ clear return buffer
+   return-buffer send-atapi-packet     \ send 'packet-cdb' , get 'return-buffer'
+;
+
+
+
+\ ********************************
+\ ATAPI packet commands
+\ ********************************
+
+\ Methods to access atapi disk
+
+: atapi-test ( -- true|false )
+   packet-cdb scsi-build-test-unit-ready     \ command-code: 00
+   atapi-packet-io                           ( )  \ send CDB, get return-buffer
+   ata-stat@ 1 and IF false ELSE true THEN
+;
+
+: atapi-sense ( -- ascq asc sense-key )
+   d# 252 packet-cdb scsi-build-request-sense ( alloc-len cdb -- )
+   atapi-packet-io                           ( )  \ send CDB, get return-buffer
+   return-buffer scsi-get-sense-data         ( cdb-addr -- ascq asc sense-key )
+;
+
+: atapi-read-blocks                    ( address block# #blocks dev# -- #read-blocks )
+   set-regs                            ( address block# #blocks )
+   dup >r                              ( address block# #blocks )
+   packet-cdb scsi-build-read-10       ( address block# #blocks cdb -- )
+   send-atapi-packet                   ( address -- )
+   r>                                  \ return requested number of blocks
+;
+
+\ ***************************************
+\ read capacity of drive medium
+\ use SCSI-Support Package
+\ ***************************************
+: atapi-read-capacity                        ( -- )
+   packet-cdb scsi-build-read-cap-10         \ fill block with command
+   atapi-packet-io                           ( )  \ send CDB, get return-buffer
+   return-buffer scsi-get-capacity-10        ( cdb -- block-size #blocks )
+   .capacity-text                            ( block-size #blocks -- )
+   status-check                              ( -- )
+;
+
+\ ***************************************
+\ read capacity of drive medium
+\ use SCSI-Support Package
+\ ***************************************
+: atapi-read-capacity-ext                    ( -- )
+   packet-cdb scsi-build-read-cap-16         \ fill block with command
+   atapi-packet-io                           ( )  \ send CDB, get return-buffer
+   return-buffer scsi-get-capacity-16        ( cdb -- block-size #blocks )
+   .capacity-text                            ( block-size #blocks -- )
+   status-check                              ( -- )
+;
+
+
+\ ***********************************************
+\ wait until media in drive is ready ( max 5 sec)
+\ ***********************************************
+: wait-for-media-ready                 ( -- true|false )
+   get-msecs                                 \ initial timer value (start)
+   >r
+   BEGIN
+      atapi-test                             \ unit ready? false if not      
+      not
+      no-timeout and
+      WHILE
+         atapi-sense  ( -- ascq asc sense-key )
+         02 =                                \ sense key 2 = media error
+         IF                                  \ check add. sense code
+            3A =                             \ asc: device not ready ?
+            IF
+               false to no-timeout
+               ."  empty (" . 29 emit        \ show asc qualifier
+            ELSE
+               drop                          \ discard asc qualifier
+            THEN                             \ medium not present, abort waiting
+         ELSE
+            drop                             \ discard asc
+            drop                             \ discard ascq
+         THEN
+         get-msecs r@ -                      \ calculate timer difference
+         FFFF AND                            \ mask-off overflow bits
+         d# 5000 >                           \ 5 seconds exceeded ?
+         IF
+            false to no-timeout              \ set global flag
+         THEN      
+   REPEAT
+   r>
+   drop
+   no-timeout
+;
+
+\ ******************************************************
+\ Method pointer for read-blocks methods
+\ controller implements 2 channels (primary / secondary)
+\ for 2 devices each (master / slasve)
+\ ******************************************************
+\ 2 channels (primary/secondary) per controller
+2 CONSTANT #chan 
+
+\ 2 devices (master/slave) per channel
+2 CONSTANT #dev
+
+\ results in a total of devices
+\ connected to a controller with
+\ two separate channels (4)
+: #totaldev #dev #chan * ;
+CREATE read-blocks-xt #totaldev cells allot read-blocks-xt #totaldev cells erase
+
+\ Execute read-blocks of device
+: dev-read-blocks  ( address block# #blocks dev# -- #read-blocks )
+   dup cells read-blocks-xt + @ execute
+;
+
+\ **********************************************************
+\ Read device type
+\ Signature      ATAPI             ATA
+\ ---------------------------------------------
+\ Sector Count    01h              01h
+\ Sector Number   01h              01h
+\ Cylinder Low    14h              00h
+\ Cylinder High   EBh              00h
+\ Device/Head     00h or 10h       00h or 01h
+\ see also ATA/ATAPI errata at:
+\ http://suif.stanford.edu/~csapuntz/blackmagic.html
+\ **********************************************************
+: read-ident  ( -- true|false )
+   false
+   00 ata-lbal!                              \ clear previous signature
+   00 ata-lbam!
+   00 ata-lbah!
+   cmd#identify-device ata-cmd! wait-for-ready \ first try ATA, ATAPI aborts command
+   ata-stat@ CF and 48 =
+   IF
+      drop true                                          \ cmd accepted, this is a ATA
+      d# 512 set-lba                                     \ set LBA to sector-length
+   ELSE                                                  \ ATAPI sends signature instead
+      ata-lbam@ 14 = IF                                  \ cylinder low  = 14 ?
+         ata-lbah@ EB = IF                               \ cylinder high = EB ?
+            cmd#device-reset ata-cmd! wait-for-ready     \ only supported by ATAPI
+            cmd#identify-packet-device ata-cmd! wait-for-ready                     \ first try ata
+            ata-stat@ CF and 48 = IF               
+               drop true                                 \ replace flag
+               THEN
+            THEN
+         THEN
+      THEN
+   dup IF
+      ata-stat@ 8 AND IF                        \ data requested (as expected) ?      
+         sector read-pio-block 
+         drop                                   \ discard address end 
+         ELSE
+         drop false
+         THEN
+      THEN
+   
+   no-timeout not IF                            \ check without any timeout ?
+      drop
+      false                                     \ no, detection discarded
+      THEN
+;
+
+scsi-close                             \ remove scsi commands from word list
+
+
+\ *************************************************
+\ Init controller ( chan 0 and 1 )
+\ device 0 (= master) and device 1 ( = slave)
+\  #dev  #chan   Dev-ID
+\ ----------------------
+\   0      0        0          Master of Channel 0
+\   0      1        1          Master of Channel 1
+\   1      0        2          Slave  of Channel 0
+\   1      1        3          Slave  of Channel 1
+\ *************************************************
+: find-disks      ( -- )   
+   #chan 0 DO                                      \ check 2 channels (primary & secondary)
+      #dev 0 DO                                    \ check 2 devices per channel (master / slave)
+         i 2 * j +
+         set-regs                                  \ set base address and dev-register for register access
+         ata-stat@ 7f and 7f <>                    \ Check, if device is connected
+         IF
+            true to no-timeout                     \ preset timeout-flag
+            read-ident        ( -- true|false )
+            IF
+               i j show-model                      \ print manufacturer + device string
+               sector 1+ c@ C0 and 80 =            \ Check for ata or atapi
+               IF
+                  wait-for-media-ready             \ wait up to 5 sec if not ready
+                  no-timeout and
+                  IF
+                     atapi-read-capacity
+                     atapi-size to block-size      \ ATAPI: 2048 bytes
+                     80000 to max-transfer
+                     ['] atapi-read-blocks i 2 * j + cells read-blocks-xt + !
+                     s" cdrom" strdup i 2 * j + s" generic-disk.fs" included
+                  ELSE
+                     ."  -"                        \ show hint for not registered
+                  THEN    
+               ELSE
+                  ata-size to block-size           \ ATA: 512 bytes
+                  80000 to max-transfer
+                  ['] ata-read-blocks i 2 * j + cells read-blocks-xt + !
+                  s" disk" strdup i 2 * j + s" generic-disk.fs" included
+               THEN
+            cr
+            THEN    
+         THEN
+         i 2 * j + 200 + cp
+      LOOP
+   LOOP
+;
+
+find-disks
+