home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 508.lha / IO_Expansion_Board / Handler / ioexp-handler.asm < prev    next >
Assembly Source File  |  1991-05-06  |  12KB  |  535 lines

  1. *****************************************************************************
  2. *  Program: ioexp-handler.asm
  3. *  Descrip: Port handler for the newser.device and eightbit.device
  4. *           for use with the I/O Expansion Board.
  5. *    Usage: Place the executable PortHandler in your L: directory
  6. *           and create the following MountList entries:
  7. *
  8. *           A sample MountList entries for this handler follows:
  9. *
  10. *           SER1: Handler   = L:ioexp-handler
  11. *                 StackSize = 2000
  12. *                 Priority  = 5
  13. *                 GlobVec   = -1
  14. *           #
  15. *
  16. *  History:     1988 AF V1.00 Written in C ©1988 Commodore-Amiga, Inc.
  17. *           12/22/90 JL V1.01 Translated into assembly.
  18. *           01/09/91 JL V1.02 Added exit code for more cases.
  19. *****************************************************************************
  20.  
  21. ;Set Tabs           |       |                 |       |
  22.  
  23.     ifnd    __m68
  24.     fail    'Wrong assembler!'
  25.     endc
  26.     exeobj
  27.     macfile    'Includes:IOexp.i' ;The One & Only include file
  28.     objfile    'ram:ioexp-handler'
  29.  
  30. DOS_FALSE    equ    0
  31. DOS_TRUE    equ    -1
  32.  
  33. OpenForInput    equr    d5    ;Flag for ?
  34. OpenForOutput    equr    d6    ;Flag for ?
  35. Error    equr    d7    ;Flag for OpenDevice()
  36.  
  37. INFO_LEVEL    equ    0    ;Assembly-time option
  38.  
  39. *** Begin mainline
  40.  
  41. MainStack    clrfo
  42. openstring    fo.l    1    ;Ptr to logical device name
  43. node    fo.l    1    ;Our device node
  44. inp    fo.b    dp_SIZEOF    ;DosPacket
  45. inpkt    fo.l    1    ;DosPacket
  46. out    fo.b    dp_SIZEOF    ;DosPacket
  47. outpkt    fo.l    1    ;DosPacket
  48. readPkt    fo.l    1    ;DosPacket
  49. writePkt    fo.l    1    ;DosPacket
  50. iob    fo.l    1    ;IOStdReq
  51. iobo    fo.l    1    ;IOStdReq
  52. devport    fo.l    1    ;Process MsgPort
  53. MS_SIZE    foval
  54.  
  55. IOExpHandler    link.w    a5,#MS_SIZE
  56.     movem.l    d2-d7/a2-a3/a6,-(sp)
  57.     moveq    #0,OpenForInput
  58.     moveq    #0,OpenForOutput
  59.     moveq    #0,Error
  60.  
  61.     clr.l    (readPkt,a5)
  62.     clr.l    (writePkt,a5)
  63.     clr.l    (iob,a5)
  64.  
  65.     PUTDEBUG 5,<'handler started'>
  66.  
  67.     movea.l    (SysBase).w,a6
  68.     movea.l    (ThisTask,a6),a0
  69.     lea    (pr_MsgPort,a0),a0
  70.     move.l    a0,(devport,a5)    ;Save ptr to our proc MsgPort
  71.  
  72.     lea    (inp,a5),a0
  73.     move.l    a0,(inpkt,a5)
  74.     lea    (out,a5),a0
  75.     move.l    a0,(outpkt,a5)
  76.  
  77.     bsr.w    WaitMsg    ;Wait for parm packet
  78.  
  79.     PUTDEBUG 5,<'Recvd parm packet'>
  80.  
  81. * Openstring tells which we are supposed to be...PAR1, SER2, etc.
  82.  
  83.     movea.l    d0,a3
  84.     move.l    (dp_Arg1,a3),d0
  85.     lsl.l    #2,d0
  86.     addq.l    #1,d0    ;Skip length byte
  87.     move.l    d0,(openstring,a5)
  88.  
  89.     ifne    INFO_LEVEL
  90.     move.l    d0,-(sp)
  91.     PUTDEBUG 5,<'openstring = "%s"'>
  92.     addq.w    #4,sp
  93.     endc
  94.  
  95.     move.l    (dp_Arg3,a3),d0
  96.     lsl.l    #2,d0
  97.     move.l    d0,(node,a5)    ;Save ptr to our DeviceNode
  98.  
  99.     movea.l    (openstring,a5),a0
  100.     lea    (NewSerName,pc),a2
  101.     moveq    #0,d2
  102.     moveq    #IOEXTSER_SIZE,d3
  103.     lea    (SER1name,pc),a1
  104.     bsr.w    strUcmp
  105.     beq.w    FoundName
  106.  
  107.     moveq    #1,d2
  108.     lea    (SER2name,pc),a1
  109.     bsr.w    strUcmp
  110.     beq.w    FoundName
  111.  
  112.     moveq    #2,d2
  113.     lea    (SER3name,pc),a1
  114.     bsr.w    strUcmp
  115.     beq.w    FoundName
  116.  
  117.     moveq    #3,d2
  118.     lea    (SER4name,pc),a1
  119.     bsr.w    strUcmp
  120.     beq.b    FoundName
  121.  
  122.     lea    (EightBitName,pc),a2
  123.     moveq    #0,d2
  124.     moveq    #IOEXTPar_SIZE,d3
  125.     lea    (PAR1name,pc),a1
  126.     bsr.w    strUcmp
  127.     beq.b    FoundName
  128.  
  129.     moveq    #1,d2
  130.     lea    (PAR2name,pc),a1
  131.     bsr.w    strUcmp
  132.     beq.b    FoundName
  133.  
  134.     moveq    #2,d2
  135.     lea    (PAR3name,pc),a1
  136.     bsr.w    strUcmp
  137.     beq.b    FoundName
  138.  
  139.     moveq    #3,d2
  140.     lea    (PAR4name,pc),a1
  141.     bsr.w    strUcmp
  142.     beq.b    FoundName
  143.  
  144.     PUTDEBUG 100,<'strUcmp() failed'>
  145.  
  146.     movea.l    a3,a0    ;Not a name we know
  147.     moveq    #DOS_FALSE,d0
  148.     moveq    #(ERROR_ACTION_NOT_KNOWN/2),d1
  149.     add.w    d1,d1
  150.     bra.w    Die
  151.  
  152. * Set up the input IOReq and the output IOReq
  153.  
  154. FoundName    move.l    #MEMF_PUBLIC!MEMF_CLEAR,d1
  155.     move.l    d3,d0
  156.     add.l    d0,d0
  157.     SYS    AllocMem
  158.     move.l    d0,(iob,a5)
  159.     bne.b    CreateIOReq
  160.  
  161.     PUTDEBUG 100,<'AllocMem() failed'>
  162.  
  163.     movea.l    a3,a0    ;Can't get memory
  164.     moveq    #DOS_FALSE,d0
  165.     moveq    #ERROR_NO_FREE_STORE,d1
  166.     bra.w    Die
  167.  
  168. CreateIOReq    movea.l    d0,a1    ;IORequest
  169.     move.b    #NT_MESSAGE,(LN_TYPE,a1)
  170.     move.w    d3,(MN_LENGTH,a1)
  171.     move.l    (devport,a5),(MN_REPLYPORT,a1)
  172.     add.l    d3,d0
  173.     move.l    d0,(iobo,a5)
  174.  
  175.     movea.l    a2,a0    ;Device name
  176.     move.l    d2,d0    ;Device unit
  177.     moveq    #0,d1    ;Flags
  178.     SYS    OpenDevice
  179.     move.l    d0,Error
  180.     beq.b    CopyIOReq
  181.  
  182.     PUTDEBUG 5,<'OpenDevice() failed'>
  183.  
  184.     movea.l    a3,a0    ;Multiple readers not allowed
  185.     moveq    #DOS_FALSE,d0
  186.     moveq    #(ERROR_OBJECT_IN_USE/2),d1
  187.     add.w    d1,d1
  188.     bra.w    Die
  189.  
  190. CopyIOReq    movea.l    (iob,a5),a0
  191.     movea.l    (iobo,a5),a1
  192.     moveq    #(IOSTD_SIZE/4)-1,d1
  193. ..    move.l    (a0)+,(a1)+
  194.     dbra    d1,..
  195.  
  196. * Patch outselves into the system
  197.  
  198.     PUTDEBUG 5,<'patching outselves into system'>
  199.  
  200.     movea.l    (outpkt,a5),a0
  201.     move.l    #ACTION_WRITE_RETURN,(dp_Type,a0)
  202.     movea.l    (inpkt,a5),a0
  203.     move.l    #ACTION_READ_RETURN,(dp_Type,a0)
  204.     movea.l    (node,a5),a0
  205.     move.l    (devport,a5),(dn_Task,a0)
  206.  
  207. * Finished with parameter packet...send back.
  208.  
  209.     PUTDEBUG 5,<'returning initial packet'>
  210.  
  211.     movea.l    a3,a0
  212.     moveq    #DOS_TRUE,d0
  213.     move.l    (dp_Res2,a0),d1    ;Tell DOS we're all set
  214.     bsr.w    ReturnPkt
  215.  
  216.     PUTDEBUG 5,<'starting MainLoop'>
  217.  
  218. ***************************************************************************
  219. ***                           Main Event Loop                           ***
  220. ***************************************************************************
  221.  
  222. MainLoop    bsr.w    WaitMsg    ;Wait for a new DOS packet
  223.     movea.l    d0,a0
  224.     move.l    (dp_Type,a0),d0    ;Find what action to perform
  225.  
  226.     ifne    INFO_LEVEL
  227.     move.l    d0,-(sp)
  228.     PUTDEBUG 5,<'Got new packet = %ld'>
  229.     addq.w    #4,sp
  230.     endc
  231.  
  232. FindInput    cmpi.l    #ACTION_FINDINPUT,d0
  233.     bne.b    FindOutput
  234.     move.l    (dp_Arg1,a0),d0    ;filehandle
  235.     lsl.l    #2,d0
  236.     movea.l    d0,a1
  237.  
  238.     tst.w    OpenForInput
  239.     beq.b    1$
  240.     moveq    #DOSFALSE,d0    ;Multiple readers not allowed
  241.     moveq    #(ERROR_OBJECT_IN_USE/2),d1
  242.     add.w    d1,d1
  243.     bra.b    2$
  244.  
  245. 1$    moveq    #DOS_TRUE,d0
  246.     move.w    d0,OpenForInput
  247.     move.l    d0,(fh_Interactive,a1)    ;Now mark as interactive
  248.     move.l    #ACTION_FINDINPUT,(fh_Arg1,a1)
  249.     moveq    #0,d1
  250. 2$    bsr.w    ReturnPkt
  251.     bra.w    CheckAction
  252.  
  253. FindOutput    cmpi.l    #ACTION_FINDOUTPUT,d0
  254.     bne.b    ActionEnd
  255.     move.l    (dp_Arg1,a0),d0    ;filehandle
  256.     lsl.l    #2,d0
  257.     movea.l    d0,a1
  258.  
  259.     tst.w    OpenForOutput
  260.     beq.b    1$
  261.     moveq    #DOSFALSE,d0    ;Multiple writers not allowed
  262.     moveq    #(ERROR_OBJECT_IN_USE/2),d1
  263.     add.w    d1,d1
  264.     bra.b    2$
  265.  
  266. 1$    moveq    #DOS_TRUE,d0
  267.     move.w    d0,OpenForOutput
  268.     move.l    d0,(fh_Interactive,a1)    ;Now mark as interactive
  269.     move.l    #ACTION_FINDOUTPUT,(fh_Arg1,a1)
  270.     moveq    #0,d1
  271. 2$    bsr.w    ReturnPkt
  272.     bra.w    CheckAction
  273.  
  274. ActionEnd    cmpi.l    #ACTION_END,d0
  275.     bne.b    IntRead
  276.     move.l    (dp_Arg1,a0),d0
  277.     cmpi.l    #ACTION_FINDINPUT,d0
  278.     bne.b    1$
  279.     moveq    #0,OpenForInput
  280.     bra.b    2$
  281.  
  282. 1$    moveq    #0,OpenForOutput
  283.  
  284. 2$    tst.w    OpenForInput
  285.     bne.b    3$
  286.     tst.w    OpenForOutput
  287.     bne.b    3$
  288.     movea.l    (node,a5),a1
  289.     clr.l    (dn_Task,a1)
  290.  
  291. 3$    moveq    #DOSTRUE,d0
  292.     moveq    #0,d1
  293.     bsr.w    ReturnPkt
  294.     bra.w    CheckAction
  295.  
  296. IntRead    cmpi.l    #ACTION_READ_RETURN,d0
  297.     bne.b    IntWrite
  298.     move.l    a0,(inpkt,a5)
  299.     movea.l    (readPkt,a5),a0
  300.     movea.l    (iob,a5),a1
  301.     bsr.w    handleReturn
  302.     bra.w    CheckAction
  303.  
  304. IntWrite    cmpi.l    #ACTION_WRITE_RETURN,d0
  305.     bne.b    ActionRead
  306.     move.l    a0,(outpkt,a5)
  307.     movea.l    (writePkt,a5),a0
  308.     movea.l    (iobo,a5),a1
  309.     bsr.w    handleReturn
  310.     bra.w    CheckAction
  311.  
  312. ActionRead    moveq    #'R',d1
  313.     cmp.l    d1,d0
  314.     bne.b    ActionWrite
  315.     move.l    a0,(readPkt,a5)
  316.     movea.l    (iob,a5),a1
  317.     moveq    #CMD_READ,d0
  318.     movea.l    (inpkt,a5),a2
  319.     bsr.w    handleRequest
  320.     clr.l    (inpkt,a5)
  321.     bra.b    CheckAction
  322.  
  323. ActionWrite    moveq    #'W',d1
  324.     cmp.l    d1,d0
  325.     bne.b    DefaultAction
  326.     move.l    a0,(writePkt,a5)
  327.     movea.l    (iobo,a5),a1
  328.     moveq    #CMD_WRITE,d0
  329.     movea.l    (outpkt,a5),a2
  330.     bsr.w    handleRequest
  331.     clr.l    (outpkt,a5)
  332.     bra.b    CheckAction
  333.  
  334. DefaultAction    tst.w    OpenForInput
  335.     bne.b    1$
  336.     tst.w    OpenForOutput
  337.     bne.b    1$
  338.     movea.l    (node,a5),a1
  339.     clr.l    (dn_Task,a1)
  340.  
  341. 1$    moveq    #DOSFALSE,d0    ;Default behaviour
  342.     moveq    #(ERROR_ACTION_NOT_KNOWN/2),d1
  343.     add.w    d1,d1
  344.     bsr.w    ReturnPkt
  345.  
  346. CheckAction    tst.w    OpenForInput
  347.     bne.b    1$
  348.     tst.w    OpenForOutput
  349.     bne.b    1$
  350.     tst.l    (outpkt,a5)
  351.     beq.b    1$
  352.     tst.l    (inpkt,a5)
  353.     bne.b    Exit
  354. 1$    bra.w    MainLoop
  355.  
  356. ***************************************************************************
  357. ***                          Termination Code                           ***
  358. ***************************************************************************
  359.  
  360. Die    bsr.w    ReturnPkt    ;Fall through to Exit
  361.  
  362. Exit    move.l    (iob,a5),d2
  363.     beq.b    2$
  364.     tst.l    Error
  365.     bne.b    1$
  366.     movea.l    d2,a1
  367.     SYS    CloseDevice
  368.  
  369. 1$    movea.l    d2,a1
  370.     moveq    #0,d0
  371.     move.w    (MN_LENGTH,a1),d0
  372.     add.l    d0,d0
  373.     SYS    FreeMem
  374.  
  375. * This looks funny, but works because DOS is not part of the code being unloaded
  376.  
  377. 2$    lea    (DosName,pc),a1
  378.     SYS    OldOpenLibrary
  379.     movea.l    a6,a0
  380.     movea.l    d0,a6
  381.  
  382.     addq.b    #1,(TDNestCnt,a0)
  383.     movea.l    (node,a5),a2
  384.     move.l    (dn_SegList,a2),d1
  385.     SYS    UnLoadSeg
  386.  
  387.     movea.l    a6,a1
  388.     movea.l    (SysBase).w,a6
  389.     SYS    CloseLibrary
  390.  
  391.     clr.l    (dn_SegList,a2)
  392.  
  393.     PUTDEBUG 5,<'exit'>
  394.  
  395.     movem.l    (sp)+,d2-d7/a2-a3/a6
  396.     unlk    a5
  397.     rts
  398.  
  399. *****************************************************************************
  400. * NAME:     handleRequest(rp, iob, command, tp)
  401. * FUNCTION: Handle an IO request. Passed command, transmission packet (tp)
  402. *           and request packet (rp). rp contains buffer and length in arg2/3.
  403. * INPUTS:   A0 = Ptr to request packet.
  404. *           A1 = Ptr to IOReq.
  405. *           A2 = Ptr to transmission packet.
  406. *           D0 = Command.
  407. * RETURN:   None
  408. * SCRATCH:  D0-D1/A0-A1
  409. *****************************************************************************
  410.  
  411. handleRequest    PUTDEBUG 100,<'handleRequest() called'>
  412.  
  413.     move.w    d0,(IO_COMMAND,a1)
  414.     move.l    (dp_Arg2,a0),(IO_DATA,a1)
  415.     move.l    (dp_Arg3,a0),(IO_LENGTH,a1)
  416.     move.l    a2,(LN_NAME,a1)
  417.     move.l    a1,(dp_Link,a2)
  418.     SYS    SendIO
  419.     rts
  420.  
  421. *****************************************************************************
  422. * NAME:     handleReturn(packet, iob)
  423. * FUNCTION: Handle a returning IO request. The user request packet is passed
  424. *           as packet, and must be returned with success/failure message.
  425. * INPUTS:   A0 = Ptr to packet.
  426. *           A1 = Ptr to IOReq.
  427. * RETURN:   None
  428. * SCRATCH:  D0-D1/A0-A1
  429. *****************************************************************************
  430.  
  431. handleReturn    PUTDEBUG 100,<'handleReturn() called'>
  432.  
  433.     moveq    #0,d1
  434.     move.b    (IO_ERROR,a1),d1
  435.     bne.b    1$
  436.     move.l    (IO_ACTUAL,a1),d0
  437.     moveq    #0,d1
  438.     bra.b    ReturnPkt
  439.  
  440. 1$    moveq    #DOS_TRUE,d0    ;Fall thru to ReturnPkt
  441.  
  442. *****************************************************************************
  443. * NAME:     ReturnPkt(packet, res1 res2)
  444. * FUNCTION: Return a DosPacket with arguments.
  445. * INPUTS:   A0 = Ptr to packet.
  446. *           D0 = Res1.
  447. *           D1 = Res2.
  448. * RETURN:   None
  449. * SCRATCH:  D0-D1/A0-A1
  450. *****************************************************************************
  451.  
  452. ReturnPkt    PUTDEBUG 100,<'ReturnPkt() called'>
  453.  
  454.     move.l    a2,-(sp)
  455.     move.l    d0,(dp_Res1,a0)
  456.     move.l    d1,(dp_Res2,a0)
  457.     movea.l    (dp_Port,a0),a2
  458.     move.l    (devport,a5),(a2)
  459.     movea.l    (dp_Link,a0),a1    ;Message
  460.     move.l    a0,(LN_NAME,a1)
  461.     clr.l    (LN_SUCC,a1)
  462.     clr.l    (LN_PRED,a1)
  463.     movea.l    a2,a0    ;ReplyPort
  464.     SYS    PutMsg
  465.     movea.l    (sp)+,a2
  466.     rts
  467.  
  468. *****************************************************************************
  469. * NAME:     WaitMsg()
  470. * FUNCTION: Waits for a message to arrive at the port and returns
  471. *           the packet address.
  472. * INPUTS:   None
  473. * RETURN:   D0 = Ptr to Packet.
  474. * SCRATCH:  D0-D1/A0-A1
  475. *****************************************************************************
  476.  
  477. WaitMsg    PUTDEBUG 100,<'WaitMsg() called'>
  478.  
  479.     move.l    #1<<8,d2
  480.     moveq    #0,d0
  481.     move.l    d2,d1
  482.     SYS    SetSignal
  483.     bra.b    2$
  484.  
  485. 1$    move.l    d2,d0
  486.     SYS    Wait
  487.  
  488. 2$    movea.l    (devport,a5),a0
  489.     SYS    GetMsg
  490.     tst.l    d0
  491.     beq.b    1$
  492.     movea.l    d0,a0
  493.     move.l    (LN_NAME,a0),d0
  494.     rts
  495.  
  496. *****************************************************************************
  497. * NAME:     strUcmp(str1, str2)
  498. * FUNCTION: Compare U/C chars of string1 and string2.
  499. * INPUTS:   A0 = String1 (preserved).
  500. *           A1 = String2
  501. * RETURN:   Z  = 1 if strings are equal, else Z = 0.
  502. * SCRATCH:  D0-D1/A1
  503. *****************************************************************************
  504.  
  505. strUcmp    move.l    a0,-(sp)
  506. 1$    move.b    (a0)+,d0
  507.     cmpi.b    #'a',d0
  508.     blo.s    2$
  509.     cmpi.b    #'z',d0
  510.     bhi.s    2$
  511.     subi.b    #$20,d0
  512. 2$    move.b    (a1)+,d1
  513.     cmp.b    d0,d1
  514.     bne.s    3$
  515.     tst.b    (-1,a1)
  516.     bne.b    1$
  517. 3$    movea.l    (sp)+,a0
  518.     rts
  519.  
  520.     ISDEBUG    'handler'    ;This name for debugging use
  521.  
  522. DosName    cstr    'dos.library'
  523. NewSerName    MYDEVNAME
  524. EightBitName    PARDEVNAME
  525. SER1name    MYUNITNAME1
  526. SER2name    MYUNITNAME2
  527. SER3name    MYUNITNAME3
  528. SER4name    MYUNITNAME4
  529. PAR1name    PARUNITNAME1
  530. PAR2name    PARUNITNAME2
  531. PAR3name    PARUNITNAME3
  532. PAR4name    PARUNITNAME4
  533.  
  534.     end
  535.