This patch uses the hotswap API in patch 02 to grant the Promise SATA(II)150 Tx4/Tx2 Plus controllers hotswapping powers. Also, some silly integers which should have been unsigned in patch 01 now are. Signed-off-by: Luke Kosewski <lkosewsk@xxxxxxxxx> Luke Kosewski
29.12.05 Luke Kosewski <lkosewsk@xxxxxxxxx> * A patch which uses the API in patch 02 in this series to give the Promise SATA150 Tx4/Tx2 Plus and SATAII150 Tx4/Tx2 Plus controllers drive hotswap. * Since I noticed a few places where unsigned and signed integers were being cast around, this patch also changed all the signed integers in question into unsigned ones. Signed-off-by: Luke Kosewski <lkosewsk@xxxxxxxxx> --- linux-2.6.15-rc7/drivers/scsi/sata_promise.c.old 2005-12-28 23:40:06.000000000 -0500 +++ linux-2.6.15-rc7/drivers/scsi/sata_promise.c 2005-12-29 16:21:55.000000000 -0500 @@ -85,7 +85,7 @@ struct pdc_port_priv { }; struct pdc_host_priv { - int hotplug_offset; + unsigned int hotplug_offset; }; static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg); @@ -346,10 +346,36 @@ static void pdc_reset_port(struct ata_po readl(mmio); /* flush */ } +/* Mask/unmask hotplug interrupts for one channel (ap) */ +static void pdc_chan_hot_status(struct ata_port *ap, int enable) +{ + struct pdc_host_priv *hp = ap->host_set->private_data; + void *mmio = ap->host_set->mmio_base + hp->hotplug_offset; + u8 maskflags; + + if (enable) { + /* Clear channel hotplug interrupts */ + maskflags = readb(mmio); + maskflags |= (0x11 << ap->hard_port_no); + writeb(maskflags, mmio); + } + + maskflags = readb(mmio + 2); + if (enable) /* Unmask channel hotplug interrupts */ + maskflags &= ~(0x11 << ap->hard_port_no); + else /* Mask */ + maskflags |= (0x11 << ap->hard_port_no); + + writeb(maskflags, mmio + 2); +} + static void pdc_sata_phy_reset(struct ata_port *ap) { pdc_reset_port(ap); + + pdc_chan_hot_status(ap, 0); sata_phy_reset(ap); + pdc_chan_hot_status(ap, 1); } static void pdc_pata_phy_reset(struct ata_port *ap) @@ -497,11 +523,13 @@ static void pdc_irq_clear(struct ata_por static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) { struct ata_host_set *host_set = dev_instance; + struct pdc_host_priv *hp = host_set->private_data; struct ata_port *ap; u32 mask = 0; unsigned int i, tmp; - unsigned int handled = 0; + unsigned int handled = 0, hotplug_offset = hp->hotplug_offset; void __iomem *mmio_base; + u8 plugdata, maskflags; VPRINTK("ENTER\n"); @@ -525,7 +553,7 @@ static irqreturn_t pdc_interrupt (int ir mask &= 0xffff; /* only 16 tags possible */ if (!mask) { VPRINTK("QUICK EXIT 3\n"); - goto done_irq; + goto try_hotplug; } writel(mask, mmio_base + PDC_INT_SEQMASK); @@ -544,9 +572,27 @@ static irqreturn_t pdc_interrupt (int ir } } - VPRINTK("EXIT\n"); +try_hotplug: + plugdata = readb(mmio_base + hotplug_offset); + maskflags = readb(mmio_base + hotplug_offset + 2); + plugdata &= ~maskflags; + if (plugdata) { + writeb(plugdata, mmio_base + hotplug_offset); + for (i = 0; i < host_set->n_ports; ++i) { + ap = host_set->ports[i]; + if (!(ap->flags & ATA_FLAG_SATA)) + continue; /* No PATA support here... continue */ + if (plugdata & 0x1) /* Check unplug flag */ + sata_hot_unplug(ap); + if ((plugdata >> 4) & 0x1) /* Check plug flag */ + sata_hot_plug(ap); + plugdata >>= 1; + } + handled = 1; + } + + VPRINTK("EXIT 4\n"); -done_irq: spin_unlock(&host_set->lock); return IRQ_RETVAL(handled); } @@ -626,7 +672,7 @@ static void pdc_host_init(unsigned int c { void __iomem *mmio = pe->mmio_base; struct pdc_host_priv *hp = pe->private_data; - int hotplug_offset = hp->hotplug_offset; + unsigned int hotplug_offset = hp->hotplug_offset; u32 tmp; /* @@ -644,9 +690,9 @@ static void pdc_host_init(unsigned int c tmp = readl(mmio + hotplug_offset); writel(tmp | 0xff, mmio + hotplug_offset); - /* mask plug/unplug ints */ + /* unmask plug/unplug ints */ tmp = readl(mmio + hotplug_offset); - writel(tmp | 0xff0000, mmio + hotplug_offset); + writel(tmp & ~0xff0000, mmio + hotplug_offset); /* reduce TBG clock to 133 Mhz. */ tmp = readl(mmio + PDC_TBG_MODE);