Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 18 Jul 1997 20:25:58 +0200
From:      Stefan Esser <se@FreeBSD.ORG>
To:        Simon Shapiro <Shimon@i-connect.net>
Cc:        freebsd-hackers@FreeBSD.ORG, Stefan Esser <se@FreeBSD.ORG>
Subject:   Re: pcireg.h lost children... ?
Message-ID:  <19970718202558.63332@mi.uni-koeln.de>
In-Reply-To: <XFMail.970717212105.Shimon@i-Connect.Net>; from Simon Shapiro on Thu, Jul 17, 1997 at 04:35:22PM -0700
References:  <19970716214222.61218@mi.uni-koeln.de> <XFMail.970717212105.Shimon@i-Connect.Net>

next in thread | previous in thread | raw e-mail | index | archive | help
On Jul 17, Simon Shapiro <Shimon@i-Connect.Net> wrote:
[ ... new macro names for PCI classes and config register bits ... ]
> It did, for a while, break compatability...

Well, I'm sorry for that.
But I did not expect drivers to actually use those names ...

And you were warned: I left no doubt in my commit messages, 
that the new PCI code was a independent implementation :)

> > I did not expect drivers to actually care for the class code
> > or command register values of a device, since higher level 
> > code should take care of things ...
> > 
> > What are you using those values for ?
> 
> In pci/dpt_pci.c:
> 
> dpt_pci_probe()
> ....
> 
>   if ((dpt_id = (type & 0xffff0000) >> 16) == DPT_DEVICE_ID) {
>     /* This one appears to belong to us, but what is it? */
>     class = pci_conf_read(tag, PCI_CLASS_REG);
>     if (((class & PCI_CLASS_MASK) == PCI_CLASS_MASS_STORAGE) &&
>         ((class & PCI_SUBCLASS_MASK) == PCI_SUBCLASS_MASS_STORAGE_SCSI) ) {
>       /* It is a SCSI storage device.  How do talk to it? */
>       command = pci_conf_read(tag, PCI_COMMAND_STATUS_REG);
>       if ( ((command & PCI_COMMAND_MEM_ENABLE) == 0)
>            && ((command & PCI_COMMAND_IO_ENABLE) == 0) ) {
>         printf("DPT:  Cannot map the controller as memory, nor as I/O :-(\n");
>         return(NULL);
>       }
>     } else {
>       printf("DPT:  Device is not Mass Storage, nor SCSI controller :-(\n");
>       return(NULL);
>     }

Hmmm, why don't you probe for known vendor and device IDs ?

One of the changes to the PCI code, that might follow (I have
not completely made up my mind) is, that the probe will just
associate a driver with a list of vendor/device IDs, and there
will no longer be a xxx_probe() function in the drivers.

One reason is that I want to be able to assign drivers to IDs
(chip or cards IDs) without recompilation.

NCR put a similar probe into their SDMS BIOS (3.xx.xx), where
they used the vendor ID and class code, but changed the code to 
check for specific decide IDs in 4.xx.xx.

The old approach caused trouble to people with NCR SCSI cards
based on new chips, which came with their own 4.xx BIOS, but 
had the (inappropriate) 3.xx BIOS trying to initialize them.

>     command = pci_conf_read(tag, PCI_COMMAND_STATUS_REG);
>     if ( (command & PCI_COMMAND_MASTER_ENABLE) == 0 ) {
>       printf("DPT:  BUSMASTER disabled :-(\n");
>       return (NULL);
>     }

I've never heard of a PCI BIOS, that failed to enable the 
bus-master functionality, but did set up the chip correctly,
else. I really can't imagine a system that would trigger 
this condition!

> And in dpt_pci_attach()
> ....
>   io_base = 0;
>   vaddr   = 0;
>   paddr   = 0;
>   data = pci_conf_read(config_id, PCI_BASEADR0);
> 
>   command = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG);
>   if ( ((command & PCI_COMMAND_MEM_ENABLE) == 0)
>        || (pci_map_mem(config_id, PCI_BASEADR0, &vaddr, &paddr) == 0) ) {
>     /* Either not memory mappable or mapping failed.  Try I/O mapping */
>     if ((command & PCI_COMMAND_IO_ENABLE) == 0
>         || (pci_map_port(config_id, PCI_BASEADR0, &io_base) == 0) ) {
>       free(dpt, M_DEVBUF);
>       printf ("dpt%d: Failed to map memory or I/O registers :-(\n", unit);
>       return;
>     }
>   }
> 
> Makes sense?

The other driver's don't test for the enable bits, and
just rely on the error indication returned by the call
to pci_map_XXX().

You should not check those values from within any driver,
IMHO, but instead just try to map the regions you need,
and perform an error exit if mandatory mappings failed.

BTW: There appears to be a buglet in your code: Every
base address register may only hold either a memory or
a port address, and the address type is hard-wired into
the chip!

This means, that the use of base addr reg 0 for both the 
call to pci_map_mem() and pci_map_port() must be wrong.
(I assume the letter is never tried, since the prior
always succeeds.)

The PCI BIOS needs the type bits (low order bits of the 
address base registers) to be R/O in order to assign valid
addresses. If both memory and port accesses are supported,
then one register will have the two low order bits wired
to 01, and another one will have low order 4 bits of 0000
(or less likely some other even number).

The PCI BIOS uses the low order bits to decide whether 
some currently unused port or memory region is reserved
for that chip, and then puts the base into the register.

You know from the data sheet, which register will hold
a port and which one will hold a memory address, if they
can be assigned.

BTW: Your test of the memory and port enable bits is not
sufficient, if the devices are behind a PCI to PCI bridge,
as Justin Gibbs pointed out to me. (And I'll modify the 
PCI code to correctly return an error indication to the
pci_map_xxx() call, in such a case.)

Regards, STefan



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19970718202558.63332>