CAM(4)

πŸ’– CAM(4) πŸ’– β€” the Common Access Method Storage subsystem

okay bestie, sit DOWN, because we're about to talk about the storage backbone of your whole system and she is lowkey iconic. This is the CAM(4) manual page, and yes, we're doing this together. Grab a strawberry πŸ“, hydrate, and let's go.


✨ SYNOPSIS ✨

device scbus
device ada
device cd
device ch
device da
device pass
device pt
device sa
options CAMDEBUG
options CAM_DEBUG_BUS=-1
options CAM_DEBUG_TARGET=-1
options CAM_DEBUG_LUN=-1
options CAM_DEBUG_COMPILE=CAM_DEBUG_INFO|CAM_DEBUG_CDB|CAM_DEBUG_PROBE
options CAM_DEBUG_FLAGS=CAM_DEBUG_INFO|CAM_DEBUG_CDB
options CAM_MAX_HIGHPOWER=4
options SCSI_NO_SENSE_STRINGS
options SCSI_NO_OP_STRINGS
options SCSI_DELAY=8000

look at her. all those little device lines. it's giving kernel config realness πŸ’…


πŸ¦‹ DESCRIPTION πŸ¦‹

The CAM subsystem is the uniform and modular girl of the kernel β€” she gives you one clean way to implement drivers that control all your SCSI, ATA, NMVe, and MMC / SD devices, and she lets you use all sorts of different SCSI, ATA, NVMe, and MMC / SD host adapters through host adapter drivers. Modular! Flexible! She contains multitudes πŸ’–

When the system probes buses, it attaches any devices it finds to the appropriate drivers. And the pass(4) driver β€” if it's configured in the kernel β€” will attach to all devices. Yes, all of them. She's nosy and we love her for it πŸ™ˆ


πŸŽ€ KERNEL CONFIGURATION πŸŽ€

So there are a bunch of generic kernel configuration options for CAM, and honestly each one has main character energy in her own way:

  • CAMDEBUG β€” this one compiles in all the CAM debugging printf code. But heads up bestie: including it by itself will not actually cause any debugging info to be printed out. It's just the vibes. The potential. See below for the details, fr fr.
  • CAM_MAX_HIGHPOWER=4 β€” sets the maximum allowable number of concurrent "high power" commands. A "high power" command is one that takes more electrical power than most to complete β€” think the SCSI START UNIT command, because spinning up a disk takes significantly more electrical power than normal operation. This option lets you say how many concurrent high power commands may be outstanding without overloading the power supply on your computer. No cap, this is a real one πŸ”₯
  • SCSI_NO_SENSE_STRINGS β€” eliminates the text descriptions of each SCSI Additional Sense Code and Additional Sense Code Qualifier pair. It's a fairly large text database, so dropping it shrinks the kernel somewhat. Primarily necessary for boot floppies and other low disk space or low memory space environments. But β€” in most cases this should be enabled, because it speeds up the interpretation of SCSI error messages. And honestly? do not let the "kernel bloat" zealots get to you β€” leave the sense descriptions in your kernel! πŸ’€
  • SCSI_NO_OP_STRINGS β€” disables text descriptions of each SCSI opcode. Like the sense string option above, it's primarily useful for environments like a boot floppy where kernel size is critical. Enabling this option for normal use is not recommended, since it slows debugging of SCSI problems. Don't do it unless you have to πŸ₯Ί
  • SCSI_DELAY=8000 β€” this is the SCSI "bus settle delay." In CAM it's specified in milliseconds, not seconds like the old SCSI layer used to do (we've evolved ✨). When the kernel boots, it sends a bus reset to each SCSI bus to tell each device to reset itself to a default set of transfer negotiations and other settings. Most SCSI devices need some time to recover from that bus reset. Newer disks may need as little as 100ms, while old, slow devices may need much longer. If SCSI_DELAY is not specified, it defaults to 2 seconds. The minimum allowable value is "100", or 100ms. One special case: if SCSI_DELAY is set to 0, that's taken to mean the "lowest possible value" β€” and in that case, SCSI_DELAY gets reset to 100ms.

All devices and buses support dynamic allocation, so you don't need to configure an upper number of devices and controllers β€” device da will suffice for any number of disk drivers. Slay, scalable queen πŸ‘‘

The devices are either wired so they appear as a particular device unit, or counted so they appear as the next available unused unit.

Units are wired down by setting kernel environment hints. This is usually done either interactively from the loader(8), or automatically via the /boot/device.hints file. The basic syntax is:

hint.device.unit.property="value"

Individual CAM bus numbers can be wired down to specific controllers with a config line like this:

hint.scbus.0.at="ahd1"

That assigns CAM bus number 0 to the ahd1 driver instance. For controllers supporting more than one bus, a particular bus can be assigned like so:

hint.scbus.0.at="ahc1"
hint.scbus.0.bus="1"

That assigns CAM bus 0 to the bus 1 instance on ahc1. And peripheral drivers can be wired to a specific bus, target, and lun like this:

hint.da.0.at="scbus0"
hint.da.0.target="0"
hint.da.0.unit="0"

That assigns da0 to target 0, unit (lun) 0 of scbus 0. Omitting the target or unit hints will instruct CAM to treat them as wildcards and use the first respective counted instances. And you can combine all these examples together to allow a peripheral device to be wired to any particular controller, bus, target, and/or unit instance. Mix and match, babe πŸ’…

This also works with nvme(4) drives as well:

hint.nvme.4.at="pci7:0:0"
hint.scbus.10.at="nvme4"
hint.nda.10.at="scbus10"
hint.nda.10.target="1"
hint.nda.10.unit="12"
hint.nda.11.at="scbus10"
hint.nda.11.target="1"
hint.nda.11.unit="2"

That assigns the NVMe card living at PCI bus 7 to scbus 10 (in PCIe, slot and function are rarely used and usually 0). The target for nda(4) devices is always 1. The unit is the namespace identifier from the drive. So namespace id 1 is exported as nda10 and namespace id 2 is exported as nda11. Cute, right? 🌸

When you have a mixture of wired down and counted devices, the counting begins with the first non-wired down unit for a particular type. That is, if you have a disk wired down as device da1, then the first non-wired disk shall come on line as da2. Math! She does it ✨


🌈 ADAPTERS 🌈

The system allows common device drivers to work through many different types of adapters. The adapters take requests from the upper layers and do all IO between the SCSI, ATA, NVMe, or MMC / SD bus and the system. The maximum size of a transfer is governed by the adapter β€” most adapters can transfer 64KB in a single operation, though many can transfer larger amounts. Overachievers 🫢


πŸ’œ TARGET MODE πŸ’œ

Some adapters support target mode, in which the system is capable of operating as a device, responding to operations initiated by another system. Target mode is supported for some adapters, but it is not yet complete for this version of the CAM SCSI subsystem. So like… she's on her way, but she's not there yet. We're patient πŸ’–


🧚 FILES 🧚

see other CAM device entries. (short and mysterious. she said "go read my sisters' pages." valid.)


⭐ DIAGNOSTICS ⭐

An XPT_DEBUG CCB can be used to enable various amounts of tracing information on any specific bus/device, from the list of options compiled into the kernel. There are currently seven debugging flags that may be compiled in and used:

  • CAM_DEBUG_INFO β€” enables general informational printfs for the device or devices in question.
  • CAM_DEBUG_TRACE β€” enables function-level command flow tracing, i.e., kernel printfs will happen at the entrance and exit of various functions.
  • CAM_DEBUG_SUBTRACE β€” enables debugging output internal to various functions.
  • CAM_DEBUG_CDB β€” causes the kernel to print out all ATA and SCSI commands sent to a particular device or devices.
  • CAM_DEBUG_XPT β€” enables command scheduler tracing.
  • CAM_DEBUG_PERIPH β€” enables peripheral drivers messages.
  • CAM_DEBUG_PROBE β€” enables devices probe process tracing.
warning bestie!! Some of these flags, most notably CAM_DEBUG_TRACE and CAM_DEBUG_SUBTRACE, will produce kernel printfs in EXTREME numbers. Like, the console will simply not shut up. You have been warned 😭

Users can enable debugging from their kernel config file by using the following kernel config options:

  • CAMDEBUG β€” builds into the kernel all possible CAM debugging.
  • CAM_DEBUG_COMPILE β€” lets you specify support for which debugging flags described above should be built into the kernel. Flags may be ORed together if the user wishes to see printfs for multiple debugging levels.
  • CAM_DEBUG_FLAGS β€” lets you set the various debugging flags from a kernel config file.
  • CAM_DEBUG_BUS β€” specify a bus to debug. To debug all buses, set this to -1.
  • CAM_DEBUG_TARGET β€” specify a target to debug. To debug all targets, set this to -1.
  • CAM_DEBUG_LUN β€” specify a lun to debug. To debug all luns, set this to -1.

Users may also enable debugging on the fly by using the camcontrol(8) utility, if they wanted those options built into the kernel. See camcontrol(8) for details πŸ‘‘


πŸŽ€ SEE ALSO πŸŽ€

ada(4), aha(4), ahc(4), ahci(4), ahd(4), ata(4), bt(4), cd(4), ch(4), da(4), nda(4), nvme(4), pass(4), pt(4), sa(4), xpt(4), camcontrol(8)

the whole friend group showed up to the function πŸ’…


🌸 HISTORY 🌸

The CAM SCSI subsystem first appeared in FreeBSD 3.0. The CAM ATA support was added in FreeBSD 8.0. a legacy. an icon. we stan a consistent queen.


πŸ’– AUTHORS πŸ’–

The CAM SCSI subsystem was written by Justin Gibbs and Kenneth Merry. The CAM ATA support was added by Alexander Motin <mav@FreeBSD.org>. The CAM NVMe support was added by Warner Losh <imp@FreeBSD.org>.

thank you for your service, legends 🫢✨


and that's the whole page, bestie!! this one's from the Debian edition, dated December 20, 2017, and it lives in section 4 as CAM(4). now go forth and configure some storage πŸ’–πŸ¦‹πŸŒΈπŸ’…πŸ‘‘

πŸ“¦ where this page comes from