Commit 90d2aee3 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://gkernel.bkbits.net/libata-2.5

into ppc970.osdl.org:/home/torvalds/v2.5/linux
parents 7265df88 333f957c
/*
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);
}
/**
......@@ -2385,41 +2408,6 @@ static inline unsigned int ata_host_intr (struct ata_port *ap,
return handled;
}
/**
* 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:
......@@ -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);
}
}
......
......@@ -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 */
}
......
......@@ -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;
......
......@@ -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);
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment