home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / DevCon / Washington_1988 / DevCon88.1 / DosHandlers / port-handler.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  9.0 KB  |  356 lines

  1. /* This is a C version of the Port Handler
  2.  *     Andy Finkel
  3.  * Copyright (c) 1988 Commodore-Amiga, Inc.
  4.  *
  5.  * Executables based on this information may be used in software
  6.  * for Commodore Amiga computers.  All other rights reserved.
  7.  *
  8.  * This information is provided "as is"; no warranties are made.
  9.  * All use is at your own risk, and no liability or
  10.  * responsibility is assumed.
  11.  *
  12.  * This version is Mounted, rather than automatically called, since
  13.  * DOS.Library seems to call the Port-handler assuming it is a
  14.  * BCPL program, for some reason.
  15.  *
  16.  * The mountlist entries for this handler are as follows:
  17.  * cser:    Handler= L:CPort-Handler
  18.  *        Priority=5
  19.  *        StackSize=2000
  20.  *        GlobVec = -1
  21.  *#
  22.  * cpar:    Handler= L:CPort-Handler
  23.  *        Priority=5
  24.  *        StackSize=2000
  25.  *        GlobVec = -1
  26.  *#
  27.  * cprt:    Handler= L:CPort-Handler
  28.  *        Priority=5
  29.  *        StackSize=2000
  30.  *        GlobVec = -1
  31.  *#
  32.  */
  33.  
  34. #include "exec/types.h"
  35. #include "exec/nodes.h"
  36. #include "exec/lists.h"
  37. #include "exec/ports.h"
  38. #include "exec/libraries.h"
  39. #include "exec/devices.h"
  40. #include "exec/io.h"
  41. #include "exec/memory.h"
  42. #include "libraries/dos.h"
  43. #include "libraries/dosextens.h"
  44. #include "libraries/filehandler.h"
  45. #include "devices/serial.h"
  46. #include "devices/parallel.h"
  47. #include "devices/printer.h"
  48.  
  49. union pio {
  50.     struct IOStdReq ios;
  51.     struct IODRPReq iodrp;
  52.     struct IOPrtCmdReq iopc;
  53.     struct IOExtSer ioser;
  54.     struct IOExtPar iopar;
  55. };
  56.  
  57.  
  58. #define DOS_TRUE        -1
  59. #define IOSIZE    sizeof(union pio)
  60.  
  61. #define QTOUPPER(c)      ((c)>='a'&&(c)<='z'?(c)-'a'+'A':(c))
  62.  
  63. /* internal packets */
  64. #define action_read             1001
  65. #define action_write            1002
  66.  
  67. #define ACTION_FIND_INPUT       1005
  68. #define ACTION_FIND_OUTPUT      1006
  69. #define ACTION_END              1007
  70.  
  71. #undef  BADDR
  72. #define BADDR(x)        ((CPTR)((LONG)x << 2))
  73.  
  74. extern struct DosPacket *taskwait();
  75. extern VOID setIO();
  76. extern VOID sendIO();
  77. extern VOID returnpkt();
  78.  
  79. extern struct ExecBase *AbsExecBase;
  80. struct ExecBase *SysBase;
  81. struct DOSLibrary *DOSBase;
  82.  
  83. main()
  84. {
  85.  
  86.     ULONG i;
  87.     UBYTE *openstring;
  88.     UBYTE *devname;
  89.     BOOL error;
  90.     BOOL printer=FALSE;
  91.     BOOL OpenForInput  = FALSE, OpenForOutput = FALSE;
  92.  
  93.     struct DeviceNode       *node;  /* our device node is passed in parm pkt Arg3 */
  94.  
  95.     struct DosPacket        *packet;
  96.     struct FileHandle        *scb;
  97.  
  98.     struct DosPacket     inp;
  99.     struct DosPacket     *inpkt;
  100.     struct DosPacket      out;
  101.     struct DosPacket      *outpkt;
  102.  
  103.     struct DosPacket    *readPkt;
  104.     struct DosPacket    *writePkt;
  105.  
  106.     struct   IOStdReq    *iob;
  107.     struct   IOStdReq    *iobo;
  108.  
  109.     struct   MsgPort *devport;
  110.     struct Process *process;
  111.     
  112.     SysBase = AbsExecBase;
  113.  
  114.     process=(struct Process *) FindTask(NULL);
  115.     devport = &process->pr_MsgPort;
  116.     inpkt = &inp;
  117.     outpkt = &out;
  118.  
  119.     packet = taskwait();    /* wait for parm. packet */
  120.  
  121.     /* openstring tells which we are supposed to be...prt, par, or ser */
  122.     openstring = (UBYTE *)BADDR(packet->dp_Arg1);
  123.     node = (struct DeviceNode *) BADDR(packet->dp_Arg3);
  124.  
  125.     /* we need DOS.library to unload ourselves later */
  126.     DOSBase = (struct DosLibrary *) OpenLibrary("dos.library",0);
  127.  
  128.     if(!strcmpi(openstring,"cprt:")) {
  129.     printer = DOS_TRUE;
  130.     devname = "printer.device";
  131.     }
  132.     else if (!strcmpi(openstring,"cpar:"))devname = "parallel.device";
  133.     else devname = "serial.device";
  134.  
  135.     /* set up the input IOR and the output IOR */
  136.     iob=(struct IOStdReq *)CreateExtIO(devport,(LONG)IOSIZE);
  137.     iobo=(struct IOStdReq *)CreateExtIO(devport,(LONG)IOSIZE);
  138.     if(!iob || !iobo) goto exit;
  139.  
  140.     /* open the device */
  141.     if(error=OpenDevice(devname,0,iob, 0)) {
  142.         returnpkt(packet,FALSE,ERROR_OBJECT_IN_USE);
  143.     goto exit;
  144.     }
  145.     *iobo = *iob; /* copy input req to output req */
  146.  
  147. /*     Turn CR conversion off if raw mode is selected for printer */
  148.     if (printer) {     /* must be cprt: or cprt:raw */
  149.        if(strlen(openstring) > 5) {
  150.       setIO(iobo,CMD_WRITE,"\033[20l",5);
  151.       DoIO(iobo);
  152.        }
  153.     }
  154.  
  155.    /* patch outselves into the system */
  156.  
  157.     outpkt->dp_Type = action_write;
  158.     inpkt->dp_Type  = action_read;
  159.     node->dn_Task = devport;
  160.  
  161. /*    Finished with parameter packet...send back...*/
  162.     returnpkt(packet,DOS_TRUE,packet->dp_Res2);
  163.  
  164. /*    Main Event Loop */
  165.     do { 
  166.         packet = taskwait();
  167.     switch (packet->dp_Type) {
  168.  
  169.             case ACTION_FIND_INPUT:
  170.         scb = (struct FileHandle *) BADDR(packet->dp_Arg1);
  171.                 if (OpenForInput) {
  172.                 returnpkt(packet,FALSE,ERROR_OBJECT_IN_USE);
  173.                 continue;
  174.             }
  175.             OpenForInput = DOS_TRUE;
  176.                /* now mark as interactive */
  177.                 scb->fh_Port   = (struct MsgPort *)DOS_TRUE;
  178.             scb->fh_Arg1 = ACTION_FIND_INPUT;
  179.                 returnpkt(packet,DOS_TRUE,0);
  180.                 continue;
  181.  
  182.               case ACTION_FIND_OUTPUT:
  183.               scb = (struct FileHandle *) BADDR(packet->dp_Arg1);
  184.          if(OpenForOutput) {
  185.              returnpkt(packet,FALSE,ERROR_OBJECT_IN_USE);
  186.                 continue;
  187.         }
  188.         OpenForOutput = DOS_TRUE;
  189.         /* set interactive flag */
  190.              scb->fh_Port = (struct MsgPort *)DOS_TRUE;
  191.          scb->fh_Arg1 = ACTION_FIND_OUTPUT;
  192.              returnpkt(packet,DOS_TRUE,0);
  193.              continue;
  194.  
  195.         case ACTION_END:          /* Close request */
  196.          if (packet->dp_Arg1 == ACTION_FIND_INPUT) OpenForInput  = FALSE;
  197.            else OpenForOutput = FALSE;
  198.          if(!OpenForInput && !OpenForOutput)node->dn_Task = 0;
  199.              returnpkt(packet,DOS_TRUE,0);
  200.         continue;
  201.  
  202.             case action_read:             /* Read request returning */
  203.              inpkt = packet;
  204.              handleReturn(iob,readPkt);
  205.         continue;
  206.  
  207.             case action_write:            /* Write request returning */
  208.                  outpkt = packet;
  209.                 handleReturn(iobo,writePkt);
  210.         continue;
  211.  
  212.             case 'R':                /* Read Request */
  213.              readPkt = packet;
  214.                  handleRequest(iob,CMD_READ,packet,inpkt);
  215.             inpkt = 0;
  216.         continue;
  217.  
  218.             case 'W':                /* Write Request */
  219.              writePkt = packet;
  220.              handleRequest(iobo,CMD_WRITE,packet,outpkt);
  221.             outpkt = 0;
  222.         continue;
  223.  
  224.               default:
  225.          if(!OpenForInput && !OpenForOutput) node->dn_Task = 0;
  226.              returnpkt(packet,FALSE,ERROR_ACTION_NOT_KNOWN);
  227.     }
  228.     } while (OpenForInput || OpenForOutput || (outpkt==0) || (inpkt==0));
  229.  
  230. exit:
  231.     if(!error)CloseDevice(iob);
  232.     if(iob)DeleteExtIO(iob,(ULONG)IOSIZE);
  233.     if(iobo)DeleteExtIO(iobo,(ULONG)IOSIZE);
  234.  
  235. /* This looks funny, but works because DOS is not part of the code being unloaded */
  236.     Forbid();
  237.     UnLoadSeg(node->dn_SegList);
  238.     CloseLibrary(DOSBase);
  239.     node->dn_SegList=0;
  240. }
  241.  
  242. /* Handle an IO request. Passed command, transmission packet (tp)
  243.    and request packet (rp). rp contains buffer and length in arg2/3. */
  244.  
  245. handleRequest(iob, command, rp, tp )
  246. struct IOStdReq  *iob;
  247. ULONG command;
  248. struct DosPacket *rp;
  249. struct DosPacket *tp;
  250. {
  251.    UBYTE  *buff = (UBYTE *)rp->dp_Arg2;
  252.    int len  = (int)rp->dp_Arg3;
  253.  
  254.    setIO( iob, command, 0, rp->dp_Arg3, 0 );
  255.    iob->io_Data = buff;
  256.    sendIO( iob, tp );
  257. }
  258.  
  259. /* Handle a returning IO request. The user request packet is
  260.    passed as packet, and must be returned with success/failure message. */
  261.  
  262. handleReturn(iob, packet )
  263. struct IOStdReq  *iob;
  264. struct DosPacket *packet;
  265. {
  266. int errcode = iob->io_Error;
  267. int len=iob->io_Actual;
  268.  
  269.    if( errcode==0) returnpkt(packet, len ,0);
  270.    else returnpkt(packet, -1, errcode );
  271. }
  272.  
  273. /* Initialize IO request block */
  274.  
  275. VOID setIO(iob,cmd,data,len)
  276. struct IOStdReq *iob;
  277. UWORD           cmd;
  278. APTR            data;
  279. ULONG           len;
  280. {
  281.     iob->io_Command = cmd;
  282.     iob->io_Data    = data;
  283.     iob->io_Length  = len;
  284. }
  285.  
  286. VOID sendIO(iob,packet)
  287. struct IOStdReq  *iob;
  288. struct DosPacket *packet;
  289. {
  290.      iob->io_Message.mn_Node.ln_Name = (char *) packet;
  291.      packet->dp_Link = (struct Message *) iob;
  292.      SendIO(iob);
  293. }
  294.  
  295. VOID returnpkt(packet,res1,res2)
  296. struct DosPacket *packet;
  297. ULONG  res1,res2;
  298. {
  299.  struct Message *message;
  300.  struct MsgPort *replyport;
  301.  struct Process *process;
  302.  
  303.  packet->dp_Res1          = res1;
  304.  packet->dp_Res2          = res2; 
  305.  replyport                = packet->dp_Port;
  306.  message                  = packet->dp_Link;
  307.  process                  = (struct Process *) FindTask(NULL);
  308.  packet->dp_Port          = &process->pr_MsgPort;
  309.  message->mn_Node.ln_Name    = (char *) packet;
  310.  message->mn_Node.ln_Succ    = NULL;
  311.  message->mn_Node.ln_Pred    = NULL;
  312.  
  313.  PutMsg(replyport,message); 
  314. }
  315.  
  316.  /* taskwait()  waits for a message to arrive at the port and 
  317.     returns the packet address  */
  318.  
  319. struct DosPacket *taskwait()
  320. {
  321.  struct Process *process;
  322.  struct MsgPort *port;
  323.  struct Message *message;
  324.  
  325.  process = (struct Process *) FindTask(0L);
  326.  port = &process->pr_MsgPort;
  327.  
  328.  /* wait for packet */
  329.  SetSignal(FALSE,1<<8);    /* clear sigbit 8 */
  330.  while( !(message = (struct Message *) GetMsg(port)) )  Wait(1<<8);
  331.  
  332. /* return the pointer to the packet */
  333. return((struct DosPacket *) message->mn_Node.ln_Name);
  334. }
  335.  
  336. strlen( s )
  337. UBYTE *s;
  338. {
  339.     int i = 0;
  340.     while( *s++ ) i++;
  341.     return( i );
  342. }
  343.  
  344. strcmpi(str1, str2)
  345. char *str1,*str2;
  346. {
  347.     UBYTE *astr =str1;
  348.     UBYTE *bstr =str2;
  349.     UBYTE c;
  350.  
  351.     while ( (c = QTOUPPER(*astr)) && (c == QTOUPPER(*bstr))) astr++, bstr++;
  352.     if( ! c ) return ( 0 );
  353.     if( c < *bstr ) return( -1 );
  354.     return( 1 );
  355. }
  356.