|
|
1.1.1.2 ! root 1: /* $Id: am7990.c,v 1.4 2010/06/05 14:33:45 fredette Exp $ */ 1.1 root 2: 3: /* ic/am7990.c - implementation of Am7990 emulation: */ 4: 5: /* 6: * Copyright (c) 2006 Matt Fredette 7: * All rights reserved. 8: * 9: * Redistribution and use in source and binary forms, with or without 10: * modification, are permitted provided that the following conditions 11: * are met: 12: * 1. Redistributions of source code must retain the above copyright 13: * notice, this list of conditions and the following disclaimer. 14: * 2. Redistributions in binary form must reproduce the above copyright 15: * notice, this list of conditions and the following disclaimer in the 16: * documentation and/or other materials provided with the distribution. 17: * 3. All advertising materials mentioning features or use of this software 18: * must display the following acknowledgement: 19: * This product includes software developed by Matt Fredette. 20: * 4. The name of the author may not be used to endorse or promote products 21: * derived from this software without specific prior written permission. 22: * 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33: * POSSIBILITY OF SUCH DAMAGE. 34: */ 35: 36: #include <tme/common.h> 1.1.1.2 ! root 37: _TME_RCSID("$Id: am7990.c,v 1.4 2010/06/05 14:33:45 fredette Exp $"); 1.1 root 38: 39: /* includes: */ 40: #include <tme/generic/bus-device.h> 41: #include <tme/generic/ethernet.h> 42: 43: /* macros: */ 44: 45: /* CSR0: */ 46: #define TME_AM7990_CSR0_ERR TME_BIT(15) 47: #define TME_AM7990_CSR0_BABL TME_BIT(14) 48: #define TME_AM7990_CSR0_CERR TME_BIT(13) 49: #define TME_AM7990_CSR0_MISS TME_BIT(12) 50: #define TME_AM7990_CSR0_MERR TME_BIT(11) 51: #define TME_AM7990_CSR0_RINT TME_BIT(10) 52: #define TME_AM7990_CSR0_TINT TME_BIT(9) 53: #define TME_AM7990_CSR0_IDON TME_BIT(8) 54: #define TME_AM7990_CSR0_INTR TME_BIT(7) 55: #define TME_AM7990_CSR0_INEA TME_BIT(6) 56: #define TME_AM7990_CSR0_RXON TME_BIT(5) 57: #define TME_AM7990_CSR0_TXON TME_BIT(4) 58: #define TME_AM7990_CSR0_TDMD TME_BIT(3) 59: #define TME_AM7990_CSR0_STOP TME_BIT(2) 60: #define TME_AM7990_CSR0_STRT TME_BIT(1) 61: #define TME_AM7990_CSR0_INIT TME_BIT(0) 62: #define TME_AM7990_CSR0_READ_ONLY \ 63: (TME_AM7990_CSR0_ERR \ 64: | TME_AM7990_CSR0_INTR \ 65: | TME_AM7990_CSR0_RXON \ 66: | TME_AM7990_CSR0_TXON) 67: #define TME_AM7990_CSR0_WRITE_ONE_TO_CLEAR \ 68: (TME_AM7990_CSR0_BABL \ 69: | TME_AM7990_CSR0_CERR \ 70: | TME_AM7990_CSR0_MISS \ 71: | TME_AM7990_CSR0_MERR \ 72: | TME_AM7990_CSR0_RINT \ 73: | TME_AM7990_CSR0_TINT \ 74: | TME_AM7990_CSR0_IDON) 75: #define TME_AM7990_CSR0_WRITE_ONE_ONLY \ 76: (TME_AM7990_CSR0_TDMD \ 77: | TME_AM7990_CSR0_STOP \ 78: | TME_AM7990_CSR0_STRT \ 79: | TME_AM7990_CSR0_INIT) 80: 81: /* CSR3: */ 82: #define TME_AM7990_CSR3_BSWAP TME_BIT(2) 83: #define TME_AM7990_CSR3_ACON TME_BIT(1) 84: #define TME_AM7990_CSR3_BCON TME_BIT(0) 85: 86: /* Mode: */ 87: #define TME_AM7990_MODE_PROM TME_BIT(15) 88: #define TME_AM7990_MODE_EMBA TME_BIT(7) 89: #define TME_AM7990_MODE_INTL TME_BIT(6) 90: #define TME_AM7990_MODE_DRTY TME_BIT(5) 91: #define TME_AM7990_MODE_COLL TME_BIT(4) 92: #define TME_AM7990_MODE_DTCR TME_BIT(3) 93: #define TME_AM7990_MODE_LOOP TME_BIT(2) 94: #define TME_AM7990_MODE_DTX TME_BIT(1) 95: #define TME_AM7990_MODE_DRX TME_BIT(0) 96: 97: /* a Descriptor Ring Pointer: */ 98: #define TME_AM7990_DRP_XDRA (0x00fffff8) 99: #define TME_AM7990_DRP_XLEN_LOG2 (0xe0000000) 100: 101: /* a descriptor table entry: */ 102: #define TME_AM7990_DTE_OFFSET_XMD0 (0 * sizeof(tme_uint16_t)) 103: #define TME_AM7990_DTE_OFFSET_XMD1 (1 * sizeof(tme_uint16_t)) 104: #define TME_AM7990_DTE_OFFSET_XMD2 (2 * sizeof(tme_uint16_t)) 105: #define TME_AM7990_DTE_OFFSET_XMD3 (3 * sizeof(tme_uint16_t)) 106: #define TME_AM7990_DTE_SIZE (4 * sizeof(tme_uint16_t)) 107: 108: /* common parts of TMD1 and RMD1: */ 109: #define TME_AM7990_XMD1_OWN TME_BIT(15) 110: #define TME_AM7990_XMD1_ERR TME_BIT(14) 111: #define TME_AM7990_XMD1_STP TME_BIT(9) 112: #define TME_AM7990_XMD1_ENP TME_BIT(8) 113: #define TME_AM7990_XMD1_HADR (0x00ff) 114: 115: /* common parts of TMD2 and RMD2: */ 116: #define TME_AM7990_XMD2_BCNT (0x0fff) 117: 118: /* TMD1: */ 119: #define TME_AM7990_TMD1_ADD_FCS TME_BIT(13) 120: 121: /* TMD3: */ 122: #define TME_AM7990_TMD3_BUFF TME_BIT(15) 123: 124: /* RMD1: */ 125: #define TME_AM7990_RMD1_BUFF TME_BIT(10) 126: 127: /* the callout flags: */ 128: #define TME_AM7990_CALLOUTS_RUNNING TME_BIT(0) 129: #define TME_AM7990_CALLOUTS_MASK (-2) 130: #define TME_AM7990_CALLOUT_RECEIVE TME_BIT(1) 131: #define TME_AM7990_CALLOUT_TRANSMIT_SCAN TME_BIT(2) 132: #define TME_AM7990_CALLOUT_CONFIG TME_BIT(3) 133: #define TME_AM7990_CALLOUT_DMA_READ TME_BIT(4) 134: #define TME_AM7990_CALLOUT_DMA_WRITE TME_BIT(5) 135: 136: /* the default locks: */ 137: #define TME_AM7990_LOCKS_DEFAULT (0) 138: 139: /* the size of the TLB entry hash: */ 140: #define TME_AM7990_TLB_HASH_SIZE (512) 141: 142: /* structures: */ 143: 144: /* the chip: */ 145: struct tme_am7990 { 146: 147: /* our simple bus device header: */ 148: struct tme_bus_device tme_am7990_device; 149: #define tme_am7990_element tme_am7990_device.tme_bus_device_element 150: 151: /* the Ethernet connection: */ 152: struct tme_ethernet_connection *tme_am7990_eth_connection; 153: 154: /* the mutex protecting the chip: */ 155: tme_mutex_t tme_am7990_mutex; 156: 157: /* the callout flags: */ 158: int tme_am7990_callout_flags; 159: 160: /* our DMA TLB hash: */ 1.1.1.2 ! root 161: struct tme_bus_tlb tme_am7990_tlb_hash[TME_AM7990_TLB_HASH_SIZE]; ! 162: int tme_am7990_tlb_hash_added; 1.1 root 163: 164: /* our bus addresses: */ 1.1.1.2 ! root 165: tme_bus_addr32_t tme_am7990_offset_rap; ! 166: tme_bus_addr32_t tme_am7990_offset_rdp; 1.1 root 167: 168: /* registers: */ 169: tme_uint16_t tme_am7990_rap; 170: tme_uint16_t tme_am7990_csrs[4]; 171: #define tme_am7990_csr0 tme_am7990_csrs[0] 172: 173: /* the initialization block: */ 174: tme_uint16_t tme_am7990_init[12]; 175: #define tme_am7990_mode tme_am7990_init[0] 176: #define tme_am7990_padr tme_am7990_init[1] 177: #define tme_am7990_ladrf tme_am7990_init[4] 178: #define tme_am7990_rdra tme_am7990_init[8] 179: #define tme_am7990_rlen_rdra tme_am7990_init[9] 180: #define tme_am7990_tdra tme_am7990_init[10] 181: #define tme_am7990_tlen_tdra tme_am7990_init[11] 182: 183: /* the transmit ring: */ 184: unsigned int tme_am7990_transmit_dte_index_mask; 185: tme_uint32_t tme_am7990_transmit_dte_address; 186: 187: /* the current transmit DTE index, and any previously read TMD1 188: value: */ 189: unsigned int tme_am7990_transmit_dte_index; 190: tme_uint16_t tme_am7990_transmit_dte_tmd1; 191: 192: /* the receive buffer: */ 193: tme_uint8_t tme_am7990_receive_buffer[TME_ETHERNET_FRAME_MAX]; 194: unsigned int tme_am7990_receive_buffer_length; 195: 196: /* the receive ring: */ 197: unsigned int tme_am7990_receive_dte_index_mask; 198: tme_uint32_t tme_am7990_receive_dte_address; 199: 200: /* the current receive DTE index: */ 201: unsigned int tme_am7990_receive_dte_index; 202: 203: /* this is nonzero if the interrupt is asserted: */ 204: int tme_am7990_int_asserted; 205: 206: /* the input and output Ethernet controls: */ 207: unsigned int tme_am7990_ether_ctrl_out; 208: unsigned int tme_am7990_ether_ctrl_in; 209: }; 210: 211: /* prototypes: */ 212: static int _tme_am7990_transmit _TME_P((struct tme_ethernet_connection *, 213: tme_ethernet_fid_t *, 214: struct tme_ethernet_frame_chunk *, 215: unsigned int)); 216: 217: /* this resets the am7990: */ 218: static void 219: _tme_am7990_reset(struct tme_am7990 *am7990) 220: { 221: 222: tme_log(&am7990->tme_am7990_element->tme_element_log_handle, 223: 100, TME_OK, 224: (&am7990->tme_am7990_element->tme_element_log_handle, 225: "reset")); 226: 227: /* clear all pending callouts: */ 228: am7990->tme_am7990_callout_flags &= TME_AM7990_CALLOUTS_MASK; 229: 230: /* reset CSR0: */ 231: am7990->tme_am7990_csr0 = TME_AM7990_CSR0_STOP; 232: 233: /* reset CSR3: */ 234: am7990->tme_am7990_csrs[3] = 0; 235: 236: /* "EMBA is cleared by activation of the RESET pin or setting the 237: STOP bit." */ 238: am7990->tme_am7990_mode &= ~TME_AM7990_MODE_EMBA; 239: } 240: 241: /* this hashes an address into a TLB entry: */ 242: static struct tme_bus_tlb * 243: _tme_am7990_tlb_hash(void *_am7990, 244: tme_bus_addr_t linear_address, 245: unsigned int cycles) 246: { 247: struct tme_am7990 *am7990; 248: 249: /* recover our data structure: */ 250: am7990 = (struct tme_am7990 *) _am7990; 251: 252: /* return the TLB entry: */ 1.1.1.2 ! root 253: return (am7990->tme_am7990_tlb_hash ! 254: + ((((tme_bus_addr32_t) linear_address) >> 10) & (TME_AM7990_TLB_HASH_SIZE - 1))); 1.1 root 255: } 256: 257: /* this locks the mutex: */ 258: static void 259: _tme_am7990_lock(void *_am7990, 260: unsigned int locks) 261: { 262: struct tme_am7990 *am7990; 263: 264: /* recover our data structure: */ 265: am7990 = (struct tme_am7990 *) _am7990; 266: 267: /* lock the mutex: */ 268: tme_mutex_lock(&am7990->tme_am7990_mutex); 269: } 270: 271: /* this unlocks the mutex: */ 272: static void 273: _tme_am7990_unlock(void *_am7990, 274: unsigned int locks) 275: { 276: struct tme_am7990 *am7990; 277: 278: /* recover our data structure: */ 279: am7990 = (struct tme_am7990 *) _am7990; 280: 281: /* unlock the mutex: */ 282: tme_mutex_unlock(&am7990->tme_am7990_mutex); 283: } 284: 285: /* this does a DMA: */ 286: static int 287: _tme_am7990_dma(struct tme_am7990 *am7990, 288: tme_uint32_t callout_flags, 289: tme_uint32_t address, 290: unsigned int count, 291: tme_uint8_t *buffer) 292: { 293: int rc; 294: 295: /* make the callout: */ 296: rc = ((callout_flags & TME_AM7990_CALLOUT_DMA_READ) 297: ? tme_bus_device_dma_read_16(&am7990->tme_am7990_device, 298: address, 299: count, 300: buffer, 301: TME_AM7990_LOCKS_DEFAULT) 302: : tme_bus_device_dma_write_16(&am7990->tme_am7990_device, 303: address, 304: count, 305: buffer, 306: TME_AM7990_LOCKS_DEFAULT)); 307: 308: /* if we got a bus error: */ 309: if (rc != TME_OK) { 310: 311: /* set MERR: */ 312: am7990->tme_am7990_csr0 |= TME_AM7990_CSR0_MERR; 313: 314: /* we were cancelled: */ 315: return (TRUE); 316: } 317: 318: /* we weren't cancelled: */ 319: return (FALSE); 320: } 321: 322: /* this returns the address for a 16-bit DTE read or write: */ 323: static inline tme_uint32_t 324: _tme_am7990_dte_address(struct tme_am7990 *am7990, 325: tme_uint32_t callout_flags, 326: tme_uint32_t dte_offset) 327: { 328: tme_uint32_t dte_address; 329: tme_uint32_t dte_index; 330: tme_uint32_t dte_index_mask; 331: 332: /* get the DTE address, index, and index mask: */ 333: if (callout_flags & TME_AM7990_CALLOUT_RECEIVE) { 334: dte_address = am7990->tme_am7990_receive_dte_address; 335: dte_index = am7990->tme_am7990_receive_dte_index; 336: dte_index_mask = am7990->tme_am7990_receive_dte_index_mask; 337: } 338: else { 339: dte_address = am7990->tme_am7990_transmit_dte_address; 340: dte_index = am7990->tme_am7990_transmit_dte_index; 341: dte_index_mask = am7990->tme_am7990_transmit_dte_index_mask; 342: } 343: 344: /* get the DTE address to read or write: */ 345: dte_address 346: += (((dte_index * TME_AM7990_DTE_SIZE) 347: + dte_offset) 348: & ((dte_index_mask * TME_AM7990_DTE_SIZE) 349: | (TME_AM7990_DTE_SIZE - 1))); 350: assert ((dte_address % sizeof(tme_uint16_t)) == 0); 351: 352: return (dte_address); 353: } 354: 355: /* this does a 16-bit DTE read: */ 356: static tme_uint16_t 357: _tme_am7990_read(struct tme_am7990 *am7990, 358: tme_uint32_t callout_flags, 359: tme_uint32_t dte_offset, 360: int *_cancelled) 361: { 362: tme_uint16_t value; 363: 364: /* do the DMA read: */ 365: *_cancelled = 366: _tme_am7990_dma(am7990, 367: callout_flags, 368: _tme_am7990_dte_address(am7990, 369: callout_flags, 370: dte_offset), 371: sizeof(value), 372: (tme_uint8_t *) &value); 373: 374: /* possibly byteswap the value read: */ 375: assert (am7990->tme_am7990_device.tme_bus_device_router != NULL); 376: if (am7990->tme_am7990_device.tme_bus_device_router 377: != (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE 378: ? tme_bus_device_router_16el 379: : tme_bus_device_router_16eb)) { 380: value = tme_bswap_u16(value); 381: } 382: 383: return (value); 384: } 385: #define _tme_am7990_tx_read(am7990, dte_offset, _cancelled) \ 386: _tme_am7990_read((am7990), TME_AM7990_CALLOUT_DMA_READ, (dte_offset), (_cancelled)) 387: #define _tme_am7990_rx_read(am7990, dte_offset, _cancelled) \ 388: _tme_am7990_read((am7990), TME_AM7990_CALLOUT_DMA_READ | TME_AM7990_CALLOUT_RECEIVE, (dte_offset), (_cancelled)) 389: 390: /* this does a 16-bit DTE write: */ 391: static int 392: _tme_am7990_write(struct tme_am7990 *am7990, 393: tme_uint32_t callout_flags, 394: tme_uint32_t dte_offset, 395: tme_uint16_t value) 396: { 397: 398: /* possibly byteswap the value to write: */ 399: assert (am7990->tme_am7990_device.tme_bus_device_router != NULL); 400: if (am7990->tme_am7990_device.tme_bus_device_router 401: != (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE 402: ? tme_bus_device_router_16el 403: : tme_bus_device_router_16eb)) { 404: value = tme_bswap_u16(value); 405: } 406: 407: /* do the DMA write: */ 408: return (_tme_am7990_dma(am7990, 409: callout_flags, 410: _tme_am7990_dte_address(am7990, 411: callout_flags, 412: dte_offset), 413: sizeof(value), 414: (tme_uint8_t *) &value)); 415: } 416: #define _tme_am7990_tx_write(am7990, dte_offset, value) \ 417: _tme_am7990_write((am7990), TME_AM7990_CALLOUT_DMA_WRITE, (dte_offset), (value)) 418: #define _tme_am7990_rx_write(am7990, dte_offset, value) \ 419: _tme_am7990_write((am7990), TME_AM7990_CALLOUT_DMA_WRITE | TME_AM7990_CALLOUT_RECEIVE, (dte_offset), (value)) 420: 421: /* this initializes the am7990: */ 422: static void 423: _tme_am7990_init(struct tme_am7990 *am7990) 424: { 425: tme_uint32_t iadr; 426: int cancelled; 427: unsigned int init_i; 428: tme_uint16_t csr0; 429: tme_uint32_t drp; 430: 431: /* DMA in the initialization block: */ 432: iadr = am7990->tme_am7990_csrs[2]; 433: iadr = (iadr << 16) + am7990->tme_am7990_csrs[1]; 434: cancelled 435: = _tme_am7990_dma(am7990, 436: TME_AM7990_CALLOUT_DMA_READ, 437: iadr, 438: sizeof(am7990->tme_am7990_init), 439: (tme_uint8_t *) am7990->tme_am7990_init); 440: if (cancelled) { 441: return; 442: } 443: 444: /* possibly byteswap the 16-bit words of the initialization block: */ 445: assert (am7990->tme_am7990_device.tme_bus_device_router != NULL); 446: if (am7990->tme_am7990_device.tme_bus_device_router 447: != (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE 448: ? tme_bus_device_router_16el 449: : tme_bus_device_router_16eb)) { 450: for (init_i = 0; init_i < TME_ARRAY_ELS(am7990->tme_am7990_init); init_i++) { 451: am7990->tme_am7990_init[init_i] = tme_bswap_u16(am7990->tme_am7990_init[init_i]); 452: } 453: } 454: 455: /* the least significant byte of PADR is actually the "first" byte 456: of the Ethernet address as is is normally seen, but otherwise the 457: 16-bit words of PADR are in the correct order. so we only need 458: to swap those words into little-endian order: */ 459: (&am7990->tme_am7990_padr)[0] = tme_htole_u16((&am7990->tme_am7990_padr)[0]); 460: (&am7990->tme_am7990_padr)[1] = tme_htole_u16((&am7990->tme_am7990_padr)[1]); 461: (&am7990->tme_am7990_padr)[2] = tme_htole_u16((&am7990->tme_am7990_padr)[2]); 462: 463: tme_log(&am7990->tme_am7990_element->tme_element_log_handle, 464: 100, TME_OK, 465: (&am7990->tme_am7990_element->tme_element_log_handle, 466: "init CSR0 0x%04x IADR 0x%08x MODE 0x%04x", 467: (unsigned int) am7990->tme_am7990_csr0, 468: iadr, 469: (unsigned int) am7990->tme_am7990_mode)); 470: 471: /* get CSR0: */ 472: csr0 = am7990->tme_am7990_csr0; 473: 474: /* set IDON: */ 475: csr0 |= TME_AM7990_CSR0_IDON; 476: 477: /* "RXON is cleared when IDON is set from setting the INIT bit and 478: DRX = 1 in the MODE register" */ 479: if (am7990->tme_am7990_mode & TME_AM7990_MODE_DRX) { 480: csr0 &= ~TME_AM7990_CSR0_RXON; 481: } 482: 483: /* "TXON is cleared when IDON is set and DTX = 1 in the MODE 484: register" */ 485: if (am7990->tme_am7990_mode & TME_AM7990_MODE_DTX) { 486: csr0 &= ~TME_AM7990_CSR0_TXON; 487: } 488: 489: /* clear STOP: */ 490: csr0 &= ~TME_AM7990_CSR0_STOP; 491: 492: /* update CSR0: */ 493: am7990->tme_am7990_csr0 = csr0; 494: 495: /* call out an Ethernet configuration update: */ 496: am7990->tme_am7990_callout_flags |= TME_AM7990_CALLOUT_CONFIG; 497: 498: /* if we're not in internal loopback mode, and the Ethernet 499: connection is readable, call out an Ethernet receive: */ 500: if (!(am7990->tme_am7990_mode & TME_AM7990_MODE_INTL) 501: && (am7990->tme_am7990_ether_ctrl_in & TME_ETHERNET_CTRL_OK_READ)) { 502: am7990->tme_am7990_callout_flags |= TME_AM7990_CALLOUT_RECEIVE; 503: } 504: 505: /* initialize for the receive ring: */ 506: drp = am7990->tme_am7990_rlen_rdra; 507: drp = (drp << 16) | am7990->tme_am7990_rdra; 508: am7990->tme_am7990_receive_dte_address = drp & TME_AM7990_DRP_XDRA; 509: am7990->tme_am7990_receive_dte_index_mask = (1 << TME_FIELD_MASK_EXTRACTU(drp, TME_AM7990_DRP_XLEN_LOG2)) - 1; 510: am7990->tme_am7990_receive_dte_index = 0; 511: 512: /* initialize for the transmit ring: */ 513: drp = am7990->tme_am7990_tlen_tdra; 514: drp = (drp << 16) | am7990->tme_am7990_tdra; 515: am7990->tme_am7990_transmit_dte_address = drp & TME_AM7990_DRP_XDRA; 516: am7990->tme_am7990_transmit_dte_index_mask = (1 << TME_FIELD_MASK_EXTRACTU(drp, TME_AM7990_DRP_XLEN_LOG2)) - 1; 517: am7990->tme_am7990_transmit_dte_index = 0; 518: am7990->tme_am7990_transmit_dte_tmd1 = 0; 519: } 520: 521: /* this starts the am7990: */ 522: static void 523: _tme_am7990_start(struct tme_am7990 *am7990) 524: { 525: tme_uint16_t csr0; 526: 527: tme_log(&am7990->tme_am7990_element->tme_element_log_handle, 528: 100, TME_OK, 529: (&am7990->tme_am7990_element->tme_element_log_handle, 530: "start CSR0 0x%04x MODE 0x%04x", 531: (unsigned int) am7990->tme_am7990_csr0, 532: (unsigned int) am7990->tme_am7990_mode)); 533: 534: /* get CSR0: */ 535: csr0 = am7990->tme_am7990_csr0; 536: 537: /* "RXON is set when STRT is set if DRX = 0 in the MODE register" */ 538: if (!(am7990->tme_am7990_mode & TME_AM7990_MODE_DRX)) { 539: csr0 |= TME_AM7990_CSR0_RXON; 540: } 541: 542: /* "TXON is set when STRT is set if DTX = 0 in the MODE register" */ 543: if (!(am7990->tme_am7990_mode & TME_AM7990_MODE_DTX)) { 544: csr0 |= TME_AM7990_CSR0_TXON; 545: } 546: 547: /* clear STOP: */ 548: csr0 &= ~TME_AM7990_CSR0_STOP; 549: 550: /* update CSR0: */ 551: am7990->tme_am7990_csr0 = csr0; 552: } 553: 554: /* this scans for a start-of-packet transmit buffer owned by us: */ 555: static void 556: _tme_am7990_transmit_scan(struct tme_am7990 *am7990) 557: { 558: tme_uint16_t transmit_dte_tmd1; 559: int cancelled; 560: 561: /* if the transmitter is not on, return now: */ 562: if (!(am7990->tme_am7990_csr0 & TME_AM7990_CSR0_TXON)) { 563: return; 564: } 565: 566: /* clear TDMD: */ 567: am7990->tme_am7990_csr0 &= ~TME_AM7990_CSR0_TDMD; 568: 569: /* loop forever: */ 570: for (;;) { 571: 572: /* if we own the current transmit buffer: */ 573: transmit_dte_tmd1 = am7990->tme_am7990_transmit_dte_tmd1; 574: if (transmit_dte_tmd1 & TME_AM7990_XMD1_OWN) { 575: 576: /* if the current transmit buffer is also for the start of a 577: packet, return now: */ 578: if (transmit_dte_tmd1 & TME_AM7990_XMD1_STP) { 579: return; 580: } 581: 582: /* write TMD1 to clear OWN: */ 583: cancelled 584: = _tme_am7990_tx_write(am7990, 585: TME_AM7990_DTE_OFFSET_XMD1, 586: (transmit_dte_tmd1 587: & ~TME_AM7990_XMD1_OWN)); 588: if (cancelled) { 589: return; 590: } 591: 592: /* advance to the next transmit buffer and request a transmit 593: interrupt: */ 594: am7990->tme_am7990_transmit_dte_index 595: = ((am7990->tme_am7990_transmit_dte_index 596: + 1) 597: & am7990->tme_am7990_transmit_dte_index_mask); 598: am7990->tme_am7990_transmit_dte_tmd1 = 0; 599: am7990->tme_am7990_csr0 |= TME_AM7990_CSR0_TINT; 600: } 601: 602: /* otherwise, we must not own the current transmit buffer: */ 603: else { 604: 605: /* read TMD1: */ 606: transmit_dte_tmd1 607: = _tme_am7990_tx_read(am7990, 608: TME_AM7990_DTE_OFFSET_XMD1, 609: &cancelled); 610: if (cancelled) { 611: return; 612: } 613: am7990->tme_am7990_transmit_dte_tmd1 = transmit_dte_tmd1; 614: 615: /* if we still don't own the current transmit buffer, return now: */ 616: if (!(transmit_dte_tmd1 & TME_AM7990_XMD1_OWN)) { 617: return; 618: } 619: } 620: } 621: /* NOTREACHED */ 622: } 623: 624: /* this receives a frame: */ 625: static void 626: _tme_am7990_receive(struct tme_am7990 *am7990) 627: { 628: struct tme_ethernet_frame_chunk frame_chunk_buffer; 629: struct tme_ethernet_connection *conn_eth; 630: tme_ethernet_fid_t frame_id; 631: int resid; 632: tme_uint8_t *frame_chunk_bytes; 633: unsigned int frame_chunk_bytes_count; 634: struct tme_ethernet_header *ether_header; 635: tme_uint32_t crc32; 636: tme_uint16_t receive_dte_rmd0; 637: tme_uint16_t receive_dte_rmd1; 638: tme_uint16_t receive_dte_rmd2; 639: tme_uint16_t receive_dte_rmd1_next; 640: tme_uint32_t receive_buffer_address; 641: tme_uint16_t receive_buffer_count; 642: int cancelled; 643: int stop; 644: 645: /* assume that there is no loopback packet: */ 646: resid = 0; 647: 648: /* if we're in loopback mode: */ 649: if (am7990->tme_am7990_mode & TME_AM7990_MODE_LOOP) { 650: 651: /* get and clear any loopback packet length: */ 652: resid = am7990->tme_am7990_receive_buffer_length; 653: am7990->tme_am7990_receive_buffer_length = 0; 654: 655: /* "The C-LANCE will not receive any packets externally when it is 656: in internal loopback mode." */ 657: if (resid == 0 658: && (am7990->tme_am7990_mode & TME_AM7990_MODE_INTL)) { 659: return; 660: } 661: } 662: 663: /* if there isn't any loopback packet, and the Ethernet connection 664: is not readable, return now: */ 665: if (resid == 0 666: && !(am7990->tme_am7990_ether_ctrl_in & TME_ETHERNET_CTRL_OK_READ)) { 667: return; 668: } 669: 670: /* receive the packet into the internal buffer: */ 671: frame_chunk_buffer.tme_ethernet_frame_chunk_next = NULL; 672: frame_chunk_buffer.tme_ethernet_frame_chunk_bytes_count = sizeof(am7990->tme_am7990_receive_buffer); 673: frame_chunk_buffer.tme_ethernet_frame_chunk_bytes = &am7990->tme_am7990_receive_buffer[0]; 674: 675: /* if there isn't any loopback packet: */ 676: if (resid == 0) { 677: 678: /* assume that the Ethernet read will fail: */ 679: am7990->tme_am7990_ether_ctrl_in &= ~TME_ETHERNET_CTRL_OK_READ; 680: 681: /* get the Ethernet connection: */ 682: conn_eth = am7990->tme_am7990_eth_connection; 683: 684: /* unlock the mutex: */ 685: tme_mutex_unlock(&am7990->tme_am7990_mutex); 686: 687: /* do the callout: */ 688: resid = (conn_eth == NULL 689: ? 0 690: : ((*conn_eth->tme_ethernet_connection_read) 691: (conn_eth, 692: &frame_id, 693: &frame_chunk_buffer, 694: TME_ETHERNET_READ_NEXT))); 695: 696: /* lock the mutex: */ 697: tme_mutex_lock(&am7990->tme_am7990_mutex); 698: 699: /* if the read failed, return now: */ 700: if (resid <= 0) { 701: return; 702: } 703: 704: /* assume that the Ethernet connection is still readable: */ 705: am7990->tme_am7990_ether_ctrl_in |= TME_ETHERNET_CTRL_OK_READ; 706: 707: /* append four dummy CRC bytes: */ 708: resid = TME_MIN((unsigned int) resid + TME_ETHERNET_CRC_SIZE, 709: sizeof(am7990->tme_am7990_receive_buffer)); 710: } 711: 712: /* assume that we should callout another receive after this one: */ 713: am7990->tme_am7990_callout_flags |= TME_AM7990_CALLOUT_RECEIVE; 714: 715: /* if the receiver is not on, return now: */ 716: if (!(am7990->tme_am7990_csr0 & TME_AM7990_CSR0_RXON)) { 717: return; 718: } 719: 720: /* if this packet is not addressed to our physical address: */ 721: ether_header = (struct tme_ethernet_header *) &am7990->tme_am7990_receive_buffer[0]; 722: if (memcmp(ðer_header->tme_ethernet_header_dst[0], 723: &am7990->tme_am7990_padr, 724: TME_ETHERNET_ADDR_SIZE) != 0) { 725: 726: /* if this is not a multicast packet, return now: */ 727: if (!(ether_header->tme_ethernet_header_dst[0] & 0x1)) { 728: return; 729: } 730: 731: /* if this is not a broadcast packet: */ 732: if (memcmp(ðer_header->tme_ethernet_header_dst[0], 733: &tme_ethernet_addr_broadcast[0], 734: TME_ETHERNET_ADDR_SIZE) != 0) { 735: 736: /* calculate the CRC of the destination address: */ 737: crc32 = tme_ethernet_crc32_el(ðer_header->tme_ethernet_header_dst[0], 738: TME_ETHERNET_ADDR_SIZE); 739: 740: /* the am7990 only uses the most significant six bits of the CRC: */ 741: crc32 >>= (32 - 6); 742: 743: /* if the bit in the logical address filter is clear, return now: */ 744: if (((&am7990->tme_am7990_ladrf)[crc32 / (8 * sizeof(am7990->tme_am7990_ladrf))] 745: & TME_BIT(crc32 % (8 * sizeof(am7990->tme_am7990_ladrf)))) == 0) { 746: return; 747: } 748: } 749: } 750: 751: /* read RMD1: */ 752: receive_dte_rmd1 753: = _tme_am7990_rx_read(am7990, 754: TME_AM7990_DTE_OFFSET_XMD1, 755: &cancelled); 756: if (cancelled) { 757: return; 758: } 759: 760: /* if we don't own this receive buffer: */ 761: if (!(receive_dte_rmd1 & TME_AM7990_XMD1_OWN)) { 762: 763: if ((am7990->tme_am7990_csr0 & TME_AM7990_CSR0_MISS) == 0) { 764: tme_log(&am7990->tme_am7990_element->tme_element_log_handle, 765: 500, TME_OK, 766: (&am7990->tme_am7990_element->tme_element_log_handle, 767: "receive MISS")); 768: } 769: 770: /* set MISS in CSR0 and return now: */ 771: am7990->tme_am7990_csr0 |= TME_AM7990_CSR0_MISS; 772: return; 773: } 774: 775: /* set STP in RMD1: */ 776: receive_dte_rmd1 |= TME_AM7990_XMD1_STP; 777: 778: /* while we have bytes to write: */ 779: frame_chunk_bytes = &am7990->tme_am7990_receive_buffer[0]; 780: frame_chunk_bytes_count = resid; 781: do { 782: 783: /* read RMD0 and RMD2: */ 784: receive_dte_rmd0 785: = _tme_am7990_rx_read(am7990, 786: TME_AM7990_DTE_OFFSET_XMD0, 787: &cancelled); 788: if (cancelled) { 789: break; 790: } 791: receive_dte_rmd2 792: = _tme_am7990_rx_read(am7990, 793: TME_AM7990_DTE_OFFSET_XMD2, 794: &cancelled); 795: if (cancelled) { 796: break; 797: } 798: 799: /* get the receive buffer address and count: */ 800: receive_buffer_address = (receive_dte_rmd1 & TME_AM7990_XMD1_HADR); 801: receive_buffer_address = (receive_buffer_address << 16) + receive_dte_rmd0; 802: receive_buffer_count = (0 - receive_dte_rmd2) & TME_AM7990_XMD2_BCNT; 803: 804: /* get the count of bytes to write in this iteration: */ 805: receive_buffer_count = TME_MIN(frame_chunk_bytes_count, receive_buffer_count); 806: 807: /* do the write: */ 808: cancelled 809: = _tme_am7990_dma(am7990, 810: (TME_AM7990_CALLOUT_DMA_WRITE 811: | TME_AM7990_CALLOUT_RECEIVE), 812: receive_buffer_address, 813: receive_buffer_count, 814: frame_chunk_bytes); 815: if (cancelled) { 816: break; 817: } 818: 819: /* advance: */ 820: frame_chunk_bytes += receive_buffer_count; 821: frame_chunk_bytes_count -= receive_buffer_count; 822: 823: /* if this is the last buffer for this packet: */ 824: if (frame_chunk_bytes_count == 0) { 825: 826: /* write RMD3 to set MCNT: */ 827: cancelled 828: = _tme_am7990_rx_write(am7990, 829: TME_AM7990_DTE_OFFSET_XMD3, 830: (unsigned int) resid); 831: if (cancelled) { 832: break; 833: } 834: 835: /* set ENP in RMD1: */ 836: receive_dte_rmd1 |= TME_AM7990_XMD1_ENP; 837: 838: /* we don't read RMD1 for the next receive buffer: */ 839: receive_dte_rmd1_next = 0; 840: 841: /* stop now: */ 842: stop = TRUE; 843: } 844: 845: /* otherwise, this is not the last buffer for this packet: */ 846: else { 847: 848: /* read RMD1 for the next transmit buffer: */ 849: receive_dte_rmd1_next 850: = _tme_am7990_rx_read(am7990, 851: (TME_AM7990_DTE_SIZE 852: + TME_AM7990_DTE_OFFSET_XMD1), 853: &cancelled); 854: if (cancelled) { 855: break; 856: } 857: 858: /* if we don't own the next buffer: */ 859: stop = !(receive_dte_rmd1_next & TME_AM7990_XMD1_OWN); 860: if (stop) { 861: 862: tme_log(&am7990->tme_am7990_element->tme_element_log_handle, 863: 500, TME_OK, 864: (&am7990->tme_am7990_element->tme_element_log_handle, 865: "receive BUFF")); 866: 867: /* set BUFF and ERR in RMD1: */ 868: receive_dte_rmd1 |= TME_AM7990_RMD1_BUFF | TME_AM7990_XMD1_ERR; 869: } 870: } 871: 872: /* write RMD1 to clear OWN: */ 873: cancelled 874: = _tme_am7990_rx_write(am7990, 875: TME_AM7990_DTE_OFFSET_XMD1, 876: (receive_dte_rmd1 877: & ~TME_AM7990_XMD1_OWN)); 878: if (cancelled) { 879: break; 880: } 881: 882: /* advance to the next receive buffer: */ 883: am7990->tme_am7990_receive_dte_index 884: = ((am7990->tme_am7990_receive_dte_index 885: + 1) 886: & am7990->tme_am7990_receive_dte_index_mask); 887: receive_dte_rmd1 = receive_dte_rmd1_next; 888: } while (!stop); 889: 890: /* if nothing was cancelled: */ 891: if (!cancelled) { 892: 893: /* generate a receive interrupt: */ 894: am7990->tme_am7990_csr0 |= TME_AM7990_CSR0_RINT; 895: } 896: } 897: 898: /* the am7990 callout function. it must be called with the mutex locked: */ 899: static void 900: _tme_am7990_callout(struct tme_am7990 *am7990) 901: { 902: struct tme_ethernet_connection *conn_eth; 903: struct tme_ethernet_connection conn_eth_buffer; 904: struct tme_bus_connection *conn_bus; 905: unsigned int ctrl; 906: struct tme_ethernet_config config; 907: const tme_uint8_t *config_addrs[2]; 908: int again; 909: int rc; 910: int int_asserted; 911: 912: /* if this function is already running in another thread, simply 913: return now. the other thread will do our work: */ 914: if (am7990->tme_am7990_callout_flags & TME_AM7990_CALLOUTS_RUNNING) { 915: return; 916: } 917: 918: /* callouts are now running: */ 919: am7990->tme_am7990_callout_flags |= TME_AM7990_CALLOUTS_RUNNING; 920: 921: /* loop while we have work to do: */ 922: do { 923: again = FALSE; 924: 925: /* if we need to do a transmit scan: */ 926: if (am7990->tme_am7990_callout_flags & TME_AM7990_CALLOUT_TRANSMIT_SCAN) { 927: again = TRUE; 928: 929: /* clear the callout flag: */ 930: am7990->tme_am7990_callout_flags &= ~TME_AM7990_CALLOUT_TRANSMIT_SCAN; 931: 932: /* do the transmit scan: */ 933: _tme_am7990_transmit_scan(am7990); 934: } 935: 936: /* form our ctrl: */ 937: ctrl = 0; 938: 939: /* if the transmitter is on and the next transmit buffer is for 940: the start of a packet and is owned by us, we are readable: */ 941: if ((am7990->tme_am7990_csr0 942: & TME_AM7990_CSR0_TXON) 943: && ((am7990->tme_am7990_transmit_dte_tmd1 944: & (TME_AM7990_XMD1_OWN 945: | TME_AM7990_XMD1_STP)) 946: == (TME_AM7990_XMD1_OWN 947: | TME_AM7990_XMD1_STP))) { 948: ctrl |= TME_ETHERNET_CTRL_OK_READ; 949: } 950: 951: /* if we are readable and in loopback mode: */ 952: if ((ctrl & TME_ETHERNET_CTRL_OK_READ) 953: && (am7990->tme_am7990_mode & TME_AM7990_MODE_LOOP)) { 954: again = TRUE; 955: 956: /* unlock the mutex: */ 957: tme_mutex_unlock(&am7990->tme_am7990_mutex); 958: 959: /* call out a loopback transmit: */ 960: conn_eth_buffer.tme_ethernet_connection.tme_connection_element = am7990->tme_am7990_element; 961: _tme_am7990_transmit(&conn_eth_buffer, 962: NULL, 963: NULL, 964: 0); 965: 966: /* lock the mutex: */ 967: tme_mutex_lock(&am7990->tme_am7990_mutex); 968: 969: /* don't call out any new control information for now: */ 970: ctrl = am7990->tme_am7990_ether_ctrl_out; 971: } 972: 973: /* if we need to call out new control information: */ 974: if (am7990->tme_am7990_ether_ctrl_out != ctrl) { 975: again = TRUE; 976: 977: /* note the new state of the called-out control information: */ 978: am7990->tme_am7990_ether_ctrl_out = ctrl; 979: 980: /* get this card's connection: */ 981: conn_eth = am7990->tme_am7990_eth_connection; 982: 983: /* unlock the mutex: */ 984: tme_mutex_unlock(&am7990->tme_am7990_mutex); 985: 986: /* do the callout: */ 987: rc = (conn_eth != NULL 988: ? ((*conn_eth->tme_ethernet_connection_ctrl) 989: (conn_eth, 990: ctrl)) 991: : TME_OK); 992: assert (rc == TME_OK); 993: 994: /* lock the mutex: */ 995: tme_mutex_lock(&am7990->tme_am7990_mutex); 996: } 997: 998: /* if we need to call out new config information: */ 999: if (am7990->tme_am7990_callout_flags & TME_AM7990_CALLOUT_CONFIG) { 1000: again = TRUE; 1001: 1002: /* clear the callout flag: */ 1003: am7990->tme_am7990_callout_flags &= ~TME_AM7990_CALLOUT_CONFIG; 1004: 1005: /* form the new config: */ 1006: memset(&config, 0, sizeof(config)); 1007: 1008: /* if we're in promiscuous mode or any bits the logical address 1009: filter are nonzero: */ 1010: if ((am7990->tme_am7990_mode & TME_AM7990_MODE_PROM) 1011: || (&am7990->tme_am7990_ladrf)[0] 1012: || (&am7990->tme_am7990_ladrf)[1] 1013: || (&am7990->tme_am7990_ladrf)[2] 1014: || (&am7990->tme_am7990_ladrf)[3]) { 1015: 1016: /* we have to be in promiscuous mode: */ 1017: config.tme_ethernet_config_flags |= TME_ETHERNET_CONFIG_PROMISC; 1018: } 1019: 1020: /* otherwise, we only need to see packets addressed to our 1021: physical address, and broadcast packets: */ 1022: else { 1023: 1024: /* our Ethernet addresses: */ 1025: config.tme_ethernet_config_addr_count = 2; 1026: config_addrs[0] = (tme_uint8_t *) &am7990->tme_am7990_padr; 1027: config_addrs[1] = &tme_ethernet_addr_broadcast[0]; 1028: config.tme_ethernet_config_addrs = config_addrs; 1029: } 1030: 1031: /* get this card's connection: */ 1032: conn_eth = am7990->tme_am7990_eth_connection; 1033: 1034: /* unlock the mutex: */ 1035: tme_mutex_unlock(&am7990->tme_am7990_mutex); 1036: 1037: /* do the callout: */ 1038: rc = (conn_eth == NULL 1039: ? TME_OK 1040: : ((*conn_eth->tme_ethernet_connection_config) 1041: (conn_eth, 1042: &config))); 1043: assert (rc == TME_OK); 1044: 1045: /* lock the mutex: */ 1046: tme_mutex_lock(&am7990->tme_am7990_mutex); 1047: } 1048: 1049: /* if we need to receive a frame: */ 1050: if (am7990->tme_am7990_callout_flags & TME_AM7990_CALLOUT_RECEIVE) { 1051: again = TRUE; 1052: 1053: /* clear the callout flag: */ 1054: am7990->tme_am7990_callout_flags &= ~TME_AM7990_CALLOUT_RECEIVE; 1055: 1056: /* do the receive: */ 1057: _tme_am7990_receive(am7990); 1058: } 1059: 1060: /* if we need to call out an interrupt: */ 1061: if (am7990->tme_am7990_csr0 1062: & (TME_AM7990_CSR0_TINT 1063: | TME_AM7990_CSR0_BABL 1064: | TME_AM7990_CSR0_MISS 1065: | TME_AM7990_CSR0_MERR 1066: | TME_AM7990_CSR0_RINT 1067: | TME_AM7990_CSR0_TINT 1068: | TME_AM7990_CSR0_IDON)) { 1069: am7990->tme_am7990_csr0 |= TME_AM7990_CSR0_INTR; 1070: } 1071: else { 1072: am7990->tme_am7990_csr0 &= ~TME_AM7990_CSR0_INTR; 1073: } 1074: int_asserted 1075: = ((am7990->tme_am7990_csr0 1076: & (TME_AM7990_CSR0_INTR 1077: | TME_AM7990_CSR0_INEA)) 1078: == (TME_AM7990_CSR0_INTR 1079: | TME_AM7990_CSR0_INEA)); 1080: if (!!am7990->tme_am7990_int_asserted != int_asserted) { 1081: again = TRUE; 1082: 1083: /* note the new state of the interrupt signal: */ 1084: am7990->tme_am7990_int_asserted = int_asserted; 1085: 1086: /* get our bus connection: */ 1087: conn_bus = tme_memory_atomic_pointer_read(struct tme_bus_connection *, 1088: am7990->tme_am7990_device.tme_bus_device_connection, 1089: &am7990->tme_am7990_device.tme_bus_device_connection_rwlock); 1090: 1091: /* unlock our mutex: */ 1092: tme_mutex_unlock(&am7990->tme_am7990_mutex); 1093: 1094: /* call out the bus interrupt signal edge: */ 1095: rc = (*conn_bus->tme_bus_signal) 1096: (conn_bus, 1097: TME_BUS_SIGNAL_INT_UNSPEC 1098: | (int_asserted 1099: ? TME_BUS_SIGNAL_LEVEL_ASSERTED 1100: : TME_BUS_SIGNAL_LEVEL_NEGATED)); 1101: assert (rc == TME_OK); 1102: 1103: /* lock our mutex: */ 1104: tme_mutex_lock(&am7990->tme_am7990_mutex); 1105: } 1106: } while (again); 1107: 1108: /* clear that callouts are running: */ 1109: am7990->tme_am7990_callout_flags &= ~TME_AM7990_CALLOUTS_RUNNING; 1110: } 1111: 1112: /* the am7990 bus signal handler: */ 1113: static int 1114: _tme_am7990_signal(void *_am7990, 1115: unsigned int signal) 1116: { 1117: struct tme_am7990 *am7990; 1118: unsigned int level; 1119: 1120: /* recover our data structure: */ 1121: am7990 = (struct tme_am7990 *) _am7990; 1122: 1123: /* lock the mutex: */ 1124: tme_mutex_lock(&am7990->tme_am7990_mutex); 1125: 1126: /* take out the signal level: */ 1127: level = signal & TME_BUS_SIGNAL_LEVEL_MASK; 1128: signal = TME_BUS_SIGNAL_WHICH(signal); 1129: 1130: /* dispatch on the generic bus signals: */ 1131: switch (signal) { 1132: case TME_BUS_SIGNAL_RESET: 1133: if (level == TME_BUS_SIGNAL_LEVEL_ASSERTED) { 1134: _tme_am7990_reset(am7990); 1135: } 1136: break; 1137: default: 1138: signal = TME_BUS_SIGNAL_IGNORE; 1139: break; 1140: } 1141: 1142: /* if we didn't ignore this bus signal: */ 1143: if (signal != TME_BUS_SIGNAL_IGNORE) { 1144: 1145: /* make any new callouts: */ 1146: _tme_am7990_callout(am7990); 1147: } 1148: 1149: /* unlock the mutex: */ 1150: tme_mutex_unlock(&am7990->tme_am7990_mutex); 1151: 1152: /* no faults: */ 1153: return (TME_OK); 1154: } 1155: 1156: /* this is called when a device changes its configuration: */ 1157: static int 1158: _tme_am7990_config(struct tme_ethernet_connection *conn_eth, 1159: struct tme_ethernet_config *config) 1160: { 1161: /* we don't care when other devices on the Ethernet 1162: reconfigure themselves: */ 1163: return (TME_OK); 1164: } 1165: 1166: /* this is called when control lines change: */ 1167: static int 1168: _tme_am7990_ctrl(struct tme_ethernet_connection *conn_eth, 1169: unsigned int ctrl) 1170: { 1171: struct tme_am7990 *am7990; 1172: 1173: /* recover our data structures: */ 1174: am7990 = conn_eth->tme_ethernet_connection.tme_connection_element->tme_element_private; 1175: 1176: /* lock the mutex: */ 1177: tme_mutex_lock(&am7990->tme_am7990_mutex); 1178: 1179: /* note the new state of the controls: */ 1180: am7990->tme_am7990_ether_ctrl_in = ctrl; 1181: 1182: /* if this connection is readable, call out a read: */ 1183: if (ctrl & TME_ETHERNET_CTRL_OK_READ) { 1184: am7990->tme_am7990_callout_flags |= TME_AM7990_CALLOUT_RECEIVE; 1185: } 1186: 1187: /* make any new callouts: */ 1188: _tme_am7990_callout(am7990); 1189: 1190: /* unlock the mutex: */ 1191: tme_mutex_unlock(&am7990->tme_am7990_mutex); 1192: 1193: return (TME_OK); 1194: } 1195: 1196: /* this transmits a frame: */ 1197: static int 1198: _tme_am7990_transmit(struct tme_ethernet_connection *conn_eth, 1199: tme_ethernet_fid_t *_frame_id, 1200: struct tme_ethernet_frame_chunk *frame_chunk, 1201: unsigned int flags) 1202: { 1203: struct tme_am7990 *am7990; 1204: struct tme_ethernet_frame_chunk frame_chunk_buffer; 1205: tme_uint8_t frame_chunk_bytes_buffer[32]; 1206: tme_uint8_t *frame_chunk_bytes; 1207: unsigned int frame_chunk_bytes_count; 1208: tme_uint16_t transmit_dte_tmd0; 1209: tme_uint16_t transmit_dte_tmd1; 1210: tme_uint16_t transmit_dte_tmd2; 1211: tme_uint16_t transmit_dte_tmd1_next; 1212: tme_uint32_t transmit_buffer_address; 1213: tme_uint16_t transmit_buffer_count; 1214: unsigned int count; 1215: int rc; 1216: int add_fcs; 1217: int stop; 1218: int cancelled; 1219: 1220: /* recover our data structures: */ 1221: am7990 = conn_eth->tme_ethernet_connection.tme_connection_element->tme_element_private; 1222: 1223: /* lock our mutex: */ 1224: tme_mutex_lock(&am7990->tme_am7990_mutex); 1225: 1226: /* assume that we will have no packet to transmit: */ 1227: rc = 0; 1228: 1229: /* if the transmitter is on, and the current transmit buffer is for 1230: the start of a packet and is owned by us: */ 1231: if ((am7990->tme_am7990_csr0 1232: & TME_AM7990_CSR0_TXON) 1233: && ((am7990->tme_am7990_transmit_dte_tmd1 1234: & (TME_AM7990_XMD1_OWN 1235: | TME_AM7990_XMD1_STP)) 1236: == (TME_AM7990_XMD1_OWN 1237: | TME_AM7990_XMD1_STP))) { 1238: 1239: /* see if we will add the FCS to this transmitted packet. 1240: "ADD_FCS is only valid when STP=1." */ 1241: add_fcs = 1242: (!(am7990->tme_am7990_mode 1243: & TME_AM7990_MODE_DTCR) 1244: || (am7990->tme_am7990_transmit_dte_tmd1 1245: & TME_AM7990_TMD1_ADD_FCS)); 1246: 1247: /* if we're in loopback mode, transmit this packet directly into 1248: the receive buffer: */ 1249: if (am7990->tme_am7990_mode & TME_AM7990_MODE_LOOP) { 1250: frame_chunk_buffer.tme_ethernet_frame_chunk_bytes = &am7990->tme_am7990_receive_buffer[0]; 1251: frame_chunk_buffer.tme_ethernet_frame_chunk_bytes_count = sizeof(am7990->tme_am7990_receive_buffer); 1252: frame_chunk_buffer.tme_ethernet_frame_chunk_next = NULL; 1253: frame_chunk = &frame_chunk_buffer; 1254: } 1255: 1256: do { 1257: 1258: /* recover the previously read TMD1: */ 1259: transmit_dte_tmd1 = am7990->tme_am7990_transmit_dte_tmd1; 1260: 1261: /* read TMD0 and TMD2: */ 1262: transmit_dte_tmd0 1263: = _tme_am7990_tx_read(am7990, 1264: TME_AM7990_DTE_OFFSET_XMD0, 1265: &cancelled); 1266: if (cancelled) { 1267: break; 1268: } 1269: transmit_dte_tmd2 1270: = _tme_am7990_tx_read(am7990, 1271: TME_AM7990_DTE_OFFSET_XMD2, 1272: &cancelled); 1273: if (cancelled) { 1274: break; 1275: } 1276: 1277: /* get the transmit buffer address and count: */ 1278: transmit_buffer_address = (transmit_dte_tmd1 & TME_AM7990_XMD1_HADR); 1279: transmit_buffer_address = (transmit_buffer_address << 16) + transmit_dte_tmd0; 1280: transmit_buffer_count = (0 - transmit_dte_tmd2) & TME_AM7990_XMD2_BCNT; 1281: 1282: /* read this transmit buffer into the frame chunks: */ 1283: frame_chunk_bytes = NULL; 1284: frame_chunk_bytes_count = 0; 1285: for (; transmit_buffer_count > 0; ) { 1286: 1287: /* if we have exhausted the previous chunk: */ 1288: if (frame_chunk_bytes_count == 0) { 1289: 1290: /* advance to the next chunk: */ 1291: if (frame_chunk == NULL) { 1292: frame_chunk_bytes = &frame_chunk_bytes_buffer[0]; 1293: frame_chunk_bytes_count = sizeof(frame_chunk_bytes_buffer); 1294: } 1295: else { 1296: frame_chunk_bytes = frame_chunk->tme_ethernet_frame_chunk_bytes; 1297: frame_chunk_bytes_count = frame_chunk->tme_ethernet_frame_chunk_bytes_count; 1298: frame_chunk = frame_chunk->tme_ethernet_frame_chunk_next; 1299: continue; 1300: } 1301: } 1302: 1303: /* get the count of bytes to read in this iteration: */ 1304: count = TME_MIN(frame_chunk_bytes_count, transmit_buffer_count); 1305: 1306: /* do the read: */ 1307: cancelled 1308: = _tme_am7990_dma(am7990, 1309: TME_AM7990_CALLOUT_DMA_READ, 1310: transmit_buffer_address, 1311: count, 1312: frame_chunk_bytes); 1313: if (cancelled) { 1314: break; 1315: } 1316: 1317: /* advance: */ 1318: frame_chunk_bytes += count; 1319: frame_chunk_bytes_count -= count; 1320: transmit_buffer_address += count; 1321: transmit_buffer_count -= count; 1322: rc += count; 1323: } 1324: if (cancelled) { 1325: break; 1326: } 1327: 1328: /* if this is the last transmit buffer in the packet: */ 1329: if (transmit_dte_tmd1 & TME_AM7990_XMD1_ENP) { 1330: 1331: /* we can't suppress CRC generation: */ 1332: if (!add_fcs) { 1333: abort(); 1334: } 1335: 1336: /* clear TMD1 for the next transmit buffer: */ 1337: transmit_dte_tmd1_next = 0; 1338: 1339: /* this is the last transmit buffer: */ 1340: stop = TRUE; 1341: } 1342: 1343: /* otherwise, this is not the last transmit buffer in the packet: */ 1344: else { 1345: 1346: /* read TMD1 for the next transmit buffer: */ 1347: transmit_dte_tmd1_next 1348: = _tme_am7990_tx_read(am7990, 1349: (TME_AM7990_DTE_SIZE 1350: + TME_AM7990_DTE_OFFSET_XMD1), 1351: &cancelled); 1352: if (cancelled) { 1353: break; 1354: } 1355: 1356: /* if we don't own the next transmit buffer: */ 1357: stop = !(transmit_dte_tmd1_next & TME_AM7990_XMD1_OWN); 1358: if (stop) { 1359: 1360: tme_log(&am7990->tme_am7990_element->tme_element_log_handle, 1361: 500, TME_OK, 1362: (&am7990->tme_am7990_element->tme_element_log_handle, 1363: "transmit BUFF")); 1364: 1365: /* write a TMD3 with BUFF set: */ 1366: cancelled 1367: = _tme_am7990_tx_write(am7990, 1368: TME_AM7990_DTE_OFFSET_XMD3, 1369: TME_AM7990_TMD3_BUFF); 1370: if (cancelled) { 1371: break; 1372: } 1373: 1374: /* turn off the transmitter: */ 1375: am7990->tme_am7990_csr0 &= ~TME_AM7990_CSR0_TXON; 1376: } 1377: } 1378: 1379: /* write TMD1 to clear OWN: */ 1380: cancelled 1381: = _tme_am7990_tx_write(am7990, 1382: TME_AM7990_DTE_OFFSET_XMD1, 1383: (transmit_dte_tmd1 1384: & ~TME_AM7990_XMD1_OWN)); 1385: if (cancelled) { 1386: break; 1387: } 1388: 1389: /* advance to the next transmit buffer: */ 1390: am7990->tme_am7990_transmit_dte_index 1391: = ((am7990->tme_am7990_transmit_dte_index 1392: + 1) 1393: & am7990->tme_am7990_transmit_dte_index_mask); 1394: am7990->tme_am7990_transmit_dte_tmd1 = transmit_dte_tmd1_next; 1395: } while (!stop); 1396: 1397: /* if nothing was cancelled: */ 1398: if (!cancelled) { 1399: 1400: /* generate a transmit interrupt: */ 1401: am7990->tme_am7990_csr0 |= TME_AM7990_CSR0_TINT; 1402: } 1403: } 1404: 1405: /* if we're in loopback mode: */ 1406: if (am7990->tme_am7990_mode & TME_AM7990_MODE_LOOP) { 1407: 1408: /* if we have a loopback packet: */ 1409: if (rc > 0) { 1410: 1411: /* append the CRC bytes: */ 1412: if ((rc + sizeof(tme_uint32_t)) > sizeof(am7990->tme_am7990_receive_buffer)) { 1413: abort(); 1414: } 1415: rc += sizeof(tme_uint32_t); 1416: 1417: /* set the receive buffer length: */ 1418: am7990->tme_am7990_receive_buffer_length = rc; 1419: } 1420: 1421: /* if we have a loopback packet, call out a receive: */ 1422: if (am7990->tme_am7990_receive_buffer_length > 0) { 1423: am7990->tme_am7990_callout_flags |= TME_AM7990_CALLOUT_RECEIVE; 1424: } 1425: } 1426: 1427: /* otherwise, if we're not returning a packet: */ 1428: else if (rc <= 0) { 1429: 1430: /* we aren't considered readable any more: */ 1431: am7990->tme_am7990_ether_ctrl_out &= ~TME_ETHERNET_CTRL_OK_READ; 1432: } 1433: 1434: /* start a scan for the first buffer in the next packet to transmit: */ 1435: am7990->tme_am7990_callout_flags |= TME_AM7990_CALLOUT_TRANSMIT_SCAN; 1436: 1437: /* make any new callouts: */ 1438: _tme_am7990_callout(am7990); 1439: 1440: /* unlock our mutex: */ 1441: tme_mutex_unlock(&am7990->tme_am7990_mutex); 1442: 1443: /* done: */ 1444: return (rc); 1445: 1446: /* unused: */ 1447: _frame_id = 0; 1448: flags = 0; 1449: } 1450: 1451: /* the am7990 descriptor polling thread: */ 1452: static void 1453: _tme_am7990_poll_th(struct tme_am7990 *am7990) 1454: { 1455: 1456: /* lock our mutex: */ 1457: tme_mutex_lock(&am7990->tme_am7990_mutex); 1458: 1459: /* loop forever: */ 1460: for (;;) { 1461: 1462: /* call out a transmit scan: */ 1463: am7990->tme_am7990_callout_flags |= TME_AM7990_CALLOUT_TRANSMIT_SCAN; 1464: 1465: /* make any callouts: */ 1466: _tme_am7990_callout(am7990); 1467: 1468: /* unlock our mutex: */ 1469: tme_mutex_unlock(&am7990->tme_am7990_mutex); 1470: 1471: /* "[T]he C-LANCE will automatically poll the transmit ring in the 1472: memory once it has started .. every 1.6ms" */ 1473: tme_thread_sleep_yield(0, 16000); 1474: 1475: /* lock our mutex: */ 1476: tme_mutex_unlock(&am7990->tme_am7990_mutex); 1477: } 1478: /* NOTREACHED */ 1479: } 1480: 1481: /* the am7990 bus cycle handler: */ 1482: static int 1483: _tme_am7990_bus_cycle(void *_am7990, struct tme_bus_cycle *cycle_init) 1484: { 1485: struct tme_am7990 *am7990; 1.1.1.2 ! root 1486: tme_bus_addr32_t address, am7990_address_last; 1.1 root 1487: tme_uint16_t value; 1488: tme_uint32_t reg; 1489: tme_uint16_t csr0_old; 1490: tme_uint16_t csr0_new; 1491: tme_uint8_t port_init; 1492: unsigned int routing_index; 1493: 1494: /* recover our data structure: */ 1495: am7990 = (struct tme_am7990 *) _am7990; 1496: 1497: /* the address must be within range: */ 1498: am7990_address_last = am7990->tme_am7990_device.tme_bus_device_address_last; 1499: assert(cycle_init->tme_bus_cycle_address <= am7990_address_last); 1500: assert(cycle_init->tme_bus_cycle_size <= (am7990_address_last - cycle_init->tme_bus_cycle_address) + 1); 1501: 1502: /* get the register being accessed: */ 1503: address = cycle_init->tme_bus_cycle_address; 1504: reg = (address & ((am7990_address_last + 1) / 2)); 1505: 1506: /* save the initiator's port description: */ 1507: port_init = cycle_init->tme_bus_cycle_port; 1508: 1509: /* lock the mutex: */ 1510: tme_mutex_lock(&am7990->tme_am7990_mutex); 1511: 1512: /* if this is a write: */ 1513: if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) { 1514: 1515: /* run the bus cycle: */ 1516: tme_bus_cycle_xfer_reg(cycle_init, 1517: &value, 1518: TME_BUS16_LOG2); 1519: 1520: /* if this was a write to the RAP: */ 1521: if (reg == am7990->tme_am7990_offset_rap) { 1522: 1523: /* set the new RAP: */ 1524: am7990->tme_am7990_rap = value % TME_ARRAY_ELS(am7990->tme_am7990_csrs); 1525: } 1526: 1527: /* otherwise, this was a write to the RDP: */ 1528: else { 1529: assert (reg == am7990->tme_am7990_offset_rdp); 1530: 1531: /* if this is a write to CSR0: */ 1532: if (am7990->tme_am7990_rap == 0) { 1533: 1534: /* get the previous value of CSR0: */ 1535: csr0_old = am7990->tme_am7990_csr0; 1536: 1537: /* handle the read-only, write-1-to-clear, and write-1-only 1538: bits: */ 1539: csr0_new = ((value & ~TME_AM7990_CSR0_READ_ONLY) 1540: | (csr0_old 1541: & (TME_AM7990_CSR0_READ_ONLY 1542: | TME_AM7990_CSR0_WRITE_ONE_ONLY))); 1543: csr0_new = ((csr0_new ^ TME_AM7990_CSR0_WRITE_ONE_TO_CLEAR) 1544: & (csr0_old | ~TME_AM7990_CSR0_WRITE_ONE_TO_CLEAR)); 1545: 1546: /* update ERR: */ 1547: csr0_new &= ~TME_AM7990_CSR0_ERR; 1548: if (csr0_new 1549: & (TME_AM7990_CSR0_BABL 1550: | TME_AM7990_CSR0_CERR 1551: | TME_AM7990_CSR0_MISS 1552: | TME_AM7990_CSR0_MERR)) { 1553: csr0_new |= TME_AM7990_CSR0_ERR; 1554: } 1555: 1556: /* set the initial new CSR0 value: */ 1557: am7990->tme_am7990_csr0 = csr0_new; 1558: 1559: /* "If STRT, INIT and STOP are all set together, STOP will 1560: override the other bits and only STOP will be set." */ 1561: if (value & TME_AM7990_CSR0_STOP) { 1562: 1563: /* reset the am7990: */ 1564: _tme_am7990_reset(am7990); 1565: } 1566: 1567: /* otherwise, STOP is not set in the new CSR0 value: */ 1568: else { 1569: 1570: /* if INIT is set in the CSR0 value written, and STOP is set 1571: in the old CSR0 value: */ 1572: if ((value & TME_AM7990_CSR0_INIT) 1573: && (csr0_old & TME_AM7990_CSR0_STOP)) { 1574: 1575: /* run the initialization procedure: */ 1576: _tme_am7990_init(am7990); 1577: } 1578: 1579: /* if STRT is set in the CSR0 value written, and STRT is not 1580: set in the old CSR0 value: */ 1581: if ((value & TME_AM7990_CSR0_STRT) 1582: && !(csr0_old & TME_AM7990_CSR0_STRT)) { 1583: 1584: /* start the am7990: */ 1585: _tme_am7990_start(am7990); 1586: } 1587: 1588: /* if TDMD is set in the CSR0 value written, call out a 1589: transmit scan: */ 1590: if (value & TME_AM7990_CSR0_TDMD) { 1591: am7990->tme_am7990_callout_flags |= TME_AM7990_CALLOUT_TRANSMIT_SCAN; 1592: } 1593: } 1594: } 1595: 1596: /* otherwise, this is writing another CSR: */ 1597: else { 1598: 1599: tme_log(&am7990->tme_am7990_element->tme_element_log_handle, 1600: 100, TME_OK, 1601: (&am7990->tme_am7990_element->tme_element_log_handle, 1602: "CSR%u <- 0x%04x", 1603: am7990->tme_am7990_rap, 1604: value)); 1605: 1606: am7990->tme_am7990_csrs[am7990->tme_am7990_rap] = value; 1607: } 1608: } 1609: } 1610: 1611: /* otherwise, this is a read: */ 1612: else { 1613: assert (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_READ); 1614: 1615: /* get the value to read: */ 1616: if (reg == am7990->tme_am7990_offset_rap) { 1617: value = am7990->tme_am7990_rap; 1618: } 1619: else { 1620: assert (reg == am7990->tme_am7990_offset_rdp); 1621: value = am7990->tme_am7990_csrs[am7990->tme_am7990_rap]; 1622: } 1623: 1624: /* run the bus cycle: */ 1625: tme_bus_cycle_xfer_reg(cycle_init, 1626: &value, 1627: TME_BUS16_LOG2); 1628: } 1629: 1630: /* NB: the generic memory implementation doesn't know its own port 1631: size or endianness, and instead just follows the endianness of 1632: whatever reads and writes it (see tme_bus_cycle_xfer_memory()). 1633: this is sort of a fragile system, but does allow the same generic 1634: memory implementation to work with all kinds of CPU emulations. 1635: 1636: the fragility shows with a chip like the am7990. for all of its 1637: non-Ethernet data bus mastering, the real chip doesn't need to 1638: know memory's endianness; it just reads a 16-bit quantity from a 1639: 16-bit aligned address and expects that the most-significant 1640: eight bits will be on D8..D15. but since the memory doesn't know 1641: its own endianness, we have to use a bus routing that matches the 1642: endianness of the bus routing used by the CPU that wrote the 1643: memory. 1644: 1645: fortunately, we can learn the endianness of the CPU when it reads 1646: or writes us. we do this here: */ 1647: if (am7990->tme_am7990_device.tme_bus_device_router == NULL) { 1648: 1649: /* get the index into the bus routing used by the initiator for 1650: this cycle. if the initiator's least lane is zero, then this 1651: is also a lane number: */ 1652: routing_index 1653: = (TME_BUS_CYCLE_PORT_LANE_LEAST(cycle_init->tme_bus_cycle_port) 1654: - TME_BUS_CYCLE_PORT_LANE_LEAST(port_init)); 1655: 1656: /* if the initiator routed a byte from a lower address to the byte 1657: lane of lesser significance, then we assume that memory is 1658: little-endian: */ 1659: am7990->tme_am7990_device.tme_bus_device_router 1660: = ((cycle_init->tme_bus_cycle_lane_routing[routing_index + 0] 1661: < cycle_init->tme_bus_cycle_lane_routing[routing_index + 1]) 1662: ? tme_bus_device_router_16el 1663: : tme_bus_device_router_16eb); 1664: } 1665: 1666: /* make any new callouts: */ 1667: _tme_am7990_callout(am7990); 1668: 1669: /* unlock the mutex: */ 1670: tme_mutex_unlock(&am7990->tme_am7990_mutex); 1671: 1672: /* no faults: */ 1673: return (TME_OK); 1674: } 1675: 1676: /* the am7990 TLB filler: */ 1677: static int 1678: _tme_am7990_tlb_fill(void *_am7990, 1679: struct tme_bus_tlb *tlb, 1680: tme_bus_addr_t address, 1681: unsigned int cycles) 1682: { 1683: struct tme_am7990 *am7990; 1.1.1.2 ! root 1684: tme_bus_addr32_t am7990_address_last; 1.1 root 1685: 1686: /* recover our data structure: */ 1687: am7990 = (struct tme_am7990 *) _am7990; 1688: 1689: /* the address must be within range: */ 1690: am7990_address_last = am7990->tme_am7990_device.tme_bus_device_address_last; 1691: assert(address <= am7990_address_last); 1692: 1693: /* initialize the TLB entry: */ 1694: tme_bus_tlb_initialize(tlb); 1695: 1696: /* this TLB entry can cover the whole device: */ 1697: tlb->tme_bus_tlb_addr_first = 0; 1698: tlb->tme_bus_tlb_addr_last = am7990_address_last; 1699: 1700: /* allow reading and writing: */ 1701: tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE; 1702: 1703: /* our bus cycle handler: */ 1704: tlb->tme_bus_tlb_cycle_private = am7990; 1705: tlb->tme_bus_tlb_cycle = _tme_am7990_bus_cycle; 1706: 1707: return (TME_OK); 1708: } 1709: 1710: /* this makes a new Ethernet connection: */ 1711: static int 1712: _tme_am7990_connection_make_eth(struct tme_connection *conn, unsigned int state) 1713: { 1714: struct tme_am7990 *am7990; 1715: struct tme_ethernet_connection *conn_eth; 1716: struct tme_ethernet_connection *conn_eth_other; 1717: 1718: /* recover our data structures: */ 1719: am7990 = conn->tme_connection_element->tme_element_private; 1720: conn_eth = (struct tme_ethernet_connection *) conn; 1721: conn_eth_other = (struct tme_ethernet_connection *) conn->tme_connection_other; 1722: 1723: /* both sides must be Ethernet connections: */ 1724: assert(conn->tme_connection_type == TME_CONNECTION_ETHERNET); 1725: assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_ETHERNET); 1726: 1727: /* we're always set up to answer calls across the connection, so we 1728: only have to do work when the connection has gone full, namely 1729: taking the other side of the connection: */ 1730: if (state == TME_CONNECTION_FULL) { 1731: 1732: /* lock our mutex: */ 1733: tme_mutex_lock(&am7990->tme_am7990_mutex); 1734: 1735: /* save our connection: */ 1736: am7990->tme_am7990_eth_connection = conn_eth_other; 1737: 1738: /* unlock our mutex: */ 1739: tme_mutex_unlock(&am7990->tme_am7990_mutex); 1740: } 1741: 1742: return (TME_OK); 1743: } 1744: 1745: /* this makes a new bus connection: */ 1746: static int 1747: _tme_am7990_connection_make_bus(struct tme_connection *conn, 1748: unsigned int state) 1749: { 1750: struct tme_am7990 *am7990; 1751: struct tme_bus_connection *conn_bus; 1752: int rc; 1753: 1754: /* recover our data structure: */ 1755: am7990 = conn->tme_connection_element->tme_element_private; 1756: 1757: /* call the bus device connection maker: */ 1758: rc = tme_bus_device_connection_make(conn, state); 1759: 1760: /* if the full connection was successful, and we don't have a TLB 1761: hash yet, allocate it: */ 1762: if (rc == TME_OK 1763: && state == TME_CONNECTION_FULL 1.1.1.2 ! root 1764: && !am7990->tme_am7990_tlb_hash_added) { 1.1 root 1765: 1766: /* get our bus connection: */ 1767: conn_bus 1768: = tme_memory_atomic_pointer_read(struct tme_bus_connection *, 1769: am7990->tme_am7990_device.tme_bus_device_connection, 1770: &am7990->tme_am7990_device.tme_bus_device_connection_rwlock); 1771: 1.1.1.2 ! root 1772: /* add the TLB set: */ ! 1773: rc = tme_bus_device_tlb_set_add(&am7990->tme_am7990_device, ! 1774: TME_AM7990_TLB_HASH_SIZE, ! 1775: am7990->tme_am7990_tlb_hash); 1.1 root 1776: assert (rc == TME_OK); 1.1.1.2 ! root 1777: am7990->tme_am7990_tlb_hash_added = TRUE; 1.1 root 1778: } 1779: 1780: return (rc); 1781: } 1782: 1783: /* this breaks a connection: */ 1784: static int 1785: _tme_am7990_connection_break(struct tme_connection *conn, unsigned int state) 1786: { 1787: abort(); 1788: } 1789: 1790: /* this makes a new connection side for a am7990: */ 1791: static int 1792: _tme_am7990_connections_new(struct tme_element *element, 1793: const char * const *args, 1794: struct tme_connection **_conns, 1795: char **_output) 1796: { 1797: struct tme_am7990 *am7990; 1798: struct tme_ethernet_connection *conn_eth; 1799: struct tme_connection *conn; 1800: int rc; 1801: 1802: /* recover our data structure: */ 1803: am7990 = (struct tme_am7990 *) element->tme_element_private; 1804: 1805: /* make the generic bus device connection side: */ 1806: rc = tme_bus_device_connections_new(element, args, _conns, _output); 1807: if (rc != TME_OK) { 1808: return (rc); 1809: } 1810: 1811: /* since we need to allocate our TLB hash when we make our bus 1812: connection, make sure any generic bus device connection sides use 1813: our connection maker: */ 1814: for (conn = *_conns; 1815: conn != NULL; 1816: conn = conn->tme_connection_next) { 1817: if ((conn->tme_connection_type 1818: == TME_CONNECTION_BUS_GENERIC) 1819: && (conn->tme_connection_make 1820: == tme_bus_device_connection_make)) { 1821: conn->tme_connection_make 1822: = _tme_am7990_connection_make_bus; 1823: } 1824: } 1825: 1826: /* if we don't have an Ethernet connection, make one: */ 1827: if (am7990->tme_am7990_eth_connection == NULL) { 1828: 1829: /* allocate the new Ethernet connection: */ 1830: conn_eth = tme_new0(struct tme_ethernet_connection, 1); 1831: conn = &conn_eth->tme_ethernet_connection; 1832: 1833: /* fill in the generic connection: */ 1834: conn->tme_connection_next = *_conns; 1835: conn->tme_connection_type = TME_CONNECTION_ETHERNET; 1836: conn->tme_connection_score = tme_ethernet_connection_score; 1837: conn->tme_connection_make = _tme_am7990_connection_make_eth; 1838: conn->tme_connection_break = _tme_am7990_connection_break; 1839: 1840: /* fill in the Ethernet connection: */ 1841: conn_eth->tme_ethernet_connection_config = _tme_am7990_config; 1842: conn_eth->tme_ethernet_connection_ctrl = _tme_am7990_ctrl; 1843: conn_eth->tme_ethernet_connection_read = _tme_am7990_transmit; 1844: 1845: /* return the connection side possibility: */ 1846: *_conns = conn; 1847: } 1848: 1849: /* done: */ 1850: return (TME_OK); 1851: } 1852: 1853: /* the new am7990 function: */ 1854: TME_ELEMENT_X_NEW_DECL(tme_ic_,am7990,am7990) { 1855: struct tme_am7990 *am7990; 1856: int arg_i; 1857: int usage; 1858: tme_uint32_t reg_size; 1859: 1860: /* check our arguments: */ 1861: usage = 0; 1862: arg_i = 1; 1863: for (;;) { 1864: 1865: if (0) { 1866: } 1867: 1868: /* if we ran out of arguments: */ 1869: else if (args[arg_i] == NULL) { 1870: 1871: break; 1872: } 1873: 1874: /* otherwise this is a bad argument: */ 1875: else { 1876: tme_output_append_error(_output, 1877: "%s %s, ", 1878: args[arg_i], 1879: _("unexpected")); 1880: usage = TRUE; 1881: break; 1882: } 1883: } 1884: 1885: if (usage) { 1886: tme_output_append_error(_output, 1887: "%s %s", 1888: _("usage:"), 1889: args[0]); 1890: return (EINVAL); 1891: } 1892: 1893: /* start the am7990 structure: */ 1894: am7990 = tme_new0(struct tme_am7990, 1); 1895: am7990->tme_am7990_element = element; 1896: tme_mutex_init(&am7990->tme_am7990_mutex); 1897: 1898: /* set the register offsets: */ 1899: /* XXX FIXME - these should come from a socket structure: */ 1900: am7990->tme_am7990_offset_rdp = 0; 1901: am7990->tme_am7990_offset_rap = sizeof(tme_uint16_t); 1902: 1903: /* get the total register size: */ 1904: assert ((am7990->tme_am7990_offset_rdp & (am7990->tme_am7990_offset_rdp - 1)) == 0); 1905: assert ((am7990->tme_am7990_offset_rap & (am7990->tme_am7990_offset_rap - 1)) == 0); 1906: reg_size = TME_MAX(am7990->tme_am7990_offset_rdp, am7990->tme_am7990_offset_rap) * 2; 1907: 1908: /* initialize our simple bus device descriptor: */ 1909: am7990->tme_am7990_device.tme_bus_device_element = element; 1910: am7990->tme_am7990_device.tme_bus_device_tlb_fill = _tme_am7990_tlb_fill; 1911: am7990->tme_am7990_device.tme_bus_device_address_last = reg_size - 1; 1912: am7990->tme_am7990_device.tme_bus_device_signal = _tme_am7990_signal; 1913: am7990->tme_am7990_device.tme_bus_device_lock = _tme_am7990_lock; 1914: am7990->tme_am7990_device.tme_bus_device_unlock = _tme_am7990_unlock; 1915: am7990->tme_am7990_device.tme_bus_device_tlb_hash = _tme_am7990_tlb_hash; 1916: 1917: /* fill the element: */ 1918: element->tme_element_private = am7990; 1919: element->tme_element_connections_new = _tme_am7990_connections_new; 1920: 1921: /* start the descriptor polling thread: */ 1922: tme_thread_create((tme_thread_t) _tme_am7990_poll_th, am7990); 1923: 1924: /* reset the am7990: */ 1925: _tme_am7990_reset(am7990); 1926: 1927: return (TME_OK); 1928: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.