1 /* 2 * Pegasus BeOS Driver 3 * 4 * Copyright 2006, Haiku, Inc. All Rights Reserved. 5 * Distributed under the terms of the MIT License. 6 * 7 * Authors: 8 * Jérôme Duval 9 */ 10 11 /*- 12 * Copyright (c) 1997, 1998, 1999, 2000 13 * Bill Paul <wpaul@ee.columbia.edu>. All rights reserved. 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions 17 * are met: 18 * 1. Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in the 22 * documentation and/or other materials provided with the distribution. 23 * 3. All advertising materials mentioning features or use of this software 24 * must display the following acknowledgement: 25 * This product includes software developed by Bill Paul. 26 * 4. Neither the name of the author nor the names of any co-contributors 27 * may be used to endorse or promote products derived from this software 28 * without specific prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 34 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 35 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 36 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 38 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 39 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 40 * THE POSSIBILITY OF SUCH DAMAGE. 41 */ 42 43 #include <string.h> 44 #include "driver.h" 45 #include "usbdevs.h" 46 47 extern usb_module_info *usb; 48 49 #define AUE_SETBIT(sc, reg, x) \ 50 aue_csr_write_1(sc, reg, aue_csr_read_1(sc, reg) | (x)) 51 52 #define AUE_CLRBIT(sc, reg, x) \ 53 aue_csr_write_1(sc, reg, aue_csr_read_1(sc, reg) & ~(x)) 54 55 static int 56 aue_csr_read_1(pegasus_dev *sc, int reg) 57 { 58 status_t err; 59 uint8 val = 0; 60 size_t length; 61 62 if (sc->aue_dying) 63 return (0); 64 65 AUE_LOCK(sc); 66 67 err = usb->send_request(sc->dev, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_IN, 68 AUE_UR_READREG, 0, reg, 1, &val, &length); 69 AUE_UNLOCK(sc); 70 71 if (err) { 72 return (0); 73 } 74 75 return (val); 76 } 77 78 static int 79 aue_csr_read_2(pegasus_dev *sc, int reg) 80 { 81 status_t err; 82 uint16 val = 0; 83 size_t length; 84 85 if (sc->aue_dying) 86 return (0); 87 88 AUE_LOCK(sc); 89 90 err = usb->send_request(sc->dev, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_IN, 91 AUE_UR_READREG, 0, reg, 2, &val, &length); 92 93 AUE_UNLOCK(sc); 94 95 if (err) { 96 return (0); 97 } 98 99 return (val); 100 } 101 102 static int 103 aue_csr_write_1(pegasus_dev *sc, int reg, int val) 104 { 105 status_t err; 106 size_t length = 1; 107 108 if (sc->aue_dying) 109 return (0); 110 111 AUE_LOCK(sc); 112 113 err = usb->send_request(sc->dev, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, 114 AUE_UR_WRITEREG, val, reg, 1, &val, &length); 115 116 AUE_UNLOCK(sc); 117 118 if (err) { 119 return (-1); 120 } 121 122 return (0); 123 } 124 125 static int 126 aue_csr_write_2(pegasus_dev *sc, int reg, int val) 127 { 128 status_t err; 129 size_t length = 2; 130 131 if (sc->aue_dying) 132 return (0); 133 134 AUE_LOCK(sc); 135 136 err = usb->send_request(sc->dev, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, 137 AUE_UR_WRITEREG, val, reg, 2, &val, &length); 138 139 AUE_UNLOCK(sc); 140 141 if (err) { 142 return (-1); 143 } 144 145 return (0); 146 } 147 148 /* 149 * Read a word of data stored in the EEPROM at address 'addr.' 150 */ 151 static void 152 aue_eeprom_getword(pegasus_dev *sc, int addr, u_int16_t *dest) 153 { 154 int i; 155 u_int16_t word = 0; 156 157 aue_csr_write_1(sc, AUE_EE_REG, addr); 158 aue_csr_write_1(sc, AUE_EE_CTL, AUE_EECTL_READ); 159 160 for (i = 0; i < AUE_TIMEOUT; i++) { 161 if (aue_csr_read_1(sc, AUE_EE_CTL) & AUE_EECTL_DONE) 162 break; 163 } 164 165 if (i == AUE_TIMEOUT) { 166 dprintf("aue%d: EEPROM read timed out\n", 167 sc->aue_unit); 168 } 169 170 word = aue_csr_read_2(sc, AUE_EE_DATA); 171 *dest = word; 172 173 return; 174 } 175 176 177 178 179 /* 180 * Read a sequence of words from the EEPROM. 181 */ 182 static void 183 aue_read_eeprom(pegasus_dev *sc, caddr_t dest, int off, int cnt, int swap) 184 { 185 int i; 186 u_int16_t word = 0, *ptr; 187 188 for (i = 0; i < cnt; i++) { 189 aue_eeprom_getword(sc, off + i, &word); 190 ptr = (u_int16_t *)(dest + (i * 2)); 191 if (swap) 192 *ptr = B_BENDIAN_TO_HOST_INT16(word); 193 else 194 *ptr = word; 195 } 196 197 return; 198 } 199 200 201 static int 202 aue_miibus_readreg(pegasus_dev *sc, int phy, int reg) 203 { 204 int i; 205 u_int16_t val = 0; 206 207 /* 208 * The Am79C901 HomePNA PHY actually contains 209 * two transceivers: a 1Mbps HomePNA PHY and a 210 * 10Mbps full/half duplex ethernet PHY with 211 * NWAY autoneg. However in the ADMtek adapter, 212 * only the 1Mbps PHY is actually connected to 213 * anything, so we ignore the 10Mbps one. It 214 * happens to be configured for MII address 3, 215 * so we filter that out. 216 */ 217 if (sc->aue_vendor == USB_VENDOR_ADMTEK && 218 sc->aue_product == USB_PRODUCT_ADMTEK_PEGASUS) { 219 if (phy == 3) 220 return (0); 221 #ifdef notdef 222 if (phy != 1) 223 return (0); 224 #endif 225 } 226 227 aue_csr_write_1(sc, AUE_PHY_ADDR, phy); 228 aue_csr_write_1(sc, AUE_PHY_CTL, reg | AUE_PHYCTL_READ); 229 230 for (i = 0; i < AUE_TIMEOUT; i++) { 231 if (aue_csr_read_1(sc, AUE_PHY_CTL) & AUE_PHYCTL_DONE) 232 break; 233 } 234 235 if (i == AUE_TIMEOUT) { 236 dprintf("aue%d: MII read timed out\n", sc->aue_unit); 237 } 238 239 val = aue_csr_read_2(sc, AUE_PHY_DATA); 240 241 return (val); 242 } 243 244 245 static int 246 aue_miibus_writereg(pegasus_dev *sc, int phy, int reg, int data) 247 { 248 int i; 249 250 if (phy == 3) 251 return (0); 252 253 aue_csr_write_2(sc, AUE_PHY_DATA, data); 254 aue_csr_write_1(sc, AUE_PHY_ADDR, phy); 255 aue_csr_write_1(sc, AUE_PHY_CTL, reg | AUE_PHYCTL_WRITE); 256 257 for (i = 0; i < AUE_TIMEOUT; i++) { 258 if (aue_csr_read_1(sc, AUE_PHY_CTL) & AUE_PHYCTL_DONE) 259 break; 260 } 261 262 if (i == AUE_TIMEOUT) { 263 dprintf("aue%d: MII read timed out\n", 264 sc->aue_unit); 265 } 266 267 return (0); 268 } 269 270 271 static uint16 272 aue_miibus_read(pegasus_dev *dev, uint16 reg) 273 { 274 return aue_miibus_readreg(dev, dev->phy, reg); 275 } 276 277 278 static void 279 aue_miibus_write(pegasus_dev *dev, uint16 reg, uint16 value) 280 { 281 aue_miibus_writereg(dev, dev->phy, reg, value); 282 } 283 284 285 static uint16 286 aue_miibus_status_from_phy(pegasus_dev *dev, uint16 phy) 287 { 288 uint16 status; 289 int i = 0; 290 291 // the status must be retrieved two times, because the first 292 // one may not work on some PHYs (notably ICS 1893) 293 while (i++ < 2) 294 status = aue_miibus_readreg(dev, phy, MII_STATUS); 295 296 return status; 297 } 298 299 300 static uint16 301 aue_miibus_status(pegasus_dev *dev) 302 { 303 return aue_miibus_status_from_phy(dev, dev->phy); 304 } 305 306 307 static status_t 308 aue_init_phy(pegasus_dev *dev) 309 { 310 uint16 phy, status; 311 int i; 312 313 dev->phy = 255; 314 315 // search for total of 32 possible MII PHY addresses 316 for (phy = 0; phy < 32; phy++) { 317 uint16 status; 318 319 status = aue_miibus_status_from_phy(dev, phy); 320 if (status == 0xffff || status == 0x0000) 321 // this MII is not accessable 322 continue; 323 324 dev->phy = phy; 325 } 326 327 if (dev->phy == 255) { 328 DPRINTF_ERR("No MII PHY transceiver found!\n"); 329 return B_ENTRY_NOT_FOUND; 330 } 331 DPRINTF_INFO("aue_init_phy MII PHY found at %d\n", dev->phy); 332 333 status = aue_miibus_read(dev, MII_CONTROL); 334 status &= ~MII_CONTROL_ISOLATE; 335 336 aue_miibus_write(dev, MII_CONTROL, status); 337 338 aue_miibus_write(dev, MII_CONTROL, MII_CONTROL_RESET); 339 for (i = 0; i < 100; i++) { 340 if ((aue_miibus_read(dev, MII_STATUS) & MII_CONTROL_RESET) == 0) 341 break; 342 DELAY(1000); 343 } 344 345 dev->link = aue_miibus_status(dev) & MII_STATUS_LINK; 346 347 return B_OK; 348 } 349 350 351 static void 352 aue_reset_pegasus_II(pegasus_dev *sc) 353 { 354 /* Magic constants taken from Linux driver. */ 355 aue_csr_write_1(sc, AUE_REG_1D, 0); 356 aue_csr_write_1(sc, AUE_REG_7B, 2); 357 #if 0 358 if ((sc->aue_flags & HAS_HOME_PNA) && mii_mode) 359 aue_csr_write_1(sc, AUE_REG_81, 6); 360 else 361 #endif 362 aue_csr_write_1(sc, AUE_REG_81, 2); 363 } 364 365 static void 366 aue_reset(pegasus_dev *sc) 367 { 368 int i; 369 370 AUE_SETBIT(sc, AUE_CTL1, AUE_CTL1_RESETMAC); 371 372 for (i = 0; i < AUE_TIMEOUT; i++) { 373 if (!(aue_csr_read_1(sc, AUE_CTL1) & AUE_CTL1_RESETMAC)) 374 break; 375 } 376 377 if (i == AUE_TIMEOUT) 378 dprintf("aue%d: reset failed\n", sc->aue_unit); 379 380 /* 381 * The PHY(s) attached to the Pegasus chip may be held 382 * in reset until we flip on the GPIO outputs. Make sure 383 * to set the GPIO pins high so that the PHY(s) will 384 * be enabled. 385 * 386 * Note: We force all of the GPIO pins low first, *then* 387 * enable the ones we want. 388 */ 389 aue_csr_write_1(sc, AUE_GPIO0, AUE_GPIO_OUT0|AUE_GPIO_SEL0); 390 aue_csr_write_1(sc, AUE_GPIO0, AUE_GPIO_OUT0|AUE_GPIO_SEL0|AUE_GPIO_SEL1); 391 392 if (sc->aue_flags & LSYS) { 393 /* Grrr. LinkSys has to be different from everyone else. */ 394 aue_csr_write_1(sc, AUE_GPIO0, 395 AUE_GPIO_SEL0 | AUE_GPIO_SEL1); 396 aue_csr_write_1(sc, AUE_GPIO0, 397 AUE_GPIO_SEL0 | AUE_GPIO_SEL1 | AUE_GPIO_OUT0); 398 } 399 400 if (sc->aue_flags & PII) 401 aue_reset_pegasus_II(sc); 402 403 /* Wait a little while for the chip to get its brains in order. */ 404 DELAY(10000); 405 406 return; 407 } 408 409 410 /* 411 * Attach 412 */ 413 void 414 aue_attach(pegasus_dev *sc) 415 { 416 u_char eaddr[ETHER_ADDRESS_LENGTH]; 417 418 AUE_LOCK(sc); 419 420 /* Reset the adapter. */ 421 aue_reset(sc); 422 423 /* 424 * Get station address from the EEPROM. 425 */ 426 aue_read_eeprom(sc, (caddr_t)&eaddr, 0, 3, 0); 427 428 memcpy(sc->macaddr, eaddr, ETHER_ADDRESS_LENGTH); 429 430 if (aue_init_phy(sc) != B_OK) 431 goto done; 432 433 sc->aue_dying = 0; 434 435 done: 436 AUE_UNLOCK(sc); 437 } 438 439 440 void 441 aue_init(pegasus_dev *sc) 442 { 443 444 /* Enable RX and TX */ 445 aue_csr_write_1(sc, AUE_CTL0, AUE_CTL0_RXSTAT_APPEND | AUE_CTL0_RX_ENB); 446 AUE_SETBIT(sc, AUE_CTL0, AUE_CTL0_TX_ENB); 447 AUE_SETBIT(sc, AUE_CTL2, AUE_CTL2_EP3_CLR); 448 449 } 450 451 452 void 453 aue_uninit(pegasus_dev *sc) 454 { 455 aue_csr_write_1(sc, AUE_CTL0, 0); 456 aue_csr_write_1(sc, AUE_CTL1, 0); 457 aue_reset(sc); 458 } 459