diff options
| author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-02-25 18:16:29 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-02-25 18:16:29 -0800 |
| commit | 90d2aee3a04cb13dfcab7d37624ffa32025eda1c (patch) | |
| tree | b6f46bffe450b44f373048314fe45b7cdc64235f | |
| parent | 7265df88a1fc37644ea0b4dddcc8ce4f9b227ee4 (diff) | |
| parent | 333f957c3d5259337b859d3d413d805450ddcc9a (diff) | |
Merge bk://gkernel.bkbits.net/libata-2.5
into ppc970.osdl.org:/home/torvalds/v2.5/linux
| -rw-r--r-- | drivers/scsi/libata-core.c | 77 | ||||
| -rw-r--r-- | drivers/scsi/libata-scsi.c | 1 | ||||
| -rw-r--r-- | drivers/scsi/libata.h | 2 | ||||
| -rw-r--r-- | drivers/scsi/sata_promise.c | 60 | ||||
| -rw-r--r-- | drivers/scsi/sata_sil.c | 37 |
5 files changed, 119 insertions, 58 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 3009f8ab6a7f..5c5211c42fd6 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1,8 +1,8 @@ /* libata-core.c - helper library for ATA - Copyright 2003 Red Hat, Inc. All rights reserved. - Copyright 2003 Jeff Garzik + Copyright 2003-2004 Red Hat, Inc. All rights reserved. + Copyright 2003-2004 Jeff Garzik The contents of this file are subject to the Open Software License version 1.1 that can be found at @@ -1653,18 +1653,41 @@ void ata_fill_sg(struct ata_queued_cmd *qc) { struct scatterlist *sg = qc->sg; struct ata_port *ap = qc->ap; - unsigned int i; + unsigned int idx, nelem; assert(sg != NULL); assert(qc->n_elem > 0); - for (i = 0; i < qc->n_elem; i++) { - ap->prd[i].addr = cpu_to_le32(sg_dma_address(&sg[i])); - ap->prd[i].flags_len = cpu_to_le32(sg_dma_len(&sg[i])); - VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", - i, le32_to_cpu(ap->prd[i].addr), le32_to_cpu(ap->prd[i].flags_len)); + idx = 0; + for (nelem = qc->n_elem; nelem; nelem--,sg++) { + u32 addr, boundary; + u32 sg_len, len; + + /* determine if physical DMA addr spans 64K boundary. + * Note h/w doesn't support 64-bit, so we unconditionally + * truncate dma_addr_t to u32. + */ + addr = (u32) sg_dma_address(sg); + sg_len = sg_dma_len(sg); + + while (sg_len) { + boundary = (addr & ~0xffff) + (0xffff + 1); + len = sg_len; + if ((addr + sg_len) > boundary) + len = boundary - addr; + + ap->prd[idx].addr = cpu_to_le32(addr); + ap->prd[idx].flags_len = cpu_to_le32(len & 0xffff); + VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len); + + idx++; + sg_len -= len; + addr += len; + } } - ap->prd[qc->n_elem - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); + + if (idx) + ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); } /** @@ -2386,41 +2409,6 @@ static inline unsigned int ata_host_intr (struct ata_port *ap, } /** - * ata_chk_spurious_int - Check for spurious interrupts - * @ap: port to which command is being issued - * - * Examines the DMA status registers and clears - * unexpected interrupts. Created to work around - * hardware bug on Intel ICH5, but is applied to all - * chipsets using the standard irq handler, just for safety. - * If the bug is not present, this is simply a single - * PIO or MMIO read addition to the irq handler. - * - * LOCKING: - */ -static inline void ata_chk_spurious_int(struct ata_port *ap) { - int host_stat; - - if (ap->flags & ATA_FLAG_MMIO) { - void *mmio = (void *) ap->ioaddr.bmdma_addr; - host_stat = readb(mmio + ATA_DMA_STATUS); - } else - host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); - - if ((host_stat & (ATA_DMA_INTR | ATA_DMA_ERR | ATA_DMA_ACTIVE)) == ATA_DMA_INTR) { - if (ap->flags & ATA_FLAG_MMIO) { - void *mmio = (void *) ap->ioaddr.bmdma_addr; - writeb(host_stat & ~ATA_DMA_ERR, mmio + ATA_DMA_STATUS); - } else - outb(host_stat & ~ATA_DMA_ERR, ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); - - DPRINTK("ata%u: Caught spurious interrupt, status 0x%X\n", ap->id, host_stat); - udelay(1); - } -} - - -/** * ata_interrupt - * @irq: * @dev_instance: @@ -2452,7 +2440,6 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs) qc = ata_qc_from_tag(ap, ap->active_tag); if (qc && ((qc->flags & ATA_QCFLAG_POLL) == 0)) handled += ata_host_intr(ap, qc); - ata_chk_spurious_int(ap); } } diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index ff01a69d8182..5b28a33a4f5c 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -123,6 +123,7 @@ int ata_scsi_slave_config(struct scsi_device *sdev) { sdev->use_10_for_rw = 1; sdev->use_10_for_ms = 1; + blk_queue_max_phys_segments(sdev->request_queue, ATA_MAX_PRD / 2); return 0; /* scsi layer doesn't check return value, sigh */ } diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 79db90a501ac..5046ddfb9db1 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -26,7 +26,7 @@ #define __LIBATA_H__ #define DRV_NAME "libata" -#define DRV_VERSION "1.00" /* must be exactly four chars */ +#define DRV_VERSION "1.01" /* must be exactly four chars */ struct ata_scsi_args { struct ata_port *ap; diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index 014c825bf033..1293a3a90049 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -35,7 +35,7 @@ #include <asm/io.h> #define DRV_NAME "sata_promise" -#define DRV_VERSION "0.89" +#define DRV_VERSION "0.90" enum { @@ -115,7 +115,12 @@ enum { PDC_DIMM_SPD_SYSTEM_FREQ = 126, PDC_CTL_STATUS = 0x08, PDC_DIMM_WINDOW_CTLR = 0x0C, + PDC_TIME_CONTROL = 0x3C, + PDC_TIME_PERIOD = 0x40, + PDC_TIME_COUNTER = 0x44, PDC_GENERAL_CTLR = 0x484, + PCI_PLL_INIT = 0x8A531824, + PCI_X_TCOUNT = 0xEE1E5CFF }; @@ -1454,13 +1459,64 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe) int speed, size, length; u32 addr,spd0,pci_status; u32 tmp=0; + u32 time_period=0; + u32 tcount=0; + u32 ticks=0; + u32 clock=0; + u32 fparam=0; void *mmio = pe->mmio_base; /* hard-code chip #0 */ mmio += PDC_CHIP0_OFS; + /* Initialize PLL based upon PCI Bus Frequency */ + + /* Initialize Time Period Register */ + writel(0xffffffff, mmio + PDC_TIME_PERIOD); + time_period = readl(mmio + PDC_TIME_PERIOD); + VPRINTK("Time Period Register (0x40): 0x%x\n", time_period); + + /* Enable timer */ + writel(0x00001a0, mmio + PDC_TIME_CONTROL); + readl(mmio + PDC_TIME_CONTROL); + + /* Wait 3 seconds */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(3 * HZ); + + /* + When timer is enabled, counter is decreased every internal + clock cycle. + */ + + tcount = readl(mmio + PDC_TIME_COUNTER); + VPRINTK("Time Counter Register (0x44): 0x%x\n", tcount); + + /* + If SX4 is on PCI-X bus, after 3 seconds, the timer counter + register should be >= (0xffffffff - 3x10^8). + */ + if(tcount >= PCI_X_TCOUNT) { + ticks = (time_period - tcount); + VPRINTK("Num counters 0x%x (%d)\n", ticks, ticks); + + clock = (ticks / 300000); + VPRINTK("10 * Internal clk = 0x%x (%d)\n", clock, clock); + + clock = (clock * 33); + VPRINTK("10 * Internal clk * 33 = 0x%x (%d)\n", clock, clock); + + /* PLL F Param (bit 22:16) */ + fparam = (1400000 / clock) - 2; + VPRINTK("PLL F Param: 0x%x (%d)\n", fparam, fparam); + + /* OD param = 0x2 (bit 31:30), R param = 0x5 (bit 29:25) */ + pci_status = (0x8a001824 | (fparam << 16)); + } else + pci_status = PCI_PLL_INIT; + /* Initialize PLL. */ - pci_status = 0x8a531824; + VPRINTK("pci_status: 0x%x\n", pci_status); writel(pci_status, mmio + PDC_CTL_STATUS); readl(mmio + PDC_CTL_STATUS); diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index f42569be4890..ae14cbbea3fe 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -35,7 +35,7 @@ #include <linux/libata.h> #define DRV_NAME "sata_sil" -#define DRV_VERSION "0.52" +#define DRV_VERSION "0.53" enum { sil_3112 = 0, @@ -44,6 +44,11 @@ enum { SIL_SYSCFG = 0x48, SIL_MASK_IDE0_INT = (1 << 22), SIL_MASK_IDE1_INT = (1 << 23), + SIL_MASK_IDE2_INT = (1 << 24), + SIL_MASK_IDE3_INT = (1 << 25), + SIL_MASK_2PORT = SIL_MASK_IDE0_INT | SIL_MASK_IDE1_INT, + SIL_MASK_4PORT = SIL_MASK_2PORT | + SIL_MASK_IDE2_INT | SIL_MASK_IDE3_INT, SIL_IDE0_TF = 0x80, SIL_IDE0_CTL = 0x8A, @@ -59,6 +64,7 @@ enum { SIL_IDE2_CTL = 0x28A, SIL_IDE2_BMDMA = 0x200, SIL_IDE2_SCR = 0x300, + SIL_INTR_STEERING = (1 << 1), SIL_IDE3_TF = 0x2C0, SIL_IDE3_CTL = 0x2CA, @@ -304,7 +310,7 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) unsigned long base; void *mmio_base; int rc; - u32 tmp; + u32 tmp, irq_mask; if (!printed_version++) printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); @@ -365,14 +371,6 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) probe_ent->port[1].scr_addr = base + SIL_IDE1_SCR; ata_std_ports(&probe_ent->port[1]); - /* make sure IDE0/1 interrupts are not masked */ - tmp = readl(mmio_base + SIL_SYSCFG); - if (tmp & (SIL_MASK_IDE0_INT | SIL_MASK_IDE1_INT)) { - tmp &= ~(SIL_MASK_IDE0_INT | SIL_MASK_IDE1_INT); - writel(tmp, mmio_base + SIL_SYSCFG); - readl(mmio_base + SIL_SYSCFG); /* flush */ - } - if (ent->driver_data == sil_3114) { probe_ent->port[2].cmd_addr = base + SIL_IDE2_TF; probe_ent->port[2].ctl_addr = base + SIL_IDE2_CTL; @@ -385,6 +383,25 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) probe_ent->port[3].bmdma_addr = base + SIL_IDE3_BMDMA; probe_ent->port[3].scr_addr = base + SIL_IDE3_SCR; ata_std_ports(&probe_ent->port[3]); + + irq_mask = SIL_MASK_4PORT; + + /* flip the magic "make 4 ports work" bit */ + tmp = readl(mmio_base + SIL_IDE2_BMDMA); + if ((tmp & SIL_INTR_STEERING) == 0) + writel(tmp | SIL_INTR_STEERING, + mmio_base + SIL_IDE2_BMDMA); + + } else { + irq_mask = SIL_MASK_2PORT; + } + + /* make sure IDE0/1/2/3 interrupts are not masked */ + tmp = readl(mmio_base + SIL_SYSCFG); + if (tmp & irq_mask) { + tmp &= ~irq_mask; + writel(tmp, mmio_base + SIL_SYSCFG); + readl(mmio_base + SIL_SYSCFG); /* flush */ } pci_set_master(pdev); |
