dillon@CORY.BERKELEY.EDU (Matt Dillon) (05/22/86)
I've gotten sick and tired of the number of things one must do to
open a device, so I wrote the following routines. With one call, and
no previous initialization, allocation, or other assorted crap, you can
get one or two io-request structures for any device.
Well, it isn't quite that easy... you still need to #include the
correct files to get the structure definitions, but.....
In any case, it's made my life a lot easier. I'm interested in
feedback. I've included a huge comment to try to explain how it works.
Once you understand, it's a surprisingly simple call.
Enjoy,
-Matt
/*
* IO.C (should be compiled w/ 32-bit ints)
*
* Matthew Dillon, Completely Public Domain (you
* don't even have to include these comments or anything. Gee.)
*
* I/O support for devices.
* io_open() - Generalized OpenDevice() which does everything for
* you.
*
* io_close() - Generalized CloseDevice(). Should only be used
* with io_open()'d devices.
*
* long
* io_open(device_name, unit, flags, &rreq, &wwreq, req_size, spec1, spec2)
*
* char *device_name -the device name (ex: "serial.device")
* int unit -unit #
* int flags -OpenDevice flags
* struct IOxxxxxx *rreq -address of pointer (will be filled in)
* struct IOxxxxxx *wreq -address of pointer (will be filled in)
* int req_size -size of above structures
* long spec1,spec2 -special arguments for preinitialization
* (depends on the device your openning)
*
* EXAMPLE:
* ----------------------
* typedef struct IOExtSer SIO;
*
* #define SERFLAGS (SERF_XDISABLED | SERF_SHARED)
* SIO *srr, *swr;
* long mask;
*
* mask = io_open("serial.device",0,0,&srr,&swr,sizeof(SIO),SERFLAGS,0);
* .
* do stuff w/ srr and swr.
* .
* io_close(srr, swr, sizeof(SIO));
*
* ----------------------
*
* The structure for rreq and wreq depend on the device you are openning.
* You must be sure to specify the correct size.
*
* Some devices, such as the serial device, require certain fields inside
* their IO structures to be initialized before the OpenDevice(). Since
* io_open() Allocates these structures for you, these extra parameters
* must be passed to io_open() via SPEC1 and SPEC2 in the arguments list
* as outlined below:
* SPEC1 SPEC2
* console.device window pointer window structure size
* parallel.device parallel flags 0
* serial.device serial flags 0
* **ALL OTHERS** 0 0
*
* note on audio device: You must ADCMD_ALLOCATE and ADCMD_FREE
* manually.
*
* You also pass io_open() the address of two pointers (e.g. **x). These
* will be filled in by io_open() to result in a READ and WRITE request
* structure, each with it's own reply port, and with it's io_Command
* fields initialized to CMD_READ and CMD_WRITE, respectively. You may
* specify a NULL for the **WRITE request structure instead of a
* **wreq. This will result in only a READ request structure being
* set up.
*
* You do not have to use the structures for only CMD_READ and CMD_WRITE,
* of course, you can use them for any io command.
*
* a signal MASK with one bit set is returned. This is the signal bit
* for the read-request structure (if rreq was NULL, then it is the
* signal for the write-request structure). an example mask:
* 00000000001000000000000000000000 in binary.
*
* 0 is returned if the open fails.
*
*
* io_close(rreq, wreq, size)
*
* specify NULL for the wreq if it doesn't exist (e.g. you passed a
* NULL for it in the io_open() ).
*/
#include <exec/types.h>
#include <exec/ports.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <devices/serial.h>
#include <devices/parallel.h>
#define FAIL(ifzero) if (!ifzero) goto fail
typedef struct IORequest IOR;
typedef struct IOStdReq STD;
typedef struct MsgPort PORT;
extern char *AllocMem();
extern PORT *CreatePort();
long
io_open(name, unit, od_arg, prr, pww, size, special1, special2)
char *name;
IOR **prr, **pww;
long special1, special2;
{
PORT *rport, *wport;
IOR *rreq, *wreq;
int ret;
rreq = wreq = NULL;
rport = wport = NULL;
rport = CreatePort(NULL,0); FAIL(rport);
rreq = (IOR *)AllocMem(size, MEMF_PUBLIC|MEMF_CLEAR); FAIL(rreq);
if (pww) {
wport = CreatePort(NULL,0); FAIL(wport);
wreq = (IOR *)AllocMem(size, MEMF_PUBLIC|MEMF_CLEAR); FAIL(wreq);
}
if (special1) {
if (scmp(name, SERIALNAME))
((struct IOExtSer *)rreq)->io_SerFlags = special1;
if (scmp(name, PARALLELNAME))
((struct IOExtPar *)rreq)->io_ParFlags = special1;
if (scmp(name, "console.device")) {
((STD *)rreq)->io_Data = (APTR)special1;
((STD *)rreq)->io_Length= special2;
}
}
rreq->io_Message.mn_ReplyPort = rport;
ret = OpenDevice(name, unit, rreq, od_arg); FAIL(!ret);
if (pww) {
*wreq = *rreq; /* structure assignment */
wreq->io_Message.mn_ReplyPort = wport;
wreq->io_Command = CMD_WRITE;
*pww = wreq;
}
rreq->io_Command = CMD_READ;
*prr = rreq;
return (1 << rport->mp_SigBit); /* return read sig bit */
fail:
if (rport) DeletePort(rport);
if (wport) DeletePort(wport);
if (rreq) FreeMem(rreq, size);
if (wreq) FreeMem(wreq, size);
return (0);
}
io_close(rreq, wreq, size)
IOR *rreq, *wreq;
{
if (rreq) {
CloseDevice(rreq);
if (rreq->io_Message.mn_ReplyPort)
DeletePort(rreq->io_Message.mn_ReplyPort);
FreeMem (rreq, size);
}
if (wreq) {
if (wreq->io_Message.mn_ReplyPort)
DeletePort(wreq->io_Message.mn_ReplyPort);
FreeMem (wreq, size);
}
}
scmp(s1, s2)
register char *s1, *s2;
{
while (*s1 == *s2) {
if ((*s1 | *s2) == 0)
return (1);
++s1; ++s2;
}
return (0);
}