Index: linux/2.4/drivers/scsi/53c7,8xx.c diff -u linux/2.4/drivers/scsi/53c7,8xx.c:1.1.1.4 linux/2.4/drivers/scsi/53c7,8xx.c:1.1.1.4.6.2 --- linux/2.4/drivers/scsi/53c7,8xx.c:1.1.1.4 Thu Feb 22 15:36:43 2001 +++ linux/2.4/drivers/scsi/53c7,8xx.c Sun Mar 4 13:23:50 2001 @@ -236,6 +236,7 @@ #include #include #include +#include #include #include "scsi.h" @@ -268,6 +269,8 @@ static int NCR53c8xx_dsa_len; static void NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs); static void do_NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs); +static void do_q720_intr(int irq, void *dev_id, struct pt_regs * regs); + static int ncr_halt (struct Scsi_Host *host); static void intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd); @@ -448,6 +451,8 @@ * and chip numbers. */ +#ifndef CONFIG_MCA + static struct { unsigned short pci_device_id; int chip; @@ -468,9 +473,6 @@ #define NPCI_CHIP_IDS (sizeof (pci_chip_ids) / sizeof(pci_chip_ids[0])) -#define ROUNDUP(adr,type) \ - ((void *) (((long) (adr) + sizeof(type) - 1) & ~(sizeof(type) - 1))) - /* * Forced detection and autoprobe code for various hardware. Currently, * entry points for these are not included in init/main.c because if the @@ -508,6 +510,20 @@ #define OVERRIDE_LIMIT commandline_current #endif +#endif /* CONFIG_MCA */ + +#ifdef CONFIG_MCA +struct q720_table { + int base; + struct q720_table *next; +}; + +static struct q720_table *q720_table = NULL; +#endif /* CONFIG_MCA */ + +#define ROUNDUP(adr,type) \ + ((void *) (((long) (adr) + sizeof(type) - 1) & ~(sizeof(type) - 1))) + /* * Function: issue_to_cmd * @@ -558,6 +574,7 @@ static void internal_setup(int board, int chip, char *str, int *ints) { +#ifndef CONFIG_MCA unsigned char pci; /* Specifies a PCI override, with bus, device, function */ @@ -595,6 +612,7 @@ } else { printk ("53c7,7x0.c:internal_setup() : too many overrides\n"); } +#endif } /* @@ -898,6 +916,18 @@ expected_clock = hostdata->scsi_clock = 40000000; expected_id = 7; break; + case NCR_Q720: + /* this is wide, but not yet supported as such */ + hostdata->dstat_sir_intr = NCR53c8x0_dstat_sir_intr; + hostdata->init_save_regs = NULL; + hostdata->dsa_fixup = NCR53c8xx_dsa_fixup; + hostdata->init_fixup = NCR53c8x0_init_fixup; + hostdata->soft_reset = NCR53c8x0_soft_reset; + hostdata->run_tests = NCR53c8xx_run_tests; +/* Is the SCSI clock ever anything else on these chips? */ + expected_clock = hostdata->scsi_clock = 40000000; + expected_id = 7; + break; default: printk ("scsi%d : chip type of %d is not supported yet, detaching.\n", host->host_no, hostdata->chip); @@ -1029,6 +1059,7 @@ */ if (hostdata->chip / 100 == 8) { expected_ccf = clock_to_ccf (expected_clock); + NCR53c7x0_write8(SCNTL3_REG_800, 0x33); hostdata->saved_scntl3 = NCR53c7x0_read8(SCNTL3_REG_800); ccf = hostdata->saved_scntl3 & SCNTL3_800_CCF_MASK; if (expected_ccf != -1 && ccf != expected_ccf && !ccf) { @@ -1109,11 +1140,13 @@ search->irq == host->irq && search != host); search=search->next); if (!search) { -#ifdef __powerpc__ - if (request_irq(host->irq, do_NCR53c7x0_intr, SA_SHIRQ, "53c7,8xx", NULL)) -#else - if (request_irq(host->irq, do_NCR53c7x0_intr, SA_INTERRUPT, "53c7,8xx", NULL)) + int ret = +#ifdef CONFIG_MCA + (hostdata->chip == NCR_Q720) ? + request_irq(host->irq, do_q720_intr, SA_INTERRUPT, "Q720", NULL) : #endif + request_irq(host->irq, do_NCR53c7x0_intr, SA_INTERRUPT, "53c7,8xx", NULL); + if (ret) { @@ -1138,9 +1171,13 @@ scsi_unregister (host); return -1; } else { - if (host->io_port) { - host->n_io_port = 128; - request_region (host->io_port, host->n_io_port, "ncr53c7,8xx"); + if (host->io_port) { + if(hostdata->chip == NCR_Q720) { + host->n_io_port = 0x80; + } else { + host->n_io_port = 112; + request_region (host->io_port, host->n_io_port, "ncr53c7,8xx"); + } } } @@ -1187,7 +1224,7 @@ switch (chip) { case 825: - case 820: + case NCR_Q720: case 815: case 810: schedule_size = (tpnt->can_queue + 1) * 8 /* JUMP instruction size */; @@ -1208,7 +1245,7 @@ else printk(", dma %d\n", dma); - if ((chip / 100 == 8) && !pci_valid) + if ((chip / 100 == 8) && chip != NCR_Q720) printk ("scsi-ncr53c7,8xx : for better reliability and performance, please use the\n" " PCI override instead.\n" " Syntax : ncr53c8{10,15,20,25}=pci,,,\n" @@ -1293,12 +1330,16 @@ */ if (base) { - instance->base = (unsigned long) base; /* Check for forced I/O mapping */ if (!(options & OPTION_IO_MAPPED)) { options |= OPTION_MEMORY_MAPPED; ok = 1; } + /* + base = ioremap(base, 0x100); + */ + printk("ncr53c7,8xx: remapped ram base to 0x%x\n", base); + instance->base = (unsigned char *) (unsigned long) base; } else { options &= ~OPTION_MEMORY_MAPPED; } @@ -1363,7 +1404,7 @@ return NCR53c7x0_init(instance); } - +#ifndef CONFIG_MCA /* * Function : static int ncr_pci_init(Scsi_Host_Template *tpnt, int board, * int chip, int bus, int device_fn, long long options) @@ -1511,7 +1552,7 @@ return normal_init (tpnt, board, chip, (int) base, io_port, (int) irq, DMA_NONE, 1, bus, device_fn, options); } - +#endif /* CONFIG_MCA */ /* * Function : int NCR53c7xx_detect(Scsi_Host_Template *tpnt) @@ -1529,13 +1570,131 @@ int __init NCR53c7xx_detect(Scsi_Host_Template *tpnt){ int i; + int count = 0; /* Number of boards detected */ +#ifdef CONFIG_MCA + int slot, pos[4]; +#else int current_override; - int count; /* Number of boards detected */ unsigned char pci_bus, pci_device_fn; static short pci_index=0; /* Device index to PCI BIOS calls */ +#endif tpnt->proc_name = "ncr53c7xx"; +#ifdef CONFIG_MCA + if((slot = mca_find_adapter(0x01ba, 0)) != MCA_NOTFOUND) { + int iobase, irq; + unsigned int rambase; + + pos[0] = mca_read_stored_pos(slot, 2); + pos[1] = mca_read_stored_pos(slot, 3); + pos[2] = mca_read_stored_pos(slot, 4); + pos[3] = mca_read_stored_pos(slot, 5); + + iobase = (pos[2] & 0xfd) << 8; + rambase = ((pos[1] & 0xf0) << 9) + 0xC0000; + switch((pos[0] & 0xd0) >> 6) { + case 2: + irq = 11; + break; + case 3: + irq = 14; + break; + default: + printk("D700: Illegal interrupt\n"); + irq = 0; + break; + } + + normal_init(tpnt, BOARD_GENERIC, 70066, rambase + 0x200, + iobase + 0x200, + irq, DMA_NONE, 0, 0, 0, 0); + count ++; + } + else if((slot = mca_find_adapter(0x0720, 0)) != MCA_NOTFOUND) { + int iobase, irq; + unsigned int rambase; + struct q720_table *new_table; + + pos[0] = mca_read_stored_pos(slot, 2); + pos[1] = mca_read_stored_pos(slot, 3); + pos[2] = mca_read_stored_pos(slot, 4); + pos[3] = mca_read_stored_pos(slot, 5); + + iobase = (0xf8 & pos[0]) << 8; + irq = pos[3] &0x0f; + rambase = ((0x7e & pos[2]) << 20); + rambase += (pos[2] & 0x80) ? 0xF8000000 : 0xB8000000; + mca_set_adapter_name(slot, "NCR Q720 SCSI Quad Host Adapter"); + printk(KERN_INFO "NCR Q720 in slot %d\n", slot); + /* set up card register region */ + request_region((u32)iobase, 64, "Q720"); + + /* set up SIOP individual region */ + request_region((u32)(iobase + 0x200), 0x80, "Q720"); + /* reset the entire adapter */ + outb(inb((u32)(iobase + 0xa)) | 0x10, (u32)(iobase + 0xa)); + /* must wait 5us before touching board again */ + udelay(5); + /* enable the adapter */ + outb(inb((u32)(iobase + 2)) | 0x03, (u32)(iobase +2)); + /* enable ram based mapping */ + outb(inb((u32)(iobase +0xa)) | 0x01, (u32)(iobase +0xa)); + /* enable ram - I/O mapping in lower 1k */ + outb(inb((u32)(iobase +0x11)) | 0x20, (u32)(iobase + 0x11)); + for(i = 0; i < 4; i++) { + /* reset the SIOP */ + outb(iobase + 0x200 + 0x80*i + ISTAT_REG_800, ISTAT_10_SRST); + udelay(5); + outb(iobase + 0x200 + 0x80*i + ISTAT_REG_800, 0x00); + /* clear the DMA FIFO */ + outb(inb(iobase + 0x200 + 0x80*i + CTEST3_REG_800) | CTEST3_800_CLF, + iobase + 0x200 + CTEST3_REG_800); + /* clear SCSI FIFO */ + outb(inb(iobase + 0x200 + 0x80*i + STEST3_REG_800) | STEST3_800_CSF, + iobase + 0x200 + STEST3_REG_800); + } + printk(KERN_INFO "Q720: (vers %d) Adapter Specific regs, iobase=0x%x, rambase=0x%x: ", + (inb(iobase + 0x200 + CTEST3_REG_800) & 0xf0) >> 4, + iobase, rambase); + /* + for(i=0; i<16; i++) + printk("0x%2x ", inb((u32)(iobase + i))); + */ + new_table = kmalloc(sizeof(struct q720_table), GFP_ATOMIC); + if(new_table != NULL) { + new_table->base = iobase; + new_table->next = q720_table; + q720_table = new_table; + for(i=0; i<4; i++) { /* 4 SIOPs per card */ + __u8 id0 = inb((__u16)(iobase + 0x270 + 0x80*i)); + /* + int j; + printk("\nQ720: SIOP%d: ", i); + for(j=0; j<4; j++) + printk("0x%2x ", inb((u32)(iobase + j +0x270 + 0x80*i))); + printk("\n"); + */ + if(id0 & 0x20) { + printk(KERN_WARNING "Q720: SIOP%d: No differential support, skipping\n", i); + continue; + } + /* we use 8xx to signal a 720 chip since the 720 registers + * behave like an 8xx and a lot of the register selection is + * done by the chip/100 == 8 selector */ + normal_init(tpnt, BOARD_GENERIC, NCR_Q720, + rambase + 0x200 + 0x80*i, + iobase + 0x200 + 0x80*i, + irq, DMA_NONE, 0, 0, 0, 0); + count++; + } + } else { + printk("Q720: failed to malloc %d bytes for table\n", + sizeof(q720_table)); + } + } + +#else for (current_override = count = 0; current_override < OVERRIDE_LIMIT; ++current_override) { if (overrides[current_override].pci ? @@ -1569,6 +1728,7 @@ pci_bus, pci_device_fn, /* no options */ 0)) ++count; } +#endif return count; } @@ -1657,12 +1817,13 @@ tmp = NCR53c7x0_read8(DMODE_REG_10); tmp &= (DMODE_800_ERL | DMODE_BL_MASK); - if (!(hostdata->options & OPTION_MEMORY_MAPPED)) { + if (!(hostdata->options & OPTION_MEMORY_MAPPED) + && hostdata->chip != NCR_Q720) { base = (u32) host->io_port; memory_to_ncr = tmp|DMODE_800_DIOM; ncr_to_memory = tmp|DMODE_800_SIOM; } else { - base = virt_to_bus((void *)host->base); + base = host->base; /* currently bus physical -- may change */ memory_to_ncr = ncr_to_memory = tmp; } @@ -4186,9 +4347,9 @@ is_8xx_chip = ((unsigned) (hostdata->chip - 800)) < 100; if (is_8xx_chip) { - sstat0_sist0 = NCR53c7x0_read8(SIST0_REG_800); + sstat0_sist0 = NCR53c7x0_read8(SIST0_REG_800) & NCR53c7x0_read8(SIEN0_REG_800); udelay(1); - sist1 = NCR53c7x0_read8(SIST1_REG_800); + sist1 = NCR53c7x0_read8(SIST1_REG_800) & NCR53c7x0_read8(SIEN1_REG_800); } else { sstat0_sist0 = NCR53c7x0_read8(SSTAT0_REG); sist1 = 0; @@ -4360,6 +4521,22 @@ spin_unlock_irqrestore(&io_request_lock, flags); } +#ifdef CONFIG_MCA +static void +do_q720_intr(int irq, void *dev_id, struct pt_regs *regs) { + unsigned long flags; + + if(q720_table == NULL || (inb(q720_table->base +0xd) & 0xf0) == 0xf0) { + /* SIOP0-3 hasn't interrupted */ + return; + } + spin_lock_irqsave(&io_request_lock, flags); + NCR53c7x0_intr(irq, dev_id, regs); + spin_unlock_irqrestore(&io_request_lock, flags); + +} +#endif + /* * Function : static void NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs) * @@ -4530,8 +4707,9 @@ interrupted = 1; hostdata->state = STATE_HALTED; - if (NCR53c7x0_read8 ((hostdata->chip / 100) == 8 ? - SSTAT1_REG : SSTAT2_REG) & SSTAT2_FF_MASK) + if ((NCR53c7x0_read8 ((hostdata->chip / 100) == 8 ? + SSTAT1_REG : SSTAT2_REG) + & SSTAT2_FF_MASK) && istat & ISTAT_SIP) printk ("scsi%d : SCSI FIFO not empty\n", host->host_no); @@ -4549,11 +4727,19 @@ cmd = (struct NCR53c7x0_cmd *) hostdata->curr; } else { dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG)); + if(hostdata->options & OPTION_DEBUG_INTR) { + printk("scsi%d : dsa = 0x%x\n", host->host_no, dsa); + } for (cmd = (struct NCR53c7x0_cmd *) hostdata->running_list; cmd && (dsa + (hostdata->dsa_start / sizeof(u32))) != cmd->dsa; - cmd = (struct NCR53c7x0_cmd *)(cmd->next)); + cmd = (struct NCR53c7x0_cmd *)(cmd->next)) { + if(hostdata->options & OPTION_DEBUG_INTR) { + printk("scsi%d : cmd (0x%x) : dsa 0x%x, pid %lu, id %d, lun %d\n", host->host_no, cmd, cmd->dsa, cmd->cmd->pid, (int) cmd->cmd->target, (int) cmd->cmd->lun); + print_command(cmd->cmd->cmnd); + } + } } if (hostdata->options & OPTION_DEBUG_INTR) { if (cmd) { @@ -4562,7 +4748,8 @@ (int) cmd->cmd->lun); print_command (cmd->cmd->cmnd); } else { - printk("scsi%d : no active command\n", host->host_no); + printk("scsi%d : no active command\n", + host->host_no); } } if (istat & ISTAT_SIP) { @@ -5011,7 +5198,7 @@ printk("scsi%d : %s : unexpected phase %s.\n", host->host_no, where ? where : "unknown location", sbcl_to_phase(sbcl)); - print_lots (host); + /*print_lots (host);*/ /* Fall through to ACTION_ABORT */ case ACTION_ABORT: abort_connected (host); @@ -5078,6 +5265,10 @@ */ if ((hostdata->chip / 100) == 8) { +#ifdef CONFIG_MCA + printk("scsi%d: fault interrupt on MCA\n", host->host_no); + return; +#else save_flags (flags); cli(); tmp = pcibios_read_config_word (hostdata->pci_bus, @@ -5099,6 +5290,7 @@ host->host_no, tmp); retry = NEVER; } +#endif /* CONFIG_MCA */ } #ifndef notyet @@ -5659,8 +5851,8 @@ save_flags(flags); cli(); ncr_halt (host); - print_lots (host); - dump_events (host, 30); + /*print_lots (host);*/ + /*dump_events (host, 30);*/ ncr_scsi_reset (host); for (tmp = nuke_list = return_outstanding_commands (host, 1 /* free */, 0 /* issue */ ); tmp; tmp = (Scsi_Cmnd *) tmp->SCp.buffer) Index: linux/2.4/drivers/scsi/53c7,8xx.h diff -u linux/2.4/drivers/scsi/53c7,8xx.h:1.1.1.2 linux/2.4/drivers/scsi/53c7,8xx.h:1.1.1.2.12.1 --- linux/2.4/drivers/scsi/53c7,8xx.h:1.1.1.2 Thu Nov 30 11:19:12 2000 +++ linux/2.4/drivers/scsi/53c7,8xx.h Fri Feb 23 20:15:27 2001 @@ -1526,5 +1526,10 @@ /* Paranoid people could use panic() here. */ #define FATAL(host) shutdown((host)); +/* Extra defines for the NCR Q720 card */ + +#define NCR_Q720 827 /* default chip id (must be > 800) */ +#define NCR_Q720_DEFAULT_SCNTL3 0x33 + #endif /* NCR53c7x0_C */ #endif /* NCR53c7x0_H */ Index: linux/2.4/drivers/scsi/Config.in diff -u linux/2.4/drivers/scsi/Config.in:1.1.1.3 linux/2.4/drivers/scsi/Config.in:1.1.1.3.10.1 --- linux/2.4/drivers/scsi/Config.in:1.1.1.3 Thu Jan 11 10:39:30 2001 +++ linux/2.4/drivers/scsi/Config.in Sun Feb 25 10:22:18 2001 @@ -112,7 +112,7 @@ fi fi dep_tristate 'NCR53c406a SCSI support' CONFIG_SCSI_NCR53C406A $CONFIG_SCSI -dep_tristate 'NCR53c7,8xx SCSI support' CONFIG_SCSI_NCR53C7xx $CONFIG_SCSI $CONFIG_PCI +dep_tristate 'NCR53c7,8xx SCSI support' CONFIG_SCSI_NCR53C7xx $CONFIG_SCSI if [ "$CONFIG_SCSI_NCR53C7xx" != "n" ]; then bool ' always negotiate synchronous transfers' CONFIG_SCSI_NCR53C7xx_sync bool ' allow FAST-SCSI [10MHz]' CONFIG_SCSI_NCR53C7xx_FAST