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); }