PCI card hacking

From MCEWiki
Revision as of 20:23, 13 January 2009 by 24.82.145.130 (talk)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

This page describes using dsp_cmd and mce_cmd to debug MCE/PCI card communication issues. These instructions can be used to resolve questions like "is the data getting dropped by the PCI card, or does it never arrive at the PCI card?"

RAM areas on the DSP

The DSP has 3 RAM banks, known as X, Y, and P. User data is in X and Y, while the program code is in P. By default, all three banks contain something like 2k x 16bits. On our hardware, however, the Y bank has been extended with an external SRAM to 8M x 16bits.

In our firmware, X memory is used to store ordinary variables while Y memory is used for large buffers.

Reading and writing DSP RAM with dsp_cmd

We can use dsp_cmd to read back the values of variables and buffers in the PCI card RAM. This is done as follows:

mhasse@mce-ubc-2:~$ dsp_cmd -x read X 0
This is dsp_cmd version MAS/slotpc/327
Line   0 : ok : X[0] = 0x208

We can also write. Don't write to X or P memory unless you really know what you're doing.

mhasse@mce-ubc-2:~$ dsp_cmd -x write Y 0 0x1234
This is dsp_cmd version MAS/slotpc/327
Line   0 : ok

It is convenient to define a few functions to make this hacking easier (you can just dump this into your bash session, or put it in a file and run "source file" whenever you want the functions to be available):

function pciread {
    dsp_cmd -qpx read $1 $2 | cut -d' ' -f5
}
function pciwrite {
    dsp_cmd -qpx write $1 $2 $3
}
function pcidump {
    # usage: pcidump <BANK> <START> <COUNT>
    for i in `seq -f '%9.0f' $2 $(( $2 + $3 - 1 ))`; do printf "%s %#8x 0x%06x\n" $1 $i `pciread $1 $i`; done
}
function pciwash {
    # usage: pciwash <BANK> <START> <COUNT> <VALUE>
    for i in `seq -f '%9.0f' $2 $(( $2 + $3 - 1 ))`; do pciwrite $1 $i $4; done
}

Then you use them like this:

mhasse@mce-ubc-2:~$ pciread x 0
0x208
mhasse@mce-ubc-2:~ pciwrite y 0 0x1234

mhasse@mce-ubc-2:~$ pcidump Y 0x100000 4
Y 0x100000 0x004f4b
Y 0x100001 0x00474f
Y 0x100002 0x000016
Y 0x100003 0x000003

MCE command, reply and data buffers

We can inspect the DSP's buffers if we know their addresses. This depends on DSP code firmware revision.

Version Data Reply Command
U0104 and earlier 0 0 0x200
U0105 0 0x100000 0x200000
  • Note about data and reply packets!*: the preamble, packet type, and frame size are stripped off. These will not appear in the buffers in Y memory. They are available at special locations in X memory, however.

(Incidentally, the collision between the "data" and reply/command buffers is why U0104 and earlier cannot be used to issue STOP or other MCE commands during frame acquisition.)

DSP internal variables

There are a few DSP internal variables, stored in X memory, that are of use in comm. hacking:

Name Address(U0104) Address(U0105) Description
STATUS 0x00 0x00 Status (and modes) of DSP, see bit break-down below
MODE n/a 0x01 Flags configuring certain modes of the DSP
HEAD_W3_0 0x21 0x14 Type of last reply or data packet, 'DA' or 'RP'
PACKET_SIZE_LOW 0x23 n/a Size of latest reply or data packet, in 16 bit words
PACKET_SIZE n/a 0x2B Size of latest reply or data packet, in 32 bit words
QT_FRAME_SIZE 0x53 0x3D The expected size of data packets in bytes
FRAME_COUNT 0x01 0x02 Number of DA packets received from the MCE (including discards)
QT_DROPS 0x5A 0x44 Number of data packets dropped due to full PC RAM buffer
RP_DROPS n/a 0x48 Number of reply packets dropped due to PC RAM buffer unavailable (quiet_RP mode only)

Currently, the number of packets that are dropped due to a packet size mismatch between PACKET_SIZE and QT_FRAME_SIZE is not recorded explicitly. However, such packets will cause FRAME_COUNT to increment.

All of the above variables, except STATUS, MODE, and FRAME_COUNT are cleared by a DSP_RESET. You can zero the frame count manually using pciwrite.

(Incidentally, the addresses in the table above are determined from the .lod symbol table of the assembler output.)