I'm in the family bunker deep in an Idaho hillside. Y2K is officially over but I'm still not sure if it's safe to come out yet. The only communication line I have is a fiber optic link to Be's world headquarters in Menlo Park. Because of some poor planning on my part, though, there's no gas for the electric generator. Instead, I have to use a candle (signal) and deck of playing cards (modulator) to send this article. Fiber optic cable was the right choice for the bunker because of its high speed and bandwidth capabilities. Coincidentally, BeOS is also known for high speed and bandwith capabilities. In particular, the new multiaudio driver API takes full advantage of BeOS's superior speed and bandwidth.
Not all of you may be familiar with the multiaudio API, as it's intended
only for driver writers. User level add-ons and applications will talk to
the multiaudio node, or "multinode" as it's called. The advantage of the
multiaudio API over other APIs (such as legacy and game) is that it's
ideally suited for professional and semiprofessional audio cards. These
cards generally have more inputs and outputs, higher sampling rates
(typically 48Khz or 96Khz), and greater bit depths (up to 32 bits per
sample) than typical game sound cards. They may also have support for
other audio formats such as
S/PDIF
and ADAT.
The "complete" documentation
for the driver API is included in three files:
multi_audio.h
,
multi_audio.gb
, and multi_audio.txt
.
To get these files, write to
trinity@be.com. Without rehashing all the information in the files, I'd
like to hit the highlights of the new API.
The API is different from the other audio APIs in that read/write calls
are combined into a single ioctl, B_MULTI_BUFFER_EXCHANGE
. This call is
synchronous—it returns after playback data has been transferred (or
queued) and capture data (if any) is present in the capture buffer. A
ping-pong type of buffer management normally used—one buffer is being
played (or filled with capture data) while a second buffer is being
prepared. In some cases, a ring buffer may be required.
Another area of interest is the mixer ioctls. Extensible mixer
implementation is tricky, and this API is no exception. However, the
burden is now off the driver writer and on the node and add-on writers
instead. That's good news for us driver writers. (There should be example
code in the future to make nodes and add-ons easier too.) The ioctls
B_MULTI_LIST_MIX_CHANNELS
, B_MULTI_LIST_MIX_CONTROLS
,
and B_MULTI_LIST_MIX_CONNECTIONS
return mixer
components associated with the device. This
allows the mixer GUI and implementation to be handled by the user mode
components.
One item that's slightly different from the documentation is the ganging
together of controls. The multi mix control structure has a member named
master
. It is intended that this value be 0 if the control is not
slaved. If it is ganged, then the ID of the master control goes here. In
order to facilitate the implementation of parameter webs, I suggest that
the master control use its own control ID here and not 0. This reduces to
using 0 if the control is not ganged or slaved, and the master control ID
if it is. The documentation will be updated to reflect these changes.
Some things are tricky. For example, say your card supports a 32Khz
sampling rate, but only if you're sample-locked to an incoming 32Khz
S/PDIF signal. You should report the actual sample rate (32 Khz) when
requested (MULTI_GET_GLOBAL_FORMAT
) but don't show
32 Khz in the B_MULTI_GET_DESCRIPTION
ioctl. This
will prevent users from manually trying to set the rate to 32 Khz.
Some people have reported confusion over the terms "bus" and "channel" as used in the multiaudio API. Busses are the connectors to the world outside the computer, while channels carry audio data inside the computer. Busses may be digital (e.g., ADAT) or analog. Channels are what's "processed" by the computer. In a typical capture scenario, an analog signal is converted to digital PCM data by an ADC. The digital PCM data is associated with the input channel, while the analog signal is part of the input bus.
The purpose of the multiaudio API is create an environment in which high-performance audio cards can excel. So the question "How fast is it?" invariably arises. The answer is "It depends." How fast is your CPU? How fast is your hard disk? How fast is your memory bus? Do you want multitrack hard disk recording or are you more interested in "real time" (<10 ms) effects processing? In audio, the primary concern is latency. How long does it take to get an analog signal into the computer, process it, and then send it back out? What if you also wish to write processed data to disk? There are many items which contribute to the latency of the entire system, including the OS, the API, A/D D/A converter latency, buffer size, etc... (If the OS is not designed properly, you may be able to get two channels of audio in and out fairly quickly, but you may not be able to access the disk simultaneously.) So how fast is the new API? The only way to know is to test your machine and card.
Everyone has a preferred method for testing audio latency and I'm no exception. I recommend the following: input a sine wave from a signal generator to the sound card, run a loopback program that doesn't bypass the converters, then measure the phase difference with an oscilloscope. Make sure that the period of the input signal is greater than the buffer playback time. A very simple loopback program is available at <ftp://ftp.be.com/pub/samples /drivers/multiaudio_test.zip
You can find the first part of this article here: Developers' Workshop: BeOS Driver FAQs (Part 1)
BeOS Driver FAQs Continued
1. How do I write a driver for: | |
Q: | a sound card? |
A: | You need to write a kernel driver that implements one of Be's audio
device ioctl opcode protocols. The protocol used up through R4.5.x is
deprecated, but the preferred multichannel protocol (defined in
|
Q: | a SCSI card? |
A: | Specific SCSI controller chipsets are supported via modules that are
loaded by the SCSI bus manager module. Consult the Buslogic or Symbios
bus module sample code at <ftp://ftp.be.com/pub/samples/add-ons/ (or
in |
Q: | a graphics card? |
A: | Graphics card support in R4 and beyond HAS two software components: a
kernel driver as described in this FAQ,
and a user space add-on to the
App Server called an accelerant. Detailed discussion of the BeOS graphics
driver model in general and accelerant development in particular is
available in the document R4 Graphics Driver Docs, found in
|
Q: | a USB device? |
A: | Write a kernel driver that uses the services of the USB manager module
declared in |
Q: | a printer? |
A: | You're in luck! Printer drivers live entirely within the velvety-soft cuddliness of user space. They are add-ons to the Print server that implement several hook functions. However, this API is not yet set in stone. For more information on writing printer drivers, contact mathias@be.com. |
Q: | a network interface card? |
A: | Network interface card support consists of a kernel driver (as described
in this FAQ) and a user space add-on to the Net Server. Consult the
EtherPCI sample code <ftp://ftp.be.com/pub/samples/drivers/EtherPCI.zip>,
or |
2. File Systems | |
Q: | What is a file system? |
A: | A good general definition of a file system is found in Dominic's book "Practical File System Design With the Be File System," on pg. 7: A file system is a way to organize, store, retrieve, and manage information on a permanent storage medium such as a disk. In BeOS parlance, a file system is a kernel add-on that can translate between the kernel's abstract notion of a file system and the implementation details of a particular concrete file system (such as BFS or ISO 9660). For more information on writing a file system for BeOS, see George Hoffman's article, "Be Engineering Insights: Chelsea 'n' Me" ), and Alfred's article, "Be Engineering Insights: Network File Systems for BeOS—The Art of Being Paranoid". |
Q: | Where do file systems live? |
A: | File systems that ship with BeOS live in
|
Q: | Where can I find file system sample code? |
A: | In optional/sample-code/add-ons/ if installed, or at <ftp://ftp.be.com/pub/samples/add-ons/>. |
3. Life in Kernel Space | |
Q: | What is kernel space vs. user space? |
A: | Kernel space refers to the runtime environment of the kernel, particularly the fact that the CPU is in supervisor mode. Code running in supervisor mode can do things that can't be done from user mode, such as manage interrupts or access any virtual address. Since drivers, modules, and filesystems are add-ons loaded by the kernel, they also enjoy the privileges and suffer the perils of running in kernel space. Similarly, user space refers to the runtime environment of user programs, in which the CPU is not running in supervisor mode but rather in user mode. |
Q: | What is a kernel add-on? |
A: | A kernel add-on is compiled code (also known as an image) that the kernel can load and unload as it is running. Indeed, any BeOS application can be designed to use add-ons to extend its functionality; examples of applications that do this include the Tracker and the ScreenSaver. Structurally, an add-on is no different from a shared library, but
instead of being dynamically linked to the host by the loader before the
host's For more information on creating and using add-ons, see "Image Concepts" TheKernelKit_ImagesOverview.html in the Be Book. |
Q: | What musn't I do in a kernel add-on? |
A: | You must not leave interrupts disabled for longer than 50 microseconds. If you're inside a spinlock-protected critical section, you must never block. Prevent these tragedies by following the rules set forth in the next answer. |
Q: | What can I do in a kernel add-on? |
A: | If interrupts are disabled and you are inside a spinlock- protected critical section, you may:
and that's it. To quote Cyril Meurillon, EVERYTHING ELSE IS FORBIDDEN. If interrupts are disabled and you are NOT inside a spinlock, you may do the following in addition to the above list:
For further discussion of the rules of kernel space, consult Cyril's articles on the subject: "Be Engineering Insights: Attention Driver Writers!" and "Be Engineering Insights: The Kernel Programming Model Revisited" |
Q: | Got any general tips for writing kernel space code? |
A: | You betcha. Dominic discusses some common constructs found in kernel space code in his article, "Be Engineering Insights: Device Driver Idioms". And Trey Boudreau's "Be Engineering Insights: Kernel Driver Tips and Traps" is aptly named, though it predates R4, so read carefully. |
Q: | How do I debug drivers (and other kernel space code)? |
A: | To debug kernel space code on BeOS, you have to leave the cushy world of
source level debugging behind. Your main debugging tools will be
There are two Newsletter on this subject. "Developers' Workshop: Welcome to the Cow...Debugging Device Drivers", by Victor Tsou,
discusses your best friends |
Q: | How do I get additional debugging information, particularly for device driver crashes? |
A: | You can add your own kernel debugger command to make it easier to view your driver-internal structures. Victor's article "Be Engineering Insights: Windows 95 Experience on BeOS—Or How to Hack on BeOS" has more on this |
Q: | How do I use floating-point in kernel space? |
A: | Please don't. Read Steven Olson's "Developers' Workshop: BeOS Programming Basics, Part 2" |
Q: | How do I use functors and vectors and deques (oh my!) in kernel space? |
A: | You should not use C++ in kernel space. There is not runtime support in the kernel for it, and there are a number of subtle issues involved with doing it. |
Wouldn't it be cool if there was, like, a web page with links to all sorts of Be developer resources grouped by topic? Yes, it is cool (how do you think I researched this FAQ?), and it's called the Be Developer Library <http://www.be.com/developers/developer_library/index.html>. It has links to Be Book documentation, Be Newsletter articles, sample code, and much more. You'll find resources pertaining to drivers and modules in the Drivers section <http://www.be.com/developers/developer_library/drivers.html>, and file systems are covered in the Add-ons section <http://www.be.com/developers/developer_library/add-ons.html>.
So that's the FAQs as they currently exist. But they don't have to end this way. Could they be better organized? Is there another question you'd like to see answered? I intend the FAQs to evolve as you need them to. Send questions, comments, corrections, etc. to tt@be.com. Really. Also, about that Developer Library thing I mentioned at the end there: I realize some of its content has grown a bit stale. The PR2 headers, for example. I hope to address that as soon as possible, although it might take awhile because the machinery that drives the Library is a rusty and should be updated. Stay tuned.