Annotation of tme/ic/am7990.c, revision 1.1.1.2

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(&ether_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(&ether_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(&ether_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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.