home *** CD-ROM | disk | FTP | other *** search
/ Dream 44 / Amiga_Dream_44.iso / Amiga / workbench / pilotes / pcmcia / cnetdevice.lha / cnetdevice / src / cnetdevice.asm < prev    next >
Assembly Source File  |  1997-07-29  |  50KB  |  1,722 lines

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