Accessing embedded system resources

Hello,

I’m developing an embedded system based on the AMD LX800. We have succesfully developed a driver for our custom PCI target. Now I need to be able to access some of the custom features of the embedded system. This is our first WinXP product, so I’m not overly familiar with the system driver aspects of WinXP.

First, I need to access the GPIO registers of the LX800 companion chip CS5536. The address of those IO registers are located in BAR1 of the PCI ISA Bridge device. WinXP is using “PCI standard ISA bridge” for this device. I also need access to the ACPI registers located a BAR5 and the PM registers at BAR4. This is to disable the Power Button momentarily to access the IO pins. Do I need to develop my own driver for the ISA Bridge to access these IO locations?

Second, I need to access the BIOS flash. For that, I just need access to the memory space 0xFFF80000-0xFFFFFFFF. What kind of driver do I make to just open a memory area?

TIA,
BK

Ugh. There’s no really good solution to this.

First: You’re going to have to resign yourself to the fact that whatever you do, it’s going to be ugly. CERTAINLY there’s no standard, supported, “nice” way to do what you want on Windows. So, you’re either going to have to (a) Write a new ISA Bridge driver (when you don’t really know what the Windows-supplied one does, because the source isn’t in the WDK and it’s not documented) or (b) Live with accessing registers that belong to another device, and hope that you won’t collide with the other driver while he’s doing things to that device.

Given that you have a closed environment, perhaps you you won’t mind taking a few liberties? Each of us has a different tolerance for this sort of hacking and whacking.

I’d probably filter the ISA Bridge driver and learn the contents of the BARs that way. Then… er… just have at those registers that you need to access. Yes, ugly and potentially prone to error. But if those registers are assigned to another device, I see no alternative.

In terms of mapping the BIOS flash area, assuming these are manifestly constant addresses, you can map it into your Kernel Virtual Address Space using MmMapIoSpace.

Ugh. I can’t believe I’m writing this on NTDEV. Note that I’m only replying to this because it’s SPECIFICALLY about a close EMBEDDED system. Do not take anything I’ve written here as license to do something equally stupid on a customer’s general purpose machine.

Peter
OSR

You can use MmMapIoSpace to map your BAR areas at driver Start time and your
driver will be able to access those areas without any problem. This will
give you a kernel-side virtual address. I didn’t try it with the Bios space,
but I don’t see why it won’t work, provided you feed MmMapIoSpace with the
actual physical address of your Bios area.

Watch out, however, if you ask the system to map too big an area it may
bounce you!

Alberto.

----- Original Message -----
From:
To: “Windows System Software Devs Interest List”
Sent: Tuesday, December 18, 2007 3:04 PM
Subject: [ntdev] Accessing embedded system resources

> Hello,
>
> I’m developing an embedded system based on the AMD LX800. We have
> succesfully developed a driver for our custom PCI target. Now I need to
> be able to access some of the custom features of the embedded system.
> This is our first WinXP product, so I’m not overly familiar with the
> system driver aspects of WinXP.
>
> First, I need to access the GPIO registers of the LX800 companion chip
> CS5536. The address of those IO registers are located in BAR1 of the PCI
> ISA Bridge device. WinXP is using “PCI standard ISA bridge” for this
> device. I also need access to the ACPI registers located a BAR5 and the
> PM registers at BAR4. This is to disable the Power Button momentarily to
> access the IO pins. Do I need to develop my own driver for the ISA Bridge
> to access these IO locations?
>
> Second, I need to access the BIOS flash. For that, I just need access to
> the memory space 0xFFF80000-0xFFFFFFFF. What kind of driver do I make to
> just open a memory area?
>
> TIA,
> BK
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer

From what’s been said, the BIOS area should be fairly straight forward to access, as it is just a fixed memory location at the top of the physical address map. Apparently MmMapIoSpace will allow me access to that area.

The BAR issue sounds a bit trickier. BARS are actually located in PCI config space, so it requires a config cycle over the PCI bus to access. The only ways I know to do this are to talk directly to the PCI host bridge at IO 0x0CF8, which is extremely scary since I would never know who might be doing what at the host bridge, or to use PCI BIOS calls to do it, which kind of has the same problem.

One advantage I have is that since this is a closed embedded system, I always know where the BAR’s are mapped to. Since I “know” the IO locations that the BAR’s point to, I should just be able to write to them directly, with the caveat that if anyone else is trying to access those register, unpredictable results would occur. Is that correct?

Would the proper way to access the IO registers be to use READ_PORT_ and WRITE_PORT_ functions?

Sorry… did you not read my reply to your original question? That’s the point of filtering the ISA Bridge: You get the resources that way, without accessing PCI Config Space.

I’d rather see you get the BARS from filtering _MN_START_DEVICE, and then directly accessing them… with the caveat you (and I) mentioned.

If the registers are in PORT space on the current machine, you use READ_PORT_xxx and WRITE_PORT_xxx. OTOH, if the registers are in MEMORY space on the current machine, you use READ_REGISTER_xxx and WRITE_REGISTER_xxx after mapping the registers into kernel virtual address space using MmMapIoSpace.

Pardon me for pointing this out, but these are pretty fundamental questions. I really strongly recommend that you do some reading on Windows drivers, and take a look at a few PCI-based driver samples (at the very least, download and read through the DIO24 sample from OSR Online), before embarking on this project.

Peter
OSR

If these are your own BARs, you get their physical addresses when you do
your PCI setup at your driver start time, inside the
PCM_PARTIAL_RESOURCE_LIST structure in your stack. If your BAR points to
memory, you do not need any kind of I/O: you can just map the provided
physical addresses into your kernel-side virtual address space.

If your BAR points to an I/O space, ask your hw guys to map it to physical
memory space. :slight_smile:

If however you need to access the PCI config space (for example, to tweak
some hardware aspect of your chip), your best bet is to call the PCI Bus
Driver to do it for you. There are samples out there, and I faintly remember
an NT Insider article on it too, although I may be wrong.

I would not use the CF8 ports, because Windows does not guarantee proper
synchronization when you access them.

Alberto.

----- Original Message -----
From:
To: “Windows System Software Devs Interest List”
Sent: Wednesday, December 19, 2007 9:40 AM
Subject: RE:[ntdev] Accessing embedded system resources

> From what’s been said, the BIOS area should be fairly straight forward to
> access, as it is just a fixed memory location at the top of the physical
> address map. Apparently MmMapIoSpace will allow me access to that area.
>
> The BAR issue sounds a bit trickier. BARS are actually located in PCI
> config space, so it requires a config cycle over the PCI bus to access.
> The only ways I know to do this are to talk directly to the PCI host
> bridge at IO 0x0CF8, which is extremely scary since I would never know who
> might be doing what at the host bridge, or to use PCI BIOS calls to do it,
> which kind of has the same problem.
>
> One advantage I have is that since this is a closed embedded system, I
> always know where the BAR’s are mapped to. Since I “know” the IO
> locations that the BAR’s point to, I should just be able to write to them
> directly, with the caveat that if anyone else is trying to access those
> register, unpredictable results would occur. Is that correct?
>
> Would the proper way to access the IO registers be to use READ_PORT_ and
> WRITE_PORT_ functions?
>
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer