mirror of
https://github.com/ctm/executor.git
synced 2024-09-28 11:54:53 +00:00
417 lines
11 KiB
C
417 lines
11 KiB
C
|
/* Copyright 1989 - 1995 by Abacus Research and
|
||
|
* Development, Inc. All rights reserved.
|
||
|
*/
|
||
|
|
||
|
/* Forward declarations in DeviceMgr.h (DO NOT DELETE THIS LINE) */
|
||
|
|
||
|
#if !defined (OMIT_RCSID_STRINGS)
|
||
|
char ROMlib_rcsid_device[] =
|
||
|
"$Id: device.c 63 2004-12-24 18:19:43Z ctm $";
|
||
|
#endif
|
||
|
|
||
|
#include "rsys/common.h"
|
||
|
#include "DeviceMgr.h"
|
||
|
#include "FileMgr.h"
|
||
|
#include "MemoryMgr.h"
|
||
|
#include "OSUtil.h"
|
||
|
#include "ResourceMgr.h"
|
||
|
#include "MenuMgr.h"
|
||
|
#include "ToolboxEvent.h"
|
||
|
#include "rsys/glue.h"
|
||
|
#include "rsys/mman.h"
|
||
|
#include "rsys/device.h"
|
||
|
#include "rsys/file.h"
|
||
|
#include "rsys/serial.h"
|
||
|
|
||
|
/*
|
||
|
* NOTE: The device manager now executes "native code" and code read
|
||
|
* in from resources. The latter is "RAM" based, the former is
|
||
|
* our version of "ROM" based. We use the same bit that the Mac
|
||
|
* uses to distinguish between the two, but our implementation of
|
||
|
* ROM based is incompatible with theirs. NOTE: even in our
|
||
|
* incompatible ROM based routines, we still byte swap the pointers
|
||
|
* that get us to the routines.
|
||
|
*/
|
||
|
|
||
|
A4(PUBLIC, OSErr, ROMlib_dispatch, ParmBlkPtr, p, /* INTERNAL */
|
||
|
BOOLEAN, async, DriverRoutineType, routine, INTEGER, trapn)
|
||
|
{
|
||
|
int devicen;
|
||
|
ramdriverhand ramdh;
|
||
|
DCtlHandle h;
|
||
|
OSErr retval;
|
||
|
typedef OSErr (*devfp_t)(ParmBlkPtr, DCtlPtr);
|
||
|
devfp_t procp;
|
||
|
|
||
|
devicen = -CW(p->cntrlParam.ioCRefNum) - 1;
|
||
|
if (devicen < 0 || devicen >= NDEVICES)
|
||
|
retval = badUnitErr;
|
||
|
else if (UTableBase == (DCtlHandlePtr) (long) CLC(0xFFFFFFFF) ||
|
||
|
(h = MR(MR(UTableBase)[devicen].p)) == 0 || (*h).p == 0)
|
||
|
retval = unitEmptyErr;
|
||
|
else {
|
||
|
HLock((Handle) h);
|
||
|
p->ioParam.ioTrap = CW(trapn);
|
||
|
if (async)
|
||
|
p->ioParam.ioTrap |= CWC(asyncTrpBit);
|
||
|
else
|
||
|
p->ioParam.ioTrap |= CWC(noQueueBit);
|
||
|
if (!(HxX(h, dCtlFlags) & CWC(RAMBASEDBIT))) {
|
||
|
switch (routine) {
|
||
|
case Open:
|
||
|
retval = (* (devfp_t) MR(HxP(h, dCtlDriver)->udrvrOpen))
|
||
|
(p, STARH(h));
|
||
|
break;
|
||
|
case Prime:
|
||
|
retval = (* (devfp_t) MR(HxP(h, dCtlDriver)->udrvrPrime))
|
||
|
(p, STARH(h));
|
||
|
break;
|
||
|
case Ctl:
|
||
|
retval = (* (devfp_t) MR(HxP(h, dCtlDriver)->udrvrCtl))
|
||
|
(p, STARH(h));
|
||
|
break;
|
||
|
case Stat:
|
||
|
retval = (* (devfp_t) MR(HxP(h, dCtlDriver)->udrvrStatus))
|
||
|
(p, STARH(h));
|
||
|
break;
|
||
|
case Close:
|
||
|
retval = (* (devfp_t) MR(HxP(h, dCtlDriver)->udrvrClose))
|
||
|
(p, STARH(h));
|
||
|
break;
|
||
|
default:
|
||
|
retval = fsDSIntErr;
|
||
|
break;
|
||
|
}
|
||
|
} else {
|
||
|
ramdh = (ramdriverhand) HxP(h, dCtlDriver);
|
||
|
LoadResource((Handle) ramdh);
|
||
|
HLock((Handle) ramdh);
|
||
|
switch (routine) {
|
||
|
case Open:
|
||
|
procp = (devfp_t) STARH(ramdh) + Hx(ramdh, drvrOpen);
|
||
|
break;
|
||
|
case Prime:
|
||
|
procp = (devfp_t) STARH(ramdh) + Hx(ramdh, drvrPrime);
|
||
|
break;
|
||
|
case Ctl:
|
||
|
procp = (devfp_t) STARH(ramdh) + Hx(ramdh, drvrCtl);
|
||
|
break;
|
||
|
case Stat:
|
||
|
procp = (devfp_t) STARH(ramdh) + Hx(ramdh, drvrStatus);
|
||
|
break;
|
||
|
case Close:
|
||
|
procp = (devfp_t) STARH(ramdh) + Hx(ramdh, drvrClose);
|
||
|
break;
|
||
|
default:
|
||
|
procp = 0;
|
||
|
break;
|
||
|
}
|
||
|
if (procp) {
|
||
|
LONGINT saved1, saved2, saved3, saved4, saved5, saved6, saved7,
|
||
|
savea2, savea3, savea4, savea5, savea6;
|
||
|
|
||
|
savea2 = EM_A2;
|
||
|
EM_A0 = (LONGINT) (long) US_TO_SYN68K(p);
|
||
|
EM_A1 = (LONGINT) (long) US_TO_SYN68K(STARH(h));
|
||
|
EM_A2 = (LONGINT) (long) US_TO_SYN68K(procp); /* for compatibility with above */
|
||
|
saved1 = EM_D1;
|
||
|
saved2 = EM_D2;
|
||
|
saved3 = EM_D3;
|
||
|
saved4 = EM_D4;
|
||
|
saved5 = EM_D5;
|
||
|
saved6 = EM_D6;
|
||
|
saved7 = EM_D7;
|
||
|
savea3 = EM_A3;
|
||
|
savea4 = EM_A4;
|
||
|
savea5 = EM_A5;
|
||
|
savea6 = EM_A6;
|
||
|
CALL_EMULATOR((syn68k_addr_t) (long) US_TO_SYN68K (procp));
|
||
|
EM_D1 = saved1;
|
||
|
EM_D2 = saved2;
|
||
|
EM_D3 = saved3;
|
||
|
EM_D4 = saved4;
|
||
|
EM_D5 = saved5;
|
||
|
EM_D6 = saved6;
|
||
|
EM_D7 = saved7;
|
||
|
EM_A3 = savea3;
|
||
|
EM_A4 = savea4;
|
||
|
EM_A5 = savea5;
|
||
|
EM_A6 = savea6;
|
||
|
retval = EM_D0;
|
||
|
EM_A2 = savea2;
|
||
|
} else
|
||
|
retval = fsDSIntErr;
|
||
|
if (routine == Open)
|
||
|
HxX(h, dCtlFlags) |= CWC(DRIVEROPENBIT);
|
||
|
else if (routine == Close) {
|
||
|
HxX(h, dCtlFlags) &= ~CWC(DRIVEROPENBIT);
|
||
|
HUnlock((Handle) h);
|
||
|
HUnlock((Handle) ramdh);
|
||
|
MBarEnable = 0;
|
||
|
/* NOTE: It's not clear whether we should zero out this
|
||
|
field or just check for DRIVEROPEN bit up above and never
|
||
|
send messages except open to non-open drivers. */
|
||
|
MR(UTableBase)[devicen].p = CLC(0);
|
||
|
}
|
||
|
|
||
|
if (routine < Close)
|
||
|
retval = CW(p->ioParam.ioResult); /* see II-193 */
|
||
|
}
|
||
|
}
|
||
|
fs_err_hook (retval);
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
/* PBOpen, PBClose, PBRead and PBWrite are part of the file manager */
|
||
|
|
||
|
A2(PUBLIC, OSErr, PBControl, ParmBlkPtr, pbp, BOOLEAN, a) /* IMII-186 */
|
||
|
{
|
||
|
OSErr err;
|
||
|
|
||
|
err = ROMlib_dispatch(pbp, a, Ctl, 0);
|
||
|
fs_err_hook (err);
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
A2(PUBLIC, OSErr, PBStatus, ParmBlkPtr, pbp, BOOLEAN, a) /* IMII-186 */
|
||
|
{
|
||
|
OSErr err;
|
||
|
|
||
|
err = ROMlib_dispatch(pbp, a, Stat, 0);
|
||
|
fs_err_hook (err);
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
A2(PUBLIC, OSErr, PBKillIO, ParmBlkPtr, pbp, BOOLEAN, a) /* IMII-187 */
|
||
|
{
|
||
|
OSErr err;
|
||
|
|
||
|
pbp->cntrlParam.csCode = CWC(killCode);
|
||
|
err = ROMlib_dispatch(pbp, a, Ctl, 0);
|
||
|
fs_err_hook (err);
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* OpenDriver is defined below ROMlib_driveropen.
|
||
|
* CloseDriver is defined below ROMlib_driverclose.
|
||
|
*/
|
||
|
|
||
|
/* FSRead, FSWrite are part of the file manager */
|
||
|
|
||
|
A3(PUBLIC, OSErr, Control, INTEGER, rn, INTEGER, code,
|
||
|
Ptr, param) /* IMII-179 */
|
||
|
{
|
||
|
ParamBlockRec pb;
|
||
|
OSErr err;
|
||
|
|
||
|
pb.cntrlParam.ioVRefNum = 0;
|
||
|
pb.cntrlParam.ioCRefNum = CW(rn);
|
||
|
pb.cntrlParam.csCode = CW(code);
|
||
|
if (param)
|
||
|
BlockMove(param, (Ptr) pb.cntrlParam.csParam,
|
||
|
(Size) sizeof(pb.cntrlParam.csParam));
|
||
|
err = PBControl(&pb, FALSE);
|
||
|
fs_err_hook (err);
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
A3(PUBLIC, OSErr, Status, INTEGER, rn, INTEGER, code, Ptr, param) /* IMII-179 */
|
||
|
{
|
||
|
ParamBlockRec pb;
|
||
|
OSErr retval;
|
||
|
|
||
|
pb.cntrlParam.ioVRefNum = 0;
|
||
|
pb.cntrlParam.ioCRefNum = CW(rn);
|
||
|
pb.cntrlParam.csCode = CW(code);
|
||
|
retval = PBStatus(&pb, FALSE);
|
||
|
if (param)
|
||
|
BlockMove((Ptr) pb.cntrlParam.csParam, param,
|
||
|
(Size) sizeof(pb.cntrlParam.csParam));
|
||
|
fs_err_hook (retval);
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
A1(PUBLIC, OSErr, KillIO, INTEGER, rn) /* IMII-179 */
|
||
|
{
|
||
|
ParamBlockRec pb;
|
||
|
OSErr err;
|
||
|
|
||
|
pb.cntrlParam.ioCRefNum = CW(rn);
|
||
|
err = PBKillIO(&pb, FALSE);
|
||
|
fs_err_hook (err);
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
A1(PUBLIC, DCtlHandle, GetDCtlEntry, INTEGER, rn)
|
||
|
{
|
||
|
int devicen;
|
||
|
|
||
|
devicen = -rn - 1;
|
||
|
return (devicen < 0 || devicen >= NDEVICES) ?
|
||
|
0
|
||
|
:
|
||
|
MR(MR(UTableBase)[devicen].p);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* ROMlib_driveropen will be called by PBOpen if it encounters a name
|
||
|
* beginning with * a period.
|
||
|
*/
|
||
|
|
||
|
PUBLIC driverinfo *ROMlib_otherdrivers = 0; /* for extensibility */
|
||
|
|
||
|
PRIVATE driverinfo knowndrivers[] = {
|
||
|
#if defined (LINUX) || defined (NEXTSTEP) || defined (MSDOS) || defined (CYGWIN32)
|
||
|
{ ROMlib_serialopen, ROMlib_serialprime, ROMlib_serialctl,
|
||
|
ROMlib_serialstatus, ROMlib_serialclose, (StringPtr) "\004.AIn", -6, },
|
||
|
|
||
|
{ ROMlib_serialopen, ROMlib_serialprime, ROMlib_serialctl,
|
||
|
ROMlib_serialstatus, ROMlib_serialclose, (StringPtr) "\005.AOut", -7, },
|
||
|
|
||
|
{ ROMlib_serialopen, ROMlib_serialprime, ROMlib_serialctl,
|
||
|
ROMlib_serialstatus, ROMlib_serialclose, (StringPtr) "\004.BIn", -8, },
|
||
|
|
||
|
{ ROMlib_serialopen, ROMlib_serialprime, ROMlib_serialctl,
|
||
|
ROMlib_serialstatus, ROMlib_serialclose, (StringPtr) "\005.BOut", -9, },
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
A2(PUBLIC, OSErr, ROMlib_driveropen, ParmBlkPtr, pbp, /* INTERNAL */
|
||
|
BOOLEAN, a)
|
||
|
{
|
||
|
driverinfo *dip, *edip;
|
||
|
OSErr err;
|
||
|
INTEGER devicen;
|
||
|
umacdriverptr up;
|
||
|
DCtlHandle h;
|
||
|
ramdriverhand ramdh;
|
||
|
ResType typ;
|
||
|
BOOLEAN alreadyopen;
|
||
|
|
||
|
ZONE_SAVE_EXCURSION
|
||
|
(SysZone,
|
||
|
{
|
||
|
err = noErr;
|
||
|
|
||
|
if ((ramdh =
|
||
|
(ramdriverhand) GetNamedResource(TICK("DRVR"),
|
||
|
MR(pbp->ioParam.ioNamePtr)))) {
|
||
|
LoadResource((Handle) ramdh);
|
||
|
GetResInfo((Handle) ramdh, &devicen, &typ, (StringPtr) 0);
|
||
|
devicen = CW(devicen);
|
||
|
h = MR(MR(UTableBase)[devicen].p);
|
||
|
alreadyopen = h && (HxX(h, dCtlFlags) & CWC(DRIVEROPENBIT));
|
||
|
if (!h && !(h = MR(MR(UTableBase)[devicen].p =
|
||
|
RM((DCtlHandle) NewHandle(sizeof(DCtlEntry))))))
|
||
|
err = MemError();
|
||
|
else if (!alreadyopen) {
|
||
|
memset((char *) STARH(h), 0, sizeof(DCtlEntry));
|
||
|
HxX(h, dCtlDriver) = (umacdriverptr) RM(ramdh);
|
||
|
HxX(h, dCtlFlags) = HxX(ramdh, drvrFlags) | CWC(RAMBASEDBIT);
|
||
|
HxX(h, dCtlRefNum) = CW(- (devicen + 1));
|
||
|
HxX(h, dCtlDelay) = HxX(ramdh, drvrDelay);
|
||
|
HxX(h, dCtlEMask) = HxX(ramdh, drvrEMask);
|
||
|
HxX(h, dCtlMenu) = HxX(ramdh, drvrMenu);
|
||
|
if (HxX(h, dCtlFlags) & CWC(NEEDTIMEBIT))
|
||
|
HxX(h, dCtlCurTicks) = CL(TickCount() + Hx(h, dCtlDelay));
|
||
|
else
|
||
|
HxX(h, dCtlCurTicks) = CLC(0x7FFFFFFF);
|
||
|
/*
|
||
|
* NOTE: this code doesn't check to see if something is already open.
|
||
|
* TODO: fix this
|
||
|
*/
|
||
|
pbp->cntrlParam.ioCRefNum = HxX(h, dCtlRefNum);
|
||
|
err = ROMlib_dispatch(pbp, a, Open, 0);
|
||
|
} else
|
||
|
{
|
||
|
pbp->cntrlParam.ioCRefNum = HxX(h, dCtlRefNum);
|
||
|
err = noErr;
|
||
|
}
|
||
|
} else {
|
||
|
|
||
|
dip = 0;
|
||
|
if (ROMlib_otherdrivers) {
|
||
|
for (dip = ROMlib_otherdrivers; dip->open &&
|
||
|
!EqualString(dip->name, MR(pbp->ioParam.ioNamePtr), FALSE, TRUE);
|
||
|
dip++)
|
||
|
;
|
||
|
if (!dip->open)
|
||
|
dip = 0;
|
||
|
}
|
||
|
if (!dip) {
|
||
|
for (dip = knowndrivers, edip = dip + NELEM(knowndrivers);
|
||
|
dip != edip &&
|
||
|
!EqualString(dip->name, MR(pbp->ioParam.ioNamePtr), FALSE, TRUE);
|
||
|
dip++)
|
||
|
;
|
||
|
if (dip == edip)
|
||
|
dip = 0;
|
||
|
}
|
||
|
if (dip) {
|
||
|
devicen = -dip->refnum -1;
|
||
|
if (devicen < 0 || devicen >= NDEVICES)
|
||
|
err = badUnitErr;
|
||
|
else if (MR(UTableBase)[devicen].p)
|
||
|
err = noErr; /* note: if we choose to support desk */
|
||
|
/* accessories, we will have to */
|
||
|
/* check to see if this is one and */
|
||
|
/* call the open routine if it is */
|
||
|
else {
|
||
|
if (!(h = MR(MR(UTableBase)[devicen].p =
|
||
|
RM((DCtlHandle) NewHandle(sizeof(DCtlEntry))))))
|
||
|
err = MemError();
|
||
|
else {
|
||
|
memset((char *) STARH(h), 0, sizeof(DCtlEntry));
|
||
|
up = (umacdriverptr) NewPtr(sizeof(umacdriver));
|
||
|
if (!(HxX(h, dCtlDriver) = RM(up)))
|
||
|
err = MemError();
|
||
|
else {
|
||
|
up->udrvrOpen = (ProcPtr) RM(dip->open);
|
||
|
up->udrvrPrime = (ProcPtr) RM(dip->prime);
|
||
|
up->udrvrCtl = (ProcPtr) RM(dip->ctl);
|
||
|
up->udrvrStatus = (ProcPtr) RM(dip->status);
|
||
|
up->udrvrClose = (ProcPtr) RM(dip->close);
|
||
|
str255assign(up->udrvrName, dip->name);
|
||
|
err = noErr;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (err == noErr) {
|
||
|
pbp->cntrlParam.ioCRefNum = CW(dip->refnum);
|
||
|
err = ROMlib_dispatch(pbp, a, Open, 0);
|
||
|
}
|
||
|
} else
|
||
|
err = dInstErr;
|
||
|
}
|
||
|
});
|
||
|
fs_err_hook (err);
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
A2(PUBLIC, OSErr, OpenDriver, StringPtr, name, INTEGER *, rnp) /* IMII-178 */
|
||
|
{
|
||
|
ParamBlockRec pb;
|
||
|
OSErr retval;
|
||
|
|
||
|
pb.ioParam.ioRefNum = CWC (0); /* so we can't get garbage for ioRefNum. */
|
||
|
pb.ioParam.ioPermssn = fsCurPerm;
|
||
|
pb.ioParam.ioNamePtr = RM(name);
|
||
|
retval = ROMlib_driveropen(&pb, FALSE);
|
||
|
*rnp = pb.ioParam.ioRefNum;
|
||
|
fs_err_hook (retval);
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
A1(PUBLIC, OSErr, CloseDriver, INTEGER, rn) /* IMII-178 */
|
||
|
{
|
||
|
ParamBlockRec pb;
|
||
|
OSErr err;
|
||
|
|
||
|
pb.cntrlParam.ioCRefNum = CW(rn);
|
||
|
err = PBClose(&pb, FALSE);
|
||
|
fs_err_hook (err);
|
||
|
return err;
|
||
|
}
|
||
|
|