summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/machine/sgi.cpp
blob: f1fe3f20a215dd55931a11222f390165ebcb01e0 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13

                               










                                                                      







                                
                                

                                                                                        
                           
                     
 
                                                                            
 
                                                                                                             


                                                      
                                  
                               
                               
                              




















                                    






                             
                      



                                  


 


                                            
                                          

 




                                                   
 
                                     
                                          
 


                                               


                                             
                                       







                                           
                                      












                                                 

                                            






                                          
                                   
                                       




                                               
 

                                  























                                    




                                          






                             
                      
                          

                                                                                          


                                  

                                                
 
 
                                                                       


                                        








                                                         

 



                                                       
                                                                                       
                 
                                                                             







                                                                                                                                  
                                   
 













                                                    
                 

                                             
                         
















                                                                                                                   
 









                                                                                                                                  
 








                                                                    
 









                                                                                                                          
 

                                                                             

                                 


                                              
                         



                                                                 

                         











                                             
                                               


         
                                  
 
                            
         







                                                                                                                                                    

                                                                                                                                      
                      

                                                                                                                            
                      
                                                                                                                                    
                                      







                                                                                                                          

                                                                                                                                                
                      

                                                                                                                                
                      

                                                                                                                                                   
                      

                                                                                                                                         
                      

                                                                                                                                                  







                                                                                                                                                                      

                                                                                                                                                                 
                      

                                                                                                                                                                 
                      

                                                                                                                                            
                      

                                                                                                                                             
                      

                                                                                                                                            
                      

                                                                                                                                             
                      

                                                                                                                                          
                      

                                                                                                                             
                      

                                                                                                                               
                      
                                                                                                                                                                         
                                              
                      
                                                                                                                                                                                       
                                               
                      
                                                                                                                                                  
                                       
                      
                                                                                                                                             
                                     
                      

                                                                                                                                                              
                      

                                                                                                                                                             
                      

                                                                                                                                                              
                      

                                                                                                                                                             
                      

                                                                                                                                                              
                      

                                                                                                                                                             
                      

                                                                                                                                                              
                      

                                                                                                                                                             
                      
                                                                                                                                          
                                      

                      
                                                                                                                                                     
                                      
                      
                                                                                                                                                       
                                  
                      
                                                                                                                                                         
                                    

                      
                                                                                                                                                      
                                        
                      
                                                                                                                                        
                                  
                      
                                                                                                                                              
                                   
                      
                                                                                                     
                         
                      

                                        
                 
                                                                                                                                             
                 

                                 















                       
         



                                                                                                                                  


                            
                                                                                                                                                         
                         
         


                 
                                      
 
                            
         





                                                                                                                                      
                      

                      

                                                                                                    
                      
                      
                                                                                                                           



                                                                   
                      
                      

                                                                                                                     



                                                  
                      
                      

                                                                                                                                      
                      
                      

                                                                                                                                        
                      
                      

                                                                                                                                 
                      
                      

                                                                                                                                        
                      


















                                                                                                                                                                                
                      

                      

                                                                                                                                                
                      
                      

                                                                                                                                                
                      
                      
                                                                                                    
                                                         
                                       
                      
                      
                                                                                                    
                                                         
                                       
                      
                      

                                                                                                                                 
                      
                      

                                                                                                                         
                      
                      

                                                                                                                          
                      
                      
                                                                                                                                                         
                                              
                      
                      
                                                                                                                                                                      
                                               
                      
                      
                                                                                                                                              
                                       

                                                      
                      
                      
                                                                                                                                      
                                     
                      
                      

                                                                                                                                               
                      
                      

                                                                                                                                              
                      
                      

                                                                                                                                               
                      
                      

                                                                                                                                              
                      
                      

                                                                                                                                               
                      
                      

                                                                                                                                              
                      
                      

                                                                                                                                               
                      
                      

                                                                                                                                              
                      
                      
                                                                                                                                             
                                      
                      
                      
                                                                                                                                                              
                                      
                      
                      


                                                                                                                                                   
                                  
                      
                      


                                                                                                                                                   
                                    
                      
                      
                                                                                                                                            
                                        
                      
                      

                                                                                                                                                        
                                        
                                  
                                                                                                       
                      
         
                      
                                                                                                                                   
                                  
                      
                      
                                                                                                                                                      
                                   
                      
                      





                                                                                                                                    
                      
                      
                                                                                                                                                                               
                                        





                                                                                                 
                      



















                                                                                                                                    
                      
         
                
                                                                                                                                                                       



                      
                                                                                            
 








                                                                    

                                 
                                
         
 
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/*********************************************************************

    sgi.c

    Silicon Graphics MC (Memory Controller) code

*********************************************************************/

#include "emu.h"
#include "sgi.h"

#define LOG_UNKNOWN     (1 << 0)
#define LOG_READS       (1 << 1)
#define LOG_WRITES      (1 << 2)
#define LOG_RPSS        (1 << 3)
#define LOG_WATCHDOG    (1 << 4)
#define LOG_MEMCFG      (1 << 5)
#define LOG_MEMCFG_EXT  (1 << 6)
#define LOG_EEPROM      (1 << 7)
#define LOG_DMA         (1 << 8)
#define LOG_DEFAULT     (LOG_READS | LOG_WRITES | LOG_RPSS | LOG_WATCHDOG | LOG_UNKNOWN)

#define VERBOSE         (0)
#include "logmacro.h"

DEFINE_DEVICE_TYPE(SGI_MC, sgi_mc_device, "sgi_mc", "SGI Memory Controller")

sgi_mc_device::sgi_mc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, SGI_MC, tag, owner, clock)
	, m_maincpu(*this, finder_base::DUMMY_TAG)
	, m_eeprom(*this, finder_base::DUMMY_TAG)
	, m_int_dma_done_cb(*this)
	, m_eisa_present(*this)
	, m_rpss_timer(nullptr)
	, m_dma_timer(nullptr)
	, m_watchdog(0)
	, m_sys_id(0)
	, m_rpss_divider(0)
	, m_refcnt_preload(0)
	, m_refcnt(0)
	, m_gio64_arb_param(0)
	, m_arb_cpu_time(0)
	, m_arb_burst_time(0)
	, m_cpu_mem_access_config(0)
	, m_gio_mem_access_config(0)
	, m_cpu_error_addr(0)
	, m_cpu_error_status(0)
	, m_gio_error_addr(0)
	, m_gio_error_status(0)
	, m_sys_semaphore(0)
	, m_gio_lock(0)
	, m_eisa_lock(0)
	, m_gio64_translate_mask(0)
	, m_gio64_substitute_bits(0)
	, m_dma_int_cause(0)
	, m_dma_control(0)
	, m_rpss_counter(0)
	, m_dma_mem_addr(0)
	, m_dma_size(0)
	, m_dma_stride(0)
	, m_dma_gio64_addr(0)
	, m_dma_mode(0)
	, m_dma_count(0)
	, m_dma_run(0)
	, m_eeprom_ctrl(0)
	, m_rpss_divide_counter(0)
	, m_rpss_divide_count(0)
	, m_rpss_increment(0)
{
}

void sgi_mc_device::device_resolve_objects()
{
	m_int_dma_done_cb.resolve_safe();
	m_eisa_present.resolve_safe(true);
}

//-------------------------------------------------
//  device_start - device-specific startup
//-------------------------------------------------

void sgi_mc_device::device_start()
{
	m_sys_id = 0x03; // rev. C MC
	m_sys_id |= m_eisa_present() << 4;

	m_rpss_timer = timer_alloc(TIMER_RPSS);
	m_rpss_timer->adjust(attotime::never);

	m_dma_timer = timer_alloc(TIMER_DMA);
	m_dma_timer->adjust(attotime::never);

	save_item(NAME(m_cpu_control));
	save_item(NAME(m_watchdog));
	save_item(NAME(m_sys_id));
	save_item(NAME(m_rpss_divider));
	save_item(NAME(m_refcnt_preload));
	save_item(NAME(m_refcnt));
	save_item(NAME(m_gio64_arb_param));
	save_item(NAME(m_arb_cpu_time));
	save_item(NAME(m_arb_burst_time));
	save_item(NAME(m_mem_config));
	save_item(NAME(m_cpu_mem_access_config));
	save_item(NAME(m_gio_mem_access_config));
	save_item(NAME(m_cpu_error_addr));
	save_item(NAME(m_cpu_error_status));
	save_item(NAME(m_gio_error_addr));
	save_item(NAME(m_gio_error_status));
	save_item(NAME(m_sys_semaphore));
	save_item(NAME(m_gio_lock));
	save_item(NAME(m_eisa_lock));
	save_item(NAME(m_gio64_translate_mask));
	save_item(NAME(m_gio64_substitute_bits));
	save_item(NAME(m_dma_int_cause));
	save_item(NAME(m_dma_control));
	save_item(NAME(m_dma_tlb_entry_hi));
	save_item(NAME(m_dma_tlb_entry_lo));
	save_item(NAME(m_rpss_counter));
	save_item(NAME(m_dma_mem_addr));
	save_item(NAME(m_dma_size));
	save_item(NAME(m_dma_stride));
	save_item(NAME(m_dma_gio64_addr));
	save_item(NAME(m_dma_mode));
	save_item(NAME(m_dma_count));
	save_item(NAME(m_dma_run));
	save_item(NAME(m_eeprom_ctrl));
	save_item(NAME(m_semaphore));
	save_item(NAME(m_rpss_divide_counter));
	save_item(NAME(m_rpss_divide_count));
	save_item(NAME(m_rpss_increment));
}

void sgi_mc_device::device_reset()
{
	m_cpu_control[0] = 0;
	m_cpu_control[1] = 0;
	m_watchdog = 0;
	m_rpss_divider = 0x0104;
	m_refcnt_preload = 0;
	m_refcnt = 0;
	m_gio64_arb_param = 0;
	m_arb_cpu_time = 0;
	m_arb_burst_time = 0;
	m_mem_config[0] = 0;
	m_mem_config[1] = 0;
	m_cpu_mem_access_config = 0;
	m_gio_mem_access_config = 0;
	m_cpu_error_addr = 0;
	m_cpu_error_status = 0;
	m_gio_error_addr = 0;
	m_gio_error_status = 0;
	m_sys_semaphore = 0;
	m_gio_lock = 0;
	m_eisa_lock = 0;
	m_gio64_translate_mask = 0;
	m_gio64_substitute_bits = 0;
	m_dma_int_cause = 0;
	m_dma_control = 0;
	for (int i = 0; i < 4; i++)
	{
		m_dma_tlb_entry_hi[i] = 0;
		m_dma_tlb_entry_lo[i] = 0;
	}
	m_rpss_counter = 0;
	m_dma_mem_addr = 0;
	m_dma_size = 0;
	m_dma_stride = 0;
	m_dma_gio64_addr = 0;
	m_dma_mode = 0;
	m_dma_count = 0;
	m_dma_run = 0;
	m_eeprom_ctrl = 0;
	memset(m_semaphore, 0, sizeof(uint32_t) * 16);
	m_rpss_timer->adjust(attotime::from_hz(10000000), 0, attotime::from_hz(10000000));
	m_rpss_divide_counter = 4;
	m_rpss_divide_count = 4;
	m_rpss_increment = 1;

	m_space = &m_maincpu->space(AS_PROGRAM);
}

void sgi_mc_device::set_cpu_buserr(uint32_t address, uint64_t mem_mask)
{
	m_cpu_error_addr = address;
	m_cpu_error_status = 0x00000400;
	uint64_t mask = 0x00000000000000ffULL;
	for (uint32_t bit = 0; bit < 8; bit++)
	{
		if (mem_mask & mask)
		{
			m_cpu_error_status |= (1 << bit);
		}
		mask <<= 8;
	}
}

uint32_t sgi_mc_device::dma_translate(uint32_t address)
{
	for (int entry = 0; entry < 4; entry++)
	{
		if ((address & 0xffc00000) == (m_dma_tlb_entry_hi[entry] & 0xffc00000))
		{
			const uint32_t vpn_lo = (address & 0x003ff000) >> 12;
			const uint32_t pte = m_space->read_dword(((m_dma_tlb_entry_lo[entry] & 0x003fffc0) << 6) + (vpn_lo << 2));
			const uint32_t offset = address & 0xfff;
			return ((pte & 0x03ffffc0) << 6) + offset;
		}
	}
	return 0;
}

void sgi_mc_device::dma_immediate()
{
	uint32_t memory_addr = m_dma_mem_addr;
	uint32_t linecount = get_line_count();
	uint32_t zoomcount = get_zoom_count();
	uint32_t bytecount = get_byte_count();
	const uint32_t gio_addr = m_dma_gio64_addr;
	const uint32_t linewidth = get_line_width();
	const uint32_t linezoom = get_line_zoom();
	const uint32_t stride = get_stride();
	m_dma_size &= 0x0000ffff;
	m_dma_count = 0;
	while (linecount > 0)
	{
		linecount--;
		while (zoomcount > 0)
		{
			zoomcount--;
			while (bytecount > 0)
			{
				if (m_dma_mode & MODE_TO_HOST)
				{
					if (m_dma_mode & MODE_FILL)
					{   // Fill mode
						m_space->write_dword(dma_translate(memory_addr), m_dma_gio64_addr);
						if (m_dma_mode & MODE_DIR)
							memory_addr += 4;
						else
							memory_addr -= 4;
						bytecount -= 4;
					}
					else
					{
						uint32_t length = 8;
						uint64_t shift = 56;
						if (bytecount < 8)
							length = bytecount;

						uint64_t data = m_space->read_qword(gio_addr);
						for (uint32_t i = 0; i < length; i++)
						{
							m_space->write_byte(dma_translate(memory_addr), (uint8_t)(data >> shift));
							if (m_dma_mode & MODE_DIR)
								memory_addr++;
							else
								memory_addr--;
							shift -= 8;
						}

						bytecount -= length;
					}
				}
				else
				{
					uint32_t length = 8;
					uint64_t shift = 56;
					if (bytecount < 8)
						length = bytecount;

					uint64_t data = 0;
					for (uint32_t i = 0; i < length; i++)
					{
						data |= (uint64_t)m_space->read_byte(dma_translate(memory_addr)) << shift;
						if (m_dma_mode & MODE_DIR)
							memory_addr++;
						else
							memory_addr--;
						shift -= 8;
					}

					m_space->write_qword(gio_addr, data);
					bytecount -= length;
				}
			}
			bytecount = linewidth;

			if (zoomcount > 0)
			{
				if (m_dma_mode & MODE_DIR)
					memory_addr -= linewidth;
				else
					memory_addr += linewidth;
			}
		}
		zoomcount = linezoom;
		memory_addr += stride;
	}

	m_dma_mem_addr = memory_addr;

	m_dma_timer->adjust(attotime::never);
	m_dma_run |= (1 << 3);
	m_dma_run &= ~(1 << 6);
	if (BIT(m_dma_control, 4))
	{
		m_dma_int_cause |= (1 << 3);
		m_int_dma_done_cb(ASSERT_LINE);
	}
}

READ32_MEMBER(sgi_mc_device::read)
{
	switch (offset & ~1)
	{
	case 0x0000/4:
	case 0x0008/4:
	{
		const uint32_t index = (offset >> 3) & 1;
		LOGMASKED(LOG_READS, "%s: CPU Control %d Read: %08x & %08x\n", machine().describe_context(), index, m_cpu_control[index], mem_mask);
		return m_cpu_control[index];
	}
	case 0x0010/4:
		LOGMASKED(LOG_WATCHDOG, "%s: Watchdog Timer Read: %08x & %08x\n", machine().describe_context(), m_watchdog, mem_mask);
		return m_watchdog;
	case 0x0018/4:
		LOGMASKED(LOG_READS, "%s: System ID Read: %08x & %08x\n", machine().describe_context(), m_sys_id, mem_mask);
		return m_sys_id;
	case 0x0028/4:
		LOGMASKED(LOG_RPSS, "%s: RPSS Divider Read: %08x & %08x\n", machine().describe_context(), m_rpss_divider, mem_mask);
		return m_rpss_divider;
	case 0x0030/4:
	{
		// Disabled - we don't have a dump from real hardware, and IRIX 5.x freaks out with default contents.
		uint32_t ret = (m_eeprom_ctrl & ~0x10);// | m_eeprom->do_read() << 4;
		LOGMASKED(LOG_READS, "%s: R4000 EEPROM Read: %08x & %08x\n", machine().describe_context(), ret, mem_mask);
		return ret;
	}
	case 0x0040/4:
		LOGMASKED(LOG_READS, "%s: Refresh Count Preload Read: %08x & %08x\n", machine().describe_context(), m_refcnt_preload, mem_mask);
		return m_refcnt_preload;
	case 0x0048/4:
		LOGMASKED(LOG_READS, "%s: Refresh Count Read: %08x & %08x\n", machine().describe_context(), m_refcnt, mem_mask);
		return m_refcnt;
	case 0x0080/4:
		LOGMASKED(LOG_READS, "%s: GIO64 Arbitration Param Read: %08x & %08x\n", machine().describe_context(), m_gio64_arb_param, mem_mask);
		return m_gio64_arb_param;
	case 0x0088/4:
		LOGMASKED(LOG_READS, "%s: Arbiter CPU Time Read: %08x & %08x\n", machine().describe_context(), m_arb_cpu_time, mem_mask);
		return m_arb_cpu_time;
	case 0x0098/4:
		LOGMASKED(LOG_READS, "%s: Arbiter Long Burst Time Read: %08x & %08x\n", machine().describe_context(), m_arb_burst_time, mem_mask);
		return m_arb_burst_time;
	case 0x00c0/4:
	case 0x00c8/4:
	{
		const uint32_t index = (offset >> 1) & 1;
		LOGMASKED(LOG_MEMCFG, "%s: Memory Configuration Register %d Read: %08x & %08x\n", machine().describe_context(), index, m_mem_config[index], mem_mask);
		return m_mem_config[index];
	}
	case 0x00d0/4:
		LOGMASKED(LOG_READS, "%s: CPU Memory Access Config Params Read: %08x & %08x\n", machine().describe_context(), m_cpu_mem_access_config, mem_mask);
		return m_cpu_mem_access_config;
	case 0x00d8/4:
		LOGMASKED(LOG_READS, "%s: GIO Memory Access Config Params Read: %08x & %08x\n", machine().describe_context(), m_gio_mem_access_config, mem_mask);
		return m_gio_mem_access_config;
	case 0x00e0/4:
		LOGMASKED(LOG_READS, "%s: CPU Error Address Read: %08x & %08x\n", machine().describe_context(), m_cpu_error_addr, mem_mask);
		return m_cpu_error_addr;
	case 0x00e8/4:
		LOGMASKED(LOG_READS, "%s: CPU Error Status Read: %08x & %08x\n", machine().describe_context(), m_cpu_error_status, mem_mask);
		return m_cpu_error_status;
	case 0x00f0/4:
		LOGMASKED(LOG_READS, "%s: GIO Error Address Read: %08x & %08x\n", machine().describe_context(), m_gio_error_addr, mem_mask);
		return m_gio_error_addr;
	case 0x00f8/4:
		LOGMASKED(LOG_READS, "%s: GIO Error Status Read: %08x & %08x\n", machine().describe_context(), m_gio_error_status, mem_mask);
		return m_gio_error_status;
	case 0x0100/4:
		LOGMASKED(LOG_READS, "%s: System Semaphore Read: %08x & %08x\n", machine().describe_context(), m_sys_semaphore, mem_mask);
		return m_sys_semaphore;
	case 0x0108/4:
		LOGMASKED(LOG_READS, "%s: GIO Lock Read: %08x & %08x\n", machine().describe_context(), m_gio_lock, mem_mask);
		return m_gio_lock;
	case 0x0110/4:
		LOGMASKED(LOG_READS, "%s: EISA Lock Read: %08x & %08x\n", machine().describe_context(), m_eisa_lock, mem_mask);
		return m_eisa_lock;
	case 0x0150/4:
		LOGMASKED(LOG_READS | LOG_DMA, "%s: GIO64 Translation Address Mask Read: %08x & %08x\n", machine().describe_context(), m_gio64_translate_mask, mem_mask);
		return m_gio64_translate_mask;
	case 0x0158/4:
		LOGMASKED(LOG_READS | LOG_DMA, "%s: GIO64 Translation Address Substitution Bits Read: %08x & %08x\n", machine().describe_context(), m_gio64_substitute_bits, mem_mask);
		return m_gio64_substitute_bits;
	case 0x0160/4:
		LOGMASKED(LOG_READS | LOG_DMA, "%s: DMA Interrupt Cause: %08x & %08x\n", machine().describe_context(), m_dma_int_cause, mem_mask);
		return m_dma_int_cause;
	case 0x0168/4:
		LOGMASKED(LOG_READS | LOG_DMA, "%s: DMA Control Read: %08x & %08x\n", machine().describe_context(), m_dma_control, mem_mask);
		return m_dma_control;
	case 0x0180/4:
		LOGMASKED(LOG_READS | LOG_DMA, "%s: DMA TLB Entry 0 High Read: %08x & %08x\n", machine().describe_context(), m_dma_tlb_entry_hi[0], mem_mask);
		return m_dma_tlb_entry_hi[0];
	case 0x0188/4:
		LOGMASKED(LOG_READS | LOG_DMA, "%s: DMA TLB Entry 0 Low Read: %08x & %08x\n", machine().describe_context(), m_dma_tlb_entry_lo[0], mem_mask);
		return m_dma_tlb_entry_lo[0];
	case 0x0190/4:
		LOGMASKED(LOG_READS | LOG_DMA, "%s: DMA TLB Entry 1 High Read: %08x & %08x\n", machine().describe_context(), m_dma_tlb_entry_hi[1], mem_mask);
		return m_dma_tlb_entry_hi[1];
	case 0x0198/4:
		LOGMASKED(LOG_READS | LOG_DMA, "%s: DMA TLB Entry 1 Low Read: %08x & %08x\n", machine().describe_context(), m_dma_tlb_entry_lo[1], mem_mask);
		return m_dma_tlb_entry_lo[1];
	case 0x01a0/4:
		LOGMASKED(LOG_READS | LOG_DMA, "%s: DMA TLB Entry 2 High Read: %08x & %08x\n", machine().describe_context(), m_dma_tlb_entry_hi[2], mem_mask);
		return m_dma_tlb_entry_hi[2];
	case 0x01a8/4:
		LOGMASKED(LOG_READS | LOG_DMA, "%s: DMA TLB Entry 2 Low Read: %08x & %08x\n", machine().describe_context(), m_dma_tlb_entry_lo[2], mem_mask);
		return m_dma_tlb_entry_lo[2];
	case 0x01b0/4:
		LOGMASKED(LOG_READS | LOG_DMA, "%s: DMA TLB Entry 3 High Read: %08x & %08x\n", machine().describe_context(), m_dma_tlb_entry_hi[3], mem_mask);
		return m_dma_tlb_entry_hi[3];
	case 0x01b8/4:
		LOGMASKED(LOG_READS | LOG_DMA, "%s: DMA TLB Entry 3 Low Read: %08x & %08x\n", machine().describe_context(), m_dma_tlb_entry_lo[3], mem_mask);
		return m_dma_tlb_entry_lo[3];
	case 0x1000/4:
		LOGMASKED(LOG_RPSS, "%s: RPSS 100ns Counter Read: %08x & %08x\n", machine().describe_context(), m_rpss_counter, mem_mask);
		return m_rpss_counter;
	case 0x2000/4:
	case 0x2008/4:
		LOGMASKED(LOG_READS | LOG_DMA, "%s: DMA Memory Address Read: %08x & %08x\n", machine().describe_context(), m_dma_mem_addr, mem_mask);
		return m_dma_mem_addr;
	case 0x2010/4:
		LOGMASKED(LOG_READS | LOG_DMA, "%s: DMA Line Count and Width Read: %08x & %08x\n", machine().describe_context(), m_dma_size, mem_mask);
		return m_dma_size;
	case 0x2018/4:
		LOGMASKED(LOG_READS | LOG_DMA, "%s: DMA Line Zoom and Stride Read: %08x & %08x\n", machine().describe_context(), m_dma_stride, mem_mask);
		return m_dma_stride;
	case 0x2020/4:
	case 0x2028/4:
		LOGMASKED(LOG_READS | LOG_DMA, "%s: DMA GIO64 Address Read: %08x & %08x\n", machine().describe_context(), m_dma_gio64_addr, mem_mask);
		return m_dma_gio64_addr;
	case 0x2030/4:
		LOGMASKED(LOG_READS | LOG_DMA, "%s: DMA Mode Write: %08x & %08x\n", machine().describe_context(), m_dma_mode, mem_mask);
		return m_dma_mode;
	case 0x2038/4:
		LOGMASKED(LOG_READS | LOG_DMA, "%s: DMA Zoom Count Read: %08x & %08x\n", machine().describe_context(), m_dma_count, mem_mask);
		return m_dma_count;
	case 0x2040/4:
		LOGMASKED(LOG_READS | LOG_DMA, "%s: DMA Start Read\n", machine().describe_context());
		return 0;
	case 0x2048/4:
	{
		if (!(m_dma_run & 0x40))
		{
			LOGMASKED(LOG_READS | LOG_DMA, "%s: DMA Run Read: %08x & %08x\n", machine().describe_context(), m_dma_run, mem_mask);
		}
		return m_dma_run;
	}
	case 0x10000/4:
	case 0x11000/4:
	case 0x12000/4:
	case 0x13000/4:
	case 0x14000/4:
	case 0x15000/4:
	case 0x16000/4:
	case 0x17000/4:
	case 0x18000/4:
	case 0x19000/4:
	case 0x1a000/4:
	case 0x1b000/4:
	case 0x1c000/4:
	case 0x1d000/4:
	case 0x1e000/4:
	case 0x1f000/4:
	{
		const uint32_t index = (offset - 0x4000) >> 10;
		const uint32_t data = m_semaphore[index];
		LOGMASKED(LOG_READS, "%s: Semaphore %d Read: %08x & %08x\n", machine().describe_context(), index, data, mem_mask);
		m_semaphore[index] = 1;
		return data;
	}
	default:
		LOGMASKED(LOG_READS | LOG_UNKNOWN, "%s: Unmapped MC read: %08x & %08x\n", machine().describe_context(), 0x1fa00000 + offset*4, mem_mask);
		return 0;
	}
	return 0;
}

WRITE32_MEMBER( sgi_mc_device::write )
{
	switch (offset & ~1)
	{
	case 0x0000/4:
	case 0x0008/4:
	{
		const uint32_t index = (offset >> 1) & 1;
		LOGMASKED(LOG_WRITES, "%s: CPU Control %d Write: %08x & %08x\n", machine().describe_context(), index, data, mem_mask);
		m_cpu_control[index] = data;
		break;
	}
	case 0x0010/4:
		LOGMASKED(LOG_WATCHDOG, "%s: Watchdog Timer Clear\n", machine().describe_context());
		m_watchdog = 0;
		break;
	case 0x0028/4:
		LOGMASKED(LOG_RPSS, "%s: RPSS Divider Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_rpss_divider = data;
		m_rpss_divide_count = (int)(m_rpss_divider & 0xff);
		m_rpss_divide_counter = m_rpss_divide_count;
		m_rpss_increment = (m_rpss_divider >> 8) & 0xff;
		break;
	case 0x0030/4:
		LOGMASKED(LOG_WRITES, "%s: R4000 EEPROM Write: CS:%d, SCK:%d, SO:%d\n", machine().describe_context(),
			BIT(data, 1), BIT(data, 2), BIT(data, 3));
		m_eeprom_ctrl = data;
		m_eeprom->di_write(BIT(data, 3));
		m_eeprom->cs_write(BIT(data, 1));
		m_eeprom->clk_write(BIT(data, 2));
		break;
	case 0x0040/4:
		LOGMASKED(LOG_WRITES, "%s: Refresh Count Preload Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_refcnt_preload = data;
		break;
	case 0x0080/4:
		LOGMASKED(LOG_WRITES, "%s: GIO64 Arbitration Param Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_gio64_arb_param = data;
		break;
	case 0x0088/4:
		LOGMASKED(LOG_WRITES, "%s: Arbiter CPU Time Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_arb_cpu_time = data;
		break;
	case 0x0098/4:
		LOGMASKED(LOG_WRITES, "%s: Arbiter Long Burst Time Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_arb_burst_time = data;
		break;
	case 0x00c0/4:
	case 0x00c8/4:
	{
		static const char* const s_mem_size[32] = {
				"256Kx36", "512Kx36, 2 subbanks", "Invalid", "1Mx36", "Invalid", "Invalid", "Invalid", "2Mx36, 2 subbanks",
				"Invalid", "Invalid", "Invalid", "Invalid", "Invalid", "Invalid", "Invalid", "4Mx36",
				"Invalid", "Invalid", "Invalid", "Invalid", "Invalid", "Invalid", "Invalid", "Invalid",
				"Invalid", "Invalid", "Invalid", "Invalid", "Invalid", "Invalid", "Invalid", "8Mx36, 2 subbanks" };
		const uint32_t index = (offset >> 1) & 1;
		LOGMASKED(LOG_MEMCFG, "%s: Memory Configuration Register %d Write: %08x & %08x\n", machine().describe_context(), index, data, mem_mask);
		LOGMASKED(LOG_MEMCFG_EXT, "%s:     Bank %d, Base Address: %02x\n", machine().describe_context(), index, (data >> 16) & 0xff);
		LOGMASKED(LOG_MEMCFG_EXT, "%s:     Bank %d, SIMM Size: %02x (%s)\n", machine().describe_context(), index, (data >> 24) & 0x1f, s_mem_size[(data >> 24) & 0x1f]);
		LOGMASKED(LOG_MEMCFG_EXT, "%s:     Bank %d, Valid: %d\n", machine().describe_context(), index, BIT(data, 29));
		LOGMASKED(LOG_MEMCFG_EXT, "%s:     Bank %d, # Subbanks: %d\n", machine().describe_context(), index, BIT(data, 30) + 1);
		LOGMASKED(LOG_MEMCFG_EXT, "%s:     Bank %d, Base Address: %02x\n", machine().describe_context(), index+1, data & 0xff);
		LOGMASKED(LOG_MEMCFG_EXT, "%s:     Bank %d, SIMM Size: %02x (%s)\n", machine().describe_context(), index+1, (data >> 8) & 0x1f, s_mem_size[(data >> 8) & 0x1f]);
		LOGMASKED(LOG_MEMCFG_EXT, "%s:     Bank %d, Valid: %d\n", machine().describe_context(), index+1, BIT(data, 13));
		LOGMASKED(LOG_MEMCFG_EXT, "%s:     Bank %d, # Subbanks: %d\n", machine().describe_context(), index+1, BIT(data, 14) + 1);
		m_mem_config[index] = data;
		break;
	}
	case 0x00d0/4:
		LOGMASKED(LOG_WRITES, "%s: CPU Memory Access Config Params Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_cpu_mem_access_config = data;
		break;
	case 0x00d8/4:
		LOGMASKED(LOG_WRITES, "%s: GIO Memory Access Config Params Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_gio_mem_access_config = data;
		break;
	case 0x00e8/4:
		LOGMASKED(LOG_WRITES, "%s: CPU Error Status Clear\n", machine().describe_context());
		m_maincpu->set_input_line(4, CLEAR_LINE);
		m_cpu_error_status = 0;
		break;
	case 0x00f8/4:
		LOGMASKED(LOG_WRITES, "%s: GIO Error Status Clear\n", machine().describe_context());
		m_maincpu->set_input_line(4, CLEAR_LINE);
		m_gio_error_status = 0;
		break;
	case 0x0100/4:
		LOGMASKED(LOG_WRITES, "%s: System Semaphore Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_sys_semaphore = data;
		break;
	case 0x0108/4:
		LOGMASKED(LOG_WRITES, "%s: GIO Lock Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_gio_lock = data;
		break;
	case 0x0110/4:
		LOGMASKED(LOG_WRITES, "%s: EISA Lock Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_eisa_lock = data;
		break;
	case 0x0150/4:
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: GIO64 Translation Address Mask Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_gio64_translate_mask = data;
		break;
	case 0x0158/4:
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: GIO64 Translation Address Substitution Bits Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_gio64_substitute_bits = data;
		break;
	case 0x0160/4:
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: DMA Interrupt Cause Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_dma_int_cause = data;
		if (m_dma_int_cause == 0)
			m_int_dma_done_cb(CLEAR_LINE);
		break;
	case 0x0168/4:
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: DMA Control Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_dma_control = data;
		break;
	case 0x0180/4:
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: DMA TLB Entry 0 High Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_dma_tlb_entry_hi[0] = data;
		break;
	case 0x0188/4:
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: DMA TLB Entry 0 Low Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_dma_tlb_entry_lo[0] = data;
		break;
	case 0x0190/4:
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: DMA TLB Entry 1 High Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_dma_tlb_entry_hi[1] = data;
		break;
	case 0x0198/4:
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: DMA TLB Entry 1 Low Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_dma_tlb_entry_lo[1] = data;
		break;
	case 0x01a0/4:
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: DMA TLB Entry 2 High Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_dma_tlb_entry_hi[2] = data;
		break;
	case 0x01a8/4:
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: DMA TLB Entry 2 Low Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_dma_tlb_entry_lo[2] = data;
		break;
	case 0x01b0/4:
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: DMA TLB Entry 3 High Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_dma_tlb_entry_hi[3] = data;
		break;
	case 0x01b8/4:
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: DMA TLB Entry 3 Low Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_dma_tlb_entry_lo[3] = data;
		break;
	case 0x2000/4:
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: DMA Memory Address Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_dma_mem_addr = data;
		break;
	case 0x2008/4:
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: DMA Memory Address + Default Params Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_dma_mem_addr = data;
		break;
	case 0x2010/4:
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: DMA Line Count and Width Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_dma_count &= 0xffff0000;
		m_dma_count |= data & 0x0000ffff;
		m_dma_size = data;
		break;
	case 0x2018/4:
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: DMA Line Zoom and Stride Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_dma_count &= 0x0000ffff;
		m_dma_count |= data & 0x03ff0000;
		m_dma_stride = data;
		break;
	case 0x2020/4:
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: DMA GIO64 Address Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_dma_gio64_addr = data;
		break;
	case 0x2028/4:
	{
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: DMA GIO64 Address Write + Start DMA: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_dma_gio64_addr = data;
		m_dma_run |= 0x40;
		m_dma_timer->adjust(attotime::from_ticks(4, 33333333), 0, attotime::from_hz(33333333));
		break;
	}
	case 0x2030/4:
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: DMA Mode Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_dma_mode = data;
		break;
	case 0x2038/4:
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: DMA Zoom Count + Byte Count Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_dma_count = data;
		break;
	case 0x2040/4:
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: DMA Start Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		if (data & 1)
		{
			m_dma_run |= 0x40;
			m_dma_timer->adjust(attotime::from_hz(33333333), 0, attotime::from_hz(33333333));
		}
		break;
	case 0x2070/4:
		LOGMASKED(LOG_WRITES | LOG_DMA, "%s: DMA GIO64 Address Write + Default Params Write + Start DMA: %08x & %08x\n", machine().describe_context(), data, mem_mask);
		m_dma_gio64_addr = data;
		m_dma_size = 0x0001000c;
		m_dma_stride = 0x00010000;
		m_dma_count = 0x0001000c;
		m_dma_mode = 0x00000028;
		m_dma_run |= 0x40;
		m_dma_timer->adjust(attotime::from_hz(33333333), 0, attotime::from_hz(33333333));
		break;
	case 0x10000/4:
	case 0x11000/4:
	case 0x12000/4:
	case 0x13000/4:
	case 0x14000/4:
	case 0x15000/4:
	case 0x16000/4:
	case 0x17000/4:
	case 0x18000/4:
	case 0x19000/4:
	case 0x1a000/4:
	case 0x1b000/4:
	case 0x1c000/4:
	case 0x1d000/4:
	case 0x1e000/4:
	case 0x1f000/4:
	{
		const uint32_t index = (offset - 0x10000/4) >> 10;
		LOGMASKED(LOG_WRITES, "%s: Semaphore %d Write: %08x & %08x\n", machine().describe_context(), index, data, mem_mask);
		m_semaphore[index] = data & 1;
		break;
	}
	default:
		LOGMASKED(LOG_WRITES | LOG_UNKNOWN, "%s: Unmapped MC write: %08x: %08x & %08x\n", machine().describe_context(), 0x1fa00000 + offset*4, data, mem_mask);
		break;
	}
}

void sgi_mc_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
	if (id == TIMER_RPSS)
	{
		m_rpss_divide_counter--;
		if (m_rpss_divide_counter < 0)
		{
			m_rpss_divide_counter = m_rpss_divide_count;
			m_rpss_counter += m_rpss_increment;
		}
	}
	else if (id == TIMER_DMA)
	{
		dma_immediate();
	}
}