1 1.3 christos /* $NetBSD: if_cs.c,v 1.3 2005/12/11 12:17:34 christos Exp $ */ 2 1.1 igy 3 1.1 igy /* 4 1.1 igy * Copyright (c) 2003 Naoto Shimazaki. 5 1.1 igy * All rights reserved. 6 1.1 igy * 7 1.1 igy * Redistribution and use in source and binary forms, with or without 8 1.1 igy * modification, are permitted provided that the following conditions 9 1.1 igy * are met: 10 1.1 igy * 1. Redistributions of source code must retain the above copyright 11 1.1 igy * notice, this list of conditions and the following disclaimer. 12 1.1 igy * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 igy * notice, this list of conditions and the following disclaimer in the 14 1.1 igy * documentation and/or other materials provided with the distribution. 15 1.1 igy * 16 1.1 igy * THIS SOFTWARE IS PROVIDED BY NAOTO SHIMAZAKI AND CONTRIBUTORS ``AS IS'' 17 1.1 igy * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 18 1.1 igy * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 1.1 igy * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE NAOTO OR CONTRIBUTORS BE 20 1.1 igy * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 1.1 igy * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 1.1 igy * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 1.1 igy * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 1.1 igy * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 1.1 igy * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26 1.1 igy * THE POSSIBILITY OF SUCH DAMAGE. 27 1.1 igy */ 28 1.1 igy #include <sys/cdefs.h> 29 1.3 christos __KERNEL_RCSID(0, "$NetBSD: if_cs.c,v 1.3 2005/12/11 12:17:34 christos Exp $"); 30 1.1 igy 31 1.1 igy #include <sys/param.h> 32 1.1 igy #include <netinet/in.h> 33 1.1 igy 34 1.1 igy #include <lib/libsa/stand.h> 35 1.1 igy #include <lib/libsa/netif.h> 36 1.1 igy 37 1.1 igy #include <dev/ic/cs89x0reg.h> 38 1.1 igy 39 1.1 igy #include "extern.h" 40 1.1 igy 41 1.1 igy static int cs_match(struct netif *, void *); 42 1.1 igy static int cs_probe(struct netif *, void *); 43 1.1 igy static void cs_init(struct iodesc *, void *); 44 1.1 igy static int cs_get(struct iodesc *, void *, size_t, time_t); 45 1.1 igy static int cs_put(struct iodesc *, void *, size_t); 46 1.1 igy static void cs_end(struct netif *); 47 1.1 igy 48 1.1 igy static struct netif_stats cs_stats; 49 1.1 igy 50 1.1 igy static struct netif_dif cs_if = { 51 1.1 igy .dif_unit = 0, 52 1.1 igy .dif_nsel = 1, 53 1.1 igy .dif_stats = &cs_stats, 54 1.1 igy .dif_private = NULL, 55 1.1 igy .dif_used = 0, 56 1.1 igy }; 57 1.1 igy 58 1.1 igy struct netif_driver cs_driver = { 59 1.1 igy .netif_bname = "cs", 60 1.1 igy .netif_match = cs_match, 61 1.1 igy .netif_probe = cs_probe, 62 1.1 igy .netif_init = cs_init, 63 1.1 igy .netif_get = cs_get, 64 1.1 igy .netif_put = cs_put, 65 1.1 igy .netif_end = cs_end, 66 1.1 igy .netif_ifs = &cs_if, 67 1.1 igy .netif_nifs = 1, 68 1.1 igy }; 69 1.1 igy 70 1.1 igy #define CS_IO_BASE 0x14010300U 71 1.1 igy 72 1.1 igy #define CS_READ_1(off) REGREAD_1(CS_IO_BASE, (off)) 73 1.1 igy #define CS_READ_2(off) REGREAD_2(CS_IO_BASE, (off)) 74 1.1 igy #define CS_WRITE_1(off, val) REGWRITE_1(CS_IO_BASE, (off), (val)) 75 1.1 igy #define CS_WRITE_2(off, val) REGWRITE_2(CS_IO_BASE, (off), (val)) 76 1.1 igy #define CS_READ_PACKET_PAGE(off) \ 77 1.1 igy (REGWRITE_2(CS_IO_BASE, PORT_PKTPG_PTR, (off)), \ 78 1.1 igy REGREAD_2(CS_IO_BASE, PORT_PKTPG_DATA)) 79 1.1 igy #define CS_WRITE_PACKET_PAGE(off, val) \ 80 1.1 igy (REGWRITE_2(CS_IO_BASE, PORT_PKTPG_PTR, (off)), \ 81 1.1 igy REGWRITE_2(CS_IO_BASE, PORT_PKTPG_DATA, (val))) 82 1.1 igy 83 1.1 igy static inline void 84 1.1 igy delay(int n) 85 1.1 igy { 86 1.1 igy int i = 33 * n; 87 1.1 igy 88 1.1 igy while (--i > 0) 89 1.1 igy ; 90 1.1 igy } 91 1.1 igy 92 1.1 igy time_t 93 1.1 igy getsecs(void) 94 1.1 igy { 95 1.1 igy return REGREAD_4(VRETIMEL, 0) >> 15; 96 1.1 igy } 97 1.1 igy 98 1.1 igy static int 99 1.1 igy cs_match(struct netif *nif, void *machdep_hint) 100 1.1 igy { 101 1.1 igy return 1; 102 1.1 igy } 103 1.1 igy 104 1.1 igy static int 105 1.1 igy cs_probe(struct netif *nif, void *machdep_hint) 106 1.1 igy { 107 1.1 igy return 0; 108 1.1 igy } 109 1.1 igy 110 1.1 igy static void 111 1.2 igy cs_get_eeprom(int offset, u_int16_t *result) 112 1.2 igy { 113 1.2 igy int timeo; 114 1.2 igy 115 1.2 igy for (timeo = MAXLOOP; timeo > 0; timeo--) { 116 1.2 igy if (!(CS_READ_PACKET_PAGE(PKTPG_SELF_ST) 117 1.2 igy & SELF_ST_SI_BUSY)) 118 1.2 igy break; 119 1.2 igy } 120 1.2 igy if (timeo == 0) 121 1.2 igy goto eeprom_error; 122 1.2 igy 123 1.2 igy CS_WRITE_PACKET_PAGE(PKTPG_EEPROM_CMD, offset | EEPROM_CMD_READ); 124 1.2 igy 125 1.2 igy for (timeo = MAXLOOP; timeo > 0; timeo--) { 126 1.2 igy if (!(CS_READ_PACKET_PAGE(PKTPG_SELF_ST) 127 1.2 igy & SELF_ST_SI_BUSY)) 128 1.2 igy break; 129 1.2 igy } 130 1.2 igy if (timeo == 0) 131 1.2 igy goto eeprom_error; 132 1.2 igy 133 1.2 igy *result = CS_READ_PACKET_PAGE(PKTPG_EEPROM_DATA); 134 1.2 igy 135 1.2 igy return; 136 1.2 igy 137 1.2 igy eeprom_error: 138 1.2 igy panic("cannot read mac addr"); 139 1.2 igy } 140 1.2 igy 141 1.2 igy static void 142 1.1 igy cs_init(struct iodesc *desc, void *machdep_hint) 143 1.1 igy { 144 1.2 igy int i; 145 1.2 igy u_int16_t *myea; 146 1.1 igy 147 1.1 igy /* Issue a software reset command to the chip */ 148 1.1 igy CS_WRITE_PACKET_PAGE(PKTPG_SELF_CTL, SELF_CTL_RESET); 149 1.1 igy 150 1.1 igy /* We cannot touch the chip until calibration is done */ 151 1.1 igy delay(10000); 152 1.1 igy 153 1.1 igy /* 154 1.1 igy * Transition -SBHE H->L L->H is needed between reset and 155 1.1 igy * the first access to the chip's register. 156 1.1 igy */ 157 1.1 igy CS_READ_1(PORT_PKTPG_PTR + 0); 158 1.1 igy CS_READ_1(PORT_PKTPG_PTR + 1); 159 1.1 igy CS_READ_1(PORT_PKTPG_PTR + 0); 160 1.1 igy CS_READ_1(PORT_PKTPG_PTR + 1); 161 1.1 igy 162 1.1 igy /* wait for INIT_DONE */ 163 1.1 igy for (i = 10000; i > 0; i--) { 164 1.1 igy u_int16_t s; 165 1.1 igy 166 1.1 igy s = CS_READ_PACKET_PAGE(PKTPG_SELF_ST); 167 1.1 igy if ((s & SELF_ST_INIT_DONE) && !(s & SELF_ST_SI_BUSY)) 168 1.1 igy break; 169 1.1 igy } 170 1.1 igy if (i == 0) 171 1.1 igy panic("cannot reset netif"); 172 1.1 igy 173 1.2 igy myea = (u_int16_t *) desc->myea; 174 1.1 igy 175 1.2 igy cs_get_eeprom(EEPROM_IND_ADDR_H, &myea[0]); 176 1.2 igy cs_get_eeprom(EEPROM_IND_ADDR_M, &myea[1]); 177 1.2 igy cs_get_eeprom(EEPROM_IND_ADDR_L, &myea[2]); 178 1.1 igy 179 1.2 igy for (i = 0; i < 3; i++) 180 1.2 igy CS_WRITE_PACKET_PAGE(PKTPG_IND_ADDR + (i << 1), myea[i]); 181 1.1 igy 182 1.1 igy /* 183 1.1 igy * Accepting frames: 184 1.1 igy * RX_CTL_RX_OK_A: correct crc, and valid length 185 1.1 igy * RX_CTL_IND_A: dest addr maches individual address 186 1.1 igy * RX_CTL_BCAST_A: dest addr maches broadcast address 187 1.1 igy */ 188 1.1 igy CS_WRITE_PACKET_PAGE(PKTPG_RX_CTL, 189 1.1 igy RX_CTL_RX_OK_A | RX_CTL_IND_A | RX_CTL_BCAST_A); 190 1.1 igy CS_WRITE_PACKET_PAGE(PKTPG_LINE_CTL, LINE_CTL_RX_ON | LINE_CTL_TX_ON); 191 1.1 igy } 192 1.1 igy 193 1.1 igy static int 194 1.1 igy cs_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout) 195 1.1 igy { 196 1.1 igy time_t t; 197 1.1 igy int rlen; 198 1.1 igy int i; 199 1.1 igy u_int16_t *p; 200 1.1 igy 201 1.1 igy t = getsecs(); 202 1.1 igy rlen = 0; 203 1.1 igy while (getsecs() - t < timeout && rlen == 0) { 204 1.1 igy if (!(CS_READ_PACKET_PAGE(PKTPG_RX_EVENT) & RX_EVENT_RX_OK)) 205 1.1 igy continue; 206 1.1 igy 207 1.1 igy /* drop status */ 208 1.1 igy CS_READ_2(PORT_RXTX_DATA); 209 1.1 igy 210 1.1 igy /* get frame length */ 211 1.1 igy rlen = CS_READ_2(PORT_RXTX_DATA); 212 1.1 igy 213 1.1 igy if (rlen > len) { 214 1.1 igy CS_WRITE_PACKET_PAGE(PKTPG_RX_CFG, RX_CFG_SKIP); 215 1.1 igy rlen = 0; 216 1.1 igy continue; 217 1.1 igy } 218 1.1 igy 219 1.1 igy p = pkt; 220 1.1 igy for (i = rlen >> 1; i > 0; i--) 221 1.1 igy *p++ = CS_READ_2(PORT_RXTX_DATA); 222 1.1 igy if (rlen & 1) 223 1.1 igy *((u_int8_t *) p + 1) = CS_READ_1(PORT_RXTX_DATA); 224 1.1 igy 225 1.1 igy /* exit while loop */ 226 1.1 igy } 227 1.1 igy 228 1.1 igy return rlen; 229 1.1 igy } 230 1.1 igy 231 1.1 igy static int 232 1.1 igy cs_put(struct iodesc *desc, void *pkt, size_t len) 233 1.1 igy { 234 1.1 igy int timeo; 235 1.1 igy int i; 236 1.1 igy u_int16_t *p; 237 1.1 igy 238 1.1 igy CS_WRITE_2(PORT_TX_CMD, TX_CMD_START_ALL); 239 1.1 igy CS_WRITE_2(PORT_TX_LENGTH, len); 240 1.1 igy 241 1.1 igy for (timeo = 1000000; timeo > 0; timeo--) { 242 1.1 igy if (CS_READ_PACKET_PAGE(PKTPG_BUS_ST) & BUS_ST_RDY4TXNOW) 243 1.1 igy break; 244 1.1 igy } 245 1.1 igy if (timeo == 0) 246 1.1 igy panic("cs: cannot send frame"); 247 1.1 igy 248 1.1 igy p = pkt; 249 1.1 igy i = (len + 1) >> 1; 250 1.1 igy while (i > 0) { 251 1.1 igy CS_WRITE_2(PORT_RXTX_DATA, *p++); 252 1.1 igy i--; 253 1.1 igy } 254 1.1 igy 255 1.1 igy return len; 256 1.1 igy } 257 1.1 igy 258 1.1 igy static void 259 1.1 igy cs_end(struct netif *nif) 260 1.1 igy { 261 1.1 igy CS_WRITE_PACKET_PAGE(PKTPG_LINE_CTL, 0); 262 1.1 igy } 263