IEEE 1394 and Linux


The FireWire Serial Bus and its Implementation
















Chad N. Tindel

Brian D. Pietsch

CSC550, Spring 2000

Dr. Keller









In the mid 1980s, Apple Computer began development of a new serial bus architecture called FireWire.  It was designed to address several issues related to current and upcoming technology:


  1. Parallel buses are expensive.  Apple chose to instead create a serial bus that has massive bandwidth capabilities.
  2. There was expected to be an increased market in consumer electronics, and Apple wanted a standardized interconnection mechanism for them.
  3. They wanted the devices on the bus to be self-configurable (Plug and Play) immediately upon connection to the bus.
  4. Operation of the entire bus should be independent of the host system, eliminating the host processor and memory bottleneck.
  5. They also wanted support for reserved bus bandwidth (termed “isochronous” by the standard)


FireWire devices are generally multimedia based; examples are Digital Cameras and Camcorders, Digital VCRs, and Pro-audio equipment like DAT stations and other multi-track recorders.  However, they can also be general PC peripherals like Hard Disk Drives, CD-ROM/DVD Drives, and Laser Printers.


Apple’s work caught the eyes of other vendors and an IEEE committee was formed to create a formal standard.  This paper explains the concepts created by the resulting IEEE 1394-1995 specification and also explains the data structures and algorithms used by the FireWire subsystem in the 2.3.99-pre6 Linux kernel.




The 1394 specification creates a light amount of terminology that must be discussed before jumping into the technical details.  A module is one physical device attached to the bus, containing at least one node.  Generally physical devices are multimedia based; examples are digital cameras, digital camcorders, digital VCRs, and pro-audio equipment like DAT stations and other multi-track recorders.  However, they can also be general PC peripherals like hard disk drives, CD-ROM/DVD drives, and laser printers.  A node is a logical entity within a module.  Devices on the bus are addressed at the node level.  A unit is a functional subcomponent of a node that can identify processing, memory, or I/O functionality.  Units of a node generally operate independently (they have their own drivers) but may share registers with each other.  Figure 1 shows the internal architecture of a module.  A port is a point of I/O within a node (where the node plugs into the bus).  As shown in the Figure 2, nodes can be single or multi-ported.  Packets are transferred in a peer-to-peer fashion, so when a multiport node receives a packet, it is retransmitted over its other ports.  Each time a device is plugged into or unplugged from the bus, the entire bus topology is reconfigured.  Each bus can be viewed as a tree of devices with one and only one root.  The device at the root of the tree is the root node.


Figure 1.  The Module Architecture[1]



Figure 2.  A Generic Set Of Interconnected Devices[2]



The 1394 Virtual Address Space






Figure 3.  The 1394 64-bit Virtual Address[3]


The FireWire bus uses a 64-bit fixed addressing model.  The address space is divided into equal space for 64k nodes, and these nodes are divided into 1024 buses with 64 nodes per bus.  Bits [0-9] define the target bus, bits [10-15] identify the target node on the selected bus, and bits [16-63] define 256 terabytes of memory address space for each node.


For practical purposes, there can only be 63 nodes on each bus, because the last node is used as a broadcast address, which addresses the entire bus.


Bus Transfers


A Transfer describes how data is moved around between nodes.  IEEE 1394 defines two different transfer modes:


  1. Asynchronous Transfer Mode allows for periodic data transfer with guaranteed delivery.
  2. In Isochronous Transfer Mode best-effort delivery is used to deliver data across the bus at a constant rate


The transfer type is dependent on the nature of the data being moved around.  For example, if you wanted to stream video from a digital camera to the Internet, you would use an isochronous transfer because the necessary bandwidth is known a priori and the data needs to be sent at constant intervals.  However, if you were simply copying the data from a CD-ROM to a hard drive you would use the asynchronous transfer mode because you don’t want to lose any information during the copy.  These two transfer types have direct analogs in the socket-programming world; isochronous transfers are analogous to communication over a datagram socket and asynchronous transfers are analogous to communication over a stream socket.


Bus Arbitration


When a node wishes to transmit a packet on the bus it needs to request permission to do so.  The procedure for determining which node gets control of the bus is known as arbitration.  There are two different kinds of arbitration depending on what kinds of nodes are on the bus: arbitration with only asynchronous devices and arbitration with isochronous devices.  If isochronous devices are present, arbitration is handled the same whether or not any asynchronous devices are present.


Asynchronous-only arbitration is based on fair scheduling with priorities.  After a 20μs gap (bus idle time) a new “arbitration round” starts.  If a node wishes to transmit, it sends an arbitration request, which propagates up to the root node.  If multiple nodes request arbitration at the same time, the node closest to the root node wins arbitration.  If the nodes requesting arbitration are the same distance from the root node, then the node connecting to the lowest numbered root port wins arbitration.  Each node can speak at most once during a given arbitration round.  After a 10μs gap the remaining nodes arbitrate for their turn to use the bus; this continues until all nodes that wish to use the bus during that round have used it.  Following another 20μs gap a new round starts over.


The arbitration mechanism gets more complicated when isochronous devices are connected on the bus, because those devices have already been guaranteed bandwidth.  Each arbitration round is approximately 125μs long, so bandwidth is allocated as a portion of the 125μs interval.  The root node broadcasts (sends a message to node 63, the broadcast address) a cycle start packet, which begins the arbitration round.    All interested nodes send an arbitration request as before, and the winning node is still the node closest to the root.  After .04μs of bus idle time, the remaining nodes arbitrate for control of the bus.  Once each isochronous node has completed its transaction the time remaining in the 125μs interval is used for asynchronous transactions.  Up to 80% of the bus bandwidth may be allocated to isochronous transactions and the remaining 20% is left available for asynchronous transactions.


Linux Background


Support for IEEE 1394 began with Linux kernel version 2.3.99 as part of the mainstream kernel, though patches are available for version 2.2.14.  The project is still under development, though the current implementation is fairly complete and stable.  The general subsystem is maintained by Andreas Bombe while others maintain the individual device drivers for supported PCI cards.


Host Data Structures and Architecture


Two main data structures define the Linux host architecture: hpsb_host and hpsb_host_template.  The hpsb_host_template structure is filled in and registered with Linux by each host device driver.  There is exactly one instance of a host template per host type (i.e. PCI Lynx, Adaptec 5800, etc.).  This structure holds function pointers for dealing with hosts on the system, such as detecting hosts, initializing them, releasing them, transmitting packets, etc.  The hpsb_host structure serves to store information about a particular host.  The most important field is a pointer to the hpsb_host_template that represents the type of host the structure is representing.  Other fields stored in hpsb_host include the host’s node id, the bus manager’s id, a list of pending packets, etc.  Figure 4 shows how these structures interact with one another in the system.






















Figure 4.  Interaction of Host Related Data Structures

High Level Callbacks


The IEEE 1394 subsystem provides a callback mechanism for interaction with the bus.  Two important data structures exist that allow users to register callback functions with the system to be called when certain events occur: hpsb_highlevel_ops and hpsb_address_ops.  The first of these structures contains functions for host-level operations.  These functions are called by the system when, for example, a host is added or removed, or when an isochronous packet is received.  The second structure allows users to provide operations related to a specific address range.  The functions provided include read, write, and lock.  When a device on the bus attempts to read or write an address in the range specified for a particular hpsb_address_ops, the function in that structure is called by the system.


High Level Operations


The high level callbacks are provided for when the bus wishes to interact with the system.  When the system wishes to interact with the bus, however, it must use the high level operations provided by the IEEE 1394 subsystem.  Many of the high level operations provided by the Linux subsystem mirror those of the high level callbacks.  For example, there are functions to read, write, add a host, remove a host, listen on an isochronous channel, etc.




The IEEE 1394 subsystem in Linux provides a convenient interface to the bus in the form of the raw1394 module.  The raw1394 module is both a hpsb_highlevel_ops and a character device.  Being an hpsb_highlevel_ops allows the module to know about all hosts that exist on the system so that users can access all buses available on the system.  As a character device, raw1394 provides the standard fops functions that allow reading, writing, etc.  Reading and writing are accomplished in a slightly different manner than is traditionally used for character devices.  There is a data structure, raw1394_request, which has data members for all important information regarding an IEEE 1394 transaction including type, address, and buffers for the actual data.  An instance of this structure is passed to the read and write methods instead of actual buffers of data as is traditionally done.


Summary and Conclusion


The IEEE 1394 subsystem allows high speed devices to be interconnected independent of the host system, processor, memory, etc.  It provides for both guaranteed bandwidth and guaranteed delivery type transactions via a simple, fairness based arbitration system.  The Linux implementation supports all of the features of the IEEE 1394 subsystem in a simple to use manner that is consistent with current support for other subsystems and architectures.



  1. Anderson, Don.  FireWire System Architecture.  Addison Wesley Longman Inc., 1998.
  2. Rubini, Alessandro.  Linux Device Drivers.  O’Reilly & Associates, Inc., 1998.
  3. Torvalds, Linus, et al.  Linux Kernel Source Code.


[1] Taken from FireWire System Architecture.  (See references)

[2] Ibid.

[3] Ibid.