Subject: Re: more PCI expansion rom stuff (macro declarations)
To: Jason Thorpe <thorpej@shagadelic.org>
From: Garrett D'Amore <garrett_damore@tadpole.com>
List: tech-kern
Date: 02/27/2006 21:25:57
Jason Thorpe wrote:
>
> On Feb 27, 2006, at 7:50 PM, Garrett D'Amore wrote:
>
>> I have considered also providing a standard function to parse (locate)
>> the matching ROM image, but it isn't clear that there is a truly elegant
>> way to do this.  I have code to do it in my radeonfb driver.  If you
>> want it generalized, I'm happy to add the code to pci_subr.c as well.
>> Here is the API that I would initially propose in that case:
>
> The API you propose looks fine to me at first glance, except:
>
>>
>> int pci_find_rom(struct pci_attach_args *, bus_space_tag_t *,
>> bus_space_handle_t *,
>>         bus_size_t, int code, bus_space_handle_t *subhandle);
>
> romt and romh are bus_space_tag_t and bus_space_handle_t,
> respectively... not *'s to those types.
Yes, good catch.  :-)  It is correct in my radeon driver. :-) 
(Actually, in the radeonfb driver it passes a softc instead to narrow
the interface a bit. :-)

What I don't know yet is whether folks feel that this function is
generally useful enough to include in the PCI framework or not.  I
suppose I could wrap it in #ifdef's.   The routine probably adds a
kilobyte or so to a typical image.  It is 1048 bytes in my MIPS32 code,
and there are a few checks against the class code registers that aren't
in it, that I would add in a "generic" version.  But I wouldn't have to
dereference a few fields, because they are passed in directly.  So it is
probably a net wash around 1 kilobyte.

So, is the API useful as is to anyone else?  Or likely enough to be so
that it should be part of the PCI framework?

I'm ambivalent.

FWIW, I certainly know of certain device drivers on Sun hardware that
require initialization which has to be performed by open firmware. 
Hotplug of those devices requires a userland daemon (efcode interpreter)
and the ability to map the ROMs for them in order to extract the
necessary Fcode.

Certain unmentioned SCSI HBAs suffer from this deficiency.

NetBSD drivers for those devices might not have this problem.

    -- Garrett

PS: Those curious might wonder why on God's green earth we would want to
access PCI expansion ROMs.   The Radeon hardware stores various clocking
parameters, as well as video initialization parameters, which vary from
card to card, in the PC BIOS area.  For x86 hardware this works well
because x86 BIOS generally initializes the device to a sane state, and
often leaves breadcrumbs in various registers where things like XFree86
can find them.  On non-PC hardware, this is problematic, and so
supporting things like Radeon on such hardware is problematic.  For some
platforms blessed with Open Firmware, ATI provides an Open Firmware
version of the BIOS on certain cards, but they generally cost more and
are harder to locate.  And on hardware with BIOS *or* OpenFirmware (such
as pretty much all MIPS and ARM boxes), there isn't a good solution that
doesn't involve "parsing" the BIOS, or at least extracting the relevant
data from known BIOS offsets.

>
>>
>> And the caller would do something like this (error checking elided for
>> clarity):
>>
>> pci_mapreg_map(paa, PCI_MAPREG_TYPE_ROM, PCI_MAPREG_ROM, 0,
>> &sc->sc_romt,
>>         &sc->sc_romh, &sc->sc_romsz);
>>
>> pci_find_rom(paa, sc->sc_romt, sc->sc_romh, PCI_ROM_CODE_TYPE_X86,
>>         &sc->sc_biosh);
>>
>> where tag and primary handle are just like pci_mapreg_map
>>
>>
>> Anyway, please let me know if you think I can commit the pcireg.h
>> changes, and also if you're interested in having a new pci_find_rom()
>> code in the common PCI framework.
>>
>>     -- Garrett
>> Index: pcireg.h
>> ===================================================================
>> RCS file: /cvsroot/src/sys/dev/pci/pcireg.h,v
>> retrieving revision 1.48
>> diff -u -r1.48 pcireg.h
>> --- pcireg.h    27 Feb 2006 16:11:58 -0000    1.48
>> +++ pcireg.h    28 Feb 2006 03:49:48 -0000
>> @@ -702,6 +702,42 @@
>>   */
>>
>>  /*
>> + * PCI Expansion Rom
>> + */
>> +
>> +struct pci_rom_header {
>> +    uint16_t        romh_magic;    /* 0xAA55 little endian */
>> +    uint8_t            romh_reserved[22];
>> +    uint16_t        romh_data_ptr;    /* pointer to pci_rom struct */
>> +} __attribute__((__packed__));
>> +
>> +#define    PCI_ROM_HEADER_MAGIC    0xAA55        /* little endian */
>> +
>> +struct pci_rom {
>> +    uint32_t        rom_signature;
>> +    pci_vendor_id_t        rom_vendor;
>> +    pci_product_id_t    rom_product;
>> +    uint16_t        rom_vpd_ptr;    /* reserved in PCI 2.2 */
>> +    uint16_t        rom_data_len;
>> +    uint8_t            rom_data_rev;
>> +    pci_class_t        rom_class;
>> +    pci_subclass_t        rom_subclass;
>> +    pci_interface_t        rom_interface;
>> +    uint16_t        rom_len;    /* code length / 512 byte */
>> +    uint16_t        rom_rev;    /* code revision level */
>> +    uint8_t            rom_code_type;    /* type of code */
>> +    uint8_t            rom_indicator;
>> +    uint16_t        rom_reserved;
>> +    /* Actual data. */
>> +} __attribute__((__packed__));
>> +
>> +#define    PCI_ROM_SIGNATURE    0x52494350    /* "PCIR", endian
>> reversed */
>> +#define    PCI_ROM_CODE_TYPE_X86    0        /* Intel x86 BIOS */
>> +#define    PCI_ROM_CODE_TYPE_OFW    1        /* Open Firmware */
>> +#define    PCI_ROM_CODE_TYPE_HPPA    2        /* HP PA/RISC */
>> +
>> +/*
>> +/*
>>   * Threshold below which 32bit PCI DMA needs bouncing.
>>   */
>>  #define PCI32_DMA_BOUNCE_THRESHOLD    0x100000000ULL
>
> -- thorpej


-- 
Garrett D'Amore, Principal Software Engineer
Tadpole Computer / Computing Technologies Division,
General Dynamics C4 Systems
http://www.tadpolecomputer.com/
Phone: 951 325-2134  Fax: 951 325-2191