How does Microsoft Storport work with SATA legacy mode? - windows

I have a driver designed in Storport-miniport model. I'm trying to modify the driver to support SATA legacy mode. Here are some questions which I am looking for help:
the I/O Address
In Native mode, the IO address is shown in BAR0 to BAR3. But in legacy mode, the IO address is fixed(0x1f0 for command, 0x3f6 for control in channel-0). In native mode, we used StorPortGetDeviceBase to get the memory-map of the IO address, but it doesn't work with legacy mode since Storport could only handle the IO space announced in PCI space. Therefore, I tried to use MmMapIoSpace to allocate memories. Is this a correct way?
The IRQ
Just like IO Address, IRQ is fix for legacy mode. But the whole thing about IRQ is done by Storport, should I or could I do anything here?
the HwStorInitialize does not called
MSDN says HwStorInitialize should be called if HwStorFindAdapter return true. But in my driver with legacy mode, the HwStorInitialize does not called so the adapter in device manager shows not ready with yellow mark. Did I miss something?
ATAport-minoport
When I was trying to figure out those problems, I found there's another driver mode called ATAport-miniport. Does this mean I should design my driver in the model if my adapter is in legacy mode? Is it possible to implement legacy mode in the same driver as native mode by Storport-miniport?

Related

Serial driver in userspace

Is it possible to write serial driver in userspace, yet, have the device appear as regular serial driver /dev/ttyS0 in the system ?
The full story is that we have a pci express fpga, and there are several devices behind the pci express fpga: serials, canbus, i2c, mdio, etc.
I thought to implement it as uio_pci_generic, yet the serial driver is a bit problematic because we rather that it will appear as regular serial /dev/ttyS0.
If the above is not possible: Is it possible to implement some of the pci devices in kernel (serial) and others in userspace ? Is it problematic in terms of interrupt ?
Thanks for any idea.
Yes, you can do this using a pty. The user mode driver opens the master end of the pty and the application that wants to use the serial port opens the slave end. Search for Linux pty.
Everywhere where you need to use interrupts you need to write code for kernel space not user space. Interrupt handlers need to be serviced in atomic context and user space is not able to provide atomic context. Second thing - if you need to write HAL layer - it also has to be written in kernel space.

Communication between 2 windows kernel mode drivers

Never develop any driver before.
Anyway I'm now writing 2 simple windows kernel mode drivers, and the 2 drivers will be installed onto 2 different devices which connect to 2 different buses(ISA bus / PCI bus), and somehow the 2 drivers need to talk to each other and data exchange is also expected, is there any efficient way to achieve that??
Kernel event might be able to enable the synchronization, but how about the data exchange?
In user mode, pipe/socket might be an option, but in kernel mode, is there a counterpart of named pipe or something? Google said that there's no documented API for kernel mode pipe usage...
I'm not quite familiar with windows driver framework, hope I'm making sense..
thanks!
There is IRP_MJ_INTERNAL_DEVICE_CONTROL for communication between kernel-mode components. Driver #1 opens Driver #2 by its name and sends internal IOCTLs with input or/and output data.
#Harry Johnston: You do need to be careful about writing to a shared memory location. I presume you were responding with the context of implementing a serial buffer between the two devices (only one device can write, and the other can only read), but it should obviously be added that you should approach shared memory locations between devices with caution, especially if there is going to be frequent writes to that location by both devices and cause undefined behavior or lock-ups from interrupts being serviced seemingly unexpectedly.

where is device driver code executed? Kernel space or User space?

Part1:
To the linux/unix experts out there, Could you please help me understanding about device drivers. As i understood, a driver is a piece of code that directly interacts with hardware and exposes some apis to access the device. My question is where does this piece of code runs, User space or Kernel space?
I know that code that is executed in kernel space has some extra privileges like accessing any memory location(pls correct if i'm wrong). If we install a third party driver and if it runs in kernel space, wouldn't this be harmful for the whole system? How any OS handles this?
Part2:
Lets take an example of USB device(camera, keyboard..), How the system recognizes these devices? how does the system know which driver to install? How does the driver know the address of the device to read and write the data?
(if this is too big to answer here, pls provide links of some good documentation or tutorials.., I've tried and couldn't find answers for these. pls help)
Part 1
On linux, drivers run in kernel space. And yes, as you state there a significant security implications to this. Most exceptions in drivers will take down the kernel, potentially corrupt kernel memory (with all manner of consequences). Buggy drivers also have an impact on system security, and malicious drivers can do absolutely anything they want.
A trend seen on MacOSX and Window NT kernels is user-space drivers. Microsoft has for some time been pushing the Windows Userspace Driver Framework, and MacOSX has long provided user-space APIs for Firewire and USB drivers, and class-compliant drivers for many USB peripherals. it is quite unusual to install 3rd party kernel-mode device drivers on MacOSX.
Arguably, the bad reputation Windows used to have for kernel panics can be attributed to the (often poor quality) kernel mode drivers that came with just about every mobile phone, camera and printer.
Linux graphics drivers are pretty much all implemented in user-space with a minimal kernel-resident portion, and Fuse allows the implementation of filing systems in user-space.
Part 2
USB, Firewire, MCI (and also PCI-e) all have enumeration mechanisms through which a bus driver can match the device to a driver. In practice this means that all devices expose metadata describing what they are.
Contained within the metadata is a DeviceID, VendorID and a description of functions the device provides and associated ClassIDs. ClassIDs facilitate generic Class Drivers.
Conceptually, the operating system will attempt to find a driver that specifically supports the VendorID and DeviceID, and then fall back to one that supports the ClassID(s).
Matching devices to drivers is a core concept at the heart of the Linux Device Model, and exact matching criteria used for matching is match() function in the specific bus driver.
Once device drivers are bound to a device, it uses the bus-driver (or addressing information given by it) to perform read and writes. In the case of PCI and Firewire, this is a memory mapped IO address. For USB it bus addressing information.
The Linux Documentation tree provides some insight into the design of the Linux Device Model, but isn't really entry-level reading.
I'd also recommend reading Linux Device Driver (3rd Edition)

What is a Windows Kernel Driver?

What is Windows Kernel Driver written with the WDK?
What is different from normal app or service?
Kernel drivers are programs written against Windows NT's native API (rather than the Win32 Subsystem's API) and which execute in kernel mode on the underlying hardware. This means that a driver needs to be able to deal with switching virtual memory contexts between processes, and needs to be written to be incredibly stable -- because kernel drivers run in kernel mode, if one crashes, it brings down the entire system. Kernel drivers are unsuitable for anything but hardware devices because they require administrative access to install or start, and because they remove the security the kernel normally provides to programs that crash -- namely, that they crash themselves and not the entire system.
Long story short:
Drivers use the native API rather than the Win32 API
This means that drivers generally cannot display any UI.
Drivers need to manage memory and how memory is paged explicitly -- using things like paged pool and nonpaged pool.
Drivers need to deal with process context switching and not depend on which process happens to have the page table while they're running.
Drivers cannot be installed into the kernel by limited users.
Drivers run with privileged rights at the processor level.
A fault in a user-level program results in termination of that program's process. A fault in a driver brings down the system with a Blue Screen of Death.
Drivers need to deal with low level hardware bits like Interrupts and Interrupt Request Levels (IRQLs).
It is code that runs in kernel mode rather than user mode. Kernel mode code has direct access to the internals of the OS, hardware etc.
Invariably you write kernel mode modules to implement device drivers.
A kernel driver is a low-level implementation of an "application".
Because it runs in the kernel context, it has the ability to access the kernel API and memory directly.
For example, a kernel driver should be used to:
Control access to files (password protection,hiding)
Allow accessing non-standard filesystems (like ext, reiserfs, zfs and etc.) and devices
True API hooks
...and for many other reasons
If you'd like to get know more, you can search for keyword "ring0" with your favorite search engine.
Others have explained the difference as the perspective of system level.
If you are doing development in C++, there are below differences in User mode development and kernel-mode development.
Unhandled exceptions crash the process in User mode, but in kernel mode, it crashes the whole system(face BSOD).
When the user-mode process terminates without free private memory, the system implicitly free process memory. But in kernel mode, remaining memory free after system boot.
The user-mode code is written and execute in PASSIVE_LEVEL. In kernel mode, there are more IRQL level.
Kernel code debugging done using separate machines. But you can debug user mode on same machine.
you can't use all C++ functionality in kernel-mode such as Exception handling and STL.
Entry points are different, in user mode, you use the main as the entry point. But in kernel mode, we need to use DriverEntry.
You can't use new operator in kernel mode, you need to overload it explictly.

Device drivers and Windows

I am trying to complete the picture of how the PC and the OS interacts together. And I am at point, where I am little out of guess when it comes to device drivers.
Please, don´t write things like its too complicated, or you don´t need to know when using high programming laguage and winapi functions. I want to know, it´s for study purposes.
So, the very basic structure of how OS and PC (by PC I mean of course HW) is how I see it is that all other than direct CPU commands, which can CPU do on itself (arithmetic operation, its registers access and memory access) must pass thru OS. Mainly becouse from ring level 3 you cannot use in and out intructions which are used for acesing other HW. I know that there is MMIO,but it must be set by port comunication first.
It was not like this all the time. Even I am bit young to remember MSDOS, I know you could access HW directly, becouse there ws no limitation, no ring mode. So you could to write string to diplay use wheather DOS function, or directly acess video card memory and write it by yourself.
But as OS developed, there is no longer this possibility. But it is fine, since OS now handles all the HW comunication, and frankly it more convinient and much more safe (I would say the only option) in multitasking environment. So nowdays you instead of using int instructions to use BIOS mapped function or DOS function you call dll which internally than handles everything you don´t need to know about.
I understand this. I also undrstand that device drivers is the piece of code that runs in ring level 0, so it can do all the HW interactions. But what I don´t understand is connection between OS and device driver. Let´s take a example - I want to make a sound card make a sound. So I call windows API to acess sound card, but what happens than? Does windows call device drivers to do so?
But if it does call device driver, does it mean, that all device drivers which can be called by winAPI function, must have routines named in some specific way? I mean, when I have new sound card, must its drivers have functions named same as the old one? So Windows can actually call the same function from its perspective? But if Windows have predefined sets of functions requored by device drivers, that it cannot use new drivers that doesent existed before last version of OS came out.
Please, help me understand this mess. I am really getting mad. Thanks.
A Windows device driver is a bit like a DLL: except that instead of an application dynamic linking/loading it, it's the O/S that dynamic links/loads it.
Registry entries tell the O/S what device drivers exist (so that the O/S knows which device drivers to dynamic-link/load).
The device drivers run in ring 0. In ring zero, they (device drivers) don't have access to (can't link to or use) Windows APIs: instead they have access to various NT kernel APIs.
But if it does call device driver, does it mean, that all device drivers which can be called by winAPI function, must have routines named in some specific way? I mean, when I have new sound card, must its drivers have functions named same as the old one? So Windows can actually call the same function from its perspective?
Basically yes. All the device drivers within a given type or class (e.g. all video drivers, or all disk drivers) have a similar API, which is invoked by the O/S (and/or invoked by higher-level drivers, for example disk drivers are used/invoked by file system drivers).
The Windows Device Driver Kit defines the various APIs and includes sample drivers for the various types of device.
But if Windows have predefined sets of functions requored by device drivers, that it cannot use new drivers that doesent existed before last version of OS came out.
The O/S is dynamic-linking to the device driver functions: because device driver APIs are predefined, device drivers are interchangeable as far as the O/S is concerned; new device drivers can be written, provided they support (are backward-compatible with) the standard device driver API.
The dynamic-linking mechanism is very similar to the way in which COM objects or C++ classes implement any predefined pure-abstract interface: a header file in the DDK declares the pure-abstract interface (like virtual functions), device drivers implement these functions, and the O/S loads the drivers and invokes these functions.
The basics:
Please note that this explanation is simplified and sometime only true for most cases and not all.
Most HW devices you will ever encounter will have these basic operations:
Write to memory(or Registers) on them.
Read from memory(or Registers) on them.
This is enough to control the HW, to give it the data it needs, and to get the data you want from it.
These memory areas are mapped by the BIOS and/or the OS to the Physical memory range on your PC (which may in turn be accessed by your driver.)
So we now have two operations READ and WRITE that the device driver knows to do.
In addition, the driver can read and write in a manner that does not involve the cpu. This is called Direct Memory Access (DMA) and usually performed by your HW.
The last type of operation is called INTERRUPTS and is meant for your HW to notify your driver of something that just happend. This is usually done by the HW interrupting the CPU and calling your driver to perform some operation in high priority. For example: an image is ready in the HW to be read by the driver.

Resources