SMBus driver for UMDF

To be able to use SMBus from pci I need to enumerate devices on PCI find SMBus device and then to map addreess in kernel space. In normal driver I can do it in 2 ways (kmdf):

  1. WRITE_PORT_ULONG( (PULONG )0xCF8, …); - not recommended
  2. WdfFdoQueryForInterface with GUID_BUS_INTERFACE_STANDARD and then GetBusData - recommended

What about UMDF?
WdfFdoQueryForInterface - this is not supported (this is ok taking care about isolation).
If you want to open driver WdfIoTargetCreate->WdfIoTargetOpen you need a path to PCI driver. And then you need permission to open it.

For Gpio/I2C you have some “SDK” but nothing for SMBus and this bus is very used in board management.
Some suggestion?

xxxxx@yahoo.com wrote:

To be able to use SMBus from pci I need to enumerate devices on PCI find SMBus device and then to map addreess in kernel space. In normal driver I can do it in 2 ways (kmdf):

  1. WRITE_PORT_ULONG( (PULONG )0xCF8, …); - not recommended
  2. WdfFdoQueryForInterface with GUID_BUS_INTERFACE_STANDARD and then GetBusData - recommended

Neither is recommended for SMBus access.  The SMBus resources are
typically assigned to and owned by an SMBus Controller driver.  You
can’t just steal resources that belong to another driver.

What about UMDF?
WdfFdoQueryForInterface - this is not supported…

Right, because a device interface is a set of function pointers.  You
can’t call kernel functions from user-mode code.

If you want to open driver WdfIoTargetCreate->WdfIoTargetOpen you need a path to PCI driver. And then you need permission to open it.

But you still couldn’t access the interface.

For Gpio/I2C you have some “SDK” but nothing for SMBus and this bus is very used in board management.
Some suggestion?

How is it “very used in board management”?  Board management is handled
by board vendors, who write the SMBus Controller drivers and know how to
arbitrate between competing users.  The proper way to do what you’re
doing is to become a child driver of the SMBus Controller and use
whatever interface that driver exposes.  That generally requires DSDT
modifications.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Yup! In the ACPI BIOS.

If you want to play with one of the system SMBus devices, you need to be in the BIOS. There are widely available utilities that resort to butchery to access various SMBus devices… but this is exactly that: Butchery.

So, my suggestion is: Connect it via SPI or I2C if you want to write a driver for it in Windows. If it’s a device on one of the system SMBus controllers and you (a) need to access it for some legitimate business need, do so in the ACPI BIOS, (b) you want to fool with it for fun, forget it.

Simplest question this week!

Peter
OSR
@OSRDrivers

Hi Peter

> If you want to play with one of the system SMBus devices, you need to be in the
BIOS.
Really. How do you realize it? Did you read my post? I explain 2 ways without BIOS.

> So, my suggestion is: Connect it via SPI or I2C if you want to write a driver
for it in Windows
I have another a suggestion. Why don’t make a filter driver for hard disk and redirect I/O to SPI bus to send data to I2C via SMBus. It is faster. Great idea.

Hi Tim,

> Neither is recommended for SMBus access.? The SMBus resources are yypically assigned to and owned by an SMBus Controller driver.? You can’t just steal resources that belong to another driver.

If you install any windows system with correct drivers you will realize there’s no SMBus driver and resource is free. Why is not detected in device manager. No idea. So I don’t steal any resource. It’s there and there’s no for it. 100%.

> Board management is handled by board vendors, who write the SMBus Controller drivers and know how to arbitrate between competing users

Absolute correct. Can you explain me how they succeeded to communicate with SMBus controller from user mode driver and how they can detected it? Practicaly they should have a way to enumerate all PCI devices and get SMBus memory. Because so far I didn’t find any clear explanation in UMDF V2 documentation.

On Jul 2, 2018, at 10:32 PM, xxxxx@yahoo.com wrote:
>
> Hi Peter
>
>>> If you want to play with one of the system SMBus devices, you need to be in the
> BIOS.
> Really. How do you realize it? Did you read my post? I explain 2 ways without BIOS.

No, you didn’t. You gave two unsupported mechanisms that will crash systems sooner or later. Just because something is possible does not mean it is right.

> I have another a suggestion. Why don’t make a filter driver for hard disk and redirect I/O to SPI bus to send data to I2C via SMBus. It is faster. Great idea.

Sarcasm is not an appropriate response when someone is legitimately trying to help you achieve your goal in a supportable and maintainable way.

>>> Board management is handled by board vendors, who write the SMBus Controller drivers and know how to arbitrate between competing users
>
> Absolute correct. Can you explain me how they succeeded to communicate with SMBus controller from user mode driver and how they can detected it? Practicaly they should have a way to enumerate all PCI devices and get SMBus memory. Because so far I didn’t find any clear explanation in UMDF V2 documentation.

What makes you think this is being done from a user-mode driver? The SMBus controllers are making ACPI calls into the BIOS to do the real work. The BIOS owns the resources.

Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Hi Tim,

> What makes you think this is being done from a user-mode driver?
May be some companies do it in user mode - to be more safe?

> The SMBus controllers are making ACPI calls into the BIOS to do the real work. The BIOS owns the resources.???
Ok. Bios is owner of SMBus and we need to do it via ACPI calls. Perfect:

Here we have an SMBus controller:
(d=1f, f=3) 80868c22 devext 0xffffc501308271b0 devstack 0xffffc50130827060 0c05 Serial Bus Controller/Unknown Sub Class

with 2 PDO objects
1: kd> !devstack ffffc50130827060
!DevObj !DrvObj !DevExt ObjectName
ffffc501306a9450 \Driver\ACPI ffffc50130770c40

ffffc50130827060 \Driver\pci ffffc501308271b0 NTPNP_PCI0014

So when I install driver for my hardware PCI\VEN_8086&DEV_8C22&SUBSYS_8C228086 I’ll got 2 FDO. One for ACPI one for PCI.
ACPI will return me next resources:
Int 12
Port: 0xF040-0xF050
And 256 memory space. - Then how can I communicate with ACPI via memory/via port - not documented at all. What data are send it - normal ACPI command? There’s nowhere described.
This is my big problem and I think also for other which directly speak via 0CF8 port.

BR

Mr. “Alabama 2000”… You have less than 10 posts to this list, and I’m going to give you your first warning: Be appreciative of the time and effort ANYone on this forum expends to help you. We’re not doing it as our job… we’re doing it because we want you to succeed in what you’re doing. A little humility on your part will go a long way… especially when you’re in my house – which is exactly what his forum is.

Let me repeat to you, again, what I said earlier but using different words.

Just because you don’t see a driver for a given resource (Windows will typically use “NODRV” for SMBus controllers provided by the the PCH, for example) it does not mean those resources are not in use. These resources are typically in use by the ACPI BIOS. The BIOS uses them during POST and (for example) to configure the memory on the system.

It is, therefore, not relevant that you can create a driver and install it on an SMBus controller instance. Because that controller instance is almost certainly being controller *internally* by the ACPI BIOS.

Therefore… as I said earlier… you can control your SMBus device by writing ACPI BIOS code. That’s the way it’s done on Windows.

ACPI does not provide a generic mechanism for you to talk to arbitrary devices on the SMBus.

If the devices on the SMBus that you’re trying to talk to are YOURs (you put them on the SMBus) you made a mistake in putting them there, because they are not generically accessible in a Windows system except via the BIOS.

If the devices on the SMBus that you’re trying to talk to aren’t specifically yours… then they’re not for your use.

If you WANT to connect a device via a low-cost, low-power, bus that you can control, use I2C or SPI.

Those are your options. I’ve been through this before. I’m not guessing. I’ve done prototyping/proof-of-concept type projects that load drivers and fool with arbitrary SMBus controller on Windows. This type of thing is not suitable for use on a production system. There is stuff using the PCH/ICH resident controllers that you can not properly coordinate with from the host-side. That is the definitive answer.

Peter
OSR
@OSRDrivers

xxxxx@yahoo.com wrote:

> What makes you think this is being done from a user-mode driver?
May be some companies do it in user mode - to be more safe?

No.  You can’t talk to ACPI from user-mode.

Here we have an SMBus controller:
(d=1f, f=3) 80868c22 devext 0xffffc501308271b0 devstack 0xffffc50130827060 0c05 Serial Bus Controller/Unknown Sub Class

with 2 PDO objects
1: kd> !devstack ffffc50130827060
!DevObj !DrvObj !DevExt ObjectName
ffffc501306a9450 \Driver\ACPI ffffc50130770c40
> ffffc50130827060 \Driver\pci ffffc501308271b0 NTPNP_PCI0014
So when I install driver for my hardware PCI\VEN_8086&DEV_8C22&SUBSYS_8C228086 I’ll got 2 FDO. One for ACPI one for PCI.

No, you don’t.  You’ll get one FDO for your driver.  The driver below
you in the stack is the ACPI driver, and  the driver below that is the
PCI bus driver.

        FDO    <– your driver
         v
        PDO    Created by ACPI to allow an SMBus controller driver
         v
        FDO    \driver\ACPI
         v
        PDO    Created by PCI to load ACPI
         v
        FDO    \driver\PCI

ACPI will return me next resources:
Int 12
Port: 0xF040-0xF050
And 256 memory space. - Then how can I communicate with ACPI via memory/via port - not documented at all. What data are send it - normal ACPI command? There’s nowhere described.

You do not communicate with ACPI through memory or I/O ports.  Those are
owned by the ACPI BIOS.  To communicate with ACPI, your driver fetches
the device interface GUID_ACPI_INTERFACE_STANDARD.  That gets you an
ACPI_INTERFACE_STANDARD structure, which contains a set of function
pointers.  Those function pointers call entry points in the ACPI driver,
which calls into the BIOS to do the real work.

//
// ACPI interfaces
//
PGPE_CONNECT_VECTOR GpeConnectVector;
PGPE_DISCONNECT_VECTOR GpeDisconnectVector;
PGPE_ENABLE_EVENT GpeEnableEvent;
PGPE_DISABLE_EVENT GpeDisableEvent;
PGPE_CLEAR_STATUS GpeClearStatus;
PREGISTER_FOR_DEVICE_NOTIFICATIONS RegisterForDeviceNotifications;
PUNREGISTER_FOR_DEVICE_NOTIFICATIONS UnregisterForDeviceNotifications;

What on earth are you actually trying to?  What’s the point of this hackery?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Hi Peter,

Please accept my appologies regarding this missunderstantig. I’m sure that your description is correct way how we should use SMBus. Thank you very much for help.

Hi Tim,

> What on earth are you actually trying to?? What’s the point of this hackery?

Nothing special. I have a computer with board management device on SMBus. I choose a plan where ventilator is quite.
Program send command to board management put ventilator quite and last command is put ventilator max speed - hard but true. This make my programming days a nightmare.
So let’s fix:

  1. Brute force and ignorance -> remove ventilator. Works.
  2. I found that this controller is on SMBus. Then I monitorize commands send it via SMBus. I figure out which command turn ventilator low speed.
    Write a driver in kernel => use 0xCF8 to communicate with SMBus -> Ventilator low -> worked.
    Next step use GetBusData -> ventilator low ->worked.
    So let’s try ultimate let’s move it in user mode. So no chance to use 0x0CF8 or GetBusData. Try to figure a way to do it.

I try to figure out what represent resources but looks this resources are SMBus port and memory and I can use it to send data to SMBus.

Thank you in advance
BR

>This make my programming days a

nightmare. So let’s fix:

Oh… it?s a HOBBY project! Why didn?t you say so at the beginning! Then I wouldn?t have tortured you with my answers.

Peter
OSR
@OSRDrivers

xxxxx@yahoo.com wrote:

>> What on earth are you actually trying to? What’s the point of this hackery?
Nothing special. I have a computer with board management device on SMBus. I choose a plan where ventilator is quite.
Program send command to board management put ventilator quite and last command is put ventilator max speed - hard but true. This make my programming days a nightmare.

So this is all about setting your fan speed??  Have you done any web
searching for this?  There are myriad motherboard tools out there that
can monitor and set your fan speeds.  It’s all been done before.

Of course, if you turn your fan off because the sound bothers you,
there’s a very real chance the end result will be toasted motherboard.

 

So let’s fix:

  1. Brute force and ignorance -> remove ventilator. Works.
  2. I found that this controller is on SMBus. Then I monitorize commands send it via SMBus. I figure out which command turn ventilator low speed.
    Write a driver in kernel => use 0xCF8 to communicate with SMBus -> Ventilator low -> worked.
    Next step use GetBusData -> ventilator low ->worked.
    So let’s try ultimate let’s move it in user mode. So no chance to use 0x0CF8 or GetBusData. Try to figure a way to do it.

You can’t do I/O port access from user-mode.  It’s just that simple. 
User-mode drivers are great for protocol devices like USB, HID, 1394,
etc.  Not so good for hardwired buses like PCI.

 

I try to figure out what represent resources but looks this resources are SMBus port and memory and I can use it to send data to SMBus.

The memory ranges you saw are for way more than the SMBus.  If you go
download the complete 822-page datasheet for the Lynx Point chipset, you
can see what every register in that 256-address range actually does.  It
controls everything from the system DMA controller to the serial ports
to the parallel ports to the real-time clock to the interrupt
controller, and on and on.

However, the chipset doesn’t specify how to set the fan speed.  The
motherboard designer is expected to add that on his own.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

> Not so good for hardwired buses like PCI.

Actually, that does work, as,of,auMDF 2. You can read/write device registers directly from user mode via UMDF. You even can take interrupts. No DMA, though.

Not saying I recommend it…

Peter
OSR
@OSRDrivers

xxxxx@osr.com wrote:

> Not so good for hardwired buses like PCI.
Actually, that does work, as,of,auMDF 2. You can read/write device registers directly from user mode via UMDF. You even can take interrupts. No DMA, though.

Yes, but I didn’t think that included I/O ports.  That takes dangerous
magic manipulating the I/O permission mask.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Ahhhhh… PORTS, specifically.

I really don?t know. I can?t imagine why it wouldn?t work with ports, and I?ve never read any restriction saying that ports won?t work. Remember… one of the alternatives for register manipulation is to forward the operation to kernel mode.

When I get back into the office, I?ll check the code.

Peter
OSR
@OSRDrivers

Hi All,

Thank you very much for support. So ventilator it’s quite(CTRL+1= goes quite CTRL + 2 = goes fast). I map memory to kernal space - not using read/write port. I can read write SMBus registry map. I can arbitrate access to SMBus. All looks perfect. Problem which I met it (small):

  1. create link is changed \DosDevice\MyDevice to \DosDevice\Global\MyDevice
  2. Regitry entry - for inf file - to allow mapping memory to kernel
  3. I use devcon to install it. Must be “devcon update” not “devcon install” - or you have 2 FDO

But from development part it’s absolute not a big difference. I lern something new which is a good day in programming. Thank you again.

BR

I don’t want to leave the archives with something misleading.

I can arbitrate access to SMBus

No, no you can’t. You might THINK you can… but you can’t. You might be using the built-in “this controller is busy and in-use” technique, but that absolutely, positively, does not protect you from access by the BIOS.

So… it’s a hobby project (and I don’t comment on or help people with hobby projects) and a hack. Fine. But let’s not leave the world thinking that this is a real solution. Because it’s not.

I am now locking this thread.

Peter
OSR
@OSRDrivers