--- tme/ic/i825x6.c 2018/04/24 16:40:13 1.1.1.1 +++ tme/ic/i825x6.c 2018/04/24 16:45:31 1.1.1.4 @@ -1,4 +1,4 @@ -/* $Id: i825x6.c,v 1.1.1.1 2018/04/24 16:40:13 root Exp $ */ +/* $Id: i825x6.c,v 1.1.1.4 2018/04/24 16:45:31 root Exp $ */ /* ic/i825x6.c - implementation of the Intel 825x6 emulation: */ @@ -34,7 +34,9 @@ */ #include -_TME_RCSID("$Id: i825x6.c,v 1.1.1.1 2018/04/24 16:40:13 root Exp $"); +_TME_RCSID("$Id: i825x6.c,v 1.1.1.4 2018/04/24 16:45:31 root Exp $"); + +/* XXX FIXME - TLB usage here is not thread-safe: */ /* includes: */ #include @@ -117,6 +119,10 @@ do { \ #define TME_I825X6_CALLOUT_CA TME_BIT(5) #define TME_I825X6_CALLOUT_CU TME_BIT(6) +#if 1 +extern int printf(const char *format, ...); +#endif + /* structures: */ /* an rx buffer: */ @@ -124,9 +130,13 @@ struct tme_i825x6_rx_buffer { /* the generic ethernet frame chunk. this must be first, since we abuse its tme_ethernet_frame_chunk_next for our own next pointer: */ - struct tme_ethernet_frame_chunk tme_i825x6_rx_buffer_frame_chunk; + union { + struct tme_i825x6_rx_buffer *_tme_i825x6_rx_buffer_u_next; + struct tme_ethernet_frame_chunk _tme_i825x6_rx_buffer_u_frame_chunk; + } _tme_i825x6_rx_buffer_u; #define TME_I825X6_RX_BUFFER_NEXT(rx_buffer) \ - (*((struct tme_i825x6_rx_buffer **) &(rx_buffer)->tme_i825x6_rx_buffer_frame_chunk.tme_ethernet_frame_chunk_next)) + ((rx_buffer)->_tme_i825x6_rx_buffer_u._tme_i825x6_rx_buffer_u_next) +#define tme_i825x6_rx_buffer_frame_chunk _tme_i825x6_rx_buffer_u._tme_i825x6_rx_buffer_u_frame_chunk /* when this is TME_I825X6_RU_ADDRESS_UNDEF, this rx buffer was made from a fast-write TLB entry, and the generic ethernet frame chunk @@ -159,7 +169,8 @@ struct tme_i825x6 { int tme_i825x6_callout_flags; /* our DMA TLB hash: */ - TME_ATOMIC(struct tme_bus_tlb *, tme_i825x6_tlb_hash); + struct tme_bus_tlb tme_i825x6_tlb_hash[TME_I825X6_TLB_HASH_SIZE]; + int tme_i825x6_tlb_hash_added; /* the i825x6 bus signals: */ struct tme_bus_signals tme_i825x6_bus_signals; @@ -254,6 +265,10 @@ _tme_i825x6_reset(struct tme_i825x6 *i82 if (i825x6->tme_i825x6_stat_cus_rus_t & TME_I825X6_SCB_STAT_MASK) { i825x6->tme_i825x6_stat_cus_rus_t &= ~TME_I825X6_SCB_STAT_MASK; +#if 1 +printf("_tme_i825x6_reset() CALLOUT_INT\n"); +#endif + i825x6->tme_i825x6_callout_flags |= TME_I825X6_CALLOUT_INT; } @@ -284,8 +299,8 @@ _tme_i825x6_tlb_hash(void *_i825x6, i825x6 = (struct tme_i825x6 *) _i825x6; /* return the TLB entry: */ - return (TME_ATOMIC_READ(struct tme_bus_tlb *, i825x6->tme_i825x6_tlb_hash) - + ((linear_address >> 10) & (TME_I825X6_TLB_HASH_SIZE - 1))); + return (i825x6->tme_i825x6_tlb_hash + + ((((tme_bus_addr32_t) linear_address) >> 10) & (TME_I825X6_TLB_HASH_SIZE - 1))); } /* this locks the mutex: */ @@ -379,8 +394,8 @@ _tme_i825x6_rx_buffers_add(struct tme_i8 struct tme_i825x6_rx_buffer *rx_buffer, **_prev; struct tme_bus_tlb *tlb, tlb_local; struct tme_bus_connection *conn_bus; - tme_bus_addr_t count_minus_one, count; - tme_bus_addr_t tlb_addr_last; + tme_bus_addr32_t count_minus_one, count; + tme_bus_addr32_t tlb_addr_last; int err; /* recover the rx buffers list: */ @@ -396,22 +411,29 @@ _tme_i825x6_rx_buffers_add(struct tme_i8 tlb = _tme_i825x6_tlb_hash(i825x6, address_init, TME_BUS_CYCLE_WRITE); + + /* busy this TLB entry: */ + tme_bus_tlb_busy(tlb); - /* if this TLB entry doesn't cover this address, or if it doesn't - allow writing, reload it: */ - tlb_addr_last = TME_ATOMIC_READ(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last); - if (address_init < TME_ATOMIC_READ(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first) + /* if this TLB entry is invalid, or doesn't cover this address, or + if it doesn't allow writing, reload it: */ + tlb_addr_last = tlb->tme_bus_tlb_addr_last; + if (tme_bus_tlb_is_invalid(tlb) + || address_init < (tme_bus_addr32_t) tlb->tme_bus_tlb_addr_first || address_init > tlb_addr_last || (tlb->tme_bus_tlb_emulator_off_write == TME_EMULATOR_OFF_UNDEF && !(tlb->tme_bus_tlb_cycles_ok & TME_BUS_CYCLE_WRITE))) { + + /* unbusy this TLB entry for filling: */ + tme_bus_tlb_unbusy_fill(tlb); - /* reserve this TLB entry: */ - tme_bus_tlb_reserve(tlb, &tlb_local); - tlb = &tlb_local; + /* pass this TLB's token: */ + tlb_local.tme_bus_tlb_token = tlb->tme_bus_tlb_token; /* get our bus connection: */ - conn_bus = TME_ATOMIC_READ(struct tme_bus_connection *, - i825x6->tme_i825x6_device.tme_bus_device_connection); + conn_bus = tme_memory_atomic_pointer_read(struct tme_bus_connection *, + i825x6->tme_i825x6_device.tme_bus_device_connection, + &i825x6->tme_i825x6_device.tme_bus_device_connection_rwlock); /* unlock the mutex: */ tme_mutex_unlock(&i825x6->tme_i825x6_mutex); @@ -419,7 +441,7 @@ _tme_i825x6_rx_buffers_add(struct tme_i8 /* reload the TLB entry: */ err = (*conn_bus->tme_bus_tlb_fill) (conn_bus, - tlb, + &tlb_local, address_init, TME_BUS_CYCLE_WRITE); @@ -432,15 +454,11 @@ _tme_i825x6_rx_buffers_add(struct tme_i8 abort(); } - /* the TLB entry must cover this address and allow writing: */ - tlb_addr_last = TME_ATOMIC_READ(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last); - assert (address_init >= TME_ATOMIC_READ(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first) - && address_init <= tlb_addr_last - && (tlb->tme_bus_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF - || (tlb->tme_bus_tlb_cycles_ok & TME_BUS_CYCLE_WRITE))); - /* store the TLB entry: */ - tme_bus_tlb_back(tlb); + *tlb = tlb_local; + + /* loop to check the newly filled TLB entry: */ + continue; } /* see how many addresses we can cover with this TLB entry, @@ -466,7 +484,12 @@ _tme_i825x6_rx_buffers_add(struct tme_i8 /* this is a fast rx buffer: */ rx_buffer->tme_i825x6_rx_buffer_rb_address = TME_I825X6_RU_ADDRESS_UNDEF; rx_buffer->tme_i825x6_rx_buffer_frame_chunk.tme_ethernet_frame_chunk_bytes - = tlb->tme_bus_tlb_emulator_off_write + address_init; + /* XXX FIXME - this breaks volatile: */ + = (tme_uint8_t *) tlb->tme_bus_tlb_emulator_off_write + address_init; + + /* unbusy the TLB: */ + /* XXX FIXME - this is not thread-safe: */ + tme_bus_tlb_unbusy(tlb); } /* otherwise, this TLB entry does not allow fast writing: */ @@ -682,6 +705,10 @@ _tme_i825x6_chunks_dma_tx(struct tme_i82 tme_uint32_t count; int rc; +#if 1 + printf("_tme_i825x6_chunks_dma_tx; xmit %d\n", size); +#endif + /* while we have bytes left to DMA: */ for (; size > 0; ) { @@ -762,6 +789,9 @@ _tme_i825x6_callout_ca(struct tme_i825x6 tme_uint16_t rbd_offset_first; int rc; +#if 1 +printf("_tme_i825x6_callout_ca()\n"); +#endif /* if this CA follows RESET: */ if (i825x6->tme_i825x6_ca_follows_reset) { @@ -802,6 +832,9 @@ _tme_i825x6_callout_ca(struct tme_i825x6 | TME_I825X6_SCB_RUS_IDLE); /* "The 82596 ... sends an interrupt to the CPU": */ +#if 1 +printf("_tme_i825x6_callout_ca() CALLOUT_INT\n"); +#endif i825x6->tme_i825x6_callout_flags = TME_I825X6_CALLOUTS_RUNNING | TME_I825X6_CALLOUT_INT; } @@ -856,16 +889,16 @@ _tme_i825x6_callout_ca(struct tme_i825x6 case TME_I825X6_SCB_RUC_START: - /* if the Receive Unit is still Ready or Suspended: */ + /* if the Receive Unit is not Idle: */ switch (stat_cus_rus_t & TME_I82586_SCB_RUS_MASK) { case TME_I825X6_SCB_RUS_READY: case TME_I825X6_SCB_RUS_SUSPENDED: + case TME_I825X6_SCB_RUS_ERESOURCE: /* abort the Receive Unit: */ _tme_i825x6_abort_ru(i825x6); break; - case TME_I825X6_SCB_RUS_ERESOURCE: case TME_I825X6_SCB_RUS_IDLE: break; @@ -1250,8 +1283,10 @@ _tme_i825x6_callout_cu(struct tme_i825x6 break; case TME_I825X6_CB_CMD_DUMP: - case TME_I825X6_CB_CMD_DIAGNOSE: abort(); + + case TME_I825X6_CB_CMD_DIAGNOSE: + break; } /* add to the callouts and return the current status: */ @@ -1455,6 +1490,9 @@ _tme_i825x6_callout_ru(struct tme_i825x6 + TME_I825X6_RFD_C_B_OK_STATUS), c_b_ok_status); +#if 1 + printf("_tme_i825x6_callout_ru() signal int\n"); +#endif /* signal an interrupt: */ stat_cus_rus_t |= TME_I825X6_SCB_STAT_FR; @@ -1602,6 +1640,9 @@ _tme_i825x6_callout(struct tme_i825x6 *i /* unlock the mutex: */ tme_mutex_unlock(&i825x6->tme_i825x6_mutex); +#if 1 + printf("_tme_i825x6_callout; \n"); +#endif /* do the callout: */ rc = (conn_eth != NULL ? ((*conn_eth->tme_ethernet_connection_ctrl) @@ -1712,6 +1753,9 @@ _tme_i825x6_callout(struct tme_i825x6 *i & TME_I825X6_SCB_STAT_MASK) != !(stat_cus_rus_t & TME_I825X6_SCB_STAT_MASK)) { +#if 1 +printf("_tme_i825x6_callout() CALLOUT_INT\n"); +#endif i825x6->tme_i825x6_callout_flags |= TME_I825X6_CALLOUT_INT; } @@ -1742,9 +1786,13 @@ _tme_i825x6_callout(struct tme_i825x6 *i tme_mutex_unlock(&i825x6->tme_i825x6_mutex); /* get our bus connection: */ - conn_bus = TME_ATOMIC_READ(struct tme_bus_connection *, - i825x6->tme_i825x6_device.tme_bus_device_connection); + conn_bus = tme_memory_atomic_pointer_read(struct tme_bus_connection *, + i825x6->tme_i825x6_device.tme_bus_device_connection, + &i825x6->tme_i825x6_device.tme_bus_device_connection_rwlock); +#if 1 + printf("_tme_i825x6_callout; signal int - asserted %x\n", (int)int_asserted); +#endif /* call out the bus interrupt signal edge: */ rc = (*conn_bus->tme_bus_signal) (conn_bus, @@ -1759,6 +1807,9 @@ _tme_i825x6_callout(struct tme_i825x6 *i /* if this callout failed, remember that at some later time this callout should be attempted again: */ if (rc != TME_OK) { +#if 1 +printf("_tme_i825x6_callout() later CALLOUT_INT\n"); +#endif later_callouts |= TME_I825X6_CALLOUT_INT; } } @@ -1788,8 +1839,13 @@ _tme_i825x6_signal(void *_i825x6, /* take out the signal level: */ level = signal & TME_BUS_SIGNAL_LEVEL_MASK; - signal ^= level; + signal = TME_BUS_SIGNAL_WHICH(signal); +#if 1 + printf("_tme_i825x6_signal() level %x, signal %x; switch index %x\n", + (int)level, (int)signal, + (int)(signal - i825x6->tme_i825x6_bus_signals.tme_bus_signals_first)); +#endif /* dispatch on the generic bus signals: */ switch (signal) { case TME_BUS_SIGNAL_RESET: @@ -1808,6 +1864,14 @@ _tme_i825x6_signal(void *_i825x6, case TME_I825X6_SIGNAL_CA: if (level == TME_BUS_SIGNAL_LEVEL_ASSERTED) { new_callouts |= TME_I825X6_CALLOUT_CA; + } else { +#if 1 + printf("TME_I825X6_SIGNAL_CA; deasserted!!!!\n"); +#endif +#if 1 + i825x6->tme_i825x6_stat_cus_rus_t &= ~TME_I825X6_SCB_STAT_MASK; + new_callouts |= TME_I825X6_CALLOUT_INT; +#endif } break; @@ -1891,6 +1955,7 @@ _tme_i825x6_read(struct tme_ethernet_con tme_uint16_t value16; tme_uint32_t value32; int rc, err; + int length; /* recover our data structures: */ i825x6 = conn_eth->tme_ethernet_connection.tme_connection_element->tme_element_private; @@ -1911,13 +1976,17 @@ _tme_i825x6_read(struct tme_ethernet_con tme_mutex_lock(&i825x6->tme_i825x6_mutex); /* assume that we will have no packet to transmit: */ - rc = 0; + length = 0; /* if we have a packet to transmit: */ if ((i825x6->tme_i825x6_el_s_i_cmd & TME_I825X6_CB_CMD_MASK) == TME_I825X6_CB_CMD_TRANSMIT) { +#if 1 + printf("_tme_i825x6_read; xmit\n"); +#endif + /* assume that we will succeed: */ err = TME_OK; do { @@ -1926,10 +1995,10 @@ _tme_i825x6_read(struct tme_ethernet_con #define CHUNKS_DMA_TX(addr, size) \ err = _tme_i825x6_chunks_dma_tx(i825x6, frame_chunks, (addr), (size)); \ if (err != TME_OK) break; \ - rc += size + length += size #define CHUNKS_MEM_TX(data, size) \ _tme_i825x6_chunks_mem_tx(frame_chunks, (data), (size)); \ - rc += size + length += size /* if AL-LOC is set to zero, add the Ethernet/802.3 MAC header: */ if (i825x6->tme_i825x6_al_loc == 0) { @@ -1991,7 +2060,7 @@ _tme_i825x6_read(struct tme_ethernet_con c_b_ok_a |= TME_I825X6_TCB_STATUS_UNDERRUN; /* return an error to our caller: */ - rc = -ENOENT; + length = -ENOENT; } /* update the CB status word: */ @@ -2014,7 +2083,7 @@ _tme_i825x6_read(struct tme_ethernet_con tme_mutex_unlock(&i825x6->tme_i825x6_mutex); /* done: */ - return (rc); + return (length); } /* this makes a new Ethernet connection: */ @@ -2071,21 +2140,20 @@ _tme_i825x6_connection_make_bus(struct t hash yet, allocate it and add our bus signals: */ if (rc == TME_OK && state == TME_CONNECTION_FULL - && TME_ATOMIC_READ(struct tme_bus_tlb *, - i825x6->tme_i825x6_tlb_hash) == NULL) { + && !i825x6->tme_i825x6_tlb_hash_added) { /* get our bus connection: */ conn_bus - = TME_ATOMIC_READ(struct tme_bus_connection *, - i825x6->tme_i825x6_device.tme_bus_device_connection); - - /* allocate the TLB set: */ - rc = ((*conn_bus->tme_bus_tlb_set_allocate) - (conn_bus, - TME_I825X6_TLB_HASH_SIZE, - sizeof(struct tme_bus_tlb), - TME_ATOMIC_POINTER(&i825x6->tme_i825x6_tlb_hash))); + = tme_memory_atomic_pointer_read(struct tme_bus_connection *, + i825x6->tme_i825x6_device.tme_bus_device_connection, + &i825x6->tme_i825x6_device.tme_bus_device_connection_rwlock); + + /* add the TLB set: */ + rc = tme_bus_device_tlb_set_add(&i825x6->tme_i825x6_device, + TME_I825X6_TLB_HASH_SIZE, + i825x6->tme_i825x6_tlb_hash); assert (rc == TME_OK); + i825x6->tme_i825x6_tlb_hash_added = TRUE; /* add our bus signals: */ i825x6->tme_i825x6_bus_signals = _tme_i825x6_bus_signals;