Source to src/nbic.c


Enter a symbol's name here to quickly find it.

#include "main.h"
#include "configuration.h"
#include "m68000.h"
#include "sysdeps.h"
#include "nbic.h"

#define LOG_NEXTBUS_LEVEL   LOG_NONE

/* NeXTbus and NeXTbus Interface Chip emulation */

/* NBIC Registers */

struct {
	Uint32 control;
	Uint32 id;
	Uint8 intstatus;
	Uint8 intmask;
} nbic;


/* Control: 0x02020000 (rw), only non-Turbo */
#define NBIC_CTRL_IGNSID0	0x10000000 /* Ignore slot ID bit 0 */
#define NBIC_CTRL_STFWD		0x08000000 /* Store forward */
#define NBIC_CTRL_RMCOL		0x04000000 /* Read modify cycle collision */

/* ID: 0x02020004 (w), 0xF0FFFFFx (r), only non-Turbo */
#define NBIC_ID_VALID		0x80000000
#define NBIC_ID_M_MASK		0x7FFF0000 /* Manufacturer ID */
#define NBIC_ID_B_MASK		0x0000FFFF /* Board ID */

/* Interrupt: 0xF0FFFFE8 (r) */
#define NBIC_INT_STATUS		0x80

/* Interrupt mask: 0xF0FFFFEC (rw) */
#define NBIC_INT_MASK		0x80


/* Register access functions */
static Uint8 nbic_control_read0(Uint32 addr) {
	Log_Printf(LOG_WARN, "[NBIC] Control (byte 0) read at %08X",addr);
	return (nbic.control>>24);
}
static Uint8 nbic_control_read1(Uint32 addr) {
	Log_Printf(LOG_WARN, "[NBIC] Control (byte 1) read at %08X",addr);
	return (nbic.control>>16);
}
static Uint8 nbic_control_read2(Uint32 addr) {
	Log_Printf(LOG_WARN, "[NBIC] Control (byte 2) read at %08X",addr);
	return (nbic.control>>8);
}
static Uint8 nbic_control_read3(Uint32 addr) {
	Log_Printf(LOG_WARN, "[NBIC] Control (byte 3) read at %08X",addr);
	return nbic.control;
}

static void nbic_control_write0(Uint32 addr, Uint8 val) {
	Log_Printf(LOG_WARN, "[NBIC] Control (byte 0) write %02X at %08X",val,addr);
	nbic.control &= 0x00FFFFFF;
	nbic.control |= (val&0xFF)<<24;
}
static void nbic_control_write1(Uint32 addr, Uint8 val) {
	Log_Printf(LOG_WARN, "[NBIC] Control (byte 1) write %02X at %08X",val,addr);
	nbic.control &= 0xFF00FFFF;
	nbic.control |= (val&0xFF)<<16;
}
static void nbic_control_write2(Uint32 addr, Uint8 val) {
	Log_Printf(LOG_WARN, "[NBIC] Control (byte 2) write %02X at %08X",val,addr);
	nbic.control &= 0xFFFF00FF;
	nbic.control |= (val&0xFF)<<8;
}
static void nbic_control_write3(Uint32 addr, Uint8 val) {
	Log_Printf(LOG_WARN, "[NBIC] Control (byte 3) write %02X at %08X",val,addr);
	nbic.control &= 0xFFFFFF00;
	nbic.control |= val&0xFF;
}


static Uint8 nbic_id_read0(Uint32 addr) {
	Log_Printf(LOG_WARN, "[NBIC] ID (byte 0) read at %08X",addr);
	return (nbic.id>>24);
}
static Uint8 nbic_id_read1(Uint32 addr) {
	Log_Printf(LOG_WARN, "[NBIC] ID (byte 1) read at %08X",addr);
	return (nbic.id>>16);
}
static Uint8 nbic_id_read2(Uint32 addr) {
	Log_Printf(LOG_WARN, "[NBIC] ID (byte 2) read at %08X",addr);
	return (nbic.id>>8);
}
static Uint8 nbic_id_read3(Uint32 addr) {
	Log_Printf(LOG_WARN, "[NBIC] ID (byte 3) read at %08X",addr);
	return nbic.id;
}

static void nbic_id_write0(Uint32 addr, Uint8 val) {
	Log_Printf(LOG_WARN, "[NBIC] ID (byte 0) write %02X at %08X",val,addr);
	nbic.id &= 0x00FFFFFF;
	nbic.id |= (val&0xFF)<<24;
}
static void nbic_id_write1(Uint32 addr, Uint8 val) {
	Log_Printf(LOG_WARN, "[NBIC] ID (byte 1) write %02X at %08X",val,addr);
	nbic.id &= 0xFF00FFFF;
	nbic.id |= (val&0xFF)<<16;
}
static void nbic_id_write2(Uint32 addr, Uint8 val) {
	Log_Printf(LOG_WARN, "[NBIC] ID (byte 2) write %02X at %08X",val,addr);
	nbic.id &= 0xFFFF00FF;
	nbic.id |= (val&0xFF)<<8;
}
static void nbic_id_write3(Uint32 addr, Uint8 val) {
	Log_Printf(LOG_WARN, "[NBIC] ID (byte 3) write %02X at %08X",val,addr);
	nbic.id &= 0xFFFFFF00;
	nbic.id |= val&0xFF;
}

static Uint8 nbic_intstatus_read(Uint32 addr) {
	Log_Printf(LOG_WARN, "[NBIC] Interrupt status read at %08X",addr);
	return nbic.intstatus;
}

static Uint8 nbic_intmask_read(Uint32 addr) {
	Log_Printf(LOG_WARN, "[NBIC] Interrupt mask read at %08X",addr);
	return nbic.intmask;
}
static void nbic_intmask_write(Uint32 addr, Uint8 val) {
	Log_Printf(LOG_WARN, "[NBIC] Interrupt mask write %02X at %08X",val,addr);
	nbic.intmask = val;
}

static Uint8 nbic_zero_read(Uint32 addr) {
	Log_Printf(LOG_WARN, "[NBIC] zero read at %08X",addr);
	return 0;
}
static void nbic_zero_write(Uint32 addr, Uint8 val) {
	Log_Printf(LOG_WARN, "[NBIC] zero write %02X at %08X",val,addr);
}

static Uint8 nbic_bus_error_read(Uint32 addr) {
	Log_Printf(LOG_WARN, "[NBIC] bus error read at %08X",addr);
	M68000_BusError(addr, 1);
	return 0;
}
static void nbic_bus_error_write(Uint32 addr, Uint8 val) {
	Log_Printf(LOG_WARN, "[NBIC] bus error write at %08X",addr);
	M68000_BusError(addr, 0);
}


/* Direct register access */
static Uint8 (*nbic_read_reg[8])(Uint32) = {
	nbic_control_read0, nbic_control_read1, nbic_control_read2, nbic_control_read3,
	nbic_bus_error_read, nbic_bus_error_read, nbic_bus_error_read, nbic_bus_error_read
};

static void (*nbic_write_reg[8])(Uint32, Uint8) = {
	nbic_control_write0, nbic_control_write1, nbic_control_write2, nbic_control_write3,
	nbic_id_write0, nbic_id_write1, nbic_id_write2, nbic_id_write3
};


Uint32 nbic_reg_lget(Uint32 addr) {
	Uint32 val = 0;
	
	if (addr&3) {
		Log_Printf(LOG_WARN, "[NBIC] Unaligned access at %08X.",addr);
		abort();
	}
	
	if ((addr&0x0000FFFF)>7) {
		nbic_bus_error_read(addr);
	} else {
		val = nbic_read_reg[addr&7](addr)<<24;
		val |= nbic_read_reg[(addr&7)+1](addr+1)<<16;
		val |= nbic_read_reg[(addr&7)+2](addr+2)<<8;
		val |= nbic_read_reg[(addr&7)+3](addr+3);
	}
	
	return val;
}

Uint32 nbic_reg_wget(uaecptr addr) {
	Uint32 val = 0;
	
	if (addr&1) {
		Log_Printf(LOG_WARN, "[NBIC] Unaligned access at %08X.",addr);
		abort();
	}
	
	if ((addr&0x0000FFFF)>7) {
		nbic_bus_error_read(addr);
	} else {
		val = nbic_read_reg[addr&7](addr)<<8;
		val |= nbic_read_reg[(addr&7)+1](addr);
	}
	
	return val;
}

Uint32 nbic_reg_bget(uaecptr addr) {
	if ((addr&0x0000FFFF)>7) {
		return nbic_bus_error_read(addr);
	} else {
		return nbic_read_reg[addr&7](addr);
	}
}

void nbic_reg_lput(uaecptr addr, Uint32 l) {
	if (addr&3) {
		Log_Printf(LOG_WARN, "[NBIC] Unaligned access at %08X.",addr);
		abort();
	}
	
	if ((addr&0x0000FFFF)>7) {
		nbic_bus_error_write(addr,0);
	} else {
		nbic_write_reg[addr&7](addr,l>>24);
		nbic_write_reg[(addr&7)+1](addr,l>>16);
		nbic_write_reg[(addr&7)+2](addr,l>>8);
		nbic_write_reg[(addr&7)+3](addr,l);
	}
}

void nbic_reg_wput(uaecptr addr, Uint32 w) {
	if (addr&1) {
		Log_Printf(LOG_WARN, "[NBIC] Unaligned access at %08X.",addr);
		abort();
	}
	
	if ((addr&0x0000FFFF)>7) {
		nbic_bus_error_write(addr,0);
	} else {
		nbic_write_reg[addr&7](addr,w>>8);
		nbic_write_reg[(addr&7)+1](addr,w);
	}
}

void nbic_reg_bput(uaecptr addr, Uint32 b) {
	if ((addr&0x0000FFFF)>7) {
		nbic_bus_error_write(addr,0);
	} else {
		nbic_write_reg[addr&7](addr,b);
	}
}


/* NeXTbus CPU board slot space access */
static Uint8 (*nbic_read_cpu_slot[32])(Uint32) = {
	nbic_bus_error_read, nbic_bus_error_read, nbic_bus_error_read, nbic_bus_error_read,
	nbic_bus_error_read, nbic_bus_error_read, nbic_bus_error_read, nbic_bus_error_read,
	nbic_intstatus_read, nbic_zero_read, nbic_zero_read, nbic_zero_read,
	nbic_intmask_read, nbic_zero_read, nbic_zero_read, nbic_zero_read,

	nbic_id_read0, nbic_zero_read, nbic_zero_read, nbic_zero_read,
	nbic_id_read1, nbic_zero_read, nbic_zero_read, nbic_zero_read,
	nbic_id_read2, nbic_zero_read, nbic_zero_read, nbic_zero_read,
	nbic_id_read3, nbic_zero_read, nbic_zero_read, nbic_zero_read,
};

static void (*nbic_write_cpu_slot[32])(Uint32, Uint8) = {
	nbic_bus_error_write, nbic_bus_error_write, nbic_bus_error_write, nbic_bus_error_write,
	nbic_bus_error_write, nbic_bus_error_write, nbic_bus_error_write, nbic_bus_error_write,
	nbic_bus_error_write, nbic_bus_error_write, nbic_bus_error_write, nbic_bus_error_write,
	nbic_intmask_write, nbic_zero_write, nbic_zero_write, nbic_zero_write,
	
	nbic_bus_error_write, nbic_bus_error_write, nbic_bus_error_write, nbic_bus_error_write,
	nbic_bus_error_write, nbic_bus_error_write, nbic_bus_error_write, nbic_bus_error_write,
	nbic_bus_error_write, nbic_bus_error_write, nbic_bus_error_write, nbic_bus_error_write,
	nbic_bus_error_write, nbic_bus_error_write, nbic_bus_error_write, nbic_bus_error_write
};

Uint32 nb_cpu_slot_lget(Uint32 addr) {
    Uint32 val = 0;
    
    if (addr&3) {
        Log_Printf(LOG_WARN, "[NBIC] Unaligned access at %08X.",addr);
        abort();
    }
    
    if ((addr&0x00FFFFFF)<0x00FFFFE8) {
        nbic_bus_error_read(addr);
    } else {
        val = nbic_read_cpu_slot[addr&0x1F](addr)<<24;
        val |= nbic_read_cpu_slot[(addr&0x1F)+1](addr+1)<<16;
        val |= nbic_read_cpu_slot[(addr&0x1F)+2](addr+2)<<8;
        val |= nbic_read_cpu_slot[(addr&0x1F)+3](addr+3);
    }
    
    return val;
}

Uint16 nb_cpu_slot_wget(Uint32 addr) {
    Uint32 val = 0;
    
    if (addr&1) {
        Log_Printf(LOG_WARN, "[NBIC] Unaligned access at %08X.",addr);
        abort();
    }
    
    if ((addr&0x00FFFFFF)<0x00FFFFE8) {
        nbic_bus_error_read(addr);
    } else {
        val = nbic_read_cpu_slot[addr&0x1F](addr)<<8;
        val |= nbic_read_cpu_slot[(addr&0x1F)+1](addr+1)<<16;
    }
    
    return val;
}

Uint8 nb_cpu_slot_bget(Uint32 addr) {
    if ((addr&0x00FFFFFF)<0x00FFFFE8) {
        return nbic_bus_error_read(addr);
    } else {
        return nbic_read_cpu_slot[addr&0x1F](addr);
    }
}

void nb_cpu_slot_lput(Uint32 addr, Uint32 l) {
    if (addr&3) {
        Log_Printf(LOG_WARN, "[NBIC] Unaligned access at %08X.",addr);
        abort();
    }
    
    if ((addr&0x00FFFFFF)<0x00FFFFE8) {
        nbic_bus_error_write(addr,0);
    } else {
        nbic_write_cpu_slot[addr&0x1F](addr,l>>24);
        nbic_write_cpu_slot[(addr&0x1F)+1](addr,l>>16);
        nbic_write_cpu_slot[(addr&0x1F)+2](addr,l>>8);
        nbic_write_cpu_slot[(addr&0x1F)+3](addr,l);
    }
}

void nb_cpu_slot_wput(Uint32 addr, Uint16 w) {
    if (addr&1) {
        Log_Printf(LOG_WARN, "[NBIC] Unaligned access at %08X.",addr);
        abort();
    }
    
    if ((addr&0x00FFFFFF)<0x00FFFFE8) {
        nbic_bus_error_write(addr,0);
    } else {
        nbic_write_cpu_slot[addr&0x1F](addr,w>>8);
        nbic_write_cpu_slot[(addr&0x1F)+1](addr,w);
    }
}

void nb_cpu_slot_bput(Uint32 addr, Uint8 b) {
    if ((addr&0x00FFFFFF)<0x00FFFFE8) {
        nbic_bus_error_write(addr,0);
    } else {
        nbic_write_cpu_slot[addr&0x1F](addr,b);
    }
}