home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * PARNET.C
- *
- */
-
- #include "defs.h"
- #include <resources/misc.h>
- #include <hardware/cia.h>
- #include <exec/memory.h>
-
- extern func_ptr DeviceVectors[];
- extern func_ptr UnitVectors[];
- extern char DeviceName[];
- extern char IdString[];
-
- extern void VInt(void); /* wakeup.asm */
- extern Task *VTask; /* wakeup.asm */
- extern long VMask; /* wakeup.asm */
- extern int AutoAllocMiscResource(int, int); /* wakeup.asm */
- extern int AutoFreeMiscResource(int); /* wakeup.asm */
- extern int VAddICRVector(int, int, struct Interrupt *); /* wakeup.asm */
- extern int VRemICRVector(int, int, struct Interrupt *); /* wakeup.asm */
-
- long SysBase = NULL; /* sysbase */
- Device *DevBase = NULL; /* device base */
- BPTR DevSegment = NULL; /* seglist for device */
- long PLock[2] = { 0, 0 }; /* arbitrate network access */
- PubPort *StickyPort= NULL;
-
- char ActiveMRPP = 0;
- char ActiveMRPB = 0;
- char ActiveTask = 0;
- char ActiveInt = 0;
-
- struct Interrupt VInterrupt = {
- {
- NULL, NULL,
- NT_INTERRUPT,
- -126,
- "parnet.device"
- },
- NULL,
- VInt
- };
-
- /* Prototyping */
-
- APTR CDevInit(BPTR);
- Device *CDevOpen(long,long,Iob *);
- long CDevExpunge(void);
- BPTR CDevClose(Iob *);
- void ReadConfig(void);
- void WriteConfig(void);
- int DetermineTimeouts(void);
-
- /*
- * Init is called when the device is loaded to create it.
- */
-
- APTR
- CDevInit(seg)
- BPTR seg;
- {
- Device *db;
-
- SysBase = *(long *)4;
-
- DevBase = db = (Device *)MakeLibrary((long **)DeviceVectors,NULL,NULL,sizeof(Device),NULL);
- db->Lib.lib_Node.ln_Type = NT_DEVICE;
- db->Lib.lib_Node.ln_Name = DeviceName;
- db->Lib.lib_Flags = LIBF_CHANGED|LIBF_SUMUSED;
- db->Lib.lib_Version = 1;
- db->Lib.lib_IdString= (APTR)IdString;
- db->ParAddress = 254; /* default address */
- db->Port.mp_Node.ln_Type = NT_MSGPORT;
- db->Port.mp_SigBit = SIGBREAKB_CTRL_E; /* for VTask */
- db->Port.mp_Flags = PA_SIGNAL;
- NewList(&db->UnitList);
- NewList(&db->Port.mp_MsgList);
-
- ReadConfig();
- WriteConfig();
-
- DevSegment = seg;
- AddDevice((struct Device *)db);
- return((APTR)db);
- }
-
- Device *
- CDevOpen(unitnum, flags, iob)
- long unitnum;
- long flags;
- Iob *iob;
- {
- Device *nd = DevBase;
-
- iob->io_Unit = NULL;
-
- LockAddr(PLock); /* because we make calls that kill Forbid() */
-
- nd->Lib.lib_Flags &= ~LIBF_DELEXP;
-
- if (++nd->Lib.lib_OpenCnt == 1) {
- /*
- * Initial Open, allocate resources
- */
-
- if (AutoAllocMiscResource(MR_PARALLELPORT, -1)) {
- iob->io_Actual = PPERR_NOPORTRES;
- goto badop;
- }
- ActiveMRPP = 1;
- if (AutoAllocMiscResource(MR_PARALLELBITS, -1)) {
- iob->io_Actual = PPERR_NOBITSRES;
- goto badop;
- }
- ActiveMRPB = 1;
- VTask = CreateTask("parnet.device", 0, (APTR)ParNetTask, 4096);
- if (VTask == NULL) {
- iob->io_Actual = PPERR_NOTASK;
- goto badop;
- }
- ActiveTask = 1;
- VMask = SIGBREAKF_CTRL_F;
- nd->Port.mp_SigTask = VTask; /* for asynchronous I/O */
-
- if (VAddICRVector(0, CIAICRB_FLG, &VInterrupt)) {
- iob->io_Actual = PPERR_NOINT;
- goto badop;
- }
- ActiveInt = 1;
-
- if (DetermineTimeouts() < 0) /* couldn't use timer.device */
- goto badop;
-
- }
- iob->io_Actual= 0;
- iob->io_Error = 0;
-
- /*
- * Attempt to open the specified unit by protocol
- */
-
- {
- short proto = iob->io_Flags & PRO_MASK;
-
- if (proto <= PRO_LAST) {
- (*UnitVectors[proto])(iob, unitnum, flags);
- if (iob->io_Error == 0) {
- UnlockAddr(PLock);
- return(nd);
- }
- }
- }
-
- /*
- * OPEN FAILED
- */
-
- badop:
- CDevClose(iob);
- iob->io_Actual = iob->io_Error;
- iob->io_Error = IOERR_OPENFAIL;
- UnlockAddr(PLock);
- return(NULL);
- }
-
- long
- CDevExpunge(void)
- {
- Device *nd = DevBase;
- BPTR ds = DevSegment;
-
- if (ds == NULL)
- Alert(24);
-
- if (nd->Lib.lib_OpenCnt) { /* delayed expunge */
- nd->Lib.lib_Flags |= LIBF_DELEXP;
- return(NULL);
- }
- Remove((NODE *)nd);
- FreeMem((char *)nd - nd->Lib.lib_NegSize, nd->Lib.lib_NegSize + nd->Lib.lib_PosSize);
- DevSegment = NULL;
- return(ds);
- }
-
- BPTR
- CDevClose(iob)
- Iob *iob;
- {
- Device *nd = DevBase;
-
- if (iob->io_Unit)
- (*iob->io_Unit->CloseFunc)(iob);
-
- iob->io_Unit = NULL; /* clear vectors */
- iob->io_Device = NULL;
-
- if (nd->Lib.lib_OpenCnt == 1) { /* last close */
- if (ActiveInt)
- VRemICRVector(0, CIAICRB_FLG, &VInterrupt);
- if (ActiveTask)
- RemTask(VTask);
- if (ActiveMRPB)
- AutoFreeMiscResource(MR_PARALLELBITS);
- if (ActiveMRPP)
- AutoFreeMiscResource(MR_PARALLELPORT);
- ActiveInt = 0;
- ActiveTask= 0;
- ActiveMRPB= 0;
- ActiveMRPP= 0;
- }
- if (nd->Lib.lib_OpenCnt && --nd->Lib.lib_OpenCnt)
- return(NULL); /* still has refs */
-
- /*
- * Note: LIBF_DELEXP never set if DevClose() called from DevOpen()
- */
-
- if (nd->Lib.lib_Flags & LIBF_DELEXP)
- return(CDevExpunge()); /* expunge */
- return(NULL); /* no expunge */
- }
-
- /*
- * UNITS
- */
-
- Unit *UnitCache = NULL;
-
- Unit *
- FindUnitForPort(port)
- uword port;
- {
- Unit *unit;
- Device *db;
-
- if (UnitCache && port == UnitCache->Port)
- return(UnitCache);
-
- db = DevBase;
- for (unit = (Unit *)db->UnitList.lh_Head; unit != (Unit *)&db->UnitList.lh_Tail; unit = (Unit *)unit->Node.ln_Succ) {
- if (port == unit->Port) {
- UnitCache = unit;
- return(unit);
- }
- }
- return(NULL);
- }
-
- Unit *
- AllocUnit(iob, beginFunc, abortFunc, dataFunc, closeFunc)
- Iob *iob;
- func_void beginFunc;
- func_void abortFunc;
- func_void dataFunc;
- func_void closeFunc;
- {
- Unit *unit = AllocMem(sizeof(Unit), MEMF_CLEAR | MEMF_PUBLIC);
- Device *db = DevBase;
-
- unit->BeginIO = beginFunc;
- unit->AbortIO = abortFunc;
- unit->CloseFunc = closeFunc;
- unit->DataFunc = dataFunc;
-
- unit->Port = iob->io_Port;
- unit->Protocol = iob->io_Flags & PRO_MASK;
- unit->DestAddr = iob->io_Addr;
-
- NewList(&unit->PendIOR);
- NewList(&unit->PendIOW);
- NewList(&unit->PendCon);
- NewList(&unit->PendLsn);
-
- AddHead(&db->UnitList, (struct Node *)unit);
-
- return(unit);
- }
-
- void
- FreeUnit(unit)
- Unit *unit;
- {
- Remove(&unit->Node);
- FreeMem(unit, sizeof(Unit));
- UnitCache = NULL;
- }
-
- /*
- * Packets
- */
-
- Packet *
- AllocParPacket(iob, unit, data1, bytes1, data2, bytes2)
- Iob *iob;
- Unit *unit;
- ubyte *data1;
- ubyte *data2;
- long bytes1;
- long bytes2;
- {
- Packet *packet = AllocMem(sizeof(Packet), MEMF_CLEAR|MEMF_PUBLIC);
-
- packet->iob = iob;
- packet->io_Unit = unit;
- if (iob)
- packet->DestAddr = iob->io_Addr;
- packet->DestPort = unit->Port;
- packet->Data1 = data1;
- packet->Data2 = data2;
- packet->DLen1 = bytes1;
- packet->DLen2 = bytes2;
-
- return(packet);
- }
-
- void
- FreeParPacket(packet)
- Packet *packet;
- {
- FreeMem(packet, sizeof(Packet));
- }
-
- /*
- * CONFIG
- */
-
- void
- ReadConfig(void)
- {
- PubPort *port;
-
- if ((port = StickyPort) == NULL)
- port = (PubPort *)FindPort(PORTNAME);
-
- if (port) {
- DevBase->ParAddress = port->Address;
- ParAddress(DevBase->ParAddress);
- /*ParLLTimeout = port->Timeout;*/
- }
- StickyPort = port;
- }
-
- void
- WriteConfig(void)
- {
- char *portName = PORTNAME;
- PubPort *port;
-
- if ((port = StickyPort) == NULL && (port = (PubPort *)FindPort(portName)) == NULL) {
- port = AllocMem(sizeof(PubPort) + strlen(portName) + 1, MEMF_PUBLIC | MEMF_CLEAR);
- port->Port.mp_Node.ln_Name = (char *)(port + 1);
-
- strcpy(port->Port.mp_Node.ln_Name, portName);
- port->Port.mp_Node.ln_Type = NT_MSGPORT;
- port->Port.mp_Node.ln_Pri = 0;
- NewList(&port->Port.mp_MsgList);
- AddPort((PORT *)port);
- }
- port->Address = DevBase->ParAddress;
- port->Timeout = ParLLTimeout;
- StickyPort = port;
- }
-
- /*
- * Determines the processor speed for soft wired timeouts in PAR.ASM
- * by timing 1 second.
- */
- int
- DetermineTimeouts(void)
- {
- IOT iot;
- long cnt = 0;
- PORT *port = CreatePort(NULL, 0);
-
- if (OpenDevice(TIMERNAME, UNIT_VBLANK, &iot, 0))
- return(-1);
- iot.tr_node.io_Command = TR_ADDREQUEST;
- iot.tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
- iot.tr_node.io_Message.mn_ReplyPort = port;
- iot.tr_time.tv_secs = 1;
- iot.tr_time.tv_micro= 0;
- SendIO(&iot);
- while (CheckIO(&iot) == NULL) {
- Time10000();
- cnt += 10000;
- }
- WaitIO(&iot);
- ParLLTimeout = cnt;
- CloseDevice(&iot);
- DeletePort(port);
- return(0);
- }
-
-
-