CAM, FreeBSD, mmccam, SDIO, Software

Implementing a MMC/SD/SDIO stack using CAM framework(Part 2)

Hi, In the next part lets look at other files which makes up the SDIO stack within mmccam framework. Please have  a look at previous part for more info:


sdio_fill_mmcio_rw_direct is basically a wrapper for CMD_52 that’s needed to read/write directly into mmc register R5. Remember that register R5 in mmc, is used for RCA(Relative card address) management. It’s right time now to talk about different command types of SD/MMC/SDIO:

  • broadcast commands (bc), no response
  • broadcast commands with response (bcr) (Note: No open drain on SD card)
  • addressed (point-to-point) commands (ac), no data transfer on DAT lines
  • addressed (point-to-point) data transfer commands (adtc), data transfer on DAT lines

CMD_53 is of ac type. where address of 8bit opcode  is provided by adr,

Note:- For those who don’t understand open drain mode,

Output pins can be configured in 3 ways,

  • open drain – a transistor connects to low and nothing else
  • open drain, with pull-up – a transistor connects to low, and a resistor connects to high
  • push-pull – a transistor connects to high, and a transistor connects to low (only one is operated at a time)

Open drain is power efficient and Push pull mode is very fast!! so, SD card initialization id done in open drain mode and then push-pull mode takes over during cmd/data transfer.

Input Pins can be connected in 4 ways:

  • pull-up – a resistor connected to high
  • pull-down – a resistor connected to low
  • pull-up and pull-down – both a resistor connected to high and a resistor connected to low (only useful in rare cases).
  • Schmitt triggered input mode

Now, to understand the above function, one should know about all the macros. Below, is the file to refer to in that case:

Now, look at SD_IO_RW_DIRECT its a class 9 command type for directly read and write in SDIO card case.  Then, there is SD_IO_RW_FUNC ( #define SD_IO_RW_FUNC(x) (((x) & 0x7) << 28) ) it takes a uint8 type value extracts it’s 7th bit and shift that bit to 28 position. then, SD_IO_RW_ADR ( #define SD_IO_RW_ADR(x) (((x) & 0x1FFFF) << 9) ) takes a 32 bit address takes it’s first 16 its shift it by 9 bit i.e [25:9] and sends it to SD card to take set these 16 bits as it’s RCA. SD_IO_RW_WR sets 1 at 31 position which indicates write operation. SD_IO_RW_RAW sets 1 at 27 position indicating raw data to be exchanged. SD_IO_RW_DAT takes 8 bit of data and put it in beginning of the packet . #define MMC_RSP_R5 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)  MMC_RSP_R5 sets the CRC and opcode of the command. MMC_CMD_AC shows that it’s an address only command no data will be transferred.

sdio_parse_mmcio_rw_direct function is pretty straight forward, it’s used to parse the response header indicating any CRC error or any other error reported by mmc card.


First two structure and character array are just a list of different functions that can be performed on mmc and SDIO card as of now.

Then we have mmc_dev_async function which as explained in previous post, is used to handle any asynchronous interrupt from CAM bus, in case of hot plug/hot unplug. It detects the device, and registers it accordingly on CAM bus.

Notice, here the keyword ‘LUN’ it refers to Logical Unit Number a storage device has. So, CAM_TARGET_WILDCARD and CAM_LUN_WILDCARD makes sure that device is a valid storage/IO device.

mmc_scan_lun basically check the Logical Unit Numbers of the device. CAM_LUN_WILDCARD only checks whether LUN == 0 or not. Each device has LUN = 0 even if it has multiple logical units , it’s a bit confusing, but it looks like device registers other LUNs only after one of it’s LUN gets attached. Source: here

mmc_action() is pretty straightforward. It calls xpt_action() after handling several standard cases. It also calls mmc_scan_lun if needed.

mmc_announce_periph is called upon confirmation of connection to any new device. notice that it creates a CCB and then initializes it with xpt_action.

Then, mmcprobe_register registers a new device on the CAM bus. only after registration, it can be associated with a CCB.

Next, important function is mmcprobe_start

Notice the switch case statement here, which converts a I/O command to it’s SCSI equivalent. That is with just the name of the command it associates all the register value corresponding to it.

Few other supporting files are left. I’ll update this post with there details as well



Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.