home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / packetdrivers.tar.gz / pd.tar / src / de600.asm < prev    next >
Assembly Source File  |  1995-06-25  |  42KB  |  2,141 lines

  1. PAGE  ,132
  2.    .286c
  3. version equ     1
  4.  
  5.     include defs.asm        ;SEE ENCLOSED COPYRIGHT MESSAGE
  6.  
  7. ;/* PC/FTP Packet Driver source, conforming to version 1.09 of the spec
  8. ;*  Portions (C) Copyright 1990 D-Link, Inc.
  9. ;*
  10. ;*  Permission is granted to any individual or institution to use, copy,
  11. ;*  modify, or redistribute this software and its documentation provided
  12. ;*  this notice and the copyright notices are retained.  This software may
  13. ;*  not be distributed for profit, either in original form or in derivative
  14. ;*  works.  D-Link, inc. makes no representations about the suitability
  15. ;*  of this software for any purpose.  D-LINK GIVES NO WARRANTY,
  16. ;*  EITHER EXPRESS OR IMPLIED, FOR THE PROGRAM AND/OR DOCUMENTATION
  17. ;*  PROVIDED, INCLUDING, WITHOUT LIMITATION, WARRANTY OF MERCHANTABILITY
  18. ;*  AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE.
  19. ;*/
  20.  
  21. BIT0            EQU     01H
  22. BIT1            EQU     02H
  23. BIT2            EQU     04H
  24. BIT3            EQU     08H
  25. BIT4            EQU     10H
  26. BIT5            EQU     20H
  27. BIT6            EQU     40H
  28. BIT7            EQU     80H
  29.  
  30. code    segment byte public
  31.     assume  cs:code, ds:code
  32.  
  33. ; DE-600's I/O port Table
  34. DAT             equ     0
  35. STAT            equ     1
  36. CMD             equ     2
  37.  
  38. ; DE-600's DATA port Command
  39. WRITE           equ     0004h   ;write memory
  40. READ            equ     0104h   ;read  memory
  41. STATUS          equ     0204h   ;read  status register
  42. COMMAND         equ     0304h   ;write command register
  43. NUL_CMD         equ     0ch     ;null command
  44. RX_LEN          equ     0504h   ;read  Rx packet length
  45. TX_ADR          equ     0604h   ;write Tx address
  46. RW_ADR          equ     0704h   ;write memory address
  47.  
  48. ;< COMMAND   bits 7-0 >
  49. RXEN            equ     08h    ; bit 3
  50. TXEN            equ     04h    ; bit 2
  51. LOOPBACK        equ     0Ch    ; RXEN=1, TXEN=1
  52. RX_NONE         equ     00h    ; M1=0, M0=0 (bit 1,0)
  53. RX_ALL          equ     01h    ; M1=0, M0=1
  54. RX_BP           equ     02h    ; M1=1, M0=0
  55. RX_MBP          equ     03h    ; M1=1, M0=1
  56. RESET           equ     80h    ; set bit 7 high
  57. STOP_RESET      equ     00h    ; set bit 7 low
  58. ;  bit 6   -- IRQ inverse
  59. ;  bit 5,4 -- Rx Page Number  ( RA12=1, RA11=0 or 1 )
  60.  
  61. ;< TX_ADR   bit 7, bit 4 >
  62. ;  bit 7   -- Tx Page Number  ( TA11=0 or 1 )
  63. ;  bit 4   -- Tx Page Number  ( TA12=0 )
  64. PAGE0           equ     00h
  65. PAGE1           equ     08h
  66. PAGE2           equ     10h
  67. PAGE3           equ     18h
  68.  
  69. ;< RW_ADR   bit 7, bit 5,4 >
  70. ;  bit 7   -- RW Page Number  ( H11 =? )
  71. ;  bit 4   -- RW Page Number  ( H12 =? )
  72. ;  bit 5   -- Address Maping  ( HA13=0 => Memory, HA13=1 => Node Number )
  73. HA13            equ     020h
  74.  
  75. ; DE-600's CMD port Command
  76. SLT_NIC         equ     004h  ;select Network Interface Card
  77. SLT_PRN         equ     01Ch  ;select Printer
  78. NML_PRN         equ     0ECh  ;normal Printer situation
  79. IRQEN           equ     010h  ;enable IRQ line
  80.  
  81. ; DE-600's STAT port bits 7-4
  82. RXBUSY          equ     80h
  83. GOOD            equ     40h
  84. RESET_FLAG      equ     20h
  85. T16             equ     10h
  86. TXBUSY          equ     08h
  87.  
  88. BFRSIZ          equ     2048    ;number of bytes in a buffer
  89. PRNTABADD       equ     408h    ;DOS printer table address
  90. RX_MIN_LEN      equ     18      ;= EADDR_LEN + EADDR_LEN + TYPE_LEN + CRC
  91.  
  92. write_sub_delay    macro    reg
  93.     mov     al,reg            ;output the low nibble.
  94.     shl     al,cl            ;cl must be four.
  95.     or      al,ch
  96.     xor     al,08h            ;raise the write line.
  97.     out     dx,al
  98.     call    delay
  99.  
  100.     xor     al,08h            ;lower the write line
  101.     out     dx,al
  102.     call    delay
  103.  
  104.     mov     al,reg            ;output the high nibble.
  105.     and     al,not 0fh        ;get us some zero bits.
  106.     or      al,ch
  107.     out     dx,al            ;(write line is low).
  108.     call    delay
  109.  
  110.     xor     al,08h            ;raise the write line.
  111.     out     dx,al
  112.     endm
  113.  
  114. write_sub_fast    macro    reg
  115.     mov     al,reg            ;output the low nibble.
  116.     shl     al,cl            ;cl must be four.
  117.     or      al,ch
  118.     out     dx,al
  119.  
  120.     mov     al,reg            ;output the high nibble.
  121.     and     al,not 0fh        ;get us some zero bits.
  122.     or      al,ch
  123.     xor     al,08h            ;raise the write line.
  124.     out     dx,al            ;(write line is low).
  125.     endm
  126.  
  127. write_sub_slow    macro    reg
  128.     mov     al,reg            ;output the low nibble.
  129.     shl     al,cl            ;cl must be four.
  130.     or      al,ch
  131.     out     dx,al
  132.     call    delay
  133.  
  134.     mov     al,reg            ;output the high nibble.
  135.     and     al,not 0fh        ;get us some zero bits.
  136.     or      al,ch
  137.     xor     al,08h            ;raise the write line.
  138.     out     dx,al            ;(write line is low).
  139.     endm
  140.  
  141. read_sub_fast    macro    reg
  142.     setport DAT
  143.     mov     al,ch
  144.     out     dx,al
  145.     pause
  146.  
  147.     setport STAT
  148.     in      al,dx
  149.     mov     reg,al
  150.     setport DAT
  151.     mov     al,ch
  152.     xor     al,08h
  153.     out     dx,al
  154.     pause
  155.  
  156.     setport STAT
  157.     in      al,dx
  158.     shr     reg,cl
  159.     and     al,0f0h
  160.     or      reg,al
  161.     endm
  162.  
  163.  
  164. read_sub_slow    macro    reg
  165.     setport DAT
  166.     mov     al,ch
  167.     out     dx,al
  168.     call    delay
  169.  
  170.     setport STAT
  171.     in      al,dx
  172.     mov     reg,al
  173.     setport DAT
  174.     mov     al,ch
  175.     xor     al,08h
  176.     out     dx,al
  177.     call    delay
  178.  
  179.     setport STAT
  180.     in      al,dx
  181.     shr     reg,cl
  182.     and     al,0f0h
  183.     or      reg,al
  184.     endm
  185.  
  186.  
  187. read_sub_delay    macro    reg, first
  188.     setport DAT
  189.     mov     al,ch
  190.   if first
  191.     xor     al,08h
  192.   endif
  193.     out     dx,al
  194.     call    delay
  195.  
  196.   if first
  197.     xor     al,08h
  198.     out     dx,al
  199.     call    delay
  200.   endif
  201.  
  202.     setport STAT
  203.     in      al,dx
  204.     mov     reg,al
  205.     setport DAT
  206.     mov     al,ch
  207.     xor     al,08h
  208.     out     dx,al
  209.     call    delay
  210.  
  211.     setport STAT
  212.     in      al,dx
  213.     shr     reg,cl
  214.     and     al,0f0h
  215.     or      reg,al
  216.     endm
  217.  
  218.  
  219. pause    macro
  220.     jmp    $+2
  221.     endm
  222.  
  223.     public  int_no
  224. int_no          db      7,0,0,0         ; IRQ interrupt number
  225. io_addr         dw      03bch,0         ; I/O address for card (jumpers)
  226.  
  227.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  228. driver_class    db      BLUEBOOK, IEEE8023, 0 ;from the packet spec
  229. driver_type     db      31              ;from the packet spec
  230. driver_name     db      'DE600',0      ;name of the driver
  231. driver_function    db    2
  232. parameter_list    label    byte
  233.     db    1    ;major rev of packet driver
  234.     db    9    ;minor rev of packet driver
  235.     db    14    ;length of parameter list
  236.     db    EADDR_LEN    ;length of MAC-layer address
  237.     dw    GIANT    ;MTU, including MAC headers
  238.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  239.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  240.     dw    0    ;(# of successive xmits) - 1
  241. int_num    dw    0    ;Interrupt # to hook for post-EOI
  242.             ;processing, 0 == none,
  243.  
  244.     public    rcv_modes
  245. rcv_modes    dw    7        ;number of receive modes in our table.
  246.         dw    0               ;There is no mode zero
  247.         dw    rcv_mode_1
  248.         dw    0
  249.         dw    rcv_mode_3
  250.         dw    0
  251.         dw    rcv_mode_5
  252.         dw    rcv_mode_6
  253.  
  254. CurTxPage       db      08h             ;the BL value when OUT DATA,TX_ADR
  255. CurRxPage       db      20h             ;the BL value when OUT DATA,COMMAND
  256. TxStartAdd      dw      ?
  257. RxStartAdd      dw      ?
  258. InitRxTxReg     dw      ?
  259. RxPktLen        dw      ?
  260. TxPktLen        dw      ?
  261. Mode_RxPg       db      ?
  262. Mode            db      RX_BP
  263. IRQinverse      db      0               ; = 40h for XT printer adapter
  264. NICstatus       db      0
  265. In_ISR          db      0
  266. In_Tx           db      0
  267. printer         dw      408h
  268. PS2             db      0
  269.  
  270. our_type        dw      ?,?
  271.  
  272.  
  273.     public bad_command_intercept
  274. bad_command_intercept:
  275. ;called with ah=command, unknown to the skeleton.
  276. ;exit with nc if okay, cy, dh=error if not.
  277.     mov    dh,BAD_COMMAND
  278.     stc
  279.     ret
  280.  
  281.     public    as_send_pkt
  282. ; The Asynchronous Transmit Packet routine.
  283. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  284. ;   interrupts possibly enabled.
  285. ; Exit with nc if ok, or else cy if error, dh set to error number.
  286. ;   es:di and interrupt enable flag preserved on exit.
  287. as_send_pkt:
  288.     ret
  289.  
  290.     public    drop_pkt
  291. ; Drop a packet from the queue.
  292. ; Enter with es:di -> iocb.
  293. drop_pkt:
  294.     assume    ds:nothing
  295.     ret
  296.  
  297.     public    xmit
  298. ; Process a transmit interrupt with the least possible latency to achieve
  299. ;   back-to-back packet transmissions.
  300. ; May only use ax and dx.
  301. xmit:
  302.     assume    ds:nothing
  303.     ret
  304.  
  305.  
  306.     public  send_pkt
  307. send_pkt:
  308. ;enter with ds:si -> packet, cx = packet length.
  309. ;exit with nc if ok, or else cy if error, dh set to error number.
  310.     assume  ds:nothing
  311.     cmp    cx,GIANT        ; Is this packet too large?
  312.     ja    send_pkt_toobig
  313.  
  314. ;select DE-600
  315.     mov     al,SLT_NIC
  316. ;*** CMD sub ***
  317.     loadport
  318.     setport CMD
  319.     out     dx,al
  320. ;*** End CMD sub ***
  321.     mov     In_Tx,1
  322.     call    delay
  323.  
  324.     cmp     cx,RUNT         ; minimum length for Ether
  325.     jae     LengthOK
  326.     mov     cx,RUNT         ; make sure size at least RUNT
  327. LengthOK:
  328.     inc     cx
  329.     and     cx,not 1
  330.  
  331.     mov     di,cx
  332. ;change Tx page to another free buffer
  333.     xor     CurTxPage,08h
  334.  
  335.     mov     bx,offset send_pkt_pointer
  336.     jmp     cs:[bx]
  337.  
  338. send_pkt_toobig:
  339.     mov    dh,NO_SPACE
  340.     stc
  341.     ret
  342.  
  343. send_pkt_pointer        dw      offset send_pkt0
  344.  
  345. send_pkt0:
  346. ;set Tx Pointer for moving packet
  347.     mov     ax,BFRSIZ
  348.     sub     ax,cx           ;AX = the pointer to TX
  349.     or      ah,CurTxPage
  350.     mov     TxStartAdd,ax   ;save Current Tx Packet Start Address
  351.     mov     bx,ax           ;write memory address
  352.     mov     cx,RW_ADR
  353.     setport DAT
  354.     write_sub_fast    bl
  355.     write_sub_fast    bh
  356.     cld
  357.     mov     cx,WRITE        ;write packet into memory
  358.     mov     ah,ch
  359.     xor     ah,08h
  360. write_mem:
  361.     lodsb
  362.     mov     bl,al
  363.     shl     al,cl
  364.     or      al,ch
  365.     out     dx,al
  366.  
  367.     mov     al,bl
  368.     and     al,0f0h
  369.     or      al,ah
  370.     dec     di
  371.     out     dx,al
  372.     jnz     write_mem
  373.  
  374.     mov     cx,4000h
  375.     setport STAT
  376. wait_Tx_idle:
  377.     in      al,dx
  378.     test    al,TXBUSY       ; Is the previous Tx successful ?
  379.     jz      command_to_Tx   ; Yes, TXBUSY is low. Then could Tx next packet.
  380.     loop    wait_Tx_idle
  381.  
  382. command_to_Tx:
  383. ;set Tx Pointer at beginning of packet
  384.     mov     bx,TxStartAdd
  385.     mov     cx,TX_ADR
  386.     loadport
  387.     setport DAT
  388.     write_sub_fast    bl
  389.     write_sub_fast    bh
  390.  
  391. ;Enable interrupt and start Tx
  392.     mov     bl,Mode_RxPg
  393.     mov     cx,COMMAND
  394.     write_sub_fast    bl
  395.     or      bl,TXEN
  396.     write_sub_fast    bl
  397.  
  398. Exit_Send_Packet:
  399.     mov     In_Tx,0
  400.  
  401.     cmp     In_ISR,0
  402.     jne     using_NIC_now
  403.     mov     al,SLT_PRN
  404.     loadport
  405.     setport CMD
  406.     out     dx,al
  407.  
  408.     cmp     PS2,0
  409.     jnz     using_NIC_now
  410.     setport STAT
  411.     in      al,dx
  412.     and     al,40h
  413.     xor     al,IRQinverse
  414.     jz      using_NIC_now
  415.     call    trigger_int
  416. using_NIC_now:
  417.     clc
  418.     ret
  419.  
  420.  
  421. send_pkt1:
  422. ;set Tx Pointer for moving packet
  423.     mov     ax,BFRSIZ
  424.     sub     ax,cx           ;AX = the pointer to TX
  425.     or      ah,CurTxPage
  426.     mov     TxStartAdd,ax   ;save Current Tx Packet Start Address
  427.     mov     bx,ax           ;write memory address
  428.     mov     cx,RW_ADR
  429.     loadport
  430.     setport DAT
  431.     write_sub_slow    bl
  432.     call    delay
  433.     write_sub_slow    bh
  434.  
  435.     cld
  436.     mov     cx,WRITE        ;write packet into memory
  437.     mov     ah,ch
  438.     xor     ah,08h
  439. write_mem1:
  440.     lodsb
  441.     mov     bl,al
  442.     shl     al,cl
  443.     or      al,ch
  444.     out     dx,al
  445.     call    delay
  446.  
  447.     mov     al,bl
  448.     and     al,0f0h
  449.     or      al,ah
  450.     dec     di
  451.     out     dx,al
  452.     call    delay
  453.     jnz     write_mem1
  454.  
  455.     mov     cx,4000h
  456.     setport STAT
  457. wait_Tx_idle1:
  458.     in      al,dx
  459.     test    al,TXBUSY       ; Is the previous Tx successful ?
  460.     jz      command_to_Tx1  ; Yes, TXBUSY is low. Then could Tx next packet.
  461.     loop    wait_Tx_idle1
  462.  
  463. command_to_Tx1:
  464. ;set Tx Pointer at beginning of packet
  465.     mov     bx,TxStartAdd
  466.     mov     cx,TX_ADR
  467.     loadport
  468.     setport DAT
  469.     write_sub_slow    bl
  470.     call    delay
  471.     write_sub_slow    bh
  472.     call    delay
  473.  
  474. ;Enable interrupt and start Tx
  475.     mov     bl,Mode_RxPg
  476.     mov     cx,COMMAND
  477.     write_sub_slow    bl
  478.     call    delay
  479.     or      bl,TXEN
  480.     write_sub_slow    bl
  481.     jmp     Exit_Send_Packet
  482.  
  483.  
  484. send_pkt2:
  485. ;set Tx Pointer for moving packet
  486.     mov     ax,BFRSIZ
  487.     sub     ax,cx           ;AX = the pointer to TX
  488.     or      ah,CurTxPage
  489.     mov     TxStartAdd,ax   ;save Current Tx Packet Start Address
  490.     mov     bx,ax           ;write memory address
  491.     mov     cx,RW_ADR
  492.     loadport
  493.     setport DAT
  494.     write_sub_delay    bl
  495.     call    delay
  496.     write_sub_delay    bh
  497.     cld
  498.     mov     cx,WRITE        ;write packet into memory
  499. write_mem2:
  500.     lodsb
  501.     mov     bl,al            ;except for this line,
  502.     shl     al,cl            ;  it's write_sub_delay
  503.     or      al,ch
  504.     xor     al,08h
  505.     out     dx,al
  506.     call    delay
  507.  
  508.     xor     al,08h
  509.     out     dx,al
  510.     call    delay
  511.  
  512.     mov     al,bl
  513.     and     al,0f0h
  514.     or      al,ch
  515.     out     dx,al
  516.     call    delay
  517.  
  518.     xor     al,08h
  519.     out     dx,al
  520.     call    delay
  521.     dec     di
  522.     jnz     write_mem2
  523.  
  524.     mov     cx,4000h
  525.     setport STAT
  526. wait_Tx_idle2:
  527.     in      al,dx
  528.     test    al,TXBUSY       ; Is the previous Tx successful ?
  529.     jz      command_to_Tx2  ; Yes, TXBUSY is low. Then could Tx next packet.
  530.     loop    wait_Tx_idle2
  531.  
  532. command_to_Tx2:
  533. ;set Tx Pointer at beginning of packet
  534.     mov     bx,TxStartAdd
  535.     mov     cx,TX_ADR
  536.     loadport
  537.     setport DAT
  538.     write_sub_delay    bl
  539.     call    delay
  540.     write_sub_delay    bh
  541.     call    delay
  542.  
  543. ;Enable interrupt and start Tx
  544.     mov     bl,Mode_RxPg
  545.     mov     cx,COMMAND
  546.     write_sub_delay    bl
  547.     call    delay
  548.     or      bl,TXEN
  549.     write_sub_delay    bl
  550.     jmp     Exit_Send_Packet
  551.  
  552.  
  553. trigger_int:
  554.     mov     al,SLT_NIC
  555.     call    CMD_sub
  556.  
  557.     mov     bl,Mode_RxPg
  558.     xor     bl,BIT6
  559.     mov     cx,COMMAND
  560.     call    Write_sub
  561.  
  562.     mov     al,SLT_PRN
  563.     call    CMD_sub
  564.  
  565.     call    delay
  566.     call    delay
  567.  
  568.     mov     al,SLT_NIC
  569.     call    CMD_sub
  570.  
  571.     mov     bl,Mode_RxPg
  572.     mov     cx,COMMAND
  573.     call    Write_sub
  574.     ret
  575.  
  576.  
  577. rcv_mode_1:
  578.     mov     cl,RX_NONE
  579.     jmp     short set_RXCR
  580. rcv_mode_3:
  581.     mov     cl,RX_BP
  582.     jmp     short set_RxCR
  583. rcv_mode_5:
  584.     mov     cl,RX_MBP
  585.     jmp     short set_RxCR
  586. rcv_mode_6:
  587.     mov     cl,RX_ALL
  588. set_RxCR:
  589.     mov     Mode,cl
  590.     mov     bl,cl
  591.     or      bl,CurRxPage            ; Add original Rx Page
  592.     mov     Mode_RxPg,bl            ; Save Rx Mode & Rx Page
  593. ;select DE-600
  594.     loadport
  595.     setport CMD
  596.     in      al,dx
  597.     pause
  598.     test    al,BIT4
  599.     jz      in_IC_mode
  600. ;not active, we have to put a wrapper around it.
  601.     mov     al,int_no
  602.     call    maskint
  603.  
  604.     mov     al,SLT_NIC        ;turn on the NIC.
  605.     call    CMD_sub
  606.     call    in_IC_mode        ;now we're in the right mode.
  607.     mov     al,SLT_PRN        ;turn on the PRN.
  608.     call    CMD_sub
  609.  
  610.     mov     al,int_no
  611.     call    unmaskint
  612.     ret
  613.  
  614. in_IC_mode:
  615.     mov     cx,COMMAND              ; Set new Rx Mode
  616.     call    Write_sub
  617.     ret
  618.  
  619.  
  620.     extrn   maskint : near
  621.     extrn   unmaskint : near
  622.  
  623.     public  set_address
  624. set_address:
  625. ;Set Ethernet address on controller
  626. ;enter with ds:si -> Ethernet address, CX = length of address.
  627. ;exit with nc if okay, or cy, dh=error if any errors.
  628. ;
  629.     assume  ds:nothing
  630.     cmp     cx,EADDR_LEN            ;make sure that we have enough room.
  631.     je      can_set_address
  632.     mov     dh,BAD_ADDRESS
  633.     stc
  634.     jmp     set_address_none
  635.  
  636. ;select DE-600
  637. can_set_address:
  638.     loadport
  639.     setport CMD
  640.     in      al,dx
  641.     push    ax
  642.     test    al,BIT4
  643.     jz      IC_mode
  644.  
  645.     mov     al,int_no
  646.     call    maskint
  647.     mov     al,SLT_NIC
  648.     call    CMD_sub
  649. IC_mode:
  650.     mov     cx,RW_ADR
  651.     xor     bl,bl
  652.     call    Write_sub
  653.     or      bl,HA13
  654.     call    Write_sub
  655.  
  656.     cld
  657.     mov     bp,cs
  658.     mov     es,bp
  659.  
  660.     mov     di,EADDR_LEN
  661.     mov     cx,WRITE
  662. set_our_address:
  663.     lodsb
  664.     mov     bl,al
  665.     call    Write_sub
  666.     dec     di
  667.     jnz     set_our_address
  668.  
  669.     pop     ax
  670.     test    al,BIT4
  671.     jz      IC_mode1
  672.  
  673.     mov     al,SLT_PRN
  674.     call    CMD_sub
  675.     mov     al,int_no
  676.     call    unmaskint
  677. IC_mode1:
  678.     clc
  679. set_address_none:
  680.     push    cs
  681.     pop     ds
  682.     assume  ds:code
  683.     ret
  684.  
  685.  
  686.     public    set_multicast_list
  687. set_multicast_list:
  688. ;enter with ds:si ->list of multicast addresses, ax = number of addresses,
  689. ;  cx = number of bytes.
  690. ;return nc if we set all of them, or cy,dh=error if we didn't.
  691.     mov    dh,NO_MULTICAST
  692.     stc
  693.     ret
  694.  
  695.  
  696.     public    terminate
  697. terminate:
  698.     ret
  699.  
  700.  
  701.     public  reset_interface
  702. reset_interface:
  703.     mov     al,int_no
  704.     call    maskint
  705. ;select DE-600
  706.  
  707.     mov     al,SLT_NIC
  708.     call    CMD_sub
  709.  
  710. ; Pulse IE_RESET
  711.     mov     bl,RESET
  712.     mov     cx,COMMAND
  713.     call    Write_sub
  714.     mov     bl,STOP_RESET
  715.     call    Write_sub
  716.  
  717. ; Initialize Rx buffer pointer, and start receive
  718.     mov     bl,Mode_RxPg
  719.     mov     cx,COMMAND
  720.     call    Write_sub
  721.     or      bl,RXEN
  722.     call    Write_sub
  723.  
  724. ; Enable Printer Adapter IRQ line
  725.     mov     al,SLT_PRN
  726.     call    CMD_sub
  727.  
  728.     mov     al,int_no
  729.     call    unmaskint
  730.     ret
  731.  
  732.  
  733.     assume  ds:nothing
  734. Write_sub:
  735.     loadport
  736.     setport DAT
  737.     write_sub_delay    bl
  738.     ret
  739.  
  740. Read_sub:
  741.     loadport
  742.     setport DAT
  743.     mov     al,ch
  744.     xor     al,08h
  745.     out     dx,al
  746.     call    delay
  747.  
  748.     xor     al,08h
  749.     out     dx,al
  750.     call    delay
  751.  
  752.     setport STAT
  753.     in      al,dx
  754.     mov     bl,al
  755.     test    ch,BIT1
  756.     jz      not_READ_STATUS
  757.     dec     dx
  758.     mov     al,NUL_CMD
  759.     xor     al,08h
  760.     out     dx,al
  761.     call    delay
  762.  
  763.     xor     al,08h
  764.     out     dx,al
  765.     jmp     short End_read
  766. not_READ_STATUS:
  767.     setport DAT
  768.     mov     al,ch
  769.     xor     al,08h
  770.     out     dx,al
  771.     call    delay
  772.  
  773.     setport STAT
  774.     in      al,dx
  775.     shr     bl,cl
  776.     and     al,0f0h
  777.     or      bl,al
  778. End_read:
  779.     ret
  780.  
  781. CMD_sub:
  782.     loadport
  783.     setport CMD
  784.     out     dx,al
  785.     ret
  786.  
  787. delay:
  788.     nop     ; pointer 0
  789.     nop     ;         1
  790.     nop     ;         2
  791.     nop     ;         3
  792.     nop     ;         4
  793.     nop     ;         5
  794.     nop     ;         6
  795.     nop     ;         7
  796.     nop     ;         8
  797.     nop     ;         9
  798.     ret
  799.  
  800. ;called when we want to determine what to do with a received packet.
  801. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  802.     extrn   recv_find: near
  803.  
  804. ;called after we have copied the packet into the buffer.
  805. ;enter with ds:si ->the packet, cx = length of the packet.
  806.     extrn   recv_copy: near
  807.  
  808.     extrn   count_in_err: near
  809.     extrn   count_out_err: near
  810.  
  811. recv_pointer    dw      offset recv0
  812.  
  813.     public  recv
  814. recv:
  815. ;called from the recv isr.  All registers have been saved, and ds=cs.
  816. ;Upon exit, the interrupt will be acknowledged.
  817.     assume  ds:code
  818. ;select DE-600
  819.     mov     al,SLT_NIC
  820. ;*** CMD sub ***
  821.     loadport
  822.     setport CMD
  823.     out     dx,al
  824. ;*** End CMD sub ***
  825. ;set watch dog
  826.     mov     In_ISR,1
  827.     call    delay
  828.  
  829. ;Check the interrupt source, Rx or Tx ?
  830.     mov     cx,STATUS               ; Read NIC Status Register
  831. ;*** Read sub ***
  832.     setport DAT
  833.     mov     al,ch
  834.     out     dx,al
  835.     pause
  836.     setport STAT
  837.     in      al,dx
  838. ;*** End Read sub ***
  839.  
  840.     jmp    recv_pointer
  841.  
  842. recv0:
  843.     mov     NICstatus,al            ; save NIC status
  844.     setport DAT
  845.     test    al,GOOD                 ; Is Rx generating interrupt ?
  846.     mov     al,NUL_CMD
  847.     out     dx,al
  848.     jnz     Rx_Good_Pkt             ; Yes, take care of this situation.
  849.     mov     al,NICstatus
  850.     test    al,RXBUSY
  851.     jz      Enable_Rx
  852.     jmp     CheckTx
  853.  
  854. Enable_Rx:
  855. ;change Rx page & enable NIC to Rx
  856.     mov     bl,Mode_RxPg
  857.     mov     cx,COMMAND
  858.     setport DAT
  859.     write_sub_fast    bl
  860.     or      bl,RXEN
  861.     write_sub_fast    bl
  862.     jmp     CheckTx
  863.  
  864. Rx_Good_Pkt:
  865. ;Put it on the receive queue
  866.     mov     cx,RX_LEN               ; read Rx Packet Length
  867.     loadport
  868.     read_sub_fast    bl
  869.     read_sub_fast    bh
  870.  
  871.     sub     bx,4                    ;subtrate 4 CRC Byte Count
  872.     mov     RxPktLen,bx             ;save Rx Packet Length
  873.  
  874. ;change Rx page & enable NIC to Rx
  875.     xor     Mode_RxPg,10h
  876.     mov     bl,Mode_RxPg
  877.     mov     cx,COMMAND
  878.     setport DAT
  879.     write_sub_fast    bl
  880.     or      bl,RXEN
  881.     write_sub_fast    bl
  882.     xor     bx,bx
  883.     mov     bh,CurRxPage            ;BL = Current Rx Page
  884.     xor     CurRxPage,10h           ;change to next page for Rx
  885.     shr     bx,1                    ;shift BX to real memory address
  886.     mov     RxStartAdd,bx           ;save just Rx Packet Start Address
  887.  
  888.     add     bx,EADDR_LEN+EADDR_LEN  ;seek to the TYPE word
  889.     mov     cx,RW_ADR
  890.     write_sub_fast    bl
  891.     write_sub_fast    bh
  892.     pause
  893.     mov     cx,READ            ;read the TYPE word
  894.     read_sub_fast    bl
  895.     read_sub_fast    bh
  896.  
  897.     mov     our_type,bx        ;save the TYPE word
  898.  
  899.     mov     cx,READ            ;read the TYPE word
  900.     read_sub_fast    bl
  901.     read_sub_fast    bh
  902.  
  903.     mov     our_type[2],bx        ;save the TYPE word
  904.  
  905.     mov     ax,ds
  906.     mov     es,ax
  907.     mov     di,offset our_type
  908.     mov     cx,RxPktLen
  909.  
  910.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  911.     mov    ax, es:[di]
  912.     xchg    ah, al
  913.     cmp     ax, 1500
  914.     ja    BlueBookPacket
  915.     inc    di            ;set di to 802.2 header
  916.     inc    di
  917.     mov    dl, IEEE8023
  918. BlueBookPacket:
  919.     call    recv_find               ;request a Rx buffer to store Rx data
  920.  
  921.     mov     ax,es                   ;is this pointer null?
  922.     or      ax,di
  923.     jnz     find_buffer
  924.     jmp     short CheckTx                 ;yes - just free the frame.
  925. find_buffer:
  926.     push    es
  927.     push    di                   ;remember where the buffer pointer is.
  928.     assume  ds:nothing
  929.     mov     bx,RxStartAdd
  930.     mov     cx,RW_ADR
  931.     loadport
  932.     setport DAT
  933.     write_sub_fast    bl
  934.     write_sub_fast    bh
  935.  
  936.     cld
  937.     mov     bp,RxPktLen             ;CX = the byte count of Rx Packet
  938.     setport STAT
  939.     mov     cx,READ
  940.     mov     ah,ch
  941.     xor     ah,08h
  942. read_mem:
  943.     setport    DAT
  944.     mov     al,ch            ;output our read request.
  945.     out     dx,al
  946.     pause
  947.  
  948.     setport    STAT
  949.     in      al,dx            ;input four bits into bl.
  950.     mov     bl,al
  951.     setport    DAT            ;now output the inverse read request.
  952.     mov     al,ah
  953.     out     dx,al
  954.     pause
  955.  
  956.     setport    STAT
  957.     in      al,dx            ;input the high four bits.
  958.     shr     bl,cl
  959.     and     al,0f0h
  960.     or      al,bl            ;combine the two nibbles.
  961.     stosb
  962.     dec     bp
  963.     jnz     read_mem
  964.  
  965. RxCopy_CheckTx:
  966.     pop     si
  967.     pop     ds
  968.     mov     cx,RxPktLen
  969.  
  970.     call    recv_copy               ;tell them that we copied it.
  971.  
  972.     mov     ax,cs                   ;restore our ds.
  973.     mov     ds,ax
  974.     assume  ds:code
  975.  
  976. CheckTx:
  977.     test    NICstatus,T16           ; Is pending a Tx Packet ?
  978.     jz      return                  ; No, then return.
  979.                                     ; Yes, send this packet.
  980. ;set Tx Pointer at beginning of packet
  981.     mov     bx,TxStartAdd
  982.     mov     cx,TX_ADR
  983.     call    Write_sub
  984.     xchg    bh,bl
  985.     call    Write_sub
  986.  
  987. ;Enable interrupt and start Tx
  988.     mov     bl,Mode_RxPg
  989.     mov     cx,COMMAND
  990.     call    Write_sub
  991.     or      bl,TXEN
  992.     call    Write_sub
  993. return:
  994.     mov     al,SLT_PRN
  995. ;*** CMD sub ***
  996.     loadport
  997.     setport CMD
  998.     out     dx,al
  999. ;*** End CMD sub ***
  1000.  
  1001.     cmp     PS2,0
  1002.     jnz     Rx_another_pkt
  1003.     setport STAT
  1004.     in      al,dx
  1005.     and     al,40h
  1006.     xor     al,IRQinverse
  1007.     jz      Rx_another_pkt
  1008.     call    trigger_int
  1009. Rx_another_pkt:
  1010.     mov     In_ISR,0
  1011.     ret
  1012.  
  1013.  
  1014. recv1:
  1015.     assume  ds:code
  1016.     mov     NICstatus,al            ; save NIC status
  1017.     loadport
  1018.     setport DAT
  1019.     test    al,GOOD                 ; Is Rx generating interrupt ?
  1020.     mov     al,NUL_CMD
  1021.     out     dx,al
  1022.     jnz     Rx_Good_Pkt1             ; Yes, take care of this situation.
  1023.     mov     al,NICstatus
  1024.     test    al,RXBUSY
  1025.     jz      Enable_Rx1
  1026.     jmp     CheckTx                 ; No, go to check Tx.
  1027.  
  1028. Enable_Rx1:
  1029. ;change Rx page & enable NIC to Rx
  1030.     mov     bl,Mode_RxPg
  1031.     mov     cx,COMMAND
  1032.     setport DAT
  1033.     write_sub_slow    bl
  1034.     call    delay
  1035.     or      bl,RXEN
  1036.     write_sub_slow    bl
  1037.     jmp     CheckTx
  1038.  
  1039. Rx_Good_Pkt1:
  1040. ;Put it on the receive queue
  1041.     mov     cx,RX_LEN               ; read Rx Packet Length
  1042.     loadport
  1043.     read_sub_slow    bl
  1044.     read_sub_slow    bh
  1045.  
  1046.     sub     bx,4                    ;subtrate 4 CRC Byte Count
  1047.     mov     RxPktLen,bx             ;save Rx Packet Length
  1048.  
  1049. ;change Rx page & enable NIC to Rx
  1050.     xor     Mode_RxPg,10h
  1051.     mov     bl,Mode_RxPg
  1052.     mov     cx,COMMAND
  1053.     setport DAT
  1054.     write_sub_slow    bl
  1055.     call    delay
  1056.     or      bl,RXEN
  1057.     write_sub_slow    bl
  1058.     call    delay
  1059.     xor     bx,bx
  1060.     mov     bh,CurRxPage            ;BL = Current Rx Page
  1061.     xor     CurRxPage,10h           ;change to next page for Rx
  1062.     shr     bx,1                    ;shift BX to real memory address
  1063.     mov     RxStartAdd,bx           ;save just Rx Packet Start Address
  1064.  
  1065.     add     bx,EADDR_LEN+EADDR_LEN  ;seek to the TYPE word
  1066.     mov     cx,RW_ADR
  1067.     write_sub_slow    bl
  1068.     call    delay
  1069.     write_sub_slow    bh
  1070.     call    delay
  1071.     mov     cx,READ                 ;read the TYPE word
  1072.  
  1073.     read_sub_slow    bl
  1074.     read_sub_slow    bh
  1075.  
  1076.     mov     our_type,bx             ;save the TYPE word
  1077.  
  1078.     mov     ax,ds
  1079.     mov     es,ax
  1080.     mov     di,offset our_type
  1081.     mov     cx,RxPktLen
  1082.  
  1083.     call    recv_find               ;request a Rx buffer to store Rx data
  1084.  
  1085.     mov     ax,es                   ;is this pointer null?
  1086.     or      ax,di
  1087.     jnz     find_buffer1
  1088.     jmp     CheckTx                 ;yes - just free the frame.
  1089. find_buffer1:
  1090.     push    es
  1091.     push    di                   ;remember where the buffer pointer is.
  1092.     assume  ds:nothing
  1093.     mov     bx,RxStartAdd
  1094.     mov     cx,RW_ADR
  1095.     loadport
  1096.     setport DAT
  1097.     write_sub_slow    bl
  1098.     call    delay
  1099.     write_sub_slow    bh
  1100.     call    delay
  1101.  
  1102.     cld
  1103.     mov     bp,RxPktLen             ;CX = the byte count of Rx Packet
  1104.     setport STAT
  1105.     mov     cx,READ
  1106.     mov     ah,ch
  1107.     xor     ah,08h
  1108. read_mem1:
  1109.     dec     dx
  1110.     mov     al,ch
  1111.     out     dx,al
  1112.     call    delay
  1113.  
  1114.     inc     dx
  1115.     in      al,dx
  1116.     mov     bl,al
  1117.     dec     dx
  1118.     mov     al,ah
  1119.     out     dx,al
  1120.     call    delay
  1121.  
  1122.     inc     dx
  1123.     in      al,dx
  1124.     shr     bl,cl
  1125.     and     al,0f0h
  1126.     or      al,bl
  1127.     stosb
  1128.     dec     bp
  1129.     jnz     read_mem1
  1130.     jmp     RxCopy_CheckTx
  1131.  
  1132.  
  1133. recv2:
  1134.     assume  ds:code
  1135.     mov     NICstatus,al            ; save NIC status
  1136.     loadport
  1137.     setport DAT
  1138.     test    al,GOOD                 ; Is Rx generating interrupt ?
  1139.     mov     al,NUL_CMD
  1140.     out     dx,al
  1141.     jnz     Rx_Good_Pkt2             ; Yes, take care of this situation.
  1142.     mov     al,NICstatus
  1143.     test    al,RXBUSY
  1144.     jz      Enable_Rx2
  1145.     jmp     CheckTx                 ; No, go to check Tx.
  1146.  
  1147. Enable_Rx2:
  1148. ;change Rx page & enable NIC to Rx
  1149.     mov     bl,Mode_RxPg
  1150.     mov     cx,COMMAND
  1151.     setport DAT
  1152.     write_sub_delay    bl
  1153.     call    delay
  1154.     or      bl,RXEN
  1155.   if 0
  1156.     write_sub_delay    bl
  1157.   else
  1158.     mov     al,bl
  1159.     shl     al,cl
  1160.     or      al,ch
  1161.     xor     al,08h
  1162.     out     dx,al
  1163.     call    delay
  1164.  
  1165.     xor     al,08h
  1166.     out     dx,al
  1167.     call    delay
  1168.  
  1169.     mov     al,bl
  1170.     and     al,0f0h
  1171.     or      al,ch
  1172.     xor     al,08h
  1173.     out     dx,al
  1174.   endif
  1175.     jmp     CheckTx
  1176.  
  1177. Rx_Good_Pkt2:
  1178. ;Put it on the receive queue
  1179.     mov     cx,RX_LEN               ; read Rx Packet Length
  1180.     loadport
  1181.  
  1182.     read_sub_delay    bl, 1
  1183.     read_sub_delay    bh, 0
  1184.  
  1185.     sub     bx,4                    ;subtrate 4 CRC Byte Count
  1186.     mov     RxPktLen,bx             ;save Rx Packet Length
  1187.  
  1188. ;change Rx page & enable NIC to Rx
  1189.     xor     Mode_RxPg,10h
  1190.     mov     bl,Mode_RxPg
  1191.     mov     cx,COMMAND
  1192.     setport DAT
  1193.     write_sub_delay    bl
  1194.     call    delay
  1195.     or      bl,RXEN
  1196.     write_sub_delay    bl
  1197.     call    delay
  1198.  
  1199.     xor     bx,bx
  1200.     mov     bh,CurRxPage            ;BL = Current Rx Page
  1201.     xor     CurRxPage,10h           ;change to next page for Rx
  1202.     shr     bx,1                    ;shift BX to real memory address
  1203.     mov     RxStartAdd,bx           ;save just Rx Packet Start Address
  1204.  
  1205.     add     bx,EADDR_LEN+EADDR_LEN  ;seek to the TYPE word
  1206.     mov     cx,RW_ADR
  1207.     write_sub_delay    bl
  1208.     call    delay
  1209.     write_sub_delay    bh
  1210.     call    delay
  1211.  
  1212.     mov     cx,READ                 ;read the TYPE word
  1213.  
  1214.     read_sub_delay    bl, 1
  1215.     read_sub_delay    bh, 0
  1216.     mov     our_type,bx             ;save the TYPE word
  1217.  
  1218.     mov     ax,ds
  1219.     mov     es,ax
  1220.     mov     di,offset our_type
  1221.     mov     cx,RxPktLen
  1222.  
  1223.     call    recv_find               ;request a Rx buffer to store Rx data
  1224.  
  1225.     mov     ax,es                   ;is this pointer null?
  1226.     or      ax,di
  1227.     jnz     find_buffer2
  1228.     jmp     CheckTx                 ;yes - just free the frame.
  1229. find_buffer2:
  1230.     push    es
  1231.     push    di                   ;remember where the buffer pointer is.
  1232.     assume  ds:nothing
  1233.     mov     bx,RxStartAdd
  1234.     mov     cx,RW_ADR
  1235.     loadport
  1236.     setport DAT
  1237.     write_sub_delay    bl
  1238.     call    delay
  1239.     write_sub_delay    bh
  1240.     call    delay
  1241.  
  1242.     cld
  1243.     mov     bp,RxPktLen             ;CX = the byte count of Rx Packet
  1244.     setport STAT
  1245.     mov     cx,READ
  1246.     mov     ah,ch
  1247.     xor     ah,08h
  1248. read_mem2:
  1249.     dec     dx
  1250.     mov     al,ch
  1251.     out     dx,al
  1252.     call    delay
  1253.  
  1254.     inc     dx
  1255.     in      al,dx
  1256.     mov     bl,al
  1257.     dec     dx
  1258.     mov     al,ah
  1259.     out     dx,al
  1260.     call    delay
  1261.  
  1262.     inc     dx
  1263.     in      al,dx
  1264.     shr     bl,cl
  1265.     and     al,0f0h
  1266.     or      al,bl
  1267.     stosb
  1268.     dec     bp
  1269.     jnz     read_mem2
  1270.     jmp     RxCopy_CheckTx
  1271.  
  1272.  
  1273.     public  end_resident,end_free_mem
  1274. end_resident    label   byte
  1275. end_free_mem    label    byte
  1276.     public    timer_isr
  1277. timer_isr:
  1278. ;if the first instruction is an iret, then the timer is not hooked
  1279.     iret
  1280.  
  1281. ;any code after this will not be kept after initialization.
  1282.  
  1283.     public  usage_msg
  1284. usage_msg       db      "usage: DE600 [options] <packet_int_no>",CR,LF,'$'
  1285.  
  1286.     public  copyright_msg
  1287. copyright_msg   db      "Packet driver for the D-Link DE-600, "
  1288.             db      "version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF,'$'
  1289.             db      "Portions Copyright 1988, Robert C. Clements, K1BC"
  1290.             db      CR,LF,'$'
  1291.  
  1292. CableErr        db      "Bad cable connection.",07,CR,LF,'$'
  1293. mem_error_msg   db      "Adapter memory buffer failure, or bad printer "
  1294.             db      "port connection.",07,CR,LF,'$'
  1295. irq_error_msg   db      "IRQ unavailable, please check other hardware in "
  1296.             db      "computer.",07,CR,LF,'$'
  1297. no_NIC_err      db      "Adapter not found, or AC adapter power is off.",07,CR,LF,'$'
  1298.  
  1299.     extrn   set_recv_isr: near
  1300.  
  1301. ;enter with si -> argument string, di -> word to store.
  1302. ;if there is no number, don't change the number.
  1303.     extrn    get_number: near
  1304.  
  1305. ;enter with dx -> name of word, di -> dword to print.
  1306.     extrn    print_number: near
  1307.  
  1308. ;-> the assigned Ethernet address of the card.
  1309.     extrn    rom_address: byte
  1310.  
  1311.     assume  ds:code
  1312.     public  parse_args
  1313. parse_args:
  1314.     ret
  1315.  
  1316.  
  1317.     public  print_parameters
  1318. print_parameters:
  1319.     ret
  1320.  
  1321. cable_err:
  1322.     mov     dx,offset CableErr
  1323.     stc
  1324.     ret
  1325. IRQ_error:
  1326.     mov     dx,offset irq_error_msg
  1327.     stc
  1328.     ret
  1329. no_our_NIC:
  1330.     mov     dx,offset no_NIC_err
  1331.     stc
  1332.     ret
  1333.  
  1334.     public  etopen
  1335. etopen:
  1336. ;  Initialize the Ethernet board.
  1337.     call    check_PS2
  1338.  
  1339.     xor     ax,ax
  1340.     mov     es,ax
  1341.     mov     si,PRNTABADD-2          ; point to printer table at low memory
  1342. next_prn_port:
  1343.     add     si,2
  1344.     mov     bx,es:[si]              ; get LPTx's I/O Base
  1345.     or      bx,bx                   ; Does LPTx really exist ?
  1346.     jz      Chk_out_of_range
  1347.     mov     io_addr,bx              ; save the I/O Base number
  1348.     mov     printer,si              ; memorize it's LPTx now
  1349.     call    Check_DE600             ; Yes, BX = I/O Base, then check.
  1350.     jnc     IO_good                 ; If carry flag is clear, so go to
  1351.     mov     al,NML_PRN
  1352.     call    CMD_sub
  1353. Chk_out_of_range:
  1354.     cmp     si,PRNTABADD+6          ; We still miss our card from LPT1 to
  1355.     jb      next_prn_port
  1356.     jmp     short no_our_NIC        ; We still miss our card from LPT1 to
  1357.                                     ; LPT4. We give it up.
  1358. IO_good:
  1359. ; Copy our Ethernet address from PROM into DE600.
  1360.     push    ds
  1361.     pop     es
  1362.     mov     di,offset rom_address
  1363.     mov     cx,RW_ADR
  1364.     xor     bl,bl
  1365.     call    Write_sub
  1366.     or      bl,HA13
  1367.     call    Write_sub
  1368.  
  1369.     cld
  1370.     mov     bp,EADDR_LEN
  1371.     mov     cx,READ
  1372. get_our_address:
  1373.     call    Read_sub
  1374.     mov     al,bl
  1375.     stosb
  1376.     dec     bp
  1377.     jnz     get_our_address
  1378.  
  1379.     mov     si,offset rom_address    ;make sure it's got the right magic
  1380.     cmp     word ptr es:[si],0de00h    ;  number.
  1381.     jne     no_our_NIC
  1382.     cmp     byte ptr es:[si+2],15h
  1383.     jne     no_our_NIC
  1384.  
  1385.     mov     word ptr es:[si],8000h    ;now modify it to the address assigned
  1386.     mov     byte ptr es:[si+2],0c8h    ;  by Xerox.
  1387.     and     byte ptr es:[si+3],0fh
  1388.     or      byte ptr es:[si+3],070h
  1389.  
  1390.     mov     cx,EADDR_LEN
  1391.     call    set_address
  1392.  
  1393. ; Check DE600's IRQ enviroment
  1394.     call    Check_IRQ
  1395.     cmp     bx,1
  1396.     je      cable_OK
  1397.     jmp     cable_err
  1398.  
  1399. cable_OK:
  1400.     mov     bx,offset delay
  1401.     mov     byte ptr [bx],0c3h     ;  ret
  1402.  
  1403. ; test 8 KBytes memory
  1404. ;********** write mode 1 *************
  1405.     mov     cx,700h
  1406.     mov     al,PAGE3
  1407.     call    Write_LoopBack_Data
  1408.     xor     bx,bx
  1409.     mov     si,bx
  1410. write_next_page:
  1411.     call    Tx_Data
  1412.     push    bx
  1413.     mov     cx,RW_ADR
  1414.     loadport
  1415.     setport DAT
  1416.     write_sub_fast    bl
  1417.     write_sub_fast    bh
  1418.  
  1419.     mov     bx,si
  1420.     mov     bp,800h
  1421.     mov     cx,WRITE
  1422.     mov     ah,ch
  1423.     xor     ah,08h
  1424. wr_this_page:
  1425.     mov     al,bl
  1426.     shl     al,cl
  1427.     or      al,ch
  1428.     out     dx,al
  1429.     mov     al,bl
  1430.     and     al,0f0h
  1431.     or      al,ah
  1432.     out     dx,al
  1433.     inc     bl
  1434.     dec     bp
  1435.     jnz     wr_this_page
  1436.     inc     si
  1437.     pop     bx
  1438.     add     bx,800h
  1439.     cmp     bx,1800h
  1440.     ja      read_memory
  1441.     jmp     short write_next_page
  1442.  
  1443. ;************ read mode 1 ************
  1444. read_memory:
  1445.     loadport
  1446.     setport DAT
  1447.     xor     bx,bx
  1448.     mov     si,bx
  1449. read_next_page:
  1450.     push    bx
  1451.     mov     cx,RW_ADR
  1452.     write_sub_fast    bl
  1453.     write_sub_fast    bh
  1454.  
  1455.     mov     bx,si
  1456.     mov     bp,800h
  1457.     mov     cx,READ
  1458.     mov     ah,ch
  1459.     xor     ah,08h
  1460. rd_this_page:
  1461.     mov     al,ch
  1462.     out     dx,al
  1463.     pause
  1464.     inc     dx
  1465.     in      al,dx
  1466.     mov     bh,al
  1467.     dec     dx
  1468.     mov     al,ah
  1469.     out     dx,al
  1470.     pause
  1471.     inc     dx
  1472.     in      al,dx
  1473.     shr     bh,cl
  1474.     and     al,0f0h
  1475.     or      bh,al
  1476.     cmp     bh,bl
  1477.     jne     memory_test
  1478.     dec     dx
  1479.     inc     bl
  1480.     dec     bp
  1481.     jnz     rd_this_page
  1482.     inc     si
  1483.     pop     bx
  1484.     add     bx,800h
  1485.     cmp     bx,1800h
  1486.     ja      mem_is_OK
  1487.     push    si
  1488.     push    bx
  1489.     mov     cx,700h
  1490.     mov     al,PAGE0
  1491.     call    Write_LoopBack_Data
  1492.     call    Tx_Data
  1493.     pop     bx
  1494.     pop     si
  1495.     jmp     short read_next_page
  1496. mem_is_OK:
  1497.     jmp     mem_OK
  1498.  
  1499. ;************ write mode 2 ***************
  1500. memory_test:
  1501.     pop     ax
  1502. memory_test1:
  1503.     mov     cx,700h
  1504.     mov     al,PAGE3
  1505.     call    Write_LoopBack_Data
  1506.     xor     bx,bx
  1507.     mov     si,bx
  1508. write_next_page1:
  1509.     call    Tx_Data
  1510.     push    bx
  1511.     mov     cx,RW_ADR
  1512.     loadport
  1513.     setport DAT
  1514.     write_sub_slow    bl
  1515.     call    delay
  1516.     write_sub_slow    bh
  1517.     call    delay
  1518.  
  1519.     mov     bx,si
  1520.     mov     bp,800h
  1521.     mov     cx,WRITE
  1522.     mov     ah,ch
  1523.     xor     ah,08h
  1524. wr_this_page1:
  1525.     mov     al,bl
  1526.     shl     al,cl
  1527.     or      al,ch
  1528.     out     dx,al
  1529.     call    delay
  1530.  
  1531.     mov     al,bl
  1532.     and     al,0f0h
  1533.     or      al,ah
  1534.     out     dx,al
  1535.     call    delay
  1536.     inc     bl
  1537.     dec     bp
  1538.     jnz     wr_this_page1
  1539.     inc     si
  1540.     pop     bx
  1541.     add     bx,800h
  1542.     cmp     bx,1800h
  1543.     ja      read_memory1
  1544.     jmp     short write_next_page1
  1545.  
  1546. ;************* read mode 2 **************
  1547. read_memory1:
  1548.     loadport
  1549.     setport DAT
  1550.     xor     bx,bx
  1551.     mov     si,bx
  1552. read_next_page1:
  1553.     push    bx
  1554.     mov     cx,RW_ADR
  1555.     write_sub_slow    bl
  1556.     call    delay
  1557.     write_sub_slow    bh
  1558.     call    delay
  1559.  
  1560.     mov     bx,si
  1561.     mov     bp,800h
  1562.     mov     cx,READ
  1563.     mov     ah,ch
  1564.     xor     ah,08h
  1565. rd_this_page1:
  1566.     mov     al,ch
  1567.     out     dx,al
  1568.     call    delay
  1569.  
  1570.     inc     dx
  1571.     in      al,dx
  1572.     mov     bh,al
  1573.     dec     dx
  1574.     mov     al,ah
  1575.     out     dx,al
  1576.     call    delay
  1577.  
  1578.     inc     dx
  1579.     in      al,dx
  1580.     shr     bh,cl
  1581.     and     al,0f0h
  1582.     or      bh,al
  1583.     cmp     bh,bl
  1584.     jne     memory_test2
  1585.     dec     dx
  1586.     inc     bl
  1587.     dec     bp
  1588.     jnz     rd_this_page1
  1589.     inc     si
  1590.     pop     bx
  1591.     add     bx,800h
  1592.     cmp     bx,1800h
  1593.     ja      mem_is_OK1
  1594.     push    si
  1595.     push    bx
  1596.     mov     cx,700h
  1597.     mov     al,PAGE0
  1598.     call    Write_LoopBack_Data
  1599.     call    Tx_Data
  1600.     pop     bx
  1601.     pop     si
  1602.     jmp     read_next_page1
  1603. mem_is_OK1:
  1604.     jmp     mem_OK1
  1605.  
  1606. ;************* write mode 3 ***************
  1607. memory_test2:
  1608.     pop     ax
  1609. memory_test3:
  1610.     mov     cx,700h
  1611.     mov     al,PAGE3
  1612.     call    Write_LoopBack_Data
  1613.     xor     bx,bx
  1614.     mov     si,bx
  1615. write_next_page3:
  1616.     call    Tx_Data
  1617.     push    bx
  1618.     mov     cx,RW_ADR
  1619.     loadport
  1620.     setport DAT
  1621.     write_sub_delay    bl
  1622.     call    delay
  1623.     write_sub_delay    bh
  1624.     call    delay
  1625.  
  1626.     mov     bx,si
  1627.     mov     bp,800h
  1628.     mov     cx,WRITE
  1629. wr_this_page3:
  1630.     mov     al,bl
  1631.     shl     al,cl
  1632.     or      al,ch
  1633.     xor     al,08h
  1634.     out     dx,al
  1635.     call    delay
  1636.  
  1637.     xor     al,08h
  1638.     out     dx,al
  1639.     call    delay
  1640.  
  1641.     mov     al,bl
  1642.     and     al,0f0h
  1643.     or      al,ch
  1644.     out     dx,al
  1645.     call    delay
  1646.  
  1647.     xor     al,08h
  1648.     out     dx,al
  1649.     call    delay
  1650.     inc     bl
  1651.     dec     bp
  1652.     jnz     wr_this_page3
  1653.     inc     si
  1654.     pop     bx
  1655.     add     bx,800h
  1656.     cmp     bx,1800h
  1657.     ja      read_memory3
  1658.     jmp     write_next_page3
  1659.  
  1660. ;************* read mode 3 ***************
  1661. read_memory3:
  1662.     loadport
  1663.     setport DAT
  1664.     xor     bx,bx
  1665.     mov     si,bx
  1666. read_next_page3:
  1667.     push    bx
  1668.     mov     cx,RW_ADR
  1669.     write_sub_delay    bl
  1670.     call    delay
  1671.     write_sub_delay    bh
  1672.  
  1673.     call    delay
  1674.  
  1675.     mov     bx,si
  1676.     mov     bp,800h
  1677.     mov     cx,READ
  1678.     mov     ah,ch
  1679.     xor     ah,08h
  1680.  
  1681.     mov     al,ch
  1682.     xor     al,08h
  1683.     out     dx,al
  1684.     call    delay
  1685. rd_this_page3:
  1686.     mov     al,ch
  1687.     out     dx,al
  1688.     call    delay
  1689.  
  1690.     setport STAT
  1691.     in      al,dx
  1692.     mov     bh,al
  1693.     setport DAT
  1694.     mov     al,ah
  1695.     out     dx,al
  1696.     call    delay
  1697.  
  1698.     setport STAT
  1699.     in      al,dx
  1700.     shr     bh,cl
  1701.     and     al,0f0h
  1702.     or      bh,al
  1703.     cmp     bh,bl
  1704.     jne     mem_err
  1705.     setport    DAT
  1706.     inc     bl
  1707.     dec     bp
  1708.     jnz     rd_this_page3
  1709.     inc     si
  1710.     pop     bx
  1711.     add     bx,800h
  1712.     cmp     bx,1800h
  1713.     ja      mem_OK2
  1714.     push    si
  1715.     push    bx
  1716.     mov     cx,700h
  1717.     mov     al,PAGE0
  1718.     call    Write_LoopBack_Data
  1719.     call    Tx_Data
  1720.     pop     bx
  1721.     pop     si
  1722.     jmp     read_next_page3
  1723.  
  1724. pointer         dw      0
  1725.  
  1726. mem_err:
  1727.     pop     bx
  1728.     cmp     pointer,9        ;too slow?  Must not be working.
  1729.     ja      mem_real_err
  1730.     mov     bx,offset delay        ;append another NOP and RET in.
  1731.     add     bx,pointer
  1732.     mov     [bx],0c390h
  1733.     inc     pointer            ;slow it down a little more and try
  1734.     jmp     memory_test3        ;  again.
  1735. mem_real_err:
  1736.     mov     dx,offset mem_error_msg
  1737.     stc
  1738.     ret
  1739.  
  1740. change_routine:
  1741.     mov     ax,offset recv1
  1742.     mov     recv_pointer,ax
  1743.     mov     ax,offset send_pkt1
  1744.     mov     send_pkt_pointer,ax
  1745.     ret
  1746.  
  1747. change_routine2:
  1748.     mov     ax,offset recv2
  1749.     mov     recv_pointer,ax
  1750.     mov     ax,offset send_pkt2
  1751.     mov     send_pkt_pointer,ax
  1752.     ret
  1753.  
  1754. ;********** memory test passed ****************
  1755. mem_OK1:
  1756.     call    change_routine
  1757.     jmp     short mem_OK
  1758. mem_OK2:
  1759.     call    change_routine2
  1760. mem_OK:
  1761.     call    speed_test
  1762.  
  1763.     push    es
  1764.     xor     ax,ax
  1765.     mov     es,ax
  1766.     mov     si,printer
  1767.     mov     word ptr es:[si],ax     ; Zero-out Printer Port
  1768.     pop     es
  1769.  
  1770. ; Initialize Rx buffer pointer, and start receive
  1771.     mov     bl,Mode
  1772.     or      bl,IRQinverse
  1773.     or      bl,CurRXPage
  1774.     mov     Mode_RxPg,bl
  1775.     mov     cx,COMMAND
  1776.     call    Write_sub
  1777.     or      bl,RXEN
  1778.     call    Write_sub
  1779.  
  1780. ; Put our Receive routine in interrupt chain
  1781.     call    set_recv_isr
  1782.  
  1783. ; We didn't need to enable the receive & transmit interrupts, they were
  1784. ; set by hardware already. (accept GOOD, SUC & T16 to generate interrupt)
  1785.  
  1786. ; Enable Printer Adapter IRQ line
  1787.     mov     al,SLT_PRN
  1788.     call    CMD_sub
  1789.  
  1790.     clc
  1791.     ret
  1792.  
  1793.  
  1794. ;*********** sub-routine *************
  1795. ; Check DE-600 routine
  1796. Check_DE600:
  1797.     mov     al,SLT_NIC
  1798.     call    CMD_sub
  1799.     call    delay
  1800.  
  1801.     loadport
  1802.     setport DAT
  1803.     mov     al,NUL_CMD
  1804.     out     dx,al
  1805.     call    delay
  1806.  
  1807.     mov     bl,RESET
  1808.     mov     cx,COMMAND
  1809.     call    Write_sub
  1810.     call    delay
  1811.     mov     bl,STOP_RESET
  1812.     call    Write_sub
  1813.     call    delay
  1814.  
  1815.     mov     cx,STATUS
  1816.     call    Read_sub
  1817.     test    bl,0f0h
  1818.     jz      Check_OK
  1819.     stc
  1820.     ret
  1821. Check_OK:
  1822.     clc
  1823.     ret
  1824.  
  1825. OldIRQ5 dd      0
  1826. OldIRQ7 dd      0
  1827.  
  1828. NewIRQ5:
  1829.     push    ax
  1830.     push    bx
  1831.     push    cx
  1832.     push    dx
  1833.     push    ds
  1834.     mov     al,20h
  1835.     out     20h,al
  1836.     mov     ax,cs
  1837.     mov     ds,ax
  1838.     cmp     LB,0
  1839.     jz      DisCare_IRQ5
  1840.     mov     bh,5
  1841.     call    Clear_int
  1842. DisCare_IRQ5:
  1843.     pop     ds
  1844.     pop     dx
  1845.     pop     cx
  1846.     pop     bx
  1847.     pop     ax
  1848.     iret
  1849.  
  1850. NewIRQ7:
  1851.     push    ax
  1852.     push    bx
  1853.     push    cx
  1854.     push    dx
  1855.     push    ds
  1856.     mov     al,20h
  1857.     out     20h,al
  1858.     mov     ax,cs
  1859.     mov     ds,ax
  1860.     cmp     LB,0
  1861.     jz      DisCare_IRQ7
  1862.     mov     bh,7
  1863.     call    Clear_int
  1864. DisCare_IRQ7:
  1865.     pop     ds
  1866.     pop     dx
  1867.     pop     cx
  1868.     pop     bx
  1869.     pop     ax
  1870.     iret
  1871.  
  1872. replace_IRQ5_7:
  1873.     xor     cx,cx
  1874.     mov     es,cx
  1875.     mov     di,034h
  1876.     mov     ax,es:[di]                      ;save old interrupt vector
  1877.     mov     word ptr OldIRQ5,ax
  1878.     mov     ax,es:[di]+2
  1879.     mov     word ptr OldIRQ5+2,ax
  1880.     mov     ax,offset NewIRQ5
  1881.     stosw
  1882.     mov     ax,cs
  1883.     stosw
  1884.  
  1885.     mov     di,03ch
  1886.     mov     ax,es:[di]                      ;save old interrupt vector
  1887.     mov     word ptr OldIRQ7,ax
  1888.     mov     ax,es:[di]+2
  1889.     mov     word ptr OldIRQ7+2,ax
  1890.     mov     ax,offset NewIRQ7
  1891.     stosw
  1892.     mov     ax,cs
  1893.     stosw
  1894.  
  1895.     in      al,21h
  1896.     mov     intmask,al
  1897.     pause
  1898.     pause
  1899.     and     al,5fh
  1900.     out     21h,al
  1901.     ret
  1902.  
  1903. intmask         db      0
  1904. INT_come        db      0
  1905. T16_flag        db      0
  1906. LB              db      0
  1907.  
  1908. restore_IRQ5_7:
  1909.     xor     cx,cx
  1910.     mov     es,cx
  1911.     mov     di,034h
  1912.     mov     ax,word ptr OldIRQ5
  1913.     mov     es:[di],ax                      ;save old interrupt vector
  1914.     mov     ax,word ptr OldIRQ5+2
  1915.     mov     es:[di]+2,ax
  1916.  
  1917.     mov     di,03ch
  1918.     mov     ax,word ptr OldIRQ7
  1919.     mov     es:[di],ax                      ;save old interrupt vector
  1920.     mov     ax,word ptr OldIRQ7+2
  1921.     mov     es:[di]+2,ax
  1922.  
  1923.     mov     al,intmask
  1924.     out     21h,al
  1925.     ret
  1926.  
  1927. Write_LoopBack_Data:
  1928.     mov     si,offset rom_address
  1929.     mov     di,si
  1930. ;set Tx Pointer for moving packet
  1931.     mov     bx,BFRSIZ
  1932.     sub     bx,cx           ;CX= Packet Length
  1933.     or      bh,al           ;AL= Page Number
  1934.     mov     TxStartAdd,bx   ;BX= the pointer to TX
  1935.     mov     cx,RW_ADR       ;write memory address
  1936.     call    Write_sub
  1937.     mov     bl,bh
  1938.     call    Write_sub
  1939.     cld
  1940.     loadport
  1941.     setport DAT
  1942.     mov     bp,12
  1943.     mov     cx,WRITE
  1944. write_our_node_ID:
  1945.     lodsb
  1946.     mov     bl,al
  1947.     call    Write_sub
  1948.     cmp     bp,7
  1949.     jne     not_second_ID
  1950.     mov     si,di
  1951. not_second_ID:
  1952.     dec     bp
  1953.     jnz     write_our_node_ID
  1954.     ret
  1955.  
  1956. Tx_Data:
  1957. ;Check TXIDLE, if high then wait for previous Tx end, if low then Tx it
  1958.     mov     cx,800h        ; Avoid infinite loop
  1959.     loadport
  1960.     setport STAT
  1961. wait_Txidle0:
  1962.     in      al,dx
  1963.     test    al,TXBUSY       ; Is the previous Tx successful ?
  1964.     jz      Tx_next0        ; Yes, TXBUSY is low. Then could Tx next packet.
  1965.     loop    wait_Txidle0
  1966. Tx_next0:
  1967. ;set Tx Pointer at beginning of packet
  1968.     push    bx
  1969.     mov     cx,TX_ADR
  1970.     mov     bx,TxStartAdd
  1971.     call    Write_sub
  1972.     mov     bl,bh
  1973.     call    Write_sub
  1974. ;Enable interrupt and start Tx
  1975.     mov     cx,COMMAND
  1976.     mov     bl,RX_NONE
  1977.     call    Write_sub
  1978.     or      bl,TXEN
  1979.     call    Write_sub
  1980.     pop     bx
  1981.     ret
  1982.  
  1983. LoopBack_Tx:
  1984. ;set Tx Pointer at beginning of packet
  1985.     mov     bx,TxStartAdd
  1986.     mov     cx,TX_ADR
  1987.     call    Write_sub
  1988.     mov     bl,bh
  1989.     call    Write_sub
  1990. ;Enable interrupt and start Tx
  1991.     mov     bl,RX_BP
  1992.     or      bl,IRQinverse
  1993.     mov     cx,COMMAND
  1994.     call    Write_sub
  1995.     or      bl,LOOPBACK
  1996.     call    Write_sub
  1997.  
  1998.     mov     LB,1
  1999.     mov     al,SLT_PRN
  2000.     call    CMD_sub
  2001.  
  2002.     xor     bx,bx
  2003.     mov     cx,8000h
  2004. wait_int:
  2005.     cmp     INT_come,0
  2006.     jz      have_T16
  2007.     mov     bx,1
  2008.     jmp     short exit_LoopBack
  2009. have_T16:
  2010.     cmp     T16_flag,0
  2011.     jz      still_wait
  2012.     mov     bx,-1
  2013.     jmp     short exit_LoopBack
  2014. still_wait:
  2015.     loop    wait_int
  2016.  
  2017. exit_LoopBack:
  2018.     mov     LB,0
  2019.     mov     al,SLT_NIC
  2020.     call    CMD_sub
  2021.  
  2022.     push    bx
  2023.     mov     cx,STATUS
  2024.     call    Read_sub
  2025.     pop     bx
  2026.     ret
  2027.  
  2028. Clear_int:
  2029.     mov     al,SLT_NIC
  2030.     call    CMD_sub
  2031.     pause
  2032.     mov     cx,STATUS
  2033.     call    Read_sub
  2034.  
  2035.     mov     T16_flag,0
  2036.     test    bl,GOOD         ; Is Rx generating interrupt ?
  2037.     jz      chk_T16
  2038.     mov     INT_come,1
  2039.     mov     int_no,bh
  2040.     jmp     short exit_Clear_int
  2041. chk_T16:
  2042.     test    bl,T16          ; Is pending a Tx Packet ?
  2043.     jz      exit_Clear_int
  2044.     mov     T16_flag,1
  2045. exit_Clear_int:
  2046.     ret
  2047.  
  2048. Check_IRQ:
  2049.     call    replace_IRQ5_7
  2050.     sti
  2051.     mov     cx,RUNT
  2052.     mov     al,PAGE0
  2053.     call    Write_LoopBack_Data
  2054.     call    LoopBack_Tx     ; check IRQ= 7 or 5 but IRQ not inverse
  2055.     cmp     bx,0
  2056.     jnz     IRQ_OK
  2057.  
  2058. ;Check TXIDLE, if high then wait for previous Tx end, if low then Tx it
  2059.     mov     cx,800h        ; Avoid infinite loop
  2060.     loadport
  2061.     setport STAT
  2062. wait_Txidle:
  2063.     in      al,dx
  2064.     test    al,TXBUSY       ; Is the previous Tx successful ?
  2065.     jz      Tx_next         ; Yes, TXBUSY is low. Then could Tx next packet.
  2066.     loop    wait_Txidle
  2067. Tx_next:
  2068.     mov     IRQinverse,40h  ; check IRQ= 7 or 5 but IRQ inverse
  2069.     mov     PS2,0
  2070.     call    LoopBack_Tx
  2071. IRQ_OK:
  2072.     cli
  2073.     call    restore_IRQ5_7
  2074.     ret
  2075.  
  2076. check_PS2:
  2077.     mov     ax,0c400h
  2078.     int     15h
  2079.     jc      not_PS2
  2080.     mov     PS2,1
  2081. not_PS2:
  2082.     ret
  2083.  
  2084. speed_test:
  2085.     xor     ax,ax
  2086.     mov     es,ax
  2087.     mov     si,20h
  2088.     mov     ax, es:[si]
  2089.     mov     cs:old_int8, ax
  2090.     mov     ax, es:[si+2]
  2091.     mov     cs:old_int8[2], ax
  2092.     cli
  2093.     mov     ax,offset new_int8
  2094.     mov     es:[si],ax
  2095.     mov     es:[si+2],cs
  2096.     sti
  2097.  
  2098. next_test1:
  2099.     mov     ticks_start,0
  2100. next_test:
  2101.     cmp     ticks_start,0
  2102.     jz      next_test
  2103.     mov     ticks,0
  2104.     xor     bx,bx
  2105. loop_again:
  2106.     mov     cx,6
  2107.     loop    $
  2108.     cmp     ticks,2
  2109.     jae     End_count
  2110.     inc     bx
  2111.     jmp     short loop_again
  2112.  
  2113. End_count:
  2114.     cli
  2115.     xor     ax,ax
  2116.     mov     es,ax
  2117.     mov     si,20h
  2118.     mov     ax,old_int8
  2119.     mov     es:[si],ax
  2120.     mov     ax,old_int8[2]
  2121.     mov     es:[si+2],ax
  2122.     sti
  2123.     cmp     bx,0a000h
  2124.     jb      low_speed
  2125.     mov     ax,offset recv1         ; special for high speed EISA
  2126.     mov     recv_pointer,ax
  2127. low_speed:
  2128.     ret
  2129.  
  2130. ticks_start     db      0
  2131. ticks           db      0
  2132. old_int8        dw      ?
  2133.             dw      ?
  2134. new_int8:
  2135.     inc     ticks
  2136.     inc     ticks_start
  2137.     jmp     dword ptr cs:old_int8
  2138.  
  2139.     code    ends
  2140.     end
  2141.