haiku/docs/develop/kernel/sdhci_mmc_driver.md
krish_iyer 0ea0138965 SDHCI MMC Driver Documentation
Change-Id: I4bbe302fabd21133a9c03b9e48a407db8afbc70e
Reviewed-on: https://review.haiku-os.org/452
Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
2018-08-10 12:08:35 +00:00

7.6 KiB

SDHCI MMC Driver

This driver project is a part of GSoC'18 and is aimed at providing support for PCI devices with class 8 and subclass 5 over x86 architecture. This document will make you familiar with the code produced during GSoC, loading and testing the driver(including hardware emulation), insight into the code and future tasks.

For detailed explanations about the project, you can refer the weekly reports and comment issues if any. For this project we have referred SD Host Controller Spec Version 1.00 and Physical Layer Spec Version 1.10.

Loading and testing the driver

Emulating the hardware

We will emulate a SDHC device using qemu as all system may not have the device. These days systems provide transfer to SD/ MMC card over USB. The document will not instruct you on how to build haiku but you can refer the link to compile and build the haiku images or the week #1 and #2 project report will also work. You can also cherry pick changes from another ticket

After building the image, we will emulate the hardware and host haiku on top of that.

Installing Qemu

apt-get install qemu

Creating Virtual Harddrive

qemu-img create haiku-vm.img 10G

Booting OS in virtual drive

Note: if you generated a raw image during build then creating virtual hard drive and booting the OS in hard drive is not required.

qemu-system-x86_64 -boot d -cdrom haiku/generated.x86_64/haiku-nightly-anyboot.iso -m 512 -hda haiku-vm.img

Hosting Haiku on x86

qemu-system-x86_64 haiku-vm.img

Emulation

For emulating a sdhci-pci device

qemu-img create sd-card.img 10G
qemu-system-x86_64 ~/haiku/generated.x86_64/haiku.image -hdd haiku_drive_2.img -device sdhci-pci -device sd-card,drive=mydrive -drive if=sd,index=0,file=sd.img,format=raw,id=mydrive -m 512M -enable-kvm

Testing and loading the driver

Note: This project's code has already been merged but currently disabled because it's not useful en user currently. In order to add binary to kernel and load it, we need to mention the package in build files.

:build/jam/images/definitions/minimum

In SYSTEM_ADD_ONS_BUS_MANAGERS and add following line under that.

mmc_bus
:haiku/build/jam/packages/Haiku

Under # modules add

AddFilesToPackage add-ons kernel busses mmc : sdhci_pci ;

Under # boot module links

sdhci_pci

Under # drivers add

AddNewDriversToPackage disk mmc : mmc_disk ;

Above following code in the build files will include your module, in order to build with the kernel you need to execute

cd generated.x86_64
jam -q update-image kernel sdhci_pci mmc_disk mmc_bus

Now host haiku with sdhci-pci device, open the terminal and execute following commands: Note: Don't worry if you don't understand the log output of the commands.

cat /var/log/syslog | grep "sdhci_pci\|mmc_bus\|mmc_disk"

If you are able to see some output of above-mentioned command then it means that you have successfully loaded the driver.

Insight into the code and future tasks

MMC Bus

  • src/add-ons/kernel/busses/mmc * sdhci-pci.cpp * sdhci-pci.h * Jamfile

The Bus Manager

  • src/add-ons/kernel/bus_managers/mmc
    • mmc_bus.cpp
    • mmc_module.cpp
    • mmc_bus.h
    • Jamfile

Disk Driver

  • src/add-ons/kernel/drivers/disk/mmc
    • mmc_disk.cpp
    • mmc_disk.h
    • Jamfile

Hardcoding the driver

  • src/system/kernel/device_manager
    • device_manager.cpp

Insight into the code

MMC Bus

So there's some called PCI bus and it something which was developed in order to manage the load on the CPU and easy for the CPU to manage the devices. Now our controller, SDHC will be plugged to the PCI bus, also which has the control over card. Now the first job will be finding the controller form PCI bus from all the devices connected. Every device is a node which has certain info about the device. So we need to get the PCI bus node(parent node) and get the device and register another node which will be called a child node or MMC bus. So if suppose I have another driver which get data from MMC bus and register another node then in that case MMC bus will be a parent node and the node I will be registering with the information will be the child node.

So supports_device() will do that job of finding the device of particular class and subclass. Now with register_child_devices() we will register the bus node and attach certain info like slot info etc. Now that we have a bus, we can read number of slots and map the register set for each one of them, these register will help us to operate the controller and drive the card. We mapped the register using MMUIO method where we take register address form physical memory and assign to virtual one. In order to do that we have declared structure(struct registers) with no zero padding so that mapping will be precise.

After we mapped the registers, resetting the register sets confirmed that register mapping is functional. We have then declared functions for setting up the clock, reset etc.

static void sdhci_register_dump(uint8_t, struct registers*);
static void sdhci_reset(struct registers*);
static void sdhci_set_clock(struct registers*, uint16_t);
static void sdhci_set_power(struct registers*);
static void sdhci_stop_clock(struct registers*);

After this much we need to setup a interrupt handler which will call a function in the driver when something occurs

status_t sdhci_generic_interrupt(void*);

The Bus Manager

We need something to take up the job of certain tasks like data transfer and return back to driver when job is done. Class was a ideal tool for us because as soon as the job is done we no longer any of the data which stays with the variable, we have destructor for deleting the object.

It is not linked for time being but will be useful at the time of data transfer etc.

Disk Driver

So it's main job is to publish slots somewhere like /dev/mmc/.. So after disk gets published, we can mount the device and do transfer function on the memory device(SD/ MMC).

Hardcoding the driver

In order to make the driver loadable and to tell the kernel that we really has built the support for a particular device, we need to mention the class and location of the driver module to the device_manager.

Tasks to be completed

We have to get the response from the card of commands which controller issues. We have tried a lot and looked into more deeper aspect but nothing worked, I am sure we have really missed something. The detailed report on responses and testing will found in last few weeks report.

Once we get the response from the card, we can complete the power sequence and so does other sequence which are mentioned in third phase outline.

If you find it difficult to understand the driver development and it's functioning and role, please refer docs/develop/kernel/device_manager_introduction.html