emailler/drivers/cs8900a.s

550 lines
11 KiB
ArmAsm
Raw Normal View History

2013-12-13 21:24:03 +00:00
;
; Copyright (c) 2007, Adam Dunkels and Oliver Schmidt
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions
; are met:
; 1. Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; 2. Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
; 3. Neither the name of the Institute nor the names of its contributors
; may be used to endorse or promote products derived from this software
; without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
; ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
; SUCH DAMAGE.
;
; This file is part of the Contiki operating system.
;
; Author: Adam Dunkels <adam@sics.se>, Oliver Schmidt <ol.sc@web.de>
;
;---------------------------------------------------------------------
.macpack module
module_header _cs8900a
; Driver signature
.byte $65, $74, $68 ; "eth"
.byte $01 ; Ethernet driver API version number
; Ethernet address
mac: .byte $00, $0E, $3A ; OUI of Cirrus Logic
.ifdef __C64__
.byte $64, $64, $64
.endif
.ifdef __C128__
.byte $28, $28, $28
.endif
.ifdef __APPLE2__
.byte $A2, $A2, $A2
.endif
.ifdef __ATARI__
.byte $A8, $A8, $A8
.endif
.ifdef __VIC20__
.byte $20, $20, $20
.endif
; Buffer attributes
bufaddr:.res 2 ; Address
bufsize:.res 2 ; Size
; Jump table.
jmp init
jmp poll
jmp send
jmp exit
;---------------------------------------------------------------------
.if DYN_DRV
.zeropage
sp: .res 2 ; Stack pointer (Do not trash !)
reg: .res 2 ; Address of rxtxreg
ptr: .res 2 ; Indirect addressing pointer
len: .res 2 ; Frame length
cnt: .res 2 ; Frame length counter
.else
.include "zeropage.inc"
reg := ptr1 ; Address of rxtxreg
ptr := ptr2 ; Indirect addressing pointer
len := ptr3 ; Frame length
cnt := ptr4 ; Frame length counter
.endif
;=====================================================================
.ifdef __CBM__
.rodata
; Ethernet address
rrnet: .byte $28, $CD, $4C ; OUI of Individual Computers
.byte $FF ; Reserved for RR-Net
;---------------------------------------------------------------------
.if .defined (__C64__) .or .defined (__C128__)
rxtxreg := $DE08
txcmd := $DE0C
txlen := $DE0E
isq := $DE00
packetpp := $DE02
ppdata := $DE04
.endif
.ifdef __VIC20__
rxtxreg := $9808
txcmd := $980C
txlen := $980E
isq := $9800
packetpp := $9802
ppdata := $9804
.endif
;---------------------------------------------------------------------
.code
init:
; Activate C64 RR clockport in order to operate RR-Net
; (RR config register overlays unused CS8900A ISQ register)
lda isq+1
ora #$01 ; Set clockport bit
sta isq+1
; Check EISA registration number of Crystal Semiconductor
; PACKETPP = $0000, PPDATA == $630E ?
lda #$00
tax
jsr packetpp_ax
lda #$63^$0E
eor ppdata
eor ppdata+1
beq :+
sec
rts
; "When the RR-Net MK3 is used in cartridge mode, the EEPROM will serve as a
; regular 8k ROM cartridge. It is used as a startup-ROM if the unit is plugged
; directly to a C64. The startup code will initialize the MAC address."
; PACKETPP = $0158, PPDATA == RR-Net[0], RR-Net[1] ?
; PACKETPP = $015A, PPDATA == RR-Net[2], RR-Net[3] ?
; PACKETPP = $015C, AX = PPDATA
: ldy #$58
: tya
jsr packetpp_a1
lda ppdata
ldx ppdata+1
cpy #$58+4
bcs copy
cmp rrnet-$58,y
bne :+
txa
cmp rrnet-$58+1,y
bne :+
iny
iny
bne :- ; Always
; "If the RR-Net MK3 is connected to a clockport, then the last 4 bytes of the
; EEPROM are visible by reading the last 4, normally write-only, registers."
; MAC_LO ^ MAC_HI ^ $55 == CHKSUM0 ?
: lda txcmd ; MAC_LO
eor txcmd+1 ; MAC_HI
eor #$55
cmp txlen ; CHKSUM0
bne reset
; (CHKSUM0 + MAC_LO + MAC_HI) ^ $AA == CHKSUM1 ?
clc
adc txcmd ; MAC_LO
clc
adc txcmd+1 ; MAC_HI
eor #$AA
cmp txlen+1 ; CHKSUM1
bne reset
; "When both checksums match, the CS8900A should be initialized
; to use the MAC Address 28:CD:4C:FF:<MAC_HI>:<MAC_LO>."
; AX = MAC_LO, MAC_HI
lda txcmd ; MAC_LO
ldx txcmd+1 ; MAC_HI
; MAC[4], MAC[5] = AX
; MAC[2], MAC[3] = RR-Net[2], RR-Net[3]
; MAC[0], MAC[1] = RR-Net[0], RR-Net[1]
copy: ldy #$04
bne :++ ; Always
: lda rrnet,y
ldx rrnet+1,y
: sta mac,y
txa
sta mac+1,y
dey
dey
bpl :--
.endif
;=====================================================================
.ifdef __APPLE2__
.rodata
fixup: .byte fixup02-fixup01, fixup03-fixup02, fixup04-fixup03
.byte fixup05-fixup04, fixup06-fixup05, fixup07-fixup06
.byte fixup08-fixup07, fixup09-fixup08, fixup10-fixup09
.byte fixup11-fixup10, fixup12-fixup11, fixup13-fixup12
.byte fixup14-fixup13, fixup15-fixup14, fixup16-fixup15
.byte fixup17-fixup16, fixup18-fixup17, fixup19-fixup18
.byte fixup20-fixup19, fixup21-fixup20, fixup22-fixup21
.byte fixup23-fixup22, fixup24-fixup23
fixups = * - fixup
;---------------------------------------------------------------------
Removed Ethernet driver I/O base. So far the base address of the Ethernet chip was a general property of all Ethernet drivers. It served two purposes: 1. Allowing to use a single Ethernet driver for a certain Ethernet chip, no matter what machine was connected to the chip. 2. Allowing use an Ethernet card in all Apple II slots. However, we now use customized Ethernet drivers for the individual machines so 1.) isn't relevant anymore. In fact one wants to omit the overhead of a runtime-adjustable base address where it isn't needed. So only the Apple II slots are left. But this should rather be a driver-internal approach then. We should just hand the driver the slot number the user wants to use and have the driver do its thing. Independently from the aspect if the driver parameter is a base address or a slot number the parameter handling was changed too. For asm programs there was so far a specific init function to be called prior to the main init function if it was desired to chnage the parameter default. This was done to keep the main init function backward compatible. But now that the parameter (now the slot number) is only used on the Apple II anyhow it seems reasonable to drop the specific init function again and just provide the parameter to the main init function. All C64-only user code can stay as-is. Only Apple II user code needs to by adjusted. Please note that this change only affects asm programs, C programs always used a single init function with the Apple II slot number as parameter.
2019-05-02 12:44:24 +00:00
; The addresses are fixed up at runtime
rxtxreg := $C080
txcmd := $C084
txlen := $C086
isq := $C088
packetpp := $C08A
ppdata := $C08C
;---------------------------------------------------------------------
.data
init:
Removed Ethernet driver I/O base. So far the base address of the Ethernet chip was a general property of all Ethernet drivers. It served two purposes: 1. Allowing to use a single Ethernet driver for a certain Ethernet chip, no matter what machine was connected to the chip. 2. Allowing use an Ethernet card in all Apple II slots. However, we now use customized Ethernet drivers for the individual machines so 1.) isn't relevant anymore. In fact one wants to omit the overhead of a runtime-adjustable base address where it isn't needed. So only the Apple II slots are left. But this should rather be a driver-internal approach then. We should just hand the driver the slot number the user wants to use and have the driver do its thing. Independently from the aspect if the driver parameter is a base address or a slot number the parameter handling was changed too. For asm programs there was so far a specific init function to be called prior to the main init function if it was desired to chnage the parameter default. This was done to keep the main init function backward compatible. But now that the parameter (now the slot number) is only used on the Apple II anyhow it seems reasonable to drop the specific init function again and just provide the parameter to the main init function. All C64-only user code can stay as-is. Only Apple II user code needs to by adjusted. Please note that this change only affects asm programs, C programs always used a single init function with the Apple II slot number as parameter.
2019-05-02 12:44:24 +00:00
; Convert slot number to slot I/O offset
asl
asl
asl
asl
sta reg
; Start with first fixup location
lda #<(fixup01+1)
ldx #>(fixup01+1)
sta ptr
stx ptr+1
ldx #$FF
ldy #$00
; Fixup address at location
: lda (ptr),y
Removed Ethernet driver I/O base. So far the base address of the Ethernet chip was a general property of all Ethernet drivers. It served two purposes: 1. Allowing to use a single Ethernet driver for a certain Ethernet chip, no matter what machine was connected to the chip. 2. Allowing use an Ethernet card in all Apple II slots. However, we now use customized Ethernet drivers for the individual machines so 1.) isn't relevant anymore. In fact one wants to omit the overhead of a runtime-adjustable base address where it isn't needed. So only the Apple II slots are left. But this should rather be a driver-internal approach then. We should just hand the driver the slot number the user wants to use and have the driver do its thing. Independently from the aspect if the driver parameter is a base address or a slot number the parameter handling was changed too. For asm programs there was so far a specific init function to be called prior to the main init function if it was desired to chnage the parameter default. This was done to keep the main init function backward compatible. But now that the parameter (now the slot number) is only used on the Apple II anyhow it seems reasonable to drop the specific init function again and just provide the parameter to the main init function. All C64-only user code can stay as-is. Only Apple II user code needs to by adjusted. Please note that this change only affects asm programs, C programs always used a single init function with the Apple II slot number as parameter.
2019-05-02 12:44:24 +00:00
and #%10001111 ; Allow for re-init
ora reg
sta (ptr),y
; Advance to next fixup location
inx
cpx #fixups
bcs :+
lda ptr
clc
adc fixup,x
sta ptr
bcc :-
inc ptr+1
bcs :- ; Always
; Check EISA registration number of Crystal Semiconductor
; PACKETPP = $0000, PPDATA == $630E ?
: lda #$00
tax
jsr packetpp_ax
lda #$63^$0E
fixup01:eor ppdata
fixup02:eor ppdata+1
beq reset
sec
rts
.endif
;=====================================================================
.ifdef __ATARI__
rxtxreg := $D500
txcmd := $D504
txlen := $D506
isq := $D508
packetpp := $D50A
ppdata := $D50C
;---------------------------------------------------------------------
.code
init:
; Check EISA registration number of Crystal Semiconductor
; PACKETPP = $0000, PPDATA == $630E ?
lda #$00
tax
jsr packetpp_ax
lda #$63^$0E
eor ppdata
eor ppdata+1
beq reset
sec
rts
.endif
;=====================================================================
reset:
; Initiate a chip-wide reset
; PACKETPP = $0114, PPDATA = $0040
lda #$14
jsr packetpp_a1
ldy #$40
fixup03:sty ppdata
: jsr packetpp_a1
fixup04:ldy ppdata
and #$40
bne :-
; Accept valid unicast + broadcast frames
; PACKETPP = $0104, PPDATA = $0D05
lda #$04
jsr packetpp_a1
lda #$05
ldx #$0D
jsr ppdata_ax
; Set MAC address
; PACKETPP = $0158, PPDATA = MAC[0], MAC[1]
; PACKETPP = $015A, PPDATA = MAC[2], MAC[3]
; PACKETPP = $015C, PPDATA = MAC[4], MAC[5]
ldy #$58
: tya
jsr packetpp_a1
lda mac-$58,y
ldx mac-$58+1,y
jsr ppdata_ax
iny
iny
cpy #$58+6
bcc :-
; Turn on transmission and reception of frames
; PACKETPP = $0112, PPDATA = $00D3
lda #$12
jsr packetpp_a1
lda #$D3
ldx #$00
jsr ppdata_ax
txa
clc
rts
;---------------------------------------------------------------------
poll:
; Check receiver event register to see if there
; are any valid unicast frames avaliable
; PACKETPP = $0124, PPDATA & $0D00 ?
lda #$24
jsr packetpp_a1
fixup05:lda ppdata+1
and #$0D
beq :+
; Process the incoming frame
; --------------------------
; Read receiver event and discard it
; RXTXREG
fixup06:ldx rxtxreg+1
fixup07:lda rxtxreg
; Read frame length
; cnt = len = RXTXREG
fixup08:ldx rxtxreg+1
fixup09:lda rxtxreg
sta len
stx len+1
sta cnt
stx cnt+1
; Adjust odd frame length
jsr adjustcnt
; Is bufsize < cnt ?
lda bufsize
cmp cnt
lda bufsize+1
sbc cnt+1
bcs :++
; Yes, skip frame
jsr skipframe
; No frame ready
lda #$00
: tax
sec
rts
; Read bytes into buffer
: jsr adjustptr
:
fixup10:lda rxtxreg
sta (ptr),y
iny
fixup11:lda rxtxreg+1
sta (ptr),y
iny
bne :-
inc ptr+1
dex
bpl :-
; Return frame length
lda len
ldx len+1
clc
rts
;---------------------------------------------------------------------
send:
; Save frame length
sta cnt
stx cnt+1
; Transmit command
lda #$C9
ldx #$00
fixup12:sta txcmd
fixup13:stx txcmd+1
lda cnt
ldx cnt+1
fixup14:sta txlen
fixup15:stx txlen+1
; Adjust odd frame length
jsr adjustcnt
; 8 retries
ldy #$08
; Check for avaliable buffer space
; PACKETPP = $0138, PPDATA & $0100 ?
: lda #$38
jsr packetpp_a1
fixup16:lda ppdata+1
and #$01
bne :+
; No space avaliable, skip a received frame
jsr skipframe
; And try again
dey
bne :-
sec
rts
; Send the frame
; --------------
; Write bytes from buffer
: jsr adjustptr
: lda (ptr),y
fixup17:sta rxtxreg
iny
lda (ptr),y
fixup18:sta rxtxreg+1
iny
bne :-
inc ptr+1
dex
bpl :-
clc
rts
;---------------------------------------------------------------------
exit:
rts
;---------------------------------------------------------------------
packetpp_a1:
ldx #$01
packetpp_ax:
fixup19:sta packetpp
fixup20:stx packetpp+1
rts
;---------------------------------------------------------------------
ppdata_ax:
fixup21:sta ppdata
fixup22:stx ppdata+1
rts
;---------------------------------------------------------------------
skipframe:
; PACKETPP = $0102, PPDATA = PPDATA | $0040
lda #$02
jsr packetpp_a1
fixup23:lda ppdata
ora #$40
fixup24:sta ppdata
rts
;---------------------------------------------------------------------
adjustcnt:
lsr
bcc :+
inc cnt
bne :+
inc cnt+1
: rts
;---------------------------------------------------------------------
adjustptr:
lda cnt
ldx cnt+1
eor #$FF ; Two's complement part 1
tay
iny ; Two's complement part 2
sty reg
sec
lda bufaddr
sbc reg
sta ptr
lda bufaddr+1
sbc #$00
sta ptr+1
rts
;---------------------------------------------------------------------