diff -r -C 3 tme-0.6.orig/ic/nec765.c tme-0.6/ic/nec765.c *** tme-0.6.orig/ic/nec765.c Sun Jan 7 16:31:17 2007 --- tme-0.6/ic/nec765.c Wed Jan 27 23:11:03 2010 *************** *** 44,49 **** --- 44,53 ---- /* macros: */ + /* the callout flags: */ + #define TME_NEC765_CALLOUTS_RUNNING TME_BIT(0) + #define TME_NEC765_CALLOUTS_MASK (-2) + /* the different parts: */ #define TME_NEC765_PART_NEC765 (0) #define TME_NEC765_PART_I82072 (1) *************** *** 59,65 **** #define TME_NEC765_REG_DRS (4) /* write-only */ #define TME_NEC765_REG_FIFO (5) #define TME_NEC765_SIZ_REG_NEC765 (2) ! #define TME_NEC765_SIZ_REG_I82072 (4) #define TME_NEC765_SIZ_REG_I82077 (8) /* the MSR register: */ --- 63,70 ---- #define TME_NEC765_REG_DRS (4) /* write-only */ #define TME_NEC765_REG_FIFO (5) #define TME_NEC765_SIZ_REG_NEC765 (2) ! #define TME_NEC765_SIZ_REG_I82072 (8) ! /*#define TME_NEC765_SIZ_REG_I82072 (4)*/ #define TME_NEC765_SIZ_REG_I82077 (8) /* the MSR register: */ *************** *** 93,100 **** --- 98,107 ---- #define _TME_NEC765_CMD(nec765, mask, cmd) (((nec765)->tme_nec765_data_fifo[0] & (mask)) == (cmd)) #define TME_NEC765_CMD_TRACK_READ(nec765) _TME_NEC765_CMD(nec765, 0x9f, 0x02) #define TME_NEC765_CMD_FIX_DRIVE_DATA(nec765) _TME_NEC765_CMD(nec765, 0xff, 0x03) + #define TME_NEC765_CMD_RECALIBRATE(nec765) _TME_NEC765_CMD(nec765, 0xff, 0x07) #define TME_NEC765_CMD_CHECK_INTS(nec765) _TME_NEC765_CMD(nec765, 0xff, 0x08) #define TME_NEC765_CMD_I82072_CONFIG(nec765) _TME_NEC765_CMD(nec765, 0xff, 0x13) + /* XXX FIXME - is this right? */ #define TME_NEC765_CMD_I82072_DUMPREG(nec765) _TME_NEC765_CMD(nec765, 0xff, 0x0e) *************** *** 135,140 **** --- 142,150 ---- /* the mutex protecting the card: */ tme_mutex_t tme_nec765_mutex; + /* the callout flags: */ + int tme_nec765_callout_flags; + /* the part emulated: */ unsigned int tme_nec765_part; #define TME_NEC765_IS_NEC765(nec765) ((nec765)->tme_nec765_part == TME_NEC765_PART_NEC765) *************** *** 144,149 **** --- 154,161 ---- /* if the interrupt is currently asserted: */ int tme_nec765_int_asserted; + int tme_nec765_int_currently_asserted; + /* the data FIFO: */ tme_uint8_t tme_nec765_data_fifo[512]; unsigned int tme_nec765_data_fifo_head; *************** *** 167,172 **** --- 179,236 ---- nec765->tme_nec765_status_fifo_tail = 0; } + /* the nec765 callout function. it must be called with the mutex locked: */ + static void + _tme_nec765_callout(struct tme_nec765 *nec765) + { + struct tme_bus_connection *conn_bus; + int again; + int rc; + int int_asserted; + + /* if this function is already running in another thread, simply + return now. the other thread will do our work: */ + if (nec765->tme_nec765_callout_flags & TME_NEC765_CALLOUTS_RUNNING) { + return; + } + /* callouts are now running: */ + nec765->tme_nec765_callout_flags |= TME_NEC765_CALLOUTS_RUNNING; + + /* loop while we have work to do: */ + do { + again = FALSE; + + /* if we need to call out an interrupt: */ + if (!!nec765->tme_nec765_int_asserted != !!nec765->tme_nec765_int_currently_asserted) { + again = TRUE; + + /* get our bus connection: */ + conn_bus = tme_memory_atomic_pointer_read(struct tme_bus_connection *, + nec765->tme_nec765_device.tme_bus_device_connection, + &nec765->tme_nec765_device.tme_bus_device_connection_rwlock); + + /* unlock our mutex: */ + tme_mutex_unlock(&nec765->tme_nec765_mutex); + /* call out the bus interrupt signal edge: */ + rc = (*conn_bus->tme_bus_signal) + (conn_bus, + TME_BUS_SIGNAL_INT_UNSPEC + | (nec765->tme_nec765_int_asserted + ? TME_BUS_SIGNAL_LEVEL_ASSERTED + : TME_BUS_SIGNAL_LEVEL_NEGATED)); + assert (rc == TME_OK); + + /* note the new state of the interrupt signal: */ + nec765->tme_nec765_int_currently_asserted = nec765->tme_nec765_int_asserted; + + /* lock our mutex: */ + tme_mutex_lock(&nec765->tme_nec765_mutex); + } + } while (again); + /* clear that callouts are running: */ + nec765->tme_nec765_callout_flags &= ~TME_NEC765_CALLOUTS_RUNNING; + } + /* the nec765 bus cycle handler: */ static int _tme_nec765_bus_cycle(void *_nec765, *************** *** 191,196 **** --- 255,262 ---- /* lock the mutex: */ tme_mutex_lock(&nec765->tme_nec765_mutex); + + nec765->tme_nec765_int_asserted = FALSE; /* set the register offset: */ reg_offset *************** *** 223,228 **** --- 289,295 ---- /* if we need to soft-reset the chip: */ if (value & TME_NEC765_I82072_DRS_RESET) { _tme_nec765_reset(nec765, FALSE); + nec765->tme_nec765_int_asserted = TRUE; } reg = "DRS"; *************** *** 275,280 **** --- 342,348 ---- /* return a unit check, drive not ready ST0: */ TME_NEC765_STATUS(nec765, 0, (TME_NEC765_ST0_UC | TME_NEC765_ST0_NR)); + nec765->tme_nec765_int_asserted = TRUE; } } *************** *** 302,308 **** TME_NEC765_CMD_DONE(nec765); } } ! /* otherwise, this is an unknown command: */ else { abort(); --- 370,385 ---- TME_NEC765_CMD_DONE(nec765); } } ! /* the recalibrate command: */ ! else if (TME_NEC765_CMD_RECALIBRATE(nec765)) { ! /* the dump registers command is a two-byte command: */ ! if (fifo_head == (sizeof(tme_uint8_t) * 2)) { ! /* return a unit check, drive not ready ST0: */ ! TME_NEC765_STATUS(nec765, 0, (TME_NEC765_ST0_UC)); ! /*TME_NEC765_CMD_DONE(nec765);*/ ! /*nec765->tme_nec765_int_asserted = TRUE;*/ ! } ! } /* otherwise, this is an unknown command: */ else { abort(); *************** *** 313,319 **** break; default: ! abort(); } tme_log(TME_NEC765_LOG_HANDLE(nec765), 1000, TME_OK, (TME_NEC765_LOG_HANDLE(nec765), --- 390,397 ---- break; default: ! reg = "(invalid)"; ! /*abort();*/ } tme_log(TME_NEC765_LOG_HANDLE(nec765), 1000, TME_OK, (TME_NEC765_LOG_HANDLE(nec765), *************** *** 365,372 **** value = nec765->tme_nec765_status_fifo[fifo_tail]; nec765->tme_nec765_status_fifo_tail = fifo_tail + 1; reg = "FIFO (status)"; - } else { abort(); } --- 443,450 ---- value = nec765->tme_nec765_status_fifo[fifo_tail]; nec765->tme_nec765_status_fifo_tail = fifo_tail + 1; reg = "FIFO (status)"; + } else { abort(); } *************** *** 374,380 **** break; default: ! abort(); } tme_log(TME_NEC765_LOG_HANDLE(nec765), 1000, TME_OK, --- 452,460 ---- break; default: ! reg = "(unknown)"; ! value = 0; ! /*abort();*/ } tme_log(TME_NEC765_LOG_HANDLE(nec765), 1000, TME_OK, *************** *** 388,393 **** --- 468,476 ---- &value - address, address); } + + /* make any new callouts */ + _tme_nec765_callout(nec765); /* unlock the mutex: */ tme_mutex_unlock(&nec765->tme_nec765_mutex); diff -r -C 3 tme-0.6.orig/ic/z8530.c tme-0.6/ic/z8530.c *** tme-0.6.orig/ic/z8530.c Sat Aug 25 14:53:51 2007 --- tme-0.6/ic/z8530.c Wed Jan 27 23:11:06 2010 *************** *** 548,553 **** --- 548,554 ---- return (rr3 > z8530->tme_z8530_ius ? rr3 : 0); + /*return (rr3);*/ } /* this does an interrupt acknowledge. it returns TME_OK iff an *************** *** 587,593 **** } /* if the chip's IEI pin is tied low, return no vector: */ ! else if (z8530->tme_z8530_socket.tme_z8530_socket_flags & TME_Z8530_SOCKET_FLAG_IEI_TIED_LOW) { *_vector = TME_BUS_INTERRUPT_VECTOR_UNDEF; } --- 588,594 ---- } /* if the chip's IEI pin is tied low, return no vector: */ ! else if (z8530->tme_z8530_socket.tme_z8530_socket_flags & (TME_Z8530_SOCKET_FLAG_IEI_TIED_LOW | TME_Z8530_SOCKET_FLAG_NO_INTACK)) { *_vector = TME_BUS_INTERRUPT_VECTOR_UNDEF; } *************** *** 632,638 **** int callouts; int later_callouts_a, later_callouts_b, *_later_callouts; int rc; ! /* add in any new callouts: */ chan->tme_z8530_chan_callout_flags |= new_callouts; --- 633,639 ---- int callouts; int later_callouts_a, later_callouts_b, *_later_callouts; int rc; ! /* add in any new callouts: */ chan->tme_z8530_chan_callout_flags |= new_callouts; *************** *** 1073,1079 **** break; case TME_Z8530_WR0_CMD_RESET_TX: ! /* get the IP_TX bit for this channel: */ rr3_ip_tx = ((chan == &z8530->tme_z8530_chan_a) ? TME_Z8530_RR3_CHAN_A_IP_TX --- 1074,1080 ---- break; case TME_Z8530_WR0_CMD_RESET_TX: ! /* get the IP_TX bit for this channel: */ rr3_ip_tx = ((chan == &z8530->tme_z8530_chan_a) ? TME_Z8530_RR3_CHAN_A_IP_TX *************** *** 1127,1132 **** --- 1128,1134 ---- transmit Interrupt Pending bit works this way. is the SCC manual wrong? in any case, if TME_Z8530_WR1_TX_INT_ENABLE is clear, clear the IP_TX bit for this channel: */ + #if 0 if (!(value & TME_Z8530_WR1_TX_INT_ENABLE)) { /* get the IP_TX bit for this channel: */ *************** *** 1140,1146 **** new_callouts |= TME_Z8530_CALLOUT_INT; } } ! break; /* WR2: */ --- 1142,1148 ---- new_callouts |= TME_Z8530_CALLOUT_INT; } } ! #endif break; /* WR2: */ *************** *** 1188,1193 **** --- 1190,1203 ---- /* update RR1: */ chan->tme_z8530_chan_rdreg[1] &= ~TME_Z8530_RR1_ALL_SENT; + + if (z8530->tme_z8530_socket.tme_z8530_socket_flags & TME_Z8530_SOCKET_FLAG_NO_INTACK + && z8530->tme_z8530_wr9 & TME_Z8530_WR9_MIE){ + z8530->tme_z8530_ius = 0; + /* update RR2: */ + _tme_z8530_rr2_update(z8530); + new_callouts |= TME_Z8530_CALLOUT_INT; + } break; /* WR9: */ *************** *** 1254,1260 **** /* otherwise, this is a read: */ else { assert(cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_READ); - /* dispatch on the register pointer: */ switch (register_pointer) { --- 1264,1269 ---- *************** *** 1296,1301 **** --- 1305,1317 ---- refill it: */ value = chan->tme_z8530_chan_rdreg[8]; new_callouts |= _tme_z8530_rx_fifo_refill(z8530, chan); + if (z8530->tme_z8530_socket.tme_z8530_socket_flags & TME_Z8530_SOCKET_FLAG_NO_INTACK + && z8530->tme_z8530_wr9 & TME_Z8530_WR9_MIE){ + z8530->tme_z8530_ius = 0; + /* update RR2: */ + _tme_z8530_rr2_update(z8530); + new_callouts |= TME_Z8530_CALLOUT_INT; + } break; /* RR10: */ *************** *** 1344,1350 **** value)); } #endif /* !TME_NO_LOG */ ! /* run the bus cycle: */ buffer = value; cycle_resp.tme_bus_cycle_buffer = &buffer; --- 1360,1373 ---- value)); } #endif /* !TME_NO_LOG */ ! if (z8530->tme_z8530_socket.tme_z8530_socket_flags & TME_Z8530_SOCKET_FLAG_NO_INTACK ! /*&& z8530->tme_z8530_wr9 & TME_Z8530_WR9_MIE){*/ ! && new_callouts & TME_Z8530_CALLOUT_INT){ ! z8530->tme_z8530_ius = 0; ! /* update RR2: */ ! _tme_z8530_rr2_update(z8530); ! /*new_callouts |= TME_Z8530_CALLOUT_INT;*/ ! } /* run the bus cycle: */ buffer = value; cycle_resp.tme_bus_cycle_buffer = &buffer; diff -r -C 3 tme-0.6.orig/tme/ic/z8530.h tme-0.6/tme/ic/z8530.h *** tme-0.6.orig/tme/ic/z8530.h Thu Aug 23 19:09:06 2007 --- tme-0.6/tme/ic/z8530.h Wed Jan 27 22:29:59 2010 *************** *** 48,53 **** --- 48,54 ---- /* socket flags: */ #define TME_Z8530_SOCKET_FLAG_IEI_TIED_LOW (1 << 0) + #define TME_Z8530_SOCKET_FLAG_NO_INTACK (1 << 1) /* structures: */ struct tme_z8530_socket { diff -r -C 3 tme-0.6.orig/tme/machine/sun.h tme-0.6/tme/machine/sun.h *** tme-0.6.orig/tme/machine/sun.h Thu Aug 23 19:09:40 2007 --- tme-0.6/tme/machine/sun.h Wed Jan 27 22:29:59 2010 *************** *** 54,60 **** /* classic Sun z8530 socket: */ #define TME_SUN_Z8530_SOCKET_INIT { \ TME_Z8530_SOCKET_0, /* the socket version */ \ ! 0, /* socket flags */ \ 4, /* the bus address of channel A */ \ 0, /* the bus address of channel B */ \ 0, /* within each channel, the offset of the csr register */ \ --- 54,60 ---- /* classic Sun z8530 socket: */ #define TME_SUN_Z8530_SOCKET_INIT { \ TME_Z8530_SOCKET_0, /* the socket version */ \ ! TME_Z8530_SOCKET_FLAG_NO_INTACK, /* socket flags */ \ 4, /* the bus address of channel A */ \ 0, /* the bus address of channel B */ \ 0, /* within each channel, the offset of the csr register */ \