mirror of
https://github.com/bobbimanners/emailler.git
synced 2024-11-12 14:04:34 +00:00
483 lines
12 KiB
HTML
483 lines
12 KiB
HTML
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><link rel="stylesheet" type="text/css" href="ca65-doc-style.css"/></head><body><a href="ref_index.html"><h1>ip65 technical reference</h1></a><h1>File : drivers/lan91c96.s</h1><pre> Ethernet driver for SMC LAN91C96 chip
|
|
|
|
</pre><h2 id="functions">functions</h2><table><tr><th>function</th><th>description</th></tr><tr><td id="eth_init">eth_init</td><td><pre>initialize the ethernet adaptor
|
|
inputs: none
|
|
outputs: carry flag is set if there was an error, clear otherwise
|
|
</pre></td></tr><tr><td id="eth_rx">eth_rx</td><td><pre>receive a packet
|
|
inputs: none
|
|
outputs:
|
|
if there was an error receiving the packet (or no packet was ready) then carry flag is set
|
|
if packet was received correctly then carry flag is clear,
|
|
eth_inp contains the received packet,
|
|
and eth_inp_len contains the length of the packet
|
|
</pre></td></tr><tr><td id="eth_tx">eth_tx</td><td><pre> send a packet
|
|
inputs:
|
|
eth_outp: packet to send
|
|
eth_outp_len: length of packet to send
|
|
outputs:
|
|
if there was an error sending the packet then carry flag is set
|
|
otherwise carry flag is cleared
|
|
</pre></td></tr></table><h2 id="constants">constants</h2><table><tr><th>constants</th><th>description</th><th>value</th></tr><tr><td id="eth_driver_io_base">eth_driver_io_base</td><td></td><td>fixlan01+1
|
|
</td></tr><tr><td id="eth_driver_name">eth_driver_name</td><td></td><td>"LANceGS (91C96)"
|
|
</td></tr></table><h2>implementation</h2><pre id="code">
|
|
|
|
|
|
|
|
; Ethernet driver for SMC LAN91C96 chip
|
|
;
|
|
|
|
.ifndef KPR_API_VERSION_NUMBER
|
|
.define EQU =
|
|
.include "../inc/kipper_constants.i"
|
|
.endif
|
|
|
|
.include "../inc/common.i"
|
|
|
|
.export eth_init
|
|
.export eth_rx
|
|
.export eth_tx
|
|
.export eth_driver_name
|
|
.export eth_driver_io_base
|
|
.import eth_inp
|
|
.import eth_inp_len
|
|
.import eth_outp
|
|
.import eth_outp_len
|
|
|
|
.import cfg_mac
|
|
|
|
; LANceGS hardware addresses
|
|
ethbsr := $c00E ; Bank select register R/W (2B)
|
|
|
|
; Register bank 0
|
|
ethtcr := $c000 ; Transmission control register R/W (2B)
|
|
ethephsr := $c002 ; EPH status register R/O (2B)
|
|
ethrcr := $c004 ; Receive control register R/W (2B)
|
|
ethecr := $c006 ; Counter register R/O (2B)
|
|
ethmir := $c008 ; Memory information register R/O (2B)
|
|
ethmcr := $c00A ; Memory Config. reg. +0 R/W +1 R/O (2B)
|
|
|
|
; Register bank 1
|
|
ethcr := $c000 ; Configuration register R/W (2B)
|
|
ethbar := $c002 ; Base address register R/W (2B)
|
|
ethiar := $c004 ; Individual address register R/W (6B)
|
|
ethgpr := $c00A ; General address register R/W (2B)
|
|
ethctr := $c00C ; Control register R/W (2B)
|
|
|
|
; Register bank 2
|
|
ethmmucr := $c000 ; MMU command register W/O (1B)
|
|
ethautotx := $c001 ; AUTO TX start register R/W (1B)
|
|
ethpnr := $c002 ; Packet number register R/W (1B)
|
|
etharr := $c003 ; Allocation result register R/O (1B)
|
|
ethfifo := $c004 ; FIFO ports register R/O (2B)
|
|
ethptr := $c006 ; Pointer register R/W (2B)
|
|
ethdata := $c008 ; Data register R/W (4B)
|
|
ethist := $c00C ; Interrupt status register R/O (1B)
|
|
ethack := $c00C ; Interrupt acknowledge register W/O (1B)
|
|
ethmsk := $c00D ; Interrupt mask register R/W (1B)
|
|
|
|
; Register bank 3
|
|
ethmt := $c000 ; Multicast table R/W (8B)
|
|
ethmgmt := $c008 ; Management interface R/W (2B)
|
|
ethrev := $c00A ; Revision register R/W (2B)
|
|
ethercv := $c00C ; Early RCV register R/W (2B)
|
|
|
|
.segment "IP65ZP" : zeropage
|
|
|
|
eth_packet: .res 2
|
|
|
|
.data
|
|
|
|
;initialize the ethernet adaptor
|
|
;inputs: none
|
|
;outputs: carry flag is set if there was an error, clear otherwise
|
|
eth_init:
|
|
jsr lan_self_modify
|
|
lda #$01
|
|
fixlan00:
|
|
sta ethbsr ; Select register bank 1
|
|
fixlan01:
|
|
lda ethcr ; Read first four bytes - $31, $20, $67, $18
|
|
cmp #$31
|
|
bne lanerror
|
|
fixlan03:
|
|
lda ethbar
|
|
cmp #$67
|
|
bne lanerror
|
|
fixlan04:
|
|
lda ethbar+1
|
|
cmp #$18
|
|
bne lanerror
|
|
; we have the magic signature
|
|
|
|
; Reset ETH card
|
|
lda #$00 ; Bank 0
|
|
fixlan05:
|
|
sta ethbsr
|
|
lda #%10000000 ; Software reset
|
|
fixlan06:
|
|
sta ethrcr+1
|
|
|
|
ldy #$00
|
|
fixlan07:
|
|
sty ethrcr
|
|
fixlan08:
|
|
sty ethrcr+1
|
|
|
|
; Delay
|
|
: cmp ($FF,x) ; 6 cycles
|
|
cmp ($FF,x) ; 6 cycles
|
|
iny ; 2 cycles
|
|
bne :- ; 3 cycles
|
|
; 17 * 256 = 4352 -> 4,4 ms
|
|
|
|
; Enable transmit and receive
|
|
lda #%10000001 ; Enable transmit TXENA, PAD_EN
|
|
ldx #%00000011 ; Enable receive, strip CRC ???
|
|
fixlan09:
|
|
sta ethtcr
|
|
fixlan10:
|
|
stx ethrcr+1
|
|
|
|
lda #$01 ; Bank 1
|
|
fixlan11:
|
|
sta ethbsr
|
|
|
|
fixlan12:
|
|
lda ethcr+1
|
|
ora #%00010000 ; No wait (IOCHRDY)
|
|
fixlan13:
|
|
sta ethcr+1
|
|
|
|
lda #%00001001 ; Auto release
|
|
fixlan14:
|
|
sta ethctr+1
|
|
|
|
; Set MAC address
|
|
lda cfg_mac
|
|
ldx cfg_mac + 1
|
|
fixlan15:
|
|
sta ethiar
|
|
fixlan16:
|
|
stx ethiar + 1
|
|
lda cfg_mac + 2
|
|
ldx cfg_mac + 3
|
|
fixlan17:
|
|
sta ethiar + 2
|
|
fixlan18:
|
|
stx ethiar + 3
|
|
lda cfg_mac + 4
|
|
ldx cfg_mac + 5
|
|
fixlan19:
|
|
sta ethiar + 4
|
|
fixlan20:
|
|
stx ethiar + 5
|
|
|
|
; Set interrupt mask
|
|
lda #$02 ; Bank 2
|
|
fixlan21:
|
|
sta ethbsr
|
|
|
|
lda #%00000000 ; No interrupts
|
|
fixlan22:
|
|
sta ethmsk
|
|
clc
|
|
rts
|
|
|
|
lanerror:
|
|
sec
|
|
rts
|
|
|
|
|
|
;receive a packet
|
|
;inputs: none
|
|
;outputs:
|
|
; if there was an error receiving the packet (or no packet was ready) then carry flag is set
|
|
; if packet was received correctly then carry flag is clear,
|
|
; eth_inp contains the received packet,
|
|
; and eth_inp_len contains the length of the packet
|
|
eth_rx:
|
|
fixlan38:
|
|
lda ethist
|
|
and #%00000001 ; Check receive interrupt
|
|
bne :+
|
|
sec ; No packet available
|
|
rts
|
|
|
|
: lda #$00
|
|
ldx #%11100000 ; Receive, Auto Increment, Read
|
|
fixlan39:
|
|
sta ethptr
|
|
fixlan40:
|
|
stx ethptr + 1
|
|
|
|
; Last word contains 'last data byte' and $60 or 'fill byte' and $40
|
|
fixlan41:
|
|
lda ethdata ; Status word
|
|
fixlan42:
|
|
lda ethdata ; Only need high byte
|
|
|
|
; Move ODDFRM bit into carry:
|
|
; - Even packet length -> carry clear -> subtract 6 bytes
|
|
; - Odd packet length -> carry set -> subtract 5 bytes
|
|
lsr
|
|
lsr
|
|
lsr
|
|
lsr
|
|
lsr
|
|
|
|
; The packet contains 3 extra words
|
|
fixlan43:
|
|
lda ethdata ; Total number of bytes
|
|
sbc #$05 ; Actually 5 or 6 depending on carry
|
|
sta eth_inp_len
|
|
fixlan44:
|
|
lda ethdata
|
|
sbc #$00
|
|
sta eth_inp_len+1
|
|
|
|
; Read bytes into buffer
|
|
lda #<eth_inp
|
|
ldx #>eth_inp
|
|
sta eth_packet
|
|
stx eth_packet+1
|
|
ldx eth_inp_len+1
|
|
ldy #$00
|
|
lanread:
|
|
fixlan46:
|
|
lda ethdata
|
|
sta (eth_packet),y
|
|
iny
|
|
bne :+
|
|
inc eth_packet+1
|
|
: cpy eth_inp_len
|
|
bne lanread
|
|
dex
|
|
bpl lanread
|
|
|
|
; Remove and release RX packet from the FIFO
|
|
lda #%10000000
|
|
fixlan47:
|
|
sta ethmmucr
|
|
|
|
clc
|
|
rts
|
|
|
|
|
|
; send a packet
|
|
;inputs:
|
|
; eth_outp: packet to send
|
|
; eth_outp_len: length of packet to send
|
|
;outputs:
|
|
; if there was an error sending the packet then carry flag is set
|
|
; otherwise carry flag is cleared
|
|
eth_tx:
|
|
lda eth_outp_len + 1 ;
|
|
ora #%00100000
|
|
fixlan23:
|
|
sta ethmmucr ; Allocate memory for transmission
|
|
fixlan24:
|
|
lda ethist
|
|
and #%00001000 ; Allocation interrupt
|
|
bne :+
|
|
sec
|
|
rts ; Not able to allocate; bail
|
|
|
|
: lda #%00001000
|
|
fixlan25:
|
|
sta ethack ; Acknowledge interrupt
|
|
|
|
fixlan26:
|
|
lda etharr
|
|
fixlan27:
|
|
sta ethpnr ; Set packet number
|
|
|
|
lda #$00
|
|
ldx #%01000000 ; Auto increment
|
|
fixlan28:
|
|
sta ethptr
|
|
fixlan29:
|
|
stx ethptr + 1
|
|
|
|
lda #$00 ; Status written by CSMA
|
|
fixlan30:
|
|
sta ethdata
|
|
fixlan31:
|
|
sta ethdata
|
|
|
|
lda eth_outp_len
|
|
eor #$01
|
|
lsr
|
|
lda eth_outp_len
|
|
adc #$05 ; Actually will be 5 or 6 depending on carry
|
|
fixlan32:
|
|
sta ethdata
|
|
lda eth_outp_len + 1
|
|
adc #$00
|
|
fixlan33:
|
|
sta ethdata
|
|
|
|
lda #<eth_outp ; Send the packet
|
|
ldx #>eth_outp
|
|
sta eth_packet
|
|
stx eth_packet + 1
|
|
ldx eth_outp_len + 1
|
|
ldy #$00
|
|
lanwrite:
|
|
lda (eth_packet),y
|
|
fixlan34:
|
|
sta ethdata
|
|
iny
|
|
bne :+
|
|
inc eth_packet + 1
|
|
: cpy eth_outp_len
|
|
bne lanwrite
|
|
dex
|
|
bpl lanwrite
|
|
|
|
lda eth_outp_len ; Odd packet length?
|
|
lsr
|
|
bcc :+
|
|
|
|
lda #%001000000 ; Yes, Odd
|
|
bne fixlan36 ; Always
|
|
|
|
: lda #$00 ; No
|
|
fixlan35:
|
|
sta ethdata ; Fill byte
|
|
fixlan36:
|
|
sta ethdata ; Control byte
|
|
lda #%11000000 ; Enqueue packet - transmit
|
|
fixlan37:
|
|
sta ethmmucr
|
|
|
|
clc
|
|
rts
|
|
|
|
|
|
;
|
|
; lan_self_modify - make all entry points variable so we can move the
|
|
; LANceGS card around in the Apple
|
|
;
|
|
lan_self_modify:
|
|
lda #$C0 ; FIXME - hardcoded to slot 4
|
|
clc ; We'll be adding later, so clear carry
|
|
; Make the accumulator contain slot number plus $80
|
|
; i.e. Slot 1 = $90
|
|
; i.e. Slot 2 = $A0
|
|
; i.e. Slot 3 = $B0
|
|
; i.e. Slot 4 = $C0
|
|
; i.e. Slot 5 = $D0
|
|
; i.e. Slot 6 = $E0
|
|
; i.e. Slot 7 = $F0
|
|
; $C0s0: Save off all ethtcr, ethcr, ethmmucr, and ethmt mods
|
|
sta fixlan01 + 1
|
|
sta fixlan09 + 1
|
|
sta fixlan23 + 1
|
|
sta fixlan37 + 1
|
|
; sta fixlan45 + 1 ; Removed
|
|
sta fixlan47 + 1
|
|
|
|
; $C0s1: Save off all ethtcr+1, ethcr+1, ethmmucr+1, and ethmt+1 mods
|
|
adc #$01
|
|
; sta fixlan02 + 1 ; Removed
|
|
sta fixlan12 + 1
|
|
sta fixlan13 + 1
|
|
|
|
; $C0s2: Save off all ethephsr, ethbar, and ethpnr mods
|
|
adc #$01
|
|
sta fixlan03 + 1
|
|
sta fixlan27 + 1
|
|
|
|
; $C0s3: Save off all ethephsr+1, ethbar+1, ethpnr+1, and etharr mods
|
|
adc #$01
|
|
sta fixlan04 + 1
|
|
sta fixlan26 + 1
|
|
|
|
; $C0s4: Save off all ethrcr, ethiar, and ethfifo mods
|
|
adc #$01
|
|
sta fixlan07 + 1
|
|
sta fixlan15 + 1
|
|
|
|
; $C0s5: Save off all ethrcr+1, ethiar+1, and ethfifo+1 mods
|
|
adc #$01
|
|
sta fixlan06 + 1
|
|
sta fixlan08 + 1
|
|
sta fixlan10 + 1
|
|
sta fixlan16 + 1
|
|
|
|
; $C0s6: Save off all ethecr, ethptr, and ethiar+2 mods
|
|
adc #$01
|
|
sta fixlan17 + 1
|
|
sta fixlan28 + 1
|
|
sta fixlan39 + 1
|
|
|
|
; $C0s7: Save off all ethecr+1, ethptr+1, and ethiar+3 mods
|
|
adc #$01
|
|
sta fixlan18 + 1
|
|
sta fixlan29 + 1
|
|
sta fixlan40 + 1
|
|
|
|
; $C0s8: Save off all ethmir, ethdata, ethmgmt, and ethiar+4 mods
|
|
adc #$01
|
|
sta fixlan19 + 1
|
|
sta fixlan30 + 1
|
|
sta fixlan31 + 1
|
|
sta fixlan32 + 1
|
|
sta fixlan33 + 1
|
|
sta fixlan34 + 1
|
|
sta fixlan35 + 1
|
|
sta fixlan36 + 1
|
|
sta fixlan41 + 1
|
|
sta fixlan42 + 1
|
|
sta fixlan43 + 1
|
|
sta fixlan44 + 1
|
|
sta fixlan46 + 1
|
|
|
|
; $C0s9: Save off all ethmir+1, ethdata+1, ethmgmt+1, and ethiar+5 mods
|
|
adc #$01
|
|
sta fixlan20 + 1
|
|
|
|
; $C0sA: Save off all ethmcr, ethgpr, and ethrev mods
|
|
; $C0sB: Save off all ethmcr+1, ethgpr+1, and ethrev+1 mods
|
|
; None
|
|
|
|
; $C0sC: Save off all ethctr, ethist, ethack, and ethercv mods
|
|
adc #$03 ; Because there were no a or b mods
|
|
sta fixlan24 + 1
|
|
sta fixlan25 + 1
|
|
sta fixlan38 + 1
|
|
|
|
; $C0sD: Save off all ethmsk, ethctr+1 mods
|
|
adc #$01
|
|
sta fixlan14 + 1
|
|
sta fixlan22 + 1
|
|
|
|
; $C0sE: Save off all ethbsr mods
|
|
adc #$01
|
|
sta fixlan00 + 1
|
|
sta fixlan05 + 1
|
|
sta fixlan11 + 1
|
|
sta fixlan21 + 1
|
|
|
|
rts
|
|
|
|
.rodata
|
|
eth_driver_name:
|
|
.asciiz "LANceGS (91C96)"
|
|
eth_driver_io_base=fixlan01+1
|
|
|
|
|
|
; The contents of this file are subject to the Mozilla Public License
|
|
; Version 1.1 (the "License"); you may not use this file except in
|
|
; compliance with the License. You may obtain a copy of the License at
|
|
; http://www.mozilla.org/MPL/
|
|
;
|
|
; Software distributed under the License is distributed on an "AS IS"
|
|
; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
|
; License for the specific language governing rights and limitations
|
|
; under the License.
|
|
;
|
|
; The Original Code is ip65.
|
|
;
|
|
; The Initial Developer of the Original Code is David Schmidt
|
|
; Portions created by the Initial Developer is Copyright (C) 2011
|
|
; All Rights Reserved.
|
|
; -- LICENSE END --
|
|
</pre></body></html> |