- pre4:
[davej-history.git] / drivers / scsi / sim710.c
blobe7489348df88043eefe478cb1b133497dc9cd1b7
1 /*
2 * sim710.c - Copyright (C) 1999 Richard Hirst <richard@sleepie.demon.co.uk>
4 *----------------------------------------------------------------------------
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *----------------------------------------------------------------------------
20 * MCA card detection code by Trent McNair.
22 * Various bits of code in this driver have been copied from 53c7,8xx,c,
23 * which is coyright Drew Eckhardt. The scripts for the SCSI chip are
24 * compiled with the script compiler written by Drew.
26 * This is a simple driver for the NCR53c710. More complex drivers
27 * for this chip (e.g. 53c7xx.c) require that the scsi chip be able to
28 * do DMA block moves between memory and on-chip registers, which can
29 * be a problem if those registers are in the I/O address space. There
30 * can also be problems on hardware where the registers are memory
31 * mapped, if the design is such that memory-to-memory transfers initiated
32 * by the scsi chip cannot access the chip registers.
34 * This driver is designed to avoid these problems and is intended to
35 * work with any Intel machines using 53c710 chips, including various
36 * Compaq and NCR machines. It was initially written for the Tadpole
37 * TP34V VME board which is 68030 based.
39 * The driver supports boot-time parameters similar to
40 * sim710=addr:0x9000,irq:15
41 * and insmod parameters similar to
42 * sim710="addr:0x9000 irq:15"
44 * The complete list of options are:
46 * addr:0x9000 Specifies the base I/O port (or address) of the 53C710.
47 * irq:15 Specifies the IRQ number used by the 53c710.
48 * debug:0xffff Generates lots of debug output.
49 * ignore:0x0a Makes the driver ignore SCSI IDs 0 and 2.
50 * nodisc:0x70 Prevents disconnects from IDs 6, 5 and 4.
51 * noneg:0x10 Prevents SDTR negotiation on ID 4.
53 * Current limitations:
55 * o Async only
56 * o Severely lacking in error recovery
57 * o Auto detection of IRQs and chip addresses only on MCA architectures
61 #include <linux/config.h>
62 #include <linux/module.h>
64 #include <linux/version.h>
65 #include <linux/kernel.h>
66 #include <linux/types.h>
67 #include <linux/string.h>
68 #include <linux/ioport.h>
69 #include <linux/delay.h>
70 #include <linux/sched.h>
71 #include <linux/proc_fs.h>
72 #include <linux/init.h>
73 #include <linux/mca.h>
74 #include <asm/dma.h>
75 #include <asm/system.h>
76 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,17)
77 #include <linux/spinlock.h>
78 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93)
79 #include <asm/spinlock.h>
80 #endif
81 #include <asm/io.h>
82 #include <asm/pgtable.h>
83 #include <asm/byteorder.h>
84 #include <linux/blk.h>
86 #ifdef CONFIG_TP34V_SCSI
88 #include <asm/tp34vhw.h>
89 #define MEM_MAPPED
91 #elif defined(CONFIG_MCA)
93 #define IO_MAPPED
96 * For each known microchannel card using the 53c710 we need a list
97 * of possible IRQ and IO settings, as well as their corresponding
98 * bit assignment in pos[]. This might get cumbersome if there
99 * are more than a few cards (I only know of 2 at this point).
102 #define MCA_53C710_IDS { 0x01bb, 0x01ba, 0x004f }
104 /* CARD ID 01BB and 01BA use the same pos values */
106 #define MCA_01BB_IO_PORTS { 0x0000, 0x0000, 0x0800, 0x0C00, 0x1000, 0x1400, \
107 0x1800, 0x1C00, 0x2000, 0x2400, 0x2800, \
108 0x2C00, 0x3000, 0x3400, 0x3800, 0x3C00, \
109 0x4000, 0x4400, 0x4800, 0x4C00, 0x5000 }
111 #define MCA_01BB_IRQS { 3, 5, 11, 14 }
113 /* CARD ID 004f */
115 #define MCA_004F_IO_PORTS { 0x0000, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600 }
117 #define MCA_004F_IRQS { 5, 9, 14 }
119 #else
121 /* Assume an Intel platform */
123 #define IO_MAPPED
125 #endif
127 #include "scsi.h"
128 #include "hosts.h"
129 #include "sim710.h"
131 #include<linux/stat.h>
133 #define DEBUG
134 #undef DEBUG_LIMIT_INTS /* Define to 10 to hang driver after 10 ints */
136 /* Debug options available via the "debug:0x1234" parameter */
138 #define DEB_NONE 0x0000 /* Nothing */
139 #define DEB_HALT 0x0001 /* Detailed trace of chip halt funtion */
140 #define DEB_REGS 0x0002 /* All chip register read/writes */
141 #define DEB_SYNC 0x0004 /* Sync/async negotiation */
142 #define DEB_PMM 0x0008 /* Phase mis-match handling */
143 #define DEB_INTS 0x0010 /* General interrupt trace */
144 #define DEB_TOUT 0x0020 /* Selection timeouts */
145 #define DEB_RESUME 0x0040 /* Resume addresses for the script */
146 #define DEB_CMND 0x0080 /* Commands and status returned */
147 #define DEB_FIXUP 0x0100 /* Fixup of scsi addresses */
148 #define DEB_DISC 0x0200 /* Disconnect/reselect handling */
150 #define DEB_ANY 0xffff /* Any and all debug options */
152 #ifdef DEBUG
153 #define DEB(m,x) if (sim710_debug & m) x
154 int sim710_debug = 0;
155 #else
156 #define DEB(m,x)
157 #endif
159 /* Redefine scsi_done to force renegotiation of (a)sync transfers
160 * following any failed command.
163 #define SCSI_DONE(cmd) { \
164 DEB(DEB_CMND, printk("scsi%d: Complete %08x\n", \
165 host->host_no, cmd->result)); \
166 if (cmd->result) \
167 hostdata->negotiate |= (1 << cmd->target); \
168 cmd->scsi_done(cmd); \
171 #ifndef offsetof
172 #define offsetof(t, m) ((size_t) (&((t *)0)->m))
173 #endif
175 #define STATE_INITIALISED 0
176 #define STATE_HALTED 1
177 #define STATE_IDLE 2
178 #define STATE_BUSY 3
179 #define STATE_DISABLED 4
181 #define MAXBOARDS 2 /* Increase this and the sizes of the
182 arrays below, if you need more.. */
184 #ifdef MODULE
186 char *sim710; /* command line passed by insmod */
188 MODULE_AUTHOR("Richard Hirst");
189 MODULE_DESCRIPTION("Simple NCR53C710 driver");
190 MODULE_PARM(sim710, "s");
192 #endif
194 static int sim710_errors = 0; /* Count of error interrupts */
195 static int sim710_intrs = 0; /* Count of all interrupts */
196 static int ignore_ids = 0; /* Accept all SCSI IDs */
197 static int opt_nodisc = 0; /* Allow disconnect on all IDs */
198 static int opt_noneg = 0; /* Allow SDTR negotiation on all IDs */
200 #ifdef CONFIG_TP34V_SCSI
202 /* Special hardwired case for Tadpole TP34V at the moment, otherwise
203 * boot parameters 'sim710=addr:0x8000,irq:15' (for example) must be given.
206 static int no_of_boards = 2;
208 static unsigned int bases[MAXBOARDS] = {
209 TP34V_SCSI0_BASE, TP34V_SCSI1_BASE
211 static unsigned int irq_vectors[MAXBOARDS] = {
212 TP34V_SCSI0_VECTOR, TP34V_SCSI1_VECTOR
214 static unsigned int irq_index[MAXBOARDS] = {
215 TP34V_SCSI0_IRQ_INDEX, TP34V_SCSI1_IRQ_INDEX
218 #else
220 /* All other cases use boot/module params, or auto-detect */
222 static int no_of_boards = 0;
224 static unsigned int bases[MAXBOARDS] = {
227 static unsigned int irq_vectors[MAXBOARDS] = {
231 #endif
233 /* The SCSI Script!!! */
235 #include "sim710_d.h"
237 /* Now define offsets in the DSA, as (A_dsa_xxx/4) */
239 #define DSA_SELECT (A_dsa_select/4)
240 #define DSA_MSGOUT (A_dsa_msgout/4)
241 #define DSA_CMND (A_dsa_cmnd/4)
242 #define DSA_STATUS (A_dsa_status/4)
243 #define DSA_MSGIN (A_dsa_msgin/4)
244 #define DSA_DATAIN (A_dsa_datain/4)
245 #define DSA_DATAOUT (A_dsa_dataout/4)
246 #define DSA_SIZE (A_dsa_size/4)
248 #define MAX_SG 128 /* Scatter/Gather elements */
251 #define MAX_MSGOUT 8
252 #define MAX_MSGIN 8
253 #define MAX_CMND 12
254 #define MAX_STATUS 1
256 struct sim710_hostdata{
257 int state;
258 Scsi_Cmnd * issue_queue;
259 Scsi_Cmnd * running;
260 int chip;
261 u8 negotiate;
262 u8 reselected_identify;
263 u8 msgin_buf[MAX_MSGIN];
265 struct sim710_target {
266 Scsi_Cmnd *cur_cmd;
267 u32 resume_offset;
268 u32 data_in_jump;
269 u32 data_out_jump;
270 u32 dsa[DSA_SIZE]; /* SCSI Script DSA area */
271 u8 dsa_msgout[MAX_MSGOUT];
272 u8 dsa_msgin[MAX_MSGIN];
273 u8 dsa_cdb[MAX_CMND];
274 u8 dsa_status[MAX_STATUS];
275 } target[8];
277 u32 script[sizeof(SCRIPT)/4] __attribute__ ((aligned (4)));
281 /* Template to request asynchronous transfers */
283 static const unsigned char async_message[] = {
284 EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 0, 0 /* asynchronous */};
287 static void sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs);
288 static void do_sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs);
289 static __inline__ void run_process_issue_queue(struct sim710_hostdata *);
290 static void process_issue_queue (struct sim710_hostdata *, unsigned long flags);
291 static int full_reset(struct Scsi_Host * host);
295 * Function: int param_setup(char *str)
298 #ifdef MODULE
299 #define ARG_SEP ' '
300 #else
301 #define ARG_SEP ','
302 #endif
304 static int
305 param_setup(char *str)
307 char *cur = str;
308 char *pc, *pv;
309 int val;
310 int base;
311 int c;
313 no_of_boards = 0;
314 while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
315 char *pe;
317 val = 0;
318 pv = pc;
319 c = *++pv;
321 if (c == 'n')
322 val = 0;
323 else if (c == 'y')
324 val = 1;
325 else {
326 base = 0;
327 val = (int) simple_strtoul(pv, &pe, base);
329 if (!strncmp(cur, "addr:", 5)) {
330 bases[0] = val;
331 no_of_boards = 1;
333 else if (!strncmp(cur, "irq:", 4))
334 irq_vectors[0] = val;
335 else if (!strncmp(cur, "ignore:", 7))
336 ignore_ids = val;
337 else if (!strncmp(cur, "nodisc:", 7))
338 opt_nodisc = val;
339 else if (!strncmp(cur, "noneg:", 6))
340 opt_noneg = val;
341 else if (!strncmp(cur, "disabled:", 5)) {
342 no_of_boards = -1;
343 return 1;
345 #ifdef DEBUG
346 else if (!strncmp(cur, "debug:", 6)) {
347 sim710_debug = val;
349 #endif
350 else
351 printk("sim710: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
353 if ((cur = strchr(cur, ARG_SEP)) != NULL)
354 ++cur;
356 return 1;
359 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,13)
360 #ifndef MODULE
361 __setup("sim710=", param_setup);
362 #endif
363 #else
364 /* Old boot param syntax support */
365 void
366 sim710_setup(char *str, int *ints)
368 param_setup(str);
370 #endif
374 * Function: static const char *sbcl_to_phase (int sbcl)
377 static const char *
378 sbcl_to_phase (int sbcl) {
379 switch (sbcl & SBCL_PHASE_MASK) {
380 case SBCL_PHASE_DATAIN:
381 return "DATAIN";
382 case SBCL_PHASE_DATAOUT:
383 return "DATAOUT";
384 case SBCL_PHASE_MSGIN:
385 return "MSGIN";
386 case SBCL_PHASE_MSGOUT:
387 return "MSGOUT";
388 case SBCL_PHASE_CMDOUT:
389 return "CMDOUT";
390 case SBCL_PHASE_STATIN:
391 return "STATUSIN";
392 default:
393 return "unknown";
399 * Function: static void disable (struct Scsi_Host *host)
402 static void
403 disable (struct Scsi_Host *host)
405 struct sim710_hostdata *hostdata = (struct sim710_hostdata *)
406 host->hostdata[0];
408 hostdata->state = STATE_DISABLED;
409 printk (KERN_ALERT "scsi%d : disabled. Unload and reload\n",
410 host->host_no);
415 * Function : static int ncr_halt (struct Scsi_Host *host)
417 * Purpose : halts the SCSI SCRIPTS(tm) processor on the NCR chip
419 * Inputs : host - SCSI chip to halt
421 * Returns : 0 on success
424 static int
425 ncr_halt (struct Scsi_Host *host)
427 unsigned long flags;
428 unsigned char istat, tmp;
429 struct sim710_hostdata *hostdata = (struct sim710_hostdata *)
430 host->hostdata[0];
431 int stage;
433 save_flags(flags);
434 cli();
435 /* Stage 0 : eat all interrupts
436 Stage 1 : set ABORT
437 Stage 2 : eat all but abort interrupts
438 Stage 3 : eat all interrupts
440 for (stage = 0;;) {
441 if (stage == 1) {
442 DEB(DEB_HALT, printk("ncr_halt: writing ISTAT_ABRT\n"));
443 NCR_write8(ISTAT_REG, ISTAT_ABRT);
444 ++stage;
446 istat = NCR_read8 (ISTAT_REG);
447 if (istat & ISTAT_SIP) {
448 DEB(DEB_HALT, printk("ncr_halt: got ISTAT_SIP, istat=%02x\n", istat));
449 tmp = NCR_read8(SSTAT0_REG);
450 DEB(DEB_HALT, printk("ncr_halt: got SSTAT0_REG=%02x\n", tmp));
451 } else if (istat & ISTAT_DIP) {
452 DEB(DEB_HALT, printk("ncr_halt: got ISTAT_DIP, istat=%02x\n", istat));
453 tmp = NCR_read8(DSTAT_REG);
454 DEB(DEB_HALT, printk("ncr_halt: got DSTAT_REG=%02x\n", tmp));
455 if (stage == 2) {
456 if (tmp & DSTAT_ABRT) {
457 DEB(DEB_HALT, printk("ncr_halt: got DSTAT_ABRT, clearing istat\n"));
458 NCR_write8(ISTAT_REG, 0);
459 ++stage;
460 } else {
461 printk(KERN_ALERT "scsi%d : could not halt NCR chip\n",
462 host->host_no);
463 disable (host);
467 if (!(istat & (ISTAT_SIP|ISTAT_DIP))) {
468 if (stage == 0)
469 ++stage;
470 else if (stage == 3)
471 break;
474 hostdata->state = STATE_HALTED;
475 restore_flags(flags);
476 return 0;
480 * Function : static void sim710_soft_reset (struct Scsi_Host *host)
482 * Purpose : perform a soft reset of the NCR53c7xx chip
484 * Inputs : host - pointer to this host adapter's structure
486 * Preconditions : sim710_init must have been called for this
487 * host.
491 static void
492 sim710_soft_reset (struct Scsi_Host *host)
494 unsigned long flags;
495 #ifdef CONFIG_TP34V_SCSI
496 struct sim710_hostdata *hostdata = (struct sim710_hostdata *)
497 host->hostdata[0];
498 #endif
500 save_flags(flags);
501 cli();
502 #ifdef CONFIG_TP34V_SCSI
503 tpvic.loc_icr[irq_index[hostdata->chip]].icr = 0x80;
504 #endif
506 * Do a soft reset of the chip so that everything is
507 * reinitialized to the power-on state.
509 * Basically follow the procedure outlined in the NCR53c700
510 * data manual under Chapter Six, How to Use, Steps Necessary to
511 * Start SCRIPTS, with the exception of actually starting the
512 * script and setting up the synchronous transfer gunk.
515 /* XXX Should we reset the scsi bus here? */
517 NCR_write8(SCNTL1_REG, SCNTL1_RST); /* Reset the bus */
518 udelay(50);
519 NCR_write8(SCNTL1_REG, 0);
521 udelay(500);
523 NCR_write8(ISTAT_REG, ISTAT_10_SRST); /* Reset the chip */
524 udelay(50);
525 NCR_write8(ISTAT_REG, 0);
527 mdelay(1000); /* Let devices recover */
529 NCR_write8(DCNTL_REG, DCNTL_10_COM | DCNTL_700_CF_3);
530 NCR_write8(CTEST7_REG, CTEST7_10_CDIS|CTEST7_STD);
531 NCR_write8(DMODE_REG, DMODE_10_BL_8 | DMODE_10_FC2);
532 NCR_write8(SCID_REG, 1 << host->this_id);
533 NCR_write8(SBCL_REG, 0);
534 NCR_write8(SXFER_REG, 0);
535 NCR_write8(SCNTL1_REG, SCNTL1_ESR_700);
536 NCR_write8(SCNTL0_REG, SCNTL0_EPC | SCNTL0_EPG_700 | SCNTL0_ARB1 |
537 SCNTL0_ARB2);
539 NCR_write8(DIEN_REG, DIEN_700_BF |
540 DIEN_ABRT | DIEN_SSI | DIEN_SIR | DIEN_700_OPC);
542 NCR_write8(SIEN_REG_700,
543 SIEN_PAR | SIEN_700_STO | SIEN_RST | SIEN_UDC | SIEN_SGE | SIEN_MA);
546 #ifdef CONFIG_TP34V_SCSI
547 tpvic.loc_icr[irq_index[hostdata->chip]].icr = 0x30 | TP34V_SCSI0n1_IPL;
548 #endif
550 restore_flags(flags);
555 * Function : static void sim710_driver_init (struct Scsi_Host *host)
557 * Purpose : Initialize internal structures, as required on startup, or
558 * after a SCSI bus reset.
560 * Inputs : host - pointer to this host adapter's structure
563 static void
564 sim710_driver_init (struct Scsi_Host *host)
566 struct sim710_hostdata *hostdata = (struct sim710_hostdata *)
567 host->hostdata[0];
568 int i;
570 hostdata->running = NULL;
571 memcpy (hostdata->script, SCRIPT, sizeof(SCRIPT));
572 for (i = 0; i < PATCHES; i++)
573 hostdata->script[LABELPATCHES[i]] += virt_to_bus(hostdata->script);
574 patch_abs_32 (hostdata->script, 0, reselected_identify,
575 virt_to_bus((void *)&(hostdata->reselected_identify)));
576 patch_abs_32 (hostdata->script, 0, msgin_buf,
577 virt_to_bus((void *)&(hostdata->msgin_buf[0])));
578 hostdata->state = STATE_INITIALISED;
579 hostdata->negotiate = 0xff;
583 /* Handle incoming Synchronous data transfer request. If our negotiate
584 * flag is set then this is a response to our request, otherwise it is
585 * spurious request from the target. Don't really expect target initiated
586 * SDTRs, because we always negotiate on the first command. Could still
587 * get them though..
588 * The chip is currently paused with ACK asserted o the last byte of the
589 * SDTR.
590 * resa is the resume address if the message is in response to our outgoing
591 * SDTR. Only possible on initial identify.
592 * resb is the resume address if the message exchange is initiated by the
593 * target.
596 static u32
597 handle_sdtr (struct Scsi_Host * host, Scsi_Cmnd * cmd, u32 resa, u32 resb)
599 struct sim710_hostdata *hostdata = (struct sim710_hostdata *)host->hostdata[0];
600 struct sim710_target *targdata = hostdata->target + cmd->target;
601 u32 resume_offset;
603 if (resa && hostdata->negotiate & (1 << cmd->target)) {
604 DEB(DEB_SYNC, printk("scsi%d: Response to host SDTR = %02x %02x\n",
605 host->host_no, hostdata->msgin_buf[3], hostdata->msgin_buf[4]));
606 /* We always issue an SDTR with the identify, so we must issue
607 * the CDB next.
609 resume_offset = resa;
610 hostdata->negotiate &= ~(1 << cmd->target);
612 else {
613 DEB(DEB_SYNC, printk("scsi%d: Target initiated SDTR = %02x %02x\n",
614 host->host_no, hostdata->msgin_buf[3], hostdata->msgin_buf[4]));
615 memcpy(targdata->dsa_msgout, async_message, sizeof(async_message));
616 targdata->dsa[DSA_MSGOUT] = sizeof(async_message);
617 /* I guess the target could do this anytime; we have to send our
618 * response, and then continue (sending the CDB if not already done).
620 resume_offset = resb;
622 return resume_offset;
627 * Function : static int datapath_residual (Scsi_Host *host)
629 * Purpose : return residual data count of what's in the chip.
631 * Inputs : host - SCSI host
634 static int
635 datapath_residual (struct Scsi_Host *host) {
636 int count, synchronous, sstat;
637 unsigned int ddir;
639 count = ((NCR_read8 (DFIFO_REG) & DFIFO_10_BO_MASK) -
640 (NCR_read32 (DBC_REG) & DFIFO_10_BO_MASK)) & DFIFO_10_BO_MASK;
641 synchronous = NCR_read8 (SXFER_REG) & SXFER_MO_MASK;
642 ddir = NCR_read8 (CTEST0_REG_700) & CTEST0_700_DDIR;
644 if (ddir) {
645 /* Receive */
646 if (synchronous)
647 count += (NCR_read8 (SSTAT2_REG) & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT;
648 else
649 if (NCR_read8 (SSTAT1_REG) & SSTAT1_ILF)
650 ++count;
651 } else {
652 /* Send */
653 sstat = NCR_read8 (SSTAT1_REG);
654 if (sstat & SSTAT1_OLF)
655 ++count;
656 if (synchronous && (sstat & SSTAT1_ORF))
657 ++count;
659 return count;
663 static u32
664 handle_idd (struct Scsi_Host * host, Scsi_Cmnd * cmd)
666 struct sim710_hostdata *hostdata =
667 (struct sim710_hostdata *)host->hostdata[0];
668 struct sim710_target *targdata = hostdata->target + cmd->target;
669 u32 resume_offset = 0, index;
671 index = (u32)((u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script);
673 switch (index) {
674 case Ent_wait_disc_complete/4 + 2:
675 cmd->result = targdata->dsa_status[0];
676 SCSI_DONE(cmd);
677 targdata->cur_cmd = NULL;
678 resume_offset = Ent_reselect;
679 break;
680 case Ent_wait_disc2/4 + 2:
681 /* Disconnect after command - just wait for a reselect */
682 targdata->resume_offset = Ent_resume_msgin2a;
683 resume_offset = Ent_reselect;
684 break;
685 case Ent_wait_disc3/4 + 2:
686 /* Disconnect after the data phase */
687 targdata->resume_offset = Ent_resume_msgin3a;
688 resume_offset = Ent_reselect;
689 break;
690 case Ent_wait_disc1/4 + 2:
691 /* Disconnect before command - not expected */
692 targdata->resume_offset = Ent_resume_msgin1a;
693 resume_offset = Ent_reselect;
694 break;
695 default:
696 printk("scsi%d: Unexpected Illegal Instruction, script[%04x]\n",
697 host->host_no, index);
698 sim710_errors++;
699 /* resume_offset is zero, which will cause host reset */
701 return resume_offset;
705 /* Handle a phase mismatch.
708 static u32
709 handle_phase_mismatch (struct Scsi_Host * host, Scsi_Cmnd * cmd)
711 struct sim710_hostdata *hostdata =
712 (struct sim710_hostdata *)host->hostdata[0];
713 struct sim710_target *targdata = hostdata->target + cmd->target;
714 u32 resume_offset = 0, index;
715 unsigned char sbcl;
717 sbcl = NCR_read8(SBCL_REG) & SBCL_PHASE_MASK;
718 index = (u32)((u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script);
720 DEB(DEB_PMM, printk("scsi%d: Phase mismatch, phase %s (%x) at script[0x%x]\n",
721 host->host_no, sbcl_to_phase(sbcl), sbcl, index));
722 DEB(DEB_PMM, print_command(cmd->cmnd));
724 if (index == Ent_done_ident/4) {
725 /* Sending initial message out - probably rejecting our sync
726 * negotiation request.
728 NCR_write8(SOCL_REG, 0); /* Negate ATN */
729 if (sbcl == SBCL_PHASE_MSGIN)
730 resume_offset = Ent_resume_rej_ident;
731 else if (sbcl == SBCL_PHASE_CMDOUT) {
732 /* Some old devices (SQ555) switch to cmdout after the first
733 * byte of an identify message, regardless of whether we
734 * have more bytes to send!
736 printk("scsi%d: Unexpected switch to CMDOUT during IDENTIFY\n",
737 host->host_no);
738 resume_offset = Ent_resume_cmd;
740 else {
741 printk("scsi%d: Unexpected phase change to %s on initial msgout\n",
742 host->host_no, sbcl_to_phase(sbcl));
743 /* resume_offset is zero, which will cause a host reset */
745 hostdata->negotiate &= ~(1 << cmd->target);
747 else if (index > Ent_patch_input_data/4 &&
748 index < Ent_patch_output_data/4) {
749 /* DataIn transfer phase */
750 u32 sg_id, oaddr, olen, naddr, nlen;
751 int residual;
753 sg_id = (index - Ent_patch_input_data/4 - 4) / 2;
754 targdata->data_in_jump = hostdata->script[Ent_patch_input_data/4+1] =
755 virt_to_bus(hostdata->script + Ent_patch_input_data/4 + sg_id * 2 + 2);
756 olen = targdata->dsa[DSA_DATAIN + sg_id * 2];
757 oaddr = targdata->dsa[DSA_DATAIN + sg_id * 2 + 1];
758 residual = datapath_residual (host);
759 if (residual)
760 printk("scsi%d: Residual count %d on DataIn - NOT expected!!!",
761 host->host_no, residual);
762 naddr = NCR_read32(DNAD_REG) - residual;
763 nlen = (NCR_read32(DBC_REG) & 0x00ffffff) + residual;
764 DEB(DEB_PMM, printk("scsi%d: DIN sg %d, old %08x/%08x, new %08x/%08x (%d)\n",
765 host->host_no, sg_id, oaddr, olen, naddr, nlen, residual));
766 if (oaddr+olen != naddr+nlen) {
767 printk("scsi%d: PMM DIN counts error: 0x%x + 0x%x != 0x%x + 0x%x",
768 host->host_no, oaddr, olen, naddr, nlen);
770 else {
771 targdata->dsa[DSA_DATAIN + sg_id * 2] = nlen;
772 targdata->dsa[DSA_DATAIN + sg_id * 2 + 1] = naddr;
773 resume_offset = Ent_resume_pmm;
776 else if (index > Ent_patch_output_data/4 &&
777 index <= Ent_end_data_trans/4) {
778 /* Dataout transfer phase */
779 u32 sg_id, oaddr, olen, naddr, nlen;
780 int residual;
782 sg_id = (index - Ent_patch_output_data/4 - 4) / 2;
783 targdata->data_out_jump = hostdata->script[Ent_patch_output_data/4+1] =
784 virt_to_bus(hostdata->script + Ent_patch_output_data/4 + sg_id * 2 + 2);
785 olen = targdata->dsa[DSA_DATAOUT + sg_id * 2];
786 oaddr = targdata->dsa[DSA_DATAOUT + sg_id * 2 + 1];
787 residual = datapath_residual (host);
788 naddr = NCR_read32(DNAD_REG) - residual;
789 nlen = (NCR_read32(DBC_REG) & 0x00ffffff) + residual;
790 DEB(DEB_PMM, printk("scsi%d: DOUT sg %d, old %08x/%08x, new %08x/%08x (%d)\n",
791 host->host_no, sg_id, oaddr, olen, naddr, nlen, residual));
792 if (oaddr+olen != naddr+nlen) {
793 printk("scsi%d: PMM DOUT counts error: 0x%x + 0x%x != 0x%x + 0x%x",
794 host->host_no, oaddr, olen, naddr, nlen);
796 else {
797 targdata->dsa[DSA_DATAOUT + sg_id * 2] = nlen;
798 targdata->dsa[DSA_DATAOUT + sg_id * 2 + 1] = naddr;
799 resume_offset = Ent_resume_pmm;
802 else {
803 printk("scsi%d: Unexpected phase change to %s at index 0x%x\n",
804 host->host_no, sbcl_to_phase(sbcl), index);
805 /* resume_offset is zero, which will cause a host reset */
807 /* Flush DMA FIFO */
808 NCR_write8 (CTEST8_REG, CTEST8_10_CLF);
809 while (NCR_read8 (CTEST8_REG) & CTEST8_10_CLF);
811 return resume_offset;
815 static u32
816 handle_script_int(struct Scsi_Host * host, Scsi_Cmnd * cmd)
818 struct sim710_hostdata *hostdata =
819 (struct sim710_hostdata *)host->hostdata[0];
820 struct sim710_target *targdata = hostdata->target + cmd->target;
821 u32 dsps, resume_offset = 0;
822 unsigned char sbcl;
824 dsps = NCR_read32(DSPS_REG);
826 switch (dsps) {
827 case A_int_cmd_complete:
828 cmd->result = targdata->dsa_status[0];
829 SCSI_DONE(cmd);
830 targdata->cur_cmd = NULL;
831 resume_offset = Ent_reselect;
832 break;
833 case A_int_msg_sdtr1:
834 resume_offset = handle_sdtr(host, cmd,
835 Ent_resume_msgin1a, Ent_resume_msgin1b);
836 break;
837 case A_int_msg_sdtr2:
838 resume_offset = handle_sdtr(host, cmd, 0, Ent_resume_msgin2b);
839 break;
840 case A_int_msg_sdtr3:
841 resume_offset = handle_sdtr(host, cmd, 0, Ent_resume_msgin3b);
842 break;
843 case A_int_disc1:
844 /* Disconnect before command - not expected */
845 targdata->resume_offset = Ent_resume_msgin1a;
846 resume_offset = Ent_reselect;
847 break;
848 case A_int_disc2:
849 /* Disconnect after command - just wait for a reselect */
850 targdata->resume_offset = Ent_resume_msgin2a;
851 resume_offset = Ent_reselect;
852 break;
853 case A_int_disc3:
854 /* Disconnect after the data phase */
855 targdata->resume_offset = Ent_resume_msgin3a;
856 resume_offset = Ent_reselect;
857 break;
858 case A_int_reselected:
859 hostdata->script[Ent_patch_output_data/4+1] = targdata->data_out_jump;
860 hostdata->script[Ent_patch_input_data/4+1] = targdata->data_in_jump;
861 NCR_write32(DSA_REG, virt_to_bus(targdata->dsa));
862 resume_offset = targdata->resume_offset;
863 break;
864 case A_int_data_bad_phase:
865 sbcl = NCR_read8(SBCL_REG) & SBCL_PHASE_MASK;
866 printk("scsi%d: int_data_bad_phase, phase %s (%x)\n",
867 host->host_no, sbcl_to_phase(sbcl), sbcl);
868 break;
869 case A_int_bad_extmsg1a:
870 case A_int_bad_extmsg1b:
871 case A_int_bad_extmsg2a:
872 case A_int_bad_extmsg2b:
873 case A_int_bad_extmsg3a:
874 case A_int_bad_extmsg3b:
875 case A_int_bad_msg1:
876 case A_int_bad_msg2:
877 case A_int_bad_msg3:
878 case A_int_cmd_bad_phase:
879 case A_int_no_msgout1:
880 case A_int_no_msgout2:
881 case A_int_no_msgout3:
882 case A_int_not_cmd_complete:
883 case A_int_sel_no_ident:
884 case A_int_sel_not_cmd:
885 case A_int_status_not_msgin:
886 case A_int_resel_not_msgin:
887 case A_int_selected:
888 case A_int_not_rej:
889 default:
890 sbcl = NCR_read8(SBCL_REG) & SBCL_PHASE_MASK;
891 printk("scsi%d: Unimplemented script interrupt: %08x, phase %s\n",
892 host->host_no, dsps, sbcl_to_phase(sbcl));
893 sim710_errors++;
894 /* resume_offset is zero, which will cause a host reset */
896 return resume_offset;
900 /* A quick wrapper for sim710_intr_handle to grab the spin lock */
902 static void
903 do_sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
905 unsigned long flags;
907 spin_lock_irqsave(&io_request_lock, flags);
908 sim710_intr_handle(irq, dev_id, regs);
909 spin_unlock_irqrestore(&io_request_lock, flags);
913 /* A "high" level interrupt handler */
915 static void
916 sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
918 unsigned int flags;
919 struct Scsi_Host * host = (struct Scsi_Host *)dev_id;
920 struct sim710_hostdata *hostdata = (struct sim710_hostdata *)host->hostdata[0];
921 Scsi_Cmnd * cmd;
922 unsigned char istat, dstat;
923 unsigned char sstat0;
924 u32 dsps, resume_offset = 0;
926 save_flags(flags);
927 cli();
928 sim710_intrs++;
929 while ((istat = NCR_read8(ISTAT_REG)) & (ISTAT_SIP|ISTAT_DIP)) {
930 dsps = NCR_read32(DSPS_REG);
931 hostdata->state = STATE_HALTED;
932 sstat0 = dstat = 0;
933 if (istat & ISTAT_SIP) {
934 sstat0 = NCR_read8(SSTAT0_REG);
936 if (istat & ISTAT_DIP) {
937 udelay(10); /* Some comment somewhere about 10cycles
938 * between accesses to sstat0 and dstat ??? */
939 dstat = NCR_read8(DSTAT_REG);
941 DEB(DEB_INTS, printk("scsi%d: Int %d, istat %02x, sstat0 %02x "
942 "dstat %02x, dsp [%04x], scratch %02x\n",
943 host->host_no, sim710_intrs, istat, sstat0, dstat,
944 (u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script,
945 NCR_read32(SCRATCH_REG)));
946 if ((dstat & DSTAT_SIR) && dsps == A_int_reselected) {
947 /* Reselected. Identify the target from LCRC_REG, and
948 * update current command. If we were trying to select
949 * a device, then that command needs to go back on the
950 * issue_queue for later.
952 unsigned char lcrc = NCR_read8(LCRC_REG_10);
953 int id = 0;
955 if (!(lcrc & 0x7f)) {
956 printk("scsi%d: Reselected with LCRC = %02x\n",
957 host->host_no, lcrc);
958 cmd = NULL;
960 else {
961 while (!(lcrc & 1)) {
962 id++;
963 lcrc >>= 1;
965 DEB(DEB_DISC, printk("scsi%d: Reselected by ID %d\n",
966 host->host_no, id));
967 if (hostdata->running) {
968 /* Clear SIGP */
969 (void)NCR_read8(CTEST2_REG_700);
971 DEB(DEB_DISC, printk("scsi%d: Select of %d interrupted "
972 "by reselect from %d (%p)\n",
973 host->host_no, hostdata->running->target,
974 id, hostdata->target[id].cur_cmd));
975 cmd = hostdata->running;
976 hostdata->target[cmd->target].cur_cmd = NULL;
977 cmd->SCp.ptr = (unsigned char *) hostdata->issue_queue;
978 hostdata->issue_queue = cmd;
980 cmd = hostdata->running = hostdata->target[id].cur_cmd;
983 else
984 cmd = hostdata->running;
986 if (!cmd) {
987 printk("scsi%d: No active command!\n", host->host_no);
988 printk("scsi%d: Int %d, istat %02x, sstat0 %02x "
989 "dstat %02x, dsp [%04x], scratch %02x, dsps %08x\n",
990 host->host_no, sim710_intrs, istat, sstat0, dstat,
991 (u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script,
992 NCR_read32(SCRATCH_REG), dsps);
993 /* resume_offset is zero, which will cause a host reset */
995 else if (sstat0 & SSTAT0_700_STO) {
996 DEB(DEB_TOUT, printk("scsi%d: Selection timeout\n", host->host_no));
997 cmd->result = DID_NO_CONNECT << 16;
998 SCSI_DONE(cmd);
999 hostdata->target[cmd->target].cur_cmd = NULL;
1000 resume_offset = Ent_reselect;
1002 else if (dstat & DSTAT_SIR)
1003 resume_offset = handle_script_int(host, cmd);
1004 else if (sstat0 & SSTAT0_MA) {
1005 resume_offset = handle_phase_mismatch(host, cmd);
1007 else if (sstat0 & (SSTAT0_MA|SSTAT0_SGE|SSTAT0_UDC|SSTAT0_RST|SSTAT0_PAR)) {
1008 printk("scsi%d: Serious error, sstat0 = %02x\n", host->host_no,
1009 sstat0);
1010 sim710_errors++;
1011 /* resume_offset is zero, which will cause a host reset */
1013 else if (dstat & (DSTAT_BF|DSTAT_ABRT|DSTAT_SSI|DSTAT_WTD)) {
1014 printk("scsi%d: Serious error, dstat = %02x\n", host->host_no,
1015 dstat);
1016 sim710_errors++;
1017 /* resume_offset is zero, which will cause a host reset */
1019 else if (dstat & DSTAT_IID) {
1020 /* This can be due to a quick reselect while doing a WAIT
1021 * DISCONNECT.
1023 resume_offset = handle_idd(host, cmd);
1025 else {
1026 sim710_errors++;
1027 printk("scsi%d: Spurious interrupt!\n", host->host_no);
1028 /* resume_offset is zero, which will cause a host reset */
1032 if (resume_offset) {
1033 if (resume_offset == Ent_reselect) {
1034 hostdata->running = NULL;
1035 hostdata->state = STATE_IDLE;
1037 else
1038 hostdata->state = STATE_BUSY;
1039 DEB(DEB_RESUME, printk("scsi%d: Resuming at script[0x%x]\n",
1040 host->host_no, resume_offset/4));
1041 #ifdef DEBUG_LIMIT_INTS
1042 if (sim710_intrs < DEBUG_LIMIT_INTS)
1043 #endif
1044 NCR_write32(DSP_REG, virt_to_bus(hostdata->script+resume_offset/4));
1045 if (resume_offset == Ent_reselect)
1046 run_process_issue_queue(hostdata);
1048 else {
1049 printk("scsi%d: Failed to handle interrupt. Failing commands "
1050 "and resetting SCSI bus and chip\n", host->host_no);
1051 mdelay(4000); /* Give chance to read screen!! */
1052 full_reset(host);
1055 restore_flags(flags);
1059 static void
1060 run_command (struct sim710_hostdata *hostdata, Scsi_Cmnd *cmd)
1062 struct Scsi_Host *host = cmd->host;
1063 struct sim710_target *targdata = hostdata->target + cmd->target;
1064 int i, datain, dataout, sg_start;
1065 u32 *dip, *dop, dsa;
1067 DEB(DEB_CMND, printk("scsi%d: id%d starting ", host->host_no,
1068 cmd->target));
1069 DEB(DEB_CMND, print_command(cmd->cmnd));
1071 switch (cmd->cmnd[0]) {
1072 case INQUIRY:
1073 case MODE_SENSE:
1074 case READ_6:
1075 case READ_10:
1076 case READ_CAPACITY:
1077 case REQUEST_SENSE:
1078 case READ_BLOCK_LIMITS:
1079 case READ_TOC:
1080 datain = 1;
1081 dataout = 0;
1082 break;
1083 case MODE_SELECT:
1084 case WRITE_6:
1085 case WRITE_10:
1086 datain = 0;
1087 dataout = 1;
1088 break;
1089 case TEST_UNIT_READY:
1090 case ALLOW_MEDIUM_REMOVAL:
1091 case START_STOP:
1092 datain = dataout = 0;
1093 break;
1094 default:
1095 datain = dataout = 1;
1098 memcpy(targdata->dsa_cdb, cmd->cmnd, MAX_CMND);
1100 targdata->dsa_msgout[0] =
1101 IDENTIFY((opt_nodisc & (1<<cmd->target)) ? 0 : 1 ,0);
1102 if (hostdata->negotiate & (1 << cmd->target)) {
1103 if (opt_noneg & (1 << cmd->target)) {
1104 hostdata->negotiate ^= (1 << cmd->target);
1105 targdata->dsa[DSA_MSGOUT] = 1;
1107 else {
1108 DEB(DEB_SYNC, printk("scsi%d: Negotiating async transfers "
1109 "for ID %d\n",
1110 host->host_no, cmd->target));
1111 memcpy(targdata->dsa_msgout+1, async_message, sizeof(async_message));
1112 targdata->dsa[DSA_MSGOUT] = sizeof(async_message) + 1;
1115 else
1116 targdata->dsa[DSA_MSGOUT] = 1;
1118 targdata->dsa_msgin[0] = 0xff;
1119 targdata->dsa_status[0] = 0xff;
1121 targdata->dsa[DSA_SELECT] = (1 << cmd->target) << 16;
1122 targdata->dsa[DSA_MSGOUT+1] = virt_to_bus(targdata->dsa_msgout);
1123 targdata->dsa[DSA_CMND] = cmd->cmd_len;
1124 targdata->dsa[DSA_CMND+1] = virt_to_bus(targdata->dsa_cdb);
1125 targdata->dsa[DSA_STATUS] = 1;
1126 targdata->dsa[DSA_STATUS+1] = virt_to_bus(targdata->dsa_status);
1127 targdata->dsa[DSA_MSGIN] = 1;
1128 targdata->dsa[DSA_MSGIN+1] = virt_to_bus(targdata->dsa_msgin);
1130 sg_start = (MAX_SG - (cmd->use_sg ? cmd->use_sg : 1)) * 2;
1131 dip = targdata->dsa + DSA_DATAIN + sg_start;
1132 dop = targdata->dsa + DSA_DATAOUT + sg_start;
1134 for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; i++) {
1135 u32 vbuf = cmd->use_sg ?
1136 (u32)(((struct scatterlist *)cmd->buffer)[i].address) :
1137 (u32)(cmd->request_buffer);
1138 u32 bbuf = virt_to_bus((void *)vbuf);
1139 u32 cnt = cmd->use_sg ?
1140 ((struct scatterlist *)cmd->buffer)[i].length :
1141 cmd->request_bufflen;
1143 if (datain) {
1144 #ifdef CONFIG_TP34V_SCSI
1145 cache_clear(virt_to_phys((void *)vbuf), cnt);
1146 #endif
1147 *dip++ = cnt;
1148 *dip++ = bbuf;
1150 if (dataout) {
1151 #ifdef CONFIG_TP34V_SCSI
1152 cache_push(virt_to_phys((void *)vbuf), cnt);
1153 #endif
1154 *dop++ = cnt;
1155 *dop++ = bbuf;
1158 targdata->data_out_jump = hostdata->script[Ent_patch_output_data/4+1] =
1159 virt_to_bus(hostdata->script + Ent_patch_output_data/4 + sg_start + 2);
1160 targdata->data_in_jump = hostdata->script[Ent_patch_input_data/4+1] =
1161 virt_to_bus(hostdata->script + Ent_patch_input_data/4 + sg_start + 2);
1163 for (i = 0, dsa = virt_to_bus(targdata->dsa); i < 4; i++) {
1164 u32 v = hostdata->script[Ent_patch_new_dsa/4 + i * 2];
1166 v &= ~0x0000ff00;
1167 v |= (dsa & 0xff) << 8;
1168 hostdata->script[Ent_patch_new_dsa/4 + i * 2] = v;
1169 dsa >>= 8;
1171 hostdata->running = targdata->cur_cmd = cmd;
1172 hostdata->state = STATE_BUSY;
1174 NCR_write8(ISTAT_REG, ISTAT_10_SIGP);
1178 static volatile int process_issue_queue_running = 0;
1180 static __inline__ void
1181 run_process_issue_queue(struct sim710_hostdata *hostdata)
1183 unsigned long flags;
1184 save_flags (flags);
1185 cli();
1186 if (!process_issue_queue_running) {
1187 process_issue_queue_running = 1;
1188 process_issue_queue(hostdata, flags);
1190 * process_issue_queue_running is cleared in process_issue_queue
1191 * once it can't do more work, and process_issue_queue exits with
1192 * interrupts disabled.
1195 restore_flags (flags);
1200 * Function : process_issue_queue (hostdata, flags)
1202 * Purpose : Start next command for any idle target.
1204 * NOTE : process_issue_queue exits with interrupts *disabled*, so the
1205 * caller must reenable them if it desires.
1207 * NOTE : process_issue_queue should be called from both
1208 * sim710_queue_command() and from the interrupt handler
1209 * after command completion.
1212 static void
1213 process_issue_queue (struct sim710_hostdata *hostdata, unsigned long flags)
1215 Scsi_Cmnd *tmp, *prev;
1216 int done;
1219 * We run (with interrupts disabled) until we're sure that none of
1220 * the host adapters have anything that can be done, at which point
1221 * we set process_issue_queue_running to 0 and exit.
1223 * Interrupts are enabled before doing various other internal
1224 * instructions, after we've decided that we need to run through
1225 * the loop again.
1229 do {
1230 cli(); /* Freeze request queues */
1231 done = 1;
1232 if (hostdata->issue_queue) {
1233 if (hostdata->state == STATE_DISABLED) {
1234 tmp = (Scsi_Cmnd *) hostdata->issue_queue;
1235 hostdata->issue_queue = (Scsi_Cmnd *) tmp->SCp.ptr;
1236 tmp->result = (DID_BAD_TARGET << 16);
1237 tmp->scsi_done (tmp);
1238 done = 0;
1240 else if (hostdata->state == STATE_IDLE) {
1241 for (tmp = hostdata->issue_queue, prev = NULL; tmp;
1242 prev = tmp, tmp = (Scsi_Cmnd *) tmp->SCp.ptr) {
1243 if (hostdata->target[tmp->target].cur_cmd == NULL) {
1244 if (prev)
1245 prev->SCp.ptr = tmp->SCp.ptr;
1246 else
1247 hostdata->issue_queue = (Scsi_Cmnd *) tmp->SCp.ptr;
1248 tmp->SCp.ptr = NULL;
1249 run_command (hostdata, tmp);
1250 done = 0;
1251 } /* if target/lun is not busy */
1252 } /* scan issue queue for work */
1253 } /* host is idle */
1254 } /* if hostdata->issue_queue */
1255 if (!done)
1256 restore_flags (flags);
1257 } while (!done);
1258 process_issue_queue_running = 0;
1263 sim710_queuecommand(Scsi_Cmnd * cmd, void (*done)(Scsi_Cmnd *))
1265 struct Scsi_Host *host = cmd->host;
1266 struct sim710_hostdata *hostdata = (struct sim710_hostdata *)host->hostdata[0];
1267 Scsi_Cmnd *tmp;
1268 unsigned long flags;
1270 if (cmd->lun) {
1271 /* Silently ignore luns other than zero! */
1272 cmd->result = (DID_BAD_TARGET << 16);
1273 done(cmd);
1274 return 0;
1277 DEB(DEB_CMND, printk("scsi%d: id%d queuing ", host->host_no,
1278 cmd->target));
1279 DEB(DEB_CMND, print_command(cmd->cmnd));
1281 cmd->scsi_done = done;
1282 cmd->host_scribble = NULL;
1283 cmd->SCp.ptr = NULL;
1284 cmd->SCp.buffer = NULL;
1286 save_flags(flags);
1287 cli();
1289 if (ignore_ids & (1 << cmd->target)) {
1290 printk("scsi%d: ignoring target %d\n", host->host_no, cmd->target);
1291 cmd->result = (DID_BAD_TARGET << 16);
1292 done(cmd);
1293 restore_flags (flags);
1294 return 0;
1296 #ifdef DEBUG_LIMIT_INTS
1297 if (sim710_intrs > DEBUG_LIMIT_INTS) {
1298 cmd->result = (DID_BAD_TARGET << 16);
1299 done(cmd);
1300 restore_flags (flags);
1301 return 0;
1303 #endif
1304 if (cmd->use_sg > MAX_SG)
1305 panic ("cmd->use_sg = %d\n", cmd->use_sg);
1307 if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
1308 cmd->SCp.ptr = (unsigned char *) hostdata->issue_queue;
1309 hostdata->issue_queue = cmd;
1310 } else {
1311 for (tmp = hostdata->issue_queue; tmp->SCp.ptr;
1312 tmp = (Scsi_Cmnd *) tmp->SCp.ptr);
1313 tmp->SCp.ptr = (unsigned char *) cmd;
1315 restore_flags (flags);
1316 run_process_issue_queue(hostdata);
1317 return 0;
1322 sim710_detect(Scsi_Host_Template * tpnt)
1324 unsigned char irq_vector;
1325 unsigned char scsi_id;
1326 unsigned int base_addr;
1327 struct Scsi_Host * host = NULL;
1328 struct sim710_hostdata *hostdata;
1329 int chips = 0;
1330 int indx;
1331 int revision;
1332 int order, size;
1334 #ifdef MODULE
1335 if (sim710)
1336 param_setup(sim710);
1337 #endif
1339 if (no_of_boards < 0) {
1340 printk("sim710: NCR53C710 driver disabled\n");
1341 return 0;
1344 #ifdef CONFIG_MCA
1345 /* If board details have been specified via boot/module parameters,
1346 * then don't bother probing.
1348 if (no_of_boards == 0) {
1349 int slot;
1350 int pos[3];
1351 int mca_53c710_ids[] = MCA_53C710_IDS;
1352 int *id_to_check = mca_53c710_ids;
1353 static int io_004f_by_pos[] = MCA_004F_IO_PORTS;
1354 static int irq_004f_by_pos[] = MCA_004F_IRQS;
1355 static int io_01bb_by_pos[] = MCA_01BB_IO_PORTS;
1356 static int irq_01bb_by_pos[] = MCA_01BB_IRQS;
1358 while ( *id_to_check && no_of_boards < MAXBOARDS) {
1359 if (!MCA_bus)
1360 return 0;
1362 if ((slot = mca_find_adapter(*id_to_check, 0)) != MCA_NOTFOUND) {
1364 pos[0] = mca_read_stored_pos(slot, 2);
1365 pos[1] = mca_read_stored_pos(slot, 3);
1366 pos[2] = mca_read_stored_pos(slot, 4);
1369 * 01BB & 01BA port base by bits 7,6,5,4,3,2 in pos[2]
1371 * 000000 <disabled> 001010 0x2800
1372 * 000001 <invalid> 001011 0x2C00
1373 * 000010 0x0800 001100 0x3000
1374 * 000011 0x0C00 001101 0x3400
1375 * 000100 0x1000 001110 0x3800
1376 * 000101 0x1400 001111 0x3C00
1377 * 000110 0x1800 010000 0x4000
1378 * 000111 0x1C00 010001 0x4400
1379 * 001000 0x2000 010010 0x4800
1380 * 001001 0x2400 010011 0x4C00
1381 * 010100 0x5000
1383 * 00F4 port base by bits 3,2,1 in pos[0]
1385 * 000 <disabled> 001 0x200
1386 * 010 0x300 011 0x400
1387 * 100 0x500 101 0x600
1389 * 01BB & 01BA IRQ is specified in pos[0] bits 7 and 6:
1391 * 00 3 10 11
1392 * 01 5 11 14
1394 * 00F4 IRQ specified by bits 6,5,4 in pos[0]
1396 * 100 5 101 9
1397 * 110 14
1400 if ( *id_to_check == 0x01bb || *id_to_check == 0x01ba ) {
1401 bases[no_of_boards] = io_01bb_by_pos[(pos[2] & 0xFC) >> 2];
1402 irq_vectors[no_of_boards] =
1403 irq_01bb_by_pos[((pos[0] & 0xC0) >> 6)];
1404 if (bases[no_of_boards] == 0x0000)
1405 printk("sim710: NCR53C710 Adapter ID 0x01bb is disabled.\n");
1406 else {
1407 no_of_boards++;
1408 if ( *id_to_check == 0x01bb )
1409 mca_set_adapter_name( slot,
1410 "NCR 3360/3430 SCSI SubSystem" );
1411 else
1412 mca_set_adapter_name(slot,
1413 "NCR Dual SIOP SCSI Host Adapter Board");
1416 else if ( *id_to_check == 0x004f ) {
1417 bases[no_of_boards] = io_004f_by_pos[((pos[0] & 0x0E) >> 1)];
1418 irq_vectors[no_of_boards] =
1419 irq_004f_by_pos[((pos[0] & 0x70) >> 4) - 4];
1420 if (bases[no_of_boards] == 0x0000)
1421 printk("sim710: NCR53C710 Adapter ID 0x004f is disabled.\n");
1422 else {
1423 no_of_boards++;
1424 mca_set_adapter_name(slot,
1425 "NCR 53c710 SCSI Host Adapter Board");
1429 id_to_check++;
1432 #endif
1434 if (!no_of_boards) {
1435 printk("sim710: No NCR53C710 adapter found.\n");
1436 return 0;
1439 size = sizeof(struct sim710_hostdata);
1440 order = 0;
1441 while (size > (PAGE_SIZE << order))
1442 order++;
1443 size = PAGE_SIZE << order;
1445 DEB(DEB_ANY, printk("sim710: hostdata %d bytes, size %d, order %d\n",
1446 sizeof(struct sim710_hostdata), size, order));
1448 tpnt->proc_name = "sim710";
1450 for(indx = 0; indx < no_of_boards; indx++) {
1451 host = scsi_register(tpnt, 4);
1452 host->hostdata[0] = __get_free_pages(GFP_ATOMIC, order);
1453 if (host->hostdata[0] == 0)
1454 panic ("sim710: Couldn't get hostdata memory");
1455 hostdata = (struct sim710_hostdata *)host->hostdata[0];
1456 memset(hostdata, 0, size);
1457 #ifdef CONFIG_TP34V_SCSI
1458 cache_push(virt_to_phys(hostdata), size);
1459 cache_clear(virt_to_phys(hostdata), size);
1460 kernel_set_cachemode((void *)hostdata,size,IOMAP_NOCACHE_SER);
1461 #endif
1462 scsi_id = 7;
1463 base_addr = bases[indx];
1464 irq_vector = irq_vectors[indx];
1465 printk("sim710: Configuring Sim710 (SCSI-ID %d) at %x, IRQ %d\n",
1466 scsi_id, base_addr, irq_vector);
1467 DEB(DEB_ANY, printk("sim710: hostdata = %p (%d bytes), dsa0 = %p\n",
1468 hostdata, sizeof(struct sim710_hostdata),
1469 hostdata->target[0].dsa));
1470 hostdata->chip = indx;
1471 host->irq = irq_vector;
1472 host->this_id = scsi_id;
1473 host->unique_id = base_addr;
1474 host->base = base_addr;
1476 ncr_halt(host);
1478 revision = (NCR_read8(CTEST8_REG) & 0xF0) >> 4;
1479 printk("scsi%d: Revision 0x%x\n",host->host_no,revision);
1481 sim710_soft_reset(host);
1483 sim710_driver_init(host);
1485 #ifdef CONFIG_TP34V_SCSI
1486 if (request_irq(irq_vector,do_sim710_intr_handle, 0, "sim710", host))
1487 #else
1488 if (request_irq(irq_vector,do_sim710_intr_handle, SA_INTERRUPT, "sim710", host))
1489 #endif
1491 printk("scsi%d : IRQ%d not free, detaching\n",
1492 host->host_no, host->irq);
1494 scsi_unregister (host);
1496 else {
1497 #ifdef IO_MAPPED
1498 request_region((u32)host->base, 64, "sim710");
1499 #endif
1500 chips++;
1502 NCR_write32(DSP_REG, virt_to_bus(hostdata->script+Ent_reselect/4));
1503 hostdata->state = STATE_IDLE;
1505 return chips;
1509 sim710_abort(Scsi_Cmnd * cmd)
1511 struct Scsi_Host * host = cmd->host;
1513 printk("scsi%d: Unable to abort command for target %d\n",
1514 host->host_no, cmd->target);
1515 return FAILED;
1519 * This is a device reset. Need to select and send a Bus Device Reset msg.
1523 sim710_dev_reset(Scsi_Cmnd * SCpnt)
1525 struct Scsi_Host * host = SCpnt->host;
1527 printk("scsi%d: Unable to send Bus Device Reset for target %d\n",
1528 host->host_no, SCpnt->target);
1529 return FAILED;
1533 * This is bus reset. We need to reset the bus and fail any active commands.
1537 sim710_bus_reset(Scsi_Cmnd * SCpnt)
1539 struct Scsi_Host * host = SCpnt->host;
1541 printk("scsi%d: Unable to do SCSI bus reset\n", host->host_no);
1542 return FAILED;
1545 static int
1546 full_reset(struct Scsi_Host * host)
1548 struct sim710_hostdata *hostdata = (struct sim710_hostdata *)
1549 host->hostdata[0];
1550 int target;
1551 Scsi_Cmnd *cmd;
1553 ncr_halt(host);
1554 printk("scsi%d: dsp = %08x (script[0x%04x]), scratch = %08x\n",
1555 host->host_no, NCR_read32(DSP_REG),
1556 ((u32)bus_to_virt(NCR_read32(DSP_REG)) - (u32)hostdata->script)/4,
1557 NCR_read32(SCRATCH_REG));
1559 for (target = 0; target < 7; target++) {
1560 if ((cmd = hostdata->target[target].cur_cmd)) {
1561 printk("scsi%d: Failing command for ID%d\n",
1562 host->host_no, target);
1563 cmd->result = DID_RESET << 16;
1564 cmd->scsi_done(cmd);
1565 hostdata->target[target].cur_cmd = NULL;
1569 sim710_soft_reset(host);
1570 sim710_driver_init(host);
1572 NCR_write32(DSP_REG, virt_to_bus(hostdata->script+Ent_reselect/4));
1573 hostdata->state = STATE_IDLE;
1575 run_process_issue_queue(hostdata);
1577 return SUCCESS;
1581 * This is host reset. We need to reset the chip and the bus.
1585 sim710_host_reset(Scsi_Cmnd * SCpnt)
1587 struct Scsi_Host * host = SCpnt->host;
1589 printk("scsi%d: >>>>>>>>>>>> Host reset <<<<<<<<<<<<\n", host->host_no);
1591 return full_reset(host);
1594 #ifdef MODULE
1597 sim710_release(struct Scsi_Host *host)
1599 free_irq(host->irq, host);
1600 #ifdef IO_MAPPED
1601 release_region((u32)host->base, 64);
1602 #endif
1603 return 1;
1606 Scsi_Host_Template driver_template = SIM710_SCSI;
1608 #include "scsi_module.c"
1609 #endif