- int MAXLOOPS = 1000000;
- int maxloops = MAXLOOPS;
-@@ -181,25 +182,30 @@
- } else if ((cmd - &dbri->dma->cmd[0]) >= DBRI_NO_CMDS-1) {
- printk("DBRI: Command buffer overflow! (bug in driver)\n");
- } else {
-- *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0);
-+ if (pause)
-+ *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0);
- *(cmd++) = DBRI_CMD(D_WAIT, 1, 0);
- dbri->wait_seen = 0;
- sbus_writel(dbri->dma_dvma, dbri->regs + REG8);
-- while ((--maxloops) > 0 &&
-- (sbus_readl(dbri->regs + REG0) & D_P))
-- barrier();
-- if (maxloops == 0) {
-- printk("DBRI: Chip never completed command buffer\n");
-- } else {
-- while ((--maxloops) > 0 && (! dbri->wait_seen))
-- dbri_process_interrupt_buffer(dbri);
-+ if (pause) {
-+ while ((--maxloops) > 0 &&
-+ (sbus_readl(dbri->regs + REG0) & D_P))
-+ barrier();
- if (maxloops == 0) {
-- printk("DBRI: Chip never acked WAIT\n");
-+ printk("DBRI: Chip never completed command buffer\n");
- } else {
-- dprintk(D_INT, ("DBRI: Chip completed command "
-- "buffer (%d)\n",
-- MAXLOOPS - maxloops));
-+ while ((--maxloops) > 0 && (! dbri->wait_seen))
-+ dbri_process_interrupt_buffer(dbri);
-+ if (maxloops == 0) {
-+ printk("DBRI: Chip never acked WAIT\n");
-+ } else {
-+ dprintk(D_INT, ("DBRI: Chip completed command "
-+ "buffer (%d)\n",
-+ MAXLOOPS - maxloops));
-+ }
- }
-+ } else {
-+ dprintk(D_INT, ("DBRI: NO PAUSE\n"));
- }
- }
-
-@@ -257,7 +263,10 @@
- /* We should query the openprom to see what burst sizes this
- * SBus supports. For now, just disable all SBus bursts */
- tmp = sbus_readl(dbri->regs + REG0);
-- tmp &= ~(D_G | D_S | D_E);
-+ /* A brute approach - DBRI falls back to working burst size by itself
-+ * On SS20 D_S does not work, so do not try so high. */
-+ tmp |= D_G | D_E;
-+ tmp &= ~D_S;
- sbus_writel(tmp, dbri->regs + REG0);
-
- /*
-@@ -268,7 +277,7 @@
- *(cmd++) = DBRI_CMD(D_IIQ, 0, 0);
- *(cmd++) = dma_addr;
-
-- dbri_cmdsend(dbri, cmd);
-+ dbri_cmdsend(dbri, cmd, 1);
- }
-
-
-@@ -455,7 +464,7 @@
- dbri->pipes[pipe].sdp
- | D_SDP_P | D_SDP_C | D_SDP_2SAME);
- *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, td);
-- dbri_cmdsend(dbri, cmd);
-+ dbri_cmdsend(dbri, cmd, 1);
- }
-
- if (code == D_INTR_FXDT) {
-@@ -579,7 +588,7 @@
- cmd = dbri_cmdlock(dbri);
- *(cmd++) = DBRI_CMD(D_SDP, 0, sdp | D_SDP_C | D_SDP_P);
- *(cmd++) = 0;
-- dbri_cmdsend(dbri, cmd);
-+ dbri_cmdsend(dbri, cmd, 1);
-
- desc = dbri->pipes[pipe].desc;
- while (desc != -1) {
-@@ -722,7 +731,7 @@
- *(cmd++) = D_TS_LEN(length) | D_TS_CYCLE(cycle) | D_TS_NEXT(nextpipe);
- }
-
-- dbri_cmdsend(dbri, cmd);
-+ dbri_cmdsend(dbri, cmd, 1);
- }
-
- /* I don't use this function, so it's basically untested. */
-@@ -752,7 +761,7 @@
- *(cmd++) = D_TS_NEXT(nextpipe);
- }
-
-- dbri_cmdsend(dbri, cmd);
-+ dbri_cmdsend(dbri, cmd, 1);
- }
-
- /* xmit_fixed() / recv_fixed()
-@@ -803,7 +812,7 @@
- *(cmd++) = DBRI_CMD(D_SSP, 0, pipe);
- *(cmd++) = data;
-
-- dbri_cmdsend(dbri, cmd);
-+ dbri_cmdsend(dbri, cmd, 1);
- }
-
- static void recv_fixed(struct dbri *dbri, int pipe, volatile __u32 *ptr)
-@@ -884,7 +893,9 @@
- }
-
- if (len > ((1 << 13) - 1)) {
-- mylen = (1 << 13) - 1;
-+ /* One should not leave a buffer shorter than */
-+ /* a single sample. Otherwise bad things happens.*/
-+ mylen = (1 << 13) - 4;
- } else {
- mylen = len;
- }
-@@ -954,7 +965,7 @@
-
- cmd = dbri_cmdlock(dbri);
- *(cmd++) = DBRI_CMD(D_CDP, 0, pipe);
-- dbri_cmdsend(dbri,cmd);
-+ dbri_cmdsend(dbri,cmd, 0);
- } else {
- /* Pipe isn't active - issue an SDP command to start
- * our chain of TDs running.
-@@ -965,7 +976,7 @@
- dbri->pipes[pipe].sdp
- | D_SDP_P | D_SDP_EVERY | D_SDP_C);
- *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_td);
-- dbri_cmdsend(dbri, cmd);
-+ dbri_cmdsend(dbri, cmd, 0);
- }
-
- restore_flags(flags);
-@@ -1083,7 +1094,7 @@
- *(cmd++) = DBRI_CMD(D_SDP, 0, dbri->pipes[pipe].sdp | D_SDP_P | D_SDP_C);
- *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_rd);
-
-- dbri_cmdsend(dbri, cmd);
-+ dbri_cmdsend(dbri, cmd, 1);
- }
-
-
-@@ -1191,7 +1202,7 @@
- *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0);
- *(cmd++) = DBRI_CMD(D_CDM, 0, D_CDM_XCE|D_CDM_XEN|D_CDM_REN);
-
-- dbri_cmdsend(dbri, cmd);
-+ dbri_cmdsend(dbri, cmd, 1);
- }
-
- /*
-@@ -1538,7 +1549,6 @@
- xmit_on_pipe(dbri, 4, buffer, count,
- &dbri_audio_output_callback, drv);
-
--#if 0
- /* Notify midlevel that we're a DMA-capable driver that
- * can accept another buffer immediately. We should probably
- * check that we've got enough resources (i.e, descriptors)
-@@ -1551,9 +1561,14 @@
- * DBRI with a chain of buffers, but the midlevel code is
- * so tricky that I really don't want to deal with it.
- */
-+ /*
-+ * This must be enabled otherwise the output is noisy
-+ * as return to user space is done when all buffers
-+ * are already played, so user space player has no time
-+ * to prepare next ones without a period of silence. - Krzysztof Helt
-+ */
-
- sparcaudio_output_done(drv, 2);
--#endif
- }
-
- static void dbri_stop_output(struct sparcaudio_driver *drv)
-@@ -1842,6 +1857,12 @@
- return dbri_get_output_rate(drv);
- }
-
-+static int dbri_get_formats(struct sparcaudio_driver *drv)
-+{
-+/* 8-bit format is not working */
-+ return (AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE);
-+}
-+
- /******************* sparcaudio midlevel - ports ***********************/
-
- static int dbri_set_output_port(struct sparcaudio_driver *drv, int port)
-@@ -1983,6 +2004,19 @@
- dbri_get_input_ports,
- dbri_set_output_muted,
- dbri_get_output_muted,
-+ NULL, /* dbri_set_output_pause, */
-+ NULL, /* dbri_get_output_pause, */
-+ NULL, /* dbri_set_input_pause, */
-+ NULL, /* dbri_get_input_pause, */
-+ NULL, /* dbri_set_output_samples, */
-+ NULL, /* dbri_get_output_samples, */
-+ NULL, /* dbri_set_input_samples, */
-+ NULL, /* dbri_get_input_samples, */
-+ NULL, /* dbri_set_output_error, */
-+ NULL, /* dbri_get_output_error, */
-+ NULL, /* dbri_set_input_error, */
-+ NULL, /* dbri_get_input_error, */
-+ dbri_get_formats
- };
-
-
-@@ -2093,7 +2127,7 @@
- #endif
- *(cmd++) = DBRI_CMD(D_TE, 0, val);
-
-- dbri_cmdsend(dbri, cmd);
-+ dbri_cmdsend(dbri, cmd, 1);
-
- /* Activate the interface */
- tmp = sbus_readl(dbri->regs + REG0);
-diff -Nur linux-2.4.29/drivers/scsi/ahci.c linux-mips/drivers/scsi/ahci.c
---- linux-2.4.29/drivers/scsi/ahci.c 2005-01-19 15:10:01.000000000 +0100
-+++ linux-mips/drivers/scsi/ahci.c 2005-03-26 11:47:32.448326225 +0100
-@@ -40,8 +40,6 @@
- #define DRV_NAME "ahci"
- #define DRV_VERSION "1.00"
-
--#define msleep libata_msleep /* 2.4-specific */
--
- enum {
- AHCI_PCI_BAR = 5,
- AHCI_MAX_SG = 168, /* hardware max is 64K */
-@@ -180,6 +178,7 @@
- static void ahci_host_stop(struct ata_host_set *host_set);
- static void ahci_qc_prep(struct ata_queued_cmd *qc);
- static u8 ahci_check_status(struct ata_port *ap);
-+static u8 ahci_check_err(struct ata_port *ap);
- static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
-
- static Scsi_Host_Template ahci_sht = {
-@@ -206,6 +205,8 @@
- .port_disable = ata_port_disable,
-
- .check_status = ahci_check_status,
-+ .check_altstatus = ahci_check_status,
-+ .check_err = ahci_check_err,
- .dev_select = ata_noop_dev_select,
-
- .phy_reset = ahci_phy_reset,
-@@ -248,6 +249,12 @@
- board_ahci }, /* ICH7 */
- { PCI_VENDOR_ID_INTEL, 0x27c5, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- board_ahci }, /* ICH7M */
-+ { PCI_VENDOR_ID_INTEL, 0x27c2, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ board_ahci }, /* ICH7R */
-+ { PCI_VENDOR_ID_INTEL, 0x27c3, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ board_ahci }, /* ICH7R */
-+ { PCI_VENDOR_ID_AL, 0x5288, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ board_ahci }, /* ULi M5288 */
- { } /* terminate list */
- };
-
-@@ -448,6 +455,13 @@
- return readl(mmio + PORT_TFDATA) & 0xFF;
- }
-
-+static u8 ahci_check_err(struct ata_port *ap)
-+{
-+ void *mmio = (void *) ap->ioaddr.cmd_addr;
-+
-+ return (readl(mmio + PORT_TFDATA) >> 8) & 0xFF;
-+}
-+
- static void ahci_fill_sg(struct ata_queued_cmd *qc)
- {
- struct ahci_port_priv *pp = qc->ap->private_data;
-@@ -515,15 +529,6 @@
- ahci_fill_sg(qc);
- }
-
--static inline void ahci_dma_complete (struct ata_port *ap,
-- struct ata_queued_cmd *qc,
-- int have_err)
--{
-- /* get drive status; clear intr; complete txn */
-- ata_qc_complete(ata_qc_from_tag(ap, ap->active_tag),
-- have_err ? ATA_ERR : 0);
--}
--
- static void ahci_intr_error(struct ata_port *ap, u32 irq_stat)
- {
- void *mmio = ap->host_set->mmio_base;
-@@ -569,7 +574,7 @@
- writel(tmp, port_mmio + PORT_CMD);
- readl(port_mmio + PORT_CMD); /* flush */
-
-- printk(KERN_WARNING "ata%u: error occurred, port reset\n", ap->port_no);
-+ printk(KERN_WARNING "ata%u: error occurred, port reset\n", ap->id);
- }
-
- static void ahci_eng_timeout(struct ata_port *ap)
-@@ -761,10 +766,10 @@
-
- using_dac = hpriv->cap & HOST_CAP_64;
- if (using_dac &&
-- !pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) {
-+ !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
- hpriv->flags |= HOST_CAP_64;
- } else {
-- rc = pci_set_dma_mask(pdev, 0xffffffffULL);
-+ rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
- if (rc) {
- printk(KERN_ERR DRV_NAME "(%s): 32-bit DMA enable failed\n",
- pci_name(pdev));
-@@ -929,6 +934,7 @@
- unsigned long base;
- void *mmio_base;
- unsigned int board_idx = (unsigned int) ent->driver_data;
-+ int pci_dev_busy = 0;
- int rc;
-
- VPRINTK("ENTER\n");
-@@ -941,8 +947,10 @@
- return rc;
-
- rc = pci_request_regions(pdev, DRV_NAME);
-- if (rc)
-+ if (rc) {
-+ pci_dev_busy = 1;
- goto err_out;
-+ }
-
- pci_enable_intx(pdev);
-
-@@ -1002,7 +1010,8 @@
- err_out_regions:
- pci_release_regions(pdev);
- err_out:
-- pci_disable_device(pdev);
-+ if (!pci_dev_busy)
-+ pci_disable_device(pdev);
- return rc;
- }
-
-diff -Nur linux-2.4.29/drivers/scsi/aic7xxx/aic79xx_pci.c linux-mips/drivers/scsi/aic7xxx/aic79xx_pci.c
---- linux-2.4.29/drivers/scsi/aic7xxx/aic79xx_pci.c 2003-08-25 13:44:42.000000000 +0200
-+++ linux-mips/drivers/scsi/aic7xxx/aic79xx_pci.c 2005-03-26 11:47:34.828935512 +0100
-@@ -451,8 +451,10 @@
- * or read prefetching could be initiated by the
- * CPU or host bridge. Our device does not support
- * either, so look for data corruption and/or flaged
-- * PCI errors.
-+ * PCI errors. First pause without causing another
-+ * chip reset.
- */
-+ hcntrl &= ~CHIPRST;
- ahd_outb(ahd, HCNTRL, hcntrl|PAUSE);
- while (ahd_is_paused(ahd) == 0)
- ;
-diff -Nur linux-2.4.29/drivers/scsi/aic7xxx/aic7xxx_pci.c linux-mips/drivers/scsi/aic7xxx/aic7xxx_pci.c
---- linux-2.4.29/drivers/scsi/aic7xxx/aic7xxx_pci.c 2003-08-25 13:44:42.000000000 +0200
-+++ linux-mips/drivers/scsi/aic7xxx/aic7xxx_pci.c 2005-03-26 11:47:34.831935020 +0100
-@@ -1284,8 +1284,10 @@
- * or read prefetching could be initiated by the
- * CPU or host bridge. Our device does not support
- * either, so look for data corruption and/or flagged
-- * PCI errors.
-+ * PCI errors. First pause without causing another
-+ * chip reset.
- */
-+ hcntrl &= ~CHIPRST;
- ahc_outb(ahc, HCNTRL, hcntrl|PAUSE);
- while (ahc_is_paused(ahc) == 0)
- ;
-diff -Nur linux-2.4.29/drivers/scsi/ata_piix.c linux-mips/drivers/scsi/ata_piix.c
---- linux-2.4.29/drivers/scsi/ata_piix.c 2005-01-19 15:10:01.000000000 +0100
-+++ linux-mips/drivers/scsi/ata_piix.c 2005-03-26 11:47:32.450325897 +0100
-@@ -139,6 +139,8 @@
-
- .bmdma_setup = ata_bmdma_setup,
- .bmdma_start = ata_bmdma_start,
-+ .bmdma_stop = ata_bmdma_stop,
-+ .bmdma_status = ata_bmdma_status,
- .qc_prep = ata_qc_prep,
- .qc_issue = ata_qc_issue_prot,
-
-@@ -164,6 +166,8 @@
-
- .bmdma_setup = ata_bmdma_setup,
- .bmdma_start = ata_bmdma_start,
-+ .bmdma_stop = ata_bmdma_stop,
-+ .bmdma_status = ata_bmdma_status,
- .qc_prep = ata_qc_prep,
- .qc_issue = ata_qc_issue_prot,
-
-diff -Nur linux-2.4.29/drivers/scsi/Config.in linux-mips/drivers/scsi/Config.in
---- linux-2.4.29/drivers/scsi/Config.in 2005-01-19 15:09:59.000000000 +0100
-+++ linux-mips/drivers/scsi/Config.in 2005-03-26 11:47:32.437328030 +0100
-@@ -73,6 +73,7 @@
- dep_tristate ' ServerWorks Frodo / Apple K2 SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SVW $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
- dep_tristate ' Intel PIIX/ICH SATA support' CONFIG_SCSI_ATA_PIIX $CONFIG_SCSI_SATA $CONFIG_PCI
- dep_tristate ' NVIDIA SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_NV $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
-+dep_tristate ' Pacific Digital SATA QStor support' CONFIG_SCSI_SATA_QSTOR $CONFIG_SCSI_SATA $CONFIG_PCI
- dep_tristate ' Promise SATA TX2/TX4 support (EXPERIMENTAL)' CONFIG_SCSI_SATA_PROMISE $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
- dep_tristate ' Promise SATA SX4 support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SX4 $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
- dep_tristate ' Silicon Image SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SIL $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
-diff -Nur linux-2.4.29/drivers/scsi/libata-core.c linux-mips/drivers/scsi/libata-core.c
---- linux-2.4.29/drivers/scsi/libata-core.c 2005-01-19 15:10:03.000000000 +0100
-+++ linux-mips/drivers/scsi/libata-core.c 2005-03-26 11:47:32.481320810 +0100
-@@ -376,7 +376,7 @@
- }
-
- /**
-- * ata_check_status - Read device status reg & clear interrupt
-+ * ata_check_status_pio - Read device status reg & clear interrupt
- * @ap: port where the device is
- *
- * Reads ATA taskfile status register for currently-selected device
-@@ -414,6 +414,27 @@
- return ata_check_status_pio(ap);
- }
-
-+u8 ata_altstatus(struct ata_port *ap)
-+{
-+ if (ap->ops->check_altstatus)
-+ return ap->ops->check_altstatus(ap);
-+
-+ if (ap->flags & ATA_FLAG_MMIO)
-+ return readb((void __iomem *)ap->ioaddr.altstatus_addr);
-+ return inb(ap->ioaddr.altstatus_addr);
-+}
-+
-+u8 ata_chk_err(struct ata_port *ap)
-+{
-+ if (ap->ops->check_err)
-+ return ap->ops->check_err(ap);
-+
-+ if (ap->flags & ATA_FLAG_MMIO) {
-+ return readb((void __iomem *) ap->ioaddr.error_addr);
-+ }
-+ return inb(ap->ioaddr.error_addr);
-+}
-+
- /**
- * ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure
- * @tf: Taskfile to convert
-@@ -1160,7 +1181,6 @@
- printk(KERN_WARNING "ata%u: dev %u not supported, ignoring\n",
- ap->id, device);
- err_out:
-- ata_irq_on(ap); /* re-enable interrupts */
- dev->class++; /* converts ATA_DEV_xxx into ATA_DEV_xxx_UNSUP */
- DPRINTK("EXIT, err\n");
- }
-@@ -1668,7 +1688,8 @@
- ata_dev_try_classify(ap, 1);
-
- /* re-enable interrupts */
-- ata_irq_on(ap);
-+ if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */
-+ ata_irq_on(ap);
-
- /* is double-select really necessary? */
- if (ap->device[1].class != ATA_DEV_NONE)
-@@ -1699,6 +1720,69 @@
- DPRINTK("EXIT\n");
- }
-
-+static void ata_pr_blacklisted(struct ata_port *ap, struct ata_device *dev)
-+{
-+ printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, disabling DMA\n",
-+ ap->id, dev->devno);
-+}
-+
-+static const char * ata_dma_blacklist [] = {
-+ "WDC AC11000H",
-+ "WDC AC22100H",
-+ "WDC AC32500H",
-+ "WDC AC33100H",
-+ "WDC AC31600H",
-+ "WDC AC32100H",
-+ "WDC AC23200L",
-+ "Compaq CRD-8241B",
-+ "CRD-8400B",
-+ "CRD-8480B",
-+ "CRD-8482B",
-+ "CRD-84",
-+ "SanDisk SDP3B",
-+ "SanDisk SDP3B-64",
-+ "SANYO CD-ROM CRD",
-+ "HITACHI CDR-8",
-+ "HITACHI CDR-8335",
-+ "HITACHI CDR-8435",
-+ "Toshiba CD-ROM XM-6202B",
-+ "CD-532E-A",
-+ "E-IDE CD-ROM CR-840",
-+ "CD-ROM Drive/F5A",
-+ "WPI CDD-820",
-+ "SAMSUNG CD-ROM SC-148C",
-+ "SAMSUNG CD-ROM SC",
-+ "SanDisk SDP3B-64",
-+ "SAMSUNG CD-ROM SN-124",
-+ "ATAPI CD-ROM DRIVE 40X MAXIMUM",
-+ "_NEC DV5800A",
-+};
-+
-+static int ata_dma_blacklisted(struct ata_port *ap, struct ata_device *dev)
-+{
-+ unsigned char model_num[40];
-+ char *s;
-+ unsigned int len;
-+ int i;
-+
-+ ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS,
-+ sizeof(model_num));
-+ s = &model_num[0];
-+ len = strnlen(s, sizeof(model_num));
-+
-+ /* ATAPI specifies that empty space is blank-filled; remove blanks */
-+ while ((len > 0) && (s[len - 1] == ' ')) {
-+ len--;
-+ s[len] = 0;
-+ }
-+
-+ for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i++)
-+ if (!strncmp(ata_dma_blacklist[i], s, len))
-+ return 1;
-+
-+ return 0;
-+}
-+
- static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift)
- {
- struct ata_device *master, *slave;
-@@ -1711,17 +1795,37 @@
-
- if (shift == ATA_SHIFT_UDMA) {
- mask = ap->udma_mask;
-- if (ata_dev_present(master))
-+ if (ata_dev_present(master)) {
- mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff);
-- if (ata_dev_present(slave))
-+ if (ata_dma_blacklisted(ap, master)) {
-+ mask = 0;
-+ ata_pr_blacklisted(ap, master);
-+ }
-+ }
-+ if (ata_dev_present(slave)) {
- mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff);
-+ if (ata_dma_blacklisted(ap, slave)) {
-+ mask = 0;
-+ ata_pr_blacklisted(ap, slave);
-+ }
-+ }
- }
- else if (shift == ATA_SHIFT_MWDMA) {
- mask = ap->mwdma_mask;
-- if (ata_dev_present(master))
-+ if (ata_dev_present(master)) {
- mask &= (master->id[ATA_ID_MWDMA_MODES] & 0x07);
-- if (ata_dev_present(slave))
-+ if (ata_dma_blacklisted(ap, master)) {
-+ mask = 0;
-+ ata_pr_blacklisted(ap, master);
-+ }
-+ }
-+ if (ata_dev_present(slave)) {
- mask &= (slave->id[ATA_ID_MWDMA_MODES] & 0x07);
-+ if (ata_dma_blacklisted(ap, slave)) {
-+ mask = 0;
-+ ata_pr_blacklisted(ap, slave);
-+ }
-+ }
- }
- else if (shift == ATA_SHIFT_PIO) {
- mask = ap->pio_mask;
-@@ -2518,10 +2622,10 @@
-
- case ATA_PROT_DMA:
- case ATA_PROT_ATAPI_DMA:
-- host_stat = ata_bmdma_status(ap);
-+ host_stat = ap->ops->bmdma_status(ap);
-
- /* before we do anything else, clear DMA-Start bit */
-- ata_bmdma_stop(ap);
-+ ap->ops->bmdma_stop(ap);
-
- /* fall through */
-
-@@ -2530,7 +2634,7 @@
- drv_stat = ata_chk_status(ap);
-
- /* ack bmdma irq events */
-- ata_bmdma_ack_irq(ap);
-+ ap->ops->irq_clear(ap);
-
- printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n",
- ap->id, qc->tf.command, drv_stat, host_stat);
-@@ -2669,6 +2773,24 @@
- }
-
- /**
-+ * ata_qc_free - free unused ata_queued_cmd
-+ * @qc: Command to complete
-+ *
-+ * Designed to free unused ata_queued_cmd object
-+ * in case something prevents using it.
-+ *
-+ * LOCKING:
-+ *
-+ */
-+void ata_qc_free(struct ata_queued_cmd *qc)
-+{
-+ assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */
-+ assert(qc->waiting == NULL); /* nothing should be waiting */
-+
-+ __ata_qc_complete(qc);
-+}
-+
-+/**
- * ata_qc_complete - Complete an active ATA command
- * @qc: Command to complete
- * @drv_stat: ATA status register contents
-@@ -2717,7 +2839,7 @@
- return 1;
-
- /* fall through */
--
-+
- default:
- return 0;
- }
-@@ -2959,7 +3081,43 @@
-
- void ata_bmdma_irq_clear(struct ata_port *ap)
- {
-- ata_bmdma_ack_irq(ap);
-+ if (ap->flags & ATA_FLAG_MMIO) {
-+ void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS;
-+ writeb(readb(mmio), mmio);
-+ } else {
-+ unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
-+ outb(inb(addr), addr);
-+ }
-+
-+}
-+
-+u8 ata_bmdma_status(struct ata_port *ap)
-+{
-+ u8 host_stat;
-+ if (ap->flags & ATA_FLAG_MMIO) {
-+ void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
-+ host_stat = readb(mmio + ATA_DMA_STATUS);
-+ } else
-+ host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
-+ return host_stat;
-+}
-+
-+void ata_bmdma_stop(struct ata_port *ap)
-+{
-+ if (ap->flags & ATA_FLAG_MMIO) {
-+ void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
-+
-+ /* clear start/stop bit */
-+ writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
-+ mmio + ATA_DMA_CMD);
-+ } else {
-+ /* clear start/stop bit */
-+ outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
-+ ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-+ }
-+
-+ /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
-+ ata_altstatus(ap); /* dummy read */
- }
-
- /**
-@@ -2989,7 +3147,7 @@
- case ATA_PROT_ATAPI_DMA:
- case ATA_PROT_ATAPI:
- /* check status of DMA engine */
-- host_stat = ata_bmdma_status(ap);
-+ host_stat = ap->ops->bmdma_status(ap);
- VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat);
-
- /* if it's not our irq... */
-@@ -2997,7 +3155,7 @@
- goto idle_irq;
-
- /* before we do anything else, clear DMA-Start bit */
-- ata_bmdma_stop(ap);
-+ ap->ops->bmdma_stop(ap);
-
- /* fall through */
-
-@@ -3016,7 +3174,7 @@
- ap->id, qc->tf.protocol, status);
-
- /* ack bmdma irq events */
-- ata_bmdma_ack_irq(ap);
-+ ap->ops->irq_clear(ap);
-
- /* complete taskfile transaction */
- ata_qc_complete(qc, status);
-@@ -3470,32 +3628,28 @@
- }
-
- static struct ata_probe_ent *
--ata_probe_ent_alloc(int n, struct device *dev, struct ata_port_info **port)
-+ata_probe_ent_alloc(struct device *dev, struct ata_port_info *port)
- {
- struct ata_probe_ent *probe_ent;
-- int i;
-
-- probe_ent = kmalloc(sizeof(*probe_ent) * n, GFP_KERNEL);
-+ probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
- if (!probe_ent) {
- printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
- pci_name(to_pci_dev(dev)));
- return NULL;
- }
-
-- memset(probe_ent, 0, sizeof(*probe_ent) * n);
-+ memset(probe_ent, 0, sizeof(*probe_ent));
-
-- for (i = 0; i < n; i++) {
-- INIT_LIST_HEAD(&probe_ent[i].node);
-- probe_ent[i].dev = dev;
--
-- probe_ent[i].sht = port[i]->sht;
-- probe_ent[i].host_flags = port[i]->host_flags;
-- probe_ent[i].pio_mask = port[i]->pio_mask;
-- probe_ent[i].mwdma_mask = port[i]->mwdma_mask;
-- probe_ent[i].udma_mask = port[i]->udma_mask;
-- probe_ent[i].port_ops = port[i]->port_ops;
-+ INIT_LIST_HEAD(&probe_ent->node);
-+ probe_ent->dev = dev;
-
-- }
-+ probe_ent->sht = port->sht;
-+ probe_ent->host_flags = port->host_flags;
-+ probe_ent->pio_mask = port->pio_mask;
-+ probe_ent->mwdma_mask = port->mwdma_mask;
-+ probe_ent->udma_mask = port->udma_mask;
-+ probe_ent->port_ops = port->port_ops;
-
- return probe_ent;
- }
-@@ -3505,7 +3659,7 @@
- ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port)
- {
- struct ata_probe_ent *probe_ent =
-- ata_probe_ent_alloc(1, pci_dev_to_dev(pdev), port);
-+ ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
- if (!probe_ent)
- return NULL;
-
-@@ -3531,39 +3685,47 @@
- return probe_ent;
- }
-
--struct ata_probe_ent *
--ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port)
-+static struct ata_probe_ent *
-+ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port,
-+ struct ata_probe_ent **ppe2)
- {
-- struct ata_probe_ent *probe_ent =
-- ata_probe_ent_alloc(2, pci_dev_to_dev(pdev), port);
-+ struct ata_probe_ent *probe_ent, *probe_ent2;
-+
-+ probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
- if (!probe_ent)
- return NULL;
-+ probe_ent2 = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[1]);
-+ if (!probe_ent2) {
-+ kfree(probe_ent);
-+ return NULL;
-+ }
-+
-+ probe_ent->n_ports = 1;
-+ probe_ent->irq = 14;
-
-- probe_ent[0].n_ports = 1;
-- probe_ent[0].irq = 14;
-+ probe_ent->hard_port_no = 0;
-+ probe_ent->legacy_mode = 1;
-
-- probe_ent[0].hard_port_no = 0;
-- probe_ent[0].legacy_mode = 1;
-+ probe_ent2->n_ports = 1;
-+ probe_ent2->irq = 15;
-
-- probe_ent[1].n_ports = 1;
-- probe_ent[1].irq = 15;
-+ probe_ent2->hard_port_no = 1;
-+ probe_ent2->legacy_mode = 1;
-
-- probe_ent[1].hard_port_no = 1;
-- probe_ent[1].legacy_mode = 1;
--
-- probe_ent[0].port[0].cmd_addr = 0x1f0;
-- probe_ent[0].port[0].altstatus_addr =
-- probe_ent[0].port[0].ctl_addr = 0x3f6;
-- probe_ent[0].port[0].bmdma_addr = pci_resource_start(pdev, 4);
--
-- probe_ent[1].port[0].cmd_addr = 0x170;
-- probe_ent[1].port[0].altstatus_addr =
-- probe_ent[1].port[0].ctl_addr = 0x376;
-- probe_ent[1].port[0].bmdma_addr = pci_resource_start(pdev, 4)+8;
-+ probe_ent->port[0].cmd_addr = 0x1f0;
-+ probe_ent->port[0].altstatus_addr =
-+ probe_ent->port[0].ctl_addr = 0x3f6;
-+ probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
-+
-+ probe_ent2->port[0].cmd_addr = 0x170;
-+ probe_ent2->port[0].altstatus_addr =
-+ probe_ent2->port[0].ctl_addr = 0x376;
-+ probe_ent2->port[0].bmdma_addr = pci_resource_start(pdev, 4)+8;
-
-- ata_std_ports(&probe_ent[0].port[0]);
-- ata_std_ports(&probe_ent[1].port[0]);
-+ ata_std_ports(&probe_ent->port[0]);
-+ ata_std_ports(&probe_ent2->port[0]);
-
-+ *ppe2 = probe_ent2;
- return probe_ent;
- }
-
-@@ -3587,6 +3749,7 @@
- struct ata_port_info *port[2];
- u8 tmp8, mask;
- unsigned int legacy_mode = 0;
-+ int disable_dev_on_err = 1;
- int rc;
-
- DPRINTK("ENTER\n");
-@@ -3597,7 +3760,8 @@
- else
- port[1] = port[0];
-
-- if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0) {
-+ if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0
-+ && (pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
- /* TODO: support transitioning to native mode? */
- pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
- mask = (1 << 2) | (1 << 0);
-@@ -3616,18 +3780,22 @@
- return rc;
-
- rc = pci_request_regions(pdev, DRV_NAME);
-- if (rc)
-+ if (rc) {
-+ disable_dev_on_err = 0;
- goto err_out;
-+ }
-
- if (legacy_mode) {
-- if (!request_region(0x1f0, 8, "libata"))
-+ if (!request_region(0x1f0, 8, "libata")) {
-+ disable_dev_on_err = 0;
- printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n");
-- else
-+ } else
- legacy_mode |= (1 << 0);
-
-- if (!request_region(0x170, 8, "libata"))
-+ if (!request_region(0x170, 8, "libata")) {
-+ disable_dev_on_err = 0;
- printk(KERN_WARNING "ata: 0x170 IDE port busy\n");
-- else
-+ } else
- legacy_mode |= (1 << 1);
- }
-
-@@ -3642,9 +3810,7 @@
- goto err_out_regions;
-
- if (legacy_mode) {
-- probe_ent = ata_pci_init_legacy_mode(pdev, port);
-- if (probe_ent)
-- probe_ent2 = &probe_ent[1];
-+ probe_ent = ata_pci_init_legacy_mode(pdev, port, &probe_ent2);
- } else
- probe_ent = ata_pci_init_native_mode(pdev, port);
- if (!probe_ent) {
-@@ -3656,17 +3822,14 @@
-
- spin_lock(&ata_module_lock);
- if (legacy_mode) {
-- int free = 0;
- if (legacy_mode & (1 << 0))
- list_add_tail(&probe_ent->node, &ata_probe_list);
- else
-- free++;
-+ kfree(probe_ent);
- if (legacy_mode & (1 << 1))
- list_add_tail(&probe_ent2->node, &ata_probe_list);
- else
-- free++;
-- if (free > 1)
-- kfree(probe_ent);
-+ kfree(probe_ent2);
- } else {
- list_add_tail(&probe_ent->node, &ata_probe_list);
- }
-@@ -3681,7 +3844,8 @@
- release_region(0x170, 8);
- pci_release_regions(pdev);
- err_out:
-- pci_disable_device(pdev);
-+ if (disable_dev_on_err)
-+ pci_disable_device(pdev);
- return rc;
- }
-
-@@ -3723,15 +3887,12 @@
- if (host_set->mmio_base)
- iounmap(host_set->mmio_base);
-
-- pci_release_regions(pdev);
--
- for (i = 0; i < host_set->n_ports; i++) {
-- struct ata_ioports *ioaddr;
--
- ap = host_set->ports[i];
-- ioaddr = &ap->ioaddr;
-
- if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) {
-+ struct ata_ioports *ioaddr = &ap->ioaddr;
-+
- if (ioaddr->cmd_addr == 0x1f0)
- release_region(0x1f0, 8);
- else if (ioaddr->cmd_addr == 0x170)
-@@ -3740,6 +3901,8 @@
- }
-
- kfree(host_set);
-+
-+ pci_release_regions(pdev);
- pci_disable_device(pdev);
- dev_set_drvdata(dev, NULL);
- }
-@@ -3839,6 +4002,8 @@
- EXPORT_SYMBOL_GPL(ata_tf_to_fis);
- EXPORT_SYMBOL_GPL(ata_tf_from_fis);
- EXPORT_SYMBOL_GPL(ata_check_status);
-+EXPORT_SYMBOL_GPL(ata_altstatus);
-+EXPORT_SYMBOL_GPL(ata_chk_err);
- EXPORT_SYMBOL_GPL(ata_exec_command);
- EXPORT_SYMBOL_GPL(ata_port_start);
- EXPORT_SYMBOL_GPL(ata_port_stop);
-@@ -3847,6 +4012,8 @@
- EXPORT_SYMBOL_GPL(ata_bmdma_setup);
- EXPORT_SYMBOL_GPL(ata_bmdma_start);
- EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
-+EXPORT_SYMBOL_GPL(ata_bmdma_status);
-+EXPORT_SYMBOL_GPL(ata_bmdma_stop);
- EXPORT_SYMBOL_GPL(ata_port_probe);
- EXPORT_SYMBOL_GPL(sata_phy_reset);
- EXPORT_SYMBOL_GPL(__sata_phy_reset);
-@@ -3857,7 +4024,6 @@
- EXPORT_SYMBOL_GPL(ata_scsi_error);
- EXPORT_SYMBOL_GPL(ata_scsi_detect);
- EXPORT_SYMBOL_GPL(ata_add_to_probe_list);
--EXPORT_SYMBOL_GPL(libata_msleep);
- EXPORT_SYMBOL_GPL(ssleep);
- EXPORT_SYMBOL_GPL(ata_scsi_release);
- EXPORT_SYMBOL_GPL(ata_host_intr);
-@@ -3867,7 +4033,6 @@
-
- #ifdef CONFIG_PCI
- EXPORT_SYMBOL_GPL(pci_test_config_bits);
--EXPORT_SYMBOL_GPL(ata_pci_init_legacy_mode);
- EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
- EXPORT_SYMBOL_GPL(ata_pci_init_one);
- EXPORT_SYMBOL_GPL(ata_pci_remove_one);
-diff -Nur linux-2.4.29/drivers/scsi/libata.h linux-mips/drivers/scsi/libata.h
---- linux-2.4.29/drivers/scsi/libata.h 2005-01-19 15:10:03.000000000 +0100
-+++ linux-mips/drivers/scsi/libata.h 2005-03-26 11:47:32.487319825 +0100
-@@ -37,6 +37,7 @@
- /* libata-core.c */
- extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
- struct ata_device *dev);
-+extern void ata_qc_free(struct ata_queued_cmd *qc);
- extern int ata_qc_issue(struct ata_queued_cmd *qc);
- extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
- extern void ata_dev_select(struct ata_port *ap, unsigned int device,
-diff -Nur linux-2.4.29/drivers/scsi/libata-scsi.c linux-mips/drivers/scsi/libata-scsi.c
---- linux-2.4.29/drivers/scsi/libata-scsi.c 2005-01-19 15:10:03.000000000 +0100
-+++ linux-mips/drivers/scsi/libata-scsi.c 2005-03-26 11:47:32.485320153 +0100
-@@ -203,7 +203,7 @@
- {0x40, MEDIUM_ERROR, 0x11, 0x04}, // Uncorrectable ECC error Unrecovered read error
- /* BBD - block marked bad */
- {0x80, MEDIUM_ERROR, 0x11, 0x04}, // Block marked bad Medium error, unrecovered read error
-- {0xFF, 0xFF, 0xFF, 0xFF}, // END mark
-+ {0xFF, 0xFF, 0xFF, 0xFF}, // END mark
- };
- static unsigned char stat_table[][4] = {
- /* Must be first because BUSY means no other bits valid */
-@@ -211,22 +211,22 @@
- {0x20, HARDWARE_ERROR, 0x00, 0x00}, // Device fault
- {0x08, ABORTED_COMMAND, 0x47, 0x00}, // Timed out in xfer, fake parity for now
- {0x04, RECOVERED_ERROR, 0x11, 0x00}, // Recovered ECC error Medium error, recovered
-- {0xFF, 0xFF, 0xFF, 0xFF}, // END mark
-+ {0xFF, 0xFF, 0xFF, 0xFF}, // END mark
- };
- int i = 0;
-
- cmd->result = SAM_STAT_CHECK_CONDITION;
--
-+
- /*
- * Is this an error we can process/parse
- */
--
-+
- if(drv_stat & ATA_ERR)
- /* Read the err bits */
- err = ata_chk_err(qc->ap);
-
- /* Display the ATA level error info */
--
-+
- printk(KERN_WARNING "ata%u: status=0x%02x { ", qc->ap->id, drv_stat);
- if(drv_stat & 0x80)
- {
-@@ -243,7 +243,7 @@
- if(drv_stat & 0x01) printk("Error ");
- }
- printk("}\n");
--
-+
- if(err)
- {
- printk(KERN_WARNING "ata%u: error=0x%02x { ", qc->ap->id, err);
-@@ -260,11 +260,11 @@
- if(err & 0x02) printk("TrackZeroNotFound ");
- if(err & 0x01) printk("AddrMarkNotFound ");
- printk("}\n");
--
-+
- /* Should we dump sector info here too ?? */
- }
--
--
-+
-+
- /* Look for err */
- while(sense_table[i][0] != 0xFF)
- {
-@@ -283,7 +283,8 @@
- /* No immediate match */
- if(err)
- printk(KERN_DEBUG "ata%u: no sense translation for 0x%02x\n", qc->ap->id, err);
--
-+
-+ i = 0;
- /* Fall back to interpreting status bits */
- while(stat_table[i][0] != 0xFF)
- {
-@@ -301,7 +302,7 @@
- /* No error ?? */
- printk(KERN_ERR "ata%u: called with no error (%02X)!\n", qc->ap->id, drv_stat);
- /* additional-sense-code[-qualifier] */
--
-+
- sb[0] = 0x70;
- sb[2] = MEDIUM_ERROR;
- sb[7] = 0x0A;
-@@ -449,19 +450,24 @@
- }
-
- if (lba48) {
-+ tf->command = ATA_CMD_VERIFY_EXT;
-+
- tf->hob_nsect = (n_sect >> 8) & 0xff;
-
- tf->hob_lbah = (sect >> 40) & 0xff;
- tf->hob_lbam = (sect >> 32) & 0xff;
- tf->hob_lbal = (sect >> 24) & 0xff;
-- } else
-+ } else {
-+ tf->command = ATA_CMD_VERIFY;
-+
- tf->device |= (sect >> 24) & 0xf;
-+ }
-
- tf->nsect = n_sect & 0xff;
-
-- tf->hob_lbah = (sect >> 16) & 0xff;
-- tf->hob_lbam = (sect >> 8) & 0xff;
-- tf->hob_lbal = sect & 0xff;
-+ tf->lbah = (sect >> 16) & 0xff;
-+ tf->lbam = (sect >> 8) & 0xff;
-+ tf->lbal = sect & 0xff;
-
- return 0;
- }
-@@ -561,7 +567,7 @@
- return 1;
-
- /* stores LBA27:24 in lower 4 bits of device reg */
-- tf->device |= scsicmd[2];
-+ tf->device |= scsicmd[6];
-
- qc->nsect = scsicmd[13];
- }
-@@ -657,6 +663,7 @@
- return;
-
- err_out:
-+ ata_qc_free(qc);
- ata_bad_cdb(cmd, done);
- DPRINTK("EXIT - badcmd\n");
- }
-diff -Nur linux-2.4.29/drivers/scsi/Makefile linux-mips/drivers/scsi/Makefile
---- linux-2.4.29/drivers/scsi/Makefile 2005-01-19 15:09:59.000000000 +0100
-+++ linux-mips/drivers/scsi/Makefile 2005-03-26 11:47:32.445326717 +0100
-@@ -134,6 +134,7 @@
- obj-$(CONFIG_SCSI_SATA_SVW) += libata.o sata_svw.o
- obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o
- obj-$(CONFIG_SCSI_SATA_PROMISE) += libata.o sata_promise.o
-+obj-$(CONFIG_SCSI_SATA_QSTOR) += libata.o sata_qstor.o
- obj-$(CONFIG_SCSI_SATA_SIL) += libata.o sata_sil.o
- obj-$(CONFIG_SCSI_SATA_VIA) += libata.o sata_via.o
- obj-$(CONFIG_SCSI_SATA_VITESSE) += libata.o sata_vsc.o
-diff -Nur linux-2.4.29/drivers/scsi/megaraid2.c linux-mips/drivers/scsi/megaraid2.c
---- linux-2.4.29/drivers/scsi/megaraid2.c 2004-11-17 12:54:21.000000000 +0100
-+++ linux-mips/drivers/scsi/megaraid2.c 2005-03-26 11:47:33.007234495 +0100
-@@ -14,7 +14,7 @@
- * - speed-ups (list handling fixes, issued_list, optimizations.)
- * - lots of cleanups.
- *
-- * Version : v2.10.3 (Apr 08, 2004)
-+ * Version : v2.10.8.2 (July 26, 2004)
- *
- * Authors: Atul Mukker <Atul.Mukker@lsil.com>
- * Sreenivas Bagalkote <Sreenivas.Bagalkote@lsil.com>
-@@ -46,7 +46,7 @@
-
- #include "megaraid2.h"
-
--#ifdef LSI_CONFIG_COMPAT
-+#if defined(__x86_64__)
- #include <asm/ioctl32.h>
- #endif
-
-@@ -90,10 +90,15 @@
- static struct mega_hbas mega_hbas[MAX_CONTROLLERS];
-
- /*
-+ * Lock to protect access to IOCTL
-+ */
-+static struct semaphore megaraid_ioc_mtx;
-+
-+/*
- * The File Operations structure for the serial/ioctl interface of the driver
- */
- static struct file_operations megadev_fops = {
-- .ioctl = megadev_ioctl,
-+ .ioctl = megadev_ioctl_entry,
- .open = megadev_open,
- .release = megadev_close,
- .owner = THIS_MODULE,
-@@ -107,7 +112,7 @@
- static struct mcontroller mcontroller[MAX_CONTROLLERS];
-
- /* The current driver version */
--static u32 driver_ver = 0x02100000;
-+static u32 driver_ver = 0x02104000;
-
- /* major number used by the device for character interface */
- static int major;
-@@ -189,6 +194,11 @@
- */
- mega_reorder_hosts();
-
-+ /*
-+ * Initialize the IOCTL lock
-+ */
-+ init_MUTEX( &megaraid_ioc_mtx );
-+
- #ifdef CONFIG_PROC_FS
- mega_proc_dir_entry = proc_mkdir("megaraid", &proc_root);
-
-@@ -223,7 +233,7 @@
- "MegaRAID Shutdown routine not registered!!\n");
- }
-
--#ifdef LSI_CONFIG_COMPAT
-+#if defined(__x86_64__)
- /*
- * Register the 32-bit ioctl conversion
- */
-@@ -273,6 +283,8 @@
- unsigned long tbase;
- unsigned long flag = 0;
- int i, j;
-+ u8 did_int_pthru_f = 0;
-+ u8 did_int_data_f = 0;
-
- while((pdev = pci_find_device(pci_vendor, pci_device, pdev))) {
-
-@@ -328,6 +340,7 @@
- (subsysvid != HP_SUBSYS_VID) &&
- (subsysvid != INTEL_SUBSYS_VID) &&
- (subsysvid != FSC_SUBSYS_VID) &&
-+ (subsysvid != ACER_SUBSYS_VID) &&
- (subsysvid != LSI_SUBSYS_VID) ) continue;
-
-
-@@ -465,6 +478,33 @@
-
- alloc_scb_f = 1;
-
-+ /*
-+ * Allocate memory for ioctls
-+ */
-+ adapter->int_pthru = pci_alloc_consistent (
-+ adapter->dev,
-+ sizeof(mega_passthru),
-+ &adapter->int_pthru_dma_hndl );
-+
-+ if( adapter->int_pthru == NULL ) {
-+ printk(KERN_WARNING "megaraid: out of RAM.\n");
-+ goto fail_attach;
-+ }
-+ else
-+ did_int_pthru_f = 1;
-+
-+ adapter->int_data = pci_alloc_consistent (
-+ adapter->dev,
-+ INT_MEMBLK_SZ,
-+ &adapter->int_data_dma_hndl );
-+
-+ if( adapter->int_data == NULL ) {
-+ printk(KERN_WARNING "megaraid: out of RAM.\n");
-+ goto fail_attach;
-+ }
-+ else
-+ did_int_data_f = 1;
-+
- /* Request our IRQ */
- if( adapter->flag & BOARD_MEMMAP ) {
- if(request_irq(irq, megaraid_isr_memmapped, SA_SHIRQ,
-@@ -676,6 +716,19 @@
- continue;
-
- fail_attach:
-+ if( did_int_data_f ) {
-+ pci_free_consistent(
-+ adapter->dev, INT_MEMBLK_SZ, adapter->int_data,
-+ adapter->int_data_dma_hndl );
-+ }
-+
-+ if( did_int_pthru_f ) {
-+ pci_free_consistent(
-+ adapter->dev, sizeof(mega_passthru),
-+ (void*) adapter->int_pthru,
-+ adapter->int_pthru_dma_hndl );
-+ }
-+
- if( did_setup_mbox_f ) {
- pci_free_consistent(adapter->dev, sizeof(mbox64_t),
- (void *)adapter->una_mbox64,
-@@ -937,6 +990,78 @@
-
-
- /**
-+ * issue_scb()
-+ * @adapter - pointer to our soft state
-+ * @scb - scsi control block
-+ *
-+ * Post a command to the card if the mailbox is available, otherwise return
-+ * busy. We also take the scb from the pending list if the mailbox is
-+ * available.
-+ */
-+static inline int
-+issue_scb(adapter_t *adapter, scb_t *scb)
-+{
-+ volatile mbox64_t *mbox64 = adapter->mbox64;
-+ volatile mbox_t *mbox = adapter->mbox;
-+ unsigned int i = 0;
-+
-+ if(unlikely(mbox->busy)) {
-+ do {
-+ udelay(1);
-+ i++;
-+ } while( mbox->busy && (i < max_mbox_busy_wait) );
-+
-+ if(mbox->busy) return -1;
-+ }
-+
-+ /* Copy mailbox data into host structure */
-+ memcpy((char *)mbox, (char *)scb->raw_mbox, 16);
-+
-+ mbox->cmdid = scb->idx; /* Set cmdid */
-+ mbox->busy = 1; /* Set busy */
-+
-+
-+ /*
-+ * Increment the pending queue counter
-+ */
-+ atomic_inc(&adapter->pend_cmds);
-+
-+ switch (mbox->cmd) {
-+ case MEGA_MBOXCMD_EXTPTHRU:
-+ if( !adapter->has_64bit_addr ) break;
-+ // else fall through
-+ case MEGA_MBOXCMD_LREAD64:
-+ case MEGA_MBOXCMD_LWRITE64:
-+ case MEGA_MBOXCMD_PASSTHRU64:
-+ mbox64->xfer_segment_lo = mbox->xferaddr;
-+ mbox64->xfer_segment_hi = 0;
-+ mbox->xferaddr = 0xFFFFFFFF;
-+ break;
-+ default:
-+ mbox64->xfer_segment_lo = 0;
-+ mbox64->xfer_segment_hi = 0;
-+ }
-+
-+ /*
-+ * post the command
-+ */
-+ scb->state |= SCB_ISSUED;
-+
-+ if( likely(adapter->flag & BOARD_MEMMAP) ) {
-+ mbox->poll = 0;
-+ mbox->ack = 0;
-+ WRINDOOR(adapter, adapter->mbox_dma | 0x1);
-+ }
-+ else {
-+ irq_enable(adapter);
-+ issue_command(adapter);
-+ }
-+
-+ return 0;
-+}
-+
-+
-+/**
- * mega_runpendq()
- * @adapter - pointer to our soft state
- *
-@@ -949,52 +1074,26 @@
- __mega_runpendq(adapter);
- }
-
--/*
-- * megaraid_queue()
-- * @scmd - Issue this scsi command
-- * @done - the callback hook into the scsi mid-layer
-- *
-- * The command queuing entry point for the mid-layer.
-- */
--static int
--megaraid_queue(Scsi_Cmnd *scmd, void (*done)(Scsi_Cmnd *))
--{
-- adapter_t *adapter;
-- scb_t *scb;
-- int busy=0;
--
-- adapter = (adapter_t *)scmd->host->hostdata;
--
-- scmd->scsi_done = done;
-
-+static void
-+__mega_runpendq(adapter_t *adapter)
-+{
-+ scb_t *scb;
-+ struct list_head *pos, *next;
-
-- /*
-- * Allocate and build a SCB request
-- * busy flag will be set if mega_build_cmd() command could not
-- * allocate scb. We will return non-zero status in that case.
-- * NOTE: scb can be null even though certain commands completed
-- * successfully, e.g., MODE_SENSE and TEST_UNIT_READY, we would
-- * return 0 in that case.
-- */
-+ /* Issue any pending commands to the card */
-+ list_for_each_safe(pos, next, &adapter->pending_list) {
-
-- scb = mega_build_cmd(adapter, scmd, &busy);
-+ scb = list_entry(pos, scb_t, list);
-
-- if(scb) {
-- scb->state |= SCB_PENDQ;
-- list_add_tail(&scb->list, &adapter->pending_list);
-+ if( !(scb->state & SCB_ISSUED) ) {
-
-- /*
-- * Check if the HBA is in quiescent state, e.g., during a
-- * delete logical drive opertion. If it is, don't run
-- * the pending_list.
-- */
-- if(atomic_read(&adapter->quiescent) == 0) {
-- mega_runpendq(adapter);
-+ if( issue_scb(adapter, scb) != 0 )
-+ return;
- }
-- return 0;
- }
-
-- return busy;
-+ return;
- }
-
-
-@@ -1068,25 +1167,136 @@
- }
-
- /*
-- * If "delete logical drive" feature is enabled on this controller.
-- * Do only if at least one delete logical drive operation was done.
-- *
-- * Also, after logical drive deletion, instead of logical drive number,
-+ * If "delete logical drive" feature is enabled on this controller,
- * the value returned should be 0x80+logical drive id.
-- *
-- * These is valid only for IO commands.
- */
-+ if (adapter->support_random_del)
-+ ldrv_num += 0x80;
-
-- if (adapter->support_random_del && adapter->read_ldidmap )
-- switch (cmd->cmnd[0]) {
-- case READ_6: /* fall through */
-- case WRITE_6: /* fall through */
-- case READ_10: /* fall through */
-- case WRITE_10:
-- ldrv_num += 0x80;
-+ return ldrv_num;
-+}
-+
-+/*
-+ * Wait until the controller's mailbox is available
-+ */
-+static inline int
-+mega_busywait_mbox (adapter_t *adapter)
-+{
-+ if (adapter->mbox->busy)
-+ return __mega_busywait_mbox(adapter);
-+ return 0;
-+}
-+
-+
-+/**
-+ * megaraid_iombox_ack_sequence - interrupt ack sequence for IO mapped HBAs
-+ * @adapter - controller's soft state
-+ *
-+ * Interrupt ackrowledgement sequence for IO mapped HBAs
-+ */
-+static inline void
-+megaraid_iombox_ack_sequence(adapter_t *adapter)
-+{
-+ u8 status;
-+ u8 nstatus;
-+ u8 completed[MAX_FIRMWARE_STATUS];
-+ u8 byte;
-+ int i;
-+
-+
-+ /*
-+ * loop till F/W has more commands for us to complete.
-+ */
-+ do {
-+ /* Check if a valid interrupt is pending */
-+ byte = irq_state(adapter);
-+ if( (byte & VALID_INTR_BYTE) == 0 ) {
-+ return;
- }
-+ set_irq_state(adapter, byte);
-
-- return ldrv_num;
-+ while ((nstatus = adapter->mbox->numstatus) == 0xFF) {
-+ cpu_relax();
-+ }
-+ adapter->mbox->numstatus = 0xFF;
-+
-+ for (i = 0; i < nstatus; i++) {
-+ while ((completed[i] = adapter->mbox->completed[i])
-+ == 0xFF) {
-+ cpu_relax();
-+ }
-+
-+ adapter->mbox->completed[i] = 0xFF;
-+ }
-+
-+ // we must read the valid status now
-+ if ((status = adapter->mbox->status) == 0xFF) {
-+ printk(KERN_WARNING
-+ "megaraid critical: status 0xFF from firmware.\n");
-+ }
-+ adapter->mbox->status = 0xFF;
-+
-+ /*
-+ * decrement the pending queue counter
-+ */
-+ atomic_sub(nstatus, &adapter->pend_cmds);
-+
-+ /* Acknowledge interrupt */
-+ irq_ack(adapter);
-+
-+ mega_cmd_done(adapter, completed, nstatus, status);
-+
-+ } while(1);
-+}
-+
-+
-+
-+/*
-+ * megaraid_queue()
-+ * @scmd - Issue this scsi command
-+ * @done - the callback hook into the scsi mid-layer
-+ *
-+ * The command queuing entry point for the mid-layer.
-+ */
-+static int
-+megaraid_queue(Scsi_Cmnd *scmd, void (*done)(Scsi_Cmnd *))
-+{
-+ adapter_t *adapter;
-+ scb_t *scb;
-+ int busy=0;
-+
-+ adapter = (adapter_t *)scmd->host->hostdata;
-+
-+ scmd->scsi_done = done;
-+
-+
-+ /*
-+ * Allocate and build a SCB request
-+ * busy flag will be set if mega_build_cmd() command could not
-+ * allocate scb. We will return non-zero status in that case.
-+ * NOTE: scb can be null even though certain commands completed
-+ * successfully, e.g., MODE_SENSE and TEST_UNIT_READY, we would
-+ * return 0 in that case.
-+ */
-+
-+ scb = mega_build_cmd(adapter, scmd, &busy);
-+
-+ if(scb) {
-+ scb->state |= SCB_PENDQ;
-+ list_add_tail(&scb->list, &adapter->pending_list);
-+
-+ /*
-+ * Check if the HBA is in quiescent state, e.g., during a
-+ * delete logical drive opertion. If it is, don't run
-+ * the pending_list.
-+ */
-+ if(atomic_read(&adapter->quiescent) == 0) {
-+ mega_runpendq(adapter);
-+ }
-+ return 0;
-+ }
-+
-+ return busy;
- }
-
-
-@@ -1112,7 +1322,6 @@
- mbox_t *mbox;
- long seg;
- char islogical;
-- int max_ldrv_num;
- int channel = 0;
- int target = 0;
- int ldrv_num = 0; /* logical drive number */
-@@ -1184,24 +1393,6 @@
- }
-
- ldrv_num = mega_get_ldrv_num(adapter, cmd, channel);
--
--
-- max_ldrv_num = (adapter->flag & BOARD_40LD) ?
-- MAX_LOGICAL_DRIVES_40LD : MAX_LOGICAL_DRIVES_8LD;
--
-- /*
-- * max_ldrv_num increases by 0x80 if some logical drive was
-- * deleted.
-- */
-- if(adapter->read_ldidmap)
-- max_ldrv_num += 0x80;
--
-- if(ldrv_num > max_ldrv_num ) {
-- cmd->result = (DID_BAD_TARGET << 16);
-- cmd->scsi_done(cmd);
-- return NULL;
-- }
--
- }
- else {
- if( cmd->lun > 7) {
-@@ -1671,111 +1862,6 @@
- }
-
-
--static void
--__mega_runpendq(adapter_t *adapter)
--{
-- scb_t *scb;
-- struct list_head *pos, *next;
--
-- /* Issue any pending commands to the card */
-- list_for_each_safe(pos, next, &adapter->pending_list) {
--
-- scb = list_entry(pos, scb_t, list);
--
-- if( !(scb->state & SCB_ISSUED) ) {
--
-- if( issue_scb(adapter, scb) != 0 )
-- return;
-- }
-- }
--
-- return;
--}
--
--
--/**
-- * issue_scb()
-- * @adapter - pointer to our soft state
-- * @scb - scsi control block
-- *
-- * Post a command to the card if the mailbox is available, otherwise return
-- * busy. We also take the scb from the pending list if the mailbox is
-- * available.
-- */
--static int
--issue_scb(adapter_t *adapter, scb_t *scb)
--{
-- volatile mbox64_t *mbox64 = adapter->mbox64;
-- volatile mbox_t *mbox = adapter->mbox;
-- unsigned int i = 0;
--
-- if(unlikely(mbox->busy)) {
-- do {
-- udelay(1);
-- i++;
-- } while( mbox->busy && (i < max_mbox_busy_wait) );
--
-- if(mbox->busy) return -1;
-- }
--
-- /* Copy mailbox data into host structure */
-- memcpy((char *)mbox, (char *)scb->raw_mbox, 16);
--
-- mbox->cmdid = scb->idx; /* Set cmdid */
-- mbox->busy = 1; /* Set busy */
--
--
-- /*
-- * Increment the pending queue counter
-- */
-- atomic_inc(&adapter->pend_cmds);
--
-- switch (mbox->cmd) {
-- case MEGA_MBOXCMD_EXTPTHRU:
-- if( !adapter->has_64bit_addr ) break;
-- // else fall through
-- case MEGA_MBOXCMD_LREAD64:
-- case MEGA_MBOXCMD_LWRITE64:
-- case MEGA_MBOXCMD_PASSTHRU64:
-- mbox64->xfer_segment_lo = mbox->xferaddr;
-- mbox64->xfer_segment_hi = 0;
-- mbox->xferaddr = 0xFFFFFFFF;
-- break;
-- default:
-- mbox64->xfer_segment_lo = 0;
-- mbox64->xfer_segment_hi = 0;
-- }
--
-- /*
-- * post the command
-- */
-- scb->state |= SCB_ISSUED;
--
-- if( likely(adapter->flag & BOARD_MEMMAP) ) {
-- mbox->poll = 0;
-- mbox->ack = 0;
-- WRINDOOR(adapter, adapter->mbox_dma | 0x1);
-- }
-- else {
-- irq_enable(adapter);
-- issue_command(adapter);
-- }
--
-- return 0;
--}
--
--
--/*
-- * Wait until the controller's mailbox is available
-- */
--static inline int
--mega_busywait_mbox (adapter_t *adapter)
--{
-- if (adapter->mbox->busy)
-- return __mega_busywait_mbox(adapter);
-- return 0;
--}
--
- /**
- * issue_scb_block()
- * @adapter - pointer to our soft state
-@@ -1865,77 +1951,47 @@
- // invalidate the completed command id array. After command
- // completion, firmware would write the valid id.
- for (i = 0; i < MAX_FIRMWARE_STATUS; i++) {
-- mbox->completed[i] = 0xFF;
-- }
--
-- return status;
--
--bug_blocked_mailbox:
-- printk(KERN_WARNING "megaraid: Blocked mailbox......!!\n");
-- udelay (1000);
-- return -1;
--}
--
--
--/**
-- * megaraid_iombox_ack_sequence - interrupt ack sequence for IO mapped HBAs
-- * @adapter - controller's soft state
-- *
-- * Interrupt ackrowledgement sequence for IO mapped HBAs
-- */
--static inline void
--megaraid_iombox_ack_sequence(adapter_t *adapter)
--{
-- u8 status;
-- u8 nstatus;
-- u8 completed[MAX_FIRMWARE_STATUS];
-- u8 byte;
-- int i;
--
--
-- /*
-- * loop till F/W has more commands for us to complete.
-- */
-- do {
-- /* Check if a valid interrupt is pending */
-- byte = irq_state(adapter);
-- if( (byte & VALID_INTR_BYTE) == 0 ) {
-- return;
-- }
-- set_irq_state(adapter, byte);
-+ mbox->completed[i] = 0xFF;
-+ }
-
-- while ((nstatus = adapter->mbox->numstatus) == 0xFF) {
-- cpu_relax();
-- }
-- adapter->mbox->numstatus = 0xFF;
-+ return status;
-
-- for (i = 0; i < nstatus; i++) {
-- while ((completed[i] = adapter->mbox->completed[i])
-- == 0xFF) {
-- cpu_relax();
-- }
-+bug_blocked_mailbox:
-+ printk(KERN_WARNING "megaraid: Blocked mailbox......!!\n");
-+ udelay (1000);
-+ return -1;
-+}
-
-- adapter->mbox->completed[i] = 0xFF;
-- }
-
-- // we must read the valid status now
-- if ((status = adapter->mbox->status) == 0xFF) {
-- printk(KERN_WARNING
-- "megaraid critical: status 0xFF from firmware.\n");
-- }
-- adapter->mbox->status = 0xFF;
-+/**
-+ * megaraid_isr_iomapped()
-+ * @irq - irq
-+ * @devp - pointer to our soft state
-+ * @regs - unused
-+ *
-+ * Interrupt service routine for io-mapped controllers.
-+ * Find out if our device is interrupting. If yes, acknowledge the interrupt
-+ * and service the completed commands.
-+ */
-+static void
-+megaraid_isr_iomapped(int irq, void *devp, struct pt_regs *regs)
-+{
-+ adapter_t *adapter = devp;
-+ unsigned long flags;
-
-- /*
-- * decrement the pending queue counter
-- */
-- atomic_sub(nstatus, &adapter->pend_cmds);
-
-- /* Acknowledge interrupt */
-- irq_ack(adapter);
-+ spin_lock_irqsave(adapter->host_lock, flags);
-
-- mega_cmd_done(adapter, completed, nstatus, status);
-+ megaraid_iombox_ack_sequence(adapter);
-
-- } while(1);
-+ /* Loop through any pending requests */
-+ if( atomic_read(&adapter->quiescent ) == 0) {
-+ mega_runpendq(adapter);
-+ }
-+
-+ spin_unlock_irqrestore(adapter->host_lock, flags);
-+
-+ return;
- }
-
-
-@@ -2007,38 +2063,6 @@
-
-
- /**
-- * megaraid_isr_iomapped()
-- * @irq - irq
-- * @devp - pointer to our soft state
-- * @regs - unused
-- *
-- * Interrupt service routine for io-mapped controllers.
-- * Find out if our device is interrupting. If yes, acknowledge the interrupt
-- * and service the completed commands.
-- */
--static void
--megaraid_isr_iomapped(int irq, void *devp, struct pt_regs *regs)
--{
-- adapter_t *adapter = devp;
-- unsigned long flags;
--
--
-- spin_lock_irqsave(adapter->host_lock, flags);
--
-- megaraid_iombox_ack_sequence(adapter);
--
-- /* Loop through any pending requests */
-- if( atomic_read(&adapter->quiescent ) == 0) {
-- mega_runpendq(adapter);
-- }
--
-- spin_unlock_irqrestore(adapter->host_lock, flags);
--
-- return;
--}
--
--
--/**
- * megaraid_isr_memmapped()
- * @irq - irq
- * @devp - pointer to our soft state
-@@ -2069,7 +2093,6 @@
- return;
- }
-
--
- /**
- * mega_cmd_done()
- * @adapter - pointer to our soft state
-@@ -2381,7 +2404,6 @@
- list_add(&scb->list, &adapter->free_list);
- }
-
--
- static int
- __mega_busywait_mbox (adapter_t *adapter)
- {
-@@ -2412,6 +2434,10 @@
-
- cmd = scb->cmd;
-
-+ /* return 0 elements if no data transfer */
-+ if (!cmd->request_buffer || !cmd->request_bufflen)
-+ return 0;
-+
- /* Scatter-gather not used */
- if( !cmd->use_sg ) {
-
-@@ -2535,7 +2561,6 @@
- enquiry3->pdrv_state[i] = inquiry->pdrv_info.pdrv_state[i];
- }
-
--
- static inline void
- mega_free_sgl(adapter_t *adapter)
- {
-@@ -2666,6 +2691,13 @@
- pci_free_consistent(adapter->dev, sizeof(mbox64_t),
- (void *)adapter->una_mbox64, adapter->una_mbox64_dma);
-
-+ pci_free_consistent( adapter->dev, sizeof(mega_passthru),
-+ (void*) adapter->int_pthru,
-+ adapter->int_pthru_dma_hndl );
-+
-+ pci_free_consistent( adapter->dev, INT_MEMBLK_SZ, adapter->int_data,
-+ adapter->int_data_dma_hndl );
-+
- hba_count--;
-
- if( hba_count == 0 ) {
-@@ -2694,7 +2726,7 @@
- */
- scsi_unregister(host);
-
--#ifdef LSI_CONFIG_COMPAT
-+#if defined(__x86_64__)
- unregister_ioctl32_conversion(MEGAIOCCMD);
- #endif
-
-@@ -2736,30 +2768,36 @@
- }
-
-
--/**
-- * megaraid_abort - abort the scsi command
-- * @scp - command to be aborted
-- *
-- * Abort a previous SCSI request. Only commands on the pending list can be
-- * aborted. All the commands issued to the F/W must complete.
-- */
- static int
- megaraid_abort(Scsi_Cmnd *scp)
- {
- adapter_t *adapter;
- struct list_head *pos, *next;
- scb_t *scb;
-- long iter;
-- int rval = SUCCESS;
-+
-+ printk("megaraid: aborting-%ld cmd=%x <c=%d t=%d l=%d>\n",
-+ scp->serial_number, scp->cmnd[0], scp->channel,
-+ scp->target, scp->lun);
-
- adapter = (adapter_t *)scp->host->hostdata;
-
-- ASSERT( spin_is_locked(adapter->host_lock) );
-+ /*
-+ * Check if hw_error flag was set in previous RESET call. If it was,
-+ * then FW is hanging and unlikely to function. We can return FAILURE
-+ * from here and expect the RESET handler to be called.
-+ */
-
-- printk("megaraid: aborting-%ld cmd=%x <c=%d t=%d l=%d>\n",
-- scp->serial_number, scp->cmnd[0], scp->channel, scp->target,
-- scp->lun);
-+ if (adapter->hw_error) {
-+ printk("megaraid: hw error, cannot abort\n");
-+ return FAILED;
-+ }
-+
-+ ASSERT( spin_is_locked(adapter->host_lock) );
-
-+ /*
-+ * If cmd is waiting to be issued to FW, ABORT it with SUCEESS. If it
-+ * has already been issued, return FAILURE and expect RESET later.
-+ */
-
- list_for_each_safe( pos, next, &adapter->pending_list ) {
-
-@@ -2769,15 +2807,11 @@
-
- scb->state |= SCB_ABORT;
-
-- /*
-- * Check if this command was never issued. If this is
-- * the case, take it off from the pending list and
-- * complete.
-- */
- if( !(scb->state & SCB_ISSUED) ) {
-
-- printk(KERN_WARNING
-- "megaraid: %ld:%d, driver owner.\n",
-+ /* Not issued to the FW yet; ABORT it */
-+
-+ printk( "megaraid: %ld:%d, driver owner.\n",
- scp->serial_number, scb->idx);
-
- scp->result = (DID_ABORT << 16);
-@@ -2786,67 +2820,31 @@
-
- scp->scsi_done(scp);
-
-- break;
-+ return SUCCESS;
-+ }
-+ else {
-+ /* Issued to the FW; can do nothing */
-+ return FAILED;
- }
- }
- }
-
- /*
-- * By this time, either all commands are completed or aborted by
-- * mid-layer. Do not return until all the commands are actually
-- * completed by the firmware
-+ * cmd is _not_ in our pending_list. Most likely we completed the cmd
- */
-- iter = 0;
-- while( atomic_read(&adapter->pend_cmds) > 0 ) {
-- /*
-- * Perform the ack sequence, since interrupts are not
-- * available right now!
-- */
-- if( adapter->flag & BOARD_MEMMAP ) {
-- megaraid_memmbox_ack_sequence(adapter);
-- }
-- else {
-- megaraid_iombox_ack_sequence(adapter);
-- }
--
-- /*
-- * print a message once every second only
-- */
-- if( !(iter % 1000) ) {
-- printk(
-- "megaraid: Waiting for %d commands to flush: iter:%ld\n",
-- atomic_read(&adapter->pend_cmds), iter);
-- }
--
-- if( iter++ < MBOX_ABORT_SLEEP*1000 ) {
-- mdelay(1);
-- }
-- else {
-- printk(KERN_WARNING
-- "megaraid: critical hardware error!\n");
--
-- rval = FAILED;
--
-- break;
-- }
-- }
--
-- if( rval == SUCCESS ) {
-- printk(KERN_INFO
-- "megaraid: abort sequence successfully completed.\n");
-- }
--
-- return rval;
-+ return SUCCESS;
- }
-
-
- static int
- megaraid_reset(Scsi_Cmnd *cmd)
- {
-- adapter_t *adapter;
-- megacmd_t mc;
-- long iter;
-- int rval = SUCCESS;
-+ DECLARE_WAIT_QUEUE_HEAD(wq);
-+ int i;
-+ scb_t *scb;
-+ adapter_t *adapter;
-+ struct list_head *pos, *next;
-+ int rval;
-
- adapter = (adapter_t *)cmd->host->hostdata;
-
-@@ -2856,31 +2854,54 @@
- cmd->serial_number, cmd->cmnd[0], cmd->channel, cmd->target,
- cmd->lun);
-
-+ /*
-+ * Check if hw_error flag was set in previous RESET call. If it was,
-+ * then we needn't do any handling here. The controller will be marked
-+ * offline soon
-+ */
-
--#if MEGA_HAVE_CLUSTERING
-- mc.cmd = MEGA_CLUSTER_CMD;
-- mc.opcode = MEGA_RESET_RESERVATIONS;
--
-- spin_unlock_irq(adapter->host_lock);
-- if( mega_internal_command(adapter, LOCK_INT, &mc, NULL) != 0 ) {
-- printk(KERN_WARNING
-- "megaraid: reservation reset failed.\n");
-+ if (adapter->hw_error) {
-+ printk("megaraid: hw error, cannot reset\n");
-+ return FAILED;
- }
-- else {
-- printk(KERN_INFO "megaraid: reservation reset.\n");
-+
-+ /*
-+ * Return all the pending cmds to the mid-layer with the cmd result
-+ * DID_RESET. Make sure you don't return the cmds ISSUED to FW.
-+ */
-+ list_for_each_safe( pos, next, &adapter->pending_list ) {
-+
-+ scb = list_entry(pos, scb_t, list);
-+ scb->state |= SCB_RESET;
-+
-+ if( !(scb->state & SCB_ISSUED) ) {
-+
-+ /* Not issued to the FW; return with RESET */
-+ cmd->result = (DID_RESET << 16);
-+
-+ mega_free_scb(adapter, scb);
-+ cmd->scsi_done(cmd);
-+ }
- }
-- spin_lock_irq(adapter->host_lock);
--#endif
-
- /*
-- * Do not return until all the commands are actually completed by the
-- * firmware
-+ * Under exceptional conditions, FW may take up to 3 mins to complete
-+ * processing all pending commands. We'll wait for maximum 3 mins to
-+ * see if all outstanding commands are completed.
- */
-- iter = 0;
-- while( atomic_read(&adapter->pend_cmds) > 0 ) {
-+
-+ if (atomic_read(&adapter->pend_cmds) == 0)
-+ return SUCCESS;
-+
-+ printk("megaraid: %d pending cmds; max wait %d seconds\n",
-+ atomic_read(&adapter->pend_cmds), MBOX_RESET_WAIT );
-+
-+ for(i=0; (i<MBOX_RESET_WAIT)&&(atomic_read(&adapter->pend_cmds)); i++){
-+
-+ ASSERT( spin_is_locked(adapter->host_lock) );
-+
- /*
-- * Perform the ack sequence, since interrupts are not
-- * available right now!
-+ * Perform the ack sequence, since interrupts are unavailable
- */
- if( adapter->flag & BOARD_MEMMAP ) {
- megaraid_memmbox_ack_sequence(adapter);
-@@ -2889,55 +2910,35 @@
- megaraid_iombox_ack_sequence(adapter);
- }
-
-- /*
-- * print a message once every second only
-- */
-- if( !(iter % 1000) ) {
-- printk(
-- "megaraid: Waiting for %d commands to flush: iter:%ld\n",
-- atomic_read(&adapter->pend_cmds), iter);
-- }
-+ spin_unlock(adapter->host_lock);
-
-- if( iter++ < MBOX_RESET_SLEEP*1000 ) {
-- mdelay(1);
-+ /* Print a message once every 5 seconds */
-+ if (!(i % 5)) {
-+ printk("megaraid: pending %d; remaining %d seconds\n",
-+ atomic_read(&adapter->pend_cmds),
-+ MBOX_RESET_WAIT - i);
- }
-- else {
-- printk(KERN_WARNING
-- "megaraid: critical hardware error!\n");
-
-- rval = FAILED;
--
-- break;
-- }
-- }
-+ sleep_on_timeout(&wq, HZ);
-
-- if( rval == SUCCESS ) {
-- printk(KERN_INFO
-- "megaraid: reset sequence successfully completed.\n");
-+ spin_lock(adapter->host_lock);
- }
-
-- return rval;
--}
--
-+ /*
-+ * If after 3 mins there are still outstanding cmds, set the hw_error
-+ * flag so that we can return from subsequent ABORT/RESET handlers
-+ * without any processing
-+ */
-
--/**
-- * mega_allocate_inquiry()
-- * @dma_handle - handle returned for dma address
-- * @pdev - handle to pci device
-- *
-- * allocates memory for inquiry structure
-- */
--static inline caddr_t
--mega_allocate_inquiry(dma_addr_t *dma_handle, struct pci_dev *pdev)
--{
-- return pci_alloc_consistent(pdev, sizeof(mega_inquiry3), dma_handle);
--}
-+ rval = SUCCESS;
-+ if (atomic_read(&adapter->pend_cmds)) {
-
-+ adapter->hw_error = 1;
-+ printk("megaraid: critical hardware error!\n" );
-+ rval = FAILED;
-+ }
-
--static inline void
--mega_free_inquiry(caddr_t inquiry, dma_addr_t dma_handle, struct pci_dev *pdev)
--{
-- pci_free_consistent(pdev, sizeof(mega_inquiry3), inquiry, dma_handle);
-+ return rval;
- }
-
-
-@@ -3199,6 +3200,26 @@
- return len;
- }
-
-+/**
-+ * mega_allocate_inquiry()
-+ * @dma_handle - handle returned for dma address
-+ * @pdev - handle to pci device
-+ *
-+ * allocates memory for inquiry structure
-+ */
-+static inline caddr_t
-+mega_allocate_inquiry(dma_addr_t *dma_handle, struct pci_dev *pdev)
-+{
-+ return pci_alloc_consistent(pdev, sizeof(mega_inquiry3), dma_handle);
-+}
-+
-+
-+static inline void
-+mega_free_inquiry(caddr_t inquiry, dma_addr_t dma_handle, struct pci_dev *pdev)
-+{
-+ pci_free_consistent(pdev, sizeof(mega_inquiry3), inquiry, dma_handle);
-+}
-+
-
- /**
- * proc_rebuild_rate()
-@@ -3988,6 +4009,7 @@
- megaraid_reboot_notify (struct notifier_block *this, unsigned long code,
- void *unused)
- {
-+ DECLARE_WAIT_QUEUE_HEAD(wq);
- adapter_t *adapter;
- struct Scsi_Host *host;
- u8 raw_mbox[sizeof(mbox_t)];
-@@ -4040,10 +4062,10 @@
- printk(KERN_INFO "megaraid: cache flush delay: ");
- for( i = 9; i >= 0; i-- ) {
- printk("\b\b\b[%d]", i);
-- mdelay(1000);
-+ sleep_on_timeout(&wq, HZ);
- }
- printk("\b\b\b[done]\n");
-- mdelay(1000);
-+ sleep_on_timeout(&wq, HZ);
-
- return NOTIFY_DONE;
- }
-@@ -4150,17 +4172,27 @@
- }
-
-
--#ifdef LSI_CONFIG_COMPAT
-+#if defined(__x86_64__)
- static int
- megadev_compat_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg,
- struct file *filep)
- {
- struct inode *inode = filep->f_dentry->d_inode;
-
-- return megadev_ioctl(inode, filep, cmd, arg);
-+ return megadev_ioctl_entry(inode, filep, cmd, arg);
- }
- #endif
-
-+static int
-+megadev_ioctl_entry(struct inode *inode, struct file *filep, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ int rval;
-+ down( &megaraid_ioc_mtx );
-+ rval = megadev_ioctl( inode, filep, cmd, arg );
-+ up( &megaraid_ioc_mtx );
-+ return rval;
-+}
-
- /**
- * megadev_ioctl()
-@@ -4184,9 +4216,8 @@
- int rval;
- mega_passthru *upthru; /* user address for passthru */
- mega_passthru *pthru; /* copy user passthru here */
-- dma_addr_t pthru_dma_hndl;
- void *data = NULL; /* data to be transferred */
-- dma_addr_t data_dma_hndl; /* dma handle for data xfer area */
-+ dma_addr_t data_dma_hndl = 0;
- megacmd_t mc;
- megastat_t *ustats;
- int num_ldrv;
-@@ -4302,7 +4333,7 @@
- /*
- * Which adapter
- */
-- if( (adapno = GETADAP(uioc.adapno)) >= hba_count )
-+ if( (adapno = GETADAP(uioc.adapno)) >= hba_count )
- return (-ENODEV);
-
- adapter = hba_soft_state[adapno];
-@@ -4358,13 +4389,7 @@
- if( uioc.uioc_rmbox[0] == MEGA_MBOXCMD_PASSTHRU ) {
- /* Passthru commands */
-
-- pthru = pci_alloc_consistent(pdev,
-- sizeof(mega_passthru),
-- &pthru_dma_hndl);
--
-- if( pthru == NULL ) {
-- return (-ENOMEM);
-- }
-+ pthru = adapter->int_pthru;
-
- /*
- * The user passthru structure
-@@ -4376,29 +4401,27 @@
- */
- if( copy_from_user(pthru, (char *)upthru,
- sizeof(mega_passthru)) ) {
--
-- pci_free_consistent(pdev,
-- sizeof(mega_passthru), pthru,
-- pthru_dma_hndl);
--
- return (-EFAULT);
- }
-
- /*
-- * Is there a data transfer
-+ * Is there a data transfer; If the data transfer
-+ * length is <= INT_MEMBLK_SZ, usr the buffer
-+ * allocated at the load time. Otherwise, allocate it
-+ * here.
- */
-- if( pthru->dataxferlen ) {
-- data = pci_alloc_consistent(pdev,
-- pthru->dataxferlen,
-- &data_dma_hndl);
--
-- if( data == NULL ) {
-- pci_free_consistent(pdev,
-- sizeof(mega_passthru),
-- pthru,
-- pthru_dma_hndl);
-+ if (pthru->dataxferlen) {
-+ if (pthru->dataxferlen > INT_MEMBLK_SZ) {
-+ data = pci_alloc_consistent (
-+ pdev,
-+ pthru->dataxferlen,
-+ &data_dma_hndl );
-
-- return (-ENOMEM);
-+ if (data == NULL)
-+ return (-ENOMEM);
-+ }
-+ else {
-+ data = adapter->int_data;
- }
-
- /*
-@@ -4406,7 +4429,11 @@
- * address at just allocated memory
- */
- uxferaddr = pthru->dataxferaddr;
-- pthru->dataxferaddr = data_dma_hndl;
-+ if (data_dma_hndl)
-+ pthru->dataxferaddr = data_dma_hndl;
-+ else
-+ pthru->dataxferaddr =
-+ adapter->int_data_dma_hndl;
- }
-
-
-@@ -4421,14 +4448,14 @@
- (char *)((ulong)uxferaddr),
- pthru->dataxferlen) ) {
- rval = (-EFAULT);
-- goto freemem_and_return;
-+ goto freedata_and_return;
- }
- }
-
- memset(&mc, 0, sizeof(megacmd_t));
-
- mc.cmd = MEGA_MBOXCMD_PASSTHRU;
-- mc.xferaddr = (u32)pthru_dma_hndl;
-+ mc.xferaddr = (u32)adapter->int_pthru_dma_hndl;
-
- /*
- * Issue the command
-@@ -4437,7 +4464,7 @@
-
- rval = mega_n_to_m((void *)arg, &mc);
-
-- if( rval ) goto freemem_and_return;
-+ if( rval ) goto freedata_and_return;
-
-
- /*
-@@ -4456,18 +4483,14 @@
- */
- copy_to_user(upthru->reqsensearea,
- pthru->reqsensearea, 14);
--
--freemem_and_return:
-- if( pthru->dataxferlen ) {
-- pci_free_consistent(pdev,
-- pthru->dataxferlen, data,
-- data_dma_hndl);
-+freedata_and_return:
-+ if (data_dma_hndl) {
-+ pci_free_consistent( pdev, pthru->dataxferlen,
-+ data, data_dma_hndl );
- }
-
-- pci_free_consistent(pdev, sizeof(mega_passthru),
-- pthru, pthru_dma_hndl);
--
- return rval;
-+
- }
- else {
- /* DCMD commands */
-@@ -4476,13 +4499,18 @@
- * Is there a data transfer
- */
- if( uioc.xferlen ) {
-- data = pci_alloc_consistent(pdev,
-- uioc.xferlen, &data_dma_hndl);
-+ if (uioc.xferlen > INT_MEMBLK_SZ) {
-+ data = pci_alloc_consistent(
-+ pdev,
-+ uioc.xferlen,
-+ &data_dma_hndl );
-
-- if( data == NULL ) {
-- return (-ENOMEM);
-+ if (data == NULL)
-+ return (-ENOMEM);
-+ }
-+ else {
-+ data = adapter->int_data;
- }
--
- uxferaddr = MBOX(uioc)->xferaddr;
- }
-
-@@ -4497,9 +4525,9 @@
- (char *)((ulong)uxferaddr),
- uioc.xferlen) ) {
-
-- pci_free_consistent(pdev,
-- uioc.xferlen, data,
-- data_dma_hndl);
-+ pci_free_consistent(
-+ pdev, uioc.xferlen,
-+ data, data_dma_hndl );
-
- return (-EFAULT);
- }
-@@ -4507,7 +4535,10 @@
-
- memcpy(&mc, MBOX(uioc), sizeof(megacmd_t));
-
-- mc.xferaddr = (u32)data_dma_hndl;
-+ if (data_dma_hndl )
-+ mc.xferaddr = (u32)data_dma_hndl;
-+ else
-+ mc.xferaddr = (u32)(adapter->int_data_dma_hndl);
-
- /*
- * Issue the command
-@@ -4517,12 +4548,10 @@
- rval = mega_n_to_m((void *)arg, &mc);
-
- if( rval ) {
-- if( uioc.xferlen ) {
-- pci_free_consistent(pdev,
-- uioc.xferlen, data,
-- data_dma_hndl);
-+ if (data_dma_hndl) {
-+ pci_free_consistent( pdev, uioc.xferlen,
-+ data, data_dma_hndl );
- }
--
- return rval;
- }
-
-@@ -4537,10 +4566,9 @@
- }
- }
-
-- if( uioc.xferlen ) {
-- pci_free_consistent(pdev,
-- uioc.xferlen, data,
-- data_dma_hndl);
-+ if (data_dma_hndl) {
-+ pci_free_consistent( pdev, uioc.xferlen,
-+ data, data_dma_hndl );
- }
-
- return rval;
-@@ -4725,19 +4753,22 @@
- else {
- uioc_mimd = (struct uioctl_t *)arg;
-
-- if( put_user(mc->status, (u8 *)&uioc_mimd->mbox[17]) )
-+ if( put_user(mc->status, (u8 *)&uioc_mimd->mbox[17]) ) {
- return (-EFAULT);
-+ }
-
- if( mc->cmd == MEGA_MBOXCMD_PASSTHRU ) {
-
- umc = (megacmd_t *)uioc_mimd->mbox;
-- if (copy_from_user(&kmc, umc, sizeof(megacmd_t)))
-+ if (copy_from_user(&kmc, umc, sizeof(megacmd_t))) {
- return -EFAULT;
-+ }
-
- upthru = (mega_passthru *)((ulong)kmc.xferaddr);
-
-- if( put_user(mc->status, (u8 *)&upthru->scsistatus) )
-+ if( put_user(mc->status, (u8 *)&upthru->scsistatus) ){
- return (-EFAULT);
-+ }
- }
- }
-
-@@ -5148,7 +5179,6 @@
- }
-
-
--
- /**
- * mega_reorder_hosts()
- *
-@@ -5363,6 +5393,7 @@
- }
-
-
-+
- /** mega_internal_dev_inquiry()
- * @adapter - pointer to our soft state
- * @ch - channel for this device
-diff -Nur linux-2.4.29/drivers/scsi/megaraid2.h linux-mips/drivers/scsi/megaraid2.h
---- linux-2.4.29/drivers/scsi/megaraid2.h 2004-11-17 12:54:21.000000000 +0100
-+++ linux-mips/drivers/scsi/megaraid2.h 2005-03-26 11:47:33.143212178 +0100
-@@ -6,7 +6,7 @@
-
-
- #define MEGARAID_VERSION \
-- "v2.10.3 (Release Date: Thu Apr 8 16:16:05 EDT 2004)\n"
-+ "v2.10.8.2 (Release Date: Mon Jul 26 12:15:51 EDT 2004)\n"
-
- /*
- * Driver features - change the values to enable or disable features in the
-@@ -82,6 +82,7 @@
- #define LSI_SUBSYS_VID 0x1000
- #define INTEL_SUBSYS_VID 0x8086
- #define FSC_SUBSYS_VID 0x1734
-+#define ACER_SUBSYS_VID 0x1025
-
- #define HBA_SIGNATURE 0x3344
- #define HBA_SIGNATURE_471 0xCCCC
-@@ -978,6 +979,15 @@
- cmds */
-
- int has_cluster; /* cluster support on this HBA */
-+
-+#define INT_MEMBLK_SZ (28*1024)
-+ mega_passthru *int_pthru; /*internal pthru*/
-+ dma_addr_t int_pthru_dma_hndl;
-+ caddr_t int_data; /*internal data*/
-+ dma_addr_t int_data_dma_hndl;
-+
-+ int hw_error;
-+
- }adapter_t;
-
-
-@@ -1085,18 +1095,21 @@
-
- #define MBOX_ABORT_SLEEP 60
- #define MBOX_RESET_SLEEP 30
-+#define MBOX_RESET_WAIT 180
-
- const char *megaraid_info (struct Scsi_Host *);
-
- static int megaraid_detect(Scsi_Host_Template *);
- static void mega_find_card(Scsi_Host_Template *, u16, u16);
- static int mega_query_adapter(adapter_t *);
--static int issue_scb(adapter_t *, scb_t *);
-+static inline int issue_scb(adapter_t *, scb_t *);
- static int mega_setup_mailbox(adapter_t *);
-
- static int megaraid_queue (Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
- static scb_t * mega_build_cmd(adapter_t *, Scsi_Cmnd *, int *);
-+static inline scb_t *mega_allocate_scb(adapter_t *, Scsi_Cmnd *);
- static void __mega_runpendq(adapter_t *);
-+static inline void mega_runpendq(adapter_t *);
- static int issue_scb_block(adapter_t *, u_char *);
-
- static void megaraid_isr_memmapped(int, void *, struct pt_regs *);
-@@ -1113,6 +1126,7 @@
-
- static int mega_build_sglist (adapter_t *adapter, scb_t *scb,
- u32 *buffer, u32 *length);
-+static inline int mega_busywait_mbox (adapter_t *);
- static int __mega_busywait_mbox (adapter_t *);
- static void mega_cmd_done(adapter_t *, u8 [], int, int);
- static inline void mega_free_sgl (adapter_t *adapter);
-@@ -1123,15 +1137,13 @@
- unsigned long, void *);
- static int megadev_open (struct inode *, struct file *);
-
--#if defined(CONFIG_COMPAT) || defined( __x86_64__) || defined(IA32_EMULATION)
--#define LSI_CONFIG_COMPAT
--#endif
--
--#ifdef LSI_CONFIG_COMPAT
-+#if defined(__x86_64__)
- static int megadev_compat_ioctl(unsigned int, unsigned int, unsigned long,
- struct file *);
- #endif
-
-+static int megadev_ioctl_entry (struct inode *, struct file *, unsigned int,
-+ unsigned long);
- static int megadev_ioctl (struct inode *, struct file *, unsigned int,
- unsigned long);
- static int mega_m_to_n(void *, nitioctl_t *);
-@@ -1164,6 +1176,8 @@
-
- static int mega_adapinq(adapter_t *, dma_addr_t);
- static int mega_internal_dev_inquiry(adapter_t *, u8, u8, dma_addr_t);
-+static inline caddr_t mega_allocate_inquiry(dma_addr_t *, struct pci_dev *);
-+static inline void mega_free_inquiry(caddr_t, dma_addr_t, struct pci_dev *);
- static int mega_print_inquiry(char *, char *);
- #endif
-
-@@ -1174,6 +1188,7 @@
- scb_t *, Scsi_Cmnd *, int, int);
- static void mega_enum_raid_scsi(adapter_t *);
- static void mega_get_boot_drv(adapter_t *);
-+static inline int mega_get_ldrv_num(adapter_t *, Scsi_Cmnd *, int);
- static int mega_support_random_del(adapter_t *);
- static int mega_del_logdrv(adapter_t *, int);
- static int mega_do_del_logdrv(adapter_t *, int);
-diff -Nur linux-2.4.29/drivers/scsi/NCR53C9x.h linux-mips/drivers/scsi/NCR53C9x.h
---- linux-2.4.29/drivers/scsi/NCR53C9x.h 2004-02-18 14:36:31.000000000 +0100
-+++ linux-mips/drivers/scsi/NCR53C9x.h 2003-12-15 19:19:51.000000000 +0100
-@@ -144,12 +144,7 @@
-
- #ifndef MULTIPLE_PAD_SIZES
-
--#ifdef CONFIG_CPU_HAS_WB
--#include <asm/wbflush.h>
--#define esp_write(__reg, __val) do{(__reg) = (__val); wbflush();} while(0)
--#else
--#define esp_write(__reg, __val) ((__reg) = (__val))
--#endif
-+#define esp_write(__reg, __val) do{(__reg) = (__val); iob();} while(0)
- #define esp_read(__reg) (__reg)
-
- struct ESP_regs {
-diff -Nur linux-2.4.29/drivers/scsi/osst.c linux-mips/drivers/scsi/osst.c
---- linux-2.4.29/drivers/scsi/osst.c 2004-08-08 01:26:05.000000000 +0200
-+++ linux-mips/drivers/scsi/osst.c 2005-03-26 11:47:33.149211193 +0100
-@@ -5505,7 +5505,6 @@
- read: osst_read,
- write: osst_write,
- ioctl: osst_ioctl,
-- llseek: no_llseek,
- open: os_scsi_tape_open,
- flush: os_scsi_tape_flush,
- release: os_scsi_tape_close,
-diff -Nur linux-2.4.29/drivers/scsi/sata_nv.c linux-mips/drivers/scsi/sata_nv.c
---- linux-2.4.29/drivers/scsi/sata_nv.c 2005-01-19 15:10:03.000000000 +0100
-+++ linux-mips/drivers/scsi/sata_nv.c 2005-03-26 11:47:33.156210045 +0100
-@@ -20,6 +20,10 @@
- * If you do not delete the provisions above, a recipient may use your
- * version of this file under either the OSL or the GPL.
- *
-+ * 0.06
-+ * - Added generic SATA support by using a pci_device_id that filters on
-+ * the IDE storage class code.
-+ *
- * 0.03
- * - Fixed a bug where the hotplug handlers for non-CK804/MCP04 were using
- * mmio_base, which is only set for the CK804/MCP04 case.
-@@ -44,7 +48,7 @@
- #include <linux/libata.h>
-
- #define DRV_NAME "sata_nv"
--#define DRV_VERSION "0.5"
-+#define DRV_VERSION "0.6"
-
- #define NV_PORTS 2
- #define NV_PIO_MASK 0x1f
-@@ -95,7 +99,8 @@
- #define NV_MCP_SATA_CFG_20_SATA_SPACE_EN 0x04
-
- static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
--irqreturn_t nv_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
-+static irqreturn_t nv_interrupt (int irq, void *dev_instance,
-+ struct pt_regs *regs);
- static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg);
- static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
- static void nv_host_stop (struct ata_host_set *host_set);
-@@ -108,6 +113,7 @@
-
- enum nv_host_type
- {
-+ GENERIC,
- NFORCE2,
- NFORCE3,
- CK804
-@@ -128,6 +134,9 @@
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
-+ { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
-+ PCI_ANY_ID, PCI_ANY_ID,
-+ PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC },
- { 0, } /* terminate list */
- };
-
-@@ -136,7 +145,6 @@
- struct nv_host_desc
- {
- enum nv_host_type host_type;
-- unsigned long host_flags;
- void (*enable_hotplug)(struct ata_probe_ent *probe_ent);
- void (*disable_hotplug)(struct ata_host_set *host_set);
- void (*check_hotplug)(struct ata_host_set *host_set);
-@@ -144,21 +152,24 @@
- };
- static struct nv_host_desc nv_device_tbl[] = {
- {
-+ .host_type = GENERIC,
-+ .enable_hotplug = NULL,
-+ .disable_hotplug= NULL,
-+ .check_hotplug = NULL,
-+ },
-+ {
- .host_type = NFORCE2,
-- .host_flags = 0x00000000,
- .enable_hotplug = nv_enable_hotplug,
- .disable_hotplug= nv_disable_hotplug,
- .check_hotplug = nv_check_hotplug,
- },
- {
- .host_type = NFORCE3,
-- .host_flags = 0x00000000,
- .enable_hotplug = nv_enable_hotplug,
- .disable_hotplug= nv_disable_hotplug,
- .check_hotplug = nv_check_hotplug,
- },
- { .host_type = CK804,
-- .host_flags = NV_HOST_FLAGS_SCR_MMIO,
- .enable_hotplug = nv_enable_hotplug_ck804,
- .disable_hotplug= nv_disable_hotplug_ck804,
- .check_hotplug = nv_check_hotplug_ck804,
-@@ -168,6 +179,7 @@
- struct nv_host
- {
- struct nv_host_desc *host_desc;
-+ unsigned long host_flags;
- };
-
- static struct pci_driver nv_pci_driver = {
-@@ -207,6 +219,8 @@
- .phy_reset = sata_phy_reset,
- .bmdma_setup = ata_bmdma_setup,
- .bmdma_start = ata_bmdma_start,
-+ .bmdma_stop = ata_bmdma_stop,
-+ .bmdma_status = ata_bmdma_status,
- .qc_prep = ata_qc_prep,
- .qc_issue = ata_qc_issue_prot,
- .eng_timeout = ata_eng_timeout,
-@@ -245,7 +259,8 @@
- MODULE_DEVICE_TABLE(pci, nv_pci_tbl);
- MODULE_VERSION(DRV_VERSION);
-
--irqreturn_t nv_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
-+static irqreturn_t nv_interrupt (int irq, void *dev_instance,
-+ struct pt_regs *regs)
- {
- struct ata_host_set *host_set = dev_instance;
- struct nv_host *host = host_set->private_data;
-@@ -285,8 +300,8 @@
- if (sc_reg > SCR_CONTROL)
- return 0xffffffffU;
-
-- if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO)
-- return readl(ap->ioaddr.scr_addr + (sc_reg * 4));
-+ if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO)
-+ return readl((void*)ap->ioaddr.scr_addr + (sc_reg * 4));
- else
- return inl(ap->ioaddr.scr_addr + (sc_reg * 4));
- }
-@@ -299,8 +314,8 @@
- if (sc_reg > SCR_CONTROL)
- return;
-
-- if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO)
-- writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));
-+ if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO)
-+ writel(val, (void*)ap->ioaddr.scr_addr + (sc_reg * 4));
- else
- outl(val, ap->ioaddr.scr_addr + (sc_reg * 4));
- }
-@@ -322,7 +337,16 @@
- struct nv_host *host;
- struct ata_port_info *ppi;
- struct ata_probe_ent *probe_ent;
-+ int pci_dev_busy = 0;
- int rc;
-+ u32 bar;
-+
-+ // Make sure this is a SATA controller by counting the number of bars
-+ // (NVIDIA SATA controllers will always have six bars). Otherwise,
-+ // it's an IDE controller and we ignore it.
-+ for (bar=0; bar<6; bar++)
-+ if (pci_resource_start(pdev, bar) == 0)
-+ return -ENODEV;
-
- if (!printed_version++)
- printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
-@@ -332,8 +356,10 @@
- goto err_out;
-
- rc = pci_request_regions(pdev, DRV_NAME);
-- if (rc)
-+ if (rc) {
-+ pci_dev_busy = 1;
- goto err_out_disable;
-+ }
-
- rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
- if (rc)
-@@ -350,11 +376,15 @@
- if (!host)
- goto err_out_free_ent;
-
-+ memset(host, 0, sizeof(struct nv_host));
- host->host_desc = &nv_device_tbl[ent->driver_data];
-
- probe_ent->private_data = host;
-
-- if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO) {
-+ if (pci_resource_flags(pdev, 5) & IORESOURCE_MEM)
-+ host->host_flags |= NV_HOST_FLAGS_SCR_MMIO;
-+
-+ if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO) {
- unsigned long base;
-
- probe_ent->mmio_base = ioremap(pci_resource_start(pdev, 5),
-@@ -395,7 +425,8 @@
- err_out_regions:
- pci_release_regions(pdev);
- err_out_disable:
-- pci_disable_device(pdev);
-+ if (!pci_dev_busy)
-+ pci_disable_device(pdev);
- err_out:
- return rc;
- }
-diff -Nur linux-2.4.29/drivers/scsi/sata_promise.c linux-mips/drivers/scsi/sata_promise.c
---- linux-2.4.29/drivers/scsi/sata_promise.c 2005-01-19 15:10:03.000000000 +0100
-+++ linux-mips/drivers/scsi/sata_promise.c 2005-03-26 11:47:33.159209552 +0100
-@@ -42,8 +42,6 @@
- #define DRV_NAME "sata_promise"
- #define DRV_VERSION "1.01"
-
--#define msleep libata_msleep /* 2.4-specific */
--
- enum {
- PDC_PKT_SUBMIT = 0x40, /* Command packet pointer addr */
- PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */
-@@ -158,10 +156,18 @@
- board_2037x },
- { PCI_VENDOR_ID_PROMISE, 0x3376, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- board_2037x },
-+ { PCI_VENDOR_ID_PROMISE, 0x3574, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ board_2037x },
-+ { PCI_VENDOR_ID_PROMISE, 0x3d75, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ board_2037x },
-+
- { PCI_VENDOR_ID_PROMISE, 0x3318, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- board_20319 },
- { PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- board_20319 },
-+ { PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ board_20319 },
-+
- { } /* terminate list */
- };
-
-@@ -408,9 +414,11 @@
- return IRQ_NONE;
- }
-
-- spin_lock(&host_set->lock);
-+ spin_lock(&host_set->lock);
-+
-+ writel(mask, mmio_base + PDC_INT_SEQMASK);
-
-- for (i = 0; i < host_set->n_ports; i++) {
-+ for (i = 0; i < host_set->n_ports; i++) {
- VPRINTK("port %u\n", i);
- ap = host_set->ports[i];
- tmp = mask & (1 << (i + 1));
-@@ -548,6 +556,7 @@
- unsigned long base;
- void *mmio_base;
- unsigned int board_idx = (unsigned int) ent->driver_data;
-+ int pci_dev_busy = 0;
- int rc;
-
- if (!printed_version++)
-@@ -562,8 +571,10 @@
- return rc;
-
- rc = pci_request_regions(pdev, DRV_NAME);
-- if (rc)
-+ if (rc) {
-+ pci_dev_busy = 1;
- goto err_out;
-+ }
-
- rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
- if (rc)
-@@ -637,7 +648,8 @@
- err_out_regions:
- pci_release_regions(pdev);
- err_out:
-- pci_disable_device(pdev);
-+ if (!pci_dev_busy)
-+ pci_disable_device(pdev);
- return rc;
- }
-
-diff -Nur linux-2.4.29/drivers/scsi/sata_qstor.c linux-mips/drivers/scsi/sata_qstor.c
---- linux-2.4.29/drivers/scsi/sata_qstor.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-mips/drivers/scsi/sata_qstor.c 2005-03-18 13:13:28.000000000 +0100
-@@ -0,0 +1,717 @@
-+/*
-+ * sata_qstor.c - Pacific Digital Corporation QStor SATA
-+ *
-+ * Maintained by: Mark Lord <mlord@pobox.com>
-+ *
-+ * Copyright 2005 Pacific Digital Corporation.
-+ * (OSL/GPL code release authorized by Jalil Fadavi).
-+ *
-+ * The contents of this file are subject to the Open
-+ * Software License version 1.1 that can be found at
-+ * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
-+ * by reference.
-+ *
-+ * Alternatively, the contents of this file may be used under the terms
-+ * of the GNU General Public License version 2 (the "GPL") as distributed
-+ * in the kernel source COPYING file, in which case the provisions of
-+ * the GPL are applicable instead of the above. If you wish to allow
-+ * the use of your version of this file only under the terms of the
-+ * GPL and not to allow others to use your version of this file under
-+ * the OSL, indicate your decision by deleting the provisions above and
-+ * replace them with the notice and other provisions required by the GPL.
-+ * If you do not delete the provisions above, a recipient may use your
-+ * version of this file under either the OSL or the GPL.
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/pci.h>
-+#include <linux/init.h>
-+#include <linux/blkdev.h>
-+#include <linux/delay.h>
-+#include <linux/interrupt.h>
-+#include <linux/sched.h>
-+#include "scsi.h"
-+#include <scsi/scsi_host.h>
-+#include <asm/io.h>
-+#include <linux/libata.h>
-+
-+#define DRV_NAME "sata_qstor"
-+#define DRV_VERSION "0.04"
-+
-+enum {
-+ QS_PORTS = 4,
-+ QS_MAX_PRD = LIBATA_MAX_PRD,
-+ QS_CPB_ORDER = 6,
-+ QS_CPB_BYTES = (1 << QS_CPB_ORDER),
-+ QS_PRD_BYTES = QS_MAX_PRD * 16,
-+ QS_PKT_BYTES = QS_CPB_BYTES + QS_PRD_BYTES,
-+
-+ QS_DMA_BOUNDARY = ~0UL,
-+
-+ /* global register offsets */
-+ QS_HCF_CNFG3 = 0x0003, /* host configuration offset */
-+ QS_HID_HPHY = 0x0004, /* host physical interface info */
-+ QS_HCT_CTRL = 0x00e4, /* global interrupt mask offset */
-+ QS_HST_SFF = 0x0100, /* host status fifo offset */
-+ QS_HVS_SERD3 = 0x0393, /* PHY enable offset */
-+
-+ /* global control bits */
-+ QS_HPHY_64BIT = (1 << 1), /* 64-bit bus detected */
-+ QS_CNFG3_GSRST = 0x01, /* global chip reset */
-+ QS_SERD3_PHY_ENA = 0xf0, /* PHY detection ENAble*/
-+
-+ /* per-channel register offsets */
-+ QS_CCF_CPBA = 0x0710, /* chan CPB base address */
-+ QS_CCF_CSEP = 0x0718, /* chan CPB separation factor */
-+ QS_CFC_HUFT = 0x0800, /* host upstream fifo threshold */
-+ QS_CFC_HDFT = 0x0804, /* host downstream fifo threshold */
-+ QS_CFC_DUFT = 0x0808, /* dev upstream fifo threshold */
-+ QS_CFC_DDFT = 0x080c, /* dev downstream fifo threshold */
-+ QS_CCT_CTR0 = 0x0900, /* chan control-0 offset */
-+ QS_CCT_CTR1 = 0x0901, /* chan control-1 offset */
-+ QS_CCT_CFF = 0x0a00, /* chan command fifo offset */
-+
-+ /* channel control bits */
-+ QS_CTR0_REG = (1 << 1), /* register mode (vs. pkt mode) */
-+ QS_CTR0_CLER = (1 << 2), /* clear channel errors */
-+ QS_CTR1_RDEV = (1 << 1), /* sata phy/comms reset */
-+ QS_CTR1_RCHN = (1 << 4), /* reset channel logic */
-+ QS_CCF_RUN_PKT = 0x107, /* RUN a new dma PKT */
-+
-+ /* pkt sub-field headers */
-+ QS_HCB_HDR = 0x01, /* Host Control Block header */
-+ QS_DCB_HDR = 0x02, /* Device Control Block header */
-+
-+ /* pkt HCB flag bits */
-+ QS_HF_DIRO = (1 << 0), /* data DIRection Out */
-+ QS_HF_DAT = (1 << 3), /* DATa pkt */
-+ QS_HF_IEN = (1 << 4), /* Interrupt ENable */
-+ QS_HF_VLD = (1 << 5), /* VaLiD pkt */
-+
-+ /* pkt DCB flag bits */
-+ QS_DF_PORD = (1 << 2), /* Pio OR Dma */
-+ QS_DF_ELBA = (1 << 3), /* Extended LBA (lba48) */
-+
-+ /* PCI device IDs */
-+ board_2068_idx = 0, /* QStor 4-port SATA/RAID */
-+};
-+
-+typedef enum { qs_state_idle, qs_state_pkt, qs_state_mmio } qs_state_t;
-+
-+struct qs_port_priv {
-+ u8 *pkt;
-+ dma_addr_t pkt_dma;
-+ qs_state_t state;
-+};
-+
-+static u32 qs_scr_read (struct ata_port *ap, unsigned int sc_reg);
-+static void qs_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
-+static int qs_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-+static irqreturn_t qs_intr (int irq, void *dev_instance, struct pt_regs *regs);
-+static int qs_port_start(struct ata_port *ap);
-+static void qs_host_stop(struct ata_host_set *host_set);
-+static void qs_port_stop(struct ata_port *ap);
-+static void qs_phy_reset(struct ata_port *ap);
-+static void qs_qc_prep(struct ata_queued_cmd *qc);
-+static int qs_qc_issue(struct ata_queued_cmd *qc);
-+static int qs_check_atapi_dma(struct ata_queued_cmd *qc);
-+static void qs_bmdma_stop(struct ata_port *ap);
-+static u8 qs_bmdma_status(struct ata_port *ap);
-+static void qs_irq_clear(struct ata_port *ap);
-+static void qs_eng_timeout(struct ata_port *ap);
-+
-+static Scsi_Host_Template qs_ata_sht = {
-+ .module = THIS_MODULE,
-+ .name = DRV_NAME,
-+ .detect = ata_scsi_detect,
-+ .release = ata_scsi_release,
-+ .ioctl = ata_scsi_ioctl,
-+ .queuecommand = ata_scsi_queuecmd,
-+ .eh_strategy_handler = ata_scsi_error,
-+ .can_queue = ATA_DEF_QUEUE,
-+ .this_id = ATA_SHT_THIS_ID,
-+ .sg_tablesize = QS_MAX_PRD,
-+ .max_sectors = ATA_MAX_SECTORS,
-+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
-+ .use_new_eh_code = ATA_SHT_NEW_EH_CODE,
-+ .emulated = ATA_SHT_EMULATED,
-+ //FIXME .use_clustering = ATA_SHT_USE_CLUSTERING,
-+ .use_clustering = ENABLE_CLUSTERING,
-+ .proc_name = DRV_NAME,
-+ .bios_param = ata_std_bios_param,
-+};
-+
-+static struct ata_port_operations qs_ata_ops = {
-+ .port_disable = ata_port_disable,
-+ .tf_load = ata_tf_load,
-+ .tf_read = ata_tf_read,
-+ .check_status = ata_check_status,
-+ .check_atapi_dma = qs_check_atapi_dma,
-+ .exec_command = ata_exec_command,
-+ .dev_select = ata_std_dev_select,
-+ .phy_reset = qs_phy_reset,
-+ .qc_prep = qs_qc_prep,
-+ .qc_issue = qs_qc_issue,
-+ .eng_timeout = qs_eng_timeout,
-+ .irq_handler = qs_intr,
-+ .irq_clear = qs_irq_clear,
-+ .scr_read = qs_scr_read,
-+ .scr_write = qs_scr_write,
-+ .port_start = qs_port_start,
-+ .port_stop = qs_port_stop,
-+ .host_stop = qs_host_stop,
-+ .bmdma_stop = qs_bmdma_stop,
-+ .bmdma_status = qs_bmdma_status,
-+};
-+
-+static struct ata_port_info qs_port_info[] = {
-+ /* board_2068_idx */
-+ {
-+ .sht = &qs_ata_sht,
-+ .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-+ ATA_FLAG_SATA_RESET |
-+ //FIXME ATA_FLAG_SRST |
-+ ATA_FLAG_MMIO,
-+ .pio_mask = 0x10, /* pio4 */
-+ .udma_mask = 0x7f, /* udma0-6 */
-+ .port_ops = &qs_ata_ops,
-+ },
-+};
-+
-+static struct pci_device_id qs_ata_pci_tbl[] = {
-+ { PCI_VENDOR_ID_PDC, 0x2068, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ board_2068_idx },
-+
-+ { } /* terminate list */
-+};
-+
-+static struct pci_driver qs_ata_pci_driver = {
-+ .name = DRV_NAME,
-+ .id_table = qs_ata_pci_tbl,
-+ .probe = qs_ata_init_one,
-+ .remove = ata_pci_remove_one,
-+};
-+
-+static int qs_check_atapi_dma(struct ata_queued_cmd *qc)
-+{
-+ return 1; /* ATAPI DMA not supported */
-+}
-+
-+static void qs_bmdma_stop(struct ata_port *ap)
-+{
-+ /* nothing */
-+}
-+
-+static u8 qs_bmdma_status(struct ata_port *ap)
-+{
-+ return 0;
-+}
-+
-+static void qs_irq_clear(struct ata_port *ap)
-+{
-+ /* nothing */
-+}
-+
-+static inline void qs_enter_reg_mode(struct ata_port *ap)
-+{
-+ u8 __iomem *chan = ap->host_set->mmio_base + (ap->port_no * 0x4000);
-+
-+ writeb(QS_CTR0_REG, chan + QS_CCT_CTR0);
-+ readb(chan + QS_CCT_CTR0); /* flush */
-+}
-+
-+static inline void qs_reset_channel_logic(struct ata_port *ap)
-+{
-+ u8 __iomem *chan = ap->host_set->mmio_base + (ap->port_no * 0x4000);
-+
-+ writeb(QS_CTR1_RCHN, chan + QS_CCT_CTR1);
-+ readb(chan + QS_CCT_CTR0); /* flush */
-+ qs_enter_reg_mode(ap);
-+}
-+
-+static void qs_phy_reset(struct ata_port *ap)
-+{
-+ struct qs_port_priv *pp = ap->private_data;
-+
-+ pp->state = qs_state_idle;
-+ qs_reset_channel_logic(ap);
-+ sata_phy_reset(ap);
-+}
-+
-+static void qs_eng_timeout(struct ata_port *ap)
-+{
-+ struct qs_port_priv *pp = ap->private_data;
-+
-+ if (pp->state != qs_state_idle) /* healthy paranoia */
-+ pp->state = qs_state_mmio;
-+ qs_reset_channel_logic(ap);
-+ ata_eng_timeout(ap);
-+}
-+
-+static u32 qs_scr_read (struct ata_port *ap, unsigned int sc_reg)
-+{
-+ if (sc_reg > SCR_CONTROL)
-+ return ~0U;
-+ return readl((void __iomem *)(ap->ioaddr.scr_addr + (sc_reg * 8)));
-+}
-+
-+static void qs_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
-+{
-+ if (sc_reg > SCR_CONTROL)
-+ return;
-+ writel(val, (void __iomem *)(ap->ioaddr.scr_addr + (sc_reg * 8)));
-+}
-+
-+static void qs_fill_sg(struct ata_queued_cmd *qc)
-+{
-+ struct scatterlist *sg = qc->sg;
-+ struct ata_port *ap = qc->ap;
-+ struct qs_port_priv *pp = ap->private_data;
-+ unsigned int nelem;
-+ u8 *prd = pp->pkt + QS_CPB_BYTES;
-+
-+ assert(sg != NULL);
-+ assert(qc->n_elem > 0);
-+
-+ for (nelem = 0; nelem < qc->n_elem; nelem++,sg++) {
-+ u64 addr;
-+ u32 len;
-+
-+ addr = sg_dma_address(sg);
-+ *(__le64 *)prd = cpu_to_le64(addr);
-+ prd += sizeof(u64);
-+
-+ len = sg_dma_len(sg);
-+ *(__le32 *)prd = cpu_to_le32(len);
-+ prd += sizeof(u64);
-+
-+ VPRINTK("PRD[%u] = (0x%llX, 0x%X)\n", nelem,
-+ (unsigned long long)addr, len);
-+ }
-+}
-+
-+static void qs_qc_prep(struct ata_queued_cmd *qc)
-+{
-+ struct qs_port_priv *pp = qc->ap->private_data;
-+ u8 dflags = QS_DF_PORD, *buf = pp->pkt;
-+ u8 hflags = QS_HF_DAT | QS_HF_IEN | QS_HF_VLD;
-+ u64 addr;
-+
-+ VPRINTK("ENTER\n");
-+
-+ qs_enter_reg_mode(qc->ap);
-+ if (qc->tf.protocol != ATA_PROT_DMA) {
-+ ata_qc_prep(qc);
-+ return;
-+ }
-+
-+ qs_fill_sg(qc);
-+
-+ if ((qc->tf.flags & ATA_TFLAG_WRITE))
-+ hflags |= QS_HF_DIRO;
-+ if ((qc->tf.flags & ATA_TFLAG_LBA48))
-+ dflags |= QS_DF_ELBA;
-+
-+ /* host control block (HCB) */
-+ buf[ 0] = QS_HCB_HDR;
-+ buf[ 1] = hflags;
-+ *(__le32 *)(&buf[ 4]) = cpu_to_le32(qc->nsect * ATA_SECT_SIZE);
-+ *(__le32 *)(&buf[ 8]) = cpu_to_le32(qc->n_elem);
-+ addr = ((u64)pp->pkt_dma) + QS_CPB_BYTES;
-+ *(__le64 *)(&buf[16]) = cpu_to_le64(addr);
-+
-+ /* device control block (DCB) */
-+ buf[24] = QS_DCB_HDR;
-+ buf[28] = dflags;
-+
-+ /* frame information structure (FIS) */
-+ ata_tf_to_fis(&qc->tf, &buf[32], 0);
-+}
-+
-+static inline void qs_packet_start(struct ata_queued_cmd *qc)
-+{
-+ struct ata_port *ap = qc->ap;
-+ u8 __iomem *chan = ap->host_set->mmio_base + (ap->port_no * 0x4000);
-+
-+ VPRINTK("ENTER, ap %p\n", ap);
-+
-+ writeb(QS_CTR0_CLER, chan + QS_CCT_CTR0);
-+ wmb(); /* flush PRDs and pkt to memory */
-+ writel(QS_CCF_RUN_PKT, chan + QS_CCT_CFF);
-+ readl(chan + QS_CCT_CFF); /* flush */
-+}
-+
-+static int qs_qc_issue(struct ata_queued_cmd *qc)
-+{
-+ struct qs_port_priv *pp = qc->ap->private_data;
-+
-+ switch (qc->tf.protocol) {
-+ case ATA_PROT_DMA:
-+
-+ pp->state = qs_state_pkt;
-+ qs_packet_start(qc);
-+ return 0;
-+
-+ case ATA_PROT_ATAPI_DMA:
-+ BUG();
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ pp->state = qs_state_mmio;
-+ return ata_qc_issue_prot(qc);
-+}
-+
-+static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set)
-+{
-+ unsigned int handled = 0;
-+ u8 sFFE;
-+ u8 __iomem *mmio_base = host_set->mmio_base;
-+
-+ do {
-+ u32 sff0 = readl(mmio_base + QS_HST_SFF);
-+ u32 sff1 = readl(mmio_base + QS_HST_SFF + 4);
-+ u8 sEVLD = (sff1 >> 30) & 0x01; /* valid flag */
-+ sFFE = sff1 >> 31; /* empty flag */
-+
-+ if (sEVLD) {
-+ u8 sDST = sff0 >> 16; /* dev status */
-+ u8 sHST = sff1 & 0x3f; /* host status */
-+ unsigned int port_no = (sff1 >> 8) & 0x03;
-+ struct ata_port *ap = host_set->ports[port_no];
-+
-+ DPRINTK("SFF=%08x%08x: sCHAN=%u sHST=%d sDST=%02x\n",
-+ sff1, sff0, port_no, sHST, sDST);
-+ handled = 1;
-+ if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
-+ struct ata_queued_cmd *qc;
-+ struct qs_port_priv *pp = ap->private_data;
-+ if (!pp || pp->state != qs_state_pkt)
-+ continue;
-+ qc = ata_qc_from_tag(ap, ap->active_tag);
-+ if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
-+ switch (sHST) {
-+ case 0: /* sucessful CPB */
-+ case 3: /* device error */
-+ pp->state = qs_state_idle;
-+ qs_enter_reg_mode(qc->ap);
-+ ata_qc_complete(qc, sDST);
-+ break;
-+ default:
-+ break;
-+ }
-+ }
-+ }
-+ }
-+ } while (!sFFE);
-+ return handled;
-+}
-+
-+static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set)
-+{
-+ unsigned int handled = 0, port_no;
-+
-+ for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
-+ struct ata_port *ap;
-+ ap = host_set->ports[port_no];
-+ if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
-+ struct ata_queued_cmd *qc;
-+ struct qs_port_priv *pp = ap->private_data;
-+ if (!pp || pp->state != qs_state_mmio)
-+ continue;
-+ qc = ata_qc_from_tag(ap, ap->active_tag);
-+ if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
-+
-+ /* check main status, clearing INTRQ */
-+ u8 status = ata_chk_status(ap);
-+ if ((status & ATA_BUSY))
-+ continue;
-+ DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
-+ ap->id, qc->tf.protocol, status);
-+
-+ /* complete taskfile transaction */
-+ pp->state = qs_state_idle;
-+ ata_qc_complete(qc, status);
-+ handled = 1;
-+ }
-+ }
-+ }
-+ return handled;
-+}
-+
-+static irqreturn_t qs_intr(int irq, void *dev_instance, struct pt_regs *regs)
-+{
-+ struct ata_host_set *host_set = dev_instance;
-+ unsigned int handled = 0;
-+
-+ VPRINTK("ENTER\n");
-+
-+ spin_lock(&host_set->lock);
-+ handled = qs_intr_pkt(host_set) | qs_intr_mmio(host_set);
-+ spin_unlock(&host_set->lock);
-+
-+ VPRINTK("EXIT\n");
-+
-+ return IRQ_RETVAL(handled);
-+}
-+
-+static void qs_ata_setup_port(struct ata_ioports *port, unsigned long base)
-+{
-+ port->cmd_addr =
-+ port->data_addr = base + 0x400;
-+ port->error_addr =
-+ port->feature_addr = base + 0x408; /* hob_feature = 0x409 */
-+ port->nsect_addr = base + 0x410; /* hob_nsect = 0x411 */
-+ port->lbal_addr = base + 0x418; /* hob_lbal = 0x419 */
-+ port->lbam_addr = base + 0x420; /* hob_lbam = 0x421 */
-+ port->lbah_addr = base + 0x428; /* hob_lbah = 0x429 */
-+ port->device_addr = base + 0x430;
-+ port->status_addr =
-+ port->command_addr = base + 0x438;
-+ port->altstatus_addr =
-+ port->ctl_addr = base + 0x440;
-+ port->scr_addr = base + 0xc00;
-+}
-+
-+static int qs_port_start(struct ata_port *ap)
-+{
-+ struct device *dev = ap->host_set->dev;
-+ struct qs_port_priv *pp;
-+ void __iomem *mmio_base = ap->host_set->mmio_base;
-+ void __iomem *chan = mmio_base + (ap->port_no * 0x4000);
-+ u64 addr;
-+ int rc;
-+
-+ rc = ata_port_start(ap);
-+ if (rc)
-+ return rc;
-+ qs_enter_reg_mode(ap);
-+ pp = kcalloc(1, sizeof(*pp), GFP_KERNEL);
-+ if (!pp) {
-+ rc = -ENOMEM;
-+ goto err_out;
-+ }
-+ pp->pkt = dma_alloc_coherent(dev, QS_PKT_BYTES, &pp->pkt_dma,
-+ GFP_KERNEL);
-+ if (!pp->pkt) {
-+ rc = -ENOMEM;
-+ goto err_out_kfree;
-+ }
-+ memset(pp->pkt, 0, QS_PKT_BYTES);
-+ ap->private_data = pp;
-+
-+ addr = (u64)pp->pkt_dma;
-+ writel((u32) addr, chan + QS_CCF_CPBA);
-+ writel((u32)(addr >> 32), chan + QS_CCF_CPBA + 4);
-+ return 0;
-+
-+err_out_kfree:
-+ kfree(pp);
-+err_out:
-+ ata_port_stop(ap);
-+ return rc;
-+}
-+
-+static void qs_port_stop(struct ata_port *ap)
-+{
-+ struct device *dev = ap->host_set->dev;
-+ struct qs_port_priv *pp = ap->private_data;
-+
-+ if (pp != NULL) {
-+ ap->private_data = NULL;
-+ if (pp->pkt != NULL)
-+ dma_free_coherent(dev, QS_PKT_BYTES, pp->pkt,
-+ pp->pkt_dma);
-+ kfree(pp);
-+ }
-+ ata_port_stop(ap);
-+}
-+
-+static void qs_host_stop(struct ata_host_set *host_set)
-+{
-+ void __iomem *mmio_base = host_set->mmio_base;
-+
-+ writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */
-+ writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */
-+}
-+
-+static void qs_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
-+{
-+ void __iomem *mmio_base = pe->mmio_base;
-+ unsigned int port_no;
-+
-+ writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */
-+ writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */
-+
-+ /* reset each channel in turn */
-+ for (port_no = 0; port_no < pe->n_ports; ++port_no) {
-+ u8 __iomem *chan = mmio_base + (port_no * 0x4000);
-+ writeb(QS_CTR1_RDEV|QS_CTR1_RCHN, chan + QS_CCT_CTR1);
-+ writeb(QS_CTR0_REG, chan + QS_CCT_CTR0);
-+ readb(chan + QS_CCT_CTR0); /* flush */
-+ }
-+ writeb(QS_SERD3_PHY_ENA, mmio_base + QS_HVS_SERD3); /* enable phy */
-+
-+ for (port_no = 0; port_no < pe->n_ports; ++port_no) {
-+ u8 __iomem *chan = mmio_base + (port_no * 0x4000);
-+ /* set FIFO depths to same settings as Windows driver */
-+ writew(32, chan + QS_CFC_HUFT);
-+ writew(32, chan + QS_CFC_HDFT);
-+ writew(10, chan + QS_CFC_DUFT);
-+ writew( 8, chan + QS_CFC_DDFT);
-+ /* set CPB size in bytes, as a power of two */
-+ writeb(QS_CPB_ORDER, chan + QS_CCF_CSEP);
-+ }
-+ writeb(1, mmio_base + QS_HCT_CTRL); /* enable host interrupts */
-+}
-+
-+/*
-+ * The QStor understands 64-bit buses, and uses 64-bit fields
-+ * for DMA pointers regardless of bus width. We just have to
-+ * make sure our DMA masks are set appropriately for whatever
-+ * bridge lies between us and the QStor, and then the DMA mapping
-+ * code will ensure we only ever "see" appropriate buffer addresses.
-+ * If we're 32-bit limited somewhere, then our 64-bit fields will
-+ * just end up with zeros in the upper 32-bits, without any special
-+ * logic required outside of this routine (below).
-+ */
-+static int qs_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
-+{
-+ u32 bus_info = readl(mmio_base + QS_HID_HPHY);
-+ int rc, have_64bit_bus = (bus_info & QS_HPHY_64BIT);
-+
-+ if (have_64bit_bus &&
-+ !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
-+ /* do nothing */
-+ } else {
-+ rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-+ if (rc) {
-+ printk(KERN_ERR DRV_NAME
-+ "(%s): 32-bit DMA enable failed\n",
-+ pci_name(pdev));
-+ return rc;
-+ }
-+ }
-+ return 0;
-+}
-+
-+static int qs_ata_init_one(struct pci_dev *pdev,
-+ const struct pci_device_id *ent)
-+{
-+ static int printed_version;
-+ struct ata_probe_ent *probe_ent = NULL;
-+ void __iomem *mmio_base;
-+ unsigned int board_idx = (unsigned int) ent->driver_data;
-+ int rc, port_no;
-+
-+ if (!printed_version++)
-+ printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
-+
-+ rc = pci_enable_device(pdev);
-+ if (rc)
-+ return rc;
-+
-+ rc = pci_request_regions(pdev, DRV_NAME);
-+ if (rc)
-+ goto err_out;
-+
-+ if ((pci_resource_flags(pdev, 4) & IORESOURCE_MEM) == 0) {
-+ rc = -ENODEV;
-+ goto err_out_regions;
-+ }
-+
-+ mmio_base = ioremap(pci_resource_start(pdev, 4),
-+ pci_resource_len(pdev, 4));
-+ if (mmio_base == NULL) {
-+ rc = -ENOMEM;
-+ goto err_out_regions;
-+ }
-+
-+ rc = qs_set_dma_masks(pdev, mmio_base);
-+ if (rc)
-+ goto err_out_iounmap;
-+
-+ probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
-+ if (probe_ent == NULL) {
-+ rc = -ENOMEM;
-+ goto err_out_iounmap;
-+ }
-+
-+ memset(probe_ent, 0, sizeof(*probe_ent));
-+ probe_ent->dev = pci_dev_to_dev(pdev);
-+ INIT_LIST_HEAD(&probe_ent->node);
-+
-+ probe_ent->sht = qs_port_info[board_idx].sht;
-+ probe_ent->host_flags = qs_port_info[board_idx].host_flags;
-+ probe_ent->pio_mask = qs_port_info[board_idx].pio_mask;
-+ probe_ent->mwdma_mask = qs_port_info[board_idx].mwdma_mask;
-+ probe_ent->udma_mask = qs_port_info[board_idx].udma_mask;
-+ probe_ent->port_ops = qs_port_info[board_idx].port_ops;
-+
-+ probe_ent->irq = pdev->irq;
-+ probe_ent->irq_flags = SA_SHIRQ;
-+ probe_ent->mmio_base = mmio_base;
-+ probe_ent->n_ports = QS_PORTS;
-+
-+ for (port_no = 0; port_no < probe_ent->n_ports; ++port_no) {
-+ unsigned long chan = (unsigned long)mmio_base +
-+ (port_no * 0x4000);
-+ qs_ata_setup_port(&probe_ent->port[port_no], chan);
-+ }
-+
-+ pci_set_master(pdev);
-+
-+ /* initialize adapter */
-+ qs_host_init(board_idx, probe_ent);
-+
-+ ata_add_to_probe_list(probe_ent);
-+ return 0;
-+
-+err_out_iounmap:
-+ iounmap(mmio_base);
-+err_out_regions:
-+ pci_release_regions(pdev);
-+err_out:
-+ pci_disable_device(pdev);
-+ return rc;
-+}
-+
-+static int __init qs_ata_init(void)
-+{
-+ int rc;
-+
-+ rc = pci_module_init(&qs_ata_pci_driver);
-+ if (rc)
-+ return rc;
-+
-+ rc = scsi_register_module(MODULE_SCSI_HA, &qs_ata_sht);
-+ if (rc) {
-+ rc = -ENODEV;
-+ goto err_out;
-+ }
-+
-+ return 0;
-+
-+err_out:
-+ pci_unregister_driver(&qs_ata_pci_driver);
-+ return rc;
-+}
-+
-+static void __exit qs_ata_exit(void)
-+{
-+ scsi_unregister_module(MODULE_SCSI_HA, &qs_ata_sht);
-+ pci_unregister_driver(&qs_ata_pci_driver);
-+}
-+
-+MODULE_AUTHOR("Mark Lord");
-+MODULE_DESCRIPTION("Pacific Digital Corporation QStor SATA low-level driver");
-+MODULE_LICENSE("GPL");
-+MODULE_DEVICE_TABLE(pci, qs_ata_pci_tbl);
-+MODULE_VERSION(DRV_VERSION);
-+
-+module_init(qs_ata_init);
-+module_exit(qs_ata_exit);
-diff -Nur linux-2.4.29/drivers/scsi/sata_sil.c linux-mips/drivers/scsi/sata_sil.c
---- linux-2.4.29/drivers/scsi/sata_sil.c 2005-01-19 15:10:03.000000000 +0100
-+++ linux-mips/drivers/scsi/sata_sil.c 2005-03-26 11:47:33.241196096 +0100
-@@ -71,12 +71,14 @@
- { 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
- { 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
- { 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
-+ { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-+ { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
- { } /* terminate list */
- };
-
-
- /* TODO firmware versions should be added - eric */
--struct sil_drivelist {
-+static const struct sil_drivelist {
- const char * product;
- unsigned int quirk;
- } sil_blacklist [] = {
-@@ -84,10 +86,12 @@
- { "ST330013AS", SIL_QUIRK_MOD15WRITE },
- { "ST340017AS", SIL_QUIRK_MOD15WRITE },
- { "ST360015AS", SIL_QUIRK_MOD15WRITE },
-+ { "ST380013AS", SIL_QUIRK_MOD15WRITE },
- { "ST380023AS", SIL_QUIRK_MOD15WRITE },
- { "ST3120023AS", SIL_QUIRK_MOD15WRITE },
- { "ST3160023AS", SIL_QUIRK_MOD15WRITE },
- { "ST3120026AS", SIL_QUIRK_MOD15WRITE },
-+ { "ST3200822AS", SIL_QUIRK_MOD15WRITE },
- { "ST340014ASL", SIL_QUIRK_MOD15WRITE },
- { "ST360014ASL", SIL_QUIRK_MOD15WRITE },
- { "ST380011ASL", SIL_QUIRK_MOD15WRITE },
-@@ -136,6 +140,8 @@
- .post_set_mode = sil_post_set_mode,
- .bmdma_setup = ata_bmdma_setup,
- .bmdma_start = ata_bmdma_start,
-+ .bmdma_stop = ata_bmdma_stop,
-+ .bmdma_status = ata_bmdma_status,
- .qc_prep = ata_qc_prep,
- .qc_issue = ata_qc_issue_prot,
- .eng_timeout = ata_eng_timeout,
-@@ -333,6 +339,7 @@
- void *mmio_base;
- int rc;
- unsigned int i;
-+ int pci_dev_busy = 0;
- u32 tmp, irq_mask;
-
- if (!printed_version++)
-@@ -347,8 +354,10 @@
- return rc;
-
- rc = pci_request_regions(pdev, DRV_NAME);
-- if (rc)
-+ if (rc) {
-+ pci_dev_busy = 1;
- goto err_out;
-+ }
-
- rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
- if (rc)
-@@ -430,7 +439,8 @@
- err_out_regions:
- pci_release_regions(pdev);
- err_out:
-- pci_disable_device(pdev);
-+ if (!pci_dev_busy)
-+ pci_disable_device(pdev);
- return rc;
- }
-
-diff -Nur linux-2.4.29/drivers/scsi/sata_sis.c linux-mips/drivers/scsi/sata_sis.c
---- linux-2.4.29/drivers/scsi/sata_sis.c 2005-01-19 15:10:03.000000000 +0100
-+++ linux-mips/drivers/scsi/sata_sis.c 2005-03-26 11:47:33.244195604 +0100
-@@ -103,6 +103,8 @@
- .phy_reset = sata_phy_reset,
- .bmdma_setup = ata_bmdma_setup,
- .bmdma_start = ata_bmdma_start,
-+ .bmdma_stop = ata_bmdma_stop,
-+ .bmdma_status = ata_bmdma_status,
- .qc_prep = ata_qc_prep,
- .qc_issue = ata_qc_issue_prot,
- .eng_timeout = ata_eng_timeout,
-@@ -201,14 +203,17 @@
- int rc;
- u32 genctl;
- struct ata_port_info *ppi;
-+ int pci_dev_busy = 0;
-
- rc = pci_enable_device(pdev);
- if (rc)
- return rc;
-
- rc = pci_request_regions(pdev, DRV_NAME);
-- if (rc)
-+ if (rc) {
-+ pci_dev_busy = 1;
- goto err_out;
-+ }
-
- rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
- if (rc)
-@@ -255,7 +260,8 @@
- pci_release_regions(pdev);
-
- err_out:
-- pci_disable_device(pdev);
-+ if (!pci_dev_busy)
-+ pci_disable_device(pdev);
- return rc;
-
- }
-diff -Nur linux-2.4.29/drivers/scsi/sata_svw.c linux-mips/drivers/scsi/sata_svw.c
---- linux-2.4.29/drivers/scsi/sata_svw.c 2005-01-19 15:10:03.000000000 +0100
-+++ linux-mips/drivers/scsi/sata_svw.c 2005-03-26 11:47:33.246195276 +0100
-@@ -156,7 +156,7 @@
- * spin_lock_irqsave(host_set lock)
- */
-
--void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc)
-+static void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc)
- {
- struct ata_port *ap = qc->ap;
- unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
-@@ -186,7 +186,7 @@
- * spin_lock_irqsave(host_set lock)
- */
-
--void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
-+static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
- {
- struct ata_port *ap = qc->ap;
- void *mmio = (void *) ap->ioaddr.bmdma_addr;
-@@ -302,6 +302,8 @@
- .phy_reset = sata_phy_reset,
- .bmdma_setup = k2_bmdma_setup_mmio,
- .bmdma_start = k2_bmdma_start_mmio,
-+ .bmdma_stop = ata_bmdma_stop,
-+ .bmdma_status = ata_bmdma_status,
- .qc_prep = ata_qc_prep,
- .qc_issue = ata_qc_issue_prot,
- .eng_timeout = ata_eng_timeout,
-@@ -339,6 +341,7 @@
- struct ata_probe_ent *probe_ent = NULL;
- unsigned long base;
- void *mmio_base;
-+ int pci_dev_busy = 0;
- int rc;
-
- if (!printed_version++)
-@@ -360,8 +363,10 @@
-
- /* Request PCI regions */
- rc = pci_request_regions(pdev, DRV_NAME);
-- if (rc)
-+ if (rc) {
-+ pci_dev_busy = 1;
- goto err_out;
-+ }
-
- rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
- if (rc)
-@@ -429,7 +434,8 @@
- err_out_regions:
- pci_release_regions(pdev);
- err_out:
-- pci_disable_device(pdev);
-+ if (!pci_dev_busy)
-+ pci_disable_device(pdev);
- return rc;
- }
-
-diff -Nur linux-2.4.29/drivers/scsi/sata_sx4.c linux-mips/drivers/scsi/sata_sx4.c
---- linux-2.4.29/drivers/scsi/sata_sx4.c 2005-01-19 15:10:03.000000000 +0100
-+++ linux-mips/drivers/scsi/sata_sx4.c 2005-03-26 11:47:33.249194784 +0100
-@@ -1191,8 +1191,7 @@
- error = 0;
- break;
- }
-- set_current_state(TASK_UNINTERRUPTIBLE);
-- schedule_timeout((i * 100) * HZ / 1000 + 1);
-+ msleep(i*100);
- }
- return error;
- }
-@@ -1225,8 +1224,7 @@
- readl(mmio + PDC_TIME_CONTROL);
-
- /* Wait 3 seconds */
-- set_current_state(TASK_UNINTERRUPTIBLE);
-- schedule_timeout(3 * HZ);
-+ msleep(3000);
-
- /*
- When timer is enabled, counter is decreased every internal
-@@ -1369,6 +1367,7 @@
- void *mmio_base, *dimm_mmio = NULL;
- struct pdc_host_priv *hpriv = NULL;
- unsigned int board_idx = (unsigned int) ent->driver_data;
-+ int pci_dev_busy = 0;
- int rc;
-
- if (!printed_version++)
-@@ -1383,8 +1382,10 @@
- return rc;
-
- rc = pci_request_regions(pdev, DRV_NAME);
-- if (rc)
-+ if (rc) {
-+ pci_dev_busy = 1;
- goto err_out;
-+ }
-
- rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
- if (rc)
-@@ -1469,7 +1470,8 @@
- err_out_regions:
- pci_release_regions(pdev);
- err_out:
-- pci_disable_device(pdev);
-+ if (!pci_dev_busy)
-+ pci_disable_device(pdev);
- return rc;
- }
-
-diff -Nur linux-2.4.29/drivers/scsi/sata_uli.c linux-mips/drivers/scsi/sata_uli.c
---- linux-2.4.29/drivers/scsi/sata_uli.c 2005-01-19 15:10:03.000000000 +0100
-+++ linux-mips/drivers/scsi/sata_uli.c 2005-03-26 11:47:33.252194291 +0100
-@@ -98,6 +98,8 @@
-
- .bmdma_setup = ata_bmdma_setup,
- .bmdma_start = ata_bmdma_start,
-+ .bmdma_stop = ata_bmdma_stop,
-+ .bmdma_status = ata_bmdma_status,
- .qc_prep = ata_qc_prep,
- .qc_issue = ata_qc_issue_prot,
-
-@@ -186,14 +188,17 @@
- struct ata_port_info *ppi;
- int rc;
- unsigned int board_idx = (unsigned int) ent->driver_data;
-+ int pci_dev_busy = 0;
-
- rc = pci_enable_device(pdev);
- if (rc)
- return rc;
-
- rc = pci_request_regions(pdev, DRV_NAME);
-- if (rc)
-+ if (rc) {
-+ pci_dev_busy = 1;
- goto err_out;
-+ }
-
- rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
- if (rc)
-@@ -256,7 +261,8 @@
- pci_release_regions(pdev);
-
- err_out:
-- pci_disable_device(pdev);
-+ if (!pci_dev_busy)
-+ pci_disable_device(pdev);
- return rc;
-
- }
-diff -Nur linux-2.4.29/drivers/scsi/sata_via.c linux-mips/drivers/scsi/sata_via.c
---- linux-2.4.29/drivers/scsi/sata_via.c 2005-01-19 15:10:03.000000000 +0100
-+++ linux-mips/drivers/scsi/sata_via.c 2005-03-26 11:47:33.268191666 +0100
-@@ -24,6 +24,11 @@
- If you do not delete the provisions above, a recipient may use your
- version of this file under either the OSL or the GPL.
-
-+ ----------------------------------------------------------------------
-+
-+ To-do list:
-+ * VT6421 PATA support
-+
- */
-
- #include <linux/kernel.h>
-@@ -38,11 +43,14 @@
- #include <asm/io.h>
-
- #define DRV_NAME "sata_via"
--#define DRV_VERSION "1.0"
-+#define DRV_VERSION "1.1"
-
--enum {
-- via_sata = 0,
-+enum board_ids_enum {
-+ vt6420,
-+ vt6421,
-+};
-
-+enum {
- SATA_CHAN_ENAB = 0x40, /* SATA channel enable */
- SATA_INT_GATE = 0x41, /* SATA interrupt gating */
- SATA_NATIVE_MODE = 0x42, /* Native mode enable */
-@@ -50,10 +58,8 @@
-
- PORT0 = (1 << 1),
- PORT1 = (1 << 0),
--
-- ENAB_ALL = PORT0 | PORT1,
--
-- INT_GATE_ALL = PORT0 | PORT1,
-+ ALL_PORTS = PORT0 | PORT1,
-+ N_PORTS = 2,
-
- NATIVE_MODE_ALL = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4),
-
-@@ -66,7 +72,8 @@
- static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
-
- static struct pci_device_id svia_pci_tbl[] = {
-- { 0x1106, 0x3149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, via_sata },
-+ { 0x1106, 0x3149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6420 },
-+ { 0x1106, 0x3249, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6421 },
-
- { } /* terminate list */
- };
-@@ -111,6 +118,9 @@
-
- .bmdma_setup = ata_bmdma_setup,
- .bmdma_start = ata_bmdma_start,
-+ .bmdma_stop = ata_bmdma_stop,
-+ .bmdma_status = ata_bmdma_status,
-+
- .qc_prep = ata_qc_prep,
- .qc_issue = ata_qc_issue_prot,
-
-@@ -159,18 +169,132 @@
- 8, 4, 8, 4, 16, 256
- };
-
-+static const unsigned int vt6421_bar_sizes[] = {
-+ 16, 16, 16, 16, 32, 128
-+};
-+
- static unsigned long svia_scr_addr(unsigned long addr, unsigned int port)
- {
- return addr + (port * 128);
- }
-
-+static unsigned long vt6421_scr_addr(unsigned long addr, unsigned int port)
-+{
-+ return addr + (port * 64);
-+}
-+
-+static void vt6421_init_addrs(struct ata_probe_ent *probe_ent,
-+ struct pci_dev *pdev,
-+ unsigned int port)
-+{
-+ unsigned long reg_addr = pci_resource_start(pdev, port);
-+ unsigned long bmdma_addr = pci_resource_start(pdev, 4) + (port * 8);
-+ unsigned long scr_addr;
-+
-+ probe_ent->port[port].cmd_addr = reg_addr;
-+ probe_ent->port[port].altstatus_addr =
-+ probe_ent->port[port].ctl_addr = (reg_addr + 8) | ATA_PCI_CTL_OFS;
-+ probe_ent->port[port].bmdma_addr = bmdma_addr;
-+
-+ scr_addr = vt6421_scr_addr(pci_resource_start(pdev, 5), port);
-+ probe_ent->port[port].scr_addr = scr_addr;
-+
-+ ata_std_ports(&probe_ent->port[port]);
-+}
-+
-+static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev)
-+{
-+ struct ata_probe_ent *probe_ent;
-+ struct ata_port_info *ppi = &svia_port_info;
-+
-+ probe_ent = ata_pci_init_native_mode(pdev, &ppi);
-+ if (!probe_ent)
-+ return NULL;
-+
-+ probe_ent->port[0].scr_addr =
-+ svia_scr_addr(pci_resource_start(pdev, 5), 0);
-+ probe_ent->port[1].scr_addr =
-+ svia_scr_addr(pci_resource_start(pdev, 5), 1);
-+
-+ return probe_ent;
-+}
-+
-+static struct ata_probe_ent *vt6421_init_probe_ent(struct pci_dev *pdev)
-+{
-+ struct ata_probe_ent *probe_ent;
-+ unsigned int i;
-+
-+ probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
-+ if (!probe_ent)
-+ return NULL;
-+
-+ memset(probe_ent, 0, sizeof(*probe_ent));
-+ probe_ent->dev = pci_dev_to_dev(pdev);
-+ INIT_LIST_HEAD(&probe_ent->node);
-+
-+ probe_ent->sht = &svia_sht;
-+ probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
-+ ATA_FLAG_NO_LEGACY;
-+ probe_ent->port_ops = &svia_sata_ops;
-+ probe_ent->n_ports = N_PORTS;
-+ probe_ent->irq = pdev->irq;
-+ probe_ent->irq_flags = SA_SHIRQ;
-+ probe_ent->pio_mask = 0x1f;
-+ probe_ent->mwdma_mask = 0x07;
-+ probe_ent->udma_mask = 0x7f;
-+
-+ for (i = 0; i < N_PORTS; i++)
-+ vt6421_init_addrs(probe_ent, pdev, i);
-+
-+ return probe_ent;
-+}
-+
-+static void svia_configure(struct pci_dev *pdev)
-+{
-+ u8 tmp8;
-+
-+ pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8);
-+ printk(KERN_INFO DRV_NAME "(%s): routed to hard irq line %d\n",
-+ pci_name(pdev),
-+ (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f);
-+
-+ /* make sure SATA channels are enabled */
-+ pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8);
-+ if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
-+ printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channels (0x%x)\n",
-+ pci_name(pdev), (int) tmp8);
-+ tmp8 |= ALL_PORTS;
-+ pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8);
-+ }
-+
-+ /* make sure interrupts for each channel sent to us */
-+ pci_read_config_byte(pdev, SATA_INT_GATE, &tmp8);
-+ if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
-+ printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel interrupts (0x%x)\n",
-+ pci_name(pdev), (int) tmp8);
-+ tmp8 |= ALL_PORTS;
-+ pci_write_config_byte(pdev, SATA_INT_GATE, tmp8);
-+ }
-+
-+ /* make sure native mode is enabled */
-+ pci_read_config_byte(pdev, SATA_NATIVE_MODE, &tmp8);
-+ if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) {
-+ printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel native mode (0x%x)\n",
-+ pci_name(pdev), (int) tmp8);
-+ tmp8 |= NATIVE_MODE_ALL;
-+ pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
-+ }
-+}
-+
- static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
- {
- static int printed_version;
- unsigned int i;
- int rc;
-- struct ata_port_info *ppi;
- struct ata_probe_ent *probe_ent;
-+ int board_id = (int) ent->driver_data;
-+ const int *bar_sizes;
-+ int pci_dev_busy = 0;
- u8 tmp8;
-
- if (!printed_version++)
-@@ -181,20 +305,28 @@
- return rc;
-
- rc = pci_request_regions(pdev, DRV_NAME);
-- if (rc)
-+ if (rc) {
-+ pci_dev_busy = 1;
- goto err_out;
-+ }
-
-- pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8);
-- if (tmp8 & SATA_2DEV) {
-- printk(KERN_ERR DRV_NAME "(%s): SATA master/slave not supported (0x%x)\n",
-- pci_name(pdev), (int) tmp8);
-- rc = -EIO;
-- goto err_out_regions;
-+ if (board_id == vt6420) {
-+ pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8);
-+ if (tmp8 & SATA_2DEV) {
-+ printk(KERN_ERR DRV_NAME "(%s): SATA master/slave not supported (0x%x)\n",
-+ pci_name(pdev), (int) tmp8);
-+ rc = -EIO;
-+ goto err_out_regions;
-+ }
-+
-+ bar_sizes = &svia_bar_sizes[0];
-+ } else {
-+ bar_sizes = &vt6421_bar_sizes[0];
- }
-
- for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++)
- if ((pci_resource_start(pdev, i) == 0) ||
-- (pci_resource_len(pdev, i) < svia_bar_sizes[i])) {
-+ (pci_resource_len(pdev, i) < bar_sizes[i])) {
- printk(KERN_ERR DRV_NAME "(%s): invalid PCI BAR %u (sz 0x%lx, val 0x%lx)\n",
- pci_name(pdev), i,
- pci_resource_start(pdev, i),
-@@ -207,8 +339,11 @@
- if (rc)
- goto err_out_regions;
-
-- ppi = &svia_port_info;
-- probe_ent = ata_pci_init_native_mode(pdev, &ppi);
-+ if (board_id == vt6420)
-+ probe_ent = vt6420_init_probe_ent(pdev);
-+ else
-+ probe_ent = vt6421_init_probe_ent(pdev);
-+
- if (!probe_ent) {
- printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
- pci_name(pdev));
-@@ -216,42 +351,7 @@
- goto err_out_regions;
- }
-
-- probe_ent->port[0].scr_addr =
-- svia_scr_addr(pci_resource_start(pdev, 5), 0);
-- probe_ent->port[1].scr_addr =
-- svia_scr_addr(pci_resource_start(pdev, 5), 1);
--
-- pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8);
-- printk(KERN_INFO DRV_NAME "(%s): routed to hard irq line %d\n",
-- pci_name(pdev),
-- (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f);
--
-- /* make sure SATA channels are enabled */
-- pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8);
-- if ((tmp8 & ENAB_ALL) != ENAB_ALL) {
-- printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channels (0x%x)\n",
-- pci_name(pdev), (int) tmp8);
-- tmp8 |= ENAB_ALL;
-- pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8);
-- }
--
-- /* make sure interrupts for each channel sent to us */
-- pci_read_config_byte(pdev, SATA_INT_GATE, &tmp8);
-- if ((tmp8 & INT_GATE_ALL) != INT_GATE_ALL) {
-- printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel interrupts (0x%x)\n",
-- pci_name(pdev), (int) tmp8);
-- tmp8 |= INT_GATE_ALL;
-- pci_write_config_byte(pdev, SATA_INT_GATE, tmp8);
-- }
--
-- /* make sure native mode is enabled */
-- pci_read_config_byte(pdev, SATA_NATIVE_MODE, &tmp8);
-- if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) {
-- printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel native mode (0x%x)\n",
-- pci_name(pdev), (int) tmp8);
-- tmp8 |= NATIVE_MODE_ALL;
-- pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
-- }
-+ svia_configure(pdev);
-
- pci_set_master(pdev);
-
-@@ -262,7 +362,8 @@
- err_out_regions:
- pci_release_regions(pdev);
- err_out:
-- pci_disable_device(pdev);
-+ if (!pci_dev_busy)
-+ pci_disable_device(pdev);
- return rc;
- }
-
-diff -Nur linux-2.4.29/drivers/scsi/sata_vsc.c linux-mips/drivers/scsi/sata_vsc.c
---- linux-2.4.29/drivers/scsi/sata_vsc.c 2005-01-19 15:10:03.000000000 +0100
-+++ linux-mips/drivers/scsi/sata_vsc.c 2005-03-26 11:47:33.270191338 +0100
-@@ -155,7 +155,8 @@
- *
- * Read the interrupt register and process for the devices that have them pending.
- */
--irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
-+static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance,
-+ struct pt_regs *regs)
- {
- struct ata_host_set *host_set = dev_instance;
- unsigned int i;
-@@ -218,6 +219,8 @@
- .phy_reset = sata_phy_reset,
- .bmdma_setup = ata_bmdma_setup,
- .bmdma_start = ata_bmdma_start,
-+ .bmdma_stop = ata_bmdma_stop,
-+ .bmdma_status = ata_bmdma_status,
- .qc_prep = ata_qc_prep,
- .qc_issue = ata_qc_issue_prot,
- .eng_timeout = ata_eng_timeout,
-@@ -256,6 +259,7 @@
- static int printed_version;
- struct ata_probe_ent *probe_ent = NULL;
- unsigned long base;
-+ int pci_dev_busy = 0;
- void *mmio_base;
- int rc;
-
-@@ -275,13 +279,15 @@
- }
-
- rc = pci_request_regions(pdev, DRV_NAME);
-- if (rc)
-+ if (rc) {
-+ pci_dev_busy = 1;
- goto err_out;
-+ }
-
- /*
- * Use 32 bit DMA mask, because 64 bit address support is poor.
- */
-- rc = pci_set_dma_mask(pdev, 0xFFFFFFFFULL);
-+ rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
- if (rc)
- goto err_out_regions;
-
-@@ -348,7 +354,8 @@
- err_out_regions:
- pci_release_regions(pdev);
- err_out:
-- pci_disable_device(pdev);
-+ if (!pci_dev_busy)
-+ pci_disable_device(pdev);
- return rc;
- }
-
-diff -Nur linux-2.4.29/drivers/scsi/sd.c linux-mips/drivers/scsi/sd.c
---- linux-2.4.29/drivers/scsi/sd.c 2003-08-25 13:44:42.000000000 +0200
-+++ linux-mips/drivers/scsi/sd.c 2005-03-26 11:47:33.274190681 +0100
-@@ -1220,7 +1220,7 @@
- goto cleanup_gendisks_part;
- memset(sd_gendisks[i].part, 0, (SCSI_DISKS_PER_MAJOR << 4) * sizeof(struct hd_struct));
- sd_gendisks[i].sizes = sd_sizes + (i * SCSI_DISKS_PER_MAJOR << 4);
-- sd_gendisks[i].nr_real = 0;
-+ sd_gendisks[i].nr_real = SCSI_DISKS_PER_MAJOR;
- sd_gendisks[i].real_devices =
- (void *) (rscsi_disks + i * SCSI_DISKS_PER_MAJOR);
- }
-@@ -1333,7 +1333,6 @@
- rscsi_disks[i].device = SDp;
- rscsi_disks[i].has_part_table = 0;
- sd_template.nr_dev++;
-- SD_GENDISK(i).nr_real++;
- devnum = i % SCSI_DISKS_PER_MAJOR;
- SD_GENDISK(i).de_arr[devnum] = SDp->de;
- if (SDp->removable)
-@@ -1447,7 +1446,6 @@
- SDp->attached--;
- sd_template.dev_noticed--;
- sd_template.nr_dev--;
-- SD_GENDISK(i).nr_real--;
- return;
- }
- return;
-diff -Nur linux-2.4.29/drivers/scsi/st.c linux-mips/drivers/scsi/st.c
---- linux-2.4.29/drivers/scsi/st.c 2005-01-19 15:10:04.000000000 +0100
-+++ linux-mips/drivers/scsi/st.c 2005-03-26 11:47:33.279189861 +0100
-@@ -1641,7 +1641,7 @@
- if (STps->drv_block >= 0)
- STps->drv_block += 1;
- (STp->buffer)->buffer_bytes = 0;
-- return (-EIO);
-+ return (-ENOMEM);
- }
- (STp->buffer)->buffer_bytes = bytes - transfer;
- } else {
-@@ -3778,7 +3778,6 @@
- read: st_read,
- write: st_write,
- ioctl: st_ioctl,
-- llseek: no_llseek,
- open: st_open,
- flush: st_flush,
- release: st_release,
-diff -Nur linux-2.4.29/drivers/scsi/sym53c8xx.c linux-mips/drivers/scsi/sym53c8xx.c
---- linux-2.4.29/drivers/scsi/sym53c8xx.c 2004-04-14 15:05:32.000000000 +0200
-+++ linux-mips/drivers/scsi/sym53c8xx.c 2005-03-26 11:47:34.823936333 +0100
-@@ -13182,7 +13182,7 @@
- ** descriptors.
- */
- if (chip && (chip->features & FE_DAC)) {
-- if (pci_set_dma_mask(pdev, (u64) 0xffffffffff))
-+ if (pci_set_dma_mask(pdev, (u64) 0xffffffffffULL))
- chip->features &= ~FE_DAC_IN_USE;
- else
- chip->features |= FE_DAC_IN_USE;
-diff -Nur linux-2.4.29/drivers/sound/au1550_i2s.c linux-mips/drivers/sound/au1550_i2s.c
---- linux-2.4.29/drivers/sound/au1550_i2s.c 2005-01-19 15:10:04.000000000 +0100
-+++ linux-mips/drivers/sound/au1550_i2s.c 2005-03-26 11:47:35.065896621 +0100
-@@ -41,6 +41,7 @@
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-+
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/string.h>
-@@ -62,7 +63,45 @@
- #include <asm/uaccess.h>
- #include <asm/hardirq.h>
- #include <asm/au1000.h>
-+
-+#if defined(CONFIG_SOC_AU1550)
- #include <asm/pb1550.h>
-+#endif
-+
-+#if defined(CONFIG_MIPS_PB1200)
-+#define WM8731
-+#define WM_MODE_USB
-+#include <asm/pb1200.h>
-+#endif
-+
-+#if defined(CONFIG_MIPS_FICMMP)
-+#define WM8721
-+#define WM_MODE_NORMAL
-+#include <asm/ficmmp.h>
-+#endif
-+
-+
-+#define WM_VOLUME_MIN 47
-+#define WM_VOLUME_SCALE 80
-+
-+#if defined(WM8731)
-+ /* OSS interface to the wm i2s.. */
-+ #define CODEC_NAME "Wolfson WM8731 I2S"
-+ #define WM_I2S_STEREO_MASK (SOUND_MASK_PCM | SOUND_MASK_LINE)
-+ #define WM_I2S_SUPPORTED_MASK (WM_I2S_STEREO_MASK | SOUND_MASK_MIC)
-+ #define WM_I2S_RECORD_MASK (SOUND_MASK_MIC | SOUND_MASK_LINE1 | SOUND_MASK_LINE)
-+#elif defined(WM8721)
-+ #define CODEC_NAME "Wolfson WM8721 I2S"
-+ #define WM_I2S_STEREO_MASK (SOUND_MASK_PCM)
-+ #define WM_I2S_SUPPORTED_MASK (WM_I2S_STEREO_MASK)
-+ #define WM_I2S_RECORD_MASK (0)
-+#endif
-+
-+
-+#define supported_mixer(FOO) ((FOO >= 0) && \
-+ (FOO < SOUND_MIXER_NRDEVICES) && \
-+ WM_I2S_SUPPORTED_MASK & (1<<FOO) )
-+
- #include <asm/au1xxx_psc.h>
- #include <asm/au1xxx_dbdma.h>
-
-@@ -98,13 +137,51 @@
- * 0 = no VRA, 1 = use VRA if codec supports it
- * The framework is here, but we currently force no VRA.
- */
-+#if defined(CONFIG_MIPS_PB1200) | defined(CONFIG_MIPS_PB1550)
- static int vra = 0;
-+#elif defined(CONFIG_MIPS_FICMMP)
-+static int vra = 1;
-+#endif
-+
-+#define WM_REG_L_HEADPHONE_OUT 0x02
-+#define WM_REG_R_HEADPHONE_OUT 0x03
-+#define WM_REG_ANALOGUE_AUDIO_PATH_CTRL 0x04
-+#define WM_REG_DIGITAL_AUDIO_PATH_CTRL 0x05
-+#define WM_REG_POWER_DOWN_CTRL 0x06
-+#define WM_REG_DIGITAL_AUDIO_IF 0x07
-+#define WM_REG_SAMPLING_CONTROL 0x08
-+#define WM_REG_ACTIVE_CTRL 0x09
-+#define WM_REG_RESET 0x0F
-+#define WM_SC_SR_96000 (0x7<<2)
-+#define WM_SC_SR_88200 (0xF<<2)
-+#define WM_SC_SR_48000 (0x0<<2)
-+#define WM_SC_SR_44100 (0x8<<2)
-+#define WM_SC_SR_32000 (0x6<<2)
-+#define WM_SC_SR_8018 (0x9<<2)
-+#define WM_SC_SR_8000 (0x1<<2)
-+#define WM_SC_MODE_USB 1
-+#define WM_SC_MODE_NORMAL 0
-+#define WM_SC_BOSR_250FS (0<<1)
-+#define WM_SC_BOSR_272FS (1<<1)
-+#define WM_SC_BOSR_256FS (0<<1)
-+#define WM_SC_BOSR_128FS (0<<1)
-+#define WM_SC_BOSR_384FS (1<<1)
-+#define WM_SC_BOSR_192FS (1<<1)
-+
-+#define WS_64FS 31
-+#define WS_96FS 47
-+#define WS_128FS 63
-+#define WS_192FS 95
-+
-+#define MIN_Q_COUNT 2
-+
- MODULE_PARM(vra, "i");
- MODULE_PARM_DESC(vra, "if 1 use VRA if codec supports it");
-
- static struct au1550_state {
- /* soundcore stuff */
- int dev_audio;
-+ int dev_mixer;
-
- spinlock_t lock;
- struct semaphore open_sem;
-@@ -114,6 +191,11 @@
- int no_vra;
- volatile psc_i2s_t *psc_addr;
-
-+ int level_line;
-+ int level_mic;
-+ int level_left;
-+ int level_right;
-+
- struct dmabuf {
- u32 dmanr;
- unsigned sample_rate;
-@@ -195,60 +277,224 @@
- }
- }
-
--/* Just a place holder. The Wolfson codec is a write only device,
-- * so we would have to keep a local copy of the data.
-- */
--#if 0
--static u8
--rdcodec(u8 addr)
--{
-- return 0 /* data */;
--}
--#endif
--
--
- static void
--wrcodec(u8 ctlreg, u8 val)
-+wrcodec(u8 ctlreg, u16 val)
- {
- int rcnt;
- extern int pb1550_wm_codec_write(u8 addr, u8 reg, u8 val);
--
- /* The codec is a write only device, with a 16-bit control/data
- * word. Although it is written as two bytes on the I2C, the
- * format is actually 7 bits of register and 9 bits of data.
- * The ls bit of the first byte is the ms bit of the data.
- */
- rcnt = 0;
-- while ((pb1550_wm_codec_write((0x36 >> 1), ctlreg, val) != 1)
-- && (rcnt < 50)) {
-+ while ((pb1550_wm_codec_write((0x36 >> 1),
-+ (ctlreg << 1) | ((val >> 8) & 0x01),
-+ (u8) (val & 0x00FF)) != 1) &&
-+ (rcnt < 50)) {
- rcnt++;
--#if 0
-- printk("Codec write retry %02x %02x\n", ctlreg, val);
--#endif
- }
-+
-+ au1550_delay(10);
-+}
-+
-+static int
-+au1550_open_mixdev(struct inode *inode, struct file *file)
-+{
-+ file->private_data = &au1550_state;
-+ return 0;
-+}
-+
-+static int
-+au1550_release_mixdev(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static int wm_i2s_read_mixer(struct au1550_state *s, int oss_channel)
-+{
-+ int ret = 0;
-+
-+ if (WM_I2S_STEREO_MASK & (1 << oss_channel)) {
-+ /* nice stereo mixers .. */
-+
-+ ret = s->level_left | (s->level_right << 8);
-+ } else if (oss_channel == SOUND_MIXER_MIC) {
-+ ret = 0;
-+ /* TODO: Implement read mixer for input/output codecs */
-+ }
-+
-+ return ret;
- }
-
-+static void wm_i2s_write_mixer(struct au1550_state *s, int oss_channel, unsigned int left, unsigned int right)
-+{
-+ if (WM_I2S_STEREO_MASK & (1 << oss_channel)) {
-+ /* stereo mixers */
-+ s->level_left = left;
-+ s->level_right = right;
-+
-+ right = (right * WM_VOLUME_SCALE) / 100;
-+ left = (left * WM_VOLUME_SCALE) / 100;
-+ if (right > WM_VOLUME_SCALE)
-+ right = WM_VOLUME_SCALE;
-+ if (left > WM_VOLUME_SCALE)
-+ left = WM_VOLUME_SCALE;
-+
-+ right += WM_VOLUME_MIN;
-+ left += WM_VOLUME_MIN;
-+
-+ wrcodec(WM_REG_L_HEADPHONE_OUT, left);
-+ wrcodec(WM_REG_R_HEADPHONE_OUT, right);
-+
-+ }else if (oss_channel == SOUND_MIXER_MIC) {
-+ /* TODO: implement write mixer for input/output codecs */
-+ }
-+}
-+
-+/* a thin wrapper for write_mixer */
-+static void wm_i2s_set_mixer(struct au1550_state *s, unsigned int oss_mixer, unsigned int val )
-+{
-+ unsigned int left,right;
-+
-+ /* cleanse input a little */
-+ right = ((val >> 8) & 0xff) ;
-+ left = (val & 0xff) ;
-+
-+ if (right > 100) right = 100;
-+ if (left > 100) left = 100;
-+
-+ wm_i2s_write_mixer(s, oss_mixer, left, right);
-+}
-+
-+static int
-+au1550_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+ struct au1550_state *s = (struct au1550_state *)file->private_data;
-+
-+ int i, val = 0;
-+
-+ if (cmd == SOUND_MIXER_INFO) {
-+ mixer_info info;
-+ strncpy(info.id, CODEC_NAME, sizeof(info.id));
-+ strncpy(info.name, CODEC_NAME, sizeof(info.name));
-+ info.modify_counter = 0;
-+ if (copy_to_user((void *)arg, &info, sizeof(info)))
-+ return -EFAULT;
-+ return 0;
-+ }
-+ if (cmd == SOUND_OLD_MIXER_INFO) {
-+ _old_mixer_info info;
-+ strncpy(info.id, CODEC_NAME, sizeof(info.id));
-+ strncpy(info.name, CODEC_NAME, sizeof(info.name));
-+ if (copy_to_user((void *)arg, &info, sizeof(info)))
-+ return -EFAULT;
-+ return 0;
-+ }
-+
-+ if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int))
-+ return -EINVAL;
-+
-+ if (cmd == OSS_GETVERSION)
-+ return put_user(SOUND_VERSION, (int *)arg);
-+
-+ if (_SIOC_DIR(cmd) == _SIOC_READ) {
-+ switch (_IOC_NR(cmd)) {
-+ case SOUND_MIXER_RECSRC: /* give them the current record src */
-+ val = 0;
-+ /*
-+ if (!codec->recmask_io) {
-+ val = 0;
-+ } else {
-+ val = codec->recmask_io(codec, 1, 0);
-+ }*/
-+ break;
-+
-+ case SOUND_MIXER_DEVMASK: /* give them the supported mixers */
-+ val = WM_I2S_SUPPORTED_MASK;
-+ break;
-+
-+ case SOUND_MIXER_RECMASK:
-+ /* Arg contains a bit for each supported recording
-+ * source */
-+ val = WM_I2S_RECORD_MASK;
-+ break;
-+
-+ case SOUND_MIXER_STEREODEVS:
-+ /* Mixer channels supporting stereo */
-+ val = WM_I2S_STEREO_MASK;
-+ break;
-+
-+ case SOUND_MIXER_CAPS:
-+ val = SOUND_CAP_EXCL_INPUT;
-+ break;
-+
-+ default: /* read a specific mixer */
-+ i = _IOC_NR(cmd);
-+
-+ if (!supported_mixer(i))
-+ return -EINVAL;
-+
-+ val = wm_i2s_read_mixer(s, i);
-+ break;
-+ }
-+ return put_user(val, (int *)arg);
-+ }
-+
-+ if (_SIOC_DIR(cmd) == (_SIOC_WRITE|_SIOC_READ)) {
-+ if (get_user(val, (int *)arg))
-+ return -EFAULT;
-+
-+ switch (_IOC_NR(cmd)) {
-+ case SOUND_MIXER_RECSRC:
-+ /* Arg contains a bit for each recording source */
-+ if (!WM_I2S_RECORD_MASK)
-+ return -EINVAL;
-+ if (!val)
-+ return 0;
-+ if (!(val &= WM_I2S_RECORD_MASK))
-+ return -EINVAL;
-+
-+ return 0;
-+ default: /* write a specific mixer */
-+ i = _IOC_NR(cmd);
-+
-+ if (!supported_mixer(i))
-+ return -EINVAL;
-+
-+ wm_i2s_set_mixer(s, i, val);
-+
-+ return 0;
-+ }
-+}
-+ return -EINVAL;
-+}
-+
-+static loff_t
-+au1550_llseek(struct file *file, loff_t offset, int origin)
-+{
-+ return -ESPIPE;
-+}
-+
-+static /*const */ struct file_operations au1550_mixer_fops = {
-+ owner:THIS_MODULE,
-+ llseek:au1550_llseek,
-+ ioctl:au1550_ioctl_mixdev,
-+ open:au1550_open_mixdev,
-+ release:au1550_release_mixdev,
-+};
-+
- void
--codec_init(void)
-+codec_init(struct au1550_state *s)
- {
-- wrcodec(0x1e, 0x00); /* Reset */
-- au1550_delay(200);
-- wrcodec(0x0c, 0x00); /* Power up everything */
-- au1550_delay(10);
-- wrcodec(0x12, 0x00); /* Deactivate codec */
-- au1550_delay(10);
-- wrcodec(0x08, 0x10); /* Select DAC outputs to line out */
-- au1550_delay(10);
-- wrcodec(0x0a, 0x00); /* Disable output mute */
-- au1550_delay(10);
-- wrcodec(0x05, 0x70); /* lower output volume on headphone */
-- au1550_delay(10);
-- wrcodec(0x0e, 0x02); /* Set slave, 16-bit, I2S modes */
-- au1550_delay(10);
-- wrcodec(0x10, 0x01); /* 12MHz (USB), 250fs */
-- au1550_delay(10);
-- wrcodec(0x12, 0x01); /* Activate codec */
-- au1550_delay(10);
-+ wrcodec(WM_REG_RESET, 0x00); /* Reset */
-+ wrcodec(WM_REG_POWER_DOWN_CTRL, 0x00); /* Power up everything */
-+ wrcodec(WM_REG_ACTIVE_CTRL, 0x00); /* Deactivate codec */
-+ wrcodec(WM_REG_ANALOGUE_AUDIO_PATH_CTRL, 0x10); /* Select DAC outputs to line out */
-+ wrcodec(WM_REG_DIGITAL_AUDIO_PATH_CTRL, 0x00); /* Disable output mute */
-+ wm_i2s_write_mixer(s, SOUND_MIXER_PCM, 74, 74);
-+ wrcodec(WM_REG_DIGITAL_AUDIO_IF, 0x02); /* Set slave, 16-bit, I2S modes */
-+ wrcodec(WM_REG_ACTIVE_CTRL, 0x01); /* Activate codec */
- }
-
- /* stop the ADC before calling */
-@@ -256,27 +502,16 @@
- set_adc_rate(struct au1550_state *s, unsigned rate)
- {
- struct dmabuf *adc = &s->dma_adc;
-- struct dmabuf *dac = &s->dma_dac;
-
-- if (s->no_vra) {
-- /* calc SRC factor
-- */
-+ #if defined(WM_MODE_USB)
- adc->src_factor = (((SAMP_RATE*2) / rate) + 1) >> 1;
- adc->sample_rate = SAMP_RATE / adc->src_factor;
- return;
-- }
-+ #else
-+ //TODO: Need code for normal mode
-+ #endif
-
- adc->src_factor = 1;
--
--
--#if 0
-- rate = rate > SAMP_RATE ? SAMP_RATE : rate;
--
-- wrcodec(0, 0); /* I don't yet know what to write here if we vra */
--
-- adc->sample_rate = rate;
-- dac->sample_rate = rate;
--#endif
- }
-
- /* stop the DAC before calling */
-@@ -284,26 +519,89 @@
- set_dac_rate(struct au1550_state *s, unsigned rate)
- {
- struct dmabuf *dac = &s->dma_dac;
-- struct dmabuf *adc = &s->dma_adc;
-
-- if (s->no_vra) {
-- /* calc SRC factor
-- */
-- dac->src_factor = (((SAMP_RATE*2) / rate) + 1) >> 1;
-- dac->sample_rate = SAMP_RATE / dac->src_factor;
-- return;
-+ u16 sr, ws, div, bosr, mode;
-+ volatile psc_i2s_t* ip = (volatile psc_i2s_t *)I2S_PSC_BASE;
-+ u32 cfg;
-+
-+ #if defined(CONFIG_MIPS_FICMMP)
-+ rate = ficmmp_set_i2s_sample_rate(rate);
-+ #endif
-+
-+ switch(rate)
-+ {
-+ case 96000:
-+ sr = WM_SC_SR_96000;
-+ ws = WS_64FS;
-+ div = PSC_I2SCFG_DIV2;
-+ break;
-+ case 88200:
-+ sr = WM_SC_SR_88200;
-+ ws = WS_64FS;
-+ div = PSC_I2SCFG_DIV2;
-+ break;
-+ case 44100:
-+ sr = WM_SC_SR_44100;
-+ ws = WS_128FS;
-+ div = PSC_I2SCFG_DIV2;
-+ break;
-+ case 48000:
-+ sr = WM_SC_SR_48000;
-+ ws = WS_128FS;
-+ div = PSC_I2SCFG_DIV2;
-+ break;
-+ case 32000:
-+ sr = WM_SC_SR_32000;
-+ ws = WS_96FS;
-+ div = PSC_I2SCFG_DIV4;
-+ break;
-+ case 8018:
-+ sr = WM_SC_SR_8018;
-+ ws = WS_128FS;
-+ div = PSC_I2SCFG_DIV2;
-+ break;
-+ case 8000:
-+ default:
-+ sr = WM_SC_SR_8000;
-+ ws = WS_96FS;
-+ div = PSC_I2SCFG_DIV16;
-+ break;
- }
-
-+ #if defined(WM_MODE_USB)
-+ mode = WM_SC_MODE_USB;
-+ #else
-+ mode = WM_SC_MODE_NORMAL;
-+ #endif
-+
-+ bosr = 0;
-+
- dac->src_factor = 1;
-+ dac->sample_rate = rate;
-
--#if 0
-- rate = rate > SAMP_RATE ? SAMP_RATE : rate;
-+ /* Deactivate codec */
-+ wrcodec(WM_REG_ACTIVE_CTRL, 0x00);
-
-- wrcodec(0, 0); /* I don't yet know what to write here if we vra */
-+ /* Disable I2S controller */
-+ ip->psc_i2scfg &= ~PSC_I2SCFG_DE_ENABLE;
-+ /* Wait for device disabled */
-+ while ((ip->psc_i2sstat & PSC_I2SSTAT_DR) == 1);
-+
-+ cfg = ip->psc_i2scfg;
-+ /* Clear WS and DIVIDER values */
-+ cfg &= ~(PSC_I2SCFG_WS_MASK | PSC_I2SCFG_DIV_MASK);
-+ cfg |= PSC_I2SCFG_WS(ws) | div;
-+ /* Reconfigure and enable */
-+ ip->psc_i2scfg = cfg | PSC_I2SCFG_DE_ENABLE;
-
-- adc->sample_rate = rate;
-- dac->sample_rate = rate;
--#endif
-+ /* Wait for device enabled */
-+ while ((ip->psc_i2sstat & PSC_I2SSTAT_DR) == 0);
-+
-+ /* Set appropriate sampling rate */
-+ wrcodec(WM_REG_SAMPLING_CONTROL, bosr | mode | sr);
-+
-+ /* Activate codec */
-+ wrcodec(WM_REG_ACTIVE_CTRL, 0x01);
- }
-
- static void
-@@ -354,8 +652,7 @@
- ip->psc_i2spcr = PSC_I2SPCR_RP;
- au_sync();
-
-- /* Wait for Receive Busy to show disabled.
-- */
-+ /* Wait for Receive Busy to show disabled. */
- do {
- stat = ip->psc_i2sstat;
- au_sync();
-@@ -463,7 +760,6 @@
- if (db->num_channels == 1)
- db->cnt_factor *= 2;
- db->cnt_factor *= db->src_factor;
--
- db->count = 0;
- db->dma_qcount = 0;
- db->nextIn = db->nextOut = db->rawbuf;
-@@ -546,12 +842,13 @@
- if (i2s_stat & (PSC_I2SSTAT_TF | PSC_I2SSTAT_TR | PSC_I2SSTAT_TF))
- dbg("I2S status = 0x%08x", i2s_stat);
- #endif
-+
- db->dma_qcount--;
-
- if (db->count >= db->fragsize) {
-- if (au1xxx_dbdma_put_source(db->dmanr, db->nextOut,
-- db->fragsize) == 0) {
-- err("qcount < 2 and no ring room!");
-+ if (au1xxx_dbdma_put_source(db->dmanr, db->nextOut, db->fragsize) == 0)
-+ {
-+ err("qcount < MIN_Q_COUNT and no ring room!");
- }
- db->nextOut += db->fragsize;
- if (db->nextOut >= db->rawbuf + db->dmasize)
-@@ -606,65 +903,43 @@
-
- }
-
--static loff_t
--au1550_llseek(struct file *file, loff_t offset, int origin)
--{
-- return -ESPIPE;
--}
--
--
--#if 0
--static int
--au1550_open_mixdev(struct inode *inode, struct file *file)
--{
-- file->private_data = &au1550_state;
-- return 0;
--}
--
--static int
--au1550_release_mixdev(struct inode *inode, struct file *file)
--{
-- return 0;
--}
--
--static int
--mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd,
-- unsigned long arg)
--{
-- return codec->mixer_ioctl(codec, cmd, arg);
--}
--
--static int
--au1550_ioctl_mixdev(struct inode *inode, struct file *file,
-- unsigned int cmd, unsigned long arg)
--{
-- struct au1550_state *s = (struct au1550_state *)file->private_data;
-- struct ac97_codec *codec = s->codec;
--
-- return mixdev_ioctl(codec, cmd, arg);
--}
--
--static /*const */ struct file_operations au1550_mixer_fops = {
-- owner:THIS_MODULE,
-- llseek:au1550_llseek,
-- ioctl:au1550_ioctl_mixdev,
-- open:au1550_open_mixdev,
-- release:au1550_release_mixdev,
--};
--#endif
--
- static int
- drain_dac(struct au1550_state *s, int nonblock)
- {
- unsigned long flags;
- int count, tmo;
-
-+ struct dmabuf *db = &s->dma_dac;
-+
-+ //DPRINTF();
- if (s->dma_dac.mapped || !s->dma_dac.ready || s->dma_dac.stopped)
- return 0;
-
- for (;;) {
- spin_lock_irqsave(&s->lock, flags);
-- count = s->dma_dac.count;
-+ count = db->count;
-+
-+ /* Pad the ddma buffer with zeros if the amount remaining
-+ * is not a multiple of fragsize */
-+ if(count % db->fragsize != 0)
-+ {
-+ int pad = db->fragsize - (count % db->fragsize);
-+ char* bufptr = db->nextIn;
-+ char* bufend = db->rawbuf + db->dmasize;
-+
-+ if((bufend - bufptr) < pad)
-+ printk("Error! ddma padding is bigger than available ring space!\n");
-+ else
-+ {
-+ memset((void*)bufptr, 0, pad);
-+ count += pad;
-+ db->nextIn += pad;
-+ db->count += pad;
-+ if (db->dma_qcount == 0)
-+ start_dac(s);
-+ db->dma_qcount++;
-+ }
-+ }
- spin_unlock_irqrestore(&s->lock, flags);
- if (count <= 0)
- break;
-@@ -672,9 +947,9 @@
- break;
- if (nonblock)
- return -EBUSY;
-- tmo = 1000 * count / (s->no_vra ?
-- SAMP_RATE : s->dma_dac.sample_rate);
-+ tmo = 1000 * count / s->dma_dac.sample_rate;
- tmo /= s->dma_dac.dma_bytes_per_sample;
-+
- au1550_delay(tmo);
- }
- if (signal_pending(current))
-@@ -698,8 +973,7 @@
- * If interpolating (no VRA), duplicate every audio frame src_factor times.
- */
- static int
--translate_from_user(struct dmabuf *db, char* dmabuf, char* userbuf,
-- int dmacount)
-+translate_from_user(struct dmabuf *db, char* dmabuf, char* userbuf, int dmacount)
- {
- int sample, i;
- int interp_bytes_per_sample;
-@@ -737,11 +1011,12 @@
-
- /* duplicate every audio frame src_factor times
- */
-- for (i = 0; i < db->src_factor; i++)
-+ for (i = 0; i < db->src_factor; i++) {
- memcpy(dmabuf, dmasample, db->dma_bytes_per_sample);
-+ dmabuf += interp_bytes_per_sample;
-+ }
-
- userbuf += db->user_bytes_per_sample;
-- dmabuf += interp_bytes_per_sample;
- }
-
- return num_samples * interp_bytes_per_sample;
-@@ -996,15 +1271,14 @@
- * on the dma queue. If the queue count reaches zero,
- * we know the dma has stopped.
- */
-- while ((db->dma_qcount < 2) && (db->count >= db->fragsize)) {
-+ while ((db->dma_qcount < MIN_Q_COUNT) && (db->count >= db->fragsize)) {
- if (au1xxx_dbdma_put_source(db->dmanr, db->nextOut,
- db->fragsize) == 0) {
-- err("qcount < 2 and no ring room!");
-+ err("qcount < MIN_Q_COUNT and no ring room!");
- }
- db->nextOut += db->fragsize;
- if (db->nextOut >= db->rawbuf + db->dmasize)
- db->nextOut -= db->dmasize;
-- db->count -= db->fragsize;
- db->total_bytes += db->dma_fragsize;
- if (db->dma_qcount == 0)
- start_dac(s);
-@@ -1017,7 +1291,6 @@
- buffer += usercnt;
- ret += usercnt;
- } /* while (count > 0) */
--
- out:
- up(&s->sem);
- out2:
-@@ -1371,9 +1644,6 @@
- s->dma_dac.cnt_factor;
- abinfo.fragstotal = s->dma_dac.numfrag;
- abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;
--#ifdef AU1000_VERBOSE_DEBUG
-- dbg("bytes=%d, fragments=%d", abinfo.bytes, abinfo.fragments);
--#endif
- return copy_to_user((void *) arg, &abinfo,
- sizeof(abinfo)) ? -EFAULT : 0;
-
-@@ -1536,13 +1806,9 @@
- case SNDCTL_DSP_SETSYNCRO:
- case SOUND_PCM_READ_FILTER:
- return -EINVAL;
-+ default: break;
- }
--
--#if 0
-- return mixdev_ioctl(s->codec, cmd, arg);
--#else
- return 0;
--#endif