master
c 2,473 lines 72.3 KB
Raw
1 /*
2 * QEMU NCR710 SCSI Controller
3 *
4 * Copyright (c) 2025 Soumyajyotii Ssarkar <soumyajyotisarkar23@gmail.com>
5 * This driver was developed during the Google Summer of Code 2025 program.
6 *
7 * NCR710 SCSI Controller implementation
8 * Based on the NCR53C710 Technical Manual Version 3.2, December 2000
9 *
10 * Developed from an implementation of NCR53C710 by Helge Deller
11 * which was interim based on the implementation by Toni Wilen for UAE.
12 *
13 * SPDX-License-Identifier: GPL-2.0-or-later
14 *
15 * Contents:
16 * 1. Register Definitions
17 * 2. Register name functions
18 * 3. Parity functions
19 * 4. SCSI FIFO Structures
20 * 5. Scripts Misc functions
21 * 6. DMA functions
22 * 7. Scripts functions
23 * 8. Read and Write functions
24 * 9. QEMU Device model functions
25 *
26 */
27
28 #include "qemu/osdep.h"
29 #include "qapi/error.h"
30 #include "qemu/timer.h"
31 #include "hw/core/irq.h"
32 #include "hw/core/sysbus.h"
33 #include "hw/scsi/scsi.h"
34 #include "hw/scsi/ncr53c710.h"
35 #include "migration/vmstate.h"
36 #include "system/dma.h"
37 #include "qemu/log.h"
38 #include "qemu/module.h"
39 #include "trace.h"
40 #include "qom/object.h"
41
42 #define NCR710_MAX_DEVS 7
43
44 /* SCNTL0 (0x00) - SCSI Control Register 0 */
45 #define NCR710_SCNTL0_TRG 0x01
46 #define NCR710_SCNTL0_AAP 0x02
47 #define NCR710_SCNTL0_EPG 0x04
48 #define NCR710_SCNTL0_EPC 0x08
49 #define NCR710_SCNTL0_WATN 0x10
50 #define NCR710_SCNTL0_START 0x20
51 #define NCR710_SCNTL0_ARB0 0x40
52 #define NCR710_SCNTL0_ARB1 0x80
53
54 /* SCNTL1 (0x01) - SCSI Control Register 1 */
55 #define NCR710_SCNTL1_RES0 0x01
56 #define NCR710_SCNTL1_RES1 0x02
57 #define NCR710_SCNTL1_AESP 0x04
58 #define NCR710_SCNTL1_RST 0x08
59 #define NCR710_SCNTL1_CON 0x10
60 #define NCR710_SCNTL1_ESR 0x20
61 #define NCR710_SCNTL1_ADB 0x40
62 #define NCR710_SCNTL1_EXC 0x80
63
64 /* ISTAT (0x21) - Interrupt Status Register */
65 #define NCR710_ISTAT_DIP 0x01
66 #define NCR710_ISTAT_SIP 0x02
67 #define NCR710_ISTAT_CON 0x08
68 #define NCR710_ISTAT_SIGP 0x20
69 #define NCR710_ISTAT_RST 0x40
70 #define NCR710_ISTAT_ABRT 0x80
71
72 /* SSTAT0 (0x0D) - SCSI Status Register 0 */
73 #define NCR710_SSTAT0_PAR 0x01
74 #define NCR710_SSTAT0_RST 0x02
75 #define NCR710_SSTAT0_UDC 0x04
76 #define NCR710_SSTAT0_SGE 0x08
77 #define NCR710_SSTAT0_SEL 0x10
78 #define NCR710_SSTAT0_STO 0x20
79 #define NCR710_SSTAT0_FCMP 0x40
80 #define NCR710_SSTAT0_MA 0x80
81
82 /* SSTAT1 (0x0E) - SCSI Status Register 1 */
83 #define NCR710_SSTAT1_ORF 0x02
84 #define NCR710_SSTAT1_ILF 0x04
85
86 /* SSTAT2 (0x0F) - SCSI Status Register 2 */
87 #define NCR710_SSTAT2_FF0 0x01
88 #define NCR710_SSTAT2_FF1 0x02
89 #define NCR710_SSTAT2_FF2 0x04
90 #define NCR710_SSTAT2_FF3 0x08
91
92 /* SOCL (0x07) / SBCL (0x0B) - SCSI Output/Bus Control Lines */
93 #define NCR710_SOCL_IO 0x01
94 #define NCR710_SOCL_CD 0x02
95 #define NCR710_SOCL_MSG 0x04
96 #define NCR710_SOCL_ATN 0x08
97 #define NCR710_SOCL_SEL 0x10
98 #define NCR710_SOCL_BSY 0x20
99 #define NCR710_SOCL_ACK 0x40
100 #define NCR710_SOCL_REQ 0x80
101
102 /* SBCL bits same as SOCL */
103 #define NCR710_SBCL_IO 0x01
104 #define NCR710_SBCL_CD 0x02
105 #define NCR710_SBCL_MSG 0x04
106 #define NCR710_SBCL_ATN 0x08
107 #define NCR710_SBCL_SEL 0x10
108 #define NCR710_SBCL_BSY 0x20
109 #define NCR710_SBCL_ACK 0x40
110 #define NCR710_SBCL_REQ 0x80
111
112 /* DSTAT (0x0C) - DMA Status Register */
113 #define NCR710_DSTAT_IID 0x01
114 #define NCR710_DSTAT_SIR 0x04
115 #define NCR710_DSTAT_SSI 0x08
116 #define NCR710_DSTAT_ABRT 0x10
117 #define NCR710_DSTAT_BF 0x20
118 #define NCR710_DSTAT_MDPE 0x40
119 #define NCR710_DSTAT_DFE 0x80
120
121 /* DCNTL (0x3B) - DMA Control Register */
122 #define NCR710_DCNTL_COM 0x01
123 #define NCR710_DCNTL_IRQD 0x02
124 #define NCR710_DCNTL_STD 0x04
125 #define NCR710_DCNTL_IRQM 0x08
126 #define NCR710_DCNTL_SSM 0x10
127 #define NCR710_DCNTL_PFEN 0x20
128 #define NCR710_DCNTL_PFF 0x40
129
130 /* DMODE (0x38) - DMA Mode Register */
131 #define NCR710_DMODE_MAN 0x01
132 #define NCR710_DMODE_BOF 0x02
133 #define NCR710_DMODE_ERMP 0x04
134 #define NCR710_DMODE_ERL 0x08
135 #define NCR710_DMODE_DIOM 0x10
136 #define NCR710_DMODE_SIOM 0x20
137 #define NCR710_DMODE_BL_MASK 0xC0
138 #define NCR710_DMODE_BL_1 0x00
139 #define NCR710_DMODE_BL_2 0x40
140 #define NCR710_DMODE_BL_4 0x80
141 #define NCR710_DMODE_BL_8 0xC0
142
143 /* CTEST2 (0x16) - Chip Test Register 2 */
144 #define NCR710_CTEST2_DACK 0x01
145 #define NCR710_CTEST2_DREQ 0x02
146 #define NCR710_CTEST2_TEOP 0x04
147 #define NCR710_CTEST2_PCICIE 0x08
148 #define NCR710_CTEST2_CM 0x10
149 #define NCR710_CTEST2_CIO 0x20
150 #define NCR710_CTEST2_SIGP 0x40
151 #define NCR710_CTEST2_DDIR 0x80
152
153 /* CTEST5 (0x19) - Chip Test Register 5 */
154 #define NCR710_CTEST5_BL2 0x04
155 #define NCR710_CTEST5_DDIR 0x08
156 #define NCR710_CTEST5_MASR 0x10
157 #define NCR710_CTEST5_DFSN 0x20
158 #define NCR710_CTEST5_BBCK 0x40
159 #define NCR710_CTEST5_ADCK 0x80
160
161 /* SCID (0x04) - SCSI Chip ID Register */
162 #define NCR710_SCID_RRE 0x60
163 #define NCR710_SCID_ID_MASK 0x07
164
165 #define NCR710_HOST_ID 7
166
167 /* NCR53C710 has 8-byte SCSI FIFO */
168 #define NCR710_MAX_MSGIN_LEN 8
169 #define NCR710_BUF_SIZE 4096
170
171 /* Standard SCSI Message Byte Constants */
172 #define SCSI_MSG_ABORT 0x06
173 #define SCSI_MSG_BUS_DEVICE_RESET 0x0c
174 #define SCSI_MSG_COMMAND_COMPLETE 0x00
175 #define SCSI_MSG_DISCONNECT 0x04
176 #define SCSI_MSG_EXTENDED_MESSAGE 0x01
177 #define SCSI_MSG_IDENTIFY 0x80
178 #define SCSI_MSG_IGNORE_WIDE_RESIDUE 0x23
179 #define SCSI_MSG_MESSAGE_PARITY_ERROR 0x09
180 #define SCSI_MSG_MESSAGE_REJECT 0x07
181 #define SCSI_MSG_NO_OPERATION 0x08
182 #define SCSI_MSG_RELEASE_RECOVERY 0x10
183 #define SCSI_MSG_RESTORE_POINTERS 0x03
184 #define SCSI_MSG_SAVE_DATA_POINTER 0x02
185 #define SCSI_MSG_SYNCHRONOUS_DATA_TRANSFER 0x01
186 #define SCSI_MSG_WIDE_DATA_TRANSFER 0x03
187
188 /* Script interrupt codes */
189 #define A_GOOD_STATUS_AFTER_STATUS 0x401
190 #define A_DISCONNECT_AFTER_CMD 0x380
191 #define A_DISCONNECT_AFTER_DATA 0x580
192 #define A_DISCONNECT_DURING_DATA 0x780
193 #define A_RESELECTION_IDENTIFIED 0x1003
194 #define A_UNEXPECTED_PHASE 0x20
195 #define A_FATAL 0x2000
196 #define A_DEBUG_INTERRUPT 0x3000
197
198 /* SCSI Script execution states */
199 #define SCRIPT_STATE_IDLE 0
200 #define SCRIPT_STATE_SELECTING 1
201 #define SCRIPT_STATE_COMMAND 2
202 #define SCRIPT_STATE_DATA 3
203 #define SCRIPT_STATE_STATUS 4
204 #define SCRIPT_STATE_MESSAGE 5
205 #define SCRIPT_STATE_DISCONNECTED 6
206
207 #define AFTER_SELECTION 0x100
208 #define BEFORE_CMD 0x200
209 #define AFTER_CMD 0x300
210 #define AFTER_STATUS 0x400
211 #define AFTER_DATA_IN 0x500
212 #define AFTER_DATA_OUT 0x600
213 #define DURING_DATA_IN 0x700
214
215 #define NOT_MSG_OUT 0x10
216 #define UNEXPECTED_PHASE 0x20
217 #define NOT_MSG_IN 0x30
218 #define UNEXPECTED_MSG 0x40
219 #define MSG_IN 0x50
220 #define SDTR_MSG_R 0x60
221 #define REJECT_MSG_R 0x70
222 #define DISCONNECT 0x80
223 #define MSG_OUT 0x90
224 #define WDTR_MSG_R 0xA0
225
226 #define GOOD_STATUS 0x1
227
228 #define NOT_MSG_OUT_AFTER_SELECTION 0x110
229 #define UNEXPECTED_PHASE_BEFORE_CMD 0x220
230 #define UNEXPECTED_PHASE_AFTER_CMD 0x320
231 #define NOT_MSG_IN_AFTER_STATUS 0x430
232 #define GOOD_STATUS_AFTER_STATUS 0x401
233 #define UNEXPECTED_PHASE_AFTER_DATA_IN 0x520
234 #define UNEXPECTED_PHASE_AFTER_DATA_OUT 0x620
235 #define UNEXPECTED_MSG_BEFORE_CMD 0x240
236 #define MSG_IN_BEFORE_CMD 0x250
237 #define MSG_IN_AFTER_CMD 0x350
238 #define SDTR_MSG_BEFORE_CMD 0x260
239 #define REJECT_MSG_BEFORE_CMD 0x270
240 #define DISCONNECT_AFTER_CMD 0x380
241 #define SDTR_MSG_AFTER_CMD 0x360
242 #define WDTR_MSG_AFTER_CMD 0x3A0
243 #define MSG_IN_AFTER_STATUS 0x440
244 #define DISCONNECT_AFTER_DATA 0x580
245 #define MSG_IN_AFTER_DATA_IN 0x550
246 #define MSG_IN_AFTER_DATA_OUT 0x650
247 #define MSG_OUT_AFTER_DATA_IN 0x590
248 #define DATA_IN_AFTER_DATA_IN 0x5a0
249 #define MSG_IN_DURING_DATA_IN 0x750
250 #define DISCONNECT_DURING_DATA 0x780
251
252 #define RESELECTED_DURING_SELECTION 0x1000
253 #define COMPLETED_SELECTION_AS_TARGET 0x1001
254 #define RESELECTION_IDENTIFIED 0x1003
255
256 #define FATAL 0x2000
257 #define FATAL_UNEXPECTED_RESELECTION_MSG 0x2000
258 #define FATAL_SEND_MSG 0x2001
259 #define FATAL_NOT_MSG_IN_AFTER_SELECTION 0x2002
260 #define FATAL_ILLEGAL_MSG_LENGTH 0x2003
261
262 #define DEBUG_INTERRUPT 0x3000
263 #define DEBUG_INTERRUPT1 0x3001
264 #define DEBUG_INTERRUPT2 0x3002
265 #define DEBUG_INTERRUPT3 0x3003
266 #define DEBUG_INTERRUPT4 0x3004
267 #define DEBUG_INTERRUPT5 0x3005
268 #define DEBUG_INTERRUPT6 0x3006
269
270 #define COMMAND_COMPLETE_MSG 0x00
271 #define EXTENDED_MSG 0x01
272 #define SDTR_MSG 0x01
273 #define SAVE_DATA_PTRS_MSG 0x02
274 #define RESTORE_DATA_PTRS_MSG 0x03
275 #define WDTR_MSG 0x03
276 #define DISCONNECT_MSG 0x04
277 #define REJECT_MSG 0x07
278 #define PARITY_ERROR_MSG 0x09
279 #define SIMPLE_TAG_MSG 0x20
280 #define IDENTIFY_MSG 0x80
281 #define IDENTIFY_MSG_MASK 0x7F
282 #define TWO_BYTE_MSG 0x20
283 #define TWO_BYTE_MSG_MASK 0x0F
284
285 /* SCSI phases */
286 #define PHASE_DO 0 /* Data out phase */
287 #define PHASE_DI 1 /* Data in phase */
288 #define PHASE_CO 2 /* Command phase */
289 #define PHASE_SI 3 /* Status phase */
290 #define PHASE_ST 3 /* Status phase (alias) */
291 #define PHASE_MO 6 /* Message out phase */
292 #define PHASE_MI 7 /* Message in phase */
293 #define PHASE_MASK 7 /* Mask for phase bits */
294
295 #define NCR710_TAG_VALID (1 << 16)
296
297 static void ncr710_scsi_fifo_init(NCR710_SCSI_FIFO *fifo);
298 static const char *ncr710_reg_name(int offset);
299 static void ncr710_script_scsi_interrupt(NCR710State *s, int stat0);
300 static void ncr710_update_irq(NCR710State *s);
301 static void ncr710_script_dma_interrupt(NCR710State *s, int stat);
302 static void ncr710_request_free(NCR710State *s, NCR710Request *p);
303 static inline void ncr710_dma_read(NCR710State *s, uint32_t addr,
304 void *buf, uint32_t len);
305 static inline void ncr710_dma_write(NCR710State *s, uint32_t addr,
306 const void *buf, uint32_t len);
307 static uint8_t ncr710_reg_readb(NCR710State *s, int offset);
308 static void ncr710_reg_writeb(NCR710State *s, int offset, uint8_t val);
309
310
311 static inline int ncr710_irq_on_rsl(NCR710State *s)
312 {
313 return (s->sien0 & NCR710_SSTAT0_SEL) != 0;
314 }
315
316 static void ncr710_clear_pending_irq(NCR710State *s)
317 {
318 if (s->current) {
319 if (s->current->req) {
320 s->current->req->hba_private = NULL;
321 }
322 ncr710_request_free(s, s->current);
323 s->current = NULL;
324 }
325 }
326
327 void ncr710_soft_reset(NCR710State *s)
328 {
329 trace_ncr710_reset();
330 s->carry = 0;
331 s->msg_action = NCR710_MSG_ACTION_NONE;
332 s->msg_len = 0;
333 s->waiting = NCR710_WAIT_NONE;
334 s->wait_reselect = false;
335 s->reselection_id = 0;
336 s->dsa = 0;
337 s->dnad = 0;
338 s->dbc = 0;
339 s->temp = 0;
340 s->scratch = 0;
341 s->istat &= 0x40;
342 s->dcmd = 0x40;
343 s->dstat = NCR710_DSTAT_DFE;
344 s->dien = 0x04;
345 s->sien0 = 0;
346 s->ctest2 = NCR710_CTEST2_DACK;
347 s->ctest3 = 0;
348 s->ctest4 = 0;
349 s->ctest5 = 0;
350 s->dsp = 0;
351 s->dsps = 0;
352 s->dmode = 0;
353 s->dcntl = 0;
354 s->scntl0 = 0xc0;
355 s->scntl1 = 0;
356 s->sstat0 = 0;
357 s->sstat1 = 0;
358 s->sstat2 = 0;
359 s->scid = 0x80;
360 s->sxfer = 0;
361 s->socl = 0;
362 s->sdid = 0;
363 s->sbcl = 0;
364 s->sidl = 0;
365 s->sfbr = 0;
366 qemu_set_irq(s->irq, 0);
367 ncr710_clear_pending_irq(s);
368 ncr710_scsi_fifo_init(&s->scsi_fifo);
369 }
370
371 static const char *ncr710_reg_name(int offset)
372 {
373 switch (offset) {
374 case NCR710_SCNTL0_REG: return "SCNTL0";
375 case NCR710_SCNTL1_REG: return "SCNTL1";
376 case NCR710_SDID_REG: return "SDID";
377 case NCR710_SIEN_REG: return "SIEN";
378 case NCR710_SCID_REG: return "SCID";
379 case NCR710_SXFER_REG: return "SXFER";
380 case NCR710_SODL_REG: return "SODL";
381 case NCR710_SOCL_REG: return "SOCL";
382 case NCR710_SFBR_REG: return "SFBR";
383 case NCR710_SIDL_REG: return "SIDL";
384 case NCR710_SBDL_REG: return "SBDL";
385 case NCR710_SBCL_REG: return "SBCL";
386 case NCR710_DSTAT_REG: return "DSTAT";
387 case NCR710_SSTAT0_REG: return "SSTAT0";
388 case NCR710_SSTAT1_REG: return "SSTAT1";
389 case NCR710_SSTAT2_REG: return "SSTAT2";
390 case NCR710_DSA_REG: return "DSA";
391 case NCR710_DSA_REG + 1: return "DSA+1";
392 case NCR710_DSA_REG + 2: return "DSA+2";
393 case NCR710_DSA_REG + 3: return "DSA+3";
394 case NCR710_CTEST0_REG: return "CTEST0";
395 case NCR710_CTEST1_REG: return "CTEST1";
396 case NCR710_CTEST2_REG: return "CTEST2";
397 case NCR710_CTEST3_REG: return "CTEST3";
398 case NCR710_CTEST4_REG: return "CTEST4";
399 case NCR710_CTEST5_REG: return "CTEST5";
400 case NCR710_CTEST6_REG: return "CTEST6";
401 case NCR710_CTEST7_REG: return "CTEST7";
402 case NCR710_TEMP_REG: return "TEMP";
403 case NCR710_TEMP_REG + 1: return "TEMP+1";
404 case NCR710_TEMP_REG + 2: return "TEMP+2";
405 case NCR710_TEMP_REG + 3: return "TEMP+3";
406 case NCR710_DFIFO_REG: return "DFIFO";
407 case NCR710_ISTAT_REG: return "ISTAT";
408 case NCR710_CTEST8_REG: return "CTEST8";
409 case NCR710_LCRC_REG: return "LCRC";
410 case NCR710_DBC_REG: return "DBC";
411 case NCR710_DBC_REG + 1: return "DBC+1";
412 case NCR710_DBC_REG + 2: return "DBC+2";
413 case NCR710_DCMD_REG: return "DCMD";
414 case NCR710_DNAD_REG: return "DNAD";
415 case NCR710_DNAD_REG + 1: return "DNAD+1";
416 case NCR710_DNAD_REG + 2: return "DNAD+2";
417 case NCR710_DNAD_REG + 3: return "DNAD+3";
418 case NCR710_DSP_REG: return "DSP";
419 case NCR710_DSP_REG + 1: return "DSP+1";
420 case NCR710_DSP_REG + 2: return "DSP+2";
421 case NCR710_DSP_REG + 3: return "DSP+3";
422 case NCR710_DSPS_REG: return "DSPS";
423 case NCR710_DSPS_REG + 1: return "DSPS+1";
424 case NCR710_DSPS_REG + 2: return "DSPS+2";
425 case NCR710_DSPS_REG + 3: return "DSPS+3";
426 case NCR710_SCRATCH_REG: return "SCRATCH";
427 case NCR710_SCRATCH_REG + 1: return "SCRATCH+1";
428 case NCR710_SCRATCH_REG + 2: return "SCRATCH+2";
429 case NCR710_SCRATCH_REG + 3: return "SCRATCH+3";
430 case NCR710_DMODE_REG: return "DMODE";
431 case NCR710_DIEN_REG: return "DIEN";
432 case NCR710_DWT_REG: return "DWT";
433 case NCR710_DCNTL_REG: return "DCNTL";
434 case NCR710_ADDER_REG: return "ADDER";
435 case NCR710_ADDER_REG + 1: return "ADDER+1";
436 case NCR710_ADDER_REG + 2: return "ADDER+2";
437 case NCR710_ADDER_REG + 3: return "ADDER+3";
438 default: return "UNKNOWN";
439 }
440 }
441
442 static uint8_t ncr710_generate_scsi_parity(NCR710State *s, uint8_t data)
443 {
444 uint8_t parity = parity8(data);
445
446 if (s->scntl1 & NCR710_SCNTL1_AESP) {
447 parity = !parity;
448 }
449
450 return parity;
451 }
452
453 static bool ncr710_check_scsi_parity(NCR710State *s, uint8_t data,
454 uint8_t parity)
455 {
456 if (!(s->scntl0 & NCR710_SCNTL0_EPC)) {
457 return true;
458 }
459
460 uint8_t expected_parity = ncr710_generate_scsi_parity(s, data);
461 return parity == expected_parity;
462 }
463
464 static void ncr710_handle_parity_error(NCR710State *s)
465 {
466 s->sstat0 |= NCR710_SSTAT0_PAR;
467
468 /* If parity error ATN is enabled, assert ATN */
469 if (s->scntl0 & NCR710_SCNTL0_AAP) {
470 s->socl |= NCR710_SOCL_ATN;
471 }
472
473 ncr710_script_scsi_interrupt(s, NCR710_SSTAT0_PAR);
474 }
475
476 /*
477 * NCR710 SCSI FIFO IMPLEMENTATION
478 *
479 * Hardware Specifications (NCR53C710 datasheet):
480 * - Width: 9 bits (8 data bits + 1 parity bit)
481 * - Depth: 8 bytes
482 * - Type: Circular buffer
483 *
484 * Implementation:
485 * - Enqueue: Add byte at tail position ((head + count) % 8)
486 * - Dequeue: Remove byte from head position, advance head
487 * - Status: Empty (count=0), Full (count=8)
488 *
489 * FIFO Operations:
490 * - ncr710_scsi_fifo_init() - Reset FIFO to empty state
491 * - ncr710_scsi_fifo_enqueue() - Add byte with parity to tail
492 * - ncr710_scsi_fifo_dequeue() - Remove byte with parity from head
493 * - ncr710_scsi_fifo_empty() - Check if FIFO is empty
494 * - ncr710_scsi_fifo_full() - Check if FIFO is full
495 */
496
497 static void ncr710_scsi_fifo_init(NCR710_SCSI_FIFO *fifo)
498 {
499 memset(fifo->data, 0, NCR710_SCSI_FIFO_SIZE);
500 memset(fifo->parity, 0, NCR710_SCSI_FIFO_SIZE);
501 fifo->head = 0;
502 fifo->count = 0;
503 }
504
505 static inline bool ncr710_scsi_fifo_empty(NCR710_SCSI_FIFO *fifo)
506 {
507 return fifo->count == 0;
508 }
509
510 static inline bool ncr710_scsi_fifo_full(NCR710_SCSI_FIFO *fifo)
511 {
512 return fifo->count == NCR710_SCSI_FIFO_SIZE;
513 }
514
515 static inline int ncr710_scsi_fifo_enqueue(NCR710_SCSI_FIFO *fifo,
516 uint8_t data, uint8_t parity)
517 {
518 if (ncr710_scsi_fifo_full(fifo)) {
519 return -1; /* FIFO full - 8 transfers deep */
520 }
521
522 /* Add data at the tail (head + count) */
523 int tail_pos = (fifo->head + fifo->count) % NCR710_SCSI_FIFO_SIZE;
524 fifo->data[tail_pos] = data;
525 fifo->parity[tail_pos] = parity;
526 fifo->count++;
527
528 return 0;
529 }
530
531 static inline uint8_t ncr710_scsi_fifo_dequeue(NCR710_SCSI_FIFO *fifo,
532 uint8_t *parity)
533 {
534 uint8_t data;
535
536 if (ncr710_scsi_fifo_empty(fifo)) {
537 *parity = 0;
538 return 0; /* FIFO empty */
539 }
540
541 /* Taking data from the head position */
542 data = fifo->data[fifo->head];
543 *parity = fifo->parity[fifo->head];
544 fifo->head = (fifo->head + 1) % NCR710_SCSI_FIFO_SIZE;
545 fifo->count--;
546
547 return data;
548 }
549
550 static inline uint32_t ncr710_read_dword(NCR710State *s, uint32_t addr)
551 {
552 uint32_t buf;
553 address_space_read(s->as, addr, MEMTXATTRS_UNSPECIFIED,
554 (uint8_t *)&buf, 4);
555 /*
556 * The NCR710 datasheet saying "operates internally in LE mode"
557 * refers to its internal register organization,
558 * not how it reads SCRIPTS from host memory.
559 */
560 buf = be32_to_cpu(buf);
561 NCR710_DPRINTF("Read dword %08x from %08x\n", buf, addr);
562 return buf;
563 }
564
565 static inline void ncr710_dma_read(NCR710State *s, uint32_t addr,
566 void *buf, uint32_t len)
567 {
568 address_space_read(s->as, addr, MEMTXATTRS_UNSPECIFIED,
569 buf, len);
570 NCR710_DPRINTF("Read %d bytes from %08x: ", len, addr);
571 for (int i = 0; i < len && i < 16; i++) {
572 NCR710_DPRINTF("%02x ", ((uint8_t *)buf)[i]);
573 }
574 NCR710_DPRINTF("\n");
575 }
576
577 static inline void ncr710_dma_write(NCR710State *s, uint32_t addr,
578 const void *buf, uint32_t len)
579 {
580 address_space_write(s->as, addr, MEMTXATTRS_UNSPECIFIED,
581 buf, len);
582 NCR710_DPRINTF("Wrote %d bytes to %08x\n", len, addr);
583 }
584
585 static void ncr710_stop_script(NCR710State *s)
586 {
587 s->script_active = 0;
588 s->scntl1 &= ~NCR710_SCNTL1_CON;
589 s->istat &= ~NCR710_ISTAT_CON;
590 }
591
592 static void ncr710_update_irq(NCR710State *s)
593 {
594 int level = 0;
595
596 if (s->dstat & ~NCR710_DSTAT_DFE) {
597 if (s->dstat & s->dien) {
598 level = 1;
599 }
600 s->istat |= NCR710_ISTAT_DIP;
601 } else {
602 s->istat &= ~NCR710_ISTAT_DIP;
603 }
604
605 if (s->sstat0) {
606 if ((s->sstat0 & s->sien0)) {
607 level = 1;
608 }
609 s->istat |= NCR710_ISTAT_SIP;
610 } else {
611 s->istat &= ~NCR710_ISTAT_SIP;
612 }
613
614 qemu_set_irq(s->irq, level);
615 }
616
617 static void ncr710_script_scsi_interrupt(NCR710State *s, int stat0)
618 {
619 uint32_t mask0;
620
621 trace_ncr710_script_scsi_interrupt(stat0, s->sstat0);
622 s->sstat0 |= stat0;
623 mask0 = stat0 & s->sien0;
624 if (mask0) {
625 ncr710_stop_script(s);
626 s->istat |= NCR710_ISTAT_SIP;
627 ncr710_update_irq(s);
628 }
629 }
630
631 static void ncr710_script_dma_interrupt(NCR710State *s, int stat)
632 {
633 trace_ncr710_script_dma_interrupt(stat, s->dstat);
634 if (stat == NCR710_DSTAT_SIR && (s->dstat & NCR710_DSTAT_DFE)) {
635 s->dstat &= ~NCR710_DSTAT_DFE;
636 }
637
638 s->dstat |= stat;
639 s->istat |= NCR710_ISTAT_DIP;
640 ncr710_update_irq(s);
641 ncr710_stop_script(s);
642 }
643
644 inline void ncr710_set_phase(NCR710State *s, int phase)
645 {
646 s->sstat2 = (s->sstat2 & ~PHASE_MASK) | phase;
647 s->ctest0 &= ~1;
648 if (phase == PHASE_DI) {
649 s->ctest0 |= 1;
650 }
651 s->sbcl &= ~NCR710_SBCL_REQ;
652 }
653
654 static void ncr710_disconnect(NCR710State *s)
655 {
656 trace_ncr710_disconnect(s->waiting);
657 if (s->waiting == NCR710_WAIT_NONE) {
658 s->scntl1 &= ~NCR710_SCNTL1_CON;
659 s->istat &= ~NCR710_ISTAT_CON;
660 }
661 s->sstat2 &= ~PHASE_MASK;
662 }
663
664 static void ncr710_bad_selection(NCR710State *s, uint32_t id)
665 {
666 trace_ncr710_bad_selection(id);
667 s->dstat = 0;
668 s->dsps = 0;
669 ncr710_script_scsi_interrupt(s, NCR710_SSTAT0_STO);
670 ncr710_disconnect(s);
671 }
672
673 static void ncr710_clear_selection_timeout(NCR710State *s)
674 {
675 if (s->sstat0 & NCR710_SSTAT0_STO) {
676 s->sstat0 &= ~NCR710_SSTAT0_STO;
677 ncr710_clear_pending_irq(s);
678 if (s->sstat0 == 0) {
679 s->istat &= ~NCR710_ISTAT_SIP;
680 }
681 ncr710_update_irq(s);
682 }
683 }
684
685 static void ncr710_do_dma(NCR710State *s, int out)
686 {
687 uint32_t count;
688 uint32_t addr;
689 SCSIDevice *dev;
690 assert(s->current);
691 if (!s->current->dma_len) {
692 /* We wait until data is available. */
693 return;
694 }
695
696 dev = s->current->req->dev;
697 assert(dev);
698
699 count = s->dbc;
700 if (count > s->current->dma_len) {
701 count = s->current->dma_len;
702 }
703
704 addr = s->dnad;
705
706 s->dnad += count;
707 s->dbc -= count;
708 if (s->current->dma_buf == NULL) {
709 s->current->dma_buf = scsi_req_get_buf(s->current->req);
710 }
711 /* ??? Set SFBR to first data byte. */
712 if (out) {
713 ncr710_dma_read(s, addr, s->current->dma_buf, count);
714 } else {
715 ncr710_dma_write(s, addr, s->current->dma_buf, count);
716 }
717 s->current->dma_len -= count;
718 if (s->current->dma_len == 0) {
719 s->current->dma_buf = NULL;
720 s->current->pending = 0;
721 s->waiting = NCR710_WAIT_DMA;
722 scsi_req_continue(s->current->req);
723 return;
724 } else {
725 s->current->dma_buf += count;
726 s->waiting = NCR710_WAIT_NONE;
727 ncr710_execute_script(s);
728 }
729 }
730
731 static void ncr710_add_msg_byte(NCR710State *s, uint8_t data)
732 {
733 if (s->msg_len >= NCR710_MAX_MSGIN_LEN) {
734 BADF("MSG IN data too long\n");
735 } else {
736 s->msg[s->msg_len++] = data;
737 }
738 }
739
740 static void ncr710_request_free(NCR710State *s, NCR710Request *p)
741 {
742 if (!p) {
743 return;
744 }
745 if (p->req && p->req->hba_private == p) {
746 p->req->hba_private = NULL;
747 }
748 if (p == s->current) {
749 s->current = NULL;
750 }
751 g_free(p);
752 }
753
754 void ncr710_request_cancelled(SCSIRequest *req)
755 {
756 NCR710State *s = ncr710_from_scsi_bus(req->bus);
757 NCR710Request *p = (NCR710Request *)req->hba_private;
758 if (p) {
759 req->hba_private = NULL;
760 p->req = NULL;
761 ncr710_request_free(s, p);
762 }
763 scsi_req_unref(req);
764 }
765
766 static int ncr710_queue_req(NCR710State *s, SCSIRequest *req, uint32_t len)
767 {
768 NCR710Request *p = (NCR710Request *)req->hba_private;
769
770 if (!p) {
771 return -1;
772 }
773 p->pending = len;
774 if ((s->waiting == NCR710_WAIT_RESELECT &&
775 !(s->istat & (NCR710_ISTAT_SIP | NCR710_ISTAT_DIP))) ||
776 (ncr710_irq_on_rsl(s) && !(s->scntl1 & NCR710_SCNTL1_CON) &&
777 !(s->istat & (NCR710_ISTAT_SIP | NCR710_ISTAT_DIP)))) {
778 s->current = p;
779 return 0;
780 } else {
781 s->current = p;
782 return 1;
783 }
784 }
785
786 void ncr710_command_complete(SCSIRequest *req, size_t resid)
787 {
788 NCR710State *s = ncr710_from_scsi_bus(req->bus);
789 NCR710Request *p = (NCR710Request *)req->hba_private;
790
791 trace_ncr710_command_complete(req->tag, req->status);
792
793 s->lcrc = 0;
794 s->status = req->status;
795 s->command_complete = NCR710_CMD_COMPLETE;
796
797 if (p) {
798 p->pending = 0;
799 }
800
801 ncr710_set_phase(s, PHASE_ST);
802
803 if (p) {
804 req->hba_private = NULL;
805 if (p == s->current) {
806 p->req = NULL;
807 } else {
808 ncr710_request_free(s, p);
809 }
810 scsi_req_unref(req);
811 }
812
813 if (s->waiting == NCR710_WAIT_RESELECT || s->waiting == NCR710_WAIT_DMA) {
814 s->waiting = NCR710_WAIT_NONE;
815 ncr710_execute_script(s);
816 }
817 }
818
819 void ncr710_transfer_data(SCSIRequest *req, uint32_t len)
820 {
821 NCR710State *s = ncr710_from_scsi_bus(req->bus);
822
823 assert(req->hba_private);
824
825 if (s->waiting == NCR710_WAIT_DMA) {
826 NCR710Request *p = (NCR710Request *)req->hba_private;
827 if (p) {
828 p->dma_len = len;
829 }
830 s->dsp -= 8;
831 s->waiting = NCR710_WAIT_NONE;
832 ncr710_execute_script(s);
833 return;
834 }
835
836 if (s->wait_reselect) {
837 s->current = (NCR710Request *)req->hba_private;
838 s->current->dma_len = len;
839 s->waiting = NCR710_WAIT_RESELECT;
840 }
841
842 if (req->hba_private != s->current ||
843 (ncr710_irq_on_rsl(s) && !(s->scntl1 & NCR710_SCNTL1_CON)) ||
844 s->waiting == NCR710_WAIT_RESELECT) {
845 int queue_result = ncr710_queue_req(s, req, len);
846 if (queue_result != 0) {
847 return;
848 }
849 }
850
851 /* Host adapter (re)connected */
852 s->command_complete = NCR710_CMD_DATA_READY;
853 if (!s->current) {
854 return;
855 }
856 s->current->dma_len = len;
857
858 if (s->waiting) {
859 s->scntl1 |= NCR710_SCNTL1_CON;
860 s->istat |= NCR710_ISTAT_CON;
861 s->sbcl = NCR710_SBCL_IO | NCR710_SBCL_CD | NCR710_SBCL_MSG |
862 NCR710_SBCL_BSY | NCR710_SBCL_SEL | NCR710_SBCL_REQ;
863 uint8_t host_id = (s->scid & 0x07);
864
865 /* Special case: both target and host are ID 0 */
866 if (req->dev->id == 0 && host_id == 0) {
867 s->sfbr = 0x00;
868 } else {
869 s->sfbr = (req->dev->id == 0 ? 0 : (1 << req->dev->id)) |
870 (host_id == 0 ? 0 : (1 << host_id));
871 }
872
873 ncr710_set_phase(s, PHASE_MI);
874
875 if (s->current) {
876 uint8_t identify_msg = 0x80 | (req->lun & 0x07);
877 ncr710_add_msg_byte(s, identify_msg);
878
879 if (s->current->tag) {
880 ncr710_add_msg_byte(s, 0x20); /* SIMPLE_TAG_MSG */
881 ncr710_add_msg_byte(s, s->current->tag & 0xff);
882 }
883 }
884
885 s->sstat0 |= NCR710_SSTAT0_SEL;
886 s->istat |= NCR710_ISTAT_SIP;
887 s->dsps = RESELECTED_DURING_SELECTION;
888 s->waiting = NCR710_WAIT_NONE;
889 ncr710_update_irq(s);
890 return;
891 }
892 if (!s->script_active && !s->waiting) {
893 ncr710_execute_script(s);
894 }
895 }
896
897 static int idbitstonum(uint8_t id)
898 {
899 return 7 - clz8(id);
900 }
901
902 static void ncr710_do_command(NCR710State *s)
903 {
904 SCSIDevice *dev;
905 uint8_t buf[16];
906 uint32_t id;
907 int n;
908 int bytes_read;
909 if (s->dbc > 16) {
910 s->dbc = 16;
911 }
912
913 /*
914 * Reading command data directly from memory
915 * NOTE: SCSI commands can be up to 16 bytes
916 * (e.g., READ_CAPACITY_10 is 10 bytes) but the NCR710 SCSI FIFO is
917 * only 8 bytes deep. For command phase, we bypass the FIFO and read
918 * directly from memory since commands don't need FIFO buffering.
919 */
920 bytes_read = MIN(s->dbc, sizeof(buf));
921 ncr710_dma_read(s, s->dnad, buf, bytes_read);
922
923 s->dnad += bytes_read;
924 s->dbc -= bytes_read;
925 s->sfbr = buf[0];
926
927 s->command_complete = NCR710_CMD_PENDING;
928 id = (s->select_tag >> 8) & 0xff;
929 s->lcrc = id;
930
931 dev = scsi_device_find(&s->bus, 0, idbitstonum(id), s->current_lun);
932
933 if (!dev) {
934 ncr710_bad_selection(s, id);
935 return;
936 }
937
938 if (s->current) {
939 ncr710_request_free(s, s->current);
940 s->current = NULL;
941 }
942
943 s->current = g_new0(NCR710Request, 1);
944 s->current->tag = s->select_tag;
945 s->current->resume_offset = 0;
946
947 s->current->req = scsi_req_new(dev, s->current->tag, s->current_lun, buf,
948 bytes_read, s->current);
949 n = scsi_req_enqueue(s->current->req);
950 if (n) {
951 if (n > 0) {
952 ncr710_set_phase(s, PHASE_DI);
953 } else if (n < 0) {
954 ncr710_set_phase(s, PHASE_DO);
955 }
956 scsi_req_continue(s->current->req);
957 }
958
959 if (!s->command_complete) {
960 if (!n) {
961 ncr710_set_phase(s, PHASE_SI);
962 } else {
963 NCR710_DPRINTF("Data transfer phase\n");
964 }
965 }
966 }
967
968 static void ncr710_do_status(NCR710State *s)
969 {
970 uint8_t status = s->status;
971 uint8_t parity = 0;
972
973 if (s->dbc != 1) {
974 BADF("Bad Status move\n");
975 }
976 s->dbc = 1;
977 s->sfbr = status;
978
979 /* Generate parity if enabled and enqueue status byte */
980 if (s->scntl0 & NCR710_SCNTL0_EPG) {
981 parity = ncr710_generate_scsi_parity(s, status);
982 }
983 ncr710_scsi_fifo_enqueue(&s->scsi_fifo, status, parity);
984
985 /* Dequeue status byte and write to memory */
986 status = ncr710_scsi_fifo_dequeue(&s->scsi_fifo, &parity);
987 if (s->scntl0 & NCR710_SCNTL0_EPC) {
988 if (!ncr710_check_scsi_parity(s, status, parity)) {
989 ncr710_handle_parity_error(s);
990 }
991 }
992 ncr710_dma_write(s, s->dnad, &status, 1);
993
994 s->dnad += 1;
995 s->dbc -= 1;
996
997 ncr710_set_phase(s, PHASE_MI);
998 s->msg_action = NCR710_MSG_ACTION_DISCONNECT;
999 ncr710_add_msg_byte(s, 0); /* COMMAND COMPLETE */
1000 s->command_complete = NCR710_CMD_COMPLETE;
1001 }
1002
1003 static void ncr710_do_msgin(NCR710State *s)
1004 {
1005 int len;
1006 len = s->msg_len;
1007 if (len > s->dbc) {
1008 len = s->dbc;
1009 }
1010 s->sfbr = s->msg[0];
1011
1012 for (int i = 0; i < len; i++) {
1013 uint8_t parity = 0;
1014 if (s->scntl0 & NCR710_SCNTL0_EPG) {
1015 parity = ncr710_generate_scsi_parity(s, s->msg[i]);
1016 }
1017 ncr710_scsi_fifo_enqueue(&s->scsi_fifo, s->msg[i], parity);
1018 }
1019
1020 uint8_t buf[NCR710_MAX_MSGIN_LEN];
1021 for (int i = 0; i < len; i++) {
1022 uint8_t parity;
1023 buf[i] = ncr710_scsi_fifo_dequeue(&s->scsi_fifo, &parity);
1024 if (s->scntl0 & NCR710_SCNTL0_EPC) {
1025 if (!ncr710_check_scsi_parity(s, buf[i], parity)) {
1026 ncr710_handle_parity_error(s);
1027 }
1028 }
1029 }
1030 ncr710_dma_write(s, s->dnad, buf, len);
1031
1032 s->dnad += len;
1033 s->dbc -= len;
1034 s->sidl = s->msg[len - 1];
1035 s->msg_len -= len;
1036 if (s->msg_len) {
1037 memmove(s->msg, s->msg + len, s->msg_len);
1038 return;
1039 }
1040 switch (s->msg_action) {
1041 case NCR710_MSG_ACTION_NONE:
1042 ncr710_set_phase(s, PHASE_CO);
1043 break;
1044 case NCR710_MSG_ACTION_DISCONNECT:
1045 s->sstat2 &= ~PHASE_MASK;
1046 break;
1047 case NCR710_MSG_ACTION_DATA_OUT:
1048 ncr710_set_phase(s, PHASE_DO);
1049 break;
1050 case NCR710_MSG_ACTION_DATA_IN:
1051 ncr710_set_phase(s, PHASE_DI);
1052 break;
1053 default:
1054 abort();
1055 }
1056 }
1057
1058 static void ncr710_do_msgout(NCR710State *s)
1059 {
1060 NCR710Request *current_req = s->current;
1061
1062 while (s->dbc > 0) {
1063 int to_move = MIN((int)s->dbc, NCR710_SCSI_FIFO_SIZE);
1064 uint8_t temp_buf[NCR710_SCSI_FIFO_SIZE];
1065 ncr710_dma_read(s, s->dnad, temp_buf, to_move);
1066 int filled = 0;
1067 for (int j = 0; j < to_move &&
1068 !ncr710_scsi_fifo_full(&s->scsi_fifo); j++) {
1069 uint8_t parity = 0;
1070 if (s->scntl0 & NCR710_SCNTL0_EPG) {
1071 parity = ncr710_generate_scsi_parity(s, temp_buf[j]);
1072 }
1073 if (ncr710_scsi_fifo_enqueue(&s->scsi_fifo, temp_buf[j],
1074 parity) == 0) {
1075 filled++;
1076 } else {
1077 break;
1078 }
1079 }
1080
1081 if (filled <= 0) {
1082 break;
1083 }
1084 uint8_t buf[NCR710_SCSI_FIFO_SIZE];
1085 int bytes = 0;
1086 for (int j = 0; j < filled &&
1087 !ncr710_scsi_fifo_empty(&s->scsi_fifo); j++) {
1088 uint8_t parity;
1089 buf[bytes] = ncr710_scsi_fifo_dequeue(&s->scsi_fifo, &parity);
1090 if (s->scntl0 & NCR710_SCNTL0_EPC) {
1091 if (!ncr710_check_scsi_parity(s, buf[bytes], parity)) {
1092 ncr710_handle_parity_error(s);
1093 }
1094 }
1095 bytes++;
1096 }
1097
1098 s->dnad += bytes;
1099 s->dbc -= bytes;
1100 int i = 0;
1101 while (i < bytes) {
1102 uint8_t msg = buf[i++];
1103 s->sfbr = msg;
1104
1105 switch (msg) {
1106 case SCSI_MSG_COMMAND_COMPLETE:
1107 /* 0x00 - NOP / padding byte / Command Complete */
1108 /* Just gonna ignore padding bytes, continue processing */
1109 break;
1110
1111 case SCSI_MSG_DISCONNECT: /* 0x04 - Disconnect */
1112 ncr710_disconnect(s);
1113 break;
1114
1115 case SCSI_MSG_MESSAGE_REJECT: /* 0x07 - Message Reject */
1116 /* Target is rejecting our last message */
1117 ncr710_set_phase(s, PHASE_CO);
1118 break;
1119
1120 case SCSI_MSG_NO_OPERATION: /* 0x08 - NOP */
1121 ncr710_set_phase(s, PHASE_CO);
1122 break;
1123
1124 case SCSI_MSG_SAVE_DATA_POINTER: /* 0x02 - Save Data Pointer */
1125 /* Save current data pointer for later restore */
1126 break;
1127
1128 case SCSI_MSG_RESTORE_POINTERS: /* 0x03 - Restore Pointers */
1129 /* Restore previously saved data pointer */
1130 break;
1131
1132 case SCSI_MSG_EXTENDED_MESSAGE: { /* 0x01 - Extended message */
1133 if (i >= bytes) {
1134 /* Not enough data; let next chunk continue parsing */
1135 i--; /* rewind one to reparse later */
1136 goto out_chunk;
1137 }
1138 i++; /* skip ext_len */
1139
1140 if (i >= bytes) {
1141 i -= 2; /* rewind msg + ext_len for next chunk */
1142 goto out_chunk;
1143 }
1144 uint8_t ext_code = buf[i++];
1145
1146 switch (ext_code) {
1147 case 1: /* SDTR (ignore body) */
1148 /* Body has 2 bytes, may span chunks: skip what we have */
1149 {
1150 int skip = MIN(2, bytes - i);
1151 i += skip;
1152 /*
1153 * If not all skipped this chunk, rest will arrive
1154 * in next loop
1155 */
1156 }
1157 break;
1158 case 3: /* WDTR (ignore body) */
1159 if (i < bytes) {
1160 i++; /* skip one param byte if present this chunk */
1161 }
1162 break;
1163 default:
1164 goto bad;
1165 }
1166 break;
1167 }
1168
1169 case 0x20: /* SIMPLE queue tag */
1170 case 0x21: /* HEAD of queue tag */
1171 case 0x22: /* ORDERED queue tag */
1172 if (i < bytes) {
1173 uint8_t tag = buf[i++];
1174 s->select_tag = (s->select_tag & 0xFF00) | tag |
1175 NCR710_TAG_VALID;
1176 NCR710_DPRINTF("Tagged command: tag=0x%02x, "
1177 "type=0x%02x\n", tag, msg);
1178 } else {
1179 /*
1180 * Tag byte not in this chunk; rewind and reparse
1181 * next loop
1182 */
1183 i--;
1184 goto out_chunk;
1185 }
1186 break;
1187
1188 case 0x0d: /* ABORT TAG */
1189 if (current_req) {
1190 scsi_req_cancel(current_req->req);
1191 }
1192 ncr710_disconnect(s);
1193 break;
1194
1195 case SCSI_MSG_ABORT: /* 0x06 - ABORT */
1196 case 0x0e: /* CLEAR QUEUE */
1197 case SCSI_MSG_BUS_DEVICE_RESET: /* 0x0c - BUS DEVICE RESET */
1198 if (s->current) {
1199 scsi_req_cancel(s->current->req);
1200 }
1201 ncr710_disconnect(s);
1202 break;
1203
1204 default:
1205 if (msg & SCSI_MSG_IDENTIFY) {
1206 uint8_t lun = msg & 0x07;
1207 s->current_lun = lun;
1208 ncr710_set_phase(s, PHASE_CO);
1209 break;
1210 }
1211
1212 /* Unknown message - reject it */
1213 goto bad;
1214 }
1215 }
1216
1217 out_chunk:
1218 continue;
1219 }
1220
1221 return;
1222
1223 bad:
1224 BADF("Unimplemented/Invalid message 0x%02x\n", s->sfbr);
1225 ncr710_set_phase(s, PHASE_MI);
1226 ncr710_add_msg_byte(s, 7);
1227 s->msg_action = NCR710_MSG_ACTION_NONE;
1228 }
1229
1230 static void ncr710_memcpy(NCR710State *s, uint32_t dest, uint32_t src,
1231 int count)
1232 {
1233 uint8_t buf[NCR710_BUF_SIZE];
1234
1235 while (count) {
1236 int chunk = MIN(count, NCR710_BUF_SIZE);
1237 /* Read from source */
1238 ncr710_dma_read(s, src, buf, chunk);
1239
1240 /* Write to destination */
1241 ncr710_dma_write(s, dest, buf, chunk);
1242
1243 src += chunk;
1244 dest += chunk;
1245 count -= chunk;
1246 }
1247 }
1248
1249 static void ncr710_wait_reselect(NCR710State *s)
1250 {
1251 s->wait_reselect = true;
1252 s->waiting = NCR710_WAIT_RESELECT;
1253 s->script_active = false;
1254
1255 s->scntl1 &= ~NCR710_SCNTL1_CON;
1256 s->istat &= ~NCR710_ISTAT_CON;
1257 }
1258
1259 void ncr710_reselection_retry_callback(void *opaque)
1260 {
1261 NCR710State *s = opaque;
1262
1263 if (!s->current || s->current->pending == 0) {
1264 return;
1265 }
1266
1267 if (s->waiting != NCR710_WAIT_RESELECT) {
1268 return;
1269 }
1270
1271 if (s->istat & (NCR710_ISTAT_SIP | NCR710_ISTAT_DIP)) {
1272 timer_mod(s->reselection_retry_timer,
1273 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 1000);
1274 return;
1275 }
1276
1277 NCR710Request *p = s->current;
1278 uint32_t len = p->pending;
1279 p->pending = 0;
1280
1281 SCSIRequest *req = p->req;
1282 s->command_complete = NCR710_CMD_PENDING;
1283 p->dma_len = len;
1284
1285 s->scntl1 |= NCR710_SCNTL1_CON;
1286 s->istat |= NCR710_ISTAT_CON;
1287 s->sbcl = NCR710_SBCL_IO | NCR710_SBCL_CD | NCR710_SBCL_MSG |
1288 NCR710_SBCL_BSY | NCR710_SBCL_SEL | NCR710_SBCL_REQ;
1289
1290 uint8_t host_id = (s->scid & 0x07);
1291 if (req->dev->id == 0 && host_id == 0) {
1292 s->sfbr = 0x00;
1293 } else {
1294 s->sfbr = (req->dev->id == 0 ? 0 : (1 << req->dev->id)) |
1295 (host_id == 0 ? 0 : (1 << host_id));
1296 }
1297
1298 ncr710_set_phase(s, PHASE_MI);
1299
1300 uint8_t identify_msg = 0x80 | (req->lun & 0x07);
1301 ncr710_add_msg_byte(s, identify_msg);
1302
1303 if (p->tag) {
1304 ncr710_add_msg_byte(s, 0x20); /* SIMPLE_TAG_MSG */
1305 ncr710_add_msg_byte(s, p->tag & 0xff);
1306 }
1307
1308 s->dsp = p->resume_offset - 8;
1309
1310 s->dsps = RESELECTED_DURING_SELECTION;
1311 s->sstat0 |= NCR710_SSTAT0_SEL;
1312 s->istat |= NCR710_ISTAT_SIP;
1313 ncr710_update_irq(s);
1314 s->waiting = NCR710_WAIT_NONE;
1315 }
1316
1317 void ncr710_execute_script(NCR710State *s)
1318 {
1319 uint32_t insn;
1320 uint32_t addr;
1321 int opcode;
1322 s->script_active = 1;
1323
1324 again:
1325 insn = ncr710_read_dword(s, s->dsp);
1326 if (!insn) {
1327 /*
1328 * If we receive an empty opcode increment the DSP by 4 bytes
1329 * and execute the next opcode at that location
1330 */
1331 s->dsp += 4;
1332 goto again;
1333 }
1334 addr = ncr710_read_dword(s, s->dsp + 4);
1335 s->dsps = addr;
1336 s->dcmd = insn >> 24;
1337 s->dsp += 8;
1338 switch (insn >> 30) {
1339 case 0: /* Block move. */
1340 if (s->sstat0 & NCR710_SSTAT0_STO) {
1341 NCR710_DPRINTF("Delayed select timeout\n");
1342 ncr710_stop_script(s);
1343 ncr710_update_irq(s);
1344 break;
1345 }
1346 s->dbc = insn & 0xffffff;
1347 if (insn & (1 << 29)) {
1348 /* Indirect addressing. */
1349 addr = ncr710_read_dword(s, addr);
1350 } else if (insn & (1 << 28)) {
1351 uint32_t buf[2];
1352 int32_t offset;
1353 /* Table indirect addressing. */
1354
1355 /* 32-bit Table indirect */
1356 offset = sextract32(addr, 0, 24);
1357 ncr710_dma_read(s, s->dsa + offset, buf, 8);
1358 /* byte count is stored in bits 0:23 only */
1359 s->dbc = be32_to_cpu(buf[0]) & 0xffffff;
1360 addr = be32_to_cpu(buf[1]);
1361 }
1362 /* Check phase match for block move instructions */
1363 if ((s->sstat2 & PHASE_MASK) != ((insn >> 24) & 7)) {
1364 uint8_t current_phase = s->sstat2 & PHASE_MASK;
1365
1366 ncr710_set_phase(s, current_phase);
1367 s->sbcl |= NCR710_SBCL_REQ;
1368 ncr710_script_scsi_interrupt(s, NCR710_SSTAT0_MA);
1369 ncr710_stop_script(s);
1370 break;
1371 }
1372
1373 s->dnad = addr;
1374 switch (s->sstat2 & 0x7) {
1375 case PHASE_DO:
1376 s->waiting = NCR710_WAIT_DMA;
1377 ncr710_do_dma(s, 1);
1378 break;
1379 case PHASE_DI:
1380 s->waiting = NCR710_WAIT_DMA;
1381 ncr710_do_dma(s, 0);
1382 break;
1383 case PHASE_CO:
1384 ncr710_do_command(s);
1385 break;
1386 case PHASE_SI:
1387 ncr710_do_status(s);
1388 break;
1389 case PHASE_MO:
1390 ncr710_do_msgout(s);
1391 break;
1392 case PHASE_MI:
1393 ncr710_do_msgin(s);
1394 break;
1395 default:
1396 BADF("Unimplemented phase %d\n", s->sstat2 & PHASE_MASK);
1397 }
1398 s->ctest5 = (s->ctest5 & 0xfc) | ((s->dbc >> 8) & 3);
1399 s->sbcl = s->dbc;
1400 break;
1401
1402 case 1: /* IO or Read/Write instruction. */
1403 opcode = (insn >> 27) & 7;
1404 if (opcode < 5) {
1405 uint32_t id;
1406
1407 if (insn & (1 << 25)) {
1408 id = ncr710_read_dword(s, s->dsa + sextract32(insn, 0, 24));
1409 } else {
1410 id = insn;
1411 }
1412 id = (id >> 16) & 0xff;
1413 if (insn & (1 << 26)) {
1414 addr = s->dsp + sextract32(addr, 0, 24);
1415 }
1416 s->dnad = addr;
1417 switch (opcode) {
1418 case 0: /* Select */
1419 s->sdid = id;
1420 if (s->scntl1 & NCR710_SCNTL1_CON) {
1421 if (!(insn & (1 << 24))) {
1422 s->dsp = s->dnad;
1423 break;
1424 }
1425 }
1426 bool device_exists = false;
1427 if (insn & (1 << 24)) {
1428 /* ATN set - scan all LUNs for this target */
1429 for (int lun = 0; lun < 8; lun++) {
1430 SCSIDevice *dev = scsi_device_find(&s->bus, 0,
1431 idbitstonum(id),
1432 lun);
1433 if (dev) {
1434 device_exists = true;
1435 break;
1436 }
1437 }
1438 } else {
1439 /* No ATN - check only LUN 0 */
1440 SCSIDevice *dev = scsi_device_find(&s->bus, 0,
1441 idbitstonum(id), 0);
1442 device_exists = dev != NULL;
1443 }
1444 if (!device_exists) {
1445 ncr710_bad_selection(s, id);
1446 if (!(insn & (1 << 24)) && addr != 0) {
1447 s->dsp = addr;
1448 }
1449 break;
1450 } else {
1451 /*
1452 * ??? Linux drivers compain when this is set. Maybe
1453 * it only applies in low-level mode (unimplemented).
1454 * ncr710_script_scsi_interrupt(s, NCR710_SIST0_CMP, 0);
1455 */
1456 s->select_tag = id << 8;
1457 s->scntl1 |= NCR710_SCNTL1_CON;
1458
1459 if (insn & (1 << 24)) {
1460 s->socl |= NCR710_SOCL_ATN;
1461 ncr710_set_phase(s, PHASE_MO);
1462 } else {
1463 ncr710_set_phase(s, PHASE_CO);
1464 }
1465 }
1466 break;
1467 case 1: /* Disconnect */
1468
1469 if (s->command_complete != NCR710_CMD_PENDING) {
1470 s->scntl1 &= ~NCR710_SCNTL1_CON;
1471 s->istat &= ~NCR710_ISTAT_CON;
1472 s->waiting = NCR710_WAIT_NONE;
1473 } else {
1474 if (s->current) {
1475 s->current->resume_offset = s->dsp;
1476 }
1477
1478 s->waiting = NCR710_WAIT_RESELECT;
1479 ncr710_stop_script(s);
1480 NCR710_DPRINTF("SCRIPTS paused at WAIT DISCONNECT\n");
1481 }
1482 break;
1483 case 2: /* Wait Reselect */
1484 if (!ncr710_irq_on_rsl(s)) {
1485 ncr710_wait_reselect(s);
1486 }
1487 break;
1488 case 3: /* Set */
1489 if (insn & (1 << 3)) {
1490 s->socl |= NCR710_SOCL_ATN;
1491 ncr710_set_phase(s, PHASE_MO);
1492 }
1493 if (insn & (1 << 10)) {
1494 s->carry = 1;
1495 }
1496 break;
1497 case 4: /* Clear */
1498 if (insn & (1 << 3)) {
1499 s->socl &= ~NCR710_SOCL_ATN;
1500 }
1501 if (insn & (1 << 10)) {
1502 s->carry = 0;
1503 }
1504 break;
1505 }
1506 } else {
1507 uint8_t op0;
1508 uint8_t op1;
1509 uint8_t data8;
1510 int reg;
1511 int xoperator;
1512
1513 reg = ((insn >> 16) & 0x7f) | (insn & 0x80);
1514 data8 = (insn >> 8) & 0xff;
1515 opcode = (insn >> 27) & 7;
1516 xoperator = (insn >> 24) & 7;
1517 op0 = op1 = 0;
1518 switch (opcode) {
1519 case 5: /* From SFBR */
1520 op0 = s->sfbr;
1521 op1 = data8;
1522 break;
1523 case 6: /* To SFBR */
1524 if (xoperator) {
1525 op0 = ncr710_reg_readb(s, reg);
1526 }
1527 op1 = data8;
1528 break;
1529 case 7: /* Read-modify-write */
1530 if (xoperator) {
1531 op0 = ncr710_reg_readb(s, reg);
1532 }
1533 if (insn & (1 << 23)) {
1534 op1 = s->sfbr;
1535 } else {
1536 op1 = data8;
1537 }
1538 break;
1539 }
1540
1541 switch (xoperator) {
1542 case 0: /* move */
1543 op0 = op1;
1544 break;
1545 case 1: /* Shift left */
1546 op1 = op0 >> 7;
1547 op0 = (op0 << 1) | s->carry;
1548 s->carry = op1;
1549 break;
1550 case 2: /* OR */
1551 op0 |= op1;
1552 break;
1553 case 3: /* XOR */
1554 op0 ^= op1;
1555 break;
1556 case 4: /* AND */
1557 op0 &= op1;
1558 break;
1559 case 5: /* SHR */
1560 op1 = op0 & 1;
1561 op0 = (op0 >> 1) | (s->carry << 7);
1562 s->carry = op1;
1563 break;
1564 case 6: /* ADD */
1565 op0 += op1;
1566 s->carry = op0 < op1;
1567 break;
1568 case 7: /* ADC */
1569 op0 += op1 + s->carry;
1570 if (s->carry) {
1571 s->carry = op0 <= op1;
1572 } else {
1573 s->carry = op0 < op1;
1574 }
1575 break;
1576 }
1577
1578 switch (opcode) {
1579 case 5: /* From SFBR */
1580 case 7: /* Read-modify-write */
1581 ncr710_reg_writeb(s, reg, op0);
1582 break;
1583 case 6: /* To SFBR */
1584 s->sfbr = op0;
1585 break;
1586 }
1587 }
1588 break;
1589
1590 case 2: /* Transfer Control. */
1591 {
1592 int cond;
1593 int jmp;
1594
1595
1596 if (s->sstat0 & NCR710_SSTAT0_STO) {
1597 break;
1598 }
1599 cond = jmp = (insn & (1 << 19)) != 0;
1600 if (cond == jmp && (insn & (1 << 21))) {
1601 cond = s->carry != 0;
1602 }
1603 if (cond == jmp && (insn & (1 << 17))) {
1604 cond = (s->sstat2 & PHASE_MASK) == ((insn >> 24) & 7);
1605 }
1606 if (cond == jmp && (insn & (1 << 18))) {
1607 uint8_t mask;
1608
1609 mask = (~insn >> 8) & 0xff;
1610 cond = (s->sfbr & mask) == (insn & mask);
1611 }
1612 if (cond == jmp) {
1613 if (insn & (1 << 23)) {
1614 /* Relative address. */
1615 addr = s->dsp + sextract32(addr, 0, 24);
1616 }
1617 switch ((insn >> 27) & 7) {
1618 case 0: /* Jump */
1619 s->dsp = addr;
1620 break;
1621 case 1: /* Call */
1622 s->temp = s->dsp;
1623 s->dsp = addr;
1624 break;
1625 case 2: /* Return */
1626 if (s->temp == 0) {
1627 ncr710_script_dma_interrupt(s, NCR710_DSTAT_IID);
1628 break;
1629 }
1630 s->dsp = s->temp;
1631 break;
1632 case 3: /* Interrupt */
1633 if ((insn & (1 << 20)) != 0) {
1634 ncr710_update_irq(s);
1635 } else {
1636 if (s->dsps == GOOD_STATUS_AFTER_STATUS) {
1637 NCR710_DPRINTF("Script completion: Processing "
1638 "GOOD_STATUS_AFTER_STATUS\n");
1639 NCR710_DPRINTF("Script completion: Command state "
1640 "preserved for driver processing\n");
1641 ncr710_script_dma_interrupt(s,
1642 NCR710_DSTAT_SIR);
1643 s->command_complete = NCR710_CMD_PENDING;
1644 } else {
1645 ncr710_script_dma_interrupt(s, NCR710_DSTAT_SIR);
1646 }
1647 }
1648 break;
1649 default:
1650 ncr710_script_dma_interrupt(s, NCR710_DSTAT_IID);
1651 break;
1652 }
1653 }
1654 }
1655 break;
1656
1657 case 3:
1658 if ((insn & (1 << 29)) == 0) {
1659 /* Memory move. */
1660 uint32_t dest;
1661 /*
1662 * ??? The docs imply the destination address is loaded into
1663 * the TEMP register. However the Linux drivers rely on
1664 * the value being preserved.
1665 */
1666 dest = ncr710_read_dword(s, s->dsp);
1667 s->dsp += 4;
1668 ncr710_memcpy(s, dest, addr, insn & 0xffffff);
1669 } else {
1670 uint8_t data[8];
1671 int reg;
1672 int n;
1673 int i;
1674 bool dsa_relative = (insn & (1 << 28)) != 0;
1675 bool is_load = (insn & (1 << 24)) != 0;
1676
1677 if (dsa_relative) {
1678 addr = s->dsa + sextract32(addr, 0, 24);
1679 }
1680
1681 n = (insn & 7);
1682 if (n == 0) {
1683 n = 8; /* 0 means 8 bytes */
1684 }
1685
1686 reg = (insn >> 16) & 0xff;
1687
1688 if (is_load) {
1689 ncr710_dma_read(s, addr, data, n);
1690 for (i = 0; i < n; i++) {
1691 ncr710_reg_writeb(s, reg + i, data[i]);
1692 }
1693 } else {
1694 for (i = 0; i < n; i++) {
1695 data[i] = ncr710_reg_readb(s, reg + i);
1696 }
1697 ncr710_dma_write(s, addr, data, n);
1698 }
1699 }
1700 }
1701
1702 if (s->script_active && s->waiting == NCR710_WAIT_NONE) {
1703 if (s->dcntl & NCR710_DCNTL_SSM) {
1704 ncr710_script_dma_interrupt(s, NCR710_DSTAT_SSI);
1705 return;
1706 } else {
1707 goto again;
1708 }
1709 } else if (s->waiting == NCR710_WAIT_RESELECT) {
1710 return;
1711 } else if (s->waiting == NCR710_WAIT_DMA ||
1712 s->waiting == NCR710_WAIT_RESERVED) {
1713 if (s->command_complete == NCR710_CMD_COMPLETE) {
1714 s->waiting = NCR710_WAIT_NONE;
1715 goto again;
1716 }
1717 return;
1718 }
1719 }
1720
1721 static uint8_t ncr710_reg_readb(NCR710State *s, int offset)
1722 {
1723 uint8_t ret = 0;
1724
1725 #define CASE_GET_REG24(name, addr) \
1726 case addr: \
1727 ret = s->name & 0xff; \
1728 break; \
1729 case addr + 1: \
1730 ret = (s->name >> 8) & 0xff; \
1731 break; \
1732 case addr + 2: \
1733 ret = (s->name >> 16) & 0xff; \
1734 break;
1735
1736 #define CASE_GET_REG32(name, addr) \
1737 case addr: \
1738 ret = s->name & 0xff; \
1739 break; \
1740 case addr + 1: \
1741 ret = (s->name >> 8) & 0xff; \
1742 break; \
1743 case addr + 2: \
1744 ret = (s->name >> 16) & 0xff; \
1745 break; \
1746 case addr + 3: \
1747 ret = (s->name >> 24) & 0xff; \
1748 break;
1749
1750 switch (offset) {
1751 case NCR710_SCNTL0_REG: /* SCNTL0 */
1752 ret = s->scntl0;
1753 break;
1754 case NCR710_SCNTL1_REG: /* SCNTL1 */
1755 ret = s->scntl1;
1756 break;
1757 case NCR710_SDID_REG: /* SDID */
1758 ret = s->sdid;
1759 break;
1760 case NCR710_SIEN_REG: /* SIEN */
1761 ret = s->sien0;
1762 break;
1763 case NCR710_SCID_REG:
1764 ret = s->scid;
1765 if ((ret & 0x7F) == 0) {
1766 ret = 0x80 | NCR710_HOST_ID;
1767 } else {
1768 ret |= 0x80;
1769 }
1770 break;
1771 case NCR710_SXFER_REG: /* SXFER */
1772 ret = s->sxfer;
1773 break;
1774 case NCR710_SODL_REG: /* SODL */
1775 ret = s->sodl;
1776 break;
1777 case NCR710_SOCL_REG: /* SOCL */
1778 ret = s->socl;
1779 break;
1780 case NCR710_SFBR_REG: /* SFBR */
1781 ret = s->sfbr;
1782 break;
1783 case NCR710_SIDL_REG: /* SIDL */
1784 ret = s->sidl;
1785 break;
1786 case NCR710_SBDL_REG: /* SBDL */
1787 ret = s->sbdl;
1788 break;
1789 case NCR710_SBCL_REG: /* SBCL */
1790 ret = 0;
1791 if (s->scntl1 & NCR710_SCNTL1_CON) {
1792 ret = s->sstat2 & PHASE_MASK;
1793 ret |= s->sbcl;
1794 if (s->socl & NCR710_SOCL_ATN) {
1795 ret |= NCR710_SBCL_ATN;
1796 }
1797 }
1798 break;
1799 case NCR710_DSTAT_REG: /* DSTAT */
1800 ret = s->dstat;
1801
1802 /*
1803 * Not freeing s->current here:: driver needs it for completion
1804 * processing. It will be freed when the next command starts.
1805 */
1806 if (s->dstat & NCR710_DSTAT_SIR) {
1807 /* SIR bit set */
1808 }
1809 s->dstat = 0; /* Clear all DMA interrupt status bits */
1810 s->dstat |= NCR710_DSTAT_DFE;
1811 ncr710_update_irq(s);
1812
1813 if (s->waiting == NCR710_WAIT_RESELECT && s->current &&
1814 s->current->pending > 0) {
1815 timer_mod(s->reselection_retry_timer,
1816 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
1817 }
1818
1819 if (!s->script_active && s->current && s->current->pending > 0 &&
1820 s->command_complete == NCR710_CMD_COMPLETE) {
1821 s->current->pending = 0;
1822 s->waiting = NCR710_WAIT_NONE;
1823 ncr710_execute_script(s);
1824 }
1825
1826 if (s->waiting && s->current && s->current->pending > 0 &&
1827 s->command_complete == NCR710_CMD_COMPLETE) {
1828 s->current->pending = 0;
1829 s->waiting = NCR710_WAIT_NONE;
1830 ncr710_execute_script(s);
1831 }
1832
1833 return ret;
1834 case NCR710_SSTAT0_REG: /* SSTAT0 */
1835 ret = s->sstat0;
1836 if (s->sstat0 != 0) {
1837 s->sstat0 = 0;
1838 s->istat &= ~NCR710_ISTAT_SIP;
1839 ncr710_update_irq(s);
1840 if (s->sbcl != 0) {
1841 s->sbcl = 0;
1842 }
1843 }
1844 break;
1845 case NCR710_SSTAT1_REG: /* SSTAT1 */
1846 ret = s->sstat0;
1847 break;
1848 case NCR710_SSTAT2_REG: /* SSTAT2 */
1849 ret = s->sstat2;
1850 break;
1851 CASE_GET_REG32(dsa, NCR710_DSA_REG)
1852 break;
1853 case NCR710_CTEST0_REG: /* CTEST0 */
1854 ret = s->ctest0;
1855 break;
1856 case NCR710_CTEST1_REG: /* CTEST1 */
1857 ret = s->ctest1;
1858 break;
1859 case NCR710_CTEST2_REG: /* CTEST2 */
1860 ret = s->ctest2;
1861 s->ctest2 |= 0x04;
1862 break;
1863 case NCR710_CTEST3_REG: /* CTEST3 */
1864 ret = s->ctest3;
1865 if (!ncr710_scsi_fifo_empty(&s->scsi_fifo)) {
1866 uint8_t parity;
1867 ret = ncr710_scsi_fifo_dequeue(&s->scsi_fifo, &parity);
1868 if (parity) {
1869 s->ctest2 |= 0x10;
1870 } else {
1871 s->ctest2 &= ~0x10;
1872 }
1873 }
1874 break;
1875 case NCR710_CTEST4_REG: /* CTEST4 */
1876 ret = s->ctest4;
1877 break;
1878 case NCR710_CTEST5_REG: /* CTEST5 */
1879 ret = s->ctest5;
1880 break;
1881 case NCR710_CTEST6_REG: /* CTEST6 */
1882 ret = s->ctest6;
1883 break;
1884 case NCR710_CTEST7_REG: /* CTEST7 */
1885 ret = s->ctest7;
1886 break;
1887 CASE_GET_REG32(temp, NCR710_TEMP_REG)
1888 case NCR710_DFIFO_REG: /* DFIFO */
1889 ret = s->dfifo;
1890 s->dfifo = 0; /* DMA FIFO count is always 0 */
1891 break;
1892 case NCR710_ISTAT_REG: /* ISTAT */
1893 ret = s->istat;
1894 break;
1895 case NCR710_CTEST8_REG: /* CTEST8 */
1896 ret = s->istat;
1897 break;
1898 case NCR710_LCRC_REG: /* LCRC */
1899 ret = s->lcrc;
1900 break;
1901 CASE_GET_REG24(dbc, NCR710_DBC_REG)
1902 case NCR710_DCMD_REG: /* DCMD */
1903 ret = s->dcmd;
1904 break;
1905 CASE_GET_REG32(dnad, NCR710_DNAD_REG)
1906 case NCR710_DSP_REG:
1907 ret = s->dsp & 0xff;
1908 break;
1909 case NCR710_DSP_REG + 1:
1910 ret = (s->dsp >> 8) & 0xff;
1911 break;
1912 case NCR710_DSP_REG + 2:
1913 ret = (s->dsp >> 16) & 0xff;
1914 break;
1915 case NCR710_DSP_REG + 3:
1916 ret = (s->dsp >> 24) & 0xff;
1917 if (s->dsps == GOOD_STATUS_AFTER_STATUS &&
1918 (s->dstat & NCR710_DSTAT_SIR)) {
1919 s->dstat &= ~NCR710_DSTAT_SIR;
1920 ncr710_update_irq(s);
1921 }
1922 break;
1923 case NCR710_DSPS_REG:
1924 ret = s->dsps & 0xff;
1925 break;
1926 case NCR710_DSPS_REG + 1:
1927 ret = (s->dsps >> 8) & 0xff;
1928 break;
1929 case NCR710_DSPS_REG + 2:
1930 ret = (s->dsps >> 16) & 0xff;
1931 break;
1932 case NCR710_DSPS_REG + 3:
1933 ret = (s->dsps >> 24) & 0xff;
1934 if (!(s->dstat & NCR710_DSTAT_SIR) && s->dsps != 0) {
1935 s->dsps = 0;
1936 }
1937 break;
1938 CASE_GET_REG32(scratch, NCR710_SCRATCH_REG)
1939 break;
1940 case NCR710_DMODE_REG: /* DMODE */
1941 ret = s->dmode;
1942 break;
1943 case NCR710_DIEN_REG: /* DIEN */
1944 ret = s->dien;
1945 break;
1946 case NCR710_DWT_REG: /* DWT */
1947 ret = s->dwt;
1948 break;
1949 case NCR710_DCNTL_REG: /* DCNTL */
1950 ret = s->dcntl;
1951 return ret;
1952 CASE_GET_REG32(adder, NCR710_ADDER_REG)
1953 break;
1954 default:
1955 ret = 0;
1956 break;
1957 }
1958
1959 #undef CASE_GET_REG24
1960 #undef CASE_GET_REG32
1961 return ret;
1962 }
1963
1964 static void ncr710_reg_writeb(NCR710State *s, int offset, uint8_t val)
1965 {
1966 uint8_t old_val;
1967
1968 #define CASE_SET_REG24(name, addr) \
1969 case addr: \
1970 s->name &= 0xffffff00; \
1971 s->name |= val; \
1972 break; \
1973 case addr + 1: \
1974 s->name &= 0xffff00ff; \
1975 s->name |= val << 8; \
1976 break; \
1977 case addr + 2: \
1978 s->name &= 0xff00ffff; \
1979 s->name |= val << 16; \
1980 break;
1981
1982 #define CASE_SET_REG32(name, addr) \
1983 case addr: \
1984 s->name &= 0xffffff00; \
1985 s->name |= val; \
1986 break; \
1987 case addr + 1: \
1988 s->name &= 0xffff00ff; \
1989 s->name |= val << 8; \
1990 break; \
1991 case addr + 2: \
1992 s->name &= 0xff00ffff; \
1993 s->name |= val << 16; \
1994 break; \
1995 case addr + 3: \
1996 s->name &= 0x00ffffff; \
1997 s->name |= val << 24; \
1998 break;
1999
2000 trace_ncr710_reg_write(ncr710_reg_name(offset), offset, val);
2001
2002 switch (offset) {
2003 case NCR710_SCNTL0_REG: /* SCNTL0 */
2004 old_val = s->scntl0;
2005 s->scntl0 = val;
2006 break;
2007
2008 case NCR710_SCNTL1_REG: /* SCNTL1 */
2009 old_val = s->scntl1;
2010 s->scntl1 = val;
2011
2012
2013 /* Handle Assert Even SCSI Parity (AESP) bit changes */
2014 if ((val & NCR710_SCNTL1_AESP) != (old_val & NCR710_SCNTL1_AESP)) {
2015 trace_ncr710_parity_sense_changed((val & NCR710_SCNTL1_AESP)
2016 != 0 ? "even" : "odd");
2017 }
2018
2019 if (val & NCR710_SCNTL1_RST) {
2020 if (!(s->sstat0 & NCR710_SSTAT0_RST)) {
2021 s->sstat0 |= NCR710_SSTAT0_RST;
2022 ncr710_script_scsi_interrupt(s, NCR710_SSTAT0_RST);
2023 }
2024 if (!(old_val & NCR710_SCNTL1_RST)) {
2025 NCR710_DPRINTF("NCR710: SCNTL1: SCSI bus reset "
2026 "initiated\n");
2027 ncr710_soft_reset(s);
2028 }
2029 } else {
2030 s->sstat0 &= ~NCR710_SSTAT0_RST;
2031 }
2032 break;
2033
2034 case NCR710_SDID_REG: /* SDID */
2035 s->sdid = val & 0x0F; /* Only lower 4 bits are valid */
2036 break;
2037
2038 case NCR710_SIEN_REG: /* SIEN */
2039 s->sien0 = val;
2040 NCR710_DPRINTF("SIEN: interrupt mask=0x%02x\n", val);
2041 ncr710_update_irq(s);
2042 break;
2043
2044 case NCR710_SCID_REG: /* SCID */
2045 s->scid = val;
2046 break;
2047
2048 case NCR710_SXFER_REG: /* SXFER */
2049 s->sxfer = val;
2050 break;
2051
2052 case NCR710_SODL_REG: /* SODL */
2053 s->sodl = val;
2054 s->sstat1 |= NCR710_SSTAT1_ORF; /* SCSI Output Register Full */
2055 break;
2056
2057 case NCR710_SOCL_REG: /* SOCL */
2058 s->socl = val;
2059 break;
2060
2061 case NCR710_SFBR_REG: /* SFBR */
2062 s->sfbr = val;
2063 break;
2064
2065 case NCR710_SIDL_REG: /* SIDL */
2066 case NCR710_SBDL_REG: /* SBDL */
2067 break;
2068
2069 case NCR710_SBCL_REG: /* SBCL */
2070 s->sbcl = val;
2071 ncr710_set_phase(s, val & PHASE_MASK);
2072 break;
2073
2074 case NCR710_DSTAT_REG:
2075 case NCR710_SSTAT0_REG:
2076 case NCR710_SSTAT1_REG:
2077 case NCR710_SSTAT2_REG:
2078 /* Linux writes to these readonly registers on startup */
2079 return;
2080
2081 case NCR710_DSA_REG:
2082 s->dsa &= 0xffffff00;
2083 s->dsa |= val;
2084 break;
2085 case NCR710_DSA_REG + 1:
2086 s->dsa &= 0xffff00ff;
2087 s->dsa |= val << 8;
2088 break;
2089 case NCR710_DSA_REG + 2:
2090 s->dsa &= 0xff00ffff;
2091 s->dsa |= val << 16;
2092 break;
2093 case NCR710_DSA_REG + 3:
2094 s->dsa &= 0x00ffffff;
2095 s->dsa |= val << 24;
2096 break;
2097
2098 case NCR710_CTEST0_REG: /* CTEST0 */
2099 s->ctest0 = val;
2100 break;
2101
2102 case NCR710_CTEST1_REG: /* CTEST1, read-only */
2103 s->ctest1 = val;
2104 break;
2105
2106 case NCR710_CTEST2_REG: /* CTEST2, read-only */
2107 s->ctest2 = val;
2108 break;
2109
2110 case NCR710_CTEST3_REG: /* CTEST3 */
2111 s->ctest3 = val;
2112 break;
2113
2114 case NCR710_CTEST4_REG: /* CTEST4 */
2115 s->ctest4 = val;
2116 break;
2117
2118 case NCR710_CTEST5_REG: /* CTEST5 */
2119 s->ctest5 = val;
2120 break;
2121
2122 case NCR710_CTEST6_REG: /* CTEST6 */
2123 s->ctest6 = val;
2124 break;
2125
2126 case NCR710_CTEST7_REG: /* CTEST7 */
2127 s->ctest7 = val;
2128 break;
2129
2130 CASE_SET_REG32(temp, NCR710_TEMP_REG)
2131
2132 case NCR710_DFIFO_REG: /* DFIFO, read-only */
2133 break;
2134
2135 case NCR710_ISTAT_REG: /* ISTAT */
2136 old_val = s->istat;
2137
2138 if ((old_val & NCR710_ISTAT_DIP) && !(val & NCR710_ISTAT_DIP)) {
2139 /* Clear script interrupt data after Linux processes it */
2140 s->dstat = 0;
2141 s->dsps = 0;
2142 }
2143
2144 if ((old_val & NCR710_ISTAT_SIP) && !(val & NCR710_ISTAT_SIP)) {
2145 s->sstat0 = 0;
2146 }
2147
2148 s->istat = (val & ~(NCR710_ISTAT_DIP | NCR710_ISTAT_SIP)) |
2149 (s->istat & (NCR710_ISTAT_DIP | NCR710_ISTAT_SIP));
2150 ncr710_update_irq(s);
2151
2152 if (val & NCR710_ISTAT_ABRT) {
2153 ncr710_script_dma_interrupt(s, NCR710_DSTAT_ABRT);
2154 }
2155 break;
2156
2157 case NCR710_CTEST8_REG: /* CTEST8 */
2158 if (val & 0x08) {
2159 s->dstat |= NCR710_DSTAT_DFE;
2160 }
2161 if (val & 0x04) {
2162 ncr710_scsi_fifo_init(&s->scsi_fifo);
2163 s->dstat |= NCR710_DSTAT_DFE;
2164 s->ctest1 = 0xFF;
2165 } else if (s->ctest8 & 0x04) {
2166 s->ctest1 = 0x00;
2167 }
2168 s->ctest8 = val;
2169 break;
2170 case NCR710_LCRC_REG: /* LCRC */
2171 s->lcrc = val;
2172 break;
2173
2174 CASE_SET_REG24(dbc, NCR710_DBC_REG)
2175
2176 case NCR710_DCMD_REG: /* DCMD */
2177 s->dcmd = val;
2178 break;
2179
2180 CASE_SET_REG32(dnad, NCR710_DNAD_REG)
2181 case 0x2c: /* DSP[0:7] */
2182 s->dsp &= 0xffffff00;
2183 s->dsp |= val;
2184 break;
2185 case 0x2d: /* DSP[8:15] */
2186 s->dsp &= 0xffff00ff;
2187 s->dsp |= val << 8;
2188 break;
2189 case 0x2e: /* DSP[16:23] */
2190 s->dsp &= 0xff00ffff;
2191 s->dsp |= val << 16;
2192 break;
2193 case 0x2f: /* DSP[24:31] */
2194 s->dsp &= 0x00ffffff;
2195 s->dsp |= val << 24;
2196 s->waiting = NCR710_WAIT_NONE;
2197 s->script_active = 1;
2198 s->istat |= NCR710_ISTAT_CON;
2199 ncr710_clear_selection_timeout(s);
2200 ncr710_execute_script(s);
2201 break;
2202 CASE_SET_REG32(dsps, NCR710_DSPS_REG)
2203 CASE_SET_REG32(scratch, NCR710_SCRATCH_REG)
2204 break;
2205
2206 case NCR710_DMODE_REG: /* DMODE */
2207 s->dmode = val;
2208 break;
2209
2210 case NCR710_DIEN_REG: /* DIEN */
2211 s->dien = val;
2212 NCR710_DPRINTF("DIEN: interrupt enable=0x%02x\n", val);
2213 ncr710_update_irq(s);
2214 break;
2215
2216 case NCR710_DWT_REG: /* DWT */
2217 s->dwt = val;
2218 break;
2219
2220 case NCR710_DCNTL_REG: /* DCNTL */
2221 s->dcntl = val & ~(NCR710_DCNTL_PFF);
2222 if (val & NCR710_DCNTL_STD) {
2223 s->waiting = NCR710_WAIT_NONE;
2224 ncr710_execute_script(s);
2225 s->dcntl &= ~NCR710_DCNTL_STD;
2226 }
2227 break;
2228
2229 CASE_SET_REG32(adder, NCR710_ADDER_REG)
2230 break;
2231
2232 default:
2233 break;
2234 }
2235
2236 #undef CASE_SET_REG24
2237 #undef CASE_SET_REG32
2238 }
2239
2240 /* Memory region wrapper for NCR710 registers */
2241 uint64_t ncr710_reg_read(void *opaque, hwaddr addr, unsigned size)
2242 {
2243 NCR710State *s = opaque;
2244 uint8_t offset = addr & 0xff;
2245 uint8_t val = ncr710_reg_readb(s, offset);
2246 trace_ncr710_reg_read(ncr710_reg_name(offset), offset, val);
2247 return val;
2248 }
2249
2250 void ncr710_reg_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
2251 {
2252 NCR710State *s = opaque;
2253 uint8_t offset = addr & 0xff;
2254 uint8_t val8 = val & 0xff;
2255 trace_ncr710_reg_write(ncr710_reg_name(offset), offset, val8);
2256 ncr710_reg_writeb(s, offset, val8);
2257 }
2258
2259 /* Device reset */
2260 static void ncr710_device_reset(DeviceState *dev)
2261 {
2262 SysBusNCR710State *sysbus_dev = SYSBUS_NCR710_SCSI(dev);
2263 NCR710State *s = &sysbus_dev->ncr710;
2264
2265 ncr710_soft_reset(s);
2266 }
2267
2268 static const struct SCSIBusInfo ncr710_scsi_info = {
2269 .tcq = true,
2270 .max_target = 8,
2271 .max_lun = 8, /* Full LUN support */
2272
2273 .transfer_data = ncr710_transfer_data,
2274 .complete = ncr710_command_complete,
2275 .cancel = ncr710_request_cancelled,
2276 };
2277
2278 static const MemoryRegionOps ncr710_mmio_ops = {
2279 .read = ncr710_reg_read,
2280 .write = ncr710_reg_write,
2281 .endianness = DEVICE_LITTLE_ENDIAN,
2282 .valid = {
2283 .min_access_size = 1,
2284 .max_access_size = 4,
2285 },
2286 };
2287
2288 static const VMStateDescription vmstate_ncr710_scsi_fifo = {
2289 .name = "ncr710_scsi_fifo",
2290 .version_id = 1,
2291 .minimum_version_id = 1,
2292 .fields = (VMStateField[]) {
2293 VMSTATE_UINT8_ARRAY(data, NCR710_SCSI_FIFO, NCR710_SCSI_FIFO_SIZE),
2294 VMSTATE_UINT8_ARRAY(parity, NCR710_SCSI_FIFO, NCR710_SCSI_FIFO_SIZE),
2295 VMSTATE_INT32(count, NCR710_SCSI_FIFO),
2296 VMSTATE_END_OF_LIST()
2297 }
2298 };
2299
2300 const VMStateDescription vmstate_ncr710 = {
2301 .name = "ncr710",
2302 .version_id = 1,
2303 .minimum_version_id = 1,
2304 .fields = (VMStateField[]) {
2305 VMSTATE_UINT8(scntl0, NCR710State),
2306 VMSTATE_UINT8(scntl1, NCR710State),
2307 VMSTATE_UINT8(sdid, NCR710State),
2308 VMSTATE_UINT8(sien0, NCR710State),
2309 VMSTATE_UINT8(scid, NCR710State),
2310 VMSTATE_UINT8(sxfer, NCR710State),
2311 VMSTATE_UINT8(sodl, NCR710State),
2312 VMSTATE_UINT8(socl, NCR710State),
2313 VMSTATE_UINT8(sfbr, NCR710State),
2314 VMSTATE_UINT8(sidl, NCR710State),
2315 VMSTATE_UINT8(sbdl, NCR710State),
2316 VMSTATE_UINT8(sbcl, NCR710State),
2317 VMSTATE_UINT8(dstat, NCR710State),
2318 VMSTATE_UINT8(sstat0, NCR710State),
2319 VMSTATE_UINT8(sstat1, NCR710State),
2320 VMSTATE_UINT8(sstat2, NCR710State),
2321 VMSTATE_UINT8(ctest0, NCR710State),
2322 VMSTATE_UINT8(ctest1, NCR710State),
2323 VMSTATE_UINT8(ctest2, NCR710State),
2324 VMSTATE_UINT8(ctest3, NCR710State),
2325 VMSTATE_UINT8(ctest4, NCR710State),
2326 VMSTATE_UINT8(ctest5, NCR710State),
2327 VMSTATE_UINT8(ctest6, NCR710State),
2328 VMSTATE_UINT8(ctest7, NCR710State),
2329 VMSTATE_UINT8(ctest8, NCR710State),
2330 VMSTATE_UINT32(temp, NCR710State),
2331 VMSTATE_UINT8(dfifo, NCR710State),
2332 VMSTATE_UINT8(istat, NCR710State),
2333 VMSTATE_UINT8(lcrc, NCR710State),
2334 VMSTATE_UINT8(dcmd, NCR710State),
2335 VMSTATE_UINT8(dmode, NCR710State),
2336 VMSTATE_UINT8(dien, NCR710State),
2337 VMSTATE_UINT8(dwt, NCR710State),
2338 VMSTATE_UINT8(dcntl, NCR710State),
2339 VMSTATE_UINT32(dsa, NCR710State),
2340 VMSTATE_UINT32(dbc, NCR710State),
2341 VMSTATE_UINT32(dnad, NCR710State),
2342 VMSTATE_UINT32(dsp, NCR710State),
2343 VMSTATE_UINT32(dsps, NCR710State),
2344 VMSTATE_UINT32(scratch, NCR710State),
2345 VMSTATE_UINT32(adder, NCR710State),
2346 VMSTATE_STRUCT(scsi_fifo, NCR710State, 1,
2347 vmstate_ncr710_scsi_fifo, NCR710_SCSI_FIFO),
2348 VMSTATE_UINT8(status, NCR710State),
2349 VMSTATE_UINT8_ARRAY(msg, NCR710State,
2350 NCR710_MAX_MSGIN_LEN),
2351 VMSTATE_UINT8(msg_len, NCR710State),
2352 VMSTATE_UINT8(msg_action, NCR710State),
2353 VMSTATE_INT32(carry, NCR710State),
2354 VMSTATE_BOOL(script_active, NCR710State),
2355 VMSTATE_INT32(waiting, NCR710State),
2356 VMSTATE_UINT8(command_complete, NCR710State),
2357 VMSTATE_UINT32(select_tag, NCR710State),
2358 VMSTATE_UINT8(current_lun, NCR710State),
2359 VMSTATE_END_OF_LIST()
2360 }
2361 };
2362
2363 static const VMStateDescription vmstate_sysbus_ncr710 = {
2364 .name = "sysbus_ncr710",
2365 .version_id = 1,
2366 .minimum_version_id = 1,
2367 .fields = (VMStateField[]) {
2368 VMSTATE_STRUCT(ncr710, SysBusNCR710State, 1, vmstate_ncr710,
2369 NCR710State),
2370 VMSTATE_END_OF_LIST()
2371 }
2372 };
2373
2374 DeviceState *ncr710_device_create_sysbus(hwaddr addr, qemu_irq irq)
2375 {
2376 DeviceState *dev;
2377 SysBusDevice *sysbus;
2378
2379 dev = qdev_new(TYPE_SYSBUS_NCR710_SCSI);
2380 sysbus = SYS_BUS_DEVICE(dev);
2381
2382 qdev_realize_and_unref(dev, NULL, &error_abort);
2383 sysbus_mmio_map(sysbus, 0, addr);
2384 sysbus_connect_irq(sysbus, 0, irq);
2385 return dev;
2386 }
2387
2388 DeviceState *ncr53c710_init(MemoryRegion *address_space, hwaddr addr,
2389 qemu_irq irq)
2390 {
2391 DeviceState *dev;
2392 SysBusDevice *sysbus;
2393 SysBusNCR710State *s;
2394
2395 /* trace_ncr710_device_init(addr); */
2396
2397 dev = qdev_new(TYPE_SYSBUS_NCR710_SCSI);
2398 sysbus = SYS_BUS_DEVICE(dev);
2399
2400 qdev_realize_and_unref(dev, NULL, &error_abort);
2401 sysbus_mmio_map(sysbus, 0, addr);
2402 sysbus_connect_irq(sysbus, 0, irq);
2403
2404 s = SYSBUS_NCR710_SCSI(dev);
2405 if (!s->ncr710.as) {
2406 s->ncr710.as = &address_space_memory;
2407 }
2408
2409 return dev;
2410 }
2411
2412 static void sysbus_ncr710_realize(DeviceState *dev, Error **errp)
2413 {
2414 SysBusNCR710State *s = SYSBUS_NCR710_SCSI(dev);
2415
2416 trace_ncr710_device_realize();
2417 scsi_bus_init(&s->ncr710.bus, sizeof(s->ncr710.bus), dev,
2418 &ncr710_scsi_info);
2419 s->ncr710.as = &address_space_memory;
2420
2421 ncr710_scsi_fifo_init(&s->ncr710.scsi_fifo);
2422 s->ncr710.dcntl &= ~NCR710_DCNTL_COM;
2423 s->ncr710.scid = 0x80 | NCR710_HOST_ID;
2424
2425 s->ncr710.reselection_retry_timer =
2426 timer_new_ns(QEMU_CLOCK_VIRTUAL,
2427 ncr710_reselection_retry_callback,
2428 &s->ncr710);
2429
2430 memset(s->ncr710.msg, 0, sizeof(s->ncr710.msg));
2431
2432 memory_region_init_io(&s->iomem, OBJECT(s), &ncr710_mmio_ops, &s->ncr710,
2433 "ncr710", 0x100);
2434 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
2435 sysbus_init_irq(SYS_BUS_DEVICE(s), &s->ncr710.irq);
2436
2437 }
2438
2439 static void sysbus_ncr710_init(Object *obj)
2440 {
2441 SysBusNCR710State *s = SYSBUS_NCR710_SCSI(obj);
2442 memset(&s->ncr710, 0, sizeof(NCR710State));
2443 s->ncr710.ctest0 = 0x01;
2444 s->ncr710.scid = 0x80 | NCR710_HOST_ID;
2445 s->ncr710.dstat = NCR710_DSTAT_DFE;
2446 }
2447
2448 static void sysbus_ncr710_class_init(ObjectClass *oc, const void *data)
2449 {
2450 DeviceClass *dc = DEVICE_CLASS(oc);
2451
2452 dc->realize = sysbus_ncr710_realize;
2453 device_class_set_legacy_reset(dc, ncr710_device_reset);
2454 dc->bus_type = NULL;
2455 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
2456 dc->desc = "NCR53C710 SCSI I/O Processor (SysBus)";
2457 dc->vmsd = &vmstate_sysbus_ncr710;
2458 }
2459
2460 static const TypeInfo sysbus_ncr710_info = {
2461 .name = TYPE_SYSBUS_NCR710_SCSI,
2462 .parent = TYPE_SYS_BUS_DEVICE,
2463 .instance_size = sizeof(SysBusNCR710State),
2464 .instance_init = sysbus_ncr710_init,
2465 .class_init = sysbus_ncr710_class_init,
2466 };
2467
2468 static void ncr710_register_types(void)
2469 {
2470 type_register_static(&sysbus_ncr710_info);
2471 }
2472
2473 type_init(ncr710_register_types)