rumble_support.txt 7.15 KB

                      RUMBLE PACK SUPPORT

In order to support the rumble pak directly through hardware our
SI implementation would need to support a set of commands issued
through the DMA channel. The goal of the following analysis is to
pinpoint the minimal set of commands the SI would be required to
support.  Because we already support block commands (see below),
it is the single channel commands that are of primary interest
here.

As a basis for analyzing the rumble pak requirements, the
motortest application shipped with the n64 SKD has been run and
traced. The motortest code flow is given below, but is preceded
by a summary of the SI single channel commands we would need to
support. The code flow will show where and how the various single
channel commands are issued, succeed and fail.

Here is a quick review of the two types of PIF/SI commands:
  block command - a command issued to the SI formatted to
     simultaneously address every controller (max of 4).  The
     format uses 8 bytes per controller and the response will
     also fit within 8 bytes per controller.
  single channel command - a command issued to address a single
     controller. The command specifies the controller by starting
     the transferred memory block with (controller_number - 1)
     zeroes, where controller numbering begins at zero. Then, a
     data structure conveying the actual command is issued,
     followed by a command ending marker. The command specifies
     the number of bytes to recieve. Received data is in the same
     data format (along with preceding 0x00 bytes for channel
     indexing), and the rxsize parameter of every data structure
     holds the failure indicator bits in the upper nibble.


SUMMARY OF SINGLE CHANNEL COMMANDS REQUIRED
-------------------------------------------

1) Data structure __OSContRequestFormatShort, with parameters
            txsize = 1
            rxsize = 3
            cmd    = CONT_REQUEST
            typeh  = 0xff
            typel  = 0xff
            status = 0xff

2) Data structure __OSContRamReadFormat, with parameters
            dummy   = 0xff
            txsize  = 35
            rxsize  = 1
            cmd     = CONT_RAM_WRITE
            addrh   --> these hold address 0x8000/BLOCKSIZE passed in,
            addrl       along with address CRC.
            data    = can take on various values, see CODE FLOW below.
            datacrc = 0xff
   The datacrc must be set correctly on return.

   NOTE: we can also have the above with address fields:
            addrh   --> these hold address 0xc000/BLOCKSIZE (M_ADDR),
            addrl       along with address CRC.

3) Data structure __OSContRamReadFormat, with parameters
            dummy   = 0xff
            txsize  = 3
            rxsize  = 33
            cmd     = CONT_RAM_READ
            addrh   --> these hold address 0x8000/BLOCKSIZE passed in,
            addrl       along with address CRC.
            data    --> set on return
            datacrc = 0xff
   The datacrc must be set correctly on return.


CODE FLOW
---------

osContInit() --> issues a block command
osPfsInitPak()
  __osPfsGetStatus()
    __osPfsRequestOneChannel()
      + fills a single channel request buffer of type 
        __OSContRequesFormatShort.
        Values are:
            txsize = 1
            rxsize = 3
            cmd    = CONT_REQUEST
            typeh  = 0xff
            typel  = 0xff
            status = 0xff
    + issues DMA's to produce command issue/response
    __osPfsGetOneChannelData()
      + retrieves response to previous request that has 0x00
        bytes prepended for each channel, followed by type
      __OSContRequesFormatShort.
      + insure success by checking upper bits of rxsize returned.
    + return success
  __osPfsCheckRamArea()
    __osPfsSelectBank(--bank=0x00--)
      + fill a buffer (u8 temp[BLOCKSIZE], BLOCKSIZE=0x20) with 0x00
        bytes, where the 0x00 was passed in as the "bank" argument.
      __osContRamWrite()
        + Issues single channel command with type 
          __OSContRamReadFormat.
          Values are:
            dummy   = 0xff
            txsize  = 35
            rxsize  = 1
            cmd     = CONT_RAM_WRITE
            addrh   --> these hold address 0x8000/BLOCKSIZE passed in,
            addrl       along with address CRC.
            data    = array passed in full of 0x00 bytes
            datacrc = 0xff
        + issues DMA's to produce command issue/response
        + retieve response data of format __OSContRamReadFormat
        + insure success by checking upper rxsize bits returned
        + insure returned datacrc is same as locally computed version
        + return success
      + return success
    __osContRamRead() --> to save data overwritten by ensuing test
      + Issues single channel command with type __OSContRamReadFormat.
        Values are:
            dummy   = 0xff
            txsize  = 3
            rxsize  = 33
            cmd     = CONT_RAM_READ
            addrh   --> these hold address 0x8000/BLOCKSIZE passed in,
            addrl       along with address CRC.
            data    --> filled in on return. 
            datacrc = 0xff
      + issues DMA's to produce command issue/response
      + retieve response data of format __OSContRamReadFormat
      + insure success by checking upper rxsize bits returned
      + insure returned datacrc is same as locally computed version
      + return success
    + setup test data for write to Ram
    __osContRamWrite() --> write the test data pattern
    __osContRamRead()  --> read back the test pattern
    + compare result of readback with known data written previously.
      This fails.
    + return PFS_ERR_DEVICE
  + returns PFS_ERR_DEVICE
+ detect PFS_ERR_DEVICE, specifically (i.e., no other error will allow
  us to continue).
osMotorInit()
  __osPfsSelectBank(--bank=CHECK_ID, which is 0xfe--)
  + insure previous call success
  __osContRamRead(--address=BANK_ADDR, which is 0x8000/BLOCKSIZE--)
  + insure previous call success
  __osPfsSelectBank(--bank=MOTOR_ID, which is 0x80--)
  + insure previous call success
  __osContRamRead(--address=BANK_ADDR, which is 0x8000/BLOCKSIZE--)
  + insure previous call success
  + insure data read has last byte = MOTOR_ID
  __osMakeMotorData()
    + sets up a global for this channel's use to issue commands. The
      data is of type __OSContRamReadFormat. This will be used
      to issue future commands, which just change the actual
      data, but not the parameters. Values are:
            dummy   = 0xff
            txsize  = 35
            rxsize  = 1
            cmd     = CONT_RAM_WRITE
            addrh   --> these hold address 0xc000/BLOCKSIZE (M_ADDR),
            addrl       along with address CRC.
            data    --> will be filled by actual start/stop commands.
            datacrc --> will be filled by actual start/stop commands.

osMotorStart()
  __osMotorAccess(--flag=1--)
    + fill data portion of motor command setup in __osMakeMotorData()
      with all values = flag, so 0x01.
    + issue DMA's to trigger PIF (return data is __OSContRamReadFormat).
    + insure no error by checking upper bits of rxsize returned.
    + insure returned datacrc is 0x00 for flag=0, and 0xeb for flag=1.
       
osMotorStop()
  __osMotorAccess(--flag=0--)