Re: New-bus unit wiring via hints..

From: John Baldwin <jhb_at_freebsd.org>
Date: Tue, 30 Oct 2007 16:56:54 -0400
On Tuesday 30 October 2007 04:00:28 pm Marcel Moolenaar wrote:
> On Oct 30, 2007, at 10:48 AM, John Baldwin wrote:
> 
> >>> That isn't what is happening though.  The port marked "1" is at  
> >>> 0x3f8
> >>> and happens to be "later" in the namespace than the port marked "2"
> >>> which is at 0x2e8.  The BIOS may _optionally_ decide to communicate
> >>> this to the OS via the _UID method, but the _UID is only guaranteed
> >>> to be a string that it suitable for use in a label in a GUI dialog
> >>> box.
> >>
> >> Doesn't this imply that enumerating on the lexicographical ordering
> >> of the (optional) _UID method would help us do what firmware writers
> >> intend?
> >>
> >> In other words, we don't need a number. We just need a means to
> >> determine the relative order and we enumerate in that relative
> >> order. Isn't that how it is now (and if not shouldn't it be that
> >> way)?
> >
> > No.  They are strings that have no implied ordering.
> 
> Then there's no problem, for if _UID is designed as a user-visible
> label and there's no ordering then no-one can claim that one is
> to be before the other and thus that the logical ordering in the
> AML is in fact the right ordering. This of course means that the
> user can see COM2 before COM1 in some user-interface. This of course
> is exactly in accordance with the firmware and as such correct.

It would be interesting to see what Windows does since it still 
maintains 'COM1:' and 'COM2:' device aliases (if those are the correct DOS 
device names).

> >>> Even if a PC has non-standard resources for COM1 and COM2, the  
> >>> serial
> >>> ports will show up as sio2 and sio3.
> >>
> >> This is another sio(4) bug that uart(4) doesn't have, yes :-)
> >
> > Hmmm, I don't think you parsed what I meant, but maybe you mean that  
> > uart(4)
> > doesn't have the poorly-implemented "feature" in sio(4) to make sure  
> > that all
> > non-ISA serial ports start at unit 2 to "reserve" sio0 and sio1 for  
> > COM1 and
> > COM2?
> 
> Exactly.
> 
> >  Just look in sio_pci.c for 'device_set_unit()' which the current
> > wiring patches remove with a vengance by making hints always reserve  
> > a given
> > (name, unit) tuple.
> 
> And since hints are shipped by us with default values, what
> we did is remove the poorly-implemented "feature" from sio(4)
> only to bank on hints to yield the same result, which makes
> hints nothing more than a different poorly-implemented
> "feature" :-)

So you are missing that 1) our users really want this feature, and 2) by 
making hints do the reservation instead of _hard-coding_ it into the driver 
we know let users dictate how it should work since they can adjust the hints 
to suit their needs but still satisfy what users expect on off-the-shelf 
hardware with the default hints that ship.

> >>> Since you don't care what sio0
> >>> means at all why not let other people who _do_ care have it work on
> >>> their
> >>> systems?
> >>
> >> "I" may not care what sio0 means, but that doesn't mean "I" don't
> >> care that "my" serial ports aren't numbered starting with 0.
> >
> > And you could have an empty hints file and be happy.
> 
> With the exception of course of having an OS that does the
> wrong thing OOTB and that requires extensive fiddling to
> behave correctly, increasing the amount of maintenance and
> upgrade hassle.

?  For the vast majority of x86 boxes (including all the varied boxes we
have at work) the default hints will work just fine OOTB.  Users are free to 
edit this, so it remains under user control and doesn't require a recompile.

> >>>> You rightly point out that what it really boils
> >>>> down to is how devX maps to a port on the back or
> >>>> front of the machine. This mapping should not
> >>>> change gratuitously. Device wiring achieves that.
> >>>
> >>> But on what basis will you wire things?
> >>
> >> Correcting the mapping of device instances to physical/visible
> >> ports will need to be based on user input. A default mapping,
> >> based on the self-enumerating ability of hardware/firmware, may
> >> not get it just right in all cases. But may provide a good and
> >> reliable starting point that may end up 90+% correct.
> >
> > Oof.  See, here is where I think we hit a snag. :(  I'm thinking in  
> > terms of
> > automated installations to a wide variety of server boxes that don't  
> > have
> > a GUI with a mouse and monitor hooked up so a user can clicky-clicky  
> > to set
> > which serial port is sio0. :(
> 
> I don't see a snag. But maybe that's because I use
> uart(4) on my machines and I have a serial consoles
> no matter how things are enumerated...

So.  I misread how uart's stuff works the first time, but I think I understand 
now, but I think it has its own confusion.  So uart_cpu_{i386,amd64} expect 
there to be uart hints (wait, I thought hints were the great satan?) that are 
identical to sio hints.  Thus:

hint.uart.0.at="isa"
hint.uart.0.flags="0x10"
hint.uart.0.port="0x3f8"
hint.uart.0.baud="9600"

However, if you have a system with a PCI serial device or where ACPI lists the 
darn things backwards then uart0 might be the PCI device, and, say, uart2 
might be the device corresponding to these hints.  The uart(4) driver then 
goes and scans the hints on its own to find a set of hints that matches the 
resources for uart2 and migrates the flag (and thus the serial console 
setting) over to uart2, so uart2 (device at 0x3f8) does get set to the serial 
console.  But /dev/ttyu0 in userland doesn't match hint.uart.0.  Instead, the 
user has to know (how??) that it's /dev/ttyu2 when they setup /etc/ttys to 
have a getty listening on COM1.  That seems very non-intuitive.  At least 
remove the unit numbers or something and do:

uart.console.port=0x3f8
uart.console.baud=9600

or some such.  It seems very POLA-violating to have uart0 hints match some 
other unit number.  Of course, that solves the console problem but what if
someone wants to apply a different property to a device, like 
hint.foo.0.disable? or hint.foo.0.bar?  ("baud" above corresponds to 
a "bar").

> >>> The only currently reliable
> >>> way I can see to wire things on x86 for an ISA device (and yes, the
> >>> COM port on a PC is ISA even if ACPI is what enumerates it rather  
> >>> than
> >>> PNPBIOS) is I/O resources or the name of the device in the ACPI
> >>> namespace (ACPI-only).
> >>
> >> I disagree. Since the firmware describes the legacy devices present
> >> in the system, the only reliable way is to trust that information.
> >> Sure, bugs may exist but 95+% of the FreeBSD code assumes correctness
> >> of hardware as it is, so why not in this respect?
> >
> > You've missed the point of this entirely then. :(  Yes, the firmware  
> > is
> > authoritative, and part of the goal is to fix a long-standing  
> > weakness where
> > the OS is presented with two different enumerations of hardware: one  
> > supplied
> > by the user via hints and one supplied by the firmware.
> 
> The "weakness" you mention is really the OSes own failure by
> "presenting" itself with hardware information that has no
> relation to the machine that it runs on, because it's
> actually fixated by virtue of being part of the OSes source
> code. It isn't supplied by the user at all. We supply it to
> ourselves. Don't go blaming the user for that...

Umm, the user can adjust /boot/device.hints (I do) and can even adjust it at 
boot time in the loader.
 
> >  The idea is to trust
> > the firmware's notion of resources since it probably knows better  
> > while
> > allowing for other non-resource information provided by the user to  
> > be tied
> > to the correct piece of hardware.
> 
> Agreed...
> 
> He, that's what I said previously and you responded to with
> saying that we hit a snag. I guess we don't then; or do we?
> I'm confused now :-)

The snag is you want the user to explicitly set it all up whereas I require it 
to be automated and reliable (_UID and ACPI namespace node names are not 
reliable as per previous e-mails).

> >> Anyway, when ACPI describes the hardware, I prefer not to call the
> >> legacy hardware ISA devices. It's important to make a clear  
> >> distinction
> >> between enumerating and non-enumerating hardware, because that allows
> >> you to create mechanisms for dealing with non-enumerating hardware  
> >> (i.e.
> >> hints) without creating conflicts or ambiguity with enumerating HW.
> >> We have convoluted this and mistakenly accepted this convolution as a
> >> property of ISA hardware.
> >>
> >> I've been advocating that our bus-abstraction is a good one. Devices
> >> enumerated by ACPI can be said to be attached to an ACPI bus. At  
> >> least
> >> it's not more wrong than saying that they are ISA devices when it's
> >> obvious that there's no ISA bus to be found in modern hardware and  
> >> all
> >> the legacy hardware is really on the chipsets LPC bus.
> >
> > You continue to ignore that ACPI is not just a simple bus, but is a  
> > namespace
> > that enumerates devices on multiple busses such as ISA/LPC, SMBus  
> > (e.g. an
> > IPMI SSIF interface can be enumerated via ACPI), etc.  It is much more
> > generic than just an ISA enumerator like PNPBIOS.
> 
> No, I don't ignore anything. I explicitly and deliberately use
> the term "abstraction". It's a simplified representation of
> reality. An "idea". My choice of calling ACPI a bus is probably
> what confuses you. I'm fully aware that it is much more than a
> bus, but it still "quacks" like one WRT legacy hardware...

So where do you hang non-ISA devices on "dumb" busses like IIC that ACPI 
enumerates?  Off acpi0 or the relevant parent such as iic0 or smbus0?

> >>> For uart console wiring you use I/O resources for
> >>> wiring even.
> >>
> >> Yes, but not "even". Since bus-enumeration hasn't happened yet,
> >> we can not describe the serial console by name+unit, because we
> >> have no way of knowing upfront what unit number will be assigned
> >> to the UART. The only way you can describe the serial console
> >> is by hardware resources or by firmware-level names (such as is
> >> the case on powerpc & sparc64).
> >>
> >> This is why using hints to "mark" the console is wrong.
> >>
> >> Note also that on ia64 (at least) ACPI tables exist that describe
> >> the serial console (and debug port) and those tables use hardware
> >> resources. So, the common denominator is I/O resources (even for
> >> OFW-based machines) and as it is, it's really the only thing you
> >> need (module hardware type) to make a low-level console work.
> >>
> >> The only correct way to identify hardware for use as low-level
> >> console is by it's location in I/O space (module hardware type).
> >> This is what uart(4) does and it's one of the reasons uart(4)
> >> works on all platforms even though low-level console support is
> >> highly machine dependent. It's the right way of doing it and
> >> as such it just works.
> >>
> >> Do not mistake low-level console identification with bus-enumeration
> >> device wiring or it being similar to hints.
> >>
> >> To re-iterate:
> >> We should reserve hints for describing non-enumerating hardware
> >> (which means device.hints should be non-existent OOTB) and we
> >> should add other mechanisms to wire devices to hardware, making
> >> use of the fact that underneath it mechanisms exist to enumerate
> >> the hardware (incl. hints for non-enumerating hardware). In the
> >> future we can replace hints with a more flexible and expressive
> >> means to describe hardware so that it better meets the needs of
> >> embedded environments and without it impacting device wiring.
> >
> > So what do you want: 'wire.sio.0.*?'  Or do you want XML or some  
> > binary
> > registery like Windows that can't be modified by the user w/o first  
> > booting
> > the OS (which is real handy when it gets corrupted).
> 
> What I want is something that is appropriate. If we want to wire
> hardware to devices, then we need to be able to uniquely identify
> a device in hardware. A path if you will that mentions busses,
> bridges devices and functions therein. Look at ACPI, EFI and OFW
> for example. Such an identification is the keying entity. Data
> that corresponds to that key can be complex or compound so that
> you can actually specify which driver you want to use above and
> beyond simply wiring it to a unit number. This also also allows
> us to add other pieces of information.
> 
> I'm not going to give concrete examples, because I foresee that
> the discussion will then be about how my "solution" sucks rather
> than it being treated for what it is: an illustration -- something
> to explain what I said and in no way complete or even usable.
> 
> Ok, what the heck. For better or for worse:
> 
> \begin{/boot/hardware.conf}
> # Lines starting with '#' are comments
> [pci0.0.18.0]
>     # First function: standard UART
>     # We use this for remote GDB
>     driver="sio"
>     unit=2
>     dbgport="9600,n,8,1"
> [pci0.0.18.1]
>     # Second function: standard but memory-mapped UART
>     # doesn't work with sio(4) -- needs uart(4)
>     # We use this one as console.
>     driver="uart"
>     unit=3
>     console="115200,n,8,1"
> \end{/boot/hardware.conf}
> 
> Don't get confused about marking the hardware as console
> or debug port and how we do the same in hints. It isn't
> the same.
> Hints mark the driver instance as console or debug port.
> Here I mark the *hardware* as console or debug port, even
> if we don't wish to wire it to a driver instance (although
> we do in the example)
> Fundamentally different!

I can appreciate that, though I consider that I'm binding "sio0" to a piece of 
hardware so that the other settings for sio0 are bound to the hardware and 
not to the first device that the sio(4) driver decides to attach to.  I 
actually would like the ability to do something akin 
to 'hint.pci0.18.0.0.disabled=1' to disable a PCI device.  (Granted, that's 
still in MIB form rather than a flat file, but conceptually similar.  I still 
prefer using the kernel env primed via a file in /boot because you can adjust 
the kernel env easily in the loader.)

Another thing to consider is that if you are going to "wire" a device to a 
specific driver/unit number (so I can make COM1 always be sio0/uart0 and thus 
always /dev/ttyd0|/dev/ttyu0) you need to make sure you reserve that 
driver/unit combo so it can't be probed or attached by something else.

> > Right now the current "solution" results in various places (like my  
> > employer)
> > just turning off the ACPI support for sio(4) because hints are more  
> > reliable
> > for us than ACPI when it comes to enumerating serial ports in _real_  
> > _world_
> > _x86_ server-class machines.
> 
> Use uart(4)?

No.  Having to guess which device to start the getty on rather then being able 
to always use /dev/ttyd0 is annoying for one, and just always using hints 
works fine since COM1/COM2 is an effective de facto standard on all the 
hardware we buy at work.

-- 
John Baldwin
Received on Tue Oct 30 2007 - 20:59:42 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:20 UTC