home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Misc / Vector18.lha / ParNetExample / parnet.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-18  |  9.0 KB  |  448 lines

  1. /*
  2.  * $Header: DH0:SRC/asm/parallel/parnet/RCS/parnet.c,v 1.4 1993/03/25 01:40:35 barnard Exp $
  3.  *
  4.  */
  5.  
  6. /*
  7.  * This code was originally written by Matthew Dillon and put into Public Domain
  8.  *
  9.  * All changes concerning the adaption of Matt's original code to the
  10.  * Vector Connection I/O board are © 1991-1993 by Henning Schmiedehausen
  11.  * All rights for this changes are reserved. The original code is Public Domain
  12.  *
  13.  * This code is distributed with the expressed written permission of Matthew
  14.  * Dillon (Thank you very much, Matt)
  15.  *
  16.  */
  17.  
  18. /*
  19.  *  PARNET.C
  20.  *
  21.  */
  22.  
  23. #include "defs.h"
  24. #include "parnet.device.h"
  25. #include <resources/misc.h>
  26. #include <hardware/cia.h>
  27. #include <exec/memory.h>
  28.  
  29. #include <devices/parallel.h>
  30. #include "devices/pio.h"
  31.  
  32. #define PORTA
  33. /* #define PORTB */
  34.  
  35. extern func_ptr DeviceVectors[];
  36. extern func_ptr UnitVectors[];
  37. extern char DeviceName[];
  38. extern char IdString[];
  39.  
  40. extern void PioInt();
  41.  
  42. extern Task *VTask;        /*  wakeup.asm    */
  43. extern long VMask;        /*  wakeup.asm    */
  44.  
  45. extern void ParNetTask();       /*  task.c      */
  46.  
  47. long    SysBase    = NULL;    /*  sysbase            */
  48. Device    *DevBase   = NULL;    /*  device base         */
  49. BPTR    DevSegment = NULL;    /*  seglist for device        */
  50. long    PLock[2]   = { 0, 0 };    /*  arbitrate network access    */
  51. PubPort *StickyPort= NULL;
  52.  
  53. char    ActiveMRPP = 0;
  54. char    ActiveMRPB = 0;
  55. char    ActiveTask = 0;
  56. char    ActiveInt  = 0;
  57.  
  58. struct Interrupt  PIOInt =
  59. {
  60.     {
  61.     NULL, NULL,
  62.     NT_INTERRUPT,
  63.     20,                        /* *WICHTIG* NICHT ÄNDERN! SO SITZT DER INTERRUPT *VOR* DEM DEVICE */
  64.     "parnet.device"
  65.     },
  66. NULL,
  67. PioInt
  68. };
  69.  
  70. struct MsgPort        *ParPort;
  71. struct IOExtPar        *ParRequest;
  72. ULONG                 UnitBase;
  73. ULONG                 PIOBase;
  74.  
  75. char                *version = VERSTAG;
  76.  
  77.  
  78.  
  79. /*
  80.  *  Init is called when the device is loaded to create it.
  81.  */
  82.  
  83. APTR
  84. CDevInit(seg)
  85. BPTR seg;
  86. {
  87.     Device *db;
  88.  
  89.     SysBase = *(long *)4;
  90.  
  91.     DevBase = db = (Device *)MakeLibrary((long **)DeviceVectors,NULL,NULL,sizeof(Device),NULL);
  92.     db->Lib.lib_Node.ln_Type = NT_DEVICE;
  93.     db->Lib.lib_Node.ln_Name = DeviceName;
  94.     db->Lib.lib_Flags = LIBF_CHANGED|LIBF_SUMUSED;
  95.     db->Lib.lib_Version = VERSION;
  96.     db->Lib.lib_Revision = REVISION;
  97.     db->Lib.lib_IdString= (APTR)IdString;
  98.     db->ParAddress = 254;            /*    default address     */
  99.     db->Port.mp_Node.ln_Type = NT_MSGPORT;
  100.     db->Port.mp_SigBit = SIGBREAKB_CTRL_E;  /*    for VTask        */
  101.     db->Port.mp_Flags  = PA_SIGNAL;
  102.     NewList(&db->UnitList);
  103.     NewList(&db->Port.mp_MsgList);
  104.  
  105.     ReadConfig();
  106.     WriteConfig();
  107.  
  108.     DevSegment = seg;
  109.     AddDevice((struct Device *)db);
  110.     return((APTR)db);
  111. }
  112.  
  113. Device *
  114. CDevOpen(unitnum, flags, iob)
  115. long unitnum;
  116. long flags;
  117. Iob *iob;
  118. {
  119. #ifdef PORTA
  120.     int piounit = 0;
  121. #endif
  122. #ifdef PORTB
  123.     int piounit = 1;
  124. #endif
  125.  
  126.     Device *nd = DevBase;
  127.  
  128.     iob->io_Unit = NULL;
  129.  
  130.     LockAddr(PLock);        /*  because we make calls that kill Forbid()    */
  131.  
  132.     nd->Lib.lib_Flags &= ~LIBF_DELEXP;
  133.  
  134.     if (++nd->Lib.lib_OpenCnt == 1) {
  135.     /*
  136.      *  Initial Open, allocate resources
  137.      */
  138.  
  139.     if(!(ParPort = (struct MsgPort *)CreatePort("PIONet-Port",NULL)))
  140.     {
  141.         goto badop;
  142.     }
  143.     if(!(ParRequest = (struct IOExtPar *)CreateExtIO(ParPort, sizeof(struct IOExtPar))))
  144.     {
  145.         goto badop;
  146.     }
  147.  
  148.     if(OpenDevice("pio.device", piounit, ParRequest, NULL))
  149.     {
  150.         goto badop;
  151.     }
  152.  
  153.     ParRequest->IOPar.io_Command = PIOCMD_INACTIVE;            /* Unit abklemmen */
  154.     DoIO(ParRequest);
  155.     UnitBase = (ULONG)ParRequest->IOPar.io_Actual;
  156.     PIOBase  = (ULONG)ParRequest->IOPar.io_Length;
  157.  
  158.     VTask = (struct Task *)CreateTask("parnet.device", 0, (APTR)ParNetTask, 4096);
  159.     if (VTask == NULL) {
  160.         iob->io_Actual = PPERR_NOTASK;
  161.         goto badop;
  162.     }
  163.     ActiveTask = 1;
  164.     VMask = SIGBREAKF_CTRL_F;
  165.     nd->Port.mp_SigTask = VTask;    /*  for asynchronous I/O    */
  166.  
  167.     ClearPIOInt();            /* ev. pending PIO Interrupts löschen */
  168.  
  169.     AddIntServer(INTB_PORTS, &PIOInt);
  170.  
  171.     SetUpPIO();
  172.  
  173.     ActiveInt = 1;
  174.  
  175.     if (DetermineTimeouts() < 0)    /*  couldn't use timer.device   */
  176.         goto badop;
  177.  
  178.     }
  179.     iob->io_Actual= 0;
  180.     iob->io_Error = 0;
  181.  
  182.     /*
  183.      *    Attempt to open the specified unit by protocol
  184.      */
  185.  
  186.     {
  187.     short proto = iob->io_Flags & PRO_MASK;
  188.  
  189.     if (proto <= PRO_LAST) {
  190.         (*UnitVectors[proto])(iob, unitnum, flags);
  191.         if (iob->io_Error == 0) {
  192.         UnlockAddr(PLock);
  193.         return(nd);
  194.         }
  195.     }
  196.     }
  197.  
  198.     /*
  199.      *    OPEN FAILED
  200.      */
  201.  
  202. badop:
  203.     CDevClose(iob);
  204.     iob->io_Actual = iob->io_Error;
  205.     iob->io_Error  = IOERR_OPENFAIL;
  206.     UnlockAddr(PLock);
  207.     return(NULL);
  208. }
  209.  
  210. CDevExpunge()
  211. {
  212.     Device *nd = DevBase;
  213.     BPTR ds = DevSegment;
  214.  
  215.     if (ds == NULL)
  216.     Alert(24, (char *)24);
  217.  
  218.     if (nd->Lib.lib_OpenCnt) {              /*  delayed expunge */
  219.     nd->Lib.lib_Flags |= LIBF_DELEXP;
  220.     return(NULL);
  221.     }
  222.     Remove((NODE *)nd);
  223.     FreeMem((char *)nd - nd->Lib.lib_NegSize, nd->Lib.lib_NegSize + nd->Lib.lib_PosSize);
  224.     DevSegment = NULL;
  225.     return(ds);
  226. }
  227.  
  228. BPTR
  229. CDevClose(iob)
  230. Iob *iob;
  231. {
  232.     Device *nd = DevBase;
  233.  
  234.     if (iob->io_Unit)
  235.     (*iob->io_Unit->CloseFunc)(iob);
  236.  
  237.     iob->io_Unit   = NULL;            /*  clear vectors    */
  238.     iob->io_Device = NULL;
  239.  
  240.     if (nd->Lib.lib_OpenCnt == 1)   {           /*  last close          */
  241.     if (ActiveInt)
  242.  
  243.     {
  244.     ClearPIOInt();
  245.  
  246.     RemIntServer(INTB_PORTS, &PIOInt);
  247.  
  248.     }
  249.     if (ActiveTask)
  250.         RemTask(VTask);
  251.  
  252.     ParRequest->IOPar.io_Command = PIOCMD_ACTIVE;        /* Port wieder fürs Device */
  253.     DoIO(ParRequest);
  254.  
  255.     CloseDevice(ParRequest);
  256.     DeleteExtIO(ParRequest);
  257.     DeletePort(ParPort);
  258.  
  259.     ActiveInt = 0;
  260.     ActiveTask= 0;
  261.     ActiveMRPB= 0;
  262.     ActiveMRPP= 0;
  263.     }
  264.     if (nd->Lib.lib_OpenCnt && --nd->Lib.lib_OpenCnt)
  265.     return(NULL);                           /*  still has refs      */
  266.  
  267.     /*
  268.      *    Note: LIBF_DELEXP never set if DevClose() called from DevOpen()
  269.      */
  270.  
  271.     if (nd->Lib.lib_Flags & LIBF_DELEXP)
  272.     return(CDevExpunge());                  /*  expunge             */
  273.     return(NULL);                               /*  no expunge          */
  274. }
  275.  
  276. /*
  277.  *  UNITS
  278.  */
  279.  
  280. Unit *UnitCache = NULL;
  281.  
  282. Unit *
  283. FindUnitForPort(port)
  284. uword port;
  285. {
  286.     Unit *unit;
  287.     Device *db;
  288.  
  289.     if (UnitCache && port == UnitCache->Port)
  290.     return(UnitCache);
  291.  
  292.     db = DevBase;
  293.     for (unit = (Unit *)db->UnitList.lh_Head; unit != (Unit *)&db->UnitList.lh_Tail; unit = (Unit *)unit->Node.ln_Succ) {
  294.     if (port == unit->Port) {
  295.         UnitCache = unit;
  296.         return(unit);
  297.     }
  298.     }
  299.     return(NULL);
  300. }
  301.  
  302. Unit *
  303. AllocUnit(iob, beginFunc, abortFunc, dataFunc, closeFunc)
  304. Iob *iob;
  305. func_void beginFunc;
  306. func_void abortFunc;
  307. func_void dataFunc;
  308. func_void closeFunc;
  309. {
  310.     Unit *unit = (Unit *)AllocMem(sizeof(Unit), MEMF_CLEAR | MEMF_PUBLIC);
  311.     Device *db = DevBase;
  312.  
  313.     unit->BeginIO = beginFunc;
  314.     unit->AbortIO = abortFunc;
  315.     unit->CloseFunc = closeFunc;
  316.     unit->DataFunc = dataFunc;
  317.  
  318.     unit->Port = iob->io_Port;
  319.     unit->Protocol = iob->io_Flags & PRO_MASK;
  320.     unit->DestAddr = iob->io_Addr;
  321.  
  322.     NewList(&unit->PendIOR);
  323.     NewList(&unit->PendIOW);
  324.     NewList(&unit->PendCon);
  325.     NewList(&unit->PendLsn);
  326.  
  327.     AddHead(&db->UnitList, (struct Node *)unit);
  328.  
  329.     return(unit);
  330. }
  331.  
  332. void
  333. FreeUnit(unit)
  334. Unit *unit;
  335. {
  336.     Remove(&unit->Node);
  337.     FreeMem(unit, sizeof(Unit));
  338.     UnitCache = NULL;
  339. }
  340.  
  341. /*
  342.  *  Packets
  343.  */
  344.  
  345. Packet *
  346. AllocParPacket(iob, unit, data1, bytes1, data2, bytes2)
  347. Iob *iob;
  348. Unit *unit;
  349. ubyte *data1;
  350. ubyte *data2;
  351. long bytes1;
  352. long bytes2;
  353. {
  354.     Packet *packet = (Packet *)AllocMem(sizeof(Packet), MEMF_CLEAR|MEMF_PUBLIC);
  355.  
  356.     packet->iob = iob;
  357.     packet->io_Unit = unit;
  358.     if (iob)
  359.     packet->DestAddr = iob->io_Addr;
  360.     packet->DestPort = unit->Port;
  361.     packet->Data1 = data1;
  362.     packet->Data2 = data2;
  363.     packet->DLen1 = bytes1;
  364.     packet->DLen2 = bytes2;
  365.  
  366.     return(packet);
  367. }
  368.  
  369. void
  370. FreeParPacket(packet)
  371. Packet *packet;
  372. {
  373.     FreeMem(packet, sizeof(Packet));
  374. }
  375.  
  376. /*
  377.  *                CONFIG
  378.  */
  379.  
  380. void
  381. ReadConfig()
  382. {
  383.     PubPort *port;
  384.  
  385.     if ((port = StickyPort) == NULL)
  386.     port = (PubPort *)FindPort(PORTNAME);
  387.  
  388.     if (port) {
  389.     DevBase->ParAddress = port->Address;
  390.     ParAddress(DevBase->ParAddress);
  391.     /*ParLLTimeout = port->Timeout;*/
  392.     }
  393.     StickyPort = port;
  394. }
  395.  
  396. void
  397. WriteConfig()
  398. {
  399.     char *portName = PORTNAME;
  400.     PubPort *port;
  401.  
  402.     if ((port = StickyPort) == NULL && (port = (PubPort *)FindPort(portName)) == NULL) {
  403.     port = (PubPort *)AllocMem(sizeof(PubPort) + strlen(portName) + 1, MEMF_PUBLIC | MEMF_CLEAR);
  404.     port->Port.mp_Node.ln_Name = (char *)(port + 1);
  405.  
  406.     strcpy(port->Port.mp_Node.ln_Name, portName);
  407.     port->Port.mp_Node.ln_Type = NT_MSGPORT;
  408.     port->Port.mp_Node.ln_Pri  = 0;
  409.     NewList(&port->Port.mp_MsgList);
  410.     AddPort((PORT *)port);
  411.     }
  412.     port->Address = DevBase->ParAddress;
  413.     port->Timeout = ParLLTimeout;
  414.     StickyPort = port;
  415. }
  416.  
  417. /*
  418.  *  Determines the processor speed for soft wired timeouts in PAR.ASM
  419.  *  by timing 1 second.
  420.  */
  421.  
  422. DetermineTimeouts()
  423. {
  424.     IOT iot;
  425.     long cnt = 0;
  426.     PORT *port = (PORT *)CreatePort(NULL, 0);
  427.  
  428.     if (OpenDevice(TIMERNAME, UNIT_VBLANK, &iot, 0))
  429.     return(-1);
  430.     iot.tr_node.io_Command = TR_ADDREQUEST;
  431.     iot.tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  432.     iot.tr_node.io_Message.mn_ReplyPort = port;
  433.     iot.tr_time.tv_secs = 1;
  434.     iot.tr_time.tv_micro= 0;
  435.     SendIO(&iot);
  436.     while (CheckIO(&iot) == NULL) {
  437.     Time10000();
  438.     cnt += 10000;
  439.     }
  440.     WaitIO(&iot);
  441.     ParLLTimeout = cnt;
  442.     CloseDevice(&iot);
  443.     DeletePort(port);
  444.     return(0);
  445. }
  446.  
  447.  
  448.