diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index 117a114e6..a3127ad47 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -839,6 +839,7 @@ machine_ps2_model_80_init(machine_t *model) } +#ifdef WALTJE void machine_ps2_model_80_486_init(machine_t *model) { @@ -846,3 +847,4 @@ machine_ps2_model_80_486_init(machine_t *model) ps2_mca_board_model_80_type2_init(1); } +#endif diff --git a/src/machine/machine.h b/src/machine/machine.h index 85cd82555..ee3bb16c3 100644 --- a/src/machine/machine.h +++ b/src/machine/machine.h @@ -8,7 +8,7 @@ * * Handling of the emulated machines. * - * Version: @(#)machine.h 1.0.14 2017/12/04 + * Version: @(#)machine.h 1.0.15 2017/12/25 * * Authors: Sarah Walker, * Miran Grca, @@ -136,7 +136,9 @@ extern void machine_at_r418_init(machine_t *); extern void machine_at_wd76c10_init(machine_t *); +#ifdef GREENB extern void machine_at_4gpv31_init(machine_t *); +#endif extern void machine_pcjr_init(machine_t *); @@ -148,7 +150,9 @@ extern void machine_ps2_m30_286_init(machine_t *); extern void machine_ps2_model_50_init(machine_t *); extern void machine_ps2_model_55sx_init(machine_t *); extern void machine_ps2_model_80_init(machine_t *); +#ifdef WALTJE extern void machine_ps2_model_80_486_init(machine_t *); +#endif extern void machine_amstrad_init(machine_t *); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 5e0b14d8c..ef41f5dac 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -11,7 +11,7 @@ * NOTES: OpenAT wip for 286-class machine with open BIOS. * PS2_M80-486 wip, pending receipt of TRM's for machine. * - * Version: @(#)machine_table.c 1.0.6 2017/12/05 + * Version: @(#)machine_table.c 1.0.7 2017/12/25 * * Authors: Sarah Walker, * Miran Grca, @@ -104,7 +104,9 @@ machine_t machines[] = { { "[486 PCI] Rise Computer R418", ROM_R418, "r418", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 255, 1, 127, machine_at_r418_init, NULL, nvr_at_close }, +#ifdef GREENB { "[486 VLB] Green-B 4GP V3.1", ROM_4GPV31, "4gpv31", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT, 1, 128, 1, 127, machine_at_4gpv31_init, NULL, nvr_at_close }, +#endif { "[Socket 4 LX] Intel Premiere/PCI", ROM_REVENGE, "revenge", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_batman_init, NULL, nvr_at_close }, diff --git a/src/rom.h b/src/rom.h index 5df4cfe74..67d2adba4 100644 --- a/src/rom.h +++ b/src/rom.h @@ -8,7 +8,7 @@ * * Definitions for the ROM image handler. * - * Version: @(#)rom.h 1.0.5 2017/12/04 + * Version: @(#)rom.h 1.0.6 2017/12/25 * * Author: Fred N. van Kempen, * Copyright 2017 Fred N. van Kempen. @@ -82,7 +82,9 @@ enum { ROM_IBMPS2_M80, ROM_DTK486, /* DTK PKM-0038S E-2/SiS 471/Award/SiS 85C471 */ +#ifdef UNIMPLEMENTED_MACHINES ROM_VLI486SV2G, /* ASUS VL/I-486SV2G/SiS 471/Award/SiS 85C471 */ /* 51 */ +#endif ROM_R418, /* Rise Computer R418/SiS 496/497/Award/SMC FDC37C665 */ ROM_PLATO, /* Intel Premiere/PCI II/430NX/AMI/SMC FDC37C665 */ ROM_MB500N, /* PC Partner MB500N/430FX/Award/SMC FDC37C665 */ @@ -96,7 +98,9 @@ enum { ROM_P55VA, /* Epox P55-VA/430VX/Award/SMC FDC37C932FR*/ ROM_THOR, /* Intel Advanced_ATX/430FX/AMI/NS PC87306 */ ROM_MRTHOR, /* Intel Advanced_ATX/430FX/MR.BIOS/NS PC87306 */ +#ifdef UNIMPLEMENTED_MACHINES ROM_POWERMATE_V, /* NEC PowerMate V/430FX/Phoenix/SMC FDC37C66 5*/ /* 68 */ +#endif ROM_440FX, /* Tyan Titan-Pro AT/440FX/Award BIOS/SMC FDC37C665 */ @@ -116,11 +120,17 @@ enum { ROM_IBMPS1_2133, ROM_PRESIDENT, /* President Award 430FX PCI/430FX/Award/Unknown SIO */ +#ifdef WALTJE ROM_IBMPS2_M80_486, +#endif +#ifdef GREENB ROM_4GPV31, /* Green-B 4GPV3.1 ISA/VLB 486/Pentium, AMI */ +#endif +#ifdef WALTJE ROM_OPENAT, /* PC/AT clone with Open BIOS */ +#endif ROM_MAX }; diff --git a/src/scsi/queue.h b/src/scsi/queue.h deleted file mode 100644 index 141ae5215..000000000 --- a/src/scsi/queue.h +++ /dev/null @@ -1,437 +0,0 @@ -/* $NetBSD: queue.h,v 1.52 2009/04/20 09:56:08 mschuett Exp $ */ - -/* - * QEMU version: Copy from netbsd, removed debug code, removed some of - * the implementations. Left in singly-linked lists, lists, simple - * queues, and tail queues. - */ - -/* - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - */ - -#ifndef QUEUE_H -#define QUEUE_H - -/* - * This file defines four types of data structures: singly-linked lists, - * lists, simple queues, and tail queues. - * - * A singly-linked list is headed by a single forward pointer. The - * elements are singly linked for minimum space and pointer manipulation - * overhead at the expense of O(n) removal for arbitrary elements. New - * elements can be added to the list after an existing element or at the - * head of the list. Elements being removed from the head of the list - * should use the explicit macro for this purpose for optimum - * efficiency. A singly-linked list may only be traversed in the forward - * direction. Singly-linked lists are ideal for applications with large - * datasets and few or no removals or for implementing a LIFO queue. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may only be traversed in the forward direction. - * - * A simple queue is headed by a pair of pointers, one the head of the - * list and the other to the tail of the list. The elements are singly - * linked to save space, so elements can only be removed from the - * head of the list. New elements can be added to the list after - * an existing element, at the head of the list, or at the end of the - * list. A simple queue may only be traversed in the forward direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * For details on the use of these macros, see the queue(3) manual page. - */ - -/* - * List definitions. - */ -#define QLIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define QLIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define QLIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} - -/* - * List functions. - */ -#define QLIST_INIT(head) do { \ - (head)->lh_first = NULL; \ -} while (/*CONSTCOND*/0) - -#define QLIST_SWAP(dstlist, srclist, field) do { \ - void *tmplist; \ - tmplist = (srclist)->lh_first; \ - (srclist)->lh_first = (dstlist)->lh_first; \ - if ((srclist)->lh_first != NULL) { \ - (srclist)->lh_first->field.le_prev = &(srclist)->lh_first; \ - } \ - (dstlist)->lh_first = tmplist; \ - if ((dstlist)->lh_first != NULL) { \ - (dstlist)->lh_first->field.le_prev = &(dstlist)->lh_first; \ - } \ -} while (/*CONSTCOND*/0) - -#define QLIST_INSERT_AFTER(listelm, elm, field) do { \ - if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ - (listelm)->field.le_next->field.le_prev = \ - &(elm)->field.le_next; \ - (listelm)->field.le_next = (elm); \ - (elm)->field.le_prev = &(listelm)->field.le_next; \ -} while (/*CONSTCOND*/0) - -#define QLIST_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - (elm)->field.le_next = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &(elm)->field.le_next; \ -} while (/*CONSTCOND*/0) - -#define QLIST_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.le_next = (head)->lh_first) != NULL) \ - (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ - (head)->lh_first = (elm); \ - (elm)->field.le_prev = &(head)->lh_first; \ -} while (/*CONSTCOND*/0) - -#define QLIST_REMOVE(elm, field) do { \ - if ((elm)->field.le_next != NULL) \ - (elm)->field.le_next->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = (elm)->field.le_next; \ -} while (/*CONSTCOND*/0) - -#define QLIST_FOREACH(var, head, field) \ - for ((var) = ((head)->lh_first); \ - (var); \ - (var) = ((var)->field.le_next)) - -#define QLIST_FOREACH_SAFE(var, head, field, next_var) \ - for ((var) = ((head)->lh_first); \ - (var) && ((next_var) = ((var)->field.le_next), 1); \ - (var) = (next_var)) - -/* - * List access methods. - */ -#define QLIST_EMPTY(head) ((head)->lh_first == NULL) -#define QLIST_FIRST(head) ((head)->lh_first) -#define QLIST_NEXT(elm, field) ((elm)->field.le_next) - - -/* - * Singly-linked List definitions. - */ -#define QSLIST_HEAD(name, type) \ -struct name { \ - struct type *slh_first; /* first element */ \ -} - -#define QSLIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define QSLIST_ENTRY(type) \ -struct { \ - struct type *sle_next; /* next element */ \ -} - -/* - * Singly-linked List functions. - */ -#define QSLIST_INIT(head) do { \ - (head)->slh_first = NULL; \ -} while (/*CONSTCOND*/0) - -#define QSLIST_INSERT_AFTER(slistelm, elm, field) do { \ - (elm)->field.sle_next = (slistelm)->field.sle_next; \ - (slistelm)->field.sle_next = (elm); \ -} while (/*CONSTCOND*/0) - -#define QSLIST_INSERT_HEAD(head, elm, field) do { \ - (elm)->field.sle_next = (head)->slh_first; \ - (head)->slh_first = (elm); \ -} while (/*CONSTCOND*/0) - -#define QSLIST_INSERT_HEAD_ATOMIC(head, elm, field) do { \ - typeof(elm) save_sle_next; \ - do { \ - save_sle_next = (elm)->field.sle_next = (head)->slh_first; \ - } while (atomic_cmpxchg(&(head)->slh_first, save_sle_next, (elm)) != \ - save_sle_next); \ -} while (/*CONSTCOND*/0) - -#define QSLIST_MOVE_ATOMIC(dest, src) do { \ - (dest)->slh_first = atomic_xchg(&(src)->slh_first, NULL); \ -} while (/*CONSTCOND*/0) - -#define QSLIST_REMOVE_HEAD(head, field) do { \ - (head)->slh_first = (head)->slh_first->field.sle_next; \ -} while (/*CONSTCOND*/0) - -#define QSLIST_REMOVE_AFTER(slistelm, field) do { \ - (slistelm)->field.sle_next = \ - QSLIST_NEXT(QSLIST_NEXT((slistelm), field), field); \ -} while (/*CONSTCOND*/0) - -#define QSLIST_FOREACH(var, head, field) \ - for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next) - -#define QSLIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = QSLIST_FIRST((head)); \ - (var) && ((tvar) = QSLIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -/* - * Singly-linked List access methods. - */ -#define QSLIST_EMPTY(head) ((head)->slh_first == NULL) -#define QSLIST_FIRST(head) ((head)->slh_first) -#define QSLIST_NEXT(elm, field) ((elm)->field.sle_next) - - -/* - * Simple queue definitions. - */ -#define QSIMPLEQ_HEAD(name, type) \ -struct name { \ - struct type *sqh_first; /* first element */ \ - struct type **sqh_last; /* addr of last next element */ \ -} - -#define QSIMPLEQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).sqh_first } - -#define QSIMPLEQ_ENTRY(type) \ -struct { \ - struct type *sqe_next; /* next element */ \ -} - -/* - * Simple queue functions. - */ -#define QSIMPLEQ_INIT(head) do { \ - (head)->sqh_first = NULL; \ - (head)->sqh_last = &(head)->sqh_first; \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (head)->sqh_first = (elm); \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.sqe_next = NULL; \ - *(head)->sqh_last = (elm); \ - (head)->sqh_last = &(elm)->field.sqe_next; \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL) \ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (listelm)->field.sqe_next = (elm); \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_REMOVE_HEAD(head, field) do { \ - if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL)\ - (head)->sqh_last = &(head)->sqh_first; \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_SPLIT_AFTER(head, elm, field, removed) do { \ - QSIMPLEQ_INIT(removed); \ - if (((removed)->sqh_first = (head)->sqh_first) != NULL) { \ - if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) { \ - (head)->sqh_last = &(head)->sqh_first; \ - } \ - (removed)->sqh_last = &(elm)->field.sqe_next; \ - (elm)->field.sqe_next = NULL; \ - } \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_REMOVE(head, elm, type, field) do { \ - if ((head)->sqh_first == (elm)) { \ - QSIMPLEQ_REMOVE_HEAD((head), field); \ - } else { \ - struct type *curelm = (head)->sqh_first; \ - while (curelm->field.sqe_next != (elm)) \ - curelm = curelm->field.sqe_next; \ - if ((curelm->field.sqe_next = \ - curelm->field.sqe_next->field.sqe_next) == NULL) \ - (head)->sqh_last = &(curelm)->field.sqe_next; \ - } \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_FOREACH(var, head, field) \ - for ((var) = ((head)->sqh_first); \ - (var); \ - (var) = ((var)->field.sqe_next)) - -#define QSIMPLEQ_FOREACH_SAFE(var, head, field, next) \ - for ((var) = ((head)->sqh_first); \ - (var) && ((next = ((var)->field.sqe_next)), 1); \ - (var) = (next)) - -#define QSIMPLEQ_CONCAT(head1, head2) do { \ - if (!QSIMPLEQ_EMPTY((head2))) { \ - *(head1)->sqh_last = (head2)->sqh_first; \ - (head1)->sqh_last = (head2)->sqh_last; \ - QSIMPLEQ_INIT((head2)); \ - } \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_LAST(head, type, field) \ - (QSIMPLEQ_EMPTY((head)) ? \ - NULL : \ - ((struct type *)(void *) \ - ((char *)((head)->sqh_last) - offsetof(struct type, field)))) - -/* - * Simple queue access methods. - */ -#define QSIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL) -#define QSIMPLEQ_FIRST(head) ((head)->sqh_first) -#define QSIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) - - -/* - * Tail queue definitions. - */ -#define Q_TAILQ_HEAD(name, type, qual) \ -struct name { \ - qual type *tqh_first; /* first element */ \ - qual type *qual *tqh_last; /* addr of last next element */ \ -} -#define QTAILQ_HEAD(name, type) Q_TAILQ_HEAD(name, struct type,) - -#define QTAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first } - -#define Q_TAILQ_ENTRY(type, qual) \ -struct { \ - qual type *tqe_next; /* next element */ \ - qual type *qual *tqe_prev; /* address of previous next element */\ -} -#define QTAILQ_ENTRY(type) Q_TAILQ_ENTRY(struct type,) - -/* - * Tail queue functions. - */ -#define QTAILQ_INIT(head) do { \ - (head)->tqh_first = NULL; \ - (head)->tqh_last = &(head)->tqh_first; \ -} while (/*CONSTCOND*/0) - -#define QTAILQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ - (head)->tqh_first->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (head)->tqh_first = (elm); \ - (elm)->field.tqe_prev = &(head)->tqh_first; \ -} while (/*CONSTCOND*/0) - -#define QTAILQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.tqe_next = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &(elm)->field.tqe_next; \ -} while (/*CONSTCOND*/0) - -#define QTAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ - (elm)->field.tqe_next->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (listelm)->field.tqe_next = (elm); \ - (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ -} while (/*CONSTCOND*/0) - -#define QTAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - (elm)->field.tqe_next = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ -} while (/*CONSTCOND*/0) - -#define QTAILQ_REMOVE(head, elm, field) do { \ - if (((elm)->field.tqe_next) != NULL) \ - (elm)->field.tqe_next->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ -} while (/*CONSTCOND*/0) - -#define QTAILQ_FOREACH(var, head, field) \ - for ((var) = ((head)->tqh_first); \ - (var); \ - (var) = ((var)->field.tqe_next)) - -#define QTAILQ_FOREACH_SAFE(var, head, field, next_var) \ - for ((var) = ((head)->tqh_first); \ - (var) && ((next_var) = ((var)->field.tqe_next), 1); \ - (var) = (next_var)) - -#define QTAILQ_FOREACH_REVERSE(var, head, headname, field) \ - for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \ - (var); \ - (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last))) - -/* - * Tail queue access methods. - */ -#define QTAILQ_EMPTY(head) ((head)->tqh_first == NULL) -#define QTAILQ_FIRST(head) ((head)->tqh_first) -#define QTAILQ_NEXT(elm, field) ((elm)->field.tqe_next) - -#define QTAILQ_LAST(head, headname) \ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) -#define QTAILQ_PREV(elm, headname, field) \ - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) - -#endif /* QEMU_SYS_QUEUE_H */ diff --git a/src/scsi/scsi_ncr53c810.c b/src/scsi/scsi_ncr53c810.c index 0b70b8b70..189515790 100644 --- a/src/scsi/scsi_ncr53c810.c +++ b/src/scsi/scsi_ncr53c810.c @@ -10,7 +10,7 @@ * NCR and later Symbios and LSI. This controller was designed * for the PCI bus. * - * Version: @(#)scsi_ncr53c810.c 1.0.4 2017/12/22 + * Version: @(#)scsi_ncr53c810.c 1.0.5 2017/12/25 * * Authors: Paul Brook (QEMU) * Artyom Tarasenko (QEMU) @@ -27,7 +27,6 @@ #include #include #include -#define HAVE_STDARG_H #include "../86box.h" #include "../io.h" #include "../dma.h" @@ -43,8 +42,6 @@ #include "scsi_device.h" #include "scsi_ncr53c810.h" -#define NCR_BUF_SIZE 4096 - #define NCR_SCNTL0_TRG 0x01 #define NCR_SCNTL0_AAP 0x02 #define NCR_SCNTL0_EPC 0x08 @@ -69,14 +66,14 @@ #define NCR_SCNTL2_CHM 0x40 #define NCR_SCNTL2_SDU 0x80 -#define NCR_ISTAT_DIP 0x01 -#define NCR_ISTAT_SIP 0x02 -#define NCR_ISTAT_INTF 0x04 -#define NCR_ISTAT_CON 0x08 -#define NCR_ISTAT_SEM 0x10 -#define NCR_ISTAT_SIGP 0x20 -#define NCR_ISTAT_SRST 0x40 -#define NCR_ISTAT_ABRT 0x80 +#define NCR_ISTAT_DIP 0x01 +#define NCR_ISTAT_SIP 0x02 +#define NCR_ISTAT_INTF 0x04 +#define NCR_ISTAT_CON 0x08 +#define NCR_ISTAT_SEM 0x10 +#define NCR_ISTAT_SIGP 0x20 +#define NCR_ISTAT_SRST 0x40 +#define NCR_ISTAT_ABRT 0x80 #define NCR_SSTAT0_SDP0 0x01 #define NCR_SSTAT0_RST 0x02 @@ -153,17 +150,12 @@ /* Enable Response to Reselection */ #define NCR_SCID_RRE 0x60 -#define NCR_SOCL_IO 0x01 -#define NCR_SOCL_CD 0x02 -#define NCR_SOCL_MSG 0x04 - -#define PHASE_DO 0 /* N/A, N/A, N/A */ -#define PHASE_DI 1 /* N/A, N/A, I/O */ -#define PHASE_CMD 2 /* N/A, C/D, N/A */ -#define PHASE_ST 3 /* N/A, C/D, I/O */ -#define PHASE_UNK 4 /* MSG, N/A, N/A */ -#define PHASE_MO 6 /* MSG, C/D, N/A */ -#define PHASE_MI 7 /* MSG, C/D, I/O */ +#define PHASE_DO 0 +#define PHASE_DI 1 +#define PHASE_CMD 2 +#define PHASE_ST 3 +#define PHASE_MO 6 +#define PHASE_MI 7 #define PHASE_MASK 7 /* Maximum length of MSG IN data. */ @@ -172,30 +164,26 @@ /* Flag set if this is a tagged command. */ #define NCR_TAG_VALID (1 << 16) +#define NCR_BUF_SIZE 4096 + typedef struct ncr53c810_request { uint32_t tag; uint32_t dma_len; uint8_t *dma_buf; uint32_t pending; int out; - uint8_t connected; } ncr53c810_request; typedef enum { - SCSI_STATE_SEND_COMMAND, - SCSI_STATE_READ_DATA, - SCSI_STATE_WRITE_DATA, - SCSI_STATE_READ_STATUS, - SCSI_STATE_READ_MESSAGE, - SCSI_STATE_WRITE_MESSAGE + SCSI_STATE_SEND_COMMAND, + SCSI_STATE_READ_DATA, + SCSI_STATE_WRITE_DATA, + SCSI_STATE_READ_STATUS, + SCSI_STATE_READ_MESSAGE, + SCSI_STATE_WRITE_MESSAGE } scsi_state_t; -typedef union { - uint32_t dw; - uint8_t b[4]; -} dword_t; - typedef struct { uint8_t pci_slot; int PCIBase; @@ -208,42 +196,45 @@ typedef struct { int status; /* Action to take at the end of a MSG IN phase. 0 = COMMAND, 1 = disconnect, 2 = DATA OUT, 3 = DATA IN. */ - volatile int msg_action; - volatile int msg_len; + int msg_action; + int msg_len; uint8_t msg[NCR_MAX_MSGIN_LEN]; /* 0 if SCRIPTS are running or stopped. * 1 if a Wait Reselect instruction has been issued. * 2 if processing DMA from ncr53c810_execute_script. * 3 if a DMA operation is in progress. */ - volatile uint8_t waiting, sstop; + int waiting; - volatile uint8_t current_lun; - volatile int command_complete; - ncr53c810_request requests[7]; + uint8_t current_lun; + uint8_t select_id; + int command_complete; + ncr53c810_request *current; int irq; - volatile dword_t dsa; - volatile dword_t temp; - volatile dword_t dnad; - volatile dword_t dbc; - volatile uint8_t istat; - volatile uint8_t dcmd; - volatile uint8_t dstat; - volatile uint8_t dien; - volatile uint8_t sist[2]; - volatile uint8_t sien[2]; + uint32_t dsa; + uint32_t temp; + uint32_t dnad; + uint32_t dbc; + uint8_t istat; + uint8_t dcmd; + uint8_t dstat; + uint8_t dien; + uint8_t sist0; + uint8_t sist1; + uint8_t sien0; + uint8_t sien1; uint8_t mbox0; uint8_t mbox1; - volatile uint8_t dfifo; + uint8_t dfifo; uint8_t ctest2; uint8_t ctest3; uint8_t ctest4; uint8_t ctest5; - volatile dword_t dsp; - volatile dword_t dsps; - volatile uint8_t dmode; - volatile uint8_t dcntl; + uint32_t dsp; + uint32_t dsps; + uint8_t dmode; + uint8_t dcntl; uint8_t scntl0; uint8_t scntl1; uint8_t scntl2; @@ -252,47 +243,32 @@ typedef struct { uint8_t sstat1; uint8_t scid; uint8_t sxfer; - volatile uint8_t socl; - volatile uint8_t sdid; - volatile uint8_t ssid; - volatile uint8_t sfbr; - uint8_t stest[3]; - volatile uint8_t sidl; + uint8_t socl; + uint8_t sdid; + uint8_t ssid; + uint8_t sfbr; + uint8_t stest1; + uint8_t stest2; + uint8_t stest3; + uint8_t sidl; uint8_t stime0; uint8_t respid; - dword_t scratcha; /* SCRATCHA */ - volatile dword_t adder; - dword_t scratchb; /* SCRATCHB */ - volatile uint8_t sbr; + uint32_t scratcha; + uint32_t scratchb; + uint8_t sbr; uint8_t chip_rev; - volatile int last_level; - volatile uint8_t gpreg0; - volatile uint32_t buffer_pos; - volatile int32_t temp_buf_len; - volatile uint8_t last_command; + int last_level; + void *hba_private; + uint8_t gpreg0; + uint32_t buffer_pos; + int32_t temp_buf_len; + uint8_t last_command; - volatile uint8_t ncr_to_ncr; - volatile uint8_t in_req; -} ncr53c810c_state_t; + uint8_t sstop; - -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 -ncr53c810c_state_t *ncr53c810_dev; + uint8_t regop; + uint32_t adder; +} ncr53c810_t; #ifdef ENABLE_NCR53C810_LOG @@ -314,8 +290,10 @@ ncr53c810_log(const char *fmt, ...) #endif } -static uint8_t ncr53c810_reg_readb(ncr53c810c_state_t *dev, uint32_t offset); -static void ncr53c810_reg_writeb(ncr53c810c_state_t *dev, uint32_t offset, uint8_t val); + +static uint8_t ncr53c810_reg_readb(ncr53c810_t *dev, uint32_t offset); +static void ncr53c810_reg_writeb(ncr53c810_t *dev, uint32_t offset, uint8_t val); + static __inline__ int32_t sextract32(uint32_t value, int start, int length) @@ -328,7 +306,8 @@ sextract32(uint32_t value, int start, int length) static __inline__ uint32_t -deposit32(uint32_t value, int start, int length, uint32_t fieldval) +deposit32(uint32_t value, int start, int length, + uint32_t fieldval) { uint32_t mask; mask = (~0U >> (32 - length)) << start; @@ -336,31 +315,36 @@ deposit32(uint32_t value, int start, int length, uint32_t fieldval) } -static void -ncr53c810_soft_reset(ncr53c810c_state_t *dev) +static __inline__ int +ncr53c810_irq_on_rsl(ncr53c810_t *dev) { - ncr53c810_log("NCR 810: Soft Reset\n"); + return (dev->sien0 & NCR_SIST0_RSL) && (dev->scid & NCR_SCID_RRE); +} + + +static void +ncr53c810_soft_reset(ncr53c810_t *dev) +{ + ncr53c810_log("LSI Reset\n"); dev->carry = 0; dev->msg_action = 0; dev->msg_len = 0; dev->waiting = 0; - dev->dsa.dw = 0; - dev->temp.dw = 0; - dev->dnad.dw = 0; - dev->dbc.dw = 0; - dev->dsp.dw = 0; - dev->dsps.dw = 0; - dev->scratcha.dw = 0; - dev->adder.dw = 0; - dev->scratchb.dw = 0; - + dev->dsa = 0; + dev->dnad = 0; + dev->dbc = 0; + dev->temp = 0; + dev->scratcha = 0; + dev->scratchb = 0; dev->istat = 0; dev->dcmd = 0x40; dev->dstat = NCR_DSTAT_DFE; dev->dien = 0; - memset((void *) dev->sist, 0, 2); - memset((void *) dev->sien, 0, 2); + dev->sist0 = 0; + dev->sist1 = 0; + dev->sien0 = 0; + dev->sien1 = 0; dev->mbox0 = 0; dev->mbox1 = 0; dev->dfifo = 0; @@ -368,6 +352,8 @@ ncr53c810_soft_reset(ncr53c810c_state_t *dev) dev->ctest3 = 0; dev->ctest4 = 0; dev->ctest5 = 0; + dev->dsp = 0; + dev->dsps = 0; dev->dmode = 0; dev->dcntl = 0; dev->scntl0 = 0xc0; @@ -381,7 +367,9 @@ ncr53c810_soft_reset(ncr53c810c_state_t *dev) dev->socl = 0; dev->sdid = 0; dev->ssid = 0; - memset(dev->stest, 0, 3); + dev->stest1 = 0; + dev->stest2 = 0; + dev->stest3 = 0; dev->sidl = 0; dev->stime0 = 0; dev->respid = 0x80; @@ -389,78 +377,57 @@ ncr53c810_soft_reset(ncr53c810c_state_t *dev) dev->last_level = 0; dev->gpreg0 = 0; dev->sstop = 1; - dev->ncr_to_ncr = 0; } static void -ncr53c810_read(ncr53c810c_state_t *dev, uint32_t addr, uint8_t *buf, uint32_t len, int wait) +ncr53c810_read(ncr53c810_t *dev, uint32_t addr, uint8_t *buf, uint32_t len) { - int i = 0; + int i = 0; -#if 0 - ncr53c810_log("ncr53c810_read(): %08X-%08X, length %i\n", addr, (addr + len - 1), len); -#endif + ncr53c810_log("ncr53c810_read(): %08X-%08X, length %i\n", addr, (addr + len - 1), len); - dev->ncr_to_ncr = wait; - if (dev->dmode & NCR_DMODE_SIOM) { -#if 0 - ncr53c810_log("NCR 810: Reading from I/O address %04X\n", (uint16_t) addr); -#endif - for (i = 0; i < len; i++) - buf[i] = inb((uint16_t) (addr + i)); - } else { -#if 0 - ncr53c810_log("NCR 810: Reading from memory address %08X\n", addr); -#endif - DMAPageRead(addr, buf, len); - } - dev->ncr_to_ncr = 0; + if (dev->dmode & NCR_DMODE_SIOM) { + ncr53c810_log("NCR 810: Reading from I/O address %04X\n", (uint16_t) addr); + for (i = 0; i < len; i++) + buf[i] = inb((uint16_t) (addr + i)); + } else { + ncr53c810_log("NCR 810: Reading from memory address %08X\n", addr); + DMAPageRead(addr, buf, len); + } } static void -ncr53c810_write(ncr53c810c_state_t *dev, uint32_t addr, uint8_t *buf, uint32_t len, int wait) +ncr53c810_write(ncr53c810_t *dev, uint32_t addr, uint8_t *buf, uint32_t len) { - int i = 0; + int i = 0; -#if 0 - ncr53c810_log("ncr53c810_write(): %08X-%08X, length %i\n", addr, (addr + len - 1), len); -#endif + ncr53c810_log("ncr53c810_write(): %08X-%08X, length %i\n", addr, (addr + len - 1), len); - dev->ncr_to_ncr = wait; - if (dev->dmode & NCR_DMODE_DIOM) { -#if 0 - ncr53c810_log("NCR 810: Writing to I/O address %04X\n", (uint16_t) addr); -#endif - for (i = 0; i < len; i++) - outb((uint16_t) (addr + i), buf[i]); - } else { -#if 0 - ncr53c810_log("NCR 810: Writing to memory address %08X\n", addr); -#endif - DMAPageWrite(addr, buf, len); - } - dev->ncr_to_ncr = 0; + if (dev->dmode & NCR_DMODE_DIOM) { + ncr53c810_log("NCR 810: Writing to I/O address %04X\n", (uint16_t) addr); + for (i = 0; i < len; i++) + outb((uint16_t) (addr + i), buf[i]); + } else { + ncr53c810_log("NCR 810: Writing to memory address %08X\n", addr); + DMAPageWrite(addr, buf, len); + } } static __inline__ uint32_t -read_dword(ncr53c810c_state_t *dev, uint32_t addr, int wait) +read_dword(ncr53c810_t *dev, uint32_t addr) { uint32_t buf; -#if 0 ncr53c810_log("Reading the next DWORD from memory (%08X)...\n", addr); -#endif - dev->ncr_to_ncr = wait; DMAPageRead(addr, (uint8_t *)&buf, 4); - dev->ncr_to_ncr = 0; - return buf; + return buf; } -static void -ncr53c810_do_irq(ncr53c810c_state_t *dev, int level) +static +void do_irq(ncr53c810_t *dev, int level) { if (level) { pci_set_irq(dev->pci_slot, PCI_INTA); @@ -473,16 +440,7 @@ ncr53c810_do_irq(ncr53c810c_state_t *dev, int level) static void -ncr53c810_irq_wait(ncr53c810c_state_t *dev, int wait) -{ - /* while(wait && dev->last_level) - ; */ - ncr53c810_log("Interrupt wait over\n"); -} - - -static void -ncr53c810_update_irq(ncr53c810c_state_t *dev, int wait) +ncr53c810_update_irq(ncr53c810_t *dev) { int level; @@ -491,134 +449,103 @@ ncr53c810_update_irq(ncr53c810c_state_t *dev, int wait) We currently do the formwer, which seems to work. */ level = 0; if (dev->dstat & 0x7f) { - if ((dev->dstat & dev->dien) & 0x7f) - level = 1; - dev->istat |= NCR_ISTAT_DIP; + if ((dev->dstat & dev->dien) & 0x7f) + level = 1; + dev->istat |= NCR_ISTAT_DIP; } else { - dev->istat &= ~NCR_ISTAT_DIP; + dev->istat &= ~NCR_ISTAT_DIP; } - if (dev->sist[0] || (dev->sist[1] & 0x07)) { - if ((dev->sist[0] & dev->sien[0]) || ((dev->sist[1] & dev->sien[1]) & 0x07)) - level = 1; - dev->istat |= NCR_ISTAT_SIP; + if (dev->sist0 || dev->sist1) { + if ((dev->sist0 & dev->sien0) || (dev->sist1 & dev->sien1)) + level = 1; + dev->istat |= NCR_ISTAT_SIP; } else { - dev->istat &= ~NCR_ISTAT_SIP; + dev->istat &= ~NCR_ISTAT_SIP; } if (dev->istat & NCR_ISTAT_INTF) { - level = 1; + level = 1; } if (level != dev->last_level) { - ncr53c810_log("Update IRQ level %d dstat %02x sist %02x%02x\n", level, dev->dstat, - dev->sist[1], dev->sist[0]); - dev->last_level = level; - ncr53c810_do_irq(dev, level); /* Only do something with the IRQ if the new level differs from the previous one. */ + ncr53c810_log("Update IRQ level %d dstat %02x sist %02x%02x\n", + level, dev->dstat, dev->sist1, dev->sist0); + dev->last_level = level; + do_irq(dev, level); /* Only do something with the IRQ if the new level differs from the previous one. */ } } /* Stop SCRIPTS execution and raise a SCSI interrupt. */ static void -ncr53c810_script_scsi_interrupt(ncr53c810c_state_t *dev, int stat0, int stat1, int wait) +ncr53c810_script_scsi_interrupt(ncr53c810_t *dev, int stat0, int stat1) { - uint8_t mask[2]; + uint32_t mask0; + uint32_t mask1; - if (dev->istat & NCR_ISTAT_SIP) { - fatal("SCSI interrupt %02X%02X when %02X%02X is already set\n", dev->sist[1] & 0x07, dev->sist[0], stat1 & 0x07, stat0); - return; - } - - ncr53c810_log("SCSI Interrupt 0x%02x%02x prev 0x%02x%02x\n", stat1, stat0, - dev->sist[1], dev->sist[0]); - - stat1 &= 0x07; - - dev->sist[0] |= stat0; - dev->sist[1] |= stat1; - - /* When operating in initiator role, CMP, SEL, RSL, GEN, and HTH are non-fatal, - this means they should only stop SCRIPTS if not masked. - All other interrupts are fatal and should therefore *ALWAYS* stop SCRIPTS. */ - mask[0] = dev->sien[0] | ~(NCR_SIST0_RSL | NCR_SIST0_SEL | NCR_SIST0_CMP); - mask[1] = (dev->sien[1] | ~(NCR_SIST1_HTH | NCR_SIST1_GEN)) & 0x07; - - /* Only stop the script on fatal (unmasked) interrupts. */ - if ((dev->sist[0] & mask[0]) || (dev->sist[1] & mask[1])) + ncr53c810_log("SCSI Interrupt 0x%02x%02x prev 0x%02x%02x\n", + stat1, stat0, dev->sist1, dev->sist0); + dev->sist0 |= stat0; + dev->sist1 |= stat1; + /* Stop processor on fatal or unmasked interrupt. As a special hack + we don't stop processing when raising STO. Instead continue + execution and stop at the next insn that accesses the SCSI bus. */ + mask0 = dev->sien0 | ~(NCR_SIST0_CMP | NCR_SIST0_SEL | NCR_SIST0_RSL); + mask1 = dev->sien1 | ~(NCR_SIST1_GEN | NCR_SIST1_HTH); + mask1 &= ~NCR_SIST1_STO; + if ((dev->sist0 & mask0) || (dev->sist1 & mask1)) { + ncr53c810_log("NCR 810: IRQ-mandated stop\n"); dev->sstop = 1; - /* Update the IRQ level. */ - ncr53c810_update_irq(dev, wait); - /* Wait for IRQ to be cleared. */ - ncr53c810_irq_wait(dev, wait); + } + ncr53c810_update_irq(dev); } /* Stop SCRIPTS execution and raise a DMA interrupt. */ static void -ncr53c810_script_dma_interrupt(ncr53c810c_state_t *dev, int stat, int wait) +ncr53c810_script_dma_interrupt(ncr53c810_t *dev, int stat) { - ncr53c810_log("DMA Interrupt 0x%02x prev 0x%02x mask 0x%02x\n", stat & 0x7F, dev->dstat & 0x7F, dev->dien & 0x7F); - - if (dev->istat & NCR_ISTAT_DIP) { - fatal("DMA interrupt %02X when %02X is already set\n", dev->dstat & 0x7F, stat & 0x7F); - return; - } - - dev->dstat |= (stat & 0x7f); - - /* All DMA interrupts are fatal, therefore, *ALWAYS* stop SCRIPTS. */ + ncr53c810_log("DMA Interrupt 0x%x prev 0x%x\n", stat, dev->dstat); + dev->dstat |= stat; + ncr53c810_update_irq(dev); dev->sstop = 1; - /* Update the IRQ level. */ - ncr53c810_update_irq(dev, wait); - /* Wait for IRQ to be cleared. */ - ncr53c810_irq_wait(dev, wait); } static __inline__ void -ncr53c810_set_phase(ncr53c810c_state_t *dev, int phase) +ncr53c810_set_phase(ncr53c810_t *dev, int phase) { dev->sstat1 = (dev->sstat1 & ~PHASE_MASK) | phase; - ncr53c810_log("Phase set\n"); } static void -ncr53c810_bad_phase(ncr53c810c_state_t *dev, int out, int new_phase) +ncr53c810_bad_phase(ncr53c810_t *dev, int out, int new_phase) { /* Trigger a phase mismatch. */ ncr53c810_log("Phase mismatch interrupt\n"); - ncr53c810_script_scsi_interrupt(dev, NCR_SIST0_MA, 0, 1); + ncr53c810_script_scsi_interrupt(dev, NCR_SIST0_MA, 0); dev->sstop = 1; ncr53c810_set_phase(dev, new_phase); } static void -ncr53c810_disconnect(ncr53c810c_state_t *dev, uint8_t id) +ncr53c810_disconnect(ncr53c810_t *dev) { dev->scntl1 &= ~NCR_SCNTL1_CON; dev->sstat1 &= ~PHASE_MASK; - dev->requests[id].connected = 0; - ncr53c810_log("SCSI ID %i Disconnected\n", id); + if (dev->dcmd & 0x01) /* Select with ATN */ + dev->sstat1 |= 0x07; } static void -ncr53c810_bad_selection(ncr53c810c_state_t *dev, uint32_t id) +ncr53c810_bad_selection(ncr53c810_t *dev, uint32_t id) { - /* Bad selection - raise STO interrupt, disconnect, and stop SCRIPTS if not masked. */ ncr53c810_log("Selected absent target %d\n", id); - ncr53c810_script_scsi_interrupt(dev, 0, NCR_SIST1_STO, 1); - ncr53c810_disconnect(dev, id); -} - - -static void -ncr53c810_set_wait_event(void) -{ - ncr53c810_log("NCR 810: Setting wait event arrived...\n"); - thread_set_event((event_t *)wait_evt); + ncr53c810_script_scsi_interrupt(dev, 0, NCR_SIST1_STO); + ncr53c810_disconnect(dev); } @@ -626,72 +553,62 @@ ncr53c810_set_wait_event(void) static void ncr53c810_command_complete(void *priv, uint32_t status) { - ncr53c810c_state_t *dev = (ncr53c810c_state_t *)priv; + ncr53c810_t *dev = (ncr53c810_t *)priv; int out; - + out = (dev->sstat1 & PHASE_MASK) == PHASE_DO; - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Command complete status=%d\n", - dev->sdid, dev->current_lun, dev->last_command, (int)status); + ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Command complete status=%d\n", dev->current->tag, dev->current_lun, dev->last_command, (int)status); dev->status = status; - dev->command_complete = 2; - if (dev->waiting && dev->dbc.dw != 0) { - /* Raise phase mismatch for short transfers. */ - ncr53c810_bad_phase(dev, out, PHASE_ST); - } else { - ncr53c810_set_phase(dev, PHASE_ST); - } + dev->command_complete = 2; + if (dev->waiting && dev->dbc != 0) { + /* Raise phase mismatch for short transfers. */ + ncr53c810_bad_phase(dev, out, PHASE_ST); + } else + ncr53c810_set_phase(dev, PHASE_ST); dev->sstop = 0; - - ncr53c810_log("Command complete\n"); } static void -ncr53c810_do_dma(ncr53c810c_state_t *dev, int out, uint8_t id, int wait) +ncr53c810_do_dma(ncr53c810_t *dev, int out, uint8_t id) { uint32_t addr, count, tdbc; scsi_device_t *sd; - ncr53c810_log("Do DMA...\n"); - sd = &SCSIDevices[id][dev->current_lun]; if ((((id) == -1) && !scsi_device_present(id, dev->current_lun))) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Device not present when attempting to do DMA\n", - id, dev->current_lun, dev->last_command); + ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Device not present when attempting to do DMA\n", id, dev->current_lun, dev->last_command); return; } - if (!dev->requests[id].dma_len) { - /* Wait until data is available. */ - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: DMA no data available\n", - id, dev->current_lun, dev->last_command); - return; + if (!dev->current->dma_len) { + /* Wait until data is available. */ + ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: DMA no data available\n", id, dev->current_lun, dev->last_command); + return; } /* Make sure count is never bigger than BufferLength. */ - count = tdbc = dev->dbc.dw; + count = tdbc = dev->dbc; if (count > dev->temp_buf_len) count = dev->temp_buf_len; - addr = dev->dnad.dw; + addr = dev->dnad; - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: DMA addr=0x%08x len=%d cur_len=%d dev->dbc=%d\n", - id, dev->current_lun, dev->last_command, dev->dnad.dw, dev->temp_buf_len, count, tdbc); - dev->dnad.dw += count; - dev->dbc.dw -= count; + ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: DMA addr=0x%08x len=%d cur_len=%d dev->dbc=%d\n", id, dev->current_lun, dev->last_command, dev->dnad, dev->temp_buf_len, count, tdbc); + dev->dnad += count; + dev->dbc -= count; - if (out) { - ncr53c810_read(dev, addr, sd->CmdBuffer+dev->buffer_pos, count, wait); - } else { + if (out) + ncr53c810_read(dev, addr, sd->CmdBuffer+dev->buffer_pos, count); + else { if (!dev->buffer_pos) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: SCSI Command Phase 1 on PHASE_DI\n", - id, dev->current_lun, dev->last_command); - scsi_device_command_phase1(id, dev->current_lun); + ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: SCSI Command Phase 1 on PHASE_DI\n", id, dev->current_lun, dev->last_command); + scsi_device_command_phase1(dev->current->tag, dev->current_lun); } - ncr53c810_write(dev, addr, sd->CmdBuffer+dev->buffer_pos, count, wait); + ncr53c810_write(dev, addr, sd->CmdBuffer+dev->buffer_pos, count); } dev->temp_buf_len -= count; @@ -699,8 +616,7 @@ ncr53c810_do_dma(ncr53c810c_state_t *dev, int out, uint8_t id, int wait) if (dev->temp_buf_len <= 0) { if (out) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: SCSI Command Phase 1 on PHASE_DO\n", - id, dev->current_lun, dev->last_command); + ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: SCSI Command Phase 1 on PHASE_DO\n", id, dev->current_lun, dev->last_command); scsi_device_command_phase1(id, dev->current_lun); } if (sd->CmdBuffer != NULL) { @@ -709,75 +625,57 @@ ncr53c810_do_dma(ncr53c810c_state_t *dev, int out, uint8_t id, int wait) } ncr53c810_command_complete(dev, SCSIStatus); } else { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Resume SCRIPTS\n", - id, dev->current_lun, dev->last_command); + ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Resume SCRIPTS\n", id, dev->current_lun, dev->last_command); dev->sstop = 0; } - - dev->in_req = 0; } /* Queue a byte for a MSG IN phase. */ static void -ncr53c810_add_msg_byte(ncr53c810c_state_t *dev, uint8_t data) +ncr53c810_add_msg_byte(ncr53c810_t *dev, uint8_t data) { - if (dev->msg_len >= NCR_MAX_MSGIN_LEN) { - ncr53c810_log("MSG IN data too long\n"); - } else { - ncr53c810_log("MSG IN 0x%02x\n", data); - dev->msg[dev->msg_len++] = data; + if (dev->msg_len >= NCR_MAX_MSGIN_LEN) + ncr53c810_log("MSG IN data too long\n"); + else { + ncr53c810_log("MSG IN 0x%02x\n", data); + dev->msg[dev->msg_len++] = data; } } static void -ncr53c810_busy(uint8_t set) -{ - if (busy == !!set) - return; - - busy = !!set; - if (!set) - thread_set_event((event_t *) wake_poll_thread); -} - - -static void -ncr53c810_do_command(ncr53c810c_state_t *dev, uint8_t id) +ncr53c810_do_command(ncr53c810_t *dev, uint8_t id) { scsi_device_t *sd; uint8_t buf[12]; - ncr53c810_log("Do command\n"); - memset(buf, 0, 12); - DMAPageRead(dev->dnad.dw, buf, MIN(12, dev->dbc.dw)); - if (dev->dbc.dw > 12) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: CDB length %i too big\n", - id, dev->current_lun, buf[0], dev->dbc); - dev->dbc.dw = 12; + DMAPageRead(dev->dnad, buf, MIN(12, dev->dbc)); + if (dev->dbc > 12) { + ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: CDB length %i too big\n", id, dev->current_lun, buf[0], dev->dbc); + dev->dbc = 12; } dev->sfbr = buf[0]; dev->command_complete = 0; sd = &SCSIDevices[id][dev->current_lun]; if (((id == -1) || !scsi_device_present(id, dev->current_lun))) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Bad Selection\n", id, dev->current_lun, buf[0]); - ncr53c810_bad_selection(dev, id); - return; + ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Bad Selection\n", id, dev->current_lun, buf[0]); + ncr53c810_bad_selection(dev, id); + return; } - - dev->in_req = 1; - dev->requests[id].tag = id; + + dev->current = (ncr53c810_request*)malloc(sizeof(ncr53c810_request)); + dev->current->tag = id; sd->BufferLength = -1; - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: DBC=%i\n", id, dev->current_lun, - buf[0], dev->dbc.dw); + ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: DBC=%i\n", id, dev->current_lun, buf[0], dev->dbc); dev->last_command = buf[0]; - scsi_device_command_phase0(id, dev->current_lun, dev->dbc.dw, buf); + scsi_device_command_phase0(dev->current->tag, dev->current_lun, dev->dbc, buf); + dev->hba_private = (void *)dev->current; dev->waiting = 0; dev->buffer_pos = 0; @@ -786,32 +684,31 @@ ncr53c810_do_command(ncr53c810c_state_t *dev, uint8_t id) if (sd->BufferLength > 0) { sd->CmdBuffer = (uint8_t *)malloc(sd->BufferLength); - dev->requests[id].dma_len = sd->BufferLength; + dev->current->dma_len = sd->BufferLength; } if ((SCSIPhase == SCSI_PHASE_DATA_IN) && (sd->BufferLength > 0)) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DI\n", - id, dev->current_lun, buf[0]); + ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DI\n", id, dev->current_lun, buf[0]); ncr53c810_set_phase(dev, PHASE_DI); } else if ((SCSIPhase == SCSI_PHASE_DATA_OUT) && (sd->BufferLength > 0)) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DO\n", - id, dev->current_lun, buf[0]); + ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DO\n", id, dev->current_lun, buf[0]); ncr53c810_set_phase(dev, PHASE_DO); - } else { + } else ncr53c810_command_complete(dev, SCSIStatus); - } } -static void ncr53c810_do_status(ncr53c810c_state_t *dev, int wait) + +static void +ncr53c810_do_status(ncr53c810_t *dev) { uint8_t status; ncr53c810_log("Get status len=%d status=%d\n", dev->dbc, dev->status); - if (dev->dbc.dw != 1) - ncr53c810_log("Bad Status move\n"); - dev->dbc.dw = 1; + if (dev->dbc != 1) + ncr53c810_log("Bad Status move\n"); + dev->dbc = 1; status = dev->status; dev->sfbr = status; - ncr53c810_write(dev, dev->dnad.dw, &status, 1, wait); + ncr53c810_write(dev, dev->dnad, &status, 1); ncr53c810_set_phase(dev, PHASE_MI); dev->msg_action = 1; ncr53c810_add_msg_byte(dev, 0); /* COMMAND COMPLETE */ @@ -819,36 +716,38 @@ static void ncr53c810_do_status(ncr53c810c_state_t *dev, int wait) static void -ncr53c810_do_msgin(ncr53c810c_state_t *dev, int wait) +ncr53c810_do_msgin(ncr53c810_t *dev) { int len; ncr53c810_log("Message in len=%d/%d\n", dev->dbc, dev->msg_len); dev->sfbr = dev->msg[0]; len = dev->msg_len; - if (len > dev->dbc.dw) - len = dev->dbc.dw; - ncr53c810_write(dev, dev->dnad.dw, dev->msg, len, wait); + if (len > dev->dbc) + len = dev->dbc; + ncr53c810_write(dev, dev->dnad, dev->msg, len); /* Linux drivers rely on the last byte being in the SIDL. */ dev->sidl = dev->msg[len - 1]; dev->msg_len -= len; if (dev->msg_len) memmove(dev->msg, dev->msg + len, dev->msg_len); - else { + else { + /* ??? Check if ATN (not yet implemented) is asserted and maybe + switch to PHASE_MO. */ switch (dev->msg_action) { - case 0: - ncr53c810_set_phase(dev, PHASE_CMD); - break; - case 1: - ncr53c810_disconnect(dev, dev->sdid); - break; - case 2: - ncr53c810_set_phase(dev, PHASE_DO); - break; - case 3: - ncr53c810_set_phase(dev, PHASE_DI); - break; - default: - fatal("Invalid message action: %i\n", dev->msg_action); + case 0: + ncr53c810_set_phase(dev, PHASE_CMD); + break; + case 1: + ncr53c810_disconnect(dev); + break; + case 2: + ncr53c810_set_phase(dev, PHASE_DO); + break; + case 3: + ncr53c810_set_phase(dev, PHASE_DI); + break; + default: + abort(); } } } @@ -856,29 +755,29 @@ ncr53c810_do_msgin(ncr53c810c_state_t *dev, int wait) /* Read the next byte during a MSGOUT phase. */ static uint8_t -ncr53c810_get_msgbyte(ncr53c810c_state_t *dev) +ncr53c810_get_msgbyte(ncr53c810_t *dev) { uint8_t data; - DMAPageRead(dev->dnad.dw, &data, 1); - dev->dnad.dw++; - dev->dbc.dw--; + DMAPageRead(dev->dnad, &data, 1); + dev->dnad++; + dev->dbc--; return data; } /* Skip the next n bytes during a MSGOUT phase. */ static void -ncr53c810_skip_msgbytes(ncr53c810c_state_t *dev, unsigned int n) +ncr53c810_skip_msgbytes(ncr53c810_t *dev, unsigned int n) { - dev->dnad.dw += n; - dev->dbc.dw -= n; + dev->dnad += n; + dev->dbc -= n; } static void -ncr53c810_bad_msg(ncr53c810c_state_t *dev) +ncr53c810_bad_message(ncr53c810_t *dev, uint8_t msg) { - ncr53c810_log("MSG: Illegal\n"); + ncr53c810_log("Unimplemented message 0x%02x\n", msg); ncr53c810_set_phase(dev, PHASE_MI); ncr53c810_add_msg_byte(dev, 7); /* MESSAGE REJECT */ dev->msg_action = 0; @@ -886,25 +785,26 @@ ncr53c810_bad_msg(ncr53c810c_state_t *dev) static void -ncr53c810_do_msgout(ncr53c810c_state_t *dev, uint8_t id) +ncr53c810_do_msgout(ncr53c810_t *dev, uint8_t id) { uint8_t msg; int len; + uint32_t current_tag; scsi_device_t *sd; sd = &SCSIDevices[id][dev->current_lun]; - if ((id > 7) || (dev->current_lun > 7)) - dev = NULL; + + current_tag = id; ncr53c810_log("MSG out len=%d\n", dev->dbc); - while (dev->dbc.dw) { + while (dev->dbc) { msg = ncr53c810_get_msgbyte(dev); dev->sfbr = msg; switch (msg) { case 0x04: ncr53c810_log("MSG: Disconnect\n"); - ncr53c810_disconnect(dev, id); + ncr53c810_disconnect(dev); break; case 0x08: ncr53c810_log("MSG: No Operation\n"); @@ -913,6 +813,7 @@ ncr53c810_do_msgout(ncr53c810c_state_t *dev, uint8_t id) case 0x01: len = ncr53c810_get_msgbyte(dev); msg = ncr53c810_get_msgbyte(dev); + (void) len; /* avoid a warning about unused variable*/ ncr53c810_log("Extended message 0x%x (len %d)\n", msg, len); switch (msg) { case 1: @@ -924,48 +825,61 @@ ncr53c810_do_msgout(ncr53c810c_state_t *dev, uint8_t id) ncr53c810_skip_msgbytes(dev, 1); break; default: - ncr53c810_bad_msg(dev); + ncr53c810_bad_message(dev, msg); return; } break; case 0x20: /* SIMPLE queue */ - case 0x21: /* HEAD of queue */ - case 0x22: /* ORDERED queue */ - ncr53c810_log("MSG: Queue\n"); - id |= (ncr53c810_get_msgbyte(dev) | NCR_TAG_VALID); + id |= ncr53c810_get_msgbyte(dev) | NCR_TAG_VALID; ncr53c810_log("SIMPLE queue tag=0x%x\n", id & 0xff); break; + case 0x21: /* HEAD of queue */ + ncr53c810_log("HEAD queue not implemented\n"); + id |= ncr53c810_get_msgbyte(dev) | NCR_TAG_VALID; + break; + case 0x22: /* ORDERED queue */ + ncr53c810_log("ORDERED queue not implemented\n"); + id |= ncr53c810_get_msgbyte(dev) | NCR_TAG_VALID; + break; case 0x0d: /* The ABORT TAG message clears the current I/O process only. */ - ncr53c810_log("MSG: Abort Tag\n"); - if (sd && sd->CmdBuffer) { + ncr53c810_log("MSG: ABORT TAG tag=0x%x\n", current_tag); + if (sd->CmdBuffer) { free(sd->CmdBuffer); sd->CmdBuffer = NULL; } - ncr53c810_disconnect(dev, id); + ncr53c810_disconnect(dev); break; case 0x06: case 0x0e: case 0x0c: /* The ABORT message clears all I/O processes for the selecting initiator on the specified logical unit of the target. */ - ncr53c810_log("MSG: Abort, Clear Queue, or Bus Device Reset\n"); + if (msg == 0x06) + ncr53c810_log("MSG: ABORT tag=0x%x\n", current_tag); + /* The CLEAR QUEUE message clears all I/O processes for all + initiators on the specified logical unit of the target. */ + if (msg == 0x0e) + ncr53c810_log("MSG: CLEAR QUEUE tag=0x%x\n", current_tag); + /* The BUS DEVICE RESET message clears all I/O processes for all + initiators on all logical units of the target. */ + if (msg == 0x0c) + ncr53c810_log("MSG: BUS DEVICE RESET tag=0x%x\n", current_tag); /* clear the current I/O process */ - if (sd && sd->CmdBuffer) { + if (sd->CmdBuffer) { free(sd->CmdBuffer); sd->CmdBuffer = NULL; } - - ncr53c810_disconnect(dev, id); + ncr53c810_disconnect(dev); break; default: if ((msg & 0x80) == 0) { - ncr53c810_bad_msg(dev); + ncr53c810_bad_message(dev, msg); return; } else { - ncr53c810_log("MSG: Select LUN\n"); dev->current_lun = msg & 7; + ncr53c810_log("Select LUN %d\n", dev->current_lun); ncr53c810_set_phase(dev, PHASE_CMD); } break; @@ -975,7 +889,7 @@ ncr53c810_do_msgout(ncr53c810c_state_t *dev, uint8_t id) static void -ncr53c810_memcpy(ncr53c810c_state_t *dev, uint32_t dest, uint32_t src, int count, int wait) +ncr53c810_memcpy(ncr53c810_t *dev, uint32_t dest, uint32_t src, int count) { int n; uint8_t buf[NCR_BUF_SIZE]; @@ -983,8 +897,8 @@ ncr53c810_memcpy(ncr53c810c_state_t *dev, uint32_t dest, uint32_t src, int count ncr53c810_log("memcpy dest 0x%08x src 0x%08x count %d\n", dest, src, count); while (count) { n = (count > NCR_BUF_SIZE) ? NCR_BUF_SIZE : count; - ncr53c810_read(dev, src, buf, n, wait); - ncr53c810_write(dev, dest, buf, n, wait); + ncr53c810_read(dev, src, buf, n); + ncr53c810_write(dev, dest, buf, n); src += n; dest += n; count -= n; @@ -993,73 +907,76 @@ ncr53c810_memcpy(ncr53c810c_state_t *dev, uint32_t dest, uint32_t src, int count static void -ncr53c810_execute_ins(ncr53c810c_state_t *dev, int wait) +ncr53c810_execute_script(ncr53c810_t *dev) { - uint32_t insn, addr, id, dest, buf[2]; - int opcode, reg, n, i, operator, cond, jmp, insn_processed = 0; + uint32_t insn, addr, id, buf[2], dest; + int opcode, insn_processed = 0, reg, operator, cond, jmp, n, i; int32_t offset; uint8_t op0, op1, data8, mask, data[7], *pp; dev->sstop = 0; +again: insn_processed++; - insn = read_dword(dev, dev->dsp.dw, wait); + insn = read_dword(dev, dev->dsp); if (!insn) { /* If we receive an empty opcode increment the DSP by 4 bytes instead of 8 and execute the next opcode at that location */ - dev->dsp.dw += 4; - goto end_of_ins; /* The thread will take care of resuming execution. */ + dev->dsp += 4; + goto again; } - addr = read_dword(dev, dev->dsp.dw + 4, wait); -#if 0 - ncr53c810_log("SCRIPTS dsp=%08x opcode %08x arg %08x\n", dev->dsp.dw, insn, addr); -#endif - dev->dsps.dw = addr; + addr = read_dword(dev, dev->dsp + 4); + ncr53c810_log("SCRIPTS dsp=%08x opcode %08x arg %08x\n", dev->dsp, insn, addr); + dev->dsps = addr; dev->dcmd = insn >> 24; - dev->dsp.dw += 8; - + dev->dsp += 8; + switch (insn >> 30) { case 0: /* Block move. */ ncr53c810_log("00: Block move\n"); - if (dev->sist[1] & NCR_SIST1_STO) { - ncr53c810_log("Delayed select timeout\n"); + if (dev->sist1 & NCR_SIST1_STO) { + ncr53c810_log("Delayed select timeout\n"); dev->sstop = 1; break; } - dev->dbc.dw = insn & 0xffffff; - ncr53c810_log("Block Move: DBC is now %d\n", dev->dbc); + ncr53c810_log("Block Move DBC=%d\n", dev->dbc); + dev->dbc = insn & 0xffffff; + ncr53c810_log("Block Move DBC=%d now\n", dev->dbc); /* ??? Set ESA. */ if (insn & (1 << 29)) { /* Indirect addressing. */ - addr = read_dword(dev, addr, wait); + /* Should this respect SIOM? */ + addr = read_dword(dev, addr); ncr53c810_log("Indirect Block Move address: %08X\n", addr); } else if (insn & (1 << 28)) { /* Table indirect addressing. */ /* 32-bit Table indirect */ offset = sextract32(addr, 0, 24); - DMAPageRead(dev->dsa.dw + offset, (uint8_t *)buf, 8); + DMAPageRead(dev->dsa + offset, (uint8_t *)buf, 8); /* byte count is stored in bits 0:23 only */ - dev->dbc.dw = buf[0] & 0xffffff; + dev->dbc = buf[0] & 0xffffff; addr = buf[1]; + + /* 40-bit DMA, upper addr bits [39:32] stored in first DWORD of + * table, bits [31:24] */ } if ((dev->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) { - ncr53c810_log("Wrong phase got %d, expected %d\n", - dev->sstat1 & PHASE_MASK, (insn >> 24) & 7); - ncr53c810_script_scsi_interrupt(dev, NCR_SIST0_MA, 0, wait); + ncr53c810_log("Wrong phase got %d expected %d\n", + dev->sstat1 & PHASE_MASK, (insn >> 24) & 7); + ncr53c810_script_scsi_interrupt(dev, NCR_SIST0_MA, 0); break; } - dev->dnad.dw = addr; - ncr53c810_log("Phase before: %01X\n", dev->sstat1 & 0x7); + dev->dnad = addr; switch (dev->sstat1 & 0x7) { case PHASE_DO: - dev->waiting = 0; ncr53c810_log("Data Out Phase\n"); - ncr53c810_do_dma(dev, 1, dev->sdid, wait); + dev->waiting = 0; + ncr53c810_do_dma(dev, 1, dev->sdid); break; case PHASE_DI: ncr53c810_log("Data In Phase\n"); dev->waiting = 0; - ncr53c810_do_dma(dev, 0, dev->sdid, wait); + ncr53c810_do_dma(dev, 0, dev->sdid); break; case PHASE_CMD: ncr53c810_log("Command Phase\n"); @@ -1067,7 +984,7 @@ ncr53c810_execute_ins(ncr53c810c_state_t *dev, int wait) break; case PHASE_ST: ncr53c810_log("Status Phase\n"); - ncr53c810_do_status(dev, wait); + ncr53c810_do_status(dev); break; case PHASE_MO: ncr53c810_log("MSG Out Phase\n"); @@ -1075,15 +992,13 @@ ncr53c810_execute_ins(ncr53c810c_state_t *dev, int wait) break; case PHASE_MI: ncr53c810_log("MSG In Phase\n"); - ncr53c810_do_msgin(dev, wait); + ncr53c810_do_msgin(dev); break; default: ncr53c810_log("Unimplemented phase %d\n", dev->sstat1 & PHASE_MASK); } - ncr53c810_log("Phase after: %01X\n", dev->sstat1 & 0x7); - - dev->dfifo = dev->dbc.dw & 0xff; - dev->ctest5 = (dev->ctest5 & 0xfc) | ((dev->dbc.dw >> 8) & 3); + dev->dfifo = dev->dbc & 0xff; + dev->ctest5 = (dev->ctest5 & 0xfc) | ((dev->dbc >> 8) & 3); break; case 1: /* IO or Read/Write instruction. */ @@ -1091,19 +1006,19 @@ ncr53c810_execute_ins(ncr53c810c_state_t *dev, int wait) opcode = (insn >> 27) & 7; if (opcode < 5) { if (insn & (1 << 25)) - id = read_dword(dev, dev->dsa.dw + sextract32(insn, 0, 24), wait); + id = read_dword(dev, dev->dsa + sextract32(insn, 0, 24)); else id = insn; - id = (id >> 16) & 0x07; + id = (id >> 16) & 0xf; if (insn & (1 << 26)) - addr = dev->dsp.dw + sextract32(addr, 0, 24); - dev->dnad.dw = addr; + addr = dev->dsp + sextract32(addr, 0, 24); + dev->dnad = addr; switch (opcode) { case 0: /* Select */ dev->sdid = id; if (dev->scntl1 & NCR_SCNTL1_CON) { - ncr53c810_log("Already reselected, jumping to alt. address\n"); - dev->dsp.dw = dev->dnad.dw; + ncr53c810_log("Already reselected, jumping to alternative address\n"); + dev->dsp = dev->dnad; break; } dev->sstat0 |= NCR_SSTAT0_WOA; @@ -1113,7 +1028,8 @@ ncr53c810_execute_ins(ncr53c810c_state_t *dev, int wait) break; } ncr53c810_log("Selected target %d%s\n", - id, insn & (1 << 24) ? " ATN" : ""); + id, insn & (1 << 24) ? " ATN" : ""); + dev->select_id = id << 8; dev->scntl1 |= NCR_SCNTL1_CON; if (insn & (1 << 24)) dev->socl |= NCR_SOCL_ATN; @@ -1121,18 +1037,19 @@ ncr53c810_execute_ins(ncr53c810c_state_t *dev, int wait) dev->waiting = 0; break; case 1: /* Disconnect */ - ncr53c810_log("Disconnect\n"); + ncr53c810_log("Wait Disconnect\n"); dev->scntl1 &= ~NCR_SCNTL1_CON; break; case 2: /* Wait Reselect */ - ncr53c810_log("Wait Reselect on SCSI ID %i\n", dev->sdid); - dev->waiting = 1; + ncr53c810_log("Wait Reselect\n"); + if (!ncr53c810_irq_on_rsl(dev)) + dev->waiting = 1; break; case 3: /* Set */ - ncr53c810_log("Set%s%s%s%s\n", insn & (1 << 3) ? " ATN" : "", - insn & (1 << 6) ? " ACK" : "", - insn & (1 << 9) ? " TM" : "", - insn & (1 << 10) ? " CC" : ""); + ncr53c810_log("Set%s%s%s%s\n", insn & (1 << 3) ? " ATN" : "", + insn & (1 << 6) ? " ACK" : "", + insn & (1 << 9) ? " TM" : "", + insn & (1 << 10) ? " CC" : ""); if (insn & (1 << 3)) { dev->socl |= NCR_SOCL_ATN; ncr53c810_set_phase(dev, PHASE_MO); @@ -1144,11 +1061,11 @@ ncr53c810_execute_ins(ncr53c810c_state_t *dev, int wait) break; case 4: /* Clear */ ncr53c810_log("Clear%s%s%s%s\n", insn & (1 << 3) ? " ATN" : "", - insn & (1 << 6) ? " ACK" : "", - insn & (1 << 9) ? " TM" : "", - insn & (1 << 10) ? " CC" : ""); + insn & (1 << 6) ? " ACK" : "", + insn & (1 << 9) ? " TM" : "", + insn & (1 << 10) ? " CC" : ""); if (insn & (1 << 3)) - dev->socl &= ~NCR_SOCL_ATN; + dev->socl &= ~NCR_SOCL_ATN; if (insn & (1 << 10)) dev->carry = 0; break; @@ -1159,7 +1076,6 @@ ncr53c810_execute_ins(ncr53c810c_state_t *dev, int wait) opcode = (insn >> 27) & 7; operator = (insn >> 24) & 7; op0 = op1 = 0; - switch (opcode) { case 5: /* From SFBR */ op0 = dev->sfbr; @@ -1219,9 +1135,7 @@ ncr53c810_execute_ins(ncr53c810c_state_t *dev, int wait) switch (opcode) { case 5: /* From SFBR */ case 7: /* Read-modify-write */ - dev->ncr_to_ncr = wait; ncr53c810_reg_writeb(dev, reg, op0); - dev->ncr_to_ncr = 0; break; case 6: /* To SFBR */ dev->sfbr = op0; @@ -1232,12 +1146,11 @@ ncr53c810_execute_ins(ncr53c810c_state_t *dev, int wait) case 2: /* Transfer Control. */ ncr53c810_log("02: Transfer Control\n"); - if ((insn & 0x002e0000) == 0) { ncr53c810_log("NOP\n"); break; } - if (dev->sist[1] & NCR_SIST1_STO) { + if (dev->sist1 & NCR_SIST1_STO) { ncr53c810_log("Delayed select timeout\n"); dev->sstop = 1; break; @@ -1249,47 +1162,46 @@ ncr53c810_execute_ins(ncr53c810c_state_t *dev, int wait) } if (cond == jmp && (insn & (1 << 17))) { ncr53c810_log("Compare phase %d %c= %d\n", (dev->sstat1 & PHASE_MASK), - jmp ? '=' : '!', ((insn >> 24) & 7)); + jmp ? '=' : '!', ((insn >> 24) & 7)); cond = (dev->sstat1 & PHASE_MASK) == ((insn >> 24) & 7); } if (cond == jmp && (insn & (1 << 18))) { mask = (~insn >> 8) & 0xff; ncr53c810_log("Compare data 0x%x & 0x%x %c= 0x%x\n", dev->sfbr, mask, - jmp ? '=' : '!', insn & mask); + jmp ? '=' : '!', insn & mask); cond = (dev->sfbr & mask) == (insn & mask); } if (cond == jmp) { if (insn & (1 << 23)) { /* Relative address. */ - addr = dev->dsp.dw + sextract32(addr, 0, 24); + addr = dev->dsp + sextract32(addr, 0, 24); } switch ((insn >> 27) & 7) { case 0: /* Jump */ ncr53c810_log("Jump to 0x%08x\n", addr); - dev->adder.dw = addr; - dev->dsp.dw = addr; + dev->adder = addr; + dev->dsp = addr; break; case 1: /* Call */ ncr53c810_log("Call 0x%08x\n", addr); - dev->temp.dw = dev->dsp.dw; - dev->dsp.dw = addr; + dev->temp = dev->dsp; + dev->dsp = addr; break; case 2: /* Return */ - ncr53c810_log("Return to 0x%08x\n", dev->temp.dw); - dev->dsp.dw = dev->temp.dw; + ncr53c810_log("Return to 0x%08x\n", dev->temp); + dev->dsp = dev->temp; break; case 3: /* Interrupt */ - ncr53c810_log("Interrupt 0x%08x\n", dev->dsps.dw); + ncr53c810_log("Interrupt 0x%08x\n", dev->dsps); if ((insn & (1 << 20)) != 0) { dev->istat |= NCR_ISTAT_INTF; - ncr53c810_update_irq(dev, wait); - ncr53c810_irq_wait(dev, wait); + ncr53c810_update_irq(dev); } else - ncr53c810_script_dma_interrupt(dev, NCR_DSTAT_SIR, wait); + ncr53c810_script_dma_interrupt(dev, NCR_DSTAT_SIR); break; default: - ncr53c810_log("Invalid opcode\n"); - ncr53c810_script_dma_interrupt(dev, NCR_DSTAT_IID, wait); + ncr53c810_log("Illegal transfer control\n"); + ncr53c810_script_dma_interrupt(dev, NCR_DSTAT_IID); break; } } else @@ -1297,27 +1209,30 @@ ncr53c810_execute_ins(ncr53c810c_state_t *dev, int wait) break; case 3: - ncr53c810_log("03: Memory move\n"); + ncr53c810_log("00: Memory move\n"); if ((insn & (1 << 29)) == 0) { /* Memory move. */ - dest = read_dword(dev, dev->dsp.dw, wait); - dev->dsp.dw += 4; - ncr53c810_memcpy(dev, dest, addr, insn & 0xffffff, wait); + /* ??? The docs imply the destination address is loaded into + the TEMP register. However the Linux drivers rely on + the value being presrved. */ + dest = read_dword(dev, dev->dsp); + dev->dsp += 4; + ncr53c810_memcpy(dev, dest, addr, insn & 0xffffff); } else { pp = data; if (insn & (1 << 28)) - addr = dev->dsa.dw + sextract32(addr, 0, 24); + addr = dev->dsa + sextract32(addr, 0, 24); n = (insn & 7); reg = (insn >> 16) & 0xff; if (insn & (1 << 24)) { DMAPageRead(addr, data, n); - ncr53c810_log("Load reg 0x%x size %d addr 0x%08x = %08x\n", reg, n, - addr, *(unsigned *)pp); + ncr53c810_log("Load reg 0x%x size %d addr 0x%08x = %08x\n", reg, n, addr, + *(unsigned *)pp); for (i = 0; i < n; i++) ncr53c810_reg_writeb(dev, reg + i, data[i]); } else { - ncr53c810_log("Store reg 0x%x size %d addr 0x%08x\n", reg, n, addr); + ncr53c810_log("Store reg 0x%x size %d addr 0x%08x\n", reg, n, addr); for (i = 0; i < n; i++) data[i] = ncr53c810_reg_readb(dev, reg + i); DMAPageWrite(addr, data, n); @@ -1329,139 +1244,58 @@ ncr53c810_execute_ins(ncr53c810c_state_t *dev, int wait) ncr53c810_log("%02X: Unknown command\n", (uint8_t) (insn >> 30)); } -end_of_ins: - ncr53c810_log("%i instruction(s) processed\n", insn_processed); - if ((insn_processed > 10000) && !dev->waiting) { + ncr53c810_log("instructions processed %i\n", insn_processed); + if (insn_processed > 10000 && !dev->waiting) { /* Some windows drivers make the device spin waiting for a memory location to change. If we have been executed a lot of code then assume this is the case and force an unexpected device disconnect. This is apparently sufficient to beat the drivers into submission. */ ncr53c810_log("Some windows drivers make the device spin...\n"); - if (!(dev->sien[0] & NCR_SIST0_UDC)) + if (!(dev->sien0 & NCR_SIST0_UDC)) ncr53c810_log("inf. loop with UDC masked\n"); - ncr53c810_script_scsi_interrupt(dev, NCR_SIST0_UDC, 0, wait); - ncr53c810_disconnect(dev, dev->sdid); + ncr53c810_script_scsi_interrupt(dev, NCR_SIST0_UDC, 0); + ncr53c810_disconnect(dev); } else if (!dev->sstop && !dev->waiting) { if (dev->dcntl & NCR_DCNTL_SSM) { ncr53c810_log("NCR 810: SCRIPTS: Single-step mode\n"); - ncr53c810_script_dma_interrupt(dev, NCR_DSTAT_SSI, wait); - dev->sstop = 1; + ncr53c810_script_dma_interrupt(dev, NCR_DSTAT_SSI); + } else { + ncr53c810_log("NCR 810: SCRIPTS: Normal mode\n"); + goto again; } - } - ncr53c810_log("SFBR now: %02X\n", dev->sfbr); - - if ((dev->dmode & NCR_DMODE_MAN) && dev->sstop) - dev->dcntl &= ~NCR_DCNTL_STD; -} - - -static void -ncr53c810_process_script(ncr53c810c_state_t *dev) -{ - ncr53c810_execute_ins(dev, 1); -} - - -static uint8_t -ncr53c810_is_busy(void) -{ - return(!!busy); -} - - -void -ncr53c810_wait_for_poll(void) -{ - if (ncr53c810_is_busy()) { -#if 0 - ncr53c810_log("NCR 810: Waiting for thread wake event...\n"); -#endif - thread_wait_event((event_t *) wake_poll_thread, -1); - } -#if 0 - ncr53c810_log("NCR 810: Thread wake event arrived...\n"); -#endif - thread_reset_event((event_t *) wake_poll_thread); -} - - -static void -ncr53c810_script_thread(void *priv) -{ - ncr53c810c_state_t *dev = (ncr53c810c_state_t *) ncr53c810_dev; - - thread_set_event((event_t *) thread_started); - - ncr53c810_log("Polling thread started\n"); - - while (ncr53c810_dev) { - scsi_mutex_wait(1); - - if (!dev->sstop) { - ncr53c810_wait_for_poll(); - - if (dev->waiting) { - /* Wait for event followed by a clear of the waiting state - if waiting for reselect. */ - thread_wait_event((event_t *) wait_evt, dev->waiting); - } - - if (!dev->waiting) - ncr53c810_process_script(dev); - - if (dev->sstop) - ncr53c810_log("SCRIPTS finished\n"); - } else - thread_wait_event((event_t *) wait_evt, 10); - - scsi_mutex_wait(0); + } else { + if (dev->sstop) + ncr53c810_log("NCR 810: SCRIPTS: Stopped\n"); + if (dev->waiting) + ncr53c810_log("NCR 810: SCRIPTS: Waiting\n"); } - ncr53c810_log("NCR 810: Callback: polling stopped.\n"); + ncr53c810_log("SCRIPTS execution stopped\n"); } static void -ncr53c810_thread_start(ncr53c810c_state_t *dev) -{ - if (!poll_tid) { - poll_tid = thread_create(ncr53c810_script_thread, dev); - } -} - - -static void -ncr53c810_execute_script(ncr53c810c_state_t *dev) -{ - FILE *f; - - ncr53c810_log("Starting SCRIPTS...\n"); - ncr53c810_busy(1); - dev->sstop = dev->waiting = 0; - ncr53c810_set_wait_event(); - ncr53c810_busy(0); - - ncr53c810_log("SCRIPT base address: %08X\n", dev->dsp.dw - 4096); - f = fopen("810scripts.bin", "wb"); - fwrite(&ram[dev->dsp.dw - 4096], 1, 65536, f); - fclose(f); -} - - -static void -ncr53c810_reg_writeb(ncr53c810c_state_t *dev, uint32_t offset, uint8_t val) +ncr53c810_reg_writeb(ncr53c810_t *dev, uint32_t offset, uint8_t val) { uint8_t tmp = 0; - if (!dev->ncr_to_ncr) - ncr53c810_busy(1); +#define CASE_SET_REG24(name, addr) \ + case addr : dev->name &= 0xffffff00; dev->name |= val; break; \ + case addr + 1: dev->name &= 0xffff00ff; dev->name |= val << 8; break; \ + case addr + 2: dev->name &= 0xff00ffff; dev->name |= val << 16; break; + +#define CASE_SET_REG32(name, addr) \ + case addr : dev->name &= 0xffffff00; dev->name |= val; break; \ + case addr + 1: dev->name &= 0xffff00ff; dev->name |= val << 8; break; \ + case addr + 2: dev->name &= 0xff00ffff; dev->name |= val << 16; break; \ + case addr + 3: dev->name &= 0x00ffffff; dev->name |= val << 24; break; #ifdef DEBUG_NCR_REG ncr53c810_log("Write reg %02x = %02x\n", offset, val); #endif - offset &= 0xFF; + dev->regop = 1; switch (offset) { case 0x00: /* SCNTL0 */ @@ -1470,22 +1304,22 @@ ncr53c810_reg_writeb(ncr53c810c_state_t *dev, uint32_t offset, uint8_t val) /* Looks like this (turn on bit 4 of SSTAT0 to mark arbitration in progress) is enough to make BIOS v4.x happy. */ ncr53c810_log("NCR 810: Selecting SCSI ID %i\n", dev->sdid); + dev->select_id = dev->sdid; dev->sstat0 |= 0x10; } break; case 0x01: /* SCNTL1 */ dev->scntl1 = val & ~NCR_SCNTL1_SST; if (val & NCR_SCNTL1_IARB) { - dev->waiting = 0; - ncr53c810_log("Arbitration won\n"); - dev->sstat0 |= 0x04; - dev->scntl1 &= ~NCR_SCNTL1_IARB; + dev->select_id = dev->sdid; + ncr53c810_log("Arbitration lost\n"); + dev->sstat0 |= 0x08; dev->waiting = 0; } if (val & NCR_SCNTL1_RST) { if (!(dev->sstat0 & NCR_SSTAT0_RST)) { dev->sstat0 |= NCR_SSTAT0_RST; - ncr53c810_script_scsi_interrupt(dev, NCR_SIST0_RST, 0, dev->ncr_to_ncr); + ncr53c810_script_scsi_interrupt(dev, NCR_SIST0_RST, 0); } } else dev->sstat0 &= ~NCR_SSTAT0_RST; @@ -1515,8 +1349,7 @@ ncr53c810_reg_writeb(ncr53c810c_state_t *dev, uint32_t offset, uint8_t val) case 0x08: /* SFBR */ /* The CPU is not allowed to write to this register. However the SCRIPTS register move instructions are. */ - if (dev->ncr_to_ncr) - dev->sfbr = val; + dev->sfbr = val; break; case 0x09: /* SOCL */ ncr53c810_log("NCR 810: SOCL write %02X\n", val); @@ -1524,32 +1357,31 @@ ncr53c810_reg_writeb(ncr53c810c_state_t *dev, uint32_t offset, uint8_t val) break; case 0x0a: case 0x0b: /* Openserver writes to these readonly registers on startup */ - break; + return; case 0x0c: case 0x0d: case 0x0e: case 0x0f: /* Linux writes to these readonly registers on startup. */ - break; - case 0x10: case 0x11: case 0x12: case 0x13: - dev->dsa.b[offset & 3] = val; - break; + return; + CASE_SET_REG32(dsa, 0x10) case 0x14: /* ISTAT */ ncr53c810_log("ISTAT write: %02X\n", val); tmp = dev->istat; dev->istat = (dev->istat & 0x0f) | (val & 0xf0); if ((val & NCR_ISTAT_ABRT) && !(val & NCR_ISTAT_SRST)) - ncr53c810_script_dma_interrupt(dev, NCR_DSTAT_ABRT, dev->ncr_to_ncr); + ncr53c810_script_dma_interrupt(dev, NCR_DSTAT_ABRT); if (val & NCR_ISTAT_INTF) { dev->istat &= ~NCR_ISTAT_INTF; - ncr53c810_update_irq(dev, 0); + ncr53c810_update_irq(dev); } - if ((dev->waiting == 1) && (val & NCR_ISTAT_SIGP) && !(tmp & NCR_ISTAT_SIGP) && !dev->sstop) { + + if (dev->waiting == 1 && val & NCR_ISTAT_SIGP) { ncr53c810_log("Woken by SIGP\n"); dev->waiting = 0; - dev->dsp.dw = dev->dnad.dw; - ncr53c810_set_wait_event(); + dev->dsp = dev->dnad; + ncr53c810_execute_script(dev); } if ((val & NCR_ISTAT_SRST) && !(tmp & NCR_ISTAT_SRST)) { ncr53c810_soft_reset(dev); - ncr53c810_update_irq(dev, 0); + ncr53c810_update_irq(dev); dev->istat = 0; } break; @@ -1560,6 +1392,8 @@ ncr53c810_reg_writeb(ncr53c810c_state_t *dev, uint32_t offset, uint8_t val) dev->mbox1 = val; break; case 0x18: /* CTEST0 */ + /* nothing to do */ + break; case 0x19: /* CTEST1 */ /* nothing to do */ break; @@ -1569,9 +1403,7 @@ ncr53c810_reg_writeb(ncr53c810c_state_t *dev, uint32_t offset, uint8_t val) case 0x1b: /* CTEST3 */ dev->ctest3 = val & 0x0f; break; - case 0x1c: case 0x01d: case 0x1e: case 0x1f: - dev->temp.b[offset & 3] = val; - break; + CASE_SET_REG32(temp, 0x1c) case 0x21: /* CTEST4 */ if (val & 7) ncr53c810_log("Unimplemented CTEST4-FBL 0x%x\n", val); @@ -1582,54 +1414,51 @@ ncr53c810_reg_writeb(ncr53c810c_state_t *dev, uint32_t offset, uint8_t val) ncr53c810_log("CTEST5 DMA increment not implemented\n"); dev->ctest5 = val; break; - case 0x24: case 0x25: case 0x26: - dev->dbc.b[offset & 3] = val; + CASE_SET_REG24(dbc, 0x24) + CASE_SET_REG32(dnad, 0x28) + case 0x2c: /* DSP[0:7] */ + dev->dsp &= 0xffffff00; + dev->dsp |= val; break; - case 0x28: case 0x29: case 0x2a: case 0x2b: - dev->dnad.b[offset & 3] = val; + case 0x2d: /* DSP[8:15] */ + dev->dsp &= 0xffff00ff; + dev->dsp |= val << 8; break; - case 0x2c: case 0x2d: case 0x2e: case 0x2f: - if (!dev->sstop) { - fatal("Writing to DSP while scripts are running!\n"); - return; - } - dev->dsp.b[offset & 3] = val; - if (((offset & 3) == 3) && !(dev->dmode & NCR_DMODE_MAN) && dev->sstop) + case 0x2e: /* DSP[16:23] */ + dev->dsp &= 0xff00ffff; + dev->dsp |= val << 16; + break; + case 0x2f: /* DSP[24:31] */ + dev->dsp &= 0x00ffffff; + dev->dsp |= val << 24; + if (!(dev->dmode & NCR_DMODE_MAN) && dev->sstop) ncr53c810_execute_script(dev); break; - case 0x30: case 0x31: case 0x32: case 0x33: - dev->dsps.b[offset & 3] = val; - break; - case 0x34: case 0x35: case 0x36: case 0x37: - dev->scratcha.b[offset & 3] = val; - break; + CASE_SET_REG32(dsps, 0x30) + CASE_SET_REG32(scratcha, 0x34) case 0x38: /* DMODE */ dev->dmode = val; break; case 0x39: /* DIEN */ ncr53c810_log("DIEN write: %02X\n", val); dev->dien = val; - ncr53c810_update_irq(dev, dev->ncr_to_ncr); + ncr53c810_update_irq(dev); break; case 0x3a: /* SBR */ dev->sbr = val; break; case 0x3b: /* DCNTL */ dev->dcntl = val & ~(NCR_DCNTL_PFF | NCR_DCNTL_STD); - if ((val & NCR_DCNTL_STD) && dev->sstop) { - if (dev->dcntl & NCR_DCNTL_SSM) - ncr53c810_execute_ins(dev, dev->ncr_to_ncr); - else { - if (dev->dmode & NCR_DMODE_MAN) - dev->dcntl |= NCR_DCNTL_STD; - ncr53c810_execute_script(dev); - } - } + if ((val & NCR_DCNTL_STD) && dev->sstop) + ncr53c810_execute_script(dev); break; case 0x40: /* SIEN0 */ + dev->sien0 = val; + ncr53c810_update_irq(dev); + break; case 0x41: /* SIEN1 */ - dev->sien[offset & 1] = val; - ncr53c810_update_irq(dev, 0); + dev->sien1 = val; + ncr53c810_update_irq(dev); break; case 0x47: /* GPCNTL0 */ break; @@ -1641,91 +1470,84 @@ ncr53c810_reg_writeb(ncr53c810c_state_t *dev, uint32_t offset, uint8_t val) ncr53c810_log("General purpose timer not implemented\n"); /* ??? Raising the interrupt immediately seems to be sufficient to keep the FreeBSD driver happy. */ - ncr53c810_script_scsi_interrupt(dev, 0, NCR_SIST1_GEN, dev->ncr_to_ncr); + ncr53c810_script_scsi_interrupt(dev, 0, NCR_SIST1_GEN); } break; case 0x4a: /* RESPID */ dev->respid = val; break; case 0x4d: /* STEST1 */ - dev->stest[0] = val; + dev->stest1 = val; break; case 0x4e: /* STEST2 */ if (val & 1) ncr53c810_log("Low level mode not implemented\n"); - dev->stest[1] = val; + dev->stest2 = val; break; case 0x4f: /* STEST3 */ if (val & 0x41) ncr53c810_log("SCSI FIFO test mode not implemented\n"); - dev->stest[2] = val; + dev->stest3 = val; break; case 0x54: break; - case 0x5c: case 0x5d: case 0x5e: case 0x5f: - dev->scratchb.b[offset & 3] = val; - break; + CASE_SET_REG32(scratchb, 0x5c) default: ncr53c810_log("Unhandled writeb 0x%x = 0x%x\n", offset, val); } - - if (!dev->ncr_to_ncr) - ncr53c810_busy(0); +#undef CASE_SET_REG24 +#undef CASE_SET_REG32 } -static uint8_t ncr53c810_reg_readb(ncr53c810c_state_t *dev, uint32_t offset) + +static uint8_t +ncr53c810_reg_readb(ncr53c810_t *dev, uint32_t offset) { uint8_t tmp; - uint8_t ret = 0; +#define CASE_GET_REG24(name, addr) \ + case addr: return dev->name & 0xff; \ + case addr + 1: return (dev->name >> 8) & 0xff; \ + case addr + 2: return (dev->name >> 16) & 0xff; - if (!dev->ncr_to_ncr) - ncr53c810_busy(1); +#define CASE_GET_REG32(name, addr) \ + case addr: return dev->name & 0xff; \ + case addr + 1: return (dev->name >> 8) & 0xff; \ + case addr + 2: return (dev->name >> 16) & 0xff; \ + case addr + 3: return (dev->name >> 24) & 0xff; + + dev->regop = 1; switch (offset) { case 0x00: /* SCNTL0 */ ncr53c810_log("NCR 810: Read SCNTL0 %02X\n", dev->scntl0); - ret = dev->scntl0; - break; + return dev->scntl0; case 0x01: /* SCNTL1 */ ncr53c810_log("NCR 810: Read SCNTL1 %02X\n", dev->scntl1); - ret = dev->scntl1; - break; + return dev->scntl1; case 0x02: /* SCNTL2 */ ncr53c810_log("NCR 810: Read SCNTL2 %02X\n", dev->scntl2); - ret = ((dev->scntl2) & ~0x40) | ((dev->istat & NCR_ISTAT_SIGP) ? 0x40 : 0x00); - dev->istat &= ~NCR_ISTAT_SIGP; - break; + return dev->scntl2; case 0x03: /* SCNTL3 */ ncr53c810_log("NCR 810: Read SCNTL3 %02X\n", dev->scntl3); - ret = dev->scntl3; - break; + return dev->scntl3; case 0x04: /* SCID */ ncr53c810_log("NCR 810: Read SCID %02X\n", dev->scid); - ret = dev->scid; - break; + return dev->scid; case 0x05: /* SXFER */ ncr53c810_log("NCR 810: Read SXFER %02X\n", dev->sxfer); - ret = dev->sxfer; - break; + return dev->sxfer; case 0x06: /* SDID */ ncr53c810_log("NCR 810: Read SDID %02X\n", dev->sdid); - ret = dev->sdid; - break; + return dev->sdid; case 0x07: /* GPREG0 */ ncr53c810_log("NCR 810: Read GPREG0 %02X\n", dev->gpreg0 & 3); - ret = dev->gpreg0 & 3; - break; + return dev->gpreg0 & 3; case 0x08: /* Revision ID */ - case 0x20: /* DFIFO */ - case 0x23: /* CTEST6 */ - case 0x59: /* SBDL high */ - default: - ret = 0x00; - break; + ncr53c810_log("NCR 810: Read REVID 00\n"); + return 0x00; case 0xa: /* SSID */ ncr53c810_log("NCR 810: Read SSID %02X\n", dev->ssid); - ret = dev->ssid; - break; + return dev->ssid; case 0xb: /* SBCL */ /* Bit 7 = REQ (SREQ/ status) Bit 6 = ACK (SACK/ status) @@ -1737,53 +1559,39 @@ static uint8_t ncr53c810_reg_readb(ncr53c810c_state_t *dev, uint32_t offset) Bit 0 = I/O (SI_O/ status) */ tmp = (dev->sstat1 & 7); ncr53c810_log("NCR 810: Read SBCL %02X\n", tmp); - ret = tmp; /* For now, return the MSG, C/D, and I/O bits from SSTAT1. */ - break; + return tmp; /* For now, return the MSG, C/D, and I/O bits from SSTAT1. */ case 0xc: /* DSTAT */ tmp = dev->dstat | NCR_DSTAT_DFE; if ((dev->istat & NCR_ISTAT_INTF) == 0) - dev->dstat = NCR_DSTAT_DFE; - ncr53c810_update_irq(dev, 0); + dev->dstat = 0; + ncr53c810_update_irq(dev); ncr53c810_log("NCR 810: Read DSTAT %02X\n", tmp); - ret = tmp; - break; + return tmp; case 0x0d: /* SSTAT0 */ ncr53c810_log("NCR 810: Read SSTAT0 %02X\n", dev->sstat0); - ret = dev->sstat0; - break; + return dev->sstat0; case 0x0e: /* SSTAT1 */ ncr53c810_log("NCR 810: Read SSTAT1 %02X\n", dev->sstat1); - ret = dev->sstat1; - break; + return dev->sstat1; case 0x0f: /* SSTAT2 */ - ret = (dev->scntl1 & NCR_SCNTL1_CON) ? 0 : 2; - ncr53c810_log("NCR 810: Read SSTAT2 %02X\n", ret); - break; - case 0x10: case 0x11: case 0x12: case 0x13: - ret = dev->dsa.b[offset & 3]; - break; + ncr53c810_log("NCR 810: Read SSTAT2 %02X\n", dev->scntl1 & NCR_SCNTL1_CON ? 0 : 2); + return dev->scntl1 & NCR_SCNTL1_CON ? 0 : 2; + CASE_GET_REG32(dsa, 0x10) case 0x14: /* ISTAT */ -#if 0 ncr53c810_log("NCR 810: Read ISTAT %02X\n", dev->istat); -#endif - ret = dev->istat; - break; + return dev->istat; case 0x16: /* MBOX0 */ ncr53c810_log("NCR 810: Read MBOX0 %02X\n", dev->mbox0); - ret = dev->mbox0; - break; + return dev->mbox0; case 0x17: /* MBOX1 */ ncr53c810_log("NCR 810: Read MBOX1 %02X\n", dev->mbox1); - ret = dev->mbox1; - break; + return dev->mbox1; case 0x18: /* CTEST0 */ ncr53c810_log("NCR 810: Read CTEST0 FF\n"); - ret = 0xff; - break; + return 0xff; case 0x19: /* CTEST1 */ ncr53c810_log("NCR 810: Read CTEST1 F0\n"); - ret = 0xf0; /* dma fifo empty */ - break; + return 0xf0; /* dma fifo empty */ case 0x1a: /* CTEST2 */ tmp = dev->ctest2 | NCR_CTEST2_DACK | NCR_CTEST2_CM; if (dev->istat & NCR_ISTAT_SIGP) { @@ -1791,130 +1599,120 @@ static uint8_t ncr53c810_reg_readb(ncr53c810c_state_t *dev, uint32_t offset) tmp |= NCR_CTEST2_SIGP; } ncr53c810_log("NCR 810: Read CTEST2 %02X\n", tmp); - ret = tmp; - break; + return tmp; case 0x1b: /* CTEST3 */ - ncr53c810_log("NCR 810: Read CTEST3 %02X\n", (dev->ctest3 & (0x08 | 0x02 | 0x01)) | dev->chip_rev); - ret = (dev->ctest3 & (0x08 | 0x02 | 0x01)) | dev->chip_rev; - break; - case 0x1c: case 0x1d: case 0x1e: case 0x1f: - ret = dev->temp.b[offset & 3]; - break; + ncr53c810_log("NCR 810: Read CTEST3 %02X\n", + (dev->ctest3 & (0x08 | 0x02 | 0x01)) | dev->chip_rev); + return (dev->ctest3 & (0x08 | 0x02 | 0x01)) | dev->chip_rev; + CASE_GET_REG32(temp, 0x1c) + case 0x20: /* DFIFO */ + ncr53c810_log("NCR 810: Read DFIFO 00\n"); + return 0; case 0x21: /* CTEST4 */ ncr53c810_log("NCR 810: Read CTEST4 %02X\n", dev->ctest4); - ret = dev->ctest4; - break; + return dev->ctest4; case 0x22: /* CTEST5 */ ncr53c810_log("NCR 810: Read CTEST5 %02X\n", dev->ctest5); - ret = dev->ctest5; - break; - case 0x24: case 0x25: case 0x26: - ret = dev->dbc.b[offset & 3]; - break; + return dev->ctest5; + case 0x23: /* CTEST6 */ + ncr53c810_log("NCR 810: Read CTEST6 00\n"); + return 0; + CASE_GET_REG24(dbc, 0x24) case 0x27: /* DCMD */ ncr53c810_log("NCR 810: Read DCMD %02X\n", dev->dcmd); - ret = dev->dcmd; - break; - case 0x28: case 0x29: case 0x2a: case 0x2b: - ret = dev->dnad.b[offset & 3]; - break; - case 0x2c: case 0x2d: case 0x2e: case 0x2f: - ret = dev->dsp.b[offset & 3]; - break; - case 0x30: case 0x31: case 0x32: case 0x33: - ret = dev->dsps.b[offset & 3]; - break; - case 0x34: case 0x35: case 0x36: case 0x37: - ret = dev->scratcha.b[offset & 3]; - break; + return dev->dcmd; + CASE_GET_REG32(dnad, 0x28) + CASE_GET_REG32(dsp, 0x2c) + CASE_GET_REG32(dsps, 0x30) + CASE_GET_REG32(scratcha, 0x34) case 0x38: /* DMODE */ ncr53c810_log("NCR 810: Read DMODE %02X\n", dev->dmode); - ret = dev->dmode; - break; + return dev->dmode; case 0x39: /* DIEN */ ncr53c810_log("NCR 810: Read DIEN %02X\n", dev->dien); - ret = dev->dien; - break; + return dev->dien; case 0x3a: /* SBR */ ncr53c810_log("NCR 810: Read SBR %02X\n", dev->sbr); - ret = dev->sbr; - break; + return dev->sbr; case 0x3b: /* DCNTL */ ncr53c810_log("NCR 810: Read DCNTL %02X\n", dev->dcntl); - ret = dev->dcntl; - break; - /* ADDER Output (Debug of relative jump address) */ - case 0x3c: case 0x3d: case 0x3e: case 0x3f: - ret = dev->adder.b[offset & 3]; - break; + return dev->dcntl; + CASE_GET_REG32(adder, 0x3c) /* ADDER Output (Debug of relative jump address) */ case 0x40: /* SIEN0 */ - case 0x41: /* SIEN1 */ - ret = dev->sien[offset & 1]; - break; + ncr53c810_log("NCR 810: Read SIEN0 %02X\n", dev->sien0); + return dev->sien0; + case 0x41: /* SIEN1 */ + ncr53c810_log("NCR 810: Read SIEN1 %02X\n", dev->sien1); + return dev->sien1; case 0x42: /* SIST0 */ + tmp = dev->sist0; + dev->sist0 = 0; + ncr53c810_update_irq(dev); + ncr53c810_log("NCR 810: Read SIST0 %02X\n", tmp); + return tmp; case 0x43: /* SIST1 */ - tmp = dev->sist[offset & 1]; - dev->sist[offset & 1] = 0; - ncr53c810_update_irq(dev, 0); - ret = tmp; - break; + tmp = dev->sist1; + dev->sist1 = 0; + ncr53c810_update_irq(dev); + ncr53c810_log("NCR 810: Read SIST1 %02X\n", tmp); + return tmp; case 0x46: /* MACNTL */ ncr53c810_log("NCR 810: Read MACNTL 4F\n"); - ret = 0x4f; - break; + return 0x4f; case 0x47: /* GPCNTL0 */ ncr53c810_log("NCR 810: Read GPCNTL0 0F\n"); - ret = 0x0f; - break; + return 0x0f; case 0x48: /* STIME0 */ ncr53c810_log("NCR 810: Read STIME0 %02X\n", dev->stime0); - ret = dev->stime0; - break; + return dev->stime0; case 0x4a: /* RESPID */ ncr53c810_log("NCR 810: Read RESPID %02X\n", dev->respid); - ret = dev->respid; - break; + return dev->respid; + case 0x4c: /* STEST0 */ + ncr53c810_log("NCR 810: Read STEST0 %02X\n", dev->stest1); + return 0x00; case 0x4d: /* STEST1 */ + ncr53c810_log("NCR 810: Read STEST1 %02X\n", dev->stest1); + return dev->stest1; case 0x4e: /* STEST2 */ + ncr53c810_log("NCR 810: Read STEST2 %02X\n", dev->stest2); + return dev->stest2; case 0x4f: /* STEST3 */ - ret = dev->stest[(offset & 3) - 1]; - break; + ncr53c810_log("NCR 810: Read STEST3 %02X\n", dev->stest3); + return dev->stest3; case 0x50: /* SIDL */ /* This is needed by the linux drivers. We currently only update it during the MSG IN phase. */ ncr53c810_log("NCR 810: Read SIDL %02X\n", dev->sidl); - ret = dev->sidl; - break; + return dev->sidl; case 0x52: /* STEST4 */ ncr53c810_log("NCR 810: Read STEST4 E0\n"); - ret = 0xe0; - break; + return 0xe0; case 0x58: /* SBDL */ /* Some drivers peek at the data bus during the MSG IN phase. */ if ((dev->sstat1 & PHASE_MASK) == PHASE_MI) { ncr53c810_log("NCR 810: Read SBDL %02X\n", dev->msg[0]); - ret = dev->msg[0]; - break; + return dev->msg[0]; } ncr53c810_log("NCR 810: Read SBDL 00\n"); - ret = 0; - break; - case 0x5c: case 0x5d: case 0x5e: case 0x5f: - ret = dev->scratchb.b[offset & 3]; - break; + return 0; + case 0x59: /* SBDL high */ + ncr53c810_log("NCR 810: Read SBDLH 00\n"); + return 0; + CASE_GET_REG32(scratchb, 0x5c) } + ncr53c810_log("readb 0x%x\n", offset); + return 0; - if (!dev->ncr_to_ncr) - ncr53c810_busy(0); - - return ret; +#undef CASE_GET_REG24 +#undef CASE_GET_REG32 } static uint8_t ncr53c810_io_readb(uint16_t addr, void *p) { - ncr53c810c_state_t *dev = (ncr53c810c_state_t *)p; + ncr53c810_t *dev = (ncr53c810_t *)p; return ncr53c810_reg_readb(dev, addr & 0xff); } @@ -1922,7 +1720,7 @@ ncr53c810_io_readb(uint16_t addr, void *p) static uint16_t ncr53c810_io_readw(uint16_t addr, void *p) { - ncr53c810c_state_t *dev = (ncr53c810c_state_t *)p; + ncr53c810_t *dev = (ncr53c810_t *)p; uint16_t val; addr &= 0xff; @@ -1935,7 +1733,7 @@ ncr53c810_io_readw(uint16_t addr, void *p) static uint32_t ncr53c810_io_readl(uint16_t addr, void *p) { - ncr53c810c_state_t *dev = (ncr53c810c_state_t *)p; + ncr53c810_t *dev = (ncr53c810_t *)p; uint32_t val; addr &= 0xff; @@ -1950,7 +1748,7 @@ ncr53c810_io_readl(uint16_t addr, void *p) static void ncr53c810_io_writeb(uint16_t addr, uint8_t val, void *p) { - ncr53c810c_state_t *dev = (ncr53c810c_state_t *)p; + ncr53c810_t *dev = (ncr53c810_t *)p; ncr53c810_reg_writeb(dev, addr & 0xff, val); } @@ -1958,7 +1756,7 @@ ncr53c810_io_writeb(uint16_t addr, uint8_t val, void *p) static void ncr53c810_io_writew(uint16_t addr, uint16_t val, void *p) { - ncr53c810c_state_t *dev = (ncr53c810c_state_t *)p; + ncr53c810_t *dev = (ncr53c810_t *)p; addr &= 0xff; ncr53c810_reg_writeb(dev, addr, val & 0xff); ncr53c810_reg_writeb(dev, addr + 1, (val >> 8) & 0xff); @@ -1968,7 +1766,7 @@ ncr53c810_io_writew(uint16_t addr, uint16_t val, void *p) static void ncr53c810_io_writel(uint16_t addr, uint32_t val, void *p) { - ncr53c810c_state_t *dev = (ncr53c810c_state_t *)p; + ncr53c810_t *dev = (ncr53c810_t *)p; addr &= 0xff; ncr53c810_reg_writeb(dev, addr, val & 0xff); ncr53c810_reg_writeb(dev, addr + 1, (val >> 8) & 0xff); @@ -1980,7 +1778,7 @@ ncr53c810_io_writel(uint16_t addr, uint32_t val, void *p) static void ncr53c810_mmio_writeb(uint32_t addr, uint8_t val, void *p) { - ncr53c810c_state_t *dev = (ncr53c810c_state_t *)p; + ncr53c810_t *dev = (ncr53c810_t *)p; ncr53c810_reg_writeb(dev, addr & 0xff, val); } @@ -1989,7 +1787,7 @@ ncr53c810_mmio_writeb(uint32_t addr, uint8_t val, void *p) static void ncr53c810_mmio_writew(uint32_t addr, uint16_t val, void *p) { - ncr53c810c_state_t *dev = (ncr53c810c_state_t *)p; + ncr53c810_t *dev = (ncr53c810_t *)p; addr &= 0xff; ncr53c810_reg_writeb(dev, addr, val & 0xff); @@ -2000,7 +1798,7 @@ ncr53c810_mmio_writew(uint32_t addr, uint16_t val, void *p) static void ncr53c810_mmio_writel(uint32_t addr, uint32_t val, void *p) { - ncr53c810c_state_t *dev = (ncr53c810c_state_t *)p; + ncr53c810_t *dev = (ncr53c810_t *)p; addr &= 0xff; ncr53c810_reg_writeb(dev, addr, val & 0xff); @@ -2013,7 +1811,7 @@ ncr53c810_mmio_writel(uint32_t addr, uint32_t val, void *p) static uint8_t ncr53c810_mmio_readb(uint32_t addr, void *p) { - ncr53c810c_state_t *dev = (ncr53c810c_state_t *)p; + ncr53c810_t *dev = (ncr53c810_t *)p; return ncr53c810_reg_readb(dev, addr & 0xff); } @@ -2022,7 +1820,7 @@ ncr53c810_mmio_readb(uint32_t addr, void *p) static uint16_t ncr53c810_mmio_readw(uint32_t addr, void *p) { - ncr53c810c_state_t *dev = (ncr53c810c_state_t *)p; + ncr53c810_t *dev = (ncr53c810_t *)p; uint16_t val; addr &= 0xff; @@ -2035,7 +1833,7 @@ ncr53c810_mmio_readw(uint32_t addr, void *p) static uint32_t ncr53c810_mmio_readl(uint32_t addr, void *p) { - ncr53c810c_state_t *dev = (ncr53c810c_state_t *)p; + ncr53c810_t *dev = (ncr53c810_t *)p; uint32_t val; addr &= 0xff; @@ -2048,7 +1846,7 @@ ncr53c810_mmio_readl(uint32_t addr, void *p) static void -ncr53c810_io_set(ncr53c810c_state_t *dev, uint32_t base, uint16_t len) +ncr53c810_io_set(ncr53c810_t *dev, uint32_t base, uint16_t len) { ncr53c810_log("NCR53c810: [PCI] Setting I/O handler at %04X\n", base); io_sethandler(base, len, @@ -2058,7 +1856,7 @@ ncr53c810_io_set(ncr53c810c_state_t *dev, uint32_t base, uint16_t len) static void -ncr53c810_io_remove(ncr53c810c_state_t *dev, uint32_t base, uint16_t len) +ncr53c810_io_remove(ncr53c810_t *dev, uint32_t base, uint16_t len) { ncr53c810_log("NCR53c810: Removing I/O handler at %04X\n", base); io_removehandler(base, len, @@ -2068,7 +1866,7 @@ ncr53c810_io_remove(ncr53c810c_state_t *dev, uint32_t base, uint16_t len) static void -ncr53c810_mem_init(ncr53c810c_state_t *dev, uint32_t addr) +ncr53c810_mem_init(ncr53c810_t *dev, uint32_t addr) { mem_mapping_add(&dev->mmio_mapping, addr, 0x100, ncr53c810_mmio_readb, ncr53c810_mmio_readw, ncr53c810_mmio_readl, @@ -2078,14 +1876,14 @@ ncr53c810_mem_init(ncr53c810c_state_t *dev, uint32_t addr) static void -ncr53c810_mem_set_addr(ncr53c810c_state_t *dev, uint32_t base) +ncr53c810_mem_set_addr(ncr53c810_t *dev, uint32_t base) { mem_mapping_set_addr(&dev->mmio_mapping, base, 0x100); } static void -ncr53c810_mem_disable(ncr53c810c_state_t *dev) +ncr53c810_mem_disable(ncr53c810_t *dev) { mem_mapping_disable(&dev->mmio_mapping); } @@ -2096,9 +1894,9 @@ bar_t ncr53c810_pci_bar[2]; static uint8_t -LSIPCIRead(int func, int addr, void *p) +ncr53c810_pci_read(int func, int addr, void *p) { - ncr53c810c_state_t *dev = (ncr53c810c_state_t *)p; + ncr53c810_t *dev = (ncr53c810_t *)p; ncr53c810_log("NCR53c810: Reading register %02X\n", addr & 0xff); @@ -2126,7 +1924,7 @@ LSIPCIRead(int func, int addr, void *p) case 0x09: return 0; /*Programming interface*/ case 0x0A: - return 0; /*Subclass*/ + return 0; /*devubclass*/ case 0x0B: return 1; /*Class code*/ case 0x0C: @@ -2173,9 +1971,9 @@ LSIPCIRead(int func, int addr, void *p) static void -LSIPCIWrite(int func, int addr, uint8_t val, void *p) +ncr53c810_pci_write(int func, int addr, uint8_t val, void *p) { - ncr53c810c_state_t *dev = (ncr53c810c_state_t *)p; + ncr53c810_t *dev = (ncr53c810_t *)p; uint8_t valxor; ncr53c810_log("NCR53c810: Write value %02X to register %02X\n", val, addr & 0xff); @@ -2261,13 +2059,13 @@ LSIPCIWrite(int func, int addr, uint8_t val, void *p) static void * ncr53c810_init(device_t *info) { - ncr53c810c_state_t *dev; + ncr53c810_t *dev; - dev = malloc(sizeof(ncr53c810c_state_t)); - memset(dev, 0x00, sizeof(ncr53c810c_state_t)); + dev = malloc(sizeof(ncr53c810_t)); + memset(dev, 0x00, sizeof(ncr53c810_t)); dev->chip_rev = 0; - dev->pci_slot = pci_add_card(PCI_ADD_NORMAL, LSIPCIRead, LSIPCIWrite, dev); + dev->pci_slot = pci_add_card(PCI_ADD_NORMAL, ncr53c810_pci_read, ncr53c810_pci_write, dev); ncr53c810_pci_bar[0].addr_regs[0] = 1; ncr53c810_pci_bar[1].addr_regs[0] = 0; @@ -2278,20 +2076,6 @@ ncr53c810_init(device_t *info) ncr53c810_soft_reset(dev); - ncr53c810_dev = dev; - - scsi_mutex(1); - - wake_poll_thread = thread_create_event(); - thread_started = thread_create_event(); - - /* Create a waitable event. */ - evt = thread_create_event(); - wait_evt = thread_create_event(); - - ncr53c810_thread_start(dev); - thread_wait_event((event_t *) thread_started, -1); - return(dev); } @@ -2299,45 +2083,9 @@ ncr53c810_init(device_t *info) static void ncr53c810_close(void *priv) { - ncr53c810c_state_t *dev = (ncr53c810c_state_t *)priv; + ncr53c810_t *dev = (ncr53c810_t *)priv; if (dev) { - ncr53c810_dev = NULL; - - /* Tell the thread to terminate. */ - if (poll_tid != NULL) { - ncr53c810_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 (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; } diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index dd384571c..b81113b30 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -8,7 +8,7 @@ # # Makefile for Win32 (MinGW32) environment. # -# Version: @(#)Makefile.mingw 1.0.84 2017/12/13 +# Version: @(#)Makefile.mingw 1.0.85 2017/12/25 # # Authors: Miran Grca, # Fred N. van Kempen, @@ -65,6 +65,9 @@ endif ifndef CIRRUS CIRRUS := n endif +ifndef GREENB +GREENB := n +endif ifndef NE1000 NE1000 := n endif @@ -101,6 +104,7 @@ ifeq ($(DEV_BUILD), y) DEBUG := y DEV_BRANCH := y CIRRUS := y +GREENB := y NE1000 := y NV_RIVA := y PAS16 := y