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