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

  1. version        equ     4
  2.  
  3. ;******************************************************************************;
  4. ;*                                                                            *;
  5. ;*     File: tiara.asm                                                        *;
  6. ;*     Auth: Brian Fisher                                                     *;
  7. ;*           Queens University                                                *;
  8. ;*           Computing and Communications Services                            *;
  9. ;*           Rm 2-50 Dupuis Hall                                              *;
  10. ;*           Kingston Ontario                                                 *;
  11. ;*                                                                            *;
  12. ;*     Date: January 24 1990                                                  *;
  13. ;*                                                                            *;
  14. ;*     Purp: (3C501) Packet driver for Tiara Ethernet Card.                   *;
  15. ;*                                                                            *;
  16. ;*============================================================================*;
  17. ;*     Revs: January 25 1990   V 1.6.0 Clean up code and document.            *;
  18. ;*           Feb     24 1991   V 1.8.2 Gets IRQ and I/O info from MCH POS regs*;
  19. ;*                                                                            *;
  20. ;*============================================================================*;
  21. ;*                                                                            *;
  22. ;*     Thanks, Mehdi Safipour, of Tiara Computer Systems, who supplied the    *;
  23. ;*     programming manual and examples.                                       *;
  24. ;*                                                                            *;
  25. ;*============================================================================*;
  26. ;*                                                                            *;
  27. ;*     Logic -                                                                *;
  28. ;*                                                                            *;
  29. ;*     Initialization - classic, by-the-book initialization, with one         *;
  30. ;*     exception:  The manual didn't mention the fact that receive            *;
  31. ;*     interrupts will not always work unless the receive buffer is           *;
  32. ;*     vacuumed.                                                              *;
  33. ;*                                                                            *;
  34. ;*     Byte/Word I/O mode was determined by code ruthlessly copied from       *;
  35. ;*     NI5010.ASM, auth: Russ Nelson.                                         *;
  36. ;*                                                                            *;
  37. ;*     Transmit-no surprises, data goes whoosh!                               *;
  38. ;*                                                                            *;
  39. ;*     Receive-interrupt driven receive makes upcalls to inform the ULP of    *;
  40. ;*     its status.  The 14 byte ethernet header is copied from the card to    *;
  41. ;*     a temporary buffer, to determine the ether-type.  Recv_find is called  *;
  42. ;*     to acquire a buffer from the ULP.  If no buffer, the packet is dropped.*;
  43. ;*     If a buffer is acquired, the packet is copied into it, and recv_copy   *;
  44. ;*     informs the ULP that the data is there.                                *;
  45. ;*                                                                            *;
  46. ;******************************************************************************;
  47. ;
  48.  
  49. DLCR_XMIT_STAT EQU     0               ; EtherStar I/O Register offsets
  50. DLCR_XMIT_MASK EQU     1
  51. DLCR_RECV_STAT EQU     2
  52. DLCR_RECV_MASK EQU     3
  53. DLCR_XMIT_MODE EQU     4
  54. DLCR_RECV_MODE EQU     5
  55. DLCR_ENABLE    EQU     6
  56. DLCR_TDR_LOW   EQU     7
  57. DLCR_NODE_ID   EQU     8
  58. DLCR_TDR_HIGH  EQU     0FH
  59. BMPR_MEM_PORT  EQU     10H
  60. BMPR_PKT_LEN   EQU     12H
  61. BMPR_DMA_ENABLE EQU    14H
  62. PROM_ID        EQU     18H
  63. TMST           EQU     80h
  64. TMT_OK         EQU     80h
  65. TMT_16COLL     EQU     02h
  66. BUF_EMPTY      EQU     40h
  67. card_disable   equ     80h             ; written to DLCR_ENABLE to disable card
  68. card_enable    equ     0h              ; written to DLCR_ENABLE to enable card
  69. clear_status   equ     00001111B       ; used to clear status info
  70. ;
  71. ;                      !!!!!!!!--------
  72. ;                      !!!!!!!+--------CLEAR BUS WRITE ERROR
  73. ;                      !!!!!!+---------CLEAR 16 COLLISION
  74. ;                      !!!!!+----------CLEAR COLLISION
  75. ;                      !!!!+-----------CLEAR UNDERFLOW
  76. ;                      !!!+------------NC
  77. ;                      !!+-------------NC
  78. ;                      !+--------------NC
  79. ;                      +---------------NC
  80. ;
  81. no_tx_irqs      equ     0              ; written to clear transmit IRQs
  82. clr_rcv_status  equ     0CFh           ; clears receive status
  83. en_rcv_irqs     equ     10000000B      ; enable receive interrupts
  84. ;
  85. ;                      !!!!!!!!--------
  86. ;                      !!!!!!!+--------ENABLE OVERFLOW
  87. ;                      !!!!!!+---------ENABLE CRC
  88. ;                      !!!!!+----------ENABLE ALIGN
  89. ;                      !!!!+-----------ENABLE SHORT PKT
  90. ;                      !!!+------------DISABLE REMOTE RESET
  91. ;                      !!+-------------RESERVED
  92. ;                      !+--------------RESERVED
  93. ;                      +---------------ENABLE PKT READY
  94. ;
  95. xmit_mode       equ     00000010B
  96. ;                       !!!!!!!!---------ENABLE CARRIER DETECT
  97. ;                       !!!!!!!+---------DISABLE LOOPBACK
  98. ;
  99. ;
  100. recv_mode       equ     00000010B                 ; set receive mode
  101. ;
  102. ;                       !!!!!!!!---------ACCEPT ALL PACKETS
  103. ;                       !!!!!!!+---------ACCEPT PHYSICAL, MULTICAST, AND
  104. ;                       !!!!!!+----------BROADCAST PACKETS
  105. ;                       !!!!!+-----------DISABLE REMOTE RESET
  106. ;                       !!!!+------------DISABLE SHORT PACKETS
  107. ;                       !!!+-------------USE 6 BYTE ADDRESS
  108. ;                       !!+--------------NC
  109. ;                       !+---------------NC
  110. ;                       +----------------DISABLE CRC TEST MODE
  111.  
  112. debug    = 0
  113.  
  114.     include defs.asm
  115.  
  116. code segment word public
  117.     assume  cs:code, ds:code
  118.  
  119.     public  int_no
  120. int_no    db      3,0,0,0            ;must be four bytes long for get_number
  121. io_adr    dw    300h,0            ; default I/O address
  122.     extrn    is_186: byte        ;=0 if 808[68], =1 if 80[123]86.
  123.  
  124.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  125. driver_class    db      BLUEBOOK,IEEE8023,0    ;from the packet spec
  126. driver_type    db      1        ;from the packet spec
  127. driver_name    db      'Tiara',0    ;name of the driver.
  128. driver_function    db    2
  129. parameter_list    label    byte
  130.     db    1    ;major rev of packet driver
  131.     db    9    ;minor rev of packet driver
  132.     db    14    ;length of parameter list
  133.     db    EADDR_LEN    ;length of MAC-layer address
  134.     dw    GIANT    ;MTU, including MAC headers
  135.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  136.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  137.     dw    0    ;(# of successive xmits) - 1
  138. int_num    dw    0    ;Interrupt # to hook for post-EOI
  139.             ;processing, 0 == none,
  140.  
  141.     public  rcv_modes
  142. rcv_modes    dw    7        ;number of receive modes in our table.
  143.         dw    0               ;There is no mode zero
  144.         dw    rcv_mode_1
  145.         dw    0
  146.         dw    rcv_mode_3
  147.         dw    0        ;haven't set up perfect filtering yet.
  148.         dw    0
  149.         dw    rcv_mode_6
  150.  
  151.  
  152. ;
  153. ;      Receive Packet Header Buffer: Required because addresses and e-type
  154. ;      must be read from Tiara card before upcall to find a buffer can be
  155. ;      made.  Need the number of bytes, and the e-type for the call...
  156. ;
  157. ether_buff    db    EADDR_LEN  dup(?)
  158.         db    EADDR_LEN  dup(?)
  159. ether_type    db    4 dup(?)
  160. usr_ptr        dd    ?                 ; temp storage or recv_buff ptr
  161.  
  162. writebport  macro   from_base,value
  163.     mov    dx,cs:[io_adr]        ; write byte value to port
  164.     add    dx,from_base
  165.     mov    al,value
  166.     out    dx,al
  167.     endm
  168.  
  169. ;sends $ terminated string to screen
  170. print$ macro   string
  171.     mov    ah,9
  172.     mov    dx,offset &string&    ; print $ terminated string
  173.     int    21h
  174.     endm
  175.  
  176. mark           = 0F90h                 ; marker debug pos on screen 25
  177.  
  178. marker  macro   st,nd
  179.   IF  debug NE 0                       ; do marker if debug <> 0
  180.       pushf                            ; show 2 char marker on
  181.       push es                          ; 25th line, 1st column
  182.       push ax
  183.       mov  ax,0B800h
  184.       mov  es,ax
  185.       mov  al,'&st&'
  186.       mov  byte ptr es:[mark],al
  187.       mov  al,byte ptr es:[mark+1]     ; get color value
  188.       inc  al
  189.       and  al,0Fh
  190.       or   al,1
  191.       mov  byte ptr es:[mark+1],al     ; advance it to show activity
  192.       mov  al,'&nd'
  193.       mov  byte ptr es:[mark+2],al
  194.       mov  al,byte ptr es:[mark+3]
  195.       inc  al
  196.       and  al,0Fh
  197.       or   al,1
  198.       mov  byte ptr es:[mark+3],al
  199.       pop  ax
  200.       pop  es
  201.       popf
  202.     ENDIF
  203.   endm
  204.  
  205.     public bad_command_intercept
  206. bad_command_intercept:
  207. ;called with ah=command, unknown to the skeleton.
  208. ;exit with nc if okay, cy, dh=error if not.
  209.     mov    dh,BAD_COMMAND
  210.     stc
  211.     ret
  212.  
  213.     public    as_send_pkt
  214. ; The Asynchronous Transmit Packet routine.
  215. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  216. ;   interrupts possibly enabled.
  217. ; Exit with nc if ok, or else cy if error, dh set to error number.
  218. ;   es:di and interrupt enable flag preserved on exit.
  219. as_send_pkt:
  220.     ret
  221.  
  222.     public    drop_pkt
  223. ; Drop a packet from the queue.
  224. ; Enter with es:di -> iocb.
  225. drop_pkt:
  226.     assume    ds:nothing
  227.     ret
  228.  
  229.     public    xmit
  230. ; Process a transmit interrupt with the least possible latency to achieve
  231. ;   back-to-back packet transmissions.
  232. ; May only use ax and dx.
  233. xmit:
  234.     assume    ds:nothing
  235.     ret
  236.  
  237.  
  238.     public    send_pkt
  239. send_pkt:
  240. ;enter with ds:si -> packet, cx = packet length.
  241. ;exit with nc if ok, pr else cy if error, dh set to error number.
  242.  
  243.               assume  ds:nothing
  244.               marker  T,X
  245.               cmp     cx,RUNT                 ; big enough?
  246.               jae     send_runt_ok
  247.               mov     cx,RUNT                 ; at least runt!
  248. send_runt_ok:
  249.               cmp     cx,GIANT                ; small enough?
  250.               jbe     send_size_ok
  251.               mov     dh,NO_SPACE
  252.               stc                             ; Error
  253.               ret
  254. send_size_ok:
  255.               push    cx
  256.               inc     cx
  257.               shr     cx,1                    ; words to send
  258. ;
  259. ;      8086/8088 byte mode send
  260. ;
  261.               mov     dx,cs:[io_adr]
  262.               add     dx,BMPR_MEM_PORT
  263.               cmp     cs:is_186,0  ; use BYTE or WORD mode?
  264.               jne     send_w_mode
  265.  xb:
  266.               lodsw                           ; load word, ind ds:si
  267.               out     dx,al
  268.               xchg    ah,al
  269.               out     dx,al
  270.               loop    xb                      ; set packet length (byte mode)
  271.               pop     ax
  272.               or      ah,TMST
  273.               mov     dx,cs:[io_adr]
  274.               add     dx,BMPR_PKT_LEN
  275.               out     dx,al                   ; write BMPR2, then BMPR3 to
  276.               xchg    al,ah                   ; initiate byte mode transmit
  277.               inc     dx
  278.               out     dx,al
  279.               jmp     wait_tmt_ok
  280. send_w_mode:
  281.               .286
  282.               rep    outsw
  283.               .8086
  284.               pop     ax
  285.               or      ah,TMST
  286.               mov     dx,cs:[io_adr]
  287.               add     dx,BMPR_PKT_LEN
  288.               out     dx,ax
  289. wait_tmt_ok:
  290.               xor     cx,cx
  291.               mov     dx,cs:[io_adr]
  292.               IF DLCR_XMIT_STAT NE 0
  293.                  add     dx,DLCR_XMIT_STAT
  294.               ENDIF
  295. wait_tmt:
  296.               in      al,dx            ; read status register until timeout...
  297.               test    al,TMT_OK or TMT_16COLL
  298.               jnz     send_ok
  299.               loop    wait_tmt
  300.               mov     dh,CANT_SEND
  301.               stc
  302.               ret
  303. send_ok:
  304.               clc
  305.               ret
  306.  
  307.     public  set_address
  308. set_address:
  309. ;enter with ds:si -> Ethernet address,CX = length of address.
  310. ;exit with nc if okay, or cy, dh=error if any errors.
  311.     assume    ds:nothing
  312.     ret
  313.  
  314.  
  315. rcv_mode_1:
  316.     writebport    DLCR_RECV_MODE,0    ; don't receive any packets
  317.     ret
  318.  
  319.  
  320. rcv_mode_3:
  321.     writebport    DLCR_RECV_MODE,2    ; receive mine, broads, and multis.
  322.     ret
  323.  
  324.  
  325. rcv_mode_6:
  326.     writebport    DLCR_RECV_MODE,3    ; receive all packets.
  327.     ret
  328.  
  329.  
  330.     public  set_multicast_list
  331. set_multicast_list:
  332. ;enter with ds:si ->list of multicast addresses, ax = number of addresses,
  333. ;  cx = number of bytes.
  334. ;return nc if we set all of them, or cy,dh=error if we didn't.
  335.  
  336.     mov     dh,NO_MULTICAST
  337.     stc
  338.     ret
  339.  
  340.     public    terminate
  341. terminate:
  342.     writebport    DLCR_RECV_MODE,0    ; don't receive any packets
  343.     ret
  344.  
  345.     public  reset_interface
  346. reset_interface:                       ;reset the interface.
  347.     assume  ds:code
  348.     ret
  349.  
  350. ;called when we want to determine what to do with a received packet.
  351. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  352.     extrn   recv_find: near
  353.  
  354. ;called after we've copied the packet into the buffer.
  355. ;enter with ds:si ->the packet, cx = length of the packet.
  356.     extrn   recv_copy: near
  357.  
  358.     extrn   count_in_err: near
  359.     extrn   count_out_err: near
  360.  
  361.     public  recv
  362. recv:
  363. ;called from the recv isr.  All registers have been saved, and ds=cs.
  364. ;Upon exit, the interrupt will be acknowledged.
  365.  
  366.     assume  ds:code
  367.     marker  R,X
  368.  
  369. ;clear receive masks to prevent further IRQs
  370.  
  371.     writebport    DLCR_RECV_MASK,0
  372. recv_0:
  373.     mov     ax,cs
  374.     mov     ds,ax
  375.     writebport      DLCR_RECV_STAT,clr_rcv_status
  376.  
  377. ;are there any packets to read?
  378.  
  379.     mov     dx,cs:[io_adr]
  380.     add     dx,DLCR_RECV_MODE
  381.     in      al,dx
  382.     test    al,BUF_EMPTY
  383.     jz      recv_1                    ; 0 if at least one valid pkt..
  384.     jmp     recv_99
  385.  
  386. ;yes, read out a receive packet...
  387.  
  388. recv_1:
  389.               cmp     cs:is_186,0
  390.               jne     recv11
  391.               jmp     read_b_mode
  392. ;
  393. ;        read packet out in word mode
  394. ;
  395. recv11:
  396.     mov    dx,cs:[io_adr]    ; get status and reserved byte
  397.     add    dx,BMPR_MEM_PORT
  398.     in    ax,dx
  399.     in    ax,dx                           ; get packet size
  400.     push    ax
  401.                     ;read first 14 bytes from receive buffer into ether_buff
  402.     mov    ax,cs
  403.     mov    es, ax
  404.     mov    di,offset ether_buff
  405.     mov    cx,16/2                            ; word mode, remember...
  406.     .286
  407.     rep    insw            ; read words into ether_buff
  408.     .8086
  409.  
  410. ;
  411. ;      If the sender is myself, ignore the packet.  This allows async
  412. ;      send/receive without messing up...
  413. ;
  414.     mov    si,offset ether_buff+EADDR_LEN       ; we want the SOURCE
  415.     mov    di,offset my_address
  416.     mov    cx,EADDR_LEN/2
  417.     repe    cmpsw
  418.     jne    not_mine
  419.     jmp    word_flush                      ; mine, so flush it
  420. ;
  421. ;      cx = length, es:di = pointer to ethertype
  422. ;
  423. not_mine:
  424.     pop    cx
  425.     push    cx
  426.     mov    di,offset ether_type
  427.     mov    ax,cs
  428.     mov    es,ax            ; es:di -> ether type, cx = size# bytes
  429.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  430.     mov    ax, es:[di]
  431.     xchg    ah, al
  432.     cmp     ax, 1500
  433.     ja    BlueBookPacket
  434.     inc    di            ;set di to 802.2 header
  435.     inc    di
  436.     mov    dl, IEEE8023
  437. BlueBookPacket:
  438.     call    recv_find        ; got a buffer?
  439.     mov    ax,es
  440.     or    ax,di            ; pointer zero?
  441.     je    word_flush        ; no pointer, discard data
  442. ;
  443. ;      es:di -> users buffer, do copy...
  444. ;      ds:si -> source of copy
  445. ;
  446.     mov    cs:[usr_ptr.segm],es; save ULP pointer
  447.     mov    cs:[usr_ptr.offs],di
  448.     mov    ax,cs
  449.     mov    ds,ax
  450.     mov    si,offset ether_buff    ; copy header to users buffer
  451.     mov    cx,16/2            ; 8 words to copy
  452.     rep    movsw
  453.     mov    dx,cs:[io_adr]        ;copy rest of data to user
  454.     add    dx,BMPR_MEM_PORT    ; buffer in es:di ->
  455.     pop    cx
  456.     push    cx
  457.     sub    cx,16
  458.     shr    cx,1
  459.     .286
  460.     rep    insw            ; read word, store at es:di ->
  461.     .8086
  462.     jnc    word_even
  463.     in    ax,dx
  464.     stosb
  465. word_even:
  466.     pop    cx            ;call recv_copy to say copy done
  467.     lds    si,cs:[usr_ptr]
  468.     call    recv_copy
  469.     jmp    recv_0            ; go get another packet
  470. word_flush:
  471.     mov    dx,cs:[io_adr]
  472.     add    dx,BMPR_MEM_PORT
  473.     pop    cx
  474.     sub    cx,16            ; adjust word count
  475.     inc    cx
  476.     shr    cx,1
  477. word_f:
  478.     in    ax,dx
  479.     loop    word_f
  480.     jmp    recv_0
  481. ;
  482. ;             go see of any more packets comming....
  483. ;
  484. ;             READ in BYTE MODE
  485. ;
  486. read_b_mode:
  487.     mov    dx,cs:[io_adr]    ;get status and reserved byte
  488.     add    dx,BMPR_MEM_PORT
  489.     in    al,dx        ; vacuum status and reserved
  490.     in    al,dx
  491.     in    al,dx        ; get packet size
  492.     xchg    al,ah        ; low byte in ah
  493.     in    al,dx        ; get packet size
  494.     xchg    al,ah        ; fix size ah/al order
  495.     push    ax        ; keep number of bytes
  496.     ;      read first 16 bytes from receive buffer into ether_buff
  497.     mov    ax,cs
  498.     mov    es,ax
  499.     mov    di,offset ether_buff
  500.     mov    cx,16            ; byte mode, 16 byte header
  501. rdb:
  502.     in    al,dx            ; read 16 bytes into ether_buff
  503.     stosb
  504.     loop    rdb
  505. ;
  506. ;      If the sender is myself, ignore the packet.
  507. ;
  508.     mov    si,offset ether_buff+EADDR_LEN       ; we want the SOURCE
  509.     mov    di,offset my_address
  510.     mov    cx,EADDR_LEN/2
  511.     repe    cmpsw
  512.     jne    not_mineb
  513.     jmp    byte_flush                  ; mine, so flush it
  514. ;
  515. ;      cx = length, es:di = pointer to ethertype
  516. ;
  517. not_mineb:
  518.     pop    cx
  519.     push    cx
  520.     mov    di,offset ether_type
  521.     mov    ax,cs
  522.     mov    es,ax             ; es:di -> ether type, cx = size#bytes
  523.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  524.     mov    ax, es:[di]
  525.     xchg    ah, al
  526.     cmp     ax, 1500
  527.     ja    BlueBookPacket1
  528.     inc    di            ;set di to 802.2 header
  529.     inc    di
  530.     mov    dl, IEEE8023
  531. BlueBookPacket1:
  532.     call    recv_find                   ; got a buffer?
  533.     mov    ax,es
  534.     or    ax,di                       ; pointer zero?
  535.     je    byte_flush                  ; no pointer, discard data
  536. ;
  537. ;      es:di -> users buffer, do copy...
  538. ;      ds:si -> source of copy
  539. ;
  540.     mov    cs:[usr_ptr.segm],es    ; save ULP pointer
  541.     mov    cs:[usr_ptr.offs],di
  542.     mov    ax,cs
  543.     mov    ds,ax
  544.     mov    si,offset ether_buff        ; copy header to users buffer
  545.     mov    cx,16/2            ; 16 bytes in header to copy
  546.     rep    movsw
  547.     mov    dx,cs:io_adr     ; copy rest of data to users
  548.     add    dx,BMPR_MEM_PORT            ; buffer in es:di ->
  549.     pop    cx
  550.     push    cx
  551.     sub    cx,14
  552. cpyb:
  553.     in    al,dx            ; read byte
  554.     stosb                ; store at es:di ->
  555.     loop    cpyb
  556.     pop    cx            ; call recv_copy to say copy done
  557.     lds    si,cs:[usr_ptr]
  558.     call    recv_copy
  559.     jmp    recv_0            ; go get another packet...
  560. byte_flush:
  561.     mov    dx,cs:io_adr
  562.     add    dx,BMPR_MEM_PORT
  563.     pop    cx
  564.     sub    cx,16            ; adjust byte count header
  565. byte_f:
  566.     in    al,dx
  567.     loop    byte_f
  568.     jmp    recv_0            ; go to see if any more packets comming...
  569. recv_99:
  570. ;      receive ok, restore recive mask and exit
  571. ;
  572.     writebport    DLCR_RECV_MASK,en_rcv_irqs
  573.     ret
  574.  
  575.  
  576.     public    timer_isr
  577. timer_isr:
  578. ;if the first instruction is an iret, then the timer is not hooked
  579.     iret
  580.  
  581. ;any code after this will not be kept.  Buffers used by the program, if any,
  582. ;are allocated from the memory between end_resident and end_free_mem.
  583.     public end_resident,end_free_mem
  584. end_resident    label    byte
  585. end_free_mem    label    byte
  586.  
  587. io_adr_msg    db    "I/O Base Address: ",'$'
  588. int_no_msg    db    " Interrupt Level: ",'$'
  589. no_card_msg    db    "INIT: No card at I/O address specified",CR,LF,'$'
  590. installed_ok    db    "INIT: Installation Complete",CR,LF,'$'
  591.  
  592.     public  usage_msg
  593. usage_msg   db  "usage: tiara [options] <packet_int_no> <hardware_irq> <io_adr>",CR,LF,'$'
  594.  
  595.     public  copyright_msg
  596. copyright_msg    label    byte
  597.  db "Packet driver for Tiara Card, Version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version, CR,LF
  598.  db "         - for PC, PC-AT, and Micro Channel (IBM tm)",CR,LF
  599.  db "Portions Copyright 1990, 1991 Queens University",CR,LF
  600.  db "    Written by Brian Fisher",CR,LF
  601.  db CR,LF,'$'
  602.  
  603.     extrn   set_recv_isr: near
  604. ;enter with si-> argument string,di->wword to store.
  605. ;if there is no number, don't change  the number.
  606.  
  607. ;enter with si -> argument string, di -> word to store.
  608. ;if there is no number, don't change the number.
  609.     extrn   get_number: near
  610.  
  611. ;enter with dx -> name of word, di -> dword to print.
  612.     extrn    print_number: near
  613.  
  614. ;-> the assigned Ethernet address of the card.
  615.     extrn    rom_address: byte
  616.  
  617. ;-> the current Ethernet address of the card.
  618.     extrn    my_address: byte
  619.  
  620. ;==============================================================================;
  621. ;========================= SYS_MCA SUPPORT ===============================;
  622. ;==============================================================================;
  623.  
  624. POS_max         equ     7h              ; max number of slots to check
  625.  
  626. POS_select      equ     096h            ; POS Select register location
  627. POS_mask        equ     008h            ; POS Select mask
  628.  
  629. POS_0           equ     100h            ; POS Registers
  630. POS_1           equ     101h
  631. POS_2           equ     102h
  632.  
  633. ;       Card Specific Items
  634.  
  635. Adapter_ID      equ     6001h           ; POS_0 | POS_1
  636.  
  637. Adapter_open    equ     00000001b       ; POS_2
  638. ;                       ||||||||
  639. ;                       |||||||+-------- 1 = card enabled (open)
  640. ;                       ||||||+--------- 1 = Boot Prom Enable
  641. ;                       |||||+---------- } IRQ Level Select
  642. ;                       ||||+----------- } IRQ Level Select
  643. ;                       |||+------------ )
  644. ;                       ||+------------- ) I/O Port Base Address Select
  645. ;                       |+-------------- )
  646. ;                       +--------------- )
  647.  
  648. ; Adapter Boot PROM is disabled for this configuration, so POS_5 has no
  649. ; meaning, and is ignored.
  650.  
  651. irq_list       dw       3              ;  00h    POS_2 after [POS_2]&0Ch
  652.                dw       4              ;  04h
  653.                dw       7              ;  08h
  654.                dw       9              ;  0Ch
  655.  
  656. io_list        dw       1200h          ; MCH I/O Address List
  657.                dw       1220h
  658.                dw       1240h
  659.                dw       1260h
  660.                dw       1280h
  661.                dw       12A0h
  662.                dw       12C0h
  663.                dw       12E0h
  664.                dw       1300h
  665.                dw       1320h
  666.                dw       1340h
  667.                dw       1360h
  668.                dw       1380h
  669.                dw       13A0h
  670.                dw       13C0h
  671.                dw       13E0h
  672.  
  673.  
  674.     public  parse_args
  675. parse_args:
  676. ;
  677. ;      Look for MicroChannel POS information, and if found, set default
  678. ;      values for I/O base address and IRQ level before parsing the
  679. ;      command line.
  680. ;
  681.         pushf                  ; save flags
  682.         cli                    ; no IRQ's during this phase
  683.  
  684.         mov     cx,POS_max+1   ; start with the last slot first...
  685.         mov     dx,POS_select
  686.         in      al,dx          ; Save old POS_select value
  687.         push    ax
  688.  
  689. mch_chk:
  690.         mov     al,cl          ; get slot count
  691.         dec     al             ; adjust it
  692.         or      al,POS_mask    ; add the mask
  693.         mov     dx,POS_select
  694.         out     dx,al          ; write select value
  695.  
  696.         mov     dx,POS_1       ; read the Adapter_id
  697.         in      al,dx          ; get hi byte
  698.         xchg    al,ah
  699.         dec     dx
  700.         in      al,dx          ; get lo byte
  701.         cmp     ax,Adapter_id  ; did I find the card?
  702.         je      mch_chk_match  ; yes...
  703.         loop    mch_chk
  704.  
  705. ;       use this to leave microchannel POS_select as we found it...
  706.         pop     ax
  707.         mov     dx,POS_select
  708.         out     dx,al
  709.         popf
  710.         jmp     parse_start
  711.  
  712. mch_chk_match:
  713. ;       parse I/O base address and interrupt level from POS_2 data
  714.         mov     dx,POS_2
  715.         in      al,dx
  716. ;
  717. ;       determine interrupt level
  718.         and     al,0Ch                  ; bits 2,3 are IRQ level
  719.         mov     cl,2-1
  720.         shr     al,cl                   ; index for irq_list
  721.         xor     ah,ah
  722.         mov     bx,ax
  723.         mov     ax,irq_list[bx]
  724.         mov     int_no,al
  725.  
  726.         in      al,dx                   ; read POS_2 again
  727.         and     al,0F0h                 ; get index into io_list
  728.         mov     cl,4-1
  729.         shr     al,cl
  730.         xor     ah,ah
  731.         mov     bx,ax
  732.         mov     ax,io_list[bx]
  733.         mov     io_adr,ax
  734.  
  735.         pop     ax
  736.         mov     dx,POS_select
  737.         out     dx,al
  738.         popf
  739.  
  740. parse_start:
  741.  
  742. ;      parse  hardware interrupt number and I/O base address from the
  743. ;      command line.
  744. ;
  745.     mov    bx,offset int_no_msg    ; interrupt level?
  746.     mov    di,offset int_no
  747.     call    get_number
  748.     jc    _parse_exit
  749.     mov    bx,offset io_adr_msg    ; first comes the I/O base address
  750.     mov    di,offset io_adr
  751.     call    get_number
  752. _parse_exit:
  753.     clc
  754.     ret
  755.  
  756. ;==============================================================================;
  757. ;==================== SYS_MCA SUPPORT ENDS ===============================;
  758. ;==============================================================================;
  759.  
  760.     public etopen
  761. etopen:
  762.     writebport    DLCR_ENABLE,card_disable    ; disable etherstar
  763.     writebport    DLCR_XMIT_STAT,clear_status    ; clr xmit status
  764.     writebport    DLCR_XMIT_MASK,no_tx_irqs    ; disable xmit IRQ's
  765.     writebport    DLCR_RECV_STAT,clr_rcv_status    ; clear rcv status
  766.     writebport    DLCR_RECV_MASK,en_rcv_irqs    ; enable rcv IRQ's
  767.     writebport    DLCR_XMIT_MODE,xmit_mode    ; set xmit mode
  768.     writebport    DLCR_RECV_MODE,recv_mode    ; set receive mode
  769. ;
  770. ;      Set Node ID:
  771. ;
  772.     mov    cx,EADDR_LEN        ; calc base of I/O regs for node id
  773.     mov    bx,cs:io_adr
  774.     mov    dx,bx
  775.     add    bx,DLCR_NODE_ID
  776.     add    dx,PROM_ID        ; and base of PROM for copy
  777.     mov    ah,0ffh            ;start with all bits set.
  778. etopen0:
  779.     in    al,dx            ; read byte of factory address
  780.     and    ah,al            ;remove any bits that are zeroes.
  781.     xchg    bx,dx
  782.     out    dx,al            ; write to register
  783.     xchg    bx,dx
  784.     inc    dx
  785.     inc    bx
  786.     loop    etopen0            ; until copy is done...
  787. ;
  788. ;       Verify card address is not all 1's
  789. ;
  790.         cmp     ah,-1
  791.         jne     etopen0a
  792.         jmp     etopen_nocard           ;   all 1's, no card found
  793. etopen0a:
  794. ;
  795. ;      Verify card exists by comparing address to PROM
  796. ;
  797.     mov    cx,EADDR_LEN
  798. etopen1:
  799.     dec    dx
  800.     dec    bx
  801.     in    al,dx
  802.     xchg    bx,dx
  803.     mov    ah,al
  804.     in    al,dx
  805.     xchg    bx,dx
  806.     cmp    al,ah
  807.     jne    etopen_nocard        ; no card found
  808.     loop    etopen1
  809.  
  810.                                         ; repeat until BUF_EMPTY vacuum data port
  811.     mov    dx,cs:io_adr
  812.     mov    bx,dx
  813.     add    bx,DLCR_RECV_MODE
  814.     add    dx,BMPR_MEM_PORT
  815.     cmp    cs:is_186,0
  816.     je    vac_88
  817. vac_86:
  818.         in      ax,dx
  819.         xchg    dx,bx
  820.         in      ax,dx
  821.         xchg    dx,bx
  822.         test    al,BUF_EMPTY
  823.         jz      vac_86
  824.         jmp     short all_done
  825. vac_88:
  826.     in    al,dx
  827.         xchg    dx,bx
  828.         in      al,dx
  829.         xchg    dx,bx
  830.         test    al,BUF_EMPTY
  831.         jz      vac_88
  832. all_done:
  833.         writebport      DLCR_RECV_STAT,clr_rcv_status; clear possible underflow
  834.     writebport    DLCR_ENABLE,card_enable
  835.     call    set_recv_isr                ; install receive IRQ routine
  836.  
  837.     mov    al, int_no        ; Get board's interrupt vector
  838.     add    al, 8
  839.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  840.     jb    set_int_num        ; No.
  841.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  842. set_int_num:
  843.     xor    ah, ah            ; Clear high byte
  844.     mov    int_num, ax        ; Set parameter_list int num.
  845.  
  846.     movseg    es,cs
  847.     mov    di,offset rom_address
  848.     mov    cx,EADDR_LEN
  849.     mov    dx,cs:[io_adr]         ; get address from PROM
  850.     add    dx,PROM_ID
  851. get_adr:
  852.     in    al,dx
  853.     inc    dx
  854.     stosb
  855.     loop    get_adr
  856.  
  857.     print$    installed_ok                ; if all is okay,
  858.     clc
  859.     ret
  860. etopen_nocard:
  861.     mov    dx,offset no_card_msg    ; couldn't verify card exists...
  862.     stc
  863.     ret
  864.  
  865.     public    print_parameters
  866. print_parameters:
  867. ;echo our command-line parameters
  868.     mov    di,offset int_no    ; interrupt level.
  869.     mov    dx,offset int_no_msg
  870.     call    print_number
  871.     mov    di,offset io_adr    ; now comes the I/O base address
  872.     mov    dx,offset io_adr_msg
  873.     call    print_number
  874.     ret
  875.  
  876. code    ends
  877.  
  878.     end
  879.