On Sun, Jul 13, 2008 at 12:34 PM, Attila Kinali <[EMAIL PROTECTED]> wrote:
> On Tue, 1 Jul 2008 14:26:14 -0400
> "Timothy Normand Miller" <[EMAIL PROTECTED]> wrote:
>
>> The first, most critical thing is diagnostic software.  When we plug
>> an OGD1 for the first time into a PC, we need software that lets us
>> bang directly on the hardware, sets up video, etc.  I've done this
>> before, but I can't release the code (not soon enough anyhow).
>> Basically, you'll need libpci to start with.  Use it to scan for the
>> device, map it, enable the mapping in the hardware, etc.  That mapping
>> would be one submodule of the diag suite.  Others would include video
>> setup (mostly based on Patrick's code), memory setup (grab the numbers
>> from the simulation code), and other minor things.  Oh, and let's not
>> forget programming the SPI prom that loads the S3.
>
> Can you be a little bit more specific here what you need?
> Ie what device are we scanning for? What values should we
> bang to which registers? Do you want to have an application
> that just writes some fixed values or do you want to have
> it defined on the command line?

Using libpci, first, you need to get the device list so that you can
iterate through it.

    struct pci_access *pacc;
    struct pci_dev *dev;
    pacc = pci_alloc();         /* Get the pci_access structure */
    /* Set all options you want -- here we stick with the defaults */
    pci_init(pacc);             /* Initialize the PCI library */
    pci_scan_bus(pacc);         /* We want to get the list of devices */

We'll probably want to have some sort of config file where we can list
vendor and subvendor IDs that will be searched for.  Then we iterate
through the list of devices until we find what we're after.

    for(dev=pacc->devices; dev; dev=dev->next)  /* Iterate over all devices */
    {
        pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES |
PCI_FILL_SIZES | PCI_FILL_ROM_BASE);
        for (i=0; i<n_ids; i++) {
            if (pci_read_long(dev, 0) == vendor_ids[i] &&
                pci_read_long(dev, 0x2c) == subvendor_ids[i]) {
                    // This code is an example spits out the
identifier that you'd get with lspci
                    printf("%02x:%02x.%d\n", dev->bus, dev->dev, dev->func);
            }
        }
    }

Now, once you have identified the device, we need to map it into memory

Among other things, we need to enable the memory space in the hardware
(without a kernel driver, Linux leaves it off):

    // Write to PCI cfg space to turn on memory decoding
    c = pci_read_byte(dev, PCI_COMMAND);
    if (!(c & PCI_COMMAND_MEMORY)) {
        pci_write_byte(dev, PCI_COMMAND, c | 7);
    }

And we need to open the memory device:

    if ((mem_fd = open("/dev/mem", O_RDWR)) < 0)
    {
        printf("can't open /dev/mem\n");
        exit(-1);
    }

Finally, we can map the engine and main memory, like this:

    base0_ptr  = (unsigned char *)mmap(
        (caddr_t)0,
        dev->size[0],
        PROT_READ | PROT_WRITE,
        MAP_SHARED,
        mem_fd,
        dev->base_addr[0]);
    if (base0_ptr == MAP_FAILED)
    {
        perror("mmap error");
        exit(-1);
    }
    base0_size = dev->size[0];
    printf("Mapped phy=0x%08x, size=0x%x, virt=0x%08llx\n",
        dev->base_addr[0], base0_size, base0_ptr);

We need to map engine (BAR0), memory (BAR1), and PROM.

This all should go into some library/module that we can link to.

For accessing registers, we want some macros.  Here's something like a
write macro:

#define write32(base,offset,data) \
    (*((volatile unsigned int *) ((char *)base + offset))) = data;

The read macro is basically the same thing as a RHS.

Then we can do:

#define DDC0_SCK 0x???
...
write32(engine_base, DDC0_SCK, 1);


We'll need functions that perform various tasks on the hardware.
Memory setup is basically just a bunch of write32's with some delays
(10ms here, 100ms there).  Video setup involves calling some of
Patrick's code that we have in SVN that generates video programs.

Then we need a memory test module.  Something that will take any
pointer and buffer size and walk through it checking integrity.
Walking 1's, random address/random data.  If you use the right kind of
random number generator, you can get a sequence that doesn't repeat,
so you can write every address in random order with random data, then
reset the random seed and walk back through, reading and checking that
it got stored correctly.

Then we need a test pattern module.  Based on something else having
set up video, we could use another module that fills the screen with a
regular, recognizable pattern that would make sense to us on the
monitor.  For instance, a big box with an X through it, some color
bars, alternating black/white vertical or horizontal lines, etc.

If done right, it would be just as easy to build a monolithic test
suite as it would be to build separate programs that can be run in
sequence in a script.


-- 
Timothy Normand Miller
http://www.cse.ohio-state.edu/~millerti
Open Graphics Project
_______________________________________________
Open-graphics mailing list
[email protected]
http://lists.duskglow.com/mailman/listinfo/open-graphics
List service provided by Duskglow Consulting, LLC (www.duskglow.com)

Reply via email to