Statistics
| Branch: | Revision:

root / hw / lsi53c895a.c @ b79e1752

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