--- tme/bus/multibus/sun-sc.c 2018/04/24 16:38:46 1.1 +++ tme/bus/multibus/sun-sc.c 2018/04/24 16:41:31 1.1.1.3 @@ -1,4 +1,4 @@ -/* $Id: sun-sc.c,v 1.1 2018/04/24 16:38:46 root Exp $ */ +/* $Id: sun-sc.c,v 1.1.1.3 2018/04/24 16:41:31 root Exp $ */ /* bus/multibus/sun-sc.c - implementation of Sun `sc' SCSI Multibus board emulation: */ @@ -34,7 +34,7 @@ */ #include -_TME_RCSID("$Id: sun-sc.c,v 1.1 2018/04/24 16:38:46 root Exp $"); +_TME_RCSID("$Id: sun-sc.c,v 1.1.1.3 2018/04/24 16:41:31 root Exp $"); /* includes: */ #include @@ -124,8 +124,9 @@ struct tme_sun_sc_cycle { tme_scsi_control_t tme_sun_sc_cycle_control; tme_scsi_data_t tme_sun_sc_cycle_data; - /* the SCSI sequence to run: */ - const struct tme_scsi_sequence *tme_sun_sc_cycle_sequence; + /* the SCSI events to wait on, and the actions to take: */ + tme_uint32_t tme_sun_sc_cycle_events; + tme_uint32_t tme_sun_sc_cycle_actions; /* a DMA structure needed: */ struct tme_scsi_dma tme_sun_sc_cycle_dma; @@ -159,17 +160,14 @@ struct tme_sun_sc { /* it's easiest to just model the card as a chunk of memory: */ tme_uint8_t tme_sun_sc_card[TME_SUN_SC_SIZ_CARD]; - /* the SCSI sequences: */ - const struct tme_scsi_sequence *tme_sun_sc_sequence_info_dma_initiator; - const struct tme_scsi_sequence *tme_sun_sc_sequence_wait_change; - /* the cycle ring buffer: */ struct tme_sun_sc_cycle tme_sun_sc_cycles[TME_SUN_SC_CYCLE_RING_SIZE]; int tme_sun_sc_cycle_head; int tme_sun_sc_cycle_tail; /* our DMA TLB set: */ - TME_ATOMIC(struct tme_bus_tlb *, tme_sun_sc_dma_tlb); + struct tme_bus_tlb * tme_shared tme_sun_sc_dma_tlb; + tme_rwlock_t tme_sun_sc_dma_tlb_rwlock; /* the internal DMA buffer: */ tme_uint8_t tme_sun_sc_int_dma[2]; @@ -288,7 +286,8 @@ _tme_sun_sc_reg16_put(struct tme_sun_sc /* this allocates the next cycle in the ring buffer: */ struct tme_sun_sc_cycle * _tme_sun_sc_cycle_new(struct tme_sun_sc *sun_sc, - const struct tme_scsi_sequence *sequence) + tme_uint32_t events, + tme_uint32_t actions) { int old_head; struct tme_sun_sc_cycle *sun_sc_cycle; @@ -323,12 +322,12 @@ _tme_sun_sc_cycle_new(struct tme_sun_sc sun_sc_cycle->tme_sun_sc_cycle_control = sun_sc_cycle_old->tme_sun_sc_cycle_control; sun_sc_cycle->tme_sun_sc_cycle_data - = ((sequence - == sun_sc->tme_sun_sc_sequence_info_dma_initiator) + = ((actions + == TME_SCSI_ACTION_DMA_INITIATOR) ? 0 : sun_sc_cycle_old->tme_sun_sc_cycle_data); - sun_sc_cycle->tme_sun_sc_cycle_sequence - = sequence; + sun_sc_cycle->tme_sun_sc_cycle_events = events; + sun_sc_cycle->tme_sun_sc_cycle_actions = actions; /* XXX parity? */ sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_flags = TME_SCSI_DMA_8BIT; @@ -366,7 +365,7 @@ _tme_sun_sc_bus_cycle_dma(struct tme_sun cycle_init.tme_bus_cycle_lane_routing = &tme_sun_sc_router[0]; cycle_init.tme_bus_cycle_size - = sizeof(tme_uint16_t); + = sizeof(tme_uint8_t); } assert (tlb->tme_bus_tlb_addr_shift == 0); @@ -404,6 +403,7 @@ _tme_sun_sc_callout(struct tme_sun_sc *s struct tme_scsi_connection *conn_scsi; struct tme_bus_connection *conn_bus; struct tme_bus_tlb *tlb; + struct tme_bus_tlb tlb_local; int old_tail; struct tme_sun_sc_cycle *sun_sc_cycle; int callouts, later_callouts; @@ -447,8 +447,9 @@ _tme_sun_sc_callout(struct tme_sun_sc *s /* get this card's bus and SCSI connections: */ conn_scsi = sun_sc->tme_sun_sc_scsi_connection; - conn_bus = TME_ATOMIC_READ(struct tme_bus_connection *, - sun_sc->tme_sun_sc_device.tme_bus_device_connection); + conn_bus = tme_memory_atomic_pointer_read(struct tme_bus_connection *, + sun_sc->tme_sun_sc_device.tme_bus_device_connection, + &sun_sc->tme_sun_sc_device.tme_bus_device_connection_rwlock); /* if we need to call out a SCSI bus cycle: */ if (callouts & TME_SUN_SC_CALLOUT_CYCLE) { @@ -464,14 +465,18 @@ _tme_sun_sc_callout(struct tme_sun_sc *s tme_mutex_unlock(&sun_sc->tme_sun_sc_mutex); /* do the callout: */ + /* XXX FIXME THREADS - this is not thread-safe, since we're + passing values from (and pointers to) the non-local + sun_sc_cycle: */ rc = (conn_scsi != NULL ? ((*conn_scsi->tme_scsi_connection_cycle) (conn_scsi, sun_sc_cycle->tme_sun_sc_cycle_control, sun_sc_cycle->tme_sun_sc_cycle_data, - sun_sc_cycle->tme_sun_sc_cycle_sequence, - ((sun_sc_cycle->tme_sun_sc_cycle_sequence - == sun_sc->tme_sun_sc_sequence_info_dma_initiator) + sun_sc_cycle->tme_sun_sc_cycle_events, + sun_sc_cycle->tme_sun_sc_cycle_actions, + ((sun_sc_cycle->tme_sun_sc_cycle_actions + == TME_SCSI_ACTION_DMA_INITIATOR) ? &sun_sc_cycle->tme_sun_sc_cycle_dma : NULL))) : TME_OK); @@ -488,8 +493,8 @@ _tme_sun_sc_callout(struct tme_sun_sc *s /* otherwise, this callout was successful. if this cycle did not use the DMA initiator sequence, it either used no sequence or it used the wait_change sequence: */ - else if (sun_sc_cycle->tme_sun_sc_cycle_sequence - != sun_sc->tme_sun_sc_sequence_info_dma_initiator) { + else if (sun_sc_cycle->tme_sun_sc_cycle_actions + != TME_SCSI_ACTION_DMA_INITIATOR) { /* advance the tail pointer if it hasn't been advanced already: */ @@ -547,8 +552,13 @@ _tme_sun_sc_callout(struct tme_sun_sc *s /* get the TLB entry: */ tlb - = TME_ATOMIC_READ(struct tme_bus_tlb *, - sun_sc->tme_sun_sc_dma_tlb); + = tme_memory_atomic_pointer_read(struct tme_bus_tlb *, + sun_sc->tme_sun_sc_dma_tlb, + &sun_sc->tme_sun_sc_dma_tlb_rwlock); + + /* reserve this TLB entry: */ + tlb_local.tme_bus_tlb_global = tlb; + tlb = &tlb_local; /* unlock the mutex: */ tme_mutex_unlock(&sun_sc->tme_sun_sc_mutex); @@ -575,10 +585,12 @@ _tme_sun_sc_callout(struct tme_sun_sc *s DMA sequence: */ else { + /* store the TLB entry: */ + tme_bus_tlb_back(tlb); + /* get the number of bytes available in this TLB entry: */ avail - = ((TME_ATOMIC_READ(tme_bus_addr_t, - tlb->tme_bus_tlb_addr_last) + = ((tlb->tme_bus_tlb_addr_last - address) + 1); if (avail == 0 @@ -594,14 +606,16 @@ _tme_sun_sc_callout(struct tme_sun_sc *s /* allocate the new SCSI bus cycle: */ sun_sc_cycle = _tme_sun_sc_cycle_new(sun_sc, - sun_sc->tme_sun_sc_sequence_info_dma_initiator); + TME_SCSI_EVENT_NONE, + TME_SCSI_ACTION_DMA_INITIATOR); /* if this TLB entry allows fast transfers: */ emulator_off = ((cycle_type == TME_BUS_CYCLE_READ) - ? tlb->tme_bus_tlb_emulator_off_read - : tlb->tme_bus_tlb_emulator_off_write); + /* XXX FIXME - this breaks volatile: */ + ? (tme_uint8_t *) tlb->tme_bus_tlb_emulator_off_read + : (tme_uint8_t *) tlb->tme_bus_tlb_emulator_off_write); if (emulator_off != TME_EMULATOR_OFF_UNDEF) { @@ -618,6 +632,7 @@ _tme_sun_sc_callout(struct tme_sun_sc *s read cycle into our internal DMA buffer: */ if (cycle_type == TME_BUS_CYCLE_READ) { rc = _tme_sun_sc_bus_cycle_dma(sun_sc, + /* XXX FIXME this is not thread-safe: */ tlb, TME_BUS_CYCLE_READ, address, @@ -674,8 +689,7 @@ _tme_sun_sc_callout(struct tme_sun_sc *s TME_BUS_SIGNAL_INT_UNSPEC | (int_asserted ? TME_BUS_SIGNAL_LEVEL_ASSERTED - : TME_BUS_SIGNAL_LEVEL_NEGATED) - | TME_BUS_SIGNAL_EDGE); + : TME_BUS_SIGNAL_LEVEL_NEGATED)); /* lock our mutex: */ tme_mutex_lock(&sun_sc->tme_sun_sc_mutex); @@ -699,6 +713,21 @@ _tme_sun_sc_callout(struct tme_sun_sc *s sun_sc->tme_sun_sc_callout_flags = later_callouts; } +/* the interrupt acknowledge function for the VME version: */ +static int +_tme_sun_sc_intack(void *_sun_sc, unsigned int signal, int *_vector) +{ + struct tme_sun_sc *sun_sc; + + /* recover our data structure: */ + sun_sc = (struct tme_sun_sc *) _sun_sc; + + /* return the interrupt vector: */ + *_vector = sun_sc->tme_sun_sc_card[TME_SUN_SC_REG_INTVEC]; + + return (TME_OK); +} + /* the Sun sc bus cycle handler for the data and cmd_stat registers. these registers are connected directly to the SCSI data signals. @@ -770,7 +799,8 @@ _tme_sun_sc_bus_cycle_data_reg(struct tm /* XXX parity? */ sun_sc_cycle = _tme_sun_sc_cycle_new(sun_sc, - sun_sc->tme_sun_sc_sequence_info_dma_initiator); + TME_SCSI_EVENT_NONE, + TME_SCSI_ACTION_DMA_INITIATOR); sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_resid = sizeof(sun_sc_cycle->tme_sun_sc_cycle_cmd_stat); sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_in @@ -826,7 +856,8 @@ _tme_sun_sc_bus_cycle_data_reg(struct tm data_new)); sun_sc_cycle = _tme_sun_sc_cycle_new(sun_sc, - sun_sc->tme_sun_sc_sequence_wait_change); + TME_SCSI_EVENT_BUS_CHANGE, + TME_SCSI_ACTION_NONE); sun_sc_cycle->tme_sun_sc_cycle_data = data_new; new_callouts @@ -1004,7 +1035,8 @@ _tme_sun_sc_bus_cycle_icr(void *_sun_sc, except possibly for RST: */ sun_sc_cycle = _tme_sun_sc_cycle_new(sun_sc, - sun_sc->tme_sun_sc_sequence_wait_change); + TME_SCSI_EVENT_BUS_CHANGE, + TME_SCSI_ACTION_NONE); sun_sc_cycle->tme_sun_sc_cycle_control = ((icr_new & TME_SUN_SC_ICR_RESET) @@ -1022,7 +1054,8 @@ _tme_sun_sc_bus_cycle_icr(void *_sun_sc, /* make a new cycle that sets the new state of SEL: */ sun_sc_cycle = _tme_sun_sc_cycle_new(sun_sc, - sun_sc->tme_sun_sc_sequence_wait_change); + TME_SCSI_EVENT_BUS_CHANGE, + TME_SCSI_ACTION_NONE); sun_sc_cycle->tme_sun_sc_cycle_control = ((sun_sc_cycle->tme_sun_sc_cycle_control & ~TME_SCSI_SIGNAL_SEL) @@ -1140,14 +1173,8 @@ do { \ + (siz)))) { \ \ /* this TLB entry covers this register: */ \ - TME_ATOMIC_WRITE(tme_bus_addr_t, \ - tlb->tme_bus_tlb_addr_first,\ - (reg)); \ - TME_ATOMIC_WRITE(tme_bus_addr_t, \ - tlb->tme_bus_tlb_addr_last,\ - ((reg) \ - + (siz) \ - - 1)); \ + tlb->tme_bus_tlb_addr_first = (reg); \ + tlb->tme_bus_tlb_addr_last = (reg) + (siz) - 1;\ \ /* our bus cycle handler: */ \ tlb->tme_bus_tlb_cycle = (handler); \ @@ -1183,21 +1210,12 @@ do { \ if (address >= (TME_SUN_SC_REG_ICR + TME_SUN_SC_SIZ_ICR)) { - TME_ATOMIC_WRITE(tme_bus_addr_t, - tlb->tme_bus_tlb_addr_first, - (TME_SUN_SC_REG_ICR - + TME_SUN_SC_SIZ_ICR)); - TME_ATOMIC_WRITE(tme_bus_addr_t, - tlb->tme_bus_tlb_addr_last, - TME_SUN_SC_SIZ_CARD - 1); + tlb->tme_bus_tlb_addr_first = TME_SUN_SC_REG_ICR + TME_SUN_SC_SIZ_ICR; + tlb->tme_bus_tlb_addr_last = TME_SUN_SC_SIZ_CARD - 1; } else { - TME_ATOMIC_WRITE(tme_bus_addr_t, - tlb->tme_bus_tlb_addr_first, - address); - TME_ATOMIC_WRITE(tme_bus_addr_t, - tlb->tme_bus_tlb_addr_last, - address); + tlb->tme_bus_tlb_addr_first = address; + tlb->tme_bus_tlb_addr_last = address; } /* this TLB entry allows fast reading and writing: */ @@ -1235,8 +1253,9 @@ static int _tme_sun_sc_scsi_cycle(struct tme_scsi_connection *conn_scsi, tme_scsi_control_t control, tme_scsi_data_t data, - _tme_const struct tme_scsi_sequence *sequence, - struct tme_scsi_dma *dma) + tme_uint32_t events_triggered, + tme_uint32_t actions_taken, + const struct tme_scsi_dma *dma) { struct tme_sun_sc *sun_sc; struct tme_sun_sc_cycle *sun_sc_cycle; @@ -1307,8 +1326,11 @@ do { \ = &sun_sc->tme_sun_sc_cycles[sun_sc->tme_sun_sc_cycle_tail]; /* if the last SCSI cycle was for a DMA sequence: */ - if (sun_sc_cycle->tme_sun_sc_cycle_sequence - == sun_sc->tme_sun_sc_sequence_info_dma_initiator) { + if (sun_sc_cycle->tme_sun_sc_cycle_actions + == TME_SCSI_ACTION_DMA_INITIATOR) { + + /* copy in the finished DMA structure: */ + sun_sc_cycle->tme_sun_sc_cycle_dma = *dma; /* if the last SCSI cycle was for a genuine DMA sequence (as opposed to a DMA sequence to transfer the cmd_stat register), update the @@ -1329,8 +1351,9 @@ do { \ /* get the TLB entry: */ tlb - = TME_ATOMIC_READ(struct tme_bus_tlb *, - sun_sc->tme_sun_sc_dma_tlb); + = tme_memory_atomic_pointer_read(struct tme_bus_tlb *, + sun_sc->tme_sun_sc_dma_tlb, + &sun_sc->tme_sun_sc_dma_tlb_rwlock); /* get the DMA address: */ address @@ -1351,6 +1374,7 @@ do { \ && (tlb->tme_bus_tlb_emulator_off_write == TME_EMULATOR_OFF_UNDEF)) { rc = _tme_sun_sc_bus_cycle_dma(sun_sc, + /* XXX FIXME this is not thread-safe: */ tlb, TME_BUS_CYCLE_WRITE, address, @@ -1419,7 +1443,8 @@ do { \ else { sun_sc_cycle = _tme_sun_sc_cycle_new(sun_sc, - sun_sc->tme_sun_sc_sequence_wait_change); + TME_SCSI_EVENT_BUS_CHANGE, + TME_SCSI_ACTION_NONE); new_callouts |= TME_SUN_SC_CALLOUT_CYCLE; } @@ -1456,20 +1481,22 @@ _tme_sun_sc_connection_make_bus(struct t set yet, allocate it: */ if (rc == TME_OK && state == TME_CONNECTION_FULL - && TME_ATOMIC_READ(struct tme_bus_tlb *, - sun_sc->tme_sun_sc_dma_tlb) == NULL) { + && tme_memory_atomic_pointer_read(struct tme_bus_tlb *, + sun_sc->tme_sun_sc_dma_tlb, + &sun_sc->tme_sun_sc_dma_tlb_rwlock) == NULL) { /* get our bus connection: */ - conn_bus - = TME_ATOMIC_READ(struct tme_bus_connection *, - sun_sc->tme_sun_sc_device.tme_bus_device_connection); + conn_bus = tme_memory_atomic_pointer_read(struct tme_bus_connection *, + sun_sc->tme_sun_sc_device.tme_bus_device_connection, + &sun_sc->tme_sun_sc_device.tme_bus_device_connection_rwlock); /* allocate the TLB set: */ rc = ((*conn_bus->tme_bus_tlb_set_allocate) (conn_bus, 1, sizeof(struct tme_bus_tlb), - TME_ATOMIC_POINTER(&sun_sc->tme_sun_sc_dma_tlb))); + &sun_sc->tme_sun_sc_dma_tlb, + &sun_sc->tme_sun_sc_dma_tlb_rwlock)); assert (rc == TME_OK); } @@ -1506,16 +1533,6 @@ _tme_sun_sc_connection_make_scsi(struct /* save our connection: */ sun_sc->tme_sun_sc_scsi_connection = conn_scsi_other; - /* get the sequences that we need: */ - sun_sc->tme_sun_sc_sequence_info_dma_initiator - = ((*conn_scsi_other->tme_scsi_connection_sequence_get) - (conn_scsi_other, - TME_SCSI_SEQUENCE_INFO_DMA_INITIATOR)); - sun_sc->tme_sun_sc_sequence_wait_change - = ((*conn_scsi_other->tme_scsi_connection_sequence_get) - (conn_scsi_other, - TME_SCSI_SEQUENCE_WAIT_CHANGE)); - /* call out a cycle that asserts no signals and runs the wait-change sequence. this also fully-initializes this cycle - _tme_sun_sc_cycle_new copies the previous @@ -1523,7 +1540,8 @@ _tme_sun_sc_connection_make_scsi(struct starts the chain of well-initialized cycles: */ sun_sc_cycle = _tme_sun_sc_cycle_new(sun_sc, - sun_sc->tme_sun_sc_sequence_wait_change); + TME_SCSI_EVENT_BUS_CHANGE, + TME_SCSI_ACTION_NONE); sun_sc_cycle->tme_sun_sc_cycle_control = 0; sun_sc_cycle->tme_sun_sc_cycle_data @@ -1596,7 +1614,6 @@ _tme_sun_sc_connections_new(struct tme_e /* fill in the SCSI connection: */ conn_scsi->tme_scsi_connection_cycle = _tme_sun_sc_scsi_cycle; - conn_scsi->tme_scsi_connection_sequence_get = NULL; /* return the connection side possibility: */ *_conns = conn; @@ -1611,13 +1628,17 @@ TME_ELEMENT_SUB_NEW_DECL(tme_bus_multibu struct tme_sun_sc *sun_sc; int arg_i; int usage; + int vme; /* check our arguments: */ usage = 0; arg_i = 1; + vme = FALSE; for (;;) { - if (0) { + if (TME_ARG_IS(args[arg_i], "vme")) { + vme = TRUE; + arg_i++; } /* if we ran out of arguments: */ @@ -1639,7 +1660,7 @@ TME_ELEMENT_SUB_NEW_DECL(tme_bus_multibu if (usage) { tme_output_append_error(_output, - "%s %s", + "%s %s [ vme ]", _("usage:"), args[0]); return (EINVAL); @@ -1655,6 +1676,9 @@ TME_ELEMENT_SUB_NEW_DECL(tme_bus_multibu sun_sc->tme_sun_sc_device.tme_bus_device_element = element; sun_sc->tme_sun_sc_device.tme_bus_device_tlb_fill = _tme_sun_sc_tlb_fill; sun_sc->tme_sun_sc_device.tme_bus_device_address_last = TME_SUN_SC_SIZ_CARD - 1; + if (vme) { + sun_sc->tme_sun_sc_device.tme_bus_device_intack = _tme_sun_sc_intack; + } /* fill the element: */ element->tme_element_private = sun_sc;