diff options
Diffstat (limited to 'static/netbsd/man4/midi.4 3.html')
| -rw-r--r-- | static/netbsd/man4/midi.4 3.html | 454 |
1 files changed, 0 insertions, 454 deletions
diff --git a/static/netbsd/man4/midi.4 3.html b/static/netbsd/man4/midi.4 3.html deleted file mode 100644 index 95f05fd4..00000000 --- a/static/netbsd/man4/midi.4 3.html +++ /dev/null @@ -1,454 +0,0 @@ -<table class="head"> - <tr> - <td class="head-ltitle">MIDI(4)</td> - <td class="head-vol">Device Drivers Manual</td> - <td class="head-rtitle">MIDI(4)</td> - </tr> -</table> -<div class="manual-text"> -<section class="Sh"> -<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1> -<p class="Pp"><code class="Nm">midi</code> — - <span class="Nd">device-independent MIDI driver layer</span></p> -</section> -<section class="Sh"> -<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1> -<p class="Pp"><code class="Cd">midi* at midibus?</code> - <br/> - <code class="Cd">midi* at pcppi?</code> - <br/> - <code class="Cd">pseudo-device sequencer</code></p> -<p class="Pp"> - <br/> - <code class="In">#include <<a class="In">sys/types.h</a>></code> - <br/> - <code class="In">#include <<a class="In">sys/midiio.h</a>></code></p> -</section> -<section class="Sh"> -<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1> -<p class="Pp">The <code class="Nm">midi</code> driver is the machine independent - layer over anything that can source or sink a MIDI data stream, whether a - physical MIDI IN or MIDI OUT jack on a soundcard, cabled to some external - synthesizer or input controller, an on-board programmable tone generator, or - a single jack, synthesizer, or controller component within a complex USB or - IEEE1394 MIDI device that has several such components and appears as several - MIDI streams.</p> -<section class="Ss"> -<h2 class="Ss" id="Concepts"><a class="permalink" href="#Concepts">Concepts</a></h2> -<p class="Pp">One MIDI data stream is a unidirectional stream of MIDI messages, - as could be carried over one MIDI cable in the MIDI 1.0 specification. Many - MIDI messages carry a four-bit channel number, creating up to 16 MIDI - channels within a single MIDI stream. There may be multiple consumers of a - MIDI stream, each configured to react only to messages on specific channels; - the sets of channels different consumers react to need not be disjoint. Many - modern devices such as multitimbral keyboards and tone generators listen on - all 16 channels, or may be viewed as collections of 16 independent consumers - each listening on one channel. MIDI defines some messages that take no - channel number, and apply to all consumers of the stream on which they are - sent. For an inbound stream, <code class="Nm">midi</code> is a promiscuous - receiver, capturing all messages regardless of channel number. For an - outbound stream, the writer can specify a channel number per message; there - is no notion of binding the stream to one destination channel in - advance.</p> -<p class="Pp">A single <code class="Nm">midi</code> device instance is the - endpoint of one outbound stream, one inbound stream, or one of each. In the - third case, the write and read sides are independent MIDI streams. For - example, a soundcard driver may map its MIDI OUT and MIDI IN jacks to the - write and read sides of a single device instance, but those jacks can be - cabled to completely different pieces of gear. Information from - <a class="Xr">dmesg(8)</a>, and a diagram of any external MIDI cabling, will - help clarify the mapping.</p> -</section> -<section class="Ss"> -<h2 class="Ss" id="Underlying_drivers_and_MIDI_protocol"><a class="permalink" href="#Underlying_drivers_and_MIDI_protocol">Underlying - drivers and MIDI protocol</a></h2> -<p class="Pp">Drivers <code class="Nm">midi</code> can attach include soundcard - drivers, many of which support a UART resembling Roland's MPU401 and handled - by <a class="Xr">mpu(4)</a>, USB MIDI devices via - <a class="Xr">umidi(4)</a>, and on-board devices that can make sounds, - whether a lowly PC speaker or a Yamaha OPL. Serial port and IEEE1394 - connections are currently science fiction.</p> -<p class="Pp">The MIDI protocol permits some forms of message compression such - as running status and hidden note-off. Received messages on inbound streams - are always canonicalized by <code class="Nm">midi</code> before presentation - to higher layers. Messages for transmission are accepted by - <code class="Nm">midi</code> in any valid form.</p> -</section> -<section class="Ss"> -<h2 class="Ss" id="Device_access"><a class="permalink" href="#Device_access">Device - access</a></h2> -<p class="Pp">Access to <code class="Nm">midi</code> device instances can be - through the raw device nodes, <span class="Pa">/dev/rmidiN</span>, or - through the sequencer, <span class="Pa">/dev/music</span>.</p> -</section> -<section class="Ss"> -<h2 class="Ss" id="Raw_MIDI_access"><a class="permalink" href="#Raw_MIDI_access">Raw - MIDI access</a></h2> -<p class="Pp">A <span class="Pa">/dev/rmidiN</span> device supports - <a class="Xr">read(2)</a>, <a class="Xr">write(2)</a>, - <a class="Xr">ioctl(2)</a>, - <a class="Xr">select(2)</a>/<a class="Xr">poll(2)</a> and the corresponding - <a class="Xr">kevent(2)</a> filters, and may be opened only when it is not - already open. It may be opened in <code class="Dv">O_RDONLY</code>, - <code class="Dv">O_WRONLY</code>, or <code class="Dv">O_RDWR</code> mode, - but a later <a class="Xr">read(2)</a> or <a class="Xr">write(2)</a> will - return -1 if the device has no associated input or output stream, - respectively.</p> -<p class="Pp">Bytes written are passed as quickly as possible to the underlying - driver as complete MIDI messages; a maximum of two bytes at the end of a - <a class="Xr">write(2)</a> may remain buffered if they do not complete a - message, until completed by a following <a class="Xr">write(2)</a>.</p> -<p class="Pp">A <a class="Xr">read(2)</a> will not block or return - <code class="Er">EWOULDBLOCK</code> when it could immediately return any - nonzero count, and MIDI messages received are available to - <a class="Xr">read(2)</a> as soon as they are complete, with a maximum of - two received bytes remaining buffered if they do not complete a message.</p> -<p class="Pp">As all MIDI messages are three bytes or fewer except for System - Exclusive, which can have arbitrary length, these rules imply that System - Exclusive messages are the only ones of which some bytes can be delivered - before all are available.</p> -<p class="Pp">System Realtime messages are passed with minimum delay in either - direction, ahead of any possible buffered incomplete message. As a result, - they will never interrupt any MIDI message except possibly System - Exclusive.</p> -<p class="Pp">A <a class="Xr">read(2)</a> with a buffer large enough to - accommodate the first complete message available will be satisfied with as - many complete messages as will fit. A buffer too small for the first - complete message will be filled to capacity. Therefore, an application that - reads from an <span class="Pa">rmidi</span> device with buffers of three - bytes or larger need never parse across read boundaries to assemble a - received message, except possibly in the case of a System Exclusive message. - However, if the application reads through a buffering layer such as - <a class="Xr">fread(3)</a>, this property will not be preserved.</p> -<p class="Pp">The <code class="Nm">midi</code> driver itself supports the - <a class="Xr">ioctl(2)</a> operations <code class="Dv">FIOASYNC</code>, - <code class="Dv">FIONBIO</code>, and <code class="Dv">FIONREAD</code>. - Underlying devices may support others. The value returned for - <code class="Dv">FIONREAD</code> reflects the size in bytes of complete - messages (or System Exclusive chunks) ready to read. If the - <a class="Xr">ioctl(2)</a> returns <var class="Va">n</var> and a - <a class="Xr">read(2)</a> of size <var class="Va">n</var> is issued, - <var class="Va">n</var> bytes will be read, but if a - <a class="Xr">read(2)</a> of size <var class="Va">m</var> < - <var class="Va">n</var> is issued, fewer than <var class="Va">m</var> bytes - may be read if <var class="Va">m</var> does not fall on a message/chunk - boundary.</p> -<p class="Pp">Raw MIDI access can be used to receive bulk dumps from - synthesizers, download bulk data to them, and so on. Simple patching of one - device to another can be done at the command line, as with</p> -<div class="Bd Bd-indent"><code class="Li">$ cat -u 0<>/dev/rmidi0 - 1>&0</code></div> -which will loop all messages received on the input stream of - <span class="Pa">rmidi0</span> input stream back to its output stream in real - time. However, an attempt to record and play back music with -<div class="Bd Bd-indent"><code class="Li">$ cat /dev/rmidiN >foo; cat foo - >/dev/rmidiN</code></div> -will be disappointing. The file <span class="Pa">foo</span> will contain all of - the notes that were played, but because MIDI messages carry no explicit - timing, the ‘playback’ will reproduce them all at once, as fast - as they can be transmitted. To preserve timing information, the sequencer - device can be used. -</section> -<section class="Ss"> -<h2 class="Ss" id="Active_Sensing"><a class="permalink" href="#Active_Sensing">Active - Sensing</a></h2> -<p class="Pp">The MIDI protocol includes a keepalive function called Active - Sensing. In any receiver that has - <a class="permalink" href="#not"><i class="Em" id="not">not</i></a> received - at least one Active Sense MIDI message, the feature is suppressed and no - timeout applies. If at least one such message has been received, the lapse - of any subsequent 300 ms interval without receipt of any message reflects - loss of communication, and the receiver should silence any currently - sounding notes and return to non-Active-Sensing behavior. A sender using - Active Sensing generally avoids 300 ms gaps in transmission by sending - Active Sense messages (which have no other effect) as needed when there is - no other traffic to send in the interval. This feature can be important for - MIDI, which relies on separate Note On and Note Off messages, to avoid notes - stuck on indefinitely if communication is interrupted before a Note Off - message arrives.</p> -<p class="Pp">This protocol is supported in <code class="Nm">midi</code>. An - outbound stream will be kept alive by sending Active Sense messages as - needed, beginning after any real traffic is sent on the stream, and - continuing until the stream is closed. On an inbound stream, if any Active - Sense has been received, then a process reading an - <span class="Pa">rmidi</span> device will see an end-of-file indication if - the input timeout elapses. The stream remains open, the driver reverts to - enforcing no timeout, and the process may continue to read for more input. - Subsequent receipt of an Active Sense message will re-arm the timeout. As - received Active Sense messages are handled by <code class="Nm">midi</code>, - they are not included among messages read from the - <span class="Pa">/dev/rmidiN</span> device.</p> -<p class="Pp">These rules support end-to-end Active Sensing behavior in simple - cases without special action in an application. For example, in</p> -<div class="Bd Bd-indent"><code class="Li">$ cat -u /dev/rmidi0 - >/dev/rmidi1</code></div> -if the input stream to <span class="Pa">rmidi0</span> is lost, the - <a class="Xr">cat(1)</a> command exits; on the <a class="Xr">close(2)</a> of - <span class="Pa">rmidi1</span>, <code class="Nm">midi</code> ceases to send - Active Sense messages, and the receiving device will detect the loss and - silence any outstanding notes. -</section> -<section class="Ss"> -<h2 class="Ss" id="Access_through_the_sequencer"><a class="permalink" href="#Access_through_the_sequencer">Access - through the sequencer</a></h2> -<p class="Pp">To play music using the raw MIDI API would require an application - to issue many small writes with very precise timing. The sequencer device, - <span class="Pa">/dev/music</span>, can manage the timing of MIDI data in - the kernel, to avoid such demanding real-time constraints on a user - process.</p> -<p class="Pp">The <span class="Pa">/dev/music</span> device can be opened only - when it is not already open. When opened, the sequencer internally opens all - MIDI instances existing in the system that are not already open at their raw - nodes; any attempts to open them at their raw nodes while the sequencer is - open will fail. All access to the corresponding MIDI streams will then be - through the sequencer.</p> -<p class="Pp">Reads and writes of <span class="Pa">/dev/music</span> pass - eight-byte event structures defined in - <code class="In"><<a class="In">sys/midiio.h</a>></code> (which see - for their documentation and examples of use). Some events correspond to MIDI - messages, and carry an integer <var class="Va">device</var> field to - identify one of the MIDI devices opened by the sequencer. Other events carry - timing information interpreted or generated by the sequencer itself.</p> -<p class="Pp">A message received on an input stream is wrapped in a sequencer - event along with the device index of the stream it arrived on, and queued - for the reader of <span class="Pa">/dev/music</span>. If a measurable time - interval passed since the last preceding message, a timing event that - represents a delay for that interval is queued ahead of the received event. - The sequencer handles output events by interpreting any timing event, and - routing any MIDI message event at the proper time to an underlying output - stream according to its <var class="Va">device</var> index. Therefore</p> -<div class="Bd Bd-indent"><code class="Li">$ cat /dev/music >foo; cat foo - >/dev/music</code></div> -can be expected to capture and reproduce an input performance including timing. -<p class="Pp">The process of playing back a complex MIDI file is illustrated - below. The file may contain several tracks—four, in this - example—of MIDI events, each marked with a device index and a time - stamp, that may overlap in time. In the example, <var class="Va">a</var>, - <var class="Va">b</var>, and <var class="Va">c</var> are device indices of - the three output MIDI streams; the left-hand digit in each input event - represents a MIDI channel on the selected stream, and the right-hand digit - represents a time for the event's occurrence. As illustrated, the input - tracks are not firmly associated with output streams; any track may contain - events for any stream.</p> -<div class="Bd Pp Li"> -<pre> | | a2|4 | - a0|3 | c1|3 c0|3 - | b0|2 b1|2 | - | b1|1 | c0|1 - a0|0 | b0|0 | - v v v v - +---------------------------+ - | merge to 1 ordered stream | - | user code, eg midiplay(1) | - +---------------------------+ - b1|2 - b0|2 - c0|1 - b1|1 - b0|0 - a0|0 - v - _______+-------------+_______user - | /dev/music | kernel - | (sequencer) | - +-------------+ - | 1 0 - +-----' | '-----. - 0 0 | - v v v - +-------+ +--------+ +---------+ - |midi(4)| |midi(4) | |midi(4) | - |rmidia | |rmidib | |rmidic | - +-------+ +--------+ +---------+ - | mpu(4)| |umidi(4)| |midisyn | - +-------+ +--------+ +---------+ - | HW | | | opl(4) | - | MIDI | U +---------+ - | UART | S | internal| - +-------+ B | tone | - | | |generator| - v | +---------+ - external v - MIDI device external - MIDI device</pre> -</div> -<p class="Pp">A user process must merge the tracks into a single stream of - sequencer MIDI and timing events in order by desired timing. The sequencer - obeys the timing events and distributes the MIDI events to the three - destinations, in this case two external devices connected to a sound card - UART and a USB interface, and an OPL tone generator on a sound card.</p> -</section> -</section> -<section class="Sh"> -<h1 class="Sh" id="NOTES"><a class="permalink" href="#NOTES">NOTES</a></h1> -<p class="Pp">Use of <a class="Xr">select(2)</a>/<a class="Xr">poll(2)</a> with - the sequencer is supported, however, there is no guarantee that a - <a class="Xr">write(2)</a> will not block or return - <code class="Er">EWOULDBLOCK</code> if it begins with a timer-wait event, - even if <a class="Xr">select(2)</a>/<a class="Xr">poll(2)</a> reported the - sequencer writable.</p> -<p class="Pp">The delivery of a realtime message ahead of buffered bytes of an - incomplete message may cause the realtime message to seem, in a saved byte - stream, to have arrived up to 640 us earlier than it really did, at MIDI 1.0 - data rates. Higher data rates make the effect less significant.</p> -<p class="Pp">Another sequencer device, <span class="Pa">/dev/sequencer</span>, - is provided only for backward compatibility with an obsolete OSS interface - in which some sequencer events were four-byte records. It is not further - documented here, and the <span class="Pa">/dev/music</span> API should be - used in new code. The <span class="Pa">/dev/sequencer</span> emulation is - implemented only for writing, and that might not be complete.</p> -</section> -<section class="Sh"> -<h1 class="Sh" id="IMPLEMENTATION_NOTES"><a class="permalink" href="#IMPLEMENTATION_NOTES">IMPLEMENTATION - NOTES</a></h1> -<p class="Pp">Some hardware devices supporting <code class="Nm">midi</code> lack - transmit-ready interrupts, and some have the capability in hardware but - currently lack driver support. They can be recognized by the annotation - <code class="Li">(CPU-intensive output)</code> in - <a class="Xr">dmesg(8)</a>. While suitable for music playback, they may have - an objectionable impact on system responsiveness during bulk transmission - such as patch downloads, and are best avoided for that purpose if other - suitable devices are present.</p> -<p class="Pp">Buffer space in <code class="Nm">midi</code> itself is adequate - for about 200 ms of traffic at MIDI 1.0 data rates, per stream.</p> -<p class="Pp">Event counters record bytes and messages discarded because of - protocol errors or buffer overruns, and can be viewed with - <code class="Li">vmstat -e</code>. They can be useful in diagnosing flaky - cables and other communication problems.</p> -<p class="Pp">A raw sound generator uses the <b class="Sy">midisyn</b> layer to - present a MIDI message-driven interface attachable by - <code class="Nm">midi</code>.</p> -<p class="Pp">While <code class="Nm">midi</code> accepts messages for - transmission in any valid mixture of compressed or canonical form, they are - always presented to an underlying driver in the form it prefers. Drivers for - simple UART-like devices register their preference for a compressed byte - stream, while those like <a class="Xr">umidi(4)</a>, which uses a packet - protocol, or <b class="Sy">midisyn</b>, which interprets complete messages, - register for intact canonical messages. This design eliminates the need for - compression and canonicalization logic from all layers above and below - <code class="Nm">midi</code> itself.</p> -</section> -<section class="Sh"> -<h1 class="Sh" id="FILES"><a class="permalink" href="#FILES">FILES</a></h1> -<dl class="Bl-tag Bl-compact"> - <dt><span class="Pa">/dev/rmidiN</span></dt> - <dd style="width: auto;"> </dd> - <dt><span class="Pa">/dev/music</span></dt> - <dd style="width: auto;"> </dd> - <dt><span class="Pa">/dev/sequencer</span></dt> - <dd style="width: auto;"> </dd> -</dl> -</section> -<section class="Sh"> -<h1 class="Sh" id="ERRORS"><a class="permalink" href="#ERRORS">ERRORS</a></h1> -<p class="Pp">In addition to other errors documented for the - <a class="Xr">write(2)</a> family of system calls, - <code class="Er">EPROTO</code> can be returned if the bytes to be written on - a raw <code class="Nm">midi</code> device would violate MIDI protocol.</p> -</section> -<section class="Sh"> -<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE - ALSO</a></h1> -<p class="Pp"><a class="Xr">midiplay(1)</a>, <a class="Xr">midirecord(1)</a>, - <a class="Xr">ioctl(2)</a>, <a class="Xr">ossaudio(3)</a>, - <a class="Xr">audio(4)</a>, <a class="Xr">mpu(4)</a>, - <a class="Xr">opl(4)</a>, <a class="Xr">umidi(4)</a></p> -<p class="Pp">For ports using the ISA bus: <a class="Xr">cms(4)</a>, - <a class="Xr">pcppi(4)</a>, <a class="Xr">sb(4)</a></p> -<p class="Pp">For ports using the PCI bus: <a class="Xr">autri(4)</a>, - <a class="Xr">clcs(4)</a>, <a class="Xr">eap(4)</a></p> -</section> -<section class="Sh"> -<h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1> -<p class="Pp">The <code class="Nm">midi</code> driver first appeared in - <span class="Ux">NetBSD 1.4</span>. It was overhauled and this manual page - rewritten for <span class="Ux">NetBSD 4.0</span>.</p> -</section> -<section class="Sh"> -<h1 class="Sh" id="BUGS"><a class="permalink" href="#BUGS">BUGS</a></h1> -<p class="Pp">Some OSS sequencer events and <a class="Xr">ioctl(2)</a> - operations are unimplemented, as - <code class="In"><<a class="In">sys/midiio.h</a>></code> notes.</p> -<p class="Pp">OSS source-compatible sequencer macros should be added to - <code class="In"><<a class="In">sys/soundcard.h</a>></code>, - implemented with the <span class="Ux">NetBSD</span> ones in - <code class="In"><<a class="In">sys/midiio.h</a>></code>, so sources - written for OSS can be easily compiled.</p> -<p class="Pp">The sequencer blocks (or returns - <code class="Er">EWOULDBLOCK</code>) only when its buffer physically fills, - which can represent an arbitrary latency because of buffered timing events. - As a result, interrupting a process writing the sequencer may not interrupt - music playback for a considerable time. The sequencer could enforce a - reasonable latency bound by examining timing events as they are enqueued and - blocking appropriately.</p> -<p class="Pp"><code class="Dv">FIOASYNC</code> enables signal delivery to the - calling process only; <code class="Dv">FIOSETOWN</code> is not - supported.</p> -<p class="Pp">The sequencer can only be a timing master, but does not send - timing messages to synchronize any slave device; it cannot be slaved to - timing messages received on any interface (which would presumably require a - PLL algorithm similar to NTP's, and expertise in that area to implement it). - The sequencer ignores timing messages received on any interface and does not - pass them along to the reading process, and the OSS operations to change - that behavior are unimplemented.</p> -<p class="Pp">The <code class="Dv">SEQUENCER_TMR_TIMEBASE</code> - <a class="Xr">ioctl(2)</a> will report successfully setting any timebase up - to ridiculously high resolutions, though the actual resolution, and - therefore jitter, is constrained by <a class="Xr">hz(9)</a>. Comparable - sequencer implementations typically allow a selection from available sources - of time interrupts that may be programmable.</p> -<p class="Pp">The device number in a sequencer event is treated on - <a class="Xr">write(2)</a> as index into the array of MIDI devices the - sequencer has opened, but on <a class="Xr">read(2)</a> as the unit number of - the source MIDI device; these are usually the same if the sequencer has - opened all the MIDI devices (that is, none was already open at its raw node - when the sequencer was opened), but might not be the same otherwise.</p> -<p class="Pp">There is at present no way to make reception nonpromiscuous, - should anyone have a reason to want to.</p> -<p class="Pp">There should be ways to override default Active Sense behavior. As - one obvious case, if an application is seen to send Active Sense explicitly, - <code class="Nm">midi</code> should refrain from adding its own. On receive, - there should be an option to pass Active Sense through rather than - interpreting it, for apps that wish to handle or ignore it themselves and - never see <code class="Dv">EOF</code>.</p> -<p class="Pp">When a <code class="Nm">midi</code> stream is open by the - sequencer, Active Sense messages received on the stream are passed to the - sequencer and not interpreted by <code class="Nm">midi</code>. The sequencer - at present neither does anything itself with Active Sense messages received, - nor supports the OSS API for making them available to the user process.</p> -<p class="Pp">System Exclusive messages can be received by reading a raw device, - but not by reading the sequencer; they are discarded on receipt when the - stream is open by the sequencer, rather than being presented as the - OSS-defined sequencer events.</p> -<p class="Pp"><b class="Sy">midisyn</b> is too rudimentary at present to get - satisfactory results from any onboard synth. It lacks the required special - interpretation of the General MIDI percussion channel in GM mode. More - devices should be supported; some sound cards with synthesis capability have - <span class="Ux">NetBSD</span> drivers that implement the - <a class="Xr">audio(4)</a> but not the <b class="Sy">midisyn</b> interface. - Voice stealing algorithm does not follow the General MIDI Developer - Guidelines.</p> -<p class="Pp">ALSA sequencer compatibility is lacking, but becoming important to - applications. It would require the function of merging multiple tracks into - a single ordered stream to be moved from user space into the sequencer. - Assuming the sequencer driven by periodic interrupts, timing wheels could be - used as in <a class="Xr">hardclock(9)</a> itself. Similar functionality will - be in OSS4; with the right infrastructure it should be possible to support - both. When merging MIDI streams, a notion of transaction is needed to group - critical message sequences. If ALSA or OSS4 have no such notion, it should - be provided as an upward-compatible extension.</p> -<p class="Pp">I would rather have <a class="Xr">open(2)</a> itself return an - error (by the POSIX description <code class="Er">ENODEV</code> looks most - appropriate) if a read or write mode is requested that is not supported by - the instance, rather than letting <a class="Xr">open(2)</a> succeed and - <a class="Xr">read(2)</a> or <a class="Xr">write(2)</a> return -1, but so - help me, the latter seems the more common <span class="Ux">UNIX</span> - practice.</p> -</section> -</div> -<table class="foot"> - <tr> - <td class="foot-date">April 28, 2017</td> - <td class="foot-os">NetBSD 10.1</td> - </tr> -</table> |
