<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//en">
<!–Converted with LaTeX2HTML 2022 (Released January 1, 2022) –>
<HTML lang="en">
<HEAD>
<TITLE>Contents of Standardizing through another software level</TITLE>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
<META NAME="viewport" CONTENT="width=device-width, initial-scale=1.0">
<META NAME="Generator" CONTENT="LaTeX2HTML v2022">
<LINK REL="STYLESHEET" HREF="cdrom-st.css">
<LINK REL="next" HREF="node20_mn.html">
<LINK REL="previous" HREF="node1_mn.html">
<LINK REL="up" HREF="cdrom-st_mn.html">
<LINK REL="next" HREF="node3_mn.html">
</HEAD>
<BODY bgcolor="#ffffff" text="#000000" link="#9944EE" vlink="#0000ff" alink="#00ff00">
<H1><A ID="SECTION00020000000000000000"></A>
<A ID="cdrom.c"></A>
<BR>
Standardizing through another software level
</H1>
<P>
<TT>At the time this document is written, all drivers directly implement
the <I>ioctl</I> () calls through their own routines, with the danger of
forgetting calls to <!– MATH
verifyarea()
–>
<I>verify</I><SUB>a</SUB><I>rea</I>() and the risk of divergence in
implementation.
</TT>
<P>
<TT>For this reason, we<A NAME="tex2html1" HREF="footnode_mn.html#foot21" TARGET="footer"><SUP>1</SUP></A> propose to define
another software-level, that separates the <I>ioctl</I> () and <I>open</I>()
implementation from the actual hardware implementation. We believe
that CD<SMALL>ROM</SMALL> drives are specific enough (i.e., different from other
block-devices such as floppy or hard disc drives), to define a set of
<EM>CD<SMALL>ROM</SMALL> device operations</EM>, <!– MATH
< cdrom - device > dops
–>
< <I>cdrom</I> - <I>device</I> > <SUB>d</SUB><I>ops</I>. These are of a
different nature than the classical block-device file operations
<!– MATH
< block - device > fops
–>
< <I>block</I> - <I>device</I> > <SUB>f</SUB><I>ops</I>.
</TT>
<P>
<TT>The extra interfacing level routines are implemented in a file
<TT>cdrom.c</TT>, and a low-level CD<SMALL>ROM</SMALL> driver hands over the interfacing to
the kernel by registering the following general <!– MATH
struct fileoperations
–>
<I>struct</I> <I>file</I><SUB>o</SUB><I>perations</I>:
</TT><P><!– MATH

$#$ & $#$ & $/*$ #$*/$
struct &
fileoperations cdromfops={


&
NULL, &
lseek
&
blockread, &
read—
general block-
dev read
&
blockwrite, &
write—
generalblock-
devwrite
&
NULL, &
readdir
&
NULL, &
select
&
cdromioctl, &
ioctl
&
NULL, &
mmap
&
cdromopen, &
open
&
cdromrelease, &
release
&
NULL, &
fsync
&
NULL, &
fasync
&
cdrommediachanged, &
mediachange
&
NULL &
revalidate
};
–>
</P>
<DIV ALIGN="CENTER">
<IMG
STYLE="" SRC="img1.png"
ALT="
"># & # & /*#*/<IMG
STYLE="" SRC="img2.png"
ALT="
"><I>struct</I> & <I>file</I><SUB>o</SUB><I>perations</I> <I>cdrom</I><SUB>f</SUB><I>ops</I>=<IMG
STYLE="" SRC="img3.png"
ALT="
"><IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>NULL</I>, & <I>lseek</I><IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>block</I><SUB>r</SUB><I>ead</I>, & <I>read</I>—<I>general</I> <I>block</I>-<I>dev</I> <I>read</I><IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>block</I><SUB>w</SUB><I>rite</I>, & <I>write</I>—<I>generalblock</I>-<I>devwrite</I><IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>NULL</I>, & <I>readdir</I><IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>NULL</I>, & <I>select</I><IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>cdrom</I><SUB>i</SUB><I>octl</I>, & <I>ioctl</I><IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>NULL</I>, & <I>mmap</I><IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>cdrom</I><SUB>o</SUB><I>pen</I>, & <I>open</I><IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>cdrom</I><SUB>r</SUB><I>elease</I>, & <I>release</I><IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>NULL</I>, & <I>fsync</I><IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>NULL</I>, & <I>fasync</I><IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>cdrom</I><SUB>m</SUB><I>edia</I><SUB>c</SUB><I>hanged</I>, & <I>media</I><SUB>c</SUB><I>hange</I><IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>NULL</I> & <I>revalidate</I><IMG
STYLE="" SRC="img2.png"
ALT="
">;<IMG
STYLE="" SRC="img2.png"
ALT="
">
</DIV><P></P><TT>
Every active CD<SMALL>ROM</SMALL> device shares this <I>struct</I>. The routines declared
above are all implemented in <TT>cdrom.c</TT>, and this is the place where the
<EM>behavior</EM> of all CD<SMALL>ROM</SMALL>-devices is defined, and hence
standardized. The implementation of the interfacing to the various
types of hardware still is done by the various CD<SMALL>ROM</SMALL>-device drivers,
but these routines only implement certain <EM>capabilities</EM> that
are typical to CD<SMALL>ROM</SMALL> (removable-media) devices.
</TT>
<P>
<TT>Registration of the CD<SMALL>ROM</SMALL> device driver should now be to the general
routines in <TT>cdrom.c</TT>, not to the VFS any more. This is done though the
call
</TT><P><!– MATH
registercdrom(int major, char*name, struct cdromdeviceops deviceoptions)
–>
</P>
<DIV ALIGN="CENTER">
<I>register</I><SUB>c</SUB><I>drom</I>(<I>int</I> <I>major</I>, <I>char</I>*<I>name</I>, <I>struct</I> <I>cdrom</I><SUB>d</SUB><I>evice</I><SUB>o</SUB><I>ps</I> <I>device</I><SUB>o</SUB><I>ptions</I>)
</DIV><P></P>
<P>
<TT>The device operations structure lists the implemented routines for
interfacing to the hardware, and some specifications of capabilities
of the device, such as the maximum head-transfer rate. [It is
impossible to come up with a complete list of all capabilities of
(future) CD<SMALL>ROM</SMALL> drives, as the developments in technology follow-up
at an incredible rate. Maybe write-operation (WORM devices) will
become very popular in the future.] The list now is:
</TT><P><!– MATH

$#$ & $#$ &
to10
em$#$

& $/*$ #$*/$
struct &
cdromdeviceops {


&
int & (*
open)(
kdevt,
int)

&
void & (*
release)(
kdevt);

&
int & (*
openfiles)(
kdevt);

&
int & (*
drivestatus)(
kdevt);

&
int & (*
discstatus)(
kdevt);

&
int & (*
mediachanged )(
kdevt);

&
int & (*
traymove)(
kdevt,
int);

&
int & (*
lockdoor)(
kdevt,
int);

&
int & (*
selectspeed )(
kdevt,
int);

&
int & (*
selectdisc)(
kdevt,
int);

&
int & (*
getlastsession)(
kdevt,
struct cdrommultisession*);

&
int & (*
getmcn)(
kdevt,
struct cdrommcn*);

&
int & (*
reset)(
kdevt);

&
int & (*
audioioctl )(
kdevt,
unsigned int,
void*);

&
int & (*
devioctl )(
kdevt,
unsigned int,
unsigned long);

&
const int & capability; & capabilityflags
& int & mask; & maskofcapability:disablesthem
&
$const $float & speed; & maximumspeedforreadingdata
&
$const $int & minors; & numberofsupportedminordevices
&
$const $int & capacity; & numberofdiscsinjukebox
& int & options; & optionsflags
& long & mcflags; & media-changebufferflags($2×16$)
}
–>
</P>
<DIV ALIGN="CENTER">
<IMG
STYLE="" SRC="img1.png"
ALT="
"># & # & <I>to</I>10<I>em</I>#<IMG
STYLE="" SRC="img4.png"
ALT="
"> & /*#*/<IMG
STYLE="" SRC="img2.png"
ALT="
"><I>struct</I> & <I>cdrom</I><SUB>d</SUB><I>evice</I><SUB>o</SUB><I>ps</I> <IMG
STYLE="" SRC="img3.png"
ALT="
"><IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>int</I> & (*<I>open</I>)(<I>kdev</I><SUB>t</SUB>, <I>int</I>)<IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>void</I> & (*<I>release</I>)(<I>kdev</I><SUB>t</SUB>);<IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>int</I> & (*<I>open</I><SUB>f</SUB><I>iles</I>)(<I>kdev</I><SUB>t</SUB>);<IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>int</I> & (*<I>drive</I><SUB>s</SUB><I>tatus</I>)(<I>kdev</I><SUB>t</SUB>);<IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>int</I> & (*<I>disc</I><SUB>s</SUB><I>tatus</I>)(<I>kdev</I><SUB>t</SUB>);<IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>int</I> & (*<I>media</I><SUB>c</SUB><I>hanged</I> )(<I>kdev</I><SUB>t</SUB>);<IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>int</I> & (*<I>tray</I><SUB>m</SUB><I>ove</I>)(<I>kdev</I><SUB>t</SUB>, <I>int</I>);<IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>int</I> & (*<I>lock</I><SUB>d</SUB><I>oor</I>)(<I>kdev</I><SUB>t</SUB>, <I>int</I>);<IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>int</I> & (*<I>select</I><SUB>s</SUB><I>peed</I> )(<I>kdev</I><SUB>t</SUB>, <I>int</I>);<IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>int</I> & (*<I>select</I><SUB>d</SUB><I>isc</I>)(<I>kdev</I><SUB>t</SUB>, <I>int</I>);<IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>int</I> & (*<I>get</I><SUB>l</SUB><I>ast</I><SUB>s</SUB><I>ession</I>)(<I>kdev</I><SUB>t</SUB>, <I>struct</I> <I>cdrom</I><SUB>m</SUB><I>ultisession</I>*);<IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>int</I> & (*<I>get</I><SUB>m</SUB><I>cn</I>)(<I>kdev</I><SUB>t</SUB>, <I>struct</I> <I>cdrom</I><SUB>m</SUB><I>cn</I>*);<IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>int</I> & (*<I>reset</I>)(<I>kdev</I><SUB>t</SUB>);<IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>int</I> & (*<I>audio</I><SUB>i</SUB><I>octl</I> )(<I>kdev</I><SUB>t</SUB>, <I>unsigned</I> <I>int</I>, <I>void</I>*);<IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>int</I> & (*<I>dev</I><SUB>i</SUB><I>octl</I> )(<I>kdev</I><SUB>t</SUB>, <I>unsigned</I> <I>int</I>, <I>unsigned</I> <I>long</I>);<IMG
STYLE="" SRC="img2.png"
ALT="
"><P>
<BR> & <IMG
STYLE="" SRC="img5.png"
ALT="
"><I>const</I> <I>int</I> & <I>capability</I>; & <I>capabilityflags</I><IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>int</I> & <I>mask</I>; & <I>maskofcapability</I>:<I>disablesthem</I><IMG
STYLE="" SRC="img2.png"
ALT="
"> & <IMG
STYLE="" SRC="img5.png"
ALT="
">
< I > const < /I > & nbsp;<I>float</I> & <I>speed</I>; & <I>maximumspeedforreadingdata</I><IMG
STYLE="" SRC="img2.png"
ALT="
"> & <IMG
STYLE="" SRC="img5.png"
ALT="
">
< I > const < /I > & nbsp;<I>int</I> & <I>minors</I>; & <I>numberofsupportedminordevices</I><IMG
STYLE="" SRC="img2.png"
ALT="
"> & <IMG
STYLE="" SRC="img5.png"
ALT="
">
< I > const < /I > & nbsp;<I>int</I> & <I>capacity</I>; & <I>numberofdiscsinjukebox</I><IMG
STYLE="" SRC="img2.png"
ALT="
"><P>
<BR> & <I>int</I> & <I>options</I>; & <I>optionsflags</I><IMG
STYLE="" SRC="img2.png"
ALT="
"> & <I>long</I> & <I>mc</I><SUB>f</SUB><I>lags</I>; & <I>media</I>-<I>changebufferflags</I>(
2 & #215;16)<IMG
STYLE="" SRC="img2.png"
ALT="
"><IMG
STYLE="" SRC="img2.png"
ALT="
">
</DIV><P></P><TT> The CD<SMALL>ROM</SMALL>-driver should simply implement (some of) these
functions, and register the functions to the global CD<SMALL>ROM</SMALL> driver,
which performs interfacing with the Virtual File System and system
<I>ioctl</I>s. The flags <!– MATH
capability
–>
<I>capability</I> specify the hardware-capabilities on
registration of the device, the flags <I>mask</I> can be used to mask some
of those capabilities (for one reason or another). The value <I>minors</I>
should be a positive value indicating the number of minor devices that
are supported by the driver, normally 1. (They are supposed to be
numbered from 0 upwards). The value <I>capacity</I> should be the number of
discs the drive can hold simultaneously, if it is designed as a
juke-box, or otherwise 1.
</TT>
<P>
<TT>Two registers contain variables local to the CD<SMALL>ROM</SMALL> device. The flags
<I>options</I> are used to specify how the general CD<SMALL>ROM</SMALL> routines
should behave. These various flags registers should provide enough
flexibility to adapt to the different user's wishes (and <EM>not</EM>
the `arbitrary' wishes of the author of the low-level device driver,
as is the case in the old scheme). The register <I>mc</I><SUB>f</SUB><I>lags</I> is used to
buffer the information from <!– MATH
mediachanged ()
–>
<I>media</I><SUB>c</SUB><I>hanged</I> () to two separate queues.
</TT>
<P>
<TT>Note that most functions have fewer parameters than their
<!– MATH
blkdevfops
–>
<I>blkdev</I><SUB>f</SUB><I>ops</I> counterparts. This is because very little of the
information in the structures <I>inode</I> and <I>file</I> are used, the main
parameter is the device <I>dev</I>, from which the minor-number can be
extracted. (Most low-level CD<SMALL>ROM</SMALL> drivers don't even look at that value
as only one device is supported.)
</TT>
<P>
<TT>The intermediate software layer that <TT>cdrom.c</TT> forms will performs some
additional bookkeeping. The minor number of the device is checked
against the maximum registered in <!– MATH
< device > dops
–>
< <I>device</I> > <SUB>d</SUB><I>ops</I>. The function
<!– MATH
cdromioctl ()
–>
<I>cdrom</I><SUB>i</SUB><I>octl</I> () will verify the appropriate user-memory regions for
read and write, and in case a location on the CD is transferred, it
will `sanitize' the format by making requests to the low-level drivers
in a standard format, and translating all formats between the
user-software and low level drivers. This relieves much of the drivers
memory checking and format checking and translation. Also, the
necessary structures will be declared on the program stack.
</TT>
<P>
<TT>The implementation of the functions should be as defined in the
following sections. Three functions <EM>must</EM> be implemented,
namely <I>open</I>(), <I>release</I>() and <!– MATH
openfiles()
–>
<I>open</I><SUB>f</SUB><I>iles</I>(). Other functions may
be omitted, their corresponding capability flags will be cleared upon
registration. Generally, a function returns zero on success and
negative on error. A function call should return only after the
command has completed, but of course waiting for the device should not
use processor time.
</TT>
<P>
<BR><HR>
<!–Table of Child-Links–>
<A ID="CHILD_LINKS"><STRONG>Subsections</STRONG></A>
<UL>
<LI><A NAME="tex2html39" HREF="node3_ct.html" TARGET="contents"><SMALL><!– MATH
Open(kdevt dev, int purpose)
–>
<I>Open</I>(<I>kdev</I><SUB>t</SUB> <I>dev</I>, <I>int</I> <I>purpose</I>)</SMALL></A>
<LI><A NAME="tex2html40" HREF="node4_mn.html" TARGET="main"><SMALL><!– MATH
Release(kdevt dev)
–>
<I>Release</I>(<I>kdev</I><SUB>t</SUB> <I>dev</I>)</SMALL></A>
<LI><A NAME="tex2html41" HREF="node5_mn.html" TARGET="main"><SMALL><!– MATH
Openfiles(kdevt dev)
–>
<I>Open</I><SUB>f</SUB><I>iles</I>(<I>kdev</I><SUB>t</SUB> <I>dev</I>)</SMALL></A>
<LI><A NAME="tex2html42" HREF="node6_mn.html" TARGET="main"><SMALL><!– MATH
Drivestatus(kdevt dev)
–>
<I>Drive</I><SUB>s</SUB><I>tatus</I>(<I>kdev</I><SUB>t</SUB> <I>dev</I>)</SMALL></A>
<LI><A NAME="tex2html43" HREF="node7_mn.html" TARGET="main"><SMALL><!– MATH
Discstatus(kdevt dev)
–>
<I>Disc</I><SUB>s</SUB><I>tatus</I>(<I>kdev</I><SUB>t</SUB> <I>dev</I>)</SMALL></A>
<LI><A NAME="tex2html44" HREF="node8_mn.html" TARGET="main"><SMALL><!– MATH
Mediachanged (dev
dev)
–>
<I>Media</I><SUB>c</SUB><I>hanged</I> (<I>dev</I><IMG
STYLE="" SRC="img6.png"
ALT="
"> <I>dev</I>)</SMALL></A>
<LI><A NAME="tex2html45" HREF="node9_mn.html" TARGET="main"><SMALL><!– MATH
Traymove(kdevt dev, int position)
–>
<I>Tray</I><SUB>m</SUB><I>ove</I>(<I>kdev</I><SUB>t</SUB> <I>dev</I>, <I>int</I> <I>position</I>)</SMALL></A>
<LI><A NAME="tex2html46" HREF="node10_mn.html" TARGET="main"><SMALL><!– MATH
Lockdoor(kdevt dev, int lock)
–>
<I>Lock</I><SUB>d</SUB><I>oor</I>(<I>kdev</I><SUB>t</SUB> <I>dev</I>, <I>int</I> <I>lock</I>)</SMALL></A>
<LI><A NAME="tex2html47" HREF="node11_mn.html" TARGET="main"><SMALL><!– MATH
Selectspeed (kdevt dev, int speed )
–>
<I>Select</I><SUB>s</SUB><I>peed</I> (<I>kdev</I><SUB>t</SUB> <I>dev</I>, <I>int</I> <I>speed</I> )</SMALL></A>
<LI><A NAME="tex2html48" HREF="node12_mn.html" TARGET="main"><SMALL><!– MATH
Selectdisc(kdevt dev, int number)
–>
<I>Select</I><SUB>d</SUB><I>isc</I>(<I>kdev</I><SUB>t</SUB> <I>dev</I>, <I>int</I> <I>number</I>)</SMALL></A>
<LI><A NAME="tex2html49" HREF="node13_mn.html" TARGET="main"><SMALL><!– MATH
Getlastsession(kdevt dev, struct cdrommultisession*msinfo)
–>
<I>Get</I><SUB>l</SUB><I>ast</I><SUB>s</SUB><I>ession</I>(<I>kdev</I><SUB>t</SUB> <I>dev</I>, <I>struct</I> <I>cdrom</I><SUB>m</SUB><I>ultisession</I>*<I>ms</I><SUB>i</SUB><I>nfo</I>)</SMALL></A>
<LI><A NAME="tex2html50" HREF="node14_mn.html" TARGET="main"><SMALL><!– MATH
Getmcn(kdevt dev, struct cdrommcn*mcn)
–>
<I>Get</I><SUB>m</SUB><I>cn</I>(<I>kdev</I><SUB>t</SUB> <I>dev</I>, <I>struct</I> <I>cdrom</I><SUB>m</SUB><I>cn</I>*<I>mcn</I>)</SMALL></A>
<LI><A NAME="tex2html51" HREF="node15_mn.html" TARGET="main"><SMALL><!– MATH
Reset(kdevtdev)
–>
<I>Reset</I>(<I>kdev</I><SUB>t</SUB><I>dev</I>)</SMALL></A>
<LI><A NAME="tex2html52" HREF="node16_mn.html" TARGET="main"><SMALL><!– MATH
Audioioctl (kdevt dev, unsigned int cmd, void*arg)
–>
<I>Audio</I><SUB>i</SUB><I>octl</I> (<I>kdev</I><SUB>t</SUB> <I>dev</I>, <I>unsigned</I> <I>int</I> <I>cmd</I>, <I>void</I>*<I>arg</I>)</SMALL></A>
<LI><A NAME="tex2html53" HREF="node17_mn.html" TARGET="main"><SMALL><!– MATH
Devioctl (kdevt dev, unsigned int cmd, unsigned longI>arg)
–>
<I>Dev</I><SUB>i</SUB><I>octl</I> (<I>kdev</I><SUB>t</SUB> <I>dev</I>, <I>unsigned</I> <I>int</I> <I>cmd</I>, <I>unsigned</I> <I>long</I>I>arg</I>)</SMALL></A>
<LI><A NAME="tex2html54" HREF="node18_mn.html" TARGET="main"><SMALL>CD<SMALL>ROM</SMALL> capabilities</SMALL></A>
<LI><A NAME="tex2html55" HREF="node19_mn.html" TARGET="main"><SMALL>Options</SMALL></A>
</UL>
<!–End of Table of Child-Links–>
<HR>
</BODY>
</HTML>