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 */ \
