| /* |
| * Copyright (c) 2001, Adam Dunkels. |
| * 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. All advertising materials mentioning features or use of this software |
| * must display the following acknowledgement: |
| * This product includes software developed by Adam Dunkels. |
| * 4. The name of the author may not be used to endorse or promote |
| * products derived from this software without specific prior |
| * written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 C64 RealAudio server demo project. |
| * |
| * $Id: cs8900a.c,v 1.1 2003/03/19 16:26:19 adamdunkels Exp $ |
| * |
| */ |
| |
| /* cs8900a.c: device driver for the CS8900a chip in 8-bit mode. Mostly |
| written in 6502 assembler for speed. */ |
| |
| #include "cs8900a.h" |
| #include "uip.h" |
| #include "uip_arp.h" |
| |
| #define RXTXREG (*(u16_t *)0xde00) |
| #define PACKETPP (*(u16_t *)0xde0a) |
| #define PPDATA (*(u16_t *)0xde0c) |
| |
| static u16_t len; |
| static u8_t r; |
| |
| |
| /*-----------------------------------------------------------------------------------*/ |
| void |
| cs8900a_init(void) |
| { |
| /* Turn on transmission and reception of frames. */ |
| /* PACKETPP = 0x0112; |
| PPDATA = 0x00c0; */ |
| asm("lda #$12"); |
| asm("sta $de0a"); |
| asm("lda #$01"); |
| asm("sta $de0b"); |
| asm("lda #$c0"); |
| asm("sta $de0c"); |
| asm("lda #$00"); |
| asm("sta $de0d"); |
| |
| /* Accept valid unicast+broadcast frames. */ |
| /* PACKETPP = 0x0104; |
| PPDATA = 0x0d05; */ |
| asm("lda #$04"); |
| asm("sta $de0a"); |
| asm("lda #$01"); |
| asm("sta $de0b"); |
| asm("lda #$05"); |
| asm("sta $de0c"); |
| asm("lda #$0d"); |
| asm("sta $de0d"); |
| |
| /* Set MAC address. */ |
| /* PACKETPP = 0x0158; |
| PPDATA = (ETHADDR1 << 8) | (ETHADDR0); */ |
| asm("lda #$58"); |
| asm("sta $de0a"); |
| asm("lda #$01"); |
| asm("sta $de0b"); |
| asm("lda #%b", UIP_ETHADDR0); |
| asm("sta $de0c"); |
| asm("lda #%b", UIP_ETHADDR1); |
| asm("sta $de0d"); |
| |
| /* PACKETPP = 0x015a; |
| PPDATA = (ETHADDR3 << 8) | (ETHADDR2); */ |
| asm("lda #$5a"); |
| asm("sta $de0a"); |
| asm("lda #$01"); |
| asm("sta $de0b"); |
| asm("lda #%b", UIP_ETHADDR2); |
| asm("sta $de0c"); |
| asm("lda #%b", UIP_ETHADDR3); |
| asm("sta $de0d"); |
| |
| /* PACKETPP = 0x015c; |
| PPDATA = (ETHADDR5 << 8) | (ETHADDR4); */ |
| asm("lda #$5c"); |
| asm("sta $de0a"); |
| asm("lda #$01"); |
| asm("sta $de0b"); |
| asm("lda #%b", UIP_ETHADDR4); |
| asm("sta $de0c"); |
| asm("lda #%b", UIP_ETHADDR5); |
| asm("sta $de0d"); |
| |
| } |
| /*-----------------------------------------------------------------------------------*/ |
| void |
| cs8900a_send(void) |
| { |
| if(uip_len >= UIP_BUFSIZE) { |
| asm("inc $d020"); |
| return; |
| } |
| |
| /* Transmit command. */ |
| asm("lda #$c0"); |
| asm("sta $de04"); |
| asm("lda #$00"); |
| asm("sta $de05"); |
| asm("lda _uip_len"); |
| asm("sta $de06"); |
| #if UIP_BUFSIZE > 255 |
| asm("lda _uip_len+1"); |
| #else |
| asm("lda #0"); |
| #endif |
| asm("sta $de07"); |
| |
| asm("ldx #8"); |
| asm("tryagain:"); |
| /* Check for avaliable buffer space. */ |
| asm("lda #$38"); |
| asm("sta $de0a"); |
| asm("lda #$01"); |
| asm("sta $de0b"); |
| asm("lda $de0d"); |
| asm("and #1"); |
| asm("bne send"); |
| |
| /* No space avaliable, skip a received frame and try again. */ |
| asm("lda #$02"); |
| asm("sta $de0a"); |
| asm("lda #$01"); |
| asm("sta $de0b"); |
| asm("lda $de0c"); |
| asm("ora #$40"); |
| asm("sta $de0c"); |
| |
| asm("dex"); |
| asm("bne tryagain"); |
| |
| asm("bailout:"); |
| return; |
| |
| /* Send the frame. */ |
| asm("send:"); |
| |
| |
| /* First, send 40+14=54 bytes of header. */ |
| |
| asm("ldx #54"); |
| asm("ldy #0"); |
| asm("sendloop1:"); |
| asm("lda _uip_buf,y"); |
| asm("sta $de00"); |
| asm("lda _uip_buf+1,y"); |
| asm("sta $de01"); |
| asm("iny"); |
| asm("iny"); |
| asm("dex"); |
| asm("dex"); |
| asm("bne sendloop1"); |
| |
| if(uip_len <= 54) { |
| return; |
| } |
| |
| /* Next, send rest of the packet. */ |
| |
| uip_len -= 54; |
| |
| |
| asm("lda ptr1"); |
| asm("pha"); |
| asm("lda ptr1+1"); |
| asm("pha"); |
| |
| asm("lda _uip_appdata"); |
| asm("sta ptr1"); |
| asm("lda _uip_appdata+1"); |
| asm("sta ptr1+1"); |
| |
| asm("sendloop2:"); |
| asm("lda _uip_len"); |
| asm("tax"); |
| asm("and #1"); |
| asm("beq noinc"); |
| asm("inx"); |
| asm("noinc:"); |
| #if UIP_BUFSIZE > 255 |
| asm("lda _uip_len+1"); |
| #else |
| asm("lda #0"); |
| #endif |
| asm("beq nozero"); |
| asm("ldx #0"); |
| asm("nozero:"); |
| asm("ldy #0"); |
| asm("sendloop:"); |
| asm("lda (ptr1),y"); |
| asm("sta $de00"); |
| asm("iny"); |
| asm("lda (ptr1),y"); |
| asm("sta $de01"); |
| asm("iny"); |
| asm("dex"); |
| asm("dex"); |
| asm("bne sendloop"); |
| asm("inc ptr1+1"); |
| #if UIP_BUFSIZE > 255 |
| asm("dec _uip_len+1"); |
| asm("bpl sendloop2"); |
| #endif |
| |
| asm("pla"); |
| asm("sta ptr1+1"); |
| asm("pla"); |
| asm("sta ptr1"); |
| } |
| /*-----------------------------------------------------------------------------------*/ |
| static void |
| skip_frame(void) |
| { |
| /* PACKETPP = 0x0102; |
| PPDATA = PPDATA | 0x0040; */ |
| asm("lda #$02"); |
| asm("sta $de0a"); |
| asm("lda #$01"); |
| asm("sta $de0b"); |
| asm("lda $de0c"); |
| asm("ora #$40"); |
| asm("sta $de0c"); |
| } |
| /*-----------------------------------------------------------------------------------*/ |
| u8_t |
| cs8900a_poll(void) |
| { |
| /* Check receiver event register to see if there are any valid |
| unicast frames avaliable. */ |
| /* PACKETPP = 0x0124; |
| if(PPDATA & 0x000d == 0x0000) { |
| return 0; |
| } |
| */ |
| asm("lda #$24"); |
| asm("sta $de0a"); |
| asm("lda #$01"); |
| asm("sta $de0b"); |
| asm("lda $de0d"); |
| asm("and #$0d"); |
| asm("cmp #$00"); |
| asm("bne noreturn"); |
| /* No frame ready. */ |
| return 0; |
| |
| asm("noreturn:"); |
| /* Process the incoming frame. */ |
| |
| /* Read receiver event and discard it. */ |
| /* dummy = RXTXREG; */ |
| |
| asm("lda $de01"); |
| asm("sta _len+1"); |
| asm("lda $de00"); |
| asm("sta _len"); |
| |
| /* Read frame length. */ |
| /* len = uip_len = RXTXREG; */ |
| asm("lda $de01"); |
| asm("sta _len+1"); |
| asm("sta _uip_len+1"); |
| asm("lda $de00"); |
| asm("sta _len"); |
| asm("sta _uip_len"); |
| |
| |
| if(len > UIP_BUFSIZE) { |
| skip_frame(); |
| return 0; |
| } |
| |
| /* Read bytes into uip_buf. */ |
| asm("lda ptr1"); |
| asm("pha"); |
| asm("lda ptr1+1"); |
| asm("pha"); |
| |
| asm("lda #<_uip_buf"); |
| asm("sta ptr1"); |
| asm("lda #>_uip_buf"); |
| asm("sta ptr1+1"); |
| |
| asm("lda _len+1"); |
| asm("beq read256"); |
| |
| /* Read first 256*n bytes. */ |
| asm("ldy #0"); |
| asm("read256loop:"); |
| asm("lda $de00"); |
| asm("sta (ptr1),y"); |
| asm("iny"); |
| asm("lda $de01"); |
| asm("sta (ptr1),y"); |
| asm("iny"); |
| asm("bne read256loop"); |
| asm("inc ptr1+1"); |
| |
| asm("dec _len+1"); |
| asm("bne read256loop"); |
| |
| /* Read last 255 or less bytes. */ |
| asm("read256:"); |
| asm("lda _len"); |
| asm("lsr"); |
| asm("bcc noinc"); |
| asm("inc _len"); |
| asm("noinc:"); |
| asm("ldy #$0"); |
| asm("readloop:"); |
| asm("lda $de00"); |
| asm("sta (ptr1),y"); |
| asm("iny"); |
| asm("lda $de01"); |
| asm("sta (ptr1),y"); |
| asm("iny"); |
| asm("cpy _len"); |
| asm("bne readloop"); |
| |
| asm("pla"); |
| asm("sta ptr1+1"); |
| asm("pla"); |
| asm("sta ptr1"); |
| return len; |
| } |