The NCR 53C810 is now threaded;
Reverted my IDIV fixes - fixes font glitches in Windows XP and possibly other things as well; Slight fix to line repeat detection in pclog_ex().
This commit is contained in:
@@ -463,31 +463,28 @@ int divl(uint32_t val)
|
|||||||
}
|
}
|
||||||
int idivl(int32_t val)
|
int idivl(int32_t val)
|
||||||
{
|
{
|
||||||
uint64_t templ;
|
int64_t num, quo;
|
||||||
int64_t tempsrc, tempws, tempws2 = 0;
|
int32_t rem, quo32;
|
||||||
|
|
||||||
if (val == 0) {
|
if (val==0)
|
||||||
divexcp(); /* Divide by zero. */
|
{
|
||||||
return 1;
|
divexcp();
|
||||||
}
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
templ = (uint64_t) EDX;
|
num=(((uint64_t)EDX)<<32)|EAX;
|
||||||
templ = (templ << 32) | EAX;
|
quo=num/val;
|
||||||
tempsrc = (int64_t) templ;
|
rem=num%val;
|
||||||
tempws = tempsrc / val;
|
quo32=(int32_t)(quo&0xFFFFFFFF);
|
||||||
|
|
||||||
if ((tempws > 2147483647LL) || (tempws < -2147483648LL)) {
|
if (quo!=(int64_t)quo32)
|
||||||
divexcp();
|
{
|
||||||
return 1;
|
divexcp();
|
||||||
}
|
return 1;
|
||||||
|
}
|
||||||
tempws = (int32_t) tempws;
|
EDX=rem;
|
||||||
tempws2 = (int32_t) (templ % val);
|
EAX=quo32;
|
||||||
|
return 0;
|
||||||
EDX = (int32_t) tempws2;
|
|
||||||
EAX = (int32_t) tempws;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -84,8 +84,12 @@ static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs)
|
|||||||
while (block)
|
while (block)
|
||||||
{
|
{
|
||||||
if (a == block->cmp)
|
if (a == block->cmp)
|
||||||
break;
|
{
|
||||||
else if (a < block->cmp)
|
if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
|
||||||
|
((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (a < block->cmp)
|
||||||
block = block->left;
|
block = block->left;
|
||||||
else
|
else
|
||||||
block = block->right;
|
block = block->right;
|
||||||
|
|||||||
@@ -64,9 +64,10 @@ static int opSETALC(uint32_t fetchdat)
|
|||||||
|
|
||||||
static int opF6_a16(uint32_t fetchdat)
|
static int opF6_a16(uint32_t fetchdat)
|
||||||
{
|
{
|
||||||
int32_t tempsrc, tempdst, tempws, tempws2 = 0;
|
int tempws, tempws2 = 0;
|
||||||
uint16_t tempw, src16;
|
uint16_t tempw, src16;
|
||||||
uint8_t src, dst;
|
uint8_t src, dst;
|
||||||
|
int8_t temps;
|
||||||
|
|
||||||
fetch_ea_16(fetchdat);
|
fetch_ea_16(fetchdat);
|
||||||
dst = geteab(); if (cpu_state.abrt) return 1;
|
dst = geteab(); if (cpu_state.abrt) return 1;
|
||||||
@@ -130,32 +131,24 @@ static int opF6_a16(uint32_t fetchdat)
|
|||||||
PREFETCH_RUN(is486 ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
PREFETCH_RUN(is486 ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
||||||
break;
|
break;
|
||||||
case 0x38: /*IDIV AL,b*/
|
case 0x38: /*IDIV AL,b*/
|
||||||
if (dst == 0) {
|
tempws = (int)(int16_t)AX;
|
||||||
x86_int(0); /* Divide by zero. */
|
if (dst != 0) tempws2 = tempws / (int)((int8_t)dst);
|
||||||
return 1;
|
temps = tempws2 & 0xff;
|
||||||
}
|
if (dst && ((int)temps == tempws2))
|
||||||
|
{
|
||||||
tempsrc = (int16_t) AX;
|
AH = (tempws % (int)((int8_t)dst)) & 0xff;
|
||||||
tempdst = (int8_t) dst;
|
AL = tempws2 & 0xff;
|
||||||
|
if (!cpu_iscyrix)
|
||||||
tempws = tempsrc / tempdst;
|
{
|
||||||
|
flags_rebuild();
|
||||||
if ((tempws > 127) || (tempws < -128)) {
|
flags|=0x8D5; /*Not a Cyrix*/
|
||||||
x86_int(0);
|
}
|
||||||
return 1;
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
tempws = (int8_t) tempws;
|
x86_int(0);
|
||||||
tempws2 = (int8_t) (tempsrc % tempdst);
|
return 1;
|
||||||
|
}
|
||||||
AH = (uint8_t) tempws2;
|
|
||||||
AL = (uint8_t) tempws;
|
|
||||||
|
|
||||||
if (!cpu_iscyrix) {
|
|
||||||
flags_rebuild();
|
|
||||||
flags|=0x8D5; /*Not a Cyrix*/
|
|
||||||
}
|
|
||||||
|
|
||||||
CLOCK_CYCLES(19);
|
CLOCK_CYCLES(19);
|
||||||
PREFETCH_RUN(19, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
PREFETCH_RUN(19, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
||||||
break;
|
break;
|
||||||
@@ -168,9 +161,10 @@ static int opF6_a16(uint32_t fetchdat)
|
|||||||
}
|
}
|
||||||
static int opF6_a32(uint32_t fetchdat)
|
static int opF6_a32(uint32_t fetchdat)
|
||||||
{
|
{
|
||||||
int tempsrc, tempdst, tempws, tempws2 = 0;
|
int tempws, tempws2 = 0;
|
||||||
uint16_t tempw, src16;
|
uint16_t tempw, src16;
|
||||||
uint8_t src, dst;
|
uint8_t src, dst;
|
||||||
|
int8_t temps;
|
||||||
|
|
||||||
fetch_ea_32(fetchdat);
|
fetch_ea_32(fetchdat);
|
||||||
dst = geteab(); if (cpu_state.abrt) return 1;
|
dst = geteab(); if (cpu_state.abrt) return 1;
|
||||||
@@ -234,32 +228,24 @@ static int opF6_a32(uint32_t fetchdat)
|
|||||||
PREFETCH_RUN(is486 ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
PREFETCH_RUN(is486 ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
||||||
break;
|
break;
|
||||||
case 0x38: /*IDIV AL,b*/
|
case 0x38: /*IDIV AL,b*/
|
||||||
if (dst == 0) {
|
tempws = (int)(int16_t)AX;
|
||||||
x86_int(0); /* Divide by zero. */
|
if (dst != 0) tempws2 = tempws / (int)((int8_t)dst);
|
||||||
return 1;
|
temps = tempws2 & 0xff;
|
||||||
}
|
if (dst && ((int)temps == tempws2))
|
||||||
|
{
|
||||||
tempsrc = (int16_t) AX;
|
AH = (tempws % (int)((int8_t)dst)) & 0xff;
|
||||||
tempdst = (int8_t) dst;
|
AL = tempws2 & 0xff;
|
||||||
|
if (!cpu_iscyrix)
|
||||||
tempws = tempsrc / tempdst;
|
{
|
||||||
|
flags_rebuild();
|
||||||
if ((tempws > 127) || (tempws < -128)) {
|
flags|=0x8D5; /*Not a Cyrix*/
|
||||||
x86_int(0);
|
}
|
||||||
return 1;
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
tempws = (int8_t) tempws;
|
x86_int(0);
|
||||||
tempws2 = (int8_t) (tempsrc % tempdst);
|
return 1;
|
||||||
|
}
|
||||||
AH = (uint8_t) tempws2;
|
|
||||||
AL = (uint8_t) tempws;
|
|
||||||
|
|
||||||
if (!cpu_iscyrix) {
|
|
||||||
flags_rebuild();
|
|
||||||
flags|=0x8D5; /*Not a Cyrix*/
|
|
||||||
}
|
|
||||||
|
|
||||||
CLOCK_CYCLES(19);
|
CLOCK_CYCLES(19);
|
||||||
PREFETCH_RUN(19, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
PREFETCH_RUN(19, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
||||||
break;
|
break;
|
||||||
@@ -276,7 +262,8 @@ static int opF6_a32(uint32_t fetchdat)
|
|||||||
static int opF7_w_a16(uint32_t fetchdat)
|
static int opF7_w_a16(uint32_t fetchdat)
|
||||||
{
|
{
|
||||||
uint32_t templ, templ2;
|
uint32_t templ, templ2;
|
||||||
int32_t tempsrc, tempdst, tempws, tempws2 = 0;
|
int tempws, tempws2 = 0;
|
||||||
|
int16_t temps16;
|
||||||
uint16_t src, dst;
|
uint16_t src, dst;
|
||||||
|
|
||||||
fetch_ea_16(fetchdat);
|
fetch_ea_16(fetchdat);
|
||||||
@@ -339,32 +326,21 @@ static int opF7_w_a16(uint32_t fetchdat)
|
|||||||
CLOCK_CYCLES(is486 ? 24 : 22);
|
CLOCK_CYCLES(is486 ? 24 : 22);
|
||||||
PREFETCH_RUN(is486 ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
PREFETCH_RUN(is486 ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
||||||
break;
|
break;
|
||||||
case 0x38: /*IDIV DX:AX,w*/
|
case 0x38: /*IDIV AX,w*/
|
||||||
if (dst == 0) {
|
tempws = (int)((DX << 16)|AX);
|
||||||
x86_int(0); /* Divide by zero. */
|
if (dst) tempws2 = tempws / (int)((int16_t)dst);
|
||||||
return 1;
|
temps16 = tempws2 & 0xffff;
|
||||||
}
|
if ((dst != 0) && ((int)temps16 == tempws2))
|
||||||
|
{
|
||||||
templ = (uint32_t) DX;
|
DX = tempws % (int)((int16_t)dst);
|
||||||
templ = (templ << 16) | AX;
|
AX = tempws2 & 0xffff;
|
||||||
tempsrc = (int32_t) templ;
|
if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/
|
||||||
tempdst = (int16_t) dst;
|
}
|
||||||
|
else
|
||||||
tempws = tempsrc / tempdst;
|
{
|
||||||
|
x86_int(0);
|
||||||
if ((tempws > 32767) || (tempws < -32768)) {
|
return 1;
|
||||||
x86_int(0);
|
}
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tempws = (int16_t) tempws;
|
|
||||||
tempws2 = (int16_t) (tempsrc % tempdst);
|
|
||||||
|
|
||||||
DX = (uint16_t) tempws2;
|
|
||||||
AX = (uint16_t) tempws;
|
|
||||||
|
|
||||||
if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/
|
|
||||||
|
|
||||||
CLOCK_CYCLES(27);
|
CLOCK_CYCLES(27);
|
||||||
PREFETCH_RUN(27, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
PREFETCH_RUN(27, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
||||||
break;
|
break;
|
||||||
@@ -378,7 +354,8 @@ static int opF7_w_a16(uint32_t fetchdat)
|
|||||||
static int opF7_w_a32(uint32_t fetchdat)
|
static int opF7_w_a32(uint32_t fetchdat)
|
||||||
{
|
{
|
||||||
uint32_t templ, templ2;
|
uint32_t templ, templ2;
|
||||||
int tempsrc, tempdst, tempws, tempws2 = 0;
|
int tempws, tempws2 = 0;
|
||||||
|
int16_t temps16;
|
||||||
uint16_t src, dst;
|
uint16_t src, dst;
|
||||||
|
|
||||||
fetch_ea_32(fetchdat);
|
fetch_ea_32(fetchdat);
|
||||||
@@ -441,32 +418,21 @@ static int opF7_w_a32(uint32_t fetchdat)
|
|||||||
CLOCK_CYCLES(is486 ? 24 : 22);
|
CLOCK_CYCLES(is486 ? 24 : 22);
|
||||||
PREFETCH_RUN(is486 ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
PREFETCH_RUN(is486 ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
||||||
break;
|
break;
|
||||||
case 0x38: /*IDIV DX:AX,w*/
|
case 0x38: /*IDIV AX,w*/
|
||||||
if (dst == 0) {
|
tempws = (int)((DX << 16)|AX);
|
||||||
x86_int(0); /* Divide by zero. */
|
if (dst) tempws2 = tempws / (int)((int16_t)dst);
|
||||||
return 1;
|
temps16 = tempws2 & 0xffff;
|
||||||
}
|
if ((dst != 0) && ((int)temps16 == tempws2))
|
||||||
|
{
|
||||||
templ = (uint32_t) DX;
|
DX = tempws % (int)((int16_t)dst);
|
||||||
templ = (templ << 16) | AX;
|
AX = tempws2 & 0xffff;
|
||||||
tempsrc = (int32_t) templ;
|
if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/
|
||||||
tempdst = (int16_t) dst;
|
}
|
||||||
|
else
|
||||||
tempws = tempsrc / tempdst;
|
{
|
||||||
|
x86_int(0);
|
||||||
if ((tempws > 32767) || (tempws < -32768)) {
|
return 1;
|
||||||
x86_int(0);
|
}
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tempws = (int16_t) tempws;
|
|
||||||
tempws2 = (int16_t) (tempsrc % tempdst);
|
|
||||||
|
|
||||||
DX = (uint16_t) tempws2;
|
|
||||||
AX = (uint16_t) tempws;
|
|
||||||
|
|
||||||
if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/
|
|
||||||
|
|
||||||
CLOCK_CYCLES(27);
|
CLOCK_CYCLES(27);
|
||||||
PREFETCH_RUN(27, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
PREFETCH_RUN(27, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
||||||
break;
|
break;
|
||||||
|
|||||||
4
src/pc.c
4
src/pc.c
@@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
* Main emulator module where most things are controlled.
|
* Main emulator module where most things are controlled.
|
||||||
*
|
*
|
||||||
* Version: @(#)pc.c 1.0.50 2017/12/15
|
* Version: @(#)pc.c 1.0.51 2017/12/16
|
||||||
*
|
*
|
||||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||||
* Miran Grca, <mgrca8@gmail.com>
|
* Miran Grca, <mgrca8@gmail.com>
|
||||||
@@ -196,8 +196,8 @@ pclog_ex(const char *fmt, va_list ap)
|
|||||||
} else {
|
} else {
|
||||||
if (seen) {
|
if (seen) {
|
||||||
fprintf(stdlog, "*** %d repeats ***\n", seen);
|
fprintf(stdlog, "*** %d repeats ***\n", seen);
|
||||||
seen = 0;
|
|
||||||
}
|
}
|
||||||
|
seen = 0;
|
||||||
strcpy(buff, temp);
|
strcpy(buff, temp);
|
||||||
fprintf(stdlog, temp, ap);
|
fprintf(stdlog, temp, ap);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
* NCR and later Symbios and LSI. This controller was designed
|
* NCR and later Symbios and LSI. This controller was designed
|
||||||
* for the PCI bus.
|
* for the PCI bus.
|
||||||
*
|
*
|
||||||
* Version: @(#)scsi_ncr53c810.c 1.0.1 2017/12/15
|
* Version: @(#)scsi_ncr53c810.c 1.0.2 2017/12/16
|
||||||
*
|
*
|
||||||
* Authors: Paul Brook (QEMU)
|
* Authors: Paul Brook (QEMU)
|
||||||
* Artyom Tarasenko (QEMU)
|
* Artyom Tarasenko (QEMU)
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
#define HAVE_STDARG_H
|
||||||
#include "../86box.h"
|
#include "../86box.h"
|
||||||
#include "../io.h"
|
#include "../io.h"
|
||||||
#include "../dma.h"
|
#include "../dma.h"
|
||||||
@@ -208,7 +209,7 @@ typedef struct {
|
|||||||
* 1 if a Wait Reselect instruction has been issued.
|
* 1 if a Wait Reselect instruction has been issued.
|
||||||
* 2 if processing DMA from lsi_execute_script.
|
* 2 if processing DMA from lsi_execute_script.
|
||||||
* 3 if a DMA operation is in progress. */
|
* 3 if a DMA operation is in progress. */
|
||||||
int waiting;
|
volatile uint8_t waiting, sstop;
|
||||||
|
|
||||||
uint8_t current_lun;
|
uint8_t current_lun;
|
||||||
uint8_t select_id;
|
uint8_t select_id;
|
||||||
@@ -261,7 +262,8 @@ typedef struct {
|
|||||||
uint8_t stime0;
|
uint8_t stime0;
|
||||||
uint8_t respid0;
|
uint8_t respid0;
|
||||||
uint8_t respid1;
|
uint8_t respid1;
|
||||||
uint32_t scratch[4]; /* SCRATCHA-SCRATCHR */
|
uint32_t scratch;
|
||||||
|
uint32_t scratch2; /* SCRATCHA-SCRATCHD */
|
||||||
uint8_t sbr;
|
uint8_t sbr;
|
||||||
uint8_t chip_rev;
|
uint8_t chip_rev;
|
||||||
int last_level;
|
int last_level;
|
||||||
@@ -273,16 +275,33 @@ typedef struct {
|
|||||||
|
|
||||||
/* Script ram is stored as 32-bit words in host byteorder. */
|
/* Script ram is stored as 32-bit words in host byteorder. */
|
||||||
uint8_t script_ram[8192];
|
uint8_t script_ram[8192];
|
||||||
uint8_t sstop;
|
|
||||||
|
|
||||||
uint32_t prefetch;
|
|
||||||
uint8_t prefetch_used;
|
|
||||||
|
|
||||||
uint8_t regop;
|
|
||||||
uint32_t adder;
|
uint32_t adder;
|
||||||
|
uint8_t ncr_to_ncr;
|
||||||
} LSIState;
|
} LSIState;
|
||||||
|
|
||||||
|
|
||||||
|
static volatile
|
||||||
|
thread_t *poll_tid;
|
||||||
|
static volatile
|
||||||
|
int busy;
|
||||||
|
|
||||||
|
static volatile
|
||||||
|
event_t *evt;
|
||||||
|
static volatile
|
||||||
|
event_t *wait_evt;
|
||||||
|
|
||||||
|
static volatile
|
||||||
|
event_t *wake_poll_thread;
|
||||||
|
static volatile
|
||||||
|
event_t *thread_started;
|
||||||
|
static volatile
|
||||||
|
event_t *waiting_state;
|
||||||
|
|
||||||
|
static volatile
|
||||||
|
LSIState *lsi_dev;
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_NCR53C810_LOG
|
#ifdef ENABLE_NCR53C810_LOG
|
||||||
int ncr53c810_do_log = ENABLE_NCR53C810_LOG;
|
int ncr53c810_do_log = ENABLE_NCR53C810_LOG;
|
||||||
#endif
|
#endif
|
||||||
@@ -313,9 +332,6 @@ static void lsi_reg_writeb(LSIState *s, uint32_t offset, uint8_t val);
|
|||||||
static void lsi_execute_script(LSIState *s);
|
static void lsi_execute_script(LSIState *s);
|
||||||
static void lsi_reselect(LSIState *s, lsi_request *p);
|
static void lsi_reselect(LSIState *s, lsi_request *p);
|
||||||
static void lsi_command_complete(void *priv, uint32_t status);
|
static void lsi_command_complete(void *priv, uint32_t status);
|
||||||
#if 0
|
|
||||||
static void lsi_transfer_data(void *priv, uint32_t len, uint8_t id);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline int32_t sextract32(uint32_t value, int start, int length)
|
static inline int32_t sextract32(uint32_t value, int start, int length)
|
||||||
{
|
{
|
||||||
@@ -350,7 +366,7 @@ static void lsi_soft_reset(LSIState *s)
|
|||||||
s->dnad = 0;
|
s->dnad = 0;
|
||||||
s->dbc = 0;
|
s->dbc = 0;
|
||||||
s->temp = 0;
|
s->temp = 0;
|
||||||
memset(s->scratch, 0, sizeof(s->scratch));
|
s->scratch = s->scratch2 = 0;
|
||||||
s->istat0 = 0;
|
s->istat0 = 0;
|
||||||
s->istat1 = 0;
|
s->istat1 = 0;
|
||||||
s->dcmd = 0x40;
|
s->dcmd = 0x40;
|
||||||
@@ -393,8 +409,7 @@ static void lsi_soft_reset(LSIState *s)
|
|||||||
s->last_level = 0;
|
s->last_level = 0;
|
||||||
s->gpreg0 = 0;
|
s->gpreg0 = 0;
|
||||||
s->sstop = 1;
|
s->sstop = 1;
|
||||||
s->prefetch = 0;
|
s->ncr_to_ncr = 0;
|
||||||
s->prefetch_used = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -406,10 +421,28 @@ static void lsi_read(LSIState *s, uint32_t addr, uint8_t *buf, uint32_t len)
|
|||||||
|
|
||||||
if (s->dmode & LSI_DMODE_SIOM) {
|
if (s->dmode & LSI_DMODE_SIOM) {
|
||||||
ncr53c810_log("NCR 810: Reading from I/O address %04X\n", (uint16_t) addr);
|
ncr53c810_log("NCR 810: Reading from I/O address %04X\n", (uint16_t) addr);
|
||||||
|
|
||||||
|
if ((addr & 0xFF00) == s->PCIBase) {
|
||||||
|
s->ncr_to_ncr = 1;
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
buf[i] = lsi_reg_readb(s, addr & 0xFF);
|
||||||
|
s->ncr_to_ncr = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
buf[i] = inb((uint16_t) (addr + i));
|
buf[i] = inb((uint16_t) (addr + i));
|
||||||
} else {
|
} else {
|
||||||
ncr53c810_log("NCR 810: Reading from memory address %08X\n", addr);
|
ncr53c810_log("NCR 810: Reading from memory address %08X\n", addr);
|
||||||
|
|
||||||
|
if ((addr & 0xFFFFFF00) == s->MMIOBase) {
|
||||||
|
s->ncr_to_ncr = 1;
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
buf[i] = lsi_reg_readb(s, addr & 0xFF);
|
||||||
|
s->ncr_to_ncr = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
DMAPageRead(addr, buf, len);
|
DMAPageRead(addr, buf, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -422,10 +455,28 @@ static void lsi_write(LSIState *s, uint32_t addr, uint8_t *buf, uint32_t len)
|
|||||||
|
|
||||||
if (s->dmode & LSI_DMODE_DIOM) {
|
if (s->dmode & LSI_DMODE_DIOM) {
|
||||||
ncr53c810_log("NCR 810: Writing to I/O address %04X\n", (uint16_t) addr);
|
ncr53c810_log("NCR 810: Writing to I/O address %04X\n", (uint16_t) addr);
|
||||||
|
|
||||||
|
if ((addr & 0xFF00) == s->PCIBase) {
|
||||||
|
s->ncr_to_ncr = 1;
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
lsi_reg_writeb(s, addr & 0xFF, buf[i]);
|
||||||
|
s->ncr_to_ncr = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
outb((uint16_t) (addr + i), buf[i]);
|
outb((uint16_t) (addr + i), buf[i]);
|
||||||
} else {
|
} else {
|
||||||
ncr53c810_log("NCR 810: Writing to memory address %08X\n", addr);
|
ncr53c810_log("NCR 810: Writing to memory address %08X\n", addr);
|
||||||
|
|
||||||
|
if ((addr & 0xFFFFFF00) == s->MMIOBase) {
|
||||||
|
s->ncr_to_ncr = 1;
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
lsi_reg_writeb(s, addr & 0xFF, buf[i]);
|
||||||
|
s->ncr_to_ncr = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
DMAPageWrite(addr, buf, len);
|
DMAPageWrite(addr, buf, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -543,19 +594,8 @@ static void lsi_bad_phase(LSIState *s, int out, int new_phase)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Resume SCRIPTS execution after a DMA operation. */
|
static void
|
||||||
static void lsi_resume_script(LSIState *s)
|
lsi_disconnect(LSIState *s)
|
||||||
{
|
|
||||||
ncr53c810_log("lsi_resume_script()\n");
|
|
||||||
if (s->waiting != 2) {
|
|
||||||
s->waiting = 0;
|
|
||||||
lsi_execute_script(s);
|
|
||||||
} else {
|
|
||||||
s->waiting = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lsi_disconnect(LSIState *s)
|
|
||||||
{
|
{
|
||||||
s->scntl1 &= ~LSI_SCNTL1_CON;
|
s->scntl1 &= ~LSI_SCNTL1_CON;
|
||||||
s->sstat1 &= ~PHASE_MASK;
|
s->sstat1 &= ~PHASE_MASK;
|
||||||
@@ -563,14 +603,18 @@ static void lsi_disconnect(LSIState *s)
|
|||||||
s->sstat1 |= 0x07;
|
s->sstat1 |= 0x07;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lsi_bad_selection(LSIState *s, uint32_t id)
|
|
||||||
|
static void
|
||||||
|
lsi_bad_selection(LSIState *s, uint32_t id)
|
||||||
{
|
{
|
||||||
DPRINTF("Selected absent target %d\n", id);
|
DPRINTF("Selected absent target %d\n", id);
|
||||||
lsi_script_scsi_interrupt(s, 0, LSI_SIST1_STO);
|
lsi_script_scsi_interrupt(s, 0, LSI_SIST1_STO);
|
||||||
lsi_disconnect(s);
|
lsi_disconnect(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lsi_do_dma(LSIState *s, int out, uint8_t id)
|
|
||||||
|
static void
|
||||||
|
lsi_do_dma(LSIState *s, int out, uint8_t id)
|
||||||
{
|
{
|
||||||
uint32_t addr, count, tdbc;
|
uint32_t addr, count, tdbc;
|
||||||
|
|
||||||
@@ -625,12 +669,14 @@ static void lsi_do_dma(LSIState *s, int out, uint8_t id)
|
|||||||
lsi_command_complete(s, SCSIStatus);
|
lsi_command_complete(s, SCSIStatus);
|
||||||
} else {
|
} else {
|
||||||
DPRINTF("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Resume SCRIPTS\n", id, s->current_lun, s->last_command);
|
DPRINTF("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Resume SCRIPTS\n", id, s->current_lun, s->last_command);
|
||||||
lsi_resume_script(s);
|
s->sstop = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Queue a byte for a MSG IN phase. */
|
/* Queue a byte for a MSG IN phase. */
|
||||||
static void lsi_add_msg_byte(LSIState *s, uint8_t data)
|
static void
|
||||||
|
lsi_add_msg_byte(LSIState *s, uint8_t data)
|
||||||
{
|
{
|
||||||
if (s->msg_len >= LSI_MAX_MSGIN_LEN) {
|
if (s->msg_len >= LSI_MAX_MSGIN_LEN) {
|
||||||
BADF("MSG IN data too long\n");
|
BADF("MSG IN data too long\n");
|
||||||
@@ -640,8 +686,33 @@ static void lsi_add_msg_byte(LSIState *s, uint8_t data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
lsi_busy(uint8_t set)
|
||||||
|
{
|
||||||
|
if (busy == !!set)
|
||||||
|
return;
|
||||||
|
|
||||||
|
busy = !!set;
|
||||||
|
ncr53c810_log("NCR 810: Busy is now %s...\n", busy ? "ON" : "OFF");
|
||||||
|
if (!set) {
|
||||||
|
ncr53c810_log("NCR 810: Setting thread wake event...\n", busy ? "ON" : "OFF");
|
||||||
|
thread_set_event((event_t *) wake_poll_thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
lsi_set_wake_event(void)
|
||||||
|
{
|
||||||
|
ncr53c810_log("NCR 810: Setting wait event arrived...\n");
|
||||||
|
thread_set_event((event_t *)waiting_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Perform reselection to continue a command. */
|
/* Perform reselection to continue a command. */
|
||||||
static void lsi_reselect(LSIState *s, lsi_request *p)
|
static void
|
||||||
|
lsi_reselect(LSIState *s, lsi_request *p)
|
||||||
{
|
{
|
||||||
int id;
|
int id;
|
||||||
|
|
||||||
@@ -671,6 +742,9 @@ static void lsi_reselect(LSIState *s, lsi_request *p)
|
|||||||
if (lsi_irq_on_rsl(s)) {
|
if (lsi_irq_on_rsl(s)) {
|
||||||
lsi_script_scsi_interrupt(s, LSI_SIST0_RSL, 0);
|
lsi_script_scsi_interrupt(s, LSI_SIST0_RSL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s->sstop = s->waiting = 0;
|
||||||
|
lsi_set_wake_event();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -726,7 +800,7 @@ static void lsi_command_complete(void *priv, uint32_t status)
|
|||||||
s->hba_private = NULL;
|
s->hba_private = NULL;
|
||||||
lsi_request_free(s, s->current);
|
lsi_request_free(s, s->current);
|
||||||
}
|
}
|
||||||
lsi_resume_script(s);
|
s->sstop = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lsi_do_command(LSIState *s, uint8_t id)
|
static void lsi_do_command(LSIState *s, uint8_t id)
|
||||||
@@ -1004,7 +1078,8 @@ static void lsi_wait_reselect(LSIState *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lsi_execute_script(LSIState *s)
|
static void
|
||||||
|
lsi_process_script(LSIState *s)
|
||||||
{
|
{
|
||||||
uint32_t insn;
|
uint32_t insn;
|
||||||
uint32_t addr;
|
uint32_t addr;
|
||||||
@@ -1012,16 +1087,14 @@ static void lsi_execute_script(LSIState *s)
|
|||||||
int insn_processed = 0;
|
int insn_processed = 0;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
|
||||||
/* s->istat1 |= LSI_ISTAT1_SRUN; */
|
|
||||||
s->sstop = 0;
|
s->sstop = 0;
|
||||||
again:
|
|
||||||
insn_processed++;
|
insn_processed++;
|
||||||
insn = read_dword(s, s->dsp);
|
insn = read_dword(s, s->dsp);
|
||||||
if (!insn) {
|
if (!insn) {
|
||||||
/* If we receive an empty opcode increment the DSP by 4 bytes
|
/* If we receive an empty opcode increment the DSP by 4 bytes
|
||||||
instead of 8 and execute the next opcode at that location */
|
instead of 8 and execute the next opcode at that location */
|
||||||
s->dsp += 4;
|
s->dsp += 4;
|
||||||
goto again;
|
return; /* The thread will take care of resuming execution. */
|
||||||
}
|
}
|
||||||
addr = read_dword(s, s->dsp + 4);
|
addr = read_dword(s, s->dsp + 4);
|
||||||
DPRINTF("SCRIPTS dsp=%08x opcode %08x arg %08x\n", s->dsp, insn, addr);
|
DPRINTF("SCRIPTS dsp=%08x opcode %08x arg %08x\n", s->dsp, insn, addr);
|
||||||
@@ -1266,7 +1339,9 @@ again:
|
|||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case 5: /* From SFBR */
|
case 5: /* From SFBR */
|
||||||
case 7: /* Read-modify-write */
|
case 7: /* Read-modify-write */
|
||||||
|
s->ncr_to_ncr = 1;
|
||||||
lsi_reg_writeb(s, reg, op0);
|
lsi_reg_writeb(s, reg, op0);
|
||||||
|
s->ncr_to_ncr = 0;
|
||||||
break;
|
break;
|
||||||
case 6: /* To SFBR */
|
case 6: /* To SFBR */
|
||||||
s->sfbr = op0;
|
s->sfbr = op0;
|
||||||
@@ -1410,9 +1485,10 @@ again:
|
|||||||
if (s->dcntl & LSI_DCNTL_SSM) {
|
if (s->dcntl & LSI_DCNTL_SSM) {
|
||||||
ncr53c810_log("NCR 810: SCRIPTS: Single-step mode\n");
|
ncr53c810_log("NCR 810: SCRIPTS: Single-step mode\n");
|
||||||
lsi_script_dma_interrupt(s, LSI_DSTAT_SSI);
|
lsi_script_dma_interrupt(s, LSI_DSTAT_SSI);
|
||||||
|
s->sstop = 1;
|
||||||
} else {
|
} else {
|
||||||
ncr53c810_log("NCR 810: SCRIPTS: Normal mode\n");
|
ncr53c810_log("NCR 810: SCRIPTS: Normal mode\n");
|
||||||
goto again;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (s->sstop)
|
if (s->sstop)
|
||||||
@@ -1424,7 +1500,102 @@ again:
|
|||||||
DPRINTF("SCRIPTS execution stopped\n");
|
DPRINTF("SCRIPTS execution stopped\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lsi_reg_writeb(LSIState *s, uint32_t offset, uint8_t val)
|
|
||||||
|
static uint8_t
|
||||||
|
lsi_is_busy(void)
|
||||||
|
{
|
||||||
|
return(!!busy);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
lsi_wait_for_poll(void)
|
||||||
|
{
|
||||||
|
if (lsi_is_busy()) {
|
||||||
|
ncr53c810_log("NCR 810: Waiting for thread wake event...\n");
|
||||||
|
thread_wait_event((event_t *) wake_poll_thread, -1);
|
||||||
|
}
|
||||||
|
ncr53c810_log("NCR 810: Thread wake event arrived...\n");
|
||||||
|
thread_reset_event((event_t *) wake_poll_thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
lsi_wait_for_resume(void)
|
||||||
|
{
|
||||||
|
if (lsi_dev && (lsi_dev->waiting == 1)) {
|
||||||
|
ncr53c810_log("NCR 810: Waiting for thread resume event...\n");
|
||||||
|
thread_wait_event((event_t *) waiting_state, -1);
|
||||||
|
}
|
||||||
|
ncr53c810_log("NCR 810: Thread resume event arrived...\n");
|
||||||
|
thread_reset_event((event_t *) waiting_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
lsi_script_thread(void *priv)
|
||||||
|
{
|
||||||
|
LSIState *dev = (LSIState *) lsi_dev;
|
||||||
|
|
||||||
|
thread_set_event((event_t *) thread_started);
|
||||||
|
|
||||||
|
ncr53c810_log("Polling thread started\n");
|
||||||
|
|
||||||
|
while (lsi_dev) {
|
||||||
|
scsi_mutex_wait(1);
|
||||||
|
|
||||||
|
if (!dev->sstop) {
|
||||||
|
lsi_wait_for_poll();
|
||||||
|
|
||||||
|
if (dev->waiting) {
|
||||||
|
/* Wait for event followed by a clear of the waiting state
|
||||||
|
if waiting for reselect. */
|
||||||
|
lsi_wait_for_resume();
|
||||||
|
|
||||||
|
thread_wait_event((event_t *) wait_evt, dev->waiting);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dev->waiting)
|
||||||
|
lsi_process_script(dev);
|
||||||
|
} else
|
||||||
|
thread_wait_event((event_t *) wait_evt, 10);
|
||||||
|
|
||||||
|
scsi_mutex_wait(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ncr53c810_log("NCR 810: Callback: polling stopped.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
lsi_thread_start(LSIState *dev)
|
||||||
|
{
|
||||||
|
if (!poll_tid) {
|
||||||
|
poll_tid = thread_create(lsi_script_thread, dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
lsi_set_wait_event(void)
|
||||||
|
{
|
||||||
|
ncr53c810_log("NCR 810: Setting wait event arrived...\n");
|
||||||
|
thread_set_event((event_t *)wait_evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
lsi_execute_script(LSIState *s)
|
||||||
|
{
|
||||||
|
lsi_busy(1);
|
||||||
|
s->sstop = s->waiting = 0;
|
||||||
|
lsi_set_wait_event();
|
||||||
|
lsi_busy(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
lsi_reg_writeb(LSIState *s, uint32_t offset, uint8_t val)
|
||||||
{
|
{
|
||||||
uint8_t tmp = 0;
|
uint8_t tmp = 0;
|
||||||
|
|
||||||
@@ -1439,11 +1610,12 @@ static void lsi_reg_writeb(LSIState *s, uint32_t offset, uint8_t val)
|
|||||||
case addr + 2: s->name &= 0xff00ffff; s->name |= val << 16; break; \
|
case addr + 2: s->name &= 0xff00ffff; s->name |= val << 16; break; \
|
||||||
case addr + 3: s->name &= 0x00ffffff; s->name |= val << 24; break;
|
case addr + 3: s->name &= 0x00ffffff; s->name |= val << 24; break;
|
||||||
|
|
||||||
// #ifdef DEBUG_LSI_REG
|
if (!s->ncr_to_ncr)
|
||||||
DPRINTF("Write reg %02x = %02x\n", offset, val);
|
lsi_busy(1);
|
||||||
// #endif
|
|
||||||
|
|
||||||
s->regop = 1;
|
#ifdef DEBUG_LSI_REG
|
||||||
|
DPRINTF("Write reg %02x = %02x\n", offset, val);
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
case 0x00: /* SCNTL0 */
|
case 0x00: /* SCNTL0 */
|
||||||
@@ -1516,10 +1688,10 @@ static void lsi_reg_writeb(LSIState *s, uint32_t offset, uint8_t val)
|
|||||||
break;
|
break;
|
||||||
case 0x0a: case 0x0b:
|
case 0x0a: case 0x0b:
|
||||||
/* Openserver writes to these readonly registers on startup */
|
/* Openserver writes to these readonly registers on startup */
|
||||||
return;
|
break;
|
||||||
case 0x0c: case 0x0d: case 0x0e: case 0x0f:
|
case 0x0c: case 0x0d: case 0x0e: case 0x0f:
|
||||||
/* Linux writes to these readonly registers on startup. */
|
/* Linux writes to these readonly registers on startup. */
|
||||||
return;
|
break;
|
||||||
CASE_SET_REG32(dsa, 0x10)
|
CASE_SET_REG32(dsa, 0x10)
|
||||||
case 0x14: /* ISTAT0 */
|
case 0x14: /* ISTAT0 */
|
||||||
ncr53c810_log("ISTAT0 write: %02X\n", val);
|
ncr53c810_log("ISTAT0 write: %02X\n", val);
|
||||||
@@ -1537,7 +1709,7 @@ static void lsi_reg_writeb(LSIState *s, uint32_t offset, uint8_t val)
|
|||||||
DPRINTF("Woken by SIGP\n");
|
DPRINTF("Woken by SIGP\n");
|
||||||
s->waiting = 0;
|
s->waiting = 0;
|
||||||
s->dsp = s->dnad;
|
s->dsp = s->dnad;
|
||||||
lsi_execute_script(s);
|
lsi_set_wake_event();
|
||||||
}
|
}
|
||||||
if ((val & LSI_ISTAT0_SRST) && !(tmp & LSI_ISTAT0_SRST)) {
|
if ((val & LSI_ISTAT0_SRST) && !(tmp & LSI_ISTAT0_SRST)) {
|
||||||
lsi_soft_reset(s);
|
lsi_soft_reset(s);
|
||||||
@@ -1598,7 +1770,7 @@ static void lsi_reg_writeb(LSIState *s, uint32_t offset, uint8_t val)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
CASE_SET_REG32(dsps, 0x30)
|
CASE_SET_REG32(dsps, 0x30)
|
||||||
CASE_SET_REG32(scratch[0], 0x34)
|
CASE_SET_REG32(scratch, 0x34)
|
||||||
case 0x38: /* DMODE */
|
case 0x38: /* DMODE */
|
||||||
s->dmode = val;
|
s->dmode = val;
|
||||||
break;
|
break;
|
||||||
@@ -1658,19 +1830,16 @@ static void lsi_reg_writeb(LSIState *s, uint32_t offset, uint8_t val)
|
|||||||
}
|
}
|
||||||
s->stest3 = val;
|
s->stest3 = val;
|
||||||
break;
|
break;
|
||||||
case 0x54:
|
case 0x54:
|
||||||
break;
|
break;
|
||||||
|
CASE_SET_REG32(scratch2, 0x5c)
|
||||||
default:
|
default:
|
||||||
if (offset >= 0x5c && offset < 0x60) {
|
BADF("Unhandled writeb 0x%x = 0x%x\n", offset, val);
|
||||||
int n;
|
|
||||||
int shift;
|
|
||||||
n = (offset - 0x58) >> 2;
|
|
||||||
shift = (offset & 3) * 8;
|
|
||||||
s->scratch[n] = deposit32(s->scratch[n], shift, 8, val);
|
|
||||||
} else {
|
|
||||||
BADF("Unhandled writeb 0x%x = 0x%x\n", offset, val);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!s->ncr_to_ncr)
|
||||||
|
lsi_busy(0);
|
||||||
|
|
||||||
#undef CASE_SET_REG24
|
#undef CASE_SET_REG24
|
||||||
#undef CASE_SET_REG32
|
#undef CASE_SET_REG32
|
||||||
}
|
}
|
||||||
@@ -1678,50 +1847,62 @@ static void lsi_reg_writeb(LSIState *s, uint32_t offset, uint8_t val)
|
|||||||
static uint8_t lsi_reg_readb(LSIState *s, uint32_t offset)
|
static uint8_t lsi_reg_readb(LSIState *s, uint32_t offset)
|
||||||
{
|
{
|
||||||
uint8_t tmp;
|
uint8_t tmp;
|
||||||
|
uint8_t ret = 0;
|
||||||
#define CASE_GET_REG24(name, addr) \
|
#define CASE_GET_REG24(name, addr) \
|
||||||
case addr: return s->name & 0xff; \
|
case addr: ret = s->name & 0xff; break; \
|
||||||
case addr + 1: return (s->name >> 8) & 0xff; \
|
case addr + 1: ret = (s->name >> 8) & 0xff; break; \
|
||||||
case addr + 2: return (s->name >> 16) & 0xff;
|
case addr + 2: ret = (s->name >> 16) & 0xff; break;
|
||||||
|
|
||||||
#define CASE_GET_REG32(name, addr) \
|
#define CASE_GET_REG32(name, addr) \
|
||||||
case addr: return s->name & 0xff; \
|
case addr: ret = s->name & 0xff; break; \
|
||||||
case addr + 1: return (s->name >> 8) & 0xff; \
|
case addr + 1: ret = (s->name >> 8) & 0xff; break; \
|
||||||
case addr + 2: return (s->name >> 16) & 0xff; \
|
case addr + 2: ret = (s->name >> 16) & 0xff; break; \
|
||||||
case addr + 3: return (s->name >> 24) & 0xff;
|
case addr + 3: ret = (s->name >> 24) & 0xff; break;
|
||||||
|
|
||||||
s->regop = 1;
|
if (!s->ncr_to_ncr)
|
||||||
|
lsi_busy(1);
|
||||||
|
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
case 0x00: /* SCNTL0 */
|
case 0x00: /* SCNTL0 */
|
||||||
ncr53c810_log("NCR 810: Read SCNTL0 %02X\n", s->scntl0);
|
ncr53c810_log("NCR 810: Read SCNTL0 %02X\n", s->scntl0);
|
||||||
return s->scntl0;
|
ret = s->scntl0;
|
||||||
|
break;
|
||||||
case 0x01: /* SCNTL1 */
|
case 0x01: /* SCNTL1 */
|
||||||
ncr53c810_log("NCR 810: Read SCNTL1 %02X\n", s->scntl1);
|
ncr53c810_log("NCR 810: Read SCNTL1 %02X\n", s->scntl1);
|
||||||
return s->scntl1;
|
ret = s->scntl1;
|
||||||
|
break;
|
||||||
case 0x02: /* SCNTL2 */
|
case 0x02: /* SCNTL2 */
|
||||||
ncr53c810_log("NCR 810: Read SCNTL2 %02X\n", s->scntl2);
|
ncr53c810_log("NCR 810: Read SCNTL2 %02X\n", s->scntl2);
|
||||||
return s->scntl2;
|
ret = s->scntl2;
|
||||||
|
break;
|
||||||
case 0x03: /* SCNTL3 */
|
case 0x03: /* SCNTL3 */
|
||||||
ncr53c810_log("NCR 810: Read SCNTL3 %02X\n", s->scntl3);
|
ncr53c810_log("NCR 810: Read SCNTL3 %02X\n", s->scntl3);
|
||||||
return s->scntl3;
|
ret = s->scntl3;
|
||||||
|
break;
|
||||||
case 0x04: /* SCID */
|
case 0x04: /* SCID */
|
||||||
ncr53c810_log("NCR 810: Read SCID %02X\n", s->scid);
|
ncr53c810_log("NCR 810: Read SCID %02X\n", s->scid);
|
||||||
return s->scid;
|
ret = s->scid;
|
||||||
|
break;
|
||||||
case 0x05: /* SXFER */
|
case 0x05: /* SXFER */
|
||||||
ncr53c810_log("NCR 810: Read SXFER %02X\n", s->sxfer);
|
ncr53c810_log("NCR 810: Read SXFER %02X\n", s->sxfer);
|
||||||
return s->sxfer;
|
ret = s->sxfer;
|
||||||
|
break;
|
||||||
case 0x06: /* SDID */
|
case 0x06: /* SDID */
|
||||||
ncr53c810_log("NCR 810: Read SDID %02X\n", s->sdid);
|
ncr53c810_log("NCR 810: Read SDID %02X\n", s->sdid);
|
||||||
return s->sdid;
|
ret = s->sdid;
|
||||||
|
break;
|
||||||
case 0x07: /* GPREG0 */
|
case 0x07: /* GPREG0 */
|
||||||
ncr53c810_log("NCR 810: Read GPREG0 %02X\n", s->gpreg0 & 3);
|
ncr53c810_log("NCR 810: Read GPREG0 %02X\n", s->gpreg0 & 3);
|
||||||
return s->gpreg0 & 3;
|
ret = s->gpreg0 & 3;
|
||||||
|
break;
|
||||||
case 0x08: /* Revision ID */
|
case 0x08: /* Revision ID */
|
||||||
ncr53c810_log("NCR 810: Read REVID 00\n");
|
ncr53c810_log("NCR 810: Read REVID 00\n");
|
||||||
return 0x00;
|
ret = 0x00;
|
||||||
|
break;
|
||||||
case 0xa: /* SSID */
|
case 0xa: /* SSID */
|
||||||
ncr53c810_log("NCR 810: Read SSID %02X\n", s->ssid);
|
ncr53c810_log("NCR 810: Read SSID %02X\n", s->ssid);
|
||||||
return s->ssid;
|
ret = s->ssid;
|
||||||
|
break;
|
||||||
case 0xb: /* SBCL */
|
case 0xb: /* SBCL */
|
||||||
/* ??? This is not correct. However it's (hopefully) only
|
/* ??? This is not correct. However it's (hopefully) only
|
||||||
used for diagnostics, so should be ok. */
|
used for diagnostics, so should be ok. */
|
||||||
@@ -1735,42 +1916,53 @@ static uint8_t lsi_reg_readb(LSIState *s, uint32_t offset)
|
|||||||
Bit 0 = I/O (SI_O/ status) */
|
Bit 0 = I/O (SI_O/ status) */
|
||||||
tmp = (s->sstat1 & 7);
|
tmp = (s->sstat1 & 7);
|
||||||
ncr53c810_log("NCR 810: Read SBCL %02X\n", tmp);
|
ncr53c810_log("NCR 810: Read SBCL %02X\n", tmp);
|
||||||
return tmp; /* For now, return the MSG, C/D, and I/O bits from SSTAT1. */
|
ret = tmp; /* For now, return the MSG, C/D, and I/O bits from SSTAT1. */
|
||||||
|
break;
|
||||||
case 0xc: /* DSTAT */
|
case 0xc: /* DSTAT */
|
||||||
tmp = s->dstat | LSI_DSTAT_DFE;
|
tmp = s->dstat | LSI_DSTAT_DFE;
|
||||||
if ((s->istat0 & LSI_ISTAT0_INTF) == 0)
|
if ((s->istat0 & LSI_ISTAT0_INTF) == 0)
|
||||||
s->dstat = 0;
|
s->dstat = 0;
|
||||||
lsi_update_irq(s);
|
lsi_update_irq(s);
|
||||||
ncr53c810_log("NCR 810: Read DSTAT %02X\n", tmp);
|
ncr53c810_log("NCR 810: Read DSTAT %02X\n", tmp);
|
||||||
return tmp;
|
ret = tmp;
|
||||||
|
break;
|
||||||
case 0x0d: /* SSTAT0 */
|
case 0x0d: /* SSTAT0 */
|
||||||
ncr53c810_log("NCR 810: Read SSTAT0 %02X\n", s->sstat0);
|
ncr53c810_log("NCR 810: Read SSTAT0 %02X\n", s->sstat0);
|
||||||
return s->sstat0;
|
ret = s->sstat0;
|
||||||
|
break;
|
||||||
case 0x0e: /* SSTAT1 */
|
case 0x0e: /* SSTAT1 */
|
||||||
ncr53c810_log("NCR 810: Read SSTAT1 %02X\n", s->sstat1);
|
ncr53c810_log("NCR 810: Read SSTAT1 %02X\n", s->sstat1);
|
||||||
return s->sstat1;
|
ret = s->sstat1;
|
||||||
|
break;
|
||||||
case 0x0f: /* SSTAT2 */
|
case 0x0f: /* SSTAT2 */
|
||||||
ncr53c810_log("NCR 810: Read SSTAT2 %02X\n", s->scntl1 & LSI_SCNTL1_CON ? 0 : 2);
|
ncr53c810_log("NCR 810: Read SSTAT2 %02X\n", s->scntl1 & LSI_SCNTL1_CON ? 0 : 2);
|
||||||
return s->scntl1 & LSI_SCNTL1_CON ? 0 : 2;
|
ret = s->scntl1 & LSI_SCNTL1_CON ? 0 : 2;
|
||||||
|
break;
|
||||||
CASE_GET_REG32(dsa, 0x10)
|
CASE_GET_REG32(dsa, 0x10)
|
||||||
case 0x14: /* ISTAT0 */
|
case 0x14: /* ISTAT0 */
|
||||||
ncr53c810_log("NCR 810: Read ISTAT0 %02X\n", s->istat0);
|
ncr53c810_log("NCR 810: Read ISTAT0 %02X\n", s->istat0);
|
||||||
return s->istat0;
|
ret = s->istat0;
|
||||||
|
break;
|
||||||
case 0x15: /* ISTAT1 */
|
case 0x15: /* ISTAT1 */
|
||||||
ncr53c810_log("NCR 810: Read ISTAT1 %02X\n", s->istat1);
|
ncr53c810_log("NCR 810: Read ISTAT1 %02X\n", s->istat1);
|
||||||
return s->istat1;
|
ret = s->istat1;
|
||||||
|
break;
|
||||||
case 0x16: /* MBOX0 */
|
case 0x16: /* MBOX0 */
|
||||||
ncr53c810_log("NCR 810: Read MBOX0 %02X\n", s->mbox0);
|
ncr53c810_log("NCR 810: Read MBOX0 %02X\n", s->mbox0);
|
||||||
return s->mbox0;
|
ret = s->mbox0;
|
||||||
|
break;
|
||||||
case 0x17: /* MBOX1 */
|
case 0x17: /* MBOX1 */
|
||||||
ncr53c810_log("NCR 810: Read MBOX1 %02X\n", s->mbox1);
|
ncr53c810_log("NCR 810: Read MBOX1 %02X\n", s->mbox1);
|
||||||
return s->mbox1;
|
ret = s->mbox1;
|
||||||
|
break;
|
||||||
case 0x18: /* CTEST0 */
|
case 0x18: /* CTEST0 */
|
||||||
ncr53c810_log("NCR 810: Read CTEST0 FF\n");
|
ncr53c810_log("NCR 810: Read CTEST0 FF\n");
|
||||||
return 0xff;
|
ret = 0xff;
|
||||||
|
break;
|
||||||
case 0x19: /* CTEST1 */
|
case 0x19: /* CTEST1 */
|
||||||
ncr53c810_log("NCR 810: Read CTEST1 F0\n");
|
ncr53c810_log("NCR 810: Read CTEST1 F0\n");
|
||||||
return 0xf0; /* dma fifo empty */
|
ret = 0xf0; /* dma fifo empty */
|
||||||
|
break;
|
||||||
case 0x1a: /* CTEST2 */
|
case 0x1a: /* CTEST2 */
|
||||||
tmp = s->ctest2 | LSI_CTEST2_DACK | LSI_CTEST2_CM;
|
tmp = s->ctest2 | LSI_CTEST2_DACK | LSI_CTEST2_CM;
|
||||||
if (s->istat0 & LSI_ISTAT0_SIGP) {
|
if (s->istat0 & LSI_ISTAT0_SIGP) {
|
||||||
@@ -1778,119 +1970,146 @@ static uint8_t lsi_reg_readb(LSIState *s, uint32_t offset)
|
|||||||
tmp |= LSI_CTEST2_SIGP;
|
tmp |= LSI_CTEST2_SIGP;
|
||||||
}
|
}
|
||||||
ncr53c810_log("NCR 810: Read CTEST2 %02X\n", tmp);
|
ncr53c810_log("NCR 810: Read CTEST2 %02X\n", tmp);
|
||||||
return tmp;
|
ret = tmp;
|
||||||
|
break;
|
||||||
case 0x1b: /* CTEST3 */
|
case 0x1b: /* CTEST3 */
|
||||||
ncr53c810_log("NCR 810: Read CTEST3 %02X\n", (s->ctest3 & (0x08 | 0x02 | 0x01)) | s->chip_rev);
|
ncr53c810_log("NCR 810: Read CTEST3 %02X\n", (s->ctest3 & (0x08 | 0x02 | 0x01)) | s->chip_rev);
|
||||||
return (s->ctest3 & (0x08 | 0x02 | 0x01)) | s->chip_rev;
|
ret = (s->ctest3 & (0x08 | 0x02 | 0x01)) | s->chip_rev;
|
||||||
|
break;
|
||||||
CASE_GET_REG32(temp, 0x1c)
|
CASE_GET_REG32(temp, 0x1c)
|
||||||
case 0x20: /* DFIFO */
|
case 0x20: /* DFIFO */
|
||||||
ncr53c810_log("NCR 810: Read DFIFO 00\n");
|
ncr53c810_log("NCR 810: Read DFIFO 00\n");
|
||||||
return 0;
|
ret = 0;
|
||||||
|
break;
|
||||||
case 0x21: /* CTEST4 */
|
case 0x21: /* CTEST4 */
|
||||||
ncr53c810_log("NCR 810: Read CTEST4 %02X\n", s->ctest4);
|
ncr53c810_log("NCR 810: Read CTEST4 %02X\n", s->ctest4);
|
||||||
return s->ctest4;
|
ret = s->ctest4;
|
||||||
|
break;
|
||||||
case 0x22: /* CTEST5 */
|
case 0x22: /* CTEST5 */
|
||||||
ncr53c810_log("NCR 810: Read CTEST5 %02X\n", s->ctest5);
|
ncr53c810_log("NCR 810: Read CTEST5 %02X\n", s->ctest5);
|
||||||
return s->ctest5;
|
ret = s->ctest5;
|
||||||
|
break;
|
||||||
case 0x23: /* CTEST6 */
|
case 0x23: /* CTEST6 */
|
||||||
ncr53c810_log("NCR 810: Read CTEST6 00\n");
|
ncr53c810_log("NCR 810: Read CTEST6 00\n");
|
||||||
return 0;
|
ret = 0;
|
||||||
|
break;
|
||||||
CASE_GET_REG24(dbc, 0x24)
|
CASE_GET_REG24(dbc, 0x24)
|
||||||
case 0x27: /* DCMD */
|
case 0x27: /* DCMD */
|
||||||
ncr53c810_log("NCR 810: Read DCMD %02X\n", s->dcmd);
|
ncr53c810_log("NCR 810: Read DCMD %02X\n", s->dcmd);
|
||||||
return s->dcmd;
|
ret = s->dcmd;
|
||||||
|
break;
|
||||||
CASE_GET_REG32(dnad, 0x28)
|
CASE_GET_REG32(dnad, 0x28)
|
||||||
CASE_GET_REG32(dsp, 0x2c)
|
CASE_GET_REG32(dsp, 0x2c)
|
||||||
CASE_GET_REG32(dsps, 0x30)
|
CASE_GET_REG32(dsps, 0x30)
|
||||||
CASE_GET_REG32(scratch[0], 0x34)
|
CASE_GET_REG32(scratch, 0x34)
|
||||||
case 0x38: /* DMODE */
|
case 0x38: /* DMODE */
|
||||||
ncr53c810_log("NCR 810: Read DMODE %02X\n", s->dmode);
|
ncr53c810_log("NCR 810: Read DMODE %02X\n", s->dmode);
|
||||||
return s->dmode;
|
ret = s->dmode;
|
||||||
|
break;
|
||||||
case 0x39: /* DIEN */
|
case 0x39: /* DIEN */
|
||||||
ncr53c810_log("NCR 810: Read DIEN %02X\n", s->dien);
|
ncr53c810_log("NCR 810: Read DIEN %02X\n", s->dien);
|
||||||
return s->dien;
|
ret = s->dien;
|
||||||
|
break;
|
||||||
case 0x3a: /* SBR */
|
case 0x3a: /* SBR */
|
||||||
ncr53c810_log("NCR 810: Read SBR %02X\n", s->sbr);
|
ncr53c810_log("NCR 810: Read SBR %02X\n", s->sbr);
|
||||||
return s->sbr;
|
ret = s->sbr;
|
||||||
|
break;
|
||||||
case 0x3b: /* DCNTL */
|
case 0x3b: /* DCNTL */
|
||||||
ncr53c810_log("NCR 810: Read DCNTL %02X\n", s->dcntl);
|
ncr53c810_log("NCR 810: Read DCNTL %02X\n", s->dcntl);
|
||||||
return s->dcntl;
|
ret = s->dcntl;
|
||||||
|
break;
|
||||||
/* ADDER Output (Debug of relative jump address) */
|
/* ADDER Output (Debug of relative jump address) */
|
||||||
CASE_GET_REG32(adder, 0x3c)
|
CASE_GET_REG32(adder, 0x3c)
|
||||||
case 0x40: /* SIEN0 */
|
case 0x40: /* SIEN0 */
|
||||||
ncr53c810_log("NCR 810: Read SIEN0 %02X\n", s->sien0);
|
ncr53c810_log("NCR 810: Read SIEN0 %02X\n", s->sien0);
|
||||||
return s->sien0;
|
ret = s->sien0;
|
||||||
|
break;
|
||||||
case 0x41: /* SIEN1 */
|
case 0x41: /* SIEN1 */
|
||||||
ncr53c810_log("NCR 810: Read SIEN1 %02X\n", s->sien1);
|
ncr53c810_log("NCR 810: Read SIEN1 %02X\n", s->sien1);
|
||||||
return s->sien1;
|
ret = s->sien1;
|
||||||
|
break;
|
||||||
case 0x42: /* SIST0 */
|
case 0x42: /* SIST0 */
|
||||||
tmp = s->sist0;
|
tmp = s->sist0;
|
||||||
s->sist0 = 0;
|
s->sist0 = 0;
|
||||||
lsi_update_irq(s);
|
lsi_update_irq(s);
|
||||||
ncr53c810_log("NCR 810: Read SIST0 %02X\n", tmp);
|
ncr53c810_log("NCR 810: Read SIST0 %02X\n", tmp);
|
||||||
return tmp;
|
ret = tmp;
|
||||||
|
break;
|
||||||
case 0x43: /* SIST1 */
|
case 0x43: /* SIST1 */
|
||||||
tmp = s->sist1;
|
tmp = s->sist1;
|
||||||
s->sist1 = 0;
|
s->sist1 = 0;
|
||||||
lsi_update_irq(s);
|
lsi_update_irq(s);
|
||||||
ncr53c810_log("NCR 810: Read SIST1 %02X\n", tmp);
|
ncr53c810_log("NCR 810: Read SIST1 %02X\n", tmp);
|
||||||
return tmp;
|
ret = tmp;
|
||||||
|
break;
|
||||||
case 0x46: /* MACNTL */
|
case 0x46: /* MACNTL */
|
||||||
ncr53c810_log("NCR 810: Read MACNTL 4F\n");
|
ncr53c810_log("NCR 810: Read MACNTL 4F\n");
|
||||||
return 0x4f;
|
ret = 0x4f;
|
||||||
|
break;
|
||||||
case 0x47: /* GPCNTL0 */
|
case 0x47: /* GPCNTL0 */
|
||||||
ncr53c810_log("NCR 810: Read GPCNTL0 0F\n");
|
ncr53c810_log("NCR 810: Read GPCNTL0 0F\n");
|
||||||
return 0x0f;
|
ret = 0x0f;
|
||||||
|
break;
|
||||||
case 0x48: /* STIME0 */
|
case 0x48: /* STIME0 */
|
||||||
ncr53c810_log("NCR 810: Read STIME0 %02X\n", s->stime0);
|
ncr53c810_log("NCR 810: Read STIME0 %02X\n", s->stime0);
|
||||||
return s->stime0;
|
ret = s->stime0;
|
||||||
|
break;
|
||||||
case 0x4a: /* RESPID0 */
|
case 0x4a: /* RESPID0 */
|
||||||
ncr53c810_log("NCR 810: Read RESPID0 %02X\n", s->respid0);
|
ncr53c810_log("NCR 810: Read RESPID0 %02X\n", s->respid0);
|
||||||
return s->respid0;
|
ret = s->respid0;
|
||||||
|
break;
|
||||||
case 0x4b: /* RESPID1 */
|
case 0x4b: /* RESPID1 */
|
||||||
ncr53c810_log("NCR 810: Read RESPID1 %02X\n", s->respid1);
|
ncr53c810_log("NCR 810: Read RESPID1 %02X\n", s->respid1);
|
||||||
return s->respid1;
|
ret = s->respid1;
|
||||||
|
break;
|
||||||
case 0x4d: /* STEST1 */
|
case 0x4d: /* STEST1 */
|
||||||
ncr53c810_log("NCR 810: Read STEST1 %02X\n", s->stest1);
|
ncr53c810_log("NCR 810: Read STEST1 %02X\n", s->stest1);
|
||||||
return s->stest1;
|
ret = s->stest1;
|
||||||
|
break;
|
||||||
case 0x4e: /* STEST2 */
|
case 0x4e: /* STEST2 */
|
||||||
ncr53c810_log("NCR 810: Read STEST2 %02X\n", s->stest2);
|
ncr53c810_log("NCR 810: Read STEST2 %02X\n", s->stest2);
|
||||||
return s->stest2;
|
ret = s->stest2;
|
||||||
|
break;
|
||||||
case 0x4f: /* STEST3 */
|
case 0x4f: /* STEST3 */
|
||||||
ncr53c810_log("NCR 810: Read STEST3 %02X\n", s->stest3);
|
ncr53c810_log("NCR 810: Read STEST3 %02X\n", s->stest3);
|
||||||
return s->stest3;
|
ret = s->stest3;
|
||||||
|
break;
|
||||||
case 0x50: /* SIDL */
|
case 0x50: /* SIDL */
|
||||||
/* This is needed by the linux drivers. We currently only update it
|
/* This is needed by the linux drivers. We currently only update it
|
||||||
during the MSG IN phase. */
|
during the MSG IN phase. */
|
||||||
ncr53c810_log("NCR 810: Read SIDL %02X\n", s->sidl);
|
ncr53c810_log("NCR 810: Read SIDL %02X\n", s->sidl);
|
||||||
return s->sidl;
|
ret = s->sidl;
|
||||||
|
break;
|
||||||
case 0x52: /* STEST4 */
|
case 0x52: /* STEST4 */
|
||||||
ncr53c810_log("NCR 810: Read STEST4 E0\n");
|
ncr53c810_log("NCR 810: Read STEST4 E0\n");
|
||||||
return 0xe0;
|
ret = 0xe0;
|
||||||
|
break;
|
||||||
case 0x58: /* SBDL */
|
case 0x58: /* SBDL */
|
||||||
/* Some drivers peek at the data bus during the MSG IN phase. */
|
/* Some drivers peek at the data bus during the MSG IN phase. */
|
||||||
if ((s->sstat1 & PHASE_MASK) == PHASE_MI) {
|
if ((s->sstat1 & PHASE_MASK) == PHASE_MI) {
|
||||||
ncr53c810_log("NCR 810: Read SBDL %02X\n", s->msg[0]);
|
ncr53c810_log("NCR 810: Read SBDL %02X\n", s->msg[0]);
|
||||||
return s->msg[0];
|
ret = s->msg[0];
|
||||||
}
|
}
|
||||||
ncr53c810_log("NCR 810: Read SBDL 00\n");
|
ncr53c810_log("NCR 810: Read SBDL 00\n");
|
||||||
return 0;
|
ret = 0;
|
||||||
|
break;
|
||||||
case 0x59: /* SBDL high */
|
case 0x59: /* SBDL high */
|
||||||
ncr53c810_log("NCR 810: Read SBDLH 00\n");
|
ncr53c810_log("NCR 810: Read SBDLH 00\n");
|
||||||
return 0;
|
ret = 0;
|
||||||
|
break;
|
||||||
|
CASE_GET_REG32(scratch2, 0x5c)
|
||||||
|
default:
|
||||||
|
BADF("readb 0x%x\n", offset);
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (offset >= 0x5c && offset < 0x60) {
|
|
||||||
int n;
|
|
||||||
int shift;
|
|
||||||
n = (offset - 0x58) >> 2;
|
|
||||||
shift = (offset & 3) * 8;
|
|
||||||
ncr53c810_log("NCR 810: Read SCRATCH%i %02X\n", offset & 3, (s->scratch[n] >> shift) & 0xff);
|
|
||||||
return (s->scratch[n] >> shift) & 0xff;
|
|
||||||
}
|
|
||||||
BADF("readb 0x%x\n", offset);
|
|
||||||
return 0;
|
|
||||||
#undef CASE_GET_REG24
|
#undef CASE_GET_REG24
|
||||||
#undef CASE_GET_REG32
|
#undef CASE_GET_REG32
|
||||||
|
|
||||||
|
if (!s->ncr_to_ncr)
|
||||||
|
lsi_busy(0);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t lsi_io_readb(uint16_t addr, void *p)
|
static uint8_t lsi_io_readb(uint16_t addr, void *p)
|
||||||
@@ -2232,6 +2451,21 @@ ncr53c810_init(device_t *info)
|
|||||||
|
|
||||||
lsi_soft_reset(s);
|
lsi_soft_reset(s);
|
||||||
|
|
||||||
|
lsi_dev = s;
|
||||||
|
|
||||||
|
scsi_mutex(1);
|
||||||
|
|
||||||
|
wake_poll_thread = thread_create_event();
|
||||||
|
thread_started = thread_create_event();
|
||||||
|
waiting_state = thread_create_event();
|
||||||
|
|
||||||
|
/* Create a waitable event. */
|
||||||
|
evt = thread_create_event();
|
||||||
|
wait_evt = thread_create_event();
|
||||||
|
|
||||||
|
lsi_thread_start(s);
|
||||||
|
thread_wait_event((event_t *) thread_started, -1);
|
||||||
|
|
||||||
return(s);
|
return(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2239,11 +2473,52 @@ ncr53c810_init(device_t *info)
|
|||||||
static void
|
static void
|
||||||
ncr53c810_close(void *priv)
|
ncr53c810_close(void *priv)
|
||||||
{
|
{
|
||||||
LSIState *s = (LSIState *)priv;
|
LSIState *dev = (LSIState *)priv;
|
||||||
|
|
||||||
if (s) {
|
if (dev) {
|
||||||
free(s);
|
lsi_dev = NULL;
|
||||||
s = NULL;
|
|
||||||
|
/* Tell the thread to terminate. */
|
||||||
|
if (poll_tid != NULL) {
|
||||||
|
lsi_busy(0);
|
||||||
|
|
||||||
|
/* Wait for the end event. */
|
||||||
|
thread_wait((event_t *) poll_tid, -1);
|
||||||
|
|
||||||
|
poll_tid = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->sstop = 1;
|
||||||
|
|
||||||
|
if (wait_evt) {
|
||||||
|
thread_destroy_event((event_t *) evt);
|
||||||
|
evt = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (evt) {
|
||||||
|
thread_destroy_event((event_t *) evt);
|
||||||
|
evt = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waiting_state) {
|
||||||
|
thread_destroy_event((event_t *) waiting_state);
|
||||||
|
thread_started = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thread_started) {
|
||||||
|
thread_destroy_event((event_t *) thread_started);
|
||||||
|
thread_started = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wake_poll_thread) {
|
||||||
|
thread_destroy_event((event_t *) wake_poll_thread);
|
||||||
|
wake_poll_thread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
scsi_mutex(0);
|
||||||
|
|
||||||
|
free(dev);
|
||||||
|
dev = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user