home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 1 / Mecomp-CD.iso / amiga / tools / misc / cnetdevice / src / cnetdevice.asm next >
Assembly Source File  |  1997-06-02  |  47KB  |  1,574 lines

  1. ;---------------------------------------------------------------------------
  2. ;           CNet CN40BC PCMCIA ethernet card driver for A1200
  3. ;---------------------------------------------------------------------------
  4. ;
  5. ; HISTORY:
  6. ;
  7. ; 10-4-97  v0.1 - Created by Bruce Abbott (bhabbott@inhb.co.nz)
  8. ;                      *** First Aminet Release ***
  9. ;
  10. ; 29-4-97  v0.2 - Implemented CMD_ONLINE/OFFLINE/FLUSH (for Miami).
  11. ;
  12. ;               - Enabled interrupts during RemoteWrite (no more serial
  13. ;                 port overruns!).
  14. ;
  15. ; 6-5-97   v0.3 - Added a flag so that we won't try to ReleaseCard()
  16. ;                 unless there was a successful OwnCard()!
  17. ;
  18. ; 2-6-97   v0.4 - CMD_CONFIGINTERFACE now overrides the default hardware
  19. ;                 address (for Maimi).
  20. ;
  21. ;               - Device now goes offline if the PCMCIA card is removed.
  22. ;
  23. ;               - CMD_ONEVENT implemented.
  24. ;
  25. ;               - Loosened hardware address verification to accept the
  26. ;                 Accton EN2216.
  27. ;
  28. ;               - Unrolled loops to improve data transfer speed. Now
  29. ;                 about 20% faster on an unexpanded A600.
  30. ;
  31. ;               - Hack to fix problem with missed interrupts. Now we
  32. ;                 clear the Gayle interrupt bits instead of letting
  33. ;                 card.resource do it for us.
  34. ;                        *** Second Aminet Release ***
  35. ;
  36. ;
  37.  output devs:networks/cnet.device
  38.  
  39.  
  40.  include amiga.i              ; commodore includes (WB1.3)
  41.  include pcmcia.i             ; card.resource etc.
  42.  include sanaii.i             ; the essential network stuff
  43.  include cnet.i               ; hardware specific stuff
  44.  
  45.  
  46. VERSION  = 0
  47. REVISION = 4
  48.  
  49.  
  50. ; 1uS delay before nic register access
  51. ; May not be required with slower CPU.
  52.  
  53. delay MACRO
  54.  tst.b   $bfe001              ; at least 1uS, even on fast machines
  55.  ENDM
  56.  
  57. ;===========================================================================
  58.  
  59.     Section 0,CODE
  60.  
  61. start_exe:
  62.  moveq   #-1,D0   ; it's a device, not an application!
  63.  rts
  64.  
  65. romtag:
  66.  dc.w    RTC_MATCHWORD   ; RT_MATCHWORD
  67.  dc.l    romtag          ; RT_MATCHTAG
  68.  dc.l    Endcode         ; RT_ENDSKIP
  69.  dc.b    RTF_AUTOINIT    ; RT_FLAGS
  70.  dc.b    VERSION         ; RT_VERSION
  71.  dc.b    NT_DEVICE       ; RT_TYPE
  72.  dc.b    0               ; RT_PRI
  73.  dc.l    DeviceName      ; RT_NAME
  74.  dc.l    IDString        ; RT_IDSTRING
  75.  dc.l    Init            ; RT_INIT
  76.  
  77. Init:
  78.  dc.l    dd_extsize      ; data space size
  79.  dc.l    funcTable       ; pointer to function initializers
  80.  dc.l    dataTable       ; pointer to data initializers
  81.  dc.l    initRoutine     ; routine to run at startup
  82.  
  83. funcTable:
  84.  dc.w  -1
  85.  dc.w  Open_Device-funcTable
  86.  dc.w  Close_Device-funcTable
  87.  dc.w  _DevExpunge-funcTable
  88.  dc.w  _Null-funcTable
  89.  dc.w  _DevBeginIO-funcTable
  90.  dc.w  _DevAbortIO-funcTable
  91.  dc.w  -1
  92.  
  93. dataTable:
  94.  INITBYTE LN_TYPE,NT_DEVICE
  95.  INITLONG LN_NAME,DeviceName
  96.  INITBYTE LIB_FLAGS,LIBF_SUMUSED!LIBF_CHANGED
  97.  INITWORD LIB_VERSION,VERSION
  98.  INITWORD LIB_REVISION,REVISION
  99.  INITLONG LIB_IDSTRING,idString
  100.  dc.w   0
  101.  
  102.  
  103. ;=======================================================
  104. ;                      initRoutine
  105. ;=======================================================
  106. ;
  107. ; Called after device has been allocated.
  108. ; This routine is single threaded
  109. ;
  110. ; input:   a0 = seglist
  111. ;          d0 = device
  112. ;
  113. initRoutine:
  114.  movem.l d1-d7/a0-a5,-(A7)
  115.  move.l  d0,a5
  116.  move.l  a0,dd_SegList(a5)  ; seglist for expunge
  117.  move.l  4,execbase         ; local copy of execbase
  118.  move.l  a5,d0
  119.  movem.l (A7)+,d1-d7/a0-a5
  120.  rts
  121.  
  122. _Null:
  123.  moveq   #0,d0
  124.  rts
  125.  
  126. ;=================================================================
  127. ;                         Open Device
  128. ;=================================================================
  129. ;
  130. ; error = Open_Device(device, ioreq, unitnum, flags)
  131. ;  d0                   a6      a1     d0      d1
  132. ;
  133. Open_Device:
  134.  movem.l D2-D4/A2-A4/A6,-(A7)
  135.  move.l  A6,A3                       ; a3 = device
  136.  move.l  A1,A4                       ; a4 = ioreq
  137.  move.l  D0,D4                       ; d4 = unit
  138.  move.l  a3,a1
  139.  bsr     init_device                 ; init device data structures
  140.  move.l  a3,a0
  141.  move.l  a4,a1
  142.  move.l  d4,d0
  143.  bsr     Open_Unit                   ; open unit
  144.  move.l  d0,io_unit(a4)
  145.  beq.s   .error
  146.  move.l  A3,A1
  147.  bsr     init_card                   ; init PCMCIA card
  148.  tst.l   D0
  149.  bne.s   .error
  150.  move.l  a3,a1
  151.  bsr     init_nic                    ; init Network Interface Controller
  152.  tst.l   d0
  153.  beq.s   .ok
  154. .error:
  155.  move.l  dd_cardres(a3),d1
  156.  beq.s   .nocard
  157.  move.l  d1,a6
  158.  bclr    #DDB_OWNED,dd_flags(a3)
  159.  beq.s   .nocard
  160.  lea     dd_cardhandle(a3),a1
  161.  moveq   #CARDF_REMOVEHANDLE,d0
  162.  jsr     _LVOReleaseCard(a6)         ; release card if error
  163. .nocard:
  164.  moveq   #IOERR_OPENFAIL,d0
  165.  move.b  d0,io_error(a4)
  166.  move.l  d0,io_device(a4)
  167.  bra.s   .done
  168. .ok:
  169.  bset    #DDB_ONLINE,dd_flags(a3)    ; ready to accept packets
  170.  moveq   #0,d0
  171.  move.b  d0,io_error(a4)             ; complete the ioreq
  172.  move.b  #NT_REPLYMSG,ln_type(a4)
  173.  addq.w  #1,lib_OpenCnt(a3)          ; opened successfully
  174. .done:
  175.  movem.l (A7)+,D2-D4/A2-A4/A6
  176.  rts
  177.  
  178.  
  179. ;===============================================================
  180. ;                 unit=Open Unit(device, ioreq, unitnum)
  181. ;                  d0              a0      a1     d0
  182. ;===============================================================
  183. ;
  184. ; Get the caller's buffer copy callback vectors
  185. ;
  186. ; NOTE: we only keep the vectors from the current caller
  187. ;
  188. Open_Unit:
  189.  movem.l D2-D4/A2-A5,-(A7)
  190.  move.l  A0,A4                    ; A4 = device
  191.  move.l  A1,A5                    ; A5 = ioreq
  192.  tst.l   D0                       ; only unit 0 is supported
  193.  bne     .error
  194.  move.l  ios2_buffermanagement(A5),D0  ; tag list supplied?
  195.  beq     .ok
  196.  moveq   #0,D2                    ; d2 = number of required tags found
  197.  move.l  D0,A0                    ; a0 = tag list
  198. .next_tag:
  199.  move.l  (A0)+,D0                 ; d0 = tag number
  200.  beq     .got_tags                ; end of tag list?
  201.  move.l  (A0)+,D1                 ; d1 = tag value
  202.  cmp.l   #S2_COPYFROMBUFF,D0
  203.  beq.s   .from                    ; tag_copyfrombuf ?
  204.  cmp.l   #S2_COPYTOBUFF,D0
  205.  bne.s   .next_tag                ; tag_copytobuf ?
  206. .to:
  207.  move.l  D1,dd_copytobuf(a4)      ; store function
  208.  addq.w  #1,D2                    ; got the tag
  209.  bra     .next_tag
  210. .from:
  211.  move.l  D1,dd_copyfrombuf(a4)    ; store function
  212.  addq.w  #1,D2                    ; got the tag
  213.  bra     .next_tag
  214. .got_tags:
  215.  subq.w  #2,D2                    ; got both tags ?
  216.  beq.s   .ok
  217. .error:
  218.  moveq   #0,d0                    ; return error
  219.  bra.s   .done
  220. .ok:
  221.  moveq   #1,d0                    ; return OK
  222. .done:
  223.  movem.l (A7)+,D2-D4/A2-A5
  224.  rts
  225.  
  226.  
  227. ;============================================================
  228. ;                      Expunge Device
  229. ;============================================================
  230. ;
  231. ; called when system wants us to close down
  232. ;
  233. _DevExpunge:
  234.  tst.w   lib_opencnt(a6)
  235.  bne.s   .done
  236.  bset    #LIBB_DELEXP,lib_flags(a6)
  237. .done:
  238.  moveq   #0,d0
  239.  rts
  240.  
  241.  
  242.  
  243. ;============================================================
  244. ;                      Close Device
  245. ;============================================================
  246. ;
  247. ;  Seglist = CloseDevice(device)
  248. ;    d0                    a6
  249. ;
  250. Close_Device:
  251.  move.w  lib_OpenCnt(a6),d0
  252.  beq.s   .done                        ; already closed ?
  253.  subq.w  #1,d0
  254.  move.w  d0,lib_OpenCnt(a6)
  255. .done:
  256.  moveq   #0,d0
  257.  rts
  258.  
  259.  
  260. ;===============================================================
  261. ;                       Dev_BeginIO
  262. ;===============================================================
  263. ; the entry point for all device commands
  264. ;
  265. _DevBeginIO:
  266.  move.b  #NT_MESSAGE,ln_type(A1) ; make sure type is message
  267.  moveq   #0,d0
  268.  move.w  io_command(A1),D0       ; get command number
  269.  cmp.w   #S2_END,D0
  270.  bhs.s   .error                  ; valid command?
  271.  lsl.w   #2,D0
  272.  move.l  cmds(PC,D0.w),D0        ; get command vector
  273.  bne.s   .ok
  274. .error:
  275.  move.b  #IOERR_NOCMD,io_error(A1)
  276.  bra     TermIO                  ; return invalid command
  277. .ok:
  278.  clr.b   io_error(A1)            ; no errors yet
  279.  move.l  D0,A0
  280.  jmp     (A0)                    ; jump to command
  281.  
  282.  
  283. ; command vector array   ( those marked '*' are commonly used by AmiTCP )
  284.  
  285. cmds:
  286.  dc.l    0                           ;  0
  287.  dc.l    0                           ;  1
  288.  dc.l    devcmd_read                 ;  2 = cmd_read               *
  289.  dc.l    devcmd_write                ;  3 = cmd_write              *
  290.  dc.l    0                           ;  4
  291.  dc.l    0                           ;  5
  292.  dc.l    0                           ;  6
  293.  dc.l    0                           ;  7
  294.  dc.l    devcmd_flush                ;  8 = cmd_flush
  295.  dc.l    devcmd_devicequery          ;  9 = S2_DEVICEQUERY         *
  296.  dc.l    devcmd_getstationaddress    ;  10= S2_GETSTATIONADDRESS   *
  297.  dc.l    devcmd_configinterface      ;  11= S2_CONFIGINTERFACE     *
  298.  dc.l    0                           ;  12
  299.  dc.l    0                           ;  13
  300.  dc.l    0                           ;  14= S2_ADDMULTICASTADDRESS
  301.  dc.l    0                           ;  15= S2_DELMULTICASTADDRESS
  302.  dc.l    0                           ;  16= S2_MULTICAST
  303.  dc.l    devcmd_broadcast            ;  17= S2_BROADCAST           *
  304.  dc.l    devcmd_tracktype            ;  18= S2_TRACKTYPE           *
  305.  dc.l    0                           ;  19= S2_UNTRACKTYPE
  306.  dc.l    0                           ;  20= S2_GETTYPESTATS
  307.  dc.l    0                           ;  21= S2_GETSPECIALSTATS
  308.  dc.l    0                           ;  22= S2_GETGLOBALSTATS
  309.  dc.l    devcmd_onevent              ;  23= S2_ONEVENT
  310.  dc.l    0                           ;  24= S2_READORPHAN
  311.  dc.l    devcmd_online               ;  25= S2_ONLINE
  312.  dc.l    devcmd_offline              ;  26= S2_OFFLINE
  313.  
  314.  
  315. ;====================================================================
  316. ;                              Abort_IO
  317. ;====================================================================
  318. ;
  319. ;                   try to cancel a pending ioreq
  320. ;
  321. _DevAbortIO:
  322.  movem.l A2/A6,-(A7)
  323.  move.l  A1,A2
  324.  moveq   #-1,D0                           ; assume failure
  325.  cmp.b   #NT_MESSAGE,ln_type(A2)          ; only cancel queued ioreq's
  326.  bne.s   .done
  327.  move.l  execbase(PC),A6
  328.  jsr     _LVODisable(A6)
  329.  move.l  A2,A1
  330.  jsr     _LVORemove(A6)                   ; remove ioreq from list
  331.  move.b  #IOERR_ABORTED,io_error(A2)
  332.  move.l  A2,A1
  333.  jsr     _LVOReplyMsg(A6)                 ; reply to originator's message
  334.  jsr     _LVOEnable(A6)
  335.  moveq   #0,D0                            ; aborted OK
  336. .done:
  337.  movem.l (A7)+,A2/A6
  338.  rts
  339.  
  340.  
  341.  
  342. ;===========================================================
  343. ;                      termio(ioreq)
  344. ;                               a1
  345. ;===========================================================
  346. ;
  347. ; return completed ioreq to sender.
  348. ;
  349. TermIO:
  350.  movem.l A2/A6,-(A7)
  351.  move.l  A1,A2
  352.  move.b  io_error(a1),d0             ; completed OK ?
  353.  beq.s   .noerr
  354.  moveq   #0,d1
  355.  move.w  io_command(a2),d1
  356.  move.l  io_device(A2),A0
  357.  moveq   #S2EVENT_ERROR,D0
  358.  bsr     DoEvent                     ; create error event
  359. .noerr:
  360.  move.b  #NT_REPLYMSG,ln_type(A2)
  361.  btst    #IOB_QUICK,io_flags(A2)
  362.  bne.s   .quick                      ; does sender need a reply ?
  363.  move.l  A2,A1
  364.  move.l  execbase(PC),A6
  365.  jsr     _LVOReplyMsg(A6)            ; not quick, so send reply
  366. .quick
  367. .done:
  368.  movem.l (A7)+,A2/A6
  369.  rts
  370.  
  371.  
  372.  
  373.  
  374. ;====================================================
  375. ;                     CMD_READ
  376. ;====================================================
  377. ;
  378. devcmd_read:
  379.  movem.l A2/A3/A6,-(A7)
  380.  move.l  A1,A2                           ; A2 = ioreq
  381.  move.l  io_device(A2),A3
  382.  btst    #DDB_CONFIGURED,dd_flags(A3)    ; configured ?
  383.  bne.s   .configured
  384.  move.b  #S2ERR_BAD_STATE,io_error(A2)
  385.  moveq   #S2WERR_NOT_CONFIGURED,D0
  386.  move.l  D0,ios2_WireError(A2)           ; error, device is not configured
  387.  bra.s   .error
  388. .configured:
  389.  bclr    #IOB_QUICK,io_flags(A2)         ; must be queued
  390.  move.l  execbase(PC),A6
  391.  jsr     _LVODisable(A6)
  392.  lea     dd_readlist(A3),A0
  393.  move.l  A2,A1
  394.  jsr     _LVOAddTail(A6)                 ; add ioreq to read queue
  395.  jsr     _LVOEnable(A6)
  396.  bra.s   .done
  397. .error:
  398.  move.l  A2,A1
  399.  bsr     TermIO                          ; terminate with error
  400. .done:
  401.  movem.l (A7)+,A2/A3/A6
  402.  rts
  403.  
  404.  
  405. ;======================================================
  406. ;                      CMD_WRITE
  407. ;======================================================
  408. ;
  409. devcmd_write:
  410.  movem.l A2/A3/A6,-(A7)
  411.  move.l  A1,A2                            ; A2 = ioreq
  412.  move.l  io_device(A2),A3
  413.  btst    #DDB_CONFIGURED,dd_flags(A3)     ; configured ?
  414.  bne.s   .configured
  415.  move.b  #S2ERR_BAD_STATE,io_error(A2)
  416.  moveq   #S2WERR_NOT_CONFIGURED,D0
  417.  move.l  D0,ios2_WireError(A2)            ; error, not configured
  418.  bra     .error
  419. .configured:
  420.  btst    #SANA2IOB_RAW,io_flags(A2)       ; raw packets ?
  421.  beq.s   .cooked
  422.  move.l  ios2_DataLength(A2),D1
  423.  cmp.l   #RAWPKT_SIZE,D1
  424.  bls.s   .goodlen                         ; check packet size
  425.  bra.s   .toobig
  426. .cooked:
  427.  move.l  ios2_DataLength(A2),D1
  428.  cmp.l   #ETHERPKT_SIZE,D1
  429.  bls.s   .goodlen
  430. .toobig:
  431.  move.b  #S2ERR_MTU_EXCEEDED,io_error(A2) ; oops! packet too big
  432.  clr.l   ios2_WireError(A2)
  433.  bra     .error
  434. .goodlen:
  435.  bclr    #IOB_QUICK,io_flags(A2)          ; must be queued
  436.  move.l  execbase(PC),A6
  437.  jsr     _LVODisable(A6)
  438.  lea     dd_writelist(A3),A0
  439.  move.l  A2,A1
  440.  jsr     _LVOAddTail(A6)                  ; add ioreq to write queue
  441.  jsr     _LVOEnable(A6)
  442.  lea     dd_txint(A3),A1
  443.  jsr     _LVOCause(A6)                    ; start tx
  444.  bra.s   .done
  445. .error:
  446.  move.l  A2,A1
  447.  bsr     TermIO                           ; terminate with error
  448. .done:
  449.  movem.l (A7)+,A2/A3/A6
  450.  rts
  451.  
  452.  
  453. ;==============================================
  454. ;                CMD_FLUSH
  455. ;==============================================
  456. ;
  457. devcmd_flush:
  458.  movem.l A1/A2/A6,-(A7)
  459.  move.l  io_device(A1),A2
  460.  move.l  execbase(PC),A6
  461.  jsr     _LVODisable(A6)
  462.  bra.s   .flushreads
  463. .readloop:
  464.  move.l  D0,A1
  465.  move.b  #IOERR_ABORTED,io_error(A1)
  466.  jsr     _LVOReplyMsg(A6)             ; abort all Read requests
  467. .flushreads:
  468.  lea     dd_readlist(A2),A0
  469.  jsr     _LVORemHead(A6)
  470.  tst.l   D0
  471.  bne.s   .readloop
  472.  bra.s   .flushwrites
  473. .writeloop:
  474.  move.l  D0,A1
  475.  move.b  #IOERR_ABORTED,io_error(A1)
  476.  jsr     _LVOReplyMsg(A6)             ; abort all Write requests
  477. .flushwrites:
  478.  lea     dd_writelist(A2),A0
  479.  jsr     _LVORemHead(A6)
  480.  tst.l   D0
  481.  bne.s   .writeloop
  482.  bra.s   .flushevents
  483. .eventloop:
  484.  move.l  D0,A1                        ; abort all Event requests
  485.  move.b  #IOERR_ABORTED,io_error(A1)
  486.  jsr     _LVOReplyMsg(A6)
  487. .flushevents:
  488.  lea     dd_eventlist(A2),A0
  489.  jsr     _LVORemHead(A6)
  490.  tst.l   D0
  491.  bne.s   .eventloop
  492.  jsr     _LVOEnable(A6)
  493.  movem.l (A7)+,A1/A2/A6
  494.  bra     TermIO
  495.  
  496.  
  497. ;==============================================
  498. ;               CMD_ONLINE
  499. ;==============================================
  500. ;
  501. ;         Try to put device online
  502. ;
  503. devcmd_online:
  504.  movem.l a1/a2,-(a7)
  505.  move.l  io_device(a1),a2
  506.  btst    #DDB_CONFIGURED,dd_flags(a2)   ; won't go online unless configured!
  507.  beq.s   .error
  508.  bset    #DDB_ONLINE,dd_flags(a2)
  509.  bne.s   .done                          ; already online ?
  510.  move.l  ioaddr(pc),a0
  511.  move.b  dd_rcr(a2),nic_rcr(a0)         ; set receiver to normal mode
  512.  moveq   #S2EVENT_ONLINE,D0
  513.  bsr     DoEvent                        ; create ONLINE event
  514.  bra.s   .done
  515. .error:
  516.  move.b  #S2ERR_OUTOFSERVICE,io_error(a1)
  517.  moveq   #S2WERR_UNIT_OFFLINE,d0
  518.  move.l  d0,ios2_wireerror(a1)
  519. .done:
  520.  movem.l (a7)+,a1/a2
  521.  bra     TermIO
  522.  
  523.  
  524. ;==============================================
  525. ;               CMD_OFFLINE
  526. ;==============================================
  527. ;
  528. ;           take device offline
  529. ;
  530. devcmd_offline
  531.  move.l  a1,-(a7)
  532.  move.l  io_device(a1),a0
  533.  bclr    #DDB_ONLINE,dd_flags(a0)
  534.  beq.s   .done                          ; already offline ?
  535.  move.l  ioaddr(pc),a0
  536.  move.b  #DSRC_MON,nic_rcr(a0)          ; set receiver to monitor mode
  537.  moveq   #S2EVENT_OFFLINE,D0
  538.  bsr     DoEvent                        ; create OFFLINE event
  539. .done:
  540.  move.l  (a7)+,a1
  541.  bra     TermIO
  542.  
  543.  
  544. ;==============================================
  545. ;               CMD_ONEVENT
  546. ;==============================================
  547. ;
  548. ;         queue up event requests
  549. ;
  550. devcmd_onevent:
  551.  movem.l a1/a6,-(a7)
  552.  move.l  io_device(a1),a0
  553.  bclr    #IOB_QUICK,io_flags(a1)     ; must be queued
  554.  move.l  execbase(PC),A6
  555.  jsr     _LVODisable(A6)
  556.  lea     dd_eventlist(A0),A0
  557.  jsr     _LVOAddTail(A6)             ; add ioreq to event queue
  558.  jsr     _LVOEnable(A6)
  559.  movem.l (a7)+,a1/a6
  560.  bra     TermIO
  561.  
  562.  
  563.  
  564.  
  565. ;==============================================
  566. ;             CMD_DEVICEQUERY
  567. ;==============================================
  568. ;
  569. devcmd_devicequery:
  570.  move.l  A1,-(A7)
  571.  move.l  ios2_statdata(A1),A0    ; a0 = caller's buffer
  572.  move.l  (A0),D1                 ; D1 = buffer size
  573.  move.l  size_supplied(pc),D0
  574.  cmp.l   D0,D1                   ; enough space to store info?
  575.  bhs.s   .get
  576.  clr.l   S2DQ_SIZESUPPLIED(A0)   ; nope!
  577.  bra.s   .done
  578. .get:
  579.  lea     S2DQ_SIZESUPPLIED(A0),A1
  580.  lea     size_supplied(pc),A0
  581.  subq.l  #4,D0                   ; skip bytes_available
  582.  bra.s   .copy
  583. .copyloop:
  584.  move.b  (A0)+,(A1)+             ; copy info to caller's buffer
  585. .copy:
  586.  dbf     D0,.copyloop
  587. .done:
  588.  move.l  (A7)+,A1
  589.  bra     TermIO
  590.  
  591.  
  592.  
  593. ;==============================================
  594. ;           CMD_GETSTATIONADDRESS
  595. ;==============================================
  596. ;
  597. devcmd_getstationaddress:
  598.  move.l  A1,-(A7)
  599.  move.l  io_device(A1),A0
  600.  lea     dd_stationaddress(A0),A0
  601.  move.l  A0,D1
  602.  lea     ios2_srcaddr(A1),A1
  603.  move.w  #ETHER_ADDR_SIZE-1,D0
  604. .copysrc:
  605.  move.b  (A0)+,(A1)+             ; source address = station address
  606.  dbf     d0,.copysrc
  607.  move.l  (A7),A1
  608.  lea     ios2_dstaddr(A1),A1
  609.  move.w  #ETHER_ADDR_SIZE-1,D0
  610.  move.l  D1,A0
  611. .copydst:
  612.  moveq   #0,d1
  613.  move.b  (A0)+,d1
  614.  move.b  d1,(A1)+                ; dest address = station address
  615.  dbf     d0,.copydst
  616.  move.l  (A7)+,A1
  617.  bra     TermIO
  618.  
  619.  
  620. ;==============================================
  621. ;             CMD_CONFIGINTERFACE
  622. ;==============================================
  623. ;
  624. ; NOTE: a default station address has already
  625. ;       been set by init_nic
  626. ;
  627. devcmd_configinterface:
  628.  movem.l a1/a6,-(sp)
  629.  move.l  io_device(A1),A0
  630.  move.l  ios2_srcaddr(a1),d0
  631.  ble     .done                          ; check for valid address
  632.  move.l  d0,dd_stationaddress(a0)
  633.  move.w  ios2_srcaddr+4(a1),dd_stationaddress+4(a0)
  634.  move.l  execbase(pc),a6
  635.  jsr     _LVODisable(a6)
  636.  move.l  ioaddr(pc),a1
  637.  move.b  nic_cr(a1),d1                  ; remember current command
  638.  delay
  639.  move.b  #DSCM_NODMA|DSCM_PG1,nic_cr(a1)           ; select bank 1
  640.  delay
  641.  move.b  dd_stationaddress+0(a0),nic_par0(a1)
  642.  delay
  643.  move.b  dd_stationaddress+1(a0),nic_par1(a1)
  644.  delay
  645.  move.b  dd_stationaddress+2(a0),nic_par2(a1)
  646.  delay                                             ; set station address
  647.  move.b  dd_stationaddress+3(a0),nic_par3(a1)
  648.  delay
  649.  move.b  dd_stationaddress+4(a0),nic_par4(a1)
  650.  delay
  651.  move.b  dd_stationaddress+5(a0),nic_par5(a1)
  652.  delay
  653.  move.b  d1,nic_cr(a1)                  ; restore command
  654.  jsr     _LVOEnable(a6)
  655.  bset    #DDB_CONFIGURED,dd_flags(a0)   ; now configured
  656. .done:
  657.  movem.l (sp)+,a1/a6
  658.  bra     TermIO
  659.  
  660.  
  661.  
  662. ;==============================================
  663. ;              CMD_BROADCAST
  664. ;==============================================
  665. ;
  666. devcmd_broadcast:
  667.  move.w  #ETHER_ADDR_SIZE-1,D0
  668.  moveq   #0,d1
  669. .loop:
  670.  move.b  #255,ios2_dstaddr(a1,d1.w)    ; dest address = BROADCAST
  671.  addq.w  #1,d1
  672.  dbf     d0,.loop
  673. .doit:
  674.  bra     devcmd_write
  675.  
  676.  
  677.  
  678. ;============================================
  679. ;              CMD_TRACKTYPE
  680. ;============================================
  681. ;
  682. ; This function adds a packet type to the
  683. ; list of those that are being tracked.
  684. ;
  685. devcmd_tracktype:
  686.  bra     TermIO    ; but we won't actually track anything
  687.  
  688.  
  689. ;=========================================
  690. ;      doevent(device, event)
  691. ;                a0     d0
  692. ;=========================================
  693. ;
  694. ; called when an 'important' event occurs
  695. ;
  696. DoEvent:
  697.  movem.l D2/A2/A6,-(A7)
  698.  move.l  D0,D2
  699.  move.l  dd_eventlist(A0),A2     ; get first ioreq
  700.  move.l  execbase(PC),A6
  701.  jsr     _LVODisable(A6)         ; exclusive access to list required
  702.  bra.s   .start
  703. .loop:
  704.  move.l  ios2_wireerror(A2),D0
  705.  and.l   D2,D0                   ; should this ioreq be completed?
  706.  beq.s   .next
  707.  move.l  D0,ios2_wireerror(A2)   ; clear the event
  708.  move.l  A2,A1
  709.  jsr     _LVORemove(A6)          ; remove ioreq from list
  710.  move.l  A2,A1
  711.  bsr     TermIO                  ; return ioreq to owner
  712. .next:
  713.  move.l  (A2),A2                 ; next ioreq
  714. .start:
  715.  tst.l   (A2)                    ; last ioreq ?
  716.  bne.s   .loop
  717. .done:
  718.  jsr     _LVOEnable(A6)          ; other tasks now allowed to access list
  719.  movem.l (A7)+,D2/A2/A6
  720.  rts
  721.  
  722. ;======================
  723. ;  delay approx 1.5mS
  724. ;======================
  725. ;
  726. delay1500:
  727.  move.l   D0,-(A7)
  728.  move.w   #1500,D0
  729. .loop:
  730.  tst.b    $bfe001       ; wait 1uS
  731.  dbf      D0,.loop
  732.  move.l   (A7)+,D0
  733.  rts
  734.  
  735.  
  736.  
  737. ;==================================================================
  738. ;        RemoteRead(buffer, nicbuffer, length)
  739. ;                     a1       d0.w     d1.w
  740. ;==================================================================
  741. ;
  742. ; Get a copy of data stored in the network card's onboard RAM.
  743. ;
  744. ;  buffer     = Amiga RAM
  745. ;
  746. ;  nicbuffer  = 16 bit address in card memory
  747. ;
  748. RemoteRead:
  749.  move.l  ioaddr(pc),a0
  750.  addq.w  #1,D1                   ; bump up count to even value
  751.  bclr    #0,d1
  752.  swap    d1
  753.  delay
  754.  move.b  nic_cr(a0),d1           ; save old command
  755.  swap    d1
  756.  delay
  757.  move.b  #DSCM_NODMA|DSCM_START,nic_cr(A0)  ; select bank 0
  758.  delay
  759.  move.b  D1,nic_rbcr0(A0)        ;   set count.lo
  760.  ror.w   #8,D1
  761.  delay
  762.  move.b  D1,nic_rbcr1(A0)        ;   set count.hi
  763.  delay
  764.  move.b  D0,nic_rsar0(A0)        ;   set address.lo
  765.  ror.w   #8,D0
  766.  delay
  767.  move.b  D0,nic_rsar1(A0)        ;   set address.hi
  768.  delay
  769.  move.b  #DSCM_RREAD|DSCM_START,nic_cr(A0) ; request Remote Read
  770.  ror.w   #8,D1
  771.  move.w  #1600,d0
  772.  sub.w   d1,d0                   ; calculate jump address for required
  773.  lea     nic_data(a0),a0         ; number of 'move.w' opcodes
  774.  jmp     .dmaread(pc,d0)
  775. .dmaread:
  776.  rept     1600/2
  777.  move.w  (A0),(A1)+              ; read data words from nic
  778.  endr
  779.  move.l  ioaddr(pc),a0
  780.  move.b  #DSIS_RDC,nic_isr(A0)   ; Remote DMA Complete
  781.  swap    d1
  782.  delay
  783.  move.b  d1,nic_cr(a0)           ; restore old command
  784.  rts
  785.  
  786.  
  787.  
  788. ;=================================================================
  789. ;         RemoteWrite( buffer, nicbuffer, count )
  790. ;                        a1      d0.w     d1.w
  791. ;=================================================================
  792. ;
  793. ;      Puts data into the network card's onboard RAM
  794. ;
  795. ;  buffer    = Amiga memory
  796. ;
  797. ;  nicbuffer = 16 bit address in card RAM
  798. ;
  799. ;
  800. RemoteWrite:
  801.  addq.w  #1,D1
  802.  bclr    #0,D1                   ; bump up count to even value
  803.  move.l  ioaddr(pc),a0
  804.  swap    d1
  805.  delay
  806.  move.b  nic_cr(a0),d1           ; save old command
  807.  swap    d1
  808.  delay
  809.  move.b  #DSIS_RDC,nic_isr(A0)   ; remote DMA complete
  810.  delay
  811.  move.b  #DSCM_NODMA|DSCM_START,nic_cr(A0) ; select bank 0
  812.  delay
  813.  move.b  D0,nic_rsar0(A0)        ; set address.lo
  814.  lsr.w   #8,D0
  815.  delay
  816.  move.b  D0,nic_rsar1(A0)        ; set address.hi
  817.  delay
  818.  move.b  D1,nic_rbcr0(A0)        ; set count.lo
  819.  ror.w   #8,D1
  820.  delay
  821.  move.b  D1,nic_rbcr1(A0)        ; set count.hi
  822.  delay
  823.  move.b  #DSCM_START|DSCM_RWRITE,nic_cr(A0) ; request remote write
  824.  ror.w   #8,D1
  825.  move.w  #1600,d0
  826.  sub.w   d1,d0
  827.  lea     nic_data(a0),a0
  828.  jmp     .dmaread(pc,d0)
  829. .dmaread:
  830.  rept     1600/2
  831.  move.w  (A1)+,(A0)
  832.  endr
  833.  move.l  ioaddr(pc),a0
  834.  move.w  #30000,D0               ; set timeout
  835. .check:
  836.  delay
  837.  move.b  nic_isr(A0),d1          ; wait for remote DMA complete
  838.  and.b   #DSIS_RDC,d1
  839.  bne.s   .OK
  840.  dbf     D0,.check
  841.  moveq   #1,D0                   ; timed out error
  842.  bra.s   .done
  843. .ok:
  844.  moveq   #0,D0                   ; OK
  845. .done:
  846.  delay
  847.  move.b  #DSIS_RDC,nic_isr(a0)   ; Remote DMA complete
  848.  swap    d1
  849.  delay
  850.  move.b  d1,nic_cr(a0)           ; restore old command
  851.  rts
  852.  
  853.  
  854. ;=========================================================
  855. ;                      reset_nic()
  856. ;=========================================================
  857. ;
  858. reset_nic:
  859.  move.l  ioaddr(pc),a0
  860.  delay
  861.  move.b  nic_rst(A0),D0                   ; start reset pulse
  862.  delay
  863.  move.b  D0,nic_rst(A0)                   ; end reset pulse
  864.  delay
  865.  move.b  #DSCM_NODMA|DSCM_STOP,nic_cr(A0) ; stop controller
  866.  bsr     delay1500                        ; wait 1.5mS
  867.  move.b  #$ff,nic_isr(A0)                 ; clear all nic ints
  868.  rts
  869.  
  870.  
  871. ;========================================================================
  872. ;                           init_nic(device)
  873. ;                                      a1
  874. ;========================================================================
  875. ;
  876. ;            set up the network card for online operation
  877. ;
  878. ; Here we also get the hardware station address from the nic's ROM. The
  879. ; CNet card sometimes doesn't read its ROM correctly, so in this case we
  880. ; use a fixed address instead.
  881. ;
  882. init_nic:
  883.  movem.l D2/A4-A6,-(A7)
  884.  move.l  A1,A5                             ; a5 = device data
  885.  move.l  execbase(PC),A6
  886.  jsr     _LVODisable(A6)                   ; ignore ints while setting up
  887.  btst    #DDB_NICUP,dd_flags(a5)
  888.  bne     .ok                               ; already initialised ?
  889.  move.b  #DSDC_WTS|DSDC_FT1|DSDC_BMS,dd_dcr(A5)  ; Word Xfer, FIFO, Burst
  890.  move.b  #DSRC_AB,dd_rcr(A5)                     ; accept broadcast packets
  891.  move.b  #INTMASK,dd_imr(A5)                     ; accept useful interrupts
  892.  move.l  ioaddr(pc),d0
  893.  beq     .bad                              ; valid I/O Address ?
  894.  move.l  D0,A4                             ; A4 = CNet card I/O address
  895.  bsr     reset_nic                         ; reset the controller
  896.  delay
  897.  move.b  nic_cr(A4),D0                     ; get command
  898.  cmp.b   #DSCM_NODMA|DSCM_STOP,d0
  899.  bne     .error                            ; is it correct ?
  900.  delay
  901.  move.b  dd_dcr(A5),nic_dcr(A4)            ; set data configuration register
  902.  delay
  903.  move.b  #0,nic_rbcr0(A4)                  ; clear remote byte count
  904.  delay
  905.  move.b  #0,nic_rbcr1(A4)                  ;         ''
  906.  delay
  907.  move.b  #DSRC_MON,nic_rcr(A4)             ; set rx to monitor mode
  908.  delay
  909.  move.b  #DSTC_LB0,nic_tcr(A4)             ; set tx to loopback mode 1
  910.  delay
  911.  move.b  #(RBUFEND/256)-1,nic_bnry(A4)     ; set boundary page
  912.  delay
  913.  move.b  #RBUF/256,nic_pstart(A4)          ; set start of rx ring buffer
  914.  delay
  915.  move.b  #RBUFEND/256,nic_pstop(A4)        ; set end of rx ring buffer
  916.  delay
  917.  move.b  #$ff,nic_isr(a4)                  ; clear all interrupts
  918.  delay
  919.  move.b  #0,nic_imr(a4)                    ; no interrupts allowed
  920.  delay
  921.  move.b  nic_rsr(a4),d0
  922.  delay
  923.  move.b  nic_ncr(a4),d0
  924.  delay
  925.  move.b  nic_cntr0(a4),d0                  ; read status registers
  926.  delay
  927.  move.b  nic_cntr1(a4),d0
  928.  delay
  929.  move.b  nic_cntr2(a4),d0
  930.  delay
  931.  move.b  #ETHER_ADDR_SIZE*2,nic_rbcr0(A4)  ; byte count low = (words)
  932.  delay
  933.  move.b  #0,nic_rbcr1(A4)                  ; byte count high = 0
  934.  delay
  935.  move.b  #0,nic_rsar0(A4)                  ; remote start addr low = 0 (ROM)
  936.  delay
  937.  move.b  #0,nic_rsar1(A4)                  ; remote start addr high = 0 (ROM)
  938.  delay
  939.  move.b  #DSCM_RREAD,nic_cr(A4)            ; start remote read to get
  940.  delay                                     ; station address from ROM
  941.  lea     dd_romstationaddress(a5),A0
  942.  move.w  #ETHER_ADDR_SIZE-1,D0
  943. .getaddr:
  944.  move.b  nic_data(A4),(A0)+                ; get ROM station address
  945.  dbf     D0,.getaddr                       ; NOTE: 'move.b' as ROM is 8 bit
  946.  move.w  #30000,d1
  947. .waitloop:
  948.  delay
  949.  move.b  nic_isr(A4),d0
  950.  and.b   #DSIS_RDC,d0                      ; wait for remote DMA complete
  951.  dbne    d1,.waitloop
  952.  tst.w   d0
  953.  beq     .error                            ; error if timed out
  954.  delay
  955.  move.b  #DSIS_RDC,nic_isr(A4)             ; clear remote DMA complete int
  956.  lea     dd_romstationaddress(a5),a0
  957.  btst    #7,(a0)
  958.  bne.s   .badaddr                          ; good station address ?
  959.  move.l  2(a0),d0
  960.  beq.s   .badaddr
  961.  cmp.l   #-1,d0
  962.  bne.s   .gotstation
  963. .badaddr:
  964.  lea     default_address(pc),a0            ; use known good station address
  965. .gotstation:
  966.  lea    dd_stationaddress(a5),a1
  967.  moveq  #ETHER_ADDR_SIZE-1,d0
  968. .copyaddr:
  969.  move.b (a0)+,(a1)+                        ; copy address to device data
  970.  dbf    d0,.copyaddr
  971.  delay
  972.  move.b  #DSCM_NODMA|DSCM_PG1|DSCM_STOP,nic_cr(A4) ; select bank 1
  973.  delay
  974.  move.b  dd_stationaddress+0(a5),nic_par0(a4)
  975.  delay
  976.  move.b  dd_stationaddress+1(a5),nic_par1(a4)
  977.  delay
  978.  move.b  dd_stationaddress+2(a5),nic_par2(a4)
  979.  delay                                             ; set station address
  980.  move.b  dd_stationaddress+3(a5),nic_par3(a4)
  981.  delay
  982.  move.b  dd_stationaddress+4(a5),nic_par4(a4)
  983.  delay
  984.  move.b  dd_stationaddress+5(a5),nic_par5(a4)
  985.  delay
  986.  move.b  #RBUF/256,nic_curr(A4)         ; set current page for rx
  987.  move.b  #DSCM_NODMA|DSCM_START,d0
  988.  delay
  989.  move.b  d0,nic_cr(A4)                  ; start controller
  990.  delay
  991.  cmp.b   nic_cr(A4),D0
  992.  bne     .error                         ; command accepted ?
  993.  delay
  994.  move.b  dd_rcr(A5),nic_rcr(A4)         ; normal rx mode
  995.  delay
  996.  move.b  #0,nic_tcr(A4)                 ; loopback mode off
  997.  delay
  998.  move.b  #TBUF/256,nic_tpsr(a4)         ; init tx start page
  999.  delay
  1000.  move.b  #$ff,nic_isr(A4)               ; clear all interrupts
  1001.  delay
  1002.  move.b  dd_imr(A5),nic_imr(A4)         ; enable nic interrupts
  1003. .ok:
  1004.  bset    #DDB_NICUP,dd_flags(a5)        ; nic is initialised
  1005.  moveq   #0,D0
  1006.  bra.s   .done                          ; return OK
  1007. .error:
  1008.  bsr     reset_nic                      ; reset nic after malfunction
  1009. .bad:
  1010.  moveq   #-1,D0                         ; return error
  1011. .done:
  1012.  jsr     _LVOEnable(A6)                 ; allow interrupt processing
  1013.  movem.l (A7)+,D2/A4-A6
  1014.  rts
  1015.  
  1016.  
  1017. ;========================================================
  1018. ;                 txintcode(device)
  1019. ;                             a1
  1020. ;========================================================
  1021. ;
  1022. ;  send packets to network card. packets will be put
  1023. ;  into the card's onboard 16 bit ram, and then
  1024. ;  transmitted to the wire.
  1025. ;
  1026. txintcode:
  1027.  movem.l D4-D7/A2-A4/A6,-(A7)
  1028.  move.l  A1,A4                      ; a4 = device
  1029. .next:
  1030.  btst    #DDB_TX,dd_flags(a4)       ; quit if tx in progress (status int
  1031.  bne     .done                      ; will restart us when tx complete)
  1032. .getreq:
  1033.  lea     dd_writelist(A4),A0
  1034.  move.l  execbase(pc),a6            ; remove top ioreq
  1035.  jsr     _LVORemHead(A6)
  1036.  tst.l   D0                         ; any ioreqs to process?
  1037.  beq     .done
  1038.  move.l  D0,A3                      ; A3 = ioreq
  1039.  lea     txbuffer,A1                ; A1 = our internal packet buffer
  1040.  btst    #SANA2IOB_RAW,io_flags(A3) ; raw packets?
  1041.  beq.s   .notraw
  1042.  move.l  ios2_datalength(A3),D6     ; raw packet is full length
  1043.  bra.s   .send
  1044. .notraw:
  1045.  lea     ios2_dstaddr(A3),A0
  1046.  moveq   #ETHER_ADDR_SIZE-1,D0
  1047. .copy1:
  1048.  move.b  (A0)+,(A1)+                ; insert dest stationaddr into packet
  1049.  dbra    D0,.copy1
  1050.  lea     dd_stationaddress(A4),A0
  1051.  moveq   #ETHER_ADDR_SIZE-1,D0
  1052. .copy2:
  1053.  move.b  (A0)+,(A1)+                ; insert src address into packet
  1054.  dbra    D0,.copy2
  1055.  move.l  ios2_packettype(A3),D0     ; insert packettype into packet
  1056.  move.w  D0,(A1)+
  1057.  moveq   #ether_data,D6
  1058.  add.l   ios2_datalength(A3),D6     ; d6 = length of header + data
  1059. .send:
  1060.  move.l  dd_copyfrombuf(a4),a2
  1061.  move.l  a1,a0
  1062.  move.l  ios2_data(A3),A1
  1063.  move.l  ios2_datalength(A3),D0
  1064.  jsr     (a2)                       ; call copyfrombuf
  1065.  moveq   #ETHER_MIN_LEN,D0
  1066.  cmp.l   D0,D6
  1067.  bge.s   .min                       ; d6 adjusted to legal packet size
  1068.  move.l  D0,D6
  1069. .min:
  1070.  move.l  D6,D1
  1071.  move.w  #TBUF,d0
  1072.  lea     txbuffer,A1
  1073.  bsr     RemoteWrite                ; put packet into nic tx buffer
  1074.  tst.l   D0
  1075.  bne.s   .termio
  1076.  move.l  execbase(PC),A6            ; disable interrupts during tx setup
  1077.  jsr     _LVODisable(A6)
  1078.  bset    #DDB_TX,dd_flags(A4)       ; set our "buffer full" flag
  1079.  move.l  ioaddr(pc),a0              ; a0 = nic
  1080.  delay
  1081.  move.b  D6,nic_tbcr0(A0)           ; set tx byte count lo
  1082.  ror.w   #8,D6
  1083.  delay
  1084.  move.b  D6,nic_tbcr1(A0)           ; set tx byte count hi
  1085.  delay
  1086.  move.b  #DSCM_NODMA|DSCM_TRANS|DSCM_START,nic_cr(A0) ; start tx
  1087.  move.l  execbase(PC),A6
  1088.  jsr     _LVOEnable(A6)             ; enable interrupts
  1089. .termio:
  1090.  move.l  A3,A1
  1091.  bsr     TermIO                     ; finish IOrequest
  1092.  bra     .next                      ; process next ioreq
  1093. .done:
  1094.  movem.l (A7)+,D4-D7/A2-A4/A6
  1095.  moveq   #0,d0
  1096.  rts
  1097.  
  1098.  
  1099. ;============================================================
  1100. ;                   rxintcode(device)
  1101. ;                               a1
  1102. ;============================================================
  1103. ;
  1104. ;                service rx interrupts
  1105. ;
  1106. rxintcode:
  1107.  movem.l D6/D7/A3-A6,-(A7)
  1108.  move.l  A1,A3                             ; a3 = device
  1109.  move.l  ioaddr(pc),A4                     ; a4 = nic registers
  1110.  move.l  execbase(PC),A6
  1111. .nextpage:
  1112.  jsr     _LVODisable(A6)
  1113.  delay
  1114.  move.b  #DSCM_NODMA|DSCM_PG1|DSCM_START,nic_cr(A4) ; select bank 1
  1115.  moveq   #0,D7
  1116.  move.b  nic_curr(A4),D7                   ; d7 = current page
  1117.  delay
  1118.  move.b  #DSCM_NODMA|DSCM_START,nic_cr(A4) ; select bank 0
  1119.  jsr     _LVOEnable(A6)
  1120.  moveq   #0,D6
  1121.  delay
  1122.  move.b  nic_bnry(A4),D6
  1123.  addq.w  #1,D6                             ; d6 = next page (boundary+1)
  1124.  cmp.w   #RBUFEND/256,D6
  1125.  blo.s   .nowrap                           ; end of buffer mem  ?
  1126.  moveq   #RBUF/256,D6                      ; wrap around to start
  1127. .nowrap:
  1128.  cmp.w   D6,D7                             ; current page = next page ?
  1129.  beq     .done                             ; if so then nothing to get
  1130.  move.w  D6,D0
  1131.  asl.w   #8,D0                             ; d0 = 16 bit page address
  1132.  lea     rx_header(pc),A1                  ; a1 = buffer
  1133.  moveq   #20,D1                            ; 20 bytes to get
  1134.  bsr     RemoteRead                        ; get packet header
  1135.  move.b  rx_header+prhdr_status(pc),d0
  1136.  and.b   #DSRS_RPC,d0                      ; complete packet received ?
  1137.  bne.s   .goodpacket
  1138.  addq.l  #1,dd_errors(a3)                  ; another packet error
  1139.  bra.s   .next
  1140. .goodpacket:
  1141.  move.l  A3,A0
  1142.  move.w  D6,D0
  1143.  lea     rx_header(pc),A1
  1144.  bsr     readpacket                        ; read whole packet into ioreqs
  1145. .next:
  1146.  moveq   #0,D0
  1147.  move.b  rx_header+prhdr_nxtpg(pc),D0      ; get next page number
  1148.  move.w  D0,D7
  1149.  subq.w  #1,D0                             ; nxtpage-1 = new boundary
  1150.  cmp.w   #RBUF/256,D0
  1151.  bge.s   .boundary                         ; wrap if before 1st page
  1152.  moveq   #(RBUFEND/256)-1,D0
  1153. .boundary:
  1154.  delay
  1155.  move.b  D0,nic_bnry(A4)                   ; set new boundary
  1156.  bra     .nextpage                         ; back for more
  1157. .done:
  1158.  delay
  1159.  move.b  #DSCM_NODMA|DSCM_START,nic_cr(A4) ; select bank 0
  1160.  jsr     _LVODisable(A6)
  1161.  delay
  1162.  move.b  nic_rsr(a4),d0                    ; read rx status
  1163.  delay
  1164.  move.b  nic_cntr0(A4),D0
  1165.  delay
  1166.  move.b  nic_cntr1(A4),D0                  ; read counters
  1167.  delay
  1168.  move.b  nic_cntr2(A4),D0
  1169.  or.b    #DSIM_OVWE|DSIM_RXEE|DSIM_PRXE,dd_imr(A3)
  1170.  move.b  dd_imr(a3),nic_imr(a4)            ; allow rx interrupts
  1171.  jsr     _LVOEnable(A6)
  1172.  movem.l (A7)+,D6/D7/A3-A6
  1173.  moveq   #0,D0
  1174.  rts
  1175.  
  1176.  
  1177. ;==============================================================
  1178. ;             readpacket( device, pkthdr, page )
  1179. ;                           a0     a1     d0.w
  1180. ;==============================================================
  1181. ;
  1182. ; get packet from network card and feed it to next ioreq
  1183. ;
  1184. ; Inputs:
  1185. ;
  1186. ;       pkthdr = packet header info extracted from nic
  1187. ;
  1188. ;       page = 256 byte page in nic RAM that holds packet
  1189. ;
  1190. ;
  1191. readpacket:
  1192.  movem.l D3-D7/A2-A6,-(A7)
  1193.  move.l  D0,D7                          ; D7 = page
  1194.  move.l  A0,A5                          ; A5 = device
  1195.  move.l  A1,A4                          ; a4 = header
  1196.  moveq   #0,D6
  1197.  move.b  prhdr_sz1(A4),D6
  1198.  lsl.w   #8,D6                          ; D6 = packet data length
  1199.  move.b  prhdr_sz0(A4),D6
  1200.  sub.w   #prhdr_sizeof+ether_data,D6    ; D6 = length of user data
  1201.  moveq   #0,D3
  1202.  move.w  prhdr_sizeof+ether_type(A4),D3 ; d3 = type
  1203.  move.l  dd_readlist(A5),A3             ; a3 = first ioreq
  1204.  bra.s   .getreq                        ; find a suitable ioreq
  1205. .checkreq:
  1206.  cmp.l   ios2_packettype(A3),D3         ; does it want our packet ?
  1207.  beq.s   .gotreq
  1208. .nextreq:
  1209.  move.l  D1,A3                          ; a3 = next ioreq in list
  1210. .getreq:
  1211.  move.l  (A3),D1                        ; end of list ?
  1212.  bne.s   .checkreq
  1213.  bra     .done
  1214. .gotreq:
  1215.  move.l  A3,A1
  1216.  move.l  execbase(PC),A6
  1217.  jsr     _LVORemove(A6)                 ; remove ioreq from list
  1218.  lea     ios2_dstaddr(A3),A0
  1219.  moveq   #ETHER_ADDR_SIZE-1,D0
  1220. .dst:
  1221.  move.b  (A4)+,(A0)+                    ; extract the dest address
  1222.  dbf     D0,.dst
  1223.  lea     ios2_srcaddr(A3),A0
  1224.  moveq   #ETHER_ADDR_SIZE-1,D0
  1225. .src:
  1226.  move.b  (A4)+,(A0)+                    ; extract the src address
  1227.  dbf     D0,.src
  1228.  move.w  D7,D5
  1229.  asl.w   #8,D5                          ; address=page*256
  1230.  add.w   #prhdr_sizeof+ether_data,D5    ; skip pageheader and etherheader
  1231.  btst    #SANA2IOB_RAW,io_flags(A3)
  1232.  beq.s   .getpacket                     ; is etherheader wanted ?
  1233.  moveq   #ether_data,D0
  1234.  add.l   D0,D6                        ; add header length for raw packet
  1235.  sub.w   D0,D5                        ; backup nic address to include header
  1236. .getpacket:
  1237.  lea     rxbuffer,A1
  1238.  move.w  D5,D0
  1239.  move.w  D6,D1
  1240.  bsr     RemoteRead                   ; get packet from network card's RAM
  1241.  move.l  dd_copytobuf(a5),a2
  1242.  move.l  ios2_data(A3),A0
  1243.  lea     rxbuffer,A1
  1244.  move.l  D6,ios2_datalength(A3)       ; set data length in ioreq
  1245.  move.l  d6,d0
  1246.  jsr     (a2)                         ; call copytobuf
  1247.  move.l  A3,A1
  1248.  bsr     TermIO                       ; IO finished
  1249. .done:
  1250.  movem.l (A7)+,D3-D7/A2-A6
  1251.  rts
  1252.  
  1253. ;======================================================================
  1254. ;                  init_card(device)
  1255. ;                              a1
  1256. ;======================================================================
  1257. ;
  1258. ;                    Initialise PCMCIA card
  1259. ;
  1260. init_card:
  1261.  movem.l A3-A6,-(A7)
  1262.  move.l  A1,A3                        ; a3 = device
  1263.  btst    #DDB_OWNED,dd_flags(a3)      ; port already set up ?
  1264.  bne     .owned
  1265.  lea     cardname(pc),a1
  1266.  move.l  execbase(pc),a6
  1267.  jsr     _LVOOpenResource(a6)         ; open credit card resource
  1268.  move.l  d0,dd_cardres(a3)
  1269.  beq     .error
  1270.  move.l  d0,a6
  1271.  jsr     _LVOGetCardMap(a6)
  1272.  move.l  d0,dd_cmm(a3)                ; remember Card Memory Map
  1273.  lea     dd_cardhandle(a3),a1
  1274.  lea     dd_cardremoved(a3),a0        ; init interrupt for card removed
  1275.  move.l  a3,is_data(a0)
  1276.  move.l  #card_removed_code,is_code(a0)
  1277.  move.l  a0,cah_CardRemoved(a1)
  1278.  lea     dd_cardinserted(a3),a0       ; init interrupt for card inserted
  1279.  move.l  a3,is_data(a0)
  1280.  move.l  #card_inserted_code,is_code(a0)
  1281.  move.l  a0,cah_CardInserted(a1)
  1282.  lea     dd_cardstatus(a3),a0         ; init interrupt for status change
  1283.  move.l  a3,is_data(a0)
  1284.  move.l  #status_int_code,is_code(a0)
  1285.  move.l  a0,cah_CardStatus(a1)
  1286.  lea     devicename(pc),a0
  1287.  move.l  a0,ln_name(a1)
  1288.  move.b  #20,ln_pri(a1)               ; high priority for I/O card
  1289.  move.b  #CARDF_IFAVAILABLE,cah_cardflags(a1)
  1290.  jsr     _LVOOwnCard(a6)              ; own card (sets up interrupt vectors)
  1291.  tst.l   d0
  1292.  bne     .error
  1293.  bset    #DDB_OWNED,dd_flags(a3)      ; card is now owned by us
  1294.  lea     dd_cardhandle(a3),a1
  1295.  move.l  #CARDF_DISABLE_WP|CARDF_ENABLE_DIGAUDIO,d1
  1296.  jsr     _LVOCardMiscControl(a6)      ; enable card I/O functions
  1297.  bset    #DDB_CARDIN,dd_flags(a3)     ; card is inserted
  1298. .owned:
  1299.  btst    #DDB_CARDIN,dd_flags(a3)     ; is card is inserted ?
  1300.  beq.s   .error
  1301.  move.l  dd_cmm(a3),d0
  1302.  beq.s   .error                       ; valid card memory map ?
  1303.  move.l  d0,a1
  1304.  move.l  cmm_AttributeMemory(a1),a0
  1305.  move.b  #IOat300,Config_Register(a0) ; set Card Configuration Register
  1306.  move.l  cmm_IOMemory(a1),d0
  1307.  add.l   #IOBase,d0
  1308.  move.l  d0,ioaddr                    ; calculate I/O base address
  1309.  bra.s   .ok
  1310. .error:
  1311.  moveq   #-1,d0                       ; could not get card, return error
  1312.  bra.s   .done
  1313. .ok:
  1314.  moveq   #0,D0                        ; card is active, return OK
  1315. .done:
  1316.  movem.l (A7)+,A3-A6
  1317.  rts
  1318.  
  1319.  
  1320. ;=================================================================
  1321. ;              initialise device data structures
  1322. ;=================================================================
  1323. ;
  1324. ;   init_device(device)
  1325. ;                 a1
  1326. ;
  1327. init_device:
  1328.  move.l  A3,-(A7)
  1329.  move.l  A1,A3
  1330.  bset    #DDB_DEVINIT,dd_flags(A3)     ; already initialised ?
  1331.  bne     .done
  1332.  lea     dd_readlist(A3),A0
  1333.  move.l  A0,mlh_tailpred(A0)
  1334.  lea     mlh_tail(A0),A1               ; New MinList for read queue
  1335.  clr.l   (A1)
  1336.  move.l  A1,(A0)
  1337.  lea     dd_writelist(A3),A0
  1338.  move.l  A0,mlh_tailpred(A0)           ; New MinList for write queue
  1339.  lea     mlh_tail(A0),A1
  1340.  clr.l   (A1)
  1341.  move.l  A1,(A0)
  1342.  lea     dd_eventlist(A3),A0           ; New MinList for event queue
  1343.  move.l  A0,mlh_tailpred(A0)
  1344.  lea     mlh_tail(A0),A1
  1345.  clr.l   (A1)
  1346.  move.l  A1,(A0)
  1347.  move.b  #NT_INTERRUPT,dd_rxint+ln_type(a3)
  1348.  move.b  #16,dd_rxint+ln_pri(a3)
  1349.  lea     rxintname(pc),a0
  1350.  move.l  a0,dd_rxint+ln_name(a3)       ; set up rx swi
  1351.  lea     rxintcode(pc),a0
  1352.  move.l  a0,dd_rxint+is_code(a3)
  1353.  move.l  a3,dd_rxint+is_data(a3)
  1354.  move.b  #NT_INTERRUPT,dd_txint+ln_type(a3)
  1355.  move.b  #0,dd_txint+ln_pri(a3)
  1356.  lea     txintname(pc),a0
  1357.  move.l  a0,dd_txint+ln_name(a3)       ; set up tx swi
  1358.  lea     txintcode(pc),a0
  1359.  move.l  a0,dd_txint+is_code(a3)
  1360.  move.l  a3,dd_txint+is_data(a3)
  1361. .done:
  1362.  move.l  (A7)+,A3
  1363.  rts
  1364.  
  1365.  
  1366. ;============================================================
  1367. ;             PCMCIA status change interrupt
  1368. ;============================================================
  1369. ;
  1370. ;   Occurs whenever a PCMCIA status line changes
  1371. ;
  1372. ;   eg. when the network card activates it's interrupt line
  1373. ;
  1374. ;
  1375. ;  entry:   d0 = status change(s)
  1376. ;           a1 = device
  1377. ;
  1378. ;  exit:    d0 must be preserved!
  1379. ;
  1380. status_int_code:
  1381.  movem.l D2-D6/A2-A4,-(A7)
  1382.  move.l  D0,D6                      ; d6 = status changes
  1383.  move.l  A1,A4                      ; a4 = device
  1384.  btst    #DDB_ONLINE,dd_flags(a4)   ; is device online ?
  1385.  beq     .done
  1386.  move.l  ioaddr(pc),a3              ; a3 = nic I/O address
  1387.  delay
  1388.  move.b  nic_cr(a3),d5              ; save old command
  1389.  delay
  1390.  move.b  #0,nic_imr(a3)             ; prevent nic interrupts
  1391.  bra     .checkint
  1392.  
  1393. ; interrupt service loop    (D3 = interrupt status)
  1394.  
  1395. .intloop:
  1396.  btst    #DSIB_ROVRN,d3
  1397.  beq     .no_overflow
  1398.  
  1399. ; receiver ring buffer overflowed (eek!)
  1400.  addq.l  #1,dd_overflows(a4)
  1401.  delay
  1402.  move.b  #0,nic_rbcr0(a3)
  1403.  delay
  1404.  move.b  #0,nic_rbcr1(a3)                  ; reset remote byte count
  1405.  delay
  1406.  move.b  #DSTC_LB0,nic_tcr(a3)
  1407.  delay                                     ; monitor mode
  1408.  move.b  #DSRC_MON,nic_rcr(a3)
  1409.  delay
  1410.  move.b  #DSCM_NODMA|DSCM_START,nic_cr(a3) ; try to restart controller
  1411.  delay
  1412.  move.b  #DSRC_AB,nic_rcr(a3)
  1413.  delay                                     ; normal rx mode
  1414.  move.b  #0,nic_tcr(a3)
  1415.  
  1416. .no_overflow:
  1417.  btst    #DSIB_RXE,d3
  1418.  beq.s   .norxerr
  1419.  addq.l  #1,dd_errors(a4)
  1420.  delay
  1421.  move.b  nic_rsr(a3),d0           ; read rx status
  1422.  delay
  1423.  move.b  nic_cntr0(A3),D0
  1424.  delay
  1425.  move.b  nic_cntr1(A3),D0         ; read counters
  1426.  delay
  1427.  move.b  nic_cntr2(A3),D0
  1428.  bra.s   .rx
  1429.  
  1430. .norxerr:
  1431.  btst    #DSIB_RX,d3
  1432.  beq.s   .no_rx
  1433.  
  1434. ; new packet(s) arrived in receive ring buffer
  1435. .rx:
  1436.  and.b   #~(DSIM_OVWE|DSIM_RXEE|DSIM_PRXE),dd_imr(A4) ; ignore rx ints
  1437.  lea     dd_rxint(A4),A1
  1438.  move.l  execbase(PC),A6
  1439.  jsr     _LVOCause(A6)            ; to copy packet(s) into waiting ioreqs
  1440.  
  1441. .no_rx:
  1442.  btst    #DSIB_TXE,d3
  1443.  bne.s   .tx
  1444.  btst    #DSIB_TX,d3
  1445.  beq     .no_tx
  1446.  
  1447. ; a packet has just been transmitted
  1448. .tx:
  1449.  moveq   #0,d0
  1450.  delay
  1451.  move.b  nic_ncr(A3),d0           ; read collision count
  1452.  add.l   d0,dd_collisions(a4)
  1453.  bclr    #DDB_TX,dd_flags(A4)     ; buffer now free
  1454.  lea     dd_txint(A4),A1
  1455.  move.l  execbase(PC),A6
  1456.  jsr     _LVOCause(A6)            ; to transmit next packet
  1457.  
  1458. .no_tx:
  1459.  btst    #DSIB_CTRS,d3            ; counter overflow ?
  1460.  bne.s   .counter
  1461.  bra.s   .checkint                ; all ints processed
  1462.  
  1463. ; counter overflow
  1464. .counter:
  1465.  delay
  1466.  move.b  nic_cntr0(A3),D0
  1467.  delay
  1468.  move.b  nic_cntr1(A3),D0         ; read counters
  1469.  delay
  1470.  move.b  nic_cntr2(A3),D0
  1471.  
  1472. .checkint:
  1473.  delay
  1474.  move.b  nic_isr(a3),D3           ; D3 = nic interrupt status
  1475.  delay
  1476.  move.b  d3,nic_isr(a3)           ; clear current interrupt bit(s)
  1477.  and.b   dd_imr(a4),d3
  1478.  bne     .intloop                 ; any valid interrupts ?
  1479. .end:
  1480.  delay
  1481.  move.b  d5,nic_cr(a3)            ; restore old command
  1482.  eor.b   #$2c,d6
  1483.  or.b    #$c0,d6
  1484.  move.b  d6,$da9000               ; clear PCMCIA status change bits
  1485.  delay
  1486.  move.b  dd_imr(a4),nic_imr(a3)   ; enable nic interrupts
  1487.  moveq   #0,d0                    ; don't clear status bits coz we did
  1488. .done:
  1489.  movem.l (A7)+,D2-D6/A2-A4
  1490.  rts
  1491.  
  1492.  
  1493. ;============================================================
  1494. ;             PCMCIA Card Inserted interrupt
  1495. ;============================================================
  1496. ;
  1497. ;   Occurs whenever a PCMCIA card is plugged in
  1498. ;
  1499. card_inserted_code:
  1500.  bset    #DDB_CARDIN,dd_flags(a1)     ; card is inserted
  1501.  rts
  1502.  
  1503. ;============================================================
  1504. ;             PCMCIA Card Removed interrupt
  1505. ;============================================================
  1506. ;
  1507. ;   Occurs whenever a PCMCIA card is unplugged
  1508. ;
  1509. card_removed_code:
  1510.  bclr  #DDB_CARDIN,dd_flags(a1)       ; card removed
  1511.  bclr  #DDB_ONLINE,dd_flags(a1)       ; device not online
  1512.  bclr  #DDB_CONFIGURED,dd_flags(a1)   ; hardware address not configured
  1513.  bclr  #DDB_NICUP,dd_flags(a1)        ; nic not initialised
  1514.  rts
  1515.  
  1516.  
  1517. rxintname:
  1518.  dc.b "cnet.device rxint",0
  1519. txintname:
  1520.  dc.b "cnet.device txint",0
  1521.  
  1522. cardname:
  1523.  dc.b "card.resource",0
  1524.  
  1525. DeviceName:
  1526.  dc.b    "cnet.device",0
  1527. IDString:
  1528.  dc.b    "$VER: cnet.device "
  1529.  dc.b    (VERSION+"0"),".",(REVISION+"0")," "
  1530.  dc.b    __DATE
  1531.  dc.b    " by Bruce Abbott (bhabbott@inhb.co.nz)",10,0
  1532.  even
  1533.  
  1534. ; devicequery block
  1535.  
  1536. size_supplied:
  1537.  dc.l    S2DQ_SIZE            ; bytes supplied (size of this block)
  1538.  dc.l    0                    ; this is type 0
  1539.  dc.l    0                    ; this document is level 0
  1540.  dc.w    ETHER_ADDR_SIZE*8    ; address size in bits
  1541.  dc.l    ETHERPKT_SIZE        ; maximum packet data size
  1542.  dc.l    10000000             ; line rate (10 Megabits/sec)
  1543.  dc.l    S2WIRETYPE_ETHERNET  ; what the wire is
  1544.  
  1545.  
  1546. ; default station address to use if the card won't give it to us.
  1547.  
  1548. default_address:
  1549.  dc.b $00,$80,$ad,$a2,$31,$a7 ; replace this with your card's address!
  1550.  
  1551.  
  1552. ;--------------------------------------------------------
  1553. ;                      Global data
  1554. ;--------------------------------------------------------
  1555.  
  1556. execbase    dc.l 0      ; local copy of execbase
  1557.  
  1558. ioaddr      dc.l 0      ; address of nic I/O registers
  1559.  
  1560. rx_header:
  1561.  ds.b    20             ; received packet header
  1562.  
  1563. Endcode:
  1564.  
  1565.  section buffers,bss
  1566.  
  1567. rxbuffer:
  1568.  ds.b  1600             ; received packet buffer
  1569.  
  1570. txbuffer:
  1571.  ds.b  1600             ; transmit packet buffer
  1572.  
  1573.  
  1574.