home *** CD-ROM | disk | FTP | other *** search
- version equ 0
-
- include defs.asm
- ; ntinet.mac
- ;
- ; macros used for calling c routines.
- ;
- pusharg macro seg, off
- ifnb <seg>
- push seg
- $$cnt = $$cnt+2
- endif
- ifnb <off>
- push off
- $$cnt = $$cnt+2
- endif
- endm
-
-
- ccall macro rtn, p1, p2, p3, p4, p5
- $$cnt = 0
- ifnb <p5>
- pusharg p5
- endif
- ifnb <p4>
- pusharg p4
- endif
- ifnb <p3>
- pusharg p3
- endif
- ifnb <p2>
- pusharg p2
- endif
- ifnb <p1>
- pusharg p1
- endif
- call rtn
- if $$cnt
- add sp,$$cnt
- endif
- endm
-
- save macro regs
- irp arg,<regs>
- push arg
- endm
- endm
-
- restore macro regs
- irp arg,<regs>
- pop arg
- endm
- endm
-
- ;
-
- include lance.inc
-
- ;
- ; GLBL.INC
- ;
- ; global equates for lance dumb board
- ;
- pt_status equ 0 ;read status port
- pt_clrclk equ 0 ;write to clear clock interrupt
- pt_etaddr equ 1 ;read ether address rom offset
- pt_resetl equ 1 ;write to reset lance
- pt_ldata equ 2 ;lance data port 2,3
- pt_laddr equ 4 ;lance address port 4,5
-
- st_mask equ 0ch ;00001100B for (is1 is0)
-
- ;int selects
- irqn_10 equ 00h ;(is0 is1) = (0 0)
- irqn_11 equ 04h ;(0 1)
- irqn_12 equ 08h ;(1 0)
- irqn_15 equ 0ch ;(1 1)
-
- IRQ10 equ 10
-
- ; status port bits
-
- NET_INT equ 01h ;bit for net interrupt status
- CLK_INT equ 02h ;bit for clock interrupt status
- IPL equ 04h ;ipl bit
- HILO equ 08h ;ram at 0000, or ram at 8000
- MINT equ net_int+clk_int ;interrupt mask
- ADDR equ 0F0h ;mask for dual port segment
-
-
- DPLEN equ 8000h ;length of dual port ram
- BUFSIZE equ 1518 ;should change to GIANT + 4(CRC)
-
- ; Packet sizes = source(6) + destination(6) + type (2) + I field. (803.2 spec)
- ;
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;
- ;Following is the list of variables that need to be adjusted if the dp
- ;usage is changed:
- ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- XAREA equ 5F78H ;start of transmit descriptors
- RAREA equ 0018h ;start of receive descriptors
-
- NUMTDESC equ 4 ;number of transmit descriptors
- NUMRDESC equ 16 ;number of receive descriptors
-
- TBAREA equ XAREA+(NUMTDESC*tdesclen) ;xmit buf pool
- RBAREA equ RAREA+(NUMRDESC*rdesclen) ;rcv buffer pool
-
- ;our data segment is a constant distance from the es!
- OUROFFSET equ TBAREA + NUMTDESC*BUFSIZE
-
- RLEN equ RLEN16 ;lance mask for rcv-descriptors
- TLEN equ TLEN4 ;lance mask for snd-descriptors
-
- ;the total dp size reserved for lance use
- LANCE_SZ equ INITBLK_SZ+ NUMRDESC*(RDESCLEN+BUFSIZE)+ NUMTDESC*(TDESCLEN+BUFSIZE)
-
- ;the end of RAERA
- OUTOF_BOUND equ RBAREA ;98; for wrap up checking of r-descs
-
-
- code segment word public
- assume cs:code, ds:code
-
- extrn maskint:near
- extrn set_recv_isr: near
-
-
- public int_no, io_addr, base_addr
- int_no db 3,0,0,0 ; interrupt number.
- io_addr dw 0338h,0 ; I/O address for card (jumpers)
- base_addr dw 0d000h,0 ; base segment for board (jumper set)
-
- int_no_name db "Interrupt number ",'$'
- io_addr_name db "I/O port ",'$'
- base_addr_name db "Memory address ",'$'
-
- nosdesc_msg db "no send descriptor.",CR,LF,'$'
- chperr_msg db "chip doesn't want to finish init",CR,LF,'$'
- porterr_msg db "wrong port #",CR,LF,'$'
- hwerr_msg db "hardware error",CR,LF,'$'
- initerr_msg db "can't init lance chip",CR,LF,'$'
- good_msg db "Lance initialized successfully.",CR,LF,'$'
- reset_msg db "Can't reset the interface",CR,LF,'$'
- interr_msg db "IRQ# parameter wrong.",CR,LF,'$'
-
- public driver_class, driver_type, driver_name, driver_function, parameter_list
- driver_class db BLUEBOOK, IEEE8023, 0 ;from the packet spec
- driver_type db 100 ;--mz?
- driver_name db 'nti',0,'$' ;name of the driver.
- driver_function db 2
- parameter_list label byte
- db 1 ;major rev of packet driver
- db 9 ;minor rev of packet driver
- db 14 ;length of parameter list
- db EADDR_LEN ;length of MAC-layer address
- dw GIANT ;MTU, including MAC headers
- dw MAX_MULTICAST * EADDR_LEN ;buffer size of multicast addrs
- dw 0 ;(# of back-to-back MTU rcvs) - 1
- dw 0 ;(# of successive xmits) - 1
- int_num dw 0 ;Interrupt # to hook for post-EOI
- ;processing, 0 == none,
-
- public rcv_modes
- rcv_modes dw 4 ;number of receive modes in our table.
- dw 0,0,0,rcv_mode_3
-
-
- ;begin importing data
- public UNITID, sdesc_cnt, rdesc_cnt, actsdesc, actrdesc
- UNITID db 6 dup (0) ;current ether address of the interface
- sdesc_cnt dw 2 ;
- rdesc_cnt dw 8
- actsdesc dw 0
- actrdesc dw 0
-
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; send_pkt:
- ;
- ;enter with ds:si -> packet, cx = packet length.
- ;exit with nc if ok, or else cy if error, dh set to error number.
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public as_send_pkt
- ; The Asynchronous Transmit Packet routine.
- ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
- ; interrupts possibly enabled.
- ; Exit with nc if ok, or else cy if error, dh set to error number.
- ; es:di and interrupt enable flag preserved on exit.
- as_send_pkt:
- ret
-
- public drop_pkt
- ; Drop a packet from the queue.
- ; Enter with es:di -> iocb.
- drop_pkt:
- assume ds:nothing
- ret
-
- public xmit
- ; Process a transmit interrupt with the least possible latency to achieve
- ; back-to-back packet transmissions.
- ; May only use ax and dx.
- xmit:
- assume ds:nothing
- ret
-
-
- public send_pkt
- send_pkt:
- assume ds:nothing
- push es
- call set_dp
-
- push ds
- call set_ds ;set out ds-->cs
-
- mov dx,cx ;a copy of length
-
- cmp dx,GIANT ; Is this packet too large?
- ja send_pkt_toobig
-
- cmp dx,RUNT ; minimum length for Ether
- jnb oklen
- mov dx,RUNT ; make sure size at least RUNT
- oklen:
- mov bx,[actsdesc] ;get pointer to active snd desc
- mov cx,0 ;set up count down parameters
- td10:
- test es:td_stat[bx],t_own ;have empty buffer?
- jz dox0 ;yes, then send message
- loop td10 ;otherwise, wait for it
- mov dx,offset nosdesc_msg
- ccall _dispMSG,dx
- mov dh,CANT_SEND
- stc ;error ret
- pop ds
- pop es
- ret
-
- dox0:
- pop ds
- mov cx,dx ;get back the real length
- call fill ;ds:si - source, es:bx - dest, cx:length
- ;ax has the return code, either 0 or 0ffh
-
- ;is chip functioning?
- cmp ax,0ffh ;fatal error happened last time?
- je td15 ;error!
- clc ;good ret
- pop es
- ret
- td15:
- mov dh,CANT_SEND
- stc
- pop es
- ret
-
- send_pkt_toobig:
- mov dh,NO_SPACE
- stc
- pop ds
- pop es
- ret
-
- include movemem.asm
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; fill - proc the xerror & copy message to xmit buffer
- ;
- ; entry - es:bx points to free xmit descriptor (dest)
- ; ds:si --> source buf pointer
- ; cx:length of data
- ;
- ; exit - xmit buffer (bx) filled
- ; ax = 0: OK; 0ffh: fatal error happened last send
- ; bx changed
- ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- public fill
- fill:
- assume ds:nothing
- push ds ;save theirs
-
- call set_ds ;set ours
-
- call xmt_errs ;process previous errors
- cmp ax,0
- je success
- pop ds
- ret ;ax == ffh
-
- success:
- ;ds:si - source, es:bx - dest, cx - length
- ;simply send whatever given by the application, assuming the
- ;destination address and everything has been taken care of
-
- pop ds
- push cx ;save it
- mov di,es:td_addr[bx] ;get dest buf pointer
- call movemem ;ds:si --> es:di
- pop cx
-
- push ds
- call set_ds
- ;get the sdesc ready and pump the data out
- neg cx ;two's compliment
- or cx,td_bmask ;set these bits
- mov es:td_bcnt[bx],cx ;set in length to descriptor
- mov ax,0 ;set descriptor status for lance
- or ax,t_own ;he now owns it
- or ax,t_stp ;start of packet
- or ax,t_enp ;end of packet
- mov es:td_stat[bx],ax ;give it away
- mov ax,l_tdnd+l_inea ;tell lance we have data
- call w_csr ;send it
-
- ;all done, update the actsdesc
- add bx,tdesclen ;point at next descriptor
- dec word ptr[sdesc_cnt] ;dec counter
- jnz tfl ;used all?
- mov word ptr[sdesc_cnt],NUMTDESC ;yes start at begining
- mov bx,XAREA
- tfl:
- mov [actsdesc],bx ;set pointer
-
- mov ax,0
- pop ds
- ret ;good ret
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; xmt_errs:
- ; Check at if the previous send has any errors or not.
- ; entry - es:bx sdesc
- ; exit - ax:0 - ok; ffh:fatal error
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public xmt_errs
- xmt_errs:
- mov ax,es:td_tdr[bx] ;get rest of status
- test ax,t_more ;more than one retry needed
- jz xisr2
- call count_out_err
- jmp xisr3
- xisr2:
- test ax,t_one ;one retry?
- jz xisr3 ;no
- call count_out_err
- xisr3:
- test ax,t_lcol ;late collision
- jz xisr4 ;no
- call count_out_err
- xisr4:
- test ax,t_def ;deferred xmit?
- jz xisr5
- call count_out_err
- xisr5:
- test ax,t_lcar ;loss of carrier
- jz xisr6
- call count_out_err
- xisr6:
- test ax,t_uflo ;silo underflow?
- jz xisr7
- jmp fatal_err
- xisr7:
- test ax,t_buff ;buffer error no end
- jz all_rite ;last sent all right
- fatal_err:
- call count_out_err
- mov ax,0ffh ;fatal error
- ret ;
-
- all_rite:
- mov ax,0
- ret
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;get_address:
- ; We get the interface address from our internal version UNITID.
- ; set_address() could change the value of UNITID.
- ;
- ;enter with es:di -> place to put the address, cx = size of address buffer.
- ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public get_address
- get_address:
- assume ds:code
- cmp cx,EADDR_LEN ;make sure that we have enough room.
- jb get_address_2
- mov cx,EADDR_LEN
- lea si,UNITID
- get_address_1:
- call movemem
- mov cx,EADDR_LEN
- clc
- ret
- get_address_2:
- stc
- ret
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; set_address:
- ; set current ethernet address in UNITID, also change the init block
- ;
- ;enter with ds:si -> Ethernet address, CX = length of address.
- ;exit with nc if okay, or cy, dh=error if any errors.
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public set_address
- set_address:
- assume ds:nothing
- push ax
- push di
- push es
- mov ax,cs
- mov es,ax
-
- cmp cx,EADDR_LEN
- jne set_address2
-
- push si ;save it for later use
- push cx
-
- mov di,offset UNITID
- call movemem
-
- ;should also change the init_block
- call set_dp
- mov di,offset i_padr
- pop cx
- pop si ;get back the old pointer
- call movemem
-
- pop es
- pop di
- pop ax
- clc
- ret
-
- set_address2:
- mov dh,BAD_ADDRESS
- stc
- pop es
- pop di
- pop ax
- ret
-
-
-
- rcv_mode_3:
- ;receive mode 3 is the only one we support, so we don't have to do anything.
- ret
-
-
- public set_multicast_list
- set_multicast_list:
- ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
- ;return nc if we set all of them, or cy,dh=error if we didn't.
- mov dh,NO_MULTICAST
- stc
- ret
-
-
- public terminate
- terminate:
- ret
-
- public reset_interface
- reset_interface:
- ;reset the interface.
- assume ds:code
- call hardware ;reset the UNITID
- cmp al,0
- jne port_err
-
- cli
-
- call lance_init ;init_blk, xmt, rcv
- cmp ax,0 ;init ok?
- jne lance_err
- sti
- clc
- ret
-
- lance_err:
- mov dx,offset initerr_msg
- ccall _dispMSG,dx
- jmp error
-
- port_err:
- mov dx,offset reset_msg
- ccall _dispMSG,dx
- error:
- mov dh,CANT_RESET
- stc
- ret
-
- ;called when we want to determine what to do with a received packet.
- ;enter with cx = packet length, es:di -> packet type, dl = packet class.
- extrn recv_find: near
-
- ;called after we have copied the packet into the buffer.
- ;enter with ds:si ->the packet, cx = length of the packet.
- extrn recv_copy: near
-
- extrn count_in_err: near
- extrn count_out_err: near
-
- ;called from the net_isr isr. All registers have been saved, and ds=cs.
- ;Upon exit, the interrupt will be acknowledged.
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; risr
- ; receive interrupt service routine
- ; exit: es,bx not changed
- ; registers: si,ax
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public risr
- risr proc near
- assume ds:code
- save <es,bx>
- call set_dp ;set es to dual port
- begin:
- mov si,[actrdesc] ;active receive descriptor
- mov ax,es:rd_stat[si] ;get descriptor status
- test ax,r_own ;do we own it?
- jnz risr_done ;this one is not filled
-
- call dp_rcv ;lance chip has rev'd a new packet
- ;reserve si
- ;One rint might indicate multiple recv's, check at the next one
- add si,SIZE rec_desc_ring ;point at next descriptor
- cmp si,OUTOF_BOUND ;RAREA+(numrxbuf-1)*(SIZE rec_desc_ring) = XAREA
- jl within
- mov si,RAREA
- within:
- mov [actrdesc],si ;set active pointer
- jmp begin
- risr_done:
- restore <bx,es>
- ret
- risr endp
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; dp_rcv:
- ; lance chip has one buffer filled, process it.
- ; enter: es:si = actrdesc
- ; exit: actrdesc updated to next desc, si unchanged
- ; registers: di,ax,bx
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public dp_rcv
- dp_rcv proc near
- push si ;save the old actdesc
- push es ;gonna be changed in recv_find()
-
- mov ax,es:rd_stat[si] ;is it errored packet?
- test ax,r_err ;
- jz noerr ;no err
- call rcverror ;handle the err
- jmp clrup
-
- noerr:
- mov di,es:rd_addr[si] ;received packet pointer es:di
- add di,EADDR_LEN + EADDR_LEN;stript off the two ether addresses
- ; & get to the packet type field
- mov cx,es:rd_mcnt[si] ;everything (icl'g addresses)
- and cx,mcnt_mask ;mask out the reserved bits
-
- push ds ;entry value saved
-
- push es ;es:di --> rcv'd data (icl'ing type)
- push di
-
- mov dl, BLUEBOOK ;assume bluebook Ethernet.
- mov ax, es:[di]
- xchg ah, al
- cmp ax, 1500
- ja BlueBookPacket
- inc di ;set di to 802.2 header
- inc di
- mov dl, IEEE8023
- BlueBookPacket:
-
- call recv_find ;ask for buffer from application es:di
- mov ax,es ;is this pointer null?
- or ax,di
- jz too_bad ;yes - just free the frame.
- pop si ;put rcv'd data in ds:si, di->si
- sub si,EADDR_LEN + EADDR_LEN;we hand everything to the client
- pop ds ;es->ds
-
- push cx
- push es ;for recv_copy(), es:di is user buf
- push di
-
- call movemem ;do the copy (including ether header)
-
- pop si ;di->si, es->ds
- pop ds ;ds:si --> user buffer now
- pop cx ;get back the length
- call recv_copy
-
- pop ds ;original ds restored
- jmp clrup
-
- too_bad:
- pop di
- pop es
- pop ds
- clrup:
- ;either a bad or a good packet, we're done with it now
- pop es ;good old dp seg
- pop si
- mov es:rd_stat[si],r_own ;desc reusable now
- ret
- dp_rcv endp
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; eisr
- ; for lance error service routine
- ;
- ; entry - bx has status
- ; exit - bx unchanged, ax,cx changed
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public eisr
- eisr proc near
- test bx,l_babl ;transmission timeout?
- jz eisr1 ;no
- call count_out_err
- eisr1:
- test bx,l_cerr
- jz eisr2 ;no
- call count_out_err
- eisr2:
- test bx,l_miss ;missed packet?
- jz eisr3
- call count_out_err
- eisr3:
- test bx,l_merr ;bus timeout?
- jz eisr4 ;no
- call count_out_err ;this is a fatal error
- eisr4:
- ret
- eisr endp
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; rcverror:
- ; entry ax has rd_stat
- ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public rcverror
- rcverror proc near
-
- test ax,r_fram ;framing error?
- jz rerr0
- call count_in_err
- rerr0:
- test ax,r_crc ;crc error?
- jz rerr1
- call count_in_err
- rerr1:
- test ax,r_oflo ;silo overflow?
- jz rerr2
- call count_in_err
- rerr2:
- test ax,r_buff ;buffer error?
- jz rerr3
- call count_in_err
- rerr3:
- ret
- rcverror endp
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; init_csr:
- ;
- ; initialize lance registers csr1, csr2, csr3
- ; entry - csr0 stop bit must have been set
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public init_csr
- init_csr proc near
- mov al,csr1 ;set rap to csr1
- call set_rap
- mov ax,i_mode ;init block starts at 0
- call w_csr
-
- mov al,csr2 ;set rap to csr2
- call set_rap
- mov ax,0 ;init block upper 8 bits are 0
- call w_csr
-
- mov al,csr3 ;set rap for csr3
- call set_rap
- mov ax,bus_master ;bswp,acon,bcon
- call w_csr
-
- mov al,csr0 ;leave rap at csr0
- call set_rap
- ret
- init_csr endp
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; r_csr:
- ;
- ; read lance csr already selected into ax
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public r_csr
- r_csr proc near
- push dx
- mov dx,io_addr ;now data port
- add dx,pt_ldata
- in ax,dx
- pop dx
- ret
- r_csr endp
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; r_csr0
- ;
- ; read lance csr0
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public r_csr0
- r_csr0 proc near
- push dx
- mov al,csr0 ;set rap to csr1
- call set_rap
- mov dx,io_addr ;now data port
- add dx,pt_ldata
- in ax,dx
- pop dx
- ret
- r_csr0 endp
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; set_initblk:
- ;
- ; set up lance initialization block in the dual port
- ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;
-
- public set_initblk,si11
- set_initblk proc near
- push es
- call set_dp ;get lance data seg
-
- mov ax,run_mode ;mode
- mov es:[i_mode],ax ;(es = dpseg);1st word in the dp
- lea si,UNITID ;set in physical address
- mov di,i_padr ; from the board
- si11:
- mov cx,6
- rep movsb
- ;
- ;forget about the logical address filter for now --mz??
- ;
- mov ax,RAREA ;set in pointer to 1ST receive desc.
- mov es:[i_rdra],ax ;set lo addr (0-15)
- mov ah,rlen ;set in rlen parameter & hi addr (00s)
- mov al,0
- mov es:[i_rlen],ax ;4 rcv descriptors
- mov ax,XAREA ;pointer to xmit descriptors
- mov es:[i_tdra],ax
- mov ah,tlen ;set in tlen parameter 1 = 2
- mov al,0
- mov es:[i_tlen],ax
- pop es
- ret
- set_initblk endp
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; set_dp
- ; es<-- cs:base_address
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public set_dp
- set_dp:
- assume cs:code
- push ax
- mov ax,cs:[base_addr]
- mov es,ax
- pop ax
- ret
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; set_ds:
- ; ds<--cs
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- set_ds:
- push ax
- mov ax,cs
- mov ds,ax
- pop ax
- ret
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; set up transmit message descriptors
- ;
- ; entry - cx has number of descriptors and buffers to set up
- ; bx has pointer of start of descriptors
- ; di has pointer to start of buffer area
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public su_tmd
- su_tmd proc near
- push es
- call set_dp ;get lance data seg
-
- ;first set the relative parameters
- mov [sdesc_cnt],cx ;set in count
- mov [actsdesc],bx
-
- su_t0:
- mov es:td_addr[bx],di ;set in pointer
- mov ax,BUFSIZE ;total size
- neg ax ;two's compliment
- or ax,td_bmask ;set these bits
- mov es:td_bcnt[bx],ax ;set in length to descriptor
- mov ax,0 ;set descriptor status for lance
- or ax,t_stp ;start of packet
- or ax,t_enp ;end of packet
- mov es:td_stat[bx],ax ;give it away
- mov es:td_tdr[bx],0
- add bx,tdesclen ;point at next descriptor
- add di,BUFSIZE ;and next buffer
- loop su_t0 ;do all
- pop es
- ret
- su_tmd endp
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; set up receive message descriptors
- ;
- ; entry - cx has number of descriptors and buffers to set up
- ; bx has pointer of start of descriptors
- ; di has pointer to start of buffer area
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public su_rmd
- su_rmd proc near
- push es
- call set_dp ;get lance data seg
-
- mov [actrdesc],bx ;pointer to active descriptor
- mov [rdesc_cnt],cx ;descriptor count
- su_r0:
- mov es:rd_addr[bx],di ;set in pointer to pointer
- mov ax,r_own ;set up descriptor status
- mov es:rd_stat[bx],ax
- xor ax,ax ;zero out count
- mov es:rd_mcnt[bx],ax
- mov ax,BUFSIZE ;set in length of buffer
- neg ax ;must be two's compliment
- or ax,rd_mask ;need these bits set
- mov es:rd_bcnt[bx],ax
- add bx,rdesclen ;point at next descriptor
- add di,BUFSIZE ;and next buffer
- loop su_r0 ;do all
-
- pop es
- ret
- su_rmd endp
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; lance_reset:
- ;
- ; reset lance chip; select csr0 and set the stop bit
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public lance_reset
- lance_reset proc near
- mov dx,io_addr ;pop the reset line
- add dx,pt_resetl
- out dx,al
- mov al,csr0 ;set lance address port to csr0
- call set_rap
- mov ax,l_stop ;and set stop bit
- call w_csr
- ret
- lance_reset endp
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; w_csr:
- ;
- ; output ax to lance csr already selected
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public w_csr
- w_csr proc near
- push dx
- mov dx,io_addr ;now data port
- add dx,pt_ldata
- out dx,ax
- pop dx
- ret
- w_csr endp
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; set_rap:
- ;
- ; set lance address port to register in al
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public set_rap
- set_rap proc near
- push dx
- mov dx,io_addr ;get base address
- add dx,pt_laddr ;point at lance address port
- xor ah,ah ;point at csr
- out dx,ax
- pop dx
- ret
- set_rap endp
-
- ; hardwre() and lance_init() are TSR just for the
- ; support of reset_interface();
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; hardware:
- ; verify the port #;
- ; set ethernet addr in _UNITID
- ;
- ; exit:
- ; [_UNITID] = board ethernet address
- ; al = 0 (ok)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public hardware
- hardware proc near
- ;verify the port #
- mov dx,io_addr
- call chkaddr
- cmp al,0 ;ok?
- jz hw1 ;yes, use #1
- mov ax,offset porterr_msg
- ccall _dispMSG,ax
- jmp hw_error
-
- hw1:
- ;ok, now zero the ram out so that we can use it
- call set_dp
- call zeroram
-
- ;get ether address
- mov cx,6 ;get the ethernet address
- add dx,pt_etaddr
- mov bx,offset UNITID ;to here
- hw3:
- in al,dx
- mov byte ptr[bx],al
- inc bx
- loop hw3
-
- ;validate int_no (only support 10,11,12,15)
-
- mov bl,IRQ10 ;assume it's irq10
- mov dx,io_addr ;port base
- add dx,pt_status ;status port
- in al,dx ;get status
- and al,st_mask ;get the 2 bits
- cmp al,irqn_10 ;(IS0 IS1)=(0 0) selects irq10
- je alset
- inc bl ;try irq11
- cmp al,irqn_11
- je alset
- inc bl ;try irq12
- cmp al,irqn_12
- je alset
- mov bl,15 ;try irq15
- cmp al,irqn_15
- jne hw_error
-
- alset:
- ;did we get the right int_no in bl?
- cmp bl,int_no
- jmp ok ; #### temp patch, BKC
- ; je ok
- ;otherwise, error
- mov ax,offset interr_msg
- ccall _dispMSG,ax
- hw_error:
- mov al,0ffh
- ret
- ok:
- mov al,0 ;good return code
- ret
- hardware endp
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; chkaddr: check if we are using the right i/o port
- ; this is done by reading the port status and comparing
- ; with cs - 800h
- ;
- ; entry: io_addr == i/o port #
- ; exit: ah -- dual port segment
- ; al -- 00h (succ) or ffh (error)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public chkaddr
- chkaddr proc near
- push dx
-
- mov dx,io_addr
- in al,dx ;read in status byte
- and al,addr ;get dp seg, addr = 0f0h
- mov ah,al ;save
-
- mov dx,base_addr
- and dh,addr
- cmp al,dh
- je chk2
- mov al,0ffh ;error
- pop dx
- ret
- chk2:
- mov al,0 ;ok
- pop dx
- ret
- chkaddr endp
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; zeroram - zero dual port ram
- ; seg in [dpseg]
- ; registers: di,cx,al
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public zeroram
- zeroram proc near
- cld ;auto increment
- zram1:
- mov di,0 ;start at 0;dpseg:di
- mov cx,dplen ;dual port length
- mov al,0 ;data to go
- rep stosb ;zero em all
- ret
- zeroram endp
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; lance_init:
- ;
- ; init lance chip; first setup init_blk, r & s descriptors in dp
- ; then set the chip to go.
- ; exit: ax = 1: error; 0 OK.
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public lance_init, il0, il1
- lance_init proc near
- call set_initblk ;set up lance initialization block
-
- ;set up transmit descriptors & buffers
- mov cx,NUMTDESC ;get no. of transmit blocks to build
- mov bx,XAREA ;point at descriptor memory pool
- mov di,TBAREA ;and buffer pool
- call su_tmd ;set up transmit descriptors
-
- ;set up receive descriptors & buffers
- mov cx,NUMRDESC ;set up receive descriptors
- mov bx,RAREA ;descriptor area
- mov di,RBAREA ;buffer area
- call su_rmd ;set up receive descriptors
-
- call lance_reset ;ensure reset
- call init_csr ;initialize lance registers
- ;also set rap to csr0 with stop set
- ;now start the lance initialization action
- CLI
- mov ax,l_init+l_strt ;write init & start to csr0
- call w_csr
-
- ;rap = csr0 now, let's check at csr0
- mov cx,0
- dec cx
- il0:
- call r_csr ;get lance status register
- test ax,l_idon ;init done set?
- jnz il1
- loop il0
- ;sth wrong with the chip, can't init
- mov ax,offset chperr_msg
- ccall _dispMSG,ax
- mov ax,1 ;error return
- ret
- il1:
- mov ax,l_idon+l_inea ;this drives /intr pin to low
- call w_csr ;enable network ints
- STI
- mov ax,0 ;good return
- ret
- lance_init endp
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; tickscreen
- ;
- ; For debug this routine can be called to tick over the screen at the
- ; specified location.
- ;
- ; c callable: tickscreen(loc);
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public _tickscreen
- _tickscreen proc near
- push bp
- mov bp,sp
- save <ax,bx,ds>
- mov bx,04[bp] ;get screen position
- add bx,bx ;*2
- IFDEF COLOR
- mov ax,0b800h
- ELSE
- mov ax,0b000h
- ENDIF
- mov ds,ax
- inc byte ptr [bx] ;tick it
- restore <ds,bx,ax>
- pop bp
- ret
- _tickscreen endp
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; _dispMSG:
- ; c call: dispMSG(&msg);
- ; put the '$' terminated message to screen
- ; entry: dx - point to the message
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public _dispMSG
- _dispMSG proc near
- push bp
- mov bp,sp
- push dx
- mov dx,4[bp]
-
- push ax
- mov ah,9
- int 21h
- pop ax
-
- pop dx
- pop bp
- ret
- _dispMSG endp
-
-
- public recv
- recv:
- ;called from the recv isr. All registers have been saved, and ds=cs.
- ;Upon exit, the interrupt will be acknowledged.
- assume ds:code
-
- recv_0:
- mov dx,io_addr ;get the iobase
- add dx,pt_status ;the read status port
- in al,dx ;get board status
-
- test al,clk_int ;look for clock interrupt
- jz ni10 ;no clock int
- mov dx,base_addr
- add dx,pt_clrclk ;reset the ckock
- out dx,al
- ni10:
- test al,net_int ;network int bit cleared?
- jnz nisr5 ;look for 0 here, set means none
-
- call r_csr ;get lance status register -- in ax
- mov bx,ax
- and ax,l_mask ;clear out ints and mask any more
- call w_csr
-
- test bx,l_err ;check for errors first
- jz nisr2 ;no error
- call eisr
- nisr2:
- test bx,l_rint ;test for receive active
- jz nisr6 ;no r_int
- call risr
- nisr6:
- mov ax,l_inea ;re-enable the int
- call w_csr
- jmp recv_0 ;check again for ints
- nisr5:
- ret
-
-
- public recv_exiting
- recv_exiting:
- ;called from the recv isr after interrupts have been acknowledged.
- ;Only ds and ax have been saved.
- assume ds:nothing
- ret
-
-
- ;any code after this will not be kept after initialization.
- end_resident label byte
-
-
- public usage_msg
- usage_msg db "usage: nti16 [-n] [-d] [-w] <packet_int_no> <irq_no> <port_no> <base_addr>",CR,LF,'$'
-
- public copyright_msg
- copyright_msg db "Packet driver for nti network device, version ",'0'+majver,".",'0'+version,CR,LF
- db "Copyright 1990, Michael Zheng",CR,LF,'$'
-
-
- ;enter with si -> argument string, di -> wword to store.
- ;if there is no number, don't change the number.
- extrn get_number: near
-
- ;enter with dx -> name of word, di -> dword to print.
- extrn print_number: near
-
- public parse_args
- parse_args:
- mov di,offset int_no
- call get_number
- mov di,offset io_addr
- call get_number
- mov di,offset base_addr
- call get_number
- ret
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; etopen:
- ; initialize the interface in order to function
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- public etopen
- etopen:
-
-
- call hardware ;decide port #; _UNITID; zeroram
- ;and 16-bit board specific:
- ;decide the int_no validity --mz!!
- cmp al,0
- jz beg0 ;ok
- mov ax,offset hwerr_msg ;error return
- ccall _dispMSG,ax
- mov ax, 4c00H
- int 21h ;terminate it
- beg0:
-
- mov al,int_no
- call maskint
- call lance_init ;init the lance chip
- cmp ax,1 ;init error?
- jne good ;ok
-
- mov ax,offset initerr_msg ;can't init message
- ccall _dispMSG,ax
- stc
- ret
-
- good:
- call set_recv_isr
-
- mov al, int_no ; Get board's interrupt vector
- add al, 8
- cmp al, 8+8 ; Is it a slave 8259 interrupt?
- jb set_int_num ; No.
- add al, 70h - 8 - 8 ; Map it to the real interrupt.
- set_int_num:
- xor ah, ah ; Clear high byte
- mov int_num, ax ; Set parameter_list int num.
-
- mov ax,offset good_msg
- ccall _dispMSG,ax
-
- mov dx,offset end_resident ;in paragraphs
- clc
- ret
-
- public print_parameters
- print_parameters:
- ;echo our command-line parameters
- mov di,offset int_no
- mov bx,offset int_no_name
- call get_number
- mov di,offset io_addr
- mov bx,offset io_addr_name
- call get_number
- mov di,offset base_addr
- mov bx,offset base_addr_name
- call get_number
- ret
-
- code ends
-
- end
-