Statistics
| Branch: | Revision:

root / hw / lsi53c895a.c @ d9c32310

History | View | Annotate | Download (62.6 kB)

1 5fafdf24 ths
/*
2 7d8406be pbrook
 * QEMU LSI53C895A SCSI Host Bus Adapter emulation
3 7d8406be pbrook
 *
4 7d8406be pbrook
 * Copyright (c) 2006 CodeSourcery.
5 7d8406be pbrook
 * Written by Paul Brook
6 7d8406be pbrook
 *
7 7d8406be pbrook
 * This code is licenced under the LGPL.
8 7d8406be pbrook
 */
9 7d8406be pbrook
10 7d8406be pbrook
/* ??? Need to check if the {read,write}[wl] routines work properly on
11 7d8406be pbrook
   big-endian targets.  */
12 7d8406be pbrook
13 777aec7a Nolan
#include <assert.h>                             \
14 777aec7a Nolan
15 87ecb68b pbrook
#include "hw.h"
16 87ecb68b pbrook
#include "pci.h"
17 87ecb68b pbrook
#include "scsi-disk.h"
18 b0a7b120 aliguori
#include "block_int.h"
19 7d8406be pbrook
20 7d8406be pbrook
//#define DEBUG_LSI
21 7d8406be pbrook
//#define DEBUG_LSI_REG
22 7d8406be pbrook
23 7d8406be pbrook
#ifdef DEBUG_LSI
24 001faf32 Blue Swirl
#define DPRINTF(fmt, ...) \
25 001faf32 Blue Swirl
do { printf("lsi_scsi: " fmt , ## __VA_ARGS__); } while (0)
26 001faf32 Blue Swirl
#define BADF(fmt, ...) \
27 001faf32 Blue Swirl
do { fprintf(stderr, "lsi_scsi: error: " fmt , ## __VA_ARGS__); exit(1);} while (0)
28 7d8406be pbrook
#else
29 001faf32 Blue Swirl
#define DPRINTF(fmt, ...) do {} while(0)
30 001faf32 Blue Swirl
#define BADF(fmt, ...) \
31 001faf32 Blue Swirl
do { fprintf(stderr, "lsi_scsi: error: " fmt , ## __VA_ARGS__);} while (0)
32 7d8406be pbrook
#endif
33 7d8406be pbrook
34 7d8406be pbrook
#define LSI_SCNTL0_TRG    0x01
35 7d8406be pbrook
#define LSI_SCNTL0_AAP    0x02
36 7d8406be pbrook
#define LSI_SCNTL0_EPC    0x08
37 7d8406be pbrook
#define LSI_SCNTL0_WATN   0x10
38 7d8406be pbrook
#define LSI_SCNTL0_START  0x20
39 7d8406be pbrook
40 7d8406be pbrook
#define LSI_SCNTL1_SST    0x01
41 7d8406be pbrook
#define LSI_SCNTL1_IARB   0x02
42 7d8406be pbrook
#define LSI_SCNTL1_AESP   0x04
43 7d8406be pbrook
#define LSI_SCNTL1_RST    0x08
44 7d8406be pbrook
#define LSI_SCNTL1_CON    0x10
45 7d8406be pbrook
#define LSI_SCNTL1_DHP    0x20
46 7d8406be pbrook
#define LSI_SCNTL1_ADB    0x40
47 7d8406be pbrook
#define LSI_SCNTL1_EXC    0x80
48 7d8406be pbrook
49 7d8406be pbrook
#define LSI_SCNTL2_WSR    0x01
50 7d8406be pbrook
#define LSI_SCNTL2_VUE0   0x02
51 7d8406be pbrook
#define LSI_SCNTL2_VUE1   0x04
52 7d8406be pbrook
#define LSI_SCNTL2_WSS    0x08
53 7d8406be pbrook
#define LSI_SCNTL2_SLPHBEN 0x10
54 7d8406be pbrook
#define LSI_SCNTL2_SLPMD  0x20
55 7d8406be pbrook
#define LSI_SCNTL2_CHM    0x40
56 7d8406be pbrook
#define LSI_SCNTL2_SDU    0x80
57 7d8406be pbrook
58 7d8406be pbrook
#define LSI_ISTAT0_DIP    0x01
59 7d8406be pbrook
#define LSI_ISTAT0_SIP    0x02
60 7d8406be pbrook
#define LSI_ISTAT0_INTF   0x04
61 7d8406be pbrook
#define LSI_ISTAT0_CON    0x08
62 7d8406be pbrook
#define LSI_ISTAT0_SEM    0x10
63 7d8406be pbrook
#define LSI_ISTAT0_SIGP   0x20
64 7d8406be pbrook
#define LSI_ISTAT0_SRST   0x40
65 7d8406be pbrook
#define LSI_ISTAT0_ABRT   0x80
66 7d8406be pbrook
67 7d8406be pbrook
#define LSI_ISTAT1_SI     0x01
68 7d8406be pbrook
#define LSI_ISTAT1_SRUN   0x02
69 7d8406be pbrook
#define LSI_ISTAT1_FLSH   0x04
70 7d8406be pbrook
71 7d8406be pbrook
#define LSI_SSTAT0_SDP0   0x01
72 7d8406be pbrook
#define LSI_SSTAT0_RST    0x02
73 7d8406be pbrook
#define LSI_SSTAT0_WOA    0x04
74 7d8406be pbrook
#define LSI_SSTAT0_LOA    0x08
75 7d8406be pbrook
#define LSI_SSTAT0_AIP    0x10
76 7d8406be pbrook
#define LSI_SSTAT0_OLF    0x20
77 7d8406be pbrook
#define LSI_SSTAT0_ORF    0x40
78 7d8406be pbrook
#define LSI_SSTAT0_ILF    0x80
79 7d8406be pbrook
80 7d8406be pbrook
#define LSI_SIST0_PAR     0x01
81 7d8406be pbrook
#define LSI_SIST0_RST     0x02
82 7d8406be pbrook
#define LSI_SIST0_UDC     0x04
83 7d8406be pbrook
#define LSI_SIST0_SGE     0x08
84 7d8406be pbrook
#define LSI_SIST0_RSL     0x10
85 7d8406be pbrook
#define LSI_SIST0_SEL     0x20
86 7d8406be pbrook
#define LSI_SIST0_CMP     0x40
87 7d8406be pbrook
#define LSI_SIST0_MA      0x80
88 7d8406be pbrook
89 7d8406be pbrook
#define LSI_SIST1_HTH     0x01
90 7d8406be pbrook
#define LSI_SIST1_GEN     0x02
91 7d8406be pbrook
#define LSI_SIST1_STO     0x04
92 7d8406be pbrook
#define LSI_SIST1_SBMC    0x10
93 7d8406be pbrook
94 7d8406be pbrook
#define LSI_SOCL_IO       0x01
95 7d8406be pbrook
#define LSI_SOCL_CD       0x02
96 7d8406be pbrook
#define LSI_SOCL_MSG      0x04
97 7d8406be pbrook
#define LSI_SOCL_ATN      0x08
98 7d8406be pbrook
#define LSI_SOCL_SEL      0x10
99 7d8406be pbrook
#define LSI_SOCL_BSY      0x20
100 7d8406be pbrook
#define LSI_SOCL_ACK      0x40
101 7d8406be pbrook
#define LSI_SOCL_REQ      0x80
102 7d8406be pbrook
103 7d8406be pbrook
#define LSI_DSTAT_IID     0x01
104 7d8406be pbrook
#define LSI_DSTAT_SIR     0x04
105 7d8406be pbrook
#define LSI_DSTAT_SSI     0x08
106 7d8406be pbrook
#define LSI_DSTAT_ABRT    0x10
107 7d8406be pbrook
#define LSI_DSTAT_BF      0x20
108 7d8406be pbrook
#define LSI_DSTAT_MDPE    0x40
109 7d8406be pbrook
#define LSI_DSTAT_DFE     0x80
110 7d8406be pbrook
111 7d8406be pbrook
#define LSI_DCNTL_COM     0x01
112 7d8406be pbrook
#define LSI_DCNTL_IRQD    0x02
113 7d8406be pbrook
#define LSI_DCNTL_STD     0x04
114 7d8406be pbrook
#define LSI_DCNTL_IRQM    0x08
115 7d8406be pbrook
#define LSI_DCNTL_SSM     0x10
116 7d8406be pbrook
#define LSI_DCNTL_PFEN    0x20
117 7d8406be pbrook
#define LSI_DCNTL_PFF     0x40
118 7d8406be pbrook
#define LSI_DCNTL_CLSE    0x80
119 7d8406be pbrook
120 7d8406be pbrook
#define LSI_DMODE_MAN     0x01
121 7d8406be pbrook
#define LSI_DMODE_BOF     0x02
122 7d8406be pbrook
#define LSI_DMODE_ERMP    0x04
123 7d8406be pbrook
#define LSI_DMODE_ERL     0x08
124 7d8406be pbrook
#define LSI_DMODE_DIOM    0x10
125 7d8406be pbrook
#define LSI_DMODE_SIOM    0x20
126 7d8406be pbrook
127 7d8406be pbrook
#define LSI_CTEST2_DACK   0x01
128 7d8406be pbrook
#define LSI_CTEST2_DREQ   0x02
129 7d8406be pbrook
#define LSI_CTEST2_TEOP   0x04
130 7d8406be pbrook
#define LSI_CTEST2_PCICIE 0x08
131 7d8406be pbrook
#define LSI_CTEST2_CM     0x10
132 7d8406be pbrook
#define LSI_CTEST2_CIO    0x20
133 7d8406be pbrook
#define LSI_CTEST2_SIGP   0x40
134 7d8406be pbrook
#define LSI_CTEST2_DDIR   0x80
135 7d8406be pbrook
136 7d8406be pbrook
#define LSI_CTEST5_BL2    0x04
137 7d8406be pbrook
#define LSI_CTEST5_DDIR   0x08
138 7d8406be pbrook
#define LSI_CTEST5_MASR   0x10
139 7d8406be pbrook
#define LSI_CTEST5_DFSN   0x20
140 7d8406be pbrook
#define LSI_CTEST5_BBCK   0x40
141 7d8406be pbrook
#define LSI_CTEST5_ADCK   0x80
142 7d8406be pbrook
143 7d8406be pbrook
#define LSI_CCNTL0_DILS   0x01
144 7d8406be pbrook
#define LSI_CCNTL0_DISFC  0x10
145 7d8406be pbrook
#define LSI_CCNTL0_ENNDJ  0x20
146 7d8406be pbrook
#define LSI_CCNTL0_PMJCTL 0x40
147 7d8406be pbrook
#define LSI_CCNTL0_ENPMJ  0x80
148 7d8406be pbrook
149 b25cf589 aliguori
#define LSI_CCNTL1_EN64DBMV  0x01
150 b25cf589 aliguori
#define LSI_CCNTL1_EN64TIBMV 0x02
151 b25cf589 aliguori
#define LSI_CCNTL1_64TIMOD   0x04
152 b25cf589 aliguori
#define LSI_CCNTL1_DDAC      0x08
153 b25cf589 aliguori
#define LSI_CCNTL1_ZMOD      0x80
154 b25cf589 aliguori
155 b25cf589 aliguori
#define LSI_CCNTL1_40BIT (LSI_CCNTL1_EN64TIBMV|LSI_CCNTL1_64TIMOD)
156 b25cf589 aliguori
157 7d8406be pbrook
#define PHASE_DO          0
158 7d8406be pbrook
#define PHASE_DI          1
159 7d8406be pbrook
#define PHASE_CMD         2
160 7d8406be pbrook
#define PHASE_ST          3
161 7d8406be pbrook
#define PHASE_MO          6
162 7d8406be pbrook
#define PHASE_MI          7
163 7d8406be pbrook
#define PHASE_MASK        7
164 7d8406be pbrook
165 a917d384 pbrook
/* Maximum length of MSG IN data.  */
166 a917d384 pbrook
#define LSI_MAX_MSGIN_LEN 8
167 a917d384 pbrook
168 a917d384 pbrook
/* Flag set if this is a tagged command.  */
169 a917d384 pbrook
#define LSI_TAG_VALID     (1 << 16)
170 a917d384 pbrook
171 a917d384 pbrook
typedef struct {
172 a917d384 pbrook
    uint32_t tag;
173 a917d384 pbrook
    uint32_t pending;
174 a917d384 pbrook
    int out;
175 a917d384 pbrook
} lsi_queue;
176 4d611c9a pbrook
177 7d8406be pbrook
typedef struct {
178 7d8406be pbrook
    PCIDevice pci_dev;
179 7d8406be pbrook
    int mmio_io_addr;
180 7d8406be pbrook
    int ram_io_addr;
181 7d8406be pbrook
    uint32_t script_ram_base;
182 7d8406be pbrook
183 7d8406be pbrook
    int carry; /* ??? Should this be an a visible register somewhere?  */
184 7d8406be pbrook
    int sense;
185 a917d384 pbrook
    /* Action to take at the end of a MSG IN phase.
186 a917d384 pbrook
       0 = COMMAND, 1 = disconect, 2 = DATA OUT, 3 = DATA IN.  */
187 a917d384 pbrook
    int msg_action;
188 a917d384 pbrook
    int msg_len;
189 a917d384 pbrook
    uint8_t msg[LSI_MAX_MSGIN_LEN];
190 4d611c9a pbrook
    /* 0 if SCRIPTS are running or stopped.
191 4d611c9a pbrook
     * 1 if a Wait Reselect instruction has been issued.
192 a917d384 pbrook
     * 2 if processing DMA from lsi_execute_script.
193 a917d384 pbrook
     * 3 if a DMA operation is in progress.  */
194 7d8406be pbrook
    int waiting;
195 7d8406be pbrook
    SCSIDevice *scsi_dev[LSI_MAX_DEVS];
196 7d8406be pbrook
    SCSIDevice *current_dev;
197 7d8406be pbrook
    int current_lun;
198 a917d384 pbrook
    /* The tag is a combination of the device ID and the SCSI tag.  */
199 a917d384 pbrook
    uint32_t current_tag;
200 a917d384 pbrook
    uint32_t current_dma_len;
201 8ccc2ace ths
    int command_complete;
202 a917d384 pbrook
    uint8_t *dma_buf;
203 a917d384 pbrook
    lsi_queue *queue;
204 a917d384 pbrook
    int queue_len;
205 a917d384 pbrook
    int active_commands;
206 7d8406be pbrook
207 7d8406be pbrook
    uint32_t dsa;
208 7d8406be pbrook
    uint32_t temp;
209 7d8406be pbrook
    uint32_t dnad;
210 7d8406be pbrook
    uint32_t dbc;
211 7d8406be pbrook
    uint8_t istat0;
212 7d8406be pbrook
    uint8_t istat1;
213 7d8406be pbrook
    uint8_t dcmd;
214 7d8406be pbrook
    uint8_t dstat;
215 7d8406be pbrook
    uint8_t dien;
216 7d8406be pbrook
    uint8_t sist0;
217 7d8406be pbrook
    uint8_t sist1;
218 7d8406be pbrook
    uint8_t sien0;
219 7d8406be pbrook
    uint8_t sien1;
220 7d8406be pbrook
    uint8_t mbox0;
221 7d8406be pbrook
    uint8_t mbox1;
222 7d8406be pbrook
    uint8_t dfifo;
223 9167a69a balrog
    uint8_t ctest2;
224 7d8406be pbrook
    uint8_t ctest3;
225 7d8406be pbrook
    uint8_t ctest4;
226 7d8406be pbrook
    uint8_t ctest5;
227 7d8406be pbrook
    uint8_t ccntl0;
228 7d8406be pbrook
    uint8_t ccntl1;
229 7d8406be pbrook
    uint32_t dsp;
230 7d8406be pbrook
    uint32_t dsps;
231 7d8406be pbrook
    uint8_t dmode;
232 7d8406be pbrook
    uint8_t dcntl;
233 7d8406be pbrook
    uint8_t scntl0;
234 7d8406be pbrook
    uint8_t scntl1;
235 7d8406be pbrook
    uint8_t scntl2;
236 7d8406be pbrook
    uint8_t scntl3;
237 7d8406be pbrook
    uint8_t sstat0;
238 7d8406be pbrook
    uint8_t sstat1;
239 7d8406be pbrook
    uint8_t scid;
240 7d8406be pbrook
    uint8_t sxfer;
241 7d8406be pbrook
    uint8_t socl;
242 7d8406be pbrook
    uint8_t sdid;
243 a917d384 pbrook
    uint8_t ssid;
244 7d8406be pbrook
    uint8_t sfbr;
245 7d8406be pbrook
    uint8_t stest1;
246 7d8406be pbrook
    uint8_t stest2;
247 7d8406be pbrook
    uint8_t stest3;
248 a917d384 pbrook
    uint8_t sidl;
249 7d8406be pbrook
    uint8_t stime0;
250 7d8406be pbrook
    uint8_t respid0;
251 7d8406be pbrook
    uint8_t respid1;
252 7d8406be pbrook
    uint32_t mmrs;
253 7d8406be pbrook
    uint32_t mmws;
254 7d8406be pbrook
    uint32_t sfs;
255 7d8406be pbrook
    uint32_t drs;
256 7d8406be pbrook
    uint32_t sbms;
257 ab57d967 aliguori
    uint32_t dbms;
258 7d8406be pbrook
    uint32_t dnad64;
259 7d8406be pbrook
    uint32_t pmjad1;
260 7d8406be pbrook
    uint32_t pmjad2;
261 7d8406be pbrook
    uint32_t rbc;
262 7d8406be pbrook
    uint32_t ua;
263 7d8406be pbrook
    uint32_t ia;
264 7d8406be pbrook
    uint32_t sbc;
265 7d8406be pbrook
    uint32_t csbc;
266 dcfb9014 ths
    uint32_t scratch[18]; /* SCRATCHA-SCRATCHR */
267 bd8ee11a Sebastian Herbszt
    uint8_t sbr;
268 7d8406be pbrook
269 7d8406be pbrook
    /* Script ram is stored as 32-bit words in host byteorder.  */
270 7d8406be pbrook
    uint32_t script_ram[2048];
271 7d8406be pbrook
} LSIState;
272 7d8406be pbrook
273 7d8406be pbrook
static void lsi_soft_reset(LSIState *s)
274 7d8406be pbrook
{
275 7d8406be pbrook
    DPRINTF("Reset\n");
276 7d8406be pbrook
    s->carry = 0;
277 7d8406be pbrook
278 7d8406be pbrook
    s->waiting = 0;
279 7d8406be pbrook
    s->dsa = 0;
280 7d8406be pbrook
    s->dnad = 0;
281 7d8406be pbrook
    s->dbc = 0;
282 7d8406be pbrook
    s->temp = 0;
283 7d8406be pbrook
    memset(s->scratch, 0, sizeof(s->scratch));
284 7d8406be pbrook
    s->istat0 = 0;
285 7d8406be pbrook
    s->istat1 = 0;
286 7d8406be pbrook
    s->dcmd = 0;
287 7d8406be pbrook
    s->dstat = 0;
288 7d8406be pbrook
    s->dien = 0;
289 7d8406be pbrook
    s->sist0 = 0;
290 7d8406be pbrook
    s->sist1 = 0;
291 7d8406be pbrook
    s->sien0 = 0;
292 7d8406be pbrook
    s->sien1 = 0;
293 7d8406be pbrook
    s->mbox0 = 0;
294 7d8406be pbrook
    s->mbox1 = 0;
295 7d8406be pbrook
    s->dfifo = 0;
296 9167a69a balrog
    s->ctest2 = 0;
297 7d8406be pbrook
    s->ctest3 = 0;
298 7d8406be pbrook
    s->ctest4 = 0;
299 7d8406be pbrook
    s->ctest5 = 0;
300 7d8406be pbrook
    s->ccntl0 = 0;
301 7d8406be pbrook
    s->ccntl1 = 0;
302 7d8406be pbrook
    s->dsp = 0;
303 7d8406be pbrook
    s->dsps = 0;
304 7d8406be pbrook
    s->dmode = 0;
305 7d8406be pbrook
    s->dcntl = 0;
306 7d8406be pbrook
    s->scntl0 = 0xc0;
307 7d8406be pbrook
    s->scntl1 = 0;
308 7d8406be pbrook
    s->scntl2 = 0;
309 7d8406be pbrook
    s->scntl3 = 0;
310 7d8406be pbrook
    s->sstat0 = 0;
311 7d8406be pbrook
    s->sstat1 = 0;
312 7d8406be pbrook
    s->scid = 7;
313 7d8406be pbrook
    s->sxfer = 0;
314 7d8406be pbrook
    s->socl = 0;
315 7d8406be pbrook
    s->stest1 = 0;
316 7d8406be pbrook
    s->stest2 = 0;
317 7d8406be pbrook
    s->stest3 = 0;
318 a917d384 pbrook
    s->sidl = 0;
319 7d8406be pbrook
    s->stime0 = 0;
320 7d8406be pbrook
    s->respid0 = 0x80;
321 7d8406be pbrook
    s->respid1 = 0;
322 7d8406be pbrook
    s->mmrs = 0;
323 7d8406be pbrook
    s->mmws = 0;
324 7d8406be pbrook
    s->sfs = 0;
325 7d8406be pbrook
    s->drs = 0;
326 7d8406be pbrook
    s->sbms = 0;
327 ab57d967 aliguori
    s->dbms = 0;
328 7d8406be pbrook
    s->dnad64 = 0;
329 7d8406be pbrook
    s->pmjad1 = 0;
330 7d8406be pbrook
    s->pmjad2 = 0;
331 7d8406be pbrook
    s->rbc = 0;
332 7d8406be pbrook
    s->ua = 0;
333 7d8406be pbrook
    s->ia = 0;
334 7d8406be pbrook
    s->sbc = 0;
335 7d8406be pbrook
    s->csbc = 0;
336 bd8ee11a Sebastian Herbszt
    s->sbr = 0;
337 7d8406be pbrook
}
338 7d8406be pbrook
339 b25cf589 aliguori
static int lsi_dma_40bit(LSIState *s)
340 b25cf589 aliguori
{
341 b25cf589 aliguori
    if ((s->ccntl1 & LSI_CCNTL1_40BIT) == LSI_CCNTL1_40BIT)
342 b25cf589 aliguori
        return 1;
343 b25cf589 aliguori
    return 0;
344 b25cf589 aliguori
}
345 b25cf589 aliguori
346 dd8edf01 aliguori
static int lsi_dma_ti64bit(LSIState *s)
347 dd8edf01 aliguori
{
348 dd8edf01 aliguori
    if ((s->ccntl1 & LSI_CCNTL1_EN64TIBMV) == LSI_CCNTL1_EN64TIBMV)
349 dd8edf01 aliguori
        return 1;
350 dd8edf01 aliguori
    return 0;
351 dd8edf01 aliguori
}
352 dd8edf01 aliguori
353 dd8edf01 aliguori
static int lsi_dma_64bit(LSIState *s)
354 dd8edf01 aliguori
{
355 dd8edf01 aliguori
    if ((s->ccntl1 & LSI_CCNTL1_EN64DBMV) == LSI_CCNTL1_EN64DBMV)
356 dd8edf01 aliguori
        return 1;
357 dd8edf01 aliguori
    return 0;
358 dd8edf01 aliguori
}
359 dd8edf01 aliguori
360 7d8406be pbrook
static uint8_t lsi_reg_readb(LSIState *s, int offset);
361 7d8406be pbrook
static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val);
362 4d611c9a pbrook
static void lsi_execute_script(LSIState *s);
363 7d8406be pbrook
364 7d8406be pbrook
static inline uint32_t read_dword(LSIState *s, uint32_t addr)
365 7d8406be pbrook
{
366 7d8406be pbrook
    uint32_t buf;
367 7d8406be pbrook
368 7d8406be pbrook
    /* Optimize reading from SCRIPTS RAM.  */
369 7d8406be pbrook
    if ((addr & 0xffffe000) == s->script_ram_base) {
370 7d8406be pbrook
        return s->script_ram[(addr & 0x1fff) >> 2];
371 7d8406be pbrook
    }
372 7d8406be pbrook
    cpu_physical_memory_read(addr, (uint8_t *)&buf, 4);
373 7d8406be pbrook
    return cpu_to_le32(buf);
374 7d8406be pbrook
}
375 7d8406be pbrook
376 7d8406be pbrook
static void lsi_stop_script(LSIState *s)
377 7d8406be pbrook
{
378 7d8406be pbrook
    s->istat1 &= ~LSI_ISTAT1_SRUN;
379 7d8406be pbrook
}
380 7d8406be pbrook
381 7d8406be pbrook
static void lsi_update_irq(LSIState *s)
382 7d8406be pbrook
{
383 7d8406be pbrook
    int level;
384 7d8406be pbrook
    static int last_level;
385 7d8406be pbrook
386 7d8406be pbrook
    /* It's unclear whether the DIP/SIP bits should be cleared when the
387 7d8406be pbrook
       Interrupt Status Registers are cleared or when istat0 is read.
388 7d8406be pbrook
       We currently do the formwer, which seems to work.  */
389 7d8406be pbrook
    level = 0;
390 7d8406be pbrook
    if (s->dstat) {
391 7d8406be pbrook
        if (s->dstat & s->dien)
392 7d8406be pbrook
            level = 1;
393 7d8406be pbrook
        s->istat0 |= LSI_ISTAT0_DIP;
394 7d8406be pbrook
    } else {
395 7d8406be pbrook
        s->istat0 &= ~LSI_ISTAT0_DIP;
396 7d8406be pbrook
    }
397 7d8406be pbrook
398 7d8406be pbrook
    if (s->sist0 || s->sist1) {
399 7d8406be pbrook
        if ((s->sist0 & s->sien0) || (s->sist1 & s->sien1))
400 7d8406be pbrook
            level = 1;
401 7d8406be pbrook
        s->istat0 |= LSI_ISTAT0_SIP;
402 7d8406be pbrook
    } else {
403 7d8406be pbrook
        s->istat0 &= ~LSI_ISTAT0_SIP;
404 7d8406be pbrook
    }
405 7d8406be pbrook
    if (s->istat0 & LSI_ISTAT0_INTF)
406 7d8406be pbrook
        level = 1;
407 7d8406be pbrook
408 7d8406be pbrook
    if (level != last_level) {
409 7d8406be pbrook
        DPRINTF("Update IRQ level %d dstat %02x sist %02x%02x\n",
410 7d8406be pbrook
                level, s->dstat, s->sist1, s->sist0);
411 7d8406be pbrook
        last_level = level;
412 7d8406be pbrook
    }
413 d537cf6c pbrook
    qemu_set_irq(s->pci_dev.irq[0], level);
414 7d8406be pbrook
}
415 7d8406be pbrook
416 7d8406be pbrook
/* Stop SCRIPTS execution and raise a SCSI interrupt.  */
417 7d8406be pbrook
static void lsi_script_scsi_interrupt(LSIState *s, int stat0, int stat1)
418 7d8406be pbrook
{
419 7d8406be pbrook
    uint32_t mask0;
420 7d8406be pbrook
    uint32_t mask1;
421 7d8406be pbrook
422 7d8406be pbrook
    DPRINTF("SCSI Interrupt 0x%02x%02x prev 0x%02x%02x\n",
423 7d8406be pbrook
            stat1, stat0, s->sist1, s->sist0);
424 7d8406be pbrook
    s->sist0 |= stat0;
425 7d8406be pbrook
    s->sist1 |= stat1;
426 7d8406be pbrook
    /* Stop processor on fatal or unmasked interrupt.  As a special hack
427 7d8406be pbrook
       we don't stop processing when raising STO.  Instead continue
428 7d8406be pbrook
       execution and stop at the next insn that accesses the SCSI bus.  */
429 7d8406be pbrook
    mask0 = s->sien0 | ~(LSI_SIST0_CMP | LSI_SIST0_SEL | LSI_SIST0_RSL);
430 7d8406be pbrook
    mask1 = s->sien1 | ~(LSI_SIST1_GEN | LSI_SIST1_HTH);
431 7d8406be pbrook
    mask1 &= ~LSI_SIST1_STO;
432 7d8406be pbrook
    if (s->sist0 & mask0 || s->sist1 & mask1) {
433 7d8406be pbrook
        lsi_stop_script(s);
434 7d8406be pbrook
    }
435 7d8406be pbrook
    lsi_update_irq(s);
436 7d8406be pbrook
}
437 7d8406be pbrook
438 7d8406be pbrook
/* Stop SCRIPTS execution and raise a DMA interrupt.  */
439 7d8406be pbrook
static void lsi_script_dma_interrupt(LSIState *s, int stat)
440 7d8406be pbrook
{
441 7d8406be pbrook
    DPRINTF("DMA Interrupt 0x%x prev 0x%x\n", stat, s->dstat);
442 7d8406be pbrook
    s->dstat |= stat;
443 7d8406be pbrook
    lsi_update_irq(s);
444 7d8406be pbrook
    lsi_stop_script(s);
445 7d8406be pbrook
}
446 7d8406be pbrook
447 7d8406be pbrook
static inline void lsi_set_phase(LSIState *s, int phase)
448 7d8406be pbrook
{
449 7d8406be pbrook
    s->sstat1 = (s->sstat1 & ~PHASE_MASK) | phase;
450 7d8406be pbrook
}
451 7d8406be pbrook
452 7d8406be pbrook
static void lsi_bad_phase(LSIState *s, int out, int new_phase)
453 7d8406be pbrook
{
454 7d8406be pbrook
    /* Trigger a phase mismatch.  */
455 7d8406be pbrook
    if (s->ccntl0 & LSI_CCNTL0_ENPMJ) {
456 7d8406be pbrook
        if ((s->ccntl0 & LSI_CCNTL0_PMJCTL) || out) {
457 7d8406be pbrook
            s->dsp = s->pmjad1;
458 7d8406be pbrook
        } else {
459 7d8406be pbrook
            s->dsp = s->pmjad2;
460 7d8406be pbrook
        }
461 7d8406be pbrook
        DPRINTF("Data phase mismatch jump to %08x\n", s->dsp);
462 7d8406be pbrook
    } else {
463 7d8406be pbrook
        DPRINTF("Phase mismatch interrupt\n");
464 7d8406be pbrook
        lsi_script_scsi_interrupt(s, LSI_SIST0_MA, 0);
465 7d8406be pbrook
        lsi_stop_script(s);
466 7d8406be pbrook
    }
467 7d8406be pbrook
    lsi_set_phase(s, new_phase);
468 7d8406be pbrook
}
469 7d8406be pbrook
470 a917d384 pbrook
471 a917d384 pbrook
/* Resume SCRIPTS execution after a DMA operation.  */
472 a917d384 pbrook
static void lsi_resume_script(LSIState *s)
473 a917d384 pbrook
{
474 a917d384 pbrook
    if (s->waiting != 2) {
475 a917d384 pbrook
        s->waiting = 0;
476 a917d384 pbrook
        lsi_execute_script(s);
477 a917d384 pbrook
    } else {
478 a917d384 pbrook
        s->waiting = 0;
479 a917d384 pbrook
    }
480 a917d384 pbrook
}
481 a917d384 pbrook
482 4d611c9a pbrook
/* Initiate a SCSI layer data transfer.  */
483 7d8406be pbrook
static void lsi_do_dma(LSIState *s, int out)
484 7d8406be pbrook
{
485 7d8406be pbrook
    uint32_t count;
486 b25cf589 aliguori
    target_phys_addr_t addr;
487 7d8406be pbrook
488 a917d384 pbrook
    if (!s->current_dma_len) {
489 a917d384 pbrook
        /* Wait until data is available.  */
490 a917d384 pbrook
        DPRINTF("DMA no data available\n");
491 a917d384 pbrook
        return;
492 7d8406be pbrook
    }
493 7d8406be pbrook
494 a917d384 pbrook
    count = s->dbc;
495 a917d384 pbrook
    if (count > s->current_dma_len)
496 a917d384 pbrook
        count = s->current_dma_len;
497 a917d384 pbrook
498 a917d384 pbrook
    addr = s->dnad;
499 dd8edf01 aliguori
    /* both 40 and Table Indirect 64-bit DMAs store upper bits in dnad64 */
500 dd8edf01 aliguori
    if (lsi_dma_40bit(s) || lsi_dma_ti64bit(s))
501 b25cf589 aliguori
        addr |= ((uint64_t)s->dnad64 << 32);
502 dd8edf01 aliguori
    else if (s->dbms)
503 dd8edf01 aliguori
        addr |= ((uint64_t)s->dbms << 32);
504 b25cf589 aliguori
    else if (s->sbms)
505 b25cf589 aliguori
        addr |= ((uint64_t)s->sbms << 32);
506 b25cf589 aliguori
507 3adae656 aliguori
    DPRINTF("DMA addr=0x" TARGET_FMT_plx " len=%d\n", addr, count);
508 7d8406be pbrook
    s->csbc += count;
509 a917d384 pbrook
    s->dnad += count;
510 a917d384 pbrook
    s->dbc -= count;
511 a917d384 pbrook
512 a917d384 pbrook
    if (s->dma_buf == NULL) {
513 8ccc2ace ths
        s->dma_buf = s->current_dev->get_buf(s->current_dev,
514 8ccc2ace ths
                                             s->current_tag);
515 a917d384 pbrook
    }
516 7d8406be pbrook
517 7d8406be pbrook
    /* ??? Set SFBR to first data byte.  */
518 a917d384 pbrook
    if (out) {
519 a917d384 pbrook
        cpu_physical_memory_read(addr, s->dma_buf, count);
520 a917d384 pbrook
    } else {
521 a917d384 pbrook
        cpu_physical_memory_write(addr, s->dma_buf, count);
522 a917d384 pbrook
    }
523 a917d384 pbrook
    s->current_dma_len -= count;
524 a917d384 pbrook
    if (s->current_dma_len == 0) {
525 a917d384 pbrook
        s->dma_buf = NULL;
526 a917d384 pbrook
        if (out) {
527 a917d384 pbrook
            /* Write the data.  */
528 8ccc2ace ths
            s->current_dev->write_data(s->current_dev, s->current_tag);
529 a917d384 pbrook
        } else {
530 a917d384 pbrook
            /* Request any remaining data.  */
531 8ccc2ace ths
            s->current_dev->read_data(s->current_dev, s->current_tag);
532 a917d384 pbrook
        }
533 a917d384 pbrook
    } else {
534 a917d384 pbrook
        s->dma_buf += count;
535 a917d384 pbrook
        lsi_resume_script(s);
536 a917d384 pbrook
    }
537 a917d384 pbrook
}
538 a917d384 pbrook
539 a917d384 pbrook
540 a917d384 pbrook
/* Add a command to the queue.  */
541 a917d384 pbrook
static void lsi_queue_command(LSIState *s)
542 a917d384 pbrook
{
543 a917d384 pbrook
    lsi_queue *p;
544 a917d384 pbrook
545 a917d384 pbrook
    DPRINTF("Queueing tag=0x%x\n", s->current_tag);
546 a917d384 pbrook
    if (s->queue_len == s->active_commands) {
547 a917d384 pbrook
        s->queue_len++;
548 2137b4cc ths
        s->queue = qemu_realloc(s->queue, s->queue_len * sizeof(lsi_queue));
549 a917d384 pbrook
    }
550 a917d384 pbrook
    p = &s->queue[s->active_commands++];
551 a917d384 pbrook
    p->tag = s->current_tag;
552 a917d384 pbrook
    p->pending = 0;
553 a917d384 pbrook
    p->out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
554 a917d384 pbrook
}
555 a917d384 pbrook
556 a917d384 pbrook
/* Queue a byte for a MSG IN phase.  */
557 a917d384 pbrook
static void lsi_add_msg_byte(LSIState *s, uint8_t data)
558 a917d384 pbrook
{
559 a917d384 pbrook
    if (s->msg_len >= LSI_MAX_MSGIN_LEN) {
560 a917d384 pbrook
        BADF("MSG IN data too long\n");
561 4d611c9a pbrook
    } else {
562 a917d384 pbrook
        DPRINTF("MSG IN 0x%02x\n", data);
563 a917d384 pbrook
        s->msg[s->msg_len++] = data;
564 7d8406be pbrook
    }
565 a917d384 pbrook
}
566 a917d384 pbrook
567 a917d384 pbrook
/* Perform reselection to continue a command.  */
568 a917d384 pbrook
static void lsi_reselect(LSIState *s, uint32_t tag)
569 a917d384 pbrook
{
570 a917d384 pbrook
    lsi_queue *p;
571 a917d384 pbrook
    int n;
572 a917d384 pbrook
    int id;
573 a917d384 pbrook
574 a917d384 pbrook
    p = NULL;
575 a917d384 pbrook
    for (n = 0; n < s->active_commands; n++) {
576 a917d384 pbrook
        p = &s->queue[n];
577 a917d384 pbrook
        if (p->tag == tag)
578 a917d384 pbrook
            break;
579 a917d384 pbrook
    }
580 a917d384 pbrook
    if (n == s->active_commands) {
581 a917d384 pbrook
        BADF("Reselected non-existant command tag=0x%x\n", tag);
582 a917d384 pbrook
        return;
583 a917d384 pbrook
    }
584 a917d384 pbrook
    id = (tag >> 8) & 0xf;
585 a917d384 pbrook
    s->ssid = id | 0x80;
586 a917d384 pbrook
    DPRINTF("Reselected target %d\n", id);
587 a917d384 pbrook
    s->current_dev = s->scsi_dev[id];
588 a917d384 pbrook
    s->current_tag = tag;
589 a917d384 pbrook
    s->scntl1 |= LSI_SCNTL1_CON;
590 a917d384 pbrook
    lsi_set_phase(s, PHASE_MI);
591 a917d384 pbrook
    s->msg_action = p->out ? 2 : 3;
592 a917d384 pbrook
    s->current_dma_len = p->pending;
593 a917d384 pbrook
    s->dma_buf = NULL;
594 a917d384 pbrook
    lsi_add_msg_byte(s, 0x80);
595 a917d384 pbrook
    if (s->current_tag & LSI_TAG_VALID) {
596 a917d384 pbrook
        lsi_add_msg_byte(s, 0x20);
597 a917d384 pbrook
        lsi_add_msg_byte(s, tag & 0xff);
598 a917d384 pbrook
    }
599 a917d384 pbrook
600 a917d384 pbrook
    s->active_commands--;
601 a917d384 pbrook
    if (n != s->active_commands) {
602 a917d384 pbrook
        s->queue[n] = s->queue[s->active_commands];
603 a917d384 pbrook
    }
604 a917d384 pbrook
}
605 a917d384 pbrook
606 a917d384 pbrook
/* Record that data is available for a queued command.  Returns zero if
607 a917d384 pbrook
   the device was reselected, nonzero if the IO is deferred.  */
608 a917d384 pbrook
static int lsi_queue_tag(LSIState *s, uint32_t tag, uint32_t arg)
609 a917d384 pbrook
{
610 a917d384 pbrook
    lsi_queue *p;
611 a917d384 pbrook
    int i;
612 a917d384 pbrook
    for (i = 0; i < s->active_commands; i++) {
613 a917d384 pbrook
        p = &s->queue[i];
614 a917d384 pbrook
        if (p->tag == tag) {
615 a917d384 pbrook
            if (p->pending) {
616 a917d384 pbrook
                BADF("Multiple IO pending for tag %d\n", tag);
617 a917d384 pbrook
            }
618 a917d384 pbrook
            p->pending = arg;
619 a917d384 pbrook
            if (s->waiting == 1) {
620 a917d384 pbrook
                /* Reselect device.  */
621 a917d384 pbrook
                lsi_reselect(s, tag);
622 a917d384 pbrook
                return 0;
623 a917d384 pbrook
            } else {
624 a917d384 pbrook
               DPRINTF("Queueing IO tag=0x%x\n", tag);
625 a917d384 pbrook
                p->pending = arg;
626 a917d384 pbrook
                return 1;
627 a917d384 pbrook
            }
628 a917d384 pbrook
        }
629 a917d384 pbrook
    }
630 a917d384 pbrook
    BADF("IO with unknown tag %d\n", tag);
631 a917d384 pbrook
    return 1;
632 7d8406be pbrook
}
633 7d8406be pbrook
634 4d611c9a pbrook
/* Callback to indicate that the SCSI layer has completed a transfer.  */
635 a917d384 pbrook
static void lsi_command_complete(void *opaque, int reason, uint32_t tag,
636 a917d384 pbrook
                                 uint32_t arg)
637 4d611c9a pbrook
{
638 4d611c9a pbrook
    LSIState *s = (LSIState *)opaque;
639 4d611c9a pbrook
    int out;
640 4d611c9a pbrook
641 a917d384 pbrook
    out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
642 4d611c9a pbrook
    if (reason == SCSI_REASON_DONE) {
643 a917d384 pbrook
        DPRINTF("Command complete sense=%d\n", (int)arg);
644 a917d384 pbrook
        s->sense = arg;
645 8ccc2ace ths
        s->command_complete = 2;
646 a917d384 pbrook
        if (s->waiting && s->dbc != 0) {
647 a917d384 pbrook
            /* Raise phase mismatch for short transfers.  */
648 a917d384 pbrook
            lsi_bad_phase(s, out, PHASE_ST);
649 a917d384 pbrook
        } else {
650 a917d384 pbrook
            lsi_set_phase(s, PHASE_ST);
651 a917d384 pbrook
        }
652 a917d384 pbrook
        lsi_resume_script(s);
653 a917d384 pbrook
        return;
654 4d611c9a pbrook
    }
655 4d611c9a pbrook
656 a917d384 pbrook
    if (s->waiting == 1 || tag != s->current_tag) {
657 a917d384 pbrook
        if (lsi_queue_tag(s, tag, arg))
658 a917d384 pbrook
            return;
659 a917d384 pbrook
    }
660 a917d384 pbrook
    DPRINTF("Data ready tag=0x%x len=%d\n", tag, arg);
661 a917d384 pbrook
    s->current_dma_len = arg;
662 8ccc2ace ths
    s->command_complete = 1;
663 a917d384 pbrook
    if (!s->waiting)
664 a917d384 pbrook
        return;
665 a917d384 pbrook
    if (s->waiting == 1 || s->dbc == 0) {
666 a917d384 pbrook
        lsi_resume_script(s);
667 a917d384 pbrook
    } else {
668 4d611c9a pbrook
        lsi_do_dma(s, out);
669 4d611c9a pbrook
    }
670 4d611c9a pbrook
}
671 7d8406be pbrook
672 7d8406be pbrook
static void lsi_do_command(LSIState *s)
673 7d8406be pbrook
{
674 7d8406be pbrook
    uint8_t buf[16];
675 7d8406be pbrook
    int n;
676 7d8406be pbrook
677 7d8406be pbrook
    DPRINTF("Send command len=%d\n", s->dbc);
678 7d8406be pbrook
    if (s->dbc > 16)
679 7d8406be pbrook
        s->dbc = 16;
680 7d8406be pbrook
    cpu_physical_memory_read(s->dnad, buf, s->dbc);
681 7d8406be pbrook
    s->sfbr = buf[0];
682 8ccc2ace ths
    s->command_complete = 0;
683 8ccc2ace ths
    n = s->current_dev->send_command(s->current_dev, s->current_tag, buf,
684 8ccc2ace ths
                                     s->current_lun);
685 7d8406be pbrook
    if (n > 0) {
686 7d8406be pbrook
        lsi_set_phase(s, PHASE_DI);
687 8ccc2ace ths
        s->current_dev->read_data(s->current_dev, s->current_tag);
688 7d8406be pbrook
    } else if (n < 0) {
689 7d8406be pbrook
        lsi_set_phase(s, PHASE_DO);
690 8ccc2ace ths
        s->current_dev->write_data(s->current_dev, s->current_tag);
691 a917d384 pbrook
    }
692 8ccc2ace ths
693 8ccc2ace ths
    if (!s->command_complete) {
694 8ccc2ace ths
        if (n) {
695 8ccc2ace ths
            /* Command did not complete immediately so disconnect.  */
696 8ccc2ace ths
            lsi_add_msg_byte(s, 2); /* SAVE DATA POINTER */
697 8ccc2ace ths
            lsi_add_msg_byte(s, 4); /* DISCONNECT */
698 8ccc2ace ths
            /* wait data */
699 8ccc2ace ths
            lsi_set_phase(s, PHASE_MI);
700 8ccc2ace ths
            s->msg_action = 1;
701 8ccc2ace ths
            lsi_queue_command(s);
702 8ccc2ace ths
        } else {
703 8ccc2ace ths
            /* wait command complete */
704 8ccc2ace ths
            lsi_set_phase(s, PHASE_DI);
705 8ccc2ace ths
        }
706 7d8406be pbrook
    }
707 7d8406be pbrook
}
708 7d8406be pbrook
709 7d8406be pbrook
static void lsi_do_status(LSIState *s)
710 7d8406be pbrook
{
711 a917d384 pbrook
    uint8_t sense;
712 7d8406be pbrook
    DPRINTF("Get status len=%d sense=%d\n", s->dbc, s->sense);
713 7d8406be pbrook
    if (s->dbc != 1)
714 7d8406be pbrook
        BADF("Bad Status move\n");
715 7d8406be pbrook
    s->dbc = 1;
716 a917d384 pbrook
    sense = s->sense;
717 a917d384 pbrook
    s->sfbr = sense;
718 a917d384 pbrook
    cpu_physical_memory_write(s->dnad, &sense, 1);
719 7d8406be pbrook
    lsi_set_phase(s, PHASE_MI);
720 a917d384 pbrook
    s->msg_action = 1;
721 a917d384 pbrook
    lsi_add_msg_byte(s, 0); /* COMMAND COMPLETE */
722 7d8406be pbrook
}
723 7d8406be pbrook
724 7d8406be pbrook
static void lsi_disconnect(LSIState *s)
725 7d8406be pbrook
{
726 7d8406be pbrook
    s->scntl1 &= ~LSI_SCNTL1_CON;
727 7d8406be pbrook
    s->sstat1 &= ~PHASE_MASK;
728 7d8406be pbrook
}
729 7d8406be pbrook
730 7d8406be pbrook
static void lsi_do_msgin(LSIState *s)
731 7d8406be pbrook
{
732 a917d384 pbrook
    int len;
733 a917d384 pbrook
    DPRINTF("Message in len=%d/%d\n", s->dbc, s->msg_len);
734 a917d384 pbrook
    s->sfbr = s->msg[0];
735 a917d384 pbrook
    len = s->msg_len;
736 a917d384 pbrook
    if (len > s->dbc)
737 a917d384 pbrook
        len = s->dbc;
738 a917d384 pbrook
    cpu_physical_memory_write(s->dnad, s->msg, len);
739 a917d384 pbrook
    /* Linux drivers rely on the last byte being in the SIDL.  */
740 a917d384 pbrook
    s->sidl = s->msg[len - 1];
741 a917d384 pbrook
    s->msg_len -= len;
742 a917d384 pbrook
    if (s->msg_len) {
743 a917d384 pbrook
        memmove(s->msg, s->msg + len, s->msg_len);
744 7d8406be pbrook
    } else {
745 7d8406be pbrook
        /* ??? Check if ATN (not yet implemented) is asserted and maybe
746 7d8406be pbrook
           switch to PHASE_MO.  */
747 a917d384 pbrook
        switch (s->msg_action) {
748 a917d384 pbrook
        case 0:
749 a917d384 pbrook
            lsi_set_phase(s, PHASE_CMD);
750 a917d384 pbrook
            break;
751 a917d384 pbrook
        case 1:
752 a917d384 pbrook
            lsi_disconnect(s);
753 a917d384 pbrook
            break;
754 a917d384 pbrook
        case 2:
755 a917d384 pbrook
            lsi_set_phase(s, PHASE_DO);
756 a917d384 pbrook
            break;
757 a917d384 pbrook
        case 3:
758 a917d384 pbrook
            lsi_set_phase(s, PHASE_DI);
759 a917d384 pbrook
            break;
760 a917d384 pbrook
        default:
761 a917d384 pbrook
            abort();
762 a917d384 pbrook
        }
763 7d8406be pbrook
    }
764 7d8406be pbrook
}
765 7d8406be pbrook
766 a917d384 pbrook
/* Read the next byte during a MSGOUT phase.  */
767 a917d384 pbrook
static uint8_t lsi_get_msgbyte(LSIState *s)
768 a917d384 pbrook
{
769 a917d384 pbrook
    uint8_t data;
770 a917d384 pbrook
    cpu_physical_memory_read(s->dnad, &data, 1);
771 a917d384 pbrook
    s->dnad++;
772 a917d384 pbrook
    s->dbc--;
773 a917d384 pbrook
    return data;
774 a917d384 pbrook
}
775 a917d384 pbrook
776 7d8406be pbrook
static void lsi_do_msgout(LSIState *s)
777 7d8406be pbrook
{
778 7d8406be pbrook
    uint8_t msg;
779 a917d384 pbrook
    int len;
780 7d8406be pbrook
781 7d8406be pbrook
    DPRINTF("MSG out len=%d\n", s->dbc);
782 a917d384 pbrook
    while (s->dbc) {
783 a917d384 pbrook
        msg = lsi_get_msgbyte(s);
784 a917d384 pbrook
        s->sfbr = msg;
785 a917d384 pbrook
786 a917d384 pbrook
        switch (msg) {
787 a917d384 pbrook
        case 0x00:
788 a917d384 pbrook
            DPRINTF("MSG: Disconnect\n");
789 a917d384 pbrook
            lsi_disconnect(s);
790 a917d384 pbrook
            break;
791 a917d384 pbrook
        case 0x08:
792 a917d384 pbrook
            DPRINTF("MSG: No Operation\n");
793 a917d384 pbrook
            lsi_set_phase(s, PHASE_CMD);
794 a917d384 pbrook
            break;
795 a917d384 pbrook
        case 0x01:
796 a917d384 pbrook
            len = lsi_get_msgbyte(s);
797 a917d384 pbrook
            msg = lsi_get_msgbyte(s);
798 a917d384 pbrook
            DPRINTF("Extended message 0x%x (len %d)\n", msg, len);
799 a917d384 pbrook
            switch (msg) {
800 a917d384 pbrook
            case 1:
801 a917d384 pbrook
                DPRINTF("SDTR (ignored)\n");
802 a917d384 pbrook
                s->dbc -= 2;
803 a917d384 pbrook
                break;
804 a917d384 pbrook
            case 3:
805 a917d384 pbrook
                DPRINTF("WDTR (ignored)\n");
806 a917d384 pbrook
                s->dbc -= 1;
807 a917d384 pbrook
                break;
808 a917d384 pbrook
            default:
809 a917d384 pbrook
                goto bad;
810 a917d384 pbrook
            }
811 a917d384 pbrook
            break;
812 a917d384 pbrook
        case 0x20: /* SIMPLE queue */
813 a917d384 pbrook
            s->current_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
814 a917d384 pbrook
            DPRINTF("SIMPLE queue tag=0x%x\n", s->current_tag & 0xff);
815 a917d384 pbrook
            break;
816 a917d384 pbrook
        case 0x21: /* HEAD of queue */
817 a917d384 pbrook
            BADF("HEAD queue not implemented\n");
818 a917d384 pbrook
            s->current_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
819 a917d384 pbrook
            break;
820 a917d384 pbrook
        case 0x22: /* ORDERED queue */
821 a917d384 pbrook
            BADF("ORDERED queue not implemented\n");
822 a917d384 pbrook
            s->current_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
823 a917d384 pbrook
            break;
824 a917d384 pbrook
        default:
825 a917d384 pbrook
            if ((msg & 0x80) == 0) {
826 a917d384 pbrook
                goto bad;
827 a917d384 pbrook
            }
828 a917d384 pbrook
            s->current_lun = msg & 7;
829 a917d384 pbrook
            DPRINTF("Select LUN %d\n", s->current_lun);
830 a917d384 pbrook
            lsi_set_phase(s, PHASE_CMD);
831 a917d384 pbrook
            break;
832 a917d384 pbrook
        }
833 7d8406be pbrook
    }
834 a917d384 pbrook
    return;
835 a917d384 pbrook
bad:
836 a917d384 pbrook
    BADF("Unimplemented message 0x%02x\n", msg);
837 a917d384 pbrook
    lsi_set_phase(s, PHASE_MI);
838 a917d384 pbrook
    lsi_add_msg_byte(s, 7); /* MESSAGE REJECT */
839 a917d384 pbrook
    s->msg_action = 0;
840 7d8406be pbrook
}
841 7d8406be pbrook
842 7d8406be pbrook
/* Sign extend a 24-bit value.  */
843 7d8406be pbrook
static inline int32_t sxt24(int32_t n)
844 7d8406be pbrook
{
845 7d8406be pbrook
    return (n << 8) >> 8;
846 7d8406be pbrook
}
847 7d8406be pbrook
848 e20a8dff Blue Swirl
#define LSI_BUF_SIZE 4096
849 7d8406be pbrook
static void lsi_memcpy(LSIState *s, uint32_t dest, uint32_t src, int count)
850 7d8406be pbrook
{
851 7d8406be pbrook
    int n;
852 e20a8dff Blue Swirl
    uint8_t buf[LSI_BUF_SIZE];
853 7d8406be pbrook
854 7d8406be pbrook
    DPRINTF("memcpy dest 0x%08x src 0x%08x count %d\n", dest, src, count);
855 7d8406be pbrook
    while (count) {
856 e20a8dff Blue Swirl
        n = (count > LSI_BUF_SIZE) ? LSI_BUF_SIZE : count;
857 7d8406be pbrook
        cpu_physical_memory_read(src, buf, n);
858 7d8406be pbrook
        cpu_physical_memory_write(dest, buf, n);
859 7d8406be pbrook
        src += n;
860 7d8406be pbrook
        dest += n;
861 7d8406be pbrook
        count -= n;
862 7d8406be pbrook
    }
863 7d8406be pbrook
}
864 7d8406be pbrook
865 a917d384 pbrook
static void lsi_wait_reselect(LSIState *s)
866 a917d384 pbrook
{
867 a917d384 pbrook
    int i;
868 a917d384 pbrook
    DPRINTF("Wait Reselect\n");
869 a917d384 pbrook
    if (s->current_dma_len)
870 a917d384 pbrook
        BADF("Reselect with pending DMA\n");
871 a917d384 pbrook
    for (i = 0; i < s->active_commands; i++) {
872 a917d384 pbrook
        if (s->queue[i].pending) {
873 a917d384 pbrook
            lsi_reselect(s, s->queue[i].tag);
874 a917d384 pbrook
            break;
875 a917d384 pbrook
        }
876 a917d384 pbrook
    }
877 a917d384 pbrook
    if (s->current_dma_len == 0) {
878 a917d384 pbrook
        s->waiting = 1;
879 a917d384 pbrook
    }
880 a917d384 pbrook
}
881 a917d384 pbrook
882 7d8406be pbrook
static void lsi_execute_script(LSIState *s)
883 7d8406be pbrook
{
884 7d8406be pbrook
    uint32_t insn;
885 b25cf589 aliguori
    uint32_t addr, addr_high;
886 7d8406be pbrook
    int opcode;
887 ee4d919f aliguori
    int insn_processed = 0;
888 7d8406be pbrook
889 7d8406be pbrook
    s->istat1 |= LSI_ISTAT1_SRUN;
890 7d8406be pbrook
again:
891 ee4d919f aliguori
    insn_processed++;
892 7d8406be pbrook
    insn = read_dword(s, s->dsp);
893 02b373ad balrog
    if (!insn) {
894 02b373ad balrog
        /* If we receive an empty opcode increment the DSP by 4 bytes
895 02b373ad balrog
           instead of 8 and execute the next opcode at that location */
896 02b373ad balrog
        s->dsp += 4;
897 02b373ad balrog
        goto again;
898 02b373ad balrog
    }
899 7d8406be pbrook
    addr = read_dword(s, s->dsp + 4);
900 b25cf589 aliguori
    addr_high = 0;
901 7d8406be pbrook
    DPRINTF("SCRIPTS dsp=%08x opcode %08x arg %08x\n", s->dsp, insn, addr);
902 7d8406be pbrook
    s->dsps = addr;
903 7d8406be pbrook
    s->dcmd = insn >> 24;
904 7d8406be pbrook
    s->dsp += 8;
905 7d8406be pbrook
    switch (insn >> 30) {
906 7d8406be pbrook
    case 0: /* Block move.  */
907 7d8406be pbrook
        if (s->sist1 & LSI_SIST1_STO) {
908 7d8406be pbrook
            DPRINTF("Delayed select timeout\n");
909 7d8406be pbrook
            lsi_stop_script(s);
910 7d8406be pbrook
            break;
911 7d8406be pbrook
        }
912 7d8406be pbrook
        s->dbc = insn & 0xffffff;
913 7d8406be pbrook
        s->rbc = s->dbc;
914 dd8edf01 aliguori
        /* ??? Set ESA.  */
915 dd8edf01 aliguori
        s->ia = s->dsp - 8;
916 7d8406be pbrook
        if (insn & (1 << 29)) {
917 7d8406be pbrook
            /* Indirect addressing.  */
918 7d8406be pbrook
            addr = read_dword(s, addr);
919 7d8406be pbrook
        } else if (insn & (1 << 28)) {
920 7d8406be pbrook
            uint32_t buf[2];
921 7d8406be pbrook
            int32_t offset;
922 7d8406be pbrook
            /* Table indirect addressing.  */
923 dd8edf01 aliguori
924 dd8edf01 aliguori
            /* 32-bit Table indirect */
925 7d8406be pbrook
            offset = sxt24(addr);
926 7d8406be pbrook
            cpu_physical_memory_read(s->dsa + offset, (uint8_t *)buf, 8);
927 b25cf589 aliguori
            /* byte count is stored in bits 0:23 only */
928 b25cf589 aliguori
            s->dbc = cpu_to_le32(buf[0]) & 0xffffff;
929 7faa239c ths
            s->rbc = s->dbc;
930 7d8406be pbrook
            addr = cpu_to_le32(buf[1]);
931 b25cf589 aliguori
932 b25cf589 aliguori
            /* 40-bit DMA, upper addr bits [39:32] stored in first DWORD of
933 b25cf589 aliguori
             * table, bits [31:24] */
934 b25cf589 aliguori
            if (lsi_dma_40bit(s))
935 b25cf589 aliguori
                addr_high = cpu_to_le32(buf[0]) >> 24;
936 dd8edf01 aliguori
            else if (lsi_dma_ti64bit(s)) {
937 dd8edf01 aliguori
                int selector = (cpu_to_le32(buf[0]) >> 24) & 0x1f;
938 dd8edf01 aliguori
                switch (selector) {
939 dd8edf01 aliguori
                case 0 ... 0x0f:
940 dd8edf01 aliguori
                    /* offset index into scratch registers since
941 dd8edf01 aliguori
                     * TI64 mode can use registers C to R */
942 dd8edf01 aliguori
                    addr_high = s->scratch[2 + selector];
943 dd8edf01 aliguori
                    break;
944 dd8edf01 aliguori
                case 0x10:
945 dd8edf01 aliguori
                    addr_high = s->mmrs;
946 dd8edf01 aliguori
                    break;
947 dd8edf01 aliguori
                case 0x11:
948 dd8edf01 aliguori
                    addr_high = s->mmws;
949 dd8edf01 aliguori
                    break;
950 dd8edf01 aliguori
                case 0x12:
951 dd8edf01 aliguori
                    addr_high = s->sfs;
952 dd8edf01 aliguori
                    break;
953 dd8edf01 aliguori
                case 0x13:
954 dd8edf01 aliguori
                    addr_high = s->drs;
955 dd8edf01 aliguori
                    break;
956 dd8edf01 aliguori
                case 0x14:
957 dd8edf01 aliguori
                    addr_high = s->sbms;
958 dd8edf01 aliguori
                    break;
959 dd8edf01 aliguori
                case 0x15:
960 dd8edf01 aliguori
                    addr_high = s->dbms;
961 dd8edf01 aliguori
                    break;
962 dd8edf01 aliguori
                default:
963 dd8edf01 aliguori
                    BADF("Illegal selector specified (0x%x > 0x15)"
964 dd8edf01 aliguori
                         " for 64-bit DMA block move", selector);
965 dd8edf01 aliguori
                    break;
966 dd8edf01 aliguori
                }
967 dd8edf01 aliguori
            }
968 dd8edf01 aliguori
        } else if (lsi_dma_64bit(s)) {
969 dd8edf01 aliguori
            /* fetch a 3rd dword if 64-bit direct move is enabled and
970 dd8edf01 aliguori
               only if we're not doing table indirect or indirect addressing */
971 dd8edf01 aliguori
            s->dbms = read_dword(s, s->dsp);
972 dd8edf01 aliguori
            s->dsp += 4;
973 dd8edf01 aliguori
            s->ia = s->dsp - 12;
974 7d8406be pbrook
        }
975 7d8406be pbrook
        if ((s->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) {
976 7d8406be pbrook
            DPRINTF("Wrong phase got %d expected %d\n",
977 7d8406be pbrook
                    s->sstat1 & PHASE_MASK, (insn >> 24) & 7);
978 7d8406be pbrook
            lsi_script_scsi_interrupt(s, LSI_SIST0_MA, 0);
979 7d8406be pbrook
            break;
980 7d8406be pbrook
        }
981 7d8406be pbrook
        s->dnad = addr;
982 b25cf589 aliguori
        s->dnad64 = addr_high;
983 7d8406be pbrook
        switch (s->sstat1 & 0x7) {
984 7d8406be pbrook
        case PHASE_DO:
985 a917d384 pbrook
            s->waiting = 2;
986 7d8406be pbrook
            lsi_do_dma(s, 1);
987 a917d384 pbrook
            if (s->waiting)
988 a917d384 pbrook
                s->waiting = 3;
989 7d8406be pbrook
            break;
990 7d8406be pbrook
        case PHASE_DI:
991 a917d384 pbrook
            s->waiting = 2;
992 7d8406be pbrook
            lsi_do_dma(s, 0);
993 a917d384 pbrook
            if (s->waiting)
994 a917d384 pbrook
                s->waiting = 3;
995 7d8406be pbrook
            break;
996 7d8406be pbrook
        case PHASE_CMD:
997 7d8406be pbrook
            lsi_do_command(s);
998 7d8406be pbrook
            break;
999 7d8406be pbrook
        case PHASE_ST:
1000 7d8406be pbrook
            lsi_do_status(s);
1001 7d8406be pbrook
            break;
1002 7d8406be pbrook
        case PHASE_MO:
1003 7d8406be pbrook
            lsi_do_msgout(s);
1004 7d8406be pbrook
            break;
1005 7d8406be pbrook
        case PHASE_MI:
1006 7d8406be pbrook
            lsi_do_msgin(s);
1007 7d8406be pbrook
            break;
1008 7d8406be pbrook
        default:
1009 7d8406be pbrook
            BADF("Unimplemented phase %d\n", s->sstat1 & PHASE_MASK);
1010 7d8406be pbrook
            exit(1);
1011 7d8406be pbrook
        }
1012 7d8406be pbrook
        s->dfifo = s->dbc & 0xff;
1013 7d8406be pbrook
        s->ctest5 = (s->ctest5 & 0xfc) | ((s->dbc >> 8) & 3);
1014 7d8406be pbrook
        s->sbc = s->dbc;
1015 7d8406be pbrook
        s->rbc -= s->dbc;
1016 7d8406be pbrook
        s->ua = addr + s->dbc;
1017 7d8406be pbrook
        break;
1018 7d8406be pbrook
1019 7d8406be pbrook
    case 1: /* IO or Read/Write instruction.  */
1020 7d8406be pbrook
        opcode = (insn >> 27) & 7;
1021 7d8406be pbrook
        if (opcode < 5) {
1022 7d8406be pbrook
            uint32_t id;
1023 7d8406be pbrook
1024 7d8406be pbrook
            if (insn & (1 << 25)) {
1025 7d8406be pbrook
                id = read_dword(s, s->dsa + sxt24(insn));
1026 7d8406be pbrook
            } else {
1027 7d8406be pbrook
                id = addr;
1028 7d8406be pbrook
            }
1029 7d8406be pbrook
            id = (id >> 16) & 0xf;
1030 7d8406be pbrook
            if (insn & (1 << 26)) {
1031 7d8406be pbrook
                addr = s->dsp + sxt24(addr);
1032 7d8406be pbrook
            }
1033 7d8406be pbrook
            s->dnad = addr;
1034 7d8406be pbrook
            switch (opcode) {
1035 7d8406be pbrook
            case 0: /* Select */
1036 a917d384 pbrook
                s->sdid = id;
1037 a917d384 pbrook
                if (s->current_dma_len && (s->ssid & 0xf) == id) {
1038 a917d384 pbrook
                    DPRINTF("Already reselected by target %d\n", id);
1039 a917d384 pbrook
                    break;
1040 a917d384 pbrook
                }
1041 7d8406be pbrook
                s->sstat0 |= LSI_SSTAT0_WOA;
1042 7d8406be pbrook
                s->scntl1 &= ~LSI_SCNTL1_IARB;
1043 7d8406be pbrook
                if (id >= LSI_MAX_DEVS || !s->scsi_dev[id]) {
1044 7d8406be pbrook
                    DPRINTF("Selected absent target %d\n", id);
1045 7d8406be pbrook
                    lsi_script_scsi_interrupt(s, 0, LSI_SIST1_STO);
1046 7d8406be pbrook
                    lsi_disconnect(s);
1047 7d8406be pbrook
                    break;
1048 7d8406be pbrook
                }
1049 7d8406be pbrook
                DPRINTF("Selected target %d%s\n",
1050 7d8406be pbrook
                        id, insn & (1 << 3) ? " ATN" : "");
1051 7d8406be pbrook
                /* ??? Linux drivers compain when this is set.  Maybe
1052 7d8406be pbrook
                   it only applies in low-level mode (unimplemented).
1053 7d8406be pbrook
                lsi_script_scsi_interrupt(s, LSI_SIST0_CMP, 0); */
1054 7d8406be pbrook
                s->current_dev = s->scsi_dev[id];
1055 a917d384 pbrook
                s->current_tag = id << 8;
1056 7d8406be pbrook
                s->scntl1 |= LSI_SCNTL1_CON;
1057 7d8406be pbrook
                if (insn & (1 << 3)) {
1058 7d8406be pbrook
                    s->socl |= LSI_SOCL_ATN;
1059 7d8406be pbrook
                }
1060 7d8406be pbrook
                lsi_set_phase(s, PHASE_MO);
1061 7d8406be pbrook
                break;
1062 7d8406be pbrook
            case 1: /* Disconnect */
1063 7d8406be pbrook
                DPRINTF("Wait Disconect\n");
1064 7d8406be pbrook
                s->scntl1 &= ~LSI_SCNTL1_CON;
1065 7d8406be pbrook
                break;
1066 7d8406be pbrook
            case 2: /* Wait Reselect */
1067 a917d384 pbrook
                lsi_wait_reselect(s);
1068 7d8406be pbrook
                break;
1069 7d8406be pbrook
            case 3: /* Set */
1070 7d8406be pbrook
                DPRINTF("Set%s%s%s%s\n",
1071 7d8406be pbrook
                        insn & (1 << 3) ? " ATN" : "",
1072 7d8406be pbrook
                        insn & (1 << 6) ? " ACK" : "",
1073 7d8406be pbrook
                        insn & (1 << 9) ? " TM" : "",
1074 7d8406be pbrook
                        insn & (1 << 10) ? " CC" : "");
1075 7d8406be pbrook
                if (insn & (1 << 3)) {
1076 7d8406be pbrook
                    s->socl |= LSI_SOCL_ATN;
1077 7d8406be pbrook
                    lsi_set_phase(s, PHASE_MO);
1078 7d8406be pbrook
                }
1079 7d8406be pbrook
                if (insn & (1 << 9)) {
1080 7d8406be pbrook
                    BADF("Target mode not implemented\n");
1081 7d8406be pbrook
                    exit(1);
1082 7d8406be pbrook
                }
1083 7d8406be pbrook
                if (insn & (1 << 10))
1084 7d8406be pbrook
                    s->carry = 1;
1085 7d8406be pbrook
                break;
1086 7d8406be pbrook
            case 4: /* Clear */
1087 7d8406be pbrook
                DPRINTF("Clear%s%s%s%s\n",
1088 7d8406be pbrook
                        insn & (1 << 3) ? " ATN" : "",
1089 7d8406be pbrook
                        insn & (1 << 6) ? " ACK" : "",
1090 7d8406be pbrook
                        insn & (1 << 9) ? " TM" : "",
1091 7d8406be pbrook
                        insn & (1 << 10) ? " CC" : "");
1092 7d8406be pbrook
                if (insn & (1 << 3)) {
1093 7d8406be pbrook
                    s->socl &= ~LSI_SOCL_ATN;
1094 7d8406be pbrook
                }
1095 7d8406be pbrook
                if (insn & (1 << 10))
1096 7d8406be pbrook
                    s->carry = 0;
1097 7d8406be pbrook
                break;
1098 7d8406be pbrook
            }
1099 7d8406be pbrook
        } else {
1100 7d8406be pbrook
            uint8_t op0;
1101 7d8406be pbrook
            uint8_t op1;
1102 7d8406be pbrook
            uint8_t data8;
1103 7d8406be pbrook
            int reg;
1104 7d8406be pbrook
            int operator;
1105 7d8406be pbrook
#ifdef DEBUG_LSI
1106 7d8406be pbrook
            static const char *opcode_names[3] =
1107 7d8406be pbrook
                {"Write", "Read", "Read-Modify-Write"};
1108 7d8406be pbrook
            static const char *operator_names[8] =
1109 7d8406be pbrook
                {"MOV", "SHL", "OR", "XOR", "AND", "SHR", "ADD", "ADC"};
1110 7d8406be pbrook
#endif
1111 7d8406be pbrook
1112 7d8406be pbrook
            reg = ((insn >> 16) & 0x7f) | (insn & 0x80);
1113 7d8406be pbrook
            data8 = (insn >> 8) & 0xff;
1114 7d8406be pbrook
            opcode = (insn >> 27) & 7;
1115 7d8406be pbrook
            operator = (insn >> 24) & 7;
1116 a917d384 pbrook
            DPRINTF("%s reg 0x%x %s data8=0x%02x sfbr=0x%02x%s\n",
1117 7d8406be pbrook
                    opcode_names[opcode - 5], reg,
1118 a917d384 pbrook
                    operator_names[operator], data8, s->sfbr,
1119 7d8406be pbrook
                    (insn & (1 << 23)) ? " SFBR" : "");
1120 7d8406be pbrook
            op0 = op1 = 0;
1121 7d8406be pbrook
            switch (opcode) {
1122 7d8406be pbrook
            case 5: /* From SFBR */
1123 7d8406be pbrook
                op0 = s->sfbr;
1124 7d8406be pbrook
                op1 = data8;
1125 7d8406be pbrook
                break;
1126 7d8406be pbrook
            case 6: /* To SFBR */
1127 7d8406be pbrook
                if (operator)
1128 7d8406be pbrook
                    op0 = lsi_reg_readb(s, reg);
1129 7d8406be pbrook
                op1 = data8;
1130 7d8406be pbrook
                break;
1131 7d8406be pbrook
            case 7: /* Read-modify-write */
1132 7d8406be pbrook
                if (operator)
1133 7d8406be pbrook
                    op0 = lsi_reg_readb(s, reg);
1134 7d8406be pbrook
                if (insn & (1 << 23)) {
1135 7d8406be pbrook
                    op1 = s->sfbr;
1136 7d8406be pbrook
                } else {
1137 7d8406be pbrook
                    op1 = data8;
1138 7d8406be pbrook
                }
1139 7d8406be pbrook
                break;
1140 7d8406be pbrook
            }
1141 7d8406be pbrook
1142 7d8406be pbrook
            switch (operator) {
1143 7d8406be pbrook
            case 0: /* move */
1144 7d8406be pbrook
                op0 = op1;
1145 7d8406be pbrook
                break;
1146 7d8406be pbrook
            case 1: /* Shift left */
1147 7d8406be pbrook
                op1 = op0 >> 7;
1148 7d8406be pbrook
                op0 = (op0 << 1) | s->carry;
1149 7d8406be pbrook
                s->carry = op1;
1150 7d8406be pbrook
                break;
1151 7d8406be pbrook
            case 2: /* OR */
1152 7d8406be pbrook
                op0 |= op1;
1153 7d8406be pbrook
                break;
1154 7d8406be pbrook
            case 3: /* XOR */
1155 dcfb9014 ths
                op0 ^= op1;
1156 7d8406be pbrook
                break;
1157 7d8406be pbrook
            case 4: /* AND */
1158 7d8406be pbrook
                op0 &= op1;
1159 7d8406be pbrook
                break;
1160 7d8406be pbrook
            case 5: /* SHR */
1161 7d8406be pbrook
                op1 = op0 & 1;
1162 7d8406be pbrook
                op0 = (op0 >> 1) | (s->carry << 7);
1163 687fa640 ths
                s->carry = op1;
1164 7d8406be pbrook
                break;
1165 7d8406be pbrook
            case 6: /* ADD */
1166 7d8406be pbrook
                op0 += op1;
1167 7d8406be pbrook
                s->carry = op0 < op1;
1168 7d8406be pbrook
                break;
1169 7d8406be pbrook
            case 7: /* ADC */
1170 7d8406be pbrook
                op0 += op1 + s->carry;
1171 7d8406be pbrook
                if (s->carry)
1172 7d8406be pbrook
                    s->carry = op0 <= op1;
1173 7d8406be pbrook
                else
1174 7d8406be pbrook
                    s->carry = op0 < op1;
1175 7d8406be pbrook
                break;
1176 7d8406be pbrook
            }
1177 7d8406be pbrook
1178 7d8406be pbrook
            switch (opcode) {
1179 7d8406be pbrook
            case 5: /* From SFBR */
1180 7d8406be pbrook
            case 7: /* Read-modify-write */
1181 7d8406be pbrook
                lsi_reg_writeb(s, reg, op0);
1182 7d8406be pbrook
                break;
1183 7d8406be pbrook
            case 6: /* To SFBR */
1184 7d8406be pbrook
                s->sfbr = op0;
1185 7d8406be pbrook
                break;
1186 7d8406be pbrook
            }
1187 7d8406be pbrook
        }
1188 7d8406be pbrook
        break;
1189 7d8406be pbrook
1190 7d8406be pbrook
    case 2: /* Transfer Control.  */
1191 7d8406be pbrook
        {
1192 7d8406be pbrook
            int cond;
1193 7d8406be pbrook
            int jmp;
1194 7d8406be pbrook
1195 7d8406be pbrook
            if ((insn & 0x002e0000) == 0) {
1196 7d8406be pbrook
                DPRINTF("NOP\n");
1197 7d8406be pbrook
                break;
1198 7d8406be pbrook
            }
1199 7d8406be pbrook
            if (s->sist1 & LSI_SIST1_STO) {
1200 7d8406be pbrook
                DPRINTF("Delayed select timeout\n");
1201 7d8406be pbrook
                lsi_stop_script(s);
1202 7d8406be pbrook
                break;
1203 7d8406be pbrook
            }
1204 7d8406be pbrook
            cond = jmp = (insn & (1 << 19)) != 0;
1205 7d8406be pbrook
            if (cond == jmp && (insn & (1 << 21))) {
1206 7d8406be pbrook
                DPRINTF("Compare carry %d\n", s->carry == jmp);
1207 7d8406be pbrook
                cond = s->carry != 0;
1208 7d8406be pbrook
            }
1209 7d8406be pbrook
            if (cond == jmp && (insn & (1 << 17))) {
1210 7d8406be pbrook
                DPRINTF("Compare phase %d %c= %d\n",
1211 7d8406be pbrook
                        (s->sstat1 & PHASE_MASK),
1212 7d8406be pbrook
                        jmp ? '=' : '!',
1213 7d8406be pbrook
                        ((insn >> 24) & 7));
1214 7d8406be pbrook
                cond = (s->sstat1 & PHASE_MASK) == ((insn >> 24) & 7);
1215 7d8406be pbrook
            }
1216 7d8406be pbrook
            if (cond == jmp && (insn & (1 << 18))) {
1217 7d8406be pbrook
                uint8_t mask;
1218 7d8406be pbrook
1219 7d8406be pbrook
                mask = (~insn >> 8) & 0xff;
1220 7d8406be pbrook
                DPRINTF("Compare data 0x%x & 0x%x %c= 0x%x\n",
1221 7d8406be pbrook
                        s->sfbr, mask, jmp ? '=' : '!', insn & mask);
1222 7d8406be pbrook
                cond = (s->sfbr & mask) == (insn & mask);
1223 7d8406be pbrook
            }
1224 7d8406be pbrook
            if (cond == jmp) {
1225 7d8406be pbrook
                if (insn & (1 << 23)) {
1226 7d8406be pbrook
                    /* Relative address.  */
1227 7d8406be pbrook
                    addr = s->dsp + sxt24(addr);
1228 7d8406be pbrook
                }
1229 7d8406be pbrook
                switch ((insn >> 27) & 7) {
1230 7d8406be pbrook
                case 0: /* Jump */
1231 7d8406be pbrook
                    DPRINTF("Jump to 0x%08x\n", addr);
1232 7d8406be pbrook
                    s->dsp = addr;
1233 7d8406be pbrook
                    break;
1234 7d8406be pbrook
                case 1: /* Call */
1235 7d8406be pbrook
                    DPRINTF("Call 0x%08x\n", addr);
1236 7d8406be pbrook
                    s->temp = s->dsp;
1237 7d8406be pbrook
                    s->dsp = addr;
1238 7d8406be pbrook
                    break;
1239 7d8406be pbrook
                case 2: /* Return */
1240 7d8406be pbrook
                    DPRINTF("Return to 0x%08x\n", s->temp);
1241 7d8406be pbrook
                    s->dsp = s->temp;
1242 7d8406be pbrook
                    break;
1243 7d8406be pbrook
                case 3: /* Interrupt */
1244 7d8406be pbrook
                    DPRINTF("Interrupt 0x%08x\n", s->dsps);
1245 7d8406be pbrook
                    if ((insn & (1 << 20)) != 0) {
1246 7d8406be pbrook
                        s->istat0 |= LSI_ISTAT0_INTF;
1247 7d8406be pbrook
                        lsi_update_irq(s);
1248 7d8406be pbrook
                    } else {
1249 7d8406be pbrook
                        lsi_script_dma_interrupt(s, LSI_DSTAT_SIR);
1250 7d8406be pbrook
                    }
1251 7d8406be pbrook
                    break;
1252 7d8406be pbrook
                default:
1253 7d8406be pbrook
                    DPRINTF("Illegal transfer control\n");
1254 7d8406be pbrook
                    lsi_script_dma_interrupt(s, LSI_DSTAT_IID);
1255 7d8406be pbrook
                    break;
1256 7d8406be pbrook
                }
1257 7d8406be pbrook
            } else {
1258 7d8406be pbrook
                DPRINTF("Control condition failed\n");
1259 7d8406be pbrook
            }
1260 7d8406be pbrook
        }
1261 7d8406be pbrook
        break;
1262 7d8406be pbrook
1263 7d8406be pbrook
    case 3:
1264 7d8406be pbrook
        if ((insn & (1 << 29)) == 0) {
1265 7d8406be pbrook
            /* Memory move.  */
1266 7d8406be pbrook
            uint32_t dest;
1267 7d8406be pbrook
            /* ??? The docs imply the destination address is loaded into
1268 7d8406be pbrook
               the TEMP register.  However the Linux drivers rely on
1269 7d8406be pbrook
               the value being presrved.  */
1270 7d8406be pbrook
            dest = read_dword(s, s->dsp);
1271 7d8406be pbrook
            s->dsp += 4;
1272 7d8406be pbrook
            lsi_memcpy(s, dest, addr, insn & 0xffffff);
1273 7d8406be pbrook
        } else {
1274 7d8406be pbrook
            uint8_t data[7];
1275 7d8406be pbrook
            int reg;
1276 7d8406be pbrook
            int n;
1277 7d8406be pbrook
            int i;
1278 7d8406be pbrook
1279 7d8406be pbrook
            if (insn & (1 << 28)) {
1280 7d8406be pbrook
                addr = s->dsa + sxt24(addr);
1281 7d8406be pbrook
            }
1282 7d8406be pbrook
            n = (insn & 7);
1283 7d8406be pbrook
            reg = (insn >> 16) & 0xff;
1284 7d8406be pbrook
            if (insn & (1 << 24)) {
1285 7d8406be pbrook
                cpu_physical_memory_read(addr, data, n);
1286 a917d384 pbrook
                DPRINTF("Load reg 0x%x size %d addr 0x%08x = %08x\n", reg, n,
1287 a917d384 pbrook
                        addr, *(int *)data);
1288 7d8406be pbrook
                for (i = 0; i < n; i++) {
1289 7d8406be pbrook
                    lsi_reg_writeb(s, reg + i, data[i]);
1290 7d8406be pbrook
                }
1291 7d8406be pbrook
            } else {
1292 7d8406be pbrook
                DPRINTF("Store reg 0x%x size %d addr 0x%08x\n", reg, n, addr);
1293 7d8406be pbrook
                for (i = 0; i < n; i++) {
1294 7d8406be pbrook
                    data[i] = lsi_reg_readb(s, reg + i);
1295 7d8406be pbrook
                }
1296 7d8406be pbrook
                cpu_physical_memory_write(addr, data, n);
1297 7d8406be pbrook
            }
1298 7d8406be pbrook
        }
1299 7d8406be pbrook
    }
1300 ee4d919f aliguori
    if (insn_processed > 10000 && !s->waiting) {
1301 64c68080 pbrook
        /* Some windows drivers make the device spin waiting for a memory
1302 64c68080 pbrook
           location to change.  If we have been executed a lot of code then
1303 64c68080 pbrook
           assume this is the case and force an unexpected device disconnect.
1304 64c68080 pbrook
           This is apparently sufficient to beat the drivers into submission.
1305 64c68080 pbrook
         */
1306 ee4d919f aliguori
        if (!(s->sien0 & LSI_SIST0_UDC))
1307 ee4d919f aliguori
            fprintf(stderr, "inf. loop with UDC masked\n");
1308 ee4d919f aliguori
        lsi_script_scsi_interrupt(s, LSI_SIST0_UDC, 0);
1309 ee4d919f aliguori
        lsi_disconnect(s);
1310 ee4d919f aliguori
    } else if (s->istat1 & LSI_ISTAT1_SRUN && !s->waiting) {
1311 7d8406be pbrook
        if (s->dcntl & LSI_DCNTL_SSM) {
1312 7d8406be pbrook
            lsi_script_dma_interrupt(s, LSI_DSTAT_SSI);
1313 7d8406be pbrook
        } else {
1314 7d8406be pbrook
            goto again;
1315 7d8406be pbrook
        }
1316 7d8406be pbrook
    }
1317 7d8406be pbrook
    DPRINTF("SCRIPTS execution stopped\n");
1318 7d8406be pbrook
}
1319 7d8406be pbrook
1320 7d8406be pbrook
static uint8_t lsi_reg_readb(LSIState *s, int offset)
1321 7d8406be pbrook
{
1322 7d8406be pbrook
    uint8_t tmp;
1323 75f76531 aurel32
#define CASE_GET_REG24(name, addr) \
1324 75f76531 aurel32
    case addr: return s->name & 0xff; \
1325 75f76531 aurel32
    case addr + 1: return (s->name >> 8) & 0xff; \
1326 75f76531 aurel32
    case addr + 2: return (s->name >> 16) & 0xff;
1327 75f76531 aurel32
1328 7d8406be pbrook
#define CASE_GET_REG32(name, addr) \
1329 7d8406be pbrook
    case addr: return s->name & 0xff; \
1330 7d8406be pbrook
    case addr + 1: return (s->name >> 8) & 0xff; \
1331 7d8406be pbrook
    case addr + 2: return (s->name >> 16) & 0xff; \
1332 7d8406be pbrook
    case addr + 3: return (s->name >> 24) & 0xff;
1333 7d8406be pbrook
1334 7d8406be pbrook
#ifdef DEBUG_LSI_REG
1335 7d8406be pbrook
    DPRINTF("Read reg %x\n", offset);
1336 7d8406be pbrook
#endif
1337 7d8406be pbrook
    switch (offset) {
1338 7d8406be pbrook
    case 0x00: /* SCNTL0 */
1339 7d8406be pbrook
        return s->scntl0;
1340 7d8406be pbrook
    case 0x01: /* SCNTL1 */
1341 7d8406be pbrook
        return s->scntl1;
1342 7d8406be pbrook
    case 0x02: /* SCNTL2 */
1343 7d8406be pbrook
        return s->scntl2;
1344 7d8406be pbrook
    case 0x03: /* SCNTL3 */
1345 7d8406be pbrook
        return s->scntl3;
1346 7d8406be pbrook
    case 0x04: /* SCID */
1347 7d8406be pbrook
        return s->scid;
1348 7d8406be pbrook
    case 0x05: /* SXFER */
1349 7d8406be pbrook
        return s->sxfer;
1350 7d8406be pbrook
    case 0x06: /* SDID */
1351 7d8406be pbrook
        return s->sdid;
1352 7d8406be pbrook
    case 0x07: /* GPREG0 */
1353 7d8406be pbrook
        return 0x7f;
1354 985a03b0 ths
    case 0x08: /* Revision ID */
1355 985a03b0 ths
        return 0x00;
1356 a917d384 pbrook
    case 0xa: /* SSID */
1357 a917d384 pbrook
        return s->ssid;
1358 7d8406be pbrook
    case 0xb: /* SBCL */
1359 7d8406be pbrook
        /* ??? This is not correct. However it's (hopefully) only
1360 7d8406be pbrook
           used for diagnostics, so should be ok.  */
1361 7d8406be pbrook
        return 0;
1362 7d8406be pbrook
    case 0xc: /* DSTAT */
1363 7d8406be pbrook
        tmp = s->dstat | 0x80;
1364 7d8406be pbrook
        if ((s->istat0 & LSI_ISTAT0_INTF) == 0)
1365 7d8406be pbrook
            s->dstat = 0;
1366 7d8406be pbrook
        lsi_update_irq(s);
1367 7d8406be pbrook
        return tmp;
1368 7d8406be pbrook
    case 0x0d: /* SSTAT0 */
1369 7d8406be pbrook
        return s->sstat0;
1370 7d8406be pbrook
    case 0x0e: /* SSTAT1 */
1371 7d8406be pbrook
        return s->sstat1;
1372 7d8406be pbrook
    case 0x0f: /* SSTAT2 */
1373 7d8406be pbrook
        return s->scntl1 & LSI_SCNTL1_CON ? 0 : 2;
1374 7d8406be pbrook
    CASE_GET_REG32(dsa, 0x10)
1375 7d8406be pbrook
    case 0x14: /* ISTAT0 */
1376 7d8406be pbrook
        return s->istat0;
1377 ecabe8cc aliguori
    case 0x15: /* ISTAT1 */
1378 ecabe8cc aliguori
        return s->istat1;
1379 7d8406be pbrook
    case 0x16: /* MBOX0 */
1380 7d8406be pbrook
        return s->mbox0;
1381 7d8406be pbrook
    case 0x17: /* MBOX1 */
1382 7d8406be pbrook
        return s->mbox1;
1383 7d8406be pbrook
    case 0x18: /* CTEST0 */
1384 7d8406be pbrook
        return 0xff;
1385 7d8406be pbrook
    case 0x19: /* CTEST1 */
1386 7d8406be pbrook
        return 0;
1387 7d8406be pbrook
    case 0x1a: /* CTEST2 */
1388 9167a69a balrog
        tmp = s->ctest2 | LSI_CTEST2_DACK | LSI_CTEST2_CM;
1389 7d8406be pbrook
        if (s->istat0 & LSI_ISTAT0_SIGP) {
1390 7d8406be pbrook
            s->istat0 &= ~LSI_ISTAT0_SIGP;
1391 7d8406be pbrook
            tmp |= LSI_CTEST2_SIGP;
1392 7d8406be pbrook
        }
1393 7d8406be pbrook
        return tmp;
1394 7d8406be pbrook
    case 0x1b: /* CTEST3 */
1395 7d8406be pbrook
        return s->ctest3;
1396 7d8406be pbrook
    CASE_GET_REG32(temp, 0x1c)
1397 7d8406be pbrook
    case 0x20: /* DFIFO */
1398 7d8406be pbrook
        return 0;
1399 7d8406be pbrook
    case 0x21: /* CTEST4 */
1400 7d8406be pbrook
        return s->ctest4;
1401 7d8406be pbrook
    case 0x22: /* CTEST5 */
1402 7d8406be pbrook
        return s->ctest5;
1403 985a03b0 ths
    case 0x23: /* CTEST6 */
1404 985a03b0 ths
         return 0;
1405 75f76531 aurel32
    CASE_GET_REG24(dbc, 0x24)
1406 7d8406be pbrook
    case 0x27: /* DCMD */
1407 7d8406be pbrook
        return s->dcmd;
1408 4b9a2d6d Sebastian Herbszt
    CASE_GET_REG32(dnad, 0x28)
1409 7d8406be pbrook
    CASE_GET_REG32(dsp, 0x2c)
1410 7d8406be pbrook
    CASE_GET_REG32(dsps, 0x30)
1411 7d8406be pbrook
    CASE_GET_REG32(scratch[0], 0x34)
1412 7d8406be pbrook
    case 0x38: /* DMODE */
1413 7d8406be pbrook
        return s->dmode;
1414 7d8406be pbrook
    case 0x39: /* DIEN */
1415 7d8406be pbrook
        return s->dien;
1416 bd8ee11a Sebastian Herbszt
    case 0x3a: /* SBR */
1417 bd8ee11a Sebastian Herbszt
        return s->sbr;
1418 7d8406be pbrook
    case 0x3b: /* DCNTL */
1419 7d8406be pbrook
        return s->dcntl;
1420 7d8406be pbrook
    case 0x40: /* SIEN0 */
1421 7d8406be pbrook
        return s->sien0;
1422 7d8406be pbrook
    case 0x41: /* SIEN1 */
1423 7d8406be pbrook
        return s->sien1;
1424 7d8406be pbrook
    case 0x42: /* SIST0 */
1425 7d8406be pbrook
        tmp = s->sist0;
1426 7d8406be pbrook
        s->sist0 = 0;
1427 7d8406be pbrook
        lsi_update_irq(s);
1428 7d8406be pbrook
        return tmp;
1429 7d8406be pbrook
    case 0x43: /* SIST1 */
1430 7d8406be pbrook
        tmp = s->sist1;
1431 7d8406be pbrook
        s->sist1 = 0;
1432 7d8406be pbrook
        lsi_update_irq(s);
1433 7d8406be pbrook
        return tmp;
1434 9167a69a balrog
    case 0x46: /* MACNTL */
1435 9167a69a balrog
        return 0x0f;
1436 7d8406be pbrook
    case 0x47: /* GPCNTL0 */
1437 7d8406be pbrook
        return 0x0f;
1438 7d8406be pbrook
    case 0x48: /* STIME0 */
1439 7d8406be pbrook
        return s->stime0;
1440 7d8406be pbrook
    case 0x4a: /* RESPID0 */
1441 7d8406be pbrook
        return s->respid0;
1442 7d8406be pbrook
    case 0x4b: /* RESPID1 */
1443 7d8406be pbrook
        return s->respid1;
1444 7d8406be pbrook
    case 0x4d: /* STEST1 */
1445 7d8406be pbrook
        return s->stest1;
1446 7d8406be pbrook
    case 0x4e: /* STEST2 */
1447 7d8406be pbrook
        return s->stest2;
1448 7d8406be pbrook
    case 0x4f: /* STEST3 */
1449 7d8406be pbrook
        return s->stest3;
1450 a917d384 pbrook
    case 0x50: /* SIDL */
1451 a917d384 pbrook
        /* This is needed by the linux drivers.  We currently only update it
1452 a917d384 pbrook
           during the MSG IN phase.  */
1453 a917d384 pbrook
        return s->sidl;
1454 7d8406be pbrook
    case 0x52: /* STEST4 */
1455 7d8406be pbrook
        return 0xe0;
1456 7d8406be pbrook
    case 0x56: /* CCNTL0 */
1457 7d8406be pbrook
        return s->ccntl0;
1458 7d8406be pbrook
    case 0x57: /* CCNTL1 */
1459 7d8406be pbrook
        return s->ccntl1;
1460 a917d384 pbrook
    case 0x58: /* SBDL */
1461 a917d384 pbrook
        /* Some drivers peek at the data bus during the MSG IN phase.  */
1462 a917d384 pbrook
        if ((s->sstat1 & PHASE_MASK) == PHASE_MI)
1463 a917d384 pbrook
            return s->msg[0];
1464 a917d384 pbrook
        return 0;
1465 a917d384 pbrook
    case 0x59: /* SBDL high */
1466 7d8406be pbrook
        return 0;
1467 7d8406be pbrook
    CASE_GET_REG32(mmrs, 0xa0)
1468 7d8406be pbrook
    CASE_GET_REG32(mmws, 0xa4)
1469 7d8406be pbrook
    CASE_GET_REG32(sfs, 0xa8)
1470 7d8406be pbrook
    CASE_GET_REG32(drs, 0xac)
1471 7d8406be pbrook
    CASE_GET_REG32(sbms, 0xb0)
1472 ab57d967 aliguori
    CASE_GET_REG32(dbms, 0xb4)
1473 7d8406be pbrook
    CASE_GET_REG32(dnad64, 0xb8)
1474 7d8406be pbrook
    CASE_GET_REG32(pmjad1, 0xc0)
1475 7d8406be pbrook
    CASE_GET_REG32(pmjad2, 0xc4)
1476 7d8406be pbrook
    CASE_GET_REG32(rbc, 0xc8)
1477 7d8406be pbrook
    CASE_GET_REG32(ua, 0xcc)
1478 7d8406be pbrook
    CASE_GET_REG32(ia, 0xd4)
1479 7d8406be pbrook
    CASE_GET_REG32(sbc, 0xd8)
1480 7d8406be pbrook
    CASE_GET_REG32(csbc, 0xdc)
1481 7d8406be pbrook
    }
1482 7d8406be pbrook
    if (offset >= 0x5c && offset < 0xa0) {
1483 7d8406be pbrook
        int n;
1484 7d8406be pbrook
        int shift;
1485 7d8406be pbrook
        n = (offset - 0x58) >> 2;
1486 7d8406be pbrook
        shift = (offset & 3) * 8;
1487 7d8406be pbrook
        return (s->scratch[n] >> shift) & 0xff;
1488 7d8406be pbrook
    }
1489 7d8406be pbrook
    BADF("readb 0x%x\n", offset);
1490 7d8406be pbrook
    exit(1);
1491 75f76531 aurel32
#undef CASE_GET_REG24
1492 7d8406be pbrook
#undef CASE_GET_REG32
1493 7d8406be pbrook
}
1494 7d8406be pbrook
1495 7d8406be pbrook
static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
1496 7d8406be pbrook
{
1497 49c47daa Sebastian Herbszt
#define CASE_SET_REG24(name, addr) \
1498 49c47daa Sebastian Herbszt
    case addr    : s->name &= 0xffffff00; s->name |= val;       break; \
1499 49c47daa Sebastian Herbszt
    case addr + 1: s->name &= 0xffff00ff; s->name |= val << 8;  break; \
1500 49c47daa Sebastian Herbszt
    case addr + 2: s->name &= 0xff00ffff; s->name |= val << 16; break;
1501 49c47daa Sebastian Herbszt
1502 7d8406be pbrook
#define CASE_SET_REG32(name, addr) \
1503 7d8406be pbrook
    case addr    : s->name &= 0xffffff00; s->name |= val;       break; \
1504 7d8406be pbrook
    case addr + 1: s->name &= 0xffff00ff; s->name |= val << 8;  break; \
1505 7d8406be pbrook
    case addr + 2: s->name &= 0xff00ffff; s->name |= val << 16; break; \
1506 7d8406be pbrook
    case addr + 3: s->name &= 0x00ffffff; s->name |= val << 24; break;
1507 7d8406be pbrook
1508 7d8406be pbrook
#ifdef DEBUG_LSI_REG
1509 7d8406be pbrook
    DPRINTF("Write reg %x = %02x\n", offset, val);
1510 7d8406be pbrook
#endif
1511 7d8406be pbrook
    switch (offset) {
1512 7d8406be pbrook
    case 0x00: /* SCNTL0 */
1513 7d8406be pbrook
        s->scntl0 = val;
1514 7d8406be pbrook
        if (val & LSI_SCNTL0_START) {
1515 7d8406be pbrook
            BADF("Start sequence not implemented\n");
1516 7d8406be pbrook
        }
1517 7d8406be pbrook
        break;
1518 7d8406be pbrook
    case 0x01: /* SCNTL1 */
1519 7d8406be pbrook
        s->scntl1 = val & ~LSI_SCNTL1_SST;
1520 7d8406be pbrook
        if (val & LSI_SCNTL1_IARB) {
1521 7d8406be pbrook
            BADF("Immediate Arbritration not implemented\n");
1522 7d8406be pbrook
        }
1523 7d8406be pbrook
        if (val & LSI_SCNTL1_RST) {
1524 7d8406be pbrook
            s->sstat0 |= LSI_SSTAT0_RST;
1525 7d8406be pbrook
            lsi_script_scsi_interrupt(s, LSI_SIST0_RST, 0);
1526 7d8406be pbrook
        } else {
1527 7d8406be pbrook
            s->sstat0 &= ~LSI_SSTAT0_RST;
1528 7d8406be pbrook
        }
1529 7d8406be pbrook
        break;
1530 7d8406be pbrook
    case 0x02: /* SCNTL2 */
1531 7d8406be pbrook
        val &= ~(LSI_SCNTL2_WSR | LSI_SCNTL2_WSS);
1532 3d834c78 ths
        s->scntl2 = val;
1533 7d8406be pbrook
        break;
1534 7d8406be pbrook
    case 0x03: /* SCNTL3 */
1535 7d8406be pbrook
        s->scntl3 = val;
1536 7d8406be pbrook
        break;
1537 7d8406be pbrook
    case 0x04: /* SCID */
1538 7d8406be pbrook
        s->scid = val;
1539 7d8406be pbrook
        break;
1540 7d8406be pbrook
    case 0x05: /* SXFER */
1541 7d8406be pbrook
        s->sxfer = val;
1542 7d8406be pbrook
        break;
1543 a917d384 pbrook
    case 0x06: /* SDID */
1544 a917d384 pbrook
        if ((val & 0xf) != (s->ssid & 0xf))
1545 a917d384 pbrook
            BADF("Destination ID does not match SSID\n");
1546 a917d384 pbrook
        s->sdid = val & 0xf;
1547 a917d384 pbrook
        break;
1548 7d8406be pbrook
    case 0x07: /* GPREG0 */
1549 7d8406be pbrook
        break;
1550 a917d384 pbrook
    case 0x08: /* SFBR */
1551 a917d384 pbrook
        /* The CPU is not allowed to write to this register.  However the
1552 a917d384 pbrook
           SCRIPTS register move instructions are.  */
1553 a917d384 pbrook
        s->sfbr = val;
1554 a917d384 pbrook
        break;
1555 9167a69a balrog
    case 0x0a: case 0x0b: 
1556 9167a69a balrog
        /* Openserver writes to these readonly registers on startup */
1557 9167a69a balrog
        return;    
1558 7d8406be pbrook
    case 0x0c: case 0x0d: case 0x0e: case 0x0f:
1559 7d8406be pbrook
        /* Linux writes to these readonly registers on startup.  */
1560 7d8406be pbrook
        return;
1561 7d8406be pbrook
    CASE_SET_REG32(dsa, 0x10)
1562 7d8406be pbrook
    case 0x14: /* ISTAT0 */
1563 7d8406be pbrook
        s->istat0 = (s->istat0 & 0x0f) | (val & 0xf0);
1564 7d8406be pbrook
        if (val & LSI_ISTAT0_ABRT) {
1565 7d8406be pbrook
            lsi_script_dma_interrupt(s, LSI_DSTAT_ABRT);
1566 7d8406be pbrook
        }
1567 7d8406be pbrook
        if (val & LSI_ISTAT0_INTF) {
1568 7d8406be pbrook
            s->istat0 &= ~LSI_ISTAT0_INTF;
1569 7d8406be pbrook
            lsi_update_irq(s);
1570 7d8406be pbrook
        }
1571 4d611c9a pbrook
        if (s->waiting == 1 && val & LSI_ISTAT0_SIGP) {
1572 7d8406be pbrook
            DPRINTF("Woken by SIGP\n");
1573 7d8406be pbrook
            s->waiting = 0;
1574 7d8406be pbrook
            s->dsp = s->dnad;
1575 7d8406be pbrook
            lsi_execute_script(s);
1576 7d8406be pbrook
        }
1577 7d8406be pbrook
        if (val & LSI_ISTAT0_SRST) {
1578 7d8406be pbrook
            lsi_soft_reset(s);
1579 7d8406be pbrook
        }
1580 92d88ecb ths
        break;
1581 7d8406be pbrook
    case 0x16: /* MBOX0 */
1582 7d8406be pbrook
        s->mbox0 = val;
1583 92d88ecb ths
        break;
1584 7d8406be pbrook
    case 0x17: /* MBOX1 */
1585 7d8406be pbrook
        s->mbox1 = val;
1586 92d88ecb ths
        break;
1587 9167a69a balrog
    case 0x1a: /* CTEST2 */
1588 9167a69a balrog
        s->ctest2 = val & LSI_CTEST2_PCICIE;
1589 9167a69a balrog
        break;
1590 7d8406be pbrook
    case 0x1b: /* CTEST3 */
1591 7d8406be pbrook
        s->ctest3 = val & 0x0f;
1592 7d8406be pbrook
        break;
1593 7d8406be pbrook
    CASE_SET_REG32(temp, 0x1c)
1594 7d8406be pbrook
    case 0x21: /* CTEST4 */
1595 7d8406be pbrook
        if (val & 7) {
1596 7d8406be pbrook
           BADF("Unimplemented CTEST4-FBL 0x%x\n", val);
1597 7d8406be pbrook
        }
1598 7d8406be pbrook
        s->ctest4 = val;
1599 7d8406be pbrook
        break;
1600 7d8406be pbrook
    case 0x22: /* CTEST5 */
1601 7d8406be pbrook
        if (val & (LSI_CTEST5_ADCK | LSI_CTEST5_BBCK)) {
1602 7d8406be pbrook
            BADF("CTEST5 DMA increment not implemented\n");
1603 7d8406be pbrook
        }
1604 7d8406be pbrook
        s->ctest5 = val;
1605 7d8406be pbrook
        break;
1606 49c47daa Sebastian Herbszt
    CASE_SET_REG24(dbc, 0x24)
1607 4b9a2d6d Sebastian Herbszt
    CASE_SET_REG32(dnad, 0x28)
1608 3d834c78 ths
    case 0x2c: /* DSP[0:7] */
1609 7d8406be pbrook
        s->dsp &= 0xffffff00;
1610 7d8406be pbrook
        s->dsp |= val;
1611 7d8406be pbrook
        break;
1612 3d834c78 ths
    case 0x2d: /* DSP[8:15] */
1613 7d8406be pbrook
        s->dsp &= 0xffff00ff;
1614 7d8406be pbrook
        s->dsp |= val << 8;
1615 7d8406be pbrook
        break;
1616 3d834c78 ths
    case 0x2e: /* DSP[16:23] */
1617 7d8406be pbrook
        s->dsp &= 0xff00ffff;
1618 7d8406be pbrook
        s->dsp |= val << 16;
1619 7d8406be pbrook
        break;
1620 3d834c78 ths
    case 0x2f: /* DSP[24:31] */
1621 7d8406be pbrook
        s->dsp &= 0x00ffffff;
1622 7d8406be pbrook
        s->dsp |= val << 24;
1623 7d8406be pbrook
        if ((s->dmode & LSI_DMODE_MAN) == 0
1624 7d8406be pbrook
            && (s->istat1 & LSI_ISTAT1_SRUN) == 0)
1625 7d8406be pbrook
            lsi_execute_script(s);
1626 7d8406be pbrook
        break;
1627 7d8406be pbrook
    CASE_SET_REG32(dsps, 0x30)
1628 7d8406be pbrook
    CASE_SET_REG32(scratch[0], 0x34)
1629 7d8406be pbrook
    case 0x38: /* DMODE */
1630 7d8406be pbrook
        if (val & (LSI_DMODE_SIOM | LSI_DMODE_DIOM)) {
1631 7d8406be pbrook
            BADF("IO mappings not implemented\n");
1632 7d8406be pbrook
        }
1633 7d8406be pbrook
        s->dmode = val;
1634 7d8406be pbrook
        break;
1635 7d8406be pbrook
    case 0x39: /* DIEN */
1636 7d8406be pbrook
        s->dien = val;
1637 7d8406be pbrook
        lsi_update_irq(s);
1638 7d8406be pbrook
        break;
1639 bd8ee11a Sebastian Herbszt
    case 0x3a: /* SBR */
1640 bd8ee11a Sebastian Herbszt
        s->sbr = val;
1641 bd8ee11a Sebastian Herbszt
        break;
1642 7d8406be pbrook
    case 0x3b: /* DCNTL */
1643 7d8406be pbrook
        s->dcntl = val & ~(LSI_DCNTL_PFF | LSI_DCNTL_STD);
1644 7d8406be pbrook
        if ((val & LSI_DCNTL_STD) && (s->istat1 & LSI_ISTAT1_SRUN) == 0)
1645 7d8406be pbrook
            lsi_execute_script(s);
1646 7d8406be pbrook
        break;
1647 7d8406be pbrook
    case 0x40: /* SIEN0 */
1648 7d8406be pbrook
        s->sien0 = val;
1649 7d8406be pbrook
        lsi_update_irq(s);
1650 7d8406be pbrook
        break;
1651 7d8406be pbrook
    case 0x41: /* SIEN1 */
1652 7d8406be pbrook
        s->sien1 = val;
1653 7d8406be pbrook
        lsi_update_irq(s);
1654 7d8406be pbrook
        break;
1655 7d8406be pbrook
    case 0x47: /* GPCNTL0 */
1656 7d8406be pbrook
        break;
1657 7d8406be pbrook
    case 0x48: /* STIME0 */
1658 7d8406be pbrook
        s->stime0 = val;
1659 7d8406be pbrook
        break;
1660 7d8406be pbrook
    case 0x49: /* STIME1 */
1661 7d8406be pbrook
        if (val & 0xf) {
1662 7d8406be pbrook
            DPRINTF("General purpose timer not implemented\n");
1663 7d8406be pbrook
            /* ??? Raising the interrupt immediately seems to be sufficient
1664 7d8406be pbrook
               to keep the FreeBSD driver happy.  */
1665 7d8406be pbrook
            lsi_script_scsi_interrupt(s, 0, LSI_SIST1_GEN);
1666 7d8406be pbrook
        }
1667 7d8406be pbrook
        break;
1668 7d8406be pbrook
    case 0x4a: /* RESPID0 */
1669 7d8406be pbrook
        s->respid0 = val;
1670 7d8406be pbrook
        break;
1671 7d8406be pbrook
    case 0x4b: /* RESPID1 */
1672 7d8406be pbrook
        s->respid1 = val;
1673 7d8406be pbrook
        break;
1674 7d8406be pbrook
    case 0x4d: /* STEST1 */
1675 7d8406be pbrook
        s->stest1 = val;
1676 7d8406be pbrook
        break;
1677 7d8406be pbrook
    case 0x4e: /* STEST2 */
1678 7d8406be pbrook
        if (val & 1) {
1679 7d8406be pbrook
            BADF("Low level mode not implemented\n");
1680 7d8406be pbrook
        }
1681 7d8406be pbrook
        s->stest2 = val;
1682 7d8406be pbrook
        break;
1683 7d8406be pbrook
    case 0x4f: /* STEST3 */
1684 7d8406be pbrook
        if (val & 0x41) {
1685 7d8406be pbrook
            BADF("SCSI FIFO test mode not implemented\n");
1686 7d8406be pbrook
        }
1687 7d8406be pbrook
        s->stest3 = val;
1688 7d8406be pbrook
        break;
1689 7d8406be pbrook
    case 0x56: /* CCNTL0 */
1690 7d8406be pbrook
        s->ccntl0 = val;
1691 7d8406be pbrook
        break;
1692 7d8406be pbrook
    case 0x57: /* CCNTL1 */
1693 7d8406be pbrook
        s->ccntl1 = val;
1694 7d8406be pbrook
        break;
1695 7d8406be pbrook
    CASE_SET_REG32(mmrs, 0xa0)
1696 7d8406be pbrook
    CASE_SET_REG32(mmws, 0xa4)
1697 7d8406be pbrook
    CASE_SET_REG32(sfs, 0xa8)
1698 7d8406be pbrook
    CASE_SET_REG32(drs, 0xac)
1699 7d8406be pbrook
    CASE_SET_REG32(sbms, 0xb0)
1700 ab57d967 aliguori
    CASE_SET_REG32(dbms, 0xb4)
1701 7d8406be pbrook
    CASE_SET_REG32(dnad64, 0xb8)
1702 7d8406be pbrook
    CASE_SET_REG32(pmjad1, 0xc0)
1703 7d8406be pbrook
    CASE_SET_REG32(pmjad2, 0xc4)
1704 7d8406be pbrook
    CASE_SET_REG32(rbc, 0xc8)
1705 7d8406be pbrook
    CASE_SET_REG32(ua, 0xcc)
1706 7d8406be pbrook
    CASE_SET_REG32(ia, 0xd4)
1707 7d8406be pbrook
    CASE_SET_REG32(sbc, 0xd8)
1708 7d8406be pbrook
    CASE_SET_REG32(csbc, 0xdc)
1709 7d8406be pbrook
    default:
1710 7d8406be pbrook
        if (offset >= 0x5c && offset < 0xa0) {
1711 7d8406be pbrook
            int n;
1712 7d8406be pbrook
            int shift;
1713 7d8406be pbrook
            n = (offset - 0x58) >> 2;
1714 7d8406be pbrook
            shift = (offset & 3) * 8;
1715 7d8406be pbrook
            s->scratch[n] &= ~(0xff << shift);
1716 7d8406be pbrook
            s->scratch[n] |= (val & 0xff) << shift;
1717 7d8406be pbrook
        } else {
1718 7d8406be pbrook
            BADF("Unhandled writeb 0x%x = 0x%x\n", offset, val);
1719 7d8406be pbrook
        }
1720 7d8406be pbrook
    }
1721 49c47daa Sebastian Herbszt
#undef CASE_SET_REG24
1722 7d8406be pbrook
#undef CASE_SET_REG32
1723 7d8406be pbrook
}
1724 7d8406be pbrook
1725 7d8406be pbrook
static void lsi_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
1726 7d8406be pbrook
{
1727 7d8406be pbrook
    LSIState *s = (LSIState *)opaque;
1728 7d8406be pbrook
1729 7d8406be pbrook
    lsi_reg_writeb(s, addr & 0xff, val);
1730 7d8406be pbrook
}
1731 7d8406be pbrook
1732 7d8406be pbrook
static void lsi_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
1733 7d8406be pbrook
{
1734 7d8406be pbrook
    LSIState *s = (LSIState *)opaque;
1735 7d8406be pbrook
1736 7d8406be pbrook
    addr &= 0xff;
1737 7d8406be pbrook
    lsi_reg_writeb(s, addr, val & 0xff);
1738 7d8406be pbrook
    lsi_reg_writeb(s, addr + 1, (val >> 8) & 0xff);
1739 7d8406be pbrook
}
1740 7d8406be pbrook
1741 7d8406be pbrook
static void lsi_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
1742 7d8406be pbrook
{
1743 7d8406be pbrook
    LSIState *s = (LSIState *)opaque;
1744 7d8406be pbrook
1745 7d8406be pbrook
    addr &= 0xff;
1746 7d8406be pbrook
    lsi_reg_writeb(s, addr, val & 0xff);
1747 7d8406be pbrook
    lsi_reg_writeb(s, addr + 1, (val >> 8) & 0xff);
1748 7d8406be pbrook
    lsi_reg_writeb(s, addr + 2, (val >> 16) & 0xff);
1749 7d8406be pbrook
    lsi_reg_writeb(s, addr + 3, (val >> 24) & 0xff);
1750 7d8406be pbrook
}
1751 7d8406be pbrook
1752 7d8406be pbrook
static uint32_t lsi_mmio_readb(void *opaque, target_phys_addr_t addr)
1753 7d8406be pbrook
{
1754 7d8406be pbrook
    LSIState *s = (LSIState *)opaque;
1755 7d8406be pbrook
1756 7d8406be pbrook
    return lsi_reg_readb(s, addr & 0xff);
1757 7d8406be pbrook
}
1758 7d8406be pbrook
1759 7d8406be pbrook
static uint32_t lsi_mmio_readw(void *opaque, target_phys_addr_t addr)
1760 7d8406be pbrook
{
1761 7d8406be pbrook
    LSIState *s = (LSIState *)opaque;
1762 7d8406be pbrook
    uint32_t val;
1763 7d8406be pbrook
1764 7d8406be pbrook
    addr &= 0xff;
1765 7d8406be pbrook
    val = lsi_reg_readb(s, addr);
1766 7d8406be pbrook
    val |= lsi_reg_readb(s, addr + 1) << 8;
1767 7d8406be pbrook
    return val;
1768 7d8406be pbrook
}
1769 7d8406be pbrook
1770 7d8406be pbrook
static uint32_t lsi_mmio_readl(void *opaque, target_phys_addr_t addr)
1771 7d8406be pbrook
{
1772 7d8406be pbrook
    LSIState *s = (LSIState *)opaque;
1773 7d8406be pbrook
    uint32_t val;
1774 7d8406be pbrook
    addr &= 0xff;
1775 7d8406be pbrook
    val = lsi_reg_readb(s, addr);
1776 7d8406be pbrook
    val |= lsi_reg_readb(s, addr + 1) << 8;
1777 7d8406be pbrook
    val |= lsi_reg_readb(s, addr + 2) << 16;
1778 7d8406be pbrook
    val |= lsi_reg_readb(s, addr + 3) << 24;
1779 7d8406be pbrook
    return val;
1780 7d8406be pbrook
}
1781 7d8406be pbrook
1782 7d8406be pbrook
static CPUReadMemoryFunc *lsi_mmio_readfn[3] = {
1783 7d8406be pbrook
    lsi_mmio_readb,
1784 7d8406be pbrook
    lsi_mmio_readw,
1785 7d8406be pbrook
    lsi_mmio_readl,
1786 7d8406be pbrook
};
1787 7d8406be pbrook
1788 7d8406be pbrook
static CPUWriteMemoryFunc *lsi_mmio_writefn[3] = {
1789 7d8406be pbrook
    lsi_mmio_writeb,
1790 7d8406be pbrook
    lsi_mmio_writew,
1791 7d8406be pbrook
    lsi_mmio_writel,
1792 7d8406be pbrook
};
1793 7d8406be pbrook
1794 7d8406be pbrook
static void lsi_ram_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
1795 7d8406be pbrook
{
1796 7d8406be pbrook
    LSIState *s = (LSIState *)opaque;
1797 7d8406be pbrook
    uint32_t newval;
1798 7d8406be pbrook
    int shift;
1799 7d8406be pbrook
1800 7d8406be pbrook
    addr &= 0x1fff;
1801 7d8406be pbrook
    newval = s->script_ram[addr >> 2];
1802 7d8406be pbrook
    shift = (addr & 3) * 8;
1803 7d8406be pbrook
    newval &= ~(0xff << shift);
1804 7d8406be pbrook
    newval |= val << shift;
1805 7d8406be pbrook
    s->script_ram[addr >> 2] = newval;
1806 7d8406be pbrook
}
1807 7d8406be pbrook
1808 7d8406be pbrook
static void lsi_ram_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
1809 7d8406be pbrook
{
1810 7d8406be pbrook
    LSIState *s = (LSIState *)opaque;
1811 7d8406be pbrook
    uint32_t newval;
1812 7d8406be pbrook
1813 7d8406be pbrook
    addr &= 0x1fff;
1814 7d8406be pbrook
    newval = s->script_ram[addr >> 2];
1815 7d8406be pbrook
    if (addr & 2) {
1816 7d8406be pbrook
        newval = (newval & 0xffff) | (val << 16);
1817 7d8406be pbrook
    } else {
1818 7d8406be pbrook
        newval = (newval & 0xffff0000) | val;
1819 7d8406be pbrook
    }
1820 7d8406be pbrook
    s->script_ram[addr >> 2] = newval;
1821 7d8406be pbrook
}
1822 7d8406be pbrook
1823 7d8406be pbrook
1824 7d8406be pbrook
static void lsi_ram_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
1825 7d8406be pbrook
{
1826 7d8406be pbrook
    LSIState *s = (LSIState *)opaque;
1827 7d8406be pbrook
1828 7d8406be pbrook
    addr &= 0x1fff;
1829 7d8406be pbrook
    s->script_ram[addr >> 2] = val;
1830 7d8406be pbrook
}
1831 7d8406be pbrook
1832 7d8406be pbrook
static uint32_t lsi_ram_readb(void *opaque, target_phys_addr_t addr)
1833 7d8406be pbrook
{
1834 7d8406be pbrook
    LSIState *s = (LSIState *)opaque;
1835 7d8406be pbrook
    uint32_t val;
1836 7d8406be pbrook
1837 7d8406be pbrook
    addr &= 0x1fff;
1838 7d8406be pbrook
    val = s->script_ram[addr >> 2];
1839 7d8406be pbrook
    val >>= (addr & 3) * 8;
1840 7d8406be pbrook
    return val & 0xff;
1841 7d8406be pbrook
}
1842 7d8406be pbrook
1843 7d8406be pbrook
static uint32_t lsi_ram_readw(void *opaque, target_phys_addr_t addr)
1844 7d8406be pbrook
{
1845 7d8406be pbrook
    LSIState *s = (LSIState *)opaque;
1846 7d8406be pbrook
    uint32_t val;
1847 7d8406be pbrook
1848 7d8406be pbrook
    addr &= 0x1fff;
1849 7d8406be pbrook
    val = s->script_ram[addr >> 2];
1850 7d8406be pbrook
    if (addr & 2)
1851 7d8406be pbrook
        val >>= 16;
1852 7d8406be pbrook
    return le16_to_cpu(val);
1853 7d8406be pbrook
}
1854 7d8406be pbrook
1855 7d8406be pbrook
static uint32_t lsi_ram_readl(void *opaque, target_phys_addr_t addr)
1856 7d8406be pbrook
{
1857 7d8406be pbrook
    LSIState *s = (LSIState *)opaque;
1858 7d8406be pbrook
1859 7d8406be pbrook
    addr &= 0x1fff;
1860 7d8406be pbrook
    return le32_to_cpu(s->script_ram[addr >> 2]);
1861 7d8406be pbrook
}
1862 7d8406be pbrook
1863 7d8406be pbrook
static CPUReadMemoryFunc *lsi_ram_readfn[3] = {
1864 7d8406be pbrook
    lsi_ram_readb,
1865 7d8406be pbrook
    lsi_ram_readw,
1866 7d8406be pbrook
    lsi_ram_readl,
1867 7d8406be pbrook
};
1868 7d8406be pbrook
1869 7d8406be pbrook
static CPUWriteMemoryFunc *lsi_ram_writefn[3] = {
1870 7d8406be pbrook
    lsi_ram_writeb,
1871 7d8406be pbrook
    lsi_ram_writew,
1872 7d8406be pbrook
    lsi_ram_writel,
1873 7d8406be pbrook
};
1874 7d8406be pbrook
1875 7d8406be pbrook
static uint32_t lsi_io_readb(void *opaque, uint32_t addr)
1876 7d8406be pbrook
{
1877 7d8406be pbrook
    LSIState *s = (LSIState *)opaque;
1878 7d8406be pbrook
    return lsi_reg_readb(s, addr & 0xff);
1879 7d8406be pbrook
}
1880 7d8406be pbrook
1881 7d8406be pbrook
static uint32_t lsi_io_readw(void *opaque, uint32_t addr)
1882 7d8406be pbrook
{
1883 7d8406be pbrook
    LSIState *s = (LSIState *)opaque;
1884 7d8406be pbrook
    uint32_t val;
1885 7d8406be pbrook
    addr &= 0xff;
1886 7d8406be pbrook
    val = lsi_reg_readb(s, addr);
1887 7d8406be pbrook
    val |= lsi_reg_readb(s, addr + 1) << 8;
1888 7d8406be pbrook
    return val;
1889 7d8406be pbrook
}
1890 7d8406be pbrook
1891 7d8406be pbrook
static uint32_t lsi_io_readl(void *opaque, uint32_t addr)
1892 7d8406be pbrook
{
1893 7d8406be pbrook
    LSIState *s = (LSIState *)opaque;
1894 7d8406be pbrook
    uint32_t val;
1895 7d8406be pbrook
    addr &= 0xff;
1896 7d8406be pbrook
    val = lsi_reg_readb(s, addr);
1897 7d8406be pbrook
    val |= lsi_reg_readb(s, addr + 1) << 8;
1898 7d8406be pbrook
    val |= lsi_reg_readb(s, addr + 2) << 16;
1899 7d8406be pbrook
    val |= lsi_reg_readb(s, addr + 3) << 24;
1900 7d8406be pbrook
    return val;
1901 7d8406be pbrook
}
1902 7d8406be pbrook
1903 7d8406be pbrook
static void lsi_io_writeb(void *opaque, uint32_t addr, uint32_t val)
1904 7d8406be pbrook
{
1905 7d8406be pbrook
    LSIState *s = (LSIState *)opaque;
1906 7d8406be pbrook
    lsi_reg_writeb(s, addr & 0xff, val);
1907 7d8406be pbrook
}
1908 7d8406be pbrook
1909 7d8406be pbrook
static void lsi_io_writew(void *opaque, uint32_t addr, uint32_t val)
1910 7d8406be pbrook
{
1911 7d8406be pbrook
    LSIState *s = (LSIState *)opaque;
1912 7d8406be pbrook
    addr &= 0xff;
1913 7d8406be pbrook
    lsi_reg_writeb(s, addr, val & 0xff);
1914 7d8406be pbrook
    lsi_reg_writeb(s, addr + 1, (val >> 8) & 0xff);
1915 7d8406be pbrook
}
1916 7d8406be pbrook
1917 7d8406be pbrook
static void lsi_io_writel(void *opaque, uint32_t addr, uint32_t val)
1918 7d8406be pbrook
{
1919 7d8406be pbrook
    LSIState *s = (LSIState *)opaque;
1920 7d8406be pbrook
    addr &= 0xff;
1921 7d8406be pbrook
    lsi_reg_writeb(s, addr, val & 0xff);
1922 7d8406be pbrook
    lsi_reg_writeb(s, addr + 1, (val >> 8) & 0xff);
1923 7d8406be pbrook
    lsi_reg_writeb(s, addr + 2, (val >> 16) & 0xff);
1924 dcfb9014 ths
    lsi_reg_writeb(s, addr + 3, (val >> 24) & 0xff);
1925 7d8406be pbrook
}
1926 7d8406be pbrook
1927 5fafdf24 ths
static void lsi_io_mapfunc(PCIDevice *pci_dev, int region_num,
1928 7d8406be pbrook
                           uint32_t addr, uint32_t size, int type)
1929 7d8406be pbrook
{
1930 7d8406be pbrook
    LSIState *s = (LSIState *)pci_dev;
1931 7d8406be pbrook
1932 7d8406be pbrook
    DPRINTF("Mapping IO at %08x\n", addr);
1933 7d8406be pbrook
1934 7d8406be pbrook
    register_ioport_write(addr, 256, 1, lsi_io_writeb, s);
1935 7d8406be pbrook
    register_ioport_read(addr, 256, 1, lsi_io_readb, s);
1936 7d8406be pbrook
    register_ioport_write(addr, 256, 2, lsi_io_writew, s);
1937 7d8406be pbrook
    register_ioport_read(addr, 256, 2, lsi_io_readw, s);
1938 7d8406be pbrook
    register_ioport_write(addr, 256, 4, lsi_io_writel, s);
1939 7d8406be pbrook
    register_ioport_read(addr, 256, 4, lsi_io_readl, s);
1940 7d8406be pbrook
}
1941 7d8406be pbrook
1942 5fafdf24 ths
static void lsi_ram_mapfunc(PCIDevice *pci_dev, int region_num,
1943 7d8406be pbrook
                            uint32_t addr, uint32_t size, int type)
1944 7d8406be pbrook
{
1945 7d8406be pbrook
    LSIState *s = (LSIState *)pci_dev;
1946 7d8406be pbrook
1947 7d8406be pbrook
    DPRINTF("Mapping ram at %08x\n", addr);
1948 7d8406be pbrook
    s->script_ram_base = addr;
1949 7d8406be pbrook
    cpu_register_physical_memory(addr + 0, 0x2000, s->ram_io_addr);
1950 7d8406be pbrook
}
1951 7d8406be pbrook
1952 5fafdf24 ths
static void lsi_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
1953 7d8406be pbrook
                             uint32_t addr, uint32_t size, int type)
1954 7d8406be pbrook
{
1955 7d8406be pbrook
    LSIState *s = (LSIState *)pci_dev;
1956 7d8406be pbrook
1957 7d8406be pbrook
    DPRINTF("Mapping registers at %08x\n", addr);
1958 7d8406be pbrook
    cpu_register_physical_memory(addr + 0, 0x400, s->mmio_io_addr);
1959 7d8406be pbrook
}
1960 7d8406be pbrook
1961 9be5dafe Paul Brook
void lsi_scsi_attach(DeviceState *host, BlockDriverState *bd, int id)
1962 7d8406be pbrook
{
1963 9be5dafe Paul Brook
    LSIState *s = (LSIState *)host;
1964 7d8406be pbrook
1965 7d8406be pbrook
    if (id < 0) {
1966 7d8406be pbrook
        for (id = 0; id < LSI_MAX_DEVS; id++) {
1967 7d8406be pbrook
            if (s->scsi_dev[id] == NULL)
1968 7d8406be pbrook
                break;
1969 7d8406be pbrook
        }
1970 7d8406be pbrook
    }
1971 7d8406be pbrook
    if (id >= LSI_MAX_DEVS) {
1972 7d8406be pbrook
        BADF("Bad Device ID %d\n", id);
1973 7d8406be pbrook
        return;
1974 7d8406be pbrook
    }
1975 7d8406be pbrook
    if (s->scsi_dev[id]) {
1976 7d8406be pbrook
        DPRINTF("Destroying device %d\n", id);
1977 8ccc2ace ths
        s->scsi_dev[id]->destroy(s->scsi_dev[id]);
1978 7d8406be pbrook
    }
1979 7d8406be pbrook
    DPRINTF("Attaching block device %d\n", id);
1980 985a03b0 ths
    s->scsi_dev[id] = scsi_generic_init(bd, 1, lsi_command_complete, s);
1981 985a03b0 ths
    if (s->scsi_dev[id] == NULL)
1982 985a03b0 ths
        s->scsi_dev[id] = scsi_disk_init(bd, 1, lsi_command_complete, s);
1983 b0a7b120 aliguori
    bd->private = &s->pci_dev;
1984 7d8406be pbrook
}
1985 7d8406be pbrook
1986 777aec7a Nolan
static void lsi_scsi_save(QEMUFile *f, void *opaque)
1987 777aec7a Nolan
{
1988 777aec7a Nolan
    LSIState *s = opaque;
1989 777aec7a Nolan
1990 777aec7a Nolan
    assert(s->dma_buf == NULL);
1991 777aec7a Nolan
    assert(s->current_dma_len == 0);
1992 777aec7a Nolan
    assert(s->active_commands == 0);
1993 777aec7a Nolan
1994 777aec7a Nolan
    pci_device_save(&s->pci_dev, f);
1995 777aec7a Nolan
1996 777aec7a Nolan
    qemu_put_sbe32s(f, &s->carry);
1997 777aec7a Nolan
    qemu_put_sbe32s(f, &s->sense);
1998 777aec7a Nolan
    qemu_put_sbe32s(f, &s->msg_action);
1999 777aec7a Nolan
    qemu_put_sbe32s(f, &s->msg_len);
2000 777aec7a Nolan
    qemu_put_buffer(f, s->msg, sizeof (s->msg));
2001 777aec7a Nolan
    qemu_put_sbe32s(f, &s->waiting);
2002 777aec7a Nolan
2003 777aec7a Nolan
    qemu_put_be32s(f, &s->dsa);
2004 777aec7a Nolan
    qemu_put_be32s(f, &s->temp);
2005 777aec7a Nolan
    qemu_put_be32s(f, &s->dnad);
2006 777aec7a Nolan
    qemu_put_be32s(f, &s->dbc);
2007 777aec7a Nolan
    qemu_put_8s(f, &s->istat0);
2008 777aec7a Nolan
    qemu_put_8s(f, &s->istat1);
2009 777aec7a Nolan
    qemu_put_8s(f, &s->dcmd);
2010 777aec7a Nolan
    qemu_put_8s(f, &s->dstat);
2011 777aec7a Nolan
    qemu_put_8s(f, &s->dien);
2012 777aec7a Nolan
    qemu_put_8s(f, &s->sist0);
2013 777aec7a Nolan
    qemu_put_8s(f, &s->sist1);
2014 777aec7a Nolan
    qemu_put_8s(f, &s->sien0);
2015 777aec7a Nolan
    qemu_put_8s(f, &s->sien1);
2016 777aec7a Nolan
    qemu_put_8s(f, &s->mbox0);
2017 777aec7a Nolan
    qemu_put_8s(f, &s->mbox1);
2018 777aec7a Nolan
    qemu_put_8s(f, &s->dfifo);
2019 777aec7a Nolan
    qemu_put_8s(f, &s->ctest2);
2020 777aec7a Nolan
    qemu_put_8s(f, &s->ctest3);
2021 777aec7a Nolan
    qemu_put_8s(f, &s->ctest4);
2022 777aec7a Nolan
    qemu_put_8s(f, &s->ctest5);
2023 777aec7a Nolan
    qemu_put_8s(f, &s->ccntl0);
2024 777aec7a Nolan
    qemu_put_8s(f, &s->ccntl1);
2025 777aec7a Nolan
    qemu_put_be32s(f, &s->dsp);
2026 777aec7a Nolan
    qemu_put_be32s(f, &s->dsps);
2027 777aec7a Nolan
    qemu_put_8s(f, &s->dmode);
2028 777aec7a Nolan
    qemu_put_8s(f, &s->dcntl);
2029 777aec7a Nolan
    qemu_put_8s(f, &s->scntl0);
2030 777aec7a Nolan
    qemu_put_8s(f, &s->scntl1);
2031 777aec7a Nolan
    qemu_put_8s(f, &s->scntl2);
2032 777aec7a Nolan
    qemu_put_8s(f, &s->scntl3);
2033 777aec7a Nolan
    qemu_put_8s(f, &s->sstat0);
2034 777aec7a Nolan
    qemu_put_8s(f, &s->sstat1);
2035 777aec7a Nolan
    qemu_put_8s(f, &s->scid);
2036 777aec7a Nolan
    qemu_put_8s(f, &s->sxfer);
2037 777aec7a Nolan
    qemu_put_8s(f, &s->socl);
2038 777aec7a Nolan
    qemu_put_8s(f, &s->sdid);
2039 777aec7a Nolan
    qemu_put_8s(f, &s->ssid);
2040 777aec7a Nolan
    qemu_put_8s(f, &s->sfbr);
2041 777aec7a Nolan
    qemu_put_8s(f, &s->stest1);
2042 777aec7a Nolan
    qemu_put_8s(f, &s->stest2);
2043 777aec7a Nolan
    qemu_put_8s(f, &s->stest3);
2044 777aec7a Nolan
    qemu_put_8s(f, &s->sidl);
2045 777aec7a Nolan
    qemu_put_8s(f, &s->stime0);
2046 777aec7a Nolan
    qemu_put_8s(f, &s->respid0);
2047 777aec7a Nolan
    qemu_put_8s(f, &s->respid1);
2048 777aec7a Nolan
    qemu_put_be32s(f, &s->mmrs);
2049 777aec7a Nolan
    qemu_put_be32s(f, &s->mmws);
2050 777aec7a Nolan
    qemu_put_be32s(f, &s->sfs);
2051 777aec7a Nolan
    qemu_put_be32s(f, &s->drs);
2052 777aec7a Nolan
    qemu_put_be32s(f, &s->sbms);
2053 777aec7a Nolan
    qemu_put_be32s(f, &s->dbms);
2054 777aec7a Nolan
    qemu_put_be32s(f, &s->dnad64);
2055 777aec7a Nolan
    qemu_put_be32s(f, &s->pmjad1);
2056 777aec7a Nolan
    qemu_put_be32s(f, &s->pmjad2);
2057 777aec7a Nolan
    qemu_put_be32s(f, &s->rbc);
2058 777aec7a Nolan
    qemu_put_be32s(f, &s->ua);
2059 777aec7a Nolan
    qemu_put_be32s(f, &s->ia);
2060 777aec7a Nolan
    qemu_put_be32s(f, &s->sbc);
2061 777aec7a Nolan
    qemu_put_be32s(f, &s->csbc);
2062 777aec7a Nolan
    qemu_put_buffer(f, (uint8_t *)s->scratch, sizeof (s->scratch));
2063 777aec7a Nolan
    qemu_put_8s(f, &s->sbr);
2064 777aec7a Nolan
2065 777aec7a Nolan
    qemu_put_buffer(f, (uint8_t *)s->script_ram, sizeof (s->script_ram));
2066 777aec7a Nolan
}
2067 777aec7a Nolan
2068 777aec7a Nolan
static int lsi_scsi_load(QEMUFile *f, void *opaque, int version_id)
2069 777aec7a Nolan
{
2070 777aec7a Nolan
    LSIState *s = opaque;
2071 777aec7a Nolan
    int ret;
2072 777aec7a Nolan
2073 777aec7a Nolan
    if (version_id > 0) {
2074 777aec7a Nolan
        return -EINVAL;
2075 777aec7a Nolan
    }
2076 777aec7a Nolan
2077 777aec7a Nolan
    if ((ret = pci_device_load(&s->pci_dev, f)) < 0)
2078 777aec7a Nolan
        return ret;
2079 777aec7a Nolan
2080 777aec7a Nolan
    qemu_get_sbe32s(f, &s->carry);
2081 777aec7a Nolan
    qemu_get_sbe32s(f, &s->sense);
2082 777aec7a Nolan
    qemu_get_sbe32s(f, &s->msg_action);
2083 777aec7a Nolan
    qemu_get_sbe32s(f, &s->msg_len);
2084 777aec7a Nolan
    qemu_get_buffer(f, s->msg, sizeof (s->msg));
2085 777aec7a Nolan
    qemu_get_sbe32s(f, &s->waiting);
2086 777aec7a Nolan
2087 777aec7a Nolan
    qemu_get_be32s(f, &s->dsa);
2088 777aec7a Nolan
    qemu_get_be32s(f, &s->temp);
2089 777aec7a Nolan
    qemu_get_be32s(f, &s->dnad);
2090 777aec7a Nolan
    qemu_get_be32s(f, &s->dbc);
2091 777aec7a Nolan
    qemu_get_8s(f, &s->istat0);
2092 777aec7a Nolan
    qemu_get_8s(f, &s->istat1);
2093 777aec7a Nolan
    qemu_get_8s(f, &s->dcmd);
2094 777aec7a Nolan
    qemu_get_8s(f, &s->dstat);
2095 777aec7a Nolan
    qemu_get_8s(f, &s->dien);
2096 777aec7a Nolan
    qemu_get_8s(f, &s->sist0);
2097 777aec7a Nolan
    qemu_get_8s(f, &s->sist1);
2098 777aec7a Nolan
    qemu_get_8s(f, &s->sien0);
2099 777aec7a Nolan
    qemu_get_8s(f, &s->sien1);
2100 777aec7a Nolan
    qemu_get_8s(f, &s->mbox0);
2101 777aec7a Nolan
    qemu_get_8s(f, &s->mbox1);
2102 777aec7a Nolan
    qemu_get_8s(f, &s->dfifo);
2103 777aec7a Nolan
    qemu_get_8s(f, &s->ctest2);
2104 777aec7a Nolan
    qemu_get_8s(f, &s->ctest3);
2105 777aec7a Nolan
    qemu_get_8s(f, &s->ctest4);
2106 777aec7a Nolan
    qemu_get_8s(f, &s->ctest5);
2107 777aec7a Nolan
    qemu_get_8s(f, &s->ccntl0);
2108 777aec7a Nolan
    qemu_get_8s(f, &s->ccntl1);
2109 777aec7a Nolan
    qemu_get_be32s(f, &s->dsp);
2110 777aec7a Nolan
    qemu_get_be32s(f, &s->dsps);
2111 777aec7a Nolan
    qemu_get_8s(f, &s->dmode);
2112 777aec7a Nolan
    qemu_get_8s(f, &s->dcntl);
2113 777aec7a Nolan
    qemu_get_8s(f, &s->scntl0);
2114 777aec7a Nolan
    qemu_get_8s(f, &s->scntl1);
2115 777aec7a Nolan
    qemu_get_8s(f, &s->scntl2);
2116 777aec7a Nolan
    qemu_get_8s(f, &s->scntl3);
2117 777aec7a Nolan
    qemu_get_8s(f, &s->sstat0);
2118 777aec7a Nolan
    qemu_get_8s(f, &s->sstat1);
2119 777aec7a Nolan
    qemu_get_8s(f, &s->scid);
2120 777aec7a Nolan
    qemu_get_8s(f, &s->sxfer);
2121 777aec7a Nolan
    qemu_get_8s(f, &s->socl);
2122 777aec7a Nolan
    qemu_get_8s(f, &s->sdid);
2123 777aec7a Nolan
    qemu_get_8s(f, &s->ssid);
2124 777aec7a Nolan
    qemu_get_8s(f, &s->sfbr);
2125 777aec7a Nolan
    qemu_get_8s(f, &s->stest1);
2126 777aec7a Nolan
    qemu_get_8s(f, &s->stest2);
2127 777aec7a Nolan
    qemu_get_8s(f, &s->stest3);
2128 777aec7a Nolan
    qemu_get_8s(f, &s->sidl);
2129 777aec7a Nolan
    qemu_get_8s(f, &s->stime0);
2130 777aec7a Nolan
    qemu_get_8s(f, &s->respid0);
2131 777aec7a Nolan
    qemu_get_8s(f, &s->respid1);
2132 777aec7a Nolan
    qemu_get_be32s(f, &s->mmrs);
2133 777aec7a Nolan
    qemu_get_be32s(f, &s->mmws);
2134 777aec7a Nolan
    qemu_get_be32s(f, &s->sfs);
2135 777aec7a Nolan
    qemu_get_be32s(f, &s->drs);
2136 777aec7a Nolan
    qemu_get_be32s(f, &s->sbms);
2137 777aec7a Nolan
    qemu_get_be32s(f, &s->dbms);
2138 777aec7a Nolan
    qemu_get_be32s(f, &s->dnad64);
2139 777aec7a Nolan
    qemu_get_be32s(f, &s->pmjad1);
2140 777aec7a Nolan
    qemu_get_be32s(f, &s->pmjad2);
2141 777aec7a Nolan
    qemu_get_be32s(f, &s->rbc);
2142 777aec7a Nolan
    qemu_get_be32s(f, &s->ua);
2143 777aec7a Nolan
    qemu_get_be32s(f, &s->ia);
2144 777aec7a Nolan
    qemu_get_be32s(f, &s->sbc);
2145 777aec7a Nolan
    qemu_get_be32s(f, &s->csbc);
2146 777aec7a Nolan
    qemu_get_buffer(f, (uint8_t *)s->scratch, sizeof (s->scratch));
2147 777aec7a Nolan
    qemu_get_8s(f, &s->sbr);
2148 777aec7a Nolan
2149 777aec7a Nolan
    qemu_get_buffer(f, (uint8_t *)s->script_ram, sizeof (s->script_ram));
2150 777aec7a Nolan
2151 777aec7a Nolan
    return 0;
2152 777aec7a Nolan
}
2153 777aec7a Nolan
2154 4b09be85 aliguori
static int lsi_scsi_uninit(PCIDevice *d)
2155 4b09be85 aliguori
{
2156 4b09be85 aliguori
    LSIState *s = (LSIState *) d;
2157 4b09be85 aliguori
2158 4b09be85 aliguori
    cpu_unregister_io_memory(s->mmio_io_addr);
2159 4b09be85 aliguori
    cpu_unregister_io_memory(s->ram_io_addr);
2160 4b09be85 aliguori
2161 4b09be85 aliguori
    qemu_free(s->queue);
2162 4b09be85 aliguori
2163 4b09be85 aliguori
    return 0;
2164 4b09be85 aliguori
}
2165 4b09be85 aliguori
2166 9be5dafe Paul Brook
static void lsi_scsi_init(PCIDevice *dev)
2167 7d8406be pbrook
{
2168 9be5dafe Paul Brook
    LSIState *s = (LSIState *)dev;
2169 deb54399 aliguori
    uint8_t *pci_conf;
2170 7d8406be pbrook
2171 deb54399 aliguori
    pci_conf = s->pci_dev.config;
2172 deb54399 aliguori
2173 9167a69a balrog
    /* PCI Vendor ID (word) */
2174 deb54399 aliguori
    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_LSI_LOGIC);
2175 9167a69a balrog
    /* PCI device ID (word) */
2176 deb54399 aliguori
    pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_LSI_53C895A);
2177 9167a69a balrog
    /* PCI base class code */
2178 173a543b blueswir1
    pci_config_set_class(pci_conf, PCI_CLASS_STORAGE_SCSI);
2179 9167a69a balrog
    /* PCI subsystem ID */
2180 deb54399 aliguori
    pci_conf[0x2e] = 0x00;
2181 deb54399 aliguori
    pci_conf[0x2f] = 0x10;
2182 9167a69a balrog
    /* PCI latency timer = 255 */
2183 deb54399 aliguori
    pci_conf[0x0d] = 0xff;
2184 9167a69a balrog
    /* Interrupt pin 1 */
2185 deb54399 aliguori
    pci_conf[0x3d] = 0x01;
2186 7d8406be pbrook
2187 1eed09cb Avi Kivity
    s->mmio_io_addr = cpu_register_io_memory(lsi_mmio_readfn,
2188 7d8406be pbrook
                                             lsi_mmio_writefn, s);
2189 1eed09cb Avi Kivity
    s->ram_io_addr = cpu_register_io_memory(lsi_ram_readfn,
2190 7d8406be pbrook
                                            lsi_ram_writefn, s);
2191 7d8406be pbrook
2192 28c2c264 Avi Kivity
    pci_register_bar((struct PCIDevice *)s, 0, 256,
2193 7d8406be pbrook
                           PCI_ADDRESS_SPACE_IO, lsi_io_mapfunc);
2194 28c2c264 Avi Kivity
    pci_register_bar((struct PCIDevice *)s, 1, 0x400,
2195 7d8406be pbrook
                           PCI_ADDRESS_SPACE_MEM, lsi_mmio_mapfunc);
2196 28c2c264 Avi Kivity
    pci_register_bar((struct PCIDevice *)s, 2, 0x2000,
2197 7d8406be pbrook
                           PCI_ADDRESS_SPACE_MEM, lsi_ram_mapfunc);
2198 a917d384 pbrook
    s->queue = qemu_malloc(sizeof(lsi_queue));
2199 a917d384 pbrook
    s->queue_len = 1;
2200 a917d384 pbrook
    s->active_commands = 0;
2201 4b09be85 aliguori
    s->pci_dev.unregister = lsi_scsi_uninit;
2202 7d8406be pbrook
2203 7d8406be pbrook
    lsi_soft_reset(s);
2204 7d8406be pbrook
2205 9be5dafe Paul Brook
    scsi_bus_new(&dev->qdev, lsi_scsi_attach);
2206 777aec7a Nolan
2207 777aec7a Nolan
    register_savevm("lsiscsi", -1, 0, lsi_scsi_save, lsi_scsi_load, s);
2208 7d8406be pbrook
}
2209 9be5dafe Paul Brook
2210 0aab0d3a Gerd Hoffmann
static PCIDeviceInfo lsi_info = {
2211 0aab0d3a Gerd Hoffmann
    .qdev.name = "lsi53c895a",
2212 0aab0d3a Gerd Hoffmann
    .qdev.size = sizeof(LSIState),
2213 0aab0d3a Gerd Hoffmann
    .init      = lsi_scsi_init,
2214 0aab0d3a Gerd Hoffmann
};
2215 0aab0d3a Gerd Hoffmann
2216 9be5dafe Paul Brook
static void lsi53c895a_register_devices(void)
2217 9be5dafe Paul Brook
{
2218 0aab0d3a Gerd Hoffmann
    pci_qdev_register(&lsi_info);
2219 9be5dafe Paul Brook
}
2220 9be5dafe Paul Brook
2221 9be5dafe Paul Brook
device_init(lsi53c895a_register_devices);