3
<!-- @(#)porting.html 1.1 02 Jun 1995 -->
4
<title>WorkMan porting notes</title>
11
Porting WorkMan to a new platform is a two-step process. The first step
12
is to get the XView toolkit, version 3.0 or higher, running on your system.
13
If you're lucky, someone else has already done so. The alt.toolkits.xview
14
and comp.windows.open-look newsgroups are good places to find out whether
15
XView exists for your system.
18
Once you have XView installed, you can work on porting WorkMan itself.
19
If your system has builtin libraries for manipulating audio CDs, you can
20
use them. Or you can use your system's user-level SCSI interface, if any.
24
All of the user interface modules ought to compile without modification.
25
For the most part they're just standard C and documented XView calls.
28
The platform-dependent code in WorkMan is in source files named plat_xxx.c,
29
where xxx is the platform name. If you look at a directory listing you'll
30
see that there are files like this for Sun, HP, Linux, and other platforms
31
already. Each of these files (called "platform modules") contains a set of
32
well-defined functions for controlling and getting information from a CD-ROM
33
drive. You'll find a list of those functions below. Ordinarily, porting
34
WorkMan is simply a matter of writing those functions for your platform,
35
and you can usually use one of the existing platform modules as a starting
39
WorkMan supports the notion of running any kind of drive on any platform,
40
assuming the platform has facilities for sending arbitrary SCSI commands
41
from user processes. To this end, you'll also find "drive modules" named
42
drv_xxx.c. Each drive module contains replacement functions along the
43
lines of the functions in the platform modules; these replacement functions
44
are called when the drive doesn't respond to generic requests or when
45
something unusual needs to be done. For instance, the Sony CDU-8012 (also
46
known as the SunCD drive) has a weird volume scale, so we need to do a
47
transformation on the volume setting before passing it to the drive. But
48
other than that, the drive responds to generic CD-ROM commands, so
49
drv_sony.c only has code relating to volume control.
52
Implementing drive modules is fairly simple, but usually isn't necessary
53
so it won't be discussed here. Mail me if you need to do it.
56
Here are the functions a platform module needs to implement. All functions
57
should return integers. Unless otherwise noted, they should return 0 on
58
okay status, -1 on an error condition.
61
The first parameter of each function is a pointer to a wm_drive structure.
62
You'll find it defined in "struct.h". It's discussed after the function call
63
list. You will probably find it helpful to look at one of the existing
64
platform modules while reading this list. The Sun module is one of the
70
wmcd_open(struct wm_drive *d)
72
Figure out the drive type and fill in pointers to the rest of the
73
routines listed here. This routine should set up the device to
74
receive CD-ROM commands if necessary. If the wm_drive structure
75
says the drive is already open, this routine should return 0 --
76
in other words, it shouldn't hurt to call wmcd_open ten times
77
in a row. If the drive couldn't be opened yet, or initialization
78
couldn't be performed yet, the function should clean up and
79
return 1; it will be called again after a short delay. A common
80
example is an open() call failing because there's no CD in the
84
wmcd_open() should determine the drive type if possible. If the
85
wm_scsi() function has been implemented, it can simply call
86
wm_scsi_get_drive_type() (which is in scsi.c) to retrieve the
87
necessary information. Then find_drive_struct() (from cdrom.c)
88
should be called to look up the drive from the list of drive
89
modules; it returns a pointer to a wm_drive structure, which
90
should be copied into the buffer pointed to by the "d" parameter.
91
Finally, the drive init function should be called.
94
Some systems can't determine the drive type at all, for instance
95
because the CD-ROM drive can only be accessed through a limited
96
set of function calls. In that case, just pass empty strings
97
to find_drive_struct() and it'll return a wm_drive structure
98
pointing to the generic platform module routines.
102
wm_scsi(struct wm_drive *d, unsigned char *cdb, int cdblen,
103
unsigned char *buf, int len, int getdata)
105
Send a command to the SCSI device referenced by the wm_drive
106
structure. A CDB of appropriate size is passed in, as is a data
107
buffer. If "getdata" is true, read some data into the buffer in
108
response to the command. Otherwise the buffer might contain some
109
data to be written out as part of the command. "buf" can be
110
NULL if the caller doesn't want to pass in or receive any data.
111
Return -1 if the command doesn't complete successfully. If your
112
system doesn't support SCSI passthrough, this function should just
113
return -1 without doing anything else.
118
The following functions can be overridden by drive modules, as they're
119
always called indirectly via the wm_drive structure.
124
gen_init(struct wm_drive *d)
126
Initialize whatever drive-specific settings are required. For the
127
platform module this is usually just { return (0); } since any
128
platform-specific initialization should be performed in wmcd_open(),
129
but the function needs to be defined.
133
gen_get_trackcount(struct wm_drive *d, int *tracks)
135
Store the number of tracks on the CD in *tracks.
139
gen_get_cdlen(struct wm_drive *d, int *frames)
141
Store the total number of frames on the CD in *frames.
145
gen_get_trackinfo(struct wm_drive *d, int track, int *data, int *startframe)
147
Get the starting frame number and type (1 = data track, 0 = audio) of
148
a particular track. Tracks are numbered starting at 1, as on the CD.
152
gen_get_drive_status(struct wm_drive *d, enum mode oldmode, enum mode *mode,
153
int *pos, int *track, int *index)
155
Get the current status of the drive. Mode is one of PLAYING, PAUSED,
156
TRACK_DONE, STOPPED, and EJECTED, as is oldmode (which will be the
157
previous mode value returned by the routine.) The other parameters
158
are filled in if the drive is playing or paused: the absolute position
159
in frames, the track number, and the index number.
163
gen_get_volume(struct wm_drive *d, int *left, int *right)
165
Get the current volume settings for the left and right channels, or
166
-1 if that information can't be read from the drive. Values range
167
from 0 to 100 on a linear scale.
171
gen_set_volume(struct wm_drive *d, int left, int right)
173
Set the current volume for each channel. Values are from 0 to 100,
174
on the same linear scale as returned by gen_get_volume().
178
gen_pause(struct wm_drive *d)
184
gen_resume(struct wm_drive *d)
186
Resume playing the CD after a pause.
190
gen_stop(struct wm_drive *d)
192
Stop the CD if it's playing or paused.
196
gen_play(struct wm_drive *d, int start, int end)
198
Play a stretch of the CD. Both times are in frames. This can return
199
negative values other than -1 if playing a CD is a multi-step process,
200
e.g. a "start motor" command followed by a "play audio" command.
204
gen_eject(struct wm_drive *d)
206
Eject the CD. Return -3 if the CD can't be ejected because it
207
contains a mounted filesystem.
212
The wm_drive structure has at least the following elements:
214
<pre>struct wm_drive {
215
int fd; /* File descriptor, if used by platform */
216
char vendor[16]; /* Vendor name */
217
char model[24]; /* Drive model */
218
void *aux; /* Pointer to optional platform-specific info */
219
void *daux; /* Pointer to optional drive-specific info */
222
int (*get_trackcount)();
224
int (*get_trackinfo)();
225
int (*get_drive_status)();
236
The "fd" and/or "aux" elements should be filled in by the wmcd_open()
237
function after find_drive_struct() is called. The "fd" element is for an
238
open file descriptor pointing to the drive, though if your platform doesn't
239
use file descriptors to refer to CD-ROM drives (e.g. the BSD/386 platform,
240
whose CD library uses structure pointers) you can use the "fd" element for
241
something else or ignore it completely.
244
The "aux" element should be used to point to any state information you
245
need to keep across calls to these functions. Since WorkMan may eventually
246
support controlling multiple drives simultaneously, you should not use
247
global variables to keep per-drive state. Define a structure for whatever
248
state you need, and point "aux" to it. You can get at it in any of the
249
routines since they are all passed the wm_drive structure you fill in in
250
wmcd_open(). On many platforms, "aux" isn't needed.
253
The "daux" element is reserved for use in drive modules.
256
If you have questions, don't hesitate to send me E-mail. I want to see
257
WorkMan as widely ported as possible.
261
<a href="mailto:koreth@hyperion.com"><koreth@hyperion.com></a>
265
<a href="index.html">To the WorkMan home page</a>
267
<h5>Last update: 02 Jun 1995</h5>