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

  1. version    equ    1
  2.  
  3.     include    defs.asm
  4.  
  5. ; a driver for the EXOS 205 Ethernet controller by Dirk Koeppen (dirk@incom.de)
  6.  
  7. ; This program is free software; you can redistribute it and/or modify
  8. ; it under the terms of the GNU General Public License as published by
  9. ; the Free Software Foundation, version 1.
  10. ;
  11. ; This program is distributed in the hope that it will be useful,
  12. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ; GNU General Public License for more details.
  15. ;
  16. ; You should have received a copy of the GNU General Public License
  17. ; along with this program; if not, write to the Free Software
  18. ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20.  
  21.     public    int_no
  22.     public    driver_class, driver_type, driver_name, driver_function
  23.     public    parameter_list
  24.     public    usage_msg
  25.     public    copyright_msg
  26.     public    parse_args
  27.     public    print_parameters
  28.  
  29. ; inform 82586.asm that we have a larger amount of memory
  30. SEG586    equ    0fh
  31.  
  32. ; equates for controlling EXOS 205 i/o ports
  33. P_INTR        EQU    0        ; interrupt EXOS 205
  34. P_CTRL1        EQU    2        ; control port 1
  35.     P1_186    EQU     00000001b    ; enable 80186
  36.     P1_586    EQU     00000010b    ; enable 82586
  37.     P1_A12    EQU     00000100b    ; address bit 12 of EXOS memory
  38.     P1_NET    EQU    00001000b    ; enable net (disable loopback) 
  39.     P1_A13    EQU    00010000b    ; address bit 13 of EXOS memory 
  40.     P1_CA    EQU    00100000b    ; do a channel attention by host
  41.     P1_A14    EQU    01000000b    ; address bit 14 of EXOS memory
  42.     P1_A15    EQU    10000000b    ; address bit 15 of EXOS memory
  43. P_CTRL2        EQU    3        ; control port 2
  44.     P2_A16    EQU    00000001b    ; address bit 16 of EXOS memory
  45.     P2_SHM    EQU    01111110b    ; EXOS shared memory address on host
  46.     P2_ACC    EQU    10000000b    ; enable access to EXOS memory
  47. P_ACK        EQU    4        ; acknowledge interrupt
  48.  
  49.  
  50. ; here are some equates to syncronise the i186 and the host via a semaphore
  51. S_INST        EQU    0aah        ; a fancy value to flag installed code 
  52. S_EXEC        EQU    0a5h        ; .. code is executing
  53. S_FAILED    EQU    05ah        ; .. i186 has failed to execute code
  54. S_STOP        EQU    055h        ; .. code was successfully executed
  55.  
  56.  
  57. code    segment    word public
  58.     assume    cs:code, ds:code
  59.  
  60. int_no        db    2, 0, 0, 0    ; interrupt number
  61. io_addr        dw    310h, 0        ; I/O address for card
  62. base_addr    dw      0cc00h, 0    ; base segment for board
  63.  
  64. ex_eaddr    db      6 dup (0)    ; boards Ethernet address
  65. ex_ctrl1    db    0        ; copy of control port 1
  66. ex_ctrl2    db    0        ; .. port2
  67.  
  68. driver_class    db    BLUEBOOK, IEEE8023, 0    ; from the packet spec
  69. driver_type    db    13            ; from the packet spec
  70. driver_name    db    "EXOS205", 0        ; name of the driver
  71. driver_function    db    2
  72. parameter_list    label    byte
  73.     db    1        ; major rev of packet driver
  74.     db    9        ; minor rev of packet driver
  75.     db    14        ; length of parameter list
  76.     db    EADDR_LEN    ; length of MAC-layer address
  77.     dw    GIANT        ; MTU, including MAC headers
  78.     dw    MAX_MULTICAST * EADDR_LEN ; buffer size of multicast addrs
  79.     dw    0        ; (# of back-to-back MTU rcvs) - 1
  80.     dw    0        ; (# of successive xmits) - 1
  81. int_num    dw    0        ; interrupt # to hook for post-EOI
  82.                 ; processing, 0 == none
  83.  
  84. usage_msg    db "usage: exos205 [options] <packet_int_no> [int_no] [io_addr] [base_addr]",CR,LF,'$'
  85.  
  86. copyright_msg    db    "Packet driver for the EXOS 205, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,".",'0'+i82586_version,CR,LF
  87.         db    "Portions Copyright 1988 The Board of Trustees of the University of Illinois.",CR,LF
  88.         db    "Portions Copyright 1992 Dirk Koeppen (dirk@incom.de).",CR,LF,'$'
  89.  
  90. no_exos205    db    "Unable to initialize the EXOS 205 adapter.",CR,LF,'$'
  91.  
  92. int_no_name    db    "Interrupt number ",'$'
  93. io_addr_name    db    "I/O port ",'$'
  94. base_addr_name    db    "Shared memory address ",'$'
  95.  
  96.  
  97. ; ENABLE_NETWORK - switch on the transceiver
  98. enable_network:
  99.     ret        ; is on all the time
  100.  
  101.  
  102. ; RESET_586 - reset the network controller
  103. reset_586:
  104.     push    ds        ; could be called from different segment
  105.     push    ax
  106.     mov    ax, cs
  107.     mov    ds, ax
  108.  
  109.     loadport
  110.     setport P_CTRL1        ; load the i/o control register
  111.     mov    al, ex_ctrl1
  112.     or    al, P1_CA    ; set CA
  113.     and    al, NOT P1_586    ; disable i82586
  114.     out    dx, al        ; trigger the port
  115.     jmp    $+2        ; let the signal dry
  116.     or    al, NOT P1_586    ; enable i82586 
  117.     out    dx, al
  118.     mov    ex_ctrl1, al    ; save a copy
  119.     pop    ax
  120.     pop    ds
  121.     ret
  122.  
  123.  
  124. ; DOCA - do a channel attention
  125. doca:
  126.     push    ds        ; could be called from different segment
  127.     push    ax
  128.     mov    ax, cs
  129.     mov    ds, ax
  130.  
  131.     loadport
  132.     setport P_CTRL1        ; load the i/o control register
  133.     mov    al, ex_ctrl1
  134.     and    al, NOT P1_CA    ; clear CA
  135.     or    al, P1_586    ; enable i82586 if not already enabled
  136.     out    dx, al        ; trigger the port
  137.     jmp    $+2        ; let the signal dry
  138.      jmp    $+2
  139.     or    al, P1_CA    ; set CA
  140.     out    dx, al
  141.     mov    ex_ctrl1, al    ; save a copy
  142.  
  143.     setport    P_ACK        ; acknowledge intr (placed here because 
  144.     out    dx, ax        ; .. recv_isr calls doca each time)
  145.  
  146.     pop    ax
  147.     pop    ds
  148.     ret
  149.  
  150.  
  151. ; EX_INIT - initialize the EXOS205
  152. ex_init:
  153.     loadport        ; base of device
  154.     mov    ex_ctrl1, P1_NET+P1_A12+P1_A13+P1_A14+P1_A15 ; highest mem page
  155.  
  156.     mov    ax, base_addr    ; where the shared memory should get to
  157.     shr    ah, 1         ; shift it to the right place
  158.     and    ah, P2_SHM    ; zero all other bits
  159.     or    ah, P2_A16    ; set address bit 16
  160.     mov    ex_ctrl2, ah
  161.  
  162.     setport    P_CTRL1        ; set the EXOS memory address
  163.     mov    al, ex_ctrl1
  164.     out    dx, al
  165.  
  166.     setport    P_CTRL2
  167.     mov    al, ex_ctrl2
  168.     out    dx, al
  169.     jmp    $+2        ; let it dry
  170.     jmp    $+2
  171.     or    ex_ctrl2, P2_ACC ; enable the memory
  172.     mov    al, ex_ctrl2
  173.     out    dx, al
  174.  
  175. init_i186:            
  176.     push    es        ; save 'C' register type loop-counters
  177.     push    si
  178.     push    di
  179.     push    ds
  180.     mov    es, base_addr    ; ES:DI -> EXOS205 memory (end of last 16K page)
  181.     mov    di, 03fffh
  182.     mov    ax, cs        ; DS:SI -> code to be downloaded (end of code)
  183.     mov    ds, ax
  184.     mov    si, offset i186_end
  185.     mov    cx, (offset i186_end-offset i186_code) ; amount to be downloaded
  186.     inc    cx        ; one more because loops end at 0
  187.     std            ; copy backwards 
  188.  
  189.     rep    movsb        ; copy the code
  190.  
  191.     cld
  192.     pop    ds        ; restore original DS
  193.     mov    di, 03fffh     ; where the semaphore is located
  194.     sub     di, (offset i186_end-offset i186_sema)
  195.     mov    al, es:[di]    ; get semaphore
  196.     cmp    al, S_INST    ; check if code is installed
  197.     jne    init_failed    ; failed to init board
  198.  
  199.     setport    P_CTRL1
  200.     mov    al, ex_ctrl1    ; release the i186, let it execute the code
  201.     or    al, P1_186
  202.     mov    ex_ctrl1, al    ; .. and let it run forever
  203.     out    dx, al
  204.  
  205.     mov    ax, (36*2)    ; give it 2 seconds to start execution
  206.     call    set_timeout
  207.  
  208. init_loop1:
  209.     mov    al, es:[di]    ; get semaphore
  210.     cmp    al, S_EXEC    ; does it execute ?
  211.     je    init_i186exec
  212.  
  213.     call    do_timeout    ; loop until timeout
  214.     jne    init_loop1
  215.  
  216.     jmp    init_failed    ; failed to init board
  217.  
  218. init_i186exec:
  219.     mov    ax, (36*5)    ; give it 5 seconds to initialize
  220.     call    set_timeout
  221.  
  222. init_loop2:
  223.     mov    al, es:[di]    ; get semaphore
  224.     cmp    al, S_STOP    ; did it stop ?
  225.     je    init_i186stop
  226.  
  227.     call    do_timeout    ; loop until timeout
  228.     jne    init_loop2
  229.  
  230.     jmp    init_failed    ; failed to init board
  231.  
  232. init_i186stop:
  233.     xor    ax, ax         ; flag that everything worked all right
  234.     push    ax
  235.     mov    di, 03fffh     ; where the Ethernet address is located 
  236.     sub     di, (offset i186_end-offset i186_addr)
  237.     mov    bx, offset ex_eaddr
  238.     mov    cx, 6        ; 6 bytes to move
  239.  
  240. init_acpy:
  241.     mov    al, es:[di]    ; copy address
  242.     mov    ds:[bx], al
  243.     inc    di        ; next byte
  244.     inc    bx
  245.     loop    init_acpy    ; loop for all byte
  246.  
  247. init_end:
  248.     pop    ax
  249.  
  250.     setport    P_ACK        ; acknowledge intr to reset hardware logic
  251.     out    dx, ax
  252.  
  253.     pop    di         ; restore saved registers
  254.     pop    si
  255.     pop    es
  256.     or    ax, ax        ; setup zero flag
  257.     ret
  258.  
  259. init_failed:
  260.     setport    P_CTRL1        ; stop the i186
  261.     mov    al, ex_ctrl1
  262.     and    al, NOT P1_186    ; .. forever
  263.     mov    ex_ctrl1, al
  264.     out    dx, al
  265.     mov    ax, -1        ; failed to init board
  266.     push    ax
  267.     jmp    init_end
  268.  
  269.  
  270. ; I186_CODE - this code is downloaded to the EXOS205 to be executed by the i186
  271. i186_code:
  272. i186_addr:
  273.     db    08h, 00h, 14h    ; unique EXOS Ethernet address (byte 5-3)
  274.     db    0, 0, 0        ; .. byte 2-0 of the boards Ethernet address
  275.  
  276. i186_sema:
  277.     db    S_INST        ; semaphore will be S_STOP if code was executed
  278.  
  279. i186_ipl:            ; i186 bootstrap
  280.     cli            ; disable interrupts
  281.     xor    ax, ax        ; zero relocation register
  282.     mov    dx, 0fffeh
  283.     out    dx, ax
  284.     mov    ax, 0fff8h    ; setup UMCS register
  285.     out    0a0h, ax
  286.     mov    ax, 0007ch    ; .. PACS register
  287.     out    0a4h, ax
  288.     mov    ax, 080bch    ; .. MPCS register
  289.     out    0a8h, ax
  290.  
  291.     mov    ax, cs        ; DS -> CS
  292.     mov    ds, ax
  293.     
  294.     ; flag code execution
  295.     mov    bx, 00fffh - (offset i186_end-offset i186_sema)
  296.     mov    byte ptr ds:[bx], S_EXEC
  297.     xor    cx, cx
  298.  
  299. i186_wait:            ; spend some time to let host read the semaphore
  300.     jmp    $+2
  301.     jmp    $+2
  302.     jmp    $+2
  303.     loop    i186_wait
  304.  
  305.     ; where to write the boards Ethernet addr to (starts 3 bytes after code)
  306.     mov    si, 00fffh - (offset i186_end-offset i186_addr) + 3
  307.  
  308.     mov    dx, 0502h    ; low order nibble of byte 2 Ethernet address
  309.     xor    bx, bx        ; zero checksum
  310.     mov    cx, 3        ; 3 bytes of Ethernet address are to be read
  311.  
  312. i186_acpy:
  313.     in    al, dx        ; read one nibble
  314.     and    al, 00001111b    ; .. mask valid bits (just to get shure !)
  315.     mov    ah, al        ; .. store it
  316.     add    bl, al        ; .. add to checksum
  317.     inc    dx         ; go to high order nibble
  318.     inc    dx
  319.     in    al, dx        ; .. read it
  320.     add    bl, al        ; .. add to checksum
  321.     shl    al, 1         ; .. shift it to be high order nibble
  322.     shl    al, 1
  323.     shl    al, 1
  324.     shl    al, 1
  325.     or    al, ah        ; pack those two nibbles into one byte
  326.     mov    ds:[si], al     ; .. and store the byte
  327.  
  328.     inc    dx        ; go to next nibble of Ethernet address 
  329.     inc    dx
  330.     inc    si    
  331.     loop    i186_acpy    ; loop until all 3 bytes are read
  332.  
  333.     mov    ah, bl        ; add bottom to top nibble
  334.     shr    ah, 1        ; top nibble
  335.     shr    ah, 1
  336.     shr    ah, 1
  337.     shr    ah, 1
  338.     and    bl, 00001111b    ; bottom nibble
  339.     add    ah, bl        ; add them
  340.     xor    ah, 5        ; is x-ored by 5 to avoid 0x00 or 0xff problem
  341.  
  342.     in    al, dx        ; DX -> checksum
  343.     cmp    ah, al
  344.     je    i186_ok
  345.  
  346.     mov    byte ptr ds:[si], S_FAILED; flag that checksum failed
  347.  
  348.     jmp    $        ; stop execution (i186 will be stopped by host)
  349.  
  350. i186_ok:
  351.     mov    byte ptr ds:[si], S_STOP ; flag that we have stopped execution
  352.     xor    ax, ax        ; set the interrupt vector
  353.     mov    ds, ax        ; .. i82586 is connected to INT2
  354.     mov    si, 4*14    ; INT2 has vector type 14
  355.     mov    word ptr ds:[si], 00fffh - (offset i186_end-offset i186_intr)
  356.     inc    si
  357.     inc    si
  358.     mov    word ptr ds:[si], 0ff00h
  359.  
  360.     sti            ; enable interrupts
  361.  
  362.     mov    dx, 3ch        ; INT2 control register
  363.     mov    ax, 3        ; level triggered, unmasked and prio 3
  364.     out    dx, ax
  365.  
  366.     xor    bx, bx        ; zero counters
  367.     xor    cx, cx
  368.     mov    bp, 00fffh - (offset i186_end-offset i186_lcnt)
  369.  
  370. i186_loop:            ; endless loop to keep i186 doing something
  371.     nop
  372.     nop
  373.     nop
  374.     nop
  375.     loop    i186_loop
  376.  
  377.     inc    bx        ; count
  378.     mov    cs:[bp], bx    ; .. and store for debugging
  379.     jmp    i186_loop    ; cycle endless while waiting for interrupts 
  380.  
  381. i186_intr:            ; interrupt routine called by 82586 intr
  382.     push    dx
  383.     mov    dx, 00600h    ; interrupt host first
  384.     out    dx, ax        
  385.  
  386.     push    ax
  387.     push    bx
  388.     push    bp
  389.  
  390.     mov    bp, 00fffh - (offset i186_end-offset i186_icnt)
  391.     mov    bx, cs:[bp]
  392.     inc    bx        ; increment interrupt counter
  393.     mov    cs:[bp], bx    ; .. and store for debugging
  394.  
  395.     mov    dx, 22h        ; acknowledge interrupt
  396.     mov    ax, 8000h
  397.     out    dx, ax
  398.  
  399.     pop    bp
  400.     pop    bx
  401.     pop    ax
  402.     pop    dx
  403.     iret
  404.  
  405.     db    'INTR cnt->'    ; some debugging variables
  406. i186_icnt:
  407.     dw    0        ; counts 82586 interrupts
  408.     db    'LOOP cnt->'
  409. i186_lcnt:
  410.     dw    0        ; loops to flag execution
  411.  
  412. i586_reset_vector:
  413.     db    0eah    dup (0)    ; reserved for the i82586 reset vector
  414.  
  415. i186_reset_vector:
  416.     db    0eah        ; opcode 'jmp far'
  417.     dw    00fffh - (offset i186_end-offset i186_ipl)
  418.     dw    0ff00h
  419.     db    0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fill patterns
  420.  
  421. i186_end:
  422.     db    0        ; one more fill pattern    
  423.  
  424.  
  425. ; here we include the code that is common between 82586 implementations.
  426. ; everything above this is resident.
  427.     include    82586.asm
  428. ; everything below this is discarded upon installation.
  429.  
  430. ; CHECK_BOARD - check if there really is a EXOS 205 installed
  431. check_board:
  432.     mov    SCP, 0            ; 16 bit bus type in scb.
  433.  
  434.     call    ex_init            ; setup the board
  435.     je    check_ok
  436.  
  437.     mov    dx, offset no_exos205    ; failed to init board
  438.     jmp    error
  439.  
  440. check_ok:
  441.     xor    ax, ax            ; have a return value
  442.     ret
  443.  
  444.  
  445. ; PARSE_ARGS - read the command line option and overwrite defaults
  446. parse_args:
  447.     mov    di, offset int_no
  448.     call    get_number
  449.     mov    di, offset io_addr
  450.     call    get_number
  451.     mov    di, offset base_addr
  452.     call    get_number
  453.     clc
  454.     ret
  455.  
  456. ; PRINT_PARAMETERS - print out the boards configuration parameters
  457. print_parameters:
  458.     mov    di, offset int_no
  459.     mov    dx, offset int_no_name
  460.     call    print_number
  461.     mov    di, offset io_addr
  462.     mov    dx, offset io_addr_name
  463.     call    print_number
  464.     mov    ax, memory_begin
  465.     mov    cl, 4
  466.     shr    ax, cl
  467.     add    base_addr, ax
  468.     push    ax
  469.     mov    di, offset base_addr
  470.     mov    dx, offset base_addr_name
  471.     call    print_number
  472.     pop    ax
  473.     sub    base_addr, ax
  474.     ret
  475.  
  476. ; GET_ADDRESS - get boards Ethernet address
  477. ;    enter with es:di -> place to get the address,
  478. ;        cx = size of address buffer.
  479. ;    exit with nc, cx = actual size of address,
  480. ;         or cy if buffer not big enough.
  481. get_address:
  482.     assume    ds: code
  483.     mov    bx, offset ex_eaddr    ; where to copy is located
  484. get_address_1:
  485.     mov    al, ds:[bx]        ; copy a byte of the address
  486.     stosb                ; put it away
  487.     inc    bx            ; next address byte 
  488.     loop    get_address_1        ; go back for rest
  489.     ret
  490.  
  491.     include    memtest.asm
  492.  
  493. code    ends
  494.     end
  495.