SDHCI MMC Driver================This driver project is a part of GSoCβ18 and is aimed at providingsupport for PCI devices with class 8 and subclass 5 over x86architecture. This document will make you familiar with the `codeproduced during GSoC <https://review.haiku-os.org/#/c/haiku/+/318/>`__,loading and testing the driver(including hardware emulation), insightinto the code and future tasks.For detailed explanations about the project, you can refer the `weeklyreports <https://www.haiku-os.org/blog/krish_iyer>`__ and comment issuesif any. For this project we have referred `SD Host Controller SpecVersion1.00 <https://www.sdcard.org/downloads/pls/pdf/index.php?p=PartA2_SD_Host_Controller_Simplified_Specification_Ver1.00.jpg&f=PartA2_SD_Host_Controller_Simplified_Specification_Ver1.00.pdf&e=EN_A2100>`__and `Physical Layer Spec Version1.10 <https://www.sdcard.org/downloads/pls/pdf/index.php?p=Part1_Physical_Layer_Simplified_Specification_Ver1.10.jpg&f=Part1_Physical_Layer_Simplified_Specification_Ver1.10.pdf&e=EN_P1110>`__.Loading and testing the driver------------------------------Emulating the hardware~~~~~~~~~~~~~~~~~~~~~~We will emulate a SDHC device using qemu as all system may not have thedevice. These days systems provide transfer to SD/ MMC card over USB.The document will not instruct you on how to build haiku but you canrefer the link to `compile and build the haikuimages <https://www.haiku-os.org/guides/building/>`__ or the `week #1and#2 <https://www.haiku-os.org/blog/krish_iyer/2018-05-06_gsoc_2018_sdhci_mmc_driver_week_1_and_2/>`__project report will also work.After building the image, we will emulate the hardware and host haiku ontop of that.Emulation^^^^^^^^^For emulating a sdhci-pci device::qemu-img create sd-card.img 32Mqemu-system-x86_64 -drive index=0,file=haiku-nightly-anyboot.iso,format=raw \-device sdhci-pci -device sd-card,drive=mydrive \-drive if=sd,index=1,file=sd-card.img,format=raw,id=mydrive-m 512M -enable-kvm -usbdevice tablet -machine q35This does the following: - Create an SD card image of 32MB - Run qemuwith a bootable image in an IDE disk, and an SDHCI bus with an SD cardin it - Have enough memory to boot Haiku, use KVM mode for speed, and atablet for ease of use - Use the Q35 chipset so the mouse and SDHCIcontrollers donβt share an interrupt (not strictly required, but itavoids calls to the SDHCI interrupt handler on every mouse move).Tracing of SD operations can also be added to see how qemu isinterpreting our commands:::-trace sdhci* -trace sdbus* -trace sdcard*Testing and loading the driver~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~The code is merged and part of the default Haiku build.Insight into the code and future tasks--------------------------------------Bus, bus manager, and drivers~~~~~~~~~~~~~~~~~~~~~~~~~~~~~The MMC stack is a device manager based βnew styleβ driver. Thisrequires splitting the driver in different parts but allow easy reuse ofeach part (for example to support eMMC or SDIO with a large part of thecode in common with plain SD/MMC).MMC Bus drivers (src/add-ons/kernel/busses/mmc)^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^The bus driver provides the low level aspects: interrupts management,DMA transfer, accessing the hardware registers. It acts as a platformabstraction layer so that the bus manager and disk driver can be writtenindependently of the underlying hardare.Currently there is a single implementation for SDHCI (MMC bus over PCI).Later on, other drivers will be added for other ways to access the MMCbus (for example on ARM devices where it does not live on a PCI bus, andmay have a different register layout).For this reason, the bus drivers should only do the most low-levelthings, trying to keep as much code as possible in the upper layers.One slightly confusing thing about SDHCI is that it allows a single PCIdevice to implement multiple separate MMC busses (each of which couldhave multiple devices attached). For this reason there is an SDHCIβdeviceβ that attaches to the PCI device node for the controller, andthen publishes multiple device nodes for each available bus. The nodesthen work independently of each other.The Bus Manager (src/add-ons/kernel/bus_managers/mmc)^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^The bus manager is responsible for enumerating devices on the bus,assigning them addresses, and keeping track of which card is active atany given time.Essentially it has everything that requires collaboration betweenmultiple MMC devices, as well as things that are not specific to adevice type (common to SDIO, SD and MMC cards, for example)Disk Driver (src/add-ons/kernel/drivers/disk/mmc)^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^This is a mass storage driver for MMC, SD and SDHC cards. Currently onlySD and SDHC are tested, MMC and eMMC will have to be added (they aresimilar but there are some differences).Wiring the driver in the device manager (src/system/kernel/device_manager/device_manager.cpp)^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^(note: possibly not accurate documentation, I did not check how thingsin the device manager are actually implemented, but this is myunderstanding of it).The device manager attempts to implement lazy, on-demand scanning of thedevices. The idea is to speed up booting by not spending a lot of timescanning everything first, and only scanning small parts of the devicetree as they are needed.The trigger is accesses to the devfs. For example, when an applicationopens /dev/disk, the device manager will start looking for disks so itcan populate it. This means the device manager needs to know whichbranches of the device tree to explore. Currently this knowledge ishardcoded into the device tree sourcecode, and thereβs a TODO item aboutmoving that knowledge to drivers instead. But itβs tricky, since thewhole point is to avoid loading all the drivers.Anyway, currently, the device manager is hardcoded to look for massstorage devices under SDHCI busses, both standard ones and somenon-standard ones (for example, Ricoh provides SDHCI implenentationsthat are conform to the spec, except they donβt have the right devicetype in the PCI registers).Insight into the code~~~~~~~~~~~~~~~~~~~~~MMC Bus management overview^^^^^^^^^^^^^^^^^^^^^^^^^^^The device tree for MMC support looks like this:- PCI bus manager- (other PCI devices)- SDHCI controller- SDHCI bus- MMC bus manager- MMC device- mmc_disk device- MMC device- (other SDIO driver)- MMC bus manager (second MMC bus)- MMC device- mmc_disk deviceAt the first level, the PCI bus manager publishes a device node for eachdevice found. One of them is our SDHCI controller, identified either bythe PCI device class and subclass, or for not completely SDHCIcompatible device, by the device and vendor IDs.The SDHCI bus driver attaches to this device and publishes his own node.It then scans the device and publishes an MMC bus node for each slot(there may be multiple SD slots attached to a single PCI controller).The MMC bus manager then attach to each of these slots, and send theappropriate commands for enumerating the SD cards (there may be multiplecards in a βslotβ), and publishes a device node for each of them.Finally, the mmc_disk driver can bind itself to one of these devicenodes, and publish the corresponding disk node, which is also be madeavailable in /dev/disk/mmc.Currently the mmc bus does not publish anything in the devfs, but thiscould be added if sending raw SD/MMC commands to SD cards from userlandis considered desirable.SDHCI driver^^^^^^^^^^^^The SDHCI driver is the lowest level of the MMC stack. It providesabstraction of the SDHCI device. Later on, different way to access an SDbus may be added, for example for ARM devices which decided to use adifferent register interface.The entry point is as usual **supports_device()**. This method is calledonly for devices which may be SDHCI controllers, thanks to filteringdone in the device manager to probe only the relevant devices. Theprobing is done on-demand, currently when the system is enumerating/dev/disk in the devfs. Later on, when we have SDIO support, probingwill also be triggered in other cases.The function identifies the device by checking the class and subclass,as well as a limited set of hardcoded PCI device and vendor IDs fordevices that do not use the assigned subclass.Once a compatible device is found, **register_child_devices()** is usedto publish device nodes for each slot to be controlled by the mmc busmanager. The registers for each device are mapped into virtual memory,using the information from the PCI bar registers. **struct registers**is defined so that it matches the register layout, and provide a littleabstraction to raw register access.An SdhciBus object is created to manage each of these busses at theSDHCI level. It will be responsible for executing SD commands on thatbus, and dealing with the resulting interrupts.The Bus Manager^^^^^^^^^^^^^^^The MMC bus manager manages the MMC bus (duh). Its tasks are:- enumerating SD cards on the bus- assigning RCAs to the cards for identifying them when sendingcommands- setting the bus clock speed according to what the cards can handle- remember which SD card is currently active (CMD7)- manage cards state- publish device nodes for each cardDisk Driver^^^^^^^^^^^The disk driver is attached to devices implementing SDSC or SDHC/SDXCcommands. There will be other drivers for non-storage (SDIO) cards.To help with this, the MMC bus manager provides the device with theinformation it gathered while initializing the device. According to thecommands recognized by the card during the initialization sequence, itβspossible to know if itβs SDSC, SDHC/SDXC, or something else (SDIO,legacy MMC, etc).The disk driver publishes devfs entries in /dev/disk/mmc and implementsthe usual interface for disk devices. From this point on, the device canbe used just like any other mass storage device.Getting everything loaded^^^^^^^^^^^^^^^^^^^^^^^^^The device manager is not completely implemented yet. As a result, somedecisions about which drivers to load are hardcoded indevice_manager.cpp.It has been adjusted to handover SDHCI devices to the MMC bus. Whenevera βdiskβ device is requested, the MMC busses are searched, which resultsin loading the SDHCI driver and probing for SD cards. When we getsupport for other types of SDIO devices, we will need to adjust thedevice manager to probe the SDHCI bus when these type of devices arerequested, too.Tasks to be completed~~~~~~~~~~~~~~~~~~~~~The SDHCI driver is able to send and receive commands. However it doesnot handle card insertion and removal interrupts yet, so the card mustbe already inserted when the driver is loaded.The mmc_disk driver is complete and working, but was not tested for MMCand eMMC devices. Some changes may be needed.There is also work to be done for better performance: making sure weswitch to the high-speed clock when an SD card supports it, and use the4-bit data transfer mode instead of the default 1-bit if possible.Drivers for SDIO devices should also be added. The mmc_bus and SDHCIdrivers have been tested only with one card on the bus at a time (forlack of hardware allowing more complex setups).If you find it difficult to understand the driver development and itβsfunctioning and role, please refer*docs/develop/kernel/device_manager_introduction.html*