home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / lan / drivrs30 / tail.asm < prev    next >
Assembly Source File  |  1989-06-09  |  10KB  |  454 lines

  1. ;   PC/FTP Packet Driver source, conforming to version 1.05 of the spec
  2. ;   Russell Nelson, Clarkson University.  July 20, 1988
  3. ;   Updated to version 1.08 Feb. 17, 1989.
  4. ;   Copyright 1988,1989 Russell Nelson
  5.  
  6. ;   This program is free software; you can redistribute it and/or modify
  7. ;   it under the terms of the GNU General Public License as published by
  8. ;   the Free Software Foundation, version 1.
  9. ;
  10. ;   This program is distributed in the hope that it will be useful,
  11. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. ;   GNU General Public License for more details.
  14. ;
  15. ;   You should have received a copy of the GNU General Public License
  16. ;   along with this program; if not, write to the Free Software
  17. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19.     include    defs.asm
  20.  
  21. code    segment byte public
  22.     assume    cs:code, ds:code
  23.  
  24.     extrn    phd_dioa: byte
  25.     extrn    phd_environ: word
  26.  
  27. ;usage_msg is of the form "usage: driver <packet_int_no> <args>"
  28.     extrn    usage_msg: byte
  29.  
  30. ;copyright_msg is of the form:
  31. ;"Packet driver for the foobar",CR,LF
  32. ;"Portions Copyright 19xx, J. Random Hacker".
  33.     extrn    copyright_msg: byte
  34.  
  35. copyleft_msg    label    byte
  36.  db "Packet driver skeleton copyright 1988-89, Russell Nelson.",CR,LF
  37.  db "This program is free software; see the file COPYING for details.",CR,LF
  38.  db "NO WARRANTY; see the file COPYING for details.",CR,LF
  39. crlf_msg    db    CR,LF,'$'
  40.  
  41. ;parse_args should parse the arguments.
  42. ;called with ds:si -> immediately after the packet_int_no.
  43.     extrn    parse_args: near
  44.  
  45.     extrn    our_isr: near, their_isr: dword
  46.     extrn    packet_int_no: byte
  47.     extrn    is_at: byte
  48.     extrn    int_no: byte
  49.     extrn    driver_class: byte
  50.  
  51. packet_int_no_name    db    "Packet interrupt number ",'$'
  52. eaddr_msg    db    "My Ethernet address is ",'$'
  53.  
  54. signature    db    'PKT DRVR',0
  55. signature_len    equ    $-signature
  56.  
  57. already_msg    db    CR,LF,"There is already a packet driver at ",'$'
  58. packet_int_msg    db    CR,LF
  59.         db    "Error: <packet_int_no> should be in the range 0x60 to 0x80"
  60.         db    '$'
  61. int_msg        db    CR,LF
  62.         db    "Error: <int_no> should be no larger than "
  63. int_msg_num    label    word
  64.         db    "xx"
  65.         db    '$'
  66.  
  67. our_address    db    EADDR_LEN dup(?)
  68.  
  69. ;etopen should initialize the device.  If it needs to give an error, it
  70. ;can issue the error message and quit to dos.
  71.     extrn    etopen: near
  72.  
  73. ;get the address of the interface.
  74. ;enter with es:di -> place to get the address, cx = size of address buffer.
  75. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  76.     extrn    get_address: near
  77.  
  78. segmoffs    struc
  79. offs        dw    ?
  80. segm        dw    ?
  81. segmoffs    ends
  82.  
  83. HT    equ    09h
  84. CR    equ    0dh
  85. LF    equ    0ah
  86.  
  87. already_error:
  88.     mov    dx,offset already_msg
  89.     mov    di,offset packet_int_no
  90.     call    print_number
  91.     int    20h
  92.  
  93. usage_error:
  94.     mov    dx,offset usage_msg
  95. error:
  96.     mov    ah,9
  97.     int    21h
  98.     int    20h
  99.  
  100.     public    start_1
  101. start_1:
  102.     mov    dx,offset copyright_msg
  103.     mov    ah,9
  104.     int    21h
  105.  
  106.     mov    dx,offset copyleft_msg
  107.     mov    ah,9
  108.     int    21h
  109.  
  110.     mov    si,offset phd_dioa+1
  111.     cmp    byte ptr [si],CR    ;end of line?
  112.     je    usage_error
  113.  
  114.     mov    di,offset packet_int_no    ;parse the packet interrupt number
  115.     mov    bx,offset packet_int_no_name
  116.     call    get_number        ;  for them.
  117.  
  118.     call    parse_args
  119.  
  120.     mov    dx,offset packet_int_msg;make sure that the packet interrupt
  121.     cmp    packet_int_no,60h    ;  number is in range.
  122.     jb    error
  123.     cmp    packet_int_no,80h
  124.     ja    error
  125.  
  126.     mov    ah,35h            ;get their packet interrupt.
  127.     mov    al,packet_int_no
  128.     int    21h
  129.  
  130.     lea    di,3[bx]        ;see if there is already a signature
  131.     mov    si,offset signature    ;  there.
  132.     mov    cx,signature_len
  133.     repe    cmpsb
  134.     je    already_error        ;yes, so we can't go there.
  135.  
  136.     mov    ax,0f000h        ;ROM segment
  137.     mov    es,ax
  138.     mov    al,7            ;maximum interrupt on a PC
  139.     mov    int_msg_num,'7'+' '*256
  140.     cmp    word ptr es:[0fffeh],0fch    ;is this an AT?
  141.     jne    not_at            ;no.
  142.     mov    al,15            ;maximum interrupt on an AT
  143.     mov    int_msg_num,'1'+'5'*256
  144.  
  145.     inc    is_at            ;yes - remember that we've got an AT.
  146.  
  147.     cmp    int_no,2        ;map IRQ 2 to IRQ 9.
  148.     jne    not_at
  149.     mov    int_no,9
  150. not_at:
  151.  
  152.     mov    dx,offset int_msg    ;make sure that the packet interrupt
  153.     cmp    int_no,al        ;  number is in range.
  154.     jbe    int_ok
  155.     jmp    error
  156. int_ok:
  157.  
  158.     call    etopen            ;init the driver.  If any errors,
  159.                     ;this routine returns cy.
  160.     jc    no_resident
  161.  
  162.     push    dx            ;remember where they want to end.
  163.  
  164.     mov    ah,35h            ;remember their packet interrupt.
  165.     mov    al,packet_int_no
  166.     int    21h
  167.     mov    their_isr.offs,bx
  168.     mov    their_isr.segm,es
  169.  
  170.     mov    ah,25h            ;install our packet interrupt
  171.     mov    dx,offset our_isr
  172.     int    21h
  173.  
  174.     cmp    driver_class,1        ;Ethernet?
  175.     jne    print_addr_2        ;no, don't print what we don't have.
  176.  
  177.     push    ds
  178.     pop    es
  179.     mov    di,offset our_address
  180.     mov    cx,EADDR_LEN
  181.     call    get_address
  182.  
  183.     mov    dx,offset eaddr_msg
  184.     mov    ah,9
  185.     int    21h
  186.  
  187.     mov    cx,EADDR_LEN
  188.     mov    si,offset our_address
  189. print_addr:
  190.     push    cx
  191.     lodsb
  192.     mov    cl,' '            ;Don't eliminate leading zeroes.
  193.     call    byteout
  194.     pop    cx
  195.     cmp    cx,1
  196.     je    print_addr_1
  197.     mov    al,':'
  198.     call    chrout
  199. print_addr_1:
  200.     loop    print_addr
  201.  
  202.     mov    dx,offset crlf_msg    ;can't depend on DOS to newline for us.
  203.     mov    ah,9
  204.     int    21h
  205.  
  206. print_addr_2:
  207.  
  208.     mov    ah,49h            ;free our environment, because
  209.     mov    es,phd_environ        ;  we won't need it.
  210.     int    21h
  211.  
  212.     mov    bx,1            ;get the stdout handle.
  213.     mov    ah,3eh            ;close it in case they redirected it.
  214.     int    21h
  215.  
  216.     pop    dx            ;get their ending address.
  217.     add    dx,0fh            ;round up to next highest paragraph.
  218.     mov    cl,4
  219.     shr    dx,cl
  220.     mov    ah,31h            ;terminate, stay resident.
  221.     int    21h
  222.  
  223. no_resident:
  224.     int    20h
  225.  
  226.  
  227.     public    get_number
  228. get_number:
  229.     mov    bp,10            ;we default to 10.
  230.     jmp    short get_number_0
  231.  
  232.     public    get_hex
  233. get_hex:
  234.     mov    bp,16
  235. ;get a hex number, skipping leading blanks.
  236. ;enter with si->string of digits,
  237. ;    bx -> dollar terminated name of number,
  238. ;    di -> dword to store the number in.  [di] is not modified if no
  239. ;        digits are given, so it acts as the default.
  240. ;return cy if there are no digits at all.
  241. ;return nc, bx:cx = number, and store bx:cx at [di].
  242. get_number_0:
  243.     push    bx            ;remember the name of this number.
  244.     call    skip_blanks
  245.     call    get_digit        ;is there really a number here?
  246.     jc    get_number_3
  247.     or    al,al            ;Does the number begin with zero?
  248.     jne    get_number_4        ;no.
  249.     mov    bp,8            ;yes - they want octal.
  250. get_number_4:
  251.  
  252.     xor    cx,cx            ;get a hex number.
  253.     xor    bx,bx
  254. get_number_1:
  255.     lodsb
  256.     cmp    al,'x'            ;did they really want hex?
  257.     je    get_number_5        ;yes.
  258.     cmp    al,'X'            ;did they really want hex?
  259.     je    get_number_5        ;yes.
  260.     call    get_digit        ;convert a character into an int.
  261.     jc    get_number_2        ;not a digit (neither hex nor dec).
  262.     xor    ah,ah
  263.     cmp    ax,bp            ;larger than our base?
  264.     jae    get_number_2        ;yes.
  265.  
  266.     push    ax            ;save the new digit.
  267.  
  268.     mov    ax,bp            ;multiply the low word by ten.
  269.     mul    cx
  270.     mov    cx,ax            ;keep the low word.
  271.     push    dx            ;save the high word for later.
  272.     mov    ax,bp
  273.     mul    bx
  274.     mov    bx,ax            ;we keep only the low word (which is our high word)
  275.     pop    dx
  276.     add    bx,ax            ;add the high result from earlier.
  277.  
  278.     pop    ax            ;get the new digit back.
  279.     add    cx,ax            ;add the new digit in.
  280.     adc    bx,0
  281.     jmp    get_number_1
  282. get_number_5:
  283.     mov    bp,16            ;change the base to hex.
  284.     jmp    get_number_1
  285. get_number_2:
  286.     dec    si
  287.     mov    [di],cx            ;store the parsed number.
  288.     mov    [di+2],bx
  289.     clc
  290.     jmp    short get_number_6
  291. get_number_3:
  292.     stc
  293. get_number_6:
  294.     pop    dx            ;get the name of the number back.
  295.  
  296.     pushf                ;save some stuff.
  297.     push    bx
  298.     push    cx
  299.     push    si
  300.     push    di
  301.     call    print_number
  302.     pop    di
  303.     pop    si
  304.     pop    cx
  305.     pop    bx
  306.     popf
  307.     ret
  308.  
  309.  
  310. print_number:
  311. ;enter with dx -> dollar terminated name of number, di ->dword.
  312. ;exit with the number printed and the cursor advanced to the next line.
  313.     mov    ah,9            ;print the name of the number.
  314.     int    21h
  315.     mov    al,'0'
  316.     call    chrout
  317.     mov    al,'x'
  318.     call    chrout
  319.     mov    ax,[di]            ;print the number in hex.
  320.     mov    dx,[di+2]
  321.     call    hexout
  322.     mov    al,' '
  323.     call    chrout
  324.     mov    al,'('
  325.     call    chrout
  326.     mov    ax,[di]            ;print the number in decimal.
  327.     mov    dx,[di+2]
  328.     call    decout
  329.     mov    al,')'
  330.     call    chrout
  331.     mov    al,CR
  332.     call    chrout
  333.     mov    al,LF
  334.     call    chrout
  335.     ret
  336.  
  337.  
  338.     public    skip_blanks
  339. skip_blanks:
  340.     lodsb                ;skip blanks.
  341.     cmp    al,' '
  342.     je    skip_blanks
  343.     cmp    al,HT
  344.     je    skip_blanks
  345.     dec    si
  346.     ret
  347.  
  348.  
  349. get_digit:
  350. ;enter with al = character
  351. ;return nc, al=digit, or cy if not a digit.
  352.     cmp    al,'0'            ;decimal digit?
  353.     jb    get_digit_1        ;no.
  354.     cmp    al,'9'            ;. .?
  355.     ja    get_digit_2        ;no.
  356.     sub    al,'0'
  357.     clc
  358.     ret
  359. get_digit_2:
  360.     or    al,20h
  361.     cmp    al,'a'            ;hex digit?
  362.     jb    get_digit_1
  363.     cmp    al,'f'            ;hex digit?
  364.     ja    get_digit_1
  365.     sub    al,'a'-10
  366.     clc
  367.     ret
  368. get_digit_1:
  369.     stc
  370.     ret
  371.  
  372.  
  373.     public    hexout
  374. hexout:
  375.     mov    cl,'0'            ;prepare to eliminate leading zeroes.
  376.     xchg    ax,dx            ;just output 32 bits in hex.
  377.     call    wordout            ;output dx.
  378.     xchg    ax,dx
  379.     jmp    wordout            ;output ax.
  380.  
  381.     public    decout
  382. decout:
  383.     mov    si,ax            ;get the number where we want it.
  384.     mov    di,dx
  385.  
  386.     xor    ax,ax            ;start with all zeroes in al,bx,bp
  387.     mov    bx,ax
  388.     mov    bp,ax
  389.  
  390.     mov    cx,32            ;32 bits in two 16 bit registers.
  391. decout_1:
  392.     shl    si,1
  393.     rcl    di,1
  394.     xchg    bp,ax
  395.     call    addbit
  396.     xchg    bp,ax
  397.     xchg    bx,ax
  398.     call    addbit
  399.     xchg    bx,ax
  400.     adc    al,al
  401.     daa
  402.     loop    decout_1
  403.  
  404.     mov    cl,'0'            ;prepare to eliminate leading zeroes.
  405.     call    byteout            ;output the first two.
  406.     mov    ax,bx            ;output the next four
  407.     call    wordout            ;output the next four
  408.     mov    ax,bp
  409. wordout:
  410.     push    ax
  411.     mov    al,ah
  412.     call    byteout
  413.     pop    ax
  414. byteout:
  415.     mov    ah,al
  416.     shr    al,1
  417.     shr    al,1
  418.     shr    al,1
  419.     shr    al,1
  420.     call    digout
  421.     mov    al,ah
  422. digout:
  423.     and    al,0fh
  424.     add    al,90h    ;binary digit to ascii hex digit.
  425.     daa
  426.     adc    al,40h
  427.     daa
  428.     cmp    al,cl            ;leading zero?
  429.     je    return
  430.     mov    cl,-1            ;no more leading zeros.
  431. chrout:
  432.     push    ax            ;print the char in al.
  433.     xchg    al,dl
  434.     mov    ah,2
  435.     int    21h
  436.     xchg    al,dl
  437.     pop    ax
  438. return:
  439.     ret
  440.  
  441.  
  442. addbit:    adc    al,al
  443.     daa
  444.     xchg    al,ah
  445.     adc    al,al
  446.     daa
  447.     xchg    al,ah
  448.     ret
  449.  
  450.  
  451. code    ends
  452.  
  453.     end
  454.